@decohere/scaffold 0.0.1-dev.18 → 0.0.1-dev.81

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 (240) hide show
  1. package/commonjs/src/add-api.action.js +39 -0
  2. package/commonjs/src/add-api.command.js +41 -0
  3. package/commonjs/src/add.command.js +24 -0
  4. package/commonjs/src/add.module.js +26 -0
  5. package/commonjs/src/cli.js +9 -0
  6. package/commonjs/src/create.command.js +24 -0
  7. package/commonjs/src/create.module.js +26 -0
  8. package/commonjs/src/domain/prompt.js +64 -0
  9. package/commonjs/src/index.js +38 -0
  10. package/commonjs/src/models/compose.model.js +150 -0
  11. package/commonjs/src/models/config-yaml.model.js +88 -0
  12. package/commonjs/src/models/const.js +32 -0
  13. package/commonjs/src/models/dev-container.model.js +116 -0
  14. package/commonjs/src/models/docker-image.model.js +259 -0
  15. package/commonjs/src/models/env-file.model.js +50 -0
  16. package/commonjs/src/models/gitignore.model.js +43 -0
  17. package/commonjs/src/models/launch-json.model.js +74 -0
  18. package/commonjs/src/models/package-json.model.js +149 -0
  19. package/commonjs/src/models/project.model.js +134 -0
  20. package/commonjs/src/models/source-file.js +6 -0
  21. package/commonjs/src/models/tsconfig.model.js +34 -0
  22. package/commonjs/src/models/vitest-config.model.js +35 -0
  23. package/commonjs/src/models/vscode-settings.model.js +31 -0
  24. package/commonjs/src/program.js +57 -0
  25. package/commonjs/src/resolve-target-dir.js +19 -0
  26. package/commonjs/src/services/scaffold.service.js +62 -0
  27. package/commonjs/src/version.js +57 -0
  28. package/commonjs/src/webapi/api-name.js +95 -0
  29. package/commonjs/src/webapi/cli-options.js +101 -0
  30. package/commonjs/src/webapi/const.js +50 -0
  31. package/commonjs/src/webapi/create-api.js +237 -0
  32. package/commonjs/src/webapi/devcontainer/codebase-rag-mcp.js +166 -0
  33. package/commonjs/src/webapi/devcontainer/codebase-rag-mcp.ts +182 -0
  34. package/commonjs/src/webapi/devcontainer/host-scripts.js +52 -0
  35. package/commonjs/src/webapi/devcontainer/templates/codebase-rag.env.example +3 -0
  36. package/commonjs/src/webapi/devcontainer/templates/initialize.sh +169 -0
  37. package/commonjs/src/webapi/devcontainer/templates/post-create.sh +35 -0
  38. package/commonjs/src/webapi/devcontainer/templates/post-start.sh +65 -0
  39. package/commonjs/src/webapi/devcontainer/templates/tty-prompt.sh +38 -0
  40. package/commonjs/src/webapi/features/auth.feature.js +441 -0
  41. package/commonjs/src/webapi/features/auth0-cli.js +435 -0
  42. package/commonjs/src/webapi/features/biome-format.js +49 -0
  43. package/commonjs/src/webapi/features/database.feature.js +433 -0
  44. package/commonjs/src/webapi/features/finalize.feature.js +95 -0
  45. package/commonjs/src/webapi/features/postman.feature.js +324 -0
  46. package/commonjs/src/webapi/models/api-package-json.model.js +60 -0
  47. package/commonjs/src/webapi/models/auth-config.model.js +26 -0
  48. package/commonjs/src/webapi/models/controller-source-file.model.js +193 -0
  49. package/commonjs/src/webapi/models/github-ci.model.js +193 -0
  50. package/commonjs/src/webapi/models/main-source-file.model.js +167 -0
  51. package/commonjs/src/webapi/models/production-dockerfile.model.js +157 -0
  52. package/commonjs/src/webapi/models/sample-files.model.js +60 -0
  53. package/commonjs/src/webapi/models/webapi-image.model.js +27 -0
  54. package/commonjs/src/webapi/postman/hello-openapi.js +175 -0
  55. package/commonjs/src/webapi/postman/local-view.js +184 -0
  56. package/commonjs/src/webapi/postman/openapi-to-postman.js +202 -0
  57. package/commonjs/src/webapi/workspace-readme.js +110 -0
  58. package/commonjs/src/webapi.action.js +30 -0
  59. package/commonjs/src/webapi.command.js +45 -0
  60. package/es6/src/add-api.action.js +29 -0
  61. package/es6/src/add-api.command.js +31 -0
  62. package/es6/src/add.command.js +14 -0
  63. package/es6/src/add.module.js +16 -0
  64. package/es6/src/cli.js +5 -0
  65. package/es6/src/create.command.js +14 -0
  66. package/es6/src/create.module.js +16 -0
  67. package/es6/src/domain/prompt.js +43 -0
  68. package/es6/src/index.js +8 -0
  69. package/es6/src/models/compose.model.js +144 -0
  70. package/es6/src/models/config-yaml.model.js +76 -0
  71. package/es6/src/models/const.js +22 -0
  72. package/es6/src/models/dev-container.model.js +106 -0
  73. package/es6/src/models/docker-image.model.js +217 -0
  74. package/es6/src/models/env-file.model.js +46 -0
  75. package/es6/src/models/gitignore.model.js +33 -0
  76. package/es6/src/models/launch-json.model.js +64 -0
  77. package/es6/src/models/package-json.model.js +137 -0
  78. package/es6/src/models/project.model.js +119 -0
  79. package/es6/src/models/source-file.js +3 -0
  80. package/es6/src/models/tsconfig.model.js +24 -0
  81. package/es6/src/models/vitest-config.model.js +25 -0
  82. package/es6/src/models/vscode-settings.model.js +21 -0
  83. package/es6/src/program.js +39 -0
  84. package/es6/src/resolve-target-dir.js +9 -0
  85. package/es6/src/services/scaffold.service.js +52 -0
  86. package/es6/src/version.js +36 -0
  87. package/es6/src/webapi/api-name.js +59 -0
  88. package/es6/src/webapi/cli-options.js +36 -0
  89. package/es6/src/webapi/const.js +20 -0
  90. package/es6/src/webapi/create-api.js +217 -0
  91. package/es6/src/webapi/devcontainer/codebase-rag-mcp.js +156 -0
  92. package/es6/src/webapi/devcontainer/codebase-rag-mcp.ts +182 -0
  93. package/es6/src/webapi/devcontainer/host-scripts.js +31 -0
  94. package/es6/src/webapi/devcontainer/templates/codebase-rag.env.example +3 -0
  95. package/es6/src/webapi/devcontainer/templates/initialize.sh +169 -0
  96. package/es6/src/webapi/devcontainer/templates/post-create.sh +35 -0
  97. package/es6/src/webapi/devcontainer/templates/post-start.sh +65 -0
  98. package/es6/src/webapi/devcontainer/templates/tty-prompt.sh +38 -0
  99. package/es6/src/webapi/features/auth.feature.js +390 -0
  100. package/es6/src/webapi/features/auth0-cli.js +375 -0
  101. package/es6/src/webapi/features/biome-format.js +42 -0
  102. package/es6/src/webapi/features/database.feature.js +423 -0
  103. package/es6/src/webapi/features/finalize.feature.js +85 -0
  104. package/es6/src/webapi/features/postman.feature.js +258 -0
  105. package/es6/src/webapi/models/api-package-json.model.js +55 -0
  106. package/es6/src/webapi/models/auth-config.model.js +22 -0
  107. package/es6/src/webapi/models/controller-source-file.model.js +184 -0
  108. package/es6/src/webapi/models/github-ci.model.js +186 -0
  109. package/es6/src/webapi/models/main-source-file.model.js +163 -0
  110. package/es6/src/webapi/models/production-dockerfile.model.js +148 -0
  111. package/es6/src/webapi/models/sample-files.model.js +42 -0
  112. package/es6/src/webapi/models/webapi-image.model.js +20 -0
  113. package/es6/src/webapi/postman/hello-openapi.js +168 -0
  114. package/es6/src/webapi/postman/local-view.js +169 -0
  115. package/es6/src/webapi/postman/openapi-to-postman.js +179 -0
  116. package/es6/src/webapi/workspace-readme.js +89 -0
  117. package/es6/src/webapi.action.js +20 -0
  118. package/es6/src/webapi.command.js +35 -0
  119. package/package.json +8 -8
  120. package/types/src/add-api.action.d.ts +13 -0
  121. package/types/src/add-api.command.d.ts +7 -0
  122. package/types/src/add.command.d.ts +6 -0
  123. package/types/src/add.module.d.ts +14 -0
  124. package/types/src/cli.d.ts +2 -0
  125. package/types/src/create.command.d.ts +6 -0
  126. package/types/src/create.module.d.ts +14 -0
  127. package/types/src/domain/prompt.d.ts +4 -0
  128. package/types/src/models/compose.model.d.ts +64 -0
  129. package/types/src/models/config-yaml.model.d.ts +27 -0
  130. package/types/src/models/const.d.ts +20 -0
  131. package/types/src/models/dev-container.model.d.ts +37 -0
  132. package/types/src/models/docker-image.model.d.ts +84 -0
  133. package/types/src/models/env-file.model.d.ts +16 -0
  134. package/types/src/models/gitignore.model.d.ts +7 -0
  135. package/types/src/models/launch-json.model.d.ts +7 -0
  136. package/types/src/models/package-json.model.d.ts +35 -0
  137. package/types/src/models/project.model.d.ts +60 -0
  138. package/{src/models/source-file.ts → types/src/models/source-file.d.ts} +4 -6
  139. package/types/src/models/tsconfig.model.d.ts +5 -0
  140. package/types/src/models/vitest-config.model.d.ts +5 -0
  141. package/types/src/models/vscode-settings.model.d.ts +7 -0
  142. package/types/src/program.d.ts +3 -0
  143. package/{src/resolve-target-dir.ts → types/src/resolve-target-dir.d.ts} +1 -4
  144. package/types/src/services/scaffold.service.d.ts +22 -0
  145. package/types/src/version.d.ts +6 -0
  146. package/types/src/webapi/api-name.d.ts +14 -0
  147. package/types/src/webapi/cli-options.d.ts +6 -0
  148. package/{src/webapi/const.ts → types/src/webapi/const.d.ts} +7 -21
  149. package/types/src/webapi/create-api.d.ts +15 -0
  150. package/types/src/webapi/devcontainer/codebase-rag-mcp.d.ts +32 -0
  151. package/types/src/webapi/devcontainer/codebase-rag-mcp.ts +182 -0
  152. package/types/src/webapi/devcontainer/host-scripts.d.ts +7 -0
  153. package/types/src/webapi/devcontainer/templates/codebase-rag.env.example +3 -0
  154. package/types/src/webapi/devcontainer/templates/initialize.sh +169 -0
  155. package/types/src/webapi/devcontainer/templates/post-create.sh +35 -0
  156. package/types/src/webapi/devcontainer/templates/post-start.sh +65 -0
  157. package/types/src/webapi/devcontainer/templates/tty-prompt.sh +38 -0
  158. package/types/src/webapi/features/auth.feature.d.ts +10 -0
  159. package/types/src/webapi/features/auth0-cli.d.ts +80 -0
  160. package/types/src/webapi/features/biome-format.d.ts +5 -0
  161. package/types/src/webapi/features/database.feature.d.ts +7 -0
  162. package/types/src/webapi/features/finalize.feature.d.ts +2 -0
  163. package/types/src/webapi/features/postman.feature.d.ts +16 -0
  164. package/types/src/webapi/models/api-package-json.model.d.ts +18 -0
  165. package/types/src/webapi/models/auth-config.model.d.ts +26 -0
  166. package/types/src/webapi/models/controller-source-file.model.d.ts +46 -0
  167. package/types/src/webapi/models/github-ci.model.d.ts +9 -0
  168. package/types/src/webapi/models/main-source-file.model.d.ts +54 -0
  169. package/types/src/webapi/models/production-dockerfile.model.d.ts +23 -0
  170. package/types/src/webapi/models/sample-files.model.d.ts +7 -0
  171. package/types/src/webapi/models/webapi-image.model.d.ts +12 -0
  172. package/types/src/webapi/postman/hello-openapi.d.ts +19 -0
  173. package/types/src/webapi/postman/local-view.d.ts +17 -0
  174. package/types/src/webapi/postman/openapi-to-postman.d.ts +62 -0
  175. package/types/src/webapi/workspace-readme.d.ts +18 -0
  176. package/types/src/webapi.action.d.ts +14 -0
  177. package/types/src/webapi.command.d.ts +11 -0
  178. package/src/add-api.action.ts +0 -25
  179. package/src/add-api.command.ts +0 -31
  180. package/src/add.command.ts +0 -20
  181. package/src/add.module.ts +0 -11
  182. package/src/cli.ts +0 -4
  183. package/src/create.command.ts +0 -20
  184. package/src/create.module.ts +0 -11
  185. package/src/domain/prompt.ts +0 -50
  186. package/src/models/compose.model.ts +0 -205
  187. package/src/models/config-yaml.model.ts +0 -83
  188. package/src/models/const.ts +0 -20
  189. package/src/models/dev-container.model.ts +0 -136
  190. package/src/models/docker-image.model.ts +0 -343
  191. package/src/models/env-file.model.ts +0 -45
  192. package/src/models/gitignore.model.ts +0 -35
  193. package/src/models/launch-json.model.ts +0 -60
  194. package/src/models/package-json.model.ts +0 -169
  195. package/src/models/project.model.ts +0 -141
  196. package/src/models/tsconfig.model.ts +0 -29
  197. package/src/models/vitest-config.model.ts +0 -26
  198. package/src/models/vscode-settings.model.ts +0 -24
  199. package/src/program.ts +0 -63
  200. package/src/services/scaffold.service.ts +0 -89
  201. package/src/version.ts +0 -56
  202. package/src/webapi/api-name.ts +0 -73
  203. package/src/webapi/cli-options.ts +0 -56
  204. package/src/webapi/create-api.ts +0 -275
  205. package/src/webapi/devcontainer/host-scripts.ts +0 -35
  206. package/src/webapi/features/auth.feature.ts +0 -454
  207. package/src/webapi/features/auth0-cli.ts +0 -421
  208. package/src/webapi/features/biome-format.ts +0 -34
  209. package/src/webapi/features/database.feature.ts +0 -522
  210. package/src/webapi/features/finalize.feature.ts +0 -112
  211. package/src/webapi/features/postman.feature.ts +0 -287
  212. package/src/webapi/models/api-package-json.model.ts +0 -60
  213. package/src/webapi/models/auth-config.model.ts +0 -36
  214. package/src/webapi/models/controller-source-file.model.ts +0 -232
  215. package/src/webapi/models/github-ci.model.ts +0 -188
  216. package/src/webapi/models/main-source-file.model.ts +0 -208
  217. package/src/webapi/models/production-dockerfile.model.ts +0 -162
  218. package/src/webapi/models/sample-files.model.ts +0 -45
  219. package/src/webapi/models/webapi-image.model.ts +0 -21
  220. package/src/webapi/postman/hello-openapi.ts +0 -92
  221. package/src/webapi/postman/local-view.ts +0 -195
  222. package/src/webapi/postman/openapi-to-postman.ts +0 -208
  223. package/src/webapi/workspace-readme.ts +0 -192
  224. package/src/webapi.action.ts +0 -22
  225. package/src/webapi.command.ts +0 -41
  226. package/tests/auth-postman.wiring.spec.ts +0 -263
  227. package/tests/auth0-cli.spec.ts +0 -232
  228. package/tests/biome-format.spec.ts +0 -49
  229. package/tests/cli.integration.spec.ts +0 -658
  230. package/tests/compose.model.spec.ts +0 -51
  231. package/tests/container-image.model.spec.ts +0 -162
  232. package/tests/dev-container.model.spec.ts +0 -29
  233. package/tests/devcontainer-base-image.spec.ts +0 -32
  234. package/tests/hello-di-inject.scaffold.spec.ts +0 -18
  235. package/tests/hello-route.contract.spec.ts +0 -94
  236. package/tests/package-json.order.spec.ts +0 -59
  237. package/tests/postman-from-openapi.spec.ts +0 -197
  238. package/tests/seed-devcontainer-templates.ts +0 -40
  239. package/tests/webapi/devcontainer/codebase-rag-mcp.spec.ts +0 -96
  240. /package/{src/index.ts → types/src/index.d.ts} +0 -0
