diff --git a/.changeset/configured-metadata-output.md b/.changeset/configured-metadata-output.md new file mode 100644 index 0000000..8b89fd2 --- /dev/null +++ b/.changeset/configured-metadata-output.md @@ -0,0 +1,5 @@ +--- +'@openai/sites-vite-plugin': patch +--- + +Package hosting metadata and Drizzle migrations in Vite's configured build output directory. diff --git a/packages/sites-vite-plugin/README.md b/packages/sites-vite-plugin/README.md index 0de9e09..628fad0 100644 --- a/packages/sites-vite-plugin/README.md +++ b/packages/sites-vite-plugin/README.md @@ -17,9 +17,11 @@ deployment artifact: - Required: `.openai/hosting.json` to `dist/.openai/hosting.json` - Optional: `drizzle/**` to `dist/.openai/drizzle/**` -The build fails when `.openai/hosting.json` is missing. The generated -`dist/.openai` directory is replaced on every build. V1 assumes Vite's default -`dist` output directory and does not expose configuration. +The build fails when `.openai/hosting.json` is missing. The generated `.openai` +directory is replaced on every build. These paths use Vite's default `dist` +output directory; when `build.outDir` is configured, metadata is placed under +that directory instead. Relative output directories are resolved against the +Vite project root, and absolute output directories are supported. ## Local sign-in diff --git a/packages/sites-vite-plugin/src/index.ts b/packages/sites-vite-plugin/src/index.ts index 82176b5..906d1bf 100644 --- a/packages/sites-vite-plugin/src/index.ts +++ b/packages/sites-vite-plugin/src/index.ts @@ -29,12 +29,14 @@ async function exists(path: string): Promise { export function sites(): Plugin { let root = process.cwd(); + let outDir = 'dist'; let command: 'build' | 'serve' = 'build'; return { name: 'sites', configResolved(config) { root = config.root; + outDir = config.build.outDir; command = config.command; }, configureServer(server) { @@ -168,7 +170,7 @@ export function sites(): Plugin { async closeBundle() { if (command !== 'build') return; - const outputDirectory = resolve(root, 'dist', '.openai'); + const outputDirectory = resolve(root, outDir, '.openai'); const hostingConfig = resolve(root, '.openai', 'hosting.json'); const drizzleSource = resolve(root, 'drizzle'); diff --git a/packages/sites-vite-plugin/test/sites.test.ts b/packages/sites-vite-plugin/test/sites.test.ts index 681d421..b679497 100644 --- a/packages/sites-vite-plugin/test/sites.test.ts +++ b/packages/sites-vite-plugin/test/sites.test.ts @@ -272,6 +272,55 @@ describe('sites', () => { ).resolves.toBe('{}\n'); }); + test.each(['relative', 'nested', 'absolute'])( + 'packages metadata in the configured %s output directory', + async (kind) => { + const root = await createProject(); + const outDir = + kind === 'absolute' + ? join(root, 'absolute-output') + : kind === 'nested' + ? 'build/client' + : 'build'; + const output = join( + root, + kind === 'absolute' ? 'absolute-output' : outDir, + ); + await mkdir(join(root, '.openai')); + await writeFile(join(root, '.openai', 'hosting.json'), '{"d1":"DB"}\n'); + await mkdir(join(root, 'drizzle')); + await writeFile(join(root, 'drizzle', '0000.sql'), 'SELECT 1;\n'); + await mkdir(join(root, 'dist', '.openai'), { recursive: true }); + await writeFile(join(root, 'dist', '.openai', 'unrelated.txt'), 'keep'); + + await build({ root, configFile, logLevel: 'silent', build: { outDir } }); + + await expect( + readFile(join(output, '.openai', 'hosting.json'), 'utf8'), + ).resolves.toBe('{"d1":"DB"}\n'); + await expect( + readFile(join(output, '.openai', 'drizzle', '0000.sql'), 'utf8'), + ).resolves.toBe('SELECT 1;\n'); + await expect( + readFile(join(output, 'index.html'), 'utf8'), + ).resolves.toContain('Sites'); + await expect( + readFile(join(root, 'dist', '.openai', 'unrelated.txt'), 'utf8'), + ).resolves.toBe('keep'); + + await rm(join(root, 'drizzle'), { recursive: true }); + await build({ + root, + configFile, + logLevel: 'silent', + build: { outDir, emptyOutDir: false }, + }); + await expect(readdir(join(output, '.openai'))).resolves.toEqual([ + 'hosting.json', + ]); + }, + ); + test('removes stale Drizzle sidecars when migrations disappear', async () => { const root = await createProject(); await mkdir(join(root, '.openai'));