@decohere/scaffold 0.0.1-dev.18 → 0.0.1-dev.20261105.46
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 +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 +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 +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 +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 +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 +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
|
+
import {
|
|
2
|
+
chmodSync,
|
|
3
|
+
mkdirSync,
|
|
4
|
+
readFileSync,
|
|
5
|
+
renameSync,
|
|
6
|
+
statSync,
|
|
7
|
+
writeFileSync,
|
|
8
|
+
} from "node:fs";
|
|
9
|
+
import { dirname, join } from "node:path";
|
|
10
|
+
import { fileURLToPath } from "node:url";
|
|
11
|
+
|
|
12
|
+
export type CodebaseRagCredentials = {
|
|
13
|
+
url: string;
|
|
14
|
+
token: string;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export type McpJson = {
|
|
18
|
+
mcpServers?: Record<string, unknown>;
|
|
19
|
+
[key: string]: unknown;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
23
|
+
return value != null && typeof value === "object" && !Array.isArray(value);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function loadDotenv(path: string, env: NodeJS.ProcessEnv): void {
|
|
27
|
+
let raw: string;
|
|
28
|
+
try {
|
|
29
|
+
raw = readFileSync(path, "utf8");
|
|
30
|
+
} catch {
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
for (const line of raw.split(/\r?\n/)) {
|
|
34
|
+
const trimmed = line.trim();
|
|
35
|
+
if (!trimmed || trimmed.startsWith("#") || !trimmed.includes("=")) continue;
|
|
36
|
+
const eq = trimmed.indexOf("=");
|
|
37
|
+
const key = trimmed.slice(0, eq).trim();
|
|
38
|
+
const value = trimmed
|
|
39
|
+
.slice(eq + 1)
|
|
40
|
+
.trim()
|
|
41
|
+
.replace(/^["']|["']$/g, "");
|
|
42
|
+
if (key && env[key] === undefined) env[key] = value;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function seedFromMcpJson(raw: string): CodebaseRagCredentials | null {
|
|
47
|
+
let data: unknown;
|
|
48
|
+
try {
|
|
49
|
+
data = JSON.parse(raw);
|
|
50
|
+
} catch {
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
if (!isRecord(data)) return null;
|
|
54
|
+
const servers = data.mcpServers;
|
|
55
|
+
if (!isRecord(servers)) return null;
|
|
56
|
+
const server = servers["codebase-rag"];
|
|
57
|
+
if (!isRecord(server)) return null;
|
|
58
|
+
const url = typeof server.url === "string" ? server.url.trim() : "";
|
|
59
|
+
const headers = isRecord(server.headers) ? server.headers : {};
|
|
60
|
+
const auth = typeof headers.Authorization === "string" ? headers.Authorization.trim() : "";
|
|
61
|
+
const token = auth.toLowerCase().startsWith("bearer ") ? auth.slice(7).trim() : "";
|
|
62
|
+
if (!url.startsWith("http") || token.length === 0) return null;
|
|
63
|
+
return { url, token };
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function mergeIntoMcpJson(input: {
|
|
67
|
+
mcpPath: string;
|
|
68
|
+
url: string;
|
|
69
|
+
token: string;
|
|
70
|
+
hostRoot: string;
|
|
71
|
+
}): { skipped?: string; path?: string; root?: string } {
|
|
72
|
+
const { mcpPath, url, token, hostRoot } = input;
|
|
73
|
+
if (!url || !token) {
|
|
74
|
+
return { skipped: "no URL/token" };
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const xRoot = hostRoot || "${workspaceFolder}";
|
|
78
|
+
mkdirSync(dirname(mcpPath), { recursive: true });
|
|
79
|
+
|
|
80
|
+
let data: McpJson = { mcpServers: {} };
|
|
81
|
+
try {
|
|
82
|
+
if (statSync(mcpPath).size > 0) {
|
|
83
|
+
const loaded: unknown = JSON.parse(readFileSync(mcpPath, "utf8"));
|
|
84
|
+
if (isRecord(loaded)) data = loaded as McpJson;
|
|
85
|
+
}
|
|
86
|
+
} catch (err) {
|
|
87
|
+
const code = isRecord(err) && typeof err.code === "string" ? err.code : "";
|
|
88
|
+
if (code !== "ENOENT") {
|
|
89
|
+
console.log(
|
|
90
|
+
"codebase-rag MCP: existing mcp.json is invalid JSON; replacing rag entry only after backup",
|
|
91
|
+
);
|
|
92
|
+
renameSync(mcpPath, `${mcpPath}.bak`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const servers = isRecord(data.mcpServers) ? data.mcpServers : {};
|
|
97
|
+
data.mcpServers = servers;
|
|
98
|
+
servers["codebase-rag"] = {
|
|
99
|
+
url,
|
|
100
|
+
headers: {
|
|
101
|
+
Authorization: `Bearer ${token}`,
|
|
102
|
+
"X-Codebase-Root": xRoot,
|
|
103
|
+
},
|
|
104
|
+
};
|
|
105
|
+
writeFileSync(mcpPath, `${JSON.stringify(data, null, 2)}\n`, "utf8");
|
|
106
|
+
try {
|
|
107
|
+
chmodSync(mcpPath, 0o600);
|
|
108
|
+
} catch {
|
|
109
|
+
// memfs and some hosts omit chmod
|
|
110
|
+
}
|
|
111
|
+
return { path: mcpPath, root: xRoot };
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function workspaceRoot(env: NodeJS.ProcessEnv = process.env): string {
|
|
115
|
+
const fromEnv = env.CODEBASE_RAG_WORKSPACE?.trim();
|
|
116
|
+
if (fromEnv) return fromEnv;
|
|
117
|
+
// Scaffolded copy lives at <repo>/.devcontainer/codebase-rag-mcp.ts
|
|
118
|
+
return dirname(dirname(fileURLToPath(import.meta.url)));
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function mergeFromEnv(env: NodeJS.ProcessEnv = process.env): number {
|
|
122
|
+
const root = workspaceRoot(env);
|
|
123
|
+
const cursorDir = join(root, ".cursor");
|
|
124
|
+
loadDotenv(join(cursorDir, "codebase-rag.env"), env);
|
|
125
|
+
const url = (env.CODEBASE_RAG_MCP_URL ?? "").trim();
|
|
126
|
+
const token = (env.CODEBASE_RAG_MCP_TOKEN ?? "").trim();
|
|
127
|
+
const hostRoot = (env.CODEBASE_RAG_MCP_ROOT ?? "").trim() || root;
|
|
128
|
+
const result = mergeIntoMcpJson({
|
|
129
|
+
mcpPath: join(cursorDir, "mcp.json"),
|
|
130
|
+
url,
|
|
131
|
+
token,
|
|
132
|
+
hostRoot,
|
|
133
|
+
});
|
|
134
|
+
if (result.skipped != null) {
|
|
135
|
+
console.log(`codebase-rag MCP: skipped (${result.skipped})`);
|
|
136
|
+
return 0;
|
|
137
|
+
}
|
|
138
|
+
console.log(`codebase-rag MCP: wrote ${result.path} url=${url} root=${result.root}`);
|
|
139
|
+
return 0;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function seedPrint(mcpPath: string): number {
|
|
143
|
+
let raw: string;
|
|
144
|
+
try {
|
|
145
|
+
raw = readFileSync(mcpPath, "utf8");
|
|
146
|
+
} catch {
|
|
147
|
+
return 1;
|
|
148
|
+
}
|
|
149
|
+
const creds = seedFromMcpJson(raw);
|
|
150
|
+
if (creds == null) return 1;
|
|
151
|
+
console.log(creds.url);
|
|
152
|
+
console.log(creds.token);
|
|
153
|
+
return 0;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function main(argv = process.argv.slice(2)): number {
|
|
157
|
+
const command = argv[0] ?? "merge";
|
|
158
|
+
if (command === "seed-print") {
|
|
159
|
+
const mcpPath = argv[1];
|
|
160
|
+
if (mcpPath == null || mcpPath.length === 0) return 1;
|
|
161
|
+
return seedPrint(mcpPath);
|
|
162
|
+
}
|
|
163
|
+
if (command === "merge") {
|
|
164
|
+
return mergeFromEnv();
|
|
165
|
+
}
|
|
166
|
+
console.error(`codebase-rag MCP: unknown command ${command}`);
|
|
167
|
+
return 1;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
const invoked = (process.argv[1] ?? "").replaceAll("\\", "/");
|
|
171
|
+
if (invoked.endsWith("/codebase-rag-mcp.ts") || invoked.endsWith("/codebase-rag-mcp.js")) {
|
|
172
|
+
process.exit(main());
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
export const codebaseRagMcp = {
|
|
176
|
+
loadDotenv,
|
|
177
|
+
seedFromMcpJson,
|
|
178
|
+
mergeIntoMcpJson,
|
|
179
|
+
mergeFromEnv,
|
|
180
|
+
seedPrint,
|
|
181
|
+
main,
|
|
182
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { SourceFile, SourceFileProvider } from "../../models/source-file.js";
|
|
2
|
+
export declare function devcontainerTemplatePath(name: string): string;
|
|
3
|
+
export declare function codebaseRagMcpSourcePath(): string;
|
|
4
|
+
/** Host + container scripts for the scaffolded Dev Container. */
|
|
5
|
+
export declare class DevContainerHostScripts implements SourceFileProvider {
|
|
6
|
+
files(): SourceFile[];
|
|
7
|
+
}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Runs on the host before the container is created (devcontainer initializeCommand).
|
|
3
|
+
# Creates bind-mount sources as the host user so Docker does not create them as root.
|
|
4
|
+
# Optional npm / gh / MCP setup is y/N on a TTY; no TTY skips.
|
|
5
|
+
set -euo pipefail
|
|
6
|
+
|
|
7
|
+
root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
8
|
+
here="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
9
|
+
# shellcheck source=tty-prompt.sh
|
|
10
|
+
source "$here/tty-prompt.sh"
|
|
11
|
+
|
|
12
|
+
npm_dir="$root/.devcontainer/npm-auth"
|
|
13
|
+
gh_dir="$root/.devcontainer/gh-auth"
|
|
14
|
+
gh_env="$root/.devcontainer/gh.env"
|
|
15
|
+
cursor_dir="$root/.cursor"
|
|
16
|
+
RAG_ENV="$cursor_dir/codebase-rag.env"
|
|
17
|
+
|
|
18
|
+
run_codebase_rag_mcp() {
|
|
19
|
+
local script="$here/codebase-rag-mcp.ts"
|
|
20
|
+
CODEBASE_RAG_WORKSPACE="$root" node --experimental-strip-types "$script" "$@"
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
load_rag_env() {
|
|
24
|
+
RAG_URL=""
|
|
25
|
+
RAG_TOKEN=""
|
|
26
|
+
[[ -f "$RAG_ENV" ]] || return 0
|
|
27
|
+
# shellcheck disable=SC1090
|
|
28
|
+
set -a
|
|
29
|
+
# shellcheck disable=SC1090
|
|
30
|
+
source "$RAG_ENV"
|
|
31
|
+
set +a
|
|
32
|
+
RAG_URL="${CODEBASE_RAG_MCP_URL:-}"
|
|
33
|
+
RAG_TOKEN="${CODEBASE_RAG_MCP_TOKEN:-}"
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
write_rag_env() {
|
|
37
|
+
mkdir -p "$(dirname "$RAG_ENV")"
|
|
38
|
+
umask 077
|
|
39
|
+
cat >"$RAG_ENV" <<EOF
|
|
40
|
+
# Written by .devcontainer/initialize.sh. Not in git.
|
|
41
|
+
CODEBASE_RAG_MCP_URL=${RAG_URL}
|
|
42
|
+
CODEBASE_RAG_MCP_TOKEN=${RAG_TOKEN}
|
|
43
|
+
CODEBASE_RAG_MCP_ROOT=${root}
|
|
44
|
+
EOF
|
|
45
|
+
chmod 600 "$RAG_ENV"
|
|
46
|
+
if [[ -n "$RAG_URL" && -n "$RAG_TOKEN" ]]; then
|
|
47
|
+
run_codebase_rag_mcp merge || true
|
|
48
|
+
fi
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
seed_rag_from_host_mcp() {
|
|
52
|
+
local mcp="${HOME}/.cursor/mcp.json"
|
|
53
|
+
[[ -f "$mcp" ]] || return 1
|
|
54
|
+
command -v node >/dev/null 2>&1 || return 1
|
|
55
|
+
run_codebase_rag_mcp seed-print "$mcp"
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
ensure_cursor_dir() {
|
|
59
|
+
mkdir -p "$cursor_dir"
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
ensure_auth_dir() {
|
|
63
|
+
local dir="$1"
|
|
64
|
+
if ! mkdir -p "$dir" 2>/dev/null; then
|
|
65
|
+
echo "Cannot create $dir (permission denied)." >&2
|
|
66
|
+
echo "The scaffold container likely left .devcontainer root-owned. Fix with:" >&2
|
|
67
|
+
echo " sudo chown -R \"$USER:$USER\" \"$root\"" >&2
|
|
68
|
+
exit 1
|
|
69
|
+
fi
|
|
70
|
+
{
|
|
71
|
+
echo "*"
|
|
72
|
+
echo "!.gitignore"
|
|
73
|
+
} >"$dir/.gitignore"
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
ensure_gh_env() {
|
|
77
|
+
if [[ -d "$gh_env" ]]; then
|
|
78
|
+
echo "Refusing to start: $gh_env is a directory (left by a prior bind mount). Remove it and rebuild." >&2
|
|
79
|
+
exit 1
|
|
80
|
+
fi
|
|
81
|
+
touch "$gh_env"
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
setup_npm_auth() {
|
|
85
|
+
if [[ -f "$npm_dir/.npmrc" ]]; then
|
|
86
|
+
echo "npm auth: using $npm_dir/.npmrc"
|
|
87
|
+
return 0
|
|
88
|
+
fi
|
|
89
|
+
if ! prompt_yn "Configure npm auth for this workspace?"; then
|
|
90
|
+
echo "npm auth: skipped"
|
|
91
|
+
return 0
|
|
92
|
+
fi
|
|
93
|
+
if [[ -f "${HOME}/.npmrc" ]]; then
|
|
94
|
+
cp -a "${HOME}/.npmrc" "$npm_dir/.npmrc"
|
|
95
|
+
echo "npm auth: copied ~/.npmrc → $npm_dir/.npmrc"
|
|
96
|
+
return 0
|
|
97
|
+
fi
|
|
98
|
+
echo "npm auth: no ~/.npmrc — log in inside the container if prompted"
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
setup_gh_auth() {
|
|
102
|
+
if [[ -f "$gh_dir/hosts.yml" ]]; then
|
|
103
|
+
echo "gh auth: using $gh_dir/hosts.yml"
|
|
104
|
+
return 0
|
|
105
|
+
fi
|
|
106
|
+
if ! prompt_yn "Configure GitHub CLI auth for this workspace?"; then
|
|
107
|
+
echo "gh auth: skipped"
|
|
108
|
+
return 0
|
|
109
|
+
fi
|
|
110
|
+
if [[ -f "${HOME}/.config/gh/hosts.yml" ]]; then
|
|
111
|
+
cp -a "${HOME}/.config/gh/hosts.yml" "$gh_dir/hosts.yml"
|
|
112
|
+
[[ -f "${HOME}/.config/gh/config.yml" ]] &&
|
|
113
|
+
cp -a "${HOME}/.config/gh/config.yml" "$gh_dir/config.yml"
|
|
114
|
+
echo "gh auth: copied ~/.config/gh → $gh_dir"
|
|
115
|
+
return 0
|
|
116
|
+
fi
|
|
117
|
+
echo "gh auth: no ~/.config/gh/hosts.yml — log in inside the container if prompted"
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
setup_codebase_rag_env() {
|
|
121
|
+
load_rag_env
|
|
122
|
+
if [[ -n "$RAG_URL" && -n "$RAG_TOKEN" ]]; then
|
|
123
|
+
write_rag_env
|
|
124
|
+
echo "codebase-rag MCP: using $RAG_ENV"
|
|
125
|
+
return 0
|
|
126
|
+
fi
|
|
127
|
+
|
|
128
|
+
local seeded
|
|
129
|
+
if seeded="$(seed_rag_from_host_mcp 2>/dev/null)"; then
|
|
130
|
+
if prompt_yn "Found codebase-rag in ~/.cursor/mcp.json. Use it for this workspace?" y; then
|
|
131
|
+
RAG_URL="$(printf '%s\n' "$seeded" | sed -n '1p')"
|
|
132
|
+
RAG_TOKEN="$(printf '%s\n' "$seeded" | sed -n '2p')"
|
|
133
|
+
write_rag_env
|
|
134
|
+
echo "codebase-rag MCP: imported HTTP server from ~/.cursor/mcp.json → $RAG_ENV"
|
|
135
|
+
return 0
|
|
136
|
+
fi
|
|
137
|
+
fi
|
|
138
|
+
|
|
139
|
+
if ! prompt_yn "Configure codebase RAG MCP (semantic search)?"; then
|
|
140
|
+
RAG_URL=""
|
|
141
|
+
RAG_TOKEN=""
|
|
142
|
+
write_rag_env
|
|
143
|
+
echo "codebase-rag MCP: skipped"
|
|
144
|
+
return 0
|
|
145
|
+
fi
|
|
146
|
+
|
|
147
|
+
printf '%s\n' "Empty URL skips. Example: https://rag.example.com/mcp" >/dev/tty
|
|
148
|
+
printf '%s' "MCP URL: " >/dev/tty
|
|
149
|
+
read_tty RAG_URL
|
|
150
|
+
RAG_URL="$(printf '%s' "$RAG_URL" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')"
|
|
151
|
+
if [[ -z "$RAG_URL" ]]; then
|
|
152
|
+
RAG_TOKEN=""
|
|
153
|
+
write_rag_env
|
|
154
|
+
echo "codebase-rag MCP: skipped"
|
|
155
|
+
return 0
|
|
156
|
+
fi
|
|
157
|
+
printf '%s' "Bearer token (hidden): " >/dev/tty
|
|
158
|
+
read_tty RAG_TOKEN hidden
|
|
159
|
+
write_rag_env
|
|
160
|
+
echo "codebase-rag MCP: saved $RAG_ENV"
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
ensure_auth_dir "$npm_dir"
|
|
164
|
+
ensure_auth_dir "$gh_dir"
|
|
165
|
+
ensure_gh_env
|
|
166
|
+
ensure_cursor_dir
|
|
167
|
+
setup_npm_auth
|
|
168
|
+
setup_gh_auth
|
|
169
|
+
setup_codebase_rag_env
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Runs after container create and when workspace content updates
|
|
3
|
+
# (devcontainer postCreateCommand / updateContentCommand).
|
|
4
|
+
# Installs deps when missing or when the lockfile changed; skips otherwise.
|
|
5
|
+
set -euo pipefail
|
|
6
|
+
|
|
7
|
+
root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
8
|
+
cd "$root"
|
|
9
|
+
|
|
10
|
+
lockfile="pnpm-lock.yaml"
|
|
11
|
+
stamp="node_modules/.decohere-pnpm-lock.sha"
|
|
12
|
+
|
|
13
|
+
current_hash=""
|
|
14
|
+
if [[ -f "$lockfile" ]]; then
|
|
15
|
+
current_hash="$(sha256sum "$lockfile" | awk '{print $1}')"
|
|
16
|
+
elif [[ -f package.json ]]; then
|
|
17
|
+
current_hash="$(sha256sum package.json | awk '{print $1}')"
|
|
18
|
+
fi
|
|
19
|
+
|
|
20
|
+
if [[ -d node_modules/.bin ]] && [[ -n "$current_hash" ]] && [[ -f "$stamp" ]] && [[ "$(cat "$stamp")" == "$current_hash" ]]; then
|
|
21
|
+
echo "node_modules: up to date, skipping pnpm install"
|
|
22
|
+
exit 0
|
|
23
|
+
fi
|
|
24
|
+
|
|
25
|
+
echo "node_modules: installing dependencies (first create may take a while)..."
|
|
26
|
+
if [[ -f "$lockfile" ]]; then
|
|
27
|
+
pnpm install --frozen-lockfile
|
|
28
|
+
else
|
|
29
|
+
pnpm install
|
|
30
|
+
fi
|
|
31
|
+
|
|
32
|
+
if [[ -n "$current_hash" ]]; then
|
|
33
|
+
mkdir -p node_modules
|
|
34
|
+
printf '%s\n' "$current_hash" >"$stamp"
|
|
35
|
+
fi
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Runs on every container start (devcontainer postStartCommand).
|
|
3
|
+
# Optional npm / gh login is y/N on a TTY. Install is post-create.sh.
|
|
4
|
+
# MCP merge also runs here for later reconnects; the Compose service command
|
|
5
|
+
# merges before Cursor attaches (postStart is too late for the first snapshot).
|
|
6
|
+
set -euo pipefail
|
|
7
|
+
|
|
8
|
+
here="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
9
|
+
root="$(cd "$here/.." && pwd)"
|
|
10
|
+
# shellcheck source=tty-prompt.sh
|
|
11
|
+
source "$here/tty-prompt.sh"
|
|
12
|
+
|
|
13
|
+
CODEBASE_RAG_WORKSPACE="$root" node --experimental-strip-types "$here/codebase-rag-mcp.ts" merge ||
|
|
14
|
+
echo "codebase-rag MCP: merge skipped" >&2
|
|
15
|
+
|
|
16
|
+
AUTH_REGISTRY="https://registry.npmjs.org"
|
|
17
|
+
|
|
18
|
+
ensure_npm_auth() {
|
|
19
|
+
if npm whoami --registry "$AUTH_REGISTRY" >/dev/null 2>&1; then
|
|
20
|
+
echo "npm: logged in as $(npm whoami --registry "$AUTH_REGISTRY")"
|
|
21
|
+
return 0
|
|
22
|
+
fi
|
|
23
|
+
|
|
24
|
+
if prompt_yn "Log in to npm?"; then
|
|
25
|
+
echo "npm: starting login..."
|
|
26
|
+
npm login --registry "$AUTH_REGISTRY" </dev/tty >/dev/tty
|
|
27
|
+
return 0
|
|
28
|
+
fi
|
|
29
|
+
|
|
30
|
+
echo "npm: skipped. Open a terminal and run: npm login" >&2
|
|
31
|
+
echo " (creds persist in .devcontainer/npm-auth/)" >&2
|
|
32
|
+
return 1
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
ensure_gh_auth() {
|
|
36
|
+
if ! command -v gh >/dev/null 2>&1; then
|
|
37
|
+
echo "gh: not installed in this container" >&2
|
|
38
|
+
return 1
|
|
39
|
+
fi
|
|
40
|
+
|
|
41
|
+
if gh auth status >/dev/null 2>&1; then
|
|
42
|
+
echo "gh: $(gh auth status 2>&1 | head -n1)"
|
|
43
|
+
return 0
|
|
44
|
+
fi
|
|
45
|
+
|
|
46
|
+
local token="${GH_TOKEN:-${GITHUB_TOKEN:-}}"
|
|
47
|
+
if [[ -n "$token" ]]; then
|
|
48
|
+
echo "gh: authenticating from GH_TOKEN..."
|
|
49
|
+
printf '%s\n' "$token" | gh auth login --with-token
|
|
50
|
+
return 0
|
|
51
|
+
fi
|
|
52
|
+
|
|
53
|
+
if prompt_yn "Log in to GitHub CLI (gh)?"; then
|
|
54
|
+
echo "gh: starting login..."
|
|
55
|
+
gh auth login </dev/tty >/dev/tty
|
|
56
|
+
return 0
|
|
57
|
+
fi
|
|
58
|
+
|
|
59
|
+
echo "gh: skipped. Open a terminal and run: gh auth login" >&2
|
|
60
|
+
echo " (creds persist in .devcontainer/gh-auth/; or set GH_TOKEN in .devcontainer/gh.env)" >&2
|
|
61
|
+
return 1
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
ensure_npm_auth || true
|
|
65
|
+
ensure_gh_auth || true
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
can_prompt() {
|
|
2
|
+
[[ -r /dev/tty && -w /dev/tty ]]
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
read_tty() {
|
|
6
|
+
local var="$1"
|
|
7
|
+
local hidden="${2:-}"
|
|
8
|
+
local value=""
|
|
9
|
+
if [[ -n "$hidden" ]]; then
|
|
10
|
+
read -r -s value </dev/tty || true
|
|
11
|
+
printf '\n' >/dev/tty
|
|
12
|
+
else
|
|
13
|
+
read -r value </dev/tty || true
|
|
14
|
+
fi
|
|
15
|
+
printf -v "$var" '%s' "$value"
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
# Returns 0 for yes. Default is n unless the second argument is y.
|
|
19
|
+
prompt_yn() {
|
|
20
|
+
local question="$1"
|
|
21
|
+
local default="${2:-n}"
|
|
22
|
+
local reply=""
|
|
23
|
+
if ! can_prompt; then
|
|
24
|
+
return 1
|
|
25
|
+
fi
|
|
26
|
+
local hint="y/N"
|
|
27
|
+
if [[ "$default" == "y" ]]; then
|
|
28
|
+
hint="Y/n"
|
|
29
|
+
fi
|
|
30
|
+
printf '%s [%s] ' "$question" "$hint" >/dev/tty
|
|
31
|
+
read_tty reply
|
|
32
|
+
reply="$(printf '%s' "$reply" | tr '[:upper:]' '[:lower:]' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')"
|
|
33
|
+
if [[ -z "$reply" ]]; then
|
|
34
|
+
[[ "$default" == "y" ]]
|
|
35
|
+
return
|
|
36
|
+
fi
|
|
37
|
+
[[ "$reply" == "y" || "$reply" == "yes" ]]
|
|
38
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Feature } from "../../services/scaffold.service.js";
|
|
2
|
+
export type AuthOptions = {
|
|
3
|
+
authProvider?: "auth0" | "none";
|
|
4
|
+
issuerBaseUrl?: string;
|
|
5
|
+
audience?: string;
|
|
6
|
+
databaseProvider?: "none" | "postgres/typeorm";
|
|
7
|
+
adminUsername?: string;
|
|
8
|
+
adminPassword?: string;
|
|
9
|
+
};
|
|
10
|
+
export declare const AuthFeature: Feature<AuthOptions>;
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/** Management API scopes needed for API, SPA, connections, and admin users. */
|
|
2
|
+
declare const REQUIRED_SCOPES: string;
|
|
3
|
+
/** Default API scopes matching Hello CASL Authorize decorators. */
|
|
4
|
+
export declare const HELLO_API_SCOPES: readonly ["read:Hello", "create:Hello", "update:Hello", "delete:Hello"];
|
|
5
|
+
export declare const DB_CONNECTION_NAME = "Username-Password-Authentication";
|
|
6
|
+
export declare class Auth0AuthError extends Error {
|
|
7
|
+
constructor(message: string);
|
|
8
|
+
}
|
|
9
|
+
export interface Auth0Tenant {
|
|
10
|
+
name: string;
|
|
11
|
+
active?: boolean;
|
|
12
|
+
}
|
|
13
|
+
export declare function isInstalled(): boolean;
|
|
14
|
+
export declare function listTenants(): Auth0Tenant[];
|
|
15
|
+
/** Device/URL login (`--no-input`) so Docker can print a host-browser URL. */
|
|
16
|
+
export declare function login(): boolean;
|
|
17
|
+
export declare function listApis(): Array<{
|
|
18
|
+
identifier: string;
|
|
19
|
+
name: string;
|
|
20
|
+
}>;
|
|
21
|
+
export declare function createApi(name: string, identifier: string, scopes?: readonly string[]): {
|
|
22
|
+
identifier: string;
|
|
23
|
+
};
|
|
24
|
+
export declare function listApiScopes(identifier: string): string[];
|
|
25
|
+
/** Assign API permissions to a user (Authorization Core). Idempotent when already granted. */
|
|
26
|
+
export declare function assignUserPermissions(userId: string, audience: string, permissions: readonly string[]): void;
|
|
27
|
+
/**
|
|
28
|
+
* Replace an API's scopes and enable RBAC policy enforcement.
|
|
29
|
+
* Auth0 CLI `--scopes` replaces the full set.
|
|
30
|
+
*/
|
|
31
|
+
export declare function updateApiScopes(identifier: string, scopes?: readonly string[]): void;
|
|
32
|
+
/** True when Auth0 refuses create because the tenant hit its Applications quota. */
|
|
33
|
+
export declare function isAuth0EntityLimitError(err: unknown): boolean;
|
|
34
|
+
/**
|
|
35
|
+
* Actionable message when Auth0 will not create another application.
|
|
36
|
+
* Does not suggest reusing unrelated apps — free tenants must delete unused ones.
|
|
37
|
+
*/
|
|
38
|
+
export declare function formatSpaEntityLimitError(appName: string, apps: Auth0App[]): string;
|
|
39
|
+
export declare function createSpaApp(name: string, callbackUrls: string | readonly string[]): {
|
|
40
|
+
client_id: string;
|
|
41
|
+
};
|
|
42
|
+
export type Auth0App = {
|
|
43
|
+
client_id: string;
|
|
44
|
+
name: string;
|
|
45
|
+
};
|
|
46
|
+
export declare function listApps(): Auth0App[];
|
|
47
|
+
export declare function updateSpaCallbacks(clientId: string, callbackUrls: string | readonly string[]): void;
|
|
48
|
+
/**
|
|
49
|
+
* Create a Postman SPA, or reuse an existing app with the same name (re-scaffold).
|
|
50
|
+
* Always returns a client_id suitable for Postman auth0ClientId.
|
|
51
|
+
* On Auth0 application-quota errors, throws a clear delete-apps message (no cross-app reuse).
|
|
52
|
+
*/
|
|
53
|
+
export declare function ensureSpaApp(name: string, callbackUrls: string | readonly string[]): {
|
|
54
|
+
client_id: string;
|
|
55
|
+
reused: boolean;
|
|
56
|
+
};
|
|
57
|
+
/** Enable a database connection for an application (required for username/password login). */
|
|
58
|
+
export declare function enableConnectionForClient(connectionName: string, clientId: string): void;
|
|
59
|
+
export type AdminDatabaseUser = {
|
|
60
|
+
user_id: string;
|
|
61
|
+
email: string;
|
|
62
|
+
password: string;
|
|
63
|
+
username: string;
|
|
64
|
+
};
|
|
65
|
+
/** Strong default password when the scaffolder caller leaves password blank. */
|
|
66
|
+
export declare function generateAdminPassword(): string;
|
|
67
|
+
/** Look up a user by email (Management API users-by-email). */
|
|
68
|
+
export declare function findUserByEmail(email: string): {
|
|
69
|
+
user_id: string;
|
|
70
|
+
email: string;
|
|
71
|
+
} | null;
|
|
72
|
+
/** Reset password so a re-scaffold can write a known password to .env. */
|
|
73
|
+
export declare function updateUserPassword(userId: string, password: string): void;
|
|
74
|
+
/**
|
|
75
|
+
* Create a DB connection root-admin user for local / Postman login.
|
|
76
|
+
* If the user already exists, look them up, reset password to `input.password`,
|
|
77
|
+
* and return that identity so callers can still write .env credentials.
|
|
78
|
+
*/
|
|
79
|
+
export declare function createAdminDatabaseUser(input: {
|
|
80
|
+
email: string;
|
|
81
|
+
password: string;
|
|
82
|
+
username: string;
|
|
83
|
+
}): AdminDatabaseUser;
|
|
84
|
+
export { REQUIRED_SCOPES };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Feature } from "../../services/scaffold.service.js";
|
|
2
|
+
export type DatabaseOptions = {
|
|
3
|
+
databaseProvider?: "none" | "postgres/typeorm";
|
|
4
|
+
/** When true, merge into an existing workspace (\`webapi add\`). */
|
|
5
|
+
add?: boolean;
|
|
6
|
+
};
|
|
7
|
+
export declare const DatabaseFeature: Feature<DatabaseOptions>;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Feature } from "../../services/scaffold.service.js";
|
|
2
|
+
import { type Auth0Env } from "../postman/openapi-to-postman.js";
|
|
3
|
+
/** Postman OAuth callback URLs (popup + "Authorize using browser"). */
|
|
4
|
+
declare const POSTMAN_CALLBACKS: readonly ["https://oauth.pstmn.io/v1/callback", "https://oauth.pstmn.io/v1/browser-callback"];
|
|
5
|
+
/** Scopes requested for Auth0 access tokens (OIDC + Hello CASL permissions). */
|
|
6
|
+
declare const POSTMAN_SCOPES: string;
|
|
7
|
+
export type PostmanOptions = {
|
|
8
|
+
postmanProvider?: "api" | "local" | "none";
|
|
9
|
+
apiKey?: string;
|
|
10
|
+
workspaceId?: string;
|
|
11
|
+
};
|
|
12
|
+
/** Build Postman collection: OpenAPI routes + Auth0 auth overlay. */
|
|
13
|
+
export declare function buildHybridPostmanCollection(projectName: string, auth?: Auth0Env): Promise<import("../postman/openapi-to-postman.js").PostmanCollection>;
|
|
14
|
+
export declare const PostmanFeature: Feature<PostmanOptions>;
|
|
15
|
+
export { buildHelloOpenApiDocument } from "../postman/hello-openapi.js";
|
|
16
|
+
export { POSTMAN_CALLBACKS, POSTMAN_SCOPES };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { KeyedModel, SourceFile } from "../../models/source-file.js";
|
|
2
|
+
/**
|
|
3
|
+
* Builder for `projects/<api>/package.json`.
|
|
4
|
+
*
|
|
5
|
+
* Starts with the core `@decohere/http` + `@decohere/crucible` deps. Features can call
|
|
6
|
+
* `addDependency` / `addDevDependency` to extend.
|
|
7
|
+
*/
|
|
8
|
+
export declare class ApiPackageJson implements KeyedModel {
|
|
9
|
+
private readonly workspaceName;
|
|
10
|
+
private readonly apiName;
|
|
11
|
+
readonly key: string;
|
|
12
|
+
private readonly _dependencies;
|
|
13
|
+
private readonly _devDependencies;
|
|
14
|
+
constructor(workspaceName: string, apiName?: string);
|
|
15
|
+
addDependency(name: string, version: string): this;
|
|
16
|
+
addDevDependency(name: string, version: string): this;
|
|
17
|
+
files(): SourceFile[];
|
|
18
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { KeyedModel, SourceFile } from "../../models/source-file.js";
|
|
2
|
+
export type AdminUserConfig = {
|
|
3
|
+
sub: string;
|
|
4
|
+
email: string;
|
|
5
|
+
password: string;
|
|
6
|
+
username: string;
|
|
7
|
+
};
|
|
8
|
+
export type AuthConfig = {
|
|
9
|
+
issuerBaseUrl: string;
|
|
10
|
+
audience: string;
|
|
11
|
+
adminUser?: AdminUserConfig;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Data-carrier model for auth configuration.
|
|
15
|
+
*
|
|
16
|
+
* Registered by AuthFeature when auth0 is configured. Other features (e.g.
|
|
17
|
+
* PostmanFeature) retrieve it via workspace.getModel(WELL_KNOWN_FILES.AUTH_CONFIG).
|
|
18
|
+
* Produces no files — exists solely so features can communicate auth details.
|
|
19
|
+
*/
|
|
20
|
+
export declare class AuthConfigModel implements KeyedModel {
|
|
21
|
+
readonly config: AuthConfig;
|
|
22
|
+
readonly key: string;
|
|
23
|
+
constructor(config: AuthConfig);
|
|
24
|
+
setAdminUser(adminUser: AdminUserConfig): void;
|
|
25
|
+
files(): SourceFile[];
|
|
26
|
+
}
|