UNPKG

@storm-software/workspace-tools

Version:

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

1,356 lines (1,321 loc) • 49.3 kB
import { withRunExecutor } from "./chunk-7P2LGXFI.mjs"; import { formatLogMessage, getConfig, getStopwatch, isVerbose, writeDebug, writeError, writeFatal, writeInfo, writeSuccess, writeTrace, writeWarning } from "./chunk-NODM27UV.mjs"; import { findWorkspaceRoot } from "./chunk-FR3YQN55.mjs"; import { correctPaths, joinPaths } from "./chunk-ATIBREWM.mjs"; import { __dirname, __name, __require } from "./chunk-2BPV2XV2.mjs"; // ../esbuild/src/build.ts import { createProjectGraphAsync, readProjectsConfigurationFromProjectGraph as readProjectsConfigurationFromProjectGraph2, writeJsonFile } from "@nx/devkit"; // ../build-tools/src/config.ts var DEFAULT_COMPILED_BANNER = `/***************************************** * * \u26A1 Built by Storm Software * *****************************************/ `; var DEFAULT_ENVIRONMENT = "production"; var DEFAULT_TARGET = "esnext"; var DEFAULT_ORGANIZATION = "storm-software"; // ../build-tools/src/plugins/swc.ts import { transform } from "@swc/core"; // ../build-tools/src/plugins/ts-resolve.ts import fs from "node:fs"; import { builtinModules } from "node:module"; import path from "node:path"; import _resolve from "resolve"; // ../build-tools/src/plugins/type-definitions.ts import { stripIndents } from "@nx/devkit"; import { relative } from "path"; // ../build-tools/src/utilities/copy-assets.ts import { CopyAssetsHandler } from "@nx/js/src/utils/assets/copy-assets-handler"; import { glob } from "glob"; import { readFile, writeFile } from "node:fs/promises"; var copyAssets = /* @__PURE__ */ __name(async (config, assets, outputPath, projectRoot, sourceRoot, generatePackageJson2 = true, includeSrc = false, banner, footer) => { const pendingAssets = Array.from(assets ?? []); pendingAssets.push({ input: projectRoot, glob: "*.md", output: "." }); pendingAssets.push({ input: ".", glob: "LICENSE", output: "." }); if (generatePackageJson2 === false) { pendingAssets.push({ input: projectRoot, glob: "package.json", output: "." }); } if (includeSrc === true) { pendingAssets.push({ input: sourceRoot, glob: "**/{*.ts,*.tsx,*.js,*.jsx}", output: "src/" }); } writeTrace(`\u{1F4DD} Copying the following assets to the output directory: ${pendingAssets.map((pendingAsset) => typeof pendingAsset === "string" ? ` - ${pendingAsset} -> ${outputPath}` : ` - ${pendingAsset.input}/${pendingAsset.glob} -> ${joinPaths(outputPath, pendingAsset.output)}`).join("\n")}`, config); const assetHandler = new CopyAssetsHandler({ projectDir: projectRoot, rootDir: config.workspaceRoot, outputDir: outputPath, assets: pendingAssets }); await assetHandler.processAllAssetsOnce(); if (includeSrc === true) { writeDebug(`\u{1F4DD} Adding banner and writing source files: ${joinPaths(outputPath, "src")}`, config); const files = await glob([ joinPaths(config.workspaceRoot, outputPath, "src/**/*.ts"), joinPaths(config.workspaceRoot, outputPath, "src/**/*.tsx"), joinPaths(config.workspaceRoot, outputPath, "src/**/*.js"), joinPaths(config.workspaceRoot, outputPath, "src/**/*.jsx") ]); await Promise.allSettled(files.map(async (file) => writeFile(file, `${banner && typeof banner === "string" ? banner.startsWith("//") ? banner : `// ${banner}` : ""} ${await readFile(file, "utf8")} ${footer && typeof footer === "string" ? footer.startsWith("//") ? footer : `// ${footer}` : ""}`))); } }, "copyAssets"); // ../build-tools/src/utilities/generate-package-json.ts import { calculateProjectBuildableDependencies } from "@nx/js/src/utils/buildable-libs-utils"; import { Glob } from "glob"; import { existsSync, readFileSync } from "node:fs"; import { readFile as readFile2 } from "node:fs/promises"; import { readCachedProjectGraph, readProjectsConfigurationFromProjectGraph } from "nx/src/project-graph/project-graph"; var addPackageDependencies = /* @__PURE__ */ __name(async (workspaceRoot, projectRoot, projectName, packageJson) => { const projectGraph = readCachedProjectGraph(); const projectDependencies = calculateProjectBuildableDependencies(void 0, projectGraph, workspaceRoot, projectName, process.env.NX_TASK_TARGET_TARGET || "build", process.env.NX_TASK_TARGET_CONFIGURATION || "production", true); const localPackages = []; for (const project of projectDependencies.dependencies.filter((dep) => dep.node.type === "lib" && dep.node.data?.root !== projectRoot && dep.node.data?.root !== workspaceRoot)) { const projectNode = project.node; if (projectNode.data.root) { const projectPackageJsonPath = joinPaths(workspaceRoot, projectNode.data.root, "package.json"); if (existsSync(projectPackageJsonPath)) { const projectPackageJsonContent = await readFile2(projectPackageJsonPath, "utf8"); const projectPackageJson = JSON.parse(projectPackageJsonContent); if (projectPackageJson.private !== true) { localPackages.push(projectPackageJson); } } } } if (localPackages.length > 0) { writeTrace(`\u{1F4E6} Adding local packages to package.json: ${localPackages.map((p) => p.name).join(", ")}`); const projectJsonFile = await readFile2(joinPaths(projectRoot, "project.json"), "utf8"); const projectJson = JSON.parse(projectJsonFile); const projectName2 = projectJson.name; const projectConfigurations = readProjectsConfigurationFromProjectGraph(projectGraph); if (!projectConfigurations?.projects?.[projectName2]) { 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 implicitDependencies = projectConfigurations.projects?.[projectName2].implicitDependencies?.reduce((ret, dep) => { if (projectConfigurations.projects?.[dep]) { const depPackageJsonPath = joinPaths(workspaceRoot, projectConfigurations.projects[dep].root, "package.json"); if (existsSync(depPackageJsonPath)) { const depPackageJsonContent = readFileSync(depPackageJsonPath, "utf8"); const depPackageJson = JSON.parse(depPackageJsonContent); if (depPackageJson.private !== true && !ret.includes(depPackageJson.name)) { ret.push(depPackageJson.name); } } } return ret; }, []); packageJson.dependencies = localPackages.reduce((ret, localPackage) => { if (!ret[localPackage.name] && !implicitDependencies?.includes(localPackage.name) && packageJson.devDependencies?.[localPackage.name] === void 0) { ret[localPackage.name] = `^${localPackage.version || "0.0.1"}`; } return ret; }, packageJson.dependencies ?? {}); packageJson.devDependencies = localPackages.reduce((ret, localPackage) => { if (!ret[localPackage.name] && implicitDependencies?.includes(localPackage.name) && packageJson.dependencies?.[localPackage.name] === void 0) { ret[localPackage.name] = localPackage.version || "0.0.1"; } return ret; }, packageJson.devDependencies ?? {}); } else { writeTrace("\u{1F4E6} No local packages dependencies to add to package.json"); } return packageJson; }, "addPackageDependencies"); var addWorkspacePackageJsonFields = /* @__PURE__ */ __name(async (config, projectRoot, sourceRoot, projectName, includeSrc = false, packageJson) => { const workspaceRoot = config.workspaceRoot ? config.workspaceRoot : findWorkspaceRoot(); const workspacePackageJsonContent = await readFile2(joinPaths(workspaceRoot, "package.json"), "utf8"); const workspacePackageJson = JSON.parse(workspacePackageJsonContent); packageJson.type ??= "module"; packageJson.sideEffects ??= false; if (includeSrc === true) { let distSrc = sourceRoot.replace(projectRoot, ""); if (distSrc.startsWith("/")) { distSrc = distSrc.substring(1); } packageJson.source ??= `${joinPaths(distSrc, "index.ts").replaceAll("\\", "/")}`; } packageJson.files ??= [ "dist/**/*" ]; if (includeSrc === true && !packageJson.files.includes("src")) { packageJson.files.push("src/**/*"); } packageJson.publishConfig ??= { access: "public" }; packageJson.description ??= workspacePackageJson.description; packageJson.homepage ??= workspacePackageJson.homepage; packageJson.bugs ??= workspacePackageJson.bugs; packageJson.license ??= workspacePackageJson.license; packageJson.keywords ??= workspacePackageJson.keywords; packageJson.funding ??= workspacePackageJson.funding; packageJson.author ??= workspacePackageJson.author; packageJson.maintainers ??= workspacePackageJson.maintainers; if (!packageJson.maintainers && packageJson.author) { packageJson.maintainers = [ packageJson.author ]; } packageJson.contributors ??= workspacePackageJson.contributors; if (!packageJson.contributors && packageJson.author) { packageJson.contributors = [ packageJson.author ]; } packageJson.repository ??= workspacePackageJson.repository; packageJson.repository.directory ??= projectRoot ? projectRoot : joinPaths("packages", projectName); return packageJson; }, "addWorkspacePackageJsonFields"); // ../config-tools/src/utilities/run.ts import { exec, execSync } from "node:child_process"; var LARGE_BUFFER = 1024 * 1e6; var run = /* @__PURE__ */ __name((config, command, cwd = config.workspaceRoot ?? process.cwd(), stdio = "inherit", env = process.env) => { return execSync(command, { cwd, env: { ...process.env, ...env, CLICOLOR: "true", FORCE_COLOR: "true" }, windowsHide: true, stdio, maxBuffer: LARGE_BUFFER, killSignal: "SIGTERM" }); }, "run"); // ../build-tools/src/utilities/get-entry-points.ts import { glob as glob2 } from "glob"; var getEntryPoints = /* @__PURE__ */ __name(async (config, projectRoot, sourceRoot, entry, emitOnAll = false) => { const workspaceRoot = config.workspaceRoot || findWorkspaceRoot(); const entryPoints = []; if (entry) { if (typeof entry === "string") { entryPoints.push(entry); } else if (Array.isArray(entry)) { entryPoints.push(...entry); } else { entryPoints.push(...Object.values(entry)); } } if (emitOnAll) { entryPoints.push(joinPaths(workspaceRoot, sourceRoot || projectRoot, "**/*.{ts,tsx}")); } const results = await Promise.all(entryPoints.map(async (entryPoint) => { const paths = []; if (entryPoint.includes("*")) { const files = await glob2(entryPoint, { withFileTypes: true, ignore: [ "**/node_modules/**" ] }); paths.push(...files.reduce((ret, filePath) => { const result = correctPaths(joinPaths(filePath.path, filePath.name).replaceAll(correctPaths(workspaceRoot), "").replaceAll(correctPaths(projectRoot), "")); if (result) { writeDebug(`Trying to add entry point ${result} at "${joinPaths(filePath.path, filePath.name)}"`, config); if (!paths.includes(result)) { paths.push(result); } } return ret; }, [])); } else { writeDebug(`Trying to add entry point ${entryPoint}"`, config); if (!paths.includes(entryPoint)) { paths.push(entryPoint); } } return paths; })); return results.filter(Boolean).reduce((ret, result) => { result.forEach((res) => { if (res && !ret.includes(res)) { ret.push(res); } }); return ret; }, []); }, "getEntryPoints"); // ../build-tools/src/utilities/get-env.ts var getEnv = /* @__PURE__ */ __name((builder, options) => { return { STORM_BUILD: builder, STORM_ORG: options.orgName || DEFAULT_ORGANIZATION, STORM_NAME: options.name, STORM_MODE: options.mode || DEFAULT_ENVIRONMENT, STORM_PLATFORM: options.platform, STORM_FORMAT: JSON.stringify(options.format), STORM_TARGET: JSON.stringify(options.target), ...options.env }; }, "getEnv"); // ../build-tools/src/utilities/read-nx-config.ts import { existsSync as existsSync2 } from "node:fs"; import { readFile as readFile3 } from "node:fs/promises"; // ../build-tools/src/utilities/task-graph.ts import { createTaskGraph, mapTargetDefaultsToDependencies } from "nx/src/tasks-runner/create-task-graph"; // ../esbuild/src/build.ts import { watch as createWatcher } from "chokidar"; import defu from "defu"; import { debounce, flatten } from "es-toolkit"; import { map } from "es-toolkit/compat"; import * as esbuild2 from "esbuild"; import { globbySync } from "globby"; import { existsSync as existsSync4 } from "node:fs"; import hf from "node:fs/promises"; import { findWorkspaceRoot as findWorkspaceRoot2 } from "nx/src/utils/find-workspace-root"; // ../esbuild/src/base/renderer-engine.ts import path3 from "node:path"; import { SourceMapConsumer, SourceMapGenerator } from "source-map"; // ../esbuild/src/utilities/output-file.ts import fs2 from "node:fs"; import path2 from "node:path"; var outputFile = /* @__PURE__ */ __name(async (filepath, data, options) => { await fs2.promises.mkdir(path2.dirname(filepath), { recursive: true }); await fs2.promises.writeFile(filepath, data, options); }, "outputFile"); // ../esbuild/src/base/renderer-engine.ts var parseSourceMap = /* @__PURE__ */ __name((map2) => { return typeof map2 === "string" ? JSON.parse(map2) : map2; }, "parseSourceMap"); var isJS = /* @__PURE__ */ __name((path6) => /\.(js|mjs|cjs)$/.test(path6), "isJS"); var isCSS = /* @__PURE__ */ __name((path6) => /\.css$/.test(path6), "isCSS"); var getSourcemapComment = /* @__PURE__ */ __name((inline, map2, filepath, isCssFile) => { if (!map2) return ""; const prefix = isCssFile ? "/*" : "//"; const suffix = isCssFile ? " */" : ""; const url = inline ? `data:application/json;base64,${Buffer.from(typeof map2 === "string" ? map2 : JSON.stringify(map2)).toString("base64")}` : `${path3.basename(filepath)}.map`; return `${prefix}# sourceMappingURL=${url}${suffix}`; }, "getSourcemapComment"); var RendererEngine = class { static { __name(this, "RendererEngine"); } #renderers; #options; constructor(renderers) { this.#renderers = renderers; } setOptions(options) { this.#options = options; } getOptions() { if (!this.#options) { throw new Error(`Renderer options is not set`); } return this.#options; } modifyEsbuildOptions(options) { for (const renderer of this.#renderers) { if (renderer.esbuildOptions) { renderer.esbuildOptions.call(this.getOptions(), options); } } } async buildStarted() { for (const renderer of this.#renderers) { if (renderer.buildStart) { await renderer.buildStart.call(this.getOptions()); } } } async buildFinished({ outputFiles, metafile }) { const files = outputFiles.filter((file) => !file.path.endsWith(".map")).map((file) => { if (isJS(file.path) || isCSS(file.path)) { let relativePath = path3.relative(this.getOptions().config.workspaceRoot, file.path); if (!relativePath.startsWith("\\\\?\\")) { relativePath = relativePath.replace(/\\/g, "/"); } const meta = metafile?.outputs[relativePath]; return { type: "chunk", path: file.path, code: file.text, map: outputFiles.find((f) => f.path === `${file.path}.map`)?.text, entryPoint: meta?.entryPoint, exports: meta?.exports, imports: meta?.imports }; } else { return { type: "asset", path: file.path, contents: file.contents }; } }); const writtenFiles = []; await Promise.all(files.map(async (info) => { for (const renderer of this.#renderers) { if (info.type === "chunk" && renderer.renderChunk) { const result = await renderer.renderChunk.call(this.getOptions(), info.code, info); if (result) { info.code = result.code; if (result.map) { const originalConsumer = await new SourceMapConsumer(parseSourceMap(info.map)); const newConsumer = await new SourceMapConsumer(parseSourceMap(result.map)); const generator = SourceMapGenerator.fromSourceMap(newConsumer); generator.applySourceMap(originalConsumer, info.path); info.map = generator.toJSON(); originalConsumer.destroy(); newConsumer.destroy(); } } } } const inlineSourceMap = this.#options.sourcemap === "inline"; const contents = info.type === "chunk" ? info.code + getSourcemapComment(inlineSourceMap, info.map, info.path, isCSS(info.path)) : info.contents; await outputFile(info.path, contents, { mode: info.type === "chunk" ? info.mode : void 0 }); writtenFiles.push({ get name() { return path3.relative(process.cwd(), info.path); }, get size() { return contents.length; } }); if (info.type === "chunk" && info.map && !inlineSourceMap) { const map2 = typeof info.map === "string" ? JSON.parse(info.map) : info.map; const outPath = `${info.path}.map`; const contents2 = JSON.stringify(map2); await outputFile(outPath, contents2); writtenFiles.push({ get name() { return path3.relative(process.cwd(), outPath); }, get size() { return contents2.length; } }); } })); for (const renderer of this.#renderers) { if (renderer.buildEnd) { await renderer.buildEnd.call(this.getOptions(), { writtenFiles }); } } } }; // ../esbuild/src/clean.ts import { rm } from "node:fs/promises"; async function cleanDirectories(name = "ESBuild", directory, config) { await rm(directory, { recursive: true, force: true }); } __name(cleanDirectories, "cleanDirectories"); // ../esbuild/src/plugins/esm-split-code-to-cjs.ts import * as esbuild from "esbuild"; var esmSplitCodeToCjsPlugin = /* @__PURE__ */ __name((options, resolvedOptions) => ({ name: "storm:esm-split-code-to-cjs", setup(build4) { build4.onEnd(async (result) => { const outFiles = Object.keys(result.metafile?.outputs ?? {}); const jsFiles = outFiles.filter((f) => f.endsWith("js")); await esbuild.build({ outdir: resolvedOptions.outdir, entryPoints: jsFiles, allowOverwrite: true, format: "cjs", logLevel: "error", packages: "external" }); }); } }), "esmSplitCodeToCjsPlugin"); // ../esbuild/src/plugins/fix-imports.ts var fixImportsPlugin = /* @__PURE__ */ __name((options, resolvedOptions) => ({ name: "storm:fix-imports", setup(build4) { build4.onResolve({ filter: /^spdx-exceptions/ }, () => { return { path: __require.resolve("spdx-exceptions") }; }); build4.onResolve({ filter: /^spdx-license-ids/ }, () => { return { path: __require.resolve("spdx-license-ids") }; }); } }), "fixImportsPlugin"); // ../esbuild/src/plugins/native-node-module.ts import { dirname } from "node:path"; var nativeNodeModulesPlugin = /* @__PURE__ */ __name((options, resolvedOptions) => { return { name: "native-node-modules", setup(build4) { build4.onResolve({ filter: /\.node$/, namespace: "file" }, (args) => { const resolvedId = __require.resolve(args.path, { paths: [ args.resolveDir ] }); if (resolvedId.endsWith(".node")) { return { path: resolvedId, namespace: "node-file" }; } return { path: resolvedId }; }); build4.onLoad({ filter: /.*/, namespace: "node-file" }, (args) => { return { contents: ` import path from ${JSON.stringify(args.path)} try { module.exports = require(path) } catch {} `, resolveDir: dirname(args.path) }; }); build4.onResolve({ filter: /\.node$/, namespace: "node-file" }, (args) => ({ path: args.path, namespace: "file" })); const opts = build4.initialOptions; opts.loader = opts.loader || {}; opts.loader[".node"] = "file"; } }; }, "nativeNodeModulesPlugin"); // ../esbuild/src/plugins/node-protocol.ts var nodeProtocolPlugin = /* @__PURE__ */ __name((options, resolvedOptions) => { const nodeProtocol = "node:"; return { name: "node-protocol-plugin", setup({ onResolve }) { onResolve({ filter: /^node:/ }, ({ path: path6 }) => ({ path: path6.slice(nodeProtocol.length), external: true })); } }; }, "nodeProtocolPlugin"); // ../esbuild/src/plugins/on-error.ts var onErrorPlugin = /* @__PURE__ */ __name((options, resolvedOptions) => ({ name: "storm:on-error", setup(build4) { build4.onEnd((result) => { if (result.errors.length > 0 && process.env.WATCH !== "true") { writeError(`The following errors occurred during the build: ${result.errors.map((error) => error.text).join("\n")} `, resolvedOptions.config); throw new Error("Storm esbuild process failed with errors."); } }); } }), "onErrorPlugin"); // ../esbuild/src/plugins/resolve-paths.ts import path4 from "node:path"; function resolvePathsConfig(options, cwd) { if (options?.compilerOptions?.paths) { const paths = Object.entries(options.compilerOptions.paths); const resolvedPaths = paths.map(([key, paths2]) => { return [ key, paths2.map((v) => path4.resolve(cwd, v)) ]; }); return Object.fromEntries(resolvedPaths); } if (options.extends) { const extendsPath = path4.resolve(cwd, options.extends); const extendsDir = path4.dirname(extendsPath); const extendsConfig = __require(extendsPath); return resolvePathsConfig(extendsConfig, extendsDir); } return []; } __name(resolvePathsConfig, "resolvePathsConfig"); var resolvePathsPlugin = /* @__PURE__ */ __name((options, resolvedOptions) => ({ name: "storm:resolve-paths", setup(build4) { const parentTsConfig = build4.initialOptions.tsconfig ? __require(joinPaths(resolvedOptions.config.workspaceRoot, build4.initialOptions.tsconfig)) : __require(joinPaths(resolvedOptions.config.workspaceRoot, "tsconfig.json")); const resolvedTsPaths = resolvePathsConfig(parentTsConfig, options.projectRoot); const packagesRegex = new RegExp(`^(${Object.keys(resolvedTsPaths).join("|")})$`); build4.onResolve({ filter: packagesRegex }, (args) => { if (build4.initialOptions.external?.includes(args.path)) { return { path: args.path, external: true }; } return { path: `${resolvedTsPaths[args.path][0]}/index.ts` }; }); } }), "resolvePathsPlugin"); // ../esbuild/src/plugins/tsc.ts import { Extractor, ExtractorConfig } from "@microsoft/api-extractor"; import { existsSync as existsSync3 } from "node:fs"; import fs3 from "node:fs/promises"; function bundleTypeDefinitions(filename, outfile, externals, options) { const { dependencies, peerDependencies, devDependencies } = __require(joinPaths(options.projectRoot, "package.json")); const dependenciesKeys = Object.keys(dependencies ?? {}).flatMap((p) => [ p, getTypeDependencyPackageName(p) ]); const peerDependenciesKeys = Object.keys(peerDependencies ?? {}).flatMap((p) => [ p, getTypeDependencyPackageName(p) ]); const devDependenciesKeys = Object.keys(devDependencies ?? {}).flatMap((p) => [ p, getTypeDependencyPackageName(p) ]); const includeDeps = devDependenciesKeys; const excludeDeps = /* @__PURE__ */ new Set([ ...dependenciesKeys, ...peerDependenciesKeys, ...externals ]); const bundledPackages = includeDeps.filter((dep) => !excludeDeps.has(dep)); const extractorConfig = ExtractorConfig.prepare({ configObject: { projectFolder: options.projectRoot, mainEntryPointFilePath: filename, bundledPackages, compiler: { tsconfigFilePath: options.tsconfig, overrideTsconfig: { compilerOptions: { paths: {} // bug with api extract + paths } } }, dtsRollup: { enabled: true, untrimmedFilePath: joinPaths(options.outdir, `${outfile}.d.ts`) }, tsdocMetadata: { enabled: false } }, packageJsonFullPath: joinPaths(options.projectRoot, "package.json"), configObjectFullPath: void 0 }); const extractorResult = Extractor.invoke(extractorConfig, { showVerboseMessages: true, localBuild: true }); if (extractorResult.succeeded === false) { writeError(`API Extractor completed with ${extractorResult.errorCount} ${extractorResult.errorCount === 1 ? "error" : "errors"}`); throw new Error("API Extractor completed with errors"); } } __name(bundleTypeDefinitions, "bundleTypeDefinitions"); var tscPlugin = /* @__PURE__ */ __name((options, resolvedOptions) => ({ name: "storm:tsc", setup(build4) { if (options.emitTypes === false) { return; } build4.onStart(async () => { if (process.env.WATCH !== "true" && process.env.DEV !== "true") { await run(resolvedOptions.config, `pnpm exec tsc --project ${resolvedOptions.tsconfig}`, resolvedOptions.config.workspaceRoot); } if (resolvedOptions.bundle && resolvedOptions.entryPoints && resolvedOptions.entryPoints.length > 0 && resolvedOptions.entryPoints[0] && resolvedOptions.entryPoints[0].endsWith(".ts")) { const sourceRoot = resolvedOptions.sourceRoot.replaceAll(resolvedOptions.projectRoot, ""); const typeOutDir = resolvedOptions.outdir; const entryPoint = resolvedOptions.entryPoints[0].replace(sourceRoot, "").replace(/\.ts$/, ""); const bundlePath = joinPaths(resolvedOptions.outdir, entryPoint); let dtsPath; if (existsSync3(joinPaths(resolvedOptions.config.workspaceRoot, typeOutDir, `${entryPoint}.d.ts`))) { dtsPath = joinPaths(resolvedOptions.config.workspaceRoot, typeOutDir, `${entryPoint}.d.ts`); } else if (existsSync3(joinPaths(resolvedOptions.config.workspaceRoot, typeOutDir, `${entryPoint.replace(/^src\//, "")}.d.ts`))) { dtsPath = joinPaths(resolvedOptions.config.workspaceRoot, typeOutDir, `${entryPoint.replace(/^src\//, "")}.d.ts`); } const ext = resolvedOptions.format === "esm" ? "d.mts" : "d.ts"; if (process.env.WATCH !== "true" && process.env.DEV !== "true") { bundleTypeDefinitions(dtsPath, bundlePath, resolvedOptions.external ?? [], resolvedOptions); const dtsContents = await fs3.readFile(`${bundlePath}.d.ts`, "utf8"); await fs3.writeFile(`${bundlePath}.${ext}`, dtsContents); } else { await fs3.writeFile(`${bundlePath}.${ext}`, `export * from './${entryPoint}'`); } } }); } }), "tscPlugin"); function getTypeDependencyPackageName(npmPackage) { if (npmPackage.startsWith("@")) { const [scope, name] = npmPackage.split("/"); return `@types/${scope?.slice(1)}__${name}`; } return `@types/${npmPackage}`; } __name(getTypeDependencyPackageName, "getTypeDependencyPackageName"); // ../esbuild/src/config.ts var getDefaultBuildPlugins = /* @__PURE__ */ __name((options, resolvedOptions) => [ nodeProtocolPlugin(options, resolvedOptions), resolvePathsPlugin(options, resolvedOptions), fixImportsPlugin(options, resolvedOptions), nativeNodeModulesPlugin(options, resolvedOptions), esmSplitCodeToCjsPlugin(options, resolvedOptions), tscPlugin(options, resolvedOptions), onErrorPlugin(options, resolvedOptions) ], "getDefaultBuildPlugins"); var DEFAULT_BUILD_OPTIONS = { platform: "node", target: "node22", format: "cjs", external: [], logLevel: "error", tsconfig: "tsconfig.json", mode: "production", keepNames: true, metafile: true, injectShims: true, color: true, watch: false, bundle: true, clean: true, debug: false, resolveExtensions: [ ".tsx", ".ts", ".cts", ".mts", ".jsx", ".js", ".cjs", ".mjs", ".css", ".json" ], 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: DEFAULT_COMPILED_BANNER }; // ../esbuild/src/plugins/deps-check.ts import { builtinModules as builtinModules2 } from "node:module"; import path5 from "node:path"; var unusedIgnore = [ // these are our dev dependencies /@types\/.*?/, /@typescript-eslint.*?/, /eslint.*?/, "esbuild", "husky", "is-ci", "lint-staged", "prettier", "typescript", "ts-node", "ts-jest", "@swc/core", "@swc/jest", "jest", // these are missing 3rd party deps "spdx-exceptions", "spdx-license-ids", // type-only, so it is not detected "ts-toolbelt", // these are indirectly used by build "buffer" ]; var missingIgnore = [ ".prisma", "@prisma/client", "ts-toolbelt" ]; var depsCheckPlugin = /* @__PURE__ */ __name((bundle) => ({ name: "storm:deps-check", setup(build4) { const pkgJsonPath = path5.join(process.cwd(), "package.json"); const pkgContents = __require(pkgJsonPath); const regDependencies = Object.keys(pkgContents["dependencies"] ?? {}); const devDependencies = Object.keys(pkgContents["devDependencies"] ?? {}); const peerDependencies = Object.keys(pkgContents["peerDependencies"] ?? {}); const dependencies = [ ...regDependencies, ...bundle ? devDependencies : [] ]; const collectedDependencies = /* @__PURE__ */ new Set(); const onlyPackages = /^[^./](?!:)|^\.[^./]|^\.\.[^/]/; build4.onResolve({ filter: onlyPackages }, (args) => { if (args.importer.includes(process.cwd())) { if (args.path[0] === "@") { const [org, pkg] = args.path.split("/"); collectedDependencies.add(`${org}/${pkg}`); } else { const [pkg] = args.path.split("/"); collectedDependencies.add(pkg); } } return { external: true }; }); build4.onEnd(() => { const unusedDependencies = [ ...dependencies ].filter((dep) => { return !collectedDependencies.has(dep) || builtinModules2.includes(dep); }); const missingDependencies = [ ...collectedDependencies ].filter((dep) => { return !dependencies.includes(dep) && !builtinModules2.includes(dep); }); const filteredUnusedDeps = unusedDependencies.filter((dep) => { return !unusedIgnore.some((pattern) => dep.match(pattern)); }); const filteredMissingDeps = missingDependencies.filter((dep) => { return !missingIgnore.some((pattern) => dep.match(pattern)) && !peerDependencies.includes(dep); }); writeWarning(`Unused Dependencies: ${JSON.stringify(filteredUnusedDeps)}`); writeError(`Missing Dependencies: ${JSON.stringify(filteredMissingDeps)}`); if (filteredMissingDeps.length > 0) { throw new Error(`Missing dependencies detected - please install them: ${JSON.stringify(filteredMissingDeps)} `); } }); } }), "depsCheckPlugin"); // ../esbuild/src/renderers/shebang.ts var shebangRenderer = { name: "shebang", renderChunk(_, __, info) { if (info.type === "chunk" && /\.(cjs|js|mjs)$/.test(info.path) && info.code.startsWith("#!")) { info.mode = 493; } } }; // ../esbuild/src/utilities/helpers.ts function handleSync(fn) { try { return fn(); } catch (error_) { return error_; } } __name(handleSync, "handleSync"); async function handleAsync(fn) { try { return await fn(); } catch (error_) { return error_; } } __name(handleAsync, "handleAsync"); var handle = handleSync; handle.async = handleAsync; var skip = Symbol("skip"); function transduceSync(list, transformer) { const transduced = []; for (const [i, element_] of list.entries()) { const transformed = transformer(element_, i); if (transformed !== skip) { transduced[transduced.length] = transformed; } } return transduced; } __name(transduceSync, "transduceSync"); async function transduceAsync(list, transformer) { const transduced = []; await Promise.all(list.entries().map(async ([i, element_]) => { const transformed = await transformer(element_, i); if (transformed !== skip) { transduced[transduced.length] = transformed; } })); return transduced; } __name(transduceAsync, "transduceAsync"); var transduce = transduceSync; transduce.async = transduceAsync; function pipeSync(fn, ...fns) { return (...args) => { let result = fn(...args); for (let i = 0; result !== skip && i < fns.length; ++i) { result = fns[i]?.(result); } return result; }; } __name(pipeSync, "pipeSync"); function pipeAsync(fn, ...fns) { return async (...args) => { let result = await fn(...args); for (let i = 0; result !== skip && i < fns.length; ++i) { result = await fns[i]?.(result); } return result; }; } __name(pipeAsync, "pipeAsync"); var pipe = pipeSync; pipe.async = pipeAsync; // ../esbuild/src/build.ts var resolveOptions = /* @__PURE__ */ __name(async (userOptions) => { const projectRoot = userOptions.projectRoot; const workspaceRoot = findWorkspaceRoot2(projectRoot); if (!workspaceRoot) { throw new Error("Cannot find Nx workspace root"); } const config = await getConfig(workspaceRoot.dir); writeDebug(" \u2699\uFE0F Resolving build options", config); const stopwatch = getStopwatch("Build options resolution"); const projectGraph = await createProjectGraphAsync({ exitOnError: true }); const projectJsonPath = joinPaths(workspaceRoot.dir, projectRoot, "project.json"); if (!existsSync4(projectJsonPath)) { throw new Error("Cannot find project.json configuration"); } const projectJsonFile = await hf.readFile(projectJsonPath, "utf8"); const projectJson = JSON.parse(projectJsonFile); const projectName = projectJson.name; const projectConfigurations = readProjectsConfigurationFromProjectGraph2(projectGraph); if (!projectConfigurations?.projects?.[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 = defu(userOptions, DEFAULT_BUILD_OPTIONS); options.name ??= `${projectName}-${options.format}`; options.target ??= DEFAULT_TARGET; const packageJsonPath = joinPaths(workspaceRoot.dir, options.projectRoot, "package.json"); if (!existsSync4(packageJsonPath)) { throw new Error("Cannot find package.json configuration"); } const env = getEnv("esbuild", options); const result = { ...options, config, mainFields: options.platform === "node" ? [ "module", "main" ] : [ "browser", "module", "main" ], ...userOptions, tsconfig: joinPaths(projectRoot, userOptions.tsconfig ? userOptions.tsconfig.replace(projectRoot, "") : "tsconfig.json"), format: options.format || "cjs", entryPoints: await getEntryPoints(config, projectRoot, projectJson.sourceRoot, userOptions.entry ?? "./src/index.ts", false), outdir: userOptions.outputPath || joinPaths("dist", projectRoot), distDir: userOptions.distDir || "dist", plugins: [], name: userOptions.name || projectName, projectConfigurations, projectName, projectGraph, sourceRoot: userOptions.sourceRoot || projectJson.sourceRoot || joinPaths(projectRoot, "src"), minify: userOptions.minify || !userOptions.debug, verbose: userOptions.verbose || isVerbose() || userOptions.debug === true, includeSrc: userOptions.includeSrc === true, metafile: userOptions.metafile !== false, generatePackageJson: userOptions.generatePackageJson !== false, clean: userOptions.clean !== false, assets: userOptions.assets ?? [], injectShims: userOptions.injectShims !== true, bundle: userOptions.bundle !== false, keepNames: true, watch: userOptions.watch === true, footer: userOptions.footer, banner: { js: options.banner || DEFAULT_COMPILED_BANNER, css: options.banner || DEFAULT_COMPILED_BANNER }, splitting: options.format === "iife" ? false : typeof options.splitting === "boolean" ? options.splitting : options.format === "esm", treeShaking: options.format === "esm", env, define: { STORM_FORMAT: JSON.stringify(options.format || "cjs"), ...options.format === "cjs" && options.injectShims ? { "import.meta.url": "importMetaUrl" } : {}, ...options.define, ...Object.keys(env || {}).reduce((res, key) => { const value = JSON.stringify(env[key]); const safeKey = key.replaceAll("(", "").replaceAll(")", ""); return { ...res, [`process.env.${safeKey}`]: value, [`import.meta.env.${safeKey}`]: value }; }, {}) }, inject: [ options.format === "cjs" && options.injectShims ? joinPaths(__dirname, "../assets/cjs_shims.js") : void 0, options.format === "esm" && options.injectShims && options.platform === "node" ? joinPaths(__dirname, "../assets/esm_shims.js") : void 0 ].filter(Boolean) }; result.plugins = userOptions.plugins ?? getDefaultBuildPlugins(userOptions, result); if (options.inject && Array.isArray(options.inject) && options.inject.length > 0) { result.inject = options.inject.reduce((ret, inj) => { if (inj && typeof inj === "string" && ret.includes(inj)) { ret.push(inj); } return ret; }, result.inject); } delete result.entry; delete result.outputPath; stopwatch(); return result; }, "resolveOptions"); async function generatePackageJson(context2) { if (context2.options.generatePackageJson !== false && existsSync4(joinPaths(context2.options.projectRoot, "package.json"))) { writeDebug(" \u270D\uFE0F Writing package.json file", context2.options.config); const stopwatch = getStopwatch("Write package.json file"); const packageJsonPath = joinPaths(context2.options.projectRoot, "project.json"); if (!existsSync4(packageJsonPath)) { throw new Error("Cannot find package.json configuration"); } const packageJsonFile = await hf.readFile(joinPaths(context2.options.config.workspaceRoot, context2.options.projectRoot, "package.json"), "utf8"); let packageJson = JSON.parse(packageJsonFile); if (!packageJson) { throw new Error("Cannot find package.json configuration file"); } packageJson = await addPackageDependencies(context2.options.config.workspaceRoot, context2.options.projectRoot, context2.options.projectName, packageJson); packageJson = await addWorkspacePackageJsonFields(context2.options.config, context2.options.projectRoot, context2.options.sourceRoot, context2.options.projectName, false, packageJson); packageJson.exports ??= {}; packageJson.exports["./package.json"] ??= "./package.json"; packageJson.exports["."] ??= `.${context2.options.distDir ? `/${context2.options.distDir}` : ""}/index.js`; let entryPoints = [ { in: "./src/index.ts", out: "./src/index.ts" } ]; if (context2.options.entryPoints) { if (Array.isArray(context2.options.entryPoints)) { entryPoints = context2.options.entryPoints.map((entryPoint) => typeof entryPoint === "string" ? { in: entryPoint, out: correctPaths(entryPoint.replaceAll(correctPaths(context2.options.config.workspaceRoot), "").replaceAll(correctPaths(context2.options.projectRoot), "")) } : entryPoint); } for (const entryPoint of entryPoints) { const split = entryPoint.out.split("."); split.pop(); const entry = split.join(".").replaceAll("\\", "/"); packageJson.exports[`./${entry}`] ??= `.${context2.options.distDir ? `/${context2.options.distDir}` : ""}/${entry}.js`; } } if (context2.options.format === "esm") { packageJson.module = packageJson.type === "module" ? `.${context2.options.distDir ? `/${context2.options.distDir}` : ""}/index.js` : `.${context2.options.distDir ? `/${context2.options.distDir}` : ""}/index.mjs`; } else { packageJson.main = packageJson.type === "commonjs" ? `.${context2.options.distDir ? `/${context2.options.distDir}` : ""}/index.js` : `.${context2.options.distDir ? `/${context2.options.distDir}` : ""}/index.cjs`; } packageJson.types = `.${context2.options.distDir ? `/${context2.options.distDir}` : ""}/index.d.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 writeJsonFile(joinPaths(context2.options.outdir, "package.json"), packageJson); stopwatch(); } return context2; } __name(generatePackageJson, "generatePackageJson"); async function createOptions(options) { return flatten(await Promise.all(map(options, (opt) => [ // we defer it so that we don't trigger glob immediately () => resolveOptions(opt) ]))); } __name(createOptions, "createOptions"); async function generateContext(getOptions) { const options = await getOptions(); const rendererEngine = new RendererEngine([ shebangRenderer, ...options.renderers || [] ]); return { options, rendererEngine }; } __name(generateContext, "generateContext"); async function executeEsBuild(context2) { writeDebug(` \u{1F680} Running ${context2.options.name} build`, context2.options.config); const stopwatch = getStopwatch(`${context2.options.name} build`); if (process.env.STORM_WATCH) { const ctx = await esbuild2.context(context2.options); watch(ctx, context2.options); } const options = { ...context2.options }; options.outdir = joinPaths(context2.options.outdir, context2.options.distDir); if (!options.inject || !Array.isArray(options.inject) || options.inject.length === 0 || // eslint-disable-next-line no-constant-binary-expression, @typescript-eslint/no-explicit-any options.inject === {}) { delete options.inject; } delete options.env; delete options.name; delete options.assets; delete options.mode; delete options.orgName; delete options.watch; delete options.clean; delete options.debug; delete options.generatePackageJson; delete options.distDir; delete options.includeSrc; delete options.verbose; delete options.projectRoot; delete options.projectName; delete options.projectGraph; delete options.projectConfigurations; delete options.renderers; delete options.config; delete options.injectShims; delete options.external; writeTrace(`Run esbuild (${context2.options.name}) with the following options: ${formatLogMessage({ ...options, define: "<Hidden>" })}`, context2.options.config); const result = await esbuild2.build(options); await esbuild2.stop(); if (result.metafile) { const metafilePath = `${context2.options.outdir}/${context2.options.name}.meta.json`; await hf.writeFile(metafilePath, JSON.stringify(result.metafile)); } stopwatch(); return context2; } __name(executeEsBuild, "executeEsBuild"); async function copyBuildAssets(context2) { if (context2.result?.errors.length === 0) { writeDebug(` \u{1F4CB} Copying asset files to output directory: ${context2.options.outdir}`, context2.options.config); const stopwatch = getStopwatch(`${context2.options.name} asset copy`); await copyAssets(context2.options.config, context2.options.assets ?? [], context2.options.outdir, context2.options.projectRoot, context2.options.sourceRoot, true, false); stopwatch(); } return context2; } __name(copyBuildAssets, "copyBuildAssets"); async function reportResults(context2) { if (context2.result?.errors.length === 0) { if (context2.result.warnings.length > 0) { writeWarning(` \u{1F6A7} The following warnings occurred during the build: ${context2.result.warnings.map((warning) => warning.text).join("\n")}`, context2.options.config); } writeSuccess(` \u{1F4E6} The ${context2.options.name} build completed successfully`, context2.options.config); } } __name(reportResults, "reportResults"); async function dependencyCheck(options) { if (process.env.DEV === "true") { return void 0; } if (process.env.CI && !process.env.BUILDKITE) { return void 0; } const buildPromise = esbuild2.build({ entryPoints: globbySync("**/*.{j,t}s", { // We don't check dependencies in ecosystem tests because tests are isolated from the build. ignore: [ "./src/__tests__/**/*", "./tests/e2e/**/*", "./dist/**/*" ], gitignore: true }), logLevel: "silent", bundle: true, write: false, outdir: "out", plugins: [ depsCheckPlugin(options.bundle) ] }); await buildPromise.catch(() => { }); return void 0; } __name(dependencyCheck, "dependencyCheck"); async function cleanOutputPath(context2) { if (context2.options.clean !== false && context2.options.outdir) { writeDebug(` \u{1F9F9} Cleaning ${context2.options.name} output path: ${context2.options.outdir}`, context2.options.config); const stopwatch = getStopwatch(`${context2.options.name} output clean`); await cleanDirectories(context2.options.name, context2.options.outdir, context2.options.config); stopwatch(); } return context2; } __name(cleanOutputPath, "cleanOutputPath"); async function build3(options) { writeDebug(` \u26A1 Executing Storm ESBuild pipeline`); const stopwatch = getStopwatch("ESBuild pipeline"); try { const opts = Array.isArray(options) ? options : [ options ]; if (opts.length === 0) { throw new Error("No build options were provided"); } void transduce.async(opts, dependencyCheck); await transduce.async(await createOptions(opts), pipe.async(generateContext, cleanOutputPath, generatePackageJson, executeEsBuild, copyBuildAssets, reportResults)); writeSuccess(" \u{1F3C1} ESBuild pipeline build completed successfully"); } catch (error) { writeFatal("Fatal errors that the build process could not recover from have occured. The build process has been terminated."); throw error; } finally { stopwatch(); } } __name(build3, "build"); var watch = /* @__PURE__ */ __name((context2, options) => { if (!options.watch) { return context2; } const config = { ignoreInitial: true, useFsEvents: true, ignored: [ "./src/__tests__/**/*", "./package.json" ] }; const changeWatcher = createWatcher([ "./src/**/*" ], config); const fastRebuild = debounce(async () => { const timeBefore = Date.now(); const rebuildResult = await handle.async(() => { return context2.rebuild(); }); if (rebuildResult instanceof Error) { writeError(rebuildResult.message); } writeTrace(`${Date.now() - timeBefore}ms [${options.name ?? ""}]`); }, 10); changeWatcher.on("change", fastRebuild); return void 0; }, "watch"); // src/executors/esbuild/executor.ts async function esbuildExecutorFn(options, context2, config) { writeInfo("\u{1F4E6} Running Storm ESBuild executor on the workspace", config); if (!context2.projectsConfigurations?.projects || !context2.projectName || !context2.projectsConfigurations.projects[context2.projectName] || !context2.projectsConfigurations.projects[context2.projectName]?.root) { throw new Error("The Build process failed because the context is not valid. Please run this command from a workspace."); } await build3({ ...options, projectRoot: context2.projectsConfigurations.projects?.[context2.projectName].root, projectName: context2.projectName, sourceRoot: context2.projectsConfigurations.projects?.[context2.projectName]?.sourceRoot, format: options.format, platform: options.format }); return { success: true }; } __name(esbuildExecutorFn, "esbuildExecutorFn"); var executor_default = withRunExecutor("Storm ESBuild build", esbuildExecutorFn, { skipReadingConfig: false, hooks: { applyDefaultOptions: /* @__PURE__ */ __name(async (options, config) => { options.entry ??= [ "src/index.ts" ]; options.outputPath ??= "dist/{projectRoot}"; options.tsconfig ??= "{projectRoot}/tsconfig.json"; return options; }, "applyDefaultOptions") } }); export { esbuildExecutorFn, executor_default };