@@ -0,0 +1,137 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { CREATE_VERSION } from "../version.js";
3
+ import { DEFAULT_WEBAPI_NAME, webapiPackageName, webapiPort, webapiReleaseEntry } from "../webapi/const.js";
4
+ import { WELL_KNOWN_FILES } from "./const.js";
5
+ /**
6
+ * Builder for the root `package.json`.
7
+ *
8
+ * Starts with the core API dependencies. Features call `addDependency` /
9
+ * `addDevDependency` during their scaffold phase to inject their own deps
10
+ * before `files()` is called at render time.
11
+ */ export class PackageJson {
12
+ name;
13
+ key = WELL_KNOWN_FILES.PACKAGE_JSON;
14
+ _dependencies;
15
+ _devDependencies;
16
+ _scripts;
17
+ _version = "0.0.1";
18
+ _type = "module";
19
+ _rest = {};
20
+ constructor(name, options){
21
+ this.name = name;
22
+ const apiNames = options?.apiNames ?? [
23
+ DEFAULT_WEBAPI_NAME
24
+ ];
25
+ const first = apiNames[0] ?? DEFAULT_WEBAPI_NAME;
26
+ const startEntry = options?.startEntry ?? webapiReleaseEntry(first);
27
+ const workspaceName = options?.workspaceName ?? stripApiSuffix(name);
28
+ const namedOrMany = apiNames.length > 1 || first !== DEFAULT_WEBAPI_NAME;
29
+ this._scripts = {
30
+ build: "forge build --configuration release",
31
+ "build:watch": "forge build --watch",
32
+ start: `node ${startEntry}`,
33
+ dev: namedOrMany ? fluxDevScript(workspaceName, first, webapiPort(0)) : "flux serve",
34
+ "lint:check": "biome check .",
35
+ typecheck: "forge typecheck",
36
+ test: "vitest run --passWithNoTests"
37
+ };
38
+ for (const [index, apiName] of apiNames.entries()){
39
+ this._scripts[`start:${apiName}`] = `node ${webapiReleaseEntry(apiName)}`;
40
+ this._scripts[`dev:${apiName}`] = fluxDevScript(workspaceName, apiName, webapiPort(index));
41
+ }
42
+ this._dependencies = {
43
+ "@decohere/cortex": CREATE_VERSION,
44
+ "@decohere/crucible": CREATE_VERSION,
45
+ "@decohere/nexus": CREATE_VERSION,
46
+ "@decohere/protocol": CREATE_VERSION,
47
+ "@decohere/scribe": CREATE_VERSION,
48
+ "@decohere/scribe-pino": CREATE_VERSION,
49
+ "pino-pretty": "^13.0.0",
50
+ "pino-roll": "^4.0.0"
51
+ };
52
+ this._devDependencies = {
53
+ "@decohere/forge": CREATE_VERSION,
54
+ "@decohere/cli": CREATE_VERSION,
55
+ typescript: "^6.0.3",
56
+ "@biomejs/biome": "^2.0.0",
57
+ vitest: "^3.2.4"
58
+ };
59
+ }
60
+ /** Load an existing root package.json so `webapi add` can merge scripts/deps. */ static fromFile(filePath) {
61
+ const raw = JSON.parse(readFileSync(filePath, "utf8"));
62
+ const pkg = new PackageJson(typeof raw.name === "string" ? raw.name : "app", {
63
+ apiNames: []
64
+ });
65
+ pkg._version = typeof raw.version === "string" ? raw.version : "0.0.1";
66
+ pkg._type = typeof raw.type === "string" ? raw.type : "module";
67
+ pkg._scripts = {
68
+ ...asStringMap(raw.scripts)
69
+ };
70
+ pkg._dependencies = {
71
+ ...asStringMap(raw.dependencies)
72
+ };
73
+ pkg._devDependencies = {
74
+ ...asStringMap(raw.devDependencies)
75
+ };
76
+ const reserved = new Set([
77
+ "name",
78
+ "version",
79
+ "type",
80
+ "scripts",
81
+ "dependencies",
82
+ "devDependencies"
83
+ ]);
84
+ pkg._rest = Object.fromEntries(Object.entries(raw).filter(([key])=>!reserved.has(key)));
85
+ return pkg;
86
+ }
87
+ addDependency(name, version) {
88
+ this._dependencies[name] = version;
89
+ return this;
90
+ }
91
+ addDevDependency(name, version) {
92
+ this._devDependencies[name] = version;
93
+ return this;
94
+ }
95
+ addScript(name, command) {
96
+ this._scripts[name] = command;
97
+ return this;
98
+ }
99
+ hasScript(name) {
100
+ return typeof this._scripts[name] === "string";
101
+ }
102
+ files() {
103
+ return [
104
+ {
105
+ filePath: "package.json",
106
+ content: JSON.stringify({
107
+ name: this.name,
108
+ version: this._version,
109
+ type: this._type,
110
+ ...this._rest,
111
+ scripts: this._scripts,
112
+ dependencies: sortStringMap(this._dependencies),
113
+ devDependencies: sortStringMap(this._devDependencies)
114
+ }, null, 2)
115
+ }
116
+ ];
117
+ }
118
+ }
119
+ function stripApiSuffix(name) {
120
+ return name.endsWith(".api") ? name.slice(0, -".api".length) : name;
121
+ }
122
+ function asStringMap(value) {
123
+ if (value == null || typeof value !== "object") return {};
124
+ const result = {};
125
+ for (const [key, entry] of Object.entries(value)){
126
+ if (typeof entry === "string") result[key] = entry;
127
+ }
128
+ return result;
129
+ }
130
+ /** Stable A→Z key order for package.json dependency maps. */ export function sortStringMap(map) {
131
+ return Object.fromEntries(Object.entries(map).sort(([left], [right])=>left.localeCompare(right, "en")));
132
+ }
133
+ function fluxDevScript(workspaceName, apiName, port) {
134
+ return `PORT=${port} flux serve --project ${webapiPackageName(workspaceName, apiName)}`;
135
+ }
136
+
137
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL3J1bm5lci93b3JrL2RlY29oZXJlL2RlY29oZXJlL3Byb2plY3RzL3NjYWZmb2xkL3NyYy9tb2RlbHMvcGFja2FnZS1qc29uLm1vZGVsLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IHJlYWRGaWxlU3luYyB9IGZyb20gXCJub2RlOmZzXCI7XG5pbXBvcnQgeyBDUkVBVEVfVkVSU0lPTiB9IGZyb20gXCIuLi92ZXJzaW9uLmpzXCI7XG5pbXBvcnQge1xuXHRERUZBVUxUX1dFQkFQSV9OQU1FLFxuXHR3ZWJhcGlQYWNrYWdlTmFtZSxcblx0d2ViYXBpUG9ydCxcblx0d2ViYXBpUmVsZWFzZUVudHJ5LFxufSBmcm9tIFwiLi4vd2ViYXBpL2NvbnN0LmpzXCI7XG5pbXBvcnQgeyBXRUxMX0tOT1dOX0ZJTEVTIH0gZnJvbSBcIi4vY29uc3QuanNcIjtcbmltcG9ydCB0eXBlIHsgS2V5ZWRNb2RlbCwgU291cmNlRmlsZSB9IGZyb20gXCIuL3NvdXJjZS1maWxlLmpzXCI7XG5cbmV4cG9ydCB0eXBlIFBhY2thZ2VKc29uT3B0aW9ucyA9IHtcblx0c3RhcnRFbnRyeT86IHN0cmluZztcblx0LyoqIEFQSSBzbHVncyBpbiB0aGlzIHdvcmtzcGFjZS4gRHJpdmVzIGBzdGFydDo8bmFtZT5gIC8gYGRldjo8bmFtZT5gLiAqL1xuXHRhcGlOYW1lcz86IHJlYWRvbmx5IHN0cmluZ1tdO1xuXHQvKiogSG9zdCB3b3Jrc3BhY2UgbmFtZSB1c2VkIGluIGBAPHdvcmtzcGFjZT4vPGFwaT5gIGZvciBmbHV4IGAtLXByb2plY3RgLiAqL1xuXHR3b3Jrc3BhY2VOYW1lPzogc3RyaW5nO1xufTtcblxuLyoqXG4gKiBCdWlsZGVyIGZvciB0aGUgcm9vdCBgcGFja2FnZS5qc29uYC5cbiAqXG4gKiBTdGFydHMgd2l0aCB0aGUgY29yZSBBUEkgZGVwZW5kZW5jaWVzLiBGZWF0dXJlcyBjYWxsIGBhZGREZXBlbmRlbmN5YCAvXG4gKiBgYWRkRGV2RGVwZW5kZW5jeWAgZHVyaW5nIHRoZWlyIHNjYWZmb2xkIHBoYXNlIHRvIGluamVjdCB0aGVpciBvd24gZGVwc1xuICogYmVmb3JlIGBmaWxlcygpYCBpcyBjYWxsZWQgYXQgcmVuZGVyIHRpbWUuXG4gKi9cbmV4cG9ydCBjbGFzcyBQYWNrYWdlSnNvbiBpbXBsZW1lbnRzIEtleWVkTW9kZWwge1xuXHRwdWJsaWMgcmVhZG9ubHkga2V5ID0gV0VMTF9LTk9XTl9GSUxFUy5QQUNLQUdFX0pTT047XG5cblx0cHJpdmF0ZSBfZGVwZW5kZW5jaWVzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+O1xuXHRwcml2YXRlIF9kZXZEZXBlbmRlbmNpZXM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz47XG5cdHByaXZhdGUgX3NjcmlwdHM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz47XG5cdHByaXZhdGUgX3ZlcnNpb24gPSBcIjAuMC4xXCI7XG5cdHByaXZhdGUgX3R5cGUgPSBcIm1vZHVsZVwiO1xuXHRwcml2YXRlIF9yZXN0OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiA9IHt9O1xuXG5cdHB1YmxpYyBjb25zdHJ1Y3Rvcihcblx0XHRwcml2YXRlIHJlYWRvbmx5IG5hbWU6IHN0cmluZyxcblx0XHRvcHRpb25zPzogUGFja2FnZUpzb25PcHRpb25zLFxuXHQpIHtcblx0XHRjb25zdCBhcGlOYW1lcyA9IG9wdGlvbnM/LmFwaU5hbWVzID8/IFtERUZBVUxUX1dFQkFQSV9OQU1FXTtcblx0XHRjb25zdCBmaXJzdCA9IGFwaU5hbWVzWzBdID8/IERFRkFVTFRfV0VCQVBJX05BTUU7XG5cdFx0Y29uc3Qgc3RhcnRFbnRyeSA9IG9wdGlvbnM/LnN0YXJ0RW50cnkgPz8gd2ViYXBpUmVsZWFzZUVudHJ5KGZpcnN0KTtcblx0XHRjb25zdCB3b3Jrc3BhY2VOYW1lID0gb3B0aW9ucz8ud29ya3NwYWNlTmFtZSA/PyBzdHJpcEFwaVN1ZmZpeChuYW1lKTtcblx0XHRjb25zdCBuYW1lZE9yTWFueSA9IGFwaU5hbWVzLmxlbmd0aCA+IDEgfHwgZmlyc3QgIT09IERFRkFVTFRfV0VCQVBJX05BTUU7XG5cblx0XHR0aGlzLl9zY3JpcHRzID0ge1xuXHRcdFx0YnVpbGQ6IFwiZm9yZ2UgYnVpbGQgLS1jb25maWd1cmF0aW9uIHJlbGVhc2VcIixcblx0XHRcdFwiYnVpbGQ6d2F0Y2hcIjogXCJmb3JnZSBidWlsZCAtLXdhdGNoXCIsXG5cdFx0XHRzdGFydDogYG5vZGUgJHtzdGFydEVudHJ5fWAsXG5cdFx0XHRkZXY6IG5hbWVkT3JNYW55ID8gZmx1eERldlNjcmlwdCh3b3Jrc3BhY2VOYW1lLCBmaXJzdCwgd2ViYXBpUG9ydCgwKSkgOiBcImZsdXggc2VydmVcIixcblx0XHRcdFwibGludDpjaGVja1wiOiBcImJpb21lIGNoZWNrIC5cIixcblx0XHRcdHR5cGVjaGVjazogXCJmb3JnZSB0eXBlY2hlY2tcIixcblx0XHRcdHRlc3Q6IFwidml0ZXN0IHJ1biAtLXBhc3NXaXRoTm9UZXN0c1wiLFxuXHRcdH07XG5cdFx0Zm9yIChjb25zdCBbaW5kZXgsIGFwaU5hbWVdIG9mIGFwaU5hbWVzLmVudHJpZXMoKSkge1xuXHRcdFx0dGhpcy5fc2NyaXB0c1tgc3RhcnQ6JHthcGlOYW1lfWBdID0gYG5vZGUgJHt3ZWJhcGlSZWxlYXNlRW50cnkoYXBpTmFtZSl9YDtcblx0XHRcdHRoaXMuX3NjcmlwdHNbYGRldjoke2FwaU5hbWV9YF0gPSBmbHV4RGV2U2NyaXB0KFxuXHRcdFx0XHR3b3Jrc3BhY2VOYW1lLFxuXHRcdFx0XHRhcGlOYW1lLFxuXHRcdFx0XHR3ZWJhcGlQb3J0KGluZGV4KSxcblx0XHRcdCk7XG5cdFx0fVxuXHRcdHRoaXMuX2RlcGVuZGVuY2llcyA9IHtcblx0XHRcdFwiQGRlY29oZXJlL2NvcnRleFwiOiBDUkVBVEVfVkVSU0lPTixcblx0XHRcdFwiQGRlY29oZXJlL2NydWNpYmxlXCI6IENSRUFURV9WRVJTSU9OLFxuXHRcdFx0XCJAZGVjb2hlcmUvbmV4dXNcIjogQ1JFQVRFX1ZFUlNJT04sXG5cdFx0XHRcIkBkZWNvaGVyZS9wcm90b2NvbFwiOiBDUkVBVEVfVkVSU0lPTixcblx0XHRcdFwiQGRlY29oZXJlL3NjcmliZVwiOiBDUkVBVEVfVkVSU0lPTixcblx0XHRcdFwiQGRlY29oZXJlL3NjcmliZS1waW5vXCI6IENSRUFURV9WRVJTSU9OLFxuXHRcdFx0XCJwaW5vLXByZXR0eVwiOiBcIl4xMy4wLjBcIixcblx0XHRcdFwicGluby1yb2xsXCI6IFwiXjQuMC4wXCIsXG5cdFx0fTtcblx0XHR0aGlzLl9kZXZEZXBlbmRlbmNpZXMgPSB7XG5cdFx0XHRcIkBkZWNvaGVyZS9mb3JnZVwiOiBDUkVBVEVfVkVSU0lPTixcblx0XHRcdFwiQGRlY29oZXJlL2NsaVwiOiBDUkVBVEVfVkVSU0lPTixcblx0XHRcdHR5cGVzY3JpcHQ6IFwiXjYuMC4zXCIsXG5cdFx0XHRcIkBiaW9tZWpzL2Jpb21lXCI6IFwiXjIuMC4wXCIsXG5cdFx0XHR2aXRlc3Q6IFwiXjMuMi40XCIsXG5cdFx0fTtcblx0fVxuXG5cdC8qKiBMb2FkIGFuIGV4aXN0aW5nIHJvb3QgcGFja2FnZS5qc29uIHNvIGB3ZWJhcGkgYWRkYCBjYW4gbWVyZ2Ugc2NyaXB0cy9kZXBzLiAqL1xuXHRwdWJsaWMgc3RhdGljIGZyb21GaWxlKGZpbGVQYXRoOiBzdHJpbmcpOiBQYWNrYWdlSnNvbiB7XG5cdFx0Y29uc3QgcmF3ID0gSlNPTi5wYXJzZShyZWFkRmlsZVN5bmMoZmlsZVBhdGgsIFwidXRmOFwiKSkgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG5cdFx0Y29uc3QgcGtnID0gbmV3IFBhY2thZ2VKc29uKHR5cGVvZiByYXcubmFtZSA9PT0gXCJzdHJpbmdcIiA/IHJhdy5uYW1lIDogXCJhcHBcIiwge1xuXHRcdFx0YXBpTmFtZXM6IFtdLFxuXHRcdH0pO1xuXHRcdHBrZy5fdmVyc2lvbiA9IHR5cGVvZiByYXcudmVyc2lvbiA9PT0gXCJzdHJpbmdcIiA/IHJhdy52ZXJzaW9uIDogXCIwLjAuMVwiO1xuXHRcdHBrZy5fdHlwZSA9IHR5cGVvZiByYXcudHlwZSA9PT0gXCJzdHJpbmdcIiA/IHJhdy50eXBlIDogXCJtb2R1bGVcIjtcblx0XHRwa2cuX3NjcmlwdHMgPSB7IC4uLmFzU3RyaW5nTWFwKHJhdy5zY3JpcHRzKSB9O1xuXHRcdHBrZy5fZGVwZW5kZW5jaWVzID0geyAuLi5hc1N0cmluZ01hcChyYXcuZGVwZW5kZW5jaWVzKSB9O1xuXHRcdHBrZy5fZGV2RGVwZW5kZW5jaWVzID0geyAuLi5hc1N0cmluZ01hcChyYXcuZGV2RGVwZW5kZW5jaWVzKSB9O1xuXHRcdGNvbnN0IHJlc2VydmVkID0gbmV3IFNldChbXG5cdFx0XHRcIm5hbWVcIixcblx0XHRcdFwidmVyc2lvblwiLFxuXHRcdFx0XCJ0eXBlXCIsXG5cdFx0XHRcInNjcmlwdHNcIixcblx0XHRcdFwiZGVwZW5kZW5jaWVzXCIsXG5cdFx0XHRcImRldkRlcGVuZGVuY2llc1wiLFxuXHRcdF0pO1xuXHRcdHBrZy5fcmVzdCA9IE9iamVjdC5mcm9tRW50cmllcyhPYmplY3QuZW50cmllcyhyYXcpLmZpbHRlcigoW2tleV0pID0+ICFyZXNlcnZlZC5oYXMoa2V5KSkpO1xuXHRcdHJldHVybiBwa2c7XG5cdH1cblxuXHRwdWJsaWMgYWRkRGVwZW5kZW5jeShuYW1lOiBzdHJpbmcsIHZlcnNpb246IHN0cmluZyk6IHRoaXMge1xuXHRcdHRoaXMuX2RlcGVuZGVuY2llc1tuYW1lXSA9IHZlcnNpb247XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxuXHRwdWJsaWMgYWRkRGV2RGVwZW5kZW5jeShuYW1lOiBzdHJpbmcsIHZlcnNpb246IHN0cmluZyk6IHRoaXMge1xuXHRcdHRoaXMuX2RldkRlcGVuZGVuY2llc1tuYW1lXSA9IHZlcnNpb247XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxuXHRwdWJsaWMgYWRkU2NyaXB0KG5hbWU6IHN0cmluZywgY29tbWFuZDogc3RyaW5nKTogdGhpcyB7XG5cdFx0dGhpcy5fc2NyaXB0c1tuYW1lXSA9IGNvbW1hbmQ7XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxuXHRwdWJsaWMgaGFzU2NyaXB0KG5hbWU6IHN0cmluZyk6IGJvb2xlYW4ge1xuXHRcdHJldHVybiB0eXBlb2YgdGhpcy5fc2NyaXB0c1tuYW1lXSA9PT0gXCJzdHJpbmdcIjtcblx0fVxuXG5cdHB1YmxpYyBmaWxlcygpOiBTb3VyY2VGaWxlW10ge1xuXHRcdHJldHVybiBbXG5cdFx0XHR7XG5cdFx0XHRcdGZpbGVQYXRoOiBcInBhY2thZ2UuanNvblwiLFxuXHRcdFx0XHRjb250ZW50OiBKU09OLnN0cmluZ2lmeShcblx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRuYW1lOiB0aGlzLm5hbWUsXG5cdFx0XHRcdFx0XHR2ZXJzaW9uOiB0aGlzLl92ZXJzaW9uLFxuXHRcdFx0XHRcdFx0dHlwZTogdGhpcy5fdHlwZSxcblx0XHRcdFx0XHRcdC4uLnRoaXMuX3Jlc3QsXG5cdFx0XHRcdFx0XHRzY3JpcHRzOiB0aGlzLl9zY3JpcHRzLFxuXHRcdFx0XHRcdFx0ZGVwZW5kZW5jaWVzOiBzb3J0U3RyaW5nTWFwKHRoaXMuX2RlcGVuZGVuY2llcyksXG5cdFx0XHRcdFx0XHRkZXZEZXBlbmRlbmNpZXM6IHNvcnRTdHJpbmdNYXAodGhpcy5fZGV2RGVwZW5kZW5jaWVzKSxcblx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdG51bGwsXG5cdFx0XHRcdFx0Mixcblx0XHRcdFx0KSxcblx0XHRcdH0sXG5cdFx0XTtcblx0fVxufVxuXG5mdW5jdGlvbiBzdHJpcEFwaVN1ZmZpeChuYW1lOiBzdHJpbmcpOiBzdHJpbmcge1xuXHRyZXR1cm4gbmFtZS5lbmRzV2l0aChcIi5hcGlcIikgPyBuYW1lLnNsaWNlKDAsIC1cIi5hcGlcIi5sZW5ndGgpIDogbmFtZTtcbn1cblxuZnVuY3Rpb24gYXNTdHJpbmdNYXAodmFsdWU6IHVua25vd24pOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+IHtcblx0aWYgKHZhbHVlID09IG51bGwgfHwgdHlwZW9mIHZhbHVlICE9PSBcIm9iamVjdFwiKSByZXR1cm4ge307XG5cdGNvbnN0IHJlc3VsdDogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHt9O1xuXHRmb3IgKGNvbnN0IFtrZXksIGVudHJ5XSBvZiBPYmplY3QuZW50cmllcyh2YWx1ZSkpIHtcblx0XHRpZiAodHlwZW9mIGVudHJ5ID09PSBcInN0cmluZ1wiKSByZXN1bHRba2V5XSA9IGVudHJ5O1xuXHR9XG5cdHJldHVybiByZXN1bHQ7XG59XG5cbi8qKiBTdGFibGUgQeKGkloga2V5IG9yZGVyIGZvciBwYWNrYWdlLmpzb24gZGVwZW5kZW5jeSBtYXBzLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNvcnRTdHJpbmdNYXAobWFwOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+KTogUmVjb3JkPHN0cmluZywgc3RyaW5nPiB7XG5cdHJldHVybiBPYmplY3QuZnJvbUVudHJpZXMoXG5cdFx0T2JqZWN0LmVudHJpZXMobWFwKS5zb3J0KChbbGVmdF0sIFtyaWdodF0pID0+IGxlZnQubG9jYWxlQ29tcGFyZShyaWdodCwgXCJlblwiKSksXG5cdCk7XG59XG5cbmZ1bmN0aW9uIGZsdXhEZXZTY3JpcHQod29ya3NwYWNlTmFtZTogc3RyaW5nLCBhcGlOYW1lOiBzdHJpbmcsIHBvcnQ6IG51bWJlcik6IHN0cmluZyB7XG5cdHJldHVybiBgUE9SVD0ke3BvcnR9IGZsdXggc2VydmUgLS1wcm9qZWN0ICR7d2ViYXBpUGFja2FnZU5hbWUod29ya3NwYWNlTmFtZSwgYXBpTmFtZSl9YDtcbn1cbiJdLCJuYW1lcyI6WyJyZWFkRmlsZVN5bmMiLCJDUkVBVEVfVkVSU0lPTiIsIkRFRkFVTFRfV0VCQVBJX05BTUUiLCJ3ZWJhcGlQYWNrYWdlTmFtZSIsIndlYmFwaVBvcnQiLCJ3ZWJhcGlSZWxlYXNlRW50cnkiLCJXRUxMX0tOT1dOX0ZJTEVTIiwiUGFja2FnZUpzb24iLCJrZXkiLCJQQUNLQUdFX0pTT04iLCJfZGVwZW5kZW5jaWVzIiwiX2RldkRlcGVuZGVuY2llcyIsIl9zY3JpcHRzIiwiX3ZlcnNpb24iLCJfdHlwZSIsIl9yZXN0IiwibmFtZSIsIm9wdGlvbnMiLCJhcGlOYW1lcyIsImZpcnN0Iiwic3RhcnRFbnRyeSIsIndvcmtzcGFjZU5hbWUiLCJzdHJpcEFwaVN1ZmZpeCIsIm5hbWVkT3JNYW55IiwibGVuZ3RoIiwiYnVpbGQiLCJzdGFydCIsImRldiIsImZsdXhEZXZTY3JpcHQiLCJ0eXBlY2hlY2siLCJ0ZXN0IiwiaW5kZXgiLCJhcGlOYW1lIiwiZW50cmllcyIsInR5cGVzY3JpcHQiLCJ2aXRlc3QiLCJmcm9tRmlsZSIsImZpbGVQYXRoIiwicmF3IiwiSlNPTiIsInBhcnNlIiwicGtnIiwidmVyc2lvbiIsInR5cGUiLCJhc1N0cmluZ01hcCIsInNjcmlwdHMiLCJkZXBlbmRlbmNpZXMiLCJkZXZEZXBlbmRlbmNpZXMiLCJyZXNlcnZlZCIsIlNldCIsIk9iamVjdCIsImZyb21FbnRyaWVzIiwiZmlsdGVyIiwiaGFzIiwiYWRkRGVwZW5kZW5jeSIsImFkZERldkRlcGVuZGVuY3kiLCJhZGRTY3JpcHQiLCJjb21tYW5kIiwiaGFzU2NyaXB0IiwiZmlsZXMiLCJjb250ZW50Iiwic3RyaW5naWZ5Iiwic29ydFN0cmluZ01hcCIsImVuZHNXaXRoIiwic2xpY2UiLCJ2YWx1ZSIsInJlc3VsdCIsImVudHJ5IiwibWFwIiwic29ydCIsImxlZnQiLCJyaWdodCIsImxvY2FsZUNvbXBhcmUiLCJwb3J0Il0sIm1hcHBpbmdzIjoiQUFBQSxTQUFTQSxZQUFZLFFBQVEsVUFBVTtBQUN2QyxTQUFTQyxjQUFjLFFBQVEsZ0JBQWdCO0FBQy9DLFNBQ0NDLG1CQUFtQixFQUNuQkMsaUJBQWlCLEVBQ2pCQyxVQUFVLEVBQ1ZDLGtCQUFrQixRQUNaLHFCQUFxQjtBQUM1QixTQUFTQyxnQkFBZ0IsUUFBUSxhQUFhO0FBVzlDOzs7Ozs7Q0FNQyxHQUNELE9BQU8sTUFBTUM7O0lBQ0lDLE1BQU1GLGlCQUFpQkcsWUFBWSxDQUFDO0lBRTVDQyxjQUFzQztJQUN0Q0MsaUJBQXlDO0lBQ3pDQyxTQUFpQztJQUNqQ0MsV0FBVyxRQUFRO0lBQ25CQyxRQUFRLFNBQVM7SUFDakJDLFFBQWlDLENBQUMsRUFBRTtJQUU1QyxZ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
@@ -0,0 +1,119 @@
1
+ import { mkdir, writeFile } from "node:fs/promises";
2
+ import { basename, dirname, join } from "node:path";
3
+ /**
4
+ * A sub-unit of the monorepo (e.g. `projects/api`).
5
+ *
6
+ * Models and files registered here produce paths relative to `dir`. The parent
7
+ * `MonoRepoScaffold` calls `files()` and prepends `dir/` to every path, so
8
+ * models remain unaware of where they live in the repo.
9
+ */ export class ProjectScaffold {
10
+ dir;
11
+ _models = new Map();
12
+ _files = [];
13
+ constructor(dir){
14
+ this.dir = dir;
15
+ }
16
+ addModel(model) {
17
+ this._models.set(model.key, model);
18
+ return model;
19
+ }
20
+ addFile(provider) {
21
+ this._files.push(...provider.files());
22
+ return this;
23
+ }
24
+ getModel(key) {
25
+ return this._models.get(key);
26
+ }
27
+ getModels(ctor) {
28
+ return [
29
+ ...this._models.values()
30
+ ].filter((m)=>m instanceof ctor);
31
+ }
32
+ /** Returns all files with `dir/` prepended to each path. */ files() {
33
+ const all = [
34
+ ...this._files,
35
+ ...[
36
+ ...this._models.values()
37
+ ].flatMap((m)=>m.files())
38
+ ];
39
+ return all.map((f)=>({
40
+ filePath: `${this.dir}/${f.filePath}`,
41
+ content: f.content
42
+ }));
43
+ }
44
+ }
45
+ export class WorkspaceScaffold {
46
+ files = [];
47
+ targetDir = process.cwd();
48
+ _name;
49
+ /** Project name — host directory basename, not the in-container mount path. */ get name() {
50
+ return this._name ?? basename(this.targetDir);
51
+ }
52
+ setName(name) {
53
+ this._name = name;
54
+ return this;
55
+ }
56
+ /** Add an ad-hoc file provider whose output is included at render time. */ addFile(provider) {
57
+ this.files.push(...provider.files());
58
+ return this;
59
+ }
60
+ }
61
+ export class MonoRepoScaffold extends WorkspaceScaffold {
62
+ _models = new Map();
63
+ _projects = [];
64
+ /** Register a named project. */ addProject(project) {
65
+ this._projects.push(project);
66
+ return project;
67
+ }
68
+ /** Retrieve a previously-registered project by its directory path. */ getProject(dir) {
69
+ return this._projects.find((p)=>p.dir === dir);
70
+ }
71
+ /** All registered projects, in registration order. */ getProjects() {
72
+ return this._projects;
73
+ }
74
+ /** Register a named model at workspace level. */ addModel(model) {
75
+ this._models.set(model.key, model);
76
+ return model;
77
+ }
78
+ /**
79
+ * Retrieve a model by key. Searches workspace models first, then all
80
+ * registered projects in order.
81
+ */ getModel(key) {
82
+ const m = this._models.get(key);
83
+ if (m !== undefined) return m;
84
+ for (const project of this._projects){
85
+ const pm = project.getModel(key);
86
+ if (pm !== undefined) return pm;
87
+ }
88
+ return undefined;
89
+ }
90
+ /**
91
+ * Retrieve all models of a given type. Searches workspace models and all
92
+ * projects, so features can discover controllers across multiple projects.
93
+ */ getModels(ctor) {
94
+ return [
95
+ ...[
96
+ ...this._models.values()
97
+ ].filter((m)=>m instanceof ctor),
98
+ ...this._projects.flatMap((p)=>p.getModels(ctor))
99
+ ];
100
+ }
101
+ /** Render all models and projects into files, then write everything to disk. */ async scaffold() {
102
+ const allFiles = [
103
+ ...this.files,
104
+ ...[
105
+ ...this._models.values()
106
+ ].flatMap((m)=>m.files()),
107
+ ...this._projects.flatMap((p)=>p.files())
108
+ ];
109
+ await Promise.all(allFiles.map(async (file)=>{
110
+ const fullPath = join(this.targetDir, file.filePath);
111
+ await mkdir(dirname(fullPath), {
112
+ recursive: true
113
+ });
114
+ await writeFile(fullPath, file.content);
115
+ }));
116
+ }
117
+ }
118
+
119
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL3J1bm5lci93b3JrL2RlY29oZXJlL2RlY29oZXJlL3Byb2plY3RzL3NjYWZmb2xkL3NyYy9tb2RlbHMvcHJvamVjdC5tb2RlbC50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBta2Rpciwgd3JpdGVGaWxlIH0gZnJvbSBcIm5vZGU6ZnMvcHJvbWlzZXNcIjtcbmltcG9ydCB7IGJhc2VuYW1lLCBkaXJuYW1lLCBqb2luIH0gZnJvbSBcIm5vZGU6cGF0aFwiO1xuaW1wb3J0IHR5cGUgeyBLZXllZE1vZGVsLCBTb3VyY2VGaWxlLCBTb3VyY2VGaWxlUHJvdmlkZXIgfSBmcm9tIFwiLi9zb3VyY2UtZmlsZS5qc1wiO1xuXG4vKipcbiAqIEEgc3ViLXVuaXQgb2YgdGhlIG1vbm9yZXBvIChlLmcuIGBwcm9qZWN0cy9hcGlgKS5cbiAqXG4gKiBNb2RlbHMgYW5kIGZpbGVzIHJlZ2lzdGVyZWQgaGVyZSBwcm9kdWNlIHBhdGhzIHJlbGF0aXZlIHRvIGBkaXJgLiBUaGUgcGFyZW50XG4gKiBgTW9ub1JlcG9TY2FmZm9sZGAgY2FsbHMgYGZpbGVzKClgIGFuZCBwcmVwZW5kcyBgZGlyL2AgdG8gZXZlcnkgcGF0aCwgc29cbiAqIG1vZGVscyByZW1haW4gdW5hd2FyZSBvZiB3aGVyZSB0aGV5IGxpdmUgaW4gdGhlIHJlcG8uXG4gKi9cbmV4cG9ydCBjbGFzcyBQcm9qZWN0U2NhZmZvbGQge1xuXHRwcml2YXRlIHJlYWRvbmx5IF9tb2RlbHMgPSBuZXcgTWFwPHN0cmluZywgU291cmNlRmlsZVByb3ZpZGVyPigpO1xuXHRwcml2YXRlIHJlYWRvbmx5IF9maWxlczogU291cmNlRmlsZVtdID0gW107XG5cblx0cHVibGljIGNvbnN0cnVjdG9yKHB1YmxpYyByZWFkb25seSBkaXI6IHN0cmluZykge31cblxuXHRwdWJsaWMgYWRkTW9kZWw8VCBleHRlbmRzIEtleWVkTW9kZWw+KG1vZGVsOiBUKTogVCB7XG5cdFx0dGhpcy5fbW9kZWxzLnNldChtb2RlbC5rZXksIG1vZGVsKTtcblx0XHRyZXR1cm4gbW9kZWw7XG5cdH1cblxuXHRwdWJsaWMgYWRkRmlsZShwcm92aWRlcjogU291cmNlRmlsZVByb3ZpZGVyKTogdGhpcyB7XG5cdFx0dGhpcy5fZmlsZXMucHVzaCguLi5wcm92aWRlci5maWxlcygpKTtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdHB1YmxpYyBnZXRNb2RlbDxUIGV4dGVuZHMgU291cmNlRmlsZVByb3ZpZGVyPihrZXk6IHN0cmluZyk6IFQgfCB1bmRlZmluZWQge1xuXHRcdHJldHVybiB0aGlzLl9tb2RlbHMuZ2V0KGtleSkgYXMgVCB8IHVuZGVmaW5lZDtcblx0fVxuXG5cdHB1YmxpYyBnZXRNb2RlbHM8VCBleHRlbmRzIFNvdXJjZUZpbGVQcm92aWRlcj4oY3RvcjogbmV3ICguLi5hcmdzOiBuZXZlcltdKSA9PiBUKTogVFtdIHtcblx0XHRyZXR1cm4gWy4uLnRoaXMuX21vZGVscy52YWx1ZXMoKV0uZmlsdGVyKChtKTogbSBpcyBUID0+IG0gaW5zdGFuY2VvZiBjdG9yKTtcblx0fVxuXG5cdC8qKiBSZXR1cm5zIGFsbCBmaWxlcyB3aXRoIGBkaXIvYCBwcmVwZW5kZWQgdG8gZWFjaCBwYXRoLiAqL1xuXHRwdWJsaWMgZmlsZXMoKTogU291cmNlRmlsZVtdIHtcblx0XHRjb25zdCBhbGwgPSBbLi4udGhpcy5fZmlsZXMsIC4uLlsuLi50aGlzLl9tb2RlbHMudmFsdWVzKCldLmZsYXRNYXAoKG0pID0+IG0uZmlsZXMoKSldO1xuXHRcdHJldHVybiBhbGwubWFwKChmKSA9PiAoeyBmaWxlUGF0aDogYCR7dGhpcy5kaXJ9LyR7Zi5maWxlUGF0aH1gLCBjb250ZW50OiBmLmNvbnRlbnQgfSkpO1xuXHR9XG59XG5cbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBXb3Jrc3BhY2VTY2FmZm9sZCB7XG5cdHB1YmxpYyByZWFkb25seSBmaWxlczogU291cmNlRmlsZVtdID0gW107XG5cdHB1YmxpYyB0YXJnZXREaXI6IHN0cmluZyA9IHByb2Nlc3MuY3dkKCk7XG5cdHByaXZhdGUgX25hbWU6IHN0cmluZyB8IHVuZGVmaW5lZDtcblxuXHQvKiogUHJvamVjdCBuYW1lIOKAlCBob3N0IGRpcmVjdG9yeSBiYXNlbmFtZSwgbm90IHRoZSBpbi1jb250YWluZXIgbW91bnQgcGF0aC4gKi9cblx0cHVibGljIGdldCBuYW1lKCk6IHN0cmluZyB7XG5cdFx0cmV0dXJuIHRoaXMuX25hbWUgPz8gYmFzZW5hbWUodGhpcy50YXJnZXREaXIpO1xuXHR9XG5cblx0cHVibGljIHNldE5hbWUobmFtZTogc3RyaW5nKTogdGhpcyB7XG5cdFx0dGhpcy5fbmFtZSA9IG5hbWU7XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxuXHQvKiogQWRkIGFuIGFkLWhvYyBmaWxlIHByb3ZpZGVyIHdob3NlIG91dHB1dCBpcyBpbmNsdWRlZCBhdCByZW5kZXIgdGltZS4gKi9cblx0cHVibGljIGFkZEZpbGUocHJvdmlkZXI6IFNvdXJjZUZpbGVQcm92aWRlcik6IHRoaXMge1xuXHRcdHRoaXMuZmlsZXMucHVzaCguLi5wcm92aWRlci5maWxlcygpKTtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdHB1YmxpYyBhYnN0cmFjdCBhZGRNb2RlbDxUIGV4dGVuZHMgS2V5ZWRNb2RlbD4obW9kZWw6IFQpOiBUO1xuXHRwdWJsaWMgYWJzdHJhY3QgZ2V0TW9kZWw8VCBleHRlbmRzIFNvdXJjZUZpbGVQcm92aWRlcj4oa2V5OiBzdHJpbmcpOiBUIHwgdW5kZWZpbmVkO1xuXHRwdWJsaWMgYWJzdHJhY3QgZ2V0TW9kZWxzPFQgZXh0ZW5kcyBTb3VyY2VGaWxlUHJvdmlkZXI+KFxuXHRcdGN0b3I6IG5ldyAoLi4uYXJnczogbmV2ZXJbXSkgPT4gVCxcblx0KTogVFtdO1xuXHRwdWJsaWMgYWJzdHJhY3QgZ2V0UHJvamVjdChkaXI6IHN0cmluZyk6IFByb2plY3RTY2FmZm9sZCB8IHVuZGVmaW5lZDtcblx0cHVibGljIGFic3RyYWN0IGdldFByb2plY3RzKCk6IHJlYWRvbmx5IFByb2plY3RTY2FmZm9sZFtdO1xuXHRwdWJsaWMgYWJzdHJhY3Qgc2NhZmZvbGQoKTogUHJvbWlzZTx2b2lkPiB8IHZvaWQ7XG59XG5cbmV4cG9ydCBjbGFzcyBNb25vUmVwb1NjYWZmb2xkIGV4dGVuZHMgV29ya3NwYWNlU2NhZmZvbGQge1xuXHRwcml2YXRlIHJlYWRvbmx5IF9tb2RlbHMgPSBuZXcgTWFwPHN0cmluZywgU291cmNlRmlsZVByb3ZpZGVyPigpO1xuXHRwcml2YXRlIHJlYWRvbmx5IF9wcm9qZWN0czogUHJvamVjdFNjYWZmb2xkW10gPSBbXTtcblxuXHQvKiogUmVnaXN0ZXIgYSBuYW1lZCBwcm9qZWN0LiAqL1xuXHRwdWJsaWMgYWRkUHJvamVjdChwcm9qZWN0OiBQcm9qZWN0U2NhZmZvbGQpOiBQcm9qZWN0U2NhZmZvbGQge1xuXHRcdHRoaXMuX3Byb2plY3RzLnB1c2gocHJvamVjdCk7XG5cdFx0cmV0dXJuIHByb2plY3Q7XG5cdH1cblxuXHQvKiogUmV0cmlldmUgYSBwcmV2aW91c2x5LXJlZ2lzdGVyZWQgcHJvamVjdCBieSBpdHMgZGlyZWN0b3J5IHBhdGguICovXG5cdHB1YmxpYyBnZXRQcm9qZWN0KGRpcjogc3RyaW5nKTogUHJvamVjdFNjYWZmb2xkIHwgdW5kZWZpbmVkIHtcblx0XHRyZXR1cm4gdGhpcy5fcHJvamVjdHMuZmluZCgocCkgPT4gcC5kaXIgPT09IGRpcik7XG5cdH1cblxuXHQvKiogQWxsIHJlZ2lzdGVyZWQgcHJvamVjdHMsIGluIHJlZ2lzdHJhdGlvbiBvcmRlci4gKi9cblx0cHVibGljIGdldFByb2plY3RzKCk6IHJlYWRvbmx5IFByb2plY3RTY2FmZm9sZFtdIHtcblx0XHRyZXR1cm4gdGhpcy5fcHJvamVjdHM7XG5cdH1cblxuXHQvKiogUmVnaXN0ZXIgYSBuYW1lZCBtb2RlbCBhdCB3b3Jrc3BhY2UgbGV2ZWwuICovXG5cdHB1YmxpYyBhZGRNb2RlbDxUIGV4dGVuZHMgS2V5ZWRNb2RlbD4obW9kZWw6IFQpOiBUIHtcblx0XHR0aGlzLl9tb2RlbHMuc2V0KG1vZGVsLmtleSwgbW9kZWwpO1xuXHRcdHJldHVybiBtb2RlbDtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZXRyaWV2ZSBhIG1vZGVsIGJ5IGtleS4gU2VhcmNoZXMgd29ya3NwYWNlIG1vZGVscyBmaXJzdCwgdGhlbiBhbGxcblx0ICogcmVnaXN0ZXJlZCBwcm9qZWN0cyBpbiBvcmRlci5cblx0ICovXG5cdHB1YmxpYyBnZXRNb2RlbDxUIGV4dGVuZHMgU291cmNlRmlsZVByb3ZpZGVyPihrZXk6IHN0cmluZyk6IFQgfCB1bmRlZmluZWQge1xuXHRcdGNvbnN0IG0gPSB0aGlzLl9tb2RlbHMuZ2V0KGtleSkgYXMgVCB8IHVuZGVmaW5lZDtcblx0XHRpZiAobSAhPT0gdW5kZWZpbmVkKSByZXR1cm4gbTtcblx0XHRmb3IgKGNvbnN0IHByb2plY3Qgb2YgdGhpcy5fcHJvamVjdHMpIHtcblx0XHRcdGNvbnN0IHBtID0gcHJvamVjdC5nZXRNb2RlbDxUPihrZXkpO1xuXHRcdFx0aWYgKHBtICE9PSB1bmRlZmluZWQpIHJldHVybiBwbTtcblx0XHR9XG5cdFx0cmV0dXJuIHVuZGVmaW5lZDtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZXRyaWV2ZSBhbGwgbW9kZWxzIG9mIGEgZ2l2ZW4gdHlwZS4gU2VhcmNoZXMgd29ya3NwYWNlIG1vZGVscyBhbmQgYWxsXG5cdCAqIHByb2plY3RzLCBzbyBmZWF0dXJlcyBjYW4gZGlzY292ZXIgY29udHJvbGxlcnMgYWNyb3NzIG11bHRpcGxlIHByb2plY3RzLlxuXHQgKi9cblx0cHVibGljIGdldE1vZGVsczxUIGV4dGVuZHMgU291cmNlRmlsZVByb3ZpZGVyPihjdG9yOiBuZXcgKC4uLmFyZ3M6IG5ldmVyW10pID0+IFQpOiBUW10ge1xuXHRcdHJldHVybiBbXG5cdFx0XHQuLi5bLi4udGhpcy5fbW9kZWxzLnZhbHVlcygpXS5maWx0ZXIoKG0pOiBtIGlzIFQgPT4gbSBpbnN0YW5jZW9mIGN0b3IpLFxuXHRcdFx0Li4udGhpcy5fcHJvamVjdHMuZmxhdE1hcCgocCkgPT4gcC5nZXRNb2RlbHMoY3RvcikpLFxuXHRcdF07XG5cdH1cblxuXHQvKiogUmVuZGVyIGFsbCBtb2RlbHMgYW5kIHByb2plY3RzIGludG8gZmlsZXMsIHRoZW4gd3JpdGUgZXZlcnl0aGluZyB0byBkaXNrLiAqL1xuXHRwdWJsaWMgYXN5bmMgc2NhZmZvbGQoKTogUHJvbWlzZTx2b2lkPiB7XG5cdFx0Y29uc3QgYWxsRmlsZXMgPSBbXG5cdFx0XHQuLi50aGlzLmZpbGVzLFxuXHRcdFx0Li4uWy4uLnRoaXMuX21vZGVscy52YWx1ZXMoKV0uZmxhdE1hcCgobSkgPT4gbS5maWxlcygpKSxcblx0XHRcdC4uLnRoaXMuX3Byb2plY3RzLmZsYXRNYXAoKHApID0+IHAuZmlsZXMoKSksXG5cdFx0XTtcblxuXHRcdGF3YWl0IFByb21pc2UuYWxsKFxuXHRcdFx0YWxsRmlsZXMubWFwKGFzeW5jIChmaWxlKSA9PiB7XG5cdFx0XHRcdGNvbnN0IGZ1bGxQYXRoID0gam9pbih0aGlzLnRhcmdldERpciwgZmlsZS5maWxlUGF0aCk7XG5cdFx0XHRcdGF3YWl0IG1rZGlyKGRpcm5hbWUoZnVsbFBhdGgpLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcblx0XHRcdFx0YXdhaXQgd3JpdGVGaWxlKGZ1bGxQYXRoLCBmaWxlLmNvbnRlbnQpO1xuXHRcdFx0fSksXG5cdFx0KTtcblx0fVxufVxuIl0sIm5hbWVzIjpbIm1rZGlyIiwid3JpdGVGaWxlIiwiYmFzZW5hbWUiLCJkaXJuYW1lIiwiam9pbiIsIlByb2plY3RTY2FmZm9sZCIsIl9tb2RlbHMiLCJNYXAiLCJfZmlsZXMiLCJkaXIiLCJhZGRNb2RlbCIsIm1vZGVsIiwic2V0Iiwia2V5IiwiYWRkRmlsZSIsInByb3ZpZGVyIiwicHVzaCIsImZpbGVzIiwiZ2V0TW9kZWwiLCJnZXQiLCJnZXRNb2RlbHMiLCJjdG9yIiwidmFsdWVzIiwiZmlsdGVyIiwibSIsImFsbCIsImZsYXRNYXAiLCJtYXAiLCJmIiwiZmlsZVBhdGgiLCJjb250ZW50IiwiV29ya3NwYWNlU2NhZmZvbGQiLCJ0YXJnZXREaXIiLCJwcm9jZXNzIiwiY3dkIiwiX25hbWUiLCJuYW1lIiwic2V0TmFtZSIsIk1vbm9SZXBvU2NhZmZvbGQiLCJfcHJvamVjdHMiLCJhZGRQcm9qZWN0IiwicHJvamVjdCIsImdldFByb2plY3QiLCJmaW5kIiwicCIsImdldFByb2plY3RzIiwidW5kZWZpbmVkIiwicG0iLCJzY2FmZm9sZCIsImFsbEZpbGVzIiwiUHJvbWlzZSIsImZpbGUiLCJmdWxsUGF0aCIsInJlY3Vyc2l2ZSJdLCJtYXBwaW5ncyI6IkFBQUEsU0FBU0EsS0FBSyxFQUFFQyxTQUFTLFFBQVEsbUJBQW1CO0FBQ3BELFNBQVNDLFFBQVEsRUFBRUMsT0FBTyxFQUFFQyxJQUFJLFFBQVEsWUFBWTtBQUdwRDs7Ozs7O0NBTUMsR0FDRCxPQUFPLE1BQU1DOztJQUNLQyxVQUFVLElBQUlDLE1BQWtDO0lBQ2hEQyxTQUF1QixFQUFFLENBQUM7SUFFM0MsWUFBbUIsQUFBZ0JDLEdBQVcsQ0FBRTthQUFiQSxNQUFBQTtJQUFjO0lBRTFDQyxTQUErQkMsS0FBUSxFQUFLO1FBQ2xELElBQUksQ0FBQ0wsT0FBTyxDQUFDTSxHQUFHLENBQUNELE1BQU1FLEdBQUcsRUFBRUY7UUFDNUIsT0FBT0E7SUFDUjtJQUVPRyxRQUFRQyxRQUE0QixFQUFRO1FBQ2xELElBQUksQ0FBQ1AsTUFBTSxDQUFDUSxJQUFJLElBQUlELFNBQVNFLEtBQUs7UUFDbEMsT0FBTyxJQUFJO0lBQ1o7SUFFT0MsU0FBdUNMLEdBQVcsRUFBaUI7UUFDekUsT0FBTyxJQUFJLENBQUNQLE9BQU8sQ0FBQ2EsR0FBRyxDQUFDTjtJQUN6QjtJQUVPTyxVQUF3Q0MsSUFBaUMsRUFBTztRQUN0RixPQUFPO2VBQUksSUFBSSxDQUFDZixPQUFPLENBQUNnQixNQUFNO1NBQUcsQ0FBQ0MsTUFBTSxDQUFDLENBQUNDLElBQWNBLGFBQWFIO0lBQ3RFO0lBRUEsMERBQTBELEdBQzFELEFBQU9KLFFBQXNCO1FBQzVCLE1BQU1RLE1BQU07ZUFBSSxJQUFJLENBQUNqQixNQUFNO2VB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
@@ -0,0 +1,3 @@
1
+ export { };
2
+
3
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL3J1bm5lci93b3JrL2RlY29oZXJlL2RlY29oZXJlL3Byb2plY3RzL3NjYWZmb2xkL3NyYy9tb2RlbHMvc291cmNlLWZpbGUudHMiXSwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0IGludGVyZmFjZSBTb3VyY2VGaWxlUHJvdmlkZXIge1xuXHRmaWxlcygpOiBTb3VyY2VGaWxlW107XG59XG5cbi8qKiBBIFNvdXJjZUZpbGVQcm92aWRlciB0aGF0IGtub3dzIGl0cyBvd24gcmVnaXN0cmF0aW9uIGtleS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgS2V5ZWRNb2RlbCBleHRlbmRzIFNvdXJjZUZpbGVQcm92aWRlciB7XG5cdHJlYWRvbmx5IGtleTogc3RyaW5nO1xufVxuXG5leHBvcnQgdHlwZSBTb3VyY2VGaWxlID0ge1xuXHRmaWxlUGF0aDogc3RyaW5nO1xuXHRjb250ZW50OiBzdHJpbmc7XG59O1xuIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQVNBLFdBR0UifQ==
@@ -0,0 +1,24 @@
1
+ import { WELL_KNOWN_FILES } from "./const.js";
2
+ export class TsConfig {
3
+ key = WELL_KNOWN_FILES.TSCONFIG;
4
+ files() {
5
+ return [
6
+ {
7
+ filePath: "tsconfig.json",
8
+ content: JSON.stringify({
9
+ compilerOptions: {
10
+ target: "ES2022",
11
+ module: "NodeNext",
12
+ moduleResolution: "NodeNext",
13
+ strict: true,
14
+ skipLibCheck: true,
15
+ experimentalDecorators: true,
16
+ emitDecoratorMetadata: true
17
+ }
18
+ }, null, 2)
19
+ }
20
+ ];
21
+ }
22
+ }
23
+
24
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL3J1bm5lci93b3JrL2RlY29oZXJlL2RlY29oZXJlL3Byb2plY3RzL3NjYWZmb2xkL3NyYy9tb2RlbHMvdHNjb25maWcubW9kZWwudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgV0VMTF9LTk9XTl9GSUxFUyB9IGZyb20gXCIuL2NvbnN0LmpzXCI7XG5pbXBvcnQgdHlwZSB7IEtleWVkTW9kZWwsIFNvdXJjZUZpbGUgfSBmcm9tIFwiLi9zb3VyY2UtZmlsZS5qc1wiO1xuXG5leHBvcnQgY2xhc3MgVHNDb25maWcgaW1wbGVtZW50cyBLZXllZE1vZGVsIHtcblx0cHVibGljIHJlYWRvbmx5IGtleSA9IFdFTExfS05PV05fRklMRVMuVFNDT05GSUc7XG5cblx0cHVibGljIGZpbGVzKCk6IFNvdXJjZUZpbGVbXSB7XG5cdFx0cmV0dXJuIFtcblx0XHRcdHtcblx0XHRcdFx0ZmlsZVBhdGg6IFwidHNjb25maWcuanNvblwiLFxuXHRcdFx0XHRjb250ZW50OiBKU09OLnN0cmluZ2lmeShcblx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRjb21waWxlck9wdGlvbnM6IHtcblx0XHRcdFx0XHRcdFx0dGFyZ2V0OiBcIkVTMjAyMlwiLFxuXHRcdFx0XHRcdFx0XHRtb2R1bGU6IFwiTm9kZU5leHRcIixcblx0XHRcdFx0XHRcdFx0bW9kdWxlUmVzb2x1dGlvbjogXCJOb2RlTmV4dFwiLFxuXHRcdFx0XHRcdFx0XHRzdHJpY3Q6IHRydWUsXG5cdFx0XHRcdFx0XHRcdHNraXBMaWJDaGVjazogdHJ1ZSxcblx0XHRcdFx0XHRcdFx0ZXhwZXJpbWVudGFsRGVjb3JhdG9yczogdHJ1ZSxcblx0XHRcdFx0XHRcdFx0ZW1pdERlY29yYXRvck1ldGFkYXRhOiB0cnVlLFxuXHRcdFx0XHRcdFx0fSxcblx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdG51bGwsXG5cdFx0XHRcdFx0Mixcblx0XHRcdFx0KSxcblx0XHRcdH0sXG5cdFx0XTtcblx0fVxufVxuIl0sIm5hbWVzIjpbIldFTExfS05PV05fRklMRVMiLCJUc0NvbmZpZyIsImtleSIsIlRTQ09ORklHIiwiZmlsZXMiLCJmaWxlUGF0aCIsImNvbnRlbnQiLCJKU09OIiwic3RyaW5naWZ5IiwiY29tcGlsZXJPcHRpb25zIiwidGFyZ2V0IiwibW9kdWxlIiwibW9kdWxlUmVzb2x1dGlvbiIsInN0cmljdCIsInNraXBMaWJDaGVjayIsImV4cGVyaW1lbnRhbERlY29yYXRvcnMiLCJlbWl0RGVjb3JhdG9yTWV0YWRhdGEiXSwibWFwcGluZ3MiOiJBQUFBLFNBQVNBLGdCQUFnQixRQUFRLGFBQWE7QUFHOUMsT0FBTyxNQUFNQztJQUNJQyxNQUFNRixpQkFBaUJHLFFBQVEsQ0FBQztJQUV6Q0MsUUFBc0I7UUFDNUIsT0FBTztZQUNOO2dCQUNDQyxVQUFVO2dCQUNWQyxTQUFTQyxLQUFLQyxTQUFTLENBQ3RCO29CQUNDQyxpQkFBaUI7d0JBQ2hCQyxRQUFRO3dCQUNSQyxRQUFRO3dCQUNSQyxrQkFBa0I7d0JBQ2xCQyxRQUFRO3dCQUNSQyxjQUFjO3dCQUNkQyx3QkFBd0I7d0JBQ3hCQyx1QkFBdUI7b0JBQ3hCO2dCQUNELEdBQ0EsTUFDQTtZQUVGO1NBQ0E7SUFDRjtBQUNEIn0=
@@ -0,0 +1,25 @@
1
+ import { WELL_KNOWN_FILES } from "./const.js";
2
+ export class VitestConfig {
3
+ key = WELL_KNOWN_FILES.VITEST_CONFIG;
4
+ files() {
5
+ return [
6
+ {
7
+ filePath: "vitest.config.ts",
8
+ content: [
9
+ 'import { forgeBuild } from "@decohere/forge/vitest";',
10
+ 'import { defineConfig } from "vitest/config";',
11
+ "",
12
+ "export default defineConfig({",
13
+ '\tplugins: [forgeBuild({ logLevel: "silent" })],',
14
+ "\ttest: {",
15
+ '\t\tinclude: ["projects/**/*.{test,spec}.?(c|m)[jt]s?(x)"],',
16
+ "\t},",
17
+ "});",
18
+ ""
19
+ ].join("\n")
20
+ }
21
+ ];
22
+ }
23
+ }
24
+
25
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL3J1bm5lci93b3JrL2RlY29oZXJlL2RlY29oZXJlL3Byb2plY3RzL3NjYWZmb2xkL3NyYy9tb2RlbHMvdml0ZXN0LWNvbmZpZy5tb2RlbC50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBXRUxMX0tOT1dOX0ZJTEVTIH0gZnJvbSBcIi4vY29uc3QuanNcIjtcbmltcG9ydCB0eXBlIHsgS2V5ZWRNb2RlbCwgU291cmNlRmlsZSB9IGZyb20gXCIuL3NvdXJjZS1maWxlLmpzXCI7XG5cbmV4cG9ydCBjbGFzcyBWaXRlc3RDb25maWcgaW1wbGVtZW50cyBLZXllZE1vZGVsIHtcblx0cHVibGljIHJlYWRvbmx5IGtleSA9IFdFTExfS05PV05fRklMRVMuVklURVNUX0NPTkZJRztcblxuXHRwdWJsaWMgZmlsZXMoKTogU291cmNlRmlsZVtdIHtcblx0XHRyZXR1cm4gW1xuXHRcdFx0e1xuXHRcdFx0XHRmaWxlUGF0aDogXCJ2aXRlc3QuY29uZmlnLnRzXCIsXG5cdFx0XHRcdGNvbnRlbnQ6IFtcblx0XHRcdFx0XHQnaW1wb3J0IHsgZm9yZ2VCdWlsZCB9IGZyb20gXCJAZGVjb2hlcmUvZm9yZ2Uvdml0ZXN0XCI7Jyxcblx0XHRcdFx0XHQnaW1wb3J0IHsgZGVmaW5lQ29uZmlnIH0gZnJvbSBcInZpdGVzdC9jb25maWdcIjsnLFxuXHRcdFx0XHRcdFwiXCIsXG5cdFx0XHRcdFx0XCJleHBvcnQgZGVmYXVsdCBkZWZpbmVDb25maWcoe1wiLFxuXHRcdFx0XHRcdCdcXHRwbHVnaW5zOiBbZm9yZ2VCdWlsZCh7IGxvZ0xldmVsOiBcInNpbGVudFwiIH0pXSwnLFxuXHRcdFx0XHRcdFwiXFx0dGVzdDoge1wiLFxuXHRcdFx0XHRcdCdcXHRcXHRpbmNsdWRlOiBbXCJwcm9qZWN0cy8qKi8qLnt0ZXN0LHNwZWN9Lj8oY3xtKVtqdF1zPyh4KVwiXSwnLFxuXHRcdFx0XHRcdFwiXFx0fSxcIixcblx0XHRcdFx0XHRcIn0pO1wiLFxuXHRcdFx0XHRcdFwiXCIsXG5cdFx0XHRcdF0uam9pbihcIlxcblwiKSxcblx0XHRcdH0sXG5cdFx0XTtcblx0fVxufVxuIl0sIm5hbWVzIjpbIldFTExfS05PV05fRklMRVMiLCJWaXRlc3RDb25maWciLCJrZXkiLCJWSVRFU1RfQ09ORklHIiwiZmlsZXMiLCJmaWxlUGF0aCIsImNvbnRlbnQiLCJqb2luIl0sIm1hcHBpbmdzIjoiQUFBQSxTQUFTQSxnQkFBZ0IsUUFBUSxhQUFhO0FBRzlDLE9BQU8sTUFBTUM7SUFDSUMsTUFBTUYsaUJBQWlCRyxhQUFhLENBQUM7SUFFOUNDLFFBQXNCO1FBQzVCLE9BQU87WUFDTjtnQkFDQ0MsVUFBVTtnQkFDVkMsU0FBUztvQkFDUjtvQkFDQTtvQkFDQTtvQkFDQTtvQkFDQTtvQkFDQTtvQkFDQTtvQkFDQTtvQkFDQTtvQkFDQTtpQkFDQSxDQUFDQyxJQUFJLENBQUM7WUFDUjtTQUNBO0lBQ0Y7QUFDRCJ9
@@ -0,0 +1,21 @@
1
+ import { WELL_KNOWN_FILES } from "./const.js";
2
+ export class VSCodeSettings {
3
+ title;
4
+ key = WELL_KNOWN_FILES.VSCODE_SETTINGS;
5
+ constructor(title){
6
+ this.title = title;
7
+ }
8
+ files() {
9
+ return [
10
+ {
11
+ filePath: ".vscode/settings.json",
12
+ content: JSON.stringify({
13
+ "window.title": `${this.title}\${separator}\${activeEditorShort}`,
14
+ "window.titleSeparator": " | "
15
+ }, null, 2)
16
+ }
17
+ ];
18
+ }
19
+ }
20
+
21
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL3J1bm5lci93b3JrL2RlY29oZXJlL2RlY29oZXJlL3Byb2plY3RzL3NjYWZmb2xkL3NyYy9tb2RlbHMvdnNjb2RlLXNldHRpbmdzLm1vZGVsLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IFdFTExfS05PV05fRklMRVMgfSBmcm9tIFwiLi9jb25zdC5qc1wiO1xuaW1wb3J0IHR5cGUgeyBLZXllZE1vZGVsLCBTb3VyY2VGaWxlIH0gZnJvbSBcIi4vc291cmNlLWZpbGUuanNcIjtcblxuZXhwb3J0IGNsYXNzIFZTQ29kZVNldHRpbmdzIGltcGxlbWVudHMgS2V5ZWRNb2RlbCB7XG5cdHB1YmxpYyByZWFkb25seSBrZXkgPSBXRUxMX0tOT1dOX0ZJTEVTLlZTQ09ERV9TRVRUSU5HUztcblxuXHRwdWJsaWMgY29uc3RydWN0b3IocHJpdmF0ZSByZWFkb25seSB0aXRsZTogc3RyaW5nKSB7fVxuXG5cdHB1YmxpYyBmaWxlcygpOiBTb3VyY2VGaWxlW10ge1xuXHRcdHJldHVybiBbXG5cdFx0XHR7XG5cdFx0XHRcdGZpbGVQYXRoOiBcIi52c2NvZGUvc2V0dGluZ3MuanNvblwiLFxuXHRcdFx0XHRjb250ZW50OiBKU09OLnN0cmluZ2lmeShcblx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRcIndpbmRvdy50aXRsZVwiOiBgJHt0aGlzLnRpdGxlfVxcJHtzZXBhcmF0b3J9XFwke2FjdGl2ZUVkaXRvclNob3J0fWAsXG5cdFx0XHRcdFx0XHRcIndpbmRvdy50aXRsZVNlcGFyYXRvclwiOiBcIiB8IFwiLFxuXHRcdFx0XHRcdH0sXG5cdFx0XHRcdFx0bnVsbCxcblx0XHRcdFx0XHQyLFxuXHRcdFx0XHQpLFxuXHRcdFx0fSxcblx0XHRdO1xuXHR9XG59XG4iXSwibmFtZXMiOlsiV0VMTF9LTk9XTl9GSUxFUyIsIlZTQ29kZVNldHRpbmdzIiwia2V5IiwiVlNDT0RFX1NFVFRJTkdTIiwidGl0bGUiLCJmaWxlcyIsImZpbGVQYXRoIiwiY29udGVudCIsIkpTT04iLCJzdHJpbmdpZnkiXSwibWFwcGluZ3MiOiJBQUFBLFNBQVNBLGdCQUFnQixRQUFRLGFBQWE7QUFHOUMsT0FBTyxNQUFNQzs7SUFDSUMsTUFBTUYsaUJBQWlCRyxlQUFlLENBQUM7SUFFdkQsWUFBbUIsQUFBaUJDLEtBQWEsQ0FBRTthQUFmQSxRQUFBQTtJQUFnQjtJQUU3Q0MsUUFBc0I7UUFDNUIsT0FBTztZQUNOO2dCQUNDQyxVQUFVO2dCQUNWQyxTQUFTQyxLQUFLQyxTQUFTLENBQ3RCO29CQUNDLGdCQUFnQixHQUFHLElBQUksQ0FBQ0wsS0FBSyxDQUFDLGtDQUFrQyxDQUFDO29CQUNqRSx5QkFBeUI7Z0JBQzFCLEdBQ0EsTUFDQTtZQUVGO1NBQ0E7SUFDRjtBQUNEIn0=
@@ -0,0 +1,39 @@
1
+ import { Command, CommanderError } from "commander";
2
+ import { CreateCliError } from "./webapi/api-name.js";
3
+ import { addWebapiFeatureOptions, collectName, runScaffoldApi, toApiOptions } from "./webapi/cli-options.js";
4
+ export function createProgram() {
5
+ const program = new Command();
6
+ program.exitOverride();
7
+ program.name("decohere").description("Decohere CLI").option("-d <directory>", "Target directory (default: current directory)", ".");
8
+ const create = program.command("create").description("Create a new Decohere workspace");
9
+ addWebapiFeatureOptions(create.command("webapi").argument("[directory]", "Target directory (default: -d or current directory)").option("--name <slug>", "API name under projects/ (repeatable; default: api)", collectName, [])).action(async (directory, _opts, cmd)=>{
10
+ await runScaffoldApi(toApiOptions(directory, cmd.optsWithGlobals()));
11
+ });
12
+ addWebapiFeatureOptions(program.command("add").description("Add to an existing Decohere workspace").command("api").argument("<name>", "API name under projects/")).action(async (name, _opts, cmd)=>{
13
+ await runScaffoldApi(toApiOptions(undefined, cmd.optsWithGlobals(), {
14
+ names: [
15
+ name
16
+ ],
17
+ add: true
18
+ }));
19
+ });
20
+ return program;
21
+ }
22
+ export async function runCli(argv = process.argv) {
23
+ try {
24
+ await createProgram().parseAsync(argv);
25
+ } catch (err) {
26
+ if (err instanceof CommanderError) {
27
+ process.exit(err.exitCode);
28
+ }
29
+ if (err instanceof CreateCliError) {
30
+ console.error(`\n ${err.message}\n`);
31
+ process.exit(1);
32
+ }
33
+ console.error(err);
34
+ process.exit(1);
35
+ }
36
+ process.exit(process.exitCode ?? 0);
37
+ }
38
+
39
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL3J1bm5lci93b3JrL2RlY29oZXJlL2RlY29oZXJlL3Byb2plY3RzL3NjYWZmb2xkL3NyYy9wcm9ncmFtLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbW1hbmQsIENvbW1hbmRlckVycm9yIH0gZnJvbSBcImNvbW1hbmRlclwiO1xuaW1wb3J0IHsgQ3JlYXRlQ2xpRXJyb3IgfSBmcm9tIFwiLi93ZWJhcGkvYXBpLW5hbWUuanNcIjtcbmltcG9ydCB7XG5cdGFkZFdlYmFwaUZlYXR1cmVPcHRpb25zLFxuXHRjb2xsZWN0TmFtZSxcblx0cnVuU2NhZmZvbGRBcGksXG5cdHRvQXBpT3B0aW9ucyxcbn0gZnJvbSBcIi4vd2ViYXBpL2NsaS1vcHRpb25zLmpzXCI7XG5cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVQcm9ncmFtKCk6IENvbW1hbmQge1xuXHRjb25zdCBwcm9ncmFtID0gbmV3IENvbW1hbmQoKTtcblx0cHJvZ3JhbS5leGl0T3ZlcnJpZGUoKTtcblx0cHJvZ3JhbVxuXHRcdC5uYW1lKFwiZGVjb2hlcmVcIilcblx0XHQuZGVzY3JpcHRpb24oXCJEZWNvaGVyZSBDTElcIilcblx0XHQub3B0aW9uKFwiLWQgPGRpcmVjdG9yeT5cIiwgXCJUYXJnZXQgZGlyZWN0b3J5IChkZWZhdWx0OiBjdXJyZW50IGRpcmVjdG9yeSlcIiwgXCIuXCIpO1xuXG5cdGNvbnN0IGNyZWF0ZSA9IHByb2dyYW0uY29tbWFuZChcImNyZWF0ZVwiKS5kZXNjcmlwdGlvbihcIkNyZWF0ZSBhIG5ldyBEZWNvaGVyZSB3b3Jrc3BhY2VcIik7XG5cdGFkZFdlYmFwaUZlYXR1cmVPcHRpb25zKFxuXHRcdGNyZWF0ZVxuXHRcdFx0LmNvbW1hbmQoXCJ3ZWJhcGlcIilcblx0XHRcdC5hcmd1bWVudChcIltkaXJlY3RvcnldXCIsIFwiVGFyZ2V0IGRpcmVjdG9yeSAoZGVmYXVsdDogLWQgb3IgY3VycmVudCBkaXJlY3RvcnkpXCIpXG5cdFx0XHQub3B0aW9uKFxuXHRcdFx0XHRcIi0tbmFtZSA8c2x1Zz5cIixcblx0XHRcdFx0XCJBUEkgbmFtZSB1bmRlciBwcm9qZWN0cy8gKHJlcGVhdGFibGU7IGRlZmF1bHQ6IGFwaSlcIixcblx0XHRcdFx0Y29sbGVjdE5hbWUsXG5cdFx0XHRcdFtdIGFzIHN0cmluZ1tdLFxuXHRcdFx0KSxcblx0KS5hY3Rpb24oYXN5bmMgKGRpcmVjdG9yeTogc3RyaW5nIHwgdW5kZWZpbmVkLCBfb3B0czogdW5rbm93biwgY21kOiBDb21tYW5kKSA9PiB7XG5cdFx0YXdhaXQgcnVuU2NhZmZvbGRBcGkodG9BcGlPcHRpb25zKGRpcmVjdG9yeSwgY21kLm9wdHNXaXRoR2xvYmFscygpKSk7XG5cdH0pO1xuXG5cdGFkZFdlYmFwaUZlYXR1cmVPcHRpb25zKFxuXHRcdHByb2dyYW1cblx0XHRcdC5jb21tYW5kKFwiYWRkXCIpXG5cdFx0XHQuZGVzY3JpcHRpb24oXCJBZGQgdG8gYW4gZXhpc3RpbmcgRGVjb2hlcmUgd29ya3NwYWNlXCIpXG5cdFx0XHQuY29tbWFuZChcImFwaVwiKVxuXHRcdFx0LmFyZ3VtZW50KFwiPG5hbWU+XCIsIFwiQVBJIG5hbWUgdW5kZXIgcHJvamVjdHMvXCIpLFxuXHQpLmFjdGlvbihhc3luYyAobmFtZTogc3RyaW5nLCBfb3B0czogdW5rbm93biwgY21kOiBDb21tYW5kKSA9PiB7XG5cdFx0YXdhaXQgcnVuU2NhZmZvbGRBcGkoXG5cdFx0XHR0b0FwaU9wdGlvbnModW5kZWZpbmVkLCBjbWQub3B0c1dpdGhHbG9iYWxzKCksIHsgbmFtZXM6IFtuYW1lXSwgYWRkOiB0cnVlIH0pLFxuXHRcdCk7XG5cdH0pO1xuXG5cdHJldHVybiBwcm9ncmFtO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcnVuQ2xpKGFyZ3Y6IHN0cmluZ1tdID0gcHJvY2Vzcy5hcmd2KTogUHJvbWlzZTx2b2lkPiB7XG5cdHRyeSB7XG5cdFx0YXdhaXQgY3JlYXRlUHJvZ3JhbSgpLnBhcnNlQXN5bmMoYXJndik7XG5cdH0gY2F0Y2ggKGVycikge1xuXHRcdGlmIChlcnIgaW5zdGFuY2VvZiBDb21tYW5kZXJFcnJvcikge1xuXHRcdFx0cHJvY2Vzcy5leGl0KGVyci5leGl0Q29kZSk7XG5cdFx0fVxuXHRcdGlmIChlcnIgaW5zdGFuY2VvZiBDcmVhdGVDbGlFcnJvcikge1xuXHRcdFx0Y29uc29sZS5lcnJvcihgXFxuICAke2Vyci5tZXNzYWdlfVxcbmApO1xuXHRcdFx0cHJvY2Vzcy5leGl0KDEpO1xuXHRcdH1cblx0XHRjb25zb2xlLmVycm9yKGVycik7XG5cdFx0cHJvY2Vzcy5leGl0KDEpO1xuXHR9XG5cdHByb2Nlc3MuZXhpdChwcm9jZXNzLmV4aXRDb2RlID8/IDApO1xufVxuIl0sIm5hbWVzIjpbIkNvbW1hbmQiLCJDb21tYW5kZXJFcnJvciIsIkNyZWF0ZUNsaUVycm9yIiwiYWRkV2ViYXBpRmVhdHVyZU9wdGlvbnMiLCJjb2xsZWN0TmFtZSIsInJ1blNjYWZmb2xkQXBpIiwidG9BcGlPcHRpb25zIiwiY3JlYXRlUHJvZ3JhbSIsInByb2dyYW0iLCJleGl0T3ZlcnJpZGUiLCJuYW1lIiwiZGVzY3JpcHRpb24iLCJvcHRpb24iLCJjcmVhdGUiLCJjb21tYW5kIiwiYXJndW1lbnQiLCJhY3Rpb24iLCJkaXJlY3RvcnkiLCJfb3B0cyIsImNtZCIsIm9wdHNXaXRoR2xvYmFscyIsInVuZGVmaW5lZCIsIm5hbWVzIiwiYWRkIiwicnVuQ2xpIiwiYXJndiIsInByb2Nlc3MiLCJwYXJzZUFzeW5jIiwiZXJyIiwiZXhpdCIsImV4aXRDb2RlIiwiY29uc29sZSIsImVycm9yIiwibWVzc2FnZSJdLCJtYXBwaW5ncyI6IkFBQUEsU0FBU0EsT0FBTyxFQUFFQyxjQUFjLFFBQVEsWUFBWTtBQUNwRCxTQUFTQyxjQUFjLFFBQVEsdUJBQXVCO0FBQ3RELFNBQ0NDLHVCQUF1QixFQUN2QkMsV0FBVyxFQUNYQyxjQUFjLEVBQ2RDLFlBQVksUUFDTiwwQkFBMEI7QUFFakMsT0FBTyxTQUFTQztJQUNmLE1BQU1DLFVBQVUsSUFBSVI7SUFDcEJRLFFBQVFDLFlBQVk7SUFDcEJELFFBQ0VFLElBQUksQ0FBQyxZQUNMQyxXQUFXLENBQUMsZ0JBQ1pDLE1BQU0sQ0FBQyxrQkFBa0IsaURBQWlEO0lBRTVFLE1BQU1DLFNBQVNMLFFBQVFNLE9BQU8sQ0FBQyxVQUFVSCxXQUFXLENBQUM7SUFDckRSLHdCQUNDVSxPQUNFQyxPQUFPLENBQUMsVUFDUkMsUUFBUSxDQUFDLGVBQWUsdURBQ3hCSCxNQUFNLENBQ04saUJBQ0EsdURBQ0FSLGFBQ0EsRUFBRSxHQUVIWSxNQUFNLENBQUMsT0FBT0MsV0FBK0JDLE9BQWdCQztRQUM5RCxNQUFNZCxlQUFlQyxhQUFhVyxXQUFXRSxJQUFJQyxlQUFlO0lBQ2pFO0lBRUFqQix3QkFDQ0ssUUFDRU0sT0FBTyxDQUFDLE9BQ1JILFdBQVcsQ0FBQyx5Q0FDWkcsT0FBTyxDQUFDLE9BQ1JDLFFBQVEsQ0FBQyxVQUFVLDZCQUNwQkMsTUFBTSxDQUFDLE9BQU9OLE1BQWNRLE9BQWdCQztRQUM3QyxNQUFNZCxlQUNMQyxhQUFhZSxXQUFXRixJQUFJQyxlQUFlLElBQUk7WUFBRUUsT0FBTztnQkFBQ1o7YUFBSztZQUFFYSxLQUFLO1FBQUs7SUFFNUU7SUFFQSxPQUFPZjtBQUNSO0FBRUEsT0FBTyxlQUFlZ0IsT0FBT0MsT0FBaUJDLFFBQVFELElBQUk7SUFDekQsSUFBSTtRQUNILE1BQU1sQixnQkFBZ0JvQixVQUFVLENBQUNGO0lBQ2xDLEVBQUUsT0FBT0csS0FBSztRQUNiLElBQUlBLGVBQWUzQixnQkFBZ0I7WUFDbEN5QixRQUFRRyxJQUFJLENBQUNELElBQUlFLFFBQVE7UUFDMUI7UUFDQSxJQUFJRixlQUFlMUIsZ0JBQWdCO1lBQ2xDNkIsUUFBUUMsS0FBSyxDQUFDLENBQUMsSUFBSSxFQUFFSixJQUFJSyxPQUFPLENBQUMsRUFBRSxDQUFDO1lBQ3BDUCxRQUFRRyxJQUFJLENBQUM7UUFDZDtRQUNBRSxRQUFRQyxLQUFLLENBQUNKO1FBQ2RGLFFBQVFHLElBQUksQ0FBQztJQUNkO0lBQ0FILFFBQVFHLElBQUksQ0FBQ0gsUUFBUUksUUFBUSxJQUFJO0FBQ2xDIn0=
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Resolve scaffold destination: positional `webapi my-app` wins over `-d`.
3
+ * `npm create … webapi -d my-app` drops `-d` (npm loglevel) and forwards `my-app`.
4
+ */ export function resolveTargetDir(positional, flag) {
5
+ const dir = positional?.trim() || flag?.trim() || ".";
6
+ return dir;
7
+ }
8
+
9
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL3J1bm5lci93b3JrL2RlY29oZXJlL2RlY29oZXJlL3Byb2plY3RzL3NjYWZmb2xkL3NyYy9yZXNvbHZlLXRhcmdldC1kaXIudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBSZXNvbHZlIHNjYWZmb2xkIGRlc3RpbmF0aW9uOiBwb3NpdGlvbmFsIGB3ZWJhcGkgbXktYXBwYCB3aW5zIG92ZXIgYC1kYC5cbiAqIGBucG0gY3JlYXRlIOKApiB3ZWJhcGkgLWQgbXktYXBwYCBkcm9wcyBgLWRgIChucG0gbG9nbGV2ZWwpIGFuZCBmb3J3YXJkcyBgbXktYXBwYC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlc29sdmVUYXJnZXREaXIocG9zaXRpb25hbD86IHN0cmluZywgZmxhZz86IHN0cmluZyk6IHN0cmluZyB7XG5cdGNvbnN0IGRpciA9IHBvc2l0aW9uYWw/LnRyaW0oKSB8fCBmbGFnPy50cmltKCkgfHwgXCIuXCI7XG5cdHJldHVybiBkaXI7XG59XG4iXSwibmFtZXMiOlsicmVzb2x2ZVRhcmdldERpciIsInBvc2l0aW9uYWwiLCJmbGFnIiwiZGlyIiwidHJpbSJdLCJtYXBwaW5ncyI6IkFBQUE7OztDQUdDLEdBQ0QsT0FBTyxTQUFTQSxpQkFBaUJDLFVBQW1CLEVBQUVDLElBQWE7SUFDbEUsTUFBTUMsTUFBTUYsWUFBWUcsVUFBVUYsTUFBTUUsVUFBVTtJQUNsRCxPQUFPRDtBQUNSIn0=
@@ -0,0 +1,52 @@
1
+ async function scaffold(workspace, cliOptions, features) {
2
+ const options = await getAllOptions(workspace, cliOptions, features);
3
+ // Features mutate workspace models first, then workspace renders to disk.
4
+ await scaffoldFeatures(workspace, options, features);
5
+ await scaffoldWorkspace(workspace, options);
6
+ // Post-write phase: install deps, print final messages, etc.
7
+ await finalizeFeatures(workspace, options, features);
8
+ }
9
+ async function scaffoldWorkspace(workspace, _options) {
10
+ await workspace.scaffold();
11
+ }
12
+ /**
13
+ * Iterate features in order, calling `getOptions` on each.
14
+ * Each feature receives the running merged options so later features can
15
+ * branch on decisions made by earlier ones (e.g. database choice affects auth).
16
+ * Results are shallow-merged, so features only need to return what they own.
17
+ */ async function getAllOptions(workspace, cliOptions, features) {
18
+ let options = {
19
+ ...cliOptions
20
+ };
21
+ for (const feature of features){
22
+ const featureOptions = await feature.getOptions(workspace, options);
23
+ options = {
24
+ ...options,
25
+ ...featureOptions
26
+ };
27
+ }
28
+ return options;
29
+ }
30
+ /**
31
+ * Iterate features in order, calling `scaffold` with the fully-resolved options.
32
+ * All option-gathering is complete before any scaffolding begins.
33
+ */ async function scaffoldFeatures(workspace, options, features) {
34
+ for (const feature of features){
35
+ await feature.scaffold(workspace, options);
36
+ }
37
+ }
38
+ /**
39
+ * Iterate features in order, calling `finalize` on each (if defined).
40
+ * All files are on disk by this point.
41
+ */ async function finalizeFeatures(workspace, options, features) {
42
+ for (const feature of features){
43
+ if (feature.finalize) {
44
+ await feature.finalize(workspace, options);
45
+ }
46
+ }
47
+ }
48
+ export const ScaffoldService = {
49
+ scaffold
50
+ };
51
+
52
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL3J1bm5lci93b3JrL2RlY29oZXJlL2RlY29oZXJlL3Byb2plY3RzL3NjYWZmb2xkL3NyYy9zZXJ2aWNlcy9zY2FmZm9sZC5zZXJ2aWNlLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB0eXBlIHsgV29ya3NwYWNlU2NhZmZvbGQgfSBmcm9tIFwiLi4vbW9kZWxzL3Byb2plY3QubW9kZWwuanNcIjtcblxuLyoqXG4gKiBBIGZlYXR1cmUgaGFzIHRocmVlIHJlc3BvbnNpYmlsaXRpZXM6XG4gKiAgMS4gYGdldE9wdGlvbnNgIOKAlCByZXNvbHZlIHByb3ZpZGVyIHNlbGVjdGlvbiBhbmQgYW55IGZvbGxvdy11cCBxdWVzdGlvbnMuXG4gKiAgICAgUmVjZWl2ZXMgdGhlIG9wdGlvbnMgY29sbGVjdGVkIHNvIGZhcjsgcmV0dXJucyBvbmx5IHRoZSBrZXlzIGl0IG93bnMuXG4gKiAgICAgU2hvcnQtY2lyY3VpdHMgaWYgdGhlIGNhbGxlciBhbHJlYWR5IHN1cHBsaWVkIHRob3NlIGtleXMgdmlhIENMSSBmbGFncy5cbiAqICAyLiBgc2NhZmZvbGRgIOKAlCBtdXRhdGUgdGhlIHdvcmtzcGFjZSBtb2RlbHMgYW5kL29yIHdyaXRlIGZpbGVzIHVzaW5nIHRoZVxuICogICAgIGZ1bGx5LXJlc29sdmVkIG9wdGlvbnMuIENhbGxlZCBhZnRlciBBTEwgZmVhdHVyZXMgaGF2ZSBnYXRoZXJlZCBvcHRpb25zXG4gKiAgICAgYnV0IEJFRk9SRSBmaWxlcyBhcmUgd3JpdHRlbiB0byBkaXNrLlxuICogIDMuIGBmaW5hbGl6ZWAgKG9wdGlvbmFsKSDigJQgcnVuIHBvc3Qtd3JpdGUgYWN0aW9ucyAoZS5nLiBpbnN0YWxsIGRlcGVuZGVuY2llcykuXG4gKiAgICAgQ2FsbGVkIGFmdGVyIHdvcmtzcGFjZS5zY2FmZm9sZCgpIGhhcyBmbHVzaGVkIGFsbCBmaWxlcyB0byBkaXNrLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIEZlYXR1cmU8VE9wdGlvbnMgZXh0ZW5kcyBvYmplY3QgPSBvYmplY3Q+IHtcblx0Z2V0T3B0aW9ucyhcblx0XHR3b3Jrc3BhY2U6IFdvcmtzcGFjZVNjYWZmb2xkLFxuXHRcdGNsaU9wdGlvbnM6IFBhcnRpYWw8VE9wdGlvbnM+LFxuXHQpOiBQcm9taXNlPFBhcnRpYWw8VE9wdGlvbnM+Pjtcblx0c2NhZmZvbGQod29ya3NwYWNlOiBXb3Jrc3BhY2VTY2FmZm9sZCwgb3B0aW9uczogVE9wdGlvbnMpOiBQcm9taXNlPHZvaWQ+IHwgdm9pZDtcblx0ZmluYWxpemU/KHdvcmtzcGFjZTogV29ya3NwYWNlU2NhZmZvbGQsIG9wdGlvbnM6IFRPcHRpb25zKTogUHJvbWlzZTx2b2lkPiB8IHZvaWQ7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHNjYWZmb2xkKFxuXHR3b3Jrc3BhY2U6IFdvcmtzcGFjZVNjYWZmb2xkLFxuXHRjbGlPcHRpb25zOiBvYmplY3QsXG5cdGZlYXR1cmVzOiBGZWF0dXJlW10sXG4pIHtcblx0Y29uc3Qgb3B0aW9ucyA9IGF3YWl0IGdldEFsbE9wdGlvbnMod29ya3NwYWNlLCBjbGlPcHRpb25zLCBmZWF0dXJlcyk7XG5cdC8vIEZlYXR1cmVzIG11dGF0ZSB3b3Jrc3BhY2UgbW9kZWxzIGZpcnN0LCB0aGVuIHdvcmtzcGFjZSByZW5kZXJzIHRvIGRpc2suXG5cdGF3YWl0IHNjYWZmb2xkRmVhdHVyZXMod29ya3NwYWNlLCBvcHRpb25zLCBmZWF0dXJlcyk7XG5cdGF3YWl0IHNjYWZmb2xkV29ya3NwYWNlKHdvcmtzcGFjZSwgb3B0aW9ucyk7XG5cdC8vIFBvc3Qtd3JpdGUgcGhhc2U6IGluc3RhbGwgZGVwcywgcHJpbnQgZmluYWwgbWVzc2FnZXMsIGV0Yy5cblx0YXdhaXQgZmluYWxpemVGZWF0dXJlcyh3b3Jrc3BhY2UsIG9wdGlvbnMsIGZlYXR1cmVzKTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gc2NhZmZvbGRXb3Jrc3BhY2Uod29ya3NwYWNlOiBXb3Jrc3BhY2VTY2FmZm9sZCwgX29wdGlvbnM6IG9iamVjdCkge1xuXHRhd2FpdCB3b3Jrc3BhY2Uuc2NhZmZvbGQoKTtcbn1cblxuLyoqXG4gKiBJdGVyYXRlIGZlYXR1cmVzIGluIG9yZGVyLCBjYWxsaW5nIGBnZXRPcHRpb25zYCBvbiBlYWNoLlxuICogRWFjaCBmZWF0dXJlIHJlY2VpdmVzIHRoZSBydW5uaW5nIG1lcmdlZCBvcHRpb25zIHNvIGxhdGVyIGZlYXR1cmVzIGNhblxuICogYnJhbmNoIG9uIGRlY2lzaW9ucyBtYWRlIGJ5IGVhcmxpZXIgb25lcyAoZS5nLiBkYXRhYmFzZSBjaG9pY2UgYWZmZWN0cyBhdXRoKS5cbiAqIFJlc3VsdHMgYXJlIHNoYWxsb3ctbWVyZ2VkLCBzbyBmZWF0dXJlcyBvbmx5IG5lZWQgdG8gcmV0dXJuIHdoYXQgdGhleSBvd24uXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGdldEFsbE9wdGlvbnMoXG5cdHdvcmtzcGFjZTogV29ya3NwYWNlU2NhZmZvbGQsXG5cdGNsaU9wdGlvbnM6IG9iamVjdCxcblx0ZmVhdHVyZXM6IEZlYXR1cmVbXSxcbik6IFByb21pc2U8b2JqZWN0PiB7XG5cdGxldCBvcHRpb25zID0geyAuLi5jbGlPcHRpb25zIH07XG5cdGZvciAoY29uc3QgZmVhdHVyZSBvZiBmZWF0dXJlcykge1xuXHRcdGNvbnN0IGZlYXR1cmVPcHRpb25zID0gYXdhaXQgZmVhdHVyZS5nZXRPcHRpb25zKHdvcmtzcGFjZSwgb3B0aW9ucyk7XG5cdFx0b3B0aW9ucyA9IHsgLi4ub3B0aW9ucywgLi4uZmVhdHVyZU9wdGlvbnMgfTtcblx0fVxuXHRyZXR1cm4gb3B0aW9ucztcbn1cblxuLyoqXG4gKiBJdGVyYXRlIGZlYXR1cmVzIGluIG9yZGVyLCBjYWxsaW5nIGBzY2FmZm9sZGAgd2l0aCB0aGUgZnVsbHktcmVzb2x2ZWQgb3B0aW9ucy5cbiAqIEFsbCBvcHRpb24tZ2F0aGVyaW5nIGlzIGNvbXBsZXRlIGJlZm9yZSBhbnkgc2NhZmZvbGRpbmcgYmVnaW5zLlxuICovXG5hc3luYyBmdW5jdGlvbiBzY2FmZm9sZEZlYXR1cmVzKFxuXHR3b3Jrc3BhY2U6IFdvcmtzcGFjZVNjYWZmb2xkLFxuXHRvcHRpb25zOiBvYmplY3QsXG5cdGZlYXR1cmVzOiBGZWF0dXJlW10sXG4pOiBQcm9taXNlPHZvaWQ+IHtcblx0Zm9yIChjb25zdCBmZWF0dXJlIG9mIGZlYXR1cmVzKSB7XG5cdFx0YXdhaXQgZmVhdHVyZS5zY2FmZm9sZCh3b3Jrc3BhY2UsIG9wdGlvbnMgYXMgbmV2ZXIpO1xuXHR9XG59XG5cbi8qKlxuICogSXRlcmF0ZSBmZWF0dXJlcyBpbiBvcmRlciwgY2FsbGluZyBgZmluYWxpemVgIG9uIGVhY2ggKGlmIGRlZmluZWQpLlxuICogQWxsIGZpbGVzIGFyZSBvbiBkaXNrIGJ5IHRoaXMgcG9pbnQuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGZpbmFsaXplRmVhdHVyZXMoXG5cdHdvcmtzcGFjZTogV29ya3NwYWNlU2NhZmZvbGQsXG5cdG9wdGlvbnM6IG9iamVjdCxcblx0ZmVhdHVyZXM6IEZlYXR1cmVbXSxcbik6IFByb21pc2U8dm9pZD4ge1xuXHRmb3IgKGNvbnN0IGZlYXR1cmUgb2YgZmVhdHVyZXMpIHtcblx0XHRpZiAoZmVhdHVyZS5maW5hbGl6ZSkge1xuXHRcdFx0YXdhaXQgZmVhdHVyZS5maW5hbGl6ZSh3b3Jrc3BhY2UsIG9wdGlvbnMgYXMgbmV2ZXIpO1xuXHRcdH1cblx0fVxufVxuXG5leHBvcnQgY29uc3QgU2NhZmZvbGRTZXJ2aWNlID0geyBzY2FmZm9sZCB9O1xuIl0sIm5hbWVzIjpbInNjYWZmb2xkIiwid29ya3NwYWNlIiwiY2xpT3B0aW9ucyIsImZlYXR1cmVzIiwib3B0aW9ucyIsImdldEFsbE9wdGlvbnMiLCJzY2FmZm9sZEZlYXR1cmVzIiwic2NhZmZvbGRXb3Jrc3BhY2UiLCJmaW5hbGl6ZUZlYXR1cmVzIiwiX29wdGlvbnMiLCJmZWF0dXJlIiwiZmVhdHVyZU9wdGlvbnMiLCJnZXRPcHRpb25zIiwiZmluYWxpemUiLCJTY2FmZm9sZFNlcnZpY2UiXSwibWFwcGluZ3MiOiJBQXNCQSxlQUFlQSxTQUNkQyxTQUE0QixFQUM1QkMsVUFBa0IsRUFDbEJDLFFBQW1CO0lBRW5CLE1BQU1DLFVBQVUsTUFBTUMsY0FBY0osV0FBV0MsWUFBWUM7SUFDM0QsMEVBQTBFO0lBQzFFLE1BQU1HLGlCQUFpQkwsV0FBV0csU0FBU0Q7SUFDM0MsTUFBTUksa0JBQWtCTixXQUFXRztJQUNuQyw2REFBNkQ7SUFDN0QsTUFBTUksaUJBQWlCUCxXQUFXRyxTQUFTRDtBQUM1QztBQUVBLGVBQWVJLGtCQUFrQk4sU0FBNEIsRUFBRVEsUUFBZ0I7SUFDOUUsTUFBTVIsVUFBVUQsUUFBUTtBQUN6QjtBQUVBOzs7OztDQUtDLEdBQ0QsZUFBZUssY0FDZEosU0FBNEIsRUFDNUJDLFVBQWtCLEVBQ2xCQyxRQUFtQjtJQUVuQixJQUFJQyxVQUFVO1FBQUUsR0FBR0YsVUFBVTtJQUFDO0lBQzlCLEtBQUssTUFBTVEsV0FBV1AsU0FBVTtRQUMvQixNQUFNUSxpQkFBaUIsTUFBTUQsUUFBUUUsVUFBVSxDQUFDWCxXQUFXRztRQUMzREEsVUFBVTtZQUFFLEdBQUdBLE9BQU87WUFBRSxHQUFHTyxjQUFjO1FBQUM7SUFDM0M7SUFDQSxPQUFPUDtBQUNSO0FBRUE7OztDQUdDLEdBQ0QsZUFBZUUsaUJBQ2RMLFNBQTRCLEVBQzVCRyxPQUFlLEVBQ2ZELFFBQW1CO0lBRW5CLEtBQUssTUFBTU8sV0FBV1AsU0FBVTtRQUMvQixNQUFNTyxRQUFRVixRQUFRLENBQUNDLFdBQVdHO0lBQ25DO0FBQ0Q7QUFFQTs7O0NBR0MsR0FDRCxlQUFlSSxpQkFDZFAsU0FBNEIsRUFDNUJHLE9BQWUsRUFDZkQsUUFBbUI7SUFFbkIsS0FBSyxNQUFNTyxXQUFXUCxTQUFVO1FBQy9CLElBQUlPLFFBQVFHLFFBQVEsRUFBRTtZQUNyQixNQUFNSCxRQUFRRyxRQUFRLENBQUNaLFdBQVdHO1FBQ25DO0lBQ0Q7QUFDRDtBQUVBLE9BQU8sTUFBTVUsa0JBQWtCO0lBQUVkO0FBQVMsRUFBRSJ9
@@ -0,0 +1,36 @@
1
+ import { createRequire } from "node:module";
2
+ import { dirname, join } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ const _require = createRequire(import.meta.url);
5
+ const DEFAULT_CREATE_VERSION = "0.0.1-dev";
6
+ const DEFAULT_CREATE_IMAGE_REPOSITORY = "ghcr.io/typesmiths/decohere/create";
7
+ const DEFAULT_DEVCONTAINER_IMAGE_REPOSITORY = "ghcr.io/typesmiths/decohere/devcontainer";
8
+ function resolveCreateMetadata() {
9
+ let dir = dirname(fileURLToPath(import.meta.url));
10
+ for(let i = 0; i < 5; i++){
11
+ try {
12
+ const pkg = _require(join(dir, "package.json"));
13
+ if (pkg.name === "@decohere/scaffold") {
14
+ return {
15
+ version: pkg.version ?? DEFAULT_CREATE_VERSION,
16
+ imageRepository: pkg.decohere?.dockerImageRepository ?? DEFAULT_CREATE_IMAGE_REPOSITORY,
17
+ devcontainerImageRepository: pkg.decohere?.devcontainerImageRepository ?? DEFAULT_DEVCONTAINER_IMAGE_REPOSITORY
18
+ };
19
+ }
20
+ } catch {}
21
+ const parent = dirname(dir);
22
+ if (parent === dir) break;
23
+ dir = parent;
24
+ }
25
+ return {
26
+ version: DEFAULT_CREATE_VERSION,
27
+ imageRepository: DEFAULT_CREATE_IMAGE_REPOSITORY,
28
+ devcontainerImageRepository: DEFAULT_DEVCONTAINER_IMAGE_REPOSITORY
29
+ };
30
+ }
31
+ const createMetadata = resolveCreateMetadata();
32
+ /** Version of @decohere/create, used to pin scaffolded @decohere/* dependencies. */ export const CREATE_VERSION = createMetadata.version;
33
+ /** Canonical published Docker repository for the @decohere/create builder image. */ export const CREATE_IMAGE_REPOSITORY = createMetadata.imageRepository;
34
+ /** Published app Dev Container base (`docker pull` updates shared layers). */ export const DEVCONTAINER_IMAGE_REPOSITORY = createMetadata.devcontainerImageRepository;
35
+
36
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL3J1bm5lci93b3JrL2RlY29oZXJlL2RlY29oZXJlL3Byb2plY3RzL3NjYWZmb2xkL3NyYy92ZXJzaW9uLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGNyZWF0ZVJlcXVpcmUgfSBmcm9tIFwibm9kZTptb2R1bGVcIjtcbmltcG9ydCB7IGRpcm5hbWUsIGpvaW4gfSBmcm9tIFwibm9kZTpwYXRoXCI7XG5pbXBvcnQgeyBmaWxlVVJMVG9QYXRoIH0gZnJvbSBcIm5vZGU6dXJsXCI7XG5cbmNvbnN0IF9yZXF1aXJlID0gY3JlYXRlUmVxdWlyZShpbXBvcnQubWV0YS51cmwpO1xuXG50eXBlIENyZWF0ZVBhY2thZ2VNZXRhZGF0YSA9IHtcblx0bmFtZT86IHN0cmluZztcblx0dmVyc2lvbj86IHN0cmluZztcblx0ZGVjb2hlcmU/OiB7XG5cdFx0ZG9ja2VySW1hZ2VSZXBvc2l0b3J5Pzogc3RyaW5nO1xuXHRcdGRldmNvbnRhaW5lckltYWdlUmVwb3NpdG9yeT86IHN0cmluZztcblx0fTtcbn07XG5cbmNvbnN0IERFRkFVTFRfQ1JFQVRFX1ZFUlNJT04gPSBcIjAuMC4xLWRldlwiO1xuY29uc3QgREVGQVVMVF9DUkVBVEVfSU1BR0VfUkVQT1NJVE9SWSA9IFwiZ2hjci5pby90eXBlc21pdGhzL2RlY29oZXJlL2NyZWF0ZVwiO1xuY29uc3QgREVGQVVMVF9ERVZDT05UQUlORVJfSU1BR0VfUkVQT1NJVE9SWSA9IFwiZ2hjci5pby90eXBlc21pdGhzL2RlY29oZXJlL2RldmNvbnRhaW5lclwiO1xuXG5mdW5jdGlvbiByZXNvbHZlQ3JlYXRlTWV0YWRhdGEoKSB7XG5cdGxldCBkaXIgPSBkaXJuYW1lKGZpbGVVUkxUb1BhdGgoaW1wb3J0Lm1ldGEudXJsKSk7XG5cdGZvciAobGV0IGkgPSAwOyBpIDwgNTsgaSsrKSB7XG5cdFx0dHJ5IHtcblx0XHRcdGNvbnN0IHBrZyA9IF9yZXF1aXJlKGpvaW4oZGlyLCBcInBhY2thZ2UuanNvblwiKSkgYXMgQ3JlYXRlUGFja2FnZU1ldGFkYXRhO1xuXHRcdFx0aWYgKHBrZy5uYW1lID09PSBcIkBkZWNvaGVyZS9zY2FmZm9sZFwiKSB7XG5cdFx0XHRcdHJldHVybiB7XG5cdFx0XHRcdFx0dmVyc2lvbjogcGtnLnZlcnNpb24gPz8gREVGQVVMVF9DUkVBVEVfVkVSU0lPTixcblx0XHRcdFx0XHRpbWFnZVJlcG9zaXRvcnk6XG5cdFx0XHRcdFx0XHRwa2cuZGVjb2hlcmU/LmRvY2tlckltYWdlUmVwb3NpdG9yeSA/PyBERUZBVUxUX0NSRUFURV9JTUFHRV9SRVBPU0lUT1JZLFxuXHRcdFx0XHRcdGRldmNvbnRhaW5lckltYWdlUmVwb3NpdG9yeTpcblx0XHRcdFx0XHRcdHBrZy5kZWNvaGVyZT8uZGV2Y29udGFpbmVySW1hZ2VSZXBvc2l0b3J5ID8/IERFRkFVTFRfREVWQ09OVEFJTkVSX0lNQUdFX1JFUE9TSVRPUlksXG5cdFx0XHRcdH07XG5cdFx0XHR9XG5cdFx0fSBjYXRjaCB7fVxuXHRcdGNvbnN0IHBhcmVudCA9IGRpcm5hbWUoZGlyKTtcblx0XHRpZiAocGFyZW50ID09PSBkaXIpIGJyZWFrO1xuXHRcdGRpciA9IHBhcmVudDtcblx0fVxuXG5cdHJldHVybiB7XG5cdFx0dmVyc2lvbjogREVGQVVMVF9DUkVBVEVfVkVSU0lPTixcblx0XHRpbWFnZVJlcG9zaXRvcnk6IERFRkFVTFRfQ1JFQVRFX0lNQUdFX1JFUE9TSVRPUlksXG5cdFx0ZGV2Y29udGFpbmVySW1hZ2VSZXBvc2l0b3J5OiBERUZBVUxUX0RFVkNPTlRBSU5FUl9JTUFHRV9SRVBPU0lUT1JZLFxuXHR9O1xufVxuXG5jb25zdCBjcmVhdGVNZXRhZGF0YSA9IHJlc29sdmVDcmVhdGVNZXRhZGF0YSgpO1xuXG4vKiogVmVyc2lvbiBvZiBAZGVjb2hlcmUvY3JlYXRlLCB1c2VkIHRvIHBpbiBzY2FmZm9sZGVkIEBkZWNvaGVyZS8qIGRlcGVuZGVuY2llcy4gKi9cbmV4cG9ydCBjb25zdCBDUkVBVEVfVkVSU0lPTiA9IGNyZWF0ZU1ldGFkYXRhLnZlcnNpb247XG5cbi8qKiBDYW5vbmljYWwgcHVibGlzaGVkIERvY2tlciByZXBvc2l0b3J5IGZvciB0aGUgQGRlY29oZXJlL2NyZWF0ZSBidWlsZGVyIGltYWdlLiAqL1xuZXhwb3J0IGNvbnN0IENSRUFURV9JTUFHRV9SRVBPU0lUT1JZID0gY3JlYXRlTWV0YWRhdGEuaW1hZ2VSZXBvc2l0b3J5O1xuXG4vKiogUHVibGlzaGVkIGFwcCBEZXYgQ29udGFpbmVyIGJhc2UgKGBkb2NrZXIgcHVsbGAgdXBkYXRlcyBzaGFyZWQgbGF5ZXJzKS4gKi9cbmV4cG9ydCBjb25zdCBERVZDT05UQUlORVJfSU1BR0VfUkVQT1NJVE9SWSA9IGNyZWF0ZU1ldGFkYXRhLmRldmNvbnRhaW5lckltYWdlUmVwb3NpdG9yeTtcbiJdLCJuYW1lcyI6WyJjcmVhdGVSZXF1aXJlIiwiZGlybmFtZSIsImpvaW4iLCJmaWxlVVJMVG9QYXRoIiwiX3JlcXVpcmUiLCJ1cmwiLCJERUZBVUxUX0NSRUFURV9WRVJTSU9OIiwiREVGQVVMVF9DUkVBVEVfSU1BR0VfUkVQT1NJVE9SWSIsIkRFRkFVTFRfREVWQ09OVEFJTkVSX0lNQUdFX1JFUE9TSVRPUlkiLCJyZXNvbHZlQ3JlYXRlTWV0YWRhdGEiLCJkaXIiLCJpIiwicGtnIiwibmFtZSIsInZlcnNpb24iLCJpbWFnZVJlcG9zaXRvcnkiLCJkZWNvaGVyZSIsImRvY2tlckltYWdlUmVwb3NpdG9yeSIsImRldmNvbnRhaW5lckltYWdlUmVwb3NpdG9yeSIsInBhcmVudCIsImNyZWF0ZU1ldGFkYXRhIiwiQ1JFQVRFX1ZFUlNJT04iLCJDUkVBVEVfSU1BR0VfUkVQT1NJVE9SWSIsIkRFVkNPTlRBSU5FUl9JTUFHRV9SRVBPU0lUT1JZIl0sIm1hcHBpbmdzIjoiQUFBQSxTQUFTQSxhQUFhLFFBQVEsY0FBYztBQUM1QyxTQUFTQyxPQUFPLEVBQUVDLElBQUksUUFBUSxZQUFZO0FBQzFDLFNBQVNDLGFBQWEsUUFBUSxXQUFXO0FBRXpDLE1BQU1DLFdBQVdKLGNBQWMsWUFBWUssR0FBRztBQVc5QyxNQUFNQyx5QkFBeUI7QUFDL0IsTUFBTUMsa0NBQWtDO0FBQ3hDLE1BQU1DLHdDQUF3QztBQUU5QyxTQUFTQztJQUNSLElBQUlDLE1BQU1ULFFBQVFFLGNBQWMsWUFBWUUsR0FBRztJQUMvQyxJQUFLLElBQUlNLElBQUksR0FBR0EsSUFBSSxHQUFHQSxJQUFLO1FBQzNCLElBQUk7WUFDSCxNQUFNQyxNQUFNUixTQUFTRixLQUFLUSxLQUFLO1lBQy9CLElBQUlFLElBQUlDLElBQUksS0FBSyxzQkFBc0I7Z0JBQ3RDLE9BQU87b0JBQ05DLFNBQVNGLElBQUlFLE9BQU8sSUFBSVI7b0JBQ3hCUyxpQkFDQ0gsSUFBSUksUUFBUSxFQUFFQyx5QkFBeUJWO29CQUN4Q1csNkJBQ0NOLElBQUlJLFFBQVEsRUFBRUUsK0JBQStCVjtnQkFDL0M7WUFDRDtRQUNELEVBQUUsT0FBTSxDQUFDO1FBQ1QsTUFBTVcsU0FBU2xCLFFBQVFTO1FBQ3ZCLElBQUlTLFdBQVdULEtBQUs7UUFDcEJBLE1BQU1TO0lBQ1A7SUFFQSxPQUFPO1FBQ05MLFNBQVNSO1FBQ1RTLGlCQUFpQlI7UUFDakJXLDZCQUE2QlY7SUFDOUI7QUFDRDtBQUVBLE1BQU1ZLGlCQUFpQlg7QUFFdkIsa0ZBQWtGLEdBQ2xGLE9BQU8sTUFBTVksaUJBQWlCRCxlQUFlTixPQUFPLENBQUM7QUFFckQsa0ZBQWtGLEdBQ2xGLE9BQU8sTUFBTVEsMEJBQTBCRixlQUFlTCxlQUFlLENBQUM7QUFFdEUsNEVBQTRFLEdBQzVFLE9BQU8sTUFBTVEsZ0NBQWdDSCxlQUFlRiwyQkFBMkIsQ0FBQyJ9
@@ -0,0 +1,59 @@
1
+ import { existsSync, readdirSync, readFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { DEFAULT_WEBAPI_NAME } from "./const.js";
4
+ /** Lowercase npm-safe directory slug: `billing`, `admin-api`. */ export const API_NAME_PATTERN = /^[a-z][a-z0-9-]*$/;
5
+ export class CreateCliError extends Error {
6
+ constructor(message){
7
+ super(message);
8
+ this.name = "CreateCliError";
9
+ }
10
+ }
11
+ export function assertValidApiName(name) {
12
+ if (!API_NAME_PATTERN.test(name)) {
13
+ throw new CreateCliError(`Invalid API name "${name}". Use a lowercase slug starting with a letter, then letters, digits, or hyphens (e.g. billing).`);
14
+ }
15
+ }
16
+ /** Default `["api"]` when the caller omitted `--name`. Rejects duplicates and invalid slugs. */ export function parseApiNames(raw) {
17
+ const names = raw != null && raw.length > 0 ? [
18
+ ...raw
19
+ ] : [
20
+ DEFAULT_WEBAPI_NAME
21
+ ];
22
+ const seen = new Set();
23
+ for (const name of names){
24
+ assertValidApiName(name);
25
+ if (seen.has(name)) {
26
+ throw new CreateCliError(`Duplicate API name "${name}".`);
27
+ }
28
+ seen.add(name);
29
+ }
30
+ return names;
31
+ }
32
+ export function isDecohereWorkspace(dir) {
33
+ try {
34
+ const pkg = JSON.parse(readFileSync(join(dir, "package.json"), "utf8"));
35
+ const build = pkg.scripts?.build;
36
+ return typeof build === "string" && build.includes("forge");
37
+ } catch {
38
+ return false;
39
+ }
40
+ }
41
+ /** Directory names under `projects/` that already have a `package.json`. */ export function listExistingApiNames(dir) {
42
+ const projectsDir = join(dir, "projects");
43
+ try {
44
+ return readdirSync(projectsDir, {
45
+ withFileTypes: true
46
+ }).filter((entry)=>entry.isDirectory() && existsSync(join(projectsDir, entry.name, "package.json"))).map((entry)=>entry.name).sort();
47
+ } catch {
48
+ return [];
49
+ }
50
+ }
51
+ /** `billing` → `BILLING`, `admin-api` → `ADMIN_API` — prefix for `{PREFIX}_DB_HOST`. */ export function apiEnvPrefix(apiName) {
52
+ return apiName.replace(/-/g, "_").toUpperCase();
53
+ }
54
+ export function apiNameFromProjectDir(dir) {
55
+ const slash = dir.lastIndexOf("/");
56
+ return slash >= 0 ? dir.slice(slash + 1) : dir;
57
+ }
58
+
59
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL3J1bm5lci93b3JrL2RlY29oZXJlL2RlY29oZXJlL3Byb2plY3RzL3NjYWZmb2xkL3NyYy93ZWJhcGkvYXBpLW5hbWUudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgZXhpc3RzU3luYywgcmVhZGRpclN5bmMsIHJlYWRGaWxlU3luYyB9IGZyb20gXCJub2RlOmZzXCI7XG5pbXBvcnQgeyBqb2luIH0gZnJvbSBcIm5vZGU6cGF0aFwiO1xuaW1wb3J0IHsgREVGQVVMVF9XRUJBUElfTkFNRSB9IGZyb20gXCIuL2NvbnN0LmpzXCI7XG5cbi8qKiBMb3dlcmNhc2UgbnBtLXNhZmUgZGlyZWN0b3J5IHNsdWc6IGBiaWxsaW5nYCwgYGFkbWluLWFwaWAuICovXG5leHBvcnQgY29uc3QgQVBJX05BTUVfUEFUVEVSTiA9IC9eW2Etel1bYS16MC05LV0qJC87XG5cbmV4cG9ydCBjbGFzcyBDcmVhdGVDbGlFcnJvciBleHRlbmRzIEVycm9yIHtcblx0cHVibGljIGNvbnN0cnVjdG9yKG1lc3NhZ2U6IHN0cmluZykge1xuXHRcdHN1cGVyKG1lc3NhZ2UpO1xuXHRcdHRoaXMubmFtZSA9IFwiQ3JlYXRlQ2xpRXJyb3JcIjtcblx0fVxufVxuXG5leHBvcnQgZnVuY3Rpb24gYXNzZXJ0VmFsaWRBcGlOYW1lKG5hbWU6IHN0cmluZyk6IHZvaWQge1xuXHRpZiAoIUFQSV9OQU1FX1BBVFRFUk4udGVzdChuYW1lKSkge1xuXHRcdHRocm93IG5ldyBDcmVhdGVDbGlFcnJvcihcblx0XHRcdGBJbnZhbGlkIEFQSSBuYW1lIFwiJHtuYW1lfVwiLiBVc2UgYSBsb3dlcmNhc2Ugc2x1ZyBzdGFydGluZyB3aXRoIGEgbGV0dGVyLCB0aGVuIGxldHRlcnMsIGRpZ2l0cywgb3IgaHlwaGVucyAoZS5nLiBiaWxsaW5nKS5gLFxuXHRcdCk7XG5cdH1cbn1cblxuLyoqIERlZmF1bHQgYFtcImFwaVwiXWAgd2hlbiB0aGUgY2FsbGVyIG9taXR0ZWQgYC0tbmFtZWAuIFJlamVjdHMgZHVwbGljYXRlcyBhbmQgaW52YWxpZCBzbHVncy4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwYXJzZUFwaU5hbWVzKHJhdzogcmVhZG9ubHkgc3RyaW5nW10gfCB1bmRlZmluZWQpOiBzdHJpbmdbXSB7XG5cdGNvbnN0IG5hbWVzID0gcmF3ICE9IG51bGwgJiYgcmF3Lmxlbmd0aCA+IDAgPyBbLi4ucmF3XSA6IFtERUZBVUxUX1dFQkFQSV9OQU1FXTtcblx0Y29uc3Qgc2VlbiA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuXHRmb3IgKGNvbnN0IG5hbWUgb2YgbmFtZXMpIHtcblx0XHRhc3NlcnRWYWxpZEFwaU5hbWUobmFtZSk7XG5cdFx0aWYgKHNlZW4uaGFzKG5hbWUpKSB7XG5cdFx0XHR0aHJvdyBuZXcgQ3JlYXRlQ2xpRXJyb3IoYER1cGxpY2F0ZSBBUEkgbmFtZSBcIiR7bmFtZX1cIi5gKTtcblx0XHR9XG5cdFx0c2Vlbi5hZGQobmFtZSk7XG5cdH1cblx0cmV0dXJuIG5hbWVzO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaXNEZWNvaGVyZVdvcmtzcGFjZShkaXI6IHN0cmluZyk6IGJvb2xlYW4ge1xuXHR0cnkge1xuXHRcdGNvbnN0IHBrZyA9IEpTT04ucGFyc2UocmVhZEZpbGVTeW5jKGpvaW4oZGlyLCBcInBhY2thZ2UuanNvblwiKSwgXCJ1dGY4XCIpKSBhcyB7XG5cdFx0XHRzY3JpcHRzPzogUmVjb3JkPHN0cmluZywgc3RyaW5nPjtcblx0XHR9O1xuXHRcdGNvbnN0IGJ1aWxkID0gcGtnLnNjcmlwdHM/LmJ1aWxkO1xuXHRcdHJldHVybiB0eXBlb2YgYnVpbGQgPT09IFwic3RyaW5nXCIgJiYgYnVpbGQuaW5jbHVkZXMoXCJmb3JnZVwiKTtcblx0fSBjYXRjaCB7XG5cdFx0cmV0dXJuIGZhbHNlO1xuXHR9XG59XG5cbi8qKiBEaXJlY3RvcnkgbmFtZXMgdW5kZXIgYHByb2plY3RzL2AgdGhhdCBhbHJlYWR5IGhhdmUgYSBgcGFja2FnZS5qc29uYC4gKi9cbmV4cG9ydCBmdW5jdGlvbiBsaXN0RXhpc3RpbmdBcGlOYW1lcyhkaXI6IHN0cmluZyk6IHN0cmluZ1tdIHtcblx0Y29uc3QgcHJvamVjdHNEaXIgPSBqb2luKGRpciwgXCJwcm9qZWN0c1wiKTtcblx0dHJ5IHtcblx0XHRyZXR1cm4gcmVhZGRpclN5bmMocHJvamVjdHNEaXIsIHsgd2l0aEZpbGVUeXBlczogdHJ1ZSB9KVxuXHRcdFx0LmZpbHRlcihcblx0XHRcdFx0KGVudHJ5KSA9PlxuXHRcdFx0XHRcdGVudHJ5LmlzRGlyZWN0b3J5KCkgJiYgZXhpc3RzU3luYyhqb2luKHByb2plY3RzRGlyLCBlbnRyeS5uYW1lLCBcInBhY2thZ2UuanNvblwiKSksXG5cdFx0XHQpXG5cdFx0XHQubWFwKChlbnRyeSkgPT4gZW50cnkubmFtZSlcblx0XHRcdC5zb3J0KCk7XG5cdH0gY2F0Y2gge1xuXHRcdHJldHVybiBbXTtcblx0fVxufVxuXG4vKiogYGJpbGxpbmdgIOKGkiBgQklMTElOR2AsIGBhZG1pbi1hcGlgIOKGkiBgQURNSU5fQVBJYCDigJQgcHJlZml4IGZvciBge1BSRUZJWH1fREJfSE9TVGAuICovXG5leHBvcnQgZnVuY3Rpb24gYXBpRW52UHJlZml4KGFwaU5hbWU6IHN0cmluZyk6IHN0cmluZyB7XG5cdHJldHVybiBhcGlOYW1lLnJlcGxhY2UoLy0vZywgXCJfXCIpLnRvVXBwZXJDYXNlKCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBhcGlOYW1lRnJvbVByb2plY3REaXIoZGlyOiBzdHJpbmcpOiBzdHJpbmcge1xuXHRjb25zdCBzbGFzaCA9IGRpci5sYXN0SW5kZXhPZihcIi9cIik7XG5cdHJldHVybiBzbGFzaCA+PSAwID8gZGlyLnNsaWNlKHNsYXNoICsgMSkgOiBkaXI7XG59XG4iXSwibmFtZXMiOlsiZXhpc3RzU3luYyIsInJlYWRkaXJTeW5jIiwicmVhZEZpbGVTeW5jIiwiam9pbiIsIkRFRkFVTFRfV0VCQVBJX05BTUUiLCJBUElfTkFNRV9QQVRURVJOIiwiQ3JlYXRlQ2xpRXJyb3IiLCJFcnJvciIsIm1lc3NhZ2UiLCJuYW1lIiwiYXNzZXJ0VmFsaWRBcGlOYW1lIiwidGVzdCIsInBhcnNlQXBpTmFtZXMiLCJyYXciLCJuYW1lcyIsImxlbmd0aCIsInNlZW4iLCJTZXQiLCJoYXMiLCJhZGQiLCJpc0RlY29oZXJlV29ya3NwYWNlIiwiZGlyIiwicGtnIiwiSlNPTiIsInBhcnNlIiwiYnVpbGQiLCJzY3JpcHRzIiwiaW5jbHVkZXMiLCJsaXN0RXhpc3RpbmdBcGlOYW1lcyIsInByb2plY3RzRGlyIiwid2l0aEZpbGVUeXBlcyIsImZpbHRlciIsImVudHJ5IiwiaXNEaXJlY3RvcnkiLCJtYXAiLCJzb3J0IiwiYXBpRW52UHJlZml4IiwiYXBpTmFtZSIsInJlcGxhY2UiLCJ0b1VwcGVyQ2FzZSIsImFwaU5hbWVGcm9tUHJvamVjdERpciIsInNsYXNoIiwibGFzdEluZGV4T2YiLCJzbGljZSJdLCJtYXBwaW5ncyI6IkFBQUEsU0FBU0EsVUFBVSxFQUFFQyxXQUFXLEVBQUVDLFlBQVksUUFBUSxVQUFVO0FBQ2hFLFNBQVNDLElBQUksUUFBUSxZQUFZO0FBQ2pDLFNBQVNDLG1CQUFtQixRQUFRLGFBQWE7QUFFakQsK0RBQStELEdBQy9ELE9BQU8sTUFBTUMsbUJBQW1CLG9CQUFvQjtBQUVwRCxPQUFPLE1BQU1DLHVCQUF1QkM7SUFDbkMsWUFBbUJDLE9BQWUsQ0FBRTtRQUNuQyxLQUFLLENBQUNBO1FBQ04sSUFBSSxDQUFDQyxJQUFJLEdBQUc7SUFDYjtBQUNEO0FBRUEsT0FBTyxTQUFTQyxtQkFBbUJELElBQVk7SUFDOUMsSUFBSSxDQUFDSixpQkFBaUJNLElBQUksQ0FBQ0YsT0FBTztRQUNqQyxNQUFNLElBQUlILGVBQ1QsQ0FBQyxrQkFBa0IsRUFBRUcsS0FBSyxnR0FBZ0csQ0FBQztJQUU3SDtBQUNEO0FBRUEsOEZBQThGLEdBQzlGLE9BQU8sU0FBU0csY0FBY0MsR0FBa0M7SUFDL0QsTUFBTUMsUUFBUUQsT0FBTyxRQUFRQSxJQUFJRSxNQUFNLEdBQUcsSUFBSTtXQUFJRjtLQUFJLEdBQUc7UUFBQ1Q7S0FBb0I7SUFDOUUsTUFBTVksT0FBTyxJQUFJQztJQUNqQixLQUFLLE1BQU1SLFFBQVFLLE1BQU87UUFDekJKLG1CQUFtQkQ7UUFDbkIsSUFBSU8sS0FBS0UsR0FBRyxDQUFDVCxPQUFPO1lBQ25CLE1BQU0sSUFBSUgsZUFBZSxDQUFDLG9CQUFvQixFQUFFRyxLQUFLLEVBQUUsQ0FBQztRQUN6RDtRQUNBTyxLQUFLRyxHQUFHLENBQUNWO0lBQ1Y7SUFDQSxPQUFPSztBQUNSO0FBRUEsT0FBTyxTQUFTTSxvQkFBb0JDLEdBQVc7SUFDOUMsSUFBSTtRQUNILE1BQU1DLE1BQU1DLEtBQUtDLEtBQUssQ0FBQ3RCLGFBQWFDLEtBQUtrQixLQUFLLGlCQUFpQjtRQUcvRCxNQUFNSSxRQUFRSCxJQUFJSSxPQUFPLEVBQUVEO1FBQzNCLE9BQU8sT0FBT0EsVUFBVSxZQUFZQSxNQUFNRSxRQUFRLENBQUM7SUFDcEQsRUFBRSxPQUFNO1FBQ1AsT0FBTztJQUNSO0FBQ0Q7QUFFQSwwRUFBMEUsR0FDMUUsT0FBTyxTQUFTQyxxQkFBcUJQLEdBQVc7SUFDL0MsTUFBTVEsY0FBYzFCLEtBQUtrQixLQUFLO0lBQzlCLElBQUk7UUFDSCxPQUFPcEIsWUFBWTRCLGFBQWE7WUFBRUMsZUFBZTtRQUFLLEdBQ3BEQyxNQUFNLENBQ04sQ0FBQ0MsUUFDQUEsTUFBTUMsV0FBVyxNQUFNakMsV0FBV0csS0FBSzBCLGFBQWFHLE1BQU12QixJQUFJLEVBQUUsa0JBRWpFeUIsR0FBRyxDQUFDLENBQUNGLFFBQVVBLE1BQU12QixJQUFJLEVBQ3pCMEIsSUFBSTtJQUNQLEVBQUUsT0FBTTtRQUNQLE9BQU8sRUFBRTtJQUNWO0FBQ0Q7QUFFQSxzRkFBc0YsR0FDdEYsT0FBTyxTQUFTQyxhQUFhQyxPQUFlO0lBQzNDLE9BQU9BLFFBQVFDLE9BQU8sQ0FBQyxNQUFNLEtBQUtDLFdBQVc7QUFDOUM7QUFFQSxPQUFPLFNBQVNDLHNCQUFzQm5CLEdBQVc7SUFDaEQsTUFBTW9CLFFBQVFwQixJQUFJcUIsV0FBVyxDQUFDO0lBQzlCLE9BQU9ELFNBQVMsSUFBSXBCLElBQUlzQixLQUFLLENBQUNGLFFBQVEsS0FBS3BCO0FBQzVDIn0=