@backstage/cli-module-build 0.1.4-next.0 → 0.1.5-next.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/bin/backstage-cli-module-build +2 -2
  3. package/dist/commands/buildWorkspace.cjs.js +1 -1
  4. package/dist/commands/buildWorkspace.cjs.js.map +1 -1
  5. package/dist/commands/package/build/command.cjs.js +1 -1
  6. package/dist/commands/package/build/command.cjs.js.map +1 -1
  7. package/dist/commands/package/bundle/command.cjs.js +1 -1
  8. package/dist/commands/package/bundle/command.cjs.js.map +1 -1
  9. package/dist/commands/package/clean.cjs.js +1 -1
  10. package/dist/commands/package/clean.cjs.js.map +1 -1
  11. package/dist/commands/package/postpack.cjs.js +1 -1
  12. package/dist/commands/package/postpack.cjs.js.map +1 -1
  13. package/dist/commands/package/prepack.cjs.js +1 -1
  14. package/dist/commands/package/prepack.cjs.js.map +1 -1
  15. package/dist/commands/package/start/command.cjs.js +1 -1
  16. package/dist/commands/package/start/command.cjs.js.map +1 -1
  17. package/dist/commands/repo/build.cjs.js +1 -1
  18. package/dist/commands/repo/build.cjs.js.map +1 -1
  19. package/dist/commands/repo/clean.cjs.js +1 -1
  20. package/dist/commands/repo/clean.cjs.js.map +1 -1
  21. package/dist/commands/repo/start.cjs.js +1 -1
  22. package/dist/commands/repo/start.cjs.js.map +1 -1
  23. package/dist/lib/packager/createDistWorkspace.cjs.js +2 -0
  24. package/dist/lib/packager/createDistWorkspace.cjs.js.map +1 -1
  25. package/dist/lib/packager/productionPack.cjs.js +73 -0
  26. package/dist/lib/packager/productionPack.cjs.js.map +1 -1
  27. package/dist/lib/runner/startEmbeddedDb.cjs.js +15 -10
  28. package/dist/lib/runner/startEmbeddedDb.cjs.js.map +1 -1
  29. package/dist/package.json.cjs.js +4 -3
  30. package/dist/package.json.cjs.js.map +1 -1
  31. package/package.json +8 -7
