@decohere/create 0.0.1-dev.48 → 0.0.1-dev.5
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/cli.js +9 -3
- package/commonjs/src/scaffold.js +48 -0
- package/commonjs/src/templates.js +64 -0
- package/es6/src/cli.js +9 -3
- package/es6/src/scaffold.js +38 -0
- package/es6/src/templates.js +40 -0
- package/package.json +3 -8
- package/types/src/scaffold.d.ts +4 -0
- package/types/src/templates.d.ts +4 -0
- package/commonjs/src/domain/prompt.js +0 -64
- package/commonjs/src/models/compose.model.js +0 -138
- package/commonjs/src/models/config-yaml.model.js +0 -88
- package/commonjs/src/models/const.js +0 -31
- package/commonjs/src/models/dev-container.model.js +0 -100
- package/commonjs/src/models/docker-image.model.js +0 -221
- package/commonjs/src/models/env-file.model.js +0 -47
- package/commonjs/src/models/gitignore.model.js +0 -31
- package/commonjs/src/models/launch-json.model.js +0 -74
- package/commonjs/src/models/package-json.model.js +0 -133
- package/commonjs/src/models/project.model.js +0 -134
- package/commonjs/src/models/source-file.js +0 -6
- package/commonjs/src/models/tsconfig.model.js +0 -34
- package/commonjs/src/models/vscode-settings.model.js +0 -31
- package/commonjs/src/program.js +0 -135
- package/commonjs/src/resolve-target-dir.js +0 -19
- package/commonjs/src/runner.js +0 -144
- package/commonjs/src/services/scaffold.service.js +0 -62
- package/commonjs/src/version.js +0 -50
- package/commonjs/src/webapi/api-name.js +0 -95
- package/commonjs/src/webapi/const.js +0 -50
- package/commonjs/src/webapi/create-api.js +0 -285
- package/commonjs/src/webapi/features/auth.feature.js +0 -463
- package/commonjs/src/webapi/features/auth0-cli.js +0 -406
- package/commonjs/src/webapi/features/biome-format.js +0 -49
- package/commonjs/src/webapi/features/database.feature.js +0 -273
- package/commonjs/src/webapi/features/finalize.feature.js +0 -91
- package/commonjs/src/webapi/features/postman.feature.js +0 -319
- package/commonjs/src/webapi/models/api-package-json.model.js +0 -63
- package/commonjs/src/webapi/models/auth-config.model.js +0 -26
- package/commonjs/src/webapi/models/controller-source-file.model.js +0 -188
- package/commonjs/src/webapi/models/github-ci.model.js +0 -193
- package/commonjs/src/webapi/models/main-source-file.model.js +0 -165
- package/commonjs/src/webapi/models/production-dockerfile.model.js +0 -138
- package/commonjs/src/webapi/models/sample-files.model.js +0 -60
- package/commonjs/src/webapi/models/webapi-image.model.js +0 -22
- package/commonjs/src/webapi/postman/hello-openapi.js +0 -175
- package/commonjs/src/webapi/postman/local-view.js +0 -184
- package/commonjs/src/webapi/postman/openapi-to-postman.js +0 -202
- package/es6/src/domain/prompt.js +0 -43
- package/es6/src/models/compose.model.js +0 -132
- package/es6/src/models/config-yaml.model.js +0 -76
- package/es6/src/models/const.js +0 -21
- package/es6/src/models/dev-container.model.js +0 -90
- package/es6/src/models/docker-image.model.js +0 -185
- package/es6/src/models/env-file.model.js +0 -43
- package/es6/src/models/gitignore.model.js +0 -21
- package/es6/src/models/launch-json.model.js +0 -64
- package/es6/src/models/package-json.model.js +0 -129
- package/es6/src/models/project.model.js +0 -119
- package/es6/src/models/source-file.js +0 -3
- package/es6/src/models/tsconfig.model.js +0 -24
- package/es6/src/models/vscode-settings.model.js +0 -21
- package/es6/src/program.js +0 -76
- package/es6/src/resolve-target-dir.js +0 -9
- package/es6/src/runner.js +0 -146
- package/es6/src/services/scaffold.service.js +0 -52
- package/es6/src/version.js +0 -32
- package/es6/src/webapi/api-name.js +0 -59
- package/es6/src/webapi/const.js +0 -20
- package/es6/src/webapi/create-api.js +0 -265
- package/es6/src/webapi/features/auth.feature.js +0 -412
- package/es6/src/webapi/features/auth0-cli.js +0 -348
- package/es6/src/webapi/features/biome-format.js +0 -42
- package/es6/src/webapi/features/database.feature.js +0 -263
- package/es6/src/webapi/features/finalize.feature.js +0 -81
- package/es6/src/webapi/features/postman.feature.js +0 -253
- package/es6/src/webapi/models/api-package-json.model.js +0 -58
- package/es6/src/webapi/models/auth-config.model.js +0 -22
- package/es6/src/webapi/models/controller-source-file.model.js +0 -179
- package/es6/src/webapi/models/github-ci.model.js +0 -186
- package/es6/src/webapi/models/main-source-file.model.js +0 -161
- package/es6/src/webapi/models/production-dockerfile.model.js +0 -126
- package/es6/src/webapi/models/sample-files.model.js +0 -42
- package/es6/src/webapi/models/webapi-image.model.js +0 -12
- package/es6/src/webapi/postman/hello-openapi.js +0 -168
- package/es6/src/webapi/postman/local-view.js +0 -169
- package/es6/src/webapi/postman/openapi-to-postman.js +0 -179
- package/pack-builder-tgz.mjs +0 -177
- package/types/src/domain/prompt.d.ts +0 -4
- package/types/src/models/compose.model.d.ts +0 -59
- package/types/src/models/config-yaml.model.d.ts +0 -27
- package/types/src/models/const.d.ts +0 -19
- package/types/src/models/dev-container.model.d.ts +0 -33
- package/types/src/models/docker-image.model.d.ts +0 -56
- package/types/src/models/env-file.model.d.ts +0 -15
- package/types/src/models/gitignore.model.d.ts +0 -6
- package/types/src/models/launch-json.model.d.ts +0 -7
- package/types/src/models/package-json.model.d.ts +0 -32
- package/types/src/models/project.model.d.ts +0 -60
- package/types/src/models/source-file.d.ts +0 -11
- package/types/src/models/tsconfig.model.d.ts +0 -5
- package/types/src/models/vscode-settings.model.d.ts +0 -7
- package/types/src/program.d.ts +0 -3
- package/types/src/resolve-target-dir.d.ts +0 -5
- package/types/src/runner.d.ts +0 -15
- package/types/src/services/scaffold.service.d.ts +0 -22
- package/types/src/version.d.ts +0 -4
- package/types/src/webapi/api-name.d.ts +0 -14
- package/types/src/webapi/const.d.ts +0 -17
- package/types/src/webapi/create-api.d.ts +0 -15
- package/types/src/webapi/features/auth.feature.d.ts +0 -10
- package/types/src/webapi/features/auth0-cli.d.ts +0 -72
- package/types/src/webapi/features/biome-format.d.ts +0 -5
- package/types/src/webapi/features/database.feature.d.ts +0 -5
- package/types/src/webapi/features/finalize.feature.d.ts +0 -2
- package/types/src/webapi/features/postman.feature.d.ts +0 -16
- package/types/src/webapi/models/api-package-json.model.d.ts +0 -18
- package/types/src/webapi/models/auth-config.model.d.ts +0 -26
- package/types/src/webapi/models/controller-source-file.model.d.ts +0 -45
- package/types/src/webapi/models/github-ci.model.d.ts +0 -9
- package/types/src/webapi/models/main-source-file.model.d.ts +0 -54
- package/types/src/webapi/models/production-dockerfile.model.d.ts +0 -20
- package/types/src/webapi/models/sample-files.model.d.ts +0 -7
- package/types/src/webapi/models/webapi-image.model.d.ts +0 -5
- package/types/src/webapi/postman/hello-openapi.d.ts +0 -19
- package/types/src/webapi/postman/local-view.d.ts +0 -17
- package/types/src/webapi/postman/openapi-to-postman.d.ts +0 -62
|
@@ -1,253 +0,0 @@
|
|
|
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
|
-
throw new Error(`Failed to ensure Auth0 SPA app for Postman — auth0ClientId would be empty: ${err instanceof Error ? err.message : err}`);
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
async function scaffold(workspace, options) {
|
|
148
|
-
if (options.postmanProvider === "none" || options.postmanProvider == null) return;
|
|
149
|
-
const authConfigModel = workspace.getModel(WELL_KNOWN_FILES.AUTH_CONFIG);
|
|
150
|
-
const authCfg = authConfigModel?.config;
|
|
151
|
-
const spaClientId = authCfg?.issuerBaseUrl ? resolveSpaClientId(workspace) : undefined;
|
|
152
|
-
const auth0Env = authCfg?.issuerBaseUrl ? {
|
|
153
|
-
auth0Domain: authCfg.issuerBaseUrl.replace(/^https?:\/\//, ""),
|
|
154
|
-
auth0Audience: authCfg.audience,
|
|
155
|
-
auth0ClientId: spaClientId
|
|
156
|
-
} : undefined;
|
|
157
|
-
const projectName = workspace.name;
|
|
158
|
-
const envName = `${projectName} Local`;
|
|
159
|
-
const collection = await buildHybridPostmanCollection(projectName, auth0Env);
|
|
160
|
-
const localFiles = buildLocalViewFilesFromCollection(collection, projectName, auth0Env, {
|
|
161
|
-
callbacks: POSTMAN_CALLBACKS,
|
|
162
|
-
scopes: POSTMAN_SCOPES
|
|
163
|
-
});
|
|
164
|
-
const envYaml = buildEnvironmentYaml(envName, auth0Env, {
|
|
165
|
-
callbacks: POSTMAN_CALLBACKS,
|
|
166
|
-
scopes: POSTMAN_SCOPES
|
|
167
|
-
});
|
|
168
|
-
workspace.addFile({
|
|
169
|
-
files: ()=>[
|
|
170
|
-
{
|
|
171
|
-
filePath: ".postman/resources.yaml",
|
|
172
|
-
content: [
|
|
173
|
-
"# Open this project root in Postman (Files → Open folder), not the postman/ subfolder.",
|
|
174
|
-
"# Postman fills workspace.id when you connect Local View.",
|
|
175
|
-
"#",
|
|
176
|
-
"# All resources under postman/ are registered automatically.",
|
|
177
|
-
"# Route requests are generated from OpenAPI; Auth0 overlay is hand-authored.",
|
|
178
|
-
""
|
|
179
|
-
].join("\n")
|
|
180
|
-
},
|
|
181
|
-
{
|
|
182
|
-
filePath: `postman/environments/${projectName}-Local.environment.yaml`,
|
|
183
|
-
content: envYaml
|
|
184
|
-
},
|
|
185
|
-
...localFiles
|
|
186
|
-
]
|
|
187
|
-
});
|
|
188
|
-
if (options.postmanProvider === "api" && options.apiKey) {
|
|
189
|
-
const headers = {
|
|
190
|
-
"X-Api-Key": options.apiKey,
|
|
191
|
-
"Content-Type": "application/json"
|
|
192
|
-
};
|
|
193
|
-
const colRes = await fetch(`https://api.getpostman.com/collections?workspace=${options.workspaceId}`, {
|
|
194
|
-
method: "POST",
|
|
195
|
-
headers,
|
|
196
|
-
body: JSON.stringify({
|
|
197
|
-
collection
|
|
198
|
-
})
|
|
199
|
-
});
|
|
200
|
-
if (colRes.ok) {
|
|
201
|
-
console.log(" ✓ Postman collection uploaded");
|
|
202
|
-
} else {
|
|
203
|
-
console.error(" ✗ Failed to upload Postman collection");
|
|
204
|
-
}
|
|
205
|
-
const envValues = [
|
|
206
|
-
{
|
|
207
|
-
key: "baseUrl",
|
|
208
|
-
value: "http://localhost:3000",
|
|
209
|
-
enabled: true
|
|
210
|
-
},
|
|
211
|
-
...auth0Env?.auth0Domain ? [
|
|
212
|
-
{
|
|
213
|
-
key: "auth0Domain",
|
|
214
|
-
value: auth0Env.auth0Domain,
|
|
215
|
-
enabled: true
|
|
216
|
-
},
|
|
217
|
-
{
|
|
218
|
-
key: "auth0Audience",
|
|
219
|
-
value: auth0Env.auth0Audience ?? "",
|
|
220
|
-
enabled: true
|
|
221
|
-
},
|
|
222
|
-
{
|
|
223
|
-
key: "auth0ClientId",
|
|
224
|
-
value: auth0Env.auth0ClientId ?? "",
|
|
225
|
-
enabled: true
|
|
226
|
-
}
|
|
227
|
-
] : []
|
|
228
|
-
];
|
|
229
|
-
const envRes = await fetch(`https://api.getpostman.com/environments?workspace=${options.workspaceId}`, {
|
|
230
|
-
method: "POST",
|
|
231
|
-
headers,
|
|
232
|
-
body: JSON.stringify({
|
|
233
|
-
environment: {
|
|
234
|
-
name: envName,
|
|
235
|
-
values: envValues
|
|
236
|
-
}
|
|
237
|
-
})
|
|
238
|
-
});
|
|
239
|
-
if (envRes.ok) {
|
|
240
|
-
console.log(" ✓ Postman environment uploaded");
|
|
241
|
-
} else {
|
|
242
|
-
console.error(" ✗ Failed to upload Postman environment");
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
export const PostmanFeature = {
|
|
247
|
-
getOptions,
|
|
248
|
-
scaffold
|
|
249
|
-
};
|
|
250
|
-
export { buildHelloOpenApiDocument } from "../postman/hello-openapi.js";
|
|
251
|
-
export { POSTMAN_CALLBACKS, POSTMAN_SCOPES };
|
|
252
|
-
|
|
253
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL3J1bm5lci93b3JrL2RlY29oZXJlL2RlY29oZXJlL3Byb2plY3RzL2NyZWF0ZS9zcmMvd2ViYXBpL2ZlYXR1cmVzL3Bvc3RtYW4uZmVhdHVyZS50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyByYW5kb21VVUlEIH0gZnJvbSBcIm5vZGU6Y3J5cHRvXCI7XG5pbXBvcnQgeyBleGlzdHNTeW5jLCByZWFkRmlsZVN5bmMgfSBmcm9tIFwibm9kZTpmc1wiO1xuaW1wb3J0IHsgam9pbiB9IGZyb20gXCJub2RlOnBhdGhcIjtcbmltcG9ydCB7IHBpY2sgfSBmcm9tIFwiLi4vLi4vZG9tYWluL3Byb21wdC5qc1wiO1xuaW1wb3J0IHsgV0VMTF9LTk9XTl9GSUxFUyB9IGZyb20gXCIuLi8uLi9tb2RlbHMvY29uc3QuanNcIjtcbmltcG9ydCB0eXBlIHsgV29ya3NwYWNlU2NhZmZvbGQgfSBmcm9tIFwiLi4vLi4vbW9kZWxzL3Byb2plY3QubW9kZWwuanNcIjtcbmltcG9ydCB0eXBlIHsgRmVhdHVyZSB9IGZyb20gXCIuLi8uLi9zZXJ2aWNlcy9zY2FmZm9sZC5zZXJ2aWNlLmpzXCI7XG5pbXBvcnQgdHlwZSB7IEF1dGhDb25maWdNb2RlbCB9IGZyb20gXCIuLi9tb2RlbHMvYXV0aC1jb25maWcubW9kZWwuanNcIjtcbmltcG9ydCB7IGJ1aWxkSGVsbG9PcGVuQXBpRG9jdW1lbnQgfSBmcm9tIFwiLi4vcG9zdG1hbi9oZWxsby1vcGVuYXBpLmpzXCI7XG5pbXBvcnQge1xuXHRidWlsZEVudmlyb25tZW50WWFtbCxcblx0YnVpbGRMb2NhbFZpZXdGaWxlc0Zyb21Db2xsZWN0aW9uLFxufSBmcm9tIFwiLi4vcG9zdG1hbi9sb2NhbC12aWV3LmpzXCI7XG5pbXBvcnQge1xuXHR0eXBlIEF1dGgwRW52LFxuXHRhcHBseVBvc3RtYW5BdXRoT3ZlcmxheSxcblx0b3BlbkFwaVRvUG9zdG1hbkNvbGxlY3Rpb24sXG59IGZyb20gXCIuLi9wb3N0bWFuL29wZW5hcGktdG8tcG9zdG1hbi5qc1wiO1xuaW1wb3J0ICogYXMgYXV0aDBDbGkgZnJvbSBcIi4vYXV0aDAtY2xpLmpzXCI7XG5cbi8qKiBQb3N0bWFuIE9BdXRoIGNhbGxiYWNrIFVSTHMgKHBvcHVwICsgXCJBdXRob3JpemUgdXNpbmcgYnJvd3NlclwiKS4gKi9cbmNvbnN0IFBPU1RNQU5fQ0FMTEJBQ0tTID0gW1xuXHRcImh0dHBzOi8vb2F1dGgucHN0bW4uaW8vdjEvY2FsbGJhY2tcIixcblx0XCJodHRwczovL29hdXRoLnBzdG1uLmlvL3YxL2Jyb3dzZXItY2FsbGJhY2tcIixcbl0gYXMgY29uc3Q7XG5cbi8qKiBTY29wZXMgcmVxdWVzdGVkIGZvciBBdXRoMCBhY2Nlc3MgdG9rZW5zIChPSURDICsgSGVsbG8gQ0FTTCBwZXJtaXNzaW9ucykuICovXG5jb25zdCBQT1NUTUFOX1NDT1BFUyA9IFtcblx0XCJvcGVuaWRcIixcblx0XCJwcm9maWxlXCIsXG5cdFwiZW1haWxcIixcblx0XCJyZWFkOkhlbGxvXCIsXG5cdFwiY3JlYXRlOkhlbGxvXCIsXG5cdFwidXBkYXRlOkhlbGxvXCIsXG5cdFwiZGVsZXRlOkhlbGxvXCIsXG5dLmpvaW4oXCIgXCIpO1xuXG5jb25zdCBDT0xMRUNUSU9OX0RFU0NSSVBUSU9OID1cblx0XCJPcGVuIHRoZSBwcm9qZWN0IHJvb3QgaW4gUG9zdG1hbiBMb2NhbCBWaWV3IChub3QgdGhlIHBvc3RtYW4vIGZvbGRlcikuIFwiICtcblx0XCJTZWxlY3QgdGhlIExvY2FsIGVudmlyb25tZW50LCB0aGVuIEF1dGhvcml6YXRpb24g4oaSIEdldCBOZXcgQWNjZXNzIFRva2VuIChQS0NFKS4gXCIgK1xuXHRcIlJvdXRlcyBhcmUgZ2VuZXJhdGVkIGZyb20gT3BlbkFQSTsgQXV0aDAgb3ZlcmxheSBpcyBoYW5kLWF1dGhvcmVkLlwiO1xuXG5leHBvcnQgdHlwZSBQb3N0bWFuT3B0aW9ucyA9IHtcblx0cG9zdG1hblByb3ZpZGVyPzogXCJhcGlcIiB8IFwibG9jYWxcIiB8IFwibm9uZVwiO1xuXHRhcGlLZXk/OiBzdHJpbmc7XG5cdHdvcmtzcGFjZUlkPzogc3RyaW5nO1xufTtcblxuYXN5bmMgZnVuY3Rpb24gZ2V0T3B0aW9ucyhcblx0X3dvcmtzcGFjZTogV29ya3NwYWNlU2NhZmZvbGQsXG5cdGNsaU9wdGlvbnM6IFBhcnRpYWw8UG9zdG1hbk9wdGlvbnM+LFxuKTogUHJvbWlzZTxQYXJ0aWFsPFBvc3RtYW5PcHRpb25zPj4ge1xuXHRpZiAoY2xpT3B0aW9ucy5wb3N0bWFuUHJvdmlkZXIgIT0gbnVsbCkgcmV0dXJuIHt9O1xuXG5cdGNvbnN0IGNob2ljZXMgPSBbXG5cdFx0eyBsYWJlbDogXCJub25lXCIgYXMgY29uc3QsIGRlc2NyaXB0aW9uOiBcInNraXBcIiB9LFxuXHRcdHtcblx0XHRcdGxhYmVsOiBcImxvY2FsXCIgYXMgY29uc3QsXG5cdFx0XHRkZXNjcmlwdGlvbjogXCJMb2NhbCBWaWV3IC8gTmF0aXZlIEdpdCBmaWxlcyAobm8gQVBJIGtleSlcIixcblx0XHR9LFxuXHRcdHtcblx0XHRcdGxhYmVsOiBcImFwaVwiIGFzIGNvbnN0LFxuXHRcdFx0ZGVzY3JpcHRpb246IFwiYWxzbyB1cGxvYWQgdG8gUG9zdG1hbi5jb20gKG5lZWRzIEFQSSBrZXkpXCIsXG5cdFx0fSxcblx0XTtcblx0Y29uc3Qgc2VsZWN0ZWQgPSBhd2FpdCBwaWNrKFxuXHRcdFwiXFxuICBQb3N0bWFuOiBcIixcblx0XHRjaG9pY2VzLFxuXHRcdChjKSA9PiBgJHtjLmxhYmVsfSDigJQgJHtjLmRlc2NyaXB0aW9ufWAsXG5cdCk7XG5cdGNvbnN0IHByb3ZpZGVyID0gc2VsZWN0ZWQ/LmxhYmVsID8/IFwibm9uZVwiO1xuXG5cdGlmIChwcm92aWRlciA9PT0gXCJub25lXCIpIHJldHVybiB7IHBvc3RtYW5Qcm92aWRlcjogXCJub25lXCIgfTtcblx0aWYgKHByb3ZpZGVyID09PSBcImxvY2FsXCIpIHJldHVybiB7IHBvc3RtYW5Qcm92aWRlcjogXCJsb2NhbFwiIH07XG5cblx0Y29uc3QgYXBpS2V5ID1cblx0XHRwcm9jZXNzLmVudi5QT1NUTUFOX0FQSV9LRVkgPz9cblx0XHQoYXdhaXQgaW1wb3J0KFwiLi4vLi4vZG9tYWluL3Byb21wdC5qc1wiKS50aGVuKChtKSA9PlxuXHRcdFx0bS5hc2soXCJcXG4gIFBvc3RtYW4gQVBJIGtleSAoYXBwLmdldHBvc3RtYW4uY29tL3NldHRpbmdzL21lL2FwaS1rZXlzKTogXCIpLFxuXHRcdCkpO1xuXG5cdGNvbnN0IGhlYWRlcnMgPSB7IFwiWC1BcGktS2V5XCI6IGFwaUtleSwgXCJDb250ZW50LVR5cGVcIjogXCJhcHBsaWNhdGlvbi9qc29uXCIgfTtcblx0Y29uc3Qgd3NSZXMgPSBhd2FpdCBmZXRjaChcImh0dHBzOi8vYXBpLmdldHBvc3RtYW4uY29tL3dvcmtzcGFjZXNcIiwgeyBoZWFkZXJzIH0pO1xuXG5cdGlmICghd3NSZXMub2spIHtcblx0XHRjb25zb2xlLmVycm9yKFwiXFxuICBQb3N0bWFuIEFQSSBrZXkgaW52YWxpZCDigJQgZmFsbGluZyBiYWNrIHRvIGxvY2FsIGZpbGVzLlwiKTtcblx0XHRyZXR1cm4geyBwb3N0bWFuUHJvdmlkZXI6IFwibG9jYWxcIiB9O1xuXHR9XG5cblx0Y29uc3QgeyB3b3Jrc3BhY2VzIH0gPSAoYXdhaXQgd3NSZXMuanNvbigpKSBhcyB7XG5cdFx0d29ya3NwYWNlczogQXJyYXk8eyBpZDogc3RyaW5nOyBuYW1lOiBzdHJpbmc7IHR5cGU6IHN0cmluZyB9Pjtcblx0fTtcblxuXHR0eXBlIFdzQ2hvaWNlID0geyBsYWJlbDogc3RyaW5nOyBpZDogc3RyaW5nIHwgbnVsbCB9O1xuXHRjb25zdCB3c0Nob2ljZXM6IFdzQ2hvaWNlW10gPSBbXG5cdFx0eyBsYWJlbDogXCI8bmV3IHdvcmtzcGFjZT5cIiwgaWQ6IG51bGwgfSxcblx0XHQuLi53b3Jrc3BhY2VzLm1hcCgodykgPT4gKHsgbGFiZWw6IGAke3cubmFtZX0gKCR7dy50eXBlfSlgLCBpZDogdy5pZCB9KSksXG5cdF07XG5cblx0Y29uc3Qgd3NQaWNrZWQgPSBhd2FpdCBwaWNrKFwiXFxuICBQb3N0bWFuIHdvcmtzcGFjZTogXCIsIHdzQ2hvaWNlcywgKGMpID0+IGMubGFiZWwpO1xuXG5cdGxldCB3b3Jrc3BhY2VJZDogc3RyaW5nO1xuXHRpZiAoIXdzUGlja2VkIHx8IHdzUGlja2VkLmlkID09PSBudWxsKSB7XG5cdFx0Y29uc3QgeyBhc2sgfSA9IGF3YWl0IGltcG9ydChcIi4uLy4uL2RvbWFpbi9wcm9tcHQuanNcIik7XG5cdFx0Y29uc3Qgd3NOYW1lID0gYXdhaXQgYXNrKGAgIFdvcmtzcGFjZSBuYW1lOiBgKTtcblx0XHRjb25zdCBjcmVhdGVSZXMgPSBhd2FpdCBmZXRjaChcImh0dHBzOi8vYXBpLmdldHBvc3RtYW4uY29tL3dvcmtzcGFjZXNcIiwge1xuXHRcdFx0bWV0aG9kOiBcIlBPU1RcIixcblx0XHRcdGhlYWRlcnMsXG5cdFx0XHRib2R5OiBKU09OLnN0cmluZ2lmeSh7IHdvcmtzcGFjZTogeyBuYW1lOiB3c05hbWUsIHR5cGU6IFwicGVyc29uYWxcIiB9IH0pLFxuXHRcdH0pO1xuXHRcdGNvbnN0IHsgd29ya3NwYWNlOiB3cyB9ID0gKGF3YWl0IGNyZWF0ZVJlcy5qc29uKCkpIGFzIHsgd29ya3NwYWNlOiB7IGlkOiBzdHJpbmcgfSB9O1xuXHRcdHdvcmtzcGFjZUlkID0gd3MuaWQ7XG5cdFx0Y29uc29sZS5sb2coYCAg4pyTIFdvcmtzcGFjZSBjcmVhdGVkOiAke3dzTmFtZX1gKTtcblx0fSBlbHNlIHtcblx0XHR3b3Jrc3BhY2VJZCA9IHdzUGlja2VkLmlkO1xuXHR9XG5cblx0cmV0dXJuIHsgcG9zdG1hblByb3ZpZGVyOiBcImFwaVwiLCBhcGlLZXksIHdvcmtzcGFjZUlkIH07XG59XG5cbi8qKiBCdWlsZCBQb3N0bWFuIGNvbGxlY3Rpb246IE9wZW5BUEkgcm91dGVzICsgQXV0aDAgYXV0aCBvdmVybGF5LiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGJ1aWxkSHlicmlkUG9zdG1hbkNvbGxlY3Rpb24ocHJvamVjdE5hbWU6IHN0cmluZywgYXV0aD86IEF1dGgwRW52KSB7XG5cdGNvbnN0IG9wZW5hcGkgPSBidWlsZEhlbGxvT3BlbkFwaURvY3VtZW50KHByb2plY3ROYW1lKTtcblx0Y29uc3QgYmFzZSA9IGF3YWl0IG9wZW5BcGlUb1Bvc3RtYW5Db2xsZWN0aW9uKG9wZW5hcGkpO1xuXHRpZiAoYmFzZS5pbmZvLl9wb3N0bWFuX2lkID09IG51bGwpIHtcblx0XHRiYXNlLmluZm8uX3Bvc3RtYW5faWQgPSByYW5kb21VVUlEKCk7XG5cdH1cblx0cmV0dXJuIGFwcGx5UG9zdG1hbkF1dGhPdmVybGF5KGJhc2UsIHByb2plY3ROYW1lLCBhdXRoLCB7XG5cdFx0Y2FsbGJhY2tzOiBQT1NUTUFOX0NBTExCQUNLUyxcblx0XHRzY29wZXM6IFBPU1RNQU5fU0NPUEVTLFxuXHRcdGRlc2NyaXB0aW9uOiBDT0xMRUNUSU9OX0RFU0NSSVBUSU9OLFxuXHR9KTtcbn1cblxuLyoqIFJlYWQgYSBwcmV2aW91c2x5IHNjYWZmb2xkZWQgYXV0aDBDbGllbnRJZCBzbyByZS1zY2FmZm9sZCBuZXZlciBibGFua3MgaXQuICovXG5mdW5jdGlvbiByZWFkRXhpc3RpbmdTcGFDbGllbnRJZCh0YXJnZXREaXI6IHN0cmluZywgcHJvamVjdE5hbWU6IHN0cmluZyk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG5cdGNvbnN0IGVudlBhdGggPSBqb2luKFxuXHRcdHRhcmdldERpcixcblx0XHRcInBvc3RtYW4vZW52aXJvbm1lbnRzXCIsXG5cdFx0YCR7cHJvamVjdE5hbWV9LUxvY2FsLmVudmlyb25tZW50LnlhbWxgLFxuXHQpO1xuXHRpZiAoIWV4aXN0c1N5bmMoZW52UGF0aCkpIHJldHVybiB1bmRlZmluZWQ7XG5cdGNvbnN0IHRleHQgPSByZWFkRmlsZVN5bmMoZW52UGF0aCwgXCJ1dGY4XCIpO1xuXHRjb25zdCBtYXRjaCA9IHRleHQubWF0Y2goL2tleTpcXHMqYXV0aDBDbGllbnRJZFxccypcXG5cXHMqdmFsdWU6XFxzKltcIiddPyhbXlwiJ1xcbl0rKS8pO1xuXHRjb25zdCB2YWx1ZSA9IG1hdGNoPy5bMV0/LnRyaW0oKTtcblx0cmV0dXJuIHZhbHVlICYmIHZhbHVlLmxlbmd0aCA+IDAgPyB2YWx1ZSA6IHVuZGVmaW5lZDtcbn1cblxuLyoqXG4gKiBSZXNvbHZlIHRoZSBQb3N0bWFuIFNQQSBjbGllbnQgaWQuIE5ldmVyIHJldHVybnMgZW1wdHkg4oCUIHByZXNlcnZlcyBhbiBleGlzdGluZ1xuICogZW52IHZhbHVlIG9uIEF1dGgwIGZhaWx1cmUsIG90aGVyd2lzZSB0aHJvd3Mgc28gd2UgZG8gbm90IHdyaXRlIGEgYmxhbmsgZW52LlxuICovXG5mdW5jdGlvbiByZXNvbHZlU3BhQ2xpZW50SWQod29ya3NwYWNlOiBXb3Jrc3BhY2VTY2FmZm9sZCk6IHN0cmluZyB7XG5cdGNvbnN0IGFwcE5hbWUgPSBgJHt3b3Jrc3BhY2UubmFtZX0gUG9zdG1hbmA7XG5cdHRyeSB7XG5cdFx0Y29uc3QgYXBwID0gYXV0aDBDbGkuZW5zdXJlU3BhQXBwKGFwcE5hbWUsIFsuLi5QT1NUTUFOX0NBTExCQUNLU10pO1xuXHRcdGNvbnNvbGUubG9nKFxuXHRcdFx0YXBwLnJldXNlZFxuXHRcdFx0XHQ/IGAgIOKckyBSZXVzaW5nIEF1dGgwIFNQQSBhcHAgZm9yIFBvc3RtYW4gUEtDRSAoJHthcHAuY2xpZW50X2lkfSlgXG5cdFx0XHRcdDogYCAg4pyTIEF1dGgwIFNQQSBhcHAgY3JlYXRlZCBmb3IgUG9zdG1hbiBQS0NFICgke2FwcC5jbGllbnRfaWR9KWAsXG5cdFx0KTtcblx0XHR0cnkge1xuXHRcdFx0YXV0aDBDbGkuZW5hYmxlQ29ubmVjdGlvbkZvckNsaWVudChhdXRoMENsaS5EQl9DT05ORUNUSU9OX05BTUUsIGFwcC5jbGllbnRfaWQpO1xuXHRcdFx0Y29uc29sZS5sb2coYCAg4pyTIEVuYWJsZWQgJHthdXRoMENsaS5EQl9DT05ORUNUSU9OX05BTUV9IG9uIFBvc3RtYW4gU1BBYCk7XG5cdFx0fSBjYXRjaCAoZXJyKSB7XG5cdFx0XHRjb25zb2xlLmVycm9yKFxuXHRcdFx0XHRgICDinJcgRmFpbGVkIHRvIGVuYWJsZSBEQiBjb25uZWN0aW9uIG9uIFNQQTogJHtlcnIgaW5zdGFuY2VvZiBFcnJvciA/IGVyci5tZXNzYWdlIDogZXJyfWAsXG5cdFx0XHQpO1xuXHRcdH1cblx0XHRyZXR1cm4gYXBwLmNsaWVudF9pZDtcblx0fSBjYXRjaCAoZXJyKSB7XG5cdFx0Y29uc3QgZXhpc3RpbmcgPSByZWFkRXhpc3RpbmdTcGFDbGllbnRJZCh3b3Jrc3BhY2UudGFyZ2V0RGlyLCB3b3Jrc3BhY2UubmFtZSk7XG5cdFx0aWYgKGV4aXN0aW5nKSB7XG5cdFx0XHRjb25zb2xlLmVycm9yKFxuXHRcdFx0XHRgICDinJcgRmFpbGVkIHRvIGVuc3VyZSBBdXRoMCBTUEEgYXBwICgke2VyciBpbnN0YW5jZW9mIEVycm9yID8gZXJyLm1lc3NhZ2UgOiBlcnJ9KWAsXG5cdFx0XHQpO1xuXHRcdFx0Y29uc29sZS5sb2coYCAg4pyTIEtlZXBpbmcgZXhpc3RpbmcgYXV0aDBDbGllbnRJZCBmcm9tIFBvc3RtYW4gZW52aXJvbm1lbnQgKCR7ZXhpc3Rpbmd9KWApO1xuXHRcdFx0cmV0dXJuIGV4aXN0aW5nO1xuXHRcdH1cblx0XHR0aHJvdyBuZXcgRXJyb3IoXG5cdFx0XHRgRmFpbGVkIHRvIGVuc3VyZSBBdXRoMCBTUEEgYXBwIGZvciBQb3N0bWFuIOKAlCBhdXRoMENsaWVudElkIHdvdWxkIGJlIGVtcHR5OiAke1xuXHRcdFx0XHRlcnIgaW5zdGFuY2VvZiBFcnJvciA/IGVyci5tZXNzYWdlIDogZXJyXG5cdFx0XHR9YCxcblx0XHQpO1xuXHR9XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHNjYWZmb2xkKHdvcmtzcGFjZTogV29ya3NwYWNlU2NhZmZvbGQsIG9wdGlvbnM6IFBvc3RtYW5PcHRpb25zKTogUHJvbWlzZTx2b2lkPiB7XG5cdGlmIChvcHRpb25zLnBvc3RtYW5Qcm92aWRlciA9PT0gXCJub25lXCIgfHwgb3B0aW9ucy5wb3N0bWFuUHJvdmlkZXIgPT0gbnVsbCkgcmV0dXJuO1xuXG5cdGNvbnN0IGF1dGhDb25maWdNb2RlbCA9IHdvcmtzcGFjZS5nZXRNb2RlbDxBdXRoQ29uZmlnTW9kZWw+KFdFTExfS05PV05fRklMRVMuQVVUSF9DT05GSUcpO1xuXHRjb25zdCBhdXRoQ2ZnID0gYXV0aENvbmZpZ01vZGVsPy5jb25maWc7XG5cblx0Y29uc3Qgc3BhQ2xpZW50SWQgPSBhdXRoQ2ZnPy5pc3N1ZXJCYXNlVXJsID8gcmVzb2x2ZVNwYUNsaWVudElkKHdvcmtzcGFjZSkgOiB1bmRlZmluZWQ7XG5cblx0Y29uc3QgYXV0aDBFbnY6IEF1dGgwRW52IHwgdW5kZWZpbmVkID0gYXV0aENmZz8uaXNzdWVyQmFzZVVybFxuXHRcdD8ge1xuXHRcdFx0XHRhdXRoMERvbWFpbjogYXV0aENmZy5pc3N1ZXJCYXNlVXJsLnJlcGxhY2UoL15odHRwcz86XFwvXFwvLywgXCJcIiksXG5cdFx0XHRcdGF1dGgwQXVkaWVuY2U6IGF1dGhDZmcuYXVkaWVuY2UsXG5cdFx0XHRcdGF1dGgwQ2xpZW50SWQ6IHNwYUNsaWVudElkLFxuXHRcdFx0fVxuXHRcdDogdW5kZWZpbmVkO1xuXG5cdGNvbnN0IHByb2plY3ROYW1lID0gd29ya3NwYWNlLm5hbWU7XG5cdGNvbnN0IGVudk5hbWUgPSBgJHtwcm9qZWN0TmFtZX0gTG9jYWxgO1xuXHRjb25zdCBjb2xsZWN0aW9uID0gYXdhaXQgYnVpbGRIeWJyaWRQb3N0bWFuQ29sbGVjdGlvbihwcm9qZWN0TmFtZSwgYXV0aDBFbnYpO1xuXHRjb25zdCBsb2NhbEZpbGVzID0gYnVpbGRMb2NhbFZpZXdGaWxlc0Zyb21Db2xsZWN0aW9uKGNvbGxlY3Rpb24sIHByb2plY3ROYW1lLCBhdXRoMEVudiwge1xuXHRcdGNhbGxiYWNrczogUE9TVE1BTl9DQUxMQkFDS1MsXG5cdFx0c2NvcGVzOiBQT1NUTUFOX1NDT1BFUyxcblx0fSk7XG5cdGNvbnN0IGVudllhbWwgPSBidWlsZEVudmlyb25tZW50WWFtbChlbnZOYW1lLCBhdXRoMEVudiwge1xuXHRcdGNhbGxiYWNrczogUE9TVE1BTl9DQUxMQkFDS1MsXG5cdFx0c2NvcGVzOiBQT1NUTUFOX1NDT1BFUyxcblx0fSk7XG5cblx0d29ya3NwYWNlLmFkZEZpbGUoe1xuXHRcdGZpbGVzOiAoKSA9PiBbXG5cdFx0XHR7XG5cdFx0XHRcdGZpbGVQYXRoOiBcIi5wb3N0bWFuL3Jlc291cmNlcy55YW1sXCIsXG5cdFx0XHRcdGNvbnRlbnQ6IFtcblx0XHRcdFx0XHRcIiMgT3BlbiB0aGlzIHByb2plY3Qgcm9vdCBpbiBQb3N0bWFuIChGaWxlcyDihpIgT3BlbiBmb2xkZXIpLCBub3QgdGhlIHBvc3RtYW4vIHN1YmZvbGRlci5cIixcblx0XHRcdFx0XHRcIiMgUG9zdG1hbiBmaWxscyB3b3Jrc3BhY2UuaWQgd2hlbiB5b3UgY29ubmVjdCBMb2NhbCBWaWV3LlwiLFxuXHRcdFx0XHRcdFwiI1wiLFxuXHRcdFx0XHRcdFwiIyBBbGwgcmVzb3VyY2VzIHVuZGVyIHBvc3RtYW4vIGFyZSByZWdpc3RlcmVkIGF1dG9tYXRpY2FsbHkuXCIsXG5cdFx0XHRcdFx0XCIjIFJvdXRlIHJlcXVlc3RzIGFyZSBnZW5lcmF0ZWQgZnJvbSBPcGVuQVBJOyBBdXRoMCBvdmVybGF5IGlzIGhhbmQtYXV0aG9yZWQuXCIsXG5cdFx0XHRcdFx0XCJcIixcblx0XHRcdFx0XS5qb2luKFwiXFxuXCIpLFxuXHRcdFx0fSxcblx0XHRcdHtcblx0XHRcdFx0ZmlsZVBhdGg6IGBwb3N0bWFuL2Vudmlyb25tZW50cy8ke3Byb2plY3ROYW1lfS1Mb2NhbC5lbnZpcm9ubWVudC55YW1sYCxcblx0XHRcdFx0Y29udGVudDogZW52WWFtbCxcblx0XHRcdH0sXG5cdFx0XHQuLi5sb2NhbEZpbGVzLFxuXHRcdF0sXG5cdH0pO1xuXG5cdGlmIChvcHRpb25zLnBvc3RtYW5Qcm92aWRlciA9PT0gXCJhcGlcIiAmJiBvcHRpb25zLmFwaUtleSkge1xuXHRcdGNvbnN0IGhlYWRlcnMgPSB7IFwiWC1BcGktS2V5XCI6IG9wdGlvbnMuYXBpS2V5LCBcIkNvbnRlbnQtVHlwZVwiOiBcImFwcGxpY2F0aW9uL2pzb25cIiB9O1xuXG5cdFx0Y29uc3QgY29sUmVzID0gYXdhaXQgZmV0Y2goXG5cdFx0XHRgaHR0cHM6Ly9hcGkuZ2V0cG9zdG1hbi5jb20vY29sbGVjdGlvbnM/d29ya3NwYWNlPSR7b3B0aW9ucy53b3Jrc3BhY2VJZH1gLFxuXHRcdFx0e1xuXHRcdFx0XHRtZXRob2Q6IFwiUE9TVFwiLFxuXHRcdFx0XHRoZWFkZXJzLFxuXHRcdFx0XHRib2R5OiBKU09OLnN0cmluZ2lmeSh7IGNvbGxlY3Rpb24gfSksXG5cdFx0XHR9LFxuXHRcdCk7XG5cdFx0aWYgKGNvbFJlcy5vaykge1xuXHRcdFx0Y29uc29sZS5sb2coXCIgIOKckyBQb3N0bWFuIGNvbGxlY3Rpb24gdXBsb2FkZWRcIik7XG5cdFx0fSBlbHNlIHtcblx0XHRcdGNvbnNvbGUuZXJyb3IoXCIgIOKclyBGYWlsZWQgdG8gdXBsb2FkIFBvc3RtYW4gY29sbGVjdGlvblwiKTtcblx0XHR9XG5cblx0XHRjb25zdCBlbnZWYWx1ZXMgPSBbXG5cdFx0XHR7IGtleTogXCJiYXNlVXJsXCIsIHZhbHVlOiBcImh0dHA6Ly9sb2NhbGhvc3Q6MzAwMFwiLCBlbmFibGVkOiB0cnVlIH0sXG5cdFx0XHQuLi4oYXV0aDBFbnY/LmF1dGgwRG9tYWluXG5cdFx0XHRcdD8gW1xuXHRcdFx0XHRcdFx0eyBrZXk6IFwiYXV0aDBEb21haW5cIiwgdmFsdWU6IGF1dGgwRW52LmF1dGgwRG9tYWluLCBlbmFibGVkOiB0cnVlIH0sXG5cdFx0XHRcdFx0XHR7IGtleTogXCJhdXRoMEF1ZGllbmNlXCIsIHZhbHVlOiBhdXRoMEVudi5hdXRoMEF1ZGllbmNlID8/IFwiXCIsIGVuYWJsZWQ6IHRydWUgfSxcblx0XHRcdFx0XHRcdHsga2V5OiBcImF1dGgwQ2xpZW50SWRcIiwgdmFsdWU6IGF1dGgwRW52LmF1dGgwQ2xpZW50SWQgPz8gXCJcIiwgZW5hYmxlZDogdHJ1ZSB9LFxuXHRcdFx0XHRcdF1cblx0XHRcdFx0OiBbXSksXG5cdFx0XTtcblx0XHRjb25zdCBlbnZSZXMgPSBhd2FpdCBmZXRjaChcblx0XHRcdGBodHRwczovL2FwaS5nZXRwb3N0bWFuLmNvbS9lbnZpcm9ubWVudHM/d29ya3NwYWNlPSR7b3B0aW9ucy53b3Jrc3BhY2VJZH1gLFxuXHRcdFx0e1xuXHRcdFx0XHRtZXRob2Q6IFwiUE9TVFwiLFxuXHRcdFx0XHRoZWFkZXJzLFxuXHRcdFx0XHRib2R5OiBKU09OLnN0cmluZ2lmeSh7XG5cdFx0XHRcdFx0ZW52aXJvbm1lbnQ6IHsgbmFtZTogZW52TmFtZSwgdmFsdWVzOiBlbnZWYWx1ZXMgfSxcblx0XHRcdFx0fSksXG5cdFx0XHR9LFxuXHRcdCk7XG5cdFx0aWYgKGVudlJlcy5vaykge1xuXHRcdFx0Y29uc29sZS5sb2coXCIgIOKckyBQb3N0bWFuIGVudmlyb25tZW50IHVwbG9hZGVkXCIpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRjb25zb2xlLmVycm9yKFwiICDinJcgRmFpbGVkIHRvIHVwbG9hZCBQb3N0bWFuIGVudmlyb25tZW50XCIpO1xuXHRcdH1cblx0fVxufVxuXG5leHBvcnQgY29uc3QgUG9zdG1hbkZlYXR1cmU6IEZlYXR1cmU8UG9zdG1hbk9wdGlvbnM+ID0geyBnZXRPcHRpb25zLCBzY2FmZm9sZCB9O1xuZXhwb3J0IHsgYnVpbGRIZWxsb09wZW5BcGlEb2N1bWVudCB9IGZyb20gXCIuLi9wb3N0bWFuL2hlbGxvLW9wZW5hcGkuanNcIjtcbmV4cG9ydCB7IFBPU1RNQU5fQ0FMTEJBQ0tTLCBQT1NUTUFOX1NDT1BFUyB9O1xuIl0sIm5hbWVzIjpbInJhbmRvbVVVSUQiLCJleGlzdHNTeW5jIiwicmVhZEZpbGVTeW5jIiwiam9pbiIsInBpY2siLCJXRUxMX0tOT1dOX0ZJTEVTIiwiYnVpbGRIZWxsb09wZW5BcGlEb2N1bWVudCIsImJ1aWxkRW52aXJvbm1lbnRZYW1sIiwiYnVpbGRMb2NhbFZpZXdGaWxlc0Zyb21Db2xsZWN0aW9uIiwiYXBwbHlQb3N0bWFuQXV0aE92ZXJsYXkiLCJvcGVuQXBpVG9Qb3N0bWFuQ29sbGVjdGlvbiIsImF1dGgwQ2xpIiwiUE9TVE1BTl9DQUxMQkFDS1MiLCJQT1NUTUFOX1NDT1BFUyIsIkNPTExFQ1RJT05fREVTQ1JJUFRJT04iLCJnZXRPcHRpb25zIiwiX3dvcmtzcGFjZSIsImNsaU9wdGlvbnMiLCJwb3N0bWFuUHJvdmlkZXIiLCJjaG9pY2VzIiwibGFiZWwiLCJkZXNjcmlwdGlvbiIsInNlbGVjdGVkIiwiYyIsInByb3ZpZGVyIiwiYXBpS2V5IiwicHJvY2VzcyIsImVudiIsIlBPU1RNQU5fQVBJX0tFWSIsInRoZW4iLCJtIiwiYXNrIiwiaGVhZGVycyIsIndzUmVzIiwiZmV0Y2giLCJvayIsImNvbnNvbGUiLCJlcnJvciIsIndvcmtzcGFjZXMiLCJqc29uIiwid3NDaG9pY2VzIiwiaWQiLCJtYXAiLCJ3IiwibmFtZSIsInR5cGUiLCJ3c1BpY2tlZCIsIndvcmtzcGFjZUlkIiwid3NOYW1lIiwiY3JlYXRlUmVzIiwibWV0aG9kIiwiYm9keSIsIkpTT04iLCJzdHJpbmdpZnkiLCJ3b3Jrc3BhY2UiLCJ3cyIsImxvZyIsImJ1aWxkSHlicmlkUG9zdG1hbkNvbGxlY3Rpb24iLCJwcm9qZWN0TmFtZSIsImF1dGgiLCJvcGVuYXBpIiwiYmFzZSIsImluZm8iLCJfcG9zdG1hbl9pZCIsImNhbGxiYWNrcyIsInNjb3BlcyIsInJlYWRFeGlzdGluZ1NwYUNsaWVudElkIiwidGFyZ2V0RGlyIiwiZW52UGF0aCIsInVuZGVmaW5lZCIsInRleHQiLCJtYXRjaCIsInZhbHVlIiwidHJpbSIsImxlbmd0aCIsInJlc29sdmVTcGFDbGllbnRJZCIsImFwcE5hbWUiLCJhcHAiLCJlbnN1cmVTcGFBcHAiLCJyZXVzZWQiLCJjbGllbnRfaWQiLCJlbmFibGVDb25uZWN0aW9uRm9yQ2xpZW50IiwiREJfQ09OTkVDVElPTl9OQU1FIiwiZXJyIiwiRXJyb3IiLCJtZXNzYWdlIiwiZXhpc3RpbmciLCJzY2FmZm9sZCIsIm9wdGlvbnMiLCJhdXRoQ29uZmlnTW9kZWwiLCJnZXRNb2RlbCIsIkFVVEhfQ09ORklHIiwiYXV0aENmZyIsImNvbmZpZyIsInNwYUNsaWVudElkIiwiaXNzdWVyQmFzZVVybCIsImF1dGgwRW52IiwiYXV0aDBEb21haW4iLCJyZXBsYWNlIiwiYXV0aDBBdWRpZW5jZSIsImF1ZGllbmNlIiwiYXV0aDBDbGllbnRJZCIsImVudk5hbWUiLCJjb2xsZWN0aW9uIiwibG9jYWxGaWxlcyIsImVudllhbWwiLCJhZGRGaWxlIiwiZmlsZXMiLCJmaWxlUGF0aCIsImNvbnRlbnQiLCJjb2xSZXMiLCJlbnZWYWx1ZXMiLCJrZXkiLCJlbmFibGVkIiwiZW52UmVzIiwiZW52aXJvbm1lbnQiLCJ2YWx1ZXMiLCJQb3N0bWFuRmVhdHVyZSJdLCJtYXBwaW5ncyI6IkFBQUEsU0FBU0EsVUFBVSxRQUFRLGNBQWM7QUFDekMsU0FBU0MsVUFBVSxFQUFFQyxZQUFZLFFBQVEsVUFBVTtBQUNuRCxTQUFTQyxJQUFJLFFBQVEsWUFBWTtBQUNqQyxTQUFTQyxJQUFJLFFBQVEseUJBQXlCO0FBQzlDLFNBQVNDLGdCQUFnQixRQUFRLHdCQUF3QjtBQUl6RCxTQUFTQyx5QkFBeUIsUUFBUSw4QkFBOEI7QUFDeEUsU0FDQ0Msb0JBQW9CLEVBQ3BCQyxpQ0FBaUMsUUFDM0IsMkJBQTJCO0FBQ2xDLFNBRUNDLHVCQUF1QixFQUN2QkMsMEJBQTBCLFFBQ3BCLG1DQUFtQztBQUMxQyxZQUFZQyxjQUFjLGlCQUFpQjtBQUUzQyxxRUFBcUUsR0FDckUsTUFBTUMsb0JBQW9CO0lBQ3pCO0lBQ0E7Q0FDQTtBQUVELDhFQUE4RSxHQUM5RSxNQUFNQyxpQkFBaUI7SUFDdEI7SUFDQTtJQUNBO0lBQ0E7SUFDQTtJQUNBO0lBQ0E7Q0FDQSxDQUFDVixJQUFJLENBQUM7QUFFUCxNQUFNVyx5QkFDTCw0RUFDQSxxRkFDQTtBQVFELGVBQWVDLFdBQ2RDLFVBQTZCLEVBQzdCQyxVQUFtQztJQUVuQyxJQUFJQSxXQUFXQyxlQUFlLElBQUksTUFBTSxPQUFPLENBQUM7SUFFaEQsTUFBTUMsVUFBVTtRQUNmO1lBQUVDLE9BQU87WUFBaUJDLGFBQWE7UUFBTztRQUM5QztZ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
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
import { WELL_KNOWN_FILES } from "../../models/const.js";
|
|
2
|
-
import { CREATE_VERSION } from "../../version.js";
|
|
3
|
-
/**
|
|
4
|
-
* Builder for `projects/<api>/package.json`.
|
|
5
|
-
*
|
|
6
|
-
* Starts with the core cortex + crucible deps. Features can call
|
|
7
|
-
* `addDependency` / `addDevDependency` to extend.
|
|
8
|
-
*/ export class ApiPackageJson {
|
|
9
|
-
workspaceName;
|
|
10
|
-
apiName;
|
|
11
|
-
key = WELL_KNOWN_FILES.API_PACKAGE_JSON;
|
|
12
|
-
_dependencies;
|
|
13
|
-
_devDependencies = {};
|
|
14
|
-
constructor(workspaceName, apiName = "api"){
|
|
15
|
-
this.workspaceName = workspaceName;
|
|
16
|
-
this.apiName = apiName;
|
|
17
|
-
this._dependencies = {
|
|
18
|
-
"@decohere/cortex": CREATE_VERSION,
|
|
19
|
-
"@decohere/crucible": CREATE_VERSION
|
|
20
|
-
};
|
|
21
|
-
}
|
|
22
|
-
addDependency(name, version) {
|
|
23
|
-
this._dependencies[name] = version;
|
|
24
|
-
return this;
|
|
25
|
-
}
|
|
26
|
-
addDevDependency(name, version) {
|
|
27
|
-
this._devDependencies[name] = version;
|
|
28
|
-
return this;
|
|
29
|
-
}
|
|
30
|
-
files() {
|
|
31
|
-
const pkg = {
|
|
32
|
-
name: `@${this.workspaceName}/${this.apiName}`,
|
|
33
|
-
version: "0.0.1",
|
|
34
|
-
private: true,
|
|
35
|
-
type: "module",
|
|
36
|
-
main: "src/main.ts",
|
|
37
|
-
scripts: {
|
|
38
|
-
lint: "biome check --write ."
|
|
39
|
-
},
|
|
40
|
-
dependencies: {
|
|
41
|
-
...this._dependencies
|
|
42
|
-
}
|
|
43
|
-
};
|
|
44
|
-
if (Object.keys(this._devDependencies).length > 0) {
|
|
45
|
-
pkg.devDependencies = {
|
|
46
|
-
...this._devDependencies
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
|
-
return [
|
|
50
|
-
{
|
|
51
|
-
filePath: "package.json",
|
|
52
|
-
content: JSON.stringify(pkg, null, 2)
|
|
53
|
-
}
|
|
54
|
-
];
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL3J1bm5lci93b3JrL2RlY29oZXJlL2RlY29oZXJlL3Byb2plY3RzL2NyZWF0ZS9zcmMvd2ViYXBpL21vZGVscy9hcGktcGFja2FnZS1qc29uLm1vZGVsLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IFdFTExfS05PV05fRklMRVMgfSBmcm9tIFwiLi4vLi4vbW9kZWxzL2NvbnN0LmpzXCI7XG5pbXBvcnQgdHlwZSB7IEtleWVkTW9kZWwsIFNvdXJjZUZpbGUgfSBmcm9tIFwiLi4vLi4vbW9kZWxzL3NvdXJjZS1maWxlLmpzXCI7XG5pbXBvcnQgeyBDUkVBVEVfVkVSU0lPTiB9IGZyb20gXCIuLi8uLi92ZXJzaW9uLmpzXCI7XG5cbi8qKlxuICogQnVpbGRlciBmb3IgYHByb2plY3RzLzxhcGk+L3BhY2thZ2UuanNvbmAuXG4gKlxuICogU3RhcnRzIHdpdGggdGhlIGNvcmUgY29ydGV4ICsgY3J1Y2libGUgZGVwcy4gRmVhdHVyZXMgY2FuIGNhbGxcbiAqIGBhZGREZXBlbmRlbmN5YCAvIGBhZGREZXZEZXBlbmRlbmN5YCB0byBleHRlbmQuXG4gKi9cbmV4cG9ydCBjbGFzcyBBcGlQYWNrYWdlSnNvbiBpbXBsZW1lbnRzIEtleWVkTW9kZWwge1xuXHRwdWJsaWMgcmVhZG9ubHkga2V5ID0gV0VMTF9LTk9XTl9GSUxFUy5BUElfUEFDS0FHRV9KU09OO1xuXG5cdHByaXZhdGUgcmVhZG9ubHkgX2RlcGVuZGVuY2llczogUmVjb3JkPHN0cmluZywgc3RyaW5nPjtcblx0cHJpdmF0ZSByZWFkb25seSBfZGV2RGVwZW5kZW5jaWVzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge307XG5cblx0cHVibGljIGNvbnN0cnVjdG9yKFxuXHRcdHByaXZhdGUgcmVhZG9ubHkgd29ya3NwYWNlTmFtZTogc3RyaW5nLFxuXHRcdHByaXZhdGUgcmVhZG9ubHkgYXBpTmFtZSA9IFwiYXBpXCIsXG5cdCkge1xuXHRcdHRoaXMuX2RlcGVuZGVuY2llcyA9IHtcblx0XHRcdFwiQGRlY29oZXJlL2NvcnRleFwiOiBDUkVBVEVfVkVSU0lPTixcblx0XHRcdFwiQGRlY29oZXJlL2NydWNpYmxlXCI6IENSRUFURV9WRVJTSU9OLFxuXHRcdH07XG5cdH1cblxuXHRwdWJsaWMgYWRkRGVwZW5kZW5jeShuYW1lOiBzdHJpbmcsIHZlcnNpb246IHN0cmluZyk6IHRoaXMge1xuXHRcdHRoaXMuX2RlcGVuZGVuY2llc1tuYW1lXSA9IHZlcnNpb247XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxuXHRwdWJsaWMgYWRkRGV2RGVwZW5kZW5jeShuYW1lOiBzdHJpbmcsIHZlcnNpb246IHN0cmluZyk6IHRoaXMge1xuXHRcdHRoaXMuX2RldkRlcGVuZGVuY2llc1tuYW1lXSA9IHZlcnNpb247XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxuXHRwdWJsaWMgZmlsZXMoKTogU291cmNlRmlsZVtdIHtcblx0XHRjb25zdCBwa2c6IFJlY29yZDxzdHJpbmcsIHVua25vd24+ID0ge1xuXHRcdFx0bmFtZTogYEAke3RoaXMud29ya3NwYWNlTmFtZX0vJHt0aGlzLmFwaU5hbWV9YCxcblx0XHRcdHZlcnNpb246IFwiMC4wLjFcIixcblx0XHRcdHByaXZhdGU6IHRydWUsXG5cdFx0XHR0eXBlOiBcIm1vZHVsZVwiLFxuXHRcdFx0bWFpbjogXCJzcmMvbWFpbi50c1wiLFxuXHRcdFx0c2NyaXB0czoge1xuXHRcdFx0XHRsaW50OiBcImJpb21lIGNoZWNrIC0td3JpdGUgLlwiLFxuXHRcdFx0fSxcblx0XHRcdGRlcGVuZGVuY2llczogeyAuLi50aGlzLl9kZXBlbmRlbmNpZXMgfSxcblx0XHR9O1xuXHRcdGlmIChPYmplY3Qua2V5cyh0aGlzLl9kZXZEZXBlbmRlbmNpZXMpLmxlbmd0aCA+IDApIHtcblx0XHRcdHBrZy5kZXZEZXBlbmRlbmNpZXMgPSB7IC4uLnRoaXMuX2RldkRlcGVuZGVuY2llcyB9O1xuXHRcdH1cblx0XHRyZXR1cm4gW1xuXHRcdFx0e1xuXHRcdFx0XHRmaWxlUGF0aDogXCJwYWNrYWdlLmpzb25cIixcblx0XHRcdFx0Y29udGVudDogSlNPTi5zdHJpbmdpZnkocGtnLCBudWxsLCAyKSxcblx0XHRcdH0sXG5cdFx0XTtcblx0fVxufVxuIl0sIm5hbWVzIjpbIldFTExfS05PV05fRklMRVMiLCJDUkVBVEVfVkVSU0lPTiIsIkFwaVBhY2thZ2VKc29uIiwia2V5IiwiQVBJX1BBQ0tBR0VfSlNPTiIsIl9kZXBlbmRlbmNpZXMiLCJfZGV2RGVwZW5kZW5jaWVzIiwid29ya3NwYWNlTmFtZSIsImFwaU5hbWUiLCJhZGREZXBlbmRlbmN5IiwibmFtZSIsInZlcnNpb24iLCJhZGREZXZEZXBlbmRlbmN5IiwiZmlsZXMiLCJwa2ciLCJwcml2YXRlIiwidHlwZSIsIm1haW4iLCJzY3JpcHRzIiwibGludCIsImRlcGVuZGVuY2llcyIsIk9iamVjdCIsImtleXMiLCJsZW5ndGgiLCJkZXZEZXBlbmRlbmNpZXMiLCJmaWxlUGF0aCIsImNvbnRlbnQiLCJKU09OIiwic3RyaW5naWZ5Il0sIm1hcHBpbmdzIjoiQUFBQSxTQUFTQSxnQkFBZ0IsUUFBUSx3QkFBd0I7QUFFekQsU0FBU0MsY0FBYyxRQUFRLG1CQUFtQjtBQUVsRDs7Ozs7Q0FLQyxHQUNELE9BQU8sTUFBTUM7OztJQUNJQyxNQUFNSCxpQkFBaUJJLGdCQUFnQixDQUFDO0lBRXZDQyxjQUFzQztJQUN0Q0MsbUJBQTJDLENBQUMsRUFBRTtJQUUvRCxZQUNDLEFBQWlCQyxhQUFxQixFQUN0QyxBQUFpQkMsVUFBVSxLQUFLLENBQy9CO2FBRmdCRCxnQkFBQUE7YUFDQUMsVUFBQUE7UUFFakIsSUFBSSxDQUFDSCxhQUFhLEdBQUc7WUFDcEIsb0JBQW9CSjtZQUNwQixzQkFBc0JBO1FBQ3ZCO0lBQ0Q7SUFFT1EsY0FBY0MsSUFBWSxFQUFFQyxPQUFlLEVBQVE7UUFDekQsSUFBSSxDQUFDTixhQUFhLENBQUNLLEtBQUssR0FBR0M7UUFDM0IsT0FBTyxJQUFJO0lBQ1o7SUFFT0MsaUJBQWlCRixJQUFZLEVBQUVDLE9BQWUsRUFBUTtRQUM1RCxJQUFJLENBQUNMLGdCQUFnQixDQUFDSSxLQUFLLEdBQUdDO1FBQzlCLE9BQU8sSUFBSTtJQUNaO0lBRU9FLFFBQXNCO1FBQzVCLE1BQU1DLE1BQStCO1lBQ3BDSixNQUFNLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQ0gsYUFBYSxDQUFDLENBQUMsRUFBRSxJQUFJLENBQUNDLE9BQU8sRUFBRTtZQUM5Q0csU0FBUztZQUNUSSxTQUFTO1lBQ1RDLE1BQU07WUFDTkMsTUFBTTtZQUNOQyxTQUFTO2dCQUNSQyxNQUFNO1lBQ1A7WUFDQUMsY0FBYztnQkFBRSxHQUFHLElBQUksQ0FBQ2YsYUFBYTtZQUFDO1FBQ3ZDO1FBQ0EsSUFBSWdCLE9BQU9DLElBQUksQ0FBQyxJQUFJLENBQUNoQixnQkFBZ0IsRUFBRWlCLE1BQU0sR0FBRyxHQUFHO1lBQ2xEVCxJQUFJVSxlQUFlLEdBQUc7Z0JBQUUsR0FBRyxJQUFJLENBQUNsQixnQkFBZ0I7WUFBQztRQUNsRDtRQUNBLE9BQU87WUFDTjtnQkFDQ21CLFVBQVU7Z0JBQ1ZDLFNBQVNDLEtBQUtDLFNBQVMsQ0FBQ2QsS0FBSyxNQUFNO1lBQ3BDO1NBQ0E7SUFDRjtBQUNEIn0=
|
|
@@ -1,22 +0,0 @@
|
|
|
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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL3J1bm5lci93b3JrL2RlY29oZXJlL2RlY29oZXJlL3Byb2plY3RzL2NyZWF0ZS9zcmMvd2ViYXBpL21vZGVscy9hdXRoLWNvbmZpZy5tb2RlbC50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBXRUxMX0tOT1dOX0ZJTEVTIH0gZnJvbSBcIi4uLy4uL21vZGVscy9jb25zdC5qc1wiO1xuaW1wb3J0IHR5cGUgeyBLZXllZE1vZGVsLCBTb3VyY2VGaWxlIH0gZnJvbSBcIi4uLy4uL21vZGVscy9zb3VyY2UtZmlsZS5qc1wiO1xuXG5leHBvcnQgdHlwZSBBZG1pblVzZXJDb25maWcgPSB7XG5cdHN1Yjogc3RyaW5nO1xuXHRlbWFpbDogc3RyaW5nO1xuXHRwYXNzd29yZDogc3RyaW5nO1xuXHR1c2VybmFtZTogc3RyaW5nO1xufTtcblxuZXhwb3J0IHR5cGUgQXV0aENvbmZpZyA9IHtcblx0aXNzdWVyQmFzZVVybDogc3RyaW5nO1xuXHRhdWRpZW5jZTogc3RyaW5nO1xuXHRhZG1pblVzZXI/OiBBZG1pblVzZXJDb25maWc7XG59O1xuXG4vKipcbiAqIERhdGEtY2FycmllciBtb2RlbCBmb3IgYXV0aCBjb25maWd1cmF0aW9uLlxuICpcbiAqIFJlZ2lzdGVyZWQgYnkgQXV0aEZlYXR1cmUgd2hlbiBhdXRoMCBpcyBjb25maWd1cmVkLiBPdGhlciBmZWF0dXJlcyAoZS5nLlxuICogUG9zdG1hbkZlYXR1cmUpIHJldHJpZXZlIGl0IHZpYSB3b3Jrc3BhY2UuZ2V0TW9kZWwoV0VMTF9LTk9XTl9GSUxFUy5BVVRIX0NPTkZJRykuXG4gKiBQcm9kdWNlcyBubyBmaWxlcyDigJQgZXhpc3RzIHNvbGVseSBzbyBmZWF0dXJlcyBjYW4gY29tbXVuaWNhdGUgYXV0aCBkZXRhaWxzLlxuICovXG5leHBvcnQgY2xhc3MgQXV0aENvbmZpZ01vZGVsIGltcGxlbWVudHMgS2V5ZWRNb2RlbCB7XG5cdHB1YmxpYyByZWFkb25seSBrZXkgPSBXRUxMX0tOT1dOX0ZJTEVTLkFVVEhfQ09ORklHO1xuXG5cdHB1YmxpYyBjb25zdHJ1Y3RvcihwdWJsaWMgcmVhZG9ubHkgY29uZmlnOiBBdXRoQ29uZmlnKSB7fVxuXG5cdHB1YmxpYyBzZXRBZG1pblVzZXIoYWRtaW5Vc2VyOiBBZG1pblVzZXJDb25maWcpOiB2b2lkIHtcblx0XHR0aGlzLmNvbmZpZy5hZG1pblVzZXIgPSBhZG1pblVzZXI7XG5cdH1cblxuXHRwdWJsaWMgZmlsZXMoKTogU291cmNlRmlsZVtdIHtcblx0XHRyZXR1cm4gW107XG5cdH1cbn1cbiJdLCJuYW1lcyI6WyJXRUxMX0tOT1dOX0ZJTEVTIiwiQXV0aENvbmZpZ01vZGVsIiwia2V5IiwiQVVUSF9DT05GSUciLCJjb25maWciLCJzZXRBZG1pblVzZXIiLCJhZG1pblVzZXIiLCJmaWxlcyJdLCJtYXBwaW5ncyI6IkFBQUEsU0FBU0EsZ0JBQWdCLFFBQVEsd0JBQXdCO0FBZ0J6RDs7Ozs7O0NBTUMsR0FDRCxPQUFPLE1BQU1DOztJQUNJQyxNQUFNRixpQkFBaUJHLFdBQVcsQ0FBQztJQUVuRCxZQUFtQixBQUFnQkMsTUFBa0IsQ0FBRTthQUFwQkEsU0FBQUE7SUFBcUI7SUFFakRDLGFBQWFDLFNBQTBCLEVBQVE7UUFDckQsSUFBSSxDQUFDRixNQUFNLENBQUNFLFNBQVMsR0FBR0E7SUFDekI7SUFFT0MsUUFBc0I7UUFDNUIsT0FBTyxFQUFFO0lBQ1Y7QUFDRCJ9
|
|
@@ -1,179 +0,0 @@
|
|
|
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
|
-
_classDecorators = [];
|
|
87
|
-
_ctorParams = [
|
|
88
|
-
"private readonly sample: SampleService"
|
|
89
|
-
];
|
|
90
|
-
_methods = new Map([
|
|
91
|
-
[
|
|
92
|
-
"getAll",
|
|
93
|
-
new ControllerMethod("getAll", "@Get()", '@Query("filter") filter: string', true, [
|
|
94
|
-
"const greeting = await this.sample.getGreeting();",
|
|
95
|
-
"return { filter, message: greeting };"
|
|
96
|
-
])
|
|
97
|
-
],
|
|
98
|
-
[
|
|
99
|
-
"getOne",
|
|
100
|
-
new ControllerMethod("getOne", '@Get("/:id")', '@Param("id") id: string', false, // biome-ignore lint/suspicious/noTemplateCurlyInString: template literal in generated code
|
|
101
|
-
[
|
|
102
|
-
"return { id, message: `Hello ${id}!` };"
|
|
103
|
-
])
|
|
104
|
-
],
|
|
105
|
-
[
|
|
106
|
-
"create",
|
|
107
|
-
new ControllerMethod("create", "@Post()", "body: HelloBody", false, [
|
|
108
|
-
"return { message: body.message };"
|
|
109
|
-
])
|
|
110
|
-
],
|
|
111
|
-
[
|
|
112
|
-
"update",
|
|
113
|
-
new ControllerMethod("update", '@Put("/:id")', '@Param("id") id: string, body: HelloBody', false, [
|
|
114
|
-
"return { id, message: body.message };"
|
|
115
|
-
])
|
|
116
|
-
],
|
|
117
|
-
[
|
|
118
|
-
"remove",
|
|
119
|
-
new ControllerMethod("remove", '@Delete("/:id")', '@Param("id") id: string', false, [
|
|
120
|
-
"return { id, deleted: true };"
|
|
121
|
-
])
|
|
122
|
-
]
|
|
123
|
-
]);
|
|
124
|
-
/** Retrieve a method by name to mutate its decorators. */ getMethod(name) {
|
|
125
|
-
const m = this._methods.get(name);
|
|
126
|
-
if (m == null) throw new Error(`No method '${name}' on ControllerSourceFile`);
|
|
127
|
-
return m;
|
|
128
|
-
}
|
|
129
|
-
/** Add a class-level decorator (e.g. `@Authorize`). */ addDecorator(decorator) {
|
|
130
|
-
this._classDecorators.push(decorator);
|
|
131
|
-
return this;
|
|
132
|
-
}
|
|
133
|
-
/** Add a named import from `@decohere/cortex`. */ addCortexImport(name, typeOnly = false) {
|
|
134
|
-
this._cortexImports.add(name, typeOnly);
|
|
135
|
-
return this;
|
|
136
|
-
}
|
|
137
|
-
/** Add a named import from any other module. */ addImport(name, from, typeOnly = false) {
|
|
138
|
-
const group = this._extraImportGroups.get(from) ?? new ImportGroup();
|
|
139
|
-
group.add(name, typeOnly);
|
|
140
|
-
this._extraImportGroups.set(from, group);
|
|
141
|
-
return this;
|
|
142
|
-
}
|
|
143
|
-
/** Add a constructor parameter (e.g. an injected dependency). */ addConstructorParam(param) {
|
|
144
|
-
this._ctorParams.push(param);
|
|
145
|
-
return this;
|
|
146
|
-
}
|
|
147
|
-
files() {
|
|
148
|
-
const lines = [
|
|
149
|
-
this._cortexImports.render("@decohere/cortex"),
|
|
150
|
-
'import { SampleService } from "../services/sample.service.js";'
|
|
151
|
-
];
|
|
152
|
-
for (const [from, group] of this._extraImportGroups){
|
|
153
|
-
lines.push(group.render(from));
|
|
154
|
-
}
|
|
155
|
-
lines.push("", "class HelloBody {", '\t@Field("body", "message")', "\tpublic message!: string;", "}", "");
|
|
156
|
-
for (const d of this._classDecorators){
|
|
157
|
-
lines.push(d);
|
|
158
|
-
}
|
|
159
|
-
lines.push('@Controller({ prefix: "/hello" })', "export class HelloController {", "");
|
|
160
|
-
lines.push("\tpublic constructor(");
|
|
161
|
-
for (const p of this._ctorParams){
|
|
162
|
-
lines.push(`\t\t${p},`);
|
|
163
|
-
}
|
|
164
|
-
lines.push("\t) {}");
|
|
165
|
-
lines.push("");
|
|
166
|
-
for (const method of this._methods.values()){
|
|
167
|
-
lines.push(...method.render(), "");
|
|
168
|
-
}
|
|
169
|
-
lines.push("}", "");
|
|
170
|
-
return [
|
|
171
|
-
{
|
|
172
|
-
filePath: "src/controllers/hello.controller.ts",
|
|
173
|
-
content: lines.join("\n")
|
|
174
|
-
}
|
|
175
|
-
];
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL3J1bm5lci93b3JrL2RlY29oZXJlL2RlY29oZXJlL3Byb2plY3RzL2NyZWF0ZS9zcmMvd2ViYXBpL21vZGVscy9jb250cm9sbGVyLXNvdXJjZS1maWxlLm1vZGVsLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IFdFTExfS05PV05fRklMRVMgfSBmcm9tIFwiLi4vLi4vbW9kZWxzL2NvbnN0LmpzXCI7XG5pbXBvcnQgdHlwZSB7IEtleWVkTW9kZWwsIFNvdXJjZUZpbGUgfSBmcm9tIFwiLi4vLi4vbW9kZWxzL3NvdXJjZS1maWxlLmpzXCI7XG5cbi8qKiBUcmFja3MgbmFtZWQgaW1wb3J0cyBmcm9tIGEgc2luZ2xlIG1vZHVsZSBwYXRoLCBzcGxpdCBpbnRvIHZhbHVlcyBhbmQgdHlwZXMuICovXG5jbGFzcyBJbXBvcnRHcm91cCB7XG5cdHByaXZhdGUgcmVhZG9ubHkgX3ZhbHVlczogc3RyaW5nW10gPSBbXTtcblx0cHJpdmF0ZSByZWFkb25seSBfdHlwZXM6IHN0cmluZ1tdID0gW107XG5cblx0cHVibGljIGFkZChuYW1lOiBzdHJpbmcsIHR5cGVPbmx5ID0gZmFsc2UpOiB0aGlzIHtcblx0XHRpZiAodHlwZU9ubHkpIHtcblx0XHRcdC8vIFZhbHVlIGltcG9ydCBhbHJlYWR5IHByZXNlbnQg4oCUIHZhbHVlIHdpbnMsIHNraXBcblx0XHRcdGlmICghdGhpcy5fdmFsdWVzLmluY2x1ZGVzKG5hbWUpICYmICF0aGlzLl90eXBlcy5pbmNsdWRlcyhuYW1lKSkge1xuXHRcdFx0XHR0aGlzLl90eXBlcy5wdXNoKG5hbWUpO1xuXHRcdFx0fVxuXHRcdH0gZWxzZSB7XG5cdFx0XHQvLyBQcm9tb3RlOiByZW1vdmUgZnJvbSB0eXBlcyBpZiBpdCB3YXMgcHJldmlvdXNseSB0eXBlLW9ubHlcblx0XHRcdGNvbnN0IHR5cGVJZHggPSB0aGlzLl90eXBlcy5pbmRleE9mKG5hbWUpO1xuXHRcdFx0aWYgKHR5cGVJZHggIT09IC0xKSB0aGlzLl90eXBlcy5zcGxpY2UodHlwZUlkeCwgMSk7XG5cdFx0XHRpZiAoIXRoaXMuX3ZhbHVlcy5pbmNsdWRlcyhuYW1lKSkgdGhpcy5fdmFsdWVzLnB1c2gobmFtZSk7XG5cdFx0fVxuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0cHVibGljIHJlbmRlcihmcm9tOiBzdHJpbmcpOiBzdHJpbmcge1xuXHRcdGNvbnN0IHZhbHVlcyA9IFsuLi50aGlzLl92YWx1ZXNdLnNvcnQoKTtcblx0XHRjb25zdCB0eXBlcyA9IFsuLi50aGlzLl90eXBlc10uc29ydCgpLm1hcCgobikgPT4gYHR5cGUgJHtufWApO1xuXHRcdHJldHVybiBgaW1wb3J0IHsgJHtbLi4udmFsdWVzLCAuLi50eXBlc10uam9pbihcIiwgXCIpfSB9IGZyb20gXCIke2Zyb219XCI7YDtcblx0fVxufVxuXG4vKipcbiAqIEEgY29udHJvbGxlciBtZXRob2QuIEZlYXR1cmVzIGNhbGwgYGFkZERlY29yYXRvcigpYCB0byBwcmVwZW5kIGRlY29yYXRvcnNcbiAqIGJlZm9yZSB0aGUgSFRUUCB2ZXJiIGRlY29yYXRvciAoZS5nLiBgQEFsbG93QW5vbnltb3VzYCBiZWZvcmUgYEBHZXQoKWApLlxuICovXG5leHBvcnQgY2xhc3MgQ29udHJvbGxlck1ldGhvZCB7XG5cdHByaXZhdGUgcmVhZG9ubHkgX2V4dHJhRGVjb3JhdG9yczogc3RyaW5nW10gPSBbXTtcblx0cHJpdmF0ZSBfYm9keTogc3RyaW5nW107XG5cdHByaXZhdGUgX2lzQXN5bmM6IGJvb2xlYW47XG5cblx0cHVibGljIGNvbnN0cnVjdG9yKFxuXHRcdHB1YmxpYyByZWFkb25seSBuYW1lOiBzdHJpbmcsXG5cdFx0cHJpdmF0ZSByZWFkb25seSBfaHR0cERlY29yYXRvcjogc3RyaW5nLFxuXHRcdHByaXZhdGUgcmVhZG9ubHkgX3BhcmFtczogc3RyaW5nLFxuXHRcdGlzQXN5bmM6IGJvb2xlYW4sXG5cdFx0Ym9keTogc3RyaW5nW10sXG5cdCkge1xuXHRcdHRoaXMuX2lzQXN5bmMgPSBpc0FzeW5jO1xuXHRcdHRoaXMuX2JvZHkgPSBib2R5O1xuXHR9XG5cblx0cHVibGljIGFkZERlY29yYXRvcihkZWNvcmF0b3I6IHN0cmluZyk6IHRoaXMge1xuXHRcdHRoaXMuX2V4dHJhRGVjb3JhdG9ycy5wdXNoKGRlY29yYXRvcik7XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxuXHQvKiogUmVwbGFjZSB0aGUgbWV0aG9kIGJvZHkgbGluZXMgKHVzZWQgYnkgZmVhdHVyZXMgdGhhdCBleHRlbmQgZ2VuZXJhdGVkIGJlaGF2aW91cikuICovXG5cdHB1YmxpYyBzZXRCb2R5KGJvZHk6IHN0cmluZ1tdKTogdGhpcyB7XG5cdFx0dGhpcy5fYm9keSA9IGJvZHk7XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxuXHRwdWJsaWMgc2V0QXN5bmMoaXNBc3luYyA9IHRydWUpOiB0aGlzIHtcblx0XHR0aGlzLl9pc0FzeW5jID0gaXNBc3luYztcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdHB1YmxpYyByZW5kZXIoKTogc3RyaW5nW10ge1xuXHRcdGNvbnN0IGxpbmVzOiBzdHJpbmdbXSA9IFtdO1xuXHRcdGZvciAoY29uc3QgZCBvZiB0aGlzLl9leHRyYURlY29yYXRvcnMpIHtcblx0XHRcdGxpbmVzLnB1c2goYFxcdCR7ZH1gKTtcblx0XHR9XG5cdFx0bGluZXMucHVzaChgXFx0JHt0aGlzLl9odHRwRGVjb3JhdG9yfWApO1xuXHRcdGNvbnN0IGFzeW5jS3cgPSB0aGlzLl9pc0FzeW5jID8gXCJhc3luYyBcIiA6IFwiXCI7XG5cdFx0bGluZXMucHVzaChgXFx0cHVibGljICR7YXN5bmNLd30ke3RoaXMubmFtZX0oJHt0aGlzLl9wYXJhbXN9KSB7YCk7XG5cdFx0Zm9yIChjb25zdCBsaW5lIG9mIHRoaXMuX2JvZHkpIHtcblx0XHRcdGxpbmVzLnB1c2goYFxcdFxcdCR7bGluZX1gKTtcblx0XHR9XG5cdFx0bGluZXMucHVzaChcIlxcdH1cIik7XG5cdFx0cmV0dXJuIGxpbmVzO1xuXHR9XG59XG5cbi8qKlxuICogTW9kZWwgZm9yIGBwcm9qZWN0cy9hcGkvc3JjL2NvbnRyb2xsZXJzL2hlbGxvLmNvbnRyb2xsZXIudHNgLlxuICpcbiAqIFByZS1pbml0aWFsaXNlZCB3aXRoIGFsbCByb3V0ZXMgYW5kIHRoZWlyIEhUVFAgZGVjb3JhdG9ycy4gRmVhdHVyZXMgbXV0YXRlXG4gKiB0aGUgbW9kZWwgdmlhIGBnZXRNZXRob2QobmFtZSkuYWRkRGVjb3JhdG9yKC4uLilgLCBgYWRkRGVjb3JhdG9yKC4uLilgIChjbGFzc1xuICogbGV2ZWwpLCBgYWRkQ29ydGV4SW1wb3J0KC4uLilgLCBgYWRkSW1wb3J0KC4uLilgLCBhbmQgYGFkZENvbnN0cnVjdG9yUGFyYW0oLi4uKWAuXG4gKi9cbmV4cG9ydCBjbGFzcyBDb250cm9sbGVyU291cmNlRmlsZSBpbXBsZW1lbnRzIEtleWVkTW9kZWwge1xuXHRwdWJsaWMgcmVhZG9ubHkga2V5ID0gV0VMTF9LTk9XTl9GSUxFUy5DT05UUk9MTEVSX1RTO1xuXG5cdHByaXZhdGUgcmVhZG9ubHkgX2NvcnRleEltcG9ydHMgPSBuZXcgSW1wb3J0R3JvdXAoKVxuXHRcdC5hZGQoXCJDb250cm9sbGVyXCIpXG5cdFx0LmFkZChcIkRlbGV0ZVwiKVxuXHRcdC5hZGQoXCJGaWVsZFwiKVxuXHRcdC5hZGQoXCJHZXRcIilcblx0XHQuYWRkKFwiUGFyYW1cIilcblx0XHQuYWRkKFwiUG9zdFwiKVxuXHRcdC5hZGQoXCJQdXRcIilcblx0XHQuYWRkKFwiUXVlcnlcIik7XG5cblx0cHJpdmF0ZSByZWFkb25seSBfZXh0cmFJbXBvcnRHcm91cHMgPSBuZXcgTWFwPHN0cmluZywgSW1wb3J0R3JvdXA+KCk7XG5cdHByaXZhdGUgcmVhZG9ubHkgX2NsYXNzRGVjb3JhdG9yczogc3RyaW5nW10gPSBbXTtcblx0cHJpdmF0ZSByZWFkb25seSBfY3RvclBhcmFtczogc3RyaW5nW10gPSBbXCJwcml2YXRlIHJlYWRvbmx5IHNhbXBsZTogU2FtcGxlU2VydmljZVwiXTtcblxuXHRwcml2YXRlIHJlYWRvbmx5IF9tZXRob2RzID0gbmV3IE1hcDxzdHJpbmcsIENvbnRyb2xsZXJNZXRob2Q+KFtcblx0XHRbXG5cdFx0XHRcImdldEFsbFwiLFxuXHRcdFx0bmV3IENvbnRyb2xsZXJNZXRob2QoXCJnZXRBbGxcIiwgXCJAR2V0KClcIiwgJ0BRdWVyeShcImZpbHRlclwiKSBmaWx0ZXI6IHN0cmluZycsIHRydWUsIFtcblx0XHRcdFx0XCJjb25zdCBncmVldGluZyA9IGF3YWl0IHRoaXMuc2FtcGxlLmdldEdyZWV0aW5nKCk7XCIsXG5cdFx0XHRcdFwicmV0dXJuIHsgZmlsdGVyLCBtZXNzYWdlOiBncmVldGluZyB9O1wiLFxuXHRcdFx0XSksXG5cdFx0XSxcblx0XHRbXG5cdFx0XHRcImdldE9uZVwiLFxuXHRcdFx0bmV3IENvbnRyb2xsZXJNZXRob2QoXG5cdFx0XHRcdFwiZ2V0T25lXCIsXG5cdFx0XHRcdCdAR2V0KFwiLzppZFwiKScsXG5cdFx0XHRcdCdAUGFyYW0oXCJpZFwiKSBpZDogc3RyaW5nJyxcblx0XHRcdFx0ZmFsc2UsXG5cdFx0XHRcdC8vIGJpb21lLWlnbm9yZSBsaW50L3N1c3BpY2lvdXMvbm9UZW1wbGF0ZUN1cmx5SW5TdHJpbmc6IHRlbXBsYXRlIGxpdGVyYWwgaW4gZ2VuZXJhdGVkIGNvZGVcblx0XHRcdFx0W1wicmV0dXJuIHsgaWQsIG1lc3NhZ2U6IGBIZWxsbyAke2lkfSFgIH07XCJdLFxuXHRcdFx0KSxcblx0XHRdLFxuXHRcdFtcblx0XHRcdFwiY3JlYXRlXCIsXG5cdFx0XHRuZXcgQ29udHJvbGxlck1ldGhvZChcImNyZWF0ZVwiLCBcIkBQb3N0KClcIiwgXCJib2R5OiBIZWxsb0JvZHlcIiwgZmFsc2UsIFtcblx0XHRcdFx0XCJyZXR1cm4geyBtZXNzYWdlOiBib2R5Lm1lc3NhZ2UgfTtcIixcblx0XHRcdF0pLFxuXHRcdF0sXG5cdFx0W1xuXHRcdFx0XCJ1cGRhdGVcIixcblx0XHRcdG5ldyBDb250cm9sbGVyTWV0aG9kKFxuXHRcdFx0XHRcInVwZGF0ZVwiLFxuXHRcdFx0XHQnQFB1dChcIi86aWRcIiknLFxuXHRcdFx0XHQnQFBhcmFtKFwiaWRcIikgaWQ6IHN0cmluZywgYm9keTogSGVsbG9Cb2R5Jyxcblx0XHRcdFx0ZmFsc2UsXG5cdFx0XHRcdFtcInJldHVybiB7IGlkLCBtZXNzYWdlOiBib2R5Lm1lc3NhZ2UgfTtcIl0sXG5cdFx0XHQpLFxuXHRcdF0sXG5cdFx0W1xuXHRcdFx0XCJyZW1vdmVcIixcblx0XHRcdG5ldyBDb250cm9sbGVyTWV0aG9kKFwicmVtb3ZlXCIsICdARGVsZXRlKFwiLzppZFwiKScsICdAUGFyYW0oXCJpZFwiKSBpZDogc3RyaW5nJywgZmFsc2UsIFtcblx0XHRcdFx0XCJyZXR1cm4geyBpZCwgZGVsZXRlZDogdHJ1ZSB9O1wiLFxuXHRcdFx0XSksXG5cdFx0XSxcblx0XSk7XG5cblx0LyoqIFJldHJpZXZlIGEgbWV0aG9kIGJ5IG5hbWUgdG8gbXV0YXRlIGl0cyBkZWNvcmF0b3JzLiAqL1xuXHRwdWJsaWMgZ2V0TWV0aG9kKG5hbWU6IHN0cmluZyk6IENvbnRyb2xsZXJNZXRob2Qge1xuXHRcdGNvbnN0IG0gPSB0aGlzLl9tZXRob2RzLmdldChuYW1lKTtcblx0XHRpZiAobSA9PSBudWxsKSB0aHJvdyBuZXcgRXJyb3IoYE5vIG1ldGhvZCAnJHtuYW1lfScgb24gQ29udHJvbGxlclNvdXJjZUZpbGVgKTtcblx0XHRyZXR1cm4gbTtcblx0fVxuXG5cdC8qKiBBZGQgYSBjbGFzcy1sZXZlbCBkZWNvcmF0b3IgKGUuZy4gYEBBdXRob3JpemVgKS4gKi9cblx0cHVibGljIGFkZERlY29yYXRvcihkZWNvcmF0b3I6IHN0cmluZyk6IHRoaXMge1xuXHRcdHRoaXMuX2NsYXNzRGVjb3JhdG9ycy5wdXNoKGRlY29yYXRvcik7XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxuXHQvKiogQWRkIGEgbmFtZWQgaW1wb3J0IGZyb20gYEBkZWNvaGVyZS9jb3J0ZXhgLiAqL1xuXHRwdWJsaWMgYWRkQ29ydGV4SW1wb3J0KG5hbWU6IHN0cmluZywgdHlwZU9ubHkgPSBmYWxzZSk6IHRoaXMge1xuXHRcdHRoaXMuX2NvcnRleEltcG9ydHMuYWRkKG5hbWUsIHR5cGVPbmx5KTtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKiBBZGQgYSBuYW1lZCBpbXBvcnQgZnJvbSBhbnkgb3RoZXIgbW9kdWxlLiAqL1xuXHRwdWJsaWMgYWRkSW1wb3J0KG5hbWU6IHN0cmluZywgZnJvbTogc3RyaW5nLCB0eXBlT25seSA9IGZhbHNlKTogdGhpcyB7XG5cdFx0Y29uc3QgZ3JvdXAgPSB0aGlzLl9leHRyYUltcG9ydEdyb3Vwcy5nZXQoZnJvbSkgPz8gbmV3IEltcG9ydEdyb3VwKCk7XG5cdFx0Z3JvdXAuYWRkKG5hbWUsIHR5cGVPbmx5KTtcblx0XHR0aGlzLl9leHRyYUltcG9ydEdyb3Vwcy5zZXQoZnJvbSwgZ3JvdXApO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqIEFkZCBhIGNvbnN0cnVjdG9yIHBhcmFtZXRlciAoZS5nLiBhbiBpbmplY3RlZCBkZXBlbmRlbmN5KS4gKi9cblx0cHVibGljIGFkZENvbnN0cnVjdG9yUGFyYW0ocGFyYW06IHN0cmluZyk6IHRoaXMge1xuXHRcdHRoaXMuX2N0b3JQYXJhbXMucHVzaChwYXJhbSk7XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxuXHRwdWJsaWMgZmlsZXMoKTogU291cmNlRmlsZVtdIHtcblx0XHRjb25zdCBsaW5lczogc3RyaW5nW10gPSBbXG5cdFx0XHR0aGlzLl9jb3J0ZXhJbXBvcnRzLnJlbmRlcihcIkBkZWNvaGVyZS9jb3J0ZXhcIiksXG5cdFx0XHQnaW1wb3J0IHsgU2FtcGxlU2VydmljZSB9IGZyb20gXCIuLi9zZXJ2aWNlcy9zYW1wbGUuc2VydmljZS5qc1wiOycsXG5cdFx0XTtcblxuXHRcdGZvciAoY29uc3QgW2Zyb20sIGdyb3VwXSBvZiB0aGlzLl9leHRyYUltcG9ydEdyb3Vwcykge1xuXHRcdFx0bGluZXMucHVzaChncm91cC5yZW5kZXIoZnJvbSkpO1xuXHRcdH1cblxuXHRcdGxpbmVzLnB1c2goXG5cdFx0XHRcIlwiLFxuXHRcdFx0XCJjbGFzcyBIZWxsb0JvZHkge1wiLFxuXHRcdFx0J1xcdEBGaWVsZChcImJvZHlcIiwgXCJtZXNzYWdlXCIpJyxcblx0XHRcdFwiXFx0cHVibGljIG1lc3NhZ2UhOiBzdHJpbmc7XCIsXG5cdFx0XHRcIn1cIixcblx0XHRcdFwiXCIsXG5cdFx0KTtcblxuXHRcdGZvciAoY29uc3QgZCBvZiB0aGlzLl9jbGFzc0RlY29yYXRvcnMpIHtcblx0XHRcdGxpbmVzLnB1c2goZCk7XG5cdFx0fVxuXHRcdGxpbmVzLnB1c2goJ0BDb250cm9sbGVyKHsgcHJlZml4OiBcIi9oZWxsb1wiIH0pJywgXCJleHBvcnQgY2xhc3MgSGVsbG9Db250cm9sbGVyIHtcIiwgXCJcIik7XG5cblx0XHRsaW5lcy5wdXNoKFwiXFx0cHVibGljIGNvbnN0cnVjdG9yKFwiKTtcblx0XHRmb3IgKGNvbnN0IHAgb2YgdGhpcy5fY3RvclBhcmFtcykge1xuXHRcdFx0bGluZXMucHVzaChgXFx0XFx0JHtwfSxgKTtcblx0XHR9XG5cdFx0bGluZXMucHVzaChcIlxcdCkge31cIik7XG5cdFx0bGluZXMucHVzaChcIlwiKTtcblxuXHRcdGZvciAoY29uc3QgbWV0aG9kIG9mIHRoaXMuX21ldGhvZHMudmFsdWVzKCkpIHtcblx0XHRcdGxpbmVzLnB1c2goLi4ubWV0aG9kLnJlbmRlcigpLCBcIlwiKTtcblx0XHR9XG5cblx0XHRsaW5lcy5wdXNoKFwifVwiLCBcIlwiKTtcblxuXHRcdHJldHVybiBbXG5cdFx0XHR7XG5cdFx0XHRcdGZpbGVQYXRoOiBcInNyYy9jb250cm9sbGVycy9oZWxsby5jb250cm9sbGVyLnRzXCIsXG5cdFx0XHRcdGNvbnRlbnQ6IGxpbmVzLmpvaW4oXCJcXG5cIiksXG5cdFx0XHR9LFxuXHRcdF07XG5cdH1cbn1cbiJdLCJuYW1lcyI6WyJXRUxMX0tOT1dOX0ZJTEVTIiwiSW1wb3J0R3JvdXAiLCJfdmFsdWVzIiwiX3R5cGVzIiwiYWRkIiwibmFtZSIsInR5cGVPbmx5IiwiaW5jbHVkZXMiLCJwdXNoIiwidHlwZUlkeCIsImluZGV4T2YiLCJzcGxpY2UiLCJyZW5kZXIiLCJmcm9tIiwidmFsdWVzIiwic29ydCIsInR5cGVzIiwibWFwIiwibiIsImpvaW4iLCJDb250cm9sbGVyTWV0aG9kIiwiX2V4dHJhRGVjb3JhdG9ycyIsIl9ib2R5IiwiX2lzQXN5bmMiLCJfaHR0cERlY29yYXRvciIsIl9wYXJhbXMiLCJpc0FzeW5jIiwiYm9keSIsImFkZERlY29yYXRvciIsImRlY29yYXRvciIsInNldEJvZHkiLCJzZXRBc3luYyIsImxpbmVzIiwiZCIsImFzeW5jS3ciLCJsaW5lIiwiQ29udHJvbGxlclNvdXJjZUZpbGUiLCJrZXkiLCJDT05UUk9MTEVSX1RTIiwiX2NvcnRleEltcG9ydHMiLCJfZXh0cmFJbXBvcnRHcm91cHMiLCJNYXAiLCJfY2xhc3NEZWNvcmF0b3JzIiwiX2N0b3JQYXJhbXMiLCJfbWV0aG9kcyIsImdldE1ldGhvZCIsIm0iLCJnZXQiLCJFcnJvciIsImFkZENvcnRleEltcG9ydCIsImFkZEltcG9ydCIsImdyb3VwIiwic2V0IiwiYWRkQ29uc3RydWN0b3JQYXJhbSIsInBhcmFtIiwiZmlsZXMiLCJwIiwibWV0aG9kIiwiZmlsZVBhdGgiLCJjb250ZW50Il0sIm1hcHBpbmdzIjoiQUFBQSxTQUFTQSxnQkFBZ0IsUUFBUSx3QkFBd0I7QUFHekQsaUZBQWlGLEdBQ2pGLE1BQU1DO0lBQ1lDLFVBQW9CLEVBQUUsQ0FBQztJQUN2QkMsU0FBbUIsRUFBRSxDQUFDO0lBRWhDQyxJQUFJQyxJQUFZLEVBQUVDLFdBQVcsS0FBSyxFQUFRO1FBQ2hELElBQUlBLFVBQVU7WUFDYixrREFBa0Q7WUFDbEQsSUFBSSxDQUFDLElBQUksQ0FBQ0osT0FBTyxDQUFDSyxRQUFRLENBQUNGLFNBQVMsQ0FBQyxJQUFJLENBQUNGLE1BQU0sQ0FBQ0ksUUFBUSxDQUFDRixPQUFPO2dCQUNoRSxJQUFJLENBQUNGLE1BQU0sQ0FBQ0ssSUFBSSxDQUFDSDtZQUNsQjtRQUNELE9BQU87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
|