UNPKG

@storm-software/workspace-tools

Version:

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

549 lines (509 loc) • 21.5 kB
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); async function _asyncNullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return await 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 _chunkNFYP774Djs = require('./chunk-NFYP774D.js'); var _chunkBSW6NZVBjs = require('./chunk-BSW6NZVB.js'); var _chunkLMYTVXGXjs = require('./chunk-LMYTVXGX.js'); var _chunkCQDBLKPFjs = require('./chunk-CQDBLKPF.js'); // ../npm-tools/src/helpers/get-registry.ts var _child_process = require('child_process'); // ../npm-tools/src/constants.ts var DEFAULT_NPM_REGISTRY = "https://registry.npmjs.org"; // ../npm-tools/src/helpers/get-registry.ts async function getRegistry(executable = "npm") { return new Promise((resolve, reject) => { _child_process.exec.call(void 0, `${executable} config get registry`, (error, stdout, stderr) => { if (error && !error.message.toLowerCase().trim().startsWith("npm warn")) { return reject(error); } if (stderr && !stderr.toLowerCase().trim().startsWith("npm warn")) { return reject(stderr); } return resolve(stdout.trim()); }); }); } async function getNpmRegistry() { if (process.env.STORM_REGISTRY_NPM) { return process.env.STORM_REGISTRY_NPM; } const workspaceConfig = await _chunkBSW6NZVBjs.getConfig.call(void 0, ); if (_optionalChain([workspaceConfig, 'optionalAccess', _ => _.registry, 'optionalAccess', _2 => _2.npm])) { return _optionalChain([workspaceConfig, 'optionalAccess', _3 => _3.registry, 'optionalAccess', _4 => _4.npm]); } return DEFAULT_NPM_REGISTRY; } // ../pnpm-tools/src/helpers/replace-deps-aliases.ts var _devkit = require('@nx/devkit'); var _fs = require('fs'); var _promises = require('fs/promises'); var _prettier = require('prettier'); // ../npm-tools/src/helpers/get-version.ts // ../pnpm-tools/src/helpers/catalog.ts var _semver = require('semver'); // ../pnpm-tools/src/helpers/pnpm-workspace.ts var _yaml = require('yaml'); function getPnpmWorkspaceFilePath(workspaceRoot = _chunkLMYTVXGXjs.findWorkspaceRoot.call(void 0, process.cwd())) { const pnpmWorkspacePath = _chunkCQDBLKPFjs.joinPaths.call(void 0, workspaceRoot, "pnpm-workspace.yaml"); if (!_fs.existsSync.call(void 0, pnpmWorkspacePath)) { throw new Error( `No \`pnpm-workspace.yaml\` file found in workspace root (searched in: ${pnpmWorkspacePath}).` ); } return pnpmWorkspacePath; } async function readPnpmWorkspaceFile(workspaceRoot = _chunkLMYTVXGXjs.findWorkspaceRoot.call(void 0, process.cwd())) { const result = await _promises.readFile.call(void 0, getPnpmWorkspaceFilePath(workspaceRoot), "utf8" ); if (!result) { return void 0; } return _yaml.parse.call(void 0, result); } // ../pnpm-tools/src/helpers/catalog.ts async function getCatalogSafe(workspaceRoot = _chunkLMYTVXGXjs.findWorkspaceRoot.call(void 0, process.cwd())) { const pnpmWorkspaceFile = await readPnpmWorkspaceFile(workspaceRoot); if (!pnpmWorkspaceFile) { throw new Error("No pnpm-workspace.yaml file found"); } if (_optionalChain([pnpmWorkspaceFile, 'optionalAccess', _5 => _5.catalog])) { return Object.fromEntries( Object.entries(pnpmWorkspaceFile.catalog).map(([key, value]) => { return [key, value.replaceAll('"', "").replaceAll("'", "")]; }) ); } else { console.warn( `No catalog found in pnpm-workspace.yaml file located in workspace root: ${workspaceRoot} File content: ${JSON.stringify( pnpmWorkspaceFile, null, 2 )}` ); } return void 0; } async function getCatalog(workspaceRoot = _chunkLMYTVXGXjs.findWorkspaceRoot.call(void 0, process.cwd())) { const catalog = await getCatalogSafe(workspaceRoot); if (!catalog) { throw new Error("No catalog entries found in pnpm-workspace.yaml file"); } return catalog; } // ../pnpm-tools/src/helpers/replace-deps-aliases.ts async function replaceDepsAliases(packageRoot = process.cwd(), workspaceRoot = _chunkLMYTVXGXjs.findWorkspaceRoot.call(void 0, packageRoot)) { const packageJsonPath = _chunkCQDBLKPFjs.joinPaths.call(void 0, packageRoot, "package.json"); const packageJsonFile = await _promises.readFile.call(void 0, packageJsonPath, "utf8"); if (!packageJsonFile) { throw new Error( "No package.json file found in package root: " + packageRoot ); } const catalog = await getCatalog(workspaceRoot); const packageJson = JSON.parse(packageJsonFile); const pnpmWorkspacePath = _chunkCQDBLKPFjs.joinPaths.call(void 0, workspaceRoot, "pnpm-workspace.yaml"); if (!_fs.existsSync.call(void 0, pnpmWorkspacePath)) { console.warn( `No \`pnpm-workspace.yaml\` file found in workspace root (searching in: ${pnpmWorkspacePath}). Skipping pnpm catalog read for now.` ); return packageJson; } if (!catalog) { console.warn( `No pnpm catalog found. Skipping dependencies replacement for now.` ); return; } for (const dependencyType of [ "dependencies", "devDependencies", "peerDependencies" ]) { const dependencies = packageJson[dependencyType]; if (!dependencies) { continue; } for (const dependencyName of Object.keys(dependencies)) { if (dependencies[dependencyName] === "catalog:") { if (!catalog) { throw new Error( `Dependency ${dependencyName} is marked as \`catalog:\`, but no catalog exists in the workspace root's \`pnpm-workspace.yaml\` file.` ); } const catalogVersion = catalog[dependencyName]; if (!catalogVersion) { throw new Error("Missing pnpm catalog version for " + dependencyName); } dependencies[dependencyName] = catalogVersion; } else if (dependencies[dependencyName].startsWith("catalog:")) { throw new Error("multiple named catalogs not supported"); } } } let projectGraph; try { projectGraph = _devkit.readCachedProjectGraph.call(void 0, ); } catch (e) { await _devkit.createProjectGraphAsync.call(void 0, ); projectGraph = _devkit.readCachedProjectGraph.call(void 0, ); } const workspacePackages = {}; if (projectGraph) { await Promise.all( Object.keys(projectGraph.nodes).map(async (node) => { const projectNode = projectGraph.nodes[node]; if (_optionalChain([projectNode, 'optionalAccess', _6 => _6.data, 'access', _7 => _7.root])) { const projectPackageJsonPath = _chunkCQDBLKPFjs.joinPaths.call(void 0, workspaceRoot, projectNode.data.root, "package.json" ); if (_fs.existsSync.call(void 0, projectPackageJsonPath)) { const projectPackageJsonContent = await _promises.readFile.call(void 0, projectPackageJsonPath, "utf8" ); const projectPackageJson = JSON.parse(projectPackageJsonContent); if (projectPackageJson.private !== true) { workspacePackages[projectPackageJson.name] = projectPackageJson.version; } } } }) ); } for (const dependencyType of [ "dependencies", "devDependencies", "peerDependencies" ]) { const dependencies = packageJson[dependencyType]; if (!dependencies) { continue; } for (const dependencyName of Object.keys(dependencies)) { if (dependencies[dependencyName].startsWith("workspace:")) { if (workspacePackages[dependencyName]) { dependencies[dependencyName] = `^${workspacePackages[dependencyName]}`; } else { throw new Error( `Workspace dependency ${dependencyName} not found in workspace packages.` ); } } } } return _promises.writeFile.call(void 0, packageJsonPath, await _prettier.format.call(void 0, JSON.stringify(packageJson), { parser: "json", proseWrap: "preserve", trailingComma: "none", tabWidth: 2, semi: true, singleQuote: false, quoteProps: "as-needed", insertPragma: false, bracketSameLine: true, printWidth: 80, bracketSpacing: true, arrowParens: "avoid", endOfLine: "lf", plugins: ["prettier-plugin-packagejson"] }) ); } // src/executors/npm-publish/executor.ts var LARGE_BUFFER = 1024 * 1e6; async function npmPublishExecutorFn(options, context) { const isDryRun = process.env.NX_DRY_RUN === "true" || options.dryRun || false; if (!context.projectName) { throw new Error("The `npm-publish` executor requires a `projectName`."); } const projectConfig = _optionalChain([context, 'access', _8 => _8.projectsConfigurations, 'optionalAccess', _9 => _9.projects, 'optionalAccess', _10 => _10[context.projectName]]); if (!projectConfig) { throw new Error( `Could not find project configuration for \`${context.projectName}\`` ); } const packageRoot = _chunkCQDBLKPFjs.joinPaths.call(void 0, context.root, options.packageRoot || _chunkCQDBLKPFjs.joinPaths.call(void 0, "dist", projectConfig.root) ); const projectRoot = _optionalChain([context, 'access', _11 => _11.projectsConfigurations, 'access', _12 => _12.projects, 'access', _13 => _13[context.projectName], 'optionalAccess', _14 => _14.root]) ? _chunkCQDBLKPFjs.joinPaths.call(void 0, context.root, // eslint-disable-next-line @typescript-eslint/no-non-null-assertion context.projectsConfigurations.projects[context.projectName].root ) : packageRoot; const packageJsonPath = _chunkCQDBLKPFjs.joinPaths.call(void 0, packageRoot, "package.json"); const packageJsonFile = await _promises.readFile.call(void 0, packageJsonPath, "utf8"); if (!packageJsonFile) { throw new Error(`Could not find \`package.json\` at ${packageJsonPath}`); } const packageJson = JSON.parse(packageJsonFile); const projectPackageJsonPath = _chunkCQDBLKPFjs.joinPaths.call(void 0, projectRoot, "package.json"); const projectPackageJsonFile = await _promises.readFile.call(void 0, projectPackageJsonPath, "utf8"); if (!projectPackageJsonFile) { throw new Error( `Could not find \`package.json\` at ${projectPackageJsonPath}` ); } const projectPackageJson = JSON.parse(projectPackageJsonFile); if (packageJson.version !== projectPackageJson.version) { console.warn( `The version in the package.json file at ${packageJsonPath} (current: ${packageJson.version}) does not match the version in the package.json file at ${projectPackageJsonPath} (current: ${projectPackageJson.version}). This file will be updated to match the version in the project package.json file.` ); if (projectPackageJson.version) { packageJson.version = projectPackageJson.version; await _promises.writeFile.call(void 0, packageJsonPath, await _prettier.format.call(void 0, JSON.stringify(packageJson), { parser: "json", proseWrap: "preserve", trailingComma: "none", tabWidth: 2, semi: true, singleQuote: false, quoteProps: "as-needed", insertPragma: false, bracketSameLine: true, printWidth: 80, bracketSpacing: true, arrowParens: "avoid", endOfLine: "lf", plugins: ["prettier-plugin-packagejson"] }) ); } } const packageName = packageJson.name; console.info( `\u{1F680} Running Storm NPM Publish executor on the ${packageName} package` ); const packageTxt = packageName === context.projectName ? `package "${packageName}"` : `package "${packageName}" from project "${context.projectName}"`; if (packageJson.private === true) { console.warn( `Skipped ${packageTxt}, because it has \`"private": true\` in ${packageJsonPath}` ); return { success: true }; } await replaceDepsAliases(packageRoot, context.root); await _chunkNFYP774Djs.addPackageJsonGitHead.call(void 0, packageRoot); const npmPublishCommandSegments = [`npm publish --json`]; const npmViewCommandSegments = [ `npm view ${packageName} versions dist-tags --json` ]; const registry = await _asyncNullishCoalesce(options.registry, async () => ( (await getRegistry() || getNpmRegistry()))); if (registry) { npmPublishCommandSegments.push(`--registry="${registry}" `); npmViewCommandSegments.push(`--registry="${registry}" `); } if (options.otp) { npmPublishCommandSegments.push(`--otp="${options.otp}" `); } if (isDryRun) { npmPublishCommandSegments.push("--dry-run"); } npmPublishCommandSegments.push("--provenance --access=public "); const tag = options.tag || _child_process.execSync.call(void 0, "npm config get tag", { cwd: packageRoot, env: { ...process.env, FORCE_COLOR: "true" }, maxBuffer: LARGE_BUFFER, killSignal: "SIGTERM" }).toString().trim(); if (tag) { npmPublishCommandSegments.push(`--tag="${tag}" `); } if (!isDryRun) { const currentVersion = options.version || packageJson.version; try { try { const result = _child_process.execSync.call(void 0, npmViewCommandSegments.join(" "), { cwd: packageRoot, env: { ...process.env, FORCE_COLOR: "true" }, maxBuffer: LARGE_BUFFER, killSignal: "SIGTERM" }); const resultJson = JSON.parse(result.toString()); const distTags = resultJson["dist-tags"] || {}; if (distTags[tag] === currentVersion) { console.warn( `Skipped ${packageTxt} because v${currentVersion} already exists in ${registry} with tag "${tag}"` ); return { success: true }; } } catch (err) { console.warn("\n ********************** \n"); console.warn( `An error occurred while checking for existing dist-tags ${JSON.stringify(err)} Note: If this is the first time this package has been published to NPM, this can be ignored. ` ); console.info(""); } try { if (!isDryRun) { const command = `npm dist-tag add ${packageName}@${currentVersion} ${tag} --registry="${registry}" `; console.info( `Adding the dist-tag ${tag} - preparing to run the following: ${command} ` ); const result = _child_process.execSync.call(void 0, command, { cwd: packageRoot, env: { ...process.env, FORCE_COLOR: "true" }, maxBuffer: LARGE_BUFFER, killSignal: "SIGTERM" }); console.info( `Added the dist-tag ${tag} to v${currentVersion} for registry "${registry}" Execution response: ${result.toString()} ` ); } else { console.info( `Would add the dist-tag ${tag} to v${currentVersion} for registry "${registry}", but [dry-run] was set. ` ); } return { success: true }; } catch (err) { try { console.warn("\n ********************** \n"); let error = err; if (Buffer.isBuffer(error)) { error = error.toString(); } console.warn( `An error occurred while adding dist-tags: ${error} Note: If this is the first time this package has been published to NPM, this can be ignored. ` ); console.info(""); const stdoutData = JSON.parse(_optionalChain([err, 'access', _15 => _15.stdout, 'optionalAccess', _16 => _16.toString, 'call', _17 => _17()]) || "{}"); if (_optionalChain([stdoutData, 'optionalAccess', _18 => _18.error]) && !(_optionalChain([stdoutData, 'access', _19 => _19.error, 'optionalAccess', _20 => _20.code, 'optionalAccess', _21 => _21.includes, 'call', _22 => _22("E404")]) && _optionalChain([stdoutData, 'access', _23 => _23.error, 'optionalAccess', _24 => _24.summary, 'optionalAccess', _25 => _25.includes, 'call', _26 => _26("no such package available")])) && !(_optionalChain([err, 'access', _27 => _27.stderr, 'optionalAccess', _28 => _28.toString, 'call', _29 => _29(), 'access', _30 => _30.includes, 'call', _31 => _31("E404")]) && _optionalChain([err, 'access', _32 => _32.stderr, 'optionalAccess', _33 => _33.toString, 'call', _34 => _34(), 'access', _35 => _35.includes, 'call', _36 => _36("no such package available")]))) { console.error( "npm dist-tag add error please see below for more information:" ); if (stdoutData.error.summary) { console.error(_optionalChain([stdoutData, 'access', _37 => _37.error, 'optionalAccess', _38 => _38.summary])); } if (stdoutData.error.detail) { console.error(_optionalChain([stdoutData, 'access', _39 => _39.error, 'optionalAccess', _40 => _40.detail])); } if (context.isVerbose) { console.error( `npm dist-tag add stdout: ${JSON.stringify(stdoutData, null, 2)}` ); } return { success: false }; } } catch (err2) { console.error( `Something unexpected went wrong when processing the npm dist-tag add output ${JSON.stringify(err2)}` ); return { success: false }; } } } catch (err) { let error = err; if (Buffer.isBuffer(error)) { error = error.toString(); } console.error("\n ********************** \n"); console.info(""); console.error( "An error occured trying to run the npm dist-tag add command." ); console.error(error); console.info(""); const stdoutData = JSON.parse(_optionalChain([err, 'access', _41 => _41.stdout, 'optionalAccess', _42 => _42.toString, 'call', _43 => _43()]) || "{}"); if (!(_optionalChain([stdoutData, 'access', _44 => _44.error, 'optionalAccess', _45 => _45.code, 'optionalAccess', _46 => _46.includes, 'call', _47 => _47("E404")]) && _optionalChain([stdoutData, 'access', _48 => _48.error, 'optionalAccess', _49 => _49.summary, 'optionalAccess', _50 => _50.toLowerCase, 'call', _51 => _51(), 'access', _52 => _52.includes, 'call', _53 => _53("not found")])) && !(_optionalChain([err, 'access', _54 => _54.stderr, 'optionalAccess', _55 => _55.toString, 'call', _56 => _56(), 'access', _57 => _57.includes, 'call', _58 => _58("E404")]) && _optionalChain([err, 'access', _59 => _59.stderr, 'optionalAccess', _60 => _60.toString, 'call', _61 => _61(), 'access', _62 => _62.toLowerCase, 'call', _63 => _63(), 'access', _64 => _64.includes, 'call', _65 => _65("not found")]))) { console.error( `Something unexpected went wrong when checking for existing dist-tags. Error: ${JSON.stringify(err)} ` ); return { success: false }; } } } try { const cwd = packageRoot; const command = npmPublishCommandSegments.join(" "); console.info( `Running publish command "${command}" in current working directory: "${cwd}" ` ); const result = _child_process.execSync.call(void 0, command, { cwd, env: { ...process.env, FORCE_COLOR: "true" }, maxBuffer: LARGE_BUFFER, killSignal: "SIGTERM" }); if (isDryRun) { console.info( `Would publish to ${registry} with tag "${tag}", but [dry-run] was set ${result ? ` Execution response: ${result.toString()}` : ""} ` ); } else { console.info(`Published to ${registry} with tag "${tag}" ${result ? ` Execution response: ${result.toString()}` : ""} `); } return { success: true }; } catch (err) { try { console.error("\n ********************** \n"); console.info(""); console.error("An error occured running npm publish."); console.error("Please see below for more information:"); console.info(""); const stdoutData = JSON.parse(_optionalChain([err, 'access', _66 => _66.stdout, 'optionalAccess', _67 => _67.toString, 'call', _68 => _68()]) || "{}"); if (stdoutData.error.summary) { console.error(stdoutData.error.summary); console.error(stdoutData.error.summary); } if (stdoutData.error.detail) { console.error(stdoutData.error.detail); } if (context.isVerbose) { console.error( `npm publish stdout: ${JSON.stringify(stdoutData, null, 2)}` ); } console.error("\n ********************** \n"); return { success: false }; } catch (err2) { let error = err2; if (Buffer.isBuffer(error)) { error = error.toString(); } console.error( `Something unexpected went wrong when processing the npm publish output Error: ${JSON.stringify(error)} ` ); console.error("\n ********************** \n"); return { success: false }; } } } exports.LARGE_BUFFER = LARGE_BUFFER; exports.npmPublishExecutorFn = npmPublishExecutorFn;