mirror of
https://github.com/withastro/astro.git
synced 2025-01-20 22:12:38 -05:00
fix: load seed file separately for build
This commit is contained in:
parent
93675795e1
commit
aa1b66f5cf
3 changed files with 120 additions and 4 deletions
|
@ -3,15 +3,20 @@ import { vitePluginDb } from './vite-plugin-db.js';
|
|||
import { vitePluginInjectEnvTs } from './vite-plugin-inject-env-ts.js';
|
||||
import { typegen } from './typegen.js';
|
||||
import { collectionsSchema } from './types.js';
|
||||
import { seed } from './seed.js';
|
||||
|
||||
export function integration(): AstroIntegration {
|
||||
return {
|
||||
name: 'astro:db',
|
||||
hooks: {
|
||||
async 'astro:config:setup'({ updateConfig, config }) {
|
||||
async 'astro:config:setup'({ updateConfig, config, command }) {
|
||||
// TODO: refine where we load collections
|
||||
// @matthewp: may want to load collections by path at runtime
|
||||
const collections = collectionsSchema.parse(config.db?.collections ?? {});
|
||||
const isDev = command === 'dev';
|
||||
if (!isDev) {
|
||||
await seed({ collections, root: config.root });
|
||||
}
|
||||
updateConfig({
|
||||
vite: {
|
||||
plugins: [
|
||||
|
@ -20,6 +25,7 @@ export function integration(): AstroIntegration {
|
|||
vitePluginDb({
|
||||
collections,
|
||||
root: config.root,
|
||||
isDev,
|
||||
}),
|
||||
// @ts-ignore
|
||||
vitePluginInjectEnvTs(config),
|
||||
|
|
106
packages/db/src/seed.ts
Normal file
106
packages/db/src/seed.ts
Normal file
|
@ -0,0 +1,106 @@
|
|||
import { existsSync, unlinkSync, writeFileSync } from 'node:fs';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { type BuildOptions, build as esbuild } from 'esbuild';
|
||||
import { SUPPORTED_SEED_FILES, VIRTUAL_MODULE_ID } from './consts.js';
|
||||
import { getVirtualModContents } from './vite-plugin-db.js';
|
||||
import type { DBCollections } from './types.js';
|
||||
|
||||
export async function seed({ collections, root }: { collections: DBCollections; root: URL }) {
|
||||
let seedFileUrl: URL | undefined;
|
||||
for (const filename of SUPPORTED_SEED_FILES) {
|
||||
const fileUrl = new URL(filename, root);
|
||||
if (!existsSync(fileUrl)) continue;
|
||||
|
||||
seedFileUrl = fileUrl;
|
||||
break;
|
||||
}
|
||||
if (!seedFileUrl) return;
|
||||
|
||||
const { code } = await bundleFile(seedFileUrl, [
|
||||
{
|
||||
name: 'resolve-astro-db',
|
||||
setup(build) {
|
||||
build.onResolve({ filter: /^astro:db$/ }, ({ path }) => {
|
||||
return { path, namespace: VIRTUAL_MODULE_ID };
|
||||
});
|
||||
build.onLoad({ namespace: VIRTUAL_MODULE_ID, filter: /.*/ }, () => {
|
||||
return {
|
||||
contents: getVirtualModContents({
|
||||
collections,
|
||||
root,
|
||||
isDev: false,
|
||||
}),
|
||||
// Needed to resolve `@packages/studio` internals
|
||||
resolveDir: process.cwd(),
|
||||
};
|
||||
});
|
||||
},
|
||||
},
|
||||
]);
|
||||
// seed file supports top-level await. Runs when config is loaded!
|
||||
await loadBundledFile({ code, root });
|
||||
|
||||
console.info('Seeding complete 🌱');
|
||||
}
|
||||
|
||||
/**
|
||||
* Bundle config file to support `.ts` files. Simplified fork from Vite's `bundleConfigFile`
|
||||
* function:
|
||||
*
|
||||
* @see https://github.com/vitejs/vite/blob/main/packages/vite/src/node/config.ts#L961
|
||||
*/
|
||||
async function bundleFile(
|
||||
fileUrl: URL,
|
||||
esbuildPlugins?: BuildOptions['plugins']
|
||||
): Promise<{ code: string; dependencies: string[] }> {
|
||||
const result = await esbuild({
|
||||
absWorkingDir: process.cwd(),
|
||||
entryPoints: [fileURLToPath(fileUrl)],
|
||||
outfile: 'out.js',
|
||||
packages: 'external',
|
||||
write: false,
|
||||
target: ['node16'],
|
||||
platform: 'node',
|
||||
bundle: true,
|
||||
format: 'esm',
|
||||
sourcemap: 'inline',
|
||||
metafile: true,
|
||||
plugins: esbuildPlugins,
|
||||
});
|
||||
|
||||
const file = result.outputFiles[0];
|
||||
if (!file) {
|
||||
throw new Error(`Unexpected: no output file`);
|
||||
}
|
||||
|
||||
return {
|
||||
code: file.text,
|
||||
dependencies: Object.keys(result.metafile.inputs),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Forked from Vite config loader, replacing CJS-based path concat with ESM only
|
||||
*
|
||||
* @see https://github.com/vitejs/vite/blob/main/packages/vite/src/node/config.ts#L1074
|
||||
*/
|
||||
async function loadBundledFile({
|
||||
code,
|
||||
root,
|
||||
}: {
|
||||
root: URL;
|
||||
code: string;
|
||||
}): Promise<{ default?: unknown }> {
|
||||
// Write it to disk, load it with native Node ESM, then delete the file.
|
||||
const tmpFileUrl = new URL(`studio.seed.timestamp-${Date.now()}.mjs`, root);
|
||||
writeFileSync(tmpFileUrl, code);
|
||||
try {
|
||||
return await import(tmpFileUrl.pathname);
|
||||
} finally {
|
||||
try {
|
||||
unlinkSync(tmpFileUrl);
|
||||
} catch {
|
||||
// already removed if this function is called twice simultaneously
|
||||
}
|
||||
}
|
||||
}
|
|
@ -15,9 +15,11 @@ const resolvedVirtualModuleId = '\0' + VIRTUAL_MODULE_ID;
|
|||
export function vitePluginDb({
|
||||
collections,
|
||||
root,
|
||||
isDev: isDev,
|
||||
}: {
|
||||
collections: DBCollections;
|
||||
root: URL;
|
||||
isDev: boolean;
|
||||
}): VitePlugin {
|
||||
return {
|
||||
name: 'astro:db',
|
||||
|
@ -29,7 +31,7 @@ export function vitePluginDb({
|
|||
},
|
||||
load(id) {
|
||||
if (id !== resolvedVirtualModuleId) return;
|
||||
return getLocalVirtualModuleContents({ collections, root });
|
||||
return getVirtualModContents({ collections, root, isDev });
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -38,12 +40,14 @@ const seedErrorMessage = `${red(
|
|||
'⚠️ Failed to seed data.'
|
||||
)} Is the seed file out-of-date with recent schema changes?`;
|
||||
|
||||
export function getLocalVirtualModuleContents({
|
||||
export function getVirtualModContents({
|
||||
collections,
|
||||
root,
|
||||
isDev,
|
||||
}: {
|
||||
collections: DBCollections;
|
||||
root: URL;
|
||||
isDev: boolean;
|
||||
}) {
|
||||
const seedFile = SUPPORTED_SEED_FILES.map((f) => fileURLToPath(new URL(f, root))).find((f) =>
|
||||
existsSync(f)
|
||||
|
@ -57,7 +61,7 @@ export * from ${DRIZZLE_MOD_IMPORT};
|
|||
${getStringifiedCollectionExports(collections)}
|
||||
|
||||
${
|
||||
seedFile
|
||||
seedFile && isDev
|
||||
? `try {
|
||||
await import(${JSON.stringify(seedFile)});
|
||||
} catch {
|
||||
|
|
Loading…
Add table
Reference in a new issue