Skip to content

Instantly share code, notes, and snippets.

@Brian-McBride
Created December 14, 2023 18:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Brian-McBride/86f43cfb4c55f778fd4c01c238d3b53c to your computer and use it in GitHub Desktop.
Save Brian-McBride/86f43cfb4c55f778fd4c01c238d3b53c to your computer and use it in GitHub Desktop.
Nx using Astro Advanced APIs (Build)
import { writeFileSync } from 'fs';
import { resolve } from 'path';
import type { ExecutorContext } from '@nx/devkit';
import {
logger,
stripIndents,
writeJsonFile,
detectPackageManager,
} from '@nx/devkit';
import { createLockFile, createPackageJson, getLockFileName } from '@nx/js';
import { removeSync } from 'fs-extra';
import { type BuildExecutorOptions } from './schema';
export default async function runExecutor(
options: BuildExecutorOptions,
context: ExecutorContext
) {
let success = false;
const cwd = process.cwd();
try {
options = normalizeOptions(options);
if (!context.workspace) {
throw new Error('Workspace is not defined');
}
if (!context.projectName) {
throw new Error('Project name is not defined');
}
if (!context.projectGraph) {
throw new Error('Project graph is not defined');
}
const projectName = context.projectName;
const projectGraph = context.projectGraph;
const projectRoot = context.workspace?.projects[projectName].root;
const projectNode = projectGraph.nodes[projectName];
let outDir = resolve(options.outputPath || `dist/${projectRoot}`);
if (!options.outputPath && context.target?.outputs?.[0]) {
outDir = resolve(
context.target.outputs[0]
.replace('{workspaceRoot}', context.root)
.replace('{projectRoot}', projectRoot)
);
}
if (options.deleteOutputPath) {
removeSync(outDir);
}
// Astro is ES Module, where Nx exectors is CommonJS. This is somewhat of a "fix"
const astro = await (Function('return import("astro")')() as Promise<
typeof import('astro')
>);
// Astro pluings seem to fail when running from workspace root, so we change the cwd to the project root.
process.chdir(resolve(projectRoot));
await astro
.build({
outDir,
})
.then(() => {
success = true;
})
.finally(() => {
process.chdir(cwd);
});
if (success && options.generatePackageJson) {
if (projectNode.type !== 'app') {
logger.warn(
stripIndents`The project ${projectName} is using the 'generatePackageJson' option which is deprecated for library projects. It should only be used for applications.
For libraries, configure the project to use the '@nx/dependency-checks' ESLint rule instead (https://nx.dev/packages/eslint-plugin/documents/dependency-checks).`
);
}
const packageManger = detectPackageManager(context.root);
const builtPackageJson = createPackageJson(projectName, projectGraph, {
target: context.targetName,
root: context.root,
isProduction: !options.includeDevDependenciesInPackageJson, // By default we remove devDependencies since this is a production build.
});
builtPackageJson.type = 'module';
writeJsonFile(`${options.outputPath}/package.json`, builtPackageJson);
const lockFile = createLockFile(
builtPackageJson,
projectGraph,
packageManger
);
writeFileSync(
`${options.outputPath}/${getLockFileName(packageManger)}`,
lockFile,
{
encoding: 'utf-8',
}
);
}
return { success };
} catch (e) {
console.error(e);
return { success };
}
}
function normalizeOptions(options: BuildExecutorOptions): BuildExecutorOptions {
return { deleteOutputPath: true, ...options };
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment