@decohere/scaffold 0.0.1-dev.18 → 0.0.1-dev.81
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/commonjs/src/add-api.action.js +39 -0
- package/commonjs/src/add-api.command.js +41 -0
- package/commonjs/src/add.command.js +24 -0
- package/commonjs/src/add.module.js +26 -0
- package/commonjs/src/cli.js +9 -0
- package/commonjs/src/create.command.js +24 -0
- package/commonjs/src/create.module.js +26 -0
- package/commonjs/src/domain/prompt.js +64 -0
- package/commonjs/src/index.js +38 -0
- package/commonjs/src/models/compose.model.js +150 -0
- package/commonjs/src/models/config-yaml.model.js +88 -0
- package/commonjs/src/models/const.js +32 -0
- package/commonjs/src/models/dev-container.model.js +116 -0
- package/commonjs/src/models/docker-image.model.js +259 -0
- package/commonjs/src/models/env-file.model.js +50 -0
- package/commonjs/src/models/gitignore.model.js +43 -0
- package/commonjs/src/models/launch-json.model.js +74 -0
- package/commonjs/src/models/package-json.model.js +149 -0
- package/commonjs/src/models/project.model.js +134 -0
- package/commonjs/src/models/source-file.js +6 -0
- package/commonjs/src/models/tsconfig.model.js +34 -0
- package/commonjs/src/models/vitest-config.model.js +35 -0
- package/commonjs/src/models/vscode-settings.model.js +31 -0
- package/commonjs/src/program.js +57 -0
- package/commonjs/src/resolve-target-dir.js +19 -0
- package/commonjs/src/services/scaffold.service.js +62 -0
- package/commonjs/src/version.js +57 -0
- package/commonjs/src/webapi/api-name.js +95 -0
- package/commonjs/src/webapi/cli-options.js +101 -0
- package/commonjs/src/webapi/const.js +50 -0
- package/commonjs/src/webapi/create-api.js +237 -0
- package/commonjs/src/webapi/devcontainer/codebase-rag-mcp.js +166 -0
- package/commonjs/src/webapi/devcontainer/codebase-rag-mcp.ts +182 -0
- package/commonjs/src/webapi/devcontainer/host-scripts.js +52 -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 +441 -0
- package/commonjs/src/webapi/features/auth0-cli.js +435 -0
- package/commonjs/src/webapi/features/biome-format.js +49 -0
- package/commonjs/src/webapi/features/database.feature.js +433 -0
- package/commonjs/src/webapi/features/finalize.feature.js +95 -0
- package/commonjs/src/webapi/features/postman.feature.js +324 -0
- package/commonjs/src/webapi/models/api-package-json.model.js +60 -0
- package/commonjs/src/webapi/models/auth-config.model.js +26 -0
- package/commonjs/src/webapi/models/controller-source-file.model.js +193 -0
- package/commonjs/src/webapi/models/github-ci.model.js +193 -0
- package/commonjs/src/webapi/models/main-source-file.model.js +167 -0
- package/commonjs/src/webapi/models/production-dockerfile.model.js +157 -0
- package/commonjs/src/webapi/models/sample-files.model.js +60 -0
- package/commonjs/src/webapi/models/webapi-image.model.js +27 -0
- package/commonjs/src/webapi/postman/hello-openapi.js +175 -0
- package/commonjs/src/webapi/postman/local-view.js +184 -0
- package/commonjs/src/webapi/postman/openapi-to-postman.js +202 -0
- package/commonjs/src/webapi/workspace-readme.js +110 -0
- package/commonjs/src/webapi.action.js +30 -0
- package/commonjs/src/webapi.command.js +45 -0
- package/es6/src/add-api.action.js +29 -0
- package/es6/src/add-api.command.js +31 -0
- package/es6/src/add.command.js +14 -0
- package/es6/src/add.module.js +16 -0
- package/es6/src/cli.js +5 -0
- package/es6/src/create.command.js +14 -0
- package/es6/src/create.module.js +16 -0
- package/es6/src/domain/prompt.js +43 -0
- package/es6/src/index.js +8 -0
- package/es6/src/models/compose.model.js +144 -0
- package/es6/src/models/config-yaml.model.js +76 -0
- package/es6/src/models/const.js +22 -0
- package/es6/src/models/dev-container.model.js +106 -0
- package/es6/src/models/docker-image.model.js +217 -0
- package/es6/src/models/env-file.model.js +46 -0
- package/es6/src/models/gitignore.model.js +33 -0
- package/es6/src/models/launch-json.model.js +64 -0
- package/es6/src/models/package-json.model.js +137 -0
- package/es6/src/models/project.model.js +119 -0
- package/es6/src/models/source-file.js +3 -0
- package/es6/src/models/tsconfig.model.js +24 -0
- package/es6/src/models/vitest-config.model.js +25 -0
- package/es6/src/models/vscode-settings.model.js +21 -0
- package/es6/src/program.js +39 -0
- package/es6/src/resolve-target-dir.js +9 -0
- package/es6/src/services/scaffold.service.js +52 -0
- package/es6/src/version.js +36 -0
- package/es6/src/webapi/api-name.js +59 -0
- package/es6/src/webapi/cli-options.js +36 -0
- package/es6/src/webapi/const.js +20 -0
- package/es6/src/webapi/create-api.js +217 -0
- package/es6/src/webapi/devcontainer/codebase-rag-mcp.js +156 -0
- package/es6/src/webapi/devcontainer/codebase-rag-mcp.ts +182 -0
- package/es6/src/webapi/devcontainer/host-scripts.js +31 -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 +390 -0
- package/es6/src/webapi/features/auth0-cli.js +375 -0
- package/es6/src/webapi/features/biome-format.js +42 -0
- package/es6/src/webapi/features/database.feature.js +423 -0
- package/es6/src/webapi/features/finalize.feature.js +85 -0
- package/es6/src/webapi/features/postman.feature.js +258 -0
- package/es6/src/webapi/models/api-package-json.model.js +55 -0
- package/es6/src/webapi/models/auth-config.model.js +22 -0
- package/es6/src/webapi/models/controller-source-file.model.js +184 -0
- package/es6/src/webapi/models/github-ci.model.js +186 -0
- package/es6/src/webapi/models/main-source-file.model.js +163 -0
- package/es6/src/webapi/models/production-dockerfile.model.js +148 -0
- package/es6/src/webapi/models/sample-files.model.js +42 -0
- package/es6/src/webapi/models/webapi-image.model.js +20 -0
- package/es6/src/webapi/postman/hello-openapi.js +168 -0
- package/es6/src/webapi/postman/local-view.js +169 -0
- package/es6/src/webapi/postman/openapi-to-postman.js +179 -0
- package/es6/src/webapi/workspace-readme.js +89 -0
- package/es6/src/webapi.action.js +20 -0
- package/es6/src/webapi.command.js +35 -0
- package/package.json +8 -8
- 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/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/models/compose.model.d.ts +64 -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 +37 -0
- package/types/src/models/docker-image.model.d.ts +84 -0
- package/types/src/models/env-file.model.d.ts +16 -0
- package/types/src/models/gitignore.model.d.ts +7 -0
- package/types/src/models/launch-json.model.d.ts +7 -0
- package/types/src/models/package-json.model.d.ts +35 -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 +3 -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/cli-options.d.ts +6 -0
- package/{src/webapi/const.ts → types/src/webapi/const.d.ts} +7 -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 +80 -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 +23 -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/github-ci.model.ts +0 -188
- 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
- /package/{src/index.ts → types/src/index.d.ts} +0 -0
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { pick } from "../../domain/prompt.js";
|
|
5
|
+
import { WELL_KNOWN_FILES } from "../../models/const.js";
|
|
6
|
+
import { buildHelloOpenApiDocument } from "../postman/hello-openapi.js";
|
|
7
|
+
import { buildEnvironmentYaml, buildLocalViewFilesFromCollection } from "../postman/local-view.js";
|
|
8
|
+
import { applyPostmanAuthOverlay, openApiToPostmanCollection } from "../postman/openapi-to-postman.js";
|
|
9
|
+
import * as auth0Cli from "./auth0-cli.js";
|
|
10
|
+
/** Postman OAuth callback URLs (popup + "Authorize using browser"). */ const POSTMAN_CALLBACKS = [
|
|
11
|
+
"https://oauth.pstmn.io/v1/callback",
|
|
12
|
+
"https://oauth.pstmn.io/v1/browser-callback"
|
|
13
|
+
];
|
|
14
|
+
/** Scopes requested for Auth0 access tokens (OIDC + Hello CASL permissions). */ const POSTMAN_SCOPES = [
|
|
15
|
+
"openid",
|
|
16
|
+
"profile",
|
|
17
|
+
"email",
|
|
18
|
+
"read:Hello",
|
|
19
|
+
"create:Hello",
|
|
20
|
+
"update:Hello",
|
|
21
|
+
"delete:Hello"
|
|
22
|
+
].join(" ");
|
|
23
|
+
const COLLECTION_DESCRIPTION = "Open the project root in Postman Local View (not the postman/ folder). " + "Select the Local environment, then Authorization → Get New Access Token (PKCE). " + "Routes are generated from OpenAPI; Auth0 overlay is hand-authored.";
|
|
24
|
+
async function getOptions(_workspace, cliOptions) {
|
|
25
|
+
if (cliOptions.postmanProvider != null) return {};
|
|
26
|
+
const choices = [
|
|
27
|
+
{
|
|
28
|
+
label: "none",
|
|
29
|
+
description: "skip"
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
label: "local",
|
|
33
|
+
description: "Local View / Native Git files (no API key)"
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
label: "api",
|
|
37
|
+
description: "also upload to Postman.com (needs API key)"
|
|
38
|
+
}
|
|
39
|
+
];
|
|
40
|
+
const selected = await pick("\n Postman: ", choices, (c)=>`${c.label} — ${c.description}`);
|
|
41
|
+
const provider = selected?.label ?? "none";
|
|
42
|
+
if (provider === "none") return {
|
|
43
|
+
postmanProvider: "none"
|
|
44
|
+
};
|
|
45
|
+
if (provider === "local") return {
|
|
46
|
+
postmanProvider: "local"
|
|
47
|
+
};
|
|
48
|
+
const apiKey = process.env.POSTMAN_API_KEY ?? await import("../../domain/prompt.js").then((m)=>m.ask("\n Postman API key (app.getpostman.com/settings/me/api-keys): "));
|
|
49
|
+
const headers = {
|
|
50
|
+
"X-Api-Key": apiKey,
|
|
51
|
+
"Content-Type": "application/json"
|
|
52
|
+
};
|
|
53
|
+
const wsRes = await fetch("https://api.getpostman.com/workspaces", {
|
|
54
|
+
headers
|
|
55
|
+
});
|
|
56
|
+
if (!wsRes.ok) {
|
|
57
|
+
console.error("\n Postman API key invalid — falling back to local files.");
|
|
58
|
+
return {
|
|
59
|
+
postmanProvider: "local"
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
const { workspaces } = await wsRes.json();
|
|
63
|
+
const wsChoices = [
|
|
64
|
+
{
|
|
65
|
+
label: "<new workspace>",
|
|
66
|
+
id: null
|
|
67
|
+
},
|
|
68
|
+
...workspaces.map((w)=>({
|
|
69
|
+
label: `${w.name} (${w.type})`,
|
|
70
|
+
id: w.id
|
|
71
|
+
}))
|
|
72
|
+
];
|
|
73
|
+
const wsPicked = await pick("\n Postman workspace: ", wsChoices, (c)=>c.label);
|
|
74
|
+
let workspaceId;
|
|
75
|
+
if (!wsPicked || wsPicked.id === null) {
|
|
76
|
+
const { ask } = await import("../../domain/prompt.js");
|
|
77
|
+
const wsName = await ask(` Workspace name: `);
|
|
78
|
+
const createRes = await fetch("https://api.getpostman.com/workspaces", {
|
|
79
|
+
method: "POST",
|
|
80
|
+
headers,
|
|
81
|
+
body: JSON.stringify({
|
|
82
|
+
workspace: {
|
|
83
|
+
name: wsName,
|
|
84
|
+
type: "personal"
|
|
85
|
+
}
|
|
86
|
+
})
|
|
87
|
+
});
|
|
88
|
+
const { workspace: ws } = await createRes.json();
|
|
89
|
+
workspaceId = ws.id;
|
|
90
|
+
console.log(` ✓ Workspace created: ${wsName}`);
|
|
91
|
+
} else {
|
|
92
|
+
workspaceId = wsPicked.id;
|
|
93
|
+
}
|
|
94
|
+
return {
|
|
95
|
+
postmanProvider: "api",
|
|
96
|
+
apiKey,
|
|
97
|
+
workspaceId
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
/** Build Postman collection: OpenAPI routes + Auth0 auth overlay. */ export async function buildHybridPostmanCollection(projectName, auth) {
|
|
101
|
+
const openapi = buildHelloOpenApiDocument(projectName);
|
|
102
|
+
const base = await openApiToPostmanCollection(openapi);
|
|
103
|
+
if (base.info._postman_id == null) {
|
|
104
|
+
base.info._postman_id = randomUUID();
|
|
105
|
+
}
|
|
106
|
+
return applyPostmanAuthOverlay(base, projectName, auth, {
|
|
107
|
+
callbacks: POSTMAN_CALLBACKS,
|
|
108
|
+
scopes: POSTMAN_SCOPES,
|
|
109
|
+
description: COLLECTION_DESCRIPTION
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
/** Read a previously scaffolded auth0ClientId so re-scaffold never blanks it. */ function readExistingSpaClientId(targetDir, projectName) {
|
|
113
|
+
const envPath = join(targetDir, "postman/environments", `${projectName}-Local.environment.yaml`);
|
|
114
|
+
if (!existsSync(envPath)) return undefined;
|
|
115
|
+
const text = readFileSync(envPath, "utf8");
|
|
116
|
+
const match = text.match(/key:\s*auth0ClientId\s*\n\s*value:\s*["']?([^"'\n]+)/);
|
|
117
|
+
const value = match?.[1]?.trim();
|
|
118
|
+
return value && value.length > 0 ? value : undefined;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Resolve the Postman SPA client id. Never returns empty — preserves an existing
|
|
122
|
+
* env value on Auth0 failure, otherwise throws so we do not write a blank env.
|
|
123
|
+
*/ function resolveSpaClientId(workspace) {
|
|
124
|
+
const appName = `${workspace.name} Postman`;
|
|
125
|
+
try {
|
|
126
|
+
const app = auth0Cli.ensureSpaApp(appName, [
|
|
127
|
+
...POSTMAN_CALLBACKS
|
|
128
|
+
]);
|
|
129
|
+
console.log(app.reused ? ` ✓ Reusing Auth0 SPA app for Postman PKCE (${app.client_id})` : ` ✓ Auth0 SPA app created for Postman PKCE (${app.client_id})`);
|
|
130
|
+
try {
|
|
131
|
+
auth0Cli.enableConnectionForClient(auth0Cli.DB_CONNECTION_NAME, app.client_id);
|
|
132
|
+
console.log(` ✓ Enabled ${auth0Cli.DB_CONNECTION_NAME} on Postman SPA`);
|
|
133
|
+
} catch (err) {
|
|
134
|
+
console.error(` ✗ Failed to enable DB connection on SPA: ${err instanceof Error ? err.message : err}`);
|
|
135
|
+
}
|
|
136
|
+
return app.client_id;
|
|
137
|
+
} catch (err) {
|
|
138
|
+
const existing = readExistingSpaClientId(workspace.targetDir, workspace.name);
|
|
139
|
+
if (existing) {
|
|
140
|
+
console.error(` ✗ Failed to ensure Auth0 SPA app (${err instanceof Error ? err.message : err})`);
|
|
141
|
+
console.log(` ✓ Keeping existing auth0ClientId from Postman environment (${existing})`);
|
|
142
|
+
return existing;
|
|
143
|
+
}
|
|
144
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
145
|
+
// Entity-limit messages are already actionable; avoid burying them.
|
|
146
|
+
if (auth0Cli.isAuth0EntityLimitError(err)) {
|
|
147
|
+
throw new Error(detail);
|
|
148
|
+
}
|
|
149
|
+
throw new Error(`Failed to ensure Auth0 SPA app for Postman — auth0ClientId would be empty: ${detail}`);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
async function scaffold(workspace, options) {
|
|
153
|
+
if (options.postmanProvider === "none" || options.postmanProvider == null) return;
|
|
154
|
+
const authConfigModel = workspace.getModel(WELL_KNOWN_FILES.AUTH_CONFIG);
|
|
155
|
+
const authCfg = authConfigModel?.config;
|
|
156
|
+
const spaClientId = authCfg?.issuerBaseUrl ? resolveSpaClientId(workspace) : undefined;
|
|
157
|
+
const auth0Env = authCfg?.issuerBaseUrl ? {
|
|
158
|
+
auth0Domain: authCfg.issuerBaseUrl.replace(/^https?:\/\//, ""),
|
|
159
|
+
auth0Audience: authCfg.audience,
|
|
160
|
+
auth0ClientId: spaClientId
|
|
161
|
+
} : undefined;
|
|
162
|
+
const projectName = workspace.name;
|
|
163
|
+
const envName = `${projectName} Local`;
|
|
164
|
+
const collection = await buildHybridPostmanCollection(projectName, auth0Env);
|
|
165
|
+
const localFiles = buildLocalViewFilesFromCollection(collection, projectName, auth0Env, {
|
|
166
|
+
callbacks: POSTMAN_CALLBACKS,
|
|
167
|
+
scopes: POSTMAN_SCOPES
|
|
168
|
+
});
|
|
169
|
+
const envYaml = buildEnvironmentYaml(envName, auth0Env, {
|
|
170
|
+
callbacks: POSTMAN_CALLBACKS,
|
|
171
|
+
scopes: POSTMAN_SCOPES
|
|
172
|
+
});
|
|
173
|
+
workspace.addFile({
|
|
174
|
+
files: ()=>[
|
|
175
|
+
{
|
|
176
|
+
filePath: ".postman/resources.yaml",
|
|
177
|
+
content: [
|
|
178
|
+
"# Open this project root in Postman (Files → Open folder), not the postman/ subfolder.",
|
|
179
|
+
"# Postman fills workspace.id when you connect Local View.",
|
|
180
|
+
"#",
|
|
181
|
+
"# All resources under postman/ are registered automatically.",
|
|
182
|
+
"# Route requests are generated from OpenAPI; Auth0 overlay is hand-authored.",
|
|
183
|
+
""
|
|
184
|
+
].join("\n")
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
filePath: `postman/environments/${projectName}-Local.environment.yaml`,
|
|
188
|
+
content: envYaml
|
|
189
|
+
},
|
|
190
|
+
...localFiles
|
|
191
|
+
]
|
|
192
|
+
});
|
|
193
|
+
if (options.postmanProvider === "api" && options.apiKey) {
|
|
194
|
+
const headers = {
|
|
195
|
+
"X-Api-Key": options.apiKey,
|
|
196
|
+
"Content-Type": "application/json"
|
|
197
|
+
};
|
|
198
|
+
const colRes = await fetch(`https://api.getpostman.com/collections?workspace=${options.workspaceId}`, {
|
|
199
|
+
method: "POST",
|
|
200
|
+
headers,
|
|
201
|
+
body: JSON.stringify({
|
|
202
|
+
collection
|
|
203
|
+
})
|
|
204
|
+
});
|
|
205
|
+
if (colRes.ok) {
|
|
206
|
+
console.log(" ✓ Postman collection uploaded");
|
|
207
|
+
} else {
|
|
208
|
+
console.error(" ✗ Failed to upload Postman collection");
|
|
209
|
+
}
|
|
210
|
+
const envValues = [
|
|
211
|
+
{
|
|
212
|
+
key: "baseUrl",
|
|
213
|
+
value: "http://localhost:3000",
|
|
214
|
+
enabled: true
|
|
215
|
+
},
|
|
216
|
+
...auth0Env?.auth0Domain ? [
|
|
217
|
+
{
|
|
218
|
+
key: "auth0Domain",
|
|
219
|
+
value: auth0Env.auth0Domain,
|
|
220
|
+
enabled: true
|
|
221
|
+
},
|
|
222
|
+
{
|
|
223
|
+
key: "auth0Audience",
|
|
224
|
+
value: auth0Env.auth0Audience ?? "",
|
|
225
|
+
enabled: true
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
key: "auth0ClientId",
|
|
229
|
+
value: auth0Env.auth0ClientId ?? "",
|
|
230
|
+
enabled: true
|
|
231
|
+
}
|
|
232
|
+
] : []
|
|
233
|
+
];
|
|
234
|
+
const envRes = await fetch(`https://api.getpostman.com/environments?workspace=${options.workspaceId}`, {
|
|
235
|
+
method: "POST",
|
|
236
|
+
headers,
|
|
237
|
+
body: JSON.stringify({
|
|
238
|
+
environment: {
|
|
239
|
+
name: envName,
|
|
240
|
+
values: envValues
|
|
241
|
+
}
|
|
242
|
+
})
|
|
243
|
+
});
|
|
244
|
+
if (envRes.ok) {
|
|
245
|
+
console.log(" ✓ Postman environment uploaded");
|
|
246
|
+
} else {
|
|
247
|
+
console.error(" ✗ Failed to upload Postman environment");
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
export const PostmanFeature = {
|
|
252
|
+
getOptions,
|
|
253
|
+
scaffold
|
|
254
|
+
};
|
|
255
|
+
export { buildHelloOpenApiDocument } from "../postman/hello-openapi.js";
|
|
256
|
+
export { POSTMAN_CALLBACKS, POSTMAN_SCOPES };
|
|
257
|
+
|
|
258
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL3J1bm5lci93b3JrL2RlY29oZXJlL2RlY29oZXJlL3Byb2plY3RzL3NjYWZmb2xkL3NyYy93ZWJhcGkvZmVhdHVyZXMvcG9zdG1hbi5mZWF0dXJlLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IHJhbmRvbVVVSUQgfSBmcm9tIFwibm9kZTpjcnlwdG9cIjtcbmltcG9ydCB7IGV4aXN0c1N5bmMsIHJlYWRGaWxlU3luYyB9IGZyb20gXCJub2RlOmZzXCI7XG5pbXBvcnQgeyBqb2luIH0gZnJvbSBcIm5vZGU6cGF0aFwiO1xuaW1wb3J0IHsgcGljayB9IGZyb20gXCIuLi8uLi9kb21haW4vcHJvbXB0LmpzXCI7XG5pbXBvcnQgeyBXRUxMX0tOT1dOX0ZJTEVTIH0gZnJvbSBcIi4uLy4uL21vZGVscy9jb25zdC5qc1wiO1xuaW1wb3J0IHR5cGUgeyBXb3Jrc3BhY2VTY2FmZm9sZCB9IGZyb20gXCIuLi8uLi9tb2RlbHMvcHJvamVjdC5tb2RlbC5qc1wiO1xuaW1wb3J0IHR5cGUgeyBGZWF0dXJlIH0gZnJvbSBcIi4uLy4uL3NlcnZpY2VzL3NjYWZmb2xkLnNlcnZpY2UuanNcIjtcbmltcG9ydCB0eXBlIHsgQXV0aENvbmZpZ01vZGVsIH0gZnJvbSBcIi4uL21vZGVscy9hdXRoLWNvbmZpZy5tb2RlbC5qc1wiO1xuaW1wb3J0IHsgYnVpbGRIZWxsb09wZW5BcGlEb2N1bWVudCB9IGZyb20gXCIuLi9wb3N0bWFuL2hlbGxvLW9wZW5hcGkuanNcIjtcbmltcG9ydCB7XG5cdGJ1aWxkRW52aXJvbm1lbnRZYW1sLFxuXHRidWlsZExvY2FsVmlld0ZpbGVzRnJvbUNvbGxlY3Rpb24sXG59IGZyb20gXCIuLi9wb3N0bWFuL2xvY2FsLXZpZXcuanNcIjtcbmltcG9ydCB7XG5cdHR5cGUgQXV0aDBFbnYsXG5cdGFwcGx5UG9zdG1hbkF1dGhPdmVybGF5LFxuXHRvcGVuQXBpVG9Qb3N0bWFuQ29sbGVjdGlvbixcbn0gZnJvbSBcIi4uL3Bvc3RtYW4vb3BlbmFwaS10by1wb3N0bWFuLmpzXCI7XG5pbXBvcnQgKiBhcyBhdXRoMENsaSBmcm9tIFwiLi9hdXRoMC1jbGkuanNcIjtcblxuLyoqIFBvc3RtYW4gT0F1dGggY2FsbGJhY2sgVVJMcyAocG9wdXAgKyBcIkF1dGhvcml6ZSB1c2luZyBicm93c2VyXCIpLiAqL1xuY29uc3QgUE9TVE1BTl9DQUxMQkFDS1MgPSBbXG5cdFwiaHR0cHM6Ly9vYXV0aC5wc3Rtbi5pby92MS9jYWxsYmFja1wiLFxuXHRcImh0dHBzOi8vb2F1dGgucHN0bW4uaW8vdjEvYnJvd3Nlci1jYWxsYmFja1wiLFxuXSBhcyBjb25zdDtcblxuLyoqIFNjb3BlcyByZXF1ZXN0ZWQgZm9yIEF1dGgwIGFjY2VzcyB0b2tlbnMgKE9JREMgKyBIZWxsbyBDQVNMIHBlcm1pc3Npb25zKS4gKi9cbmNvbnN0IFBPU1RNQU5fU0NPUEVTID0gW1xuXHRcIm9wZW5pZFwiLFxuXHRcInByb2ZpbGVcIixcblx0XCJlbWFpbFwiLFxuXHRcInJlYWQ6SGVsbG9cIixcblx0XCJjcmVhdGU6SGVsbG9cIixcblx0XCJ1cGRhdGU6SGVsbG9cIixcblx0XCJkZWxldGU6SGVsbG9cIixcbl0uam9pbihcIiBcIik7XG5cbmNvbnN0IENPTExFQ1RJT05fREVTQ1JJUFRJT04gPVxuXHRcIk9wZW4gdGhlIHByb2plY3Qgcm9vdCBpbiBQb3N0bWFuIExvY2FsIFZpZXcgKG5vdCB0aGUgcG9zdG1hbi8gZm9sZGVyKS4gXCIgK1xuXHRcIlNlbGVjdCB0aGUgTG9jYWwgZW52aXJvbm1lbnQsIHRoZW4gQXV0aG9yaXphdGlvbiDihpIgR2V0IE5ldyBBY2Nlc3MgVG9rZW4gKFBLQ0UpLiBcIiArXG5cdFwiUm91dGVzIGFyZSBnZW5lcmF0ZWQgZnJvbSBPcGVuQVBJOyBBdXRoMCBvdmVybGF5IGlzIGhhbmQtYXV0aG9yZWQuXCI7XG5cbmV4cG9ydCB0eXBlIFBvc3RtYW5PcHRpb25zID0ge1xuXHRwb3N0bWFuUHJvdmlkZXI/OiBcImFwaVwiIHwgXCJsb2NhbFwiIHwgXCJub25lXCI7XG5cdGFwaUtleT86IHN0cmluZztcblx0d29ya3NwYWNlSWQ/OiBzdHJpbmc7XG59O1xuXG5hc3luYyBmdW5jdGlvbiBnZXRPcHRpb25zKFxuXHRfd29ya3NwYWNlOiBXb3Jrc3BhY2VTY2FmZm9sZCxcblx0Y2xpT3B0aW9uczogUGFydGlhbDxQb3N0bWFuT3B0aW9ucz4sXG4pOiBQcm9taXNlPFBhcnRpYWw8UG9zdG1hbk9wdGlvbnM+PiB7XG5cdGlmIChjbGlPcHRpb25zLnBvc3RtYW5Qcm92aWRlciAhPSBudWxsKSByZXR1cm4ge307XG5cblx0Y29uc3QgY2hvaWNlcyA9IFtcblx0XHR7IGxhYmVsOiBcIm5vbmVcIiBhcyBjb25zdCwgZGVzY3JpcHRpb246IFwic2tpcFwiIH0sXG5cdFx0e1xuXHRcdFx0bGFiZWw6IFwibG9jYWxcIiBhcyBjb25zdCxcblx0XHRcdGRlc2NyaXB0aW9uOiBcIkxvY2FsIFZpZXcgLyBOYXRpdmUgR2l0IGZpbGVzIChubyBBUEkga2V5KVwiLFxuXHRcdH0sXG5cdFx0e1xuXHRcdFx0bGFiZWw6IFwiYXBpXCIgYXMgY29uc3QsXG5cdFx0XHRkZXNjcmlwdGlvbjogXCJhbHNvIHVwbG9hZCB0byBQb3N0bWFuLmNvbSAobmVlZHMgQVBJIGtleSlcIixcblx0XHR9LFxuXHRdO1xuXHRjb25zdCBzZWxlY3RlZCA9IGF3YWl0IHBpY2soXG5cdFx0XCJcXG4gIFBvc3RtYW46IFwiLFxuXHRcdGNob2ljZXMsXG5cdFx0KGMpID0+IGAke2MubGFiZWx9IOKAlCAke2MuZGVzY3JpcHRpb259YCxcblx0KTtcblx0Y29uc3QgcHJvdmlkZXIgPSBzZWxlY3RlZD8ubGFiZWwgPz8gXCJub25lXCI7XG5cblx0aWYgKHByb3ZpZGVyID09PSBcIm5vbmVcIikgcmV0dXJuIHsgcG9zdG1hblByb3ZpZGVyOiBcIm5vbmVcIiB9O1xuXHRpZiAocHJvdmlkZXIgPT09IFwibG9jYWxcIikgcmV0dXJuIHsgcG9zdG1hblByb3ZpZGVyOiBcImxvY2FsXCIgfTtcblxuXHRjb25zdCBhcGlLZXkgPVxuXHRcdHByb2Nlc3MuZW52LlBPU1RNQU5fQVBJX0tFWSA/P1xuXHRcdChhd2FpdCBpbXBvcnQoXCIuLi8uLi9kb21haW4vcHJvbXB0LmpzXCIpLnRoZW4oKG0pID0+XG5cdFx0XHRtLmFzayhcIlxcbiAgUG9zdG1hbiBBUEkga2V5IChhcHAuZ2V0cG9zdG1hbi5jb20vc2V0dGluZ3MvbWUvYXBpLWtleXMpOiBcIiksXG5cdFx0KSk7XG5cblx0Y29uc3QgaGVhZGVycyA9IHsgXCJYLUFwaS1LZXlcIjogYXBpS2V5LCBcIkNvbnRlbnQtVHlwZVwiOiBcImFwcGxpY2F0aW9uL2pzb25cIiB9O1xuXHRjb25zdCB3c1JlcyA9IGF3YWl0IGZldGNoKFwiaHR0cHM6Ly9hcGkuZ2V0cG9zdG1hbi5jb20vd29ya3NwYWNlc1wiLCB7IGhlYWRlcnMgfSk7XG5cblx0aWYgKCF3c1Jlcy5vaykge1xuXHRcdGNvbnNvbGUuZXJyb3IoXCJcXG4gIFBvc3RtYW4gQVBJIGtleSBpbnZhbGlkIOKAlCBmYWxsaW5nIGJhY2sgdG8gbG9jYWwgZmlsZXMuXCIpO1xuXHRcdHJldHVybiB7IHBvc3RtYW5Qcm92aWRlcjogXCJsb2NhbFwiIH07XG5cdH1cblxuXHRjb25zdCB7IHdvcmtzcGFjZXMgfSA9IChhd2FpdCB3c1Jlcy5qc29uKCkpIGFzIHtcblx0XHR3b3Jrc3BhY2VzOiBBcnJheTx7IGlkOiBzdHJpbmc7IG5hbWU6IHN0cmluZzsgdHlwZTogc3RyaW5nIH0+O1xuXHR9O1xuXG5cdHR5cGUgV3NDaG9pY2UgPSB7IGxhYmVsOiBzdHJpbmc7IGlkOiBzdHJpbmcgfCBudWxsIH07XG5cdGNvbnN0IHdzQ2hvaWNlczogV3NDaG9pY2VbXSA9IFtcblx0XHR7IGxhYmVsOiBcIjxuZXcgd29ya3NwYWNlPlwiLCBpZDogbnVsbCB9LFxuXHRcdC4uLndvcmtzcGFjZXMubWFwKCh3KSA9PiAoeyBsYWJlbDogYCR7dy5uYW1lfSAoJHt3LnR5cGV9KWAsIGlkOiB3LmlkIH0pKSxcblx0XTtcblxuXHRjb25zdCB3c1BpY2tlZCA9IGF3YWl0IHBpY2soXCJcXG4gIFBvc3RtYW4gd29ya3NwYWNlOiBcIiwgd3NDaG9pY2VzLCAoYykgPT4gYy5sYWJlbCk7XG5cblx0bGV0IHdvcmtzcGFjZUlkOiBzdHJpbmc7XG5cdGlmICghd3NQaWNrZWQgfHwgd3NQaWNrZWQuaWQgPT09IG51bGwpIHtcblx0XHRjb25zdCB7IGFzayB9ID0gYXdhaXQgaW1wb3J0KFwiLi4vLi4vZG9tYWluL3Byb21wdC5qc1wiKTtcblx0XHRjb25zdCB3c05hbWUgPSBhd2FpdCBhc2soYCAgV29ya3NwYWNlIG5hbWU6IGApO1xuXHRcdGNvbnN0IGNyZWF0ZVJlcyA9IGF3YWl0IGZldGNoKFwiaHR0cHM6Ly9hcGkuZ2V0cG9zdG1hbi5jb20vd29ya3NwYWNlc1wiLCB7XG5cdFx0XHRtZXRob2Q6IFwiUE9TVFwiLFxuXHRcdFx0aGVhZGVycyxcblx0XHRcdGJvZHk6IEpTT04uc3RyaW5naWZ5KHsgd29ya3NwYWNlOiB7IG5hbWU6IHdzTmFtZSwgdHlwZTogXCJwZXJzb25hbFwiIH0gfSksXG5cdFx0fSk7XG5cdFx0Y29uc3QgeyB3b3Jrc3BhY2U6IHdzIH0gPSAoYXdhaXQgY3JlYXRlUmVzLmpzb24oKSkgYXMgeyB3b3Jrc3BhY2U6IHsgaWQ6IHN0cmluZyB9IH07XG5cdFx0d29ya3NwYWNlSWQgPSB3cy5pZDtcblx0XHRjb25zb2xlLmxvZyhgICDinJMgV29ya3NwYWNlIGNyZWF0ZWQ6ICR7d3NOYW1lfWApO1xuXHR9IGVsc2Uge1xuXHRcdHdvcmtzcGFjZUlkID0gd3NQaWNrZWQuaWQ7XG5cdH1cblxuXHRyZXR1cm4geyBwb3N0bWFuUHJvdmlkZXI6IFwiYXBpXCIsIGFwaUtleSwgd29ya3NwYWNlSWQgfTtcbn1cblxuLyoqIEJ1aWxkIFBvc3RtYW4gY29sbGVjdGlvbjogT3BlbkFQSSByb3V0ZXMgKyBBdXRoMCBhdXRoIG92ZXJsYXkuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gYnVpbGRIeWJyaWRQb3N0bWFuQ29sbGVjdGlvbihwcm9qZWN0TmFtZTogc3RyaW5nLCBhdXRoPzogQXV0aDBFbnYpIHtcblx0Y29uc3Qgb3BlbmFwaSA9IGJ1aWxkSGVsbG9PcGVuQXBpRG9jdW1lbnQocHJvamVjdE5hbWUpO1xuXHRjb25zdCBiYXNlID0gYXdhaXQgb3BlbkFwaVRvUG9zdG1hbkNvbGxlY3Rpb24ob3BlbmFwaSk7XG5cdGlmIChiYXNlLmluZm8uX3Bvc3RtYW5faWQgPT0gbnVsbCkge1xuXHRcdGJhc2UuaW5mby5fcG9zdG1hbl9pZCA9IHJhbmRvbVVVSUQoKTtcblx0fVxuXHRyZXR1cm4gYXBwbHlQb3N0bWFuQXV0aE92ZXJsYXkoYmFzZSwgcHJvamVjdE5hbWUsIGF1dGgsIHtcblx0XHRjYWxsYmFja3M6IFBPU1RNQU5fQ0FMTEJBQ0tTLFxuXHRcdHNjb3BlczogUE9TVE1BTl9TQ09QRVMsXG5cdFx0ZGVzY3JpcHRpb246IENPTExFQ1RJT05fREVTQ1JJUFRJT04sXG5cdH0pO1xufVxuXG4vKiogUmVhZCBhIHByZXZpb3VzbHkgc2NhZmZvbGRlZCBhdXRoMENsaWVudElkIHNvIHJlLXNjYWZmb2xkIG5ldmVyIGJsYW5rcyBpdC4gKi9cbmZ1bmN0aW9uIHJlYWRFeGlzdGluZ1NwYUNsaWVudElkKHRhcmdldERpcjogc3RyaW5nLCBwcm9qZWN0TmFtZTogc3RyaW5nKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcblx0Y29uc3QgZW52UGF0aCA9IGpvaW4oXG5cdFx0dGFyZ2V0RGlyLFxuXHRcdFwicG9zdG1hbi9lbnZpcm9ubWVudHNcIixcblx0XHRgJHtwcm9qZWN0TmFtZX0tTG9jYWwuZW52aXJvbm1lbnQueWFtbGAsXG5cdCk7XG5cdGlmICghZXhpc3RzU3luYyhlbnZQYXRoKSkgcmV0dXJuIHVuZGVmaW5lZDtcblx0Y29uc3QgdGV4dCA9IHJlYWRGaWxlU3luYyhlbnZQYXRoLCBcInV0ZjhcIik7XG5cdGNvbnN0IG1hdGNoID0gdGV4dC5tYXRjaCgva2V5OlxccyphdXRoMENsaWVudElkXFxzKlxcblxccyp2YWx1ZTpcXHMqW1wiJ10/KFteXCInXFxuXSspLyk7XG5cdGNvbnN0IHZhbHVlID0gbWF0Y2g/LlsxXT8udHJpbSgpO1xuXHRyZXR1cm4gdmFsdWUgJiYgdmFsdWUubGVuZ3RoID4gMCA/IHZhbHVlIDogdW5kZWZpbmVkO1xufVxuXG4vKipcbiAqIFJlc29sdmUgdGhlIFBvc3RtYW4gU1BBIGNsaWVudCBpZC4gTmV2ZXIgcmV0dXJucyBlbXB0eSDigJQgcHJlc2VydmVzIGFuIGV4aXN0aW5nXG4gKiBlbnYgdmFsdWUgb24gQXV0aDAgZmFpbHVyZSwgb3RoZXJ3aXNlIHRocm93cyBzbyB3ZSBkbyBub3Qgd3JpdGUgYSBibGFuayBlbnYuXG4gKi9cbmZ1bmN0aW9uIHJlc29sdmVTcGFDbGllbnRJZCh3b3Jrc3BhY2U6IFdvcmtzcGFjZVNjYWZmb2xkKTogc3RyaW5nIHtcblx0Y29uc3QgYXBwTmFtZSA9IGAke3dvcmtzcGFjZS5uYW1lfSBQb3N0bWFuYDtcblx0dHJ5IHtcblx0XHRjb25zdCBhcHAgPSBhdXRoMENsaS5lbnN1cmVTcGFBcHAoYXBwTmFtZSwgWy4uLlBPU1RNQU5fQ0FMTEJBQ0tTXSk7XG5cdFx0Y29uc29sZS5sb2coXG5cdFx0XHRhcHAucmV1c2VkXG5cdFx0XHRcdD8gYCAg4pyTIFJldXNpbmcgQXV0aDAgU1BBIGFwcCBmb3IgUG9zdG1hbiBQS0NFICgke2FwcC5jbGllbnRfaWR9KWBcblx0XHRcdFx0OiBgICDinJMgQXV0aDAgU1BBIGFwcCBjcmVhdGVkIGZvciBQb3N0bWFuIFBLQ0UgKCR7YXBwLmNsaWVudF9pZH0pYCxcblx0XHQpO1xuXHRcdHRyeSB7XG5cdFx0XHRhdXRoMENsaS5lbmFibGVDb25uZWN0aW9uRm9yQ2xpZW50KGF1dGgwQ2xpLkRCX0NPTk5FQ1RJT05fTkFNRSwgYXBwLmNsaWVudF9pZCk7XG5cdFx0XHRjb25zb2xlLmxvZyhgICDinJMgRW5hYmxlZCAke2F1dGgwQ2xpLkRCX0NPTk5FQ1RJT05fTkFNRX0gb24gUG9zdG1hbiBTUEFgKTtcblx0XHR9IGNhdGNoIChlcnIpIHtcblx0XHRcdGNvbnNvbGUuZXJyb3IoXG5cdFx0XHRcdGAgIOKclyBGYWlsZWQgdG8gZW5hYmxlIERCIGNvbm5lY3Rpb24gb24gU1BBOiAke2VyciBpbnN0YW5jZW9mIEVycm9yID8gZXJyLm1lc3NhZ2UgOiBlcnJ9YCxcblx0XHRcdCk7XG5cdFx0fVxuXHRcdHJldHVybiBhcHAuY2xpZW50X2lkO1xuXHR9IGNhdGNoIChlcnIpIHtcblx0XHRjb25zdCBleGlzdGluZyA9IHJlYWRFeGlzdGluZ1NwYUNsaWVudElkKHdvcmtzcGFjZS50YXJnZXREaXIsIHdvcmtzcGFjZS5uYW1lKTtcblx0XHRpZiAoZXhpc3RpbmcpIHtcblx0XHRcdGNvbnNvbGUuZXJyb3IoXG5cdFx0XHRcdGAgIOKclyBGYWlsZWQgdG8gZW5zdXJlIEF1dGgwIFNQQSBhcHAgKCR7ZXJyIGluc3RhbmNlb2YgRXJyb3IgPyBlcnIubWVzc2FnZSA6IGVycn0pYCxcblx0XHRcdCk7XG5cdFx0XHRjb25zb2xlLmxvZyhgICDinJMgS2VlcGluZyBleGlzdGluZyBhdXRoMENsaWVudElkIGZyb20gUG9zdG1hbiBlbnZpcm9ubWVudCAoJHtleGlzdGluZ30pYCk7XG5cdFx0XHRyZXR1cm4gZXhpc3Rpbmc7XG5cdFx0fVxuXHRcdGNvbnN0IGRldGFpbCA9IGVyciBpbnN0YW5jZW9mIEVycm9yID8gZXJyLm1lc3NhZ2UgOiBTdHJpbmcoZXJyKTtcblx0XHQvLyBFbnRpdHktbGltaXQgbWVzc2FnZXMgYXJlIGFscmVhZHkgYWN0aW9uYWJsZTsgYXZvaWQgYnVyeWluZyB0aGVtLlxuXHRcdGlmIChhdXRoMENsaS5pc0F1dGgwRW50aXR5TGltaXRFcnJvcihlcnIpKSB7XG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoZGV0YWlsKTtcblx0XHR9XG5cdFx0dGhyb3cgbmV3IEVycm9yKFxuXHRcdFx0YEZhaWxlZCB0byBlbnN1cmUgQXV0aDAgU1BBIGFwcCBmb3IgUG9zdG1hbiDigJQgYXV0aDBDbGllbnRJZCB3b3VsZCBiZSBlbXB0eTogJHtkZXRhaWx9YCxcblx0XHQpO1xuXHR9XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHNjYWZmb2xkKHdvcmtzcGFjZTogV29ya3NwYWNlU2NhZmZvbGQsIG9wdGlvbnM6IFBvc3RtYW5PcHRpb25zKTogUHJvbWlzZTx2b2lkPiB7XG5cdGlmIChvcHRpb25zLnBvc3RtYW5Qcm92aWRlciA9PT0gXCJub25lXCIgfHwgb3B0aW9ucy5wb3N0bWFuUHJvdmlkZXIgPT0gbnVsbCkgcmV0dXJuO1xuXG5cdGNvbnN0IGF1dGhDb25maWdNb2RlbCA9IHdvcmtzcGFjZS5nZXRNb2RlbDxBdXRoQ29uZmlnTW9kZWw+KFdFTExfS05PV05fRklMRVMuQVVUSF9DT05GSUcpO1xuXHRjb25zdCBhdXRoQ2ZnID0gYXV0aENvbmZpZ01vZGVsPy5jb25maWc7XG5cblx0Y29uc3Qgc3BhQ2xpZW50SWQgPSBhdXRoQ2ZnPy5pc3N1ZXJCYXNlVXJsID8gcmVzb2x2ZVNwYUNsaWVudElkKHdvcmtzcGFjZSkgOiB1bmRlZmluZWQ7XG5cblx0Y29uc3QgYXV0aDBFbnY6IEF1dGgwRW52IHwgdW5kZWZpbmVkID0gYXV0aENmZz8uaXNzdWVyQmFzZVVybFxuXHRcdD8ge1xuXHRcdFx0XHRhdXRoMERvbWFpbjogYXV0aENmZy5pc3N1ZXJCYXNlVXJsLnJlcGxhY2UoL15odHRwcz86XFwvXFwvLywgXCJcIiksXG5cdFx0XHRcdGF1dGgwQXVkaWVuY2U6IGF1dGhDZmcuYXVkaWVuY2UsXG5cdFx0XHRcdGF1dGgwQ2xpZW50SWQ6IHNwYUNsaWVudElkLFxuXHRcdFx0fVxuXHRcdDogdW5kZWZpbmVkO1xuXG5cdGNvbnN0IHByb2plY3ROYW1lID0gd29ya3NwYWNlLm5hbWU7XG5cdGNvbnN0IGVudk5hbWUgPSBgJHtwcm9qZWN0TmFtZX0gTG9jYWxgO1xuXHRjb25zdCBjb2xsZWN0aW9uID0gYXdhaXQgYnVpbGRIeWJyaWRQb3N0bWFuQ29sbGVjdGlvbihwcm9qZWN0TmFtZSwgYXV0aDBFbnYpO1xuXHRjb25zdCBsb2NhbEZpbGVzID0gYnVpbGRMb2NhbFZpZXdGaWxlc0Zyb21Db2xsZWN0aW9uKGNvbGxlY3Rpb24sIHByb2plY3ROYW1lLCBhdXRoMEVudiwge1xuXHRcdGNhbGxiYWNrczogUE9TVE1BTl9DQUxMQkFDS1MsXG5cdFx0c2NvcGVzOiBQT1NUTUFOX1NDT1BFUyxcblx0fSk7XG5cdGNvbnN0IGVudllhbWwgPSBidWlsZEVudmlyb25tZW50WWFtbChlbnZOYW1lLCBhdXRoMEVudiwge1xuXHRcdGNhbGxiYWNrczogUE9TVE1BTl9DQUxMQkFDS1MsXG5cdFx0c2NvcGVzOiBQT1NUTUFOX1NDT1BFUyxcblx0fSk7XG5cblx0d29ya3NwYWNlLmFkZEZpbGUoe1xuXHRcdGZpbGVzOiAoKSA9PiBbXG5cdFx0XHR7XG5cdFx0XHRcdGZpbGVQYXRoOiBcIi5wb3N0bWFuL3Jlc291cmNlcy55YW1sXCIsXG5cdFx0XHRcdGNvbnRlbnQ6IFtcblx0XHRcdFx0XHRcIiMgT3BlbiB0aGlzIHByb2plY3Qgcm9vdCBpbiBQb3N0bWFuIChGaWxlcyDihpIgT3BlbiBmb2xkZXIpLCBub3QgdGhlIHBvc3RtYW4vIHN1YmZvbGRlci5cIixcblx0XHRcdFx0XHRcIiMgUG9zdG1hbiBmaWxscyB3b3Jrc3BhY2UuaWQgd2hlbiB5b3UgY29ubmVjdCBMb2NhbCBWaWV3LlwiLFxuXHRcdFx0XHRcdFwiI1wiLFxuXHRcdFx0XHRcdFwiIyBBbGwgcmVzb3VyY2VzIHVuZGVyIHBvc3RtYW4vIGFyZSByZWdpc3RlcmVkIGF1dG9tYXRpY2FsbHkuXCIsXG5cdFx0XHRcdFx0XCIjIFJvdXRlIHJlcXVlc3RzIGFyZSBnZW5lcmF0ZWQgZnJvbSBPcGVuQVBJOyBBdXRoMCBvdmVybGF5IGlzIGhhbmQtYXV0aG9yZWQuXCIsXG5cdFx0XHRcdFx0XCJcIixcblx0XHRcdFx0XS5qb2luKFwiXFxuXCIpLFxuXHRcdFx0fSxcblx0XHRcdHtcblx0XHRcdFx0ZmlsZVBhdGg6IGBwb3N0bWFuL2Vudmlyb25tZW50cy8ke3Byb2plY3ROYW1lfS1Mb2NhbC5lbnZpcm9ubWVudC55YW1sYCxcblx0XHRcdFx0Y29udGVudDogZW52WWFtbCxcblx0XHRcdH0sXG5cdFx0XHQuLi5sb2NhbEZpbGVzLFxuXHRcdF0sXG5cdH0pO1xuXG5cdGlmIChvcHRpb25zLnBvc3RtYW5Qcm92aWRlciA9PT0gXCJhcGlcIiAmJiBvcHRpb25zLmFwaUtleSkge1xuXHRcdGNvbnN0IGhlYWRlcnMgPSB7IFwiWC1BcGktS2V5XCI6IG9wdGlvbnMuYXBpS2V5LCBcIkNvbnRlbnQtVHlwZVwiOiBcImFwcGxpY2F0aW9uL2pzb25cIiB9O1xuXG5cdFx0Y29uc3QgY29sUmVzID0gYXdhaXQgZmV0Y2goXG5cdFx0XHRgaHR0cHM6Ly9hcGkuZ2V0cG9zdG1hbi5jb20vY29sbGVjdGlvbnM/d29ya3NwYWNlPSR7b3B0aW9ucy53b3Jrc3BhY2VJZH1gLFxuXHRcdFx0e1xuXHRcdFx0XHRtZXRob2Q6IFwiUE9TVFwiLFxuXHRcdFx0XHRoZWFkZXJzLFxuXHRcdFx0XHRib2R5OiBKU09OLnN0cmluZ2lmeSh7IGNvbGxlY3Rpb24gfSksXG5cdFx0XHR9LFxuXHRcdCk7XG5cdFx0aWYgKGNvbFJlcy5vaykge1xuXHRcdFx0Y29uc29sZS5sb2coXCIgIOKckyBQb3N0bWFuIGNvbGxlY3Rpb24gdXBsb2FkZWRcIik7XG5cdFx0fSBlbHNlIHtcblx0XHRcdGNvbnNvbGUuZXJyb3IoXCIgIOKclyBGYWlsZWQgdG8gdXBsb2FkIFBvc3RtYW4gY29sbGVjdGlvblwiKTtcblx0XHR9XG5cblx0XHRjb25zdCBlbnZWYWx1ZXMgPSBbXG5cdFx0XHR7IGtleTogXCJiYXNlVXJsXCIsIHZhbHVlOiBcImh0dHA6Ly9sb2NhbGhvc3Q6MzAwMFwiLCBlbmFibGVkOiB0cnVlIH0sXG5cdFx0XHQuLi4oYXV0aDBFbnY/LmF1dGgwRG9tYWluXG5cdFx0XHRcdD8gW1xuXHRcdFx0XHRcdFx0eyBrZXk6IFwiYXV0aDBEb21haW5cIiwgdmFsdWU6IGF1dGgwRW52LmF1dGgwRG9tYWluLCBlbmFibGVkOiB0cnVlIH0sXG5cdFx0XHRcdFx0XHR7IGtleTogXCJhdXRoMEF1ZGllbmNlXCIsIHZhbHVlOiBhdXRoMEVudi5hdXRoMEF1ZGllbmNlID8/IFwiXCIsIGVuYWJsZWQ6IHRydWUgfSxcblx0XHRcdFx0XHRcdHsga2V5OiBcImF1dGgwQ2xpZW50SWRcIiwgdmFsdWU6IGF1dGgwRW52LmF1dGgwQ2xpZW50SWQgPz8gXCJcIiwgZW5hYmxlZDogdHJ1ZSB9LFxuXHRcdFx0XHRcdF1cblx0XHRcdFx0OiBbXSksXG5cdFx0XTtcblx0XHRjb25zdCBlbnZSZXMgPSBhd2FpdCBmZXRjaChcblx0XHRcdGBodHRwczovL2FwaS5nZXRwb3N0bWFuLmNvbS9lbnZpcm9ubWVudHM/d29ya3NwYWNlPSR7b3B0aW9ucy53b3Jrc3BhY2VJZH1gLFxuXHRcdFx0e1xuXHRcdFx0XHRtZXRob2Q6IFwiUE9TVFwiLFxuXHRcdFx0XHRoZWFkZXJzLFxuXHRcdFx0XHRib2R5OiBKU09OLnN0cmluZ2lmeSh7XG5cdFx0XHRcdFx0ZW52aXJvbm1lbnQ6IHsgbmFtZTogZW52TmFtZSwgdmFsdWVzOiBlbnZWYWx1ZXMgfSxcblx0XHRcdFx0fSksXG5cdFx0XHR9LFxuXHRcdCk7XG5cdFx0aWYgKGVudlJlcy5vaykge1xuXHRcdFx0Y29uc29sZS5sb2coXCIgIOKckyBQb3N0bWFuIGVudmlyb25tZW50IHVwbG9hZGVkXCIpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRjb25zb2xlLmVycm9yKFwiICDinJcgRmFpbGVkIHRvIHVwbG9hZCBQb3N0bWFuIGVudmlyb25tZW50XCIpO1xuXHRcdH1cblx0fVxufVxuXG5leHBvcnQgY29uc3QgUG9zdG1hbkZlYXR1cmU6IEZlYXR1cmU8UG9zdG1hbk9wdGlvbnM+ID0geyBnZXRPcHRpb25zLCBzY2FmZm9sZCB9O1xuZXhwb3J0IHsgYnVpbGRIZWxsb09wZW5BcGlEb2N1bWVudCB9IGZyb20gXCIuLi9wb3N0bWFuL2hlbGxvLW9wZW5hcGkuanNcIjtcbmV4cG9ydCB7IFBPU1RNQU5fQ0FMTEJBQ0tTLCBQT1NUTUFOX1NDT1BFUyB9O1xuIl0sIm5hbWVzIjpbInJhbmRvbVVVSUQiLCJleGlzdHNTeW5jIiwicmVhZEZpbGVTeW5jIiwiam9pbiIsInBpY2siLCJXRUxMX0tOT1dOX0ZJTEVTIiwiYnVpbGRIZWxsb09wZW5BcGlEb2N1bWVudCIsImJ1aWxkRW52aXJvbm1lbnRZYW1sIiwiYnVpbGRMb2NhbFZpZXdGaWxlc0Zyb21Db2xsZWN0aW9uIiwiYXBwbHlQb3N0bWFuQXV0aE92ZXJsYXkiLCJvcGVuQXBpVG9Qb3N0bWFuQ29sbGVjdGlvbiIsImF1dGgwQ2xpIiwiUE9TVE1BTl9DQUxMQkFDS1MiLCJQT1NUTUFOX1NDT1BFUyIsIkNPTExFQ1RJT05fREVTQ1JJUFRJT04iLCJnZXRPcHRpb25zIiwiX3dvcmtzcGFjZSIsImNsaU9wdGlvbnMiLCJwb3N0bWFuUHJvdmlkZXIiLCJjaG9pY2VzIiwibGFiZWwiLCJkZXNjcmlwdGlvbiIsInNlbGVjdGVkIiwiYyIsInByb3ZpZGVyIiwiYXBpS2V5IiwicHJvY2VzcyIsImVudiIsIlBPU1RNQU5fQVBJX0tFWSIsInRoZW4iLCJtIiwiYXNrIiwiaGVhZGVycyIsIndzUmVzIiwiZmV0Y2giLCJvayIsImNvbnNvbGUiLCJlcnJvciIsIndvcmtzcGFjZXMiLCJqc29uIiwid3NDaG9pY2VzIiwiaWQiLCJtYXAiLCJ3IiwibmFtZSIsInR5cGUiLCJ3c1BpY2tlZCIsIndvcmtzcGFjZUlkIiwid3NOYW1lIiwiY3JlYXRlUmVzIiwibWV0aG9kIiwiYm9keSIsIkpTT04iLCJzdHJpbmdpZnkiLCJ3b3Jrc3BhY2UiLCJ3cyIsImxvZyIsImJ1aWxkSHlicmlkUG9zdG1hbkNvbGxlY3Rpb24iLCJwcm9qZWN0TmFtZSIsImF1dGgiLCJvcGVuYXBpIiwiYmFzZSIsImluZm8iLCJfcG9zdG1hbl9pZCIsImNhbGxiYWNrcyIsInNjb3BlcyIsInJlYWRFeGlzdGluZ1NwYUNsaWVudElkIiwidGFyZ2V0RGlyIiwiZW52UGF0aCIsInVuZGVmaW5lZCIsInRleHQiLCJtYXRjaCIsInZhbHVlIiwidHJpbSIsImxlbmd0aCIsInJlc29sdmVTcGFDbGllbnRJZCIsImFwcE5hbWUiLCJhcHAiLCJlbnN1cmVTcGFBcHAiLCJyZXVzZWQiLCJjbGllbnRfaWQiLCJlbmFibGVDb25uZWN0aW9uRm9yQ2xpZW50IiwiREJfQ09OTkVDVElPTl9OQU1FIiwiZXJyIiwiRXJyb3IiLCJtZXNzYWdlIiwiZXhpc3RpbmciLCJkZXRhaWwiLCJTdHJpbmciLCJpc0F1dGgwRW50aXR5TGltaXRFcnJvciIsInNjYWZmb2xkIiwib3B0aW9ucyIsImF1dGhDb25maWdNb2RlbCIsImdldE1vZGVsIiwiQVVUSF9DT05GSUciLCJhdXRoQ2ZnIiwiY29uZmlnIiwic3BhQ2xpZW50SWQiLCJpc3N1ZXJCYXNlVXJsIiwiYXV0aDBFbnYiLCJhdXRoMERvbWFpbiIsInJlcGxhY2UiLCJhdXRoMEF1ZGllbmNlIiwiYXVkaWVuY2UiLCJhdXRoMENsaWVudElkIiwiZW52TmFtZSIsImNvbGxlY3Rpb24iLCJsb2NhbEZpbGVzIiwiZW52WWFtbCIsImFkZEZpbGUiLCJmaWxlcyIsImZpbGVQYXRoIiwiY29udGVudCIsImNvbFJlcyIsImVudlZhbHVlcyIsImtleSIsImVuYWJsZWQiLCJlbnZSZXMiLCJlbnZpcm9ubWVudCIsInZhbHVlcyIsIlBvc3RtYW5GZWF0dXJlIl0sIm1hcHBpbmdzIjoiQUFBQSxTQUFTQSxVQUFVLFFBQVEsY0FBYztBQUN6QyxTQUFTQyxVQUFVLEVBQUVDLFlBQVksUUFBUSxVQUFVO0FBQ25ELFNBQVNDLElBQUksUUFBUSxZQUFZO0FBQ2pDLFNBQVNDLElBQUksUUFBUSx5QkFBeUI7QUFDOUMsU0FBU0MsZ0JBQWdCLFFBQVEsd0JBQXdCO0FBSXpELFNBQVNDLHlCQUF5QixRQUFRLDhCQUE4QjtBQUN4RSxTQUNDQyxvQkFBb0IsRUFDcEJDLGlDQUFpQyxRQUMzQiwyQkFBMkI7QUFDbEMsU0FFQ0MsdUJBQXVCLEVBQ3ZCQywwQkFBMEIsUUFDcEIsbUNBQW1DO0FBQzFDLFlBQVlDLGNBQWMsaUJBQWlCO0FBRTNDLHFFQUFxRSxHQUNyRSxNQUFNQyxvQkFBb0I7SUFDekI7SUFDQTtDQUNBO0FBRUQsOEVBQThFLEdBQzlFLE1BQU1DLGlC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
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { WELL_KNOWN_FILES } from "../../models/const.js";
|
|
2
|
+
import { sortStringMap } from "../../models/package-json.model.js";
|
|
3
|
+
import { CREATE_VERSION } from "../../version.js";
|
|
4
|
+
/**
|
|
5
|
+
* Builder for `projects/<api>/package.json`.
|
|
6
|
+
*
|
|
7
|
+
* Starts with the core cortex + crucible deps. Features can call
|
|
8
|
+
* `addDependency` / `addDevDependency` to extend.
|
|
9
|
+
*/ export class ApiPackageJson {
|
|
10
|
+
workspaceName;
|
|
11
|
+
apiName;
|
|
12
|
+
key = WELL_KNOWN_FILES.API_PACKAGE_JSON;
|
|
13
|
+
_dependencies;
|
|
14
|
+
_devDependencies = {};
|
|
15
|
+
constructor(workspaceName, apiName = "api"){
|
|
16
|
+
this.workspaceName = workspaceName;
|
|
17
|
+
this.apiName = apiName;
|
|
18
|
+
this._dependencies = {
|
|
19
|
+
"@decohere/cortex": CREATE_VERSION,
|
|
20
|
+
"@decohere/crucible": CREATE_VERSION
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
addDependency(name, version) {
|
|
24
|
+
this._dependencies[name] = version;
|
|
25
|
+
return this;
|
|
26
|
+
}
|
|
27
|
+
addDevDependency(name, version) {
|
|
28
|
+
this._devDependencies[name] = version;
|
|
29
|
+
return this;
|
|
30
|
+
}
|
|
31
|
+
files() {
|
|
32
|
+
const pkg = {
|
|
33
|
+
name: `@${this.workspaceName}/${this.apiName}`,
|
|
34
|
+
version: "0.0.1",
|
|
35
|
+
private: true,
|
|
36
|
+
type: "module",
|
|
37
|
+
main: "src/main.ts",
|
|
38
|
+
scripts: {
|
|
39
|
+
lint: "biome check --write ."
|
|
40
|
+
},
|
|
41
|
+
dependencies: sortStringMap(this._dependencies)
|
|
42
|
+
};
|
|
43
|
+
if (Object.keys(this._devDependencies).length > 0) {
|
|
44
|
+
pkg.devDependencies = sortStringMap(this._devDependencies);
|
|
45
|
+
}
|
|
46
|
+
return [
|
|
47
|
+
{
|
|
48
|
+
filePath: "package.json",
|
|
49
|
+
content: JSON.stringify(pkg, null, 2)
|
|
50
|
+
}
|
|
51
|
+
];
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL3J1bm5lci93b3JrL2RlY29oZXJlL2RlY29oZXJlL3Byb2plY3RzL3NjYWZmb2xkL3NyYy93ZWJhcGkvbW9kZWxzL2FwaS1wYWNrYWdlLWpzb24ubW9kZWwudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgV0VMTF9LTk9XTl9GSUxFUyB9IGZyb20gXCIuLi8uLi9tb2RlbHMvY29uc3QuanNcIjtcbmltcG9ydCB7IHNvcnRTdHJpbmdNYXAgfSBmcm9tIFwiLi4vLi4vbW9kZWxzL3BhY2thZ2UtanNvbi5tb2RlbC5qc1wiO1xuaW1wb3J0IHR5cGUgeyBLZXllZE1vZGVsLCBTb3VyY2VGaWxlIH0gZnJvbSBcIi4uLy4uL21vZGVscy9zb3VyY2UtZmlsZS5qc1wiO1xuaW1wb3J0IHsgQ1JFQVRFX1ZFUlNJT04gfSBmcm9tIFwiLi4vLi4vdmVyc2lvbi5qc1wiO1xuXG4vKipcbiAqIEJ1aWxkZXIgZm9yIGBwcm9qZWN0cy88YXBpPi9wYWNrYWdlLmpzb25gLlxuICpcbiAqIFN0YXJ0cyB3aXRoIHRoZSBjb3JlIGNvcnRleCArIGNydWNpYmxlIGRlcHMuIEZlYXR1cmVzIGNhbiBjYWxsXG4gKiBgYWRkRGVwZW5kZW5jeWAgLyBgYWRkRGV2RGVwZW5kZW5jeWAgdG8gZXh0ZW5kLlxuICovXG5leHBvcnQgY2xhc3MgQXBpUGFja2FnZUpzb24gaW1wbGVtZW50cyBLZXllZE1vZGVsIHtcblx0cHVibGljIHJlYWRvbmx5IGtleSA9IFdFTExfS05PV05fRklMRVMuQVBJX1BBQ0tBR0VfSlNPTjtcblxuXHRwcml2YXRlIHJlYWRvbmx5IF9kZXBlbmRlbmNpZXM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz47XG5cdHByaXZhdGUgcmVhZG9ubHkgX2RldkRlcGVuZGVuY2llczogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHt9O1xuXG5cdHB1YmxpYyBjb25zdHJ1Y3Rvcihcblx0XHRwcml2YXRlIHJlYWRvbmx5IHdvcmtzcGFjZU5hbWU6IHN0cmluZyxcblx0XHRwcml2YXRlIHJlYWRvbmx5IGFwaU5hbWUgPSBcImFwaVwiLFxuXHQpIHtcblx0XHR0aGlzLl9kZXBlbmRlbmNpZXMgPSB7XG5cdFx0XHRcIkBkZWNvaGVyZS9jb3J0ZXhcIjogQ1JFQVRFX1ZFUlNJT04sXG5cdFx0XHRcIkBkZWNvaGVyZS9jcnVjaWJsZVwiOiBDUkVBVEVfVkVSU0lPTixcblx0XHR9O1xuXHR9XG5cblx0cHVibGljIGFkZERlcGVuZGVuY3kobmFtZTogc3RyaW5nLCB2ZXJzaW9uOiBzdHJpbmcpOiB0aGlzIHtcblx0XHR0aGlzLl9kZXBlbmRlbmNpZXNbbmFtZV0gPSB2ZXJzaW9uO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0cHVibGljIGFkZERldkRlcGVuZGVuY3kobmFtZTogc3RyaW5nLCB2ZXJzaW9uOiBzdHJpbmcpOiB0aGlzIHtcblx0XHR0aGlzLl9kZXZEZXBlbmRlbmNpZXNbbmFtZV0gPSB2ZXJzaW9uO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0cHVibGljIGZpbGVzKCk6IFNvdXJjZUZpbGVbXSB7XG5cdFx0Y29uc3QgcGtnOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiA9IHtcblx0XHRcdG5hbWU6IGBAJHt0aGlzLndvcmtzcGFjZU5hbWV9LyR7dGhpcy5hcGlOYW1lfWAsXG5cdFx0XHR2ZXJzaW9uOiBcIjAuMC4xXCIsXG5cdFx0XHRwcml2YXRlOiB0cnVlLFxuXHRcdFx0dHlwZTogXCJtb2R1bGVcIixcblx0XHRcdG1haW46IFwic3JjL21haW4udHNcIixcblx0XHRcdHNjcmlwdHM6IHtcblx0XHRcdFx0bGludDogXCJiaW9tZSBjaGVjayAtLXdyaXRlIC5cIixcblx0XHRcdH0sXG5cdFx0XHRkZXBlbmRlbmNpZXM6IHNvcnRTdHJpbmdNYXAodGhpcy5fZGVwZW5kZW5jaWVzKSxcblx0XHR9O1xuXHRcdGlmIChPYmplY3Qua2V5cyh0aGlzLl9kZXZEZXBlbmRlbmNpZXMpLmxlbmd0aCA+IDApIHtcblx0XHRcdHBrZy5kZXZEZXBlbmRlbmNpZXMgPSBzb3J0U3RyaW5nTWFwKHRoaXMuX2RldkRlcGVuZGVuY2llcyk7XG5cdFx0fVxuXHRcdHJldHVybiBbXG5cdFx0XHR7XG5cdFx0XHRcdGZpbGVQYXRoOiBcInBhY2thZ2UuanNvblwiLFxuXHRcdFx0XHRjb250ZW50OiBKU09OLnN0cmluZ2lmeShwa2csIG51bGwsIDIpLFxuXHRcdFx0fSxcblx0XHRdO1xuXHR9XG59XG4iXSwibmFtZXMiOlsiV0VMTF9LTk9XTl9GSUxFUyIsInNvcnRTdHJpbmdNYXAiLCJDUkVBVEVfVkVSU0lPTiIsIkFwaVBhY2thZ2VKc29uIiwia2V5IiwiQVBJX1BBQ0tBR0VfSlNPTiIsIl9kZXBlbmRlbmNpZXMiLCJfZGV2RGVwZW5kZW5jaWVzIiwid29ya3NwYWNlTmFtZSIsImFwaU5hbWUiLCJhZGREZXBlbmRlbmN5IiwibmFtZSIsInZlcnNpb24iLCJhZGREZXZEZXBlbmRlbmN5IiwiZmlsZXMiLCJwa2ciLCJwcml2YXRlIiwidHlwZSIsIm1haW4iLCJzY3JpcHRzIiwibGludCIsImRlcGVuZGVuY2llcyIsIk9iamVjdCIsImtleXMiLCJsZW5ndGgiLCJkZXZEZXBlbmRlbmNpZXMiLCJmaWxlUGF0aCIsImNvbnRlbnQiLCJKU09OIiwic3RyaW5naWZ5Il0sIm1hcHBpbmdzIjoiQUFBQSxTQUFTQSxnQkFBZ0IsUUFBUSx3QkFBd0I7QUFDekQsU0FBU0MsYUFBYSxRQUFRLHFDQUFxQztBQUVuRSxTQUFTQyxjQUFjLFFBQVEsbUJBQW1CO0FBRWxEOzs7OztDQUtDLEdBQ0QsT0FBTyxNQUFNQzs7O0lBQ0lDLE1BQU1KLGlCQUFpQkssZ0JBQWdCLENBQUM7SUFFdkNDLGNBQXNDO0lBQ3RDQyxtQkFBMkMsQ0FBQyxFQUFFO0lBRS9ELFlBQ0MsQUFBaUJDLGFBQXFCLEVBQ3RDLEFBQWlCQyxVQUFVLEtBQUssQ0FDL0I7YUFGZ0JELGdCQUFBQTthQUNBQyxVQUFBQTtRQUVqQixJQUFJLENBQUNILGFBQWEsR0FBRztZQUNwQixvQkFBb0JKO1lBQ3BCLHNCQUFzQkE7UUFDdkI7SUFDRDtJQUVPUSxjQUFjQyxJQUFZLEVBQUVDLE9BQWUsRUFBUTtRQUN6RCxJQUFJLENBQUNOLGFBQWEsQ0FBQ0ssS0FBSyxHQUFHQztRQUMzQixPQUFPLElBQUk7SUFDWjtJQUVPQyxpQkFBaUJGLElBQVksRUFBRUMsT0FBZSxFQUFRO1FBQzVELElBQUksQ0FBQ0wsZ0JBQWdCLENBQUNJLEtBQUssR0FBR0M7UUFDOUIsT0FBTyxJQUFJO0lBQ1o7SUFFT0UsUUFBc0I7UUFDNUIsTUFBTUMsTUFBK0I7WUFDcENKLE1BQU0sQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDSCxhQUFhLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQ0MsT0FBTyxFQUFFO1lBQzlDRyxTQUFTO1lBQ1RJLFNBQVM7WUFDVEMsTUFBTTtZQUNOQyxNQUFNO1lBQ05DLFNBQVM7Z0JBQ1JDLE1BQU07WUFDUDtZQUNBQyxjQUFjcEIsY0FBYyxJQUFJLENBQUNLLGFBQWE7UUFDL0M7UUFDQSxJQUFJZ0IsT0FBT0MsSUFBSSxDQUFDLElBQUksQ0FBQ2hCLGdCQUFnQixFQUFFaUIsTUFBTSxHQUFHLEdBQUc7WUFDbERULElBQUlVLGVBQWUsR0FBR3hCLGNBQWMsSUFBSSxDQUFDTSxnQkFBZ0I7UUFDMUQ7UUFDQSxPQUFPO1lBQ047Z0JBQ0NtQixVQUFVO2dCQUNWQyxTQUFTQyxLQUFLQyxTQUFTLENBQUNkLEtBQUssTUFBTTtZQUNwQztTQUNBO0lBQ0Y7QUFDRCJ9
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { WELL_KNOWN_FILES } from "../../models/const.js";
|
|
2
|
+
/**
|
|
3
|
+
* Data-carrier model for auth configuration.
|
|
4
|
+
*
|
|
5
|
+
* Registered by AuthFeature when auth0 is configured. Other features (e.g.
|
|
6
|
+
* PostmanFeature) retrieve it via workspace.getModel(WELL_KNOWN_FILES.AUTH_CONFIG).
|
|
7
|
+
* Produces no files — exists solely so features can communicate auth details.
|
|
8
|
+
*/ export class AuthConfigModel {
|
|
9
|
+
config;
|
|
10
|
+
key = WELL_KNOWN_FILES.AUTH_CONFIG;
|
|
11
|
+
constructor(config){
|
|
12
|
+
this.config = config;
|
|
13
|
+
}
|
|
14
|
+
setAdminUser(adminUser) {
|
|
15
|
+
this.config.adminUser = adminUser;
|
|
16
|
+
}
|
|
17
|
+
files() {
|
|
18
|
+
return [];
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL3J1bm5lci93b3JrL2RlY29oZXJlL2RlY29oZXJlL3Byb2plY3RzL3NjYWZmb2xkL3NyYy93ZWJhcGkvbW9kZWxzL2F1dGgtY29uZmlnLm1vZGVsLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IFdFTExfS05PV05fRklMRVMgfSBmcm9tIFwiLi4vLi4vbW9kZWxzL2NvbnN0LmpzXCI7XG5pbXBvcnQgdHlwZSB7IEtleWVkTW9kZWwsIFNvdXJjZUZpbGUgfSBmcm9tIFwiLi4vLi4vbW9kZWxzL3NvdXJjZS1maWxlLmpzXCI7XG5cbmV4cG9ydCB0eXBlIEFkbWluVXNlckNvbmZpZyA9IHtcblx0c3ViOiBzdHJpbmc7XG5cdGVtYWlsOiBzdHJpbmc7XG5cdHBhc3N3b3JkOiBzdHJpbmc7XG5cdHVzZXJuYW1lOiBzdHJpbmc7XG59O1xuXG5leHBvcnQgdHlwZSBBdXRoQ29uZmlnID0ge1xuXHRpc3N1ZXJCYXNlVXJsOiBzdHJpbmc7XG5cdGF1ZGllbmNlOiBzdHJpbmc7XG5cdGFkbWluVXNlcj86IEFkbWluVXNlckNvbmZpZztcbn07XG5cbi8qKlxuICogRGF0YS1jYXJyaWVyIG1vZGVsIGZvciBhdXRoIGNvbmZpZ3VyYXRpb24uXG4gKlxuICogUmVnaXN0ZXJlZCBieSBBdXRoRmVhdHVyZSB3aGVuIGF1dGgwIGlzIGNvbmZpZ3VyZWQuIE90aGVyIGZlYXR1cmVzIChlLmcuXG4gKiBQb3N0bWFuRmVhdHVyZSkgcmV0cmlldmUgaXQgdmlhIHdvcmtzcGFjZS5nZXRNb2RlbChXRUxMX0tOT1dOX0ZJTEVTLkFVVEhfQ09ORklHKS5cbiAqIFByb2R1Y2VzIG5vIGZpbGVzIOKAlCBleGlzdHMgc29sZWx5IHNvIGZlYXR1cmVzIGNhbiBjb21tdW5pY2F0ZSBhdXRoIGRldGFpbHMuXG4gKi9cbmV4cG9ydCBjbGFzcyBBdXRoQ29uZmlnTW9kZWwgaW1wbGVtZW50cyBLZXllZE1vZGVsIHtcblx0cHVibGljIHJlYWRvbmx5IGtleSA9IFdFTExfS05PV05fRklMRVMuQVVUSF9DT05GSUc7XG5cblx0cHVibGljIGNvbnN0cnVjdG9yKHB1YmxpYyByZWFkb25seSBjb25maWc6IEF1dGhDb25maWcpIHt9XG5cblx0cHVibGljIHNldEFkbWluVXNlcihhZG1pblVzZXI6IEFkbWluVXNlckNvbmZpZyk6IHZvaWQge1xuXHRcdHRoaXMuY29uZmlnLmFkbWluVXNlciA9IGFkbWluVXNlcjtcblx0fVxuXG5cdHB1YmxpYyBmaWxlcygpOiBTb3VyY2VGaWxlW10ge1xuXHRcdHJldHVybiBbXTtcblx0fVxufVxuIl0sIm5hbWVzIjpbIldFTExfS05PV05fRklMRVMiLCJBdXRoQ29uZmlnTW9kZWwiLCJrZXkiLCJBVVRIX0NPTkZJRyIsImNvbmZpZyIsInNldEFkbWluVXNlciIsImFkbWluVXNlciIsImZpbGVzIl0sIm1hcHBpbmdzIjoiQUFBQSxTQUFTQSxnQkFBZ0IsUUFBUSx3QkFBd0I7QUFnQnpEOzs7Ozs7Q0FNQyxHQUNELE9BQU8sTUFBTUM7O0lBQ0lDLE1BQU1GLGlCQUFpQkcsV0FBVyxDQUFDO0lBRW5ELFlBQW1CLEFBQWdCQyxNQUFrQixDQUFFO2FBQXBCQSxTQUFBQTtJQUFxQjtJQUVqREMsYUFBYUMsU0FBMEIsRUFBUTtRQUNyRCxJQUFJLENBQUNGLE1BQU0sQ0FBQ0UsU0FBUyxHQUFHQTtJQUN6QjtJQUVPQyxRQUFzQjtRQUM1QixPQUFPLEVBQUU7SUFDVjtBQUNEIn0=
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import { WELL_KNOWN_FILES } from "../../models/const.js";
|
|
2
|
+
/** Tracks named imports from a single module path, split into values and types. */ class ImportGroup {
|
|
3
|
+
_values = [];
|
|
4
|
+
_types = [];
|
|
5
|
+
add(name, typeOnly = false) {
|
|
6
|
+
if (typeOnly) {
|
|
7
|
+
// Value import already present — value wins, skip
|
|
8
|
+
if (!this._values.includes(name) && !this._types.includes(name)) {
|
|
9
|
+
this._types.push(name);
|
|
10
|
+
}
|
|
11
|
+
} else {
|
|
12
|
+
// Promote: remove from types if it was previously type-only
|
|
13
|
+
const typeIdx = this._types.indexOf(name);
|
|
14
|
+
if (typeIdx !== -1) this._types.splice(typeIdx, 1);
|
|
15
|
+
if (!this._values.includes(name)) this._values.push(name);
|
|
16
|
+
}
|
|
17
|
+
return this;
|
|
18
|
+
}
|
|
19
|
+
render(from) {
|
|
20
|
+
const values = [
|
|
21
|
+
...this._values
|
|
22
|
+
].sort();
|
|
23
|
+
const types = [
|
|
24
|
+
...this._types
|
|
25
|
+
].sort().map((n)=>`type ${n}`);
|
|
26
|
+
return `import { ${[
|
|
27
|
+
...values,
|
|
28
|
+
...types
|
|
29
|
+
].join(", ")} } from "${from}";`;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* A controller method. Features call `addDecorator()` to prepend decorators
|
|
34
|
+
* before the HTTP verb decorator (e.g. `@AllowAnonymous` before `@Get()`).
|
|
35
|
+
*/ export class ControllerMethod {
|
|
36
|
+
name;
|
|
37
|
+
_httpDecorator;
|
|
38
|
+
_params;
|
|
39
|
+
_extraDecorators = [];
|
|
40
|
+
_body;
|
|
41
|
+
_isAsync;
|
|
42
|
+
constructor(name, _httpDecorator, _params, isAsync, body){
|
|
43
|
+
this.name = name;
|
|
44
|
+
this._httpDecorator = _httpDecorator;
|
|
45
|
+
this._params = _params;
|
|
46
|
+
this._isAsync = isAsync;
|
|
47
|
+
this._body = body;
|
|
48
|
+
}
|
|
49
|
+
addDecorator(decorator) {
|
|
50
|
+
this._extraDecorators.push(decorator);
|
|
51
|
+
return this;
|
|
52
|
+
}
|
|
53
|
+
/** Replace the method body lines (used by features that extend generated behaviour). */ setBody(body) {
|
|
54
|
+
this._body = body;
|
|
55
|
+
return this;
|
|
56
|
+
}
|
|
57
|
+
setAsync(isAsync = true) {
|
|
58
|
+
this._isAsync = isAsync;
|
|
59
|
+
return this;
|
|
60
|
+
}
|
|
61
|
+
render() {
|
|
62
|
+
const lines = [];
|
|
63
|
+
for (const d of this._extraDecorators){
|
|
64
|
+
lines.push(`\t${d}`);
|
|
65
|
+
}
|
|
66
|
+
lines.push(`\t${this._httpDecorator}`);
|
|
67
|
+
const asyncKw = this._isAsync ? "async " : "";
|
|
68
|
+
lines.push(`\tpublic ${asyncKw}${this.name}(${this._params}) {`);
|
|
69
|
+
for (const line of this._body){
|
|
70
|
+
lines.push(`\t\t${line}`);
|
|
71
|
+
}
|
|
72
|
+
lines.push("\t}");
|
|
73
|
+
return lines;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Model for `projects/api/src/controllers/hello.controller.ts`.
|
|
78
|
+
*
|
|
79
|
+
* Pre-initialised with all routes and their HTTP decorators. Features mutate
|
|
80
|
+
* the model via `getMethod(name).addDecorator(...)`, `addDecorator(...)` (class
|
|
81
|
+
* level), `addCortexImport(...)`, `addImport(...)`, and `addConstructorParam(...)`.
|
|
82
|
+
*/ export class ControllerSourceFile {
|
|
83
|
+
key = WELL_KNOWN_FILES.CONTROLLER_TS;
|
|
84
|
+
_cortexImports = new ImportGroup().add("Controller").add("Delete").add("Field").add("Get").add("Param").add("Post").add("Put").add("Query");
|
|
85
|
+
_extraImportGroups = new Map([
|
|
86
|
+
[
|
|
87
|
+
"@decohere/crucible/decorators",
|
|
88
|
+
new ImportGroup().add("inject")
|
|
89
|
+
]
|
|
90
|
+
]);
|
|
91
|
+
_classDecorators = [];
|
|
92
|
+
/** Explicit @inject — design:paramtypes can collapse to Object under SWC when the class is still undefined at decorate time. */ _ctorParams = [
|
|
93
|
+
'@inject("SampleService") private readonly sample: SampleService'
|
|
94
|
+
];
|
|
95
|
+
_methods = new Map([
|
|
96
|
+
[
|
|
97
|
+
"getAll",
|
|
98
|
+
new ControllerMethod("getAll", "@Get()", '@Query("filter") filter: string', true, [
|
|
99
|
+
"const greeting = await this.sample.getGreeting();",
|
|
100
|
+
"return { filter, message: greeting };"
|
|
101
|
+
])
|
|
102
|
+
],
|
|
103
|
+
[
|
|
104
|
+
"getOne",
|
|
105
|
+
new ControllerMethod("getOne", '@Get("/:id")', '@Param("id") id: string', false, // biome-ignore lint/suspicious/noTemplateCurlyInString: template literal in generated code
|
|
106
|
+
[
|
|
107
|
+
"return { id, message: `Hello ${id}!` };"
|
|
108
|
+
])
|
|
109
|
+
],
|
|
110
|
+
[
|
|
111
|
+
"create",
|
|
112
|
+
new ControllerMethod("create", "@Post()", "body: HelloBody", false, [
|
|
113
|
+
"return { message: body.message };"
|
|
114
|
+
])
|
|
115
|
+
],
|
|
116
|
+
[
|
|
117
|
+
"update",
|
|
118
|
+
new ControllerMethod("update", '@Put("/:id")', '@Param("id") id: string, body: HelloBody', false, [
|
|
119
|
+
"return { id, message: body.message };"
|
|
120
|
+
])
|
|
121
|
+
],
|
|
122
|
+
[
|
|
123
|
+
"remove",
|
|
124
|
+
new ControllerMethod("remove", '@Delete("/:id")', '@Param("id") id: string', false, [
|
|
125
|
+
"return { id, deleted: true };"
|
|
126
|
+
])
|
|
127
|
+
]
|
|
128
|
+
]);
|
|
129
|
+
/** Retrieve a method by name to mutate its decorators. */ getMethod(name) {
|
|
130
|
+
const m = this._methods.get(name);
|
|
131
|
+
if (m == null) throw new Error(`No method '${name}' on ControllerSourceFile`);
|
|
132
|
+
return m;
|
|
133
|
+
}
|
|
134
|
+
/** Add a class-level decorator (e.g. `@Authorize`). */ addDecorator(decorator) {
|
|
135
|
+
this._classDecorators.push(decorator);
|
|
136
|
+
return this;
|
|
137
|
+
}
|
|
138
|
+
/** Add a named import from `@decohere/cortex`. */ addCortexImport(name, typeOnly = false) {
|
|
139
|
+
this._cortexImports.add(name, typeOnly);
|
|
140
|
+
return this;
|
|
141
|
+
}
|
|
142
|
+
/** Add a named import from any other module. */ addImport(name, from, typeOnly = false) {
|
|
143
|
+
const group = this._extraImportGroups.get(from) ?? new ImportGroup();
|
|
144
|
+
group.add(name, typeOnly);
|
|
145
|
+
this._extraImportGroups.set(from, group);
|
|
146
|
+
return this;
|
|
147
|
+
}
|
|
148
|
+
/** Add a constructor parameter (e.g. an injected dependency). */ addConstructorParam(param) {
|
|
149
|
+
this._ctorParams.push(param);
|
|
150
|
+
return this;
|
|
151
|
+
}
|
|
152
|
+
files() {
|
|
153
|
+
const lines = [
|
|
154
|
+
this._cortexImports.render("@decohere/cortex"),
|
|
155
|
+
'import { SampleService } from "../services/sample.service.js";'
|
|
156
|
+
];
|
|
157
|
+
for (const [from, group] of this._extraImportGroups){
|
|
158
|
+
lines.push(group.render(from));
|
|
159
|
+
}
|
|
160
|
+
lines.push("", "class HelloBody {", '\t@Field("body", "message")', "\tpublic message!: string;", "}", "");
|
|
161
|
+
for (const d of this._classDecorators){
|
|
162
|
+
lines.push(d);
|
|
163
|
+
}
|
|
164
|
+
lines.push('@Controller({ prefix: "/hello" })', "export class HelloController {", "");
|
|
165
|
+
lines.push("\tpublic constructor(");
|
|
166
|
+
for (const p of this._ctorParams){
|
|
167
|
+
lines.push(`\t\t${p},`);
|
|
168
|
+
}
|
|
169
|
+
lines.push("\t) {}");
|
|
170
|
+
lines.push("");
|
|
171
|
+
for (const method of this._methods.values()){
|
|
172
|
+
lines.push(...method.render(), "");
|
|
173
|
+
}
|
|
174
|
+
lines.push("}", "");
|
|
175
|
+
return [
|
|
176
|
+
{
|
|
177
|
+
filePath: "src/controllers/hello.controller.ts",
|
|
178
|
+
content: lines.join("\n")
|
|
179
|
+
}
|
|
180
|
+
];
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL3J1bm5lci93b3JrL2RlY29oZXJlL2RlY29oZXJlL3Byb2plY3RzL3NjYWZmb2xkL3NyYy93ZWJhcGkvbW9kZWxzL2NvbnRyb2xsZXItc291cmNlLWZpbGUubW9kZWwudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgV0VMTF9LTk9XTl9GSUxFUyB9IGZyb20gXCIuLi8uLi9tb2RlbHMvY29uc3QuanNcIjtcbmltcG9ydCB0eXBlIHsgS2V5ZWRNb2RlbCwgU291cmNlRmlsZSB9IGZyb20gXCIuLi8uLi9tb2RlbHMvc291cmNlLWZpbGUuanNcIjtcblxuLyoqIFRyYWNrcyBuYW1lZCBpbXBvcnRzIGZyb20gYSBzaW5nbGUgbW9kdWxlIHBhdGgsIHNwbGl0IGludG8gdmFsdWVzIGFuZCB0eXBlcy4gKi9cbmNsYXNzIEltcG9ydEdyb3VwIHtcblx0cHJpdmF0ZSByZWFkb25seSBfdmFsdWVzOiBzdHJpbmdbXSA9IFtdO1xuXHRwcml2YXRlIHJlYWRvbmx5IF90eXBlczogc3RyaW5nW10gPSBbXTtcblxuXHRwdWJsaWMgYWRkKG5hbWU6IHN0cmluZywgdHlwZU9ubHkgPSBmYWxzZSk6IHRoaXMge1xuXHRcdGlmICh0eXBlT25seSkge1xuXHRcdFx0Ly8gVmFsdWUgaW1wb3J0IGFscmVhZHkgcHJlc2VudCDigJQgdmFsdWUgd2lucywgc2tpcFxuXHRcdFx0aWYgKCF0aGlzLl92YWx1ZXMuaW5jbHVkZXMobmFtZSkgJiYgIXRoaXMuX3R5cGVzLmluY2x1ZGVzKG5hbWUpKSB7XG5cdFx0XHRcdHRoaXMuX3R5cGVzLnB1c2gobmFtZSk7XG5cdFx0XHR9XG5cdFx0fSBlbHNlIHtcblx0XHRcdC8vIFByb21vdGU6IHJlbW92ZSBmcm9tIHR5cGVzIGlmIGl0IHdhcyBwcmV2aW91c2x5IHR5cGUtb25seVxuXHRcdFx0Y29uc3QgdHlwZUlkeCA9IHRoaXMuX3R5cGVzLmluZGV4T2YobmFtZSk7XG5cdFx0XHRpZiAodHlwZUlkeCAhPT0gLTEpIHRoaXMuX3R5cGVzLnNwbGljZSh0eXBlSWR4LCAxKTtcblx0XHRcdGlmICghdGhpcy5fdmFsdWVzLmluY2x1ZGVzKG5hbWUpKSB0aGlzLl92YWx1ZXMucHVzaChuYW1lKTtcblx0XHR9XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxuXHRwdWJsaWMgcmVuZGVyKGZyb206IHN0cmluZyk6IHN0cmluZyB7XG5cdFx0Y29uc3QgdmFsdWVzID0gWy4uLnRoaXMuX3ZhbHVlc10uc29ydCgpO1xuXHRcdGNvbnN0IHR5cGVzID0gWy4uLnRoaXMuX3R5cGVzXS5zb3J0KCkubWFwKChuKSA9PiBgdHlwZSAke259YCk7XG5cdFx0cmV0dXJuIGBpbXBvcnQgeyAke1suLi52YWx1ZXMsIC4uLnR5cGVzXS5qb2luKFwiLCBcIil9IH0gZnJvbSBcIiR7ZnJvbX1cIjtgO1xuXHR9XG59XG5cbi8qKlxuICogQSBjb250cm9sbGVyIG1ldGhvZC4gRmVhdHVyZXMgY2FsbCBgYWRkRGVjb3JhdG9yKClgIHRvIHByZXBlbmQgZGVjb3JhdG9yc1xuICogYmVmb3JlIHRoZSBIVFRQIHZlcmIgZGVjb3JhdG9yIChlLmcuIGBAQWxsb3dBbm9ueW1vdXNgIGJlZm9yZSBgQEdldCgpYCkuXG4gKi9cbmV4cG9ydCBjbGFzcyBDb250cm9sbGVyTWV0aG9kIHtcblx0cHJpdmF0ZSByZWFkb25seSBfZXh0cmFEZWNvcmF0b3JzOiBzdHJpbmdbXSA9IFtdO1xuXHRwcml2YXRlIF9ib2R5OiBzdHJpbmdbXTtcblx0cHJpdmF0ZSBfaXNBc3luYzogYm9vbGVhbjtcblxuXHRwdWJsaWMgY29uc3RydWN0b3IoXG5cdFx0cHVibGljIHJlYWRvbmx5IG5hbWU6IHN0cmluZyxcblx0XHRwcml2YXRlIHJlYWRvbmx5IF9odHRwRGVjb3JhdG9yOiBzdHJpbmcsXG5cdFx0cHJpdmF0ZSByZWFkb25seSBfcGFyYW1zOiBzdHJpbmcsXG5cdFx0aXNBc3luYzogYm9vbGVhbixcblx0XHRib2R5OiBzdHJpbmdbXSxcblx0KSB7XG5cdFx0dGhpcy5faXNBc3luYyA9IGlzQXN5bmM7XG5cdFx0dGhpcy5fYm9keSA9IGJvZHk7XG5cdH1cblxuXHRwdWJsaWMgYWRkRGVjb3JhdG9yKGRlY29yYXRvcjogc3RyaW5nKTogdGhpcyB7XG5cdFx0dGhpcy5fZXh0cmFEZWNvcmF0b3JzLnB1c2goZGVjb3JhdG9yKTtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKiBSZXBsYWNlIHRoZSBtZXRob2QgYm9keSBsaW5lcyAodXNlZCBieSBmZWF0dXJlcyB0aGF0IGV4dGVuZCBnZW5lcmF0ZWQgYmVoYXZpb3VyKS4gKi9cblx0cHVibGljIHNldEJvZHkoYm9keTogc3RyaW5nW10pOiB0aGlzIHtcblx0XHR0aGlzLl9ib2R5ID0gYm9keTtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdHB1YmxpYyBzZXRBc3luYyhpc0FzeW5jID0gdHJ1ZSk6IHRoaXMge1xuXHRcdHRoaXMuX2lzQXN5bmMgPSBpc0FzeW5jO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0cHVibGljIHJlbmRlcigpOiBzdHJpbmdbXSB7XG5cdFx0Y29uc3QgbGluZXM6IHN0cmluZ1tdID0gW107XG5cdFx0Zm9yIChjb25zdCBkIG9mIHRoaXMuX2V4dHJhRGVjb3JhdG9ycykge1xuXHRcdFx0bGluZXMucHVzaChgXFx0JHtkfWApO1xuXHRcdH1cblx0XHRsaW5lcy5wdXNoKGBcXHQke3RoaXMuX2h0dHBEZWNvcmF0b3J9YCk7XG5cdFx0Y29uc3QgYXN5bmNLdyA9IHRoaXMuX2lzQXN5bmMgPyBcImFzeW5jIFwiIDogXCJcIjtcblx0XHRsaW5lcy5wdXNoKGBcXHRwdWJsaWMgJHthc3luY0t3fSR7dGhpcy5uYW1lfSgke3RoaXMuX3BhcmFtc30pIHtgKTtcblx0XHRmb3IgKGNvbnN0IGxpbmUgb2YgdGhpcy5fYm9keSkge1xuXHRcdFx0bGluZXMucHVzaChgXFx0XFx0JHtsaW5lfWApO1xuXHRcdH1cblx0XHRsaW5lcy5wdXNoKFwiXFx0fVwiKTtcblx0XHRyZXR1cm4gbGluZXM7XG5cdH1cbn1cblxuLyoqXG4gKiBNb2RlbCBmb3IgYHByb2plY3RzL2FwaS9zcmMvY29udHJvbGxlcnMvaGVsbG8uY29udHJvbGxlci50c2AuXG4gKlxuICogUHJlLWluaXRpYWxpc2VkIHdpdGggYWxsIHJvdXRlcyBhbmQgdGhlaXIgSFRUUCBkZWNvcmF0b3JzLiBGZWF0dXJlcyBtdXRhdGVcbiAqIHRoZSBtb2RlbCB2aWEgYGdldE1ldGhvZChuYW1lKS5hZGREZWNvcmF0b3IoLi4uKWAsIGBhZGREZWNvcmF0b3IoLi4uKWAgKGNsYXNzXG4gKiBsZXZlbCksIGBhZGRDb3J0ZXhJbXBvcnQoLi4uKWAsIGBhZGRJbXBvcnQoLi4uKWAsIGFuZCBgYWRkQ29uc3RydWN0b3JQYXJhbSguLi4pYC5cbiAqL1xuZXhwb3J0IGNsYXNzIENvbnRyb2xsZXJTb3VyY2VGaWxlIGltcGxlbWVudHMgS2V5ZWRNb2RlbCB7XG5cdHB1YmxpYyByZWFkb25seSBrZXkgPSBXRUxMX0tOT1dOX0ZJTEVTLkNPTlRST0xMRVJfVFM7XG5cblx0cHJpdmF0ZSByZWFkb25seSBfY29ydGV4SW1wb3J0cyA9IG5ldyBJbXBvcnRHcm91cCgpXG5cdFx0LmFkZChcIkNvbnRyb2xsZXJcIilcblx0XHQuYWRkKFwiRGVsZXRlXCIpXG5cdFx0LmFkZChcIkZpZWxkXCIpXG5cdFx0LmFkZChcIkdldFwiKVxuXHRcdC5hZGQoXCJQYXJhbVwiKVxuXHRcdC5hZGQoXCJQb3N0XCIpXG5cdFx0LmFkZChcIlB1dFwiKVxuXHRcdC5hZGQoXCJRdWVyeVwiKTtcblxuXHRwcml2YXRlIHJlYWRvbmx5IF9leHRyYUltcG9ydEdyb3VwcyA9IG5ldyBNYXA8c3RyaW5nLCBJbXBvcnRHcm91cD4oW1xuXHRcdFtcIkBkZWNvaGVyZS9jcnVjaWJsZS9kZWNvcmF0b3JzXCIsIG5ldyBJbXBvcnRHcm91cCgpLmFkZChcImluamVjdFwiKV0sXG5cdF0pO1xuXHRwcml2YXRlIHJlYWRvbmx5IF9jbGFzc0RlY29yYXRvcnM6IHN0cmluZ1tdID0gW107XG5cdC8qKiBFeHBsaWNpdCBAaW5qZWN0IOKAlCBkZXNpZ246cGFyYW10eXBlcyBjYW4gY29sbGFwc2UgdG8gT2JqZWN0IHVuZGVyIFNXQyB3aGVuIHRoZSBjbGFzcyBpcyBzdGlsbCB1bmRlZmluZWQgYXQgZGVjb3JhdGUgdGltZS4gKi9cblx0cHJpdmF0ZSByZWFkb25seSBfY3RvclBhcmFtczogc3RyaW5nW10gPSBbXG5cdFx0J0BpbmplY3QoXCJTYW1wbGVTZXJ2aWNlXCIpIHByaXZhdGUgcmVhZG9ubHkgc2FtcGxlOiBTYW1wbGVTZXJ2aWNlJyxcblx0XTtcblxuXHRwcml2YXRlIHJlYWRvbmx5IF9tZXRob2RzID0gbmV3IE1hcDxzdHJpbmcsIENvbnRyb2xsZXJNZXRob2Q+KFtcblx0XHRbXG5cdFx0XHRcImdldEFsbFwiLFxuXHRcdFx0bmV3IENvbnRyb2xsZXJNZXRob2QoXCJnZXRBbGxcIiwgXCJAR2V0KClcIiwgJ0BRdWVyeShcImZpbHRlclwiKSBmaWx0ZXI6IHN0cmluZycsIHRydWUsIFtcblx0XHRcdFx0XCJjb25zdCBncmVldGluZyA9IGF3YWl0IHRoaXMuc2FtcGxlLmdldEdyZWV0aW5nKCk7XCIsXG5cdFx0XHRcdFwicmV0dXJuIHsgZmlsdGVyLCBtZXNzYWdlOiBncmVldGluZyB9O1wiLFxuXHRcdFx0XSksXG5cdFx0XSxcblx0XHRbXG5cdFx0XHRcImdldE9uZVwiLFxuXHRcdFx0bmV3IENvbnRyb2xsZXJNZXRob2QoXG5cdFx0XHRcdFwiZ2V0T25lXCIsXG5cdFx0XHRcdCdAR2V0KFwiLzppZFwiKScsXG5cdFx0XHRcdCdAUGFyYW0oXCJpZFwiKSBpZDogc3RyaW5nJyxcblx0XHRcdFx0ZmFsc2UsXG5cdFx0XHRcdC8vIGJpb21lLWlnbm9yZSBsaW50L3N1c3BpY2lvdXMvbm9UZW1wbGF0ZUN1cmx5SW5TdHJpbmc6IHRlbXBsYXRlIGxpdGVyYWwgaW4gZ2VuZXJhdGVkIGNvZGVcblx0XHRcdFx0W1wicmV0dXJuIHsgaWQsIG1lc3NhZ2U6IGBIZWxsbyAke2lkfSFgIH07XCJdLFxuXHRcdFx0KSxcblx0XHRdLFxuXHRcdFtcblx0XHRcdFwiY3JlYXRlXCIsXG5cdFx0XHRuZXcgQ29udHJvbGxlck1ldGhvZChcImNyZWF0ZVwiLCBcIkBQb3N0KClcIiwgXCJib2R5OiBIZWxsb0JvZHlcIiwgZmFsc2UsIFtcblx0XHRcdFx0XCJyZXR1cm4geyBtZXNzYWdlOiBib2R5Lm1lc3NhZ2UgfTtcIixcblx0XHRcdF0pLFxuXHRcdF0sXG5cdFx0W1xuXHRcdFx0XCJ1cGRhdGVcIixcblx0XHRcdG5ldyBDb250cm9sbGVyTWV0aG9kKFxuXHRcdFx0XHRcInVwZGF0ZVwiLFxuXHRcdFx0XHQnQFB1dChcIi86aWRcIiknLFxuXHRcdFx0XHQnQFBhcmFtKFwiaWRcIikgaWQ6IHN0cmluZywgYm9keTogSGVsbG9Cb2R5Jyxcblx0XHRcdFx0ZmFsc2UsXG5cdFx0XHRcdFtcInJldHVybiB7IGlkLCBtZXNzYWdlOiBib2R5Lm1lc3NhZ2UgfTtcIl0sXG5cdFx0XHQpLFxuXHRcdF0sXG5cdFx0W1xuXHRcdFx0XCJyZW1vdmVcIixcblx0XHRcdG5ldyBDb250cm9sbGVyTWV0aG9kKFwicmVtb3ZlXCIsICdARGVsZXRlKFwiLzppZFwiKScsICdAUGFyYW0oXCJpZFwiKSBpZDogc3RyaW5nJywgZmFsc2UsIFtcblx0XHRcdFx0XCJyZXR1cm4geyBpZCwgZGVsZXRlZDogdHJ1ZSB9O1wiLFxuXHRcdFx0XSksXG5cdFx0XSxcblx0XSk7XG5cblx0LyoqIFJldHJpZXZlIGEgbWV0aG9kIGJ5IG5hbWUgdG8gbXV0YXRlIGl0cyBkZWNvcmF0b3JzLiAqL1xuXHRwdWJsaWMgZ2V0TWV0aG9kKG5hbWU6IHN0cmluZyk6IENvbnRyb2xsZXJNZXRob2Qge1xuXHRcdGNvbnN0IG0gPSB0aGlzLl9tZXRob2RzLmdldChuYW1lKTtcblx0XHRpZiAobSA9PSBudWxsKSB0aHJvdyBuZXcgRXJyb3IoYE5vIG1ldGhvZCAnJHtuYW1lfScgb24gQ29udHJvbGxlclNvdXJjZUZpbGVgKTtcblx0XHRyZXR1cm4gbTtcblx0fVxuXG5cdC8qKiBBZGQgYSBjbGFzcy1sZXZlbCBkZWNvcmF0b3IgKGUuZy4gYEBBdXRob3JpemVgKS4gKi9cblx0cHVibGljIGFkZERlY29yYXRvcihkZWNvcmF0b3I6IHN0cmluZyk6IHRoaXMge1xuXHRcdHRoaXMuX2NsYXNzRGVjb3JhdG9ycy5wdXNoKGRlY29yYXRvcik7XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxuXHQvKiogQWRkIGEgbmFtZWQgaW1wb3J0IGZyb20gYEBkZWNvaGVyZS9jb3J0ZXhgLiAqL1xuXHRwdWJsaWMgYWRkQ29ydGV4SW1wb3J0KG5hbWU6IHN0cmluZywgdHlwZU9ubHkgPSBmYWxzZSk6IHRoaXMge1xuXHRcdHRoaXMuX2NvcnRleEltcG9ydHMuYWRkKG5hbWUsIHR5cGVPbmx5KTtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKiBBZGQgYSBuYW1lZCBpbXBvcnQgZnJvbSBhbnkgb3RoZXIgbW9kdWxlLiAqL1xuXHRwdWJsaWMgYWRkSW1wb3J0KG5hbWU6IHN0cmluZywgZnJvbTogc3RyaW5nLCB0eXBlT25seSA9IGZhbHNlKTogdGhpcyB7XG5cdFx0Y29uc3QgZ3JvdXAgPSB0aGlzLl9leHRyYUltcG9ydEdyb3Vwcy5nZXQoZnJvbSkgPz8gbmV3IEltcG9ydEdyb3VwKCk7XG5cdFx0Z3JvdXAuYWRkKG5hbWUsIHR5cGVPbmx5KTtcblx0XHR0aGlzLl9leHRyYUltcG9ydEdyb3Vwcy5zZXQoZnJvbSwgZ3JvdXApO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqIEFkZCBhIGNvbnN0cnVjdG9yIHBhcmFtZXRlciAoZS5nLiBhbiBpbmplY3RlZCBkZXBlbmRlbmN5KS4gKi9cblx0cHVibGljIGFkZENvbnN0cnVjdG9yUGFyYW0ocGFyYW06IHN0cmluZyk6IHRoaXMge1xuXHRcdHRoaXMuX2N0b3JQYXJhbXMucHVzaChwYXJhbSk7XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxuXHRwdWJsaWMgZmlsZXMoKTogU291cmNlRmlsZVtdIHtcblx0XHRjb25zdCBsaW5lczogc3RyaW5nW10gPSBbXG5cdFx0XHR0aGlzLl9jb3J0ZXhJbXBvcnRzLnJlbmRlcihcIkBkZWNvaGVyZS9jb3J0ZXhcIiksXG5cdFx0XHQnaW1wb3J0IHsgU2FtcGxlU2VydmljZSB9IGZyb20gXCIuLi9zZXJ2aWNlcy9zYW1wbGUuc2VydmljZS5qc1wiOycsXG5cdFx0XTtcblxuXHRcdGZvciAoY29uc3QgW2Zyb20sIGdyb3VwXSBvZiB0aGlzLl9leHRyYUltcG9ydEdyb3Vwcykge1xuXHRcdFx0bGluZXMucHVzaChncm91cC5yZW5kZXIoZnJvbSkpO1xuXHRcdH1cblxuXHRcdGxpbmVzLnB1c2goXG5cdFx0XHRcIlwiLFxuXHRcdFx0XCJjbGFzcyBIZWxsb0JvZHkge1wiLFxuXHRcdFx0J1xcdEBGaWVsZChcImJvZHlcIiwgXCJtZXNzYWdlXCIpJyxcblx0XHRcdFwiXFx0cHVibGljIG1lc3NhZ2UhOiBzdHJpbmc7XCIsXG5cdFx0XHRcIn1cIixcblx0XHRcdFwiXCIsXG5cdFx0KTtcblxuXHRcdGZvciAoY29uc3QgZCBvZiB0aGlzLl9jbGFzc0RlY29yYXRvcnMpIHtcblx0XHRcdGxpbmVzLnB1c2goZCk7XG5cdFx0fVxuXHRcdGxpbmVzLnB1c2goJ0BDb250cm9sbGVyKHsgcHJlZml4OiBcIi9oZWxsb1wiIH0pJywgXCJleHBvcnQgY2xhc3MgSGVsbG9Db250cm9sbGVyIHtcIiwgXCJcIik7XG5cblx0XHRsaW5lcy5wdXNoKFwiXFx0cHVibGljIGNvbnN0cnVjdG9yKFwiKTtcblx0XHRmb3IgKGNvbnN0IHAgb2YgdGhpcy5fY3RvclBhcmFtcykge1xuXHRcdFx0bGluZXMucHVzaChgXFx0XFx0JHtwfSxgKTtcblx0XHR9XG5cdFx0bGluZXMucHVzaChcIlxcdCkge31cIik7XG5cdFx0bGluZXMucHVzaChcIlwiKTtcblxuXHRcdGZvciAoY29uc3QgbWV0aG9kIG9mIHRoaXMuX21ldGhvZHMudmFsdWVzKCkpIHtcblx0XHRcdGxpbmVzLnB1c2goLi4ubWV0aG9kLnJlbmRlcigpLCBcIlwiKTtcblx0XHR9XG5cblx0XHRsaW5lcy5wdXNoKFwifVwiLCBcIlwiKTtcblxuXHRcdHJldHVybiBbXG5cdFx0XHR7XG5cdFx0XHRcdGZpbGVQYXRoOiBcInNyYy9jb250cm9sbGVycy9oZWxsby5jb250cm9sbGVyLnRzXCIsXG5cdFx0XHRcdGNvbnRlbnQ6IGxpbmVzLmpvaW4oXCJcXG5cIiksXG5cdFx0XHR9LFxuXHRcdF07XG5cdH1cbn1cbiJdLCJuYW1lcyI6WyJXRUxMX0tOT1dOX0ZJTEVTIiwiSW1wb3J0R3JvdXAiLCJfdmFsdWVzIiwiX3R5cGVzIiwiYWRkIiwibmFtZSIsInR5cGVPbmx5IiwiaW5jbHVkZXMiLCJwdXNoIiwidHlwZUlkeCIsImluZGV4T2YiLCJzcGxpY2UiLCJyZW5kZXIiLCJmcm9tIiwidmFsdWVzIiwic29ydCIsInR5cGVzIiwibWFwIiwibiIsImpvaW4iLCJDb250cm9sbGVyTWV0aG9kIiwiX2V4dHJhRGVjb3JhdG9ycyIsIl9ib2R5IiwiX2lzQXN5bmMiLCJfaHR0cERlY29yYXRvciIsIl9wYXJhbXMiLCJpc0FzeW5jIiwiYm9keSIsImFkZERlY29yYXRvciIsImRlY29yYXRvciIsInNldEJvZHkiLCJzZXRBc3luYyIsImxpbmVzIiwiZCIsImFzeW5jS3ciLCJsaW5lIiwiQ29udHJvbGxlclNvdXJjZUZpbGUiLCJrZXkiLCJDT05UUk9MTEVSX1RTIiwiX2NvcnRleEltcG9ydHMiLCJfZXh0cmFJbXBvcnRHcm91cHMiLCJNYXAiLCJfY2xhc3NEZWNvcmF0b3JzIiwiX2N0b3JQYXJhbXMiLCJfbWV0aG9kcyIsImdldE1ldGhvZCIsIm0iLCJnZXQiLCJFcnJvciIsImFkZENvcnRleEltcG9ydCIsImFkZEltcG9ydCIsImdyb3VwIiwic2V0IiwiYWRkQ29uc3RydWN0b3JQYXJhbSIsInBhcmFtIiwiZmlsZXMiLCJwIiwibWV0aG9kIiwiZmlsZVBhdGgiLCJjb250ZW50Il0sIm1hcHBpbmdzIjoiQUFBQSxTQUFTQSxnQkFBZ0IsUUFBUSx3QkFBd0I7QUFHekQsaUZBQWlGLEdBQ2pGLE1BQU1DO0lBQ1lDLFVBQW9C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
|