@@ -1 +1 @@
1
- {"version":3,"file":"clean.cjs.js","sources":["../../../src/commands/repo/clean.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { cli } from 'cleye';\nimport fs from 'fs-extra';\nimport { resolve as resolvePath } from 'node:path';\nimport { PackageGraph } from '@backstage/cli-node';\nimport { run, targetPaths } from '@backstage/cli-common';\nimport type { CliCommandContext } from '@backstage/cli-node';\n\nexport default async ({ args, info }: CliCommandContext) => {\n cli({ help: info, booleanFlagNegation: true }, undefined, args);\n const packages = await PackageGraph.listTargetPackages();\n\n await fs.remove(targetPaths.resolveRoot('dist'));\n await fs.remove(targetPaths.resolveRoot('dist-types'));\n await fs.remove(targetPaths.resolveRoot('coverage'));\n\n await Promise.all(\n Array.from(Array(10), async () => {\n while (packages.length > 0) {\n const pkg = packages.pop()!;\n const cleanScript = pkg.packageJson.scripts?.clean;\n\n if (\n cleanScript === 'backstage-cli clean' ||\n cleanScript === 'backstage-cli package clean'\n ) {\n await fs.remove(resolvePath(pkg.dir, 'dist'));\n await fs.remove(resolvePath(pkg.dir, 'dist-types'));\n await fs.remove(resolvePath(pkg.dir, 'coverage'));\n } else if (cleanScript) {\n await run(['yarn', 'run', 'clean'], {\n cwd: pkg.dir,\n }).waitForExit();\n }\n }\n }),\n );\n};\n"],"names":["cli","PackageGraph","fs","targetPaths","resolvePath","run"],"mappings":";;;;;;;;;;;;;;AAuBA,YAAe,OAAO,EAAE,IAAA,EAAM,IAAA,EAAK,KAAyB;AAC1D,EAAAA,SAAA,CAAI,EAAE,IAAA,EAAM,IAAA,EAAM,qBAAqB,IAAA,EAAK,EAAG,QAAW,IAAI,CAAA;AAC9D,EAAA,MAAM,QAAA,GAAW,MAAMC,oBAAA,CAAa,kBAAA,EAAmB;AAEvD,EAAA,MAAMC,mBAAA,CAAG,MAAA,CAAOC,qBAAA,CAAY,WAAA,CAAY,MAAM,CAAC,CAAA;AAC/C,EAAA,MAAMD,mBAAA,CAAG,MAAA,CAAOC,qBAAA,CAAY,WAAA,CAAY,YAAY,CAAC,CAAA;AACrD,EAAA,MAAMD,mBAAA,CAAG,MAAA,CAAOC,qBAAA,CAAY,WAAA,CAAY,UAAU,CAAC,CAAA;AAEnD,EAAA,MAAM,OAAA,CAAQ,GAAA;AAAA,IACZ,KAAA,CAAM,IAAA,CAAK,KAAA,CAAM,EAAE,GAAG,YAAY;AAChC,MAAA,OAAO,QAAA,CAAS,SAAS,CAAA,EAAG;AAC1B,QAAA,MAAM,GAAA,GAAM,SAAS,GAAA,EAAI;AACzB,QAAA,MAAM,WAAA,GAAc,GAAA,CAAI,WAAA,CAAY,OAAA,EAAS,KAAA;AAE7C,QAAA,IACE,WAAA,KAAgB,qBAAA,IAChB,WAAA,KAAgB,6BAAA,EAChB;AACA,UAAA,MAAMD,oBAAG,MAAA,CAAOE,iBAAA,CAAY,GAAA,CAAI,GAAA,EAAK,MAAM,CAAC,CAAA;AAC5C,UAAA,MAAMF,oBAAG,MAAA,CAAOE,iBAAA,CAAY,GAAA,CAAI,GAAA,EAAK,YAAY,CAAC,CAAA;AAClD,UAAA,MAAMF,oBAAG,MAAA,CAAOE,iBAAA,CAAY,GAAA,CAAI,GAAA,EAAK,UAAU,CAAC,CAAA;AAAA,QAClD,WAAW,WAAA,EAAa;AACtB,UAAA,MAAMC,aAAA,CAAI,CAAC,MAAA,EAAQ,KAAA,EAAO,OAAO,CAAA,EAAG;AAAA,YAClC,KAAK,GAAA,CAAI;AAAA,WACV,EAAE,WAAA,EAAY;AAAA,QACjB;AAAA,MACF;AAAA,IACF,CAAC;AAAA,GACH;AACF,CAAA;;;;"}
1
+ {"version":3,"file":"clean.cjs.js","sources":["../../../src/commands/repo/clean.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { cli } from 'cleye';\nimport fs from 'fs-extra';\nimport { resolve as resolvePath } from 'node:path';\nimport { PackageGraph } from '@backstage/cli-node';\nimport { run, targetPaths } from '@backstage/cli-common';\nimport type { CliCommandContext } from '@backstage/cli-node';\n\nexport default async ({ args, info }: CliCommandContext) => {\n cli({ name: info.usage, booleanFlagNegation: true }, undefined, args);\n const packages = await PackageGraph.listTargetPackages();\n\n await fs.remove(targetPaths.resolveRoot('dist'));\n await fs.remove(targetPaths.resolveRoot('dist-types'));\n await fs.remove(targetPaths.resolveRoot('coverage'));\n\n await Promise.all(\n Array.from(Array(10), async () => {\n while (packages.length > 0) {\n const pkg = packages.pop()!;\n const cleanScript = pkg.packageJson.scripts?.clean;\n\n if (\n cleanScript === 'backstage-cli clean' ||\n cleanScript === 'backstage-cli package clean'\n ) {\n await fs.remove(resolvePath(pkg.dir, 'dist'));\n await fs.remove(resolvePath(pkg.dir, 'dist-types'));\n await fs.remove(resolvePath(pkg.dir, 'coverage'));\n } else if (cleanScript) {\n await run(['yarn', 'run', 'clean'], {\n cwd: pkg.dir,\n }).waitForExit();\n }\n }\n }),\n );\n};\n"],"names":["cli","PackageGraph","fs","targetPaths","resolvePath","run"],"mappings":";;;;;;;;;;;;;;AAuBA,YAAe,OAAO,EAAE,IAAA,EAAM,IAAA,EAAK,KAAyB;AAC1D,EAAAA,SAAA,CAAI,EAAE,MAAM,IAAA,CAAK,KAAA,EAAO,qBAAqB,IAAA,EAAK,EAAG,QAAW,IAAI,CAAA;AACpE,EAAA,MAAM,QAAA,GAAW,MAAMC,oBAAA,CAAa,kBAAA,EAAmB;AAEvD,EAAA,MAAMC,mBAAA,CAAG,MAAA,CAAOC,qBAAA,CAAY,WAAA,CAAY,MAAM,CAAC,CAAA;AAC/C,EAAA,MAAMD,mBAAA,CAAG,MAAA,CAAOC,qBAAA,CAAY,WAAA,CAAY,YAAY,CAAC,CAAA;AACrD,EAAA,MAAMD,mBAAA,CAAG,MAAA,CAAOC,qBAAA,CAAY,WAAA,CAAY,UAAU,CAAC,CAAA;AAEnD,EAAA,MAAM,OAAA,CAAQ,GAAA;AAAA,IACZ,KAAA,CAAM,IAAA,CAAK,KAAA,CAAM,EAAE,GAAG,YAAY;AAChC,MAAA,OAAO,QAAA,CAAS,SAAS,CAAA,EAAG;AAC1B,QAAA,MAAM,GAAA,GAAM,SAAS,GAAA,EAAI;AACzB,QAAA,MAAM,WAAA,GAAc,GAAA,CAAI,WAAA,CAAY,OAAA,EAAS,KAAA;AAE7C,QAAA,IACE,WAAA,KAAgB,qBAAA,IAChB,WAAA,KAAgB,6BAAA,EAChB;AACA,UAAA,MAAMD,oBAAG,MAAA,CAAOE,iBAAA,CAAY,GAAA,CAAI,GAAA,EAAK,MAAM,CAAC,CAAA;AAC5C,UAAA,MAAMF,oBAAG,MAAA,CAAOE,iBAAA,CAAY,GAAA,CAAI,GAAA,EAAK,YAAY,CAAC,CAAA;AAClD,UAAA,MAAMF,oBAAG,MAAA,CAAOE,iBAAA,CAAY,GAAA,CAAI,GAAA,EAAK,UAAU,CAAC,CAAA;AAAA,QAClD,WAAW,WAAA,EAAa;AACtB,UAAA,MAAMC,aAAA,CAAI,CAAC,MAAA,EAAQ,KAAA,EAAO,OAAO,CAAA,EAAG;AAAA,YAClC,KAAK,GAAA,CAAI;AAAA,WACV,EAAE,WAAA,EAAY;AAAA,QACjB;AAAA,MACF;AAAA,IACF,CAAC;AAAA,GACH;AACF,CAAA;;;;"}
@@ -22,7 +22,7 @@ var start = async ({ args, info }) => {
22
22
  _: namesOrPaths
23
23
  } = cleye.cli(
24
24
  {
25
- help: { ...info, usage: `${info.usage} [packages...]` },
25
+ name: info.usage,
26
26
  booleanFlagNegation: true,
27
27
  parameters: ["[packages...]"],
28
28
  flags: {
@@ -1 +1 @@
1
- {"version":3,"file":"start.cjs.js","sources":["../../../src/commands/repo/start.ts"],"sourcesContent":["/*\n * Copyright 2025 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n BackstagePackage,\n PackageGraph,\n PackageRole,\n} from '@backstage/cli-node';\nimport { relative as relativePath } from 'node:path';\nimport { targetPaths } from '@backstage/cli-common';\nimport { cli } from 'cleye';\n\nimport { resolveLinkedWorkspace } from '../package/start/resolveLinkedWorkspace';\nimport { startPackage } from '../package/start/startPackage';\nimport { parseArgs } from 'node:util';\nimport type { CliCommandContext } from '@backstage/cli-node';\n\nconst ACCEPTED_PACKAGE_ROLES: Array<PackageRole | undefined> = [\n 'frontend',\n 'backend',\n 'frontend-plugin',\n 'backend-plugin',\n];\n\nexport default async ({ args, info }: CliCommandContext) => {\n const {\n flags: { plugin, config, require: requirePath, link, inspect, inspectBrk },\n _: namesOrPaths,\n } = cli(\n {\n help: { ...info, usage: `${info.usage} [packages...]` },\n booleanFlagNegation: true,\n parameters: ['[packages...]'],\n flags: {\n plugin: {\n type: [String],\n description:\n 'Start the dev entry-point for any matching plugin package in the repo',\n default: [],\n },\n config: {\n type: [String],\n description: 'Config files to load instead of app-config.yaml',\n default: [],\n },\n require: {\n type: String,\n description:\n 'Add a --require argument to the node process. Applies to backend package only',\n },\n link: {\n type: String,\n description: 'Link an external workspace for module resolution',\n },\n inspect: {\n type: String,\n description:\n 'Enable the Node.js inspector, optionally at a specific host:port',\n },\n inspectBrk: {\n type: String,\n description:\n 'Enable the Node.js inspector and break before user code starts',\n },\n },\n },\n undefined,\n args,\n );\n\n const targetPackages = await findTargetPackages(namesOrPaths, plugin);\n\n const packageOptions = await resolvePackageOptions(targetPackages, {\n plugin,\n config,\n inspect: inspect || (inspect === '' ? true : undefined),\n inspectBrk: inspectBrk || (inspectBrk === '' ? true : undefined),\n require: requirePath,\n link,\n });\n\n if (packageOptions.length === 0) {\n console.log('No packages found to start');\n return;\n }\n\n console.log(\n `Starting ${packageOptions\n .map(({ pkg }) => pkg.packageJson.name)\n .join(', ')}`,\n );\n\n // Each of these block until interrupted by user\n await Promise.all(packageOptions.map(entry => startPackage(entry.options)));\n};\n\nexport async function findTargetPackages(\n namesOrPaths: string[],\n pluginIds: string[],\n) {\n const targetPackages = new Array<BackstagePackage>();\n\n const packages = await PackageGraph.listTargetPackages();\n\n // Prioritize plugin options, so that the `start` script can contain a list of packages,\n // but make them easy to override by running for example `yarn start --plugin catalog`\n for (const pluginId of pluginIds) {\n const matchingPackages = packages.filter(pkg => {\n return (\n pluginId === pkg.packageJson.backstage?.pluginId &&\n ACCEPTED_PACKAGE_ROLES.includes(pkg.packageJson.backstage.role)\n );\n });\n if (matchingPackages.length === 0) {\n throw new Error(\n `Unable to find any plugin packages with plugin ID '${pluginId}'. Make sure backstage.pluginId is set in your package.json files by running 'yarn fix --publish'.`,\n );\n }\n targetPackages.push(...matchingPackages);\n }\n if (targetPackages.length > 0) {\n return targetPackages;\n }\n\n // Next check if explicit package names are provided, use them in that case.\n for (const nameOrPath of namesOrPaths) {\n let matchingPackage = packages.find(\n pkg => nameOrPath === pkg.packageJson.name,\n );\n if (!matchingPackage) {\n const absPath = targetPaths.resolveRoot(nameOrPath);\n matchingPackage = packages.find(\n pkg => relativePath(pkg.dir, absPath) === '',\n );\n }\n if (!matchingPackage) {\n throw new Error(`Unable to find package by name '${nameOrPath}'`);\n }\n targetPackages.push(matchingPackage);\n }\n\n if (targetPackages.length > 0) {\n return targetPackages;\n }\n\n // If no package names are provided, default to expect a single frontend and/or backend package\n for (const role of ['frontend', 'backend']) {\n const matchingPackages = packages.filter(\n pkg => pkg.packageJson.backstage?.role === role,\n );\n if (matchingPackages.length > 1) {\n // Final fallback is to check for the package path within the monorepo, packages/app or packages/backend\n const expectedPath = targetPaths.resolveRoot(\n role === 'frontend' ? 'packages/app' : 'packages/backend',\n );\n const matchByPath = matchingPackages.find(\n pkg => relativePath(expectedPath, pkg.dir) === '',\n );\n if (matchByPath) {\n targetPackages.push(matchByPath);\n continue;\n }\n\n throw new Error(\n `Found multiple packages with role '${role}' but none of the use the default path '${expectedPath}',` +\n `choose which packages you want to run by passing the package names explicitly ` +\n `as arguments, for example 'yarn backstage-cli repo start my-app my-backend'.`,\n );\n }\n\n targetPackages.push(...matchingPackages);\n }\n if (targetPackages.length > 0) {\n return targetPackages;\n }\n\n // If no app or backend packages are found, fall back to expecting single plugin packages\n for (const role of ['frontend-plugin', 'backend-plugin']) {\n const matchingPackages = packages.filter(\n pkg => pkg.packageJson.backstage?.role === role,\n );\n if (matchingPackages.length > 1) {\n throw new Error(\n `Found multiple packages with role '${role}', please choose which packages you want ` +\n `to run by passing the package names explicitly as arguments, for example ` +\n `'yarn backstage-cli repo start my-plugin my-plugin-backend'.`,\n );\n }\n targetPackages.push(...matchingPackages);\n }\n if (targetPackages.length > 0) {\n return targetPackages;\n }\n\n throw new Error(\n `Unable to find any packages with role 'frontend', 'backend', 'frontend-plugin', or 'backend-plugin'.`,\n );\n}\n\ntype CommandOptions = {\n plugin: string[];\n config: string[];\n inspect?: boolean | string;\n inspectBrk?: boolean | string;\n require?: string;\n link?: string;\n};\n\nasync function resolvePackageOptions(\n targetPackages: BackstagePackage[],\n options: CommandOptions,\n) {\n const linkedWorkspace = await resolveLinkedWorkspace(options.link);\n\n return targetPackages.flatMap(pkg => {\n const startScript = pkg.packageJson.scripts?.start;\n if (!startScript) {\n console.log(\n `No start script found for package ${pkg.packageJson.name}, skipping...`,\n );\n return [];\n }\n\n // Grab and parse --config and --require options from the start scripts, the rest are ignored\n // TODO(Rugvip): Prolly switch over to completely different arg parsing to avoid this duplication\n const { values: parsedOpts } = parseArgs({\n args: startScript.split(' '),\n strict: false,\n options: {\n config: {\n type: 'string',\n multiple: true,\n },\n require: {\n type: 'string',\n },\n },\n });\n const parsedRequire =\n typeof parsedOpts.require === 'string' ? parsedOpts.require : undefined;\n const parsedConfig =\n parsedOpts.config?.filter(c => typeof c === 'string') ?? [];\n\n return [\n {\n pkg,\n options: {\n role: pkg.packageJson.backstage?.role!,\n targetDir: pkg.dir,\n configPaths:\n options.config.length > 0 ? options.config : parsedConfig,\n checksEnabled: false,\n linkedWorkspace,\n inspectEnabled: options.inspect,\n inspectBrkEnabled: options.inspectBrk,\n require: options.require ?? parsedRequire,\n },\n },\n ];\n });\n}\n"],"names":["cli","startPackage","PackageGraph","targetPaths","relativePath","resolveLinkedWorkspace","parseArgs"],"mappings":";;;;;;;;;;;;AA8BA,MAAM,sBAAA,GAAyD;AAAA,EAC7D,UAAA;AAAA,EACA,SAAA;AAAA,EACA,iBAAA;AAAA,EACA;AACF,CAAA;AAEA,YAAe,OAAO,EAAE,IAAA,EAAM,IAAA,EAAK,KAAyB;AAC1D,EAAA,MAAM;AAAA,IACJ,KAAA,EAAO,EAAE,MAAA,EAAQ,MAAA,EAAQ,SAAS,WAAA,EAAa,IAAA,EAAM,SAAS,UAAA,EAAW;AAAA,IACzE,CAAA,EAAG;AAAA,GACL,GAAIA,SAAA;AAAA,IACF;AAAA,MACE,IAAA,EAAM,EAAE,GAAG,IAAA,EAAM,OAAO,CAAA,EAAG,IAAA,CAAK,KAAK,CAAA,cAAA,CAAA,EAAiB;AAAA,MACtD,mBAAA,EAAqB,IAAA;AAAA,MACrB,UAAA,EAAY,CAAC,eAAe,CAAA;AAAA,MAC5B,KAAA,EAAO;AAAA,QACL,MAAA,EAAQ;AAAA,UACN,IAAA,EAAM,CAAC,MAAM,CAAA;AAAA,UACb,WAAA,EACE,uEAAA;AAAA,UACF,SAAS;AAAC,SACZ;AAAA,QACA,MAAA,EAAQ;AAAA,UACN,IAAA,EAAM,CAAC,MAAM,CAAA;AAAA,UACb,WAAA,EAAa,iDAAA;AAAA,UACb,SAAS;AAAC,SACZ;AAAA,QACA,OAAA,EAAS;AAAA,UACP,IAAA,EAAM,MAAA;AAAA,UACN,WAAA,EACE;AAAA,SACJ;AAAA,QACA,IAAA,EAAM;AAAA,UACJ,IAAA,EAAM,MAAA;AAAA,UACN,WAAA,EAAa;AAAA,SACf;AAAA,QACA,OAAA,EAAS;AAAA,UACP,IAAA,EAAM,MAAA;AAAA,UACN,WAAA,EACE;AAAA,SACJ;AAAA,QACA,UAAA,EAAY;AAAA,UACV,IAAA,EAAM,MAAA;AAAA,UACN,WAAA,EACE;AAAA;AACJ;AACF,KACF;AAAA,IACA,MAAA;AAAA,IACA;AAAA,GACF;AAEA,EAAA,MAAM,cAAA,GAAiB,MAAM,kBAAA,CAAmB,YAAA,EAAc,MAAM,CAAA;AAEpE,EAAA,MAAM,cAAA,GAAiB,MAAM,qBAAA,CAAsB,cAAA,EAAgB;AAAA,IAEjE,MAAA;AAAA,IACA,OAAA,EAAS,OAAA,KAAY,OAAA,KAAY,EAAA,GAAK,IAAA,GAAO,MAAA,CAAA;AAAA,IAC7C,UAAA,EAAY,UAAA,KAAe,UAAA,KAAe,EAAA,GAAK,IAAA,GAAO,MAAA,CAAA;AAAA,IACtD,OAAA,EAAS,WAAA;AAAA,IACT;AAAA,GACD,CAAA;AAED,EAAA,IAAI,cAAA,CAAe,WAAW,CAAA,EAAG;AAC/B,IAAA,OAAA,CAAQ,IAAI,4BAA4B,CAAA;AACxC,IAAA;AAAA,EACF;AAEA,EAAA,OAAA,CAAQ,GAAA;AAAA,IACN,CAAA,SAAA,EAAY,cAAA,CACT,GAAA,CAAI,CAAC,EAAE,GAAA,EAAI,KAAM,GAAA,CAAI,WAAA,CAAY,IAAI,CAAA,CACrC,IAAA,CAAK,IAAI,CAAC,CAAA;AAAA,GACf;AAGA,EAAA,MAAM,OAAA,CAAQ,IAAI,cAAA,CAAe,GAAA,CAAI,WAASC,yBAAA,CAAa,KAAA,CAAM,OAAO,CAAC,CAAC,CAAA;AAC5E,CAAA;AAEA,eAAsB,kBAAA,CACpB,cACA,SAAA,EACA;AACA,EAAA,MAAM,cAAA,GAAiB,IAAI,KAAA,EAAwB;AAEnD,EAAA,MAAM,QAAA,GAAW,MAAMC,oBAAA,CAAa,kBAAA,EAAmB;AAIvD,EAAA,KAAA,MAAW,YAAY,SAAA,EAAW;AAChC,IAAA,MAAM,gBAAA,GAAmB,QAAA,CAAS,MAAA,CAAO,CAAA,GAAA,KAAO;AAC9C,MAAA,OACE,QAAA,KAAa,GAAA,CAAI,WAAA,CAAY,SAAA,EAAW,QAAA,IACxC,uBAAuB,QAAA,CAAS,GAAA,CAAI,WAAA,CAAY,SAAA,CAAU,IAAI,CAAA;AAAA,IAElE,CAAC,CAAA;AACD,IAAA,IAAI,gBAAA,CAAiB,WAAW,CAAA,EAAG;AACjC,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,sDAAsD,QAAQ,CAAA,kGAAA;AAAA,OAChE;AAAA,IACF;AACA,IAAA,cAAA,CAAe,IAAA,CAAK,GAAG,gBAAgB,CAAA;AAAA,EACzC;AACA,EAAA,IAAI,cAAA,CAAe,SAAS,CAAA,EAAG;AAC7B,IAAA,OAAO,cAAA;AAAA,EACT;AAGA,EAAA,KAAA,MAAW,cAAc,YAAA,EAAc;AACrC,IAAA,IAAI,kBAAkB,QAAA,CAAS,IAAA;AAAA,MAC7B,CAAA,GAAA,KAAO,UAAA,KAAe,GAAA,CAAI,WAAA,CAAY;AAAA,KACxC;AACA,IAAA,IAAI,CAAC,eAAA,EAAiB;AACpB,MAAA,MAAM,OAAA,GAAUC,qBAAA,CAAY,WAAA,CAAY,UAAU,CAAA;AAClD,MAAA,eAAA,GAAkB,QAAA,CAAS,IAAA;AAAA,QACzB,CAAA,GAAA,KAAOC,kBAAA,CAAa,GAAA,CAAI,GAAA,EAAK,OAAO,CAAA,KAAM;AAAA,OAC5C;AAAA,IACF;AACA,IAAA,IAAI,CAAC,eAAA,EAAiB;AACpB,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,gCAAA,EAAmC,UAAU,CAAA,CAAA,CAAG,CAAA;AAAA,IAClE;AACA,IAAA,cAAA,CAAe,KAAK,eAAe,CAAA;AAAA,EACrC;AAEA,EAAA,IAAI,cAAA,CAAe,SAAS,CAAA,EAAG;AAC7B,IAAA,OAAO,cAAA;AAAA,EACT;AAGA,EAAA,KAAA,MAAW,IAAA,IAAQ,CAAC,UAAA,EAAY,SAAS,CAAA,EAAG;AAC1C,IAAA,MAAM,mBAAmB,QAAA,CAAS,MAAA;AAAA,MAChC,CAAA,GAAA,KAAO,GAAA,CAAI,WAAA,CAAY,SAAA,EAAW,IAAA,KAAS;AAAA,KAC7C;AACA,IAAA,IAAI,gBAAA,CAAiB,SAAS,CAAA,EAAG;AAE/B,MAAA,MAAM,eAAeD,qBAAA,CAAY,WAAA;AAAA,QAC/B,IAAA,KAAS,aAAa,cAAA,GAAiB;AAAA,OACzC;AACA,MAAA,MAAM,cAAc,gBAAA,CAAiB,IAAA;AAAA,QACnC,CAAA,GAAA,KAAOC,kBAAA,CAAa,YAAA,EAAc,GAAA,CAAI,GAAG,CAAA,KAAM;AAAA,OACjD;AACA,MAAA,IAAI,WAAA,EAAa;AACf,QAAA,cAAA,CAAe,KAAK,WAAW,CAAA;AAC/B,QAAA;AAAA,MACF;AAEA,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,CAAA,mCAAA,EAAsC,IAAI,CAAA,wCAAA,EAA2C,YAAY,CAAA,4JAAA;AAAA,OAGnG;AAAA,IACF;AAEA,IAAA,cAAA,CAAe,IAAA,CAAK,GAAG,gBAAgB,CAAA;AAAA,EACzC;AACA,EAAA,IAAI,cAAA,CAAe,SAAS,CAAA,EAAG;AAC7B,IAAA,OAAO,cAAA;AAAA,EACT;AAGA,EAAA,KAAA,MAAW,IAAA,IAAQ,CAAC,iBAAA,EAAmB,gBAAgB,CAAA,EAAG;AACxD,IAAA,MAAM,mBAAmB,QAAA,CAAS,MAAA;AAAA,MAChC,CAAA,GAAA,KAAO,GAAA,CAAI,WAAA,CAAY,SAAA,EAAW,IAAA,KAAS;AAAA,KAC7C;AACA,IAAA,IAAI,gBAAA,CAAiB,SAAS,CAAA,EAAG;AAC/B,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,sCAAsC,IAAI,CAAA,8KAAA;AAAA,OAG5C;AAAA,IACF;AACA,IAAA,cAAA,CAAe,IAAA,CAAK,GAAG,gBAAgB,CAAA;AAAA,EACzC;AACA,EAAA,IAAI,cAAA,CAAe,SAAS,CAAA,EAAG;AAC7B,IAAA,OAAO,cAAA;AAAA,EACT;AAEA,EAAA,MAAM,IAAI,KAAA;AAAA,IACR,CAAA,oGAAA;AAAA,GACF;AACF;AAWA,eAAe,qBAAA,CACb,gBACA,OAAA,EACA;AACA,EAAA,MAAM,eAAA,GAAkB,MAAMC,6CAAA,CAAuB,OAAA,CAAQ,IAAI,CAAA;AAEjE,EAAA,OAAO,cAAA,CAAe,QAAQ,CAAA,GAAA,KAAO;AACnC,IAAA,MAAM,WAAA,GAAc,GAAA,CAAI,WAAA,CAAY,OAAA,EAAS,KAAA;AAC7C,IAAA,IAAI,CAAC,WAAA,EAAa;AAChB,MAAA,OAAA,CAAQ,GAAA;AAAA,QACN,CAAA,kCAAA,EAAqC,GAAA,CAAI,WAAA,CAAY,IAAI,CAAA,aAAA;AAAA,OAC3D;AACA,MAAA,OAAO,EAAC;AAAA,IACV;AAIA,IAAA,MAAM,EAAE,MAAA,EAAQ,UAAA,EAAW,GAAIC,mBAAA,CAAU;AAAA,MACvC,IAAA,EAAM,WAAA,CAAY,KAAA,CAAM,GAAG,CAAA;AAAA,MAC3B,MAAA,EAAQ,KAAA;AAAA,MACR,OAAA,EAAS;AAAA,QACP,MAAA,EAAQ;AAAA,UACN,IAAA,EAAM,QAAA;AAAA,UACN,QAAA,EAAU;AAAA,SACZ;AAAA,QACA,OAAA,EAAS;AAAA,UACP,IAAA,EAAM;AAAA;AACR;AACF,KACD,CAAA;AACD,IAAA,MAAM,gBACJ,OAAO,UAAA,CAAW,OAAA,KAAY,QAAA,GAAW,WAAW,OAAA,GAAU,MAAA;AAChE,IAAA,MAAM,YAAA,GACJ,WAAW,MAAA,EAAQ,MAAA,CAAO,OAAK,OAAO,CAAA,KAAM,QAAQ,CAAA,IAAK,EAAC;AAE5D,IAAA,OAAO;AAAA,MACL;AAAA,QACE,GAAA;AAAA,QACA,OAAA,EAAS;AAAA,UACP,IAAA,EAAM,GAAA,CAAI,WAAA,CAAY,SAAA,EAAW,IAAA;AAAA,UACjC,WAAW,GAAA,CAAI,GAAA;AAAA,UACf,aACE,OAAA,CAAQ,MAAA,CAAO,MAAA,GAAS,CAAA,GAAI,QAAQ,MAAA,GAAS,YAAA;AAAA,UAC/C,aAAA,EAAe,KAAA;AAAA,UACf,eAAA;AAAA,UACA,gBAAgB,OAAA,CAAQ,OAAA;AAAA,UACxB,mBAAmB,OAAA,CAAQ,UAAA;AAAA,UAC3B,OAAA,EAAS,QAAQ,OAAA,IAAW;AAAA;AAC9B;AACF,KACF;AAAA,EACF,CAAC,CAAA;AACH;;;;;"}
1
+ {"version":3,"file":"start.cjs.js","sources":["../../../src/commands/repo/start.ts"],"sourcesContent":["/*\n * Copyright 2025 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n BackstagePackage,\n PackageGraph,\n PackageRole,\n} from '@backstage/cli-node';\nimport { relative as relativePath } from 'node:path';\nimport { targetPaths } from '@backstage/cli-common';\nimport { cli } from 'cleye';\n\nimport { resolveLinkedWorkspace } from '../package/start/resolveLinkedWorkspace';\nimport { startPackage } from '../package/start/startPackage';\nimport { parseArgs } from 'node:util';\nimport type { CliCommandContext } from '@backstage/cli-node';\n\nconst ACCEPTED_PACKAGE_ROLES: Array<PackageRole | undefined> = [\n 'frontend',\n 'backend',\n 'frontend-plugin',\n 'backend-plugin',\n];\n\nexport default async ({ args, info }: CliCommandContext) => {\n const {\n flags: { plugin, config, require: requirePath, link, inspect, inspectBrk },\n _: namesOrPaths,\n } = cli(\n {\n name: info.usage,\n booleanFlagNegation: true,\n parameters: ['[packages...]'],\n flags: {\n plugin: {\n type: [String],\n description:\n 'Start the dev entry-point for any matching plugin package in the repo',\n default: [],\n },\n config: {\n type: [String],\n description: 'Config files to load instead of app-config.yaml',\n default: [],\n },\n require: {\n type: String,\n description:\n 'Add a --require argument to the node process. Applies to backend package only',\n },\n link: {\n type: String,\n description: 'Link an external workspace for module resolution',\n },\n inspect: {\n type: String,\n description:\n 'Enable the Node.js inspector, optionally at a specific host:port',\n },\n inspectBrk: {\n type: String,\n description:\n 'Enable the Node.js inspector and break before user code starts',\n },\n },\n },\n undefined,\n args,\n );\n\n const targetPackages = await findTargetPackages(namesOrPaths, plugin);\n\n const packageOptions = await resolvePackageOptions(targetPackages, {\n plugin,\n config,\n inspect: inspect || (inspect === '' ? true : undefined),\n inspectBrk: inspectBrk || (inspectBrk === '' ? true : undefined),\n require: requirePath,\n link,\n });\n\n if (packageOptions.length === 0) {\n console.log('No packages found to start');\n return;\n }\n\n console.log(\n `Starting ${packageOptions\n .map(({ pkg }) => pkg.packageJson.name)\n .join(', ')}`,\n );\n\n // Each of these block until interrupted by user\n await Promise.all(packageOptions.map(entry => startPackage(entry.options)));\n};\n\nexport async function findTargetPackages(\n namesOrPaths: string[],\n pluginIds: string[],\n) {\n const targetPackages = new Array<BackstagePackage>();\n\n const packages = await PackageGraph.listTargetPackages();\n\n // Prioritize plugin options, so that the `start` script can contain a list of packages,\n // but make them easy to override by running for example `yarn start --plugin catalog`\n for (const pluginId of pluginIds) {\n const matchingPackages = packages.filter(pkg => {\n return (\n pluginId === pkg.packageJson.backstage?.pluginId &&\n ACCEPTED_PACKAGE_ROLES.includes(pkg.packageJson.backstage.role)\n );\n });\n if (matchingPackages.length === 0) {\n throw new Error(\n `Unable to find any plugin packages with plugin ID '${pluginId}'. Make sure backstage.pluginId is set in your package.json files by running 'yarn fix --publish'.`,\n );\n }\n targetPackages.push(...matchingPackages);\n }\n if (targetPackages.length > 0) {\n return targetPackages;\n }\n\n // Next check if explicit package names are provided, use them in that case.\n for (const nameOrPath of namesOrPaths) {\n let matchingPackage = packages.find(\n pkg => nameOrPath === pkg.packageJson.name,\n );\n if (!matchingPackage) {\n const absPath = targetPaths.resolveRoot(nameOrPath);\n matchingPackage = packages.find(\n pkg => relativePath(pkg.dir, absPath) === '',\n );\n }\n if (!matchingPackage) {\n throw new Error(`Unable to find package by name '${nameOrPath}'`);\n }\n targetPackages.push(matchingPackage);\n }\n\n if (targetPackages.length > 0) {\n return targetPackages;\n }\n\n // If no package names are provided, default to expect a single frontend and/or backend package\n for (const role of ['frontend', 'backend']) {\n const matchingPackages = packages.filter(\n pkg => pkg.packageJson.backstage?.role === role,\n );\n if (matchingPackages.length > 1) {\n // Final fallback is to check for the package path within the monorepo, packages/app or packages/backend\n const expectedPath = targetPaths.resolveRoot(\n role === 'frontend' ? 'packages/app' : 'packages/backend',\n );\n const matchByPath = matchingPackages.find(\n pkg => relativePath(expectedPath, pkg.dir) === '',\n );\n if (matchByPath) {\n targetPackages.push(matchByPath);\n continue;\n }\n\n throw new Error(\n `Found multiple packages with role '${role}' but none of the use the default path '${expectedPath}',` +\n `choose which packages you want to run by passing the package names explicitly ` +\n `as arguments, for example 'yarn backstage-cli repo start my-app my-backend'.`,\n );\n }\n\n targetPackages.push(...matchingPackages);\n }\n if (targetPackages.length > 0) {\n return targetPackages;\n }\n\n // If no app or backend packages are found, fall back to expecting single plugin packages\n for (const role of ['frontend-plugin', 'backend-plugin']) {\n const matchingPackages = packages.filter(\n pkg => pkg.packageJson.backstage?.role === role,\n );\n if (matchingPackages.length > 1) {\n throw new Error(\n `Found multiple packages with role '${role}', please choose which packages you want ` +\n `to run by passing the package names explicitly as arguments, for example ` +\n `'yarn backstage-cli repo start my-plugin my-plugin-backend'.`,\n );\n }\n targetPackages.push(...matchingPackages);\n }\n if (targetPackages.length > 0) {\n return targetPackages;\n }\n\n throw new Error(\n `Unable to find any packages with role 'frontend', 'backend', 'frontend-plugin', or 'backend-plugin'.`,\n );\n}\n\ntype CommandOptions = {\n plugin: string[];\n config: string[];\n inspect?: boolean | string;\n inspectBrk?: boolean | string;\n require?: string;\n link?: string;\n};\n\nasync function resolvePackageOptions(\n targetPackages: BackstagePackage[],\n options: CommandOptions,\n) {\n const linkedWorkspace = await resolveLinkedWorkspace(options.link);\n\n return targetPackages.flatMap(pkg => {\n const startScript = pkg.packageJson.scripts?.start;\n if (!startScript) {\n console.log(\n `No start script found for package ${pkg.packageJson.name}, skipping...`,\n );\n return [];\n }\n\n // Grab and parse --config and --require options from the start scripts, the rest are ignored\n // TODO(Rugvip): Prolly switch over to completely different arg parsing to avoid this duplication\n const { values: parsedOpts } = parseArgs({\n args: startScript.split(' '),\n strict: false,\n options: {\n config: {\n type: 'string',\n multiple: true,\n },\n require: {\n type: 'string',\n },\n },\n });\n const parsedRequire =\n typeof parsedOpts.require === 'string' ? parsedOpts.require : undefined;\n const parsedConfig =\n parsedOpts.config?.filter(c => typeof c === 'string') ?? [];\n\n return [\n {\n pkg,\n options: {\n role: pkg.packageJson.backstage?.role!,\n targetDir: pkg.dir,\n configPaths:\n options.config.length > 0 ? options.config : parsedConfig,\n checksEnabled: false,\n linkedWorkspace,\n inspectEnabled: options.inspect,\n inspectBrkEnabled: options.inspectBrk,\n require: options.require ?? parsedRequire,\n },\n },\n ];\n });\n}\n"],"names":["cli","startPackage","PackageGraph","targetPaths","relativePath","resolveLinkedWorkspace","parseArgs"],"mappings":"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"}
@@ -179,6 +179,7 @@ async function moveToDistWorkspace(workspaceDir, localPackages, alwaysPack, enab
179
179
  localPackages,
180
180
  (pkg) => !alwaysPack && FAST_PACK_SCRIPTS.includes(pkg.packageJson.scripts?.prepack)
181
181
  );
182
+ const configSchemas = await productionPack.compilePackageConfigSchemas(fastPackPackages);
182
183
  const featureDetectionProject = fastPackPackages.length > 0 && enableFeatureDetection ? await typeDistProject.createTypeDistProject() : void 0;
183
184
  await Promise.all(
184
185
  fastPackPackages.map(async (target) => {
@@ -188,6 +189,7 @@ async function moveToDistWorkspace(workspaceDir, localPackages, alwaysPack, enab
188
189
  await productionPack.productionPack({
189
190
  packageDir: target.dir,
190
191
  targetDir: absoluteOutputPath,
192
+ configSchema: configSchemas.get(target.name),
191
193
  featureDetectionProject
192
194
  });
193
195
  })
@@ -1 +1 @@
1
- {"version":3,"file":"createDistWorkspace.cjs.js","sources":["../../../src/lib/packager/createDistWorkspace.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport chalk from 'chalk';\nimport fs from 'fs-extra';\nimport {\n join as joinPath,\n resolve as resolvePath,\n relative as relativePath,\n} from 'node:path';\nimport { tmpdir } from 'node:os';\nimport * as tar from 'tar';\nimport partition from 'lodash/partition';\n\nimport { run, targetPaths } from '@backstage/cli-common';\nimport { computeTopologicalLayers } from './computeTopologicalLayers';\nimport {\n dependencies as cliDependencies,\n devDependencies as cliDevDependencies,\n} from '../../../package.json';\nimport {\n BuildOptions,\n buildPackages,\n getOutputsForRole,\n Output,\n} from '../builder';\nimport { productionPack } from './productionPack';\nimport {\n BackstagePackage,\n PackageRoles,\n PackageGraph,\n PackageGraphNode,\n runConcurrentTasks,\n} from '@backstage/cli-node';\nimport { createTypeDistProject } from '../typeDistProject';\n\n// These packages aren't safe to pack in parallel since the CLI depends on them\nconst UNSAFE_PACKAGES = [\n ...Object.keys(cliDependencies),\n ...Object.keys(cliDevDependencies),\n];\n\ntype FileEntry =\n | string\n | {\n src: string;\n dest: string;\n };\n\ntype Options = {\n /**\n * Target directory for the dist workspace, defaults to a temporary directory\n */\n targetDir?: string;\n\n /**\n * Configuration files to load during packaging.\n */\n configPaths?: string[];\n\n /**\n * Files to copy into the target workspace.\n *\n * Defaults to ['yarn.lock', 'package.json'].\n */\n files?: FileEntry[];\n\n /**\n * If set to true, the target packages are built before they are packaged into the workspace.\n */\n buildDependencies?: boolean;\n\n /**\n * When `buildDependencies` is set, this list of packages will not be built even if they are dependencies.\n */\n buildExcludes?: string[];\n\n /**\n * If set, creates a skeleton tarball that contains all package.json files\n * with the same structure as the workspace dir.\n */\n skeleton?: 'skeleton.tar' | 'skeleton.tar.gz';\n\n /**\n * If set to true, `yarn pack` is always preferred when creating the dist\n * workspace. This ensures correct workspace output at significant cost to\n * command performance.\n */\n alwaysPack?: boolean;\n\n /**\n * If set to true, the TypeScript feature detection will be enabled, which\n * annotates the package exports field with the `backstage` export type.\n */\n enableFeatureDetection?: boolean;\n\n /**\n * If set to true, the generated code will be minified.\n */\n minify?: boolean;\n\n /**\n * Optional logger to route console output through. When not provided,\n * output goes to `console.log` / `console.warn` as before.\n */\n logger?: {\n log(msg: string): void;\n warn(msg: string): void;\n };\n};\n\nfunction prefixLogFunc(prefix: string, logFn: (msg: string) => void) {\n return (data: Buffer) => {\n for (const line of data.toString('utf8').split(/\\r?\\n/)) {\n if (line) logFn(`${prefix}${line}`);\n }\n };\n}\n\n/**\n * Uses `yarn pack` to package local packages and unpacks them into a dist workspace.\n * The target workspace will end up containing dist version of each package and\n * will be suitable for packaging e.g. into a docker image.\n *\n * This creates a structure that is functionally similar to if the packages were\n * installed from npm, but uses Yarn workspaces to link to them at runtime.\n */\nexport async function createDistWorkspace(\n packageNames: string[],\n options: Options = {},\n) {\n const logger = options.logger ?? { log: console.log, warn: console.warn };\n\n const targetDir =\n options.targetDir ??\n (await fs.mkdtemp(resolvePath(tmpdir(), 'dist-workspace')));\n\n const packages = await PackageGraph.listTargetPackages();\n const targets = await resolveLocalDependencies(packageNames, packages);\n\n if (options.buildDependencies) {\n const exclude = options.buildExcludes ?? [];\n const configPaths = options.configPaths ?? [];\n\n const toBuild = new Set(\n targets.map(_ => _.name).filter(name => !exclude.includes(name)),\n );\n\n const standardBuilds = new Array<BuildOptions>();\n const customBuild = new Array<{\n dir: string;\n name: string;\n args?: string[];\n }>();\n\n for (const pkg of packages) {\n if (!toBuild.has(pkg.packageJson.name)) {\n continue;\n }\n const role = pkg.packageJson.backstage?.role;\n if (!role) {\n logger.warn(\n `Building ${pkg.packageJson.name} separately because it has no role`,\n );\n customBuild.push({ dir: pkg.dir, name: pkg.packageJson.name });\n continue;\n }\n\n const buildScript = pkg.packageJson.scripts?.build;\n if (!buildScript) {\n customBuild.push({ dir: pkg.dir, name: pkg.packageJson.name });\n continue;\n }\n\n if (!buildScript.startsWith('backstage-cli package build')) {\n logger.warn(\n `Building ${pkg.packageJson.name} separately because it has a custom build script, '${buildScript}'`,\n );\n customBuild.push({ dir: pkg.dir, name: pkg.packageJson.name });\n continue;\n }\n\n if (PackageRoles.getRoleInfo(role).output.includes('bundle')) {\n logger.warn(\n `Building ${pkg.packageJson.name} separately because it is a bundled package`,\n );\n const args = buildScript.includes('--config')\n ? []\n : configPaths.map(p => ['--config', p]).flat();\n customBuild.push({ dir: pkg.dir, name: pkg.packageJson.name, args });\n continue;\n }\n\n const outputs = getOutputsForRole(role);\n\n // No need to build and include types in the production runtime\n outputs.delete(Output.types);\n\n if (outputs.size > 0) {\n standardBuilds.push({\n targetDir: pkg.dir,\n packageJson: pkg.packageJson,\n outputs: outputs,\n logPrefix: `${chalk.cyan(\n relativePath(targetPaths.rootDir, pkg.dir),\n )}: `,\n minify: options.minify,\n workspacePackages: packages,\n });\n }\n }\n\n await buildPackages(standardBuilds);\n\n if (customBuild.length > 0) {\n await runConcurrentTasks({\n items: customBuild,\n worker: async ({ name, dir, args }) => {\n await run(['yarn', 'run', 'build', ...(args || [])], {\n cwd: dir,\n onStdout: prefixLogFunc(`${name}: `, logger.log),\n onStderr: prefixLogFunc(`${name}: `, logger.warn),\n }).waitForExit();\n },\n });\n }\n }\n\n await moveToDistWorkspace(\n targetDir,\n targets,\n Boolean(options.alwaysPack),\n Boolean(options.enableFeatureDetection),\n logger,\n );\n\n const files: FileEntry[] = options.files ?? ['yarn.lock', 'package.json'];\n\n for (const file of files) {\n const src = typeof file === 'string' ? file : file.src;\n const dest = typeof file === 'string' ? file : file.dest;\n await fs.copy(targetPaths.resolveRoot(src), resolvePath(targetDir, dest));\n }\n\n if (options.skeleton) {\n const skeletonFiles = targets\n .map(target => {\n const dir = relativePath(targetPaths.rootDir, target.dir);\n return joinPath(dir, 'package.json');\n })\n .sort();\n\n await tar.create(\n {\n file: resolvePath(targetDir, options.skeleton),\n cwd: targetDir,\n portable: true,\n noMtime: true,\n gzip: options.skeleton.endsWith('.gz'),\n },\n skeletonFiles,\n );\n }\n\n return { targetDir, targets };\n}\n\nconst FAST_PACK_SCRIPTS = [\n undefined,\n 'backstage-cli prepack',\n 'backstage-cli package prepack',\n];\n\n/**\n * Runs `yarn pack` on a single package and extracts the resulting tarball\n * into `targetDir`. This resolves `workspace:^` and `backstage:^` dependency\n * specs to concrete versions via yarn's `beforeWorkspacePacking` hook.\n */\nexport async function packToDirectory(options: {\n packageDir: string;\n packageName: string;\n targetDir: string;\n archivePath?: string;\n logger: { log(msg: string): void; warn(msg: string): void };\n}): Promise<void> {\n const { packageDir, packageName, targetDir, logger } = options;\n const archivePath =\n options.archivePath ?? resolvePath(targetDir, 'temp-archive.tgz');\n const prefix = `${packageName} [pack]: `;\n\n await fs.ensureDir(targetDir);\n await run(['yarn', 'pack', '--filename', archivePath], {\n cwd: packageDir,\n onStdout: prefixLogFunc(prefix, logger.log),\n onStderr: prefixLogFunc(prefix, logger.warn),\n }).waitForExit();\n\n await tar.extract({ file: archivePath, cwd: targetDir, strip: 1 });\n await fs.remove(archivePath);\n}\n\nasync function moveToDistWorkspace(\n workspaceDir: string,\n localPackages: PackageGraphNode[],\n alwaysPack: boolean,\n enableFeatureDetection: boolean,\n logger: { log(msg: string): void; warn(msg: string): void },\n): Promise<void> {\n const [fastPackPackages, slowPackPackages] = partition(\n localPackages,\n pkg =>\n !alwaysPack &&\n FAST_PACK_SCRIPTS.includes(pkg.packageJson.scripts?.prepack),\n );\n\n const featureDetectionProject =\n fastPackPackages.length > 0 && enableFeatureDetection\n ? await createTypeDistProject()\n : undefined;\n\n // New an improved flow where we avoid calling `yarn pack`\n await Promise.all(\n fastPackPackages.map(async target => {\n logger.log(`Moving ${target.name} into dist workspace`);\n\n const outputDir = relativePath(targetPaths.rootDir, target.dir);\n const absoluteOutputPath = resolvePath(workspaceDir, outputDir);\n await productionPack({\n packageDir: target.dir,\n targetDir: absoluteOutputPath,\n featureDetectionProject,\n });\n }),\n );\n\n // Old flow is below, which calls `yarn pack` and extracts the tarball\n\n let archiveIndex = 0;\n\n async function pack(\n target: PackageGraphNode,\n archive: string = `temp-package-${archiveIndex++}.tgz`,\n ) {\n logger.log(`Repacking ${target.name} into dist workspace`);\n\n const absoluteOutputPath = resolvePath(\n workspaceDir,\n relativePath(targetPaths.rootDir, target.dir),\n );\n await packToDirectory({\n packageDir: target.dir,\n packageName: target.name,\n targetDir: absoluteOutputPath,\n archivePath: resolvePath(workspaceDir, archive),\n logger,\n });\n\n // We remove the dependencies from package.json of packages that are marked\n // as bundled, so that yarn doesn't try to install them.\n if (target.packageJson.bundled) {\n const pkgJson = await fs.readJson(\n resolvePath(absoluteOutputPath, 'package.json'),\n );\n delete pkgJson.dependencies;\n delete pkgJson.devDependencies;\n delete pkgJson.peerDependencies;\n delete pkgJson.optionalDependencies;\n\n await fs.writeJson(\n resolvePath(absoluteOutputPath, 'package.json'),\n pkgJson,\n {\n spaces: 2,\n },\n );\n }\n }\n\n const [unsafePackages, safePackages] = partition(slowPackPackages, p =>\n UNSAFE_PACKAGES.includes(p.name),\n );\n\n // The unsafe package are packed first one by one in order to avoid race conditions\n // where the CLI is being executed with broken dependencies.\n for (const target of unsafePackages) {\n await pack(target, `temp-package.tgz`);\n }\n\n // Pack safe packages in topological layers so that a package is never\n // packed concurrently with its own dependencies. `yarn pack` temporarily\n // rewrites each package's package.json to resolve workspace:^ references;\n // packing a package while a dependency's manifest is mid-rewrite causes\n // intermittent \"No local workspace found for this range\" failures.\n const layers = computeTopologicalLayers(safePackages);\n for (const layer of layers) {\n await runConcurrentTasks({\n items: layer,\n worker: pack,\n });\n }\n}\n\n/**\n * Resolves the full set of local (workspace) packages that the given\n * package names transitively depend on via `publishedLocalDependencies`.\n * Packages marked as `bundled` have their own dependencies excluded.\n *\n * This is the same traversal that `createDistWorkspace` performs internally.\n * Callers must supply the monorepo package list obtained from\n * `PackageGraph.listTargetPackages()`.\n */\nexport async function resolveLocalDependencies(\n packageNames: string[],\n packages: BackstagePackage[],\n): Promise<PackageGraphNode[]> {\n const packageGraph = PackageGraph.fromPackages(packages);\n const targetNames = packageGraph.collectPackageNames(packageNames, node => {\n // Don't include dependencies of packages that are marked as bundled\n if (node.packageJson.bundled) {\n return undefined;\n }\n\n return node.publishedLocalDependencies.keys();\n });\n return Array.from(targetNames).map(name => packageGraph.get(name)!);\n}\n"],"names":["cliDependencies","cliDevDependencies","fs","resolvePath","tmpdir","PackageGraph","PackageRoles","getOutputsForRole","Output","chalk","relativePath","targetPaths","buildPackages","runConcurrentTasks","run","joinPath","tar","partition","createTypeDistProject","productionPack","computeTopologicalLayers"],"mappings":"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"}
1
+ {"version":3,"file":"createDistWorkspace.cjs.js","sources":["../../../src/lib/packager/createDistWorkspace.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport chalk from 'chalk';\nimport fs from 'fs-extra';\nimport {\n join as joinPath,\n resolve as resolvePath,\n relative as relativePath,\n} from 'node:path';\nimport { tmpdir } from 'node:os';\nimport * as tar from 'tar';\nimport partition from 'lodash/partition';\n\nimport { run, targetPaths } from '@backstage/cli-common';\nimport { computeTopologicalLayers } from './computeTopologicalLayers';\nimport {\n dependencies as cliDependencies,\n devDependencies as cliDevDependencies,\n} from '../../../package.json';\nimport {\n BuildOptions,\n buildPackages,\n getOutputsForRole,\n Output,\n} from '../builder';\nimport { compilePackageConfigSchemas, productionPack } from './productionPack';\nimport {\n BackstagePackage,\n PackageRoles,\n PackageGraph,\n PackageGraphNode,\n runConcurrentTasks,\n} from '@backstage/cli-node';\nimport { createTypeDistProject } from '../typeDistProject';\n\n// These packages aren't safe to pack in parallel since the CLI depends on them\nconst UNSAFE_PACKAGES = [\n ...Object.keys(cliDependencies),\n ...Object.keys(cliDevDependencies),\n];\n\ntype FileEntry =\n | string\n | {\n src: string;\n dest: string;\n };\n\ntype Options = {\n /**\n * Target directory for the dist workspace, defaults to a temporary directory\n */\n targetDir?: string;\n\n /**\n * Configuration files to load during packaging.\n */\n configPaths?: string[];\n\n /**\n * Files to copy into the target workspace.\n *\n * Defaults to ['yarn.lock', 'package.json'].\n */\n files?: FileEntry[];\n\n /**\n * If set to true, the target packages are built before they are packaged into the workspace.\n */\n buildDependencies?: boolean;\n\n /**\n * When `buildDependencies` is set, this list of packages will not be built even if they are dependencies.\n */\n buildExcludes?: string[];\n\n /**\n * If set, creates a skeleton tarball that contains all package.json files\n * with the same structure as the workspace dir.\n */\n skeleton?: 'skeleton.tar' | 'skeleton.tar.gz';\n\n /**\n * If set to true, `yarn pack` is always preferred when creating the dist\n * workspace. This ensures correct workspace output at significant cost to\n * command performance.\n */\n alwaysPack?: boolean;\n\n /**\n * If set to true, the TypeScript feature detection will be enabled, which\n * annotates the package exports field with the `backstage` export type.\n */\n enableFeatureDetection?: boolean;\n\n /**\n * If set to true, the generated code will be minified.\n */\n minify?: boolean;\n\n /**\n * Optional logger to route console output through. When not provided,\n * output goes to `console.log` / `console.warn` as before.\n */\n logger?: {\n log(msg: string): void;\n warn(msg: string): void;\n };\n};\n\nfunction prefixLogFunc(prefix: string, logFn: (msg: string) => void) {\n return (data: Buffer) => {\n for (const line of data.toString('utf8').split(/\\r?\\n/)) {\n if (line) logFn(`${prefix}${line}`);\n }\n };\n}\n\n/**\n * Uses `yarn pack` to package local packages and unpacks them into a dist workspace.\n * The target workspace will end up containing dist version of each package and\n * will be suitable for packaging e.g. into a docker image.\n *\n * This creates a structure that is functionally similar to if the packages were\n * installed from npm, but uses Yarn workspaces to link to them at runtime.\n */\nexport async function createDistWorkspace(\n packageNames: string[],\n options: Options = {},\n) {\n const logger = options.logger ?? { log: console.log, warn: console.warn };\n\n const targetDir =\n options.targetDir ??\n (await fs.mkdtemp(resolvePath(tmpdir(), 'dist-workspace')));\n\n const packages = await PackageGraph.listTargetPackages();\n const targets = await resolveLocalDependencies(packageNames, packages);\n\n if (options.buildDependencies) {\n const exclude = options.buildExcludes ?? [];\n const configPaths = options.configPaths ?? [];\n\n const toBuild = new Set(\n targets.map(_ => _.name).filter(name => !exclude.includes(name)),\n );\n\n const standardBuilds = new Array<BuildOptions>();\n const customBuild = new Array<{\n dir: string;\n name: string;\n args?: string[];\n }>();\n\n for (const pkg of packages) {\n if (!toBuild.has(pkg.packageJson.name)) {\n continue;\n }\n const role = pkg.packageJson.backstage?.role;\n if (!role) {\n logger.warn(\n `Building ${pkg.packageJson.name} separately because it has no role`,\n );\n customBuild.push({ dir: pkg.dir, name: pkg.packageJson.name });\n continue;\n }\n\n const buildScript = pkg.packageJson.scripts?.build;\n if (!buildScript) {\n customBuild.push({ dir: pkg.dir, name: pkg.packageJson.name });\n continue;\n }\n\n if (!buildScript.startsWith('backstage-cli package build')) {\n logger.warn(\n `Building ${pkg.packageJson.name} separately because it has a custom build script, '${buildScript}'`,\n );\n customBuild.push({ dir: pkg.dir, name: pkg.packageJson.name });\n continue;\n }\n\n if (PackageRoles.getRoleInfo(role).output.includes('bundle')) {\n logger.warn(\n `Building ${pkg.packageJson.name} separately because it is a bundled package`,\n );\n const args = buildScript.includes('--config')\n ? []\n : configPaths.map(p => ['--config', p]).flat();\n customBuild.push({ dir: pkg.dir, name: pkg.packageJson.name, args });\n continue;\n }\n\n const outputs = getOutputsForRole(role);\n\n // No need to build and include types in the production runtime\n outputs.delete(Output.types);\n\n if (outputs.size > 0) {\n standardBuilds.push({\n targetDir: pkg.dir,\n packageJson: pkg.packageJson,\n outputs: outputs,\n logPrefix: `${chalk.cyan(\n relativePath(targetPaths.rootDir, pkg.dir),\n )}: `,\n minify: options.minify,\n workspacePackages: packages,\n });\n }\n }\n\n await buildPackages(standardBuilds);\n\n if (customBuild.length > 0) {\n await runConcurrentTasks({\n items: customBuild,\n worker: async ({ name, dir, args }) => {\n await run(['yarn', 'run', 'build', ...(args || [])], {\n cwd: dir,\n onStdout: prefixLogFunc(`${name}: `, logger.log),\n onStderr: prefixLogFunc(`${name}: `, logger.warn),\n }).waitForExit();\n },\n });\n }\n }\n\n await moveToDistWorkspace(\n targetDir,\n targets,\n Boolean(options.alwaysPack),\n Boolean(options.enableFeatureDetection),\n logger,\n );\n\n const files: FileEntry[] = options.files ?? ['yarn.lock', 'package.json'];\n\n for (const file of files) {\n const src = typeof file === 'string' ? file : file.src;\n const dest = typeof file === 'string' ? file : file.dest;\n await fs.copy(targetPaths.resolveRoot(src), resolvePath(targetDir, dest));\n }\n\n if (options.skeleton) {\n const skeletonFiles = targets\n .map(target => {\n const dir = relativePath(targetPaths.rootDir, target.dir);\n return joinPath(dir, 'package.json');\n })\n .sort();\n\n await tar.create(\n {\n file: resolvePath(targetDir, options.skeleton),\n cwd: targetDir,\n portable: true,\n noMtime: true,\n gzip: options.skeleton.endsWith('.gz'),\n },\n skeletonFiles,\n );\n }\n\n return { targetDir, targets };\n}\n\nconst FAST_PACK_SCRIPTS = [\n undefined,\n 'backstage-cli prepack',\n 'backstage-cli package prepack',\n];\n\n/**\n * Runs `yarn pack` on a single package and extracts the resulting tarball\n * into `targetDir`. This resolves `workspace:^` and `backstage:^` dependency\n * specs to concrete versions via yarn's `beforeWorkspacePacking` hook.\n */\nexport async function packToDirectory(options: {\n packageDir: string;\n packageName: string;\n targetDir: string;\n archivePath?: string;\n logger: { log(msg: string): void; warn(msg: string): void };\n}): Promise<void> {\n const { packageDir, packageName, targetDir, logger } = options;\n const archivePath =\n options.archivePath ?? resolvePath(targetDir, 'temp-archive.tgz');\n const prefix = `${packageName} [pack]: `;\n\n await fs.ensureDir(targetDir);\n await run(['yarn', 'pack', '--filename', archivePath], {\n cwd: packageDir,\n onStdout: prefixLogFunc(prefix, logger.log),\n onStderr: prefixLogFunc(prefix, logger.warn),\n }).waitForExit();\n\n await tar.extract({ file: archivePath, cwd: targetDir, strip: 1 });\n await fs.remove(archivePath);\n}\n\nasync function moveToDistWorkspace(\n workspaceDir: string,\n localPackages: PackageGraphNode[],\n alwaysPack: boolean,\n enableFeatureDetection: boolean,\n logger: { log(msg: string): void; warn(msg: string): void },\n): Promise<void> {\n const [fastPackPackages, slowPackPackages] = partition(\n localPackages,\n pkg =>\n !alwaysPack &&\n FAST_PACK_SCRIPTS.includes(pkg.packageJson.scripts?.prepack),\n );\n\n const configSchemas = await compilePackageConfigSchemas(fastPackPackages);\n const featureDetectionProject =\n fastPackPackages.length > 0 && enableFeatureDetection\n ? await createTypeDistProject()\n : undefined;\n\n // New an improved flow where we avoid calling `yarn pack`\n await Promise.all(\n fastPackPackages.map(async target => {\n logger.log(`Moving ${target.name} into dist workspace`);\n\n const outputDir = relativePath(targetPaths.rootDir, target.dir);\n const absoluteOutputPath = resolvePath(workspaceDir, outputDir);\n await productionPack({\n packageDir: target.dir,\n targetDir: absoluteOutputPath,\n configSchema: configSchemas.get(target.name),\n featureDetectionProject,\n });\n }),\n );\n\n // Old flow is below, which calls `yarn pack` and extracts the tarball\n\n let archiveIndex = 0;\n\n async function pack(\n target: PackageGraphNode,\n archive: string = `temp-package-${archiveIndex++}.tgz`,\n ) {\n logger.log(`Repacking ${target.name} into dist workspace`);\n\n const absoluteOutputPath = resolvePath(\n workspaceDir,\n relativePath(targetPaths.rootDir, target.dir),\n );\n await packToDirectory({\n packageDir: target.dir,\n packageName: target.name,\n targetDir: absoluteOutputPath,\n archivePath: resolvePath(workspaceDir, archive),\n logger,\n });\n\n // We remove the dependencies from package.json of packages that are marked\n // as bundled, so that yarn doesn't try to install them.\n if (target.packageJson.bundled) {\n const pkgJson = await fs.readJson(\n resolvePath(absoluteOutputPath, 'package.json'),\n );\n delete pkgJson.dependencies;\n delete pkgJson.devDependencies;\n delete pkgJson.peerDependencies;\n delete pkgJson.optionalDependencies;\n\n await fs.writeJson(\n resolvePath(absoluteOutputPath, 'package.json'),\n pkgJson,\n {\n spaces: 2,\n },\n );\n }\n }\n\n const [unsafePackages, safePackages] = partition(slowPackPackages, p =>\n UNSAFE_PACKAGES.includes(p.name),\n );\n\n // The unsafe package are packed first one by one in order to avoid race conditions\n // where the CLI is being executed with broken dependencies.\n for (const target of unsafePackages) {\n await pack(target, `temp-package.tgz`);\n }\n\n // Pack safe packages in topological layers so that a package is never\n // packed concurrently with its own dependencies. `yarn pack` temporarily\n // rewrites each package's package.json to resolve workspace:^ references;\n // packing a package while a dependency's manifest is mid-rewrite causes\n // intermittent \"No local workspace found for this range\" failures.\n const layers = computeTopologicalLayers(safePackages);\n for (const layer of layers) {\n await runConcurrentTasks({\n items: layer,\n worker: pack,\n });\n }\n}\n\n/**\n * Resolves the full set of local (workspace) packages that the given\n * package names transitively depend on via `publishedLocalDependencies`.\n * Packages marked as `bundled` have their own dependencies excluded.\n *\n * This is the same traversal that `createDistWorkspace` performs internally.\n * Callers must supply the monorepo package list obtained from\n * `PackageGraph.listTargetPackages()`.\n */\nexport async function resolveLocalDependencies(\n packageNames: string[],\n packages: BackstagePackage[],\n): Promise<PackageGraphNode[]> {\n const packageGraph = PackageGraph.fromPackages(packages);\n const targetNames = packageGraph.collectPackageNames(packageNames, node => {\n // Don't include dependencies of packages that are marked as bundled\n if (node.packageJson.bundled) {\n return undefined;\n }\n\n return node.publishedLocalDependencies.keys();\n });\n return Array.from(targetNames).map(name => packageGraph.get(name)!);\n}\n"],"names":["cliDependencies","cliDevDependencies","fs","resolvePath","tmpdir","PackageGraph","PackageRoles","getOutputsForRole","Output","chalk","relativePath","targetPaths","buildPackages","runConcurrentTasks","run","joinPath","tar","partition","compilePackageConfigSchemas","createTypeDistProject","productionPack","computeTopologicalLayers"],"mappings":"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"}
@@ -3,6 +3,7 @@
3
3
  var fs = require('fs-extra');
4
4
  var npmPackList = require('npm-packlist');
5
5
  var node_path = require('node:path');
6
+ var configLoader = require('@backstage/config-loader');
6
7
  var entryPoints = require('../entryPoints.cjs.js');
7
8
  var typeDistProject = require('../typeDistProject.cjs.js');
8
9
 
@@ -13,8 +14,40 @@ var npmPackList__default = /*#__PURE__*/_interopDefaultCompat(npmPackList);
13
14
 
14
15
  const PKG_PATH = "package.json";
15
16
  const PKG_BACKUP_PATH = "package.json-prepack";
17
+ const GENERATED_CONFIG_SCHEMA_PATH = "config.schema.json";
16
18
  const SKIPPED_KEYS = ["access", "registry", "tag"];
17
19
  const SCRIPT_EXTS = [".js", ".jsx", ".ts", ".tsx"];
20
+ function getTypeScriptConfigSchemaPath(pkg) {
21
+ const configSchema = pkg.configSchema;
22
+ return typeof configSchema === "string" && configSchema.endsWith(".d.ts") ? configSchema : void 0;
23
+ }
24
+ async function compilePackageConfigSchemas(packages) {
25
+ const schemaPackages = packages.flatMap((pkg) => {
26
+ const schemaPath = getTypeScriptConfigSchemaPath(pkg.packageJson);
27
+ return schemaPath ? [{ ...pkg, schemaPath }] : [];
28
+ });
29
+ if (schemaPackages.length === 0) {
30
+ return /* @__PURE__ */ new Map();
31
+ }
32
+ const schema = await configLoader.loadConfigSchema({
33
+ dependencies: [],
34
+ packagePaths: schemaPackages.map(
35
+ (pkg) => node_path.resolve(pkg.dir, "package.json")
36
+ ),
37
+ excludePackageDependencies: true
38
+ });
39
+ const serialized = schema.serialize();
40
+ const expectedPaths = new Map(
41
+ schemaPackages.map((pkg) => [pkg.name, node_path.resolve(pkg.dir, pkg.schemaPath)])
42
+ );
43
+ const result = /* @__PURE__ */ new Map();
44
+ for (const entry of serialized.schemas) {
45
+ if (expectedPaths.get(entry.packageName) === node_path.resolve(process.cwd(), entry.path)) {
46
+ result.set(entry.packageName, entry.value);
47
+ }
48
+ }
49
+ return result;
50
+ }
18
51
  async function productionPack(options) {
19
52
  const { packageDir, targetDir } = options;
20
53
  const pkgPath = node_path.resolve(packageDir, PKG_PATH);
@@ -36,6 +69,25 @@ async function productionPack(options) {
36
69
  delete pkg.peerDependencies;
37
70
  delete pkg.optionalDependencies;
38
71
  }
72
+ const sourceConfigSchemaPath = getTypeScriptConfigSchemaPath(pkg);
73
+ let generatedConfigSchema;
74
+ if (sourceConfigSchemaPath) {
75
+ generatedConfigSchema = options.configSchema ?? (await compilePackageConfigSchemas([
76
+ { name: pkg.name, dir: packageDir, packageJson: pkg }
77
+ ])).get(pkg.name);
78
+ if (!generatedConfigSchema) {
79
+ throw new Error(`Failed to compile configuration schema for ${pkg.name}`);
80
+ }
81
+ pkg.configSchema = GENERATED_CONFIG_SCHEMA_PATH;
82
+ if (pkg.files) {
83
+ pkg.files = pkg.files.map(
84
+ (path) => path === sourceConfigSchemaPath ? GENERATED_CONFIG_SCHEMA_PATH : path
85
+ );
86
+ if (!pkg.files.includes(GENERATED_CONFIG_SCHEMA_PATH)) {
87
+ pkg.files.push(GENERATED_CONFIG_SCHEMA_PATH);
88
+ }
89
+ }
90
+ }
39
91
  if (targetDir) {
40
92
  const filePaths = await npmPackList__default.default({
41
93
  path: packageDir,
@@ -47,6 +99,9 @@ async function productionPack(options) {
47
99
  });
48
100
  await fs__default.default.ensureDir(targetDir);
49
101
  for (const filePath of filePaths.sort()) {
102
+ if (filePath === sourceConfigSchemaPath) {
103
+ continue;
104
+ }
50
105
  const target = node_path.resolve(targetDir, filePath);
51
106
  if (filePath === PKG_PATH) {
52
107
  await fs__default.default.writeJson(target, pkg, { encoding: "utf8", spaces: 2 });
@@ -54,7 +109,21 @@ async function productionPack(options) {
54
109
  await fs__default.default.copy(node_path.resolve(packageDir, filePath), target);
55
110
  }
56
111
  }
112
+ if (generatedConfigSchema) {
113
+ await fs__default.default.writeJson(
114
+ node_path.resolve(targetDir, GENERATED_CONFIG_SCHEMA_PATH),
115
+ generatedConfigSchema,
116
+ { encoding: "utf8", spaces: 2 }
117
+ );
118
+ }
57
119
  } else {
120
+ if (generatedConfigSchema) {
121
+ await fs__default.default.writeJson(
122
+ node_path.resolve(packageDir, GENERATED_CONFIG_SCHEMA_PATH),
123
+ generatedConfigSchema,
124
+ { encoding: "utf8", spaces: 2 }
125
+ );
126
+ }
58
127
  await fs__default.default.writeJson(pkgPath, pkg, { encoding: "utf8", spaces: 2 });
59
128
  }
60
129
  }
@@ -62,6 +131,9 @@ async function revertProductionPack(packageDir) {
62
131
  try {
63
132
  await fs__default.default.move(PKG_BACKUP_PATH, PKG_PATH, { overwrite: true });
64
133
  const pkg = await fs__default.default.readJson(PKG_PATH);
134
+ if (getTypeScriptConfigSchemaPath(pkg)) {
135
+ await fs__default.default.remove(node_path.resolve(packageDir, GENERATED_CONFIG_SCHEMA_PATH));
136
+ }
65
137
  const entryPoints$1 = entryPoints.readEntryPoints(pkg);
66
138
  for (const entryPoint of entryPoints$1) {
67
139
  if (entryPoint.mount !== "." && SCRIPT_EXTS.includes(entryPoint.ext)) {
@@ -155,6 +227,7 @@ async function rewriteEntryPoints(pkg, packageDir, featureDetectionProject) {
155
227
  return void 0;
156
228
  }
157
229
 
230
+ exports.compilePackageConfigSchemas = compilePackageConfigSchemas;
158
231
  exports.productionPack = productionPack;
159
232
  exports.revertProductionPack = revertProductionPack;
160
233
  //# sourceMappingURL=productionPack.cjs.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"productionPack.cjs.js","sources":["../../../src/lib/packager/productionPack.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport fs from 'fs-extra';\nimport npmPackList from 'npm-packlist';\nimport { resolve as resolvePath, posix as posixPath } from 'node:path';\nimport { BackstagePackageJson } from '@backstage/cli-node';\nimport { readEntryPoints } from '../entryPoints';\nimport { getEntryPointDefaultFeatureType } from '../typeDistProject';\nimport { Project } from 'ts-morph';\n\nconst PKG_PATH = 'package.json';\nconst PKG_BACKUP_PATH = 'package.json-prepack';\n\nconst SKIPPED_KEYS = ['access', 'registry', 'tag'];\nconst SCRIPT_EXTS = ['.js', '.jsx', '.ts', '.tsx'];\n\ninterface ProductionPackOptions {\n packageDir: string;\n targetDir?: string;\n /**\n * Enables package feature detection using this TS-morph project.\n */\n featureDetectionProject?: Project;\n}\n\nexport async function productionPack(options: ProductionPackOptions) {\n const { packageDir, targetDir } = options;\n const pkgPath = resolvePath(packageDir, PKG_PATH);\n const pkgContent = await fs.readFile(pkgPath, 'utf8');\n const pkg = JSON.parse(pkgContent) as BackstagePackageJson;\n\n // If we're making the update in-line, back up the package.json\n if (!targetDir) {\n await fs.writeFile(PKG_BACKUP_PATH, pkgContent);\n }\n\n // This mutates pkg to fill in index exports, so call it before applying publishConfig\n await rewriteEntryPoints(pkg, packageDir, options.featureDetectionProject);\n\n // TODO(Rugvip): Once exports are rolled out more broadly we should deprecate and remove this behavior\n const publishConfig = pkg.publishConfig ?? {};\n for (const key of Object.keys(publishConfig)) {\n if (!SKIPPED_KEYS.includes(key)) {\n (pkg as any)[key] = publishConfig[key as keyof typeof publishConfig];\n }\n }\n\n // We remove the dependencies from package.json of packages that are marked\n // as bundled, so that yarn doesn't try to install them.\n if (pkg.bundled) {\n delete pkg.dependencies;\n delete pkg.devDependencies;\n delete pkg.peerDependencies;\n delete pkg.optionalDependencies;\n }\n\n if (targetDir) {\n // Lists all dist files, respecting .npmignore, files field in package.json, etc.\n const filePaths = await npmPackList({\n path: packageDir,\n // This makes sure we use the updated package.json when listing files\n packageJsonCache: new Map([\n [resolvePath(packageDir, PKG_PATH), pkg],\n ]) as any, // Seems like this parameter type is wrong,\n });\n\n await fs.ensureDir(targetDir);\n for (const filePath of filePaths.sort()) {\n const target = resolvePath(targetDir, filePath);\n if (filePath === PKG_PATH) {\n await fs.writeJson(target, pkg, { encoding: 'utf8', spaces: 2 });\n } else {\n await fs.copy(resolvePath(packageDir, filePath), target);\n }\n }\n } else {\n await fs.writeJson(pkgPath, pkg, { encoding: 'utf8', spaces: 2 });\n }\n}\n\n// Reverts the changes made by productionPack when called without a targetDir.\nexport async function revertProductionPack(packageDir: string) {\n // postpack isn't called by yarn right now, so it needs to be called manually\n try {\n await fs.move(PKG_BACKUP_PATH, PKG_PATH, { overwrite: true });\n\n // Check if we're shipping types for other release stages, clean up in that case\n const pkg = await fs.readJson(PKG_PATH);\n\n // Remove any extra entrypoint backwards compatibility directories\n const entryPoints = readEntryPoints(pkg);\n for (const entryPoint of entryPoints) {\n if (entryPoint.mount !== '.' && SCRIPT_EXTS.includes(entryPoint.ext)) {\n await fs.remove(resolvePath(packageDir, entryPoint.name));\n }\n }\n } catch (error) {\n console.warn(\n `Failed to restore package.json, ${error}. ` +\n 'Your package will be fine but you may have ended up with some garbage in the repo.',\n );\n }\n}\n\nconst EXPORT_MAP = {\n import: '.esm.js',\n require: '.cjs.js',\n types: '.d.ts',\n};\n\n/**\n * Rewrites the exports field in package.json to point to dist files, as\n * well as returning a function that creates backwards compatibility\n * entry points for importers that don't support exports.\n */\nasync function rewriteEntryPoints(\n pkg: BackstagePackageJson,\n packageDir: string,\n featureDetectionProject?: Project,\n) {\n const distPath = resolvePath(packageDir, 'dist');\n if (!(await fs.pathExists(distPath))) {\n return undefined;\n }\n const distFiles = await fs.readdir(distPath);\n const outputExports = {} as Record<string, string | Record<string, string>>;\n\n const entryPoints = readEntryPoints(pkg);\n\n // Clear to ensure a clean slate before adding entries back in further down\n if (pkg.typesVersions) {\n pkg.typesVersions = undefined;\n }\n\n for (const entryPoint of entryPoints) {\n if (!SCRIPT_EXTS.includes(entryPoint.ext)) {\n // Non-script files (like CSS) get their paths rewritten from src/ to dist/\n outputExports[entryPoint.mount] = entryPoint.path.replace(\n /^(\\.\\/)?src\\//,\n './dist/',\n );\n continue;\n }\n\n let exp = {} as Record<string, string>;\n\n for (const [key, ext] of Object.entries(EXPORT_MAP)) {\n const name = `${entryPoint.name}${ext}`;\n if (distFiles.includes(name)) {\n exp[key] = `./${posixPath.join(`dist`, name)}`;\n }\n }\n\n // Our current tooling relies on the typesVersions field rather than export.*.types\n if (exp.types) {\n if (!pkg.typesVersions) {\n pkg.typesVersions = { '*': {} };\n }\n if (entryPoint.name !== 'index') {\n pkg.typesVersions['*'][entryPoint.name] = [\n `dist/${entryPoint.name}.d.ts`,\n ];\n }\n }\n\n exp.default = exp.require ?? exp.import;\n\n // Find the default export type for the entry point, if feature detection is active\n if (exp.types && featureDetectionProject) {\n const defaultFeatureType =\n pkg.backstage?.role &&\n getEntryPointDefaultFeatureType(\n pkg.backstage?.role,\n packageDir,\n featureDetectionProject,\n exp.types,\n );\n\n if (defaultFeatureType) {\n // This ensures that the `backstage` field is at the top of the\n // `exports` field in the package.json because order is important.\n // https://nodejs.org/docs/latest-v20.x/api/packages.html#conditional-exports\n //\n // Adding this to the `exports` field in the package.json is to temporarily\n // support any existing behavior that relies on this, however not all packages\n // have exports field in their package.json.\n exp = { backstage: defaultFeatureType, ...exp };\n\n // Add the default feature type to the backstage metadata in the package.json\n pkg.backstage = pkg.backstage ?? {};\n pkg.backstage.features = pkg.backstage.features ?? {};\n pkg.backstage.features[entryPoint.mount] = defaultFeatureType;\n }\n }\n\n if (entryPoint.mount === '.') {\n if (exp.default) {\n pkg.main = exp.default;\n }\n if (exp.import) {\n pkg.module = exp.import;\n }\n if (exp.types) {\n pkg.types = exp.types;\n }\n }\n\n if (Object.keys(exp).length > 0) {\n outputExports[entryPoint.mount] = exp;\n }\n }\n\n // Make sure package.json is also available in typesVersions if present\n if (pkg.typesVersions?.['*']) {\n pkg.typesVersions['*']['package.json'] = ['package.json'];\n }\n\n if (pkg.exports) {\n pkg.exports = outputExports;\n // We treat package.json as a fixed export that is always available in the published package\n pkg.exports['./package.json'] = './package.json';\n }\n\n return undefined;\n}\n"],"names":["resolvePath","fs","npmPackList","entryPoints","readEntryPoints","posixPath","getEntryPointDefaultFeatureType"],"mappings":"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"}
1
+ {"version":3,"file":"productionPack.cjs.js","sources":["../../../src/lib/packager/productionPack.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport fs from 'fs-extra';\nimport npmPackList from 'npm-packlist';\nimport { resolve as resolvePath, posix as posixPath } from 'node:path';\nimport { BackstagePackageJson, PackageGraphNode } from '@backstage/cli-node';\nimport { loadConfigSchema } from '@backstage/config-loader';\nimport { readEntryPoints } from '../entryPoints';\nimport { getEntryPointDefaultFeatureType } from '../typeDistProject';\nimport { Project } from 'ts-morph';\n\nconst PKG_PATH = 'package.json';\nconst PKG_BACKUP_PATH = 'package.json-prepack';\nconst GENERATED_CONFIG_SCHEMA_PATH = 'config.schema.json';\n\nconst SKIPPED_KEYS = ['access', 'registry', 'tag'];\nconst SCRIPT_EXTS = ['.js', '.jsx', '.ts', '.tsx'];\n\ninterface ProductionPackOptions {\n packageDir: string;\n targetDir?: string;\n configSchema?: ConfigSchemaValue;\n /**\n * Enables package feature detection using this TS-morph project.\n */\n featureDetectionProject?: Project;\n}\n\ntype ConfigSchemaValue = Record<string, unknown>;\n\ntype PackageJsonWithConfigSchema = BackstagePackageJson & {\n configSchema?: string | ConfigSchemaValue;\n};\n\nfunction getTypeScriptConfigSchemaPath(pkg: BackstagePackageJson) {\n const configSchema = (pkg as PackageJsonWithConfigSchema).configSchema;\n return typeof configSchema === 'string' && configSchema.endsWith('.d.ts')\n ? configSchema\n : undefined;\n}\n\nexport async function compilePackageConfigSchemas(\n packages: Pick<PackageGraphNode, 'name' | 'dir' | 'packageJson'>[],\n) {\n const schemaPackages = packages.flatMap(pkg => {\n const schemaPath = getTypeScriptConfigSchemaPath(pkg.packageJson);\n return schemaPath ? [{ ...pkg, schemaPath }] : [];\n });\n if (schemaPackages.length === 0) {\n return new Map<string, ConfigSchemaValue>();\n }\n\n const schema = await loadConfigSchema({\n dependencies: [],\n packagePaths: schemaPackages.map(pkg =>\n resolvePath(pkg.dir, 'package.json'),\n ),\n excludePackageDependencies: true,\n });\n const serialized = schema.serialize() as {\n schemas: Array<{\n packageName: string;\n path: string;\n value: ConfigSchemaValue;\n }>;\n };\n const expectedPaths = new Map(\n schemaPackages.map(pkg => [pkg.name, resolvePath(pkg.dir, pkg.schemaPath)]),\n );\n const result = new Map<string, ConfigSchemaValue>();\n for (const entry of serialized.schemas) {\n if (\n expectedPaths.get(entry.packageName) ===\n resolvePath(process.cwd(), entry.path)\n ) {\n result.set(entry.packageName, entry.value);\n }\n }\n return result;\n}\n\nexport async function productionPack(options: ProductionPackOptions) {\n const { packageDir, targetDir } = options;\n const pkgPath = resolvePath(packageDir, PKG_PATH);\n const pkgContent = await fs.readFile(pkgPath, 'utf8');\n const pkg = JSON.parse(pkgContent) as BackstagePackageJson;\n\n // If we're making the update in-line, back up the package.json\n if (!targetDir) {\n await fs.writeFile(PKG_BACKUP_PATH, pkgContent);\n }\n\n // This mutates pkg to fill in index exports, so call it before applying publishConfig\n await rewriteEntryPoints(pkg, packageDir, options.featureDetectionProject);\n\n // TODO(Rugvip): Once exports are rolled out more broadly we should deprecate and remove this behavior\n const publishConfig = pkg.publishConfig ?? {};\n for (const key of Object.keys(publishConfig)) {\n if (!SKIPPED_KEYS.includes(key)) {\n (pkg as any)[key] = publishConfig[key as keyof typeof publishConfig];\n }\n }\n\n // We remove the dependencies from package.json of packages that are marked\n // as bundled, so that yarn doesn't try to install them.\n if (pkg.bundled) {\n delete pkg.dependencies;\n delete pkg.devDependencies;\n delete pkg.peerDependencies;\n delete pkg.optionalDependencies;\n }\n\n const sourceConfigSchemaPath = getTypeScriptConfigSchemaPath(pkg);\n let generatedConfigSchema: ConfigSchemaValue | undefined;\n if (sourceConfigSchemaPath) {\n generatedConfigSchema =\n options.configSchema ??\n (\n await compilePackageConfigSchemas([\n { name: pkg.name, dir: packageDir, packageJson: pkg },\n ])\n ).get(pkg.name);\n if (!generatedConfigSchema) {\n throw new Error(`Failed to compile configuration schema for ${pkg.name}`);\n }\n\n (pkg as PackageJsonWithConfigSchema).configSchema =\n GENERATED_CONFIG_SCHEMA_PATH;\n if (pkg.files) {\n pkg.files = pkg.files.map(path =>\n path === sourceConfigSchemaPath ? GENERATED_CONFIG_SCHEMA_PATH : path,\n );\n if (!pkg.files.includes(GENERATED_CONFIG_SCHEMA_PATH)) {\n pkg.files.push(GENERATED_CONFIG_SCHEMA_PATH);\n }\n }\n }\n\n if (targetDir) {\n // Lists all dist files, respecting .npmignore, files field in package.json, etc.\n const filePaths = await npmPackList({\n path: packageDir,\n // This makes sure we use the updated package.json when listing files\n packageJsonCache: new Map([\n [resolvePath(packageDir, PKG_PATH), pkg],\n ]) as any, // Seems like this parameter type is wrong,\n });\n\n await fs.ensureDir(targetDir);\n for (const filePath of filePaths.sort()) {\n if (filePath === sourceConfigSchemaPath) {\n continue;\n }\n const target = resolvePath(targetDir, filePath);\n if (filePath === PKG_PATH) {\n await fs.writeJson(target, pkg, { encoding: 'utf8', spaces: 2 });\n } else {\n await fs.copy(resolvePath(packageDir, filePath), target);\n }\n }\n if (generatedConfigSchema) {\n await fs.writeJson(\n resolvePath(targetDir, GENERATED_CONFIG_SCHEMA_PATH),\n generatedConfigSchema,\n { encoding: 'utf8', spaces: 2 },\n );\n }\n } else {\n if (generatedConfigSchema) {\n await fs.writeJson(\n resolvePath(packageDir, GENERATED_CONFIG_SCHEMA_PATH),\n generatedConfigSchema,\n { encoding: 'utf8', spaces: 2 },\n );\n }\n await fs.writeJson(pkgPath, pkg, { encoding: 'utf8', spaces: 2 });\n }\n}\n\n// Reverts the changes made by productionPack when called without a targetDir.\nexport async function revertProductionPack(packageDir: string) {\n // postpack isn't called by yarn right now, so it needs to be called manually\n try {\n await fs.move(PKG_BACKUP_PATH, PKG_PATH, { overwrite: true });\n\n // Check if we're shipping types for other release stages, clean up in that case\n const pkg = await fs.readJson(PKG_PATH);\n\n if (getTypeScriptConfigSchemaPath(pkg)) {\n await fs.remove(resolvePath(packageDir, GENERATED_CONFIG_SCHEMA_PATH));\n }\n\n // Remove any extra entrypoint backwards compatibility directories\n const entryPoints = readEntryPoints(pkg);\n for (const entryPoint of entryPoints) {\n if (entryPoint.mount !== '.' && SCRIPT_EXTS.includes(entryPoint.ext)) {\n await fs.remove(resolvePath(packageDir, entryPoint.name));\n }\n }\n } catch (error) {\n console.warn(\n `Failed to restore package.json, ${error}. ` +\n 'Your package will be fine but you may have ended up with some garbage in the repo.',\n );\n }\n}\n\nconst EXPORT_MAP = {\n import: '.esm.js',\n require: '.cjs.js',\n types: '.d.ts',\n};\n\n/**\n * Rewrites the exports field in package.json to point to dist files, as\n * well as returning a function that creates backwards compatibility\n * entry points for importers that don't support exports.\n */\nasync function rewriteEntryPoints(\n pkg: BackstagePackageJson,\n packageDir: string,\n featureDetectionProject?: Project,\n) {\n const distPath = resolvePath(packageDir, 'dist');\n if (!(await fs.pathExists(distPath))) {\n return undefined;\n }\n const distFiles = await fs.readdir(distPath);\n const outputExports = {} as Record<string, string | Record<string, string>>;\n\n const entryPoints = readEntryPoints(pkg);\n\n // Clear to ensure a clean slate before adding entries back in further down\n if (pkg.typesVersions) {\n pkg.typesVersions = undefined;\n }\n\n for (const entryPoint of entryPoints) {\n if (!SCRIPT_EXTS.includes(entryPoint.ext)) {\n // Non-script files (like CSS) get their paths rewritten from src/ to dist/\n outputExports[entryPoint.mount] = entryPoint.path.replace(\n /^(\\.\\/)?src\\//,\n './dist/',\n );\n continue;\n }\n\n let exp = {} as Record<string, string>;\n\n for (const [key, ext] of Object.entries(EXPORT_MAP)) {\n const name = `${entryPoint.name}${ext}`;\n if (distFiles.includes(name)) {\n exp[key] = `./${posixPath.join(`dist`, name)}`;\n }\n }\n\n // Our current tooling relies on the typesVersions field rather than export.*.types\n if (exp.types) {\n if (!pkg.typesVersions) {\n pkg.typesVersions = { '*': {} };\n }\n if (entryPoint.name !== 'index') {\n pkg.typesVersions['*'][entryPoint.name] = [\n `dist/${entryPoint.name}.d.ts`,\n ];\n }\n }\n\n exp.default = exp.require ?? exp.import;\n\n // Find the default export type for the entry point, if feature detection is active\n if (exp.types && featureDetectionProject) {\n const defaultFeatureType =\n pkg.backstage?.role &&\n getEntryPointDefaultFeatureType(\n pkg.backstage?.role,\n packageDir,\n featureDetectionProject,\n exp.types,\n );\n\n if (defaultFeatureType) {\n // This ensures that the `backstage` field is at the top of the\n // `exports` field in the package.json because order is important.\n // https://nodejs.org/docs/latest-v20.x/api/packages.html#conditional-exports\n //\n // Adding this to the `exports` field in the package.json is to temporarily\n // support any existing behavior that relies on this, however not all packages\n // have exports field in their package.json.\n exp = { backstage: defaultFeatureType, ...exp };\n\n // Add the default feature type to the backstage metadata in the package.json\n pkg.backstage = pkg.backstage ?? {};\n pkg.backstage.features = pkg.backstage.features ?? {};\n pkg.backstage.features[entryPoint.mount] = defaultFeatureType;\n }\n }\n\n if (entryPoint.mount === '.') {\n if (exp.default) {\n pkg.main = exp.default;\n }\n if (exp.import) {\n pkg.module = exp.import;\n }\n if (exp.types) {\n pkg.types = exp.types;\n }\n }\n\n if (Object.keys(exp).length > 0) {\n outputExports[entryPoint.mount] = exp;\n }\n }\n\n // Make sure package.json is also available in typesVersions if present\n if (pkg.typesVersions?.['*']) {\n pkg.typesVersions['*']['package.json'] = ['package.json'];\n }\n\n if (pkg.exports) {\n pkg.exports = outputExports;\n // We treat package.json as a fixed export that is always available in the published package\n pkg.exports['./package.json'] = './package.json';\n }\n\n return undefined;\n}\n"],"names":["loadConfigSchema","resolvePath","fs","npmPackList","entryPoints","readEntryPoints","posixPath","getEntryPointDefaultFeatureType"],"mappings":"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"}
@@ -3,6 +3,7 @@
3
3
  var os = require('node:os');
4
4
  var fs = require('fs-extra');
5
5
  var node_path = require('node:path');
6
+ var zod = require('zod');
6
7
  var portfinder = require('portfinder');
7
8
  var errors = require('@backstage/errors');
8
9
  var configLoader = require('@backstage/config-loader');
@@ -41,6 +42,16 @@ async function cleanStaleDatabases() {
41
42
  })
42
43
  );
43
44
  }
45
+ const connectionSchema = zod.z.object({
46
+ host: zod.z.string().optional(),
47
+ port: zod.z.number().optional(),
48
+ user: zod.z.string().optional(),
49
+ password: zod.z.string().optional(),
50
+ flags: zod.z.object({
51
+ postgres: zod.z.array(zod.z.string()).optional(),
52
+ initdb: zod.z.array(zod.z.string()).optional()
53
+ }).optional()
54
+ });
44
55
  async function startEmbeddedDb(options) {
45
56
  const dbConfig = await readDatabaseConfig(
46
57
  options.configPaths,
@@ -77,6 +88,8 @@ async function startEmbeddedDbInternal(userConfig) {
77
88
  password,
78
89
  port,
79
90
  persistent: false,
91
+ ...userConfig?.flags?.postgres ? { postgresFlags: userConfig.flags.postgres } : {},
92
+ ...userConfig?.flags?.initdb ? { initdbFlags: userConfig.flags.initdb } : {},
80
93
  onError(messageOrError) {
81
94
  console.error(`[embedded-postgres]`, messageOrError);
82
95
  },
@@ -139,16 +152,8 @@ async function readDatabaseConfig(configPaths, targetDir) {
139
152
  return void 0;
140
153
  }
141
154
  const rawConnection = config.getOptional("backend.database.connection");
142
- if (typeof rawConnection === "string" || rawConnection === void 0) {
143
- return { client };
144
- }
145
- const host = config.getOptionalString("backend.database.connection.host");
146
- const port = config.getOptionalNumber("backend.database.connection.port");
147
- const user = config.getOptionalString("backend.database.connection.user");
148
- const password = config.getOptionalString(
149
- "backend.database.connection.password"
150
- );
151
- const connection = host !== void 0 || port !== void 0 || user !== void 0 || password !== void 0 ? { host, port, user, password } : void 0;
155
+ const connectionResult = connectionSchema.safeParse(rawConnection);
156
+ const connection = connectionResult.success ? connectionResult.data : void 0;
152
157
  return { client, connection };
153
158
  } finally {
154
159
  config.close();
@@ -1 +1 @@
1
- {"version":3,"file":"startEmbeddedDb.cjs.js","sources":["../../../src/lib/runner/startEmbeddedDb.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport os from 'node:os';\nimport fs from 'fs-extra';\nimport {\n isAbsolute as isAbsolutePath,\n resolve as resolvePath,\n} from 'node:path';\nimport { getPortPromise } from 'portfinder';\nimport { ForwardedError } from '@backstage/errors';\nimport { ConfigSources } from '@backstage/config-loader';\nimport { targetPaths } from '@backstage/cli-common';\nimport chalk from 'chalk';\n\nconst TEMP_DIR_PREFIX = 'backstage-dev-db-';\nconst PID_FILE = 'backstage.pid';\n\nfunction isProcessAlive(pid: number): boolean {\n try {\n process.kill(pid, 0);\n return true;\n } catch {\n return false;\n }\n}\n\nasync function cleanStaleDatabases() {\n const tmpBase = os.tmpdir();\n const entries = (await fs.readdir(tmpBase)).filter(d =>\n d.startsWith(TEMP_DIR_PREFIX),\n );\n await Promise.all(\n entries.map(async d => {\n const dir = resolvePath(tmpBase, d);\n const raw = await fs\n .readFile(resolvePath(dir, PID_FILE), 'utf8')\n .catch(() => undefined);\n const pid = raw ? Number(raw.trim()) : NaN;\n if (!pid || !isProcessAlive(pid)) {\n await fs.remove(dir);\n }\n }),\n );\n}\n\nexport interface EmbeddedDbConnectionConfig {\n host?: string;\n port?: number;\n user?: string;\n password?: string;\n}\n\nexport interface StartEmbeddedDbOptions {\n configPaths?: string[];\n targetDir?: string;\n}\n\n/**\n * Reads the database configuration from the app config and, if the client is\n * `embedded-postgres`, starts an embedded Postgres instance. Returns the config\n * override to inject into the child process, or `undefined` if the database\n * client is not `embedded-postgres`.\n */\nexport async function startEmbeddedDb(options: StartEmbeddedDbOptions): Promise<\n | {\n configOverride: Record<string, unknown>;\n close(): Promise<void>;\n }\n | undefined\n> {\n const dbConfig = await readDatabaseConfig(\n options.configPaths,\n options.targetDir,\n );\n if (dbConfig?.client !== 'embedded-postgres') {\n return undefined;\n }\n\n return startEmbeddedDbInternal(dbConfig.connection);\n}\n\nasync function startEmbeddedDbInternal(\n userConfig?: EmbeddedDbConnectionConfig,\n) {\n console.warn(\n chalk.yellow(\n 'WARNING: Using embedded-postgres for local development is experimental and subject to change',\n ),\n );\n\n const { default: EmbeddedPostgres } = await import('embedded-postgres').catch(\n error => {\n throw new ForwardedError(\n `Failed to load 'embedded-postgres' which is required when using ` +\n `'embedded-postgres' as the database client. It must be installed ` +\n `as an explicit dependency in your project`,\n error,\n );\n },\n );\n\n await cleanStaleDatabases();\n\n const host = userConfig?.host ?? 'localhost';\n const user = userConfig?.user ?? 'postgres';\n const password = userConfig?.password ?? 'postgres';\n const port = userConfig?.port ?? (await getPortPromise());\n const tmpDir = await fs.mkdtemp(resolvePath(os.tmpdir(), TEMP_DIR_PREFIX));\n\n const pg = new EmbeddedPostgres({\n databaseDir: tmpDir,\n user,\n password,\n port,\n persistent: false,\n onError(messageOrError) {\n console.error(`[embedded-postgres]`, messageOrError);\n },\n onLog() {},\n });\n\n try {\n await pg.initialise();\n await fs.writeFile(resolvePath(tmpDir, PID_FILE), String(process.pid));\n await pg.start();\n } catch (error) {\n await pg.stop().catch(() => {});\n await fs.remove(tmpDir).catch(() => {});\n throw error;\n }\n\n const configOverride: Record<string, unknown> = {\n client: 'pg',\n };\n const defaultedConnection: Record<string, string | number> = {};\n if (!userConfig?.host) {\n defaultedConnection.host = host;\n }\n if (!userConfig?.user) {\n defaultedConnection.user = user;\n }\n if (!userConfig?.password) {\n defaultedConnection.password = password;\n }\n if (!userConfig?.port) {\n defaultedConnection.port = port;\n }\n if (Object.keys(defaultedConnection).length > 0) {\n configOverride.connection = defaultedConnection;\n }\n\n return {\n configOverride,\n async close() {\n await pg.stop();\n await fs.remove(tmpDir);\n },\n };\n}\n\nasync function readDatabaseConfig(\n configPaths?: string[],\n targetDir?: string,\n): Promise<\n | {\n client: string;\n connection?: EmbeddedDbConnectionConfig;\n }\n | undefined\n> {\n const rootDir = targetPaths.rootDir;\n const configBaseDir = targetDir ?? rootDir;\n const source = ConfigSources.default({\n rootDir,\n allowMissingDefaultConfig: true,\n argv: (configPaths ?? []).flatMap(p => [\n '--config',\n isAbsolutePath(p) ? p : resolvePath(configBaseDir, p),\n ]),\n });\n\n const config = await ConfigSources.toConfig(source);\n try {\n const client = config.getOptionalString('backend.database.client');\n if (!client) {\n return undefined;\n }\n\n // Only read structured connection config if the value is an object;\n // it can also be a plain string (e.g. ':memory:' for better-sqlite3).\n const rawConnection = config.getOptional('backend.database.connection');\n if (typeof rawConnection === 'string' || rawConnection === undefined) {\n return { client };\n }\n\n const host = config.getOptionalString('backend.database.connection.host');\n const port = config.getOptionalNumber('backend.database.connection.port');\n const user = config.getOptionalString('backend.database.connection.user');\n const password = config.getOptionalString(\n 'backend.database.connection.password',\n );\n\n const connection =\n host !== undefined ||\n port !== undefined ||\n user !== undefined ||\n password !== undefined\n ? { host, port, user, password }\n : undefined;\n\n return { client, connection };\n } finally {\n config.close();\n }\n}\n"],"names":["os","fs","resolvePath","chalk","ForwardedError","getPortPromise","targetPaths","ConfigSources","isAbsolutePath"],"mappings":"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"}
1
+ {"version":3,"file":"startEmbeddedDb.cjs.js","sources":["../../../src/lib/runner/startEmbeddedDb.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport os from 'node:os';\nimport fs from 'fs-extra';\nimport {\n isAbsolute as isAbsolutePath,\n resolve as resolvePath,\n} from 'node:path';\nimport { z } from 'zod';\nimport { getPortPromise } from 'portfinder';\nimport { ForwardedError } from '@backstage/errors';\nimport { ConfigSources } from '@backstage/config-loader';\nimport { targetPaths } from '@backstage/cli-common';\nimport chalk from 'chalk';\n\nconst TEMP_DIR_PREFIX = 'backstage-dev-db-';\nconst PID_FILE = 'backstage.pid';\n\nfunction isProcessAlive(pid: number): boolean {\n try {\n process.kill(pid, 0);\n return true;\n } catch {\n return false;\n }\n}\n\nasync function cleanStaleDatabases() {\n const tmpBase = os.tmpdir();\n const entries = (await fs.readdir(tmpBase)).filter(d =>\n d.startsWith(TEMP_DIR_PREFIX),\n );\n await Promise.all(\n entries.map(async d => {\n const dir = resolvePath(tmpBase, d);\n const raw = await fs\n .readFile(resolvePath(dir, PID_FILE), 'utf8')\n .catch(() => undefined);\n const pid = raw ? Number(raw.trim()) : NaN;\n if (!pid || !isProcessAlive(pid)) {\n await fs.remove(dir);\n }\n }),\n );\n}\n\nexport interface EmbeddedDbConnectionConfig {\n host?: string;\n port?: number;\n user?: string;\n password?: string;\n flags?: {\n postgres?: string[];\n initdb?: string[];\n };\n}\n\nconst connectionSchema: z.ZodType<EmbeddedDbConnectionConfig> = z.object({\n host: z.string().optional(),\n port: z.number().optional(),\n user: z.string().optional(),\n password: z.string().optional(),\n flags: z\n .object({\n postgres: z.array(z.string()).optional(),\n initdb: z.array(z.string()).optional(),\n })\n .optional(),\n});\n\nexport interface StartEmbeddedDbOptions {\n configPaths?: string[];\n targetDir?: string;\n}\n\n/**\n * Reads the database configuration from the app config and, if the client is\n * `embedded-postgres`, starts an embedded Postgres instance. Returns the config\n * override to inject into the child process, or `undefined` if the database\n * client is not `embedded-postgres`.\n */\nexport async function startEmbeddedDb(options: StartEmbeddedDbOptions): Promise<\n | {\n configOverride: Record<string, unknown>;\n close(): Promise<void>;\n }\n | undefined\n> {\n const dbConfig = await readDatabaseConfig(\n options.configPaths,\n options.targetDir,\n );\n if (dbConfig?.client !== 'embedded-postgres') {\n return undefined;\n }\n\n return startEmbeddedDbInternal(dbConfig.connection);\n}\n\nasync function startEmbeddedDbInternal(\n userConfig?: EmbeddedDbConnectionConfig,\n) {\n console.warn(\n chalk.yellow(\n 'WARNING: Using embedded-postgres for local development is experimental and subject to change',\n ),\n );\n\n const { default: EmbeddedPostgres } = await import('embedded-postgres').catch(\n error => {\n throw new ForwardedError(\n `Failed to load 'embedded-postgres' which is required when using ` +\n `'embedded-postgres' as the database client. It must be installed ` +\n `as an explicit dependency in your project`,\n error,\n );\n },\n );\n\n await cleanStaleDatabases();\n\n const host = userConfig?.host ?? 'localhost';\n const user = userConfig?.user ?? 'postgres';\n const password = userConfig?.password ?? 'postgres';\n const port = userConfig?.port ?? (await getPortPromise());\n const tmpDir = await fs.mkdtemp(resolvePath(os.tmpdir(), TEMP_DIR_PREFIX));\n\n const pg = new EmbeddedPostgres({\n databaseDir: tmpDir,\n user,\n password,\n port,\n persistent: false,\n ...(userConfig?.flags?.postgres\n ? { postgresFlags: userConfig.flags.postgres }\n : {}),\n ...(userConfig?.flags?.initdb\n ? { initdbFlags: userConfig.flags.initdb }\n : {}),\n onError(messageOrError) {\n console.error(`[embedded-postgres]`, messageOrError);\n },\n onLog() {},\n });\n\n try {\n await pg.initialise();\n await fs.writeFile(resolvePath(tmpDir, PID_FILE), String(process.pid));\n await pg.start();\n } catch (error) {\n await pg.stop().catch(() => {});\n await fs.remove(tmpDir).catch(() => {});\n throw error;\n }\n\n const configOverride: Record<string, unknown> = {\n client: 'pg',\n };\n const defaultedConnection: Record<string, string | number> = {};\n if (!userConfig?.host) {\n defaultedConnection.host = host;\n }\n if (!userConfig?.user) {\n defaultedConnection.user = user;\n }\n if (!userConfig?.password) {\n defaultedConnection.password = password;\n }\n if (!userConfig?.port) {\n defaultedConnection.port = port;\n }\n if (Object.keys(defaultedConnection).length > 0) {\n configOverride.connection = defaultedConnection;\n }\n\n return {\n configOverride,\n async close() {\n await pg.stop();\n await fs.remove(tmpDir);\n },\n };\n}\n\nasync function readDatabaseConfig(\n configPaths?: string[],\n targetDir?: string,\n): Promise<\n | {\n client: string;\n connection?: EmbeddedDbConnectionConfig;\n }\n | undefined\n> {\n const rootDir = targetPaths.rootDir;\n const configBaseDir = targetDir ?? rootDir;\n const source = ConfigSources.default({\n rootDir,\n allowMissingDefaultConfig: true,\n argv: (configPaths ?? []).flatMap(p => [\n '--config',\n isAbsolutePath(p) ? p : resolvePath(configBaseDir, p),\n ]),\n });\n\n const config = await ConfigSources.toConfig(source);\n try {\n const client = config.getOptionalString('backend.database.client');\n if (!client) {\n return undefined;\n }\n\n // Parse the raw connection value with zod rather than reading sub-keys\n // through the config reader, because the config reader's fallback chain\n // throws when a lower-priority config file has connection as a string.\n const rawConnection = config.getOptional('backend.database.connection');\n const connectionResult = connectionSchema.safeParse(rawConnection);\n const connection = connectionResult.success\n ? connectionResult.data\n : undefined;\n\n return { client, connection };\n } finally {\n config.close();\n }\n}\n"],"names":["os","fs","resolvePath","z","chalk","ForwardedError","getPortPromise","targetPaths","ConfigSources","isAbsolutePath"],"mappings":"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"}
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var name = "@backstage/cli-module-build";
6
- var version = "0.1.4-next.0";
6
+ var version = "0.1.5-next.0";
7
7
  var description = "CLI module for Backstage CLI";
8
8
  var backstage = {
9
9
  role: "cli-module"
@@ -64,7 +64,7 @@ var dependencies = {
64
64
  buffer: "^6.0.3",
65
65
  chalk: "^4.0.0",
66
66
  chokidar: "^3.3.1",
67
- cleye: "^2.3.0",
67
+ cleye: "^2.6.0",
68
68
  "cross-spawn": "^7.0.3",
69
69
  "css-loader": "^6.5.1",
70
70
  "ctrlc-windows": "^2.1.0",
@@ -102,7 +102,8 @@ var dependencies = {
102
102
  webpack: "~5.105.0",
103
103
  "webpack-dev-server": "^5.0.0",
104
104
  "yml-loader": "^2.1.0",
105
- yn: "^4.0.0"
105
+ yn: "^4.0.0",
106
+ zod: "^3.25.76 || ^4.0.0"
106
107
  };
107
108
  var devDependencies = {
108
109
  "@backstage/backend-test-utils": "workspace:^",
@@ -1 +1 @@
1
- {"version":3,"file":"package.json.cjs.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"package.json.cjs.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}