@backstage/cli-module-new 0.0.0-nightly-20260317031259 → 0.1.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 (162) hide show
  1. package/CHANGELOG.md +7 -4
  2. package/dist/lib/defaultTemplates.cjs.js +13 -10
  3. package/dist/lib/defaultTemplates.cjs.js.map +1 -1
  4. package/dist/lib/preparation/collectPortableTemplateInput.cjs.js +57 -2
  5. package/dist/lib/preparation/collectPortableTemplateInput.cjs.js.map +1 -1
  6. package/dist/lib/preparation/loadPortableTemplate.cjs.js +8 -8
  7. package/dist/lib/preparation/loadPortableTemplate.cjs.js.map +1 -1
  8. package/dist/lib/preparation/loadPortableTemplateConfig.cjs.js +69 -22
  9. package/dist/lib/preparation/loadPortableTemplateConfig.cjs.js.map +1 -1
  10. package/dist/lib/preparation/resolvePackageParams.cjs.js +2 -0
  11. package/dist/lib/preparation/resolvePackageParams.cjs.js.map +1 -1
  12. package/dist/lib/types.cjs.js +1 -0
  13. package/dist/lib/types.cjs.js.map +1 -1
  14. package/dist/packages/backend-defaults/package.json.cjs.js +1 -1
  15. package/dist/packages/backend-plugin-api/package.json.cjs.js +1 -1
  16. package/dist/packages/backend-test-utils/package.json.cjs.js +1 -1
  17. package/dist/packages/catalog-client/package.json.cjs.js +1 -1
  18. package/dist/packages/cli/package.json.cjs.js +1 -1
  19. package/dist/packages/cli-internal/src/InternalCliModule.cjs.js +9 -0
  20. package/dist/packages/cli-internal/src/InternalCliModule.cjs.js.map +1 -0
  21. package/dist/packages/cli-internal/src/InternalCommandNode.cjs.js +13 -0
  22. package/dist/packages/cli-internal/src/InternalCommandNode.cjs.js.map +1 -0
  23. package/dist/packages/cli-internal/src/knownPluginPackages.cjs.js +43 -0
  24. package/dist/packages/cli-internal/src/knownPluginPackages.cjs.js.map +1 -0
  25. package/dist/packages/cli-module-new/package.json.cjs.js +13 -12
  26. package/dist/packages/cli-module-new/package.json.cjs.js.map +1 -1
  27. package/dist/packages/core-app-api/package.json.cjs.js +1 -1
  28. package/dist/packages/core-components/package.json.cjs.js +1 -1
  29. package/dist/packages/core-plugin-api/package.json.cjs.js +1 -1
  30. package/dist/packages/dev-utils/package.json.cjs.js +1 -1
  31. package/dist/packages/frontend-defaults/package.json.cjs.js +1 -1
  32. package/dist/packages/frontend-dev-utils/package.json.cjs.js +1 -1
  33. package/dist/packages/frontend-plugin-api/package.json.cjs.js +1 -1
  34. package/dist/packages/frontend-test-utils/package.json.cjs.js +1 -1
  35. package/dist/packages/opaque-internal/src/OpaqueType.cjs.js +105 -0
  36. package/dist/packages/opaque-internal/src/OpaqueType.cjs.js.map +1 -0
  37. package/dist/packages/test-utils/package.json.cjs.js +1 -1
  38. package/dist/plugins/auth-backend/package.json.cjs.js +1 -1
  39. package/dist/plugins/auth-backend-module-guest-provider/package.json.cjs.js +1 -1
  40. package/dist/plugins/catalog-node/package.json.cjs.js +1 -1
  41. package/dist/plugins/scaffolder-node/package.json.cjs.js +1 -1
  42. package/dist/plugins/scaffolder-node-test-utils/package.json.cjs.js +1 -1
  43. package/package.json +11 -10
  44. package/templates/backend-plugin/.eslintrc.js.hbs +1 -0
  45. package/templates/backend-plugin/README.md.hbs +28 -0
  46. package/templates/backend-plugin/dev/index.ts.hbs +60 -0
  47. package/templates/backend-plugin/package.json.hbs +44 -0
  48. package/templates/backend-plugin/portable-template.yaml +5 -0
  49. package/templates/backend-plugin/src/index.ts.hbs +1 -0
  50. package/templates/backend-plugin/src/plugin.test.ts.hbs +129 -0
  51. package/templates/backend-plugin/src/plugin.ts.hbs +32 -0
  52. package/templates/backend-plugin/src/router.test.ts +67 -0
  53. package/templates/backend-plugin/src/router.ts +51 -0
  54. package/templates/backend-plugin/src/services/TodoListService.ts +155 -0
  55. package/templates/backend-plugin/src/setupTests.ts +1 -0
  56. package/templates/backend-plugin-module/.eslintrc.js.hbs +1 -0
  57. package/templates/backend-plugin-module/README.md.hbs +5 -0
  58. package/templates/backend-plugin-module/package.json.hbs +35 -0
  59. package/templates/backend-plugin-module/portable-template.yaml +5 -0
  60. package/templates/backend-plugin-module/src/index.ts.hbs +8 -0
  61. package/templates/backend-plugin-module/src/module.ts.hbs +17 -0
  62. package/templates/catalog-provider-module/.eslintrc.js.hbs +1 -0
  63. package/templates/catalog-provider-module/README.md.hbs +5 -0
  64. package/templates/catalog-provider-module/config.d.ts.hbs +34 -0
  65. package/templates/catalog-provider-module/package.json.hbs +36 -0
  66. package/templates/catalog-provider-module/portable-template.yaml +9 -0
  67. package/templates/catalog-provider-module/src/index.ts.hbs +8 -0
  68. package/templates/catalog-provider-module/src/module.ts.hbs +29 -0
  69. package/templates/catalog-provider-module/src/provider/readProviderConfigs.ts.hbs +78 -0
  70. package/templates/catalog-provider-module/src/provider/{{providerClass}}.test.ts.hbs +18 -0
  71. package/templates/catalog-provider-module/src/provider/{{providerClass}}.ts.hbs +109 -0
  72. package/templates/cli-module/.eslintrc.js.hbs +1 -0
  73. package/templates/cli-module/README.md.hbs +5 -0
  74. package/templates/cli-module/bin/{{binName}} +32 -0
  75. package/templates/cli-module/package.json.hbs +35 -0
  76. package/templates/cli-module/portable-template.yaml +5 -0
  77. package/templates/cli-module/src/commands/example.ts +22 -0
  78. package/templates/cli-module/src/index.ts.hbs +20 -0
  79. package/templates/frontend-plugin/.eslintrc.js.hbs +1 -0
  80. package/templates/frontend-plugin/README.md.hbs +20 -0
  81. package/templates/frontend-plugin/dev/index.tsx +5 -0
  82. package/templates/frontend-plugin/package.json.hbs +50 -0
  83. package/templates/frontend-plugin/portable-template.yaml +5 -0
  84. package/templates/frontend-plugin/src/components/ExampleComponent/ExampleComponent.test.tsx.hbs +28 -0
  85. package/templates/frontend-plugin/src/components/ExampleComponent/ExampleComponent.tsx.hbs +37 -0
  86. package/templates/frontend-plugin/src/components/ExampleComponent/index.ts +1 -0
  87. package/templates/frontend-plugin/src/components/ExampleFetchComponent/ExampleFetchComponent.test.tsx.hbs +19 -0
  88. package/templates/frontend-plugin/src/components/ExampleFetchComponent/ExampleFetchComponent.tsx.hbs +308 -0
  89. package/templates/frontend-plugin/src/components/ExampleFetchComponent/index.ts +1 -0
  90. package/templates/frontend-plugin/src/index.ts.hbs +1 -0
  91. package/templates/frontend-plugin/src/plugin.test.ts.hbs +7 -0
  92. package/templates/frontend-plugin/src/plugin.tsx.hbs +25 -0
  93. package/templates/frontend-plugin/src/routes.ts +3 -0
  94. package/templates/frontend-plugin/src/setupTests.ts +1 -0
  95. package/templates/frontend-plugin-module/.eslintrc.js.hbs +1 -0
  96. package/templates/frontend-plugin-module/README.md.hbs +5 -0
  97. package/templates/frontend-plugin-module/package.json.hbs +36 -0
  98. package/templates/frontend-plugin-module/portable-template.yaml +5 -0
  99. package/templates/frontend-plugin-module/src/index.ts.hbs +1 -0
  100. package/templates/frontend-plugin-module/src/module.tsx.hbs +8 -0
  101. package/templates/frontend-plugin-module/src/setupTests.ts +1 -0
  102. package/templates/legacy-frontend-plugin/.eslintrc.js.hbs +1 -0
  103. package/templates/legacy-frontend-plugin/README.md.hbs +13 -0
  104. package/templates/legacy-frontend-plugin/dev/index.tsx.hbs +11 -0
  105. package/templates/legacy-frontend-plugin/package.json.hbs +54 -0
  106. package/templates/legacy-frontend-plugin/portable-template.yaml +6 -0
  107. package/templates/legacy-frontend-plugin/src/components/ExampleComponent/ExampleComponent.test.tsx.hbs +28 -0
  108. package/templates/legacy-frontend-plugin/src/components/ExampleComponent/ExampleComponent.tsx.hbs +37 -0
  109. package/templates/legacy-frontend-plugin/src/components/ExampleComponent/index.ts +1 -0
  110. package/templates/legacy-frontend-plugin/src/components/ExampleFetchComponent/ExampleFetchComponent.test.tsx.hbs +19 -0
  111. package/templates/legacy-frontend-plugin/src/components/ExampleFetchComponent/ExampleFetchComponent.tsx.hbs +308 -0
  112. package/templates/legacy-frontend-plugin/src/components/ExampleFetchComponent/index.ts +1 -0
  113. package/templates/legacy-frontend-plugin/src/index.ts.hbs +1 -0
  114. package/templates/legacy-frontend-plugin/src/plugin.test.ts.hbs +7 -0
  115. package/templates/legacy-frontend-plugin/src/plugin.ts.hbs +22 -0
  116. package/templates/legacy-frontend-plugin/src/routes.ts.hbs +5 -0
  117. package/templates/legacy-frontend-plugin/src/setupTests.ts +1 -0
  118. package/templates/node-library/.eslintrc.js.hbs +1 -0
  119. package/templates/node-library/README.md.hbs +12 -0
  120. package/templates/node-library/package.json.hbs +29 -0
  121. package/templates/node-library/portable-template.yaml +3 -0
  122. package/templates/node-library/src/index.ts.hbs +1 -0
  123. package/templates/node-library/src/setupTests.ts +1 -0
  124. package/templates/plugin-common-library/.eslintrc.js.hbs +1 -0
  125. package/templates/plugin-common-library/README.md.hbs +5 -0
  126. package/templates/plugin-common-library/package.json.hbs +31 -0
  127. package/templates/plugin-common-library/portable-template.yaml +3 -0
  128. package/templates/plugin-common-library/src/index.ts.hbs +19 -0
  129. package/templates/plugin-common-library/src/setupTests.ts +1 -0
  130. package/templates/plugin-node-library/.eslintrc.js.hbs +1 -0
  131. package/templates/plugin-node-library/README.md.hbs +5 -0
  132. package/templates/plugin-node-library/package.json.hbs +30 -0
  133. package/templates/plugin-node-library/portable-template.yaml +3 -0
  134. package/templates/plugin-node-library/src/index.ts.hbs +18 -0
  135. package/templates/plugin-node-library/src/setupTests.ts +1 -0
  136. package/templates/plugin-web-library/.eslintrc.js.hbs +1 -0
  137. package/templates/plugin-web-library/README.md.hbs +5 -0
  138. package/templates/plugin-web-library/package.json.hbs +42 -0
  139. package/templates/plugin-web-library/portable-template.yaml +3 -0
  140. package/templates/plugin-web-library/src/components/ExampleComponent/ExampleComponent.test.tsx +17 -0
  141. package/templates/plugin-web-library/src/components/ExampleComponent/ExampleComponent.tsx +28 -0
  142. package/templates/plugin-web-library/src/components/ExampleComponent/index.ts +2 -0
  143. package/templates/plugin-web-library/src/components/index.ts +5 -0
  144. package/templates/plugin-web-library/src/hooks/index.ts +5 -0
  145. package/templates/plugin-web-library/src/hooks/useExample/index.ts +1 -0
  146. package/templates/plugin-web-library/src/hooks/useExample/useExample.ts +15 -0
  147. package/templates/plugin-web-library/src/index.ts.hbs +12 -0
  148. package/templates/plugin-web-library/src/setupTests.ts +1 -0
  149. package/templates/scaffolder-backend-module/.eslintrc.js.hbs +1 -0
  150. package/templates/scaffolder-backend-module/README.md.hbs +5 -0
  151. package/templates/scaffolder-backend-module/package.json.hbs +37 -0
  152. package/templates/scaffolder-backend-module/portable-template.yaml +6 -0
  153. package/templates/scaffolder-backend-module/src/actions/example.test.ts +24 -0
  154. package/templates/scaffolder-backend-module/src/actions/example.ts +39 -0
  155. package/templates/scaffolder-backend-module/src/index.ts.hbs +8 -0
  156. package/templates/scaffolder-backend-module/src/module.ts +21 -0
  157. package/templates/web-library/.eslintrc.js.hbs +1 -0
  158. package/templates/web-library/README.md.hbs +12 -0
  159. package/templates/web-library/package.json.hbs +30 -0
  160. package/templates/web-library/portable-template.yaml +3 -0
  161. package/templates/web-library/src/index.ts.hbs +1 -0
  162. package/templates/web-library/src/setupTests.ts +1 -0
