@decohere/scaffold 0.0.1-dev.100
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.
- package/commonjs/src/add-api.action.js +37 -0
- package/commonjs/src/add-api.command.js +39 -0
- package/commonjs/src/add.command.js +22 -0
- package/commonjs/src/add.module.js +24 -0
- package/commonjs/src/auth0-configure.action.js +28 -0
- package/commonjs/src/auth0-configure.command.js +24 -0
- package/commonjs/src/auth0-login.action.js +28 -0
- package/commonjs/src/auth0-login.command.js +23 -0
- package/commonjs/src/auth0.command.js +22 -0
- package/commonjs/src/auth0.module.js +28 -0
- package/commonjs/src/cli.js +7 -0
- package/commonjs/src/create.command.js +22 -0
- package/commonjs/src/create.module.js +24 -0
- package/commonjs/src/domain/prompt.js +62 -0
- package/commonjs/src/index.js +48 -0
- package/commonjs/src/models/compose.model.js +258 -0
- package/commonjs/src/models/config-yaml.model.js +86 -0
- package/commonjs/src/models/const.js +30 -0
- package/commonjs/src/models/dev-container.model.js +172 -0
- package/commonjs/src/models/docker-image.model.js +277 -0
- package/commonjs/src/models/env-file.model.js +48 -0
- package/commonjs/src/models/gitignore.model.js +48 -0
- package/commonjs/src/models/launch-json.model.js +70 -0
- package/commonjs/src/models/package-json.model.js +156 -0
- package/commonjs/src/models/project.model.js +132 -0
- package/commonjs/src/models/source-file.js +4 -0
- package/commonjs/src/models/tsconfig.model.js +32 -0
- package/commonjs/src/models/vitest-config.model.js +33 -0
- package/commonjs/src/models/vscode-settings.model.js +29 -0
- package/commonjs/src/program.js +64 -0
- package/commonjs/src/resolve-target-dir.js +17 -0
- package/commonjs/src/services/scaffold.service.js +60 -0
- package/commonjs/src/version.js +55 -0
- package/commonjs/src/webapi/api-name.js +93 -0
- package/commonjs/src/webapi/auth0-commands.js +250 -0
- package/commonjs/src/webapi/authorize-scopes.js +79 -0
- package/commonjs/src/webapi/cli-options.js +99 -0
- package/commonjs/src/webapi/const.js +54 -0
- package/commonjs/src/webapi/create-api.js +265 -0
- package/commonjs/src/webapi/devcontainer/codebase-rag-mcp.js +164 -0
- package/commonjs/src/webapi/devcontainer/codebase-rag-mcp.ts +182 -0
- package/commonjs/src/webapi/devcontainer/host-scripts.js +50 -0
- package/commonjs/src/webapi/devcontainer/templates/codebase-rag.env.example +3 -0
- package/commonjs/src/webapi/devcontainer/templates/initialize.sh +169 -0
- package/commonjs/src/webapi/devcontainer/templates/post-create.sh +35 -0
- package/commonjs/src/webapi/devcontainer/templates/post-start.sh +65 -0
- package/commonjs/src/webapi/devcontainer/templates/tty-prompt.sh +38 -0
- package/commonjs/src/webapi/features/auth.feature.js +408 -0
- package/commonjs/src/webapi/features/auth0-cli.js +472 -0
- package/commonjs/src/webapi/features/biome-format.js +47 -0
- package/commonjs/src/webapi/features/database.feature.js +432 -0
- package/commonjs/src/webapi/features/finalize.feature.js +93 -0
- package/commonjs/src/webapi/features/postman.feature.js +322 -0
- package/commonjs/src/webapi/models/api-package-json.model.js +58 -0
- package/commonjs/src/webapi/models/auth-config.model.js +24 -0
- package/commonjs/src/webapi/models/controller-source-file.model.js +190 -0
- package/commonjs/src/webapi/models/github-ci.model.js +193 -0
- package/commonjs/src/webapi/models/main-source-file.model.js +165 -0
- package/commonjs/src/webapi/models/production-dockerfile.model.js +75 -0
- package/commonjs/src/webapi/models/sample-files.model.js +58 -0
- package/commonjs/src/webapi/models/webapi-image.model.js +25 -0
- package/commonjs/src/webapi/postman/hello-openapi.js +173 -0
- package/commonjs/src/webapi/postman/local-view.js +182 -0
- package/commonjs/src/webapi/postman/openapi-to-postman.js +200 -0
- package/commonjs/src/webapi/workspace-readme.js +109 -0
- package/commonjs/src/webapi.action.js +28 -0
- package/commonjs/src/webapi.command.js +43 -0
- package/es6/src/add-api.action.js +27 -0
- package/es6/src/add-api.command.js +29 -0
- package/es6/src/add.command.js +12 -0
- package/es6/src/add.module.js +14 -0
- package/es6/src/auth0-configure.action.js +18 -0
- package/es6/src/auth0-configure.command.js +14 -0
- package/es6/src/auth0-login.action.js +18 -0
- package/es6/src/auth0-login.command.js +13 -0
- package/es6/src/auth0.command.js +12 -0
- package/es6/src/auth0.module.js +18 -0
- package/es6/src/cli.js +3 -0
- package/es6/src/create.command.js +12 -0
- package/es6/src/create.module.js +14 -0
- package/es6/src/domain/prompt.js +41 -0
- package/es6/src/index.js +9 -0
- package/es6/src/models/compose.model.js +254 -0
- package/es6/src/models/config-yaml.model.js +74 -0
- package/es6/src/models/const.js +20 -0
- package/es6/src/models/dev-container.model.js +162 -0
- package/es6/src/models/docker-image.model.js +235 -0
- package/es6/src/models/env-file.model.js +44 -0
- package/es6/src/models/gitignore.model.js +38 -0
- package/es6/src/models/launch-json.model.js +60 -0
- package/es6/src/models/package-json.model.js +141 -0
- package/es6/src/models/project.model.js +117 -0
- package/es6/src/models/source-file.js +1 -0
- package/es6/src/models/tsconfig.model.js +22 -0
- package/es6/src/models/vitest-config.model.js +23 -0
- package/es6/src/models/vscode-settings.model.js +19 -0
- package/es6/src/program.js +46 -0
- package/es6/src/resolve-target-dir.js +7 -0
- package/es6/src/services/scaffold.service.js +50 -0
- package/es6/src/version.js +34 -0
- package/es6/src/webapi/api-name.js +57 -0
- package/es6/src/webapi/auth0-commands.js +185 -0
- package/es6/src/webapi/authorize-scopes.js +55 -0
- package/es6/src/webapi/cli-options.js +34 -0
- package/es6/src/webapi/const.js +21 -0
- package/es6/src/webapi/create-api.js +245 -0
- package/es6/src/webapi/devcontainer/codebase-rag-mcp.js +154 -0
- package/es6/src/webapi/devcontainer/codebase-rag-mcp.ts +182 -0
- package/es6/src/webapi/devcontainer/host-scripts.js +29 -0
- package/es6/src/webapi/devcontainer/templates/codebase-rag.env.example +3 -0
- package/es6/src/webapi/devcontainer/templates/initialize.sh +169 -0
- package/es6/src/webapi/devcontainer/templates/post-create.sh +35 -0
- package/es6/src/webapi/devcontainer/templates/post-start.sh +65 -0
- package/es6/src/webapi/devcontainer/templates/tty-prompt.sh +38 -0
- package/es6/src/webapi/features/auth.feature.js +357 -0
- package/es6/src/webapi/features/auth0-cli.js +406 -0
- package/es6/src/webapi/features/biome-format.js +40 -0
- package/es6/src/webapi/features/database.feature.js +422 -0
- package/es6/src/webapi/features/finalize.feature.js +83 -0
- package/es6/src/webapi/features/postman.feature.js +256 -0
- package/es6/src/webapi/models/api-package-json.model.js +53 -0
- package/es6/src/webapi/models/auth-config.model.js +20 -0
- package/es6/src/webapi/models/controller-source-file.model.js +181 -0
- package/es6/src/webapi/models/github-ci.model.js +186 -0
- package/es6/src/webapi/models/main-source-file.model.js +161 -0
- package/es6/src/webapi/models/production-dockerfile.model.js +66 -0
- package/es6/src/webapi/models/sample-files.model.js +40 -0
- package/es6/src/webapi/models/webapi-image.model.js +18 -0
- package/es6/src/webapi/postman/hello-openapi.js +166 -0
- package/es6/src/webapi/postman/local-view.js +167 -0
- package/es6/src/webapi/postman/openapi-to-postman.js +177 -0
- package/es6/src/webapi/workspace-readme.js +88 -0
- package/es6/src/webapi.action.js +18 -0
- package/es6/src/webapi.command.js +33 -0
- package/package.json +36 -0
- package/src/webapi/devcontainer/codebase-rag-mcp.ts +182 -0
- package/src/webapi/devcontainer/templates/codebase-rag.env.example +3 -0
- package/src/webapi/devcontainer/templates/initialize.sh +169 -0
- package/src/webapi/devcontainer/templates/post-create.sh +35 -0
- package/src/webapi/devcontainer/templates/post-start.sh +65 -0
- package/src/webapi/devcontainer/templates/tty-prompt.sh +38 -0
- package/types/src/add-api.action.d.ts +13 -0
- package/types/src/add-api.command.d.ts +7 -0
- package/types/src/add.command.d.ts +6 -0
- package/types/src/add.module.d.ts +14 -0
- package/types/src/auth0-configure.action.d.ts +7 -0
- package/types/src/auth0-configure.command.d.ts +6 -0
- package/types/src/auth0-login.action.d.ts +4 -0
- package/types/src/auth0-login.command.d.ts +6 -0
- package/types/src/auth0.command.d.ts +6 -0
- package/types/src/auth0.module.d.ts +18 -0
- package/types/src/cli.d.ts +2 -0
- package/types/src/create.command.d.ts +6 -0
- package/types/src/create.module.d.ts +14 -0
- package/types/src/domain/prompt.d.ts +4 -0
- package/types/src/index.d.ts +13 -0
- package/types/src/models/compose.model.d.ts +73 -0
- package/types/src/models/config-yaml.model.d.ts +27 -0
- package/types/src/models/const.d.ts +20 -0
- package/types/src/models/dev-container.model.d.ts +49 -0
- package/types/src/models/docker-image.model.d.ts +90 -0
- package/types/src/models/env-file.model.d.ts +16 -0
- package/types/src/models/gitignore.model.d.ts +9 -0
- package/types/src/models/launch-json.model.d.ts +7 -0
- package/types/src/models/package-json.model.d.ts +36 -0
- package/types/src/models/project.model.d.ts +60 -0
- package/types/src/models/source-file.d.ts +11 -0
- package/types/src/models/tsconfig.model.d.ts +5 -0
- package/types/src/models/vitest-config.model.d.ts +5 -0
- package/types/src/models/vscode-settings.model.d.ts +7 -0
- package/types/src/program.d.ts +3 -0
- package/types/src/resolve-target-dir.d.ts +5 -0
- package/types/src/services/scaffold.service.d.ts +22 -0
- package/types/src/version.d.ts +6 -0
- package/types/src/webapi/api-name.d.ts +14 -0
- package/types/src/webapi/auth0-commands.d.ts +11 -0
- package/types/src/webapi/authorize-scopes.d.ts +7 -0
- package/types/src/webapi/cli-options.d.ts +6 -0
- package/types/src/webapi/const.d.ts +19 -0
- package/types/src/webapi/create-api.d.ts +15 -0
- package/types/src/webapi/devcontainer/codebase-rag-mcp.d.ts +32 -0
- package/types/src/webapi/devcontainer/codebase-rag-mcp.ts +182 -0
- package/types/src/webapi/devcontainer/host-scripts.d.ts +7 -0
- package/types/src/webapi/devcontainer/templates/codebase-rag.env.example +3 -0
- package/types/src/webapi/devcontainer/templates/initialize.sh +169 -0
- package/types/src/webapi/devcontainer/templates/post-create.sh +35 -0
- package/types/src/webapi/devcontainer/templates/post-start.sh +65 -0
- package/types/src/webapi/devcontainer/templates/tty-prompt.sh +38 -0
- package/types/src/webapi/features/auth.feature.d.ts +10 -0
- package/types/src/webapi/features/auth0-cli.d.ts +84 -0
- package/types/src/webapi/features/biome-format.d.ts +5 -0
- package/types/src/webapi/features/database.feature.d.ts +7 -0
- package/types/src/webapi/features/finalize.feature.d.ts +2 -0
- package/types/src/webapi/features/postman.feature.d.ts +16 -0
- package/types/src/webapi/models/api-package-json.model.d.ts +18 -0
- package/types/src/webapi/models/auth-config.model.d.ts +26 -0
- package/types/src/webapi/models/controller-source-file.model.d.ts +46 -0
- package/types/src/webapi/models/github-ci.model.d.ts +9 -0
- package/types/src/webapi/models/main-source-file.model.d.ts +54 -0
- package/types/src/webapi/models/production-dockerfile.model.d.ts +18 -0
- package/types/src/webapi/models/sample-files.model.d.ts +7 -0
- package/types/src/webapi/models/webapi-image.model.d.ts +12 -0
- package/types/src/webapi/postman/hello-openapi.d.ts +19 -0
- package/types/src/webapi/postman/local-view.d.ts +17 -0
- package/types/src/webapi/postman/openapi-to-postman.d.ts +62 -0
- package/types/src/webapi/workspace-readme.d.ts +18 -0
- package/types/src/webapi.action.d.ts +14 -0
- package/types/src/webapi.command.d.ts +11 -0
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
Object.defineProperty(exports, "GithubCiWorkflows", {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: function() {
|
|
8
|
+
return GithubCiWorkflows;
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
const _const = require("../../models/const.js");
|
|
12
|
+
class GithubCiWorkflows {
|
|
13
|
+
key = _const.WELL_KNOWN_FILES.GITHUB_CI;
|
|
14
|
+
files() {
|
|
15
|
+
return [
|
|
16
|
+
{
|
|
17
|
+
filePath: ".github/actions/setup-node-pnpm/action.yml",
|
|
18
|
+
content: `name: Setup Node + pnpm
|
|
19
|
+
description: Install pnpm and Node, configure npm registry auth, install deps
|
|
20
|
+
inputs:
|
|
21
|
+
node-version:
|
|
22
|
+
description: Node.js version
|
|
23
|
+
required: false
|
|
24
|
+
default: "24"
|
|
25
|
+
pnpm-version:
|
|
26
|
+
description: pnpm version
|
|
27
|
+
required: false
|
|
28
|
+
default: "10"
|
|
29
|
+
install:
|
|
30
|
+
description: Run pnpm install --frozen-lockfile
|
|
31
|
+
required: false
|
|
32
|
+
default: "true"
|
|
33
|
+
|
|
34
|
+
runs:
|
|
35
|
+
using: composite
|
|
36
|
+
steps:
|
|
37
|
+
- uses: pnpm/action-setup@v4
|
|
38
|
+
with:
|
|
39
|
+
version: \${{ inputs.pnpm-version }}
|
|
40
|
+
|
|
41
|
+
- uses: actions/setup-node@v4
|
|
42
|
+
with:
|
|
43
|
+
node-version: \${{ inputs.node-version }}
|
|
44
|
+
cache: pnpm
|
|
45
|
+
cache-dependency-path: pnpm-lock.yaml
|
|
46
|
+
|
|
47
|
+
- name: Configure npm auth
|
|
48
|
+
shell: bash
|
|
49
|
+
run: |
|
|
50
|
+
if [[ -n "\${NODE_AUTH_TOKEN:-}" ]]; then
|
|
51
|
+
echo "//registry.npmjs.org/:_authToken=\${NODE_AUTH_TOKEN}" >> .npmrc
|
|
52
|
+
fi
|
|
53
|
+
|
|
54
|
+
- name: Install dependencies
|
|
55
|
+
if: inputs.install == 'true'
|
|
56
|
+
shell: bash
|
|
57
|
+
run: |
|
|
58
|
+
if [[ -f pnpm-lock.yaml ]]; then
|
|
59
|
+
pnpm install --frozen-lockfile
|
|
60
|
+
else
|
|
61
|
+
pnpm install
|
|
62
|
+
fi
|
|
63
|
+
`
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
filePath: ".github/workflows/ci.yml",
|
|
67
|
+
content: `name: CI
|
|
68
|
+
on:
|
|
69
|
+
push:
|
|
70
|
+
branches:
|
|
71
|
+
- "*"
|
|
72
|
+
pull_request:
|
|
73
|
+
workflow_dispatch:
|
|
74
|
+
concurrency:
|
|
75
|
+
group: ci-\${{ github.ref }}
|
|
76
|
+
cancel-in-progress: true
|
|
77
|
+
env:
|
|
78
|
+
NODE_AUTH_TOKEN: \${{ secrets.NODE_AUTH_TOKEN }}
|
|
79
|
+
SCRIBE_LOG_LEVEL: info
|
|
80
|
+
|
|
81
|
+
jobs:
|
|
82
|
+
lint:
|
|
83
|
+
runs-on: ubuntu-latest
|
|
84
|
+
timeout-minutes: 15
|
|
85
|
+
permissions:
|
|
86
|
+
contents: read
|
|
87
|
+
steps:
|
|
88
|
+
- uses: actions/checkout@v4
|
|
89
|
+
with:
|
|
90
|
+
fetch-depth: 1
|
|
91
|
+
|
|
92
|
+
- uses: ./.github/actions/setup-node-pnpm
|
|
93
|
+
|
|
94
|
+
- name: Lint and typecheck
|
|
95
|
+
run: |
|
|
96
|
+
set +e
|
|
97
|
+
pnpm run lint:check &
|
|
98
|
+
lint_pid=$!
|
|
99
|
+
pnpm run typecheck &
|
|
100
|
+
tsc_pid=$!
|
|
101
|
+
wait "$lint_pid"
|
|
102
|
+
lint_code=$?
|
|
103
|
+
wait "$tsc_pid"
|
|
104
|
+
tsc_code=$?
|
|
105
|
+
set -e
|
|
106
|
+
if [[ "$lint_code" -ne 0 || "$tsc_code" -ne 0 ]]; then
|
|
107
|
+
exit 1
|
|
108
|
+
fi
|
|
109
|
+
|
|
110
|
+
test:
|
|
111
|
+
runs-on: ubuntu-latest
|
|
112
|
+
timeout-minutes: 20
|
|
113
|
+
permissions:
|
|
114
|
+
contents: read
|
|
115
|
+
steps:
|
|
116
|
+
- uses: actions/checkout@v4
|
|
117
|
+
with:
|
|
118
|
+
fetch-depth: 1
|
|
119
|
+
|
|
120
|
+
- uses: ./.github/actions/setup-node-pnpm
|
|
121
|
+
|
|
122
|
+
- name: Test
|
|
123
|
+
run: pnpm test
|
|
124
|
+
|
|
125
|
+
- name: Build and package (default branch)
|
|
126
|
+
if: github.ref == format('refs/heads/{0}', github.event.repository.default_branch)
|
|
127
|
+
run: pnpm run package
|
|
128
|
+
|
|
129
|
+
ci:
|
|
130
|
+
needs: [lint, test]
|
|
131
|
+
if: always()
|
|
132
|
+
runs-on: ubuntu-latest
|
|
133
|
+
timeout-minutes: 5
|
|
134
|
+
steps:
|
|
135
|
+
- name: Aggregate
|
|
136
|
+
run: |
|
|
137
|
+
if [[ "\${{ needs.lint.result }}" != "success" || "\${{ needs.test.result }}" != "success" ]]; then
|
|
138
|
+
echo "CI failed (lint=\${{ needs.lint.result }} test=\${{ needs.test.result }})"
|
|
139
|
+
exit 1
|
|
140
|
+
fi
|
|
141
|
+
echo "CI passed"
|
|
142
|
+
`
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
filePath: ".github/workflows/publish.yml",
|
|
146
|
+
content: `name: Publish
|
|
147
|
+
|
|
148
|
+
on:
|
|
149
|
+
workflow_run:
|
|
150
|
+
workflows: ["CI"]
|
|
151
|
+
types: [completed]
|
|
152
|
+
|
|
153
|
+
concurrency:
|
|
154
|
+
group: publish-\${{ github.event.workflow_run.head_branch }}
|
|
155
|
+
cancel-in-progress: false
|
|
156
|
+
|
|
157
|
+
env:
|
|
158
|
+
NODE_AUTH_TOKEN: \${{ secrets.NODE_AUTH_TOKEN }}
|
|
159
|
+
SCRIBE_LOG_LEVEL: info
|
|
160
|
+
|
|
161
|
+
jobs:
|
|
162
|
+
publish:
|
|
163
|
+
if: >
|
|
164
|
+
github.event.workflow_run.conclusion == 'success' &&
|
|
165
|
+
github.event.workflow_run.head_branch == github.event.repository.default_branch
|
|
166
|
+
runs-on: ubuntu-latest
|
|
167
|
+
timeout-minutes: 30
|
|
168
|
+
permissions:
|
|
169
|
+
contents: read
|
|
170
|
+
id-token: write
|
|
171
|
+
steps:
|
|
172
|
+
- uses: actions/checkout@v4
|
|
173
|
+
with:
|
|
174
|
+
ref: \${{ github.event.workflow_run.head_sha }}
|
|
175
|
+
fetch-depth: 1
|
|
176
|
+
|
|
177
|
+
- uses: ./.github/actions/setup-node-pnpm
|
|
178
|
+
|
|
179
|
+
- name: Build release
|
|
180
|
+
run: pnpm run build
|
|
181
|
+
|
|
182
|
+
- name: Publish packages
|
|
183
|
+
run: pnpm exec forge publish --configuration release
|
|
184
|
+
# Skips packages with "private": true (e.g. the webapi app).
|
|
185
|
+
# Optional registry images: replace "Build release" above with \`pnpm run package\`, then add
|
|
186
|
+
# \`pnpm exec forge docker --configuration release --push\` after configuring GHCR/OIDC.
|
|
187
|
+
# Not enabled by default. Each API's Dockerfile copies .package/, which \`forge package\`
|
|
188
|
+
# builds, so the image build itself needs no npm token.
|
|
189
|
+
`
|
|
190
|
+
}
|
|
191
|
+
];
|
|
192
|
+
}
|
|
193
|
+
}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
Object.defineProperty(exports, "MainSourceFile", {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: function() {
|
|
8
|
+
return MainSourceFile;
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
const _const = require("../../models/const.js");
|
|
12
|
+
/** Tracks named imports from a single module path, split into values and types. */ class ImportGroup {
|
|
13
|
+
_values = [];
|
|
14
|
+
_types = [];
|
|
15
|
+
add(name, typeOnly = false) {
|
|
16
|
+
if (typeOnly) {
|
|
17
|
+
// Value import already present — value wins, skip
|
|
18
|
+
if (!this._values.includes(name) && !this._types.includes(name)) {
|
|
19
|
+
this._types.push(name);
|
|
20
|
+
}
|
|
21
|
+
} else {
|
|
22
|
+
// Promote: remove from types if it was previously type-only
|
|
23
|
+
const typeIdx = this._types.indexOf(name);
|
|
24
|
+
if (typeIdx !== -1) this._types.splice(typeIdx, 1);
|
|
25
|
+
if (!this._values.includes(name)) this._values.push(name);
|
|
26
|
+
}
|
|
27
|
+
return this;
|
|
28
|
+
}
|
|
29
|
+
render(from) {
|
|
30
|
+
const values = [
|
|
31
|
+
...this._values
|
|
32
|
+
].sort();
|
|
33
|
+
const types = [
|
|
34
|
+
...this._types
|
|
35
|
+
].sort().map((n)=>`type ${n}`);
|
|
36
|
+
return `import { ${[
|
|
37
|
+
...values,
|
|
38
|
+
...types
|
|
39
|
+
].join(", ")} } from "${from}";`;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
class MainSourceFile {
|
|
43
|
+
appName;
|
|
44
|
+
key = _const.WELL_KNOWN_FILES.MAIN_TS;
|
|
45
|
+
_sideEffectImports = [];
|
|
46
|
+
_extraImports = new Map();
|
|
47
|
+
_builderCalls = [];
|
|
48
|
+
_entities = [];
|
|
49
|
+
_repositories = [];
|
|
50
|
+
_services = [];
|
|
51
|
+
_dataSourceName;
|
|
52
|
+
_typeOrmSeed;
|
|
53
|
+
constructor(appName){
|
|
54
|
+
this.appName = appName;
|
|
55
|
+
}
|
|
56
|
+
/** Adds a bare side-effect import, e.g. `@decohere/cortex/auth`. */ addSideEffectImport(path) {
|
|
57
|
+
if (!this._sideEffectImports.includes(path)) this._sideEffectImports.push(path);
|
|
58
|
+
return this;
|
|
59
|
+
}
|
|
60
|
+
/** Adds a named import, e.g. `import { Foo } from "bar"`. */ addImport(name, from, typeOnly = false) {
|
|
61
|
+
const group = this._extraImports.get(from) ?? new ImportGroup();
|
|
62
|
+
group.add(name, typeOnly);
|
|
63
|
+
this._extraImports.set(from, group);
|
|
64
|
+
return this;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Adds a builder call inserted after `.withConfiguration()` and before
|
|
68
|
+
* `.withServices()`. Pass the call without leading dot, e.g. `.withAuth()`.
|
|
69
|
+
*/ addBuilderCall(call) {
|
|
70
|
+
this._builderCalls.push(call);
|
|
71
|
+
return this;
|
|
72
|
+
}
|
|
73
|
+
/** Adds a TypeORM entity — import and entry in `withTypeOrm({ entities })`. */ addEntity(entity) {
|
|
74
|
+
this._entities.push(entity);
|
|
75
|
+
return this;
|
|
76
|
+
}
|
|
77
|
+
/** Adds a TypeORM repository — import and entry in `withTypeOrm({ repositories })`. */ addRepository(repo) {
|
|
78
|
+
this._repositories.push(repo);
|
|
79
|
+
return this;
|
|
80
|
+
}
|
|
81
|
+
/** Adds a service registered in `.withServices()`. */ addService(service) {
|
|
82
|
+
this._services.push(service);
|
|
83
|
+
return this;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Datasource name passed to `withTypeOrm({ name })`. Must match
|
|
87
|
+
* `database.dataSources[].name` in config.yaml.
|
|
88
|
+
*/ setDataSourceName(name) {
|
|
89
|
+
this._dataSourceName = name;
|
|
90
|
+
return this;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Inline seed callback body for `withTypeOrm({ seed })`.
|
|
94
|
+
* Receives `dataSource` in scope. Example: `await dataSource.getRepository(User).save(...)`.
|
|
95
|
+
*/ setTypeOrmSeed(seedBody) {
|
|
96
|
+
this._typeOrmSeed = seedBody;
|
|
97
|
+
return this;
|
|
98
|
+
}
|
|
99
|
+
files() {
|
|
100
|
+
const imports = [
|
|
101
|
+
'import "@decohere/scribe-pino";',
|
|
102
|
+
'import "@decohere/cortex/http";'
|
|
103
|
+
];
|
|
104
|
+
for (const path of this._sideEffectImports){
|
|
105
|
+
imports.push(`import "${path}";`);
|
|
106
|
+
}
|
|
107
|
+
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";');
|
|
108
|
+
for (const e of this._entities){
|
|
109
|
+
imports.push(`import { ${e.className} } from "${e.importPath}";`);
|
|
110
|
+
}
|
|
111
|
+
for (const r of this._repositories){
|
|
112
|
+
imports.push(`import { ${r.className} } from "${r.importPath}";`);
|
|
113
|
+
}
|
|
114
|
+
for (const s of this._services){
|
|
115
|
+
imports.push(`import { ${s.className} } from "${s.importPath}";`);
|
|
116
|
+
}
|
|
117
|
+
for (const [from, group] of this._extraImports){
|
|
118
|
+
imports.push(group.render(from));
|
|
119
|
+
}
|
|
120
|
+
imports.push('import { HelloController } from "./controllers/hello.controller.js";');
|
|
121
|
+
const serviceRegs = [
|
|
122
|
+
"cb.registerSingleton(SampleService);",
|
|
123
|
+
...this._services.map((s)=>s.scope === "request" ? `cb.registerRequestScoped(${s.className});` : `cb.registerSingleton(${s.className});`)
|
|
124
|
+
].join(" ");
|
|
125
|
+
const builderCalls = [
|
|
126
|
+
`\t.withHttp(FastifyProvider)`,
|
|
127
|
+
`\t.withConfiguration(YamlDataSource)`,
|
|
128
|
+
`\t.withHealth()`,
|
|
129
|
+
`\t.withOpenApi({ info: { title: "${this.appName}", version: "1.0.0" } })`,
|
|
130
|
+
...this._builderCalls.map((c)=>`\t${c}`),
|
|
131
|
+
`\t.withServices((cb) => { ${serviceRegs} })`
|
|
132
|
+
];
|
|
133
|
+
if (this._entities.length > 0) {
|
|
134
|
+
const entities = this._entities.map((e)=>e.className).join(", ");
|
|
135
|
+
const repos = this._repositories.map((r)=>r.className).join(", ");
|
|
136
|
+
const named = this._dataSourceName != null ? `name: "${this._dataSourceName}", ` : "";
|
|
137
|
+
if (this._typeOrmSeed) {
|
|
138
|
+
builderCalls.push(`\t.withTypeOrm({ ${named}entities: [${entities}], repositories: [${repos}], seed: async (dataSource) => { ${this._typeOrmSeed} } })`);
|
|
139
|
+
} else {
|
|
140
|
+
builderCalls.push(`\t.withTypeOrm({ ${named}entities: [${entities}], repositories: [${repos}] })`);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
builderCalls.push(`\t.withControllers(HelloController)`);
|
|
144
|
+
const content = [
|
|
145
|
+
...imports,
|
|
146
|
+
"",
|
|
147
|
+
`scribe.withPinoPretty().and.withPinoRoll({ file: "logs/${this.appName}.log" });`,
|
|
148
|
+
"",
|
|
149
|
+
`const app = await Builder.create({ applicationName: "${this.appName}" })`,
|
|
150
|
+
...builderCalls,
|
|
151
|
+
`\t.build();`,
|
|
152
|
+
"",
|
|
153
|
+
"await app.start({ port: Number(process.env.PORT ?? 3000) });",
|
|
154
|
+
"",
|
|
155
|
+
"export default app;",
|
|
156
|
+
""
|
|
157
|
+
].join("\n");
|
|
158
|
+
return [
|
|
159
|
+
{
|
|
160
|
+
filePath: "src/main.ts",
|
|
161
|
+
content
|
|
162
|
+
}
|
|
163
|
+
];
|
|
164
|
+
}
|
|
165
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
function _export(target, all) {
|
|
6
|
+
for(var name in all)Object.defineProperty(target, name, {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: Object.getOwnPropertyDescriptor(all, name).get
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
_export(exports, {
|
|
12
|
+
get WebapiProductionDockerfile () {
|
|
13
|
+
return WebapiProductionDockerfile;
|
|
14
|
+
},
|
|
15
|
+
get renderProductionDockerfile () {
|
|
16
|
+
return renderProductionDockerfile;
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
const _const = require("../../models/const.js");
|
|
20
|
+
const _const1 = require("../const.js");
|
|
21
|
+
class WebapiProductionDockerfile {
|
|
22
|
+
apiNames;
|
|
23
|
+
key = _const.WELL_KNOWN_FILES.PRODUCTION_DOCKERFILE;
|
|
24
|
+
constructor(apiNames = [
|
|
25
|
+
_const1.DEFAULT_WEBAPI_NAME
|
|
26
|
+
]){
|
|
27
|
+
this.apiNames = apiNames;
|
|
28
|
+
}
|
|
29
|
+
files() {
|
|
30
|
+
const names = this.apiNames.length > 0 ? this.apiNames : [
|
|
31
|
+
_const1.DEFAULT_WEBAPI_NAME
|
|
32
|
+
];
|
|
33
|
+
return names.flatMap((name)=>[
|
|
34
|
+
{
|
|
35
|
+
filePath: `${(0, _const1.webapiProjectDir)(name)}/Dockerfile`,
|
|
36
|
+
content: renderProductionDockerfile(name)
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
filePath: `${(0, _const1.webapiProjectDir)(name)}/.dockerignore`,
|
|
40
|
+
content: dockerignoreContent()
|
|
41
|
+
}
|
|
42
|
+
]);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
function renderProductionDockerfile(apiName) {
|
|
46
|
+
const projectDir = (0, _const1.webapiProjectDir)(apiName);
|
|
47
|
+
const entry = (0, _const1.webapiPackagedEntry)();
|
|
48
|
+
return `# syntax=docker/dockerfile:1
|
|
49
|
+
# Production image for ${apiName}. Docker only copies the packaged app; it installs nothing.
|
|
50
|
+
#
|
|
51
|
+
# Build the package first (release build, then .package/ in each API), then the image:
|
|
52
|
+
# pnpm run package:${apiName}
|
|
53
|
+
# docker build -t ${apiName} ${projectDir}
|
|
54
|
+
# or, with the image name and tags from the workspace:
|
|
55
|
+
# pnpm run package:${apiName} && pnpm exec forge docker --configuration release
|
|
56
|
+
#
|
|
57
|
+
# Hosts that build from a git clone (Railway, Fly) do not have .package/. Build and push the
|
|
58
|
+
# image from CI instead, or run the package step before \`docker build\`.
|
|
59
|
+
FROM node:24-bookworm-slim
|
|
60
|
+
WORKDIR /app
|
|
61
|
+
ENV NODE_ENV=production
|
|
62
|
+
|
|
63
|
+
COPY .package/ ./
|
|
64
|
+
|
|
65
|
+
EXPOSE 3000
|
|
66
|
+
CMD ["node", "${entry}"]
|
|
67
|
+
`;
|
|
68
|
+
}
|
|
69
|
+
/** The build context is the project folder; only the package belongs in the image. */ function dockerignoreContent() {
|
|
70
|
+
return [
|
|
71
|
+
"*",
|
|
72
|
+
"!.package",
|
|
73
|
+
""
|
|
74
|
+
].join("\n");
|
|
75
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
function _export(target, all) {
|
|
6
|
+
for(var name in all)Object.defineProperty(target, name, {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: Object.getOwnPropertyDescriptor(all, name).get
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
_export(exports, {
|
|
12
|
+
get SampleConfigModel () {
|
|
13
|
+
return SampleConfigModel;
|
|
14
|
+
},
|
|
15
|
+
get SampleServiceModel () {
|
|
16
|
+
return SampleServiceModel;
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
const SAMPLE_CONFIG_CONTENT = `export class SampleConfig {\n\tpublic greeting: string = "";\n}\n`;
|
|
20
|
+
const SAMPLE_SERVICE_CONTENT = [
|
|
21
|
+
`import { inject, injectable } from "@decohere/crucible/decorators";`,
|
|
22
|
+
`import { ConfigurationServiceToken } from "@decohere/nexus/configuration";`,
|
|
23
|
+
`import type { IConfigurationService } from "@decohere/nexus/configuration";`,
|
|
24
|
+
`import { SampleConfig } from "../sample.config.js";`,
|
|
25
|
+
``,
|
|
26
|
+
`@injectable()`,
|
|
27
|
+
`export class SampleService {`,
|
|
28
|
+
`\tpublic constructor(`,
|
|
29
|
+
`\t\t@inject(ConfigurationServiceToken) private readonly config: IConfigurationService,`,
|
|
30
|
+
`\t) {}`,
|
|
31
|
+
``,
|
|
32
|
+
`\tpublic async getGreeting(): Promise<string> {`,
|
|
33
|
+
`\t\tconst config = await this.config.get(SampleConfig);`,
|
|
34
|
+
`\t\treturn config.greeting;`,
|
|
35
|
+
`\t}`,
|
|
36
|
+
`}`,
|
|
37
|
+
``
|
|
38
|
+
].join("\n");
|
|
39
|
+
class SampleConfigModel {
|
|
40
|
+
files() {
|
|
41
|
+
return [
|
|
42
|
+
{
|
|
43
|
+
filePath: "src/sample.config.ts",
|
|
44
|
+
content: SAMPLE_CONFIG_CONTENT
|
|
45
|
+
}
|
|
46
|
+
];
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
class SampleServiceModel {
|
|
50
|
+
files() {
|
|
51
|
+
return [
|
|
52
|
+
{
|
|
53
|
+
filePath: "src/services/sample.service.ts",
|
|
54
|
+
content: SAMPLE_SERVICE_CONTENT
|
|
55
|
+
}
|
|
56
|
+
];
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
Object.defineProperty(exports, "WebapiDevContainer", {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: function() {
|
|
8
|
+
return WebapiDevContainer;
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
const _dockerimagemodel = require("../../models/docker-image.model.js");
|
|
12
|
+
const _version = require("../../version.js");
|
|
13
|
+
class WebapiDevContainer extends _dockerimagemodel.DockerfileModel {
|
|
14
|
+
constructor(baseImage = `${_version.DEVCONTAINER_IMAGE_REPOSITORY}:${_version.CREATE_VERSION}`){
|
|
15
|
+
super(baseImage);
|
|
16
|
+
}
|
|
17
|
+
files() {
|
|
18
|
+
return [
|
|
19
|
+
{
|
|
20
|
+
filePath: ".devcontainer/Dockerfile",
|
|
21
|
+
content: this.build()
|
|
22
|
+
}
|
|
23
|
+
];
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
/** Minimal OpenAPI 3 document shape used for Postman conversion. */ "use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
Object.defineProperty(exports, "buildHelloOpenApiDocument", {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: function() {
|
|
8
|
+
return buildHelloOpenApiDocument;
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
function buildHelloOpenApiDocument(projectName) {
|
|
12
|
+
return {
|
|
13
|
+
openapi: "3.0.3",
|
|
14
|
+
info: {
|
|
15
|
+
title: `${projectName} WebAPI`,
|
|
16
|
+
version: "1.0.0",
|
|
17
|
+
description: "Generated from OpenAPI for Postman. Auth/env overlays are applied separately."
|
|
18
|
+
},
|
|
19
|
+
servers: [
|
|
20
|
+
{
|
|
21
|
+
url: "{{baseUrl}}"
|
|
22
|
+
}
|
|
23
|
+
],
|
|
24
|
+
paths: {
|
|
25
|
+
"/hello": {
|
|
26
|
+
get: {
|
|
27
|
+
operationId: "HelloController.getAll",
|
|
28
|
+
summary: "List (anonymous)",
|
|
29
|
+
tags: [
|
|
30
|
+
"Hello"
|
|
31
|
+
],
|
|
32
|
+
parameters: [
|
|
33
|
+
{
|
|
34
|
+
name: "filter",
|
|
35
|
+
in: "query",
|
|
36
|
+
required: false,
|
|
37
|
+
schema: {
|
|
38
|
+
type: "string"
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
],
|
|
42
|
+
responses: {
|
|
43
|
+
"200": {
|
|
44
|
+
description: "Successful response"
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
post: {
|
|
49
|
+
operationId: "HelloController.create",
|
|
50
|
+
summary: "Create",
|
|
51
|
+
tags: [
|
|
52
|
+
"Hello"
|
|
53
|
+
],
|
|
54
|
+
requestBody: {
|
|
55
|
+
required: true,
|
|
56
|
+
content: {
|
|
57
|
+
"application/json": {
|
|
58
|
+
schema: {
|
|
59
|
+
type: "object",
|
|
60
|
+
properties: {
|
|
61
|
+
message: {
|
|
62
|
+
type: "string"
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
required: [
|
|
66
|
+
"message"
|
|
67
|
+
],
|
|
68
|
+
example: {
|
|
69
|
+
message: "hello"
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
responses: {
|
|
76
|
+
"200": {
|
|
77
|
+
description: "Successful response"
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
"/hello/{id}": {
|
|
83
|
+
get: {
|
|
84
|
+
operationId: "HelloController.getOne",
|
|
85
|
+
summary: "Get by id",
|
|
86
|
+
tags: [
|
|
87
|
+
"Hello"
|
|
88
|
+
],
|
|
89
|
+
parameters: [
|
|
90
|
+
{
|
|
91
|
+
name: "id",
|
|
92
|
+
in: "path",
|
|
93
|
+
required: true,
|
|
94
|
+
schema: {
|
|
95
|
+
type: "string"
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
],
|
|
99
|
+
responses: {
|
|
100
|
+
"200": {
|
|
101
|
+
description: "Successful response"
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
put: {
|
|
106
|
+
operationId: "HelloController.update",
|
|
107
|
+
summary: "Update",
|
|
108
|
+
tags: [
|
|
109
|
+
"Hello"
|
|
110
|
+
],
|
|
111
|
+
parameters: [
|
|
112
|
+
{
|
|
113
|
+
name: "id",
|
|
114
|
+
in: "path",
|
|
115
|
+
required: true,
|
|
116
|
+
schema: {
|
|
117
|
+
type: "string"
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
],
|
|
121
|
+
requestBody: {
|
|
122
|
+
required: true,
|
|
123
|
+
content: {
|
|
124
|
+
"application/json": {
|
|
125
|
+
schema: {
|
|
126
|
+
type: "object",
|
|
127
|
+
properties: {
|
|
128
|
+
message: {
|
|
129
|
+
type: "string"
|
|
130
|
+
}
|
|
131
|
+
},
|
|
132
|
+
required: [
|
|
133
|
+
"message"
|
|
134
|
+
],
|
|
135
|
+
example: {
|
|
136
|
+
message: "updated"
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
},
|
|
142
|
+
responses: {
|
|
143
|
+
"200": {
|
|
144
|
+
description: "Successful response"
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
},
|
|
148
|
+
delete: {
|
|
149
|
+
operationId: "HelloController.remove",
|
|
150
|
+
summary: "Delete",
|
|
151
|
+
tags: [
|
|
152
|
+
"Hello"
|
|
153
|
+
],
|
|
154
|
+
parameters: [
|
|
155
|
+
{
|
|
156
|
+
name: "id",
|
|
157
|
+
in: "path",
|
|
158
|
+
required: true,
|
|
159
|
+
schema: {
|
|
160
|
+
type: "string"
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
],
|
|
164
|
+
responses: {
|
|
165
|
+
"200": {
|
|
166
|
+
description: "Successful response"
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
}
|