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

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,186 @@
1
+ import { WELL_KNOWN_FILES } from "../../models/const.js";
2
+ /**
3
+ * Minimal GitHub Actions for scaffolded apps: lint ∥ test, build gate on default branch,
4
+ * npm publish after CI (skips private packages). No default forge docker --push.
5
+ */ export class GithubCiWorkflows {
6
+ key = WELL_KNOWN_FILES.GITHUB_CI;
7
+ files() {
8
+ return [
9
+ {
10
+ filePath: ".github/actions/setup-node-pnpm/action.yml",
11
+ content: `name: Setup Node + pnpm
12
+ description: Install pnpm and Node, configure npm registry auth, install deps
13
+ inputs:
14
+ node-version:
15
+ description: Node.js version
16
+ required: false
17
+ default: "24"
18
+ pnpm-version:
19
+ description: pnpm version
20
+ required: false
21
+ default: "10"
22
+ install:
23
+ description: Run pnpm install --frozen-lockfile
24
+ required: false
25
+ default: "true"
26
+
27
+ runs:
28
+ using: composite
29
+ steps:
30
+ - uses: pnpm/action-setup@v4
31
+ with:
32
+ version: \${{ inputs.pnpm-version }}
33
+
34
+ - uses: actions/setup-node@v4
35
+ with:
36
+ node-version: \${{ inputs.node-version }}
37
+ cache: pnpm
38
+ cache-dependency-path: pnpm-lock.yaml
39
+
40
+ - name: Configure npm auth
41
+ shell: bash
42
+ run: |
43
+ if [[ -n "\${NODE_AUTH_TOKEN:-}" ]]; then
44
+ echo "//registry.npmjs.org/:_authToken=\${NODE_AUTH_TOKEN}" >> .npmrc
45
+ fi
46
+
47
+ - name: Install dependencies
48
+ if: inputs.install == 'true'
49
+ shell: bash
50
+ run: |
51
+ if [[ -f pnpm-lock.yaml ]]; then
52
+ pnpm install --frozen-lockfile
53
+ else
54
+ pnpm install
55
+ fi
56
+ `
57
+ },
58
+ {
59
+ filePath: ".github/workflows/ci.yml",
60
+ content: `name: CI
61
+ on:
62
+ push:
63
+ branches:
64
+ - "*"
65
+ pull_request:
66
+ workflow_dispatch:
67
+ concurrency:
68
+ group: ci-\${{ github.ref }}
69
+ cancel-in-progress: true
70
+ env:
71
+ NODE_AUTH_TOKEN: \${{ secrets.NODE_AUTH_TOKEN }}
72
+ SCRIBE_LOG_LEVEL: info
73
+
74
+ jobs:
75
+ lint:
76
+ runs-on: ubuntu-latest
77
+ timeout-minutes: 15
78
+ permissions:
79
+ contents: read
80
+ steps:
81
+ - uses: actions/checkout@v4
82
+ with:
83
+ fetch-depth: 1
84
+
85
+ - uses: ./.github/actions/setup-node-pnpm
86
+
87
+ - name: Lint and typecheck
88
+ run: |
89
+ set +e
90
+ pnpm run lint:check &
91
+ lint_pid=$!
92
+ pnpm run typecheck &
93
+ tsc_pid=$!
94
+ wait "$lint_pid"
95
+ lint_code=$?
96
+ wait "$tsc_pid"
97
+ tsc_code=$?
98
+ set -e
99
+ if [[ "$lint_code" -ne 0 || "$tsc_code" -ne 0 ]]; then
100
+ exit 1
101
+ fi
102
+
103
+ test:
104
+ runs-on: ubuntu-latest
105
+ timeout-minutes: 20
106
+ permissions:
107
+ contents: read
108
+ steps:
109
+ - uses: actions/checkout@v4
110
+ with:
111
+ fetch-depth: 1
112
+
113
+ - uses: ./.github/actions/setup-node-pnpm
114
+
115
+ - name: Test
116
+ run: pnpm test
117
+
118
+ - name: Build (default branch)
119
+ if: github.ref == format('refs/heads/{0}', github.event.repository.default_branch)
120
+ run: pnpm run build
121
+
122
+ ci:
123
+ needs: [lint, test]
124
+ if: always()
125
+ runs-on: ubuntu-latest
126
+ timeout-minutes: 5
127
+ steps:
128
+ - name: Aggregate
129
+ run: |
130
+ if [[ "\${{ needs.lint.result }}" != "success" || "\${{ needs.test.result }}" != "success" ]]; then
131
+ echo "CI failed (lint=\${{ needs.lint.result }} test=\${{ needs.test.result }})"
132
+ exit 1
133
+ fi
134
+ echo "CI passed"
135
+ `
136
+ },
137
+ {
138
+ filePath: ".github/workflows/publish.yml",
139
+ content: `name: Publish
140
+
141
+ on:
142
+ workflow_run:
143
+ workflows: ["CI"]
144
+ types: [completed]
145
+
146
+ concurrency:
147
+ group: publish-\${{ github.event.workflow_run.head_branch }}
148
+ cancel-in-progress: false
149
+
150
+ env:
151
+ NODE_AUTH_TOKEN: \${{ secrets.NODE_AUTH_TOKEN }}
152
+ SCRIBE_LOG_LEVEL: info
153
+
154
+ jobs:
155
+ publish:
156
+ if: >
157
+ github.event.workflow_run.conclusion == 'success' &&
158
+ github.event.workflow_run.head_branch == github.event.repository.default_branch
159
+ runs-on: ubuntu-latest
160
+ timeout-minutes: 30
161
+ permissions:
162
+ contents: read
163
+ id-token: write
164
+ steps:
165
+ - uses: actions/checkout@v4
166
+ with:
167
+ ref: \${{ github.event.workflow_run.head_sha }}
168
+ fetch-depth: 1
169
+
170
+ - uses: ./.github/actions/setup-node-pnpm
171
+
172
+ - name: Build release
173
+ run: pnpm run build
174
+
175
+ - name: Publish packages
176
+ run: pnpm exec forge publish --configuration release
177
+ # Skips packages with "private": true (e.g. the webapi app).
178
+ # Optional registry images: add \`pnpm exec forge docker --configuration release --push\`
179
+ # after configuring GHCR/OIDC — not enabled by default (PaaS builds the Dockerfile).
180
+ `
181
+ }
182
+ ];
183
+ }
184
+ }
185
+
186
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL3J1bm5lci93b3JrL2RlY29oZXJlL2RlY29oZXJlL3Byb2plY3RzL3NjYWZmb2xkL3NyYy93ZWJhcGkvbW9kZWxzL2dpdGh1Yi1jaS5tb2RlbC50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBXRUxMX0tOT1dOX0ZJTEVTIH0gZnJvbSBcIi4uLy4uL21vZGVscy9jb25zdC5qc1wiO1xuaW1wb3J0IHR5cGUgeyBLZXllZE1vZGVsLCBTb3VyY2VGaWxlIH0gZnJvbSBcIi4uLy4uL21vZGVscy9zb3VyY2UtZmlsZS5qc1wiO1xuXG4vKipcbiAqIE1pbmltYWwgR2l0SHViIEFjdGlvbnMgZm9yIHNjYWZmb2xkZWQgYXBwczogbGludCDiiKUgdGVzdCwgYnVpbGQgZ2F0ZSBvbiBkZWZhdWx0IGJyYW5jaCxcbiAqIG5wbSBwdWJsaXNoIGFmdGVyIENJIChza2lwcyBwcml2YXRlIHBhY2thZ2VzKS4gTm8gZGVmYXVsdCBmb3JnZSBkb2NrZXIgLS1wdXNoLlxuICovXG5leHBvcnQgY2xhc3MgR2l0aHViQ2lXb3JrZmxvd3MgaW1wbGVtZW50cyBLZXllZE1vZGVsIHtcblx0cHVibGljIHJlYWRvbmx5IGtleSA9IFdFTExfS05PV05fRklMRVMuR0lUSFVCX0NJO1xuXG5cdHB1YmxpYyBmaWxlcygpOiBTb3VyY2VGaWxlW10ge1xuXHRcdHJldHVybiBbXG5cdFx0XHR7XG5cdFx0XHRcdGZpbGVQYXRoOiBcIi5naXRodWIvYWN0aW9ucy9zZXR1cC1ub2RlLXBucG0vYWN0aW9uLnltbFwiLFxuXHRcdFx0XHRjb250ZW50OiBgbmFtZTogU2V0dXAgTm9kZSArIHBucG1cbmRlc2NyaXB0aW9uOiBJbnN0YWxsIHBucG0gYW5kIE5vZGUsIGNvbmZpZ3VyZSBucG0gcmVnaXN0cnkgYXV0aCwgaW5zdGFsbCBkZXBzXG5pbnB1dHM6XG4gIG5vZGUtdmVyc2lvbjpcbiAgICBkZXNjcmlwdGlvbjogTm9kZS5qcyB2ZXJzaW9uXG4gICAgcmVxdWlyZWQ6IGZhbHNlXG4gICAgZGVmYXVsdDogXCIyNFwiXG4gIHBucG0tdmVyc2lvbjpcbiAgICBkZXNjcmlwdGlvbjogcG5wbSB2ZXJzaW9uXG4gICAgcmVxdWlyZWQ6IGZhbHNlXG4gICAgZGVmYXVsdDogXCIxMFwiXG4gIGluc3RhbGw6XG4gICAgZGVzY3JpcHRpb246IFJ1biBwbnBtIGluc3RhbGwgLS1mcm96ZW4tbG9ja2ZpbGVcbiAgICByZXF1aXJlZDogZmFsc2VcbiAgICBkZWZhdWx0OiBcInRydWVcIlxuXG5ydW5zOlxuICB1c2luZzogY29tcG9zaXRlXG4gIHN0ZXBzOlxuICAgIC0gdXNlczogcG5wbS9hY3Rpb24tc2V0dXBAdjRcbiAgICAgIHdpdGg6XG4gICAgICAgIHZlcnNpb246IFxcJHt7IGlucHV0cy5wbnBtLXZlcnNpb24gfX1cblxuICAgIC0gdXNlczogYWN0aW9ucy9zZXR1cC1ub2RlQHY0XG4gICAgICB3aXRoOlxuICAgICAgICBub2RlLXZlcnNpb246IFxcJHt7IGlucHV0cy5ub2RlLXZlcnNpb24gfX1cbiAgICAgICAgY2FjaGU6IHBucG1cbiAgICAgICAgY2FjaGUtZGVwZW5kZW5jeS1wYXRoOiBwbnBtLWxvY2sueWFtbFxuXG4gICAgLSBuYW1lOiBDb25maWd1cmUgbnBtIGF1dGhcbiAgICAgIHNoZWxsOiBiYXNoXG4gICAgICBydW46IHxcbiAgICAgICAgaWYgW1sgLW4gXCJcXCR7Tk9ERV9BVVRIX1RPS0VOOi19XCIgXV07IHRoZW5cbiAgICAgICAgICBlY2hvIFwiLy9yZWdpc3RyeS5ucG1qcy5vcmcvOl9hdXRoVG9rZW49XFwke05PREVfQVVUSF9UT0tFTn1cIiA+PiAubnBtcmNcbiAgICAgICAgZmlcblxuICAgIC0gbmFtZTogSW5zdGFsbCBkZXBlbmRlbmNpZXNcbiAgICAgIGlmOiBpbnB1dHMuaW5zdGFsbCA9PSAndHJ1ZSdcbiAgICAgIHNoZWxsOiBiYXNoXG4gICAgICBydW46IHxcbiAgICAgICAgaWYgW1sgLWYgcG5wbS1sb2NrLnlhbWwgXV07IHRoZW5cbiAgICAgICAgICBwbnBtIGluc3RhbGwgLS1mcm96ZW4tbG9ja2ZpbGVcbiAgICAgICAgZWxzZVxuICAgICAgICAgIHBucG0gaW5zdGFsbFxuICAgICAgICBmaVxuYCxcblx0XHRcdH0sXG5cdFx0XHR7XG5cdFx0XHRcdGZpbGVQYXRoOiBcIi5naXRodWIvd29ya2Zsb3dzL2NpLnltbFwiLFxuXHRcdFx0XHRjb250ZW50OiBgbmFtZTogQ0lcbm9uOlxuICBwdXNoOlxuICAgIGJyYW5jaGVzOlxuICAgICAgLSBcIipcIlxuICBwdWxsX3JlcXVlc3Q6XG4gIHdvcmtmbG93X2Rpc3BhdGNoOlxuY29uY3VycmVuY3k6XG4gIGdyb3VwOiBjaS1cXCR7eyBnaXRodWIucmVmIH19XG4gIGNhbmNlbC1pbi1wcm9ncmVzczogdHJ1ZVxuZW52OlxuICBOT0RFX0FVVEhfVE9LRU46IFxcJHt7IHNlY3JldHMuTk9ERV9BVVRIX1RPS0VOIH19XG4gIFNDUklCRV9MT0dfTEVWRUw6IGluZm9cblxuam9iczpcbiAgbGludDpcbiAgICBydW5zLW9uOiB1YnVudHUtbGF0ZXN0XG4gICAgdGltZW91dC1taW51dGVzOiAxNVxuICAgIHBlcm1pc3Npb25zOlxuICAgICAgY29udGVudHM6IHJlYWRcbiAgICBzdGVwczpcbiAgICAgIC0gdXNlczogYWN0aW9ucy9jaGVja291dEB2NFxuICAgICAgICB3aXRoOlxuICAgICAgICAgIGZldGNoLWRlcHRoOiAxXG5cbiAgICAgIC0gdXNlczogLi8uZ2l0aHViL2FjdGlvbnMvc2V0dXAtbm9kZS1wbnBtXG5cbiAgICAgIC0gbmFtZTogTGludCBhbmQgdHlwZWNoZWNrXG4gICAgICAgIHJ1bjogfFxuICAgICAgICAgIHNldCArZVxuICAgICAgICAgIHBucG0gcnVuIGxpbnQ6Y2hlY2sgJlxuICAgICAgICAgIGxpbnRfcGlkPSQhXG4gICAgICAgICAgcG5wbSBydW4gdHlwZWNoZWNrICZcbiAgICAgICAgICB0c2NfcGlkPSQhXG4gICAgICAgICAgd2FpdCBcIiRsaW50X3BpZFwiXG4gICAgICAgICAgbGludF9jb2RlPSQ/XG4gICAgICAgICAgd2FpdCBcIiR0c2NfcGlkXCJcbiAgICAgICAgICB0c2NfY29kZT0kP1xuICAgICAgICAgIHNldCAtZVxuICAgICAgICAgIGlmIFtbIFwiJGxpbnRfY29kZVwiIC1uZSAwIHx8IFwiJHRzY19jb2RlXCIgLW5lIDAgXV07IHRoZW5cbiAgICAgICAgICAgIGV4aXQgMVxuICAgICAgICAgIGZpXG5cbiAgdGVzdDpcbiAgICBydW5zLW9uOiB1YnVudHUtbGF0ZXN0XG4gICAgdGltZW91dC1taW51dGVzOiAyMFxuICAgIHBlcm1pc3Npb25zOlxuICAgICAgY29udGVudHM6IHJlYWRcbiAgICBzdGVwczpcbiAgICAgIC0gdXNlczogYWN0aW9ucy9jaGVja291dEB2NFxuICAgICAgICB3aXRoOlxuICAgICAgICAgIGZldGNoLWRlcHRoOiAxXG5cbiAgICAgIC0gdXNlczogLi8uZ2l0aHViL2FjdGlvbnMvc2V0dXAtbm9kZS1wbnBtXG5cbiAgICAgIC0gbmFtZTogVGVzdFxuICAgICAgICBydW46IHBucG0gdGVzdFxuXG4gICAgICAtIG5hbWU6IEJ1aWxkIChkZWZhdWx0IGJyYW5jaClcbiAgICAgICAgaWY6IGdpdGh1Yi5yZWYgPT0gZm9ybWF0KCdyZWZzL2hlYWRzL3swfScsIGdpdGh1Yi5ldmVudC5yZXBvc2l0b3J5LmRlZmF1bHRfYnJhbmNoKVxuICAgICAgICBydW46IHBucG0gcnVuIGJ1aWxkXG5cbiAgY2k6XG4gICAgbmVlZHM6IFtsaW50LCB0ZXN0XVxuICAgIGlmOiBhbHdheXMoKVxuICAgIHJ1bnMtb246IHVidW50dS1sYXRlc3RcbiAgICB0aW1lb3V0LW1pbnV0ZXM6IDVcbiAgICBzdGVwczpcbiAgICAgIC0gbmFtZTogQWdncmVnYXRlXG4gICAgICAgIHJ1bjogfFxuICAgICAgICAgIGlmIFtbIFwiXFwke3sgbmVlZHMubGludC5yZXN1bHQgfX1cIiAhPSBcInN1Y2Nlc3NcIiB8fCBcIlxcJHt7IG5lZWRzLnRlc3QucmVzdWx0IH19XCIgIT0gXCJzdWNjZXNzXCIgXV07IHRoZW5cbiAgICAgICAgICAgIGVjaG8gXCJDSSBmYWlsZWQgKGxpbnQ9XFwke3sgbmVlZHMubGludC5yZXN1bHQgfX0gdGVzdD1cXCR7eyBuZWVkcy50ZXN0LnJlc3VsdCB9fSlcIlxuICAgICAgICAgICAgZXhpdCAxXG4gICAgICAgICAgZmlcbiAgICAgICAgICBlY2hvIFwiQ0kgcGFzc2VkXCJcbmAsXG5cdFx0XHR9LFxuXHRcdFx0e1xuXHRcdFx0XHRmaWxlUGF0aDogXCIuZ2l0aHViL3dvcmtmbG93cy9wdWJsaXNoLnltbFwiLFxuXHRcdFx0XHRjb250ZW50OiBgbmFtZTogUHVibGlzaFxuXG5vbjpcbiAgd29ya2Zsb3dfcnVuOlxuICAgIHdvcmtmbG93czogW1wiQ0lcIl1cbiAgICB0eXBlczogW2NvbXBsZXRlZF1cblxuY29uY3VycmVuY3k6XG4gIGdyb3VwOiBwdWJsaXNoLVxcJHt7IGdpdGh1Yi5ldmVudC53b3JrZmxvd19ydW4uaGVhZF9icmFuY2ggfX1cbiAgY2FuY2VsLWluLXByb2dyZXNzOiBmYWxzZVxuXG5lbnY6XG4gIE5PREVfQVVUSF9UT0tFTjogXFwke3sgc2VjcmV0cy5OT0RFX0FVVEhfVE9LRU4gfX1cbiAgU0NSSUJFX0xPR19MRVZFTDogaW5mb1xuXG5qb2JzOlxuICBwdWJsaXNoOlxuICAgIGlmOiA+XG4gICAgICBnaXRodWIuZXZlbnQud29ya2Zsb3dfcnVuLmNvbmNsdXNpb24gPT0gJ3N1Y2Nlc3MnICYmXG4gICAgICBnaXRodWIuZXZlbnQud29ya2Zsb3dfcnVuLmhlYWRfYnJhbmNoID09IGdpdGh1Yi5ldmVudC5yZXBvc2l0b3J5LmRlZmF1bHRfYnJhbmNoXG4gICAgcnVucy1vbjogdWJ1bnR1LWxhdGVzdFxuICAgIHRpbWVvdXQtbWludXRlczogMzBcbiAgICBwZXJtaXNzaW9uczpcbiAgICAgIGNvbnRlbnRzOiByZWFkXG4gICAgICBpZC10b2tlbjogd3JpdGVcbiAgICBzdGVwczpcbiAgICAgIC0gdXNlczogYWN0aW9ucy9jaGVja291dEB2NFxuICAgICAgICB3aXRoOlxuICAgICAgICAgIHJlZjogXFwke3sgZ2l0aHViLmV2ZW50LndvcmtmbG93X3J1bi5oZWFkX3NoYSB9fVxuICAgICAgICAgIGZldGNoLWRlcHRoOiAxXG5cbiAgICAgIC0gdXNlczogLi8uZ2l0aHViL2FjdGlvbnMvc2V0dXAtbm9kZS1wbnBtXG5cbiAgICAgIC0gbmFtZTogQnVpbGQgcmVsZWFzZVxuICAgICAgICBydW46IHBucG0gcnVuIGJ1aWxkXG5cbiAgICAgIC0gbmFtZTogUHVibGlzaCBwYWNrYWdlc1xuICAgICAgICBydW46IHBucG0gZXhlYyBmb3JnZSBwdWJsaXNoIC0tY29uZmlndXJhdGlvbiByZWxlYXNlXG4gICAgICAgICMgU2tpcHMgcGFja2FnZXMgd2l0aCBcInByaXZhdGVcIjogdHJ1ZSAoZS5nLiB0aGUgd2ViYXBpIGFwcCkuXG4gICAgICAgICMgT3B0aW9uYWwgcmVnaXN0cnkgaW1hZ2VzOiBhZGQgXFxgcG5wbSBleGVjIGZvcmdlIGRvY2tlciAtLWNvbmZpZ3VyYXRpb24gcmVsZWFzZSAtLXB1c2hcXGBcbiAgICAgICAgIyBhZnRlciBjb25maWd1cmluZyBHSENSL09JREMg4oCUIG5vdCBlbmFibGVkIGJ5IGRlZmF1bHQgKFBhYVMgYnVpbGRzIHRoZSBEb2NrZXJmaWxlKS5cbmAsXG5cdFx0XHR9LFxuXHRcdF07XG5cdH1cbn1cbiJdLCJuYW1lcyI6WyJXRUxMX0tOT1dOX0ZJTEVTIiwiR2l0aHViQ2lXb3JrZmxvd3MiLCJrZXkiLCJHSVRIVUJfQ0kiLCJmaWxlcyIsImZpbGVQYXRoIiwiY29udGVudCJdLCJtYXBwaW5ncyI6IkFBQUEsU0FBU0EsZ0JBQWdCLFFBQVEsd0JBQXdCO0FBR3pEOzs7Q0FHQyxHQUNELE9BQU8sTUFBTUM7SUFDSUMsTUFBTUYsaUJBQWlCRyxTQUFTLENBQUM7SUFFMUNDLFFBQXNCO1FBQzVCLE9BQU87WUFDTjtnQkFDQ0MsVUFBVTtnQkFDVkMsU0FBUyxDQUFDOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUE2Q2QsQ0FBQztZQUNFO1lBQ0E7Z0JBQ0NELFVBQVU7Z0JBQ1ZDLFNBQVMsQ0FBQzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBMkVkLENBQUM7WUFDRTtZQUNBO2dCQUNDRCxVQUFVO2dCQUNWQyxTQUFTLENBQUM7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBeUNkLENBQUM7WUFDRTtTQUNBO0lBQ0Y7QUFDRCJ9
@@ -0,0 +1,163 @@
1
+ import { WELL_KNOWN_FILES } from "../../models/const.js";
2
+ /** Tracks named imports from a single module path, split into values and types. */ class ImportGroup {
3
+ _values = [];
4
+ _types = [];
5
+ add(name, typeOnly = false) {
6
+ if (typeOnly) {
7
+ // Value import already present — value wins, skip
8
+ if (!this._values.includes(name) && !this._types.includes(name)) {
9
+ this._types.push(name);
10
+ }
11
+ } else {
12
+ // Promote: remove from types if it was previously type-only
13
+ const typeIdx = this._types.indexOf(name);
14
+ if (typeIdx !== -1) this._types.splice(typeIdx, 1);
15
+ if (!this._values.includes(name)) this._values.push(name);
16
+ }
17
+ return this;
18
+ }
19
+ render(from) {
20
+ const values = [
21
+ ...this._values
22
+ ].sort();
23
+ const types = [
24
+ ...this._types
25
+ ].sort().map((n)=>`type ${n}`);
26
+ return `import { ${[
27
+ ...values,
28
+ ...types
29
+ ].join(", ")} } from "${from}";`;
30
+ }
31
+ }
32
+ /**
33
+ * Model for `projects/api/src/main.ts`.
34
+ *
35
+ * Starts with the minimal HTTP + YAML config setup. Features mutate the model
36
+ * by calling addSideEffectImport / addImport / addBuilderCall / addEntity /
37
+ * addRepository. files() renders whatever has been accumulated.
38
+ */ export class MainSourceFile {
39
+ appName;
40
+ key = WELL_KNOWN_FILES.MAIN_TS;
41
+ _sideEffectImports = [];
42
+ _extraImports = new Map();
43
+ _builderCalls = [];
44
+ _entities = [];
45
+ _repositories = [];
46
+ _services = [];
47
+ _dataSourceName;
48
+ _typeOrmSeed;
49
+ constructor(appName){
50
+ this.appName = appName;
51
+ }
52
+ /** Adds a bare side-effect import, e.g. `@decohere/cortex/auth`. */ addSideEffectImport(path) {
53
+ if (!this._sideEffectImports.includes(path)) this._sideEffectImports.push(path);
54
+ return this;
55
+ }
56
+ /** Adds a named import, e.g. `import { Foo } from "bar"`. */ addImport(name, from, typeOnly = false) {
57
+ const group = this._extraImports.get(from) ?? new ImportGroup();
58
+ group.add(name, typeOnly);
59
+ this._extraImports.set(from, group);
60
+ return this;
61
+ }
62
+ /**
63
+ * Adds a builder call inserted after `.withConfiguration()` and before
64
+ * `.withServices()`. Pass the call without leading dot, e.g. `.withAuth()`.
65
+ */ addBuilderCall(call) {
66
+ this._builderCalls.push(call);
67
+ return this;
68
+ }
69
+ /** Adds a TypeORM entity — import and entry in `withTypeOrm({ entities })`. */ addEntity(entity) {
70
+ this._entities.push(entity);
71
+ return this;
72
+ }
73
+ /** Adds a TypeORM repository — import and entry in `withTypeOrm({ repositories })`. */ addRepository(repo) {
74
+ this._repositories.push(repo);
75
+ return this;
76
+ }
77
+ /** Adds a service registered in `.withServices()`. */ addService(service) {
78
+ this._services.push(service);
79
+ return this;
80
+ }
81
+ /**
82
+ * Datasource name passed to `withTypeOrm({ name })`. Must match
83
+ * `database.dataSources[].name` in config.yaml.
84
+ */ setDataSourceName(name) {
85
+ this._dataSourceName = name;
86
+ return this;
87
+ }
88
+ /**
89
+ * Inline seed callback body for `withTypeOrm({ seed })`.
90
+ * Receives `dataSource` in scope. Example: `await dataSource.getRepository(User).save(...)`.
91
+ */ setTypeOrmSeed(seedBody) {
92
+ this._typeOrmSeed = seedBody;
93
+ return this;
94
+ }
95
+ files() {
96
+ const imports = [
97
+ 'import "@decohere/scribe-pino";',
98
+ 'import "@decohere/cortex/http";'
99
+ ];
100
+ for (const path of this._sideEffectImports){
101
+ imports.push(`import "${path}";`);
102
+ }
103
+ imports.push('import "@decohere/protocol";', 'import { YamlDataSource } from "@decohere/protocol";', 'import { Builder } from "@decohere/cortex";', 'import { FastifyProvider } from "@decohere/cortex/providers";', 'import { scribe } from "@decohere/scribe";', 'import { SampleService } from "./services/sample.service.js";');
104
+ for (const e of this._entities){
105
+ imports.push(`import { ${e.className} } from "${e.importPath}";`);
106
+ }
107
+ for (const r of this._repositories){
108
+ imports.push(`import { ${r.className} } from "${r.importPath}";`);
109
+ }
110
+ for (const s of this._services){
111
+ imports.push(`import { ${s.className} } from "${s.importPath}";`);
112
+ }
113
+ for (const [from, group] of this._extraImports){
114
+ imports.push(group.render(from));
115
+ }
116
+ imports.push('import { HelloController } from "./controllers/hello.controller.js";');
117
+ const serviceRegs = [
118
+ "cb.registerSingleton(SampleService);",
119
+ ...this._services.map((s)=>s.scope === "request" ? `cb.registerRequestScoped(${s.className});` : `cb.registerSingleton(${s.className});`)
120
+ ].join(" ");
121
+ const builderCalls = [
122
+ `\t.withHttp(FastifyProvider)`,
123
+ `\t.withConfiguration(YamlDataSource)`,
124
+ `\t.withHealth()`,
125
+ `\t.withOpenApi({ info: { title: "${this.appName}", version: "1.0.0" } })`,
126
+ ...this._builderCalls.map((c)=>`\t${c}`),
127
+ `\t.withServices((cb) => { ${serviceRegs} })`
128
+ ];
129
+ if (this._entities.length > 0) {
130
+ const entities = this._entities.map((e)=>e.className).join(", ");
131
+ const repos = this._repositories.map((r)=>r.className).join(", ");
132
+ const named = this._dataSourceName != null ? `name: "${this._dataSourceName}", ` : "";
133
+ if (this._typeOrmSeed) {
134
+ builderCalls.push(`\t.withTypeOrm({ ${named}entities: [${entities}], repositories: [${repos}], seed: async (dataSource) => { ${this._typeOrmSeed} } })`);
135
+ } else {
136
+ builderCalls.push(`\t.withTypeOrm({ ${named}entities: [${entities}], repositories: [${repos}] })`);
137
+ }
138
+ }
139
+ builderCalls.push(`\t.withControllers(HelloController)`);
140
+ const content = [
141
+ ...imports,
142
+ "",
143
+ `scribe.withPinoPretty().and.withPinoRoll({ file: "logs/${this.appName}.log" });`,
144
+ "",
145
+ `const app = await Builder.create({ applicationName: "${this.appName}" })`,
146
+ ...builderCalls,
147
+ `\t.build();`,
148
+ "",
149
+ "await app.start({ port: Number(process.env.PORT ?? 3000) });",
150
+ "",
151
+ "export default app;",
152
+ ""
153
+ ].join("\n");
154
+ return [
155
+ {
156
+ filePath: "src/main.ts",
157
+ content
158
+ }
159
+ ];
160
+ }
161
+ }
162
+
163
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL3J1bm5lci93b3JrL2RlY29oZXJlL2RlY29oZXJlL3Byb2plY3RzL3NjYWZmb2xkL3NyYy93ZWJhcGkvbW9kZWxzL21haW4tc291cmNlLWZpbGUubW9kZWwudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgV0VMTF9LTk9XTl9GSUxFUyB9IGZyb20gXCIuLi8uLi9tb2RlbHMvY29uc3QuanNcIjtcbmltcG9ydCB0eXBlIHsgS2V5ZWRNb2RlbCwgU291cmNlRmlsZSB9IGZyb20gXCIuLi8uLi9tb2RlbHMvc291cmNlLWZpbGUuanNcIjtcblxuZXhwb3J0IHR5cGUgVHlwZU9ybUltcG9ydCA9IHsgY2xhc3NOYW1lOiBzdHJpbmc7IGltcG9ydFBhdGg6IHN0cmluZyB9O1xuZXhwb3J0IHR5cGUgU2VydmljZUltcG9ydCA9IFR5cGVPcm1JbXBvcnQgJiB7IHNjb3BlPzogXCJzaW5nbGV0b25cIiB8IFwicmVxdWVzdFwiIH07XG5cbi8qKiBUcmFja3MgbmFtZWQgaW1wb3J0cyBmcm9tIGEgc2luZ2xlIG1vZHVsZSBwYXRoLCBzcGxpdCBpbnRvIHZhbHVlcyBhbmQgdHlwZXMuICovXG5jbGFzcyBJbXBvcnRHcm91cCB7XG5cdHByaXZhdGUgcmVhZG9ubHkgX3ZhbHVlczogc3RyaW5nW10gPSBbXTtcblx0cHJpdmF0ZSByZWFkb25seSBfdHlwZXM6IHN0cmluZ1tdID0gW107XG5cblx0cHVibGljIGFkZChuYW1lOiBzdHJpbmcsIHR5cGVPbmx5ID0gZmFsc2UpOiB0aGlzIHtcblx0XHRpZiAodHlwZU9ubHkpIHtcblx0XHRcdC8vIFZhbHVlIGltcG9ydCBhbHJlYWR5IHByZXNlbnQg4oCUIHZhbHVlIHdpbnMsIHNraXBcblx0XHRcdGlmICghdGhpcy5fdmFsdWVzLmluY2x1ZGVzKG5hbWUpICYmICF0aGlzLl90eXBlcy5pbmNsdWRlcyhuYW1lKSkge1xuXHRcdFx0XHR0aGlzLl90eXBlcy5wdXNoKG5hbWUpO1xuXHRcdFx0fVxuXHRcdH0gZWxzZSB7XG5cdFx0XHQvLyBQcm9tb3RlOiByZW1vdmUgZnJvbSB0eXBlcyBpZiBpdCB3YXMgcHJldmlvdXNseSB0eXBlLW9ubHlcblx0XHRcdGNvbnN0IHR5cGVJZHggPSB0aGlzLl90eXBlcy5pbmRleE9mKG5hbWUpO1xuXHRcdFx0aWYgKHR5cGVJZHggIT09IC0xKSB0aGlzLl90eXBlcy5zcGxpY2UodHlwZUlkeCwgMSk7XG5cdFx0XHRpZiAoIXRoaXMuX3ZhbHVlcy5pbmNsdWRlcyhuYW1lKSkgdGhpcy5fdmFsdWVzLnB1c2gobmFtZSk7XG5cdFx0fVxuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0cHVibGljIHJlbmRlcihmcm9tOiBzdHJpbmcpOiBzdHJpbmcge1xuXHRcdGNvbnN0IHZhbHVlcyA9IFsuLi50aGlzLl92YWx1ZXNdLnNvcnQoKTtcblx0XHRjb25zdCB0eXBlcyA9IFsuLi50aGlzLl90eXBlc10uc29ydCgpLm1hcCgobikgPT4gYHR5cGUgJHtufWApO1xuXHRcdHJldHVybiBgaW1wb3J0IHsgJHtbLi4udmFsdWVzLCAuLi50eXBlc10uam9pbihcIiwgXCIpfSB9IGZyb20gXCIke2Zyb219XCI7YDtcblx0fVxufVxuXG4vKipcbiAqIE1vZGVsIGZvciBgcHJvamVjdHMvYXBpL3NyYy9tYWluLnRzYC5cbiAqXG4gKiBTdGFydHMgd2l0aCB0aGUgbWluaW1hbCBIVFRQICsgWUFNTCBjb25maWcgc2V0dXAuIEZlYXR1cmVzIG11dGF0ZSB0aGUgbW9kZWxcbiAqIGJ5IGNhbGxpbmcgYWRkU2lkZUVmZmVjdEltcG9ydCAvIGFkZEltcG9ydCAvIGFkZEJ1aWxkZXJDYWxsIC8gYWRkRW50aXR5IC9cbiAqIGFkZFJlcG9zaXRvcnkuIGZpbGVzKCkgcmVuZGVycyB3aGF0ZXZlciBoYXMgYmVlbiBhY2N1bXVsYXRlZC5cbiAqL1xuZXhwb3J0IGNsYXNzIE1haW5Tb3VyY2VGaWxlIGltcGxlbWVudHMgS2V5ZWRNb2RlbCB7XG5cdHB1YmxpYyByZWFkb25seSBrZXkgPSBXRUxMX0tOT1dOX0ZJTEVTLk1BSU5fVFM7XG5cblx0cHJpdmF0ZSByZWFkb25seSBfc2lkZUVmZmVjdEltcG9ydHM6IHN0cmluZ1tdID0gW107XG5cdHByaXZhdGUgcmVhZG9ubHkgX2V4dHJhSW1wb3J0cyA9IG5ldyBNYXA8c3RyaW5nLCBJbXBvcnRHcm91cD4oKTtcblx0cHJpdmF0ZSByZWFkb25seSBfYnVpbGRlckNhbGxzOiBzdHJpbmdbXSA9IFtdO1xuXHRwcml2YXRlIHJlYWRvbmx5IF9lbnRpdGllczogVHlwZU9ybUltcG9ydFtdID0gW107XG5cdHByaXZhdGUgcmVhZG9ubHkgX3JlcG9zaXRvcmllczogVHlwZU9ybUltcG9ydFtdID0gW107XG5cdHByaXZhdGUgcmVhZG9ubHkgX3NlcnZpY2VzOiBTZXJ2aWNlSW1wb3J0W10gPSBbXTtcblx0cHJpdmF0ZSBfZGF0YVNvdXJjZU5hbWU6IHN0cmluZyB8IHVuZGVmaW5lZDtcblx0cHJpdmF0ZSBfdHlwZU9ybVNlZWQ6IHN0cmluZyB8IHVuZGVmaW5lZDtcblxuXHRwdWJsaWMgY29uc3RydWN0b3IocHJpdmF0ZSByZWFkb25seSBhcHBOYW1lOiBzdHJpbmcpIHt9XG5cblx0LyoqIEFkZHMgYSBiYXJlIHNpZGUtZWZmZWN0IGltcG9ydCwgZS5nLiBgQGRlY29oZXJlL2NvcnRleC9hdXRoYC4gKi9cblx0cHVibGljIGFkZFNpZGVFZmZlY3RJbXBvcnQocGF0aDogc3RyaW5nKTogdGhpcyB7XG5cdFx0aWYgKCF0aGlzLl9zaWRlRWZmZWN0SW1wb3J0cy5pbmNsdWRlcyhwYXRoKSkgdGhpcy5fc2lkZUVmZmVjdEltcG9ydHMucHVzaChwYXRoKTtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKiBBZGRzIGEgbmFtZWQgaW1wb3J0LCBlLmcuIGBpbXBvcnQgeyBGb28gfSBmcm9tIFwiYmFyXCJgLiAqL1xuXHRwdWJsaWMgYWRkSW1wb3J0KG5hbWU6IHN0cmluZywgZnJvbTogc3RyaW5nLCB0eXBlT25seSA9IGZhbHNlKTogdGhpcyB7XG5cdFx0Y29uc3QgZ3JvdXAgPSB0aGlzLl9leHRyYUltcG9ydHMuZ2V0KGZyb20pID8/IG5ldyBJbXBvcnRHcm91cCgpO1xuXHRcdGdyb3VwLmFkZChuYW1lLCB0eXBlT25seSk7XG5cdFx0dGhpcy5fZXh0cmFJbXBvcnRzLnNldChmcm9tLCBncm91cCk7XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxuXHQvKipcblx0ICogQWRkcyBhIGJ1aWxkZXIgY2FsbCBpbnNlcnRlZCBhZnRlciBgLndpdGhDb25maWd1cmF0aW9uKClgIGFuZCBiZWZvcmVcblx0ICogYC53aXRoU2VydmljZXMoKWAuIFBhc3MgdGhlIGNhbGwgd2l0aG91dCBsZWFkaW5nIGRvdCwgZS5nLiBgLndpdGhBdXRoKClgLlxuXHQgKi9cblx0cHVibGljIGFkZEJ1aWxkZXJDYWxsKGNhbGw6IHN0cmluZyk6IHRoaXMge1xuXHRcdHRoaXMuX2J1aWxkZXJDYWxscy5wdXNoKGNhbGwpO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqIEFkZHMgYSBUeXBlT1JNIGVudGl0eSDigJQgaW1wb3J0IGFuZCBlbnRyeSBpbiBgd2l0aFR5cGVPcm0oeyBlbnRpdGllcyB9KWAuICovXG5cdHB1YmxpYyBhZGRFbnRpdHkoZW50aXR5OiBUeXBlT3JtSW1wb3J0KTogdGhpcyB7XG5cdFx0dGhpcy5fZW50aXRpZXMucHVzaChlbnRpdHkpO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqIEFkZHMgYSBUeXBlT1JNIHJlcG9zaXRvcnkg4oCUIGltcG9ydCBhbmQgZW50cnkgaW4gYHdpdGhUeXBlT3JtKHsgcmVwb3NpdG9yaWVzIH0pYC4gKi9cblx0cHVibGljIGFkZFJlcG9zaXRvcnkocmVwbzogVHlwZU9ybUltcG9ydCk6IHRoaXMge1xuXHRcdHRoaXMuX3JlcG9zaXRvcmllcy5wdXNoKHJlcG8pO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqIEFkZHMgYSBzZXJ2aWNlIHJlZ2lzdGVyZWQgaW4gYC53aXRoU2VydmljZXMoKWAuICovXG5cdHB1YmxpYyBhZGRTZXJ2aWNlKHNlcnZpY2U6IFNlcnZpY2VJbXBvcnQpOiB0aGlzIHtcblx0XHR0aGlzLl9zZXJ2aWNlcy5wdXNoKHNlcnZpY2UpO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqXG5cdCAqIERhdGFzb3VyY2UgbmFtZSBwYXNzZWQgdG8gYHdpdGhUeXBlT3JtKHsgbmFtZSB9KWAuIE11c3QgbWF0Y2hcblx0ICogYGRhdGFiYXNlLmRhdGFTb3VyY2VzW10ubmFtZWAgaW4gY29uZmlnLnlhbWwuXG5cdCAqL1xuXHRwdWJsaWMgc2V0RGF0YVNvdXJjZU5hbWUobmFtZTogc3RyaW5nKTogdGhpcyB7XG5cdFx0dGhpcy5fZGF0YVNvdXJjZU5hbWUgPSBuYW1lO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqXG5cdCAqIElubGluZSBzZWVkIGNhbGxiYWNrIGJvZHkgZm9yIGB3aXRoVHlwZU9ybSh7IHNlZWQgfSlgLlxuXHQgKiBSZWNlaXZlcyBgZGF0YVNvdXJjZWAgaW4gc2NvcGUuIEV4YW1wbGU6IGBhd2FpdCBkYXRhU291cmNlLmdldFJlcG9zaXRvcnkoVXNlcikuc2F2ZSguLi4pYC5cblx0ICovXG5cdHB1YmxpYyBzZXRUeXBlT3JtU2VlZChzZWVkQm9keTogc3RyaW5nKTogdGhpcyB7XG5cdFx0dGhpcy5fdHlwZU9ybVNlZWQgPSBzZWVkQm9keTtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdHB1YmxpYyBmaWxlcygpOiBTb3VyY2VGaWxlW10ge1xuXHRcdGNvbnN0IGltcG9ydHM6IHN0cmluZ1tdID0gW1xuXHRcdFx0J2ltcG9ydCBcIkBkZWNvaGVyZS9zY3JpYmUtcGlub1wiOycsXG5cdFx0XHQnaW1wb3J0IFwiQGRlY29oZXJlL2NvcnRleC9odHRwXCI7Jyxcblx0XHRdO1xuXG5cdFx0Zm9yIChjb25zdCBwYXRoIG9mIHRoaXMuX3NpZGVFZmZlY3RJbXBvcnRzKSB7XG5cdFx0XHRpbXBvcnRzLnB1c2goYGltcG9ydCBcIiR7cGF0aH1cIjtgKTtcblx0XHR9XG5cblx0XHRpbXBvcnRzLnB1c2goXG5cdFx0XHQnaW1wb3J0IFwiQGRlY29oZXJlL3Byb3RvY29sXCI7Jyxcblx0XHRcdCdpbXBvcnQgeyBZYW1sRGF0YVNvdXJjZSB9IGZyb20gXCJAZGVjb2hlcmUvcHJvdG9jb2xcIjsnLFxuXHRcdFx0J2ltcG9ydCB7IEJ1aWxkZXIgfSBmcm9tIFwiQGRlY29oZXJlL2NvcnRleFwiOycsXG5cdFx0XHQnaW1wb3J0IHsgRmFzdGlmeVByb3ZpZGVyIH0gZnJvbSBcIkBkZWNvaGVyZS9jb3J0ZXgvcHJvdmlkZXJzXCI7Jyxcblx0XHRcdCdpbXBvcnQgeyBzY3JpYmUgfSBmcm9tIFwiQGRlY29oZXJlL3NjcmliZVwiOycsXG5cdFx0XHQnaW1wb3J0IHsgU2FtcGxlU2VydmljZSB9IGZyb20gXCIuL3NlcnZpY2VzL3NhbXBsZS5zZXJ2aWNlLmpzXCI7Jyxcblx0XHQpO1xuXG5cdFx0Zm9yIChjb25zdCBlIG9mIHRoaXMuX2VudGl0aWVzKSB7XG5cdFx0XHRpbXBvcnRzLnB1c2goYGltcG9ydCB7ICR7ZS5jbGFzc05hbWV9IH0gZnJvbSBcIiR7ZS5pbXBvcnRQYXRofVwiO2ApO1xuXHRcdH1cblxuXHRcdGZvciAoY29uc3QgciBvZiB0aGlzLl9yZXBvc2l0b3JpZXMpIHtcblx0XHRcdGltcG9ydHMucHVzaChgaW1wb3J0IHsgJHtyLmNsYXNzTmFtZX0gfSBmcm9tIFwiJHtyLmltcG9ydFBhdGh9XCI7YCk7XG5cdFx0fVxuXG5cdFx0Zm9yIChjb25zdCBzIG9mIHRoaXMuX3NlcnZpY2VzKSB7XG5cdFx0XHRpbXBvcnRzLnB1c2goYGltcG9ydCB7ICR7cy5jbGFzc05hbWV9IH0gZnJvbSBcIiR7cy5pbXBvcnRQYXRofVwiO2ApO1xuXHRcdH1cblxuXHRcdGZvciAoY29uc3QgW2Zyb20sIGdyb3VwXSBvZiB0aGlzLl9leHRyYUltcG9ydHMpIHtcblx0XHRcdGltcG9ydHMucHVzaChncm91cC5yZW5kZXIoZnJvbSkpO1xuXHRcdH1cblxuXHRcdGltcG9ydHMucHVzaCgnaW1wb3J0IHsgSGVsbG9Db250cm9sbGVyIH0gZnJvbSBcIi4vY29udHJvbGxlcnMvaGVsbG8uY29udHJvbGxlci5qc1wiOycpO1xuXG5cdFx0Y29uc3Qgc2VydmljZVJlZ3MgPSBbXG5cdFx0XHRcImNiLnJlZ2lzdGVyU2luZ2xldG9uKFNhbXBsZVNlcnZpY2UpO1wiLFxuXHRcdFx0Li4udGhpcy5fc2VydmljZXMubWFwKChzKSA9PlxuXHRcdFx0XHRzLnNjb3BlID09PSBcInJlcXVlc3RcIlxuXHRcdFx0XHRcdD8gYGNiLnJlZ2lzdGVyUmVxdWVzdFNjb3BlZCgke3MuY2xhc3NOYW1lfSk7YFxuXHRcdFx0XHRcdDogYGNiLnJlZ2lzdGVyU2luZ2xldG9uKCR7cy5jbGFzc05hbWV9KTtgLFxuXHRcdFx0KSxcblx0XHRdLmpvaW4oXCIgXCIpO1xuXG5cdFx0Y29uc3QgYnVpbGRlckNhbGxzOiBzdHJpbmdbXSA9IFtcblx0XHRcdGBcXHQud2l0aEh0dHAoRmFzdGlmeVByb3ZpZGVyKWAsXG5cdFx0XHRgXFx0LndpdGhDb25maWd1cmF0aW9uKFlhbWxEYXRhU291cmNlKWAsXG5cdFx0XHRgXFx0LndpdGhIZWFsdGgoKWAsXG5cdFx0XHRgXFx0LndpdGhPcGVuQXBpKHsgaW5mbzogeyB0aXRsZTogXCIke3RoaXMuYXBwTmFtZX1cIiwgdmVyc2lvbjogXCIxLjAuMFwiIH0gfSlgLFxuXHRcdFx0Li4udGhpcy5fYnVpbGRlckNhbGxzLm1hcCgoYykgPT4gYFxcdCR7Y31gKSxcblx0XHRcdGBcXHQud2l0aFNlcnZpY2VzKChjYikgPT4geyAke3NlcnZpY2VSZWdzfSB9KWAsXG5cdFx0XTtcblxuXHRcdGlmICh0aGlzLl9lbnRpdGllcy5sZW5ndGggPiAwKSB7XG5cdFx0XHRjb25zdCBlbnRpdGllcyA9IHRoaXMuX2VudGl0aWVzLm1hcCgoZSkgPT4gZS5jbGFzc05hbWUpLmpvaW4oXCIsIFwiKTtcblx0XHRcdGNvbnN0IHJlcG9zID0gdGhpcy5fcmVwb3NpdG9yaWVzLm1hcCgocikgPT4gci5jbGFzc05hbWUpLmpvaW4oXCIsIFwiKTtcblx0XHRcdGNvbnN0IG5hbWVkID0gdGhpcy5fZGF0YVNvdXJjZU5hbWUgIT0gbnVsbCA/IGBuYW1lOiBcIiR7dGhpcy5fZGF0YVNvdXJjZU5hbWV9XCIsIGAgOiBcIlwiO1xuXHRcdFx0aWYgKHRoaXMuX3R5cGVPcm1TZWVkKSB7XG5cdFx0XHRcdGJ1aWxkZXJDYWxscy5wdXNoKFxuXHRcdFx0XHRcdGBcXHQud2l0aFR5cGVPcm0oeyAke25hbWVkfWVudGl0aWVzOiBbJHtlbnRpdGllc31dLCByZXBvc2l0b3JpZXM6IFske3JlcG9zfV0sIHNlZWQ6IGFzeW5jIChkYXRhU291cmNlKSA9PiB7ICR7dGhpcy5fdHlwZU9ybVNlZWR9IH0gfSlgLFxuXHRcdFx0XHQpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0YnVpbGRlckNhbGxzLnB1c2goXG5cdFx0XHRcdFx0YFxcdC53aXRoVHlwZU9ybSh7ICR7bmFtZWR9ZW50aXRpZXM6IFske2VudGl0aWVzfV0sIHJlcG9zaXRvcmllczogWyR7cmVwb3N9XSB9KWAsXG5cdFx0XHRcdCk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0YnVpbGRlckNhbGxzLnB1c2goYFxcdC53aXRoQ29udHJvbGxlcnMoSGVsbG9Db250cm9sbGVyKWApO1xuXG5cdFx0Y29uc3QgY29udGVudCA9IFtcblx0XHRcdC4uLmltcG9ydHMsXG5cdFx0XHRcIlwiLFxuXHRcdFx0YHNjcmliZS53aXRoUGlub1ByZXR0eSgpLmFuZC53aXRoUGlub1JvbGwoeyBmaWxlOiBcImxvZ3MvJHt0aGlzLmFwcE5hbWV9LmxvZ1wiIH0pO2AsXG5cdFx0XHRcIlwiLFxuXHRcdFx0YGNvbnN0IGFwcCA9IGF3YWl0IEJ1aWxkZXIuY3JlYXRlKHsgYXBwbGljYXRpb25OYW1lOiBcIiR7dGhpcy5hcHBOYW1lfVwiIH0pYCxcblx0XHRcdC4uLmJ1aWxkZXJDYWxscyxcblx0XHRcdGBcXHQuYnVpbGQoKTtgLFxuXHRcdFx0XCJcIixcblx0XHRcdFwiYXdhaXQgYXBwLnN0YXJ0KHsgcG9ydDogTnVtYmVyKHByb2Nlc3MuZW52LlBPUlQgPz8gMzAwMCkgfSk7XCIsXG5cdFx0XHRcIlwiLFxuXHRcdFx0XCJleHBvcnQgZGVmYXVsdCBhcHA7XCIsXG5cdFx0XHRcIlwiLFxuXHRcdF0uam9pbihcIlxcblwiKTtcblxuXHRcdHJldHVybiBbXG5cdFx0XHR7XG5cdFx0XHRcdGZpbGVQYXRoOiBcInNyYy9tYWluLnRzXCIsXG5cdFx0XHRcdGNvbnRlbnQsXG5cdFx0XHR9LFxuXHRcdF07XG5cdH1cbn1cbiJdLCJuYW1lcyI6WyJXRUxMX0tOT1dOX0ZJTEVTIiwiSW1wb3J0R3JvdXAiLCJfdmFsdWVzIiwiX3R5cGVzIiwiYWRkIiwibmFtZSIsInR5cGVPbmx5IiwiaW5jbHVkZXMiLCJwdXNoIiwidHlwZUlkeCIsImluZGV4T2YiLCJzcGxpY2UiLCJyZW5kZXIiLCJmcm9tIiwidmFsdWVzIiwic29ydCIsInR5cGVzIiwibWFwIiwibiIsImpvaW4iLCJNYWluU291cmNlRmlsZSIsImtleSIsIk1BSU5fVFMiLCJfc2lkZUVmZmVjdEltcG9ydHMiLCJfZXh0cmFJbXBvcnRzIiwiTWFwIiwiX2J1aWxkZXJDYWxscyIsIl9lbnRpdGllcyIsIl9yZXBvc2l0b3JpZXMiLCJfc2VydmljZXMiLCJfZGF0YVNvdXJjZU5hbWUiLCJfdHlwZU9ybVNlZWQiLCJhcHBOYW1lIiwiYWRkU2lkZUVmZmVjdEltcG9ydCIsInBhdGgiLCJhZGRJbXBvcnQiLCJncm91cCIsImdldCIsInNldCIsImFkZEJ1aWxkZXJDYWxsIiwiY2FsbCIsImFkZEVudGl0eSIsImVudGl0eSIsImFkZFJlcG9zaXRvcnkiLCJyZXBvIiwiYWRkU2VydmljZSIsInNlcnZpY2UiLCJzZXREYXRhU291cmNlTmFtZSIsInNldFR5cGVPcm1TZWVkIiwic2VlZEJvZHkiLCJmaWxlcyIsImltcG9ydHMiLCJlIiwiY2xhc3NOYW1lIiwiaW1wb3J0UGF0aCIsInIiLCJzIiwic2VydmljZVJlZ3MiLCJzY29wZSIsImJ1aWxkZXJDYWxscyIsImMiLCJsZW5ndGgiLCJlbnRpdGllcyIs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
@@ -0,0 +1,148 @@
1
+ import { WELL_KNOWN_FILES } from "../../models/const.js";
2
+ import { DEFAULT_WEBAPI_NAME, webapiProjectDir, webapiReleaseEntry } from "../const.js";
3
+ /**
4
+ * Production Dockerfiles for PaaS (Railway/Fly) and local `docker build`.
5
+ *
6
+ * Context is always the **repo root** (`docker build -f Dockerfile.billing .`).
7
+ * Root `Dockerfile` is the first API (`pnpm start`). Extra or custom-named APIs
8
+ * also get `Dockerfile.<name>` so each service can be deployed on its own.
9
+ *
10
+ * Runtime `node_modules` come from a **prod-deps** stage (`pnpm install --prod`),
11
+ * not the full build install (Forge, TypeScript, Biome, Vitest).
12
+ */ export class WebapiProductionDockerfile {
13
+ apiNames;
14
+ options;
15
+ key = WELL_KNOWN_FILES.PRODUCTION_DOCKERFILE;
16
+ constructor(apiNames = [
17
+ DEFAULT_WEBAPI_NAME
18
+ ], options = {}){
19
+ this.apiNames = apiNames;
20
+ this.options = options;
21
+ }
22
+ files() {
23
+ const names = this.apiNames.length > 0 ? this.apiNames : [
24
+ DEFAULT_WEBAPI_NAME
25
+ ];
26
+ const first = names[0] ?? DEFAULT_WEBAPI_NAME;
27
+ const files = [];
28
+ if (!this.options.namedOnly) {
29
+ files.push({
30
+ filePath: ".dockerignore",
31
+ content: dockerignoreContent()
32
+ });
33
+ files.push({
34
+ filePath: "Dockerfile",
35
+ content: renderProductionDockerfile(first, "start")
36
+ });
37
+ }
38
+ const emitNamed = this.options.namedOnly || names.length > 1 || first !== DEFAULT_WEBAPI_NAME;
39
+ if (emitNamed) {
40
+ for (const name of names){
41
+ files.push({
42
+ filePath: `Dockerfile.${name}`,
43
+ content: renderProductionDockerfile(name, `start:${name}`)
44
+ });
45
+ }
46
+ }
47
+ return files;
48
+ }
49
+ }
50
+ export function renderProductionDockerfile(apiName, startScript) {
51
+ const projectDir = webapiProjectDir(apiName);
52
+ const startCmd = startScript === "start" ? 'CMD ["pnpm", "start"]' : `CMD ["pnpm", "run", "${startScript}"]`;
53
+ const startEntry = webapiReleaseEntry(apiName);
54
+ const dockerfileFlag = startScript === "start" ? "" : `.${apiName}`;
55
+ return `# syntax=docker/dockerfile:1
56
+ # Self-contained production image: install + forge build happen inside docker build.
57
+ # Hosts (Railway/Fly/etc.) clone git and run \`docker build\` — they do not receive CI dist/.
58
+ # Build from the repo root: docker build -f Dockerfile${dockerfileFlag} .
59
+ #
60
+ # Runtime node_modules are a production-only install (prod-deps). The build stage's
61
+ # full install (Forge, TypeScript, Biome, Vitest) is not copied into the run image.
62
+ #
63
+ # Private @decohere/* packages: pass a BuildKit secret named npm_token (npm auth token), e.g.
64
+ # docker build --secret id=npm_token,env=NODE_AUTH_TOKEN .
65
+ # Or set NODE_AUTH_TOKEN as a build-arg on hosts that only support build-args.
66
+
67
+ FROM node:24-bookworm AS build
68
+ WORKDIR /app
69
+ RUN corepack enable && corepack prepare pnpm@10 --activate
70
+
71
+ COPY package.json ./
72
+ COPY pnpm-lock.yaml* ./
73
+ COPY tsconfig.json biome.json ./
74
+ COPY config ./config
75
+ COPY ${projectDir} ./${projectDir}
76
+
77
+ ${renderPnpmInstall("all")}
78
+
79
+ RUN pnpm run build
80
+
81
+ FROM node:24-bookworm AS prod-deps
82
+ WORKDIR /app
83
+ ENV NODE_ENV=production
84
+ RUN corepack enable && corepack prepare pnpm@10 --activate
85
+
86
+ COPY package.json ./
87
+ COPY pnpm-lock.yaml* ./
88
+ COPY ${projectDir}/package.json ./${projectDir}/package.json
89
+
90
+ ${renderPnpmInstall("prod")}
91
+
92
+ FROM node:24-bookworm-slim AS run
93
+ WORKDIR /app
94
+ ENV NODE_ENV=production
95
+ RUN corepack enable && corepack prepare pnpm@10 --activate
96
+
97
+ COPY --from=prod-deps /app/package.json ./
98
+ COPY --from=prod-deps /app/pnpm-lock.yaml* ./
99
+ COPY --from=build /app/config ./config
100
+ COPY --from=build /app/dist ./dist
101
+ COPY --from=prod-deps /app/node_modules ./node_modules
102
+ COPY --from=prod-deps /app/${projectDir}/package.json ./${projectDir}/package.json
103
+
104
+ EXPOSE 3000
105
+ ${startCmd}
106
+ # Entry resolved by package.json "${startScript}" → node ${startEntry}
107
+ `;
108
+ }
109
+ /** npm auth + pnpm install. Token is required again in prod-deps (separate stage, no store). */ function renderPnpmInstall(mode) {
110
+ const flags = mode === "prod" ? " --prod" : "";
111
+ return `ARG NODE_AUTH_TOKEN=
112
+ RUN --mount=type=secret,id=npm_token,required=false \\
113
+ if [ -f /run/secrets/npm_token ]; then \\
114
+ TOKEN="$(cat /run/secrets/npm_token)"; \\
115
+ else \\
116
+ TOKEN="\${NODE_AUTH_TOKEN}"; \\
117
+ fi; \\
118
+ if [ -n "$TOKEN" ]; then \\
119
+ echo "//registry.npmjs.org/:_authToken=\${TOKEN}" > .npmrc; \\
120
+ fi; \\
121
+ if [ -f pnpm-lock.yaml ]; then \\
122
+ pnpm install --frozen-lockfile${flags}; \\
123
+ else \\
124
+ pnpm install${flags}; \\
125
+ fi; \\
126
+ rm -f .npmrc`;
127
+ }
128
+ function dockerignoreContent() {
129
+ return [
130
+ "node_modules",
131
+ "dist",
132
+ ".git",
133
+ ".devcontainer",
134
+ ".vscode",
135
+ ".github",
136
+ "postman",
137
+ ".postman",
138
+ ".env",
139
+ ".env.*",
140
+ "!.env.example",
141
+ "coverage",
142
+ "**/*.spec.ts",
143
+ "**/*.test.ts",
144
+ ""
145
+ ].join("\n");
146
+ }
147
+
148
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL3J1bm5lci93b3JrL2RlY29oZXJlL2RlY29oZXJlL3Byb2plY3RzL3NjYWZmb2xkL3NyYy93ZWJhcGkvbW9kZWxzL3Byb2R1Y3Rpb24tZG9ja2VyZmlsZS5tb2RlbC50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBXRUxMX0tOT1dOX0ZJTEVTIH0gZnJvbSBcIi4uLy4uL21vZGVscy9jb25zdC5qc1wiO1xuaW1wb3J0IHR5cGUgeyBLZXllZE1vZGVsLCBTb3VyY2VGaWxlIH0gZnJvbSBcIi4uLy4uL21vZGVscy9zb3VyY2UtZmlsZS5qc1wiO1xuaW1wb3J0IHsgREVGQVVMVF9XRUJBUElfTkFNRSwgd2ViYXBpUHJvamVjdERpciwgd2ViYXBpUmVsZWFzZUVudHJ5IH0gZnJvbSBcIi4uL2NvbnN0LmpzXCI7XG5cbmV4cG9ydCB0eXBlIFByb2R1Y3Rpb25Eb2NrZXJmaWxlT3B0aW9ucyA9IHtcblx0LyoqIFdoZW4gdHJ1ZSwgb25seSB3cml0ZSBgRG9ja2VyZmlsZS48bmFtZT5gIChleGlzdGluZyB3b3Jrc3BhY2Ug4oCUIGRvIG5vdCByZXBsYWNlIHJvb3QgRG9ja2VyZmlsZSkuICovXG5cdG5hbWVkT25seT86IGJvb2xlYW47XG59O1xuXG4vKipcbiAqIFByb2R1Y3Rpb24gRG9ja2VyZmlsZXMgZm9yIFBhYVMgKFJhaWx3YXkvRmx5KSBhbmQgbG9jYWwgYGRvY2tlciBidWlsZGAuXG4gKlxuICogQ29udGV4dCBpcyBhbHdheXMgdGhlICoqcmVwbyByb290KiogKGBkb2NrZXIgYnVpbGQgLWYgRG9ja2VyZmlsZS5iaWxsaW5nIC5gKS5cbiAqIFJvb3QgYERvY2tlcmZpbGVgIGlzIHRoZSBmaXJzdCBBUEkgKGBwbnBtIHN0YXJ0YCkuIEV4dHJhIG9yIGN1c3RvbS1uYW1lZCBBUElzXG4gKiBhbHNvIGdldCBgRG9ja2VyZmlsZS48bmFtZT5gIHNvIGVhY2ggc2VydmljZSBjYW4gYmUgZGVwbG95ZWQgb24gaXRzIG93bi5cbiAqXG4gKiBSdW50aW1lIGBub2RlX21vZHVsZXNgIGNvbWUgZnJvbSBhICoqcHJvZC1kZXBzKiogc3RhZ2UgKGBwbnBtIGluc3RhbGwgLS1wcm9kYCksXG4gKiBub3QgdGhlIGZ1bGwgYnVpbGQgaW5zdGFsbCAoRm9yZ2UsIFR5cGVTY3JpcHQsIEJpb21lLCBWaXRlc3QpLlxuICovXG5leHBvcnQgY2xhc3MgV2ViYXBpUHJvZHVjdGlvbkRvY2tlcmZpbGUgaW1wbGVtZW50cyBLZXllZE1vZGVsIHtcblx0cHVibGljIHJlYWRvbmx5IGtleSA9IFdFTExfS05PV05fRklMRVMuUFJPRFVDVElPTl9ET0NLRVJGSUxFO1xuXG5cdHB1YmxpYyBjb25zdHJ1Y3Rvcihcblx0XHRwcml2YXRlIHJlYWRvbmx5IGFwaU5hbWVzOiByZWFkb25seSBzdHJpbmdbXSA9IFtERUZBVUxUX1dFQkFQSV9OQU1FXSxcblx0XHRwcml2YXRlIHJlYWRvbmx5IG9wdGlvbnM6IFByb2R1Y3Rpb25Eb2NrZXJmaWxlT3B0aW9ucyA9IHt9LFxuXHQpIHt9XG5cblx0cHVibGljIGZpbGVzKCk6IFNvdXJjZUZpbGVbXSB7XG5cdFx0Y29uc3QgbmFtZXMgPSB0aGlzLmFwaU5hbWVzLmxlbmd0aCA+IDAgPyB0aGlzLmFwaU5hbWVzIDogW0RFRkFVTFRfV0VCQVBJX05BTUVdO1xuXHRcdGNvbnN0IGZpcnN0ID0gbmFtZXNbMF0gPz8gREVGQVVMVF9XRUJBUElfTkFNRTtcblx0XHRjb25zdCBmaWxlczogU291cmNlRmlsZVtdID0gW107XG5cblx0XHRpZiAoIXRoaXMub3B0aW9ucy5uYW1lZE9ubHkpIHtcblx0XHRcdGZpbGVzLnB1c2goe1xuXHRcdFx0XHRmaWxlUGF0aDogXCIuZG9ja2VyaWdub3JlXCIsXG5cdFx0XHRcdGNvbnRlbnQ6IGRvY2tlcmlnbm9yZUNvbnRlbnQoKSxcblx0XHRcdH0pO1xuXHRcdFx0ZmlsZXMucHVzaCh7XG5cdFx0XHRcdGZpbGVQYXRoOiBcIkRvY2tlcmZpbGVcIixcblx0XHRcdFx0Y29udGVudDogcmVuZGVyUHJvZHVjdGlvbkRvY2tlcmZpbGUoZmlyc3QsIFwic3RhcnRcIiksXG5cdFx0XHR9KTtcblx0XHR9XG5cblx0XHRjb25zdCBlbWl0TmFtZWQgPVxuXHRcdFx0dGhpcy5vcHRpb25zLm5hbWVkT25seSB8fCBuYW1lcy5sZW5ndGggPiAxIHx8IGZpcnN0ICE9PSBERUZBVUxUX1dFQkFQSV9OQU1FO1xuXHRcdGlmIChlbWl0TmFtZWQpIHtcblx0XHRcdGZvciAoY29uc3QgbmFtZSBvZiBuYW1lcykge1xuXHRcdFx0XHRmaWxlcy5wdXNoKHtcblx0XHRcdFx0XHRmaWxlUGF0aDogYERvY2tlcmZpbGUuJHtuYW1lfWAsXG5cdFx0XHRcdFx0Y29udGVudDogcmVuZGVyUHJvZHVjdGlvbkRvY2tlcmZpbGUobmFtZSwgYHN0YXJ0OiR7bmFtZX1gKSxcblx0XHRcdFx0fSk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0cmV0dXJuIGZpbGVzO1xuXHR9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiByZW5kZXJQcm9kdWN0aW9uRG9ja2VyZmlsZShhcGlOYW1lOiBzdHJpbmcsIHN0YXJ0U2NyaXB0OiBzdHJpbmcpOiBzdHJpbmcge1xuXHRjb25zdCBwcm9qZWN0RGlyID0gd2ViYXBpUHJvamVjdERpcihhcGlOYW1lKTtcblx0Y29uc3Qgc3RhcnRDbWQgPVxuXHRcdHN0YXJ0U2NyaXB0ID09PSBcInN0YXJ0XCJcblx0XHRcdD8gJ0NNRCBbXCJwbnBtXCIsIFwic3RhcnRcIl0nXG5cdFx0XHQ6IGBDTUQgW1wicG5wbVwiLCBcInJ1blwiLCBcIiR7c3RhcnRTY3JpcHR9XCJdYDtcblx0Y29uc3Qgc3RhcnRFbnRyeSA9IHdlYmFwaVJlbGVhc2VFbnRyeShhcGlOYW1lKTtcblx0Y29uc3QgZG9ja2VyZmlsZUZsYWcgPSBzdGFydFNjcmlwdCA9PT0gXCJzdGFydFwiID8gXCJcIiA6IGAuJHthcGlOYW1lfWA7XG5cblx0cmV0dXJuIGAjIHN5bnRheD1kb2NrZXIvZG9ja2VyZmlsZToxXG4jIFNlbGYtY29udGFpbmVkIHByb2R1Y3Rpb24gaW1hZ2U6IGluc3RhbGwgKyBmb3JnZSBidWlsZCBoYXBwZW4gaW5zaWRlIGRvY2tlciBidWlsZC5cbiMgSG9zdHMgKFJhaWx3YXkvRmx5L2V0Yy4pIGNsb25lIGdpdCBhbmQgcnVuIFxcYGRvY2tlciBidWlsZFxcYCDigJQgdGhleSBkbyBub3QgcmVjZWl2ZSBDSSBkaXN0Ly5cbiMgQnVpbGQgZnJvbSB0aGUgcmVwbyByb290OiBkb2NrZXIgYnVpbGQgLWYgRG9ja2VyZmlsZSR7ZG9ja2VyZmlsZUZsYWd9IC5cbiNcbiMgUnVudGltZSBub2RlX21vZHVsZXMgYXJlIGEgcHJvZHVjdGlvbi1vbmx5IGluc3RhbGwgKHByb2QtZGVwcykuIFRoZSBidWlsZCBzdGFnZSdzXG4jIGZ1bGwgaW5zdGFsbCAoRm9yZ2UsIFR5cGVTY3JpcHQsIEJpb21lLCBWaXRlc3QpIGlzIG5vdCBjb3BpZWQgaW50byB0aGUgcnVuIGltYWdlLlxuI1xuIyBQcml2YXRlIEBkZWNvaGVyZS8qIHBhY2thZ2VzOiBwYXNzIGEgQnVpbGRLaXQgc2VjcmV0IG5hbWVkIG5wbV90b2tlbiAobnBtIGF1dGggdG9rZW4pLCBlLmcuXG4jICAgZG9ja2VyIGJ1aWxkIC0tc2VjcmV0IGlkPW5wbV90b2tlbixlbnY9Tk9ERV9BVVRIX1RPS0VOIC5cbiMgT3Igc2V0IE5PREVfQVVUSF9UT0tFTiBhcyBhIGJ1aWxkLWFyZyBvbiBob3N0cyB0aGF0IG9ubHkgc3VwcG9ydCBidWlsZC1hcmdzLlxuXG5GUk9NIG5vZGU6MjQtYm9va3dvcm0gQVMgYnVpbGRcbldPUktESVIgL2FwcFxuUlVOIGNvcmVwYWNrIGVuYWJsZSAmJiBjb3JlcGFjayBwcmVwYXJlIHBucG1AMTAgLS1hY3RpdmF0ZVxuXG5DT1BZIHBhY2thZ2UuanNvbiAuL1xuQ09QWSBwbnBtLWxvY2sueWFtbCogLi9cbkNPUFkgdHNjb25maWcuanNvbiBiaW9tZS5qc29uIC4vXG5DT1BZIGNvbmZpZyAuL2NvbmZpZ1xuQ09QWSAke3Byb2plY3REaXJ9IC4vJHtwcm9qZWN0RGlyfVxuXG4ke3JlbmRlclBucG1JbnN0YWxsKFwiYWxsXCIpfVxuXG5SVU4gcG5wbSBydW4gYnVpbGRcblxuRlJPTSBub2RlOjI0LWJvb2t3b3JtIEFTIHByb2QtZGVwc1xuV09SS0RJUiAvYXBwXG5FTlYgTk9ERV9FTlY9cHJvZHVjdGlvblxuUlVOIGNvcmVwYWNrIGVuYWJsZSAmJiBjb3JlcGFjayBwcmVwYXJlIHBucG1AMTAgLS1hY3RpdmF0ZVxuXG5DT1BZIHBhY2thZ2UuanNvbiAuL1xuQ09QWSBwbnBtLWxvY2sueWFtbCogLi9cbkNPUFkgJHtwcm9qZWN0RGlyfS9wYWNrYWdlLmpzb24gLi8ke3Byb2plY3REaXJ9L3BhY2thZ2UuanNvblxuXG4ke3JlbmRlclBucG1JbnN0YWxsKFwicHJvZFwiKX1cblxuRlJPTSBub2RlOjI0LWJvb2t3b3JtLXNsaW0gQVMgcnVuXG5XT1JLRElSIC9hcHBcbkVOViBOT0RFX0VOVj1wcm9kdWN0aW9uXG5SVU4gY29yZXBhY2sgZW5hYmxlICYmIGNvcmVwYWNrIHByZXBhcmUgcG5wbUAxMCAtLWFjdGl2YXRlXG5cbkNPUFkgLS1mcm9tPXByb2QtZGVwcyAvYXBwL3BhY2thZ2UuanNvbiAuL1xuQ09QWSAtLWZyb209cHJvZC1kZXBzIC9hcHAvcG5wbS1sb2NrLnlhbWwqIC4vXG5DT1BZIC0tZnJvbT1idWlsZCAvYXBwL2NvbmZpZyAuL2NvbmZpZ1xuQ09QWSAtLWZyb209YnVpbGQgL2FwcC9kaXN0IC4vZGlzdFxuQ09QWSAtLWZyb209cHJvZC1kZXBzIC9hcHAvbm9kZV9tb2R1bGVzIC4vbm9kZV9tb2R1bGVzXG5DT1BZIC0tZnJvbT1wcm9kLWRlcHMgL2FwcC8ke3Byb2plY3REaXJ9L3BhY2thZ2UuanNvbiAuLyR7cHJvamVjdERpcn0vcGFja2FnZS5qc29uXG5cbkVYUE9TRSAzMDAwXG4ke3N0YXJ0Q21kfVxuIyBFbnRyeSByZXNvbHZlZCBieSBwYWNrYWdlLmpzb24gXCIke3N0YXJ0U2NyaXB0fVwiIOKGkiBub2RlICR7c3RhcnRFbnRyeX1cbmA7XG59XG5cbi8qKiBucG0gYXV0aCArIHBucG0gaW5zdGFsbC4gVG9rZW4gaXMgcmVxdWlyZWQgYWdhaW4gaW4gcHJvZC1kZXBzIChzZXBhcmF0ZSBzdGFnZSwgbm8gc3RvcmUpLiAqL1xuZnVuY3Rpb24gcmVuZGVyUG5wbUluc3RhbGwobW9kZTogXCJhbGxcIiB8IFwicHJvZFwiKTogc3RyaW5nIHtcblx0Y29uc3QgZmxhZ3MgPSBtb2RlID09PSBcInByb2RcIiA/IFwiIC0tcHJvZFwiIDogXCJcIjtcblx0cmV0dXJuIGBBUkcgTk9ERV9BVVRIX1RPS0VOPVxuUlVOIC0tbW91bnQ9dHlwZT1zZWNyZXQsaWQ9bnBtX3Rva2VuLHJlcXVpcmVkPWZhbHNlIFxcXFxcblx0aWYgWyAtZiAvcnVuL3NlY3JldHMvbnBtX3Rva2VuIF07IHRoZW4gXFxcXFxuXHRcdFRPS0VOPVwiJChjYXQgL3J1bi9zZWNyZXRzL25wbV90b2tlbilcIjsgXFxcXFxuXHRlbHNlIFxcXFxcblx0XHRUT0tFTj1cIlxcJHtOT0RFX0FVVEhfVE9LRU59XCI7IFxcXFxcblx0Zmk7IFxcXFxcblx0aWYgWyAtbiBcIiRUT0tFTlwiIF07IHRoZW4gXFxcXFxuXHRcdGVjaG8gXCIvL3JlZ2lzdHJ5Lm5wbWpzLm9yZy86X2F1dGhUb2tlbj1cXCR7VE9LRU59XCIgPiAubnBtcmM7IFxcXFxcblx0Zmk7IFxcXFxcblx0aWYgWyAtZiBwbnBtLWxvY2sueWFtbCBdOyB0aGVuIFxcXFxcblx0XHRwbnBtIGluc3RhbGwgLS1mcm96ZW4tbG9ja2ZpbGUke2ZsYWdzfTsgXFxcXFxuXHRlbHNlIFxcXFxcblx0XHRwbnBtIGluc3RhbGwke2ZsYWdzfTsgXFxcXFxuXHRmaTsgXFxcXFxuXHRybSAtZiAubnBtcmNgO1xufVxuXG5mdW5jdGlvbiBkb2NrZXJpZ25vcmVDb250ZW50KCk6IHN0cmluZyB7XG5cdHJldHVybiBbXG5cdFx0XCJub2RlX21vZHVsZXNcIixcblx0XHRcImRpc3RcIixcblx0XHRcIi5naXRcIixcblx0XHRcIi5kZXZjb250YWluZXJcIixcblx0XHRcIi52c2NvZGVcIixcblx0XHRcIi5naXRodWJcIixcblx0XHRcInBvc3RtYW5cIixcblx0XHRcIi5wb3N0bWFuXCIsXG5cdFx0XCIuZW52XCIsXG5cdFx0XCIuZW52LipcIixcblx0XHRcIiEuZW52LmV4YW1wbGVcIixcblx0XHRcImNvdmVyYWdlXCIsXG5cdFx0XCIqKi8qLnNwZWMudHNcIixcblx0XHRcIioqLyoudGVzdC50c1wiLFxuXHRcdFwiXCIsXG5cdF0uam9pbihcIlxcblwiKTtcbn1cbiJdLCJuYW1lcyI6WyJXRUxMX0tOT1dOX0ZJTEVTIiwiREVGQVVMVF9XRUJBUElfTkFNRSIsIndlYmFwaVByb2plY3REaXIiLCJ3ZWJhcGlSZWxlYXNlRW50cnkiLCJXZWJhcGlQcm9kdWN0aW9uRG9ja2VyZmlsZSIsImtleSIsIlBST0RVQ1RJT05fRE9DS0VSRklMRSIsImFwaU5hbWVzIiwib3B0aW9ucyIsImZpbGVzIiwibmFtZXMiLCJsZW5ndGgiLCJmaXJzdCIsIm5hbWVkT25seSIsInB1c2giLCJmaWxlUGF0aCIsImNvbnRlbnQiLCJkb2NrZXJpZ25vcmVDb250ZW50IiwicmVuZGVyUHJvZHVjdGlvbkRvY2tlcmZpbGUiLCJlbWl0TmFtZWQiLCJuYW1lIiwiYXBpTmFtZSIsInN0YXJ0U2NyaXB0IiwicHJvamVjdERpciIsInN0YXJ0Q21kIiwic3RhcnRFbnRyeSIsImRvY2tlcmZpbGVGbGFnIiwicmVuZGVyUG5wbUluc3RhbGwiLCJtb2RlIiwiZmxhZ3MiLCJqb2luIl0sIm1hcHBpbmdzIjoiQUFBQSxTQUFTQSxnQkFBZ0IsUUFBUSx3QkFBd0I7QUFFekQsU0FBU0MsbUJBQW1CLEVBQUVDLGdCQUFnQixFQUFFQyxrQkFBa0IsUUFBUSxjQUFjO0FBT3hGOzs7Ozs7Ozs7Q0FTQyxHQUNELE9BQU8sTUFBTUM7OztJQUNJQyxNQUFNTCxpQkFBaUJNLHFCQUFxQixDQUFDO0lBRTdELFlBQ0MsQUFBaUJDLFdBQThCO1FBQUNOO0tBQW9CLEVBQ3BFLEFBQWlCTyxVQUF1QyxDQUFDLENBQUMsQ0FDekQ7YUFGZ0JELFdBQUFBO2FBQ0FDLFVBQUFBO0lBQ2Y7SUFFSUMsUUFBc0I7UUFDNUIsTUFBTUMsUUFBUSxJQUFJLENBQUNILFFBQVEsQ0FBQ0ksTUFBTSxHQUFHLElBQUksSUFBSSxDQUFDSixRQUFRLEdBQUc7WUFBQ047U0FBb0I7UUFDOUUsTUFBTVcsUUFBUUYsS0FBSyxDQUFDLEVBQUUsSUFBSVQ7UUFDMUIsTUFBTVEsUUFBc0IsRUFBRTtRQUU5QixJQUFJLENBQUMsSUFBSSxDQUFDRCxPQUFPLENBQUNLLFNBQVMsRUFBRTtZQUM1QkosTUFBTUssSUFBSSxDQUFDO2dCQUNWQyxVQUFVO2dCQUNWQyxTQUFTQztZQUNWO1lBQ0FSLE1BQU1LLElBQUksQ0FBQztnQkFDVkMsVUFBVTtnQkFDVkMsU0FBU0UsMkJBQTJCTixPQUFPO1lBQzVDO1FBQ0Q7UUFFQSxNQUFNTyxZQUNMLElBQUksQ0FBQ1gsT0FBTyxDQUFDSyxTQUFTLElBQUlILE1BQU1DLE1BQU0sR0FBRyxLQUFLQyxVQUFVWDtRQUN6RCxJQUFJa0IsV0FBVztZQUNkLEtBQUssTUFBTUMsUUFBUVYsTUFBTztnQkFDekJELE1BQU1LLElBQUksQ0FBQztvQkFDVkMsVUFBVSxDQUFDLFdBQVcsRUFBRUssTUFBTTtvQkFDOUJKLFNBQVNFLDJCQUEyQkUsTUFBTSxDQUFDLE1BQU0sRUFBRUEsTUFBTTtnQkFDMUQ7WUFDRDtRQUNEO1FBRUEsT0FBT1g7SUFDUjtBQUNEO0FBRUEsT0FBTyxTQUFTUywyQkFBMkJHLE9BQWUsRUFBRUMsV0FBbUI7SUFDOUUsTUFBTUMsYUFBYXJCLGlCQUFpQm1CO0lBQ3BDLE1BQU1HLFdBQ0xGLGdCQUFnQixVQUNiLDBCQUNBLENBQUMscUJBQXFCLEVBQUVBLFlBQVksRUFBRSxDQUFDO0lBQzNDLE1BQU1HLGFBQWF0QixtQkFBbUJrQjtJQUN0QyxNQUFNSyxpQkFBaUJKLGdCQUFnQixVQUFVLEtBQUssQ0FBQyxDQUFDLEVBQUVELFNBQVM7SUFFbkUsT0FBTyxDQUFDOzs7c0RBRzZDLEVBQUVLLGVBQWU7Ozs7Ozs7Ozs7Ozs7Ozs7O0tBaUJsRSxFQUFFSCxXQUFXLEdBQUcsRUFBRUEsV0FBVzs7QUFFbEMsRUFBRUksa0JBQWtCLE9BQU87Ozs7Ozs7Ozs7O0tBV3RCLEVBQUVKLFdBQVcsZ0JBQWdCLEVBQUVBLFdBQVc7O0FBRS9DLEVBQUVJLGtCQUFrQixRQUFROzs7Ozs7Ozs7Ozs7MkJBWUQsRUFBRUosV0FBVyxnQkFBZ0IsRUFBRUEsV0FBVzs7O0FBR3JFLEVBQUVDLFNBQVM7a0NBQ3VCLEVBQUVGLFlBQVksU0FBUyxFQUFFRyxXQUFXO0FBQ3RFLENBQUM7QUFDRDtBQUVBLDhGQUE4RixHQUM5RixTQUFTRSxrQkFBa0JDLElBQW9CO0lBQzlDLE1BQU1DLFFBQVFELFNBQVMsU0FBUyxZQUFZO0lBQzVDLE9BQU8sQ0FBQzs7Ozs7Ozs7Ozs7Z0NBV3VCLEVBQUVDLE1BQU07O2NBRTFCLEVBQUVBLE1BQU07O2FBRVQsQ0FBQztBQUNkO0FBRUEsU0FBU1o7SUFDUixPQUFPO1FBQ047UUFDQTtRQUNBO1FBQ0E7UUFDQTtRQUNBO1FBQ0E7UUFDQTtRQUNBO1FBQ0E7UUFDQTtRQUNBO1FBQ0E7UUFDQTtRQUNBO0tBQ0EsQ0FBQ2EsSUFBSSxDQUFDO0FBQ1IifQ==
@@ -0,0 +1,42 @@
1
+ const SAMPLE_CONFIG_CONTENT = `export class SampleConfig {\n\tpublic greeting: string = "";\n}\n`;
2
+ const SAMPLE_SERVICE_CONTENT = [
3
+ `import { inject, injectable } from "@decohere/crucible/decorators";`,
4
+ `import { ConfigurationServiceToken } from "@decohere/nexus/configuration";`,
5
+ `import type { IConfigurationService } from "@decohere/nexus/configuration";`,
6
+ `import { SampleConfig } from "../sample.config.js";`,
7
+ ``,
8
+ `@injectable()`,
9
+ `export class SampleService {`,
10
+ `\tpublic constructor(`,
11
+ `\t\t@inject(ConfigurationServiceToken) private readonly config: IConfigurationService,`,
12
+ `\t) {}`,
13
+ ``,
14
+ `\tpublic async getGreeting(): Promise<string> {`,
15
+ `\t\tconst config = await this.config.get(SampleConfig);`,
16
+ `\t\treturn config.greeting;`,
17
+ `\t}`,
18
+ `}`,
19
+ ``
20
+ ].join("\n");
21
+ export class SampleConfigModel {
22
+ files() {
23
+ return [
24
+ {
25
+ filePath: "src/sample.config.ts",
26
+ content: SAMPLE_CONFIG_CONTENT
27
+ }
28
+ ];
29
+ }
30
+ }
31
+ export class SampleServiceModel {
32
+ files() {
33
+ return [
34
+ {
35
+ filePath: "src/services/sample.service.ts",
36
+ content: SAMPLE_SERVICE_CONTENT
37
+ }
38
+ ];
39
+ }
40
+ }
41
+
42
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL3J1bm5lci93b3JrL2RlY29oZXJlL2RlY29oZXJlL3Byb2plY3RzL3NjYWZmb2xkL3NyYy93ZWJhcGkvbW9kZWxzL3NhbXBsZS1maWxlcy5tb2RlbC50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgdHlwZSB7IFNvdXJjZUZpbGUsIFNvdXJjZUZpbGVQcm92aWRlciB9IGZyb20gXCIuLi8uLi9tb2RlbHMvc291cmNlLWZpbGUuanNcIjtcblxuY29uc3QgU0FNUExFX0NPTkZJR19DT05URU5UID0gYGV4cG9ydCBjbGFzcyBTYW1wbGVDb25maWcge1xcblxcdHB1YmxpYyBncmVldGluZzogc3RyaW5nID0gXCJcIjtcXG59XFxuYDtcblxuY29uc3QgU0FNUExFX1NFUlZJQ0VfQ09OVEVOVCA9IFtcblx0YGltcG9ydCB7IGluamVjdCwgaW5qZWN0YWJsZSB9IGZyb20gXCJAZGVjb2hlcmUvY3J1Y2libGUvZGVjb3JhdG9yc1wiO2AsXG5cdGBpbXBvcnQgeyBDb25maWd1cmF0aW9uU2VydmljZVRva2VuIH0gZnJvbSBcIkBkZWNvaGVyZS9uZXh1cy9jb25maWd1cmF0aW9uXCI7YCxcblx0YGltcG9ydCB0eXBlIHsgSUNvbmZpZ3VyYXRpb25TZXJ2aWNlIH0gZnJvbSBcIkBkZWNvaGVyZS9uZXh1cy9jb25maWd1cmF0aW9uXCI7YCxcblx0YGltcG9ydCB7IFNhbXBsZUNvbmZpZyB9IGZyb20gXCIuLi9zYW1wbGUuY29uZmlnLmpzXCI7YCxcblx0YGAsXG5cdGBAaW5qZWN0YWJsZSgpYCxcblx0YGV4cG9ydCBjbGFzcyBTYW1wbGVTZXJ2aWNlIHtgLFxuXHRgXFx0cHVibGljIGNvbnN0cnVjdG9yKGAsXG5cdGBcXHRcXHRAaW5qZWN0KENvbmZpZ3VyYXRpb25TZXJ2aWNlVG9rZW4pIHByaXZhdGUgcmVhZG9ubHkgY29uZmlnOiBJQ29uZmlndXJhdGlvblNlcnZpY2UsYCxcblx0YFxcdCkge31gLFxuXHRgYCxcblx0YFxcdHB1YmxpYyBhc3luYyBnZXRHcmVldGluZygpOiBQcm9taXNlPHN0cmluZz4ge2AsXG5cdGBcXHRcXHRjb25zdCBjb25maWcgPSBhd2FpdCB0aGlzLmNvbmZpZy5nZXQoU2FtcGxlQ29uZmlnKTtgLFxuXHRgXFx0XFx0cmV0dXJuIGNvbmZpZy5ncmVldGluZztgLFxuXHRgXFx0fWAsXG5cdGB9YCxcblx0YGAsXG5dLmpvaW4oXCJcXG5cIik7XG5cbmV4cG9ydCBjbGFzcyBTYW1wbGVDb25maWdNb2RlbCBpbXBsZW1lbnRzIFNvdXJjZUZpbGVQcm92aWRlciB7XG5cdHB1YmxpYyBmaWxlcygpOiBTb3VyY2VGaWxlW10ge1xuXHRcdHJldHVybiBbXG5cdFx0XHR7XG5cdFx0XHRcdGZpbGVQYXRoOiBcInNyYy9zYW1wbGUuY29uZmlnLnRzXCIsXG5cdFx0XHRcdGNvbnRlbnQ6IFNBTVBMRV9DT05GSUdfQ09OVEVOVCxcblx0XHRcdH0sXG5cdFx0XTtcblx0fVxufVxuXG5leHBvcnQgY2xhc3MgU2FtcGxlU2VydmljZU1vZGVsIGltcGxlbWVudHMgU291cmNlRmlsZVByb3ZpZGVyIHtcblx0cHVibGljIGZpbGVzKCk6IFNvdXJjZUZpbGVbXSB7XG5cdFx0cmV0dXJuIFtcblx0XHRcdHtcblx0XHRcdFx0ZmlsZVBhdGg6IFwic3JjL3NlcnZpY2VzL3NhbXBsZS5zZXJ2aWNlLnRzXCIsXG5cdFx0XHRcdGNvbnRlbnQ6IFNBTVBMRV9TRVJWSUNFX0NPTlRFTlQsXG5cdFx0XHR9LFxuXHRcdF07XG5cdH1cbn1cbiJdLCJuYW1lcyI6WyJTQU1QTEVfQ09ORklHX0NPTlRFTlQiLCJTQU1QTEVfU0VSVklDRV9DT05URU5UIiwiam9pbiIsIlNhbXBsZUNvbmZpZ01vZGVsIiwiZmlsZXMiLCJmaWxlUGF0aCIsImNvbnRlbnQiLCJTYW1wbGVTZXJ2aWNlTW9kZWwiXSwibWFwcGluZ3MiOiJBQUVBLE1BQU1BLHdCQUF3QixDQUFDLGlFQUFpRSxDQUFDO0FBRWpHLE1BQU1DLHlCQUF5QjtJQUM5QixDQUFDLG1FQUFtRSxDQUFDO0lBQ3JFLENBQUMsMEVBQTBFLENBQUM7SUFDNUUsQ0FBQywyRUFBMkUsQ0FBQztJQUM3RSxDQUFDLG1EQUFtRCxDQUFDO0lBQ3JELEVBQUU7SUFDRixDQUFDLGFBQWEsQ0FBQztJQUNmLENBQUMsNEJBQTRCLENBQUM7SUFDOUIsQ0FBQyxxQkFBcUIsQ0FBQztJQUN2QixDQUFDLHNGQUFzRixDQUFDO0lBQ3hGLENBQUMsTUFBTSxDQUFDO0lBQ1IsRUFBRTtJQUNGLENBQUMsK0NBQStDLENBQUM7SUFDakQsQ0FBQyx1REFBdUQsQ0FBQztJQUN6RCxDQUFDLDJCQUEyQixDQUFDO0lBQzdCLENBQUMsR0FBRyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7SUFDSCxFQUFFO0NBQ0YsQ0FBQ0MsSUFBSSxDQUFDO0FBRVAsT0FBTyxNQUFNQztJQUNMQyxRQUFzQjtRQUM1QixPQUFPO1lBQ047Z0JBQ0NDLFVBQVU7Z0JBQ1ZDLFNBQVNOO1lBQ1Y7U0FDQTtJQUNGO0FBQ0Q7QUFFQSxPQUFPLE1BQU1PO0lBQ0xILFFBQXNCO1FBQzVCLE9BQU87WUFDTjtnQkFDQ0MsVUFBVTtnQkFDVkMsU0FBU0w7WUFDVjtTQUNBO0lBQ0Y7QUFDRCJ9
@@ -0,0 +1,20 @@
1
+ import { DockerfileModel } from "../../models/docker-image.model.js";
2
+ import { CREATE_VERSION, DEVCONTAINER_IMAGE_REPOSITORY } from "../../version.js";
3
+ /**
4
+ * Scaffolded app `.devcontainer/Dockerfile` — thin `FROM` the published base image.
5
+ * Optional feature layers (e.g. postgresql-client) append via `addLayer`.
6
+ */ export class WebapiDevContainer extends DockerfileModel {
7
+ constructor(baseImage = `${DEVCONTAINER_IMAGE_REPOSITORY}:${CREATE_VERSION}`){
8
+ super(baseImage);
9
+ }
10
+ files() {
11
+ return [
12
+ {
13
+ filePath: ".devcontainer/Dockerfile",
14
+ content: this.build()
15
+ }
16
+ ];
17
+ }
18
+ }
19
+
20
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL3J1bm5lci93b3JrL2RlY29oZXJlL2RlY29oZXJlL3Byb2plY3RzL3NjYWZmb2xkL3NyYy93ZWJhcGkvbW9kZWxzL3dlYmFwaS1pbWFnZS5tb2RlbC50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBEb2NrZXJmaWxlTW9kZWwgfSBmcm9tIFwiLi4vLi4vbW9kZWxzL2RvY2tlci1pbWFnZS5tb2RlbC5qc1wiO1xuaW1wb3J0IHsgQ1JFQVRFX1ZFUlNJT04sIERFVkNPTlRBSU5FUl9JTUFHRV9SRVBPU0lUT1JZIH0gZnJvbSBcIi4uLy4uL3ZlcnNpb24uanNcIjtcblxuLyoqXG4gKiBTY2FmZm9sZGVkIGFwcCBgLmRldmNvbnRhaW5lci9Eb2NrZXJmaWxlYCDigJQgdGhpbiBgRlJPTWAgdGhlIHB1Ymxpc2hlZCBiYXNlIGltYWdlLlxuICogT3B0aW9uYWwgZmVhdHVyZSBsYXllcnMgKGUuZy4gcG9zdGdyZXNxbC1jbGllbnQpIGFwcGVuZCB2aWEgYGFkZExheWVyYC5cbiAqL1xuZXhwb3J0IGNsYXNzIFdlYmFwaURldkNvbnRhaW5lciBleHRlbmRzIERvY2tlcmZpbGVNb2RlbCB7XG5cdHB1YmxpYyBjb25zdHJ1Y3RvcihiYXNlSW1hZ2UgPSBgJHtERVZDT05UQUlORVJfSU1BR0VfUkVQT1NJVE9SWX06JHtDUkVBVEVfVkVSU0lPTn1gKSB7XG5cdFx0c3VwZXIoYmFzZUltYWdlKTtcblx0fVxuXG5cdHB1YmxpYyBmaWxlcygpIHtcblx0XHRyZXR1cm4gW1xuXHRcdFx0e1xuXHRcdFx0XHRmaWxlUGF0aDogXCIuZGV2Y29udGFpbmVyL0RvY2tlcmZpbGVcIixcblx0XHRcdFx0Y29udGVudDogdGhpcy5idWlsZCgpLFxuXHRcdFx0fSxcblx0XHRdO1xuXHR9XG59XG4iXSwibmFtZXMiOlsiRG9ja2VyZmlsZU1vZGVsIiwiQ1JFQVRFX1ZFUlNJT04iLCJERVZDT05UQUlORVJfSU1BR0VfUkVQT1NJVE9SWSIsIldlYmFwaURldkNvbnRhaW5lciIsImJhc2VJbWFnZSIsImZpbGVzIiwiZmlsZVBhdGgiLCJjb250ZW50IiwiYnVpbGQiXSwibWFwcGluZ3MiOiJBQUFBLFNBQVNBLGVBQWUsUUFBUSxxQ0FBcUM7QUFDckUsU0FBU0MsY0FBYyxFQUFFQyw2QkFBNkIsUUFBUSxtQkFBbUI7QUFFakY7OztDQUdDLEdBQ0QsT0FBTyxNQUFNQywyQkFBMkJIO0lBQ3ZDLFlBQW1CSSxZQUFZLEdBQUdGLDhCQUE4QixDQUFDLEVBQUVELGdCQUFnQixDQUFFO1FBQ3BGLEtBQUssQ0FBQ0c7SUFDUDtJQUVPQyxRQUFRO1FBQ2QsT0FBTztZQUNOO2dCQUNDQyxVQUFVO2dCQUNWQyxTQUFTLElBQUksQ0FBQ0MsS0FBSztZQUNwQjtTQUNBO0lBQ0Y7QUFDRCJ9