@decohere/create 0.0.1-dev.48 → 0.0.1-dev.49

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.
Files changed (124) hide show
  1. package/commonjs/src/cli.js +3 -3
  2. package/commonjs/src/resolve-launch.js +53 -0
  3. package/commonjs/src/runner.js +5 -45
  4. package/commonjs/src/version.js +1 -1
  5. package/es6/src/cli.js +3 -3
  6. package/es6/src/resolve-launch.js +46 -0
  7. package/es6/src/runner.js +8 -57
  8. package/es6/src/version.js +3 -3
  9. package/pack-builder-tgz.mjs +1 -1
  10. package/package.json +4 -11
  11. package/types/src/resolve-launch.d.ts +10 -0
  12. package/types/src/runner.d.ts +3 -13
  13. package/types/src/version.d.ts +0 -2
  14. package/commonjs/src/domain/prompt.js +0 -64
  15. package/commonjs/src/models/compose.model.js +0 -138
  16. package/commonjs/src/models/config-yaml.model.js +0 -88
  17. package/commonjs/src/models/const.js +0 -31
  18. package/commonjs/src/models/dev-container.model.js +0 -100
  19. package/commonjs/src/models/docker-image.model.js +0 -221
  20. package/commonjs/src/models/env-file.model.js +0 -47
  21. package/commonjs/src/models/gitignore.model.js +0 -31
  22. package/commonjs/src/models/launch-json.model.js +0 -74
  23. package/commonjs/src/models/package-json.model.js +0 -133
  24. package/commonjs/src/models/project.model.js +0 -134
  25. package/commonjs/src/models/source-file.js +0 -6
  26. package/commonjs/src/models/tsconfig.model.js +0 -34
  27. package/commonjs/src/models/vscode-settings.model.js +0 -31
  28. package/commonjs/src/program.js +0 -135
  29. package/commonjs/src/resolve-target-dir.js +0 -19
  30. package/commonjs/src/services/scaffold.service.js +0 -62
  31. package/commonjs/src/webapi/api-name.js +0 -95
  32. package/commonjs/src/webapi/const.js +0 -50
  33. package/commonjs/src/webapi/create-api.js +0 -285
  34. package/commonjs/src/webapi/features/auth.feature.js +0 -463
  35. package/commonjs/src/webapi/features/auth0-cli.js +0 -406
  36. package/commonjs/src/webapi/features/biome-format.js +0 -49
  37. package/commonjs/src/webapi/features/database.feature.js +0 -273
  38. package/commonjs/src/webapi/features/finalize.feature.js +0 -91
  39. package/commonjs/src/webapi/features/postman.feature.js +0 -319
  40. package/commonjs/src/webapi/models/api-package-json.model.js +0 -63
  41. package/commonjs/src/webapi/models/auth-config.model.js +0 -26
  42. package/commonjs/src/webapi/models/controller-source-file.model.js +0 -188
  43. package/commonjs/src/webapi/models/github-ci.model.js +0 -193
  44. package/commonjs/src/webapi/models/main-source-file.model.js +0 -165
  45. package/commonjs/src/webapi/models/production-dockerfile.model.js +0 -138
  46. package/commonjs/src/webapi/models/sample-files.model.js +0 -60
  47. package/commonjs/src/webapi/models/webapi-image.model.js +0 -22
  48. package/commonjs/src/webapi/postman/hello-openapi.js +0 -175
  49. package/commonjs/src/webapi/postman/local-view.js +0 -184
  50. package/commonjs/src/webapi/postman/openapi-to-postman.js +0 -202
  51. package/es6/src/domain/prompt.js +0 -43
  52. package/es6/src/models/compose.model.js +0 -132
  53. package/es6/src/models/config-yaml.model.js +0 -76
  54. package/es6/src/models/const.js +0 -21
  55. package/es6/src/models/dev-container.model.js +0 -90
  56. package/es6/src/models/docker-image.model.js +0 -185
  57. package/es6/src/models/env-file.model.js +0 -43
  58. package/es6/src/models/gitignore.model.js +0 -21
  59. package/es6/src/models/launch-json.model.js +0 -64
  60. package/es6/src/models/package-json.model.js +0 -129
  61. package/es6/src/models/project.model.js +0 -119
  62. package/es6/src/models/source-file.js +0 -3
  63. package/es6/src/models/tsconfig.model.js +0 -24
  64. package/es6/src/models/vscode-settings.model.js +0 -21
  65. package/es6/src/program.js +0 -76
  66. package/es6/src/resolve-target-dir.js +0 -9
  67. package/es6/src/services/scaffold.service.js +0 -52
  68. package/es6/src/webapi/api-name.js +0 -59
  69. package/es6/src/webapi/const.js +0 -20
  70. package/es6/src/webapi/create-api.js +0 -265
  71. package/es6/src/webapi/features/auth.feature.js +0 -412
  72. package/es6/src/webapi/features/auth0-cli.js +0 -348
  73. package/es6/src/webapi/features/biome-format.js +0 -42
  74. package/es6/src/webapi/features/database.feature.js +0 -263
  75. package/es6/src/webapi/features/finalize.feature.js +0 -81
  76. package/es6/src/webapi/features/postman.feature.js +0 -253
  77. package/es6/src/webapi/models/api-package-json.model.js +0 -58
  78. package/es6/src/webapi/models/auth-config.model.js +0 -22
  79. package/es6/src/webapi/models/controller-source-file.model.js +0 -179
  80. package/es6/src/webapi/models/github-ci.model.js +0 -186
  81. package/es6/src/webapi/models/main-source-file.model.js +0 -161
  82. package/es6/src/webapi/models/production-dockerfile.model.js +0 -126
  83. package/es6/src/webapi/models/sample-files.model.js +0 -42
  84. package/es6/src/webapi/models/webapi-image.model.js +0 -12
  85. package/es6/src/webapi/postman/hello-openapi.js +0 -168
  86. package/es6/src/webapi/postman/local-view.js +0 -169
  87. package/es6/src/webapi/postman/openapi-to-postman.js +0 -179
  88. package/types/src/domain/prompt.d.ts +0 -4
  89. package/types/src/models/compose.model.d.ts +0 -59
  90. package/types/src/models/config-yaml.model.d.ts +0 -27
  91. package/types/src/models/const.d.ts +0 -19
  92. package/types/src/models/dev-container.model.d.ts +0 -33
  93. package/types/src/models/docker-image.model.d.ts +0 -56
  94. package/types/src/models/env-file.model.d.ts +0 -15
  95. package/types/src/models/gitignore.model.d.ts +0 -6
  96. package/types/src/models/launch-json.model.d.ts +0 -7
  97. package/types/src/models/package-json.model.d.ts +0 -32
  98. package/types/src/models/project.model.d.ts +0 -60
  99. package/types/src/models/source-file.d.ts +0 -11
  100. package/types/src/models/tsconfig.model.d.ts +0 -5
  101. package/types/src/models/vscode-settings.model.d.ts +0 -7
  102. package/types/src/program.d.ts +0 -3
  103. package/types/src/resolve-target-dir.d.ts +0 -5
  104. package/types/src/services/scaffold.service.d.ts +0 -22
  105. package/types/src/webapi/api-name.d.ts +0 -14
  106. package/types/src/webapi/const.d.ts +0 -17
  107. package/types/src/webapi/create-api.d.ts +0 -15
  108. package/types/src/webapi/features/auth.feature.d.ts +0 -10
  109. package/types/src/webapi/features/auth0-cli.d.ts +0 -72
  110. package/types/src/webapi/features/biome-format.d.ts +0 -5
  111. package/types/src/webapi/features/database.feature.d.ts +0 -5
  112. package/types/src/webapi/features/finalize.feature.d.ts +0 -2
  113. package/types/src/webapi/features/postman.feature.d.ts +0 -16
  114. package/types/src/webapi/models/api-package-json.model.d.ts +0 -18
  115. package/types/src/webapi/models/auth-config.model.d.ts +0 -26
  116. package/types/src/webapi/models/controller-source-file.model.d.ts +0 -45
  117. package/types/src/webapi/models/github-ci.model.d.ts +0 -9
  118. package/types/src/webapi/models/main-source-file.model.d.ts +0 -54
  119. package/types/src/webapi/models/production-dockerfile.model.d.ts +0 -20
  120. package/types/src/webapi/models/sample-files.model.d.ts +0 -7
  121. package/types/src/webapi/models/webapi-image.model.d.ts +0 -5
  122. package/types/src/webapi/postman/hello-openapi.d.ts +0 -19
  123. package/types/src/webapi/postman/local-view.d.ts +0 -17
  124. 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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