@decohere/create 0.0.1-dev.23 → 0.0.1-dev.25

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 (36) hide show
  1. package/commonjs/src/models/compose.model.js +56 -4
  2. package/commonjs/src/models/dev-container.model.js +29 -2
  3. package/commonjs/src/models/package-json.model.js +11 -6
  4. package/commonjs/src/runner.js +26 -2
  5. package/commonjs/src/webapi/create-api.js +66 -5
  6. package/commonjs/src/webapi/features/auth.feature.js +288 -7
  7. package/commonjs/src/webapi/features/auth0-cli.js +256 -9
  8. package/commonjs/src/webapi/features/database.feature.js +56 -24
  9. package/commonjs/src/webapi/features/postman.feature.js +337 -48
  10. package/commonjs/src/webapi/models/api-package-json.model.js +4 -1
  11. package/commonjs/src/webapi/models/auth-config.model.js +4 -1
  12. package/commonjs/src/webapi/models/controller-source-file.model.js +16 -8
  13. package/commonjs/src/webapi/models/main-source-file.model.js +28 -4
  14. package/es6/src/models/compose.model.js +57 -6
  15. package/es6/src/models/dev-container.model.js +30 -8
  16. package/es6/src/models/package-json.model.js +11 -6
  17. package/es6/src/runner.js +27 -3
  18. package/es6/src/webapi/create-api.js +66 -5
  19. package/es6/src/webapi/features/auth.feature.js +288 -7
  20. package/es6/src/webapi/features/auth0-cli.js +230 -9
  21. package/es6/src/webapi/features/database.feature.js +56 -24
  22. package/es6/src/webapi/features/postman.feature.js +324 -45
  23. package/es6/src/webapi/models/api-package-json.model.js +4 -1
  24. package/es6/src/webapi/models/auth-config.model.js +4 -1
  25. package/es6/src/webapi/models/controller-source-file.model.js +16 -8
  26. package/es6/src/webapi/models/main-source-file.model.js +28 -4
  27. package/package.json +2 -2
  28. package/types/src/models/compose.model.d.ts +27 -2
  29. package/types/src/models/dev-container.model.d.ts +12 -0
  30. package/types/src/models/package-json.model.d.ts +2 -0
  31. package/types/src/webapi/features/auth.feature.d.ts +3 -0
  32. package/types/src/webapi/features/auth0-cli.d.ts +50 -3
  33. package/types/src/webapi/features/postman.feature.d.ts +5 -0
  34. package/types/src/webapi/models/auth-config.model.d.ts +8 -0
  35. package/types/src/webapi/models/controller-source-file.model.d.ts +6 -3
  36. package/types/src/webapi/models/main-source-file.model.d.ts +12 -0
@@ -1,6 +1,26 @@
1
1
  import { execFileSync, spawnSync } from "node:child_process";
2
- const REQUIRED_SCOPES = "create:clients";
2
+ import { randomBytes } from "node:crypto";
3
+ /** Management API scopes needed for API, SPA, connections, and admin users. */ const REQUIRED_SCOPES = [
4
+ "create:clients",
5
+ "read:clients",
6
+ "update:clients",
7
+ "create:resource_servers",
8
+ "read:resource_servers",
9
+ "update:resource_servers",
10
+ "read:connections",
11
+ "update:connections",
12
+ "create:users",
13
+ "read:users",
14
+ "update:users"
15
+ ].join(",");
3
16
  /** Hard timeout for any Management API call. Prevents indefinite hangs on token re-auth. */ const API_TIMEOUT_MS = 8_000;
