nuxt-prepare
Version:
Build actions for Nuxt
175 lines (170 loc) • 5.38 kB
JavaScript
import { defineNuxtModule, useLogger, findPath, addTemplate } from '@nuxt/kit';
import { defu } from 'defu';
import * as importx from 'importx';
import { interopDefault } from 'mlly';
import { join } from 'pathe';
import { pascalCase } from 'scule';
const name = "nuxt-prepare";
const version = "2.3.2";
function toArray(value) {
return Array.isArray(value) ? value : [value];
}
function isObject(value) {
return Object.prototype.toString.call(value) === "[object Object]";
}
const module = defineNuxtModule({
meta: {
name,
version,
configKey: "prepare",
compatibility: {
nuxt: ">=3.0.0"
}
},
defaults: {
scripts: ["server.prepare"],
parallel: false,
continueOnError: false,
runOnNuxtPrepare: true
},
async setup(options, nuxt) {
const moduleName = name;
const logger = useLogger(moduleName);
const extensions = [".js", ".mjs", ".ts"];
let successCount = 0;
let errorCount = 0;
let resolvedScripts = [];
let state = {};
for (const script of toArray(options.scripts)) {
let name2 = typeof script === "string" ? script : script.file;
for (const ext of extensions) {
if (name2.endsWith(ext)) {
name2 = name2.slice(0, -ext.length);
break;
}
}
const path = await findPath(name2, { extensions }, "file");
if (name2 === "server.prepare" && !path) {
continue;
}
if (!path) {
logger.error(
`Server prepare script \`${name2}{${extensions.join(",")}}\` not found. Please create the file or remove it from the \`prepare.scripts\` module option.`
);
throw new Error("Server prepare script not found");
}
resolvedScripts.push({
name: name2,
path,
runOnNuxtPrepare: typeof script === "string" ? true : script.runOnNuxtPrepare ?? true
});
}
const scriptNames = /* @__PURE__ */ new Set();
resolvedScripts = resolvedScripts.filter(({ name: name2 }) => {
if (scriptNames.has(name2))
return false;
scriptNames.add(name2);
return true;
});
const runScript = async ({ name: name2, path, runOnNuxtPrepare }) => {
if (nuxt.options._prepare && !runOnNuxtPrepare) {
logger.info(`Skipping prepare script \`${name2}\``);
return;
}
logger.info(`Running prepare script \`${name2}\``);
const result = await interopDefault(
await importx.import(path, {
parentURL: nuxt.options.rootDir,
cache: false,
loaderOptions: {
// Nuxt's TypeScript config will only be generated along
// with prepare scripts, so we disable config resolution
tsx: { tsconfig: false }
}
})
);
const isOk = result.ok ?? true;
if (!isOk) {
logger.error(`Server prepare script \`${name2}\` returned an error`);
errorCount++;
if (!options.continueOnError)
throw new TypeError("Server prepare script failed");
return;
}
successCount++;
if (result.runtimeConfig) {
nuxt.options.runtimeConfig = defu(
nuxt.options.runtimeConfig,
result.runtimeConfig
);
}
if (result.appConfig)
nuxt.options.appConfig = defu(nuxt.options.appConfig, result.appConfig);
if (result.state) {
if (!isObject(result.state))
throw new TypeError("Server prepare script returned invalid state");
state = defu(state, result.state);
}
};
if (nuxt.options._prepare && !options.runOnNuxtPrepare) {
logger.info("Skipping prepare scripts");
} else {
if (options.parallel) {
await Promise.all(resolvedScripts.map(runScript));
} else {
for (const script of resolvedScripts) {
await runScript(script);
}
}
}
nuxt.options.alias[`#${moduleName}`] = join(nuxt.options.buildDir, `module/${moduleName}`);
nuxt.hooks.hook("nitro:config", (config) => {
config.alias ||= {};
config.alias[`#${moduleName}`] = join(nuxt.options.buildDir, `module/${moduleName}`);
});
addTemplate({
filename: `module/${moduleName}.mjs`,
write: true,
getContents() {
const results = Object.entries(state);
if (!results.length) {
return `
// Generated by ${moduleName}
export {}
`.trimStart();
}
return `
// Generated by ${moduleName}
${results.map(([key, value]) => `
export const ${key} = ${JSON.stringify(value, void 0, 2)}
`.trim()).join("\n")}
`.trimStart();
}
});
addTemplate({
filename: `module/${moduleName}.d.ts`,
write: true,
getContents() {
const results = Object.entries(state);
if (!results.length) {
return `
// Generated by ${moduleName}
export {}
`.trimStart();
}
return `
// Generated by ${moduleName}
${results.map(([key, value]) => `
export declare const ${key}: ${JSON.stringify(value, void 0, 2)}
export type ${pascalCase(key)} = typeof ${key}
`.trim()).join("\n")}
`.trimStart();
}
});
if (errorCount > 0)
logger.warn(`Server prepare scripts completed with ${errorCount} error${errorCount > 1 ? "s" : ""}`);
else if (successCount > 0)
logger.success("Server prepare scripts completed");
}
});
export { module as default };