@decohere/scaffold 0.0.1-dev.18 → 0.0.1-dev.20261105.54
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/LICENSE +15 -0
- 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 +8 -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 +157 -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 +275 -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 +433 -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 +238 -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 +4 -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 +142 -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 +50 -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 +255 -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 +423 -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/{src/webapi/models/github-ci.model.ts → es6/src/webapi/models/github-ci.model.js} +27 -29
- 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 +179 -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 +19 -9
- 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/{src/index.ts → types/src/index.d.ts} +4 -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/{src/models/source-file.ts → types/src/models/source-file.d.ts} +4 -6
- 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 +8 -0
- package/{src/resolve-target-dir.ts → types/src/resolve-target-dir.d.ts} +1 -4
- 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/{src/webapi/const.ts → types/src/webapi/const.d.ts} +9 -21
- 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
- package/src/add-api.action.ts +0 -25
- package/src/add-api.command.ts +0 -31
- package/src/add.command.ts +0 -20
- package/src/add.module.ts +0 -11
- package/src/cli.ts +0 -4
- package/src/create.command.ts +0 -20
- package/src/create.module.ts +0 -11
- package/src/domain/prompt.ts +0 -50
- package/src/models/compose.model.ts +0 -205
- package/src/models/config-yaml.model.ts +0 -83
- package/src/models/const.ts +0 -20
- package/src/models/dev-container.model.ts +0 -136
- package/src/models/docker-image.model.ts +0 -343
- package/src/models/env-file.model.ts +0 -45
- package/src/models/gitignore.model.ts +0 -35
- package/src/models/launch-json.model.ts +0 -60
- package/src/models/package-json.model.ts +0 -169
- package/src/models/project.model.ts +0 -141
- package/src/models/tsconfig.model.ts +0 -29
- package/src/models/vitest-config.model.ts +0 -26
- package/src/models/vscode-settings.model.ts +0 -24
- package/src/program.ts +0 -63
- package/src/services/scaffold.service.ts +0 -89
- package/src/version.ts +0 -56
- package/src/webapi/api-name.ts +0 -73
- package/src/webapi/cli-options.ts +0 -56
- package/src/webapi/create-api.ts +0 -275
- package/src/webapi/devcontainer/host-scripts.ts +0 -35
- package/src/webapi/features/auth.feature.ts +0 -454
- package/src/webapi/features/auth0-cli.ts +0 -421
- package/src/webapi/features/biome-format.ts +0 -34
- package/src/webapi/features/database.feature.ts +0 -522
- package/src/webapi/features/finalize.feature.ts +0 -112
- package/src/webapi/features/postman.feature.ts +0 -287
- package/src/webapi/models/api-package-json.model.ts +0 -60
- package/src/webapi/models/auth-config.model.ts +0 -36
- package/src/webapi/models/controller-source-file.model.ts +0 -232
- package/src/webapi/models/main-source-file.model.ts +0 -208
- package/src/webapi/models/production-dockerfile.model.ts +0 -162
- package/src/webapi/models/sample-files.model.ts +0 -45
- package/src/webapi/models/webapi-image.model.ts +0 -21
- package/src/webapi/postman/hello-openapi.ts +0 -92
- package/src/webapi/postman/local-view.ts +0 -195
- package/src/webapi/postman/openapi-to-postman.ts +0 -208
- package/src/webapi/workspace-readme.ts +0 -192
- package/src/webapi.action.ts +0 -22
- package/src/webapi.command.ts +0 -41
- package/tests/auth-postman.wiring.spec.ts +0 -263
- package/tests/auth0-cli.spec.ts +0 -232
- package/tests/biome-format.spec.ts +0 -49
- package/tests/cli.integration.spec.ts +0 -658
- package/tests/compose.model.spec.ts +0 -51
- package/tests/container-image.model.spec.ts +0 -162
- package/tests/dev-container.model.spec.ts +0 -29
- package/tests/devcontainer-base-image.spec.ts +0 -32
- package/tests/hello-di-inject.scaffold.spec.ts +0 -18
- package/tests/hello-route.contract.spec.ts +0 -94
- package/tests/package-json.order.spec.ts +0 -59
- package/tests/postman-from-openapi.spec.ts +0 -197
- package/tests/seed-devcontainer-templates.ts +0 -40
- package/tests/webapi/devcontainer/codebase-rag-mcp.spec.ts +0 -96
|
@@ -0,0 +1,182 @@
|
|
|
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 buildEnvironmentYaml () {
|
|
13
|
+
return buildEnvironmentYaml;
|
|
14
|
+
},
|
|
15
|
+
get buildLocalViewFilesFromCollection () {
|
|
16
|
+
return buildLocalViewFilesFromCollection;
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
const _nodecrypto = require("node:crypto");
|
|
20
|
+
const _openapitopostman = require("./openapi-to-postman.js");
|
|
21
|
+
function yamlQuote(value) {
|
|
22
|
+
if (/[:#{}[\],&*?|<>=!%@`]/.test(value) || value.includes("\n") || value === "") {
|
|
23
|
+
return JSON.stringify(value);
|
|
24
|
+
}
|
|
25
|
+
return value;
|
|
26
|
+
}
|
|
27
|
+
function buildEnvironmentYaml(name, auth, options) {
|
|
28
|
+
const values = [
|
|
29
|
+
{
|
|
30
|
+
key: "baseUrl",
|
|
31
|
+
value: "http://localhost:3000"
|
|
32
|
+
}
|
|
33
|
+
];
|
|
34
|
+
if (auth?.auth0Domain) {
|
|
35
|
+
values.push({
|
|
36
|
+
key: "auth0Domain",
|
|
37
|
+
value: auth.auth0Domain
|
|
38
|
+
}, {
|
|
39
|
+
key: "auth0Audience",
|
|
40
|
+
value: auth.auth0Audience ?? ""
|
|
41
|
+
}, {
|
|
42
|
+
key: "auth0ClientId",
|
|
43
|
+
value: auth.auth0ClientId ?? ""
|
|
44
|
+
}, {
|
|
45
|
+
key: "authUrl",
|
|
46
|
+
value: `https://${auth.auth0Domain}/authorize?audience=${auth.auth0Audience ?? ""}`
|
|
47
|
+
}, {
|
|
48
|
+
key: "accessTokenUrl",
|
|
49
|
+
value: `https://${auth.auth0Domain}/oauth/token`
|
|
50
|
+
}, {
|
|
51
|
+
key: "callbackUrl",
|
|
52
|
+
value: options.callbacks[0]
|
|
53
|
+
}, {
|
|
54
|
+
key: "scope",
|
|
55
|
+
value: options.scopes
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
const lines = [
|
|
59
|
+
`name: ${yamlQuote(name)}`,
|
|
60
|
+
"values:"
|
|
61
|
+
];
|
|
62
|
+
for (const v of values){
|
|
63
|
+
lines.push(` - key: ${v.key}`);
|
|
64
|
+
lines.push(` value: ${yamlQuote(v.value)}`);
|
|
65
|
+
lines.push(" enabled: true");
|
|
66
|
+
}
|
|
67
|
+
return `${lines.join("\n")}\n`;
|
|
68
|
+
}
|
|
69
|
+
function buildLocalViewFilesFromCollection(collection, projectName, auth, options) {
|
|
70
|
+
const collectionDir = `postman/collections/${projectName} WebAPI`;
|
|
71
|
+
const files = [];
|
|
72
|
+
const authBlock = auth?.auth0Domain ? [
|
|
73
|
+
"auth:",
|
|
74
|
+
` - id: ${(0, _nodecrypto.randomUUID)()}`,
|
|
75
|
+
" type: oauth2",
|
|
76
|
+
" name: OAuth 2.0",
|
|
77
|
+
" credentials:",
|
|
78
|
+
" addTokenTo: header",
|
|
79
|
+
" grant_type: authorization_code_with_pkce",
|
|
80
|
+
` authUrl: https://${auth.auth0Domain}/authorize?audience=${auth.auth0Audience ?? ""}`,
|
|
81
|
+
` accessTokenUrl: https://${auth.auth0Domain}/oauth/token`,
|
|
82
|
+
` clientId: ${yamlQuote(auth.auth0ClientId ?? "")}`,
|
|
83
|
+
` scope: ${yamlQuote(options.scopes)}`,
|
|
84
|
+
` redirect_uri: ${options.callbacks[0]}`,
|
|
85
|
+
" useBrowser: true",
|
|
86
|
+
" challengeAlgorithm: S256",
|
|
87
|
+
" client_authentication: body",
|
|
88
|
+
' clientSecret: ""',
|
|
89
|
+
` tokenName: ${yamlQuote(`${projectName} Access Token`)}`,
|
|
90
|
+
""
|
|
91
|
+
].join("\n") : "";
|
|
92
|
+
files.push({
|
|
93
|
+
filePath: `${collectionDir}/.resources/definition.yaml`,
|
|
94
|
+
content: [
|
|
95
|
+
"$kind: collection",
|
|
96
|
+
`name: ${yamlQuote(`${projectName} WebAPI`)}`,
|
|
97
|
+
"schemaVersion: '3.0'",
|
|
98
|
+
"description: >-",
|
|
99
|
+
" Open this project root in Postman Local View (Files → Open folder).",
|
|
100
|
+
" Select the Local environment, then Authorization → Get New Access Token (PKCE).",
|
|
101
|
+
" Route requests are generated from OpenAPI; Auth0 overlay is hand-authored.",
|
|
102
|
+
authBlock
|
|
103
|
+
].filter((l)=>l !== undefined).join("\n").replace(/\n+$/, "\n")
|
|
104
|
+
});
|
|
105
|
+
let folderOrder = 1000;
|
|
106
|
+
for (const folder of collection.item ?? []){
|
|
107
|
+
if (folder.item == null) {
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
const folderName = folder.name ?? "Requests";
|
|
111
|
+
files.push({
|
|
112
|
+
filePath: `${collectionDir}/${folderName}/.resources/definition.yaml`,
|
|
113
|
+
content: [
|
|
114
|
+
"$kind: folder",
|
|
115
|
+
`name: ${yamlQuote(folderName)}`,
|
|
116
|
+
`order: ${folderOrder}`,
|
|
117
|
+
""
|
|
118
|
+
].join("\n")
|
|
119
|
+
});
|
|
120
|
+
folderOrder += 1000;
|
|
121
|
+
let requestOrder = 1000;
|
|
122
|
+
for (const child of folder.item){
|
|
123
|
+
const yaml = requestToLocalViewYaml(child, requestOrder);
|
|
124
|
+
if (yaml == null) {
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
const fileName = `${sanitizeFileName(child.name ?? "Request")}.request.yaml`;
|
|
128
|
+
files.push({
|
|
129
|
+
filePath: `${collectionDir}/${folderName}/${fileName}`,
|
|
130
|
+
content: yaml
|
|
131
|
+
});
|
|
132
|
+
requestOrder += 1000;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return files;
|
|
136
|
+
}
|
|
137
|
+
function requestToLocalViewYaml(item, order) {
|
|
138
|
+
const request = item.request;
|
|
139
|
+
if (request == null) {
|
|
140
|
+
return null;
|
|
141
|
+
}
|
|
142
|
+
const method = (request.method ?? "GET").toUpperCase();
|
|
143
|
+
const url = requestUrlForLocalView(request);
|
|
144
|
+
const lines = [
|
|
145
|
+
"$kind: http-request",
|
|
146
|
+
`name: ${yamlQuote(item.name ?? method)}`,
|
|
147
|
+
`method: ${method}`,
|
|
148
|
+
`url: ${yamlQuote(url)}`
|
|
149
|
+
];
|
|
150
|
+
if (request.auth?.type === "noauth") {
|
|
151
|
+
lines.push("auth:", " type: noauth");
|
|
152
|
+
}
|
|
153
|
+
const contentType = request.header?.find((h)=>h.key.toLowerCase() === "content-type")?.value;
|
|
154
|
+
const rawBody = request.body?.raw?.trim();
|
|
155
|
+
if (rawBody) {
|
|
156
|
+
lines.push("headers:");
|
|
157
|
+
lines.push(` Content-Type: ${contentType ?? "application/json"}`);
|
|
158
|
+
lines.push("body:");
|
|
159
|
+
lines.push(" type: json");
|
|
160
|
+
lines.push(" content: |-");
|
|
161
|
+
for (const bodyLine of rawBody.split("\n")){
|
|
162
|
+
lines.push(` ${bodyLine}`);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
lines.push(`order: ${order}`, "");
|
|
166
|
+
return lines.join("\n");
|
|
167
|
+
}
|
|
168
|
+
function requestUrlForLocalView(request) {
|
|
169
|
+
const url = request.url;
|
|
170
|
+
if (typeof url === "string") {
|
|
171
|
+
return (0, _openapitopostman.openApiPathParamsToColon)(url);
|
|
172
|
+
}
|
|
173
|
+
if (url?.raw) {
|
|
174
|
+
return (0, _openapitopostman.openApiPathParamsToColon)(url.raw);
|
|
175
|
+
}
|
|
176
|
+
const host = url?.host?.[0] ?? "{{baseUrl}}";
|
|
177
|
+
const path = (url?.path ?? []).map((segment)=>(0, _openapitopostman.openApiPathParamsToColon)(String(segment))).join("/");
|
|
178
|
+
return path ? `${host}/${path}` : host;
|
|
179
|
+
}
|
|
180
|
+
function sanitizeFileName(name) {
|
|
181
|
+
return name.replace(/[^\w\s()-]+/g, "").trim() || "Request";
|
|
182
|
+
}
|
|
@@ -0,0 +1,238 @@
|
|
|
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 applyPostmanAuthOverlay () {
|
|
13
|
+
return applyPostmanAuthOverlay;
|
|
14
|
+
},
|
|
15
|
+
get openApiPathParamsToColon () {
|
|
16
|
+
return openApiPathParamsToColon;
|
|
17
|
+
},
|
|
18
|
+
get openApiToPostmanCollection () {
|
|
19
|
+
return openApiToPostmanCollection;
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
function _getRequireWildcardCache(nodeInterop) {
|
|
23
|
+
if (typeof WeakMap !== "function") return null;
|
|
24
|
+
var cacheBabelInterop = new WeakMap();
|
|
25
|
+
var cacheNodeInterop = new WeakMap();
|
|
26
|
+
return (_getRequireWildcardCache = function(nodeInterop) {
|
|
27
|
+
return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
|
|
28
|
+
})(nodeInterop);
|
|
29
|
+
}
|
|
30
|
+
function _interop_require_wildcard(obj, nodeInterop) {
|
|
31
|
+
if (!nodeInterop && obj && obj.__esModule) {
|
|
32
|
+
return obj;
|
|
33
|
+
}
|
|
34
|
+
if (obj === null || typeof obj !== "object" && typeof obj !== "function") {
|
|
35
|
+
return {
|
|
36
|
+
default: obj
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
var cache = _getRequireWildcardCache(nodeInterop);
|
|
40
|
+
if (cache && cache.has(obj)) {
|
|
41
|
+
return cache.get(obj);
|
|
42
|
+
}
|
|
43
|
+
var newObj = {
|
|
44
|
+
__proto__: null
|
|
45
|
+
};
|
|
46
|
+
var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
|
|
47
|
+
for(var key in obj){
|
|
48
|
+
if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
49
|
+
var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
|
|
50
|
+
if (desc && (desc.get || desc.set)) {
|
|
51
|
+
Object.defineProperty(newObj, key, desc);
|
|
52
|
+
} else {
|
|
53
|
+
newObj[key] = obj[key];
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
newObj.default = obj;
|
|
58
|
+
if (cache) {
|
|
59
|
+
cache.set(obj, newObj);
|
|
60
|
+
}
|
|
61
|
+
return newObj;
|
|
62
|
+
}
|
|
63
|
+
async function convertAsync(data, options) {
|
|
64
|
+
// Loaded here, not at the top: the converter pulls in about 700 modules (lodash, faker, ajv,
|
|
65
|
+
// …), which every scaffolder run paid for even with `--postman none`.
|
|
66
|
+
const { default: converter } = await Promise.resolve().then(()=>/*#__PURE__*/ _interop_require_wildcard(require("openapi-to-postmanv2")));
|
|
67
|
+
return new Promise((resolve, reject)=>{
|
|
68
|
+
converter.convert({
|
|
69
|
+
type: "json",
|
|
70
|
+
data
|
|
71
|
+
}, options, (err, result)=>{
|
|
72
|
+
if (err) {
|
|
73
|
+
reject(err);
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
resolve(result);
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
async function openApiToPostmanCollection(document) {
|
|
81
|
+
const result = await convertAsync(document, {
|
|
82
|
+
folderStrategy: "Tags",
|
|
83
|
+
requestNameSource: "Fallback",
|
|
84
|
+
includeAuthInfoInExample: false
|
|
85
|
+
});
|
|
86
|
+
if (!result.result || result.output?.[0]?.data == null) {
|
|
87
|
+
throw new Error(result.reason ?? "openapi-to-postmanv2 conversion failed");
|
|
88
|
+
}
|
|
89
|
+
return result.output[0].data;
|
|
90
|
+
}
|
|
91
|
+
function applyPostmanAuthOverlay(collection, projectName, auth, options) {
|
|
92
|
+
const next = {
|
|
93
|
+
...collection,
|
|
94
|
+
info: {
|
|
95
|
+
...collection.info,
|
|
96
|
+
name: `${projectName} WebAPI`,
|
|
97
|
+
description: options.description,
|
|
98
|
+
schema: collection.info.schema ?? "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
if (auth?.auth0Domain) {
|
|
102
|
+
next.auth = {
|
|
103
|
+
type: "oauth2",
|
|
104
|
+
oauth2: [
|
|
105
|
+
{
|
|
106
|
+
key: "grant_type",
|
|
107
|
+
value: "authorization_code_with_pkce",
|
|
108
|
+
type: "string"
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
key: "authUrl",
|
|
112
|
+
value: "https://{{auth0Domain}}/authorize?audience={{auth0Audience}}",
|
|
113
|
+
type: "string"
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
key: "accessTokenUrl",
|
|
117
|
+
value: "https://{{auth0Domain}}/oauth/token",
|
|
118
|
+
type: "string"
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
key: "clientId",
|
|
122
|
+
value: "{{auth0ClientId}}",
|
|
123
|
+
type: "string"
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
key: "scope",
|
|
127
|
+
value: options.scopes,
|
|
128
|
+
type: "string"
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
key: "redirect_uri",
|
|
132
|
+
value: options.callbacks[0],
|
|
133
|
+
type: "string"
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
key: "useBrowser",
|
|
137
|
+
value: "true",
|
|
138
|
+
type: "boolean"
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
key: "addTokenTo",
|
|
142
|
+
value: "header",
|
|
143
|
+
type: "string"
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
key: "challengeAlgorithm",
|
|
147
|
+
value: "S256",
|
|
148
|
+
type: "string"
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
key: "client_authentication",
|
|
152
|
+
value: "body",
|
|
153
|
+
type: "string"
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
key: "clientSecret",
|
|
157
|
+
value: "",
|
|
158
|
+
type: "string"
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
key: "tokenName",
|
|
162
|
+
value: `${projectName} Access Token`,
|
|
163
|
+
type: "string"
|
|
164
|
+
}
|
|
165
|
+
]
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
next.item = rewriteCollectionItems(collection.item ?? [], {
|
|
169
|
+
markListAnonymous: true
|
|
170
|
+
});
|
|
171
|
+
return next;
|
|
172
|
+
}
|
|
173
|
+
function rewriteCollectionItems(items, opts) {
|
|
174
|
+
return items.map((item)=>{
|
|
175
|
+
if (item.item != null) {
|
|
176
|
+
return {
|
|
177
|
+
...item,
|
|
178
|
+
item: rewriteCollectionItems(item.item, opts)
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
const request = item.request;
|
|
182
|
+
if (request == null) {
|
|
183
|
+
return item;
|
|
184
|
+
}
|
|
185
|
+
const method = (request.method ?? "GET").toUpperCase();
|
|
186
|
+
const rawUrl = requestUrlRaw(request);
|
|
187
|
+
const nextRequest = {
|
|
188
|
+
...request,
|
|
189
|
+
url: toPostmanUrl(rawUrl)
|
|
190
|
+
};
|
|
191
|
+
// List Hello stays anonymous (matches scaffold AllowAnonymous on GET /hello).
|
|
192
|
+
if (opts.markListAnonymous && method === "GET" && normalizePath(rawUrl) === "/hello" && !rawUrl.includes("/:")) {
|
|
193
|
+
nextRequest.auth = {
|
|
194
|
+
type: "noauth"
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
return {
|
|
198
|
+
...item,
|
|
199
|
+
request: nextRequest
|
|
200
|
+
};
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
function requestUrlRaw(request) {
|
|
204
|
+
const url = request.url;
|
|
205
|
+
if (typeof url === "string") {
|
|
206
|
+
return url;
|
|
207
|
+
}
|
|
208
|
+
if (url?.raw) {
|
|
209
|
+
return url.raw;
|
|
210
|
+
}
|
|
211
|
+
const host = url?.host?.[0] ?? "{{baseUrl}}";
|
|
212
|
+
const path = (url?.path ?? []).join("/");
|
|
213
|
+
return path ? `${host}/${path}` : host;
|
|
214
|
+
}
|
|
215
|
+
function openApiPathParamsToColon(url) {
|
|
216
|
+
return url.replace(/(?<!\{)\{([A-Za-z_][\w]*)\}(?!\})/g, ":$1");
|
|
217
|
+
}
|
|
218
|
+
function normalizePath(rawUrl) {
|
|
219
|
+
const withoutBase = rawUrl.replace(/\{\{baseUrl\}\}/g, "").split("?")[0] ?? "";
|
|
220
|
+
const withSlash = withoutBase.startsWith("/") ? withoutBase : `/${withoutBase}`;
|
|
221
|
+
return openApiPathParamsToColon(withSlash);
|
|
222
|
+
}
|
|
223
|
+
/** Prefer Postman template URL shape used by existing Local View / API uploads. */ function toPostmanUrl(rawUrl) {
|
|
224
|
+
let pathPart = rawUrl.replace(/\{\{baseUrl\}\}/g, "");
|
|
225
|
+
if (!pathPart.startsWith("/")) {
|
|
226
|
+
pathPart = `/${pathPart}`;
|
|
227
|
+
}
|
|
228
|
+
// openapi-to-postman uses {id}; Local View / prior collections use :id
|
|
229
|
+
pathPart = openApiPathParamsToColon(pathPart);
|
|
230
|
+
const segments = pathPart.split("/").filter(Boolean);
|
|
231
|
+
return {
|
|
232
|
+
raw: `{{baseUrl}}${pathPart}`,
|
|
233
|
+
host: [
|
|
234
|
+
"{{baseUrl}}"
|
|
235
|
+
],
|
|
236
|
+
path: segments
|
|
237
|
+
};
|
|
238
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
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 renderWorkspaceReadme () {
|
|
13
|
+
return renderWorkspaceReadme;
|
|
14
|
+
},
|
|
15
|
+
get resolveWorkspaceReadmeInput () {
|
|
16
|
+
return resolveWorkspaceReadmeInput;
|
|
17
|
+
},
|
|
18
|
+
get writeWorkspaceReadme () {
|
|
19
|
+
return writeWorkspaceReadme;
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
const _nodefs = require("node:fs");
|
|
23
|
+
const _nodepath = require("node:path");
|
|
24
|
+
const _const = require("../models/const.js");
|
|
25
|
+
const _apiname = require("./api-name.js");
|
|
26
|
+
function renderWorkspaceReadme(input) {
|
|
27
|
+
const { projectName, apiNames, hasPostgres, hasAuth0, hasPostman } = input;
|
|
28
|
+
const apis = apiNames.length > 0 ? apiNames : [
|
|
29
|
+
"api"
|
|
30
|
+
];
|
|
31
|
+
const lines = [
|
|
32
|
+
`# ${projectName}`,
|
|
33
|
+
"",
|
|
34
|
+
"Decohere web API workspace. Scaffolded with [`@decohere/create`](https://www.npmjs.com/package/@decohere/create).",
|
|
35
|
+
"",
|
|
36
|
+
"## Get started",
|
|
37
|
+
"",
|
|
38
|
+
"1. Open this folder in VS Code / Cursor.",
|
|
39
|
+
"2. **Reopen in Container** (or rebuild the Dev Container).",
|
|
40
|
+
" Host `initialize.sh` and container `post-start.sh` ask y/N (TTY only) before npm auth or codebase RAG MCP.",
|
|
41
|
+
" Skip or decline; missing TTY skips. RAG credentials land in `.cursor/` (gitignored).",
|
|
42
|
+
"3. Install dependencies if needed:",
|
|
43
|
+
"",
|
|
44
|
+
"```bash",
|
|
45
|
+
"pnpm install",
|
|
46
|
+
"```",
|
|
47
|
+
"",
|
|
48
|
+
"## Develop",
|
|
49
|
+
"",
|
|
50
|
+
"```bash",
|
|
51
|
+
"pnpm dev # Flux HMR (first API)",
|
|
52
|
+
"pnpm start # run the compiled first API",
|
|
53
|
+
"pnpm run build # forge release build",
|
|
54
|
+
"pnpm run package # release build + .package/ for each API (what Docker copies)"
|
|
55
|
+
];
|
|
56
|
+
for (const name of apis){
|
|
57
|
+
lines.push(`pnpm run dev:${name} # HMR for ${name}`);
|
|
58
|
+
lines.push(`pnpm run start:${name} # production entry for ${name}`);
|
|
59
|
+
}
|
|
60
|
+
lines.push("```", "");
|
|
61
|
+
lines.push("## Logging", "", "In development, Scribe uses pino-pretty and rolling files under `logs/` (gitignored).", "When `NODE_ENV=production`, the process writes structured JSON to stdout and does not rotate files.", "Ship and retain those streams outside the app (platform logs, a sidecar, or a log agent) so shipping can change without rebuilding.", "", "Override roll path and rotation without changing app code:", "`SCRIBE_LOG_FILE`, `SCRIBE_LOG_SIZE`, `SCRIBE_LOG_FREQUENCY`, `SCRIBE_LOG_KEEP`.", "", 'Opt into in-process pretty or roll in production only with `{ when: "always" }` on `scribe.withPinoPretty` / `scribe.withPinoRoll`.', "");
|
|
62
|
+
if (hasPostgres) {
|
|
63
|
+
lines.push("## Database", "", "Postgres runs via Dev Container Compose:", "", "```bash", "pnpm db:up", "pnpm db:down", "pnpm db:reset", "```", "");
|
|
64
|
+
}
|
|
65
|
+
lines.push("## Deploy", "", "Each API has its own `projects/<name>/Dockerfile`. It copies `.package/`, which `forge package`", "writes before Docker runs: the API's compiled code, the workspace libraries it imports, and", "a plain `node_modules` of the third-party packages it uses (no symlinks). The image build", "installs nothing and needs no npm token.", "", "```bash", "pnpm run package # release build, then .package/ in every API", `docker build -t ${projectName} projects/api`, "```", "", "One API: `pnpm run package:<name>`, then `docker build projects/<name>`.", "A host that builds from a git clone does not have `.package/`; build and push the image", "from CI instead (`forge docker` after `pnpm run package`).", "");
|
|
66
|
+
lines.push("## Add another API", "", "```bash", "decohere add api <name>", "```", "", "Example: `decohere add api billing`", "");
|
|
67
|
+
if (hasAuth0) {
|
|
68
|
+
lines.push("## Auth0", "", "JWT auth is wired from `.env` (`AUTH0_ISSUER_BASE_URL`, `AUTH0_AUDIENCE`).", 'After you add a controller, `@Authorize("read", "Invoice")` becomes the Auth0 permission `read:Invoice`.', "Sync the Auth0 API, admin grants, and Postman token scopes without re-scaffolding:", "", "```bash", "npx @decohere/create auth0 login # once / when the CLI token expires", "npx @decohere/create auth0 configure # after new @Authorize decorators", "```", "");
|
|
69
|
+
}
|
|
70
|
+
if (hasPostman) {
|
|
71
|
+
lines.push("## Postman", "", "Open this **project root** in Postman Local View (Files → Open folder), not the `postman/` subfolder.", "Select the Local environment, then Authorization → Get New Access Token when Auth0 is enabled.", "");
|
|
72
|
+
}
|
|
73
|
+
lines.push("## More", "", "- Package docs: https://www.npmjs.com/package/@decohere/create", "- After `decohere add api`, this README is refreshed so scripts and APIs stay accurate.", "");
|
|
74
|
+
return `${lines.join("\n")}`;
|
|
75
|
+
}
|
|
76
|
+
function resolveWorkspaceReadmeInput(workspace, options) {
|
|
77
|
+
const newNames = workspace.getProjects().map((project)=>(0, _apiname.apiNameFromProjectDir)(project.dir));
|
|
78
|
+
const apiNames = options.add ? mergeApiNames((0, _apiname.listExistingApiNames)(workspace.targetDir), newNames) : newNames;
|
|
79
|
+
const pkg = workspace.getModel(_const.WELL_KNOWN_FILES.PACKAGE_JSON);
|
|
80
|
+
const env = workspace.getModel(_const.WELL_KNOWN_FILES.ENV_FILE);
|
|
81
|
+
const hasPostgres = options.databaseProvider === "postgres/typeorm" || Boolean(pkg?.hasScript("db:up"));
|
|
82
|
+
const hasAuth0 = options.authProvider === "auth0" || Boolean(env?.hasEntry("AUTH0_ISSUER_BASE_URL"));
|
|
83
|
+
const hasPostman = options.postmanProvider === "local" || options.postmanProvider === "api" || (0, _nodefs.existsSync)((0, _nodepath.join)(workspace.targetDir, "postman")) || (0, _nodefs.existsSync)((0, _nodepath.join)(workspace.targetDir, ".postman"));
|
|
84
|
+
return {
|
|
85
|
+
projectName: workspace.name,
|
|
86
|
+
apiNames,
|
|
87
|
+
hasPostgres,
|
|
88
|
+
hasAuth0,
|
|
89
|
+
hasPostman
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
function writeWorkspaceReadme(workspace, options) {
|
|
93
|
+
const content = renderWorkspaceReadme(resolveWorkspaceReadmeInput(workspace, options));
|
|
94
|
+
workspace.addFile({
|
|
95
|
+
files: ()=>[
|
|
96
|
+
{
|
|
97
|
+
filePath: "README.md",
|
|
98
|
+
content
|
|
99
|
+
}
|
|
100
|
+
]
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
function mergeApiNames(existing, added) {
|
|
104
|
+
const seen = new Set(existing);
|
|
105
|
+
return [
|
|
106
|
+
...existing,
|
|
107
|
+
...added.filter((name)=>!seen.has(name))
|
|
108
|
+
];
|
|
109
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
Object.defineProperty(exports, "WebapiAction", {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: function() {
|
|
8
|
+
return WebapiAction;
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
const _decorators = require("@decohere/crucible/decorators");
|
|
12
|
+
const _cli = require("@decohere/devkit/cli");
|
|
13
|
+
const _clioptions = require("./webapi/cli-options.js");
|
|
14
|
+
function _ts_decorate(decorators, target, key, desc) {
|
|
15
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
16
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
17
|
+
else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
18
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
19
|
+
}
|
|
20
|
+
class WebapiAction {
|
|
21
|
+
async run(options) {
|
|
22
|
+
await (0, _clioptions.runScaffoldApi)((0, _clioptions.toApiOptions)(options.directory, options));
|
|
23
|
+
return _cli.ActionResponse.Success("webapi");
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
WebapiAction = _ts_decorate([
|
|
27
|
+
(0, _decorators.injectable)()
|
|
28
|
+
], WebapiAction);
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
Object.defineProperty(exports, "WebapiCommand", {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: function() {
|
|
8
|
+
return WebapiCommand;
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
const _cli = require("@decohere/devkit/cli");
|
|
12
|
+
const _clioptions = require("./webapi/cli-options.js");
|
|
13
|
+
const _webapiaction = require("./webapi.action.js");
|
|
14
|
+
class WebapiCommand extends _cli.DecohereCommand {
|
|
15
|
+
get actions() {
|
|
16
|
+
return [
|
|
17
|
+
_webapiaction.WebapiAction
|
|
18
|
+
];
|
|
19
|
+
}
|
|
20
|
+
constructor(name){
|
|
21
|
+
super(name);
|
|
22
|
+
this.description("Scaffold a web API workspace");
|
|
23
|
+
this.argument("[directory]", "Target directory (default: -d or current directory)");
|
|
24
|
+
this.option("-d <directory>", "Target directory (default: current directory)", ".");
|
|
25
|
+
this.option("--name <slug>", "API name under projects/ (repeatable; default: api)", _clioptions.collectName, []);
|
|
26
|
+
(0, _clioptions.addWebapiFeatureOptions)(this);
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Commander passes positional args before options when `[directory]` is declared.
|
|
30
|
+
* ModuleFactory expects `(opts, cmd)` — stash the directory on the command.
|
|
31
|
+
*/ action(fn) {
|
|
32
|
+
return super.action((...args)=>{
|
|
33
|
+
const cmd = args.at(-1);
|
|
34
|
+
const first = args[0];
|
|
35
|
+
const hasPositional = typeof first === "string" || first === undefined;
|
|
36
|
+
const opts = hasPositional ? args[1] : args[0];
|
|
37
|
+
if (typeof first === "string" && first !== "") {
|
|
38
|
+
cmd.setOptionValue("directory", first);
|
|
39
|
+
}
|
|
40
|
+
return fn(opts, cmd);
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
function _ts_decorate(decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
}
|
|
7
|
+
import { injectable } from "@decohere/crucible/decorators";
|
|
8
|
+
import { ActionResponse } from "@decohere/devkit/cli";
|
|
9
|
+
import { runScaffoldApi, toApiOptions } from "./webapi/cli-options.js";
|
|
10
|
+
export class AddApiAction {
|
|
11
|
+
async run(options) {
|
|
12
|
+
const name = options.apiName;
|
|
13
|
+
if (name == null || name === "") {
|
|
14
|
+
return ActionResponse.Error("api", "API name is required");
|
|
15
|
+
}
|
|
16
|
+
await runScaffoldApi(toApiOptions(undefined, options, {
|
|
17
|
+
names: [
|
|
18
|
+
name
|
|
19
|
+
],
|
|
20
|
+
add: true
|
|
21
|
+
}));
|
|
22
|
+
return ActionResponse.Success("api");
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
AddApiAction = _ts_decorate([
|
|
26
|
+
injectable()
|
|
27
|
+
], AddApiAction);
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { DecohereCommand } from "@decohere/devkit/cli";
|
|
2
|
+
import { AddApiAction } from "./add-api.action.js";
|
|
3
|
+
import { addWebapiFeatureOptions } from "./webapi/cli-options.js";
|
|
4
|
+
export class AddApiCommand extends DecohereCommand {
|
|
5
|
+
get actions() {
|
|
6
|
+
return [
|
|
7
|
+
AddApiAction
|
|
8
|
+
];
|
|
9
|
+
}
|
|
10
|
+
constructor(name){
|
|
11
|
+
super(name);
|
|
12
|
+
this.description("Add an API to an existing Decohere workspace");
|
|
13
|
+
this.argument("<name>", "API name under projects/");
|
|
14
|
+
this.option("-d <directory>", "Workspace directory (default: current directory)", ".");
|
|
15
|
+
addWebapiFeatureOptions(this);
|
|
16
|
+
}
|
|
17
|
+
action(fn) {
|
|
18
|
+
return super.action((...args)=>{
|
|
19
|
+
const cmd = args.at(-1);
|
|
20
|
+
const first = args[0];
|
|
21
|
+
const hasPositional = typeof first === "string" || first === undefined;
|
|
22
|
+
const opts = hasPositional ? args[1] : args[0];
|
|
23
|
+
if (typeof first === "string" && first !== "") {
|
|
24
|
+
cmd.setOptionValue("apiName", first);
|
|
25
|
+
}
|
|
26
|
+
return fn(opts, cmd);
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { DecohereCommand } from "@decohere/devkit/cli";
|
|
2
|
+
export class AddCommand extends DecohereCommand {
|
|
3
|
+
constructor(commands, handler){
|
|
4
|
+
super(AddCommand);
|
|
5
|
+
this.description("Add to an existing Decohere workspace");
|
|
6
|
+
this.exitOverride();
|
|
7
|
+
this.registerSubcommand(commands, handler);
|
|
8
|
+
}
|
|
9
|
+
run(_actions, _options) {
|
|
10
|
+
return this.help();
|
|
11
|
+
}
|
|
12
|
+
}
|