17
+ /** Default API scopes matching Hello CASL Authorize decorators. */ export const HELLO_API_SCOPES = [
18
+ "read:Hello",
19
+ "create:Hello",
20
+ "update:Hello",
21
+ "delete:Hello"
22
+ ];
23
+ export const DB_CONNECTION_NAME = "Username-Password-Authentication";
4
24
  export class Auth0AuthError extends Error {
5
25
  constructor(message){
6
26
  super(message);
@@ -10,6 +30,16 @@ export class Auth0AuthError extends Error {
10
30
  /** Returns true if an error or stderr output looks like an expired/missing token. */ function isAuthError(text) {
11
31
  return text.includes("renew access token") || text.includes("log in") || text.includes("Unauthorized");
12
32
  }
33
+ /** Strip Auth0 CLI banner lines before JSON. */ function parseJsonOutput(stdout) {
34
+ const start = stdout.indexOf("{");
35
+ const arrayStart = stdout.indexOf("[");
36
+ let idx = -1;
37
+ if (start === -1) idx = arrayStart;
38
+ else if (arrayStart === -1) idx = start;
39
+ else idx = Math.min(start, arrayStart);
40
+ if (idx < 0) throw new Error(`Expected JSON from auth0 CLI, got: ${stdout.slice(0, 200)}`);
41
+ return JSON.parse(stdout.slice(idx));
42
+ }
13
43
  /** Run an auth0 CLI command with a hard timeout. Returns stdout on success, throws on failure. */ function runAuth0(args) {
14
44
  const result = spawnSync("auth0", args, {
15
45
  encoding: "utf8",
@@ -18,7 +48,6 @@ export class Auth0AuthError extends Error {
18
48
  stdio: "pipe"
19
49
  });
20
50
  if (result.error) {
21
- // ETIMEDOUT means the process was killed by the timeout
22
51
  const msg = result.error.message;
23
52
  if (isAuthError(msg) || result.error.code === "ETIMEDOUT") {
24
53
  throw new Auth0AuthError(msg);
@@ -77,13 +106,13 @@ export function listApis() {
77
106
  "--json",
78
107
  "--no-input"
79
108
  ]);
80
- return JSON.parse(out);
109
+ return parseJsonOutput(out);
81
110
  } catch (err) {
82
111
  if (err instanceof Auth0AuthError) throw err;
83
112
  return [];
84
113
  }
85
114
  }
86
- export function createApi(name, identifier) {
115
+ export function createApi(name, identifier, scopes = HELLO_API_SCOPES) {
87
116
  const out = runAuth0([
88
117
  "apis",
89
118
  "create",
@@ -91,12 +120,25 @@ export function createApi(name, identifier) {
91
120
  name,
92
121
  "--identifier",
93
122
  identifier,
123
+ "--scopes",
124
+ scopes.join(","),
94
125
  "--json",
95
126
  "--no-input"
96
127
  ]);
97
- return JSON.parse(out);
128
+ return parseJsonOutput(out);
129
+ }
130
+ /** Replace an API's scopes (Auth0 CLI update --scopes replaces the full set). */ export function updateApiScopes(identifier, scopes = HELLO_API_SCOPES) {
131
+ runAuth0([
132
+ "apis",
133
+ "update",
134
+ identifier,
135
+ "--scopes",
136
+ scopes.join(","),
137
+ "--no-input"
138
+ ]);
98
139
  }
99
- export function createSpaApp(name, callbackUrl) {
140
+ export function createSpaApp(name, callbackUrls) {
141
+ const callbacks = typeof callbackUrls === "string" ? callbackUrls : callbackUrls.join(",");
100
142
  const out = runAuth0([
101
143
  "apps",
102
144
  "create",
@@ -105,12 +147,191 @@ export function createSpaApp(name, callbackUrl) {
105
147
  "--type",
106
148
  "spa",
107
149
  "--callbacks",
108
- callbackUrl,
150
+ callbacks,
109
151
  "--json",
110
152
  "--no-input"
111
153
  ]);
112
- return JSON.parse(out);
154
+ const app = parseJsonOutput(out);
155
+ const clientId = app.client_id ?? app.clientId;
156
+ if (!clientId) {
157
+ throw new Error(`Auth0 create SPA response missing client_id. stdout: ${out.slice(0, 300)}`);
158
+ }
159
+ return {
160
+ client_id: clientId
161
+ };
162
+ }
163
+ export function listApps() {
164
+ try {
165
+ const out = runAuth0([
166
+ "apps",
167
+ "list",
168
+ "--json",
169
+ "--no-input"
170
+ ]);
171
+ const apps = parseJsonOutput(out);
172
+ return apps.map((a)=>({
173
+ client_id: a.client_id ?? a.clientId ?? "",
174
+ name: a.name ?? ""
175
+ })).filter((a)=>a.client_id && a.name);
176
+ } catch (err) {
177
+ if (err instanceof Auth0AuthError) throw err;
178
+ return [];
179
+ }
180
+ }
181
+ export function updateSpaCallbacks(clientId, callbackUrls) {
182
+ const callbacks = typeof callbackUrls === "string" ? callbackUrls : callbackUrls.join(",");
183
+ runAuth0([
184
+ "apps",
185
+ "update",
186
+ clientId,
187
+ "--callbacks",
188
+ callbacks,
189
+ "--no-input"
190
+ ]);
191
+ }
192
+ /**
193
+ * Create a Postman SPA, or reuse an existing app with the same name (re-scaffold).
194
+ * Always returns a client_id suitable for Postman auth0ClientId.
195
+ */ export function ensureSpaApp(name, callbackUrls) {
196
+ const existing = listApps().find((a)=>a.name === name);
197
+ if (existing) {
198
+ try {
199
+ updateSpaCallbacks(existing.client_id, callbackUrls);
200
+ } catch {
201
+ // Callbacks may already match; still usable for Postman.
202
+ }
203
+ return {
204
+ client_id: existing.client_id,
205
+ reused: true
206
+ };
207
+ }
208
+ return {
209
+ ...createSpaApp(name, callbackUrls),
210
+ reused: false
211
+ };
212
+ }
213
+ /** Enable a database connection for an application (required for username/password login). */ export function enableConnectionForClient(connectionName, clientId) {
214
+ const listOut = runAuth0([
215
+ "api",
216
+ "get",
217
+ "connections",
218
+ "--no-input"
219
+ ]);
220
+ const connections = parseJsonOutput(listOut);
221
+ const connection = connections.find((c)=>c.name === connectionName);
222
+ if (!connection) {
223
+ throw new Error(`Auth0 connection not found: ${connectionName}`);
224
+ }
225
+ const clientsOut = runAuth0([
226
+ "api",
227
+ "get",
228
+ `connections/${connection.id}/clients`,
229
+ "--no-input"
230
+ ]);
231
+ const { clients } = parseJsonOutput(clientsOut);
232
+ if (clients.some((c)=>c.client_id === clientId)) return;
233
+ // Dedicated enabled-clients endpoint (enabled_clients on connection PATCH is deprecated).
234
+ runAuth0([
235
+ "api",
236
+ "patch",
237
+ `connections/${connection.id}/clients`,
238
+ "--data",
239
+ JSON.stringify([
240
+ {
241
+ client_id: clientId,
242
+ status: true
243
+ }
244
+ ]),
245
+ "--no-input"
246
+ ]);
247
+ }
248
+ /** Strong default password when the scaffolder caller leaves password blank. */ export function generateAdminPassword() {
249
+ return `${randomBytes(12).toString("base64url")}aA1!`;
250
+ }
251
+ function isUserAlreadyExistsError(err) {
252
+ const text = err instanceof Error ? err.message : String(err);
253
+ return /already exists|user exists|Conflict|409/i.test(text);
254
+ }
255
+ /** Look up a user by email (Management API users-by-email). */ export function findUserByEmail(email) {
256
+ const out = runAuth0([
257
+ "api",
258
+ "get",
259
+ `users-by-email?email=${encodeURIComponent(email)}`,
260
+ "--no-input"
261
+ ]);
262
+ const users = parseJsonOutput(out);
263
+ const user = users.find((u)=>u.user_id && u.email);
264
+ if (!user?.user_id || !user.email) return null;
265
+ return {
266
+ user_id: user.user_id,
267
+ email: user.email
268
+ };
269
+ }
270
+ /** Reset password so a re-scaffold can write a known password to .env. */ export function updateUserPassword(userId, password) {
271
+ runAuth0([
272
+ "api",
273
+ "patch",
274
+ `users/${encodeURIComponent(userId)}`,
275
+ "--data",
276
+ JSON.stringify({
277
+ password,
278
+ connection: DB_CONNECTION_NAME
279
+ }),
280
+ "--no-input"
281
+ ]);
282
+ }
283
+ /**
284
+ * Create a DB connection root-admin user for local / Postman login.
285
+ * If the user already exists, look them up, reset password to `input.password`,
286
+ * and return that identity so callers can still write .env credentials.
287
+ */ export function createAdminDatabaseUser(input) {
288
+ const body = {
289
+ email: input.email,
290
+ connection: DB_CONNECTION_NAME,
291
+ password: input.password,
292
+ name: input.username,
293
+ email_verified: true,
294
+ verify_email: false,
295
+ app_metadata: {
296
+ roles: [
297
+ "admin"
298
+ ]
299
+ }
300
+ };
301
+ try {
302
+ const out = runAuth0([
303
+ "api",
304
+ "post",
305
+ "users",
306
+ "--data",
307
+ JSON.stringify(body),
308
+ "--no-input"
309
+ ]);
310
+ const user = parseJsonOutput(out);
311
+ if (!user.user_id || !user.email) {
312
+ throw new Error(`Auth0 create user response missing user_id/email. stdout: ${out.slice(0, 300)}`);
313
+ }
314
+ return {
315
+ user_id: user.user_id,
316
+ email: user.email,
317
+ password: input.password,
318
+ username: input.username
319
+ };
320
+ } catch (err) {
321
+ if (!isUserAlreadyExistsError(err)) throw err;
322
+ const existing = findUserByEmail(input.email);
323
+ if (!existing) {
324
+ throw new Error(`Auth0 user already exists for ${input.email}, but lookup by email returned no user.`);
325
+ }
326
+ updateUserPassword(existing.user_id, input.password);
327
+ return {
328
+ user_id: existing.user_id,
329
+ email: existing.email,
330
+ password: input.password,
331
+ username: input.username
332
+ };
333
+ }
113
334
  }
114
335
  export { REQUIRED_SCOPES };
115
336
 
116
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL3J1bm5lci93b3JrL2RlY29oZXJlL2RlY29oZXJlL3Byb2plY3RzL2NyZWF0ZS9zcmMvd2ViYXBpL2ZlYXR1cmVzL2F1dGgwLWNsaS50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBleGVjRmlsZVN5bmMsIHNwYXduU3luYyB9IGZyb20gXCJub2RlOmNoaWxkX3Byb2Nlc3NcIjtcblxuY29uc3QgUkVRVUlSRURfU0NPUEVTID0gXCJjcmVhdGU6Y2xpZW50c1wiO1xuLyoqIEhhcmQgdGltZW91dCBmb3IgYW55IE1hbmFnZW1lbnQgQVBJIGNhbGwuIFByZXZlbnRzIGluZGVmaW5pdGUgaGFuZ3Mgb24gdG9rZW4gcmUtYXV0aC4gKi9cbmNvbnN0IEFQSV9USU1FT1VUX01TID0gOF8wMDA7XG5cbmV4cG9ydCBjbGFzcyBBdXRoMEF1dGhFcnJvciBleHRlbmRzIEVycm9yIHtcblx0cHVibGljIGNvbnN0cnVjdG9yKG1lc3NhZ2U6IHN0cmluZykge1xuXHRcdHN1cGVyKG1lc3NhZ2UpO1xuXHRcdHRoaXMubmFtZSA9IFwiQXV0aDBBdXRoRXJyb3JcIjtcblx0fVxufVxuXG4vKiogUmV0dXJucyB0cnVlIGlmIGFuIGVycm9yIG9yIHN0ZGVyciBvdXRwdXQgbG9va3MgbGlrZSBhbiBleHBpcmVkL21pc3NpbmcgdG9rZW4uICovXG5mdW5jdGlvbiBpc0F1dGhFcnJvcih0ZXh0OiBzdHJpbmcpOiBib29sZWFuIHtcblx0cmV0dXJuIChcblx0XHR0ZXh0LmluY2x1ZGVzKFwicmVuZXcgYWNjZXNzIHRva2VuXCIpIHx8XG5cdFx0dGV4dC5pbmNsdWRlcyhcImxvZyBpblwiKSB8fFxuXHRcdHRleHQuaW5jbHVkZXMoXCJVbmF1dGhvcml6ZWRcIilcblx0KTtcbn1cblxuLyoqIFJ1biBhbiBhdXRoMCBDTEkgY29tbWFuZCB3aXRoIGEgaGFyZCB0aW1lb3V0LiBSZXR1cm5zIHN0ZG91dCBvbiBzdWNjZXNzLCB0aHJvd3Mgb24gZmFpbHVyZS4gKi9cbmZ1bmN0aW9uIHJ1bkF1dGgwKGFyZ3M6IHN0cmluZ1tdKTogc3RyaW5nIHtcblx0Y29uc3QgcmVzdWx0ID0gc3Bhd25TeW5jKFwiYXV0aDBcIiwgYXJncywge1xuXHRcdGVuY29kaW5nOiBcInV0ZjhcIixcblx0XHR0aW1lb3V0OiBBUElfVElNRU9VVF9NUyxcblx0XHRpbnB1dDogXCJcIixcblx0XHRzdGRpbzogXCJwaXBlXCIsXG5cdH0pO1xuXG5cdGlmIChyZXN1bHQuZXJyb3IpIHtcblx0XHQvLyBFVElNRURPVVQgbWVhbnMgdGhlIHByb2Nlc3Mgd2FzIGtpbGxlZCBieSB0aGUgdGltZW91dFxuXHRcdGNvbnN0IG1zZyA9IHJlc3VsdC5lcnJvci5tZXNzYWdlO1xuXHRcdGlmIChpc0F1dGhFcnJvcihtc2cpIHx8IChyZXN1bHQuZXJyb3IgYXMgTm9kZUpTLkVycm5vRXhjZXB0aW9uKS5jb2RlID09PSBcIkVUSU1FRE9VVFwiKSB7XG5cdFx0XHR0aHJvdyBuZXcgQXV0aDBBdXRoRXJyb3IobXNnKTtcblx0XHR9XG5cdFx0dGhyb3cgcmVzdWx0LmVycm9yO1xuXHR9XG5cblx0aWYgKHJlc3VsdC5zdGF0dXMgIT09IDApIHtcblx0XHRjb25zdCBzdGRlcnIgPSByZXN1bHQuc3RkZXJyID8/IFwiXCI7XG5cdFx0aWYgKGlzQXV0aEVycm9yKHN0ZGVycikpIHRocm93IG5ldyBBdXRoMEF1dGhFcnJvcihzdGRlcnIpO1xuXHRcdHRocm93IG5ldyBFcnJvcihzdGRlcnIgfHwgYGF1dGgwIGV4aXRlZCB3aXRoIGNvZGUgJHtyZXN1bHQuc3RhdHVzfWApO1xuXHR9XG5cblx0cmV0dXJuIHJlc3VsdC5zdGRvdXQ7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQXV0aDBUZW5hbnQge1xuXHRuYW1lOiBzdHJpbmc7XG5cdGFjdGl2ZT86IGJvb2xlYW47XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpc0luc3RhbGxlZCgpOiBib29sZWFuIHtcblx0dHJ5IHtcblx0XHRleGVjRmlsZVN5bmMoXCJhdXRoMFwiLCBbXCItLXZlcnNpb25cIl0sIHsgc3RkaW86IFwicGlwZVwiIH0pO1xuXHRcdHJldHVybiB0cnVlO1xuXHR9IGNhdGNoIHtcblx0XHRyZXR1cm4gZmFsc2U7XG5cdH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGxpc3RUZW5hbnRzKCk6IEF1dGgwVGVuYW50W10ge1xuXHR0cnkge1xuXHRcdGNvbnN0IG91dCA9IGV4ZWNGaWxlU3luYyhcImF1dGgwXCIsIFtcInRlbmFudHNcIiwgXCJsaXN0XCIsIFwiLS1qc29uXCJdLCB7XG5cdFx0XHRlbmNvZGluZzogXCJ1dGY4XCIsXG5cdFx0XHRzdGRpbzogXCJwaXBlXCIsXG5cdFx0fSk7XG5cdFx0cmV0dXJuIEpTT04ucGFyc2Uob3V0KSBhcyBBdXRoMFRlbmFudFtdO1xuXHR9IGNhdGNoIHtcblx0XHRyZXR1cm4gW107XG5cdH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGxvZ2luKCk6IGJvb2xlYW4ge1xuXHRjb25zdCByZXN1bHQgPSBzcGF3blN5bmMoXCJhdXRoMFwiLCBbXCJsb2dpblwiLCBcIi0tc2NvcGVzXCIsIFJFUVVJUkVEX1NDT1BFU10sIHtcblx0XHRzdGRpbzogXCJpbmhlcml0XCIsXG5cdH0pO1xuXHRyZXR1cm4gcmVzdWx0LnN0YXR1cyA9PT0gMDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGxpc3RBcGlzKCk6IEFycmF5PHsgaWRlbnRpZmllcjogc3RyaW5nOyBuYW1lOiBzdHJpbmcgfT4ge1xuXHR0cnkge1xuXHRcdGNvbnN0IG91dCA9IHJ1bkF1dGgwKFtcImFwaXNcIiwgXCJsaXN0XCIsIFwiLS1qc29uXCIsIFwiLS1uby1pbnB1dFwiXSk7XG5cdFx0cmV0dXJuIEpTT04ucGFyc2Uob3V0KSBhcyBBcnJheTx7IGlkZW50aWZpZXI6IHN0cmluZzsgbmFtZTogc3RyaW5nIH0+O1xuXHR9IGNhdGNoIChlcnIpIHtcblx0XHRpZiAoZXJyIGluc3RhbmNlb2YgQXV0aDBBdXRoRXJyb3IpIHRocm93IGVycjtcblx0XHRyZXR1cm4gW107XG5cdH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZUFwaShuYW1lOiBzdHJpbmcsIGlkZW50aWZpZXI6IHN0cmluZyk6IHsgaWRlbnRpZmllcjogc3RyaW5nIH0ge1xuXHRjb25zdCBvdXQgPSBydW5BdXRoMChbXG5cdFx0XCJhcGlzXCIsXG5cdFx0XCJjcmVhdGVcIixcblx0XHRcIi0tbmFtZVwiLFxuXHRcdG5hbWUsXG5cdFx0XCItLWlkZW50aWZpZXJcIixcblx0XHRpZGVudGlmaWVyLFxuXHRcdFwiLS1qc29uXCIsXG5cdFx0XCItLW5vLWlucHV0XCIsXG5cdF0pO1xuXHRyZXR1cm4gSlNPTi5wYXJzZShvdXQpIGFzIHsgaWRlbnRpZmllcjogc3RyaW5nIH07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVTcGFBcHAobmFtZTogc3RyaW5nLCBjYWxsYmFja1VybDogc3RyaW5nKTogeyBjbGllbnRfaWQ6IHN0cmluZyB9IHtcblx0Y29uc3Qgb3V0ID0gcnVuQXV0aDAoW1xuXHRcdFwiYXBwc1wiLFxuXHRcdFwiY3JlYXRlXCIsXG5cdFx0XCItLW5hbWVcIixcblx0XHRuYW1lLFxuXHRcdFwiLS10eXBlXCIsXG5cdFx0XCJzcGFcIixcblx0XHRcIi0tY2FsbGJhY2tzXCIsXG5cdFx0Y2FsbGJhY2tVcmwsXG5cdFx0XCItLWpzb25cIixcblx0XHRcIi0tbm8taW5wdXRcIixcblx0XSk7XG5cdHJldHVybiBKU09OLnBhcnNlKG91dCkgYXMgeyBjbGllbnRfaWQ6IHN0cmluZyB9O1xufVxuXG5leHBvcnQgeyBSRVFVSVJFRF9TQ09QRVMgfTtcbiJdLCJuYW1lcyI6WyJleGVjRmlsZVN5bmMiLCJzcGF3blN5bmMiLCJSRVFVSVJFRF9TQ09QRVMiLCJBUElfVElNRU9VVF9NUyIsIkF1dGgwQXV0aEVycm9yIiwiRXJyb3IiLCJtZXNzYWdlIiwibmFtZSIsImlzQXV0aEVycm9yIiwidGV4dCIsImluY2x1ZGVzIiwicnVuQXV0aDAiLCJhcmdzIiwicmVzdWx0IiwiZW5jb2RpbmciLCJ0aW1lb3V0IiwiaW5wdXQiLCJzdGRpbyIsImVycm9yIiwibXNnIiwiY29kZSIsInN0YXR1cyIsInN0ZGVyciIsInN0ZG91dCIsImlzSW5zdGFsbGVkIiwibGlzdFRlbmFudHMiLCJvdXQiLCJKU09OIiwicGFyc2UiLCJsb2dpbiIsImxpc3RBcGlzIiwiZXJyIiwiY3JlYXRlQXBpIiwiaWRlbnRpZmllciIsImNyZWF0ZVNwYUFwcCIsImNhbGxiYWNrVXJsIl0sIm1hcHBpbmdzIjoiQUFBQSxTQUFTQSxZQUFZLEVBQUVDLFNBQVMsUUFBUSxxQkFBcUI7QUFFN0QsTUFBTUMsa0JBQWtCO0FBQ3hCLDBGQUEwRixHQUMxRixNQUFNQyxpQkFBaUI7QUFFdkIsT0FBTyxNQUFNQyx1QkFBdUJDO0lBQ25DLFlBQW1CQyxPQUFlLENBQUU7UUFDbkMsS0FBSyxDQUFDQTtRQUNOLElBQUksQ0FBQ0MsSUFBSSxHQUFHO0lBQ2I7QUFDRDtBQUVBLG1GQUFtRixHQUNuRixTQUFTQyxZQUFZQyxJQUFZO0lBQ2hDLE9BQ0NBLEtBQUtDLFFBQVEsQ0FBQyx5QkFDZEQsS0FBS0MsUUFBUSxDQUFDLGFBQ2RELEtBQUtDLFFBQVEsQ0FBQztBQUVoQjtBQUVBLGdHQUFnRyxHQUNoRyxTQUFTQyxTQUFTQyxJQUFjO0lBQy9CLE1BQU1DLFNBQVNaLFVBQVUsU0FBU1csTUFBTTtRQUN2Q0UsVUFBVTtRQUNWQyxTQUFTWjtRQUNUYSxPQUFPO1FBQ1BDLE9BQU87SUFDUjtJQUVBLElBQUlKLE9BQU9LLEtBQUssRUFBRTtRQUNqQix3REFBd0Q7UUFDeEQsTUFBTUMsTUFBTU4sT0FBT0ssS0FBSyxDQUFDWixPQUFPO1FBQ2hDLElBQUlFLFlBQVlXLFFBQVEsQUFBQ04sT0FBT0ssS0FBSyxDQUEyQkUsSUFBSSxLQUFLLGFBQWE7WUFDckYsTUFBTSxJQUFJaEIsZUFBZWU7UUFDMUI7UUFDQSxNQUFNTixPQUFPSyxLQUFLO0lBQ25CO0lBRUEsSUFBSUwsT0FBT1EsTUFBTSxLQUFLLEdBQUc7UUFDeEIsTUFBTUMsU0FBU1QsT0FBT1MsTUFBTSxJQUFJO1FBQ2hDLElBQUlkLFlBQVljLFNBQVMsTUFBTSxJQUFJbEIsZUFBZWtCO1FBQ2xELE1BQU0sSUFBSWpCLE1BQU1pQixVQUFVLENBQUMsdUJBQXVCLEVBQUVULE9BQU9RLE1BQU0sRUFBRTtJQUNwRTtJQUVBLE9BQU9SLE9BQU9VLE1BQU07QUFDckI7QUFPQSxPQUFPLFNBQVNDO0lBQ2YsSUFBSTtRQUNIeEIsYUFBYSxTQUFTO1lBQUM7U0FBWSxFQUFFO1lBQUVpQixPQUFPO1FBQU87UUFDckQsT0FBTztJQUNSLEVBQUUsT0FBTTtRQUNQLE9BQU87SUFDUjtBQUNEO0FBRUEsT0FBTyxTQUFTUTtJQUNmLElBQUk7UUFDSCxNQUFNQyxNQUFNMUIsYUFBYSxTQUFTO1lBQUM7WUFBVztZQUFRO1NBQVMsRUFBRTtZQUNoRWMsVUFBVTtZQUNWRyxPQUFPO1FBQ1I7UUFDQSxPQUFPVSxLQUFLQyxLQUFLLENBQUNGO0lBQ25CLEVBQUUsT0FBTTtRQUNQLE9BQU8sRUFBRTtJQUNWO0FBQ0Q7QUFFQSxPQUFPLFNBQVNHO0lBQ2YsTUFBTWhCLFNBQVNaLFVBQVUsU0FBUztRQUFDO1FBQVM7UUFBWUM7S0FBZ0IsRUFBRTtRQUN6RWUsT0FBTztJQUNSO0lBQ0EsT0FBT0osT0FBT1EsTUFBTSxLQUFLO0FBQzFCO0FBRUEsT0FBTyxTQUFTUztJQUNmLElBQUk7UUFDSCxNQUFNSixNQUFNZixTQUFTO1lBQUM7WUFBUTtZQUFRO1lBQVU7U0FBYTtRQUM3RCxPQUFPZ0IsS0FBS0MsS0FBSyxDQUFDRjtJQUNuQixFQUFFLE9BQU9LLEtBQUs7UUFDYixJQUFJQSxlQUFlM0IsZ0JBQWdCLE1BQU0yQjtRQUN6QyxPQUFPLEVBQUU7SUFDVjtBQUNEO0FBRUEsT0FBTyxTQUFTQyxVQUFVekIsSUFBWSxFQUFFMEIsVUFBa0I7SUFDekQsTUFBTVAsTUFBTWYsU0FBUztRQUNwQjtRQUNBO1FBQ0E7UUFDQUo7UUFDQTtRQUNBMEI7UUFDQTtRQUNBO0tBQ0E7SUFDRCxPQUFPTixLQUFLQyxLQUFLLENBQUNGO0FBQ25CO0FBRUEsT0FBTyxTQUFTUSxhQUFhM0IsSUFBWSxFQUFFNEIsV0FBbUI7SUFDN0QsTUFBTVQsTUFBTWYsU0FBUztRQUNwQjtRQUNBO1FBQ0E7UUFDQUo7UUFDQTtRQUNBO1FBQ0E7UUFDQTRCO1FBQ0E7UUFDQTtLQUNBO0lBQ0QsT0FBT1IsS0FBS0MsS0FBSyxDQUFDRjtBQUNuQjtBQUVBLFNBQVN4QixlQUFlLEdBQUcifQ==
337
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL3J1bm5lci93b3JrL2RlY29oZXJlL2RlY29oZXJlL3Byb2plY3RzL2NyZWF0ZS9zcmMvd2ViYXBpL2ZlYXR1cmVzL2F1dGgwLWNsaS50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBleGVjRmlsZVN5bmMsIHNwYXduU3luYyB9IGZyb20gXCJub2RlOmNoaWxkX3Byb2Nlc3NcIjtcbmltcG9ydCB7IHJhbmRvbUJ5dGVzIH0gZnJvbSBcIm5vZGU6Y3J5cHRvXCI7XG5cbi8qKiBNYW5hZ2VtZW50IEFQSSBzY29wZXMgbmVlZGVkIGZvciBBUEksIFNQQSwgY29ubmVjdGlvbnMsIGFuZCBhZG1pbiB1c2Vycy4gKi9cbmNvbnN0IFJFUVVJUkVEX1NDT1BFUyA9IFtcblx0XCJjcmVhdGU6Y2xpZW50c1wiLFxuXHRcInJlYWQ6Y2xpZW50c1wiLFxuXHRcInVwZGF0ZTpjbGllbnRzXCIsXG5cdFwiY3JlYXRlOnJlc291cmNlX3NlcnZlcnNcIixcblx0XCJyZWFkOnJlc291cmNlX3NlcnZlcnNcIixcblx0XCJ1cGRhdGU6cmVzb3VyY2Vfc2VydmVyc1wiLFxuXHRcInJlYWQ6Y29ubmVjdGlvbnNcIixcblx0XCJ1cGRhdGU6Y29ubmVjdGlvbnNcIixcblx0XCJjcmVhdGU6dXNlcnNcIixcblx0XCJyZWFkOnVzZXJzXCIsXG5cdFwidXBkYXRlOnVzZXJzXCIsXG5dLmpvaW4oXCIsXCIpO1xuXG4vKiogSGFyZCB0aW1lb3V0IGZvciBhbnkgTWFuYWdlbWVudCBBUEkgY2FsbC4gUHJldmVudHMgaW5kZWZpbml0ZSBoYW5ncyBvbiB0b2tlbiByZS1hdXRoLiAqL1xuY29uc3QgQVBJX1RJTUVPVVRfTVMgPSA4XzAwMDtcblxuLyoqIERlZmF1bHQgQVBJIHNjb3BlcyBtYXRjaGluZyBIZWxsbyBDQVNMIEF1dGhvcml6ZSBkZWNvcmF0b3JzLiAqL1xuZXhwb3J0IGNvbnN0IEhFTExPX0FQSV9TQ09QRVMgPSBbXG5cdFwicmVhZDpIZWxsb1wiLFxuXHRcImNyZWF0ZTpIZWxsb1wiLFxuXHRcInVwZGF0ZTpIZWxsb1wiLFxuXHRcImRlbGV0ZTpIZWxsb1wiLFxuXSBhcyBjb25zdDtcblxuZXhwb3J0IGNvbnN0IERCX0NPTk5FQ1RJT05fTkFNRSA9IFwiVXNlcm5hbWUtUGFzc3dvcmQtQXV0aGVudGljYXRpb25cIjtcblxuZXhwb3J0IGNsYXNzIEF1dGgwQXV0aEVycm9yIGV4dGVuZHMgRXJyb3Ige1xuXHRwdWJsaWMgY29uc3RydWN0b3IobWVzc2FnZTogc3RyaW5nKSB7XG5cdFx0c3VwZXIobWVzc2FnZSk7XG5cdFx0dGhpcy5uYW1lID0gXCJBdXRoMEF1dGhFcnJvclwiO1xuXHR9XG59XG5cbi8qKiBSZXR1cm5zIHRydWUgaWYgYW4gZXJyb3Igb3Igc3RkZXJyIG91dHB1dCBsb29rcyBsaWtlIGFuIGV4cGlyZWQvbWlzc2luZyB0b2tlbi4gKi9cbmZ1bmN0aW9uIGlzQXV0aEVycm9yKHRleHQ6IHN0cmluZyk6IGJvb2xlYW4ge1xuXHRyZXR1cm4gKFxuXHRcdHRleHQuaW5jbHVkZXMoXCJyZW5ldyBhY2Nlc3MgdG9rZW5cIikgfHxcblx0XHR0ZXh0LmluY2x1ZGVzKFwibG9nIGluXCIpIHx8XG5cdFx0dGV4dC5pbmNsdWRlcyhcIlVuYXV0aG9yaXplZFwiKVxuXHQpO1xufVxuXG4vKiogU3RyaXAgQXV0aDAgQ0xJIGJhbm5lciBsaW5lcyBiZWZvcmUgSlNPTi4gKi9cbmZ1bmN0aW9uIHBhcnNlSnNvbk91dHB1dDxUPihzdGRvdXQ6IHN0cmluZyk6IFQge1xuXHRjb25zdCBzdGFydCA9IHN0ZG91dC5pbmRleE9mKFwie1wiKTtcblx0Y29uc3QgYXJyYXlTdGFydCA9IHN0ZG91dC5pbmRleE9mKFwiW1wiKTtcblx0bGV0IGlkeCA9IC0xO1xuXHRpZiAoc3RhcnQgPT09IC0xKSBpZHggPSBhcnJheVN0YXJ0O1xuXHRlbHNlIGlmIChhcnJheVN0YXJ0ID09PSAtMSkgaWR4ID0gc3RhcnQ7XG5cdGVsc2UgaWR4ID0gTWF0aC5taW4oc3RhcnQsIGFycmF5U3RhcnQpO1xuXHRpZiAoaWR4IDwgMCkgdGhyb3cgbmV3IEVycm9yKGBFeHBlY3RlZCBKU09OIGZyb20gYXV0aDAgQ0xJLCBnb3Q6ICR7c3Rkb3V0LnNsaWNlKDAsIDIwMCl9YCk7XG5cdHJldHVybiBKU09OLnBhcnNlKHN0ZG91dC5zbGljZShpZHgpKSBhcyBUO1xufVxuXG4vKiogUnVuIGFuIGF1dGgwIENMSSBjb21tYW5kIHdpdGggYSBoYXJkIHRpbWVvdXQuIFJldHVybnMgc3Rkb3V0IG9uIHN1Y2Nlc3MsIHRocm93cyBvbiBmYWlsdXJlLiAqL1xuZnVuY3Rpb24gcnVuQXV0aDAoYXJnczogc3RyaW5nW10pOiBzdHJpbmcge1xuXHRjb25zdCByZXN1bHQgPSBzcGF3blN5bmMoXCJhdXRoMFwiLCBhcmdzLCB7XG5cdFx0ZW5jb2Rpbmc6IFwidXRmOFwiLFxuXHRcdHRpbWVvdXQ6IEFQSV9USU1FT1VUX01TLFxuXHRcdGlucHV0OiBcIlwiLFxuXHRcdHN0ZGlvOiBcInBpcGVcIixcblx0fSk7XG5cblx0aWYgKHJlc3VsdC5lcnJvcikge1xuXHRcdGNvbnN0IG1zZyA9IHJlc3VsdC5lcnJvci5tZXNzYWdlO1xuXHRcdGlmIChpc0F1dGhFcnJvcihtc2cpIHx8IChyZXN1bHQuZXJyb3IgYXMgTm9kZUpTLkVycm5vRXhjZXB0aW9uKS5jb2RlID09PSBcIkVUSU1FRE9VVFwiKSB7XG5cdFx0XHR0aHJvdyBuZXcgQXV0aDBBdXRoRXJyb3IobXNnKTtcblx0XHR9XG5cdFx0dGhyb3cgcmVzdWx0LmVycm9yO1xuXHR9XG5cblx0aWYgKHJlc3VsdC5zdGF0dXMgIT09IDApIHtcblx0XHRjb25zdCBzdGRlcnIgPSByZXN1bHQuc3RkZXJyID8/IFwiXCI7XG5cdFx0aWYgKGlzQXV0aEVycm9yKHN0ZGVycikpIHRocm93IG5ldyBBdXRoMEF1dGhFcnJvcihzdGRlcnIpO1xuXHRcdHRocm93IG5ldyBFcnJvcihzdGRlcnIgfHwgYGF1dGgwIGV4aXRlZCB3aXRoIGNvZGUgJHtyZXN1bHQuc3RhdHVzfWApO1xuXHR9XG5cblx0cmV0dXJuIHJlc3VsdC5zdGRvdXQ7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQXV0aDBUZW5hbnQge1xuXHRuYW1lOiBzdHJpbmc7XG5cdGFjdGl2ZT86IGJvb2xlYW47XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpc0luc3RhbGxlZCgpOiBib29sZWFuIHtcblx0dHJ5IHtcblx0XHRleGVjRmlsZVN5bmMoXCJhdXRoMFwiLCBbXCItLXZlcnNpb25cIl0sIHsgc3RkaW86IFwicGlwZVwiIH0pO1xuXHRcdHJldHVybiB0cnVlO1xuXHR9IGNhdGNoIHtcblx0XHRyZXR1cm4gZmFsc2U7XG5cdH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGxpc3RUZW5hbnRzKCk6IEF1dGgwVGVuYW50W10ge1xuXHR0cnkge1xuXHRcdGNvbnN0IG91dCA9IGV4ZWNGaWxlU3luYyhcImF1dGgwXCIsIFtcInRlbmFudHNcIiwgXCJsaXN0XCIsIFwiLS1qc29uXCJdLCB7XG5cdFx0XHRlbmNvZGluZzogXCJ1dGY4XCIsXG5cdFx0XHRzdGRpbzogXCJwaXBlXCIsXG5cdFx0fSk7XG5cdFx0cmV0dXJuIEpTT04ucGFyc2Uob3V0KSBhcyBBdXRoMFRlbmFudFtdO1xuXHR9IGNhdGNoIHtcblx0XHRyZXR1cm4gW107XG5cdH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGxvZ2luKCk6IGJvb2xlYW4ge1xuXHRjb25zdCByZXN1bHQgPSBzcGF3blN5bmMoXCJhdXRoMFwiLCBbXCJsb2dpblwiLCBcIi0tc2NvcGVzXCIsIFJFUVVJUkVEX1NDT1BFU10sIHtcblx0XHRzdGRpbzogXCJpbmhlcml0XCIsXG5cdH0pO1xuXHRyZXR1cm4gcmVzdWx0LnN0YXR1cyA9PT0gMDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGxpc3RBcGlzKCk6IEFycmF5PHsgaWRlbnRpZmllcjogc3RyaW5nOyBuYW1lOiBzdHJpbmcgfT4ge1xuXHR0cnkge1xuXHRcdGNvbnN0IG91dCA9IHJ1bkF1dGgwKFtcImFwaXNcIiwgXCJsaXN0XCIsIFwiLS1qc29uXCIsIFwiLS1uby1pbnB1dFwiXSk7XG5cdFx0cmV0dXJuIHBhcnNlSnNvbk91dHB1dChvdXQpO1xuXHR9IGNhdGNoIChlcnIpIHtcblx0XHRpZiAoZXJyIGluc3RhbmNlb2YgQXV0aDBBdXRoRXJyb3IpIHRocm93IGVycjtcblx0XHRyZXR1cm4gW107XG5cdH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZUFwaShcblx0bmFtZTogc3RyaW5nLFxuXHRpZGVudGlmaWVyOiBzdHJpbmcsXG5cdHNjb3BlczogcmVhZG9ubHkgc3RyaW5nW10gPSBIRUxMT19BUElfU0NPUEVTLFxuKTogeyBpZGVudGlmaWVyOiBzdHJpbmcgfSB7XG5cdGNvbnN0IG91dCA9IHJ1bkF1dGgwKFtcblx0XHRcImFwaXNcIixcblx0XHRcImNyZWF0ZVwiLFxuXHRcdFwiLS1uYW1lXCIsXG5cdFx0bmFtZSxcblx0XHRcIi0taWRlbnRpZmllclwiLFxuXHRcdGlkZW50aWZpZXIsXG5cdFx0XCItLXNjb3Blc1wiLFxuXHRcdHNjb3Blcy5qb2luKFwiLFwiKSxcblx0XHRcIi0tanNvblwiLFxuXHRcdFwiLS1uby1pbnB1dFwiLFxuXHRdKTtcblx0cmV0dXJuIHBhcnNlSnNvbk91dHB1dChvdXQpO1xufVxuXG4vKiogUmVwbGFjZSBhbiBBUEkncyBzY29wZXMgKEF1dGgwIENMSSB1cGRhdGUgLS1zY29wZXMgcmVwbGFjZXMgdGhlIGZ1bGwgc2V0KS4gKi9cbmV4cG9ydCBmdW5jdGlvbiB1cGRhdGVBcGlTY29wZXMoXG5cdGlkZW50aWZpZXI6IHN0cmluZyxcblx0c2NvcGVzOiByZWFkb25seSBzdHJpbmdbXSA9IEhFTExPX0FQSV9TQ09QRVMsXG4pOiB2b2lkIHtcblx0cnVuQXV0aDAoW1wiYXBpc1wiLCBcInVwZGF0ZVwiLCBpZGVudGlmaWVyLCBcIi0tc2NvcGVzXCIsIHNjb3Blcy5qb2luKFwiLFwiKSwgXCItLW5vLWlucHV0XCJdKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZVNwYUFwcChcblx0bmFtZTogc3RyaW5nLFxuXHRjYWxsYmFja1VybHM6IHN0cmluZyB8IHJlYWRvbmx5IHN0cmluZ1tdLFxuKTogeyBjbGllbnRfaWQ6IHN0cmluZyB9IHtcblx0Y29uc3QgY2FsbGJhY2tzID0gdHlwZW9mIGNhbGxiYWNrVXJscyA9PT0gXCJzdHJpbmdcIiA/IGNhbGxiYWNrVXJscyA6IGNhbGxiYWNrVXJscy5qb2luKFwiLFwiKTtcblx0Y29uc3Qgb3V0ID0gcnVuQXV0aDAoW1xuXHRcdFwiYXBwc1wiLFxuXHRcdFwiY3JlYXRlXCIsXG5cdFx0XCItLW5hbWVcIixcblx0XHRuYW1lLFxuXHRcdFwiLS10eXBlXCIsXG5cdFx0XCJzcGFcIixcblx0XHRcIi0tY2FsbGJhY2tzXCIsXG5cdFx0Y2FsbGJhY2tzLFxuXHRcdFwiLS1qc29uXCIsXG5cdFx0XCItLW5vLWlucHV0XCIsXG5cdF0pO1xuXHRjb25zdCBhcHAgPSBwYXJzZUpzb25PdXRwdXQ8eyBjbGllbnRfaWQ/OiBzdHJpbmc7IGNsaWVudElkPzogc3RyaW5nIH0+KG91dCk7XG5cdGNvbnN0IGNsaWVudElkID0gYXBwLmNsaWVudF9pZCA/PyBhcHAuY2xpZW50SWQ7XG5cdGlmICghY2xpZW50SWQpIHtcblx0XHR0aHJvdyBuZXcgRXJyb3IoXG5cdFx0XHRgQXV0aDAgY3JlYXRlIFNQQSByZXNwb25zZSBtaXNzaW5nIGNsaWVudF9pZC4gc3Rkb3V0OiAke291dC5zbGljZSgwLCAzMDApfWAsXG5cdFx0KTtcblx0fVxuXHRyZXR1cm4geyBjbGllbnRfaWQ6IGNsaWVudElkIH07XG59XG5cbmV4cG9ydCB0eXBlIEF1dGgwQXBwID0geyBjbGllbnRfaWQ6IHN0cmluZzsgbmFtZTogc3RyaW5nIH07XG5cbmV4cG9ydCBmdW5jdGlvbiBsaXN0QXBwcygpOiBBdXRoMEFwcFtdIHtcblx0dHJ5IHtcblx0XHRjb25zdCBvdXQgPSBydW5BdXRoMChbXCJhcHBzXCIsIFwibGlzdFwiLCBcIi0tanNvblwiLCBcIi0tbm8taW5wdXRcIl0pO1xuXHRcdGNvbnN0IGFwcHMgPVxuXHRcdFx0cGFyc2VKc29uT3V0cHV0PEFycmF5PHsgY2xpZW50X2lkPzogc3RyaW5nOyBjbGllbnRJZD86IHN0cmluZzsgbmFtZT86IHN0cmluZyB9Pj4ob3V0KTtcblx0XHRyZXR1cm4gYXBwc1xuXHRcdFx0Lm1hcCgoYSkgPT4gKHtcblx0XHRcdFx0Y2xpZW50X2lkOiBhLmNsaWVudF9pZCA/PyBhLmNsaWVudElkID8/IFwiXCIsXG5cdFx0XHRcdG5hbWU6IGEubmFtZSA/PyBcIlwiLFxuXHRcdFx0fSkpXG5cdFx0XHQuZmlsdGVyKChhKSA9PiBhLmNsaWVudF9pZCAmJiBhLm5hbWUpO1xuXHR9IGNhdGNoIChlcnIpIHtcblx0XHRpZiAoZXJyIGluc3RhbmNlb2YgQXV0aDBBdXRoRXJyb3IpIHRocm93IGVycjtcblx0XHRyZXR1cm4gW107XG5cdH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHVwZGF0ZVNwYUNhbGxiYWNrcyhcblx0Y2xpZW50SWQ6IHN0cmluZyxcblx0Y2FsbGJhY2tVcmxzOiBzdHJpbmcgfCByZWFkb25seSBzdHJpbmdbXSxcbik6IHZvaWQge1xuXHRjb25zdCBjYWxsYmFja3MgPSB0eXBlb2YgY2FsbGJhY2tVcmxzID09PSBcInN0cmluZ1wiID8gY2FsbGJhY2tVcmxzIDogY2FsbGJhY2tVcmxzLmpvaW4oXCIsXCIpO1xuXHRydW5BdXRoMChbXCJhcHBzXCIsIFwidXBkYXRlXCIsIGNsaWVudElkLCBcIi0tY2FsbGJhY2tzXCIsIGNhbGxiYWNrcywgXCItLW5vLWlucHV0XCJdKTtcbn1cblxuLyoqXG4gKiBDcmVhdGUgYSBQb3N0bWFuIFNQQSwgb3IgcmV1c2UgYW4gZXhpc3RpbmcgYXBwIHdpdGggdGhlIHNhbWUgbmFtZSAocmUtc2NhZmZvbGQpLlxuICogQWx3YXlzIHJldHVybnMgYSBjbGllbnRfaWQgc3VpdGFibGUgZm9yIFBvc3RtYW4gYXV0aDBDbGllbnRJZC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGVuc3VyZVNwYUFwcChcblx0bmFtZTogc3RyaW5nLFxuXHRjYWxsYmFja1VybHM6IHN0cmluZyB8IHJlYWRvbmx5IHN0cmluZ1tdLFxuKTogeyBjbGllbnRfaWQ6IHN0cmluZzsgcmV1c2VkOiBib29sZWFuIH0ge1xuXHRjb25zdCBleGlzdGluZyA9IGxpc3RBcHBzKCkuZmluZCgoYSkgPT4gYS5uYW1lID09PSBuYW1lKTtcblx0aWYgKGV4aXN0aW5nKSB7XG5cdFx0dHJ5IHtcblx0XHRcdHVwZGF0ZVNwYUNhbGxiYWNrcyhleGlzdGluZy5jbGllbnRfaWQsIGNhbGxiYWNrVXJscyk7XG5cdFx0fSBjYXRjaCB7XG5cdFx0XHQvLyBDYWxsYmFja3MgbWF5IGFscmVhZHkgbWF0Y2g7IHN0aWxsIHVzYWJsZSBmb3IgUG9zdG1hbi5cblx0XHR9XG5cdFx0cmV0dXJuIHsgY2xpZW50X2lkOiBleGlzdGluZy5jbGllbnRfaWQsIHJldXNlZDogdHJ1ZSB9O1xuXHR9XG5cdHJldHVybiB7IC4uLmNyZWF0ZVNwYUFwcChuYW1lLCBjYWxsYmFja1VybHMpLCByZXVzZWQ6IGZhbHNlIH07XG59XG5cbnR5cGUgQXV0aDBDb25uZWN0aW9uID0geyBpZDogc3RyaW5nOyBuYW1lOiBzdHJpbmc7IHN0cmF0ZWd5OiBzdHJpbmcgfTtcblxuLyoqIEVuYWJsZSBhIGRhdGFiYXNlIGNvbm5lY3Rpb24gZm9yIGFuIGFwcGxpY2F0aW9uIChyZXF1aXJlZCBmb3IgdXNlcm5hbWUvcGFzc3dvcmQgbG9naW4pLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGVuYWJsZUNvbm5lY3Rpb25Gb3JDbGllbnQoY29ubmVjdGlvbk5hbWU6IHN0cmluZywgY2xpZW50SWQ6IHN0cmluZyk6IHZvaWQge1xuXHRjb25zdCBsaXN0T3V0ID0gcnVuQXV0aDAoW1wiYXBpXCIsIFwiZ2V0XCIsIFwiY29ubmVjdGlvbnNcIiwgXCItLW5vLWlucHV0XCJdKTtcblx0Y29uc3QgY29ubmVjdGlvbnMgPSBwYXJzZUpzb25PdXRwdXQ8QXV0aDBDb25uZWN0aW9uW10+KGxpc3RPdXQpO1xuXHRjb25zdCBjb25uZWN0aW9uID0gY29ubmVjdGlvbnMuZmluZCgoYykgPT4gYy5uYW1lID09PSBjb25uZWN0aW9uTmFtZSk7XG5cdGlmICghY29ubmVjdGlvbikge1xuXHRcdHRocm93IG5ldyBFcnJvcihgQXV0aDAgY29ubmVjdGlvbiBub3QgZm91bmQ6ICR7Y29ubmVjdGlvbk5hbWV9YCk7XG5cdH1cblxuXHRjb25zdCBjbGllbnRzT3V0ID0gcnVuQXV0aDAoW1xuXHRcdFwiYXBpXCIsXG5cdFx0XCJnZXRcIixcblx0XHRgY29ubmVjdGlvbnMvJHtjb25uZWN0aW9uLmlkfS9jbGllbnRzYCxcblx0XHRcIi0tbm8taW5wdXRcIixcblx0XSk7XG5cdGNvbnN0IHsgY2xpZW50cyB9ID0gcGFyc2VKc29uT3V0cHV0PHsgY2xpZW50czogQXJyYXk8eyBjbGllbnRfaWQ6IHN0cmluZyB9PiB9PihjbGllbnRzT3V0KTtcblx0aWYgKGNsaWVudHMuc29tZSgoYykgPT4gYy5jbGllbnRfaWQgPT09IGNsaWVudElkKSkgcmV0dXJuO1xuXG5cdC8vIERlZGljYXRlZCBlbmFibGVkLWNsaWVudHMgZW5kcG9pbnQgKGVuYWJsZWRfY2xpZW50cyBvbiBjb25uZWN0aW9uIFBBVENIIGlzIGRlcHJlY2F0ZWQpLlxuXHRydW5BdXRoMChbXG5cdFx0XCJhcGlcIixcblx0XHRcInBhdGNoXCIsXG5cdFx0YGNvbm5lY3Rpb25zLyR7Y29ubmVjdGlvbi5pZH0vY2xpZW50c2AsXG5cdFx0XCItLWRhdGFcIixcblx0XHRKU09OLnN0cmluZ2lmeShbeyBjbGllbnRfaWQ6IGNsaWVudElkLCBzdGF0dXM6IHRydWUgfV0pLFxuXHRcdFwiLS1uby1pbnB1dFwiLFxuXHRdKTtcbn1cblxuZXhwb3J0IHR5cGUgQWRtaW5EYXRhYmFzZVVzZXIgPSB7XG5cdHVzZXJfaWQ6IHN0cmluZztcblx0ZW1haWw6IHN0cmluZztcblx0cGFzc3dvcmQ6IHN0cmluZztcblx0dXNlcm5hbWU6IHN0cmluZztcbn07XG5cbi8qKiBTdHJvbmcgZGVmYXVsdCBwYXNzd29yZCB3aGVuIHRoZSBzY2FmZm9sZGVyIGNhbGxlciBsZWF2ZXMgcGFzc3dvcmQgYmxhbmsuICovXG5leHBvcnQgZnVuY3Rpb24gZ2VuZXJhdGVBZG1pblBhc3N3b3JkKCk6IHN0cmluZyB7XG5cdHJldHVybiBgJHtyYW5kb21CeXRlcygxMikudG9TdHJpbmcoXCJiYXNlNjR1cmxcIil9YUExIWA7XG59XG5cbmZ1bmN0aW9uIGlzVXNlckFscmVhZHlFeGlzdHNFcnJvcihlcnI6IHVua25vd24pOiBib29sZWFuIHtcblx0Y29uc3QgdGV4dCA9IGVyciBpbnN0YW5jZW9mIEVycm9yID8gZXJyLm1lc3NhZ2UgOiBTdHJpbmcoZXJyKTtcblx0cmV0dXJuIC9hbHJlYWR5IGV4aXN0c3x1c2VyIGV4aXN0c3xDb25mbGljdHw0MDkvaS50ZXN0KHRleHQpO1xufVxuXG4vKiogTG9vayB1cCBhIHVzZXIgYnkgZW1haWwgKE1hbmFnZW1lbnQgQVBJIHVzZXJzLWJ5LWVtYWlsKS4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmaW5kVXNlckJ5RW1haWwoZW1haWw6IHN0cmluZyk6IHsgdXNlcl9pZDogc3RyaW5nOyBlbWFpbDogc3RyaW5nIH0gfCBudWxsIHtcblx0Y29uc3Qgb3V0ID0gcnVuQXV0aDAoW1xuXHRcdFwiYXBpXCIsXG5cdFx0XCJnZXRcIixcblx0XHRgdXNlcnMtYnktZW1haWw/ZW1haWw9JHtlbmNvZGVVUklDb21wb25lbnQoZW1haWwpfWAsXG5cdFx0XCItLW5vLWlucHV0XCIsXG5cdF0pO1xuXHRjb25zdCB1c2VycyA9IHBhcnNlSnNvbk91dHB1dDxBcnJheTx7IHVzZXJfaWQ/OiBzdHJpbmc7IGVtYWlsPzogc3RyaW5nIH0+PihvdXQpO1xuXHRjb25zdCB1c2VyID0gdXNlcnMuZmluZCgodSkgPT4gdS51c2VyX2lkICYmIHUuZW1haWwpO1xuXHRpZiAoIXVzZXI/LnVzZXJfaWQgfHwgIXVzZXIuZW1haWwpIHJldHVybiBudWxsO1xuXHRyZXR1cm4geyB1c2VyX2lkOiB1c2VyLnVzZXJfaWQsIGVtYWlsOiB1c2VyLmVtYWlsIH07XG59XG5cbi8qKiBSZXNldCBwYXNzd29yZCBzbyBhIHJlLXNjYWZmb2xkIGNhbiB3cml0ZSBhIGtub3duIHBhc3N3b3JkIHRvIC5lbnYuICovXG5leHBvcnQgZnVuY3Rpb24gdXBkYXRlVXNlclBhc3N3b3JkKHVzZXJJZDogc3RyaW5nLCBwYXNzd29yZDogc3RyaW5nKTogdm9pZCB7XG5cdHJ1bkF1dGgwKFtcblx0XHRcImFwaVwiLFxuXHRcdFwicGF0Y2hcIixcblx0XHRgdXNlcnMvJHtlbmNvZGVVUklDb21wb25lbnQodXNlcklkKX1gLFxuXHRcdFwiLS1kYXRhXCIsXG5cdFx0SlNPTi5zdHJpbmdpZnkoeyBwYXNzd29yZCwgY29ubmVjdGlvbjogREJfQ09OTkVDVElPTl9OQU1FIH0pLFxuXHRcdFwiLS1uby1pbnB1dFwiLFxuXHRdKTtcbn1cblxuLyoqXG4gKiBDcmVhdGUgYSBEQiBjb25uZWN0aW9uIHJvb3QtYWRtaW4gdXNlciBmb3IgbG9jYWwgLyBQb3N0bWFuIGxvZ2luLlxuICogSWYgdGhlIHVzZXIgYWxyZWFkeSBleGlzdHMsIGxvb2sgdGhlbSB1cCwgcmVzZXQgcGFzc3dvcmQgdG8gYGlucHV0LnBhc3N3b3JkYCxcbiAqIGFuZCByZXR1cm4gdGhhdCBpZGVudGl0eSBzbyBjYWxsZXJzIGNhbiBzdGlsbCB3cml0ZSAuZW52IGNyZWRlbnRpYWxzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlQWRtaW5EYXRhYmFzZVVzZXIoaW5wdXQ6IHtcblx0ZW1haWw6IHN0cmluZztcblx0cGFzc3dvcmQ6IHN0cmluZztcblx0dXNlcm5hbWU6IHN0cmluZztcbn0pOiBBZG1pbkRhdGFiYXNlVXNlciB7XG5cdGNvbnN0IGJvZHkgPSB7XG5cdFx0ZW1haWw6IGlucHV0LmVtYWlsLFxuXHRcdGNvbm5lY3Rpb246IERCX0NPTk5FQ1RJT05fTkFNRSxcblx0XHRwYXNzd29yZDogaW5wdXQucGFzc3dvcmQsXG5cdFx0bmFtZTogaW5wdXQudXNlcm5hbWUsXG5cdFx0ZW1haWxfdmVyaWZpZWQ6IHRydWUsXG5cdFx0dmVyaWZ5X2VtYWlsOiBmYWxzZSxcblx0XHRhcHBfbWV0YWRhdGE6IHsgcm9sZXM6IFtcImFkbWluXCJdIH0sXG5cdH07XG5cblx0dHJ5IHtcblx0XHRjb25zdCBvdXQgPSBydW5BdXRoMChbXG5cdFx0XHRcImFwaVwiLFxuXHRcdFx0XCJwb3N0XCIsXG5cdFx0XHRcInVzZXJzXCIsXG5cdFx0XHRcIi0tZGF0YVwiLFxuXHRcdFx0SlNPTi5zdHJpbmdpZnkoYm9keSksXG5cdFx0XHRcIi0tbm8taW5wdXRcIixcblx0XHRdKTtcblx0XHRjb25zdCB1c2VyID0gcGFyc2VKc29uT3V0cHV0PHsgdXNlcl9pZD86IHN0cmluZzsgZW1haWw/OiBzdHJpbmcgfT4ob3V0KTtcblx0XHRpZiAoIXVzZXIudXNlcl9pZCB8fCAhdXNlci5lbWFpbCkge1xuXHRcdFx0dGhyb3cgbmV3IEVycm9yKFxuXHRcdFx0XHRgQXV0aDAgY3JlYXRlIHVzZXIgcmVzcG9uc2UgbWlzc2luZyB1c2VyX2lkL2VtYWlsLiBzdGRvdXQ6ICR7b3V0LnNsaWNlKDAsIDMwMCl9YCxcblx0XHRcdCk7XG5cdFx0fVxuXHRcdHJldHVybiB7XG5cdFx0XHR1c2VyX2lkOiB1c2VyLnVzZXJfaWQsXG5cdFx0XHRlbWFpbDogdXNlci5lbWFpbCxcblx0XHRcdHBhc3N3b3JkOiBpbnB1dC5wYXNzd29yZCxcblx0XHRcdHVzZXJuYW1lOiBpbnB1dC51c2VybmFtZSxcblx0XHR9O1xuXHR9IGNhdGNoIChlcnIpIHtcblx0XHRpZiAoIWlzVXNlckFscmVhZHlFeGlzdHNFcnJvcihlcnIpKSB0aHJvdyBlcnI7XG5cblx0XHRjb25zdCBleGlzdGluZyA9IGZpbmRVc2VyQnlFbWFpbChpbnB1dC5lbWFpbCk7XG5cdFx0aWYgKCFleGlzdGluZykge1xuXHRcdFx0dGhyb3cgbmV3IEVycm9yKFxuXHRcdFx0XHRgQXV0aDAgdXNlciBhbHJlYWR5IGV4aXN0cyBmb3IgJHtpbnB1dC5lbWFpbH0sIGJ1dCBsb29rdXAgYnkgZW1haWwgcmV0dXJuZWQgbm8gdXNlci5gLFxuXHRcdFx0KTtcblx0XHR9XG5cblx0XHR1cGRhdGVVc2VyUGFzc3dvcmQoZXhpc3RpbmcudXNlcl9pZCwgaW5wdXQucGFzc3dvcmQpO1xuXHRcdHJldHVybiB7XG5cdFx0XHR1c2VyX2lkOiBleGlzdGluZy51c2VyX2lkLFxuXHRcdFx0ZW1haWw6IGV4aXN0aW5nLmVtYWlsLFxuXHRcdFx0cGFzc3dvcmQ6IGlucHV0LnBhc3N3b3JkLFxuXHRcdFx0dXNlcm5hbWU6IGlucHV0LnVzZXJuYW1lLFxuXHRcdH07XG5cdH1cbn1cblxuZXhwb3J0IHsgUkVRVUlSRURfU0NPUEVTIH07XG4iXSwibmFtZXMiOlsiZXhlY0ZpbGVTeW5jIiwic3Bhd25TeW5jIiwicmFuZG9tQnl0ZXMiLCJSRVFVSVJFRF9TQ09QRVMiLCJqb2luIiwiQVBJX1RJTUVPVVRfTVMiLCJIRUxMT19BUElfU0NPUEVTIiwiREJfQ09OTkVDVElPTl9OQU1FIiwiQXV0aDBBdXRoRXJyb3IiLCJFcnJvciIsIm1lc3NhZ2UiLCJuYW1lIiwiaXNBdXRoRXJyb3IiLCJ0ZXh0IiwiaW5jbHVkZXMiLCJwYXJzZUpzb25PdXRwdXQiLCJzdGRvdXQiLCJzdGFydCIsImluZGV4T2YiLCJhcnJheVN0YXJ0IiwiaWR4IiwiTWF0aCIsIm1pbiIsInNsaWNlIiwiSlNPTiIsInBhcnNlIiwicnVuQXV0aDAiLCJhcmdzIiwicmVzdWx0IiwiZW5jb2RpbmciLCJ0aW1lb3V0IiwiaW5wdXQiLCJzdGRpbyIsImVycm9yIiwibXNnIiwiY29kZSIsInN0YXR1cyIsInN0ZGVyciIsImlzSW5zdGFsbGVkIiwibGlzdFRlbmFudHMiLCJvdXQiLCJsb2dpbiIsImxpc3RBcGlzIiwiZXJyIiwiY3JlYXRlQXBpIiwiaWRlbnRpZmllciIsInNjb3BlcyIsInVwZGF0ZUFwaVNjb3BlcyIsImNyZWF0ZVNwYUFwcCIsImNhbGxiYWNrVXJscyIsImNhbGxiYWNrcyIsImFwcCIsImNsaWVudElkIiwiY2xpZW50X2lkIiwibGlzdEFwcHMiLCJhcHBzIiwibWFwIiwiYSIsImZpbHRlciIsInVwZGF0ZVNwYUNhbGxiYWNrcyIsImVuc3VyZVNwYUFwcCIsImV4aXN0aW5nIiwiZmluZCIsInJldXNlZCIsImVuYWJsZUNvbm5lY3Rpb25Gb3JDbGllbnQiLCJjb25uZWN0aW9uTmFtZSIsImxpc3RPdXQiLCJjb25uZWN0aW9ucyIsImNvbm5lY3Rpb24iLCJjIiwiY2xpZW50c091dCIsImlkIiwiY2xpZW50cyIsInNvbWUiLCJzdHJpbmdpZnkiLCJnZW5lcmF0ZUFkbWluUGFzc3dvcmQiLCJ0b1N0cmluZyIsImlzVXNlckFscmVhZHlFeGlzdHNFcnJvciIsIlN0cmluZyIsInRlc3QiLCJmaW5kVXNlckJ5RW1haWwiLCJlbWFpbCIsImVuY29kZVVSSUNvbXBvbmVudCIsInVzZXJzIiwidXNlciIsInUiLCJ1c2VyX2lkIiwidXBkYXRlVXNlclBhc3N3b3JkIiwidXNlcklkIiwicGFzc3dvcmQiLCJjcmVhdGVBZG1pbkRhdGFiYXNlVXNlciIsImJvZHkiLCJ1c2VybmFtZSIsImVtYWlsX3ZlcmlmaWVkIiwidmVyaWZ5X2VtYWlsIiwiYXBwX21ldGFkYXRhIiwicm9sZXMiXSwibWFwcGluZ3MiOiJBQUFBLFNBQVNBLFlBQVksRUFBRUMsU0FBUyxRQUFRLHFCQUFxQjtBQUM3RCxTQUFTQyxXQUFXLFFBQVEsY0FBYztBQUUxQyw2RUFBNkUsR0FDN0UsTUFBTUMsa0JBQWtCO0lBQ3ZCO0lBQ0E7SUFDQTtJQUNBO0lBQ0E7SUFDQTtJQUNBO0lBQ0E7SUFDQTtJQUNBO0lBQ0E7Q0FDQSxDQUFDQyxJQUFJLENBQUM7QUFFUCwwRkFBMEYsR0FDMUYsTUFBTUMsaUJBQWlCO0FBRXZCLGlFQUFpRSxHQUNqRSxPQUFPLE1BQU1DLG1CQUFtQjtJQUMvQjtJQUNBO0lBQ0E7SUFDQTtDQUNBLENBQVU7QUFFWCxPQUFPLE1BQU1DLHFCQUFxQixtQ0FBbUM7QUFFckUsT0FBTyxNQUFNQyx1QkFBdUJDO0lBQ25DLFlBQW1CQyxPQUFlLENBQUU7UUFDbkMsS0FBSyxDQUFDQTtRQUNOLElBQUksQ0FBQ0MsSUFBSSxHQUFHO0lBQ2I7QUFDRDtBQUVBLG1G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
@@ -1,8 +1,20 @@
1
1
  import { randomBytes } from "node:crypto";
2
+ import { readFileSync } from "node:fs";
3
+ import { join } from "node:path";
2
4
  import { pick } from "../../domain/prompt.js";
3
5
  import { WELL_KNOWN_FILES } from "../../models/const.js";
4
6
  import { CREATE_VERSION } from "../../version.js";
5
7
  import { WEBAPI_PROJECT_DIR } from "../create-api.js";
8
+ /** Read a single KEY= from an existing target `.env` (if any). */ function readExistingEnvValue(workspace, key) {
9
+ try {
10
+ const raw = readFileSync(join(workspace.targetDir, ".env"), "utf8");
11
+ const line = raw.split("\n").find((l)=>l.startsWith(`${key}=`));
12
+ const value = line?.slice(key.length + 1).trim();
13
+ return value || undefined;
14
+ } catch {
15
+ return undefined;
16
+ }
17
+ }
6
18
  // Base config uses env-var references for production; the dev config section
7
19
  // written below overrides only the concrete values needed locally.
8
20
  const DATABASE_BASE_CONFIG_YAML = `database:
@@ -20,10 +32,10 @@ const DATABASE_BASE_CONFIG_YAML = `database:
20
32
  adminPassword: \${DB_ADMIN_PASSWORD}
21
33
  `;
22
34
  // Dev config only overrides what differs from base — credentials come from .env via env-var references.
35
+ // Host comes from DB_HOST in .env (postgres on the compose network; 127.0.0.1 from the host).
23
36
  const DATABASE_DEV_CONFIG_YAML = `database:
24
37
  dataSources:
25
- - host: postgres
26
- synchronize: true
38
+ - synchronize: true
27
39
  seed: true
28
40
  `;
29
41
  const SAMPLE_ENTITY_TS = `import { Column, Entity, PrimaryGeneratedColumn } from "typeorm";
@@ -68,34 +80,56 @@ async function getOptions(_workspace, cliOptions) {
68
80
  function scaffold(workspace, options) {
69
81
  if (options.databaseProvider !== "postgres/typeorm") return;
70
82
  const name = workspace.name;
71
- const password = randomBytes(16).toString("hex");
83
+ // Prefer an existing POSTGRES_PASSWORD so re-scaffold does not rotate credentials
84
+ // out from under an already-initialized Docker volume (Postgres only applies
85
+ // POSTGRES_PASSWORD on first data-dir init).
86
+ const existingPassword = readExistingEnvValue(workspace, "POSTGRES_PASSWORD");
87
+ const password = existingPassword || randomBytes(16).toString("hex");
72
88
  const db = `${name}_dev`;
73
89
  const user = "postgres";
74
90
  const devContainer = workspace.getModel(WELL_KNOWN_FILES.DEVCONTAINER_JSON);
75
91
  const compose = workspace.getModel(WELL_KNOWN_FILES.DOCKER_COMPOSE);
76
- // Add postgres service to compose
92
+ const networkKey = name;
93
+ const volumeName = `${name}-postgres-data`;
94
+ // Isolated compose project network + volume (not ark's shared Postgres).
95
+ // Alias `postgres` so other stacks on the same named network can use DB_HOST=postgres.
77
96
  compose?.addService("postgres", {
78
97
  image: "postgres:16",
98
+ container_name: `samples-${name}-postgres`,
79
99
  restart: "unless-stopped",
80
- environment: {
81
- // biome-ignore lint/suspicious/noTemplateCurlyInString: Docker Compose reads these from .env
82
- POSTGRES_DB: "${POSTGRES_DB}",
83
- // biome-ignore lint/suspicious/noTemplateCurlyInString: Docker Compose reads these from .env
84
- POSTGRES_USER: "${POSTGRES_USER}",
85
- // biome-ignore lint/suspicious/noTemplateCurlyInString: Docker Compose reads these from .env
86
- POSTGRES_PASSWORD: "${POSTGRES_PASSWORD}"
87
- },
100
+ // Host 5433 avoids clashing with a local/other Postgres on 5432.
88
101
  ports: [
89
- "5432:5432"
102
+ "5433:5432"
90
103
  ],
91
104
  volumes: [
92
- "postgres-data:/var/lib/postgresql/data"
93
- ]
94
- }).addVolume("postgres-data");
105
+ `${volumeName}:/var/lib/postgresql/data`
106
+ ],
107
+ networks: [
108
+ {
109
+ [networkKey]: {
110
+ aliases: [
111
+ "postgres"
112
+ ]
113
+ }
114
+ }
115
+ ],
116
+ healthcheck: {
117
+ test: [
118
+ "CMD-SHELL",
119
+ `pg_isready -U ${user} -d ${db}`
120
+ ],
121
+ interval: "2s",
122
+ timeout: "5s",
123
+ retries: 15
124
+ }
125
+ }).addEnvFile("postgres", "../.env").addVolume(volumeName);
95
126
  compose?.addService("adminer", {
96
127
  image: "adminer",
97
128
  ports: [
98
- "8080:8080"
129
+ "8081:8080"
130
+ ],
131
+ networks: [
132
+ networkKey
99
133
  ]
100
134
  });
101
135
  // Add SQLTools extension for DB browsing in VS Code
@@ -108,8 +142,7 @@ function scaffold(workspace, options) {
108
142
  className: "SampleEntityRepository",
109
143
  importPath: "./repositories/sample.repository.js"
110
144
  });
111
- // Add codex + typeorm deps to root package.json
112
- workspace.getModel(WELL_KNOWN_FILES.PACKAGE_JSON)?.addDependency("@decohere/codex", CREATE_VERSION).addDependency("typeorm", "^0.3.28").addDependency("@decohere/codex-typeorm", CREATE_VERSION);
145
+ workspace.getModel(WELL_KNOWN_FILES.PACKAGE_JSON)?.addDependency("@decohere/codex", CREATE_VERSION).addDependency("typeorm", "^0.3.28").addDependency("@decohere/codex-typeorm", CREATE_VERSION).addScript("db:up", "docker compose -f .devcontainer/docker-compose.yml up -d postgres").addScript("db:down", "docker compose -f .devcontainer/docker-compose.yml down").addScript("db:reset", "docker compose -f .devcontainer/docker-compose.yml down -v && docker compose -f .devcontainer/docker-compose.yml up -d postgres");
113
146
  // Add codex deps to api package.json
114
147
  workspace.getModel(WELL_KNOWN_FILES.API_PACKAGE_JSON)?.addDependency("@decohere/codex", CREATE_VERSION).addDependency("@decohere/codex-typeorm", CREATE_VERSION);
115
148
  // Append database config sections
@@ -128,14 +161,13 @@ function scaffold(workspace, options) {
128
161
  }
129
162
  ]
130
163
  });
131
- // .env at workspace root — mounted by compose via ../.env so both postgres
132
- // and the devcontainer service can read credentials
133
- compose?.addEnvFile("postgres", "../.env").addEnvFile("devcontainer", "../.env");
134
- workspace.getModel(WELL_KNOWN_FILES.ENV_FILE)?.addEntry("POSTGRES_DB", db).addEntry("POSTGRES_USER", user).addEntry("POSTGRES_PASSWORD", password).addEntry("DB_HOST", "localhost").addEntry("DB_PORT", "5432").addEntry("DB_NAME", db).addEntry("DB_USER", user).addEntry("DB_PASSWORD", password).addEntry("DB_ADMIN_USER", user).addEntry("DB_ADMIN_PASSWORD", password);
164
+ // .env at workspace root — postgres reads it via env_file above; devcontainer gets it here
165
+ compose?.addEnvFile("devcontainer", "../.env");
166
+ workspace.getModel(WELL_KNOWN_FILES.ENV_FILE)?.addEntry("POSTGRES_DB", db).addEntry("POSTGRES_USER", user).addEntry("POSTGRES_PASSWORD", password).addEntry("DB_HOST", "postgres").addEntry("DB_PORT", "5432").addEntry("DB_NAME", db).addEntry("DB_USER", user).addEntry("DB_PASSWORD", password).addEntry("DB_ADMIN_USER", user).addEntry("DB_ADMIN_PASSWORD", password);
135
167
  }
136
168
  export const DatabaseFeature = {
137
169
  getOptions,
138
170
  scaffold
139
171
  };
140
172
 
141
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL3J1bm5lci93b3JrL2RlY29oZXJlL2RlY29oZXJlL3Byb2plY3RzL2NyZWF0ZS9zcmMvd2ViYXBpL2ZlYXR1cmVzL2RhdGFiYXNlLmZlYXR1cmUudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgcmFuZG9tQnl0ZXMgfSBmcm9tIFwibm9kZTpjcnlwdG9cIjtcbmltcG9ydCB7IHBpY2sgfSBmcm9tIFwiLi4vLi4vZG9tYWluL3Byb21wdC5qc1wiO1xuaW1wb3J0IHR5cGUgeyBEb2NrZXJDb21wb3NlIH0gZnJvbSBcIi4uLy4uL21vZGVscy9jb21wb3NlLm1vZGVsLmpzXCI7XG5pbXBvcnQgdHlwZSB7IENvbmZpZ1lhbWwgfSBmcm9tIFwiLi4vLi4vbW9kZWxzL2NvbmZpZy15YW1sLm1vZGVsLmpzXCI7XG5pbXBvcnQgeyBXRUxMX0tOT1dOX0ZJTEVTIH0gZnJvbSBcIi4uLy4uL21vZGVscy9jb25zdC5qc1wiO1xuaW1wb3J0IHR5cGUgeyBEZXZDb250YWluZXIgfSBmcm9tIFwiLi4vLi4vbW9kZWxzL2Rldi1jb250YWluZXIubW9kZWwuanNcIjtcbmltcG9ydCB0eXBlIHsgRW52RmlsZSB9IGZyb20gXCIuLi8uLi9tb2RlbHMvZW52LWZpbGUubW9kZWwuanNcIjtcbmltcG9ydCB0eXBlIHsgUGFja2FnZUpzb24gfSBmcm9tIFwiLi4vLi4vbW9kZWxzL3BhY2thZ2UtanNvbi5tb2RlbC5qc1wiO1xuaW1wb3J0IHR5cGUgeyBXb3Jrc3BhY2VTY2FmZm9sZCB9IGZyb20gXCIuLi8uLi9tb2RlbHMvcHJvamVjdC5tb2RlbC5qc1wiO1xuaW1wb3J0IHR5cGUgeyBGZWF0dXJlIH0gZnJvbSBcIi4uLy4uL3NlcnZpY2VzL3NjYWZmb2xkLnNlcnZpY2UuanNcIjtcbmltcG9ydCB7IENSRUFURV9WRVJTSU9OIH0gZnJvbSBcIi4uLy4uL3ZlcnNpb24uanNcIjtcbmltcG9ydCB7IFdFQkFQSV9QUk9KRUNUX0RJUiB9IGZyb20gXCIuLi9jcmVhdGUtYXBpLmpzXCI7XG5pbXBvcnQgdHlwZSB7IEFwaVBhY2thZ2VKc29uIH0gZnJvbSBcIi4uL21vZGVscy9hcGktcGFja2FnZS1qc29uLm1vZGVsLmpzXCI7XG5pbXBvcnQgdHlwZSB7IE1haW5Tb3VyY2VGaWxlIH0gZnJvbSBcIi4uL21vZGVscy9tYWluLXNvdXJjZS1maWxlLm1vZGVsLmpzXCI7XG5cbmV4cG9ydCB0eXBlIERhdGFiYXNlT3B0aW9ucyA9IHtcblx0ZGF0YWJhc2VQcm92aWRlcj86IFwibm9uZVwiIHwgXCJwb3N0Z3Jlcy90eXBlb3JtXCI7XG59O1xuXG4vLyBCYXNlIGNvbmZpZyB1c2VzIGVudi12YXIgcmVmZXJlbmNlcyBmb3IgcHJvZHVjdGlvbjsgdGhlIGRldiBjb25maWcgc2VjdGlvblxuLy8gd3JpdHRlbiBiZWxvdyBvdmVycmlkZXMgb25seSB0aGUgY29uY3JldGUgdmFsdWVzIG5lZWRlZCBsb2NhbGx5LlxuY29uc3QgREFUQUJBU0VfQkFTRV9DT05GSUdfWUFNTCA9IGBkYXRhYmFzZTpcbiAgZGF0YVNvdXJjZXM6XG4gICAgLSBuYW1lOiBkZWZhdWx0XG4gICAgICBwcm92aWRlcjogcG9zdGdyZXNcbiAgICAgIGhvc3Q6IFxcJHtEQl9IT1NUfVxuICAgICAgcG9ydDogXFwke0RCX1BPUlR9XG4gICAgICBkYXRhYmFzZTogXFwke0RCX05BTUV9XG4gICAgICB1c2VybmFtZTogXFwke0RCX1VTRVJ9XG4gICAgICBwYXNzd29yZDogXFwke0RCX1BBU1NXT1JEfVxuICAgICAgc3luY2hyb25pemU6IGZhbHNlXG4gICAgICBzZWVkOiBmYWxzZVxuICAgICAgYWRtaW5Vc2VyOiBcXCR7REJfQURNSU5fVVNFUn1cbiAgICAgIGFkbWluUGFzc3dvcmQ6IFxcJHtEQl9BRE1JTl9QQVNTV09SRH1cbmA7XG5cbi8vIERldiBjb25maWcgb25seSBvdmVycmlkZXMgd2hhdCBkaWZmZXJzIGZyb20gYmFzZSDigJQgY3JlZGVudGlhbHMgY29tZSBmcm9tIC5lbnYgdmlhIGVudi12YXIgcmVmZXJlbmNlcy5cbmNvbnN0IERBVEFCQVNFX0RFVl9DT05GSUdfWUFNTCA9IGBkYXRhYmFzZTpcbiAgZGF0YVNvdXJjZXM6XG4gICAgLSBob3N0OiBwb3N0Z3Jlc1xuICAgICAgc3luY2hyb25pemU6IHRydWVcbiAgICAgIHNlZWQ6IHRydWVcbmA7XG5cbmNvbnN0IFNBTVBMRV9FTlRJVFlfVFMgPSBgaW1wb3J0IHsgQ29sdW1uLCBFbnRpdHksIFByaW1hcnlHZW5lcmF0ZWRDb2x1bW4gfSBmcm9tIFwidHlwZW9ybVwiO1xuaW1wb3J0IHR5cGUgeyBFbnRpdHkgYXMgSUVudGl0eSB9IGZyb20gXCJAZGVjb2hlcmUvY29kZXhcIjtcblxuQEVudGl0eSgpXG5leHBvcnQgY2xhc3MgU2FtcGxlRW50aXR5IGltcGxlbWVudHMgSUVudGl0eSB7XG5cXHRAUHJpbWFyeUdlbmVyYXRlZENvbHVtbigpXG5cXHRwdWJsaWMgaWQhOiBudW1iZXI7XG5cblxcdEBDb2x1bW4oKVxuXFx0cHVibGljIG5hbWUhOiBzdHJpbmc7XG59XG5gO1xuXG5jb25zdCBTQU1QTEVfUkVQT1NJVE9SWV9UUyA9IGBpbXBvcnQgeyBpbmplY3RhYmxlIH0gZnJvbSBcIkBkZWNvaGVyZS9jcnVjaWJsZS9kZWNvcmF0b3JzXCI7XG5pbXBvcnQgeyBpbmplY3RVbml0T2ZXb3JrIH0gZnJvbSBcIkBkZWNvaGVyZS9jb2RleFwiO1xuaW1wb3J0IHsgVHlwZU9ybVJlcG9zaXRvcnksIFR5cGVPcm1Vbml0T2ZXb3JrIH0gZnJvbSBcIkBkZWNvaGVyZS9jb2RleC10eXBlb3JtXCI7XG5pbXBvcnQgeyBTYW1wbGVFbnRpdHkgfSBmcm9tIFwiLi4vZW50aXRpZXMvc2FtcGxlLmVudGl0eS5qc1wiO1xuXG5AaW5qZWN0YWJsZSgpXG5leHBvcnQgY2xhc3MgU2FtcGxlRW50aXR5UmVwb3NpdG9yeSBleHRlbmRzIFR5cGVPcm1SZXBvc2l0b3J5PFNhbXBsZUVudGl0eT4ge1xuXFx0cHVibGljIGNvbnN0cnVjdG9yKEBpbmplY3RVbml0T2ZXb3JrKCkgdW5pdE9mV29yazogVHlwZU9ybVVuaXRPZldvcmspIHtcblxcdFxcdHN1cGVyKHVuaXRPZldvcmssIFNhbXBsZUVudGl0eSk7XG5cXHR9XG59XG5gO1xuXG5hc3luYyBmdW5jdGlvbiBnZXRPcHRpb25zKFxuXHRfd29ya3NwYWNlOiBXb3Jrc3BhY2VTY2FmZm9sZCxcblx0Y2xpT3B0aW9uczogUGFydGlhbDxEYXRhYmFzZU9wdGlvbnM+LFxuKTogUHJvbWlzZTxQYXJ0aWFsPERhdGFiYXNlT3B0aW9ucz4+IHtcblx0aWYgKGNsaU9wdGlvbnMuZGF0YWJhc2VQcm92aWRlciAhPSBudWxsKSByZXR1cm4ge307XG5cblx0Y29uc3QgY2hvaWNlcyA9IFt7IGxhYmVsOiBcIm5vbmVcIiBhcyBjb25zdCB9LCB7IGxhYmVsOiBcInBvc3RncmVzL3R5cGVvcm1cIiBhcyBjb25zdCB9XTtcblx0Y29uc3Qgc2VsZWN0ZWQgPSBhd2FpdCBwaWNrKFwiXFxuICBEYXRhYmFzZTogXCIsIGNob2ljZXMsIChjKSA9PiBjLmxhYmVsKTtcblx0cmV0dXJuIHsgZGF0YWJhc2VQcm92aWRlcjogc2VsZWN0ZWQ/LmxhYmVsID8/IFwibm9uZVwiIH07XG59XG5cbmZ1bmN0aW9uIHNjYWZmb2xkKHdvcmtzcGFjZTogV29ya3NwYWNlU2NhZmZvbGQsIG9wdGlvbnM6IERhdGFiYXNlT3B0aW9ucyk6IHZvaWQge1xuXHRpZiAob3B0aW9ucy5kYXRhYmFzZVByb3ZpZGVyICE9PSBcInBvc3RncmVzL3R5cGVvcm1cIikgcmV0dXJuO1xuXG5cdGNvbnN0IG5hbWUgPSB3b3Jrc3BhY2UubmFtZTtcblx0Y29uc3QgcGFzc3dvcmQgPSByYW5kb21CeXRlcygxNikudG9TdHJpbmcoXCJoZXhcIik7XG5cdGNvbnN0IGRiID0gYCR7bmFtZX1fZGV2YDtcblx0Y29uc3QgdXNlciA9IFwicG9zdGdyZXNcIjtcblxuXHRjb25zdCBkZXZDb250YWluZXIgPSB3b3Jrc3BhY2UuZ2V0TW9kZWw8RGV2Q29udGFpbmVyPihXRUxMX0tOT1dOX0ZJTEVTLkRFVkNPTlRBSU5FUl9KU09OKTtcblx0Y29uc3QgY29tcG9zZSA9IHdvcmtzcGFjZS5nZXRNb2RlbDxEb2NrZXJDb21wb3NlPihXRUxMX0tOT1dOX0ZJTEVTLkRPQ0tFUl9DT01QT1NFKTtcblxuXHQvLyBBZGQgcG9zdGdyZXMgc2VydmljZSB0byBjb21wb3NlXG5cdGNvbXBvc2Vcblx0XHQ/LmFkZFNlcnZpY2UoXCJwb3N0Z3Jlc1wiLCB7XG5cdFx0XHRpbWFnZTogXCJwb3N0Z3JlczoxNlwiLFxuXHRcdFx0cmVzdGFydDogXCJ1bmxlc3Mtc3RvcHBlZFwiLFxuXHRcdFx0ZW52aXJvbm1lbnQ6IHtcblx0XHRcdFx0Ly8gYmlvbWUtaWdub3JlIGxpbnQvc3VzcGljaW91cy9ub1RlbXBsYXRlQ3VybHlJblN0cmluZzogRG9ja2VyIENvbXBvc2UgcmVhZHMgdGhlc2UgZnJvbSAuZW52XG5cdFx0XHRcdFBPU1RHUkVTX0RCOiBcIiR7UE9TVEdSRVNfREJ9XCIsXG5cdFx0XHRcdC8vIGJpb21lLWlnbm9yZSBsaW50L3N1c3BpY2lvdXMvbm9UZW1wbGF0ZUN1cmx5SW5TdHJpbmc6IERvY2tlciBDb21wb3NlIHJlYWRzIHRoZXNlIGZyb20gLmVudlxuXHRcdFx0XHRQT1NUR1JFU19VU0VSOiBcIiR7UE9TVEdSRVNfVVNFUn1cIixcblx0XHRcdFx0Ly8gYmlvbWUtaWdub3JlIGxpbnQvc3VzcGljaW91cy9ub1RlbXBsYXRlQ3VybHlJblN0cmluZzogRG9ja2VyIENvbXBvc2UgcmVhZHMgdGhlc2UgZnJvbSAuZW52XG5cdFx0XHRcdFBPU1RHUkVTX1BBU1NXT1JEOiBcIiR7UE9TVEdSRVNfUEFTU1dPUkR9XCIsXG5cdFx0XHR9LFxuXHRcdFx0cG9ydHM6IFtcIjU0MzI6NTQzMlwiXSxcblx0XHRcdHZvbHVtZXM6IFtcInBvc3RncmVzLWRhdGE6L3Zhci9saWIvcG9zdGdyZXNxbC9kYXRhXCJdLFxuXHRcdH0pXG5cdFx0LmFkZFZvbHVtZShcInBvc3RncmVzLWRhdGFcIik7XG5cblx0Y29tcG9zZT8uYWRkU2VydmljZShcImFkbWluZXJcIiwge1xuXHRcdGltYWdlOiBcImFkbWluZXJcIixcblx0XHRwb3J0czogW1wiODA4MDo4MDgwXCJdLFxuXHR9KTtcblxuXHQvLyBBZGQgU1FMVG9vbHMgZXh0ZW5zaW9uIGZvciBEQiBicm93c2luZyBpbiBWUyBDb2RlXG5cdGRldkNvbnRhaW5lcj8uYWRkRXh0ZW5zaW9uKFwibXR4ci5zcWx0b29sc1wiKTtcblxuXHQvLyBXaXJlIHVwIG1haW4udHNcblx0d29ya3NwYWNlXG5cdFx0LmdldE1vZGVsPE1haW5Tb3VyY2VGaWxlPihXRUxMX0tOT1dOX0ZJTEVTLk1BSU5fVFMpXG5cdFx0Py5hZGRTaWRlRWZmZWN0SW1wb3J0KFwiQGRlY29oZXJlL2NvZGV4LXR5cGVvcm1cIilcblx0XHQuYWRkRW50aXR5KHsgY2xhc3NOYW1lOiBcIlNhbXBsZUVudGl0eVwiLCBpbXBvcnRQYXRoOiBcIi4vZW50aXRpZXMvc2FtcGxlLmVudGl0eS5qc1wiIH0pXG5cdFx0LmFkZFJlcG9zaXRvcnkoe1xuXHRcdFx0Y2xhc3NOYW1lOiBcIlNhbXBsZUVudGl0eVJlcG9zaXRvcnlcIixcblx0XHRcdGltcG9ydFBhdGg6IFwiLi9yZXBvc2l0b3JpZXMvc2FtcGxlLnJlcG9zaXRvcnkuanNcIixcblx0XHR9KTtcblxuXHQvLyBBZGQgY29kZXggKyB0eXBlb3JtIGRlcHMgdG8gcm9vdCBwYWNrYWdlLmpzb25cblx0d29ya3NwYWNlXG5cdFx0LmdldE1vZGVsPFBhY2thZ2VKc29uPihXRUxMX0tOT1dOX0ZJTEVTLlBBQ0tBR0VfSlNPTilcblx0XHQ/LmFkZERlcGVuZGVuY3koXCJAZGVjb2hlcmUvY29kZXhcIiwgQ1JFQVRFX1ZFUlNJT04pXG5cdFx0LmFkZERlcGVuZGVuY3koXCJ0eXBlb3JtXCIsIFwiXjAuMy4yOFwiKVxuXHRcdC5hZGREZXBlbmRlbmN5KFwiQGRlY29oZXJlL2NvZGV4LXR5cGVvcm1cIiwgQ1JFQVRFX1ZFUlNJT04pO1xuXG5cdC8vIEFkZCBjb2RleCBkZXBzIHRvIGFwaSBwYWNrYWdlLmpzb25cblx0d29ya3NwYWNlXG5cdFx0LmdldE1vZGVsPEFwaVBhY2thZ2VKc29uPihXRUxMX0tOT1dOX0ZJTEVTLkFQSV9QQUNLQUdFX0pTT04pXG5cdFx0Py5hZGREZXBlbmRlbmN5KFwiQGRlY29oZXJlL2NvZGV4XCIsIENSRUFURV9WRVJTSU9OKVxuXHRcdC5hZGREZXBlbmRlbmN5KFwiQGRlY29oZXJlL2NvZGV4LXR5cGVvcm1cIiwgQ1JFQVRFX1ZFUlNJT04pO1xuXG5cdC8vIEFwcGVuZCBkYXRhYmFzZSBjb25maWcgc2VjdGlvbnNcblx0d29ya3NwYWNlXG5cdFx0LmdldE1vZGVsPENvbmZpZ1lhbWw+KFdFTExfS05PV05fRklMRVMuQ09ORklHX1lBTUwpXG5cdFx0Py5hZGRTZWN0aW9uKERBVEFCQVNFX0JBU0VfQ09ORklHX1lBTUwpO1xuXHR3b3Jrc3BhY2Vcblx0XHQuZ2V0TW9kZWw8Q29uZmlnWWFtbD4oV0VMTF9LTk9XTl9GSUxFUy5DT05GSUdfREVWX1lBTUwpXG5cdFx0Py5hZGRTZWN0aW9uKERBVEFCQVNFX0RFVl9DT05GSUdfWUFNTCk7XG5cblx0Ly8gUmVnaXN0ZXIgZW50aXR5IGFuZCByZXBvc2l0b3J5IHNvdXJjZSBmaWxlcyBpbiB0aGUgYXBpIHByb2plY3Rcblx0d29ya3NwYWNlLmdldFByb2plY3QoV0VCQVBJX1BST0pFQ1RfRElSKT8uYWRkRmlsZSh7XG5cdFx0ZmlsZXM6ICgpID0+IFtcblx0XHRcdHtcblx0XHRcdFx0ZmlsZVBhdGg6IFwic3JjL2VudGl0aWVzL3NhbXBsZS5lbnRpdHkudHNcIixcblx0XHRcdFx0Y29udGVudDogU0FNUExFX0VOVElUWV9UUyxcblx0XHRcdH0sXG5cdFx0XHR7XG5cdFx0XHRcdGZpbGVQYXRoOiBcInNyYy9yZXBvc2l0b3JpZXMvc2FtcGxlLnJlcG9zaXRvcnkudHNcIixcblx0XHRcdFx0Y29udGVudDogU0FNUExFX1JFUE9TSVRPUllfVFMsXG5cdFx0XHR9LFxuXHRcdF0sXG5cdH0pO1xuXG5cdC8vIC5lbnYgYXQgd29ya3NwYWNlIHJvb3Qg4oCUIG1vdW50ZWQgYnkgY29tcG9zZSB2aWEgLi4vLmVudiBzbyBib3RoIHBvc3RncmVzXG5cdC8vIGFuZCB0aGUgZGV2Y29udGFpbmVyIHNlcnZpY2UgY2FuIHJlYWQgY3JlZGVudGlhbHNcblx0Y29tcG9zZT8uYWRkRW52RmlsZShcInBvc3RncmVzXCIsIFwiLi4vLmVudlwiKS5hZGRFbnZGaWxlKFwiZGV2Y29udGFpbmVyXCIsIFwiLi4vLmVudlwiKTtcblxuXHR3b3Jrc3BhY2Vcblx0XHQuZ2V0TW9kZWw8RW52RmlsZT4oV0VMTF9LTk9XTl9GSUxFUy5FTlZfRklMRSlcblx0XHQ/LmFkZEVudHJ5KFwiUE9TVEdSRVNfREJcIiwgZGIpXG5cdFx0LmFkZEVudHJ5KFwiUE9TVEdSRVNfVVNFUlwiLCB1c2VyKVxuXHRcdC5hZGRFbnRyeShcIlBPU1RHUkVTX1BBU1NXT1JEXCIsIHBhc3N3b3JkKVxuXHRcdC5hZGRFbnRyeShcIkRCX0hPU1RcIiwgXCJsb2NhbGhvc3RcIilcblx0XHQuYWRkRW50cnkoXCJEQl9QT1JUXCIsIFwiNTQzMlwiKVxuXHRcdC5hZGRFbnRyeShcIkRCX05BTUVcIiwgZGIpXG5cdFx0LmFkZEVudHJ5KFwiREJfVVNFUlwiLCB1c2VyKVxuXHRcdC5hZGRFbnRyeShcIkRCX1BBU1NXT1JEXCIsIHBhc3N3b3JkKVxuXHRcdC5hZGRFbnRyeShcIkRCX0FETUlOX1VTRVJcIiwgdXNlcilcblx0XHQuYWRkRW50cnkoXCJEQl9BRE1JTl9QQVNTV09SRFwiLCBwYXNzd29yZCk7XG59XG5cbmV4cG9ydCBjb25zdCBEYXRhYmFzZUZlYXR1cmU6IEZlYXR1cmU8RGF0YWJhc2VPcHRpb25zPiA9IHsgZ2V0T3B0aW9ucywgc2NhZmZvbGQgfTtcbiJdLCJuYW1lcyI6WyJyYW5kb21CeXRlcyIsInBpY2siLCJXRUxMX0tOT1dOX0ZJTEVTIiwiQ1JFQVRFX1ZFUlNJT04iLCJXRUJBUElfUFJPSkVDVF9ESVIiLCJEQVRBQkFTRV9CQVNFX0NPTkZJR19ZQU1MIiwiREFUQUJBU0VfREVWX0NPTkZJR19ZQU1MIiwiU0FNUExFX0VOVElUWV9UUyIsIlNBTVBMRV9SRVBPU0lUT1JZX1RTIiwiZ2V0T3B0aW9ucyIsIl93b3Jrc3BhY2UiLCJjbGlPcHRpb25zIiwiZGF0YWJhc2VQcm92aWRlciIsImNob2ljZXMiLCJsYWJlbCIsInNlbGVjdGVkIiwiYyIsInNjYWZmb2xkIiwid29ya3NwYWNlIiwib3B0aW9ucyIsIm5hbWUiLCJwYXNzd29yZCIsInRvU3RyaW5nIiwiZGIiLCJ1c2VyIiwiZGV2Q29udGFpbmVyIiwiZ2V0TW9kZWwiLCJERVZDT05UQUlORVJfSlNPTiIsImNvbXBvc2UiLCJET0NLRVJfQ09NUE9TRSIsImFkZFNlcnZpY2UiLCJpbWFnZSIsInJlc3RhcnQiLCJlbnZpcm9ubWVudCIsIlBPU1RHUkVTX0RCIiwiUE9TVEdSRVNfVVNFUiIsIlBPU1RHUkVTX1BBU1NXT1JEIiwicG9ydHMiLCJ2b2x1bWVzIiwiYWRkVm9sdW1lIiwiYWRkRXh0ZW5zaW9uIiwiTUFJTl9UUyIsImFkZFNpZGVFZmZlY3RJbXBvcnQiLCJhZGRFbnRpdHkiLCJjbGFzc05hbWUiLCJpbXBvcnRQYXRoIiwiYWRkUmVwb3NpdG9yeSIsIlBBQ0tBR0VfSlNPTiIsImFkZERlcGVuZGVuY3kiLCJBUElfUEFDS0FHRV9KU09OIiwiQ09ORklHX1lBTUwiLCJhZGRTZWN0aW9uIiwiQ09ORklHX0RFVl9ZQU1MIiwiZ2V0UHJvamVjdCIsImFkZEZpbGUiLCJmaWxlcyIsImZpbGVQYXRoIiwiY29udGVudCIsImFkZEVudkZpbGUiLCJFTlZfRklMRSIsImFkZEVudHJ5IiwiRGF0YWJhc2VGZWF0dXJlIl0sIm1hcHBpbmdzIjoiQUFBQSxTQUFTQSxXQUFXLFFBQVEsY0FBYztBQUMxQyxTQUFTQyxJQUFJLFFBQVEseUJBQXlCO0FBRzlDLFNBQVNDLGdCQUFnQixRQUFRLHdCQUF3QjtBQU16RCxTQUFTQyxjQUFjLFFBQVEsbUJBQW1CO0FBQ2xELFNBQVNDLGtCQUFrQixRQUFRLG1CQUFtQjtBQVF0RCw2RUFBNkU7QUFDN0UsbUVBQW1FO0FBQ25F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
173
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL3J1bm5lci93b3JrL2RlY29oZXJlL2RlY29oZXJlL3Byb2plY3RzL2NyZWF0ZS9zcmMvd2ViYXBpL2ZlYXR1cmVzL2RhdGFiYXNlLmZlYXR1cmUudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgcmFuZG9tQnl0ZXMgfSBmcm9tIFwibm9kZTpjcnlwdG9cIjtcbmltcG9ydCB7IHJlYWRGaWxlU3luYyB9IGZyb20gXCJub2RlOmZzXCI7XG5pbXBvcnQgeyBqb2luIH0gZnJvbSBcIm5vZGU6cGF0aFwiO1xuaW1wb3J0IHsgcGljayB9IGZyb20gXCIuLi8uLi9kb21haW4vcHJvbXB0LmpzXCI7XG5pbXBvcnQgdHlwZSB7IERvY2tlckNvbXBvc2UgfSBmcm9tIFwiLi4vLi4vbW9kZWxzL2NvbXBvc2UubW9kZWwuanNcIjtcbmltcG9ydCB0eXBlIHsgQ29uZmlnWWFtbCB9IGZyb20gXCIuLi8uLi9tb2RlbHMvY29uZmlnLXlhbWwubW9kZWwuanNcIjtcbmltcG9ydCB7IFdFTExfS05PV05fRklMRVMgfSBmcm9tIFwiLi4vLi4vbW9kZWxzL2NvbnN0LmpzXCI7XG5pbXBvcnQgdHlwZSB7IERldkNvbnRhaW5lciB9IGZyb20gXCIuLi8uLi9tb2RlbHMvZGV2LWNvbnRhaW5lci5tb2RlbC5qc1wiO1xuaW1wb3J0IHR5cGUgeyBFbnZGaWxlIH0gZnJvbSBcIi4uLy4uL21vZGVscy9lbnYtZmlsZS5tb2RlbC5qc1wiO1xuaW1wb3J0IHR5cGUgeyBQYWNrYWdlSnNvbiB9IGZyb20gXCIuLi8uLi9tb2RlbHMvcGFja2FnZS1qc29uLm1vZGVsLmpzXCI7XG5pbXBvcnQgdHlwZSB7IFdvcmtzcGFjZVNjYWZmb2xkIH0gZnJvbSBcIi4uLy4uL21vZGVscy9wcm9qZWN0Lm1vZGVsLmpzXCI7XG5pbXBvcnQgdHlwZSB7IEZlYXR1cmUgfSBmcm9tIFwiLi4vLi4vc2VydmljZXMvc2NhZmZvbGQuc2VydmljZS5qc1wiO1xuaW1wb3J0IHsgQ1JFQVRFX1ZFUlNJT04gfSBmcm9tIFwiLi4vLi4vdmVyc2lvbi5qc1wiO1xuaW1wb3J0IHsgV0VCQVBJX1BST0pFQ1RfRElSIH0gZnJvbSBcIi4uL2NyZWF0ZS1hcGkuanNcIjtcbmltcG9ydCB0eXBlIHsgQXBpUGFja2FnZUpzb24gfSBmcm9tIFwiLi4vbW9kZWxzL2FwaS1wYWNrYWdlLWpzb24ubW9kZWwuanNcIjtcbmltcG9ydCB0eXBlIHsgTWFpblNvdXJjZUZpbGUgfSBmcm9tIFwiLi4vbW9kZWxzL21haW4tc291cmNlLWZpbGUubW9kZWwuanNcIjtcblxuZXhwb3J0IHR5cGUgRGF0YWJhc2VPcHRpb25zID0ge1xuXHRkYXRhYmFzZVByb3ZpZGVyPzogXCJub25lXCIgfCBcInBvc3RncmVzL3R5cGVvcm1cIjtcbn07XG5cbi8qKiBSZWFkIGEgc2luZ2xlIEtFWT0gZnJvbSBhbiBleGlzdGluZyB0YXJnZXQgYC5lbnZgIChpZiBhbnkpLiAqL1xuZnVuY3Rpb24gcmVhZEV4aXN0aW5nRW52VmFsdWUod29ya3NwYWNlOiBXb3Jrc3BhY2VTY2FmZm9sZCwga2V5OiBzdHJpbmcpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuXHR0cnkge1xuXHRcdGNvbnN0IHJhdyA9IHJlYWRGaWxlU3luYyhqb2luKHdvcmtzcGFjZS50YXJnZXREaXIsIFwiLmVudlwiKSwgXCJ1dGY4XCIpO1xuXHRcdGNvbnN0IGxpbmUgPSByYXcuc3BsaXQoXCJcXG5cIikuZmluZCgobCkgPT4gbC5zdGFydHNXaXRoKGAke2tleX09YCkpO1xuXHRcdGNvbnN0IHZhbHVlID0gbGluZT8uc2xpY2Uoa2V5Lmxlbmd0aCArIDEpLnRyaW0oKTtcblx0XHRyZXR1cm4gdmFsdWUgfHwgdW5kZWZpbmVkO1xuXHR9IGNhdGNoIHtcblx0XHRyZXR1cm4gdW5kZWZpbmVkO1xuXHR9XG59XG5cbi8vIEJhc2UgY29uZmlnIHVzZXMgZW52LXZhciByZWZlcmVuY2VzIGZvciBwcm9kdWN0aW9uOyB0aGUgZGV2IGNvbmZpZyBzZWN0aW9uXG4vLyB3cml0dGVuIGJlbG93IG92ZXJyaWRlcyBvbmx5IHRoZSBjb25jcmV0ZSB2YWx1ZXMgbmVlZGVkIGxvY2FsbHkuXG5jb25zdCBEQVRBQkFTRV9CQVNFX0NPTkZJR19ZQU1MID0gYGRhdGFiYXNlOlxuICBkYXRhU291cmNlczpcbiAgICAtIG5hbWU6IGRlZmF1bHRcbiAgICAgIHByb3ZpZGVyOiBwb3N0Z3Jlc1xuICAgICAgaG9zdDogXFwke0RCX0hPU1R9XG4gICAgICBwb3J0OiBcXCR7REJfUE9SVH1cbiAgICAgIGRhdGFiYXNlOiBcXCR7REJfTkFNRX1cbiAgICAgIHVzZXJuYW1lOiBcXCR7REJfVVNFUn1cbiAgICAgIHBhc3N3b3JkOiBcXCR7REJfUEFTU1dPUkR9XG4gICAgICBzeW5jaHJvbml6ZTogZmFsc2VcbiAgICAgIHNlZWQ6IGZhbHNlXG4gICAgICBhZG1pblVzZXI6IFxcJHtEQl9BRE1JTl9VU0VSfVxuICAgICAgYWRtaW5QYXNzd29yZDogXFwke0RCX0FETUlOX1BBU1NXT1JEfVxuYDtcblxuLy8gRGV2IGNvbmZpZyBvbmx5IG92ZXJyaWRlcyB3aGF0IGRpZmZlcnMgZnJvbSBiYXNlIOKAlCBjcmVkZW50aWFscyBjb21lIGZyb20gLmVudiB2aWEgZW52LXZhciByZWZlcmVuY2VzLlxuLy8gSG9zdCBjb21lcyBmcm9tIERCX0hPU1QgaW4gLmVudiAocG9zdGdyZXMgb24gdGhlIGNvbXBvc2UgbmV0d29yazsgMTI3LjAuMC4xIGZyb20gdGhlIGhvc3QpLlxuY29uc3QgREFUQUJBU0VfREVWX0NPTkZJR19ZQU1MID0gYGRhdGFiYXNlOlxuICBkYXRhU291cmNlczpcbiAgICAtIHN5bmNocm9uaXplOiB0cnVlXG4gICAgICBzZWVkOiB0cnVlXG5gO1xuXG5jb25zdCBTQU1QTEVfRU5USVRZX1RTID0gYGltcG9ydCB7IENvbHVtbiwgRW50aXR5LCBQcmltYXJ5R2VuZXJhdGVkQ29sdW1uIH0gZnJvbSBcInR5cGVvcm1cIjtcbmltcG9ydCB0eXBlIHsgRW50aXR5IGFzIElFbnRpdHkgfSBmcm9tIFwiQGRlY29oZXJlL2NvZGV4XCI7XG5cbkBFbnRpdHkoKVxuZXhwb3J0IGNsYXNzIFNhbXBsZUVudGl0eSBpbXBsZW1lbnRzIElFbnRpdHkge1xuXFx0QFByaW1hcnlHZW5lcmF0ZWRDb2x1bW4oKVxuXFx0cHVibGljIGlkITogbnVtYmVyO1xuXG5cXHRAQ29sdW1uKClcblxcdHB1YmxpYyBuYW1lITogc3RyaW5nO1xufVxuYDtcblxuY29uc3QgU0FNUExFX1JFUE9TSVRPUllfVFMgPSBgaW1wb3J0IHsgaW5qZWN0YWJsZSB9IGZyb20gXCJAZGVjb2hlcmUvY3J1Y2libGUvZGVjb3JhdG9yc1wiO1xuaW1wb3J0IHsgaW5qZWN0VW5pdE9mV29yayB9IGZyb20gXCJAZGVjb2hlcmUvY29kZXhcIjtcbmltcG9ydCB7IFR5cGVPcm1SZXBvc2l0b3J5LCBUeXBlT3JtVW5pdE9mV29yayB9IGZyb20gXCJAZGVjb2hlcmUvY29kZXgtdHlwZW9ybVwiO1xuaW1wb3J0IHsgU2FtcGxlRW50aXR5IH0gZnJvbSBcIi4uL2VudGl0aWVzL3NhbXBsZS5lbnRpdHkuanNcIjtcblxuQGluamVjdGFibGUoKVxuZXhwb3J0IGNsYXNzIFNhbXBsZUVudGl0eVJlcG9zaXRvcnkgZXh0ZW5kcyBUeXBlT3JtUmVwb3NpdG9yeTxTYW1wbGVFbnRpdHk+IHtcblxcdHB1YmxpYyBjb25zdHJ1Y3RvcihAaW5qZWN0VW5pdE9mV29yaygpIHVuaXRPZldvcms6IFR5cGVPcm1Vbml0T2ZXb3JrKSB7XG5cXHRcXHRzdXBlcih1bml0T2ZXb3JrLCBTYW1wbGVFbnRpdHkpO1xuXFx0fVxufVxuYDtcblxuYXN5bmMgZnVuY3Rpb24gZ2V0T3B0aW9ucyhcblx0X3dvcmtzcGFjZTogV29ya3NwYWNlU2NhZmZvbGQsXG5cdGNsaU9wdGlvbnM6IFBhcnRpYWw8RGF0YWJhc2VPcHRpb25zPixcbik6IFByb21pc2U8UGFydGlhbDxEYXRhYmFzZU9wdGlvbnM+PiB7XG5cdGlmIChjbGlPcHRpb25zLmRhdGFiYXNlUHJvdmlkZXIgIT0gbnVsbCkgcmV0dXJuIHt9O1xuXG5cdGNvbnN0IGNob2ljZXMgPSBbeyBsYWJlbDogXCJub25lXCIgYXMgY29uc3QgfSwgeyBsYWJlbDogXCJwb3N0Z3Jlcy90eXBlb3JtXCIgYXMgY29uc3QgfV07XG5cdGNvbnN0IHNlbGVjdGVkID0gYXdhaXQgcGljayhcIlxcbiAgRGF0YWJhc2U6IFwiLCBjaG9pY2VzLCAoYykgPT4gYy5sYWJlbCk7XG5cdHJldHVybiB7IGRhdGFiYXNlUHJvdmlkZXI6IHNlbGVjdGVkPy5sYWJlbCA/PyBcIm5vbmVcIiB9O1xufVxuXG5mdW5jdGlvbiBzY2FmZm9sZCh3b3Jrc3BhY2U6IFdvcmtzcGFjZVNjYWZmb2xkLCBvcHRpb25zOiBEYXRhYmFzZU9wdGlvbnMpOiB2b2lkIHtcblx0aWYgKG9wdGlvbnMuZGF0YWJhc2VQcm92aWRlciAhPT0gXCJwb3N0Z3Jlcy90eXBlb3JtXCIpIHJldHVybjtcblxuXHRjb25zdCBuYW1lID0gd29ya3NwYWNlLm5hbWU7XG5cdC8vIFByZWZlciBhbiBleGlzdGluZyBQT1NUR1JFU19QQVNTV09SRCBzbyByZS1zY2FmZm9sZCBkb2VzIG5vdCByb3RhdGUgY3JlZGVudGlhbHNcblx0Ly8gb3V0IGZyb20gdW5kZXIgYW4gYWxyZWFkeS1pbml0aWFsaXplZCBEb2NrZXIgdm9sdW1lIChQb3N0Z3JlcyBvbmx5IGFwcGxpZXNcblx0Ly8gUE9TVEdSRVNfUEFTU1dPUkQgb24gZmlyc3QgZGF0YS1kaXIgaW5pdCkuXG5cdGNvbnN0IGV4aXN0aW5nUGFzc3dvcmQgPSByZWFkRXhpc3RpbmdFbnZWYWx1ZSh3b3Jrc3BhY2UsIFwiUE9TVEdSRVNfUEFTU1dPUkRcIik7XG5cdGNvbnN0IHBhc3N3b3JkID0gZXhpc3RpbmdQYXNzd29yZCB8fCByYW5kb21CeXRlcygxNikudG9TdHJpbmcoXCJoZXhcIik7XG5cdGNvbnN0IGRiID0gYCR7bmFtZX1fZGV2YDtcblx0Y29uc3QgdXNlciA9IFwicG9zdGdyZXNcIjtcblxuXHRjb25zdCBkZXZDb250YWluZXIgPSB3b3Jrc3BhY2UuZ2V0TW9kZWw8RGV2Q29udGFpbmVyPihXRUxMX0tOT1dOX0ZJTEVTLkRFVkNPTlRBSU5FUl9KU09OKTtcblx0Y29uc3QgY29tcG9zZSA9IHdvcmtzcGFjZS5nZXRNb2RlbDxEb2NrZXJDb21wb3NlPihXRUxMX0tOT1dOX0ZJTEVTLkRPQ0tFUl9DT01QT1NFKTtcblxuXHRjb25zdCBuZXR3b3JrS2V5ID0gbmFtZTtcblx0Y29uc3Qgdm9sdW1lTmFtZSA9IGAke25hbWV9LXBvc3RncmVzLWRhdGFgO1xuXG5cdC8vIElzb2xhdGVkIGNvbXBvc2UgcHJvamVjdCBuZXR3b3JrICsgdm9sdW1lIChub3QgYXJrJ3Mgc2hhcmVkIFBvc3RncmVzKS5cblx0Ly8gQWxpYXMgYHBvc3RncmVzYCBzbyBvdGhlciBzdGFja3Mgb24gdGhlIHNhbWUgbmFtZWQgbmV0d29yayBjYW4gdXNlIERCX0hPU1Q9cG9zdGdyZXMuXG5cdGNvbXBvc2Vcblx0XHQ/LmFkZFNlcnZpY2UoXCJwb3N0Z3Jlc1wiLCB7XG5cdFx0XHRpbWFnZTogXCJwb3N0Z3JlczoxNlwiLFxuXHRcdFx0Y29udGFpbmVyX25hbWU6IGBzYW1wbGVzLSR7bmFtZX0tcG9zdGdyZXNgLFxuXHRcdFx0cmVzdGFydDogXCJ1bmxlc3Mtc3RvcHBlZFwiLFxuXHRcdFx0Ly8gSG9zdCA1NDMzIGF2b2lkcyBjbGFzaGluZyB3aXRoIGEgbG9jYWwvb3RoZXIgUG9zdGdyZXMgb24gNTQzMi5cblx0XHRcdHBvcnRzOiBbXCI1NDMzOjU0MzJcIl0sXG5cdFx0XHR2b2x1bWVzOiBbYCR7dm9sdW1lTmFtZX06L3Zhci9saWIvcG9zdGdyZXNxbC9kYXRhYF0sXG5cdFx0XHRuZXR3b3JrczogW3sgW25ldHdvcmtLZXldOiB7IGFsaWFzZXM6IFtcInBvc3RncmVzXCJdIH0gfV0sXG5cdFx0XHRoZWFsdGhjaGVjazoge1xuXHRcdFx0XHR0ZXN0OiBbXCJDTUQtU0hFTExcIiwgYHBnX2lzcmVhZHkgLVUgJHt1c2VyfSAtZCAke2RifWBdLFxuXHRcdFx0XHRpbnRlcnZhbDogXCIyc1wiLFxuXHRcdFx0XHR0aW1lb3V0OiBcIjVzXCIsXG5cdFx0XHRcdHJldHJpZXM6IDE1LFxuXHRcdFx0fSxcblx0XHR9KVxuXHRcdC5hZGRFbnZGaWxlKFwicG9zdGdyZXNcIiwgXCIuLi8uZW52XCIpXG5cdFx0LmFkZFZvbHVtZSh2b2x1bWVOYW1lKTtcblxuXHRjb21wb3NlPy5hZGRTZXJ2aWNlKFwiYWRtaW5lclwiLCB7XG5cdFx0aW1hZ2U6IFwiYWRtaW5lclwiLFxuXHRcdHBvcnRzOiBbXCI4MDgxOjgwODBcIl0sXG5cdFx0bmV0d29ya3M6IFtuZXR3b3JrS2V5XSxcblx0fSk7XG5cblx0Ly8gQWRkIFNRTFRvb2xzIGV4dGVuc2lvbiBmb3IgREIgYnJvd3NpbmcgaW4gVlMgQ29kZVxuXHRkZXZDb250YWluZXI/LmFkZEV4dGVuc2lvbihcIm10eHIuc3FsdG9vbHNcIik7XG5cblx0Ly8gV2lyZSB1cCBtYWluLnRzXG5cdHdvcmtzcGFjZVxuXHRcdC5nZXRNb2RlbDxNYWluU291cmNlRmlsZT4oV0VMTF9LTk9XTl9GSUxFUy5NQUlOX1RTKVxuXHRcdD8uYWRkU2lkZUVmZmVjdEltcG9ydChcIkBkZWNvaGVyZS9jb2RleC10eXBlb3JtXCIpXG5cdFx0LmFkZEVudGl0eSh7IGNsYXNzTmFtZTogXCJTYW1wbGVFbnRpdHlcIiwgaW1wb3J0UGF0aDogXCIuL2VudGl0aWVzL3NhbXBsZS5lbnRpdHkuanNcIiB9KVxuXHRcdC5hZGRSZXBvc2l0b3J5KHtcblx0XHRcdGNsYXNzTmFtZTogXCJTYW1wbGVFbnRpdHlSZXBvc2l0b3J5XCIsXG5cdFx0XHRpbXBvcnRQYXRoOiBcIi4vcmVwb3NpdG9yaWVzL3NhbXBsZS5yZXBvc2l0b3J5LmpzXCIsXG5cdFx0fSk7XG5cblx0d29ya3NwYWNlXG5cdFx0LmdldE1vZGVsPFBhY2thZ2VKc29uPihXRUxMX0tOT1dOX0ZJTEVTLlBBQ0tBR0VfSlNPTilcblx0XHQ/LmFkZERlcGVuZGVuY3koXCJAZGVjb2hlcmUvY29kZXhcIiwgQ1JFQVRFX1ZFUlNJT04pXG5cdFx0LmFkZERlcGVuZGVuY3koXCJ0eXBlb3JtXCIsIFwiXjAuMy4yOFwiKVxuXHRcdC5hZGREZXBlbmRlbmN5KFwiQGRlY29oZXJlL2NvZGV4LXR5cGVvcm1cIiwgQ1JFQVRFX1ZFUlNJT04pXG5cdFx0LmFkZFNjcmlwdChcImRiOnVwXCIsIFwiZG9ja2VyIGNvbXBvc2UgLWYgLmRldmNvbnRhaW5lci9kb2NrZXItY29tcG9zZS55bWwgdXAgLWQgcG9zdGdyZXNcIilcblx0XHQuYWRkU2NyaXB0KFwiZGI6ZG93blwiLCBcImRvY2tlciBjb21wb3NlIC1mIC5kZXZjb250YWluZXIvZG9ja2VyLWNvbXBvc2UueW1sIGRvd25cIilcblx0XHQuYWRkU2NyaXB0KFxuXHRcdFx0XCJkYjpyZXNldFwiLFxuXHRcdFx0XCJkb2NrZXIgY29tcG9zZSAtZiAuZGV2Y29udGFpbmVyL2RvY2tlci1jb21wb3NlLnltbCBkb3duIC12ICYmIGRvY2tlciBjb21wb3NlIC1mIC5kZXZjb250YWluZXIvZG9ja2VyLWNvbXBvc2UueW1sIHVwIC1kIHBvc3RncmVzXCIsXG5cdFx0KTtcblxuXHQvLyBBZGQgY29kZXggZGVwcyB0byBhcGkgcGFja2FnZS5qc29uXG5cdHdvcmtzcGFjZVxuXHRcdC5nZXRNb2RlbDxBcGlQYWNrYWdlSnNvbj4oV0VMTF9LTk9XTl9GSUxFUy5BUElfUEFDS0FHRV9KU09OKVxuXHRcdD8uYWRkRGVwZW5kZW5jeShcIkBkZWNvaGVyZS9jb2RleFwiLCBDUkVBVEVfVkVSU0lPTilcblx0XHQuYWRkRGVwZW5kZW5jeShcIkBkZWNvaGVyZS9jb2RleC10eXBlb3JtXCIsIENSRUFURV9WRVJTSU9OKTtcblxuXHQvLyBBcHBlbmQgZGF0YWJhc2UgY29uZmlnIHNlY3Rpb25zXG5cdHdvcmtzcGFjZVxuXHRcdC5nZXRNb2RlbDxDb25maWdZYW1sPihXRUxMX0tOT1dOX0ZJTEVTLkNPTkZJR19ZQU1MKVxuXHRcdD8uYWRkU2VjdGlvbihEQVRBQkFTRV9CQVNFX0NPTkZJR19ZQU1MKTtcblx0d29ya3NwYWNlXG5cdFx0LmdldE1vZGVsPENvbmZpZ1lhbWw+KFdFTExfS05PV05fRklMRVMuQ09ORklHX0RFVl9ZQU1MKVxuXHRcdD8uYWRkU2VjdGlvbihEQVRBQkFTRV9ERVZfQ09ORklHX1lBTUwpO1xuXG5cdC8vIFJlZ2lzdGVyIGVudGl0eSBhbmQgcmVwb3NpdG9yeSBzb3VyY2UgZmlsZXMgaW4gdGhlIGFwaSBwcm9qZWN0XG5cdHdvcmtzcGFjZS5nZXRQcm9qZWN0KFdFQkFQSV9QUk9KRUNUX0RJUik/LmFkZEZpbGUoe1xuXHRcdGZpbGVzOiAoKSA9PiBbXG5cdFx0XHR7XG5cdFx0XHRcdGZpbGVQYXRoOiBcInNyYy9lbnRpdGllcy9zYW1wbGUuZW50aXR5LnRzXCIsXG5cdFx0XHRcdGNvbnRlbnQ6IFNBTVBMRV9FTlRJVFlfVFMsXG5cdFx0XHR9LFxuXHRcdFx0e1xuXHRcdFx0XHRmaWxlUGF0aDogXCJzcmMvcmVwb3NpdG9yaWVzL3NhbXBsZS5yZXBvc2l0b3J5LnRzXCIsXG5cdFx0XHRcdGNvbnRlbnQ6IFNBTVBMRV9SRVBPU0lUT1JZX1RTLFxuXHRcdFx0fSxcblx0XHRdLFxuXHR9KTtcblxuXHQvLyAuZW52IGF0IHdvcmtzcGFjZSByb290IOKAlCBwb3N0Z3JlcyByZWFkcyBpdCB2aWEgZW52X2ZpbGUgYWJvdmU7IGRldmNvbnRhaW5lciBnZXRzIGl0IGhlcmVcblx0Y29tcG9zZT8uYWRkRW52RmlsZShcImRldmNvbnRhaW5lclwiLCBcIi4uLy5lbnZcIik7XG5cblx0d29ya3NwYWNlXG5cdFx0LmdldE1vZGVsPEVudkZpbGU+KFdFTExfS05PV05fRklMRVMuRU5WX0ZJTEUpXG5cdFx0Py5hZGRFbnRyeShcIlBPU1RHUkVTX0RCXCIsIGRiKVxuXHRcdC5hZGRFbnRyeShcIlBPU1RHUkVTX1VTRVJcIiwgdXNlcilcblx0XHQuYWRkRW50cnkoXCJQT1NUR1JFU19QQVNTV09SRFwiLCBwYXNzd29yZClcblx0XHQuYWRkRW50cnkoXCJEQl9IT1NUXCIsIFwicG9zdGdyZXNcIilcblx0XHQuYWRkRW50cnkoXCJEQl9QT1JUXCIsIFwiNTQzMlwiKVxuXHRcdC5hZGRFbnRyeShcIkRCX05BTUVcIiwgZGIpXG5cdFx0LmFkZEVudHJ5KFwiREJfVVNFUlwiLCB1c2VyKVxuXHRcdC5hZGRFbnRyeShcIkRCX1BBU1NXT1JEXCIsIHBhc3N3b3JkKVxuXHRcdC5hZGRFbnRyeShcIkRCX0FETUlOX1VTRVJcIiwgdXNlcilcblx0XHQuYWRkRW50cnkoXCJEQl9BRE1JTl9QQVNTV09SRFwiLCBwYXNzd29yZCk7XG59XG5cbmV4cG9ydCBjb25zdCBEYXRhYmFzZUZlYXR1cmU6IEZlYXR1cmU8RGF0YWJhc2VPcHRpb25zPiA9IHsgZ2V0T3B0aW9ucywgc2NhZmZvbGQgfTtcbiJdLCJuYW1lcyI6WyJyYW5kb21CeXRlcyIsInJlYWRGaWxlU3luYyIsImpvaW4iLCJwaWNrIiwiV0VMTF9LTk9XTl9GSUxFUyIsIkNSRUFURV9WRVJTSU9OIiwiV0VCQVBJX1BST0pFQ1RfRElSIiwicmVhZEV4aXN0aW5nRW52VmFsdWUiLCJ3b3Jrc3BhY2UiLCJrZXkiLCJyYXciLCJ0YXJnZXREaXIiLCJsaW5lIiwic3BsaXQiLCJmaW5kIiwibCIsInN0YXJ0c1dpdGgiLCJ2YWx1ZSIsInNsaWNlIiwibGVuZ3RoIiwidHJpbSIsInVuZGVmaW5lZCIsIkRBVEFCQVNFX0JBU0VfQ09ORklHX1lBTUwiLCJEQVRBQkFTRV9ERVZfQ09ORklHX1lBTUwiLCJTQU1QTEVfRU5USVRZX1RTIiwiU0FNUExFX1JFUE9TSVRPUllfVFMiLCJnZXRPcHRpb25zIiwiX3dvcmtzcGFjZSIsImNsaU9wdGlvbnMiLCJkYXRhYmFzZVByb3ZpZGVyIiwiY2hvaWNlcyIsImxhYmVsIiwic2VsZWN0ZWQiLCJjIiwic2NhZmZvbGQiLCJvcHRpb25zIiwibmFtZSIsImV4aXN0aW5nUGFzc3dvcmQiLCJwYXNzd29yZCIsInRvU3RyaW5nIiwiZGIiLCJ1c2VyIiwiZGV2Q29udGFpbmVyIiwiZ2V0TW9kZWwiLCJERVZDT05UQUlORVJfSlNPTiIsImNvbXBvc2UiLCJET0NLRVJfQ09NUE9TRSIsIm5ldHdvcmtLZXkiLCJ2b2x1bWVOYW1lIiwiYWRkU2VydmljZSIsImltYWdlIiwiY29udGFpbmVyX25hbWUiLCJyZXN0YXJ0IiwicG9ydHMiLCJ2b2x1bWVzIiwibmV0d29ya3MiLCJhbGlhc2VzIiwiaGVhbHRoY2hlY2siLCJ0ZXN0IiwiaW50ZXJ2YWwiLCJ0aW1lb3V0IiwicmV0cmllcyIsImFkZEVudkZpbGUiLCJhZGRWb2x1bWUiLCJhZGRFeHRlbnNpb24iLCJNQUlOX1RTIiwiYWRkU2lkZUVmZmVjdEltcG9ydCIsImFkZEVudGl0eSIsImNsYXNzTmFtZSIsImltcG9ydFBhdGgiLCJhZGRSZXBvc2l0b3J5IiwiUEFDS0FHRV9KU09OIiwiYWRkRGVwZW5kZW5jeSIsImFkZFNjcmlwdCIsIkFQSV9QQUNLQUdFX0pTT04iLCJDT05GSUdfWUFNTCIsImFkZFNlY3Rpb24iLCJDT05GSUdfREVWX1lBTUwiLCJnZXRQcm9qZWN0IiwiYWRkRmlsZSIsImZpbGVzIiwiZmlsZVBhdGgiLCJjb250ZW50IiwiRU5WX0ZJTEUiLCJhZGRFbnRyeSIsIkRhdGFiYXNlRmVhdHVyZSJdLCJtYXBwaW5ncyI6IkFBQUEsU0FBU0EsV0FBVyxRQUFRLGNBQWM7QUFDMUMsU0FBU0MsWUFBWSxRQUFRLFVBQVU7QUFDdkMsU0FBU0MsSUFBSSxRQUFRLFlBQVk7QUFDakMsU0FBU0MsSUFBSSxRQUFRLHlCQUF5QjtBQUc5QyxTQUFTQyxnQkFBZ0IsUUFBUSx3QkFBd0I7QUFNekQsU0FBU0MsY0FBYyxRQUFRLG1CQUFtQjtBQUNsRCxTQUFTQyxrQkFBa0IsUUFBUSxtQkFBbUI7QUFRdEQsZ0VBQWdFLEdBQ2hFLFNBQVNDLHFCQUFxQkMsU0FBNEIsRUFBRUMsR0FBVztJQUN0RSxJQUFJO1FBQ0gsTUFBTUMsTUFBTVQsYUFBYUMsS0FBS00sVUFBVUcsU0FBUyxFQUFFLFNBQVM7UUFDNUQsTUFBTUMsT0FBT0YsSUFBSUcsS0FBSyxDQUFDLE1BQU1DLElBQUksQ0FBQyxDQUFDQyxJQUFNQSxFQUFFQyxVQUFVLENBQUMsR0FBR1AsSUFBSSxDQUFDLENBQUM7UUFDL0Qs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