UNPKG

@storm-software/workspace-tools

Version:

Tools for managing a Storm workspace, including various Nx generators and executors for common development tasks.

470 lines (425 loc) • 18.3 kB
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _chunkRB72JOT5js = require('./chunk-RB72JOT5.js'); var _chunkWCTC7R27js = require('./chunk-WCTC7R27.js'); var _chunkBSW6NZVBjs = require('./chunk-BSW6NZVB.js'); var _chunkIHMF6RANjs = require('./chunk-IHMF6RAN.js'); var _chunkCQDBLKPFjs = require('./chunk-CQDBLKPF.js'); // ../esbuild/src/assets.ts async function copyBuildAssets(context) { if (!_optionalChain([context, 'access', _ => _.result, 'optionalAccess', _2 => _2.errors, 'access', _3 => _3.length]) && _optionalChain([context, 'access', _4 => _4.options, 'access', _5 => _5.assets, 'optionalAccess', _6 => _6.length])) { _chunkIHMF6RANjs.writeDebug.call(void 0, ` \u{1F4CB} Copying ${context.options.assets.length} asset files to output directory: ${context.outputPath}`, context.workspaceConfig ); const stopwatch = _chunkIHMF6RANjs.getStopwatch.call(void 0, `${context.options.name} asset copy`); await _chunkRB72JOT5js.copyAssets.call(void 0, context.workspaceConfig, _nullishCoalesce(context.options.assets, () => ( [])), context.outputPath, context.options.projectRoot, context.sourceRoot, true, false ); stopwatch(); } return context; } // ../esbuild/src/clean.ts var _promises = require('fs/promises'); var _promises2 = _interopRequireDefault(_promises); async function cleanDirectories(directory) { await _promises.rm.call(void 0, directory, { recursive: true, force: true }); } // ../esbuild/src/context.ts var _devkit = require('@nx/devkit'); var _defu = require('defu'); var _defu2 = _interopRequireDefault(_defu); var _fs = require('fs'); var _findworkspaceroot = require('nx/src/utils/find-workspace-root'); // ../esbuild/src/config.ts var DEFAULT_BUILD_OPTIONS = { platform: "node", target: "node22", format: "esm", mode: "production", generatePackageJson: true, includeSrc: false, keepNames: true, metafile: false, treeshake: true, splitting: true, shims: false, watch: false, bundle: true, distDir: "dist", loader: { ".aac": "file", ".css": "file", ".eot": "file", ".flac": "file", ".gif": "file", ".jpeg": "file", ".jpg": "file", ".mp3": "file", ".mp4": "file", ".ogg": "file", ".otf": "file", ".png": "file", ".svg": "file", ".ttf": "file", ".wav": "file", ".webm": "file", ".webp": "file", ".woff": "file", ".woff2": "file" }, banner: { js: _chunkRB72JOT5js.DEFAULT_JS_BANNER, css: _chunkRB72JOT5js.DEFAULT_CSS_BANNER } }; // ../esbuild/src/context.ts async function resolveContext(userOptions) { const projectRoot = userOptions.projectRoot; const workspaceRoot = _findworkspaceroot.findWorkspaceRoot.call(void 0, projectRoot); if (!workspaceRoot) { throw new Error("Cannot find Nx workspace root"); } const workspaceConfig = await _chunkBSW6NZVBjs.getWorkspaceConfig.call(void 0, true, { workspaceRoot: workspaceRoot.dir }); _chunkIHMF6RANjs.writeDebug.call(void 0, " \u2699\uFE0F Resolving build options", workspaceConfig); const stopwatch = _chunkIHMF6RANjs.getStopwatch.call(void 0, "Build options resolution"); const projectGraph = await _devkit.createProjectGraphAsync.call(void 0, { exitOnError: true }); const projectJsonPath = _chunkCQDBLKPFjs.joinPaths.call(void 0, workspaceRoot.dir, projectRoot, "project.json" ); if (!_fs.existsSync.call(void 0, projectJsonPath)) { throw new Error("Cannot find project.json configuration"); } const projectJsonFile = await _promises2.default.readFile(projectJsonPath, "utf8"); const projectJson = JSON.parse(projectJsonFile); const projectName = projectJson.name || userOptions.name; const projectConfigurations = _devkit.readProjectsConfigurationFromProjectGraph.call(void 0, projectGraph); if (!_optionalChain([projectConfigurations, 'optionalAccess', _7 => _7.projects, 'optionalAccess', _8 => _8[projectName]])) { throw new Error( "The Build process failed because the project does not have a valid configuration in the project.json file. Check if the file exists in the root of the project." ); } const options = _defu2.default.call(void 0, userOptions, DEFAULT_BUILD_OPTIONS); options.name ??= projectName; const packageJsonPath = _chunkCQDBLKPFjs.joinPaths.call(void 0, workspaceRoot.dir, options.projectRoot, "package.json" ); if (!_fs.existsSync.call(void 0, packageJsonPath)) { throw new Error("Cannot find package.json configuration"); } const env = _chunkRB72JOT5js.getEnv.call(void 0, "esbuild", options); const define = _defu2.default.call(void 0, _nullishCoalesce(options.define, () => ( {})), _nullishCoalesce(env, () => ( {}))); const resolvedOptions = { ...options, tsconfig: userOptions.tsconfig === null ? void 0 : userOptions.tsconfig ? userOptions.tsconfig : _chunkCQDBLKPFjs.joinPaths.call(void 0, workspaceRoot.dir, projectRoot, "tsconfig.json"), metafile: userOptions.mode === "development", clean: false, env, define: { STORM_FORMAT: JSON.stringify(options.format), ...Object.keys(define).filter((key) => define[key] !== void 0).reduce((res, key) => { const value = JSON.stringify(define[key]); const safeKey = key.replaceAll("(", "").replaceAll(")", ""); return { ...res, [`process.env.${safeKey}`]: value, [`import.meta.env.${safeKey}`]: value }; }, {}) } }; stopwatch(); const context = { options: resolvedOptions, clean: userOptions.clean !== false, workspaceConfig, projectConfigurations, projectName, projectGraph, sourceRoot: resolvedOptions.sourceRoot || projectJson.sourceRoot || _chunkCQDBLKPFjs.joinPaths.call(void 0, resolvedOptions.projectRoot, "src"), outputPath: resolvedOptions.outputPath || _chunkCQDBLKPFjs.joinPaths.call(void 0, workspaceConfig.workspaceRoot, "dist", resolvedOptions.projectRoot ), minify: resolvedOptions.minify || resolvedOptions.mode === "production" }; context.options.esbuildPlugins = [..._nullishCoalesce(context.options.esbuildPlugins, () => ( []))]; if (context.options.verbose) { _chunkIHMF6RANjs.writeDebug.call(void 0, ` \u2699\uFE0F Build options resolved: ${_chunkIHMF6RANjs.formatLogMessage.call(void 0, context.options)}`, workspaceConfig ); } return context; } // ../esbuild/src/package-json.ts async function generatePackageJson(context) { if (context.options.generatePackageJson !== false && _fs.existsSync.call(void 0, _chunkCQDBLKPFjs.joinPaths.call(void 0, context.options.projectRoot, "package.json"))) { _chunkIHMF6RANjs.writeDebug.call(void 0, " \u270D\uFE0F Writing package.json file", context.workspaceConfig); const stopwatch = _chunkIHMF6RANjs.getStopwatch.call(void 0, "Write package.json file"); const packageJsonPath = _chunkCQDBLKPFjs.joinPaths.call(void 0, context.options.projectRoot, "project.json" ); if (!_fs.existsSync.call(void 0, packageJsonPath)) { throw new Error("Cannot find package.json configuration"); } const packageJsonFile = await _promises2.default.readFile( _chunkCQDBLKPFjs.joinPaths.call(void 0, context.workspaceConfig.workspaceRoot, context.options.projectRoot, "package.json" ), "utf8" ); let packageJson = JSON.parse(packageJsonFile); if (!packageJson) { throw new Error("Cannot find package.json configuration file"); } packageJson = await _chunkRB72JOT5js.addPackageDependencies.call(void 0, context.workspaceConfig.workspaceRoot, context.options.projectRoot, context.projectName, packageJson ); packageJson = await _chunkRB72JOT5js.addWorkspacePackageJsonFields.call(void 0, context.workspaceConfig, context.options.projectRoot, context.sourceRoot, context.projectName, false, packageJson ); if (context.options.entry) { packageJson.exports ??= {}; packageJson.exports["./package.json"] ??= "./package.json"; const entryPoints = Array.isArray(context.options.entry) ? context.options.entry : Object.keys(context.options.entry); if (entryPoints.length > 0) { const defaultEntry = entryPoints.includes("index") ? `.${context.options.distDir ? `/${context.options.distDir}` : ""}/index` : `.${context.options.distDir ? `/${context.options.distDir}` : ""}/${entryPoints[0]}`; const isEsm = Array.isArray(context.options.format) ? context.options.format.includes("esm") : context.options.format === "esm"; const isCjs = Array.isArray(context.options.format) ? context.options.format.includes("cjs") : context.options.format === "cjs"; const isDts = context.options.dts || context.options.experimentalDts; packageJson.exports["."] ??= `${defaultEntry}.${isEsm ? "mjs" : isCjs ? "cjs" : "js"}`; for (const entryPoint of entryPoints) { packageJson.exports[`./${entryPoint}`] ??= {}; if (isEsm) { if (isDts) { packageJson.exports[`./${entryPoint}`].import = { types: `./dist/${entryPoint}.d.mts`, default: `./dist/${entryPoint}.mjs` }; } else { packageJson.exports[`./${entryPoint}`].import = `./dist/${entryPoint}.mjs`; } if (isDts) { packageJson.exports[`./${entryPoint}`].default = { types: `./dist/${entryPoint}.d.mts`, default: `./dist/${entryPoint}.mjs` }; } else { packageJson.exports[`./${entryPoint}`].default = `./dist/${entryPoint}.mjs`; } } if (isCjs) { if (isDts) { packageJson.exports[`./${entryPoint}`].require = { types: `./dist/${entryPoint}.d.cts`, default: `./dist/${entryPoint}.cjs` }; } else { packageJson.exports[`./${entryPoint}`].require = `./dist/${entryPoint}.cjs`; } if (!isEsm) { if (isDts) { packageJson.exports[`./${entryPoint}`].default = { types: `./dist/${entryPoint}.d.cts`, default: `./dist/${entryPoint}.cjs` }; } else { packageJson.exports[`./${entryPoint}`].default = `./dist/${entryPoint}.cjs`; } } } if (!isEsm && !isCjs) { if (isDts) { packageJson.exports[`./${entryPoint}`].default = { types: `./dist/${entryPoint}.d.ts`, default: `./dist/${entryPoint}.js` }; } else { packageJson.exports[`./${entryPoint}`].default = `./dist/${entryPoint}.js`; } } } if (isEsm) { packageJson.module = `${defaultEntry}.mjs`; } else { packageJson.main = `${defaultEntry}.cjs`; } if (isDts) { packageJson.types = `${defaultEntry}.d.${isEsm ? "mts" : isCjs ? "cts" : "ts"}`; } packageJson.exports = Object.keys(packageJson.exports).reduce( (ret, key) => { if (key.endsWith("/index") && !ret[key.replace("/index", "")]) { ret[key.replace("/index", "")] = packageJson.exports[key]; } return ret; }, packageJson.exports ); } } await _devkit.writeJsonFile.call(void 0, _chunkCQDBLKPFjs.joinPaths.call(void 0, context.outputPath, "package.json"), packageJson ); stopwatch(); } return context; } // ../tsup/src/index.ts var _tsup = require('tsup'); async function build(options) { if (!options.silent) { _chunkIHMF6RANjs.writeDebug.call(void 0, ` \u{1F680} Running ${options.name || "tsup"} build`, options.workspaceConfig ); } const stopwatch = _chunkIHMF6RANjs.getStopwatch.call(void 0, `${options.name || "tsup"} build`); await _tsup.build.call(void 0, options); if (!options.silent) { stopwatch(); } } // ../esbuild/src/tsup.ts async function executeTsup(context) { _chunkIHMF6RANjs.writeDebug.call(void 0, ` \u{1F680} Running ${context.options.name} build`, context.workspaceConfig ); const stopwatch = _chunkIHMF6RANjs.getStopwatch.call(void 0, `${context.options.name} build`); await build({ ...context.options, outDir: context.options.distDir ? _chunkCQDBLKPFjs.joinPaths.call(void 0, context.outputPath, context.options.distDir) : context.outputPath, workspaceConfig: context.workspaceConfig }); stopwatch(); return context; } // ../esbuild/src/build.ts async function reportResults(context) { if (_optionalChain([context, 'access', _9 => _9.result, 'optionalAccess', _10 => _10.errors, 'access', _11 => _11.length]) === 0) { if (context.result.warnings.length > 0) { _chunkIHMF6RANjs.writeWarning.call(void 0, ` \u{1F6A7} The following warnings occurred during the build: ${context.result.warnings.map((warning) => warning.text).join("\n")}`, context.workspaceConfig ); } _chunkIHMF6RANjs.writeSuccess.call(void 0, ` \u{1F4E6} The ${context.options.name} build completed successfully`, context.workspaceConfig ); } else if (_optionalChain([context, 'access', _12 => _12.result, 'optionalAccess', _13 => _13.errors]) && _optionalChain([context, 'access', _14 => _14.result, 'optionalAccess', _15 => _15.errors, 'access', _16 => _16.length]) > 0) { _chunkIHMF6RANjs.writeError.call(void 0, ` \u274C The ${context.options.name} build failed with the following errors: ${context.result.errors.map((error) => error.text).join("\n")}`, context.workspaceConfig ); throw new Error( `The ${context.options.name} build failed with the following errors: ${context.result.errors.map((error) => error.text).join("\n")}` ); } } async function cleanOutputPath(context) { if (context.clean !== false && context.outputPath) { _chunkIHMF6RANjs.writeDebug.call(void 0, ` \u{1F9F9} Cleaning ${context.options.name} output path: ${context.outputPath}`, context.workspaceConfig ); const stopwatch = _chunkIHMF6RANjs.getStopwatch.call(void 0, `${context.options.name} output clean`); await cleanDirectories(context.outputPath); stopwatch(); } return context; } async function build2(options) { _chunkIHMF6RANjs.writeDebug.call(void 0, ` ${_chunkIHMF6RANjs.brandIcon.call(void 0, )} Executing Storm ESBuild pipeline`); const stopwatch = _chunkIHMF6RANjs.getStopwatch.call(void 0, "ESBuild pipeline"); try { const opts = Array.isArray(options) ? options : [options]; if (opts.length === 0) { throw new Error("No build options were provided"); } const context = await resolveContext(options); await cleanOutputPath(context); await Promise.all([ // dependencyCheck(context.options), generatePackageJson(context), copyBuildAssets(context), executeTsup(context) ]); await reportResults(context); _chunkIHMF6RANjs.writeSuccess.call(void 0, " \u{1F3C1} ESBuild pipeline build completed successfully"); } catch (error) { _chunkIHMF6RANjs.writeFatal.call(void 0, "Fatal errors that the build process could not recover from have occured. The build process has been terminated." ); throw error; } finally { stopwatch(); } } // src/executors/esbuild/executor.ts async function esbuildExecutorFn(options, context, config) { _chunkIHMF6RANjs.writeInfo.call(void 0, "\u{1F4E6} Running Storm ESBuild executor on the workspace", config); if (!_optionalChain([context, 'access', _17 => _17.projectsConfigurations, 'optionalAccess', _18 => _18.projects]) || !context.projectName || !context.projectsConfigurations.projects[context.projectName] || !_optionalChain([context, 'access', _19 => _19.projectsConfigurations, 'access', _20 => _20.projects, 'access', _21 => _21[context.projectName], 'optionalAccess', _22 => _22.root])) { throw new Error( "The Build process failed because the context is not valid. Please run this command from a workspace." ); } await build2({ ...options, projectRoot: ( // eslint-disable-next-line @typescript-eslint/no-non-null-assertion _optionalChain([context, 'access', _23 => _23.projectsConfigurations, 'access', _24 => _24.projects, 'optionalAccess', _25 => _25[context.projectName], 'access', _26 => _26.root]) ), name: context.projectName, sourceRoot: _optionalChain([context, 'access', _27 => _27.projectsConfigurations, 'access', _28 => _28.projects, 'optionalAccess', _29 => _29[context.projectName], 'optionalAccess', _30 => _30.sourceRoot]), format: options.format, platform: options.platform }); return { success: true }; } var executor_default = _chunkWCTC7R27js.withRunExecutor.call(void 0, "Storm ESBuild build", esbuildExecutorFn, { skipReadingConfig: false, hooks: { applyDefaultOptions: async (options) => { options.entry ??= ["src/index.ts"]; options.outputPath ??= "dist/{projectRoot}"; options.tsconfig ??= "{projectRoot}/tsconfig.json"; return options; } } } ); exports.esbuildExecutorFn = esbuildExecutorFn; exports.executor_default = executor_default;