diff --git a/client/packages/create-instant-app/src/backendConfig.test.ts b/client/packages/create-instant-app/src/backendConfig.test.ts index 494d5a56f1..440ab07034 100644 --- a/client/packages/create-instant-app/src/backendConfig.test.ts +++ b/client/packages/create-instant-app/src/backendConfig.test.ts @@ -67,6 +67,33 @@ describe('applyBackendConfig', () => { ' appId: "app-id",\n' + '});\n', ); + expect(fs.readFileSync(path.join(dir, 'instant.config.ts'), 'utf8')).toBe( + `export default { + apiURI: "http://localhost:8888", +}; +`, + ); + }); + + it('adds the dashboard URI to instant.config.ts when provided', () => { + const dir = createTempDir(); + const filePath = path.join(dir, 'src/lib/db.ts'); + fs.outputFileSync(filePath, 'export const db = init({\n});\n'); + + applyBackendConfig( + 'next-js-app-dir', + dir, + 'https://api.instant.example', + 'https://dash.instant.example', + ); + + expect(fs.readFileSync(path.join(dir, 'instant.config.ts'), 'utf8')).toBe( + `export default { + apiURI: "https://api.instant.example", + dashURI: "https://dash.instant.example", +}; +`, + ); }); it('adds only the API URI to admin init', () => { @@ -96,6 +123,7 @@ describe('applyBackendConfig', () => { applyBackendConfig('tanstack-start', dir, 'https://instant.example'), ).toThrow('Could not find init({ in scaffolded database file'); expect(fs.readFileSync(clientPath, 'utf8')).toBe(clientContents); + expect(fs.pathExistsSync(path.join(dir, 'instant.config.ts'))).toBe(false); }); it('configures the Python client', () => { diff --git a/client/packages/create-instant-app/src/backendConfig.ts b/client/packages/create-instant-app/src/backendConfig.ts index 0aaad505b2..5f04e33e9d 100644 --- a/client/packages/create-instant-app/src/backendConfig.ts +++ b/client/packages/create-instant-app/src/backendConfig.ts @@ -8,6 +8,17 @@ import { const normalizeAPIURI = (apiURI: string) => apiURI.replace(/\/+$/, ''); +const instantConfigContents = (apiURI: string, dashURI?: string) => { + const entries = [ + ` apiURI: ${JSON.stringify(apiURI)},`, + dashURI ? ` dashURI: ${JSON.stringify(dashURI)},` : null, + ] + .filter(Boolean) + .join('\n'); + + return `export default {\n${entries}\n};\n`; +}; + export const websocketURIFromAPIURI = (apiURI: string) => { let websocketURI: URL; try { @@ -91,6 +102,7 @@ export const applyBackendConfig = ( base: ProjectBase, projectDir: string, apiURI: string, + dashURI?: string, ) => { const normalizedAPIURI = normalizeAPIURI(apiURI); const websocketURI = websocketURIFromAPIURI(normalizedAPIURI); @@ -112,4 +124,9 @@ export const applyBackendConfig = ( for (const update of updates) { fs.writeFileSync(update.filePath, update.contents); } + + fs.writeFileSync( + path.join(projectDir, 'instant.config.ts'), + instantConfigContents(normalizedAPIURI, dashURI), + ); }; diff --git a/client/packages/create-instant-app/src/index.ts b/client/packages/create-instant-app/src/index.ts index 0f7d3f95f5..24ad7c172f 100644 --- a/client/packages/create-instant-app/src/index.ts +++ b/client/packages/create-instant-app/src/index.ts @@ -50,6 +50,7 @@ const main = async () => { project.base, projectDir, process.env.INSTANT_CLI_API_URI, + process.env.INSTANT_CLI_DASH_URI, ); } diff --git a/client/packages/version/src/version.ts b/client/packages/version/src/version.ts index 5bfb50a276..78c9301904 100644 --- a/client/packages/version/src/version.ts +++ b/client/packages/version/src/version.ts @@ -2,6 +2,6 @@ // Update the version here and merge your code to main to // publish a new version of all of the packages to npm. -const version = 'v1.0.62'; +const version = 'v1.0.63'; export { version }; diff --git a/client/www/components/dash/HomeStartGuide.tsx b/client/www/components/dash/HomeStartGuide.tsx index 2dd5e2ac65..34496d01d5 100644 --- a/client/www/components/dash/HomeStartGuide.tsx +++ b/client/www/components/dash/HomeStartGuide.tsx @@ -30,7 +30,12 @@ function randomInRange(min: number, max: number) { return Math.random() * (max - min) + min; } +function shellQuote(value: string) { + return `'${value.replaceAll("'", "'\\''")}'`; +} + type Framework = 'nextjs' | 'expo'; +type CliBackend = { apiURI: string; dashURI: string }; type Step = { id: string; @@ -68,8 +73,12 @@ function getSteps( dirName: string, appId: string, adminToken: string, + backend?: CliBackend, ): Step[] { const config = frameworkConfig[framework]; + const backendEnv = backend + ? `INSTANT_CLI_API_URI=${shellQuote(backend.apiURI)} INSTANT_CLI_DASH_URI=${shellQuote(backend.dashURI)} ` + : ''; const viewStep: Step = config.viewStep.type === 'link' ? { @@ -89,7 +98,7 @@ function getSteps( id: 'start_guide_create_project', title: 'Create your project', description: `Scaffold a new ${framework === 'nextjs' ? 'Next.js' : 'Expo'} app with Instant pre-configured`, - command: `npx create-instant-app ${dirName} --app ${appId} --token ${adminToken} ${config.flag} --rules`, + command: `${backendEnv}npx create-instant-app ${dirName} --app ${appId} --token ${adminToken} ${config.flag} --rules`, }, { id: 'start_guide_start_server', @@ -101,12 +110,18 @@ function getSteps( ]; } -export function AppStart({ app }: { app: InstantApp }) { +export function AppStart({ + app, + backend, +}: { + app: InstantApp; + backend?: CliBackend; +}) { const { id: appId, title: appTitle, admin_token: adminToken } = app; const posthog = usePostHog(); const [framework, setFramework] = useState('nextjs'); const dirName = toDirectoryName(appTitle); - const steps = getSteps(framework, dirName, appId, adminToken); + const steps = getSteps(framework, dirName, appId, adminToken, backend); const trackCopy = (stepId: string) => { posthog.capture(stepId, { diff --git a/client/www/pages/dash/index.tsx b/client/www/pages/dash/index.tsx index f33b51de9a..fd1611cb60 100644 --- a/client/www/pages/dash/index.tsx +++ b/client/www/pages/dash/index.tsx @@ -32,7 +32,7 @@ import NextLink from 'next/link'; import { ReactElement, useContext, useEffect, useRef, useState } from 'react'; import { usePostHog } from 'posthog-js/react'; -import config, { cliOauthParamName } from '@/lib/config'; +import config, { cliOauthParamName, isSelfHosted } from '@/lib/config'; import { TokenContext } from '@/lib/contexts'; import { jsonFetch, jsonMutate } from '@/lib/fetch'; import { successToast } from '@/lib/toast'; @@ -796,11 +796,14 @@ function Home({ app, token }: { app: InstantApp; token: string }) { const sortedOrigins = stats?.origins ? Object.entries(stats.origins).sort(([, a], [, b]) => b - a) : []; + const cliBackend = isSelfHosted + ? { apiURI: config.apiURI, dashURI: window.location.origin } + : undefined; return (
- +
Next Steps