package/CHANGELOG.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @backstage/cli-module-new
2
2
 
3
- ## 0.0.0-nightly-20260317031259
3
+ ## 0.1.0
4
4
 
5
5
  ### Minor Changes
6
6
 
@@ -8,8 +8,11 @@
8
8
 
9
9
  ### Patch Changes
10
10
 
11
+ - edf2b77: Added support for the `cli-module` template role for scaffolding new CLI module packages.
12
+ - ea90ab0: The built-in `yarn new` templates have been moved to this package from `@backstage/cli`. The default template references have been updated from `@backstage/cli/templates/*` to `@backstage/cli-module-new/templates/*`. Existing references to `@backstage/cli/templates/*` in your root `package.json` will continue to work through a backwards compatibility rewrite.
11
13
  - ebeb0d4: Updated the new frontend plugin template to use `@backstage/frontend-dev-utils` in its `dev/` entry point instead of wiring `createApp` manually. Generated plugins now get the same dev app helper setup as the built-in examples.
14
+ - 971cc94: The `new` command now prompts for the plugin package name when creating plugin modules, in order to properly populate the `package.json` file.
15
+ - a49a40d: Updated dependency `zod` to `^3.25.76 || ^4.0.0` & migrated to `/v3` or `/v4` imports.
12
16
  - Updated dependencies
13
- - @backstage/cli-node@0.0.0-nightly-20260317031259
14
- - @backstage/cli-common@0.0.0-nightly-20260317031259
15
- - @backstage/errors@1.2.7
17
+ - @backstage/cli-node@0.3.0
18
+ - @backstage/cli-common@0.2.0
@@ -1,16 +1,19 @@
1
1
  'use strict';
2
2
 
3
3
  const defaultTemplates = [
4
- "@backstage/cli/templates/frontend-plugin",
5
- "@backstage/cli/templates/backend-plugin",
6
- "@backstage/cli/templates/backend-plugin-module",
7
- "@backstage/cli/templates/plugin-web-library",
8
- "@backstage/cli/templates/plugin-node-library",
9
- "@backstage/cli/templates/plugin-common-library",
10
- "@backstage/cli/templates/web-library",
11
- "@backstage/cli/templates/node-library",
12
- "@backstage/cli/templates/catalog-provider-module",
13
- "@backstage/cli/templates/scaffolder-backend-module"
4
+ "@backstage/cli-module-new/templates/frontend-plugin",
5
+ "@backstage/cli-module-new/templates/frontend-plugin-module",
6
+ "@backstage/cli-module-new/templates/legacy-frontend-plugin",
7
+ "@backstage/cli-module-new/templates/backend-plugin",
8
+ "@backstage/cli-module-new/templates/backend-plugin-module",
9
+ "@backstage/cli-module-new/templates/plugin-web-library",
10
+ "@backstage/cli-module-new/templates/plugin-node-library",
11
+ "@backstage/cli-module-new/templates/plugin-common-library",
12
+ "@backstage/cli-module-new/templates/web-library",
13
+ "@backstage/cli-module-new/templates/node-library",
14
+ "@backstage/cli-module-new/templates/cli-module",
15
+ "@backstage/cli-module-new/templates/catalog-provider-module",
16
+ "@backstage/cli-module-new/templates/scaffolder-backend-module"
14
17
  ];
15
18
 
16
19
  exports.defaultTemplates = defaultTemplates;
@@ -1 +1 @@
1
- {"version":3,"file":"defaultTemplates.cjs.js","sources":["../../src/lib/defaultTemplates.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\nexport const defaultTemplates = [\n '@backstage/cli/templates/frontend-plugin',\n '@backstage/cli/templates/backend-plugin',\n '@backstage/cli/templates/backend-plugin-module',\n '@backstage/cli/templates/plugin-web-library',\n '@backstage/cli/templates/plugin-node-library',\n '@backstage/cli/templates/plugin-common-library',\n '@backstage/cli/templates/web-library',\n '@backstage/cli/templates/node-library',\n '@backstage/cli/templates/catalog-provider-module',\n '@backstage/cli/templates/scaffolder-backend-module',\n];\n"],"names":[],"mappings":";;AAgBO,MAAM,gBAAA,GAAmB;AAAA,EAC9B,0CAAA;AAAA,EACA,yCAAA;AAAA,EACA,gDAAA;AAAA,EACA,6CAAA;AAAA,EACA,8CAAA;AAAA,EACA,gDAAA;AAAA,EACA,sCAAA;AAAA,EACA,uCAAA;AAAA,EACA,kDAAA;AAAA,EACA;AACF;;;;"}
1
+ {"version":3,"file":"defaultTemplates.cjs.js","sources":["../../src/lib/defaultTemplates.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\nexport const defaultTemplates = [\n '@backstage/cli-module-new/templates/frontend-plugin',\n '@backstage/cli-module-new/templates/frontend-plugin-module',\n '@backstage/cli-module-new/templates/legacy-frontend-plugin',\n '@backstage/cli-module-new/templates/backend-plugin',\n '@backstage/cli-module-new/templates/backend-plugin-module',\n '@backstage/cli-module-new/templates/plugin-web-library',\n '@backstage/cli-module-new/templates/plugin-node-library',\n '@backstage/cli-module-new/templates/plugin-common-library',\n '@backstage/cli-module-new/templates/web-library',\n '@backstage/cli-module-new/templates/node-library',\n '@backstage/cli-module-new/templates/cli-module',\n '@backstage/cli-module-new/templates/catalog-provider-module',\n '@backstage/cli-module-new/templates/scaffolder-backend-module',\n];\n"],"names":[],"mappings":";;AAgBO,MAAM,gBAAA,GAAmB;AAAA,EAC9B,qDAAA;AAAA,EACA,4DAAA;AAAA,EACA,4DAAA;AAAA,EACA,oDAAA;AAAA,EACA,2DAAA;AAAA,EACA,wDAAA;AAAA,EACA,yDAAA;AAAA,EACA,2DAAA;AAAA,EACA,iDAAA;AAAA,EACA,kDAAA;AAAA,EACA,gDAAA;AAAA,EACA,6DAAA;AAAA,EACA;AACF;;;;"}
@@ -3,6 +3,12 @@
3
3
  var inquirer = require('inquirer');
4
4
  var codeowners = require('../codeowners/codeowners.cjs.js');
5
5
  var cliCommon = require('@backstage/cli-common');
6
+ require('../../packages/cli-internal/src/InternalCliModule.cjs.js');
7
+ require('../../packages/cli-internal/src/InternalCommandNode.cjs.js');
8
+ require('node:fs');
9
+ require('node:os');
10
+ require('node:path');
11
+ var knownPluginPackages = require('../../packages/cli-internal/src/knownPluginPackages.cjs.js');
6
12
  var resolvePackageParams = require('./resolvePackageParams.cjs.js');
7
13
 
8
14
  function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
@@ -28,6 +34,21 @@ async function collectPortableTemplateInput(options) {
28
34
  ...prefilledParams,
29
35
  ...deprecatedParams
30
36
  };
37
+ if (template.role === "backend-plugin-module" || template.role === "frontend-plugin-module") {
38
+ const pluginPkg = parameters.pluginPackage?.trim();
39
+ if (!pluginPkg || !isValidNpmPackageName(pluginPkg)) {
40
+ delete parameters.pluginPackage;
41
+ } else {
42
+ parameters.pluginPackage = pluginPkg;
43
+ }
44
+ if (parameters.pluginId && !parameters.pluginPackage) {
45
+ const knownPackages = template.role === "backend-plugin-module" ? knownPluginPackages.knownBackendPluginPackageNameByPluginId : knownPluginPackages.knownFrontendPluginPackageNameByPluginId;
46
+ const knownPackage = knownPackages[parameters.pluginId];
47
+ if (knownPackage) {
48
+ parameters.pluginPackage = knownPackage;
49
+ }
50
+ }
51
+ }
31
52
  const needsAnswer = [];
32
53
  const prefilledAnswers = {};
33
54
  for (const prompt of prompts) {
@@ -41,14 +62,21 @@ async function collectPortableTemplateInput(options) {
41
62
  needsAnswer
42
63
  );
43
64
  const answers = {
65
+ ...parameters,
44
66
  ...prefilledAnswers,
45
67
  ...promptAnswers
46
68
  };
69
+ let pluginPackage;
70
+ if (template.role === "backend-plugin-module" || template.role === "frontend-plugin-module") {
71
+ const knownPackages = template.role === "backend-plugin-module" ? knownPluginPackages.knownBackendPluginPackageNameByPluginId : knownPluginPackages.knownFrontendPluginPackageNameByPluginId;
72
+ pluginPackage = answers.pluginPackage ?? knownPackages[answers.pluginId];
73
+ }
47
74
  const roleParams = {
48
75
  role: template.role,
49
76
  name: answers.name,
50
77
  pluginId: answers.pluginId,
51
- moduleId: answers.moduleId
78
+ moduleId: answers.moduleId,
79
+ pluginPackage
52
80
  };
53
81
  const packageParams = resolvePackageParams.resolvePackageParams({
54
82
  roleParams,
@@ -111,11 +139,32 @@ function moduleIdIdPrompt() {
111
139
  }
112
140
  };
113
141
  }
142
+ function pluginPackagePrompt(role) {
143
+ const knownPackages = role === "backend-plugin-module" ? knownPluginPackages.knownBackendPluginPackageNameByPluginId : knownPluginPackages.knownFrontendPluginPackageNameByPluginId;
144
+ const examplePackage = role === "backend-plugin-module" ? "@backstage/plugin-catalog-backend" : "@backstage/plugin-catalog";
145
+ return {
146
+ type: "input",
147
+ name: "pluginPackage",
148
+ filter: (value) => value.trim(),
149
+ message: `Enter the package name of the plugin this module extends (e.g. ${examplePackage}) [required]`,
150
+ validate: (value) => {
151
+ if (!value) {
152
+ return "Please enter the package name of the plugin";
153
+ }
154
+ if (!isValidNpmPackageName(value)) {
155
+ return `Please enter a valid npm package name (e.g. ${examplePackage} or my-plugin)`;
156
+ }
157
+ return true;
158
+ },
159
+ when: (answers) => !knownPackages[answers.pluginId]
160
+ };
161
+ }
114
162
  function getPromptsForRole(role) {
115
163
  switch (role) {
116
164
  case "web-library":
117
165
  case "node-library":
118
166
  case "common-library":
167
+ case "cli-module":
119
168
  return [namePrompt()];
120
169
  case "plugin-web-library":
121
170
  case "plugin-node-library":
@@ -125,7 +174,7 @@ function getPromptsForRole(role) {
125
174
  return [pluginIdPrompt()];
126
175
  case "frontend-plugin-module":
127
176
  case "backend-plugin-module":
128
- return [pluginIdPrompt(), moduleIdIdPrompt()];
177
+ return [pluginIdPrompt(), moduleIdIdPrompt(), pluginPackagePrompt(role)];
129
178
  default:
130
179
  return [];
131
180
  }
@@ -147,6 +196,11 @@ function ownerPrompt() {
147
196
  }
148
197
  };
149
198
  }
199
+ const packageNamePattern = /^[a-z0-9][a-z0-9._-]*$/;
200
+ const scopedPackageNamePattern = /^@[a-z0-9][a-z0-9._-]*\/[a-z0-9][a-z0-9._-]*$/;
201
+ function isValidNpmPackageName(name) {
202
+ return packageNamePattern.test(name) || scopedPackageNamePattern.test(name);
203
+ }
150
204
 
151
205
  exports.collectPortableTemplateInput = collectPortableTemplateInput;
152
206
  exports.getPromptsForRole = getPromptsForRole;
@@ -154,4 +208,5 @@ exports.moduleIdIdPrompt = moduleIdIdPrompt;
154
208
  exports.namePrompt = namePrompt;
155
209
  exports.ownerPrompt = ownerPrompt;
156
210
  exports.pluginIdPrompt = pluginIdPrompt;
211
+ exports.pluginPackagePrompt = pluginPackagePrompt;
157
212
  //# sourceMappingURL=collectPortableTemplateInput.cjs.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"collectPortableTemplateInput.cjs.js","sources":["../../../src/lib/preparation/collectPortableTemplateInput.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 inquirer, { DistinctQuestion } from 'inquirer';\nimport { getCodeownersFilePath, parseOwnerIds } from '../codeowners';\nimport { targetPaths } from '@backstage/cli-common';\n\nimport {\n PortableTemplateConfig,\n PortableTemplateInput,\n PortableTemplateInputRoleParams,\n PortableTemplateParams,\n PortableTemplateRole,\n} from '../types';\nimport { PortableTemplate } from '../types';\nimport { resolvePackageParams } from './resolvePackageParams';\n\ntype CollectTemplateParamsOptions = {\n config: PortableTemplateConfig;\n template: PortableTemplate;\n prefilledParams: PortableTemplateParams;\n};\n\nexport async function collectPortableTemplateInput(\n options: CollectTemplateParamsOptions,\n): Promise<PortableTemplateInput> {\n const { config, template, prefilledParams } = options;\n\n const codeOwnersFilePath = await getCodeownersFilePath(targetPaths.rootDir);\n\n const prompts = getPromptsForRole(template.role);\n\n if (codeOwnersFilePath) {\n prompts.push(ownerPrompt());\n }\n\n const deprecatedParams: PortableTemplateParams = {};\n if (config.isUsingDefaultTemplates && prefilledParams.id) {\n console.warn(\n `DEPRECATION WARNING: The 'id' parameter is deprecated, use 'pluginId' instead`,\n );\n deprecatedParams.pluginId = prefilledParams.id;\n }\n\n const parameters = {\n ...template.values,\n ...prefilledParams,\n ...deprecatedParams,\n };\n\n const needsAnswer = [];\n const prefilledAnswers = {} as PortableTemplateParams;\n for (const prompt of prompts) {\n if (prompt.name && parameters[prompt.name] !== undefined) {\n prefilledAnswers[prompt.name] = parameters[prompt.name];\n } else {\n needsAnswer.push(prompt);\n }\n }\n\n const promptAnswers = await inquirer.prompt<PortableTemplateParams>(\n needsAnswer,\n );\n\n const answers = {\n ...prefilledAnswers,\n ...promptAnswers,\n };\n\n const roleParams = {\n role: template.role,\n name: answers.name,\n pluginId: answers.pluginId,\n moduleId: answers.moduleId,\n } as PortableTemplateInputRoleParams;\n\n const packageParams = resolvePackageParams({\n roleParams,\n packagePrefix: config.packageNamePrefix,\n pluginInfix: config.packageNamePluginInfix,\n });\n\n return {\n roleParams,\n owner: answers.owner as string | undefined,\n license: config.license,\n version: config.version,\n private: config.private,\n publishRegistry: config.publishRegistry,\n packageName: packageParams.packageName,\n packagePath: packageParams.packagePath,\n };\n}\n\nexport function namePrompt(): DistinctQuestion {\n return {\n type: 'input',\n name: 'name',\n message: 'Enter the name of the package, without scope [required]',\n validate: (value: string) => {\n if (!value) {\n return 'Please enter the name of the package';\n } else if (!/^[a-z0-9]+(-[a-z0-9]+)*$/.test(value)) {\n return 'Package names must be lowercase and contain only letters, digits, and dashes.';\n }\n return true;\n },\n };\n}\n\nexport function pluginIdPrompt(): DistinctQuestion {\n return {\n type: 'input',\n name: 'pluginId',\n message: 'Enter the ID of the plugin [required]',\n validate: (value: string) => {\n if (!value) {\n return 'Please enter the ID of the plugin';\n } else if (!/^[a-z0-9]+(-[a-z0-9]+)*$/.test(value)) {\n return 'Plugin IDs must be lowercase and contain only letters, digits, and dashes.';\n }\n return true;\n },\n };\n}\n\nexport function moduleIdIdPrompt(): DistinctQuestion {\n return {\n type: 'input',\n name: 'moduleId',\n message: 'Enter the ID of the module [required]',\n validate: (value: string) => {\n if (!value) {\n return 'Please enter the ID of the module';\n } else if (!/^[a-z0-9]+(-[a-z0-9]+)*$/.test(value)) {\n return 'Module IDs must be lowercase and contain only letters, digits, and dashes.';\n }\n return true;\n },\n };\n}\n\nexport function getPromptsForRole(\n role: PortableTemplateRole,\n): Array<DistinctQuestion> {\n switch (role) {\n case 'web-library':\n case 'node-library':\n case 'common-library':\n return [namePrompt()];\n case 'plugin-web-library':\n case 'plugin-node-library':\n case 'plugin-common-library':\n case 'frontend-plugin':\n case 'backend-plugin':\n return [pluginIdPrompt()];\n case 'frontend-plugin-module':\n case 'backend-plugin-module':\n return [pluginIdPrompt(), moduleIdIdPrompt()];\n default:\n return [];\n }\n}\n\nexport function ownerPrompt(): DistinctQuestion {\n return {\n type: 'input',\n name: 'owner',\n message: 'Enter an owner to add to CODEOWNERS [optional]',\n validate: (value: string) => {\n if (!value) {\n return true;\n }\n\n const ownerIds = parseOwnerIds(value);\n if (!ownerIds) {\n return 'The owner must be a space separated list of team names (e.g. @org/team-name), usernames (e.g. @username), or the email addresses (e.g. user@example.com).';\n }\n\n return true;\n },\n };\n}\n"],"names":["getCodeownersFilePath","targetPaths","inquirer","resolvePackageParams","parseOwnerIds"],"mappings":"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"}
1
+ {"version":3,"file":"collectPortableTemplateInput.cjs.js","sources":["../../../src/lib/preparation/collectPortableTemplateInput.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 inquirer, { DistinctQuestion } from 'inquirer';\nimport { getCodeownersFilePath, parseOwnerIds } from '../codeowners';\nimport { targetPaths } from '@backstage/cli-common';\nimport {\n knownBackendPluginPackageNameByPluginId,\n knownFrontendPluginPackageNameByPluginId,\n} from '@internal/cli';\n\nimport {\n PortableTemplateConfig,\n PortableTemplateInput,\n PortableTemplateInputRoleParams,\n PortableTemplateParams,\n PortableTemplateRole,\n} from '../types';\nimport { PortableTemplate } from '../types';\nimport { resolvePackageParams } from './resolvePackageParams';\n\ntype CollectTemplateParamsOptions = {\n config: PortableTemplateConfig;\n template: PortableTemplate;\n prefilledParams: PortableTemplateParams;\n};\n\nexport async function collectPortableTemplateInput(\n options: CollectTemplateParamsOptions,\n): Promise<PortableTemplateInput> {\n const { config, template, prefilledParams } = options;\n\n const codeOwnersFilePath = await getCodeownersFilePath(targetPaths.rootDir);\n\n const prompts = getPromptsForRole(template.role);\n\n if (codeOwnersFilePath) {\n prompts.push(ownerPrompt());\n }\n\n const deprecatedParams: PortableTemplateParams = {};\n if (config.isUsingDefaultTemplates && prefilledParams.id) {\n console.warn(\n `DEPRECATION WARNING: The 'id' parameter is deprecated, use 'pluginId' instead`,\n );\n deprecatedParams.pluginId = prefilledParams.id;\n }\n\n const parameters: PortableTemplateParams = {\n ...template.values,\n ...prefilledParams,\n ...deprecatedParams,\n };\n\n // Pre-populate pluginPackage for known plugins so the prompt is skipped.\n // Also clear out empty/invalid values so they don't bypass the prompt.\n if (\n template.role === 'backend-plugin-module' ||\n template.role === 'frontend-plugin-module'\n ) {\n const pluginPkg = (parameters.pluginPackage as string | undefined)?.trim();\n if (!pluginPkg || !isValidNpmPackageName(pluginPkg)) {\n delete parameters.pluginPackage;\n } else {\n parameters.pluginPackage = pluginPkg;\n }\n\n if (parameters.pluginId && !parameters.pluginPackage) {\n const knownPackages =\n template.role === 'backend-plugin-module'\n ? knownBackendPluginPackageNameByPluginId\n : knownFrontendPluginPackageNameByPluginId;\n const knownPackage = knownPackages[parameters.pluginId as string];\n if (knownPackage) {\n parameters.pluginPackage = knownPackage;\n }\n }\n }\n\n const needsAnswer = [];\n const prefilledAnswers = {} as PortableTemplateParams;\n for (const prompt of prompts) {\n if (prompt.name && parameters[prompt.name] !== undefined) {\n prefilledAnswers[prompt.name] = parameters[prompt.name];\n } else {\n needsAnswer.push(prompt);\n }\n }\n\n const promptAnswers = await inquirer.prompt<PortableTemplateParams>(\n needsAnswer,\n );\n\n const answers = {\n ...parameters,\n ...prefilledAnswers,\n ...promptAnswers,\n };\n\n let pluginPackage: string | undefined;\n if (\n template.role === 'backend-plugin-module' ||\n template.role === 'frontend-plugin-module'\n ) {\n const knownPackages =\n template.role === 'backend-plugin-module'\n ? knownBackendPluginPackageNameByPluginId\n : knownFrontendPluginPackageNameByPluginId;\n\n pluginPackage =\n (answers.pluginPackage as string) ??\n knownPackages[answers.pluginId as string];\n }\n\n const roleParams = {\n role: template.role,\n name: answers.name,\n pluginId: answers.pluginId,\n moduleId: answers.moduleId,\n pluginPackage,\n } as PortableTemplateInputRoleParams;\n\n const packageParams = resolvePackageParams({\n roleParams,\n packagePrefix: config.packageNamePrefix,\n pluginInfix: config.packageNamePluginInfix,\n });\n\n return {\n roleParams,\n owner: answers.owner as string | undefined,\n license: config.license,\n version: config.version,\n private: config.private,\n publishRegistry: config.publishRegistry,\n packageName: packageParams.packageName,\n packagePath: packageParams.packagePath,\n };\n}\n\nexport function namePrompt(): DistinctQuestion {\n return {\n type: 'input',\n name: 'name',\n message: 'Enter the name of the package, without scope [required]',\n validate: (value: string) => {\n if (!value) {\n return 'Please enter the name of the package';\n } else if (!/^[a-z0-9]+(-[a-z0-9]+)*$/.test(value)) {\n return 'Package names must be lowercase and contain only letters, digits, and dashes.';\n }\n return true;\n },\n };\n}\n\nexport function pluginIdPrompt(): DistinctQuestion {\n return {\n type: 'input',\n name: 'pluginId',\n message: 'Enter the ID of the plugin [required]',\n validate: (value: string) => {\n if (!value) {\n return 'Please enter the ID of the plugin';\n } else if (!/^[a-z0-9]+(-[a-z0-9]+)*$/.test(value)) {\n return 'Plugin IDs must be lowercase and contain only letters, digits, and dashes.';\n }\n return true;\n },\n };\n}\n\nexport function moduleIdIdPrompt(): DistinctQuestion {\n return {\n type: 'input',\n name: 'moduleId',\n message: 'Enter the ID of the module [required]',\n validate: (value: string) => {\n if (!value) {\n return 'Please enter the ID of the module';\n } else if (!/^[a-z0-9]+(-[a-z0-9]+)*$/.test(value)) {\n return 'Module IDs must be lowercase and contain only letters, digits, and dashes.';\n }\n return true;\n },\n };\n}\n\nexport function pluginPackagePrompt(\n role: 'backend-plugin-module' | 'frontend-plugin-module',\n): DistinctQuestion {\n const knownPackages =\n role === 'backend-plugin-module'\n ? knownBackendPluginPackageNameByPluginId\n : knownFrontendPluginPackageNameByPluginId;\n\n const examplePackage =\n role === 'backend-plugin-module'\n ? '@backstage/plugin-catalog-backend'\n : '@backstage/plugin-catalog';\n\n return {\n type: 'input',\n name: 'pluginPackage',\n filter: (value: string) => value.trim(),\n message: `Enter the package name of the plugin this module extends (e.g. ${examplePackage}) [required]`,\n validate: (value: string) => {\n if (!value) {\n return 'Please enter the package name of the plugin';\n }\n if (!isValidNpmPackageName(value)) {\n return `Please enter a valid npm package name (e.g. ${examplePackage} or my-plugin)`;\n }\n return true;\n },\n when: (answers: PortableTemplateParams) =>\n !knownPackages[answers.pluginId as string],\n };\n}\n\nexport function getPromptsForRole(\n role: PortableTemplateRole,\n): Array<DistinctQuestion> {\n switch (role) {\n case 'web-library':\n case 'node-library':\n case 'common-library':\n case 'cli-module':\n return [namePrompt()];\n case 'plugin-web-library':\n case 'plugin-node-library':\n case 'plugin-common-library':\n case 'frontend-plugin':\n case 'backend-plugin':\n return [pluginIdPrompt()];\n case 'frontend-plugin-module':\n case 'backend-plugin-module':\n return [pluginIdPrompt(), moduleIdIdPrompt(), pluginPackagePrompt(role)];\n default:\n return [];\n }\n}\n\nexport function ownerPrompt(): DistinctQuestion {\n return {\n type: 'input',\n name: 'owner',\n message: 'Enter an owner to add to CODEOWNERS [optional]',\n validate: (value: string) => {\n if (!value) {\n return true;\n }\n\n const ownerIds = parseOwnerIds(value);\n if (!ownerIds) {\n return 'The owner must be a space separated list of team names (e.g. @org/team-name), usernames (e.g. @username), or the email addresses (e.g. user@example.com).';\n }\n\n return true;\n },\n };\n}\n\n// Based on the same pattern as namePrompt/pluginIdPrompt, but extended to support npm scopes\n// and additional allowed characters ('.' and '_'). Matches examples like: package-name, my.package_name, @scope/package-name, @scope/package.\nconst packageNamePattern = /^[a-z0-9][a-z0-9._-]*$/;\nconst scopedPackageNamePattern =\n /^@[a-z0-9][a-z0-9._-]*\\/[a-z0-9][a-z0-9._-]*$/;\n\nfunction isValidNpmPackageName(name: string) {\n return packageNamePattern.test(name) || scopedPackageNamePattern.test(name);\n}\n"],"names":["getCodeownersFilePath","targetPaths","knownBackendPluginPackageNameByPluginId","knownFrontendPluginPackageNameByPluginId","inquirer","resolvePackageParams","parseOwnerIds"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var zod = require('zod');
3
+ var v3 = require('zod/v3');
4
4
  var fs = require('fs-extra');
5
5
  var recursiveReaddir = require('recursive-readdir');
6
6
  var path = require('node:path');
@@ -8,18 +8,18 @@ var yaml = require('yaml');
8
8
  var cliCommon = require('@backstage/cli-common');
9
9
  var types = require('../types.cjs.js');
10
10
  var errors = require('@backstage/errors');
11
- var v3 = require('zod-validation-error/v3');
11
+ var v3$1 = require('zod-validation-error/v3');
12
12
 
13
13
  function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
14
14
 
15
15
  var fs__default = /*#__PURE__*/_interopDefaultCompat(fs);
16
16
  var recursiveReaddir__default = /*#__PURE__*/_interopDefaultCompat(recursiveReaddir);
17
17
 
18
- const templateDefinitionSchema = zod.z.object({
19
- name: zod.z.string(),
20
- role: zod.z.enum(types.TEMPLATE_ROLES),
21
- description: zod.z.string().optional(),
22
- values: zod.z.record(zod.z.string()).optional()
18
+ const templateDefinitionSchema = v3.z.object({
19
+ name: v3.z.string(),
20
+ role: v3.z.enum(types.TEMPLATE_ROLES),
21
+ description: v3.z.string().optional(),
22
+ values: v3.z.record(v3.z.string()).optional()
23
23
  }).strict();
24
24
  async function loadPortableTemplate(pointer) {
25
25
  if (pointer.target.match(/https?:\/\//)) {
@@ -36,7 +36,7 @@ async function loadPortableTemplate(pointer) {
36
36
  if (!parsed.success) {
37
37
  throw new errors.ForwardedError(
38
38
  `Invalid template definition at '${pointer.target}'`,
39
- v3.fromZodError(parsed.error)
39
+ v3$1.fromZodError(parsed.error)
40
40
  );
41
41
  }
42
42
  const { role, values = {} } = parsed.data;
@@ -1 +1 @@
1
- {"version":3,"file":"loadPortableTemplate.cjs.js","sources":["../../../src/lib/preparation/loadPortableTemplate.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 { z } from 'zod';\nimport fs from 'fs-extra';\nimport recursiveReaddir from 'recursive-readdir';\nimport { resolve as resolvePath, relative as relativePath } from 'node:path';\nimport { dirname } from 'node:path';\nimport { parse as parseYaml } from 'yaml';\nimport { targetPaths } from '@backstage/cli-common';\n\nimport {\n PortableTemplateFile,\n PortableTemplatePointer,\n TEMPLATE_ROLES,\n} from '../types';\nimport { PortableTemplate } from '../types';\nimport { ForwardedError } from '@backstage/errors';\nimport { fromZodError } from 'zod-validation-error/v3';\n\nconst templateDefinitionSchema = z\n .object({\n name: z.string(),\n role: z.enum(TEMPLATE_ROLES),\n description: z.string().optional(),\n values: z.record(z.string()).optional(),\n })\n .strict();\n\nexport async function loadPortableTemplate(\n pointer: PortableTemplatePointer,\n): Promise<PortableTemplate> {\n if (pointer.target.match(/https?:\\/\\//)) {\n throw new Error('Remote templates are not supported yet');\n }\n const templateContent = await fs\n .readFile(targetPaths.resolveRoot(pointer.target), 'utf-8')\n .catch(error => {\n throw new ForwardedError(\n `Failed to load template definition from '${pointer.target}'`,\n error,\n );\n });\n const rawTemplate = parseYaml(templateContent);\n\n const parsed = templateDefinitionSchema.safeParse(rawTemplate);\n if (!parsed.success) {\n throw new ForwardedError(\n `Invalid template definition at '${pointer.target}'`,\n fromZodError(parsed.error),\n );\n }\n\n const { role, values = {} } = parsed.data;\n\n const templatePath = resolvePath(dirname(pointer.target));\n const filePaths = await recursiveReaddir(templatePath).catch(error => {\n throw new ForwardedError(\n `Failed to load template contents from '${templatePath}'`,\n error,\n );\n });\n\n const loadedFiles = new Array<PortableTemplateFile>();\n\n for (const filePath of filePaths) {\n const path = relativePath(templatePath, filePath);\n if (filePath === pointer.target) {\n continue;\n }\n\n const content = await fs.readFile(filePath, 'utf-8').catch(error => {\n throw new ForwardedError(\n `Failed to load file contents from '${path}'`,\n error,\n );\n });\n\n if (path.endsWith('.hbs')) {\n loadedFiles.push({\n path: path.slice(0, -4),\n content,\n syntax: 'handlebars',\n });\n } else {\n loadedFiles.push({ path, content });\n }\n }\n\n return {\n name: pointer.name,\n role,\n files: loadedFiles,\n values,\n };\n}\n"],"names":["z","TEMPLATE_ROLES","fs","targetPaths","ForwardedError","parseYaml","fromZodError","resolvePath","dirname","recursiveReaddir","path","relativePath"],"mappings":"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"}
1
+ {"version":3,"file":"loadPortableTemplate.cjs.js","sources":["../../../src/lib/preparation/loadPortableTemplate.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 { z } from 'zod/v3';\nimport fs from 'fs-extra';\nimport recursiveReaddir from 'recursive-readdir';\nimport { resolve as resolvePath, relative as relativePath } from 'node:path';\nimport { dirname } from 'node:path';\nimport { parse as parseYaml } from 'yaml';\nimport { targetPaths } from '@backstage/cli-common';\n\nimport {\n PortableTemplateFile,\n PortableTemplatePointer,\n TEMPLATE_ROLES,\n} from '../types';\nimport { PortableTemplate } from '../types';\nimport { ForwardedError } from '@backstage/errors';\nimport { fromZodError } from 'zod-validation-error/v3';\n\nconst templateDefinitionSchema = z\n .object({\n name: z.string(),\n role: z.enum(TEMPLATE_ROLES),\n description: z.string().optional(),\n values: z.record(z.string()).optional(),\n })\n .strict();\n\nexport async function loadPortableTemplate(\n pointer: PortableTemplatePointer,\n): Promise<PortableTemplate> {\n if (pointer.target.match(/https?:\\/\\//)) {\n throw new Error('Remote templates are not supported yet');\n }\n const templateContent = await fs\n .readFile(targetPaths.resolveRoot(pointer.target), 'utf-8')\n .catch(error => {\n throw new ForwardedError(\n `Failed to load template definition from '${pointer.target}'`,\n error,\n );\n });\n const rawTemplate = parseYaml(templateContent);\n\n const parsed = templateDefinitionSchema.safeParse(rawTemplate);\n if (!parsed.success) {\n throw new ForwardedError(\n `Invalid template definition at '${pointer.target}'`,\n fromZodError(parsed.error),\n );\n }\n\n const { role, values = {} } = parsed.data;\n\n const templatePath = resolvePath(dirname(pointer.target));\n const filePaths = await recursiveReaddir(templatePath).catch(error => {\n throw new ForwardedError(\n `Failed to load template contents from '${templatePath}'`,\n error,\n );\n });\n\n const loadedFiles = new Array<PortableTemplateFile>();\n\n for (const filePath of filePaths) {\n const path = relativePath(templatePath, filePath);\n if (filePath === pointer.target) {\n continue;\n }\n\n const content = await fs.readFile(filePath, 'utf-8').catch(error => {\n throw new ForwardedError(\n `Failed to load file contents from '${path}'`,\n error,\n );\n });\n\n if (path.endsWith('.hbs')) {\n loadedFiles.push({\n path: path.slice(0, -4),\n content,\n syntax: 'handlebars',\n });\n } else {\n loadedFiles.push({ path, content });\n }\n }\n\n return {\n name: pointer.name,\n role,\n files: loadedFiles,\n values,\n };\n}\n"],"names":["z","TEMPLATE_ROLES","fs","targetPaths","ForwardedError","parseYaml","fromZodError","resolvePath","dirname","recursiveReaddir","path","relativePath"],"mappings":";;;;;;;;;;;;;;;;;AAiCA,MAAM,wBAAA,GAA2BA,KAC9B,MAAA,CAAO;AAAA,EACN,IAAA,EAAMA,KAAE,MAAA,EAAO;AAAA,EACf,IAAA,EAAMA,IAAA,CAAE,IAAA,CAAKC,oBAAc,CAAA;AAAA,EAC3B,WAAA,EAAaD,IAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA,EACjC,QAAQA,IAAA,CAAE,MAAA,CAAOA,KAAE,MAAA,EAAQ,EAAE,QAAA;AAC/B,CAAC,EACA,MAAA,EAAO;AAEV,eAAsB,qBACpB,OAAA,EAC2B;AAC3B,EAAA,IAAI,OAAA,CAAQ,MAAA,CAAO,KAAA,CAAM,aAAa,CAAA,EAAG;AACvC,IAAA,MAAM,IAAI,MAAM,wCAAwC,CAAA;AAAA,EAC1D;AACA,EAAA,MAAM,eAAA,GAAkB,MAAME,mBAAA,CAC3B,QAAA,CAASC,qBAAA,CAAY,WAAA,CAAY,OAAA,CAAQ,MAAM,CAAA,EAAG,OAAO,CAAA,CACzD,KAAA,CAAM,CAAA,KAAA,KAAS;AACd,IAAA,MAAM,IAAIC,qBAAA;AAAA,MACR,CAAA,yCAAA,EAA4C,QAAQ,MAAM,CAAA,CAAA,CAAA;AAAA,MAC1D;AAAA,KACF;AAAA,EACF,CAAC,CAAA;AACH,EAAA,MAAM,WAAA,GAAcC,WAAU,eAAe,CAAA;AAE7C,EAAA,MAAM,MAAA,GAAS,wBAAA,CAAyB,SAAA,CAAU,WAAW,CAAA;AAC7D,EAAA,IAAI,CAAC,OAAO,OAAA,EAAS;AACnB,IAAA,MAAM,IAAID,qBAAA;AAAA,MACR,CAAA,gCAAA,EAAmC,QAAQ,MAAM,CAAA,CAAA,CAAA;AAAA,MACjDE,iBAAA,CAAa,OAAO,KAAK;AAAA,KAC3B;AAAA,EACF;AAEA,EAAA,MAAM,EAAE,IAAA,EAAM,MAAA,GAAS,EAAC,KAAM,MAAA,CAAO,IAAA;AAErC,EAAA,MAAM,YAAA,GAAeC,YAAA,CAAYC,YAAA,CAAQ,OAAA,CAAQ,MAAM,CAAC,CAAA;AACxD,EAAA,MAAM,YAAY,MAAMC,iCAAA,CAAiB,YAAY,CAAA,CAAE,MAAM,CAAA,KAAA,KAAS;AACpE,IAAA,MAAM,IAAIL,qBAAA;AAAA,MACR,0CAA0C,YAAY,CAAA,CAAA,CAAA;AAAA,MACtD;AAAA,KACF;AAAA,EACF,CAAC,CAAA;AAED,EAAA,MAAM,WAAA,GAAc,IAAI,KAAA,EAA4B;AAEpD,EAAA,KAAA,MAAW,YAAY,SAAA,EAAW;AAChC,IAAA,MAAMM,MAAA,GAAOC,aAAA,CAAa,YAAA,EAAc,QAAQ,CAAA;AAChD,IAAA,IAAI,QAAA,KAAa,QAAQ,MAAA,EAAQ;AAC/B,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,OAAA,GAAU,MAAMT,mBAAA,CAAG,QAAA,CAAS,UAAU,OAAO,CAAA,CAAE,MAAM,CAAA,KAAA,KAAS;AAClE,MAAA,MAAM,IAAIE,qBAAA;AAAA,QACR,sCAAsCM,MAAI,CAAA,CAAA,CAAA;AAAA,QAC1C;AAAA,OACF;AAAA,IACF,CAAC,CAAA;AAED,IAAA,IAAIA,MAAA,CAAK,QAAA,CAAS,MAAM,CAAA,EAAG;AACzB,MAAA,WAAA,CAAY,IAAA,CAAK;AAAA,QACf,IAAA,EAAMA,MAAA,CAAK,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA;AAAA,QACtB,OAAA;AAAA,QACA,MAAA,EAAQ;AAAA,OACT,CAAA;AAAA,IACH,CAAA,MAAO;AACL,MAAA,WAAA,CAAY,IAAA,CAAK,QAAEA,MAAA,EAAM,OAAA,EAAS,CAAA;AAAA,IACpC;AAAA,EACF;AAEA,EAAA,OAAO;AAAA,IACL,MAAM,OAAA,CAAQ,IAAA;AAAA,IACd,IAAA;AAAA,IACA,KAAA,EAAO,WAAA;AAAA,IACP;AAAA,GACF;AACF;;;;"}
@@ -6,14 +6,48 @@ var cliCommon = require('@backstage/cli-common');
6
6
  var defaultTemplates = require('../defaultTemplates.cjs.js');
7
7
  var types = require('../types.cjs.js');
8
8
  var yaml = require('yaml');
9
- var zod = require('zod');
10
- var v3 = require('zod-validation-error/v3');
9
+ var v3 = require('zod/v3');
10
+ var v3$1 = require('zod-validation-error/v3');
11
11
  var errors = require('@backstage/errors');
12
12
 
13
13
  function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
14
14
 
15
15
  var fs__default = /*#__PURE__*/_interopDefaultCompat(fs);
16
16
 
17
+ async function detectFrontendSystem(basePath) {
18
+ const appPkgPath = path.join(basePath, "packages", "app", "package.json");
19
+ try {
20
+ const appPkgJson = await fs__default.default.readJson(appPkgPath);
21
+ const deps = {
22
+ ...appPkgJson.dependencies,
23
+ ...appPkgJson.devDependencies
24
+ };
25
+ if (deps["@backstage/frontend-defaults"] || deps["@backstage/frontend-app-api"]) {
26
+ return "new";
27
+ }
28
+ if (deps["@backstage/app-defaults"] || deps["@backstage/core-app-api"]) {
29
+ return "legacy";
30
+ }
31
+ } catch {
32
+ }
33
+ return "unknown";
34
+ }
35
+ const newFrontendTemplates = [
36
+ "@backstage/cli-module-new/templates/frontend-plugin",
37
+ "@backstage/cli-module-new/templates/frontend-plugin-module"
38
+ ];
39
+ const legacyFrontendTemplates = [
40
+ "@backstage/cli-module-new/templates/legacy-frontend-plugin"
41
+ ];
42
+ function filterTemplateEntriesForFrontendSystem(entries, frontendSystem) {
43
+ if (frontendSystem === "unknown") {
44
+ return entries;
45
+ }
46
+ if (frontendSystem === "new") {
47
+ return entries.filter((e) => !legacyFrontendTemplates.includes(e.rawPointer));
48
+ }
49
+ return entries.filter((e) => !newFrontendTemplates.includes(e.rawPointer));
50
+ }
17
51
  const defaults = {
18
52
  license: "Apache-2.0",
19
53
  version: "0.1.0",
@@ -22,20 +56,20 @@ const defaults = {
22
56
  packageNamePrefix: "@internal/",
23
57
  packageNamePluginInfix: "plugin-"
24
58
  };
25
- const newConfigSchema = zod.z.object({
26
- templates: zod.z.array(zod.z.string()).optional(),
27
- globals: zod.z.object({
28
- license: zod.z.string().optional(),
29
- version: zod.z.string().optional(),
30
- private: zod.z.boolean().optional(),
31
- publishRegistry: zod.z.string().optional(),
32
- namePrefix: zod.z.string().optional(),
33
- namePluginInfix: zod.z.string().optional()
59
+ const newConfigSchema = v3.z.object({
60
+ templates: v3.z.array(v3.z.string()).optional(),
61
+ globals: v3.z.object({
62
+ license: v3.z.string().optional(),
63
+ version: v3.z.string().optional(),
64
+ private: v3.z.boolean().optional(),
65
+ publishRegistry: v3.z.string().optional(),
66
+ namePrefix: v3.z.string().optional(),
67
+ namePluginInfix: v3.z.string().optional()
34
68
  }).optional()
35
69
  }).strict();
36
- const pkgJsonWithNewConfigSchema = zod.z.object({
37
- backstage: zod.z.object({
38
- cli: zod.z.object({
70
+ const pkgJsonWithNewConfigSchema = v3.z.object({
71
+ backstage: v3.z.object({
72
+ cli: v3.z.object({
39
73
  new: newConfigSchema.optional()
40
74
  }).optional()
41
75
  }).optional()
@@ -54,12 +88,13 @@ async function loadPortableTemplateConfig(options = {}) {
54
88
  if (!parsed.success) {
55
89
  throw new errors.ForwardedError(
56
90
  `Failed to load templating configuration from '${pkgPath}'`,
57
- v3.fromZodError(parsed.error)
91
+ v3$1.fromZodError(parsed.error)
58
92
  );
59
93
  }
60
94
  const config = parsed.data.backstage?.cli?.new;
61
95
  const basePath = path.dirname(pkgPath);
62
- const templatePointerEntries = await Promise.all(
96
+ const isUsingDefaultTemplates = !config?.templates;
97
+ let templatePointerEntries = await Promise.all(
63
98
  (config?.templates ?? defaultTemplates.defaultTemplates).map(async (rawPointer) => {
64
99
  try {
65
100
  const templatePath = resolveLocalTemplatePath(rawPointer, basePath);
@@ -73,6 +108,13 @@ async function loadPortableTemplateConfig(options = {}) {
73
108
  }
74
109
  })
75
110
  );
111
+ if (isUsingDefaultTemplates) {
112
+ const frontendSystem = await detectFrontendSystem(basePath);
113
+ templatePointerEntries = filterTemplateEntriesForFrontendSystem(
114
+ templatePointerEntries,
115
+ frontendSystem
116
+ );
117
+ }
76
118
  const templateNameConflicts = /* @__PURE__ */ new Map();
77
119
  for (const { pointer, rawPointer } of templatePointerEntries) {
78
120
  const conflict = templateNameConflicts.get(pointer.name);
@@ -89,7 +131,7 @@ async function loadPortableTemplateConfig(options = {}) {
89
131
  overrides.packageNamePluginInfix ?? config?.globals?.namePluginInfix
90
132
  );
91
133
  return {
92
- isUsingDefaultTemplates: !config?.templates,
134
+ isUsingDefaultTemplates,
93
135
  templatePointers: templatePointerEntries.map(({ pointer }) => pointer),
94
136
  license: overrides.license ?? config?.globals?.license ?? defaults.license,
95
137
  version: overrides.version ?? config?.globals?.version ?? defaults.version,
@@ -99,6 +141,8 @@ async function loadPortableTemplateConfig(options = {}) {
99
141
  packageNamePluginInfix
100
142
  };
101
143
  }
144
+ const CLI_TEMPLATE_PREFIX = "@backstage/cli/templates/";
145
+ const CLI_MODULE_NEW_TEMPLATE_PREFIX = "@backstage/cli-module-new/templates/";
102
146
  function resolveLocalTemplatePath(pointer, basePath) {
103
147
  if (path.isAbsolute(pointer)) {
104
148
  throw new Error(`Template target may not be an absolute path`);
@@ -106,20 +150,23 @@ function resolveLocalTemplatePath(pointer, basePath) {
106
150
  if (pointer.startsWith(".")) {
107
151
  return path.resolve(basePath, pointer, types.TEMPLATE_FILE_NAME);
108
152
  }
109
- return require.resolve(`${pointer}/${types.TEMPLATE_FILE_NAME}`, {
153
+ const resolvedPointer = pointer.startsWith(CLI_TEMPLATE_PREFIX) ? `${CLI_MODULE_NEW_TEMPLATE_PREFIX}${pointer.slice(
154
+ CLI_TEMPLATE_PREFIX.length
155
+ )}` : pointer;
156
+ return require.resolve(`${resolvedPointer}/${types.TEMPLATE_FILE_NAME}`, {
110
157
  paths: [basePath]
111
158
  });
112
159
  }
113
- const partialTemplateDefinitionSchema = zod.z.object({
114
- name: zod.z.string(),
115
- description: zod.z.string().optional()
160
+ const partialTemplateDefinitionSchema = v3.z.object({
161
+ name: v3.z.string(),
162
+ description: v3.z.string().optional()
116
163
  });
117
164
  async function peekLocalTemplateDefinition(target) {
118
165
  const content = await fs__default.default.readFile(target, "utf8");
119
166
  const rawTemplate = yaml.parse(content);
120
167
  const parsed = partialTemplateDefinitionSchema.safeParse(rawTemplate);
121
168
  if (!parsed.success) {
122
- throw v3.fromZodError(parsed.error);
169
+ throw v3$1.fromZodError(parsed.error);
123
170
  }
124
171
  return {
125
172
  name: parsed.data.name,
@@ -1 +1 @@
1
- {"version":3,"file":"loadPortableTemplateConfig.cjs.js","sources":["../../../src/lib/preparation/loadPortableTemplateConfig.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 fs from 'fs-extra';\nimport { resolve as resolvePath, dirname, isAbsolute } from 'node:path';\nimport { targetPaths } from '@backstage/cli-common';\n\nimport { defaultTemplates } from '../defaultTemplates';\nimport {\n PortableTemplateConfig,\n PortableTemplatePointer,\n TEMPLATE_FILE_NAME,\n} from '../types';\nimport { parse as parseYaml } from 'yaml';\nimport { z } from 'zod';\nimport { fromZodError } from 'zod-validation-error/v3';\nimport { ForwardedError } from '@backstage/errors';\n\nconst defaults = {\n license: 'Apache-2.0',\n version: '0.1.0',\n private: true,\n publishRegistry: undefined,\n packageNamePrefix: '@internal/',\n packageNamePluginInfix: 'plugin-',\n};\n\nconst newConfigSchema = z\n .object({\n templates: z.array(z.string()).optional(),\n globals: z\n .object({\n license: z.string().optional(),\n version: z.string().optional(),\n private: z.boolean().optional(),\n publishRegistry: z.string().optional(),\n namePrefix: z.string().optional(),\n namePluginInfix: z.string().optional(),\n })\n .optional(),\n })\n .strict();\n\nconst pkgJsonWithNewConfigSchema = z.object({\n backstage: z\n .object({\n cli: z\n .object({\n new: newConfigSchema.optional(),\n })\n .optional(),\n })\n .optional(),\n});\n\ntype LoadConfigOptions = {\n packagePath?: string;\n overrides?: Partial<PortableTemplateConfig>;\n};\n\nfunction computePackageNamePluginInfix(\n packageNamePrefix: string,\n namePluginInfix?: string,\n) {\n const packageNamePluginInfix =\n namePluginInfix ??\n (packageNamePrefix.includes('backstage')\n ? defaults.packageNamePluginInfix\n : 'backstage-plugin-');\n\n return {\n packageNamePluginInfix,\n };\n}\n\nexport async function loadPortableTemplateConfig(\n options: LoadConfigOptions = {},\n): Promise<PortableTemplateConfig> {\n const { overrides = {} } = options;\n const pkgPath =\n options.packagePath ?? targetPaths.resolveRoot('package.json');\n const pkgJson = await fs.readJson(pkgPath);\n\n const parsed = pkgJsonWithNewConfigSchema.safeParse(pkgJson);\n if (!parsed.success) {\n throw new ForwardedError(\n `Failed to load templating configuration from '${pkgPath}'`,\n fromZodError(parsed.error),\n );\n }\n\n const config = parsed.data.backstage?.cli?.new;\n\n const basePath = dirname(pkgPath);\n const templatePointerEntries = await Promise.all(\n (config?.templates ?? defaultTemplates).map(async rawPointer => {\n try {\n const templatePath = resolveLocalTemplatePath(rawPointer, basePath);\n\n const pointer = await peekLocalTemplateDefinition(templatePath);\n return { pointer, rawPointer };\n } catch (error) {\n throw new ForwardedError(\n `Failed to load template definition '${rawPointer}'`,\n error,\n );\n }\n }),\n );\n\n const templateNameConflicts = new Map<string, string>();\n for (const { pointer, rawPointer } of templatePointerEntries) {\n const conflict = templateNameConflicts.get(pointer.name);\n if (conflict) {\n throw new Error(\n `Invalid template configuration, received conflicting template name '${pointer.name}' from '${conflict}' and '${rawPointer}'`,\n );\n }\n templateNameConflicts.set(pointer.name, rawPointer);\n }\n\n const packageNamePrefix =\n overrides.packageNamePrefix ??\n config?.globals?.namePrefix ??\n defaults.packageNamePrefix;\n\n const { packageNamePluginInfix } = computePackageNamePluginInfix(\n packageNamePrefix,\n overrides.packageNamePluginInfix ?? config?.globals?.namePluginInfix,\n );\n\n return {\n isUsingDefaultTemplates: !config?.templates,\n templatePointers: templatePointerEntries.map(({ pointer }) => pointer),\n license: overrides.license ?? config?.globals?.license ?? defaults.license,\n version: overrides.version ?? config?.globals?.version ?? defaults.version,\n private: overrides.private ?? config?.globals?.private ?? defaults.private,\n publishRegistry:\n overrides.publishRegistry ??\n config?.globals?.publishRegistry ??\n defaults.publishRegistry,\n packageNamePrefix,\n packageNamePluginInfix,\n };\n}\n\nfunction resolveLocalTemplatePath(pointer: string, basePath: string): string {\n if (isAbsolute(pointer)) {\n throw new Error(`Template target may not be an absolute path`);\n }\n\n if (pointer.startsWith('.')) {\n return resolvePath(basePath, pointer, TEMPLATE_FILE_NAME);\n }\n\n return require.resolve(`${pointer}/${TEMPLATE_FILE_NAME}`, {\n paths: [basePath],\n });\n}\n\nconst partialTemplateDefinitionSchema = z.object({\n name: z.string(),\n description: z.string().optional(),\n});\n\nasync function peekLocalTemplateDefinition(\n target: string,\n): Promise<PortableTemplatePointer> {\n const content = await fs.readFile(target, 'utf8');\n\n const rawTemplate = parseYaml(content);\n const parsed = partialTemplateDefinitionSchema.safeParse(rawTemplate);\n if (!parsed.success) {\n throw fromZodError(parsed.error);\n }\n\n return {\n name: parsed.data.name,\n description: parsed.data.description,\n target,\n };\n}\n"],"names":["z","targetPaths","fs","ForwardedError","fromZodError","dirname","defaultTemplates","isAbsolute","resolvePath","TEMPLATE_FILE_NAME","parseYaml"],"mappings":"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"}
1
+ {"version":3,"file":"loadPortableTemplateConfig.cjs.js","sources":["../../../src/lib/preparation/loadPortableTemplateConfig.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 fs from 'fs-extra';\nimport { resolve as resolvePath, dirname, isAbsolute, join } from 'node:path';\nimport { targetPaths } from '@backstage/cli-common';\nimport { defaultTemplates } from '../defaultTemplates';\nimport {\n PortableTemplateConfig,\n PortableTemplatePointer,\n TEMPLATE_FILE_NAME,\n} from '../types';\nimport { parse as parseYaml } from 'yaml';\nimport { z } from 'zod/v3';\nimport { fromZodError } from 'zod-validation-error/v3';\nimport { ForwardedError } from '@backstage/errors';\n\ntype FrontendSystem = 'new' | 'legacy' | 'unknown';\n\nasync function detectFrontendSystem(basePath: string): Promise<FrontendSystem> {\n const appPkgPath = join(basePath, 'packages', 'app', 'package.json');\n\n try {\n const appPkgJson = await fs.readJson(appPkgPath);\n const deps = {\n ...appPkgJson.dependencies,\n ...appPkgJson.devDependencies,\n };\n\n if (\n deps['@backstage/frontend-defaults'] ||\n deps['@backstage/frontend-app-api']\n ) {\n return 'new';\n }\n if (deps['@backstage/app-defaults'] || deps['@backstage/core-app-api']) {\n return 'legacy';\n }\n } catch {\n // App package doesn't exist or can't be read\n }\n\n return 'unknown';\n}\n\n// Templates to exclude based on frontend system detection (by path, not name)\nconst newFrontendTemplates = [\n '@backstage/cli-module-new/templates/frontend-plugin',\n '@backstage/cli-module-new/templates/frontend-plugin-module',\n];\nconst legacyFrontendTemplates = [\n '@backstage/cli-module-new/templates/legacy-frontend-plugin',\n];\n\nfunction filterTemplateEntriesForFrontendSystem(\n entries: Array<{ pointer: PortableTemplatePointer; rawPointer: string }>,\n frontendSystem: FrontendSystem,\n): Array<{ pointer: PortableTemplatePointer; rawPointer: string }> {\n if (frontendSystem === 'unknown') {\n return entries;\n }\n\n if (frontendSystem === 'new') {\n // Filter out legacy frontend templates\n return entries.filter(e => !legacyFrontendTemplates.includes(e.rawPointer));\n }\n\n // Legacy system - filter out new frontend templates\n return entries.filter(e => !newFrontendTemplates.includes(e.rawPointer));\n}\n\nconst defaults = {\n license: 'Apache-2.0',\n version: '0.1.0',\n private: true,\n publishRegistry: undefined,\n packageNamePrefix: '@internal/',\n packageNamePluginInfix: 'plugin-',\n};\n\nconst newConfigSchema = z\n .object({\n templates: z.array(z.string()).optional(),\n globals: z\n .object({\n license: z.string().optional(),\n version: z.string().optional(),\n private: z.boolean().optional(),\n publishRegistry: z.string().optional(),\n namePrefix: z.string().optional(),\n namePluginInfix: z.string().optional(),\n })\n .optional(),\n })\n .strict();\n\nconst pkgJsonWithNewConfigSchema = z.object({\n backstage: z\n .object({\n cli: z\n .object({\n new: newConfigSchema.optional(),\n })\n .optional(),\n })\n .optional(),\n});\n\ntype LoadConfigOptions = {\n packagePath?: string;\n overrides?: Partial<PortableTemplateConfig>;\n};\n\nfunction computePackageNamePluginInfix(\n packageNamePrefix: string,\n namePluginInfix?: string,\n) {\n const packageNamePluginInfix =\n namePluginInfix ??\n (packageNamePrefix.includes('backstage')\n ? defaults.packageNamePluginInfix\n : 'backstage-plugin-');\n\n return {\n packageNamePluginInfix,\n };\n}\n\nexport async function loadPortableTemplateConfig(\n options: LoadConfigOptions = {},\n): Promise<PortableTemplateConfig> {\n const { overrides = {} } = options;\n const pkgPath =\n options.packagePath ?? targetPaths.resolveRoot('package.json');\n const pkgJson = await fs.readJson(pkgPath);\n\n const parsed = pkgJsonWithNewConfigSchema.safeParse(pkgJson);\n if (!parsed.success) {\n throw new ForwardedError(\n `Failed to load templating configuration from '${pkgPath}'`,\n fromZodError(parsed.error),\n );\n }\n\n const config = parsed.data.backstage?.cli?.new;\n\n const basePath = dirname(pkgPath);\n const isUsingDefaultTemplates = !config?.templates;\n\n let templatePointerEntries = await Promise.all(\n (config?.templates ?? defaultTemplates).map(async rawPointer => {\n try {\n const templatePath = resolveLocalTemplatePath(rawPointer, basePath);\n\n const pointer = await peekLocalTemplateDefinition(templatePath);\n return { pointer, rawPointer };\n } catch (error) {\n throw new ForwardedError(\n `Failed to load template definition '${rawPointer}'`,\n error,\n );\n }\n }),\n );\n\n // Auto-filter frontend templates based on detected frontend system.\n // This must happen before the conflict check since both the new and legacy\n // frontend plugin templates have the same name, but only one will be shown.\n if (isUsingDefaultTemplates) {\n const frontendSystem = await detectFrontendSystem(basePath);\n templatePointerEntries = filterTemplateEntriesForFrontendSystem(\n templatePointerEntries,\n frontendSystem,\n );\n }\n\n const templateNameConflicts = new Map<string, string>();\n for (const { pointer, rawPointer } of templatePointerEntries) {\n const conflict = templateNameConflicts.get(pointer.name);\n if (conflict) {\n throw new Error(\n `Invalid template configuration, received conflicting template name '${pointer.name}' from '${conflict}' and '${rawPointer}'`,\n );\n }\n templateNameConflicts.set(pointer.name, rawPointer);\n }\n\n const packageNamePrefix =\n overrides.packageNamePrefix ??\n config?.globals?.namePrefix ??\n defaults.packageNamePrefix;\n\n const { packageNamePluginInfix } = computePackageNamePluginInfix(\n packageNamePrefix,\n overrides.packageNamePluginInfix ?? config?.globals?.namePluginInfix,\n );\n\n return {\n isUsingDefaultTemplates,\n templatePointers: templatePointerEntries.map(({ pointer }) => pointer),\n license: overrides.license ?? config?.globals?.license ?? defaults.license,\n version: overrides.version ?? config?.globals?.version ?? defaults.version,\n private: overrides.private ?? config?.globals?.private ?? defaults.private,\n publishRegistry:\n overrides.publishRegistry ??\n config?.globals?.publishRegistry ??\n defaults.publishRegistry,\n packageNamePrefix,\n packageNamePluginInfix,\n };\n}\n\nconst CLI_TEMPLATE_PREFIX = '@backstage/cli/templates/';\nconst CLI_MODULE_NEW_TEMPLATE_PREFIX = '@backstage/cli-module-new/templates/';\n\nfunction resolveLocalTemplatePath(pointer: string, basePath: string): string {\n if (isAbsolute(pointer)) {\n throw new Error(`Template target may not be an absolute path`);\n }\n\n if (pointer.startsWith('.')) {\n return resolvePath(basePath, pointer, TEMPLATE_FILE_NAME);\n }\n\n // Rewrite legacy @backstage/cli/templates/* paths to @backstage/cli-module-new/templates/*\n const resolvedPointer = pointer.startsWith(CLI_TEMPLATE_PREFIX)\n ? `${CLI_MODULE_NEW_TEMPLATE_PREFIX}${pointer.slice(\n CLI_TEMPLATE_PREFIX.length,\n )}`\n : pointer;\n\n return require.resolve(`${resolvedPointer}/${TEMPLATE_FILE_NAME}`, {\n paths: [basePath],\n });\n}\n\nconst partialTemplateDefinitionSchema = z.object({\n name: z.string(),\n description: z.string().optional(),\n});\n\nasync function peekLocalTemplateDefinition(\n target: string,\n): Promise<PortableTemplatePointer> {\n const content = await fs.readFile(target, 'utf8');\n\n const rawTemplate = parseYaml(content);\n const parsed = partialTemplateDefinitionSchema.safeParse(rawTemplate);\n if (!parsed.success) {\n throw fromZodError(parsed.error);\n }\n\n return {\n name: parsed.data.name,\n description: parsed.data.description,\n target,\n };\n}\n"],"names":["join","fs","z","targetPaths","ForwardedError","fromZodError","dirname","defaultTemplates","isAbsolute","resolvePath","TEMPLATE_FILE_NAME","parseYaml"],"mappings":"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"}
@@ -17,6 +17,8 @@ function getBaseNameForRole(roleParams) {
17
17
  case "node-library":
18
18
  case "common-library":
19
19
  return roleParams.name;
20
+ case "cli-module":
21
+ return `cli-module-${roleParams.name}`;
20
22
  case "plugin-web-library":
21
23
  return `${roleParams.pluginId}-react`;
22
24
  case "plugin-node-library":
@@ -1 +1 @@
1
- {"version":3,"file":"resolvePackageParams.cjs.js","sources":["../../../src/lib/preparation/resolvePackageParams.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 { join as joinPath } from 'node:path';\nimport { PortableTemplateInputRoleParams } from '../types';\n\nexport type ResolvePackageParamsOptions = {\n roleParams: PortableTemplateInputRoleParams;\n pluginInfix: string;\n packagePrefix: string;\n};\n\nexport type PortableTemplatePackageInfo = {\n packageName: string;\n packagePath: string;\n};\n\nexport function resolvePackageParams(\n options: ResolvePackageParamsOptions,\n): PortableTemplatePackageInfo {\n const baseName = getBaseNameForRole(options.roleParams);\n const isPlugin = options.roleParams.role.includes('plugin');\n const pluginInfix = isPlugin ? options.pluginInfix : '';\n return {\n packageName: `${options.packagePrefix}${pluginInfix}${baseName}`,\n packagePath: joinPath(isPlugin ? 'plugins' : 'packages', baseName),\n };\n}\n\nfunction getBaseNameForRole(\n roleParams: PortableTemplateInputRoleParams,\n): string {\n switch (roleParams.role) {\n case 'web-library':\n case 'node-library':\n case 'common-library':\n return roleParams.name;\n case 'plugin-web-library':\n return `${roleParams.pluginId}-react`;\n case 'plugin-node-library':\n return `${roleParams.pluginId}-node`;\n case 'plugin-common-library':\n return `${roleParams.pluginId}-common`;\n case 'frontend-plugin':\n return `${roleParams.pluginId}`;\n case 'frontend-plugin-module':\n return `${roleParams.pluginId}-module-${roleParams.moduleId}`;\n case 'backend-plugin':\n return `${roleParams.pluginId}-backend`;\n case 'backend-plugin-module':\n return `${roleParams.pluginId}-backend-module-${roleParams.moduleId}`;\n default:\n throw new Error(`Unknown role ${(roleParams as { role: string }).role}`);\n }\n}\n"],"names":["joinPath"],"mappings":";;;;AA8BO,SAAS,qBACd,OAAA,EAC6B;AAC7B,EAAA,MAAM,QAAA,GAAW,kBAAA,CAAmB,OAAA,CAAQ,UAAU,CAAA;AACtD,EAAA,MAAM,QAAA,GAAW,OAAA,CAAQ,UAAA,CAAW,IAAA,CAAK,SAAS,QAAQ,CAAA;AAC1D,EAAA,MAAM,WAAA,GAAc,QAAA,GAAW,OAAA,CAAQ,WAAA,GAAc,EAAA;AACrD,EAAA,OAAO;AAAA,IACL,aAAa,CAAA,EAAG,OAAA,CAAQ,aAAa,CAAA,EAAG,WAAW,GAAG,QAAQ,CAAA,CAAA;AAAA,IAC9D,WAAA,EAAaA,SAAA,CAAS,QAAA,GAAW,SAAA,GAAY,YAAY,QAAQ;AAAA,GACnE;AACF;AAEA,SAAS,mBACP,UAAA,EACQ;AACR,EAAA,QAAQ,WAAW,IAAA;AAAM,IACvB,KAAK,aAAA;AAAA,IACL,KAAK,cAAA;AAAA,IACL,KAAK,gBAAA;AACH,MAAA,OAAO,UAAA,CAAW,IAAA;AAAA,IACpB,KAAK,oBAAA;AACH,MAAA,OAAO,CAAA,EAAG,WAAW,QAAQ,CAAA,MAAA,CAAA;AAAA,IAC/B,KAAK,qBAAA;AACH,MAAA,OAAO,CAAA,EAAG,WAAW,QAAQ,CAAA,KAAA,CAAA;AAAA,IAC/B,KAAK,uBAAA;AACH,MAAA,OAAO,CAAA,EAAG,WAAW,QAAQ,CAAA,OAAA,CAAA;AAAA,IAC/B,KAAK,iBAAA;AACH,MAAA,OAAO,CAAA,EAAG,WAAW,QAAQ,CAAA,CAAA;AAAA,IAC/B,KAAK,wBAAA;AACH,MAAA,OAAO,CAAA,EAAG,UAAA,CAAW,QAAQ,CAAA,QAAA,EAAW,WAAW,QAAQ,CAAA,CAAA;AAAA,IAC7D,KAAK,gBAAA;AACH,MAAA,OAAO,CAAA,EAAG,WAAW,QAAQ,CAAA,QAAA,CAAA;AAAA,IAC/B,KAAK,uBAAA;AACH,MAAA,OAAO,CAAA,EAAG,UAAA,CAAW,QAAQ,CAAA,gBAAA,EAAmB,WAAW,QAAQ,CAAA,CAAA;AAAA,IACrE;AACE,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,aAAA,EAAiB,UAAA,CAAgC,IAAI,CAAA,CAAE,CAAA;AAAA;AAE7E;;;;"}
1
+ {"version":3,"file":"resolvePackageParams.cjs.js","sources":["../../../src/lib/preparation/resolvePackageParams.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 { join as joinPath } from 'node:path';\nimport { PortableTemplateInputRoleParams } from '../types';\n\nexport type ResolvePackageParamsOptions = {\n roleParams: PortableTemplateInputRoleParams;\n pluginInfix: string;\n packagePrefix: string;\n};\n\nexport type PortableTemplatePackageInfo = {\n packageName: string;\n packagePath: string;\n};\n\nexport function resolvePackageParams(\n options: ResolvePackageParamsOptions,\n): PortableTemplatePackageInfo {\n const baseName = getBaseNameForRole(options.roleParams);\n const isPlugin = options.roleParams.role.includes('plugin');\n const pluginInfix = isPlugin ? options.pluginInfix : '';\n return {\n packageName: `${options.packagePrefix}${pluginInfix}${baseName}`,\n packagePath: joinPath(isPlugin ? 'plugins' : 'packages', baseName),\n };\n}\n\nfunction getBaseNameForRole(\n roleParams: PortableTemplateInputRoleParams,\n): string {\n switch (roleParams.role) {\n case 'web-library':\n case 'node-library':\n case 'common-library':\n return roleParams.name;\n case 'cli-module':\n return `cli-module-${roleParams.name}`;\n case 'plugin-web-library':\n return `${roleParams.pluginId}-react`;\n case 'plugin-node-library':\n return `${roleParams.pluginId}-node`;\n case 'plugin-common-library':\n return `${roleParams.pluginId}-common`;\n case 'frontend-plugin':\n return `${roleParams.pluginId}`;\n case 'frontend-plugin-module':\n return `${roleParams.pluginId}-module-${roleParams.moduleId}`;\n case 'backend-plugin':\n return `${roleParams.pluginId}-backend`;\n case 'backend-plugin-module':\n return `${roleParams.pluginId}-backend-module-${roleParams.moduleId}`;\n default:\n throw new Error(`Unknown role ${(roleParams as { role: string }).role}`);\n }\n}\n"],"names":["joinPath"],"mappings":";;;;AA8BO,SAAS,qBACd,OAAA,EAC6B;AAC7B,EAAA,MAAM,QAAA,GAAW,kBAAA,CAAmB,OAAA,CAAQ,UAAU,CAAA;AACtD,EAAA,MAAM,QAAA,GAAW,OAAA,CAAQ,UAAA,CAAW,IAAA,CAAK,SAAS,QAAQ,CAAA;AAC1D,EAAA,MAAM,WAAA,GAAc,QAAA,GAAW,OAAA,CAAQ,WAAA,GAAc,EAAA;AACrD,EAAA,OAAO;AAAA,IACL,aAAa,CAAA,EAAG,OAAA,CAAQ,aAAa,CAAA,EAAG,WAAW,GAAG,QAAQ,CAAA,CAAA;AAAA,IAC9D,WAAA,EAAaA,SAAA,CAAS,QAAA,GAAW,SAAA,GAAY,YAAY,QAAQ;AAAA,GACnE;AACF;AAEA,SAAS,mBACP,UAAA,EACQ;AACR,EAAA,QAAQ,WAAW,IAAA;AAAM,IACvB,KAAK,aAAA;AAAA,IACL,KAAK,cAAA;AAAA,IACL,KAAK,gBAAA;AACH,MAAA,OAAO,UAAA,CAAW,IAAA;AAAA,IACpB,KAAK,YAAA;AACH,MAAA,OAAO,CAAA,WAAA,EAAc,WAAW,IAAI,CAAA,CAAA;AAAA,IACtC,KAAK,oBAAA;AACH,MAAA,OAAO,CAAA,EAAG,WAAW,QAAQ,CAAA,MAAA,CAAA;AAAA,IAC/B,KAAK,qBAAA;AACH,MAAA,OAAO,CAAA,EAAG,WAAW,QAAQ,CAAA,KAAA,CAAA;AAAA,IAC/B,KAAK,uBAAA;AACH,MAAA,OAAO,CAAA,EAAG,WAAW,QAAQ,CAAA,OAAA,CAAA;AAAA,IAC/B,KAAK,iBAAA;AACH,MAAA,OAAO,CAAA,EAAG,WAAW,QAAQ,CAAA,CAAA;AAAA,IAC/B,KAAK,wBAAA;AACH,MAAA,OAAO,CAAA,EAAG,UAAA,CAAW,QAAQ,CAAA,QAAA,EAAW,WAAW,QAAQ,CAAA,CAAA;AAAA,IAC7D,KAAK,gBAAA;AACH,MAAA,OAAO,CAAA,EAAG,WAAW,QAAQ,CAAA,QAAA,CAAA;AAAA,IAC/B,KAAK,uBAAA;AACH,MAAA,OAAO,CAAA,EAAG,UAAA,CAAW,QAAQ,CAAA,gBAAA,EAAmB,WAAW,QAAQ,CAAA,CAAA;AAAA,IACrE;AACE,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,aAAA,EAAiB,UAAA,CAAgC,IAAI,CAAA,CAAE,CAAA;AAAA;AAE7E;;;;"}
@@ -5,6 +5,7 @@ const TEMPLATE_ROLES = [
5
5
  "web-library",
6
6
  "node-library",
7
7
  "common-library",
8
+ "cli-module",
8
9
  "plugin-web-library",
9
10
  "plugin-node-library",
10
11
  "plugin-common-library",
@@ -1 +1 @@
1
- {"version":3,"file":"types.cjs.js","sources":["../../src/lib/types.ts"],"sourcesContent":["/*\n * Copyright 2021 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\nexport type PortableTemplateConfig = {\n /**\n * The pointers to templates that can be used.\n */\n templatePointers: PortableTemplatePointer[];\n\n /**\n * Whether the default set of templates are being used or not.\n */\n isUsingDefaultTemplates: boolean;\n\n license: string;\n\n version: string;\n\n private: boolean;\n\n publishRegistry?: string;\n\n packageNamePrefix: string;\n\n packageNamePluginInfix: string;\n};\n\nexport const TEMPLATE_FILE_NAME = 'portable-template.yaml';\n\nexport type PortableTemplatePointer = {\n name: string;\n description?: string;\n target: string;\n};\n\nexport const TEMPLATE_ROLES = [\n 'web-library',\n 'node-library',\n 'common-library',\n 'plugin-web-library',\n 'plugin-node-library',\n 'plugin-common-library',\n 'frontend-plugin',\n 'frontend-plugin-module',\n 'backend-plugin',\n 'backend-plugin-module',\n] as const;\n\nexport type PortableTemplateRole = (typeof TEMPLATE_ROLES)[number];\n\nexport type PortableTemplateFile = {\n path: string;\n content: string;\n syntax?: 'handlebars';\n};\n\nexport type PortableTemplate = {\n name: string;\n role: PortableTemplateRole;\n files: PortableTemplateFile[];\n values: Record<string, string>;\n};\n\nexport type PortableTemplateParams = {\n [KName in string]?: string | number | boolean;\n};\n\nexport type PortableTemplateInputRoleParams =\n | {\n role: 'web-library' | 'node-library' | 'common-library';\n name: string;\n }\n | {\n role:\n | 'plugin-web-library'\n | 'plugin-node-library'\n | 'plugin-common-library'\n | 'frontend-plugin'\n | 'backend-plugin';\n pluginId: string;\n }\n | {\n role: 'frontend-plugin-module' | 'backend-plugin-module';\n pluginId: string;\n moduleId: string;\n };\n\nexport type PortableTemplateInput = {\n roleParams: PortableTemplateInputRoleParams;\n\n owner?: string;\n\n license: string;\n\n version: string;\n\n private: boolean;\n\n publishRegistry?: string;\n\n packageName: string;\n\n packagePath: string;\n};\n"],"names":[],"mappings":";;AAwCO,MAAM,kBAAA,GAAqB;AAQ3B,MAAM,cAAA,GAAiB;AAAA,EAC5B,aAAA;AAAA,EACA,cAAA;AAAA,EACA,gBAAA;AAAA,EACA,oBAAA;AAAA,EACA,qBAAA;AAAA,EACA,uBAAA;AAAA,EACA,iBAAA;AAAA,EACA,wBAAA;AAAA,EACA,gBAAA;AAAA,EACA;AACF;;;;;"}
1
+ {"version":3,"file":"types.cjs.js","sources":["../../src/lib/types.ts"],"sourcesContent":["/*\n * Copyright 2021 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\nexport type PortableTemplateConfig = {\n /**\n * The pointers to templates that can be used.\n */\n templatePointers: PortableTemplatePointer[];\n\n /**\n * Whether the default set of templates are being used or not.\n */\n isUsingDefaultTemplates: boolean;\n\n license: string;\n\n version: string;\n\n private: boolean;\n\n publishRegistry?: string;\n\n packageNamePrefix: string;\n\n packageNamePluginInfix: string;\n};\n\nexport const TEMPLATE_FILE_NAME = 'portable-template.yaml';\n\nexport type PortableTemplatePointer = {\n name: string;\n description?: string;\n target: string;\n};\n\nexport const TEMPLATE_ROLES = [\n 'web-library',\n 'node-library',\n 'common-library',\n 'cli-module',\n 'plugin-web-library',\n 'plugin-node-library',\n 'plugin-common-library',\n 'frontend-plugin',\n 'frontend-plugin-module',\n 'backend-plugin',\n 'backend-plugin-module',\n] as const;\n\nexport type PortableTemplateRole = (typeof TEMPLATE_ROLES)[number];\n\nexport type PortableTemplateFile = {\n path: string;\n content: string;\n syntax?: 'handlebars';\n};\n\nexport type PortableTemplate = {\n name: string;\n role: PortableTemplateRole;\n files: PortableTemplateFile[];\n values: Record<string, string>;\n};\n\nexport type PortableTemplateParams = {\n [KName in string]?: string | number | boolean;\n};\n\nexport type PortableTemplateInputRoleParams =\n | {\n role: 'web-library' | 'node-library' | 'common-library' | 'cli-module';\n name: string;\n }\n | {\n role:\n | 'plugin-web-library'\n | 'plugin-node-library'\n | 'plugin-common-library'\n | 'frontend-plugin'\n | 'backend-plugin';\n pluginId: string;\n }\n | {\n role: 'frontend-plugin-module';\n pluginId: string;\n moduleId: string;\n pluginPackage: string;\n }\n | {\n role: 'backend-plugin-module';\n pluginId: string;\n moduleId: string;\n pluginPackage: string;\n };\n\nexport type PortableTemplateInput = {\n roleParams: PortableTemplateInputRoleParams;\n\n owner?: string;\n\n license: string;\n\n version: string;\n\n private: boolean;\n\n publishRegistry?: string;\n\n packageName: string;\n\n packagePath: string;\n};\n"],"names":[],"mappings":";;AAwCO,MAAM,kBAAA,GAAqB;AAQ3B,MAAM,cAAA,GAAiB;AAAA,EAC5B,aAAA;AAAA,EACA,cAAA;AAAA,EACA,gBAAA;AAAA,EACA,YAAA;AAAA,EACA,oBAAA;AAAA,EACA,qBAAA;AAAA,EACA,uBAAA;AAAA,EACA,iBAAA;AAAA,EACA,wBAAA;AAAA,EACA,gBAAA;AAAA,EACA;AACF;;;;;"}
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var version = "0.0.0-nightly-20260317031259";
3
+ var version = "0.16.0";
4
4
 
5
5
  exports.version = version;
6
6
  //# sourceMappingURL=package.json.cjs.js.map
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var version = "0.0.0-nightly-20260317031259";
3
+ var version = "1.8.0";
4
4
 
5
5
  exports.version = version;
6
6
  //# sourceMappingURL=package.json.cjs.js.map
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var version = "0.0.0-nightly-20260317031259";
3
+ var version = "1.11.1";
4
4
 
5
5
  exports.version = version;
6
6
  //# sourceMappingURL=package.json.cjs.js.map