@nlabs/reaktor 1.9.1 → 1.11.0

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 (41) hide show
  1. package/README.md +5 -1
  2. package/docs/GENERATION.md +86 -0
  3. package/lib/actions/contentGeneration.d.ts +22 -1
  4. package/lib/actions/contentGeneration.js +84 -16
  5. package/lib/actions/databaseAccounts.d.ts +14 -0
  6. package/lib/actions/databaseAccounts.js +211 -0
  7. package/lib/actions/databaseProvisioningLease.d.ts +6 -0
  8. package/lib/actions/databaseProvisioningLease.js +166 -0
  9. package/lib/actions/higgsfield.d.ts +2 -0
  10. package/lib/actions/higgsfield.js +7 -1
  11. package/lib/actions/imageGeneration.d.ts +5 -1
  12. package/lib/actions/imageGeneration.js +13 -2
  13. package/lib/actions/index.d.ts +2 -0
  14. package/lib/actions/index.js +3 -1
  15. package/lib/actions/videoGeneration.d.ts +5 -1
  16. package/lib/actions/videoGeneration.js +13 -2
  17. package/lib/adapters/higgsfieldAdapter.d.ts +21 -15
  18. package/lib/adapters/higgsfieldAdapter.js +24 -11
  19. package/lib/adapters/higgsfieldModelCatalog.d.ts +10 -0
  20. package/lib/adapters/higgsfieldModelCatalog.js +5363 -0
  21. package/lib/adapters/higgsfieldModels.d.ts +2 -0
  22. package/lib/adapters/higgsfieldModels.js +37 -0
  23. package/lib/index.d.ts +4 -0
  24. package/lib/index.js +4 -1
  25. package/lib/objectTypes/contentGeneration.js +26 -3
  26. package/lib/objectTypes/imageGeneration.js +3 -2
  27. package/lib/objectTypes/videoGeneration.js +2 -1
  28. package/lib/types/databaseCredentials.types.d.ts +30 -0
  29. package/lib/types/databaseCredentials.types.js +3 -0
  30. package/lib/types/index.d.ts +1 -0
  31. package/lib/types/index.js +2 -1
  32. package/lib/utils/databaseCredentials.d.ts +5 -0
  33. package/lib/utils/databaseCredentials.js +100 -0
  34. package/lib/utils/generationCallback.d.ts +23 -0
  35. package/lib/utils/generationCallback.js +49 -0
  36. package/lib/utils/index.d.ts +3 -0
  37. package/lib/utils/index.js +4 -1
  38. package/lib/utils/secretDatabase.d.ts +8 -0
  39. package/lib/utils/secretDatabase.js +153 -0
  40. package/lib/utils/testUtils.js +10 -2
  41. package/package.json +12 -10
package/README.md CHANGED
@@ -188,7 +188,7 @@ The configuration is environment-aware and supports `local`, `development`, `tes
188
188
 
189
189
  #### Anonymous RUM Configuration
190
190
 
191
- The public `rum.track` mutation sanitizes GothamJS journey events and sends them to Amazon CloudWatch RUM with `PutRumEvents`. Reaktor does not persist RUM events in ArangoDB.
191
+ The public `rum.track` mutation sanitizes GothamUI journey events and sends them to Amazon CloudWatch RUM with `PutRumEvents`. Reaktor does not persist RUM events in ArangoDB.
192
192
 
193
193
  - `AWS_REGION` - AWS region containing the CloudWatch RUM app monitors.
194
194
  - `AWS_RUM_APP_MONITORS` - JSON object mapping each public application ID to its CloudWatch RUM app-monitor UUID. Values may also be objects with `id`, `name`, `version`, `domain`, and optional resource-policy `alias` fields.
@@ -1458,6 +1458,8 @@ package. See [LICENSE](./LICENSE) for the governing terms.
1458
1458
 
1459
1459
  See the [complete generation and sessions guide](docs/GENERATION.md) for the provider matrix, server configuration, results, storage, rejection handling, and release policy.
1460
1460
 
1461
+ `verifyGenerationCallbackToken` validates an expiring per-job callback capability; `parseGenerationCallback` normalizes bounded Higgsfield callback bodies into stable reconciliation events. Confirm outcomes through authenticated provider polling before media retention or credit settlement. See the guide for durable deduplication and callback security requirements.
1462
+
1461
1463
  ### Provider-driven content generation
1462
1464
 
1463
1465
  `generateContent(input, config?)` submits a single server-side request through Rip-Hunter to
@@ -1512,3 +1514,5 @@ The initial Veo adapter accepts 4, 6, or 8 seconds, with 1080p requiring 8 secon
1512
1514
  reference inputs are rejected. Helpers perform no database or filesystem writes.
1513
1515
  Keep durable jobs and reconciliation in the application: unknown submission outcomes
1514
1516
  must not be automatically retried. Gemini image results include `mimeType` for PNG/JPEG.
1517
+
1518
+ Higgsfield generation includes a typed catalog of 80 verified image/video API variants, model-specific JSON Schema validation, allowlisted submission, and optional callbacks. See [generation](docs/GENERATION.md).
@@ -46,6 +46,37 @@ Use `getGeminiVideoStatus(requestId, {key})` to poll an existing operation. When
46
46
 
47
47
  Use `s3Put`, `s3Get`, and `s3GetSignedUrl` with their optional `S3Client` parameter for application-specific connections, or omit it for Config-based behavior. Commit metadata and graph edges in ArangoDB only after retaining the media. Persist an output pointer before retrying settlement so recovery does not download or bill twice.
48
48
 
49
+ ## Generation callbacks
50
+
51
+ Higgsfield documents terminal JSON callbacks but does not currently document a webhook signature
52
+ protocol. Reaktor does not invent an HMAC signature contract. Use `createOpaqueToken` to issue a
53
+ separate callback capability for each job; persist `hashOpaqueToken(token)` and its expiry before
54
+ submitting the generation request. Include the token only in that job's HTTPS callback URL, and
55
+ redact it from access logs. Scope the stored capability lookup to the owning account and job.
56
+
57
+ `verifyGenerationCallbackToken(token, expectedHash, expiresAt, now?)` returns a boolean. Expiry and
58
+ `now` use Unix milliseconds; comparison uses constant-time SHA-256 hashes. This proves possession
59
+ of the application capability, not a Higgsfield signature. It intentionally allows valid redelivery
60
+ until expiry; the application must persist and deduplicate events transactionally.
61
+
62
+ After authentication, `parseGenerationCallback('higgsfield', rawBody, {maxBytes?})` accepts a Buffer
63
+ or JSON string and returns `{eventId, provider, requestId, status}`. The default limit is 64 KiB,
64
+ with a configurable ceiling of 1 MiB; enforce the same limit while reading the HTTP request.
65
+ Malformed JSON, invalid envelopes, unsupported providers, and nonterminal states are rejected.
66
+ `eventId` identifies the provider, request ID, and terminal status, so delivery retries have a
67
+ stable key. Payload media URLs and error text are deliberately excluded from this event.
68
+
69
+ Treat the callback as a reconciliation hint. Verify its request ID against the durable submission
70
+ and fetch the result through the provider's authenticated status API before saving media or
71
+ settling credits. Early callbacks require durable correlation with a pending job; they must never
72
+ create a job or charge from callback data alone. Retain media in S3, commit metadata/accounting
73
+ in ArangoDB, and publish WebSocket events only after those operations succeed. Keep polling as a
74
+ fallback. Store duplicates durably or recognize an existing committed event before returning 2xx.
75
+
76
+ The [official delivery contract](https://docs.higgsfield.ai/docs/how-to/webhooks) retries network/5xx
77
+ failures for up to two hours, treats 4xx as permanent, and requires responses within ten seconds.
78
+ Keep HTTP acknowledgement separate from long-running downloads and settlement.
79
+
49
80
  ## Opaque sessions and private media
50
81
 
51
82
  `createOpaqueToken`, `hashOpaqueToken`, `isOpaqueToken`, and `readOpaqueBearerToken` are opt-in primitives alongside existing JWT authentication. Store the token hash and expiry server-side; return the raw token only to the authenticated client. The application owns expiry checks, revocation, session persistence, and resource authorization.
@@ -61,3 +92,58 @@ Publish account-scoped events only after database commit. Clients should refresh
61
92
  ## Release policy
62
93
 
63
94
  Publish only plain `major.minor.patch` versions. Build with Lex, run tests and package verification, and inspect `npm pack --dry-run` before release. The `publish:*` convenience scripts also push Git branches/tags; publishing an audited tarball with `npm publish <archive> --access public` does not implicitly push a dirty working tree.
95
+
96
+ ## Full Higgsfield API catalog
97
+
98
+ `HIGGSFIELD_MODELS` contains the 80 public image/video endpoint variants verified on 2026-09-22 (14 image, 66 video). Every entry includes `id`, `kind`, `name`, its JSON `schema`, and the exact public documentation `source`. `getHiggsfieldModel(id)` rejects unknown routes. `validateHiggsfieldModelInput(id, input)` validates nested/conditional model inputs using Ajv.
99
+
100
+ Use `generateHiggsfieldModel(context, modelId, modelInput, callbackUrl)` for direct submission. The generic `generateImage` and `generateVideo` actions also accept `provider: 'higgsfield'`, `model`, and `modelInput`; GraphQL exposes the nested payload as JSON. Model inputs use the documented snake_case field names. No paid submission is automatically retried. Credentials stay in server Config; polling and cancellation continue to validate their fixed provider origin.
101
+
102
+ This catalog is a reviewed snapshot of https://open.higgsfield.ai/explore/image and /explore/video plus each endpoint's model-specific documentation. The older shared OpenAPI file and consumer website do not define the complete public API selection. Verify account access, output retention, and model-specific billing in the integrating application. Refresh this source snapshot and its schema tests when the published API catalog changes.
103
+
104
+
105
+ ## Advanced text generation (1.11.0)
106
+
107
+ OpenAI accepts either `prompt` or ordered text `messages` (never both). Message roles are
108
+ `system`, `developer`, `user`, and `assistant`; system messages become developer messages
109
+ without flattening or reordering the conversation. Existing prompt callers remain supported.
110
+
111
+ ```ts
112
+ const result = await generateContent({
113
+ maxTokens: 16000,
114
+ messages: [
115
+ {content: 'Return JSON containing a memories array.', role: 'system'},
116
+ {content: chapterText, role: 'user'}
117
+ ],
118
+ model: configuredModel,
119
+ provider: 'openai',
120
+ reasoningEffort: 'low',
121
+ responseFormat: {type: 'json_object'},
122
+ timeoutMs: 180000
123
+ }, {openaiKey: process.env.OPENAI_API_KEY});
124
+ const memories = JSON.parse(result.text); // Validate application-specific data before saving.
125
+ ```
126
+
127
+ `responseFormat` supports `{type: 'text'}`, `{type: 'json_object'}`, or
128
+ `{type: 'json_schema', name, schema, strict?, description?}`. `reasoningEffort` accepts
129
+ `none`, `minimal`, `low`, `medium`, `high`, `xhigh`, or `max`; model support is checked by the
130
+ provider. These fields and `messages` are currently OpenAI-only; other providers reject
131
+ them before submitting instead of silently dropping them. Image messages and tools are not
132
+ supported by this text action. Gemini's existing `images` input remains available.
133
+
134
+ `timeoutMs` applies to all providers and defaults to 120000. It must be a positive
135
+ 32-bit integer. A timeout does not prove the provider stopped working or did not charge.
136
+ There is no automatic retry or transport fallback. OpenAI requests disable storage and
137
+ input truncation. The authenticated `contents.generateContent` GraphQL mutation exposes
138
+ messages, response format, reasoning effort, and timeout as well.
139
+
140
+ The action returns only completed, non-empty output. OpenAI refusal, incomplete output
141
+ items, unsupported tool output, Claude unfinished turns, and Gemini blocked or unfinished
142
+ candidates raise `ContentGenerationResponseError`. Gemini requires `finishReason: 'STOP'`.
143
+ This error represents unusable output from a potentially paid request, not a confirmed
144
+ submission rejection. Transport errors propagate unchanged. Preserve jobs for reconciliation;
145
+ do not automatically repeat a paid POST. Interactive streaming, tools, and steering remain
146
+ application-owned.
147
+
148
+ The OpenAI mapping follows the [Responses API](https://developers.openai.com/api/reference/cli/resources/responses/methods/create)
149
+ and [structured output contract](https://developers.openai.com/api/docs/guides/structured-outputs).
@@ -7,6 +7,20 @@ export interface ContentGenerationConfig {
7
7
  openaiKey?: string;
8
8
  openaiModel?: string;
9
9
  }
10
+ export interface ContentGenerationMessage {
11
+ content: string;
12
+ role: 'assistant' | 'developer' | 'system' | 'user';
13
+ }
14
+ export type ContentGenerationResponseFormat = {
15
+ type: 'json_object' | 'text';
16
+ } | {
17
+ description?: string;
18
+ name: string;
19
+ schema: Record<string, unknown>;
20
+ strict?: boolean;
21
+ type: 'json_schema';
22
+ };
23
+ export type ContentGenerationReasoningEffort = 'none' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'max';
10
24
  export interface ContentGenerationInput {
11
25
  aspectRatio?: string;
12
26
  images?: {
@@ -14,12 +28,16 @@ export interface ContentGenerationInput {
14
28
  mime: string;
15
29
  }[];
16
30
  maxTokens?: number;
31
+ messages?: ContentGenerationMessage[];
17
32
  modality?: 'image' | 'text';
18
33
  model?: string;
19
- prompt: string;
34
+ prompt?: string;
20
35
  provider: 'claude' | 'gemini' | 'openai';
36
+ reasoningEffort?: ContentGenerationReasoningEffort;
37
+ responseFormat?: ContentGenerationResponseFormat;
21
38
  search?: boolean;
22
39
  system?: string;
40
+ timeoutMs?: number;
23
41
  }
24
42
  export interface GeneratedContent {
25
43
  image?: {
@@ -36,5 +54,8 @@ export interface GeneratedContent {
36
54
  /** A confirmed rejection is distinct from an unknown paid submission outcome. */
37
55
  export declare class ContentGenerationRejectedError extends Error {
38
56
  }
57
+ /** An accepted generation did not produce usable output; do not automatically resubmit it. */
58
+ export declare class ContentGenerationResponseError extends Error {
59
+ }
39
60
  /** Single submission through Rip-Hunter; callers own durable jobs and reconciliation. */
40
61
  export declare const generateContent: (input: ContentGenerationInput, config?: ContentGenerationConfig) => Promise<GeneratedContent>;
@@ -2,13 +2,52 @@ import { post } from '@nlabs/rip-hunter';
2
2
  import { Config } from '../config.js';
3
3
  /** A confirmed rejection is distinct from an unknown paid submission outcome. */ export class ContentGenerationRejectedError extends Error {
4
4
  }
5
+ /** An accepted generation did not produce usable output; do not automatically resubmit it. */ export class ContentGenerationResponseError extends Error {
6
+ }
5
7
  /** Single submission through Rip-Hunter; callers own durable jobs and reconciliation. */ export const generateContent = async (input, config = Config.get('contentGeneration') || {})=>{
6
8
  if (![
7
9
  'claude',
8
10
  'gemini',
9
11
  'openai'
10
- ].includes(input.provider) || !input.prompt?.trim()) {
11
- throw new ContentGenerationRejectedError('A supported provider and non-empty prompt are required.');
12
+ ].includes(input.provider)) {
13
+ throw new ContentGenerationRejectedError('A supported provider is required.');
14
+ }
15
+ if (input.messages !== undefined) {
16
+ if (input.prompt !== undefined || !Array.isArray(input.messages) || !input.messages.length || input.messages.some((message)=>!message || ![
17
+ 'assistant',
18
+ 'developer',
19
+ 'system',
20
+ 'user'
21
+ ].includes(message.role) || typeof message.content !== 'string' || !message.content.trim())) {
22
+ throw new ContentGenerationRejectedError('Supply either a non-empty prompt or non-empty text messages with supported roles.');
23
+ }
24
+ } else if (typeof input.prompt !== 'string' || !input.prompt.trim()) {
25
+ throw new ContentGenerationRejectedError('A non-empty prompt is required.');
26
+ }
27
+ if (input.provider !== 'openai' && (input.messages !== undefined || input.reasoningEffort !== undefined || input.responseFormat !== undefined)) {
28
+ throw new ContentGenerationRejectedError('Messages, reasoning effort, and response format are currently supported only by OpenAI.');
29
+ }
30
+ if (input.timeoutMs !== undefined && (!Number.isInteger(input.timeoutMs) || input.timeoutMs < 1 || input.timeoutMs > 2_147_483_647)) {
31
+ throw new ContentGenerationRejectedError('timeoutMs must be a positive 32-bit integer.');
32
+ }
33
+ if (input.reasoningEffort !== undefined && ![
34
+ 'none',
35
+ 'minimal',
36
+ 'low',
37
+ 'medium',
38
+ 'high',
39
+ 'xhigh',
40
+ 'max'
41
+ ].includes(input.reasoningEffort)) {
42
+ throw new ContentGenerationRejectedError('Unsupported reasoning effort.');
43
+ }
44
+ const format = input.responseFormat;
45
+ if (format !== undefined && (!format || ![
46
+ 'text',
47
+ 'json_object',
48
+ 'json_schema'
49
+ ].includes(format.type) || format.type === 'json_schema' && (typeof format.name !== 'string' || !/^[a-zA-Z0-9_-]{1,64}$/.test(format.name) || !format.schema || typeof format.schema !== 'object' || Array.isArray(format.schema) || format.strict !== undefined && typeof format.strict !== 'boolean'))) {
50
+ throw new ContentGenerationRejectedError('Invalid response format. JSON schemas require a name and schema object.');
12
51
  }
13
52
  if (input.maxTokens !== undefined && (!Number.isInteger(input.maxTokens) || input.maxTokens < 1)) {
14
53
  throw new ContentGenerationRejectedError('maxTokens must be a positive integer.');
@@ -37,7 +76,7 @@ import { Config } from '../config.js';
37
76
  'anthropic-version': '2023-06-01',
38
77
  'x-api-key': config.claudeKey
39
78
  }),
40
- timeout: 120_000
79
+ timeout: input.timeoutMs ?? 120_000
41
80
  });
42
81
  if (response.error && [
43
82
  'authentication_error',
@@ -49,7 +88,7 @@ import { Config } from '../config.js';
49
88
  }
50
89
  const text = response.content?.filter((part)=>part.type === 'text').map((part)=>part.text || '').join('\n').trim();
51
90
  if (response.error || response.type !== 'message' || response.stop_reason !== 'end_turn' || !text) {
52
- throw new Error('Claude response could not be confirmed.');
91
+ throw new ContentGenerationResponseError('Claude response could not be confirmed.');
53
92
  }
54
93
  return {
55
94
  sources: [],
@@ -61,17 +100,31 @@ import { Config } from '../config.js';
61
100
  throw new ContentGenerationRejectedError('OpenAI is not configured on this server.');
62
101
  }
63
102
  const response = await post('https://api.openai.com/v1/responses', {
64
- input: prompt,
103
+ input: input.messages?.map((message)=>({
104
+ content: message.content,
105
+ role: message.role === 'system' ? 'developer' : message.role
106
+ })) ?? prompt,
65
107
  instructions: input.system,
66
108
  max_output_tokens: input.maxTokens ?? 4096,
67
109
  model: input.model || config.openaiModel || 'gpt-6-astra',
68
- store: false
110
+ ...input.reasoningEffort ? {
111
+ reasoning: {
112
+ effort: input.reasoningEffort
113
+ }
114
+ } : {},
115
+ store: false,
116
+ ...format ? {
117
+ text: {
118
+ format
119
+ }
120
+ } : {},
121
+ truncation: 'disabled'
69
122
  }, {
70
123
  cache: false,
71
124
  headers: new Headers({
72
125
  Authorization: `Bearer ${config.openaiKey}`
73
126
  }),
74
- timeout: 120_000
127
+ timeout: input.timeoutMs ?? 120_000
75
128
  });
76
129
  if (response.error && [
77
130
  'invalid_request_error',
@@ -80,9 +133,21 @@ import { Config } from '../config.js';
80
133
  ].includes(response.error.type || '')) {
81
134
  throw new ContentGenerationRejectedError('OpenAI rejected the request. Check the model and account access.');
82
135
  }
83
- const text = response.output?.flatMap((output)=>output.content || []).filter((part)=>part.type === 'output_text').map((part)=>part.text || '').join('\n').trim();
84
- if (response.error || response.status !== 'completed' || !text) {
85
- throw new Error('OpenAI response could not be confirmed.');
136
+ if (response.error || response.status !== 'completed' || response.output?.some((item)=>item.status === 'incomplete')) {
137
+ throw new ContentGenerationResponseError('OpenAI response could not be confirmed: generation did not complete.');
138
+ }
139
+ if (response.output?.some((item)=>item.content?.some((part)=>part.type === 'refusal'))) {
140
+ throw new ContentGenerationResponseError('OpenAI declined the request.');
141
+ }
142
+ if (response.output?.some((item)=>item.type && ![
143
+ 'message',
144
+ 'reasoning'
145
+ ].includes(item.type))) {
146
+ throw new ContentGenerationResponseError('OpenAI returned an unsupported output item.');
147
+ }
148
+ const text = response.output?.filter((item)=>item.type === 'message').flatMap((item)=>item.content || []).filter((part)=>part.type === 'output_text').map((part)=>part.text || '').join('').trim();
149
+ if (!text) {
150
+ throw new ContentGenerationResponseError('OpenAI returned empty output.');
86
151
  }
87
152
  return {
88
153
  sources: [],
@@ -148,7 +213,7 @@ import { Config } from '../config.js';
148
213
  headers: new Headers({
149
214
  'x-goog-api-key': config.geminiKey
150
215
  }),
151
- timeout: 120_000
216
+ timeout: input.timeoutMs ?? 120_000
152
217
  });
153
218
  if (response.error && [
154
219
  400,
@@ -158,10 +223,13 @@ import { Config } from '../config.js';
158
223
  ].includes(response.error.code || 0)) {
159
224
  throw new ContentGenerationRejectedError('Gemini rejected the request. Check the reference format and model access.');
160
225
  }
161
- if (response.error || !response.candidates?.length) {
162
- throw new Error('Gemini response could not be confirmed.');
226
+ if (response.promptFeedback?.blockReason || response.error || !response.candidates?.length) {
227
+ throw new ContentGenerationResponseError('Gemini response could not be confirmed.');
163
228
  }
164
229
  const candidate = response.candidates[0];
230
+ if (candidate.finishReason !== 'STOP') {
231
+ throw new ContentGenerationResponseError('Gemini response could not be confirmed: generation did not complete.');
232
+ }
165
233
  const output = (candidate.content?.parts || []).filter((part)=>!part.thought);
166
234
  const inline = output.find((part)=>part.inlineData)?.inlineData;
167
235
  let image;
@@ -171,7 +239,7 @@ import { Config } from '../config.js';
171
239
  ].includes(inline.mimeType)) {
172
240
  const bytes = Buffer.from(inline.data, 'base64');
173
241
  if (!bytes.length || bytes.length > 20 * 1024 * 1024) {
174
- throw new Error('Invalid image output.');
242
+ throw new ContentGenerationResponseError('Invalid image output.');
175
243
  }
176
244
  image = {
177
245
  bytes,
@@ -180,7 +248,7 @@ import { Config } from '../config.js';
180
248
  }
181
249
  const text = output.map((part)=>part.text || '').join('\n').trim();
182
250
  if (input.modality === 'image' ? !image : !text) {
183
- throw new Error('The requested output was not returned.');
251
+ throw new ContentGenerationResponseError('The requested output was not returned.');
184
252
  }
185
253
  const sources = (candidate.groundingMetadata?.groundingChunks || []).flatMap(({ web })=>{
186
254
  try {
@@ -203,4 +271,4 @@ import { Config } from '../config.js';
203
271
  };
204
272
  };
205
273
 
206
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9Vc2Vycy9uaXRyb2c3L0RldmVsb3BtZW50L3JlYWt0b3IvcGFja2FnZXMvcmVha3Rvci9zcmMvYWN0aW9ucy9jb250ZW50R2VuZXJhdGlvbi50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge3Bvc3R9IGZyb20gJ0BubGFicy9yaXAtaHVudGVyJztcblxuaW1wb3J0IHtDb25maWd9IGZyb20gJy4uL2NvbmZpZy5qcyc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgQ29udGVudEdlbmVyYXRpb25Db25maWcge1xuICBjbGF1ZGVLZXk/OiBzdHJpbmc7XG4gIGNsYXVkZU1vZGVsPzogc3RyaW5nO1xuICBnZW1pbmlJbWFnZU1vZGVsPzogc3RyaW5nO1xuICBnZW1pbmlLZXk/OiBzdHJpbmc7XG4gIGdlbWluaU1vZGVsPzogc3RyaW5nO1xuICBvcGVuYWlLZXk/OiBzdHJpbmc7XG4gIG9wZW5haU1vZGVsPzogc3RyaW5nO1xufVxuZXhwb3J0IGludGVyZmFjZSBDb250ZW50R2VuZXJhdGlvbklucHV0IHtcbiAgYXNwZWN0UmF0aW8/OiBzdHJpbmc7XG4gIGltYWdlcz86IHtieXRlczogQnVmZmVyOyBtaW1lOiBzdHJpbmd9W107XG4gIG1heFRva2Vucz86IG51bWJlcjtcbiAgbW9kYWxpdHk/OiAnaW1hZ2UnIHwgJ3RleHQnO1xuICBtb2RlbD86IHN0cmluZztcbiAgcHJvbXB0OiBzdHJpbmc7XG4gIHByb3ZpZGVyOiAnY2xhdWRlJyB8ICdnZW1pbmknIHwgJ29wZW5haSc7XG4gIHNlYXJjaD86IGJvb2xlYW47XG4gIHN5c3RlbT86IHN0cmluZztcbn1cbmV4cG9ydCBpbnRlcmZhY2UgR2VuZXJhdGVkQ29udGVudCB7XG4gIGltYWdlPzoge2J5dGVzOiBCdWZmZXI7IG1pbWU6ICdpbWFnZS9qcGVnJyB8ICdpbWFnZS9wbmcnfTtcbiAgc2VhcmNoU3VnZ2VzdGlvbnNIdG1sPzogc3RyaW5nO1xuICBzb3VyY2VzOiB7dGl0bGU6IHN0cmluZzsgdXJsOiBzdHJpbmd9W107XG4gIHRleHQ6IHN0cmluZztcbn1cbi8qKiBBIGNvbmZpcm1lZCByZWplY3Rpb24gaXMgZGlzdGluY3QgZnJvbSBhbiB1bmtub3duIHBhaWQgc3VibWlzc2lvbiBvdXRjb21lLiAqL1xuZXhwb3J0IGNsYXNzIENvbnRlbnRHZW5lcmF0aW9uUmVqZWN0ZWRFcnJvciBleHRlbmRzIEVycm9yIHt9XG5cbmludGVyZmFjZSBHZW1pbmlQYXJ0IHtpbmxpbmVEYXRhPzoge2RhdGE6IHN0cmluZzsgbWltZVR5cGU6IHN0cmluZ307IHRleHQ/OiBzdHJpbmc7IHRob3VnaHQ/OiBib29sZWFufVxuaW50ZXJmYWNlIEdlbWluaVJlc3BvbnNlIHtcbiAgY2FuZGlkYXRlcz86IHtcbiAgICBjb250ZW50Pzoge3BhcnRzPzogR2VtaW5pUGFydFtdfTtcbiAgICBncm91bmRpbmdNZXRhZGF0YT86IHtcbiAgICAgIGdyb3VuZGluZ0NodW5rcz86IHt3ZWI/OiB7dGl0bGU/OiBzdHJpbmc7IHVyaT86IHN0cmluZ319W107XG4gICAgICBzZWFyY2hFbnRyeVBvaW50Pzoge3JlbmRlcmVkQ29udGVudD86IHN0cmluZ307XG4gICAgfTtcbiAgfVtdO1xuICBlcnJvcj86IHtjb2RlPzogbnVtYmVyfTtcbiAgcHJvbXB0RmVlZGJhY2s/OiB7YmxvY2tSZWFzb24/OiBzdHJpbmd9O1xufVxuXG4vKiogU2luZ2xlIHN1Ym1pc3Npb24gdGhyb3VnaCBSaXAtSHVudGVyOyBjYWxsZXJzIG93biBkdXJhYmxlIGpvYnMgYW5kIHJlY29uY2lsaWF0aW9uLiAqL1xuZXhwb3J0IGNvbnN0IGdlbmVyYXRlQ29udGVudCA9IGFzeW5jIChcbiAgaW5wdXQ6IENvbnRlbnRHZW5lcmF0aW9uSW5wdXQsXG4gIGNvbmZpZzogQ29udGVudEdlbmVyYXRpb25Db25maWcgPSBDb25maWcuZ2V0PENvbnRlbnRHZW5lcmF0aW9uQ29uZmlnPignY29udGVudEdlbmVyYXRpb24nKSB8fCB7fVxuKTogUHJvbWlzZTxHZW5lcmF0ZWRDb250ZW50PiA9PiB7XG4gIGlmKCFbJ2NsYXVkZScsICdnZW1pbmknLCAnb3BlbmFpJ10uaW5jbHVkZXMoaW5wdXQucHJvdmlkZXIpIHx8ICFpbnB1dC5wcm9tcHQ/LnRyaW0oKSkge1xuICAgIHRocm93IG5ldyBDb250ZW50R2VuZXJhdGlvblJlamVjdGVkRXJyb3IoJ0Egc3VwcG9ydGVkIHByb3ZpZGVyIGFuZCBub24tZW1wdHkgcHJvbXB0IGFyZSByZXF1aXJlZC4nKTtcbiAgfVxuICBpZihpbnB1dC5tYXhUb2tlbnMgIT09IHVuZGVmaW5lZCAmJiAoIU51bWJlci5pc0ludGVnZXIoaW5wdXQubWF4VG9rZW5zKSB8fCBpbnB1dC5tYXhUb2tlbnMgPCAxKSkge1xuICAgIHRocm93IG5ldyBDb250ZW50R2VuZXJhdGlvblJlamVjdGVkRXJyb3IoJ21heFRva2VucyBtdXN0IGJlIGEgcG9zaXRpdmUgaW50ZWdlci4nKTtcbiAgfVxuICBpZihpbnB1dC5wcm92aWRlciAhPT0gJ2dlbWluaScgJiYgKGlucHV0LmltYWdlcz8ubGVuZ3RoIHx8IGlucHV0Lm1vZGFsaXR5ID09PSAnaW1hZ2UnIHx8IGlucHV0LnNlYXJjaCkpIHtcbiAgICB0aHJvdyBuZXcgQ29udGVudEdlbmVyYXRpb25SZWplY3RlZEVycm9yKCdUaGlzIHByb3ZpZGVyIG9wZXJhdGlvbiBzdXBwb3J0cyB0ZXh0IGlucHV0IGFuZCBvdXRwdXQgb25seS4nKTtcbiAgfVxuICBjb25zdCB7cHJvbXB0LCBpbWFnZXMgPSBbXX0gPSBpbnB1dDtcbiAgaWYoaW5wdXQucHJvdmlkZXIgPT09ICdjbGF1ZGUnKSB7XG4gICAgaWYoIWNvbmZpZy5jbGF1ZGVLZXkpIHtcbiAgICAgIHRocm93IG5ldyBDb250ZW50R2VuZXJhdGlvblJlamVjdGVkRXJyb3IoJ0NsYXVkZSBpcyBub3QgY29uZmlndXJlZCBvbiB0aGlzIHNlcnZlci4nKTtcbiAgICB9XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBwb3N0KCdodHRwczovL2FwaS5hbnRocm9waWMuY29tL3YxL21lc3NhZ2VzJywge1xuICAgICAgbWF4X3Rva2VuczogaW5wdXQubWF4VG9rZW5zID8/IDQwOTYsXG4gICAgICBtZXNzYWdlczogW3tjb250ZW50OiBwcm9tcHQsIHJvbGU6ICd1c2VyJ31dLFxuICAgICAgbW9kZWw6IGlucHV0Lm1vZGVsIHx8IGNvbmZpZy5jbGF1ZGVNb2RlbCB8fCAnY2xhdWRlLXNvbm5ldC01JyxcbiAgICAgIHN5c3RlbTogaW5wdXQuc3lzdGVtXG4gICAgfSwge2NhY2hlOiBmYWxzZSwgaGVhZGVyczogbmV3IEhlYWRlcnMoeydhbnRocm9waWMtdmVyc2lvbic6ICcyMDIzLTA2LTAxJywgJ3gtYXBpLWtleSc6IGNvbmZpZy5jbGF1ZGVLZXl9KSwgdGltZW91dDogMTIwXzAwMH0pIGFzIHtcbiAgICAgIGNvbnRlbnQ/OiB7dGV4dD86IHN0cmluZzsgdHlwZT86IHN0cmluZ31bXTtcbiAgICAgIGVycm9yPzoge3R5cGU/OiBzdHJpbmd9O1xuICAgICAgc3RvcF9yZWFzb24/OiBzdHJpbmc7XG4gICAgICB0eXBlPzogc3RyaW5nO1xuICAgIH07XG4gICAgaWYocmVzcG9uc2UuZXJyb3IgJiYgWydhdXRoZW50aWNhdGlvbl9lcnJvcicsICdpbnZhbGlkX3JlcXVlc3RfZXJyb3InLCAnbm90X2ZvdW5kX2Vycm9yJywgJ3Blcm1pc3Npb25fZXJyb3InXS5pbmNsdWRlcyhyZXNwb25zZS5lcnJvci50eXBlIHx8ICcnKSkge1xuICAgICAgdGhyb3cgbmV3IENvbnRlbnRHZW5lcmF0aW9uUmVqZWN0ZWRFcnJvcignQ2xhdWRlIHJlamVjdGVkIHRoZSByZXF1ZXN0LiBDaGVjayB0aGUgbW9kZWwgYW5kIGFjY291bnQgYWNjZXNzLicpO1xuICAgIH1cbiAgICBjb25zdCB0ZXh0ID0gcmVzcG9uc2UuY29udGVudD8uZmlsdGVyKChwYXJ0KSA9PiBwYXJ0LnR5cGUgPT09ICd0ZXh0JykubWFwKChwYXJ0KSA9PiBwYXJ0LnRleHQgfHwgJycpLmpvaW4oJ1xcbicpLnRyaW0oKTtcbiAgICBpZihyZXNwb25zZS5lcnJvciB8fCByZXNwb25zZS50eXBlICE9PSAnbWVzc2FnZScgfHwgcmVzcG9uc2Uuc3RvcF9yZWFzb24gIT09ICdlbmRfdHVybicgfHwgIXRleHQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2xhdWRlIHJlc3BvbnNlIGNvdWxkIG5vdCBiZSBjb25maXJtZWQuJyk7XG4gICAgfVxuICAgIHJldHVybiB7c291cmNlczogW10sIHRleHR9O1xuICB9XG4gIGlmKGlucHV0LnByb3ZpZGVyID09PSAnb3BlbmFpJykge1xuICAgIGlmKCFjb25maWcub3BlbmFpS2V5KSB7XG4gICAgICB0aHJvdyBuZXcgQ29udGVudEdlbmVyYXRpb25SZWplY3RlZEVycm9yKCdPcGVuQUkgaXMgbm90IGNvbmZpZ3VyZWQgb24gdGhpcyBzZXJ2ZXIuJyk7XG4gICAgfVxuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgcG9zdCgnaHR0cHM6Ly9hcGkub3BlbmFpLmNvbS92MS9yZXNwb25zZXMnLCB7XG4gICAgICBpbnB1dDogcHJvbXB0LFxuICAgICAgaW5zdHJ1Y3Rpb25zOiBpbnB1dC5zeXN0ZW0sXG4gICAgICBtYXhfb3V0cHV0X3Rva2VuczogaW5wdXQubWF4VG9rZW5zID8/IDQwOTYsXG4gICAgICBtb2RlbDogaW5wdXQubW9kZWwgfHwgY29uZmlnLm9wZW5haU1vZGVsIHx8ICdncHQtNi1hc3RyYScsXG4gICAgICBzdG9yZTogZmFsc2VcbiAgICB9LCB7Y2FjaGU6IGZhbHNlLCBoZWFkZXJzOiBuZXcgSGVhZGVycyh7QXV0aG9yaXphdGlvbjogYEJlYXJlciAke2NvbmZpZy5vcGVuYWlLZXl9YH0pLCB0aW1lb3V0OiAxMjBfMDAwfSkgYXMge1xuICAgICAgZXJyb3I/OiB7Y29kZT86IHN0cmluZzsgdHlwZT86IHN0cmluZ307XG4gICAgICBvdXRwdXQ/OiB7Y29udGVudD86IHt0ZXh0Pzogc3RyaW5nOyB0eXBlPzogc3RyaW5nfVtdfVtdO1xuICAgICAgc3RhdHVzPzogc3RyaW5nO1xuICAgIH07XG4gICAgaWYocmVzcG9uc2UuZXJyb3IgJiYgWydpbnZhbGlkX3JlcXVlc3RfZXJyb3InLCAnYXV0aGVudGljYXRpb25fZXJyb3InLCAncGVybWlzc2lvbl9lcnJvciddLmluY2x1ZGVzKHJlc3BvbnNlLmVycm9yLnR5cGUgfHwgJycpKSB7XG4gICAgICB0aHJvdyBuZXcgQ29udGVudEdlbmVyYXRpb25SZWplY3RlZEVycm9yKCdPcGVuQUkgcmVqZWN0ZWQgdGhlIHJlcXVlc3QuIENoZWNrIHRoZSBtb2RlbCBhbmQgYWNjb3VudCBhY2Nlc3MuJyk7XG4gICAgfVxuICAgIGNvbnN0IHRleHQgPSByZXNwb25zZS5vdXRwdXQ/LmZsYXRNYXAoKG91dHB1dCkgPT4gb3V0cHV0LmNvbnRlbnQgfHwgW10pLmZpbHRlcigocGFydCkgPT4gcGFydC50eXBlID09PSAnb3V0cHV0X3RleHQnKS5tYXAoKHBhcnQpID0+IHBhcnQudGV4dCB8fCAnJykuam9pbignXFxuJykudHJpbSgpO1xuICAgIGlmKHJlc3BvbnNlLmVycm9yIHx8IHJlc3BvbnNlLnN0YXR1cyAhPT0gJ2NvbXBsZXRlZCcgfHwgIXRleHQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignT3BlbkFJIHJlc3BvbnNlIGNvdWxkIG5vdCBiZSBjb25maXJtZWQuJyk7XG4gICAgfVxuICAgIHJldHVybiB7c291cmNlczogW10sIHRleHR9O1xuICB9XG4gIGlmKCFjb25maWcuZ2VtaW5pS2V5KSB7XG4gICAgdGhyb3cgbmV3IENvbnRlbnRHZW5lcmF0aW9uUmVqZWN0ZWRFcnJvcignR2VtaW5pIGlzIG5vdCBjb25maWd1cmVkIG9uIHRoaXMgc2VydmVyLicpO1xuICB9XG4gIGNvbnN0IHBhcnRzOiB1bmtub3duW10gPSBbe3RleHQ6IHByb21wdH0sIC4uLmltYWdlcy5tYXAoKGltYWdlKSA9PiAoe2lubGluZURhdGE6IHtkYXRhOiBpbWFnZS5ieXRlcy50b1N0cmluZygnYmFzZTY0JyksIG1pbWVUeXBlOiBpbWFnZS5taW1lfX0pKV07XG4gIGNvbnN0IG1vZGVsID0gaW5wdXQubW9kZWwgfHwgKGlucHV0Lm1vZGFsaXR5ID09PSAnaW1hZ2UnID8gY29uZmlnLmdlbWluaUltYWdlTW9kZWwgfHwgJ2dlbWluaS0zLjEtZmxhc2gtaW1hZ2UnIDogY29uZmlnLmdlbWluaU1vZGVsIHx8ICdnZW1pbmktMy44LWZsYXNoJyk7XG4gIGlmKCEvXlthLXpBLVowLTkuXy1dKyQvLnRlc3QobW9kZWwpKSB7XG4gICAgdGhyb3cgbmV3IENvbnRlbnRHZW5lcmF0aW9uUmVqZWN0ZWRFcnJvcignSW52YWxpZCBHZW1pbmkgbW9kZWwgY29uZmlndXJhdGlvbi4nKTtcbiAgfVxuICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHBvc3QoYGh0dHBzOi8vZ2VuZXJhdGl2ZWxhbmd1YWdlLmdvb2dsZWFwaXMuY29tL3YxYmV0YS9tb2RlbHMvJHttb2RlbH06Z2VuZXJhdGVDb250ZW50YCwge1xuICAgIGNvbnRlbnRzOiBbe3BhcnRzLCByb2xlOiAndXNlcid9XSxcbiAgICAuLi4oaW5wdXQuc3lzdGVtID8ge3N5c3RlbUluc3RydWN0aW9uOiB7cGFydHM6IFt7dGV4dDogaW5wdXQuc3lzdGVtfV19fSA6IHt9KSxcbiAgICBnZW5lcmF0aW9uQ29uZmlnOiBpbnB1dC5tb2RhbGl0eSA9PT0gJ2ltYWdlJyA/IHsuLi4oaW5wdXQuYXNwZWN0UmF0aW8gPyB7aW1hZ2VDb25maWc6IHthc3BlY3RSYXRpbzogaW5wdXQuYXNwZWN0UmF0aW99fSA6IHt9KSwgcmVzcG9uc2VNb2RhbGl0aWVzOiBbJ1RFWFQnLCAnSU1BR0UnXX0gOiB7bWF4T3V0cHV0VG9rZW5zOiBpbnB1dC5tYXhUb2tlbnMgPz8gNDA5Nn0sXG4gICAgLi4uKGlucHV0LnNlYXJjaCA/IHt0b29sczogW3tnb29nbGVTZWFyY2g6IHt9fV19IDoge30pXG4gIH0sIHtjYWNoZTogZmFsc2UsIGhlYWRlcnM6IG5ldyBIZWFkZXJzKHsneC1nb29nLWFwaS1rZXknOiBjb25maWcuZ2VtaW5pS2V5fSksIHRpbWVvdXQ6IDEyMF8wMDB9KSBhcyBHZW1pbmlSZXNwb25zZTtcbiAgaWYocmVzcG9uc2UuZXJyb3IgJiYgWzQwMCwgNDAxLCA0MDMsIDQwNF0uaW5jbHVkZXMocmVzcG9uc2UuZXJyb3IuY29kZSB8fCAwKSkge1xuICAgIHRocm93IG5ldyBDb250ZW50R2VuZXJhdGlvblJlamVjdGVkRXJyb3IoJ0dlbWluaSByZWplY3RlZCB0aGUgcmVxdWVzdC4gQ2hlY2sgdGhlIHJlZmVyZW5jZSBmb3JtYXQgYW5kIG1vZGVsIGFjY2Vzcy4nKTtcbiAgfVxuICBpZihyZXNwb25zZS5lcnJvciB8fCAhcmVzcG9uc2UuY2FuZGlkYXRlcz8ubGVuZ3RoKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdHZW1pbmkgcmVzcG9uc2UgY291bGQgbm90IGJlIGNvbmZpcm1lZC4nKTtcbiAgfVxuICBjb25zdCBjYW5kaWRhdGUgPSByZXNwb25zZS5jYW5kaWRhdGVzWzBdITtcbiAgY29uc3Qgb3V0cHV0ID0gKGNhbmRpZGF0ZS5jb250ZW50Py5wYXJ0cyB8fCBbXSkuZmlsdGVyKChwYXJ0KSA9PiAhcGFydC50aG91Z2h0KTtcbiAgY29uc3QgaW5saW5lID0gb3V0cHV0LmZpbmQoKHBhcnQpID0+IHBhcnQuaW5saW5lRGF0YSk/LmlubGluZURhdGE7XG4gIGxldCBpbWFnZTogR2VuZXJhdGVkQ29udGVudFsnaW1hZ2UnXTtcbiAgaWYoaW5saW5lICYmIFsnaW1hZ2UvcG5nJywgJ2ltYWdlL2pwZWcnXS5pbmNsdWRlcyhpbmxpbmUubWltZVR5cGUpKSB7XG4gICAgY29uc3QgYnl0ZXMgPSBCdWZmZXIuZnJvbShpbmxpbmUuZGF0YSwgJ2Jhc2U2NCcpO1xuICAgIGlmKCFieXRlcy5sZW5ndGggfHwgYnl0ZXMubGVuZ3RoID4gMjAgKiAxMDI0ICogMTAyNCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGltYWdlIG91dHB1dC4nKTtcbiAgICB9XG4gICAgaW1hZ2UgPSB7Ynl0ZXMsIG1pbWU6IGlubGluZS5taW1lVHlwZSBhcyAnaW1hZ2UvcG5nJyB8ICdpbWFnZS9qcGVnJ307XG4gIH1cbiAgY29uc3QgdGV4dCA9IG91dHB1dC5tYXAoKHBhcnQpID0+IHBhcnQudGV4dCB8fCAnJykuam9pbignXFxuJykudHJpbSgpO1xuICBpZihpbnB1dC5tb2RhbGl0eSA9PT0gJ2ltYWdlJyA/ICFpbWFnZSA6ICF0ZXh0KSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdUaGUgcmVxdWVzdGVkIG91dHB1dCB3YXMgbm90IHJldHVybmVkLicpO1xuICB9XG4gIGNvbnN0IHNvdXJjZXMgPSAoY2FuZGlkYXRlLmdyb3VuZGluZ01ldGFkYXRhPy5ncm91bmRpbmdDaHVua3MgfHwgW10pLmZsYXRNYXAoKHt3ZWJ9KSA9PiB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHVybCA9IG5ldyBVUkwod2ViPy51cmkgfHwgJycpO1xuICAgICAgcmV0dXJuIHVybC5wcm90b2NvbCA9PT0gJ2h0dHBzOicgPyBbe3RpdGxlOiB3ZWI/LnRpdGxlIHx8IHVybC5ob3N0bmFtZSwgdXJsOiB1cmwuaHJlZn1dIDogW107XG4gICAgfSBjYXRjaHtcbiAgICAgIHJldHVybiBbXTtcbiAgICB9XG4gIH0pO1xuICByZXR1cm4ge1xuICAgIGltYWdlLCBzZWFyY2hTdWdnZXN0aW9uc0h0bWw6IGNhbmRpZGF0ZS5ncm91bmRpbmdNZXRhZGF0YT8uc2VhcmNoRW50cnlQb2ludD8ucmVuZGVyZWRDb250ZW50LCBzb3VyY2VzLCB0ZXh0XG4gIH07XG59O1xuIl0sIm5hbWVzIjpbInBvc3QiLCJDb25maWciLCJDb250ZW50R2VuZXJhdGlvblJlamVjdGVkRXJyb3IiLCJFcnJvciIsImdlbmVyYXRlQ29udGVudCIsImlucHV0IiwiY29uZmlnIiwiZ2V0IiwiaW5jbHVkZXMiLCJwcm92aWRlciIsInByb21wdCIsInRyaW0iLCJtYXhUb2tlbnMiLCJ1bmRlZmluZWQiLCJOdW1iZXIiLCJpc0ludGVnZXIiLCJpbWFnZXMiLCJsZW5ndGgiLCJtb2RhbGl0eSIsInNlYXJjaCIsImNsYXVkZUtleSIsInJlc3BvbnNlIiwibWF4X3Rva2VucyIsIm1lc3NhZ2VzIiwiY29udGVudCIsInJvbGUiLCJtb2RlbCIsImNsYXVkZU1vZGVsIiwic3lzdGVtIiwiY2FjaGUiLCJoZWFkZXJzIiwiSGVhZGVycyIsInRpbWVvdXQiLCJlcnJvciIsInR5cGUiLCJ0ZXh0IiwiZmlsdGVyIiwicGFydCIsIm1hcCIsImpvaW4iLCJzdG9wX3JlYXNvbiIsInNvdXJjZXMiLCJvcGVuYWlLZXkiLCJpbnN0cnVjdGlvbnMiLCJtYXhfb3V0cHV0X3Rva2VucyIsIm9wZW5haU1vZGVsIiwic3RvcmUiLCJBdXRob3JpemF0aW9uIiwib3V0cHV0IiwiZmxhdE1hcCIsInN0YXR1cyIsImdlbWluaUtleSIsInBhcnRzIiwiaW1hZ2UiLCJpbmxpbmVEYXRhIiwiZGF0YSIsImJ5dGVzIiwidG9TdHJpbmciLCJtaW1lVHlwZSIsIm1pbWUiLCJnZW1pbmlJbWFnZU1vZGVsIiwiZ2VtaW5pTW9kZWwiLCJ0ZXN0IiwiY29udGVudHMiLCJzeXN0ZW1JbnN0cnVjdGlvbiIsImdlbmVyYXRpb25Db25maWciLCJhc3BlY3RSYXRpbyIsImltYWdlQ29uZmlnIiwicmVzcG9uc2VNb2RhbGl0aWVzIiwibWF4T3V0cHV0VG9rZW5zIiwidG9vbHMiLCJnb29nbGVTZWFyY2giLCJjb2RlIiwiY2FuZGlkYXRlcyIsImNhbmRpZGF0ZSIsInRob3VnaHQiLCJpbmxpbmUiLCJmaW5kIiwiQnVmZmVyIiwiZnJvbSIsImdyb3VuZGluZ01ldGFkYXRhIiwiZ3JvdW5kaW5nQ2h1bmtzIiwid2ViIiwidXJsIiwiVVJMIiwidXJpIiwicHJvdG9jb2wiLCJ0aXRsZSIsImhvc3RuYW1lIiwiaHJlZiIsInNlYXJjaFN1Z2dlc3Rpb25zSHRtbCIsInNlYXJjaEVudHJ5UG9pbnQiLCJyZW5kZXJlZENvbnRlbnQiXSwibWFwcGluZ3MiOiJBQUFBLFNBQVFBLElBQUksUUFBTyxvQkFBb0I7QUFFdkMsU0FBUUMsTUFBTSxRQUFPLGVBQWU7QUE0QnBDLCtFQUErRSxHQUMvRSxPQUFPLE1BQU1DLHVDQUF1Q0M7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
274
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9Vc2Vycy9uaXRyb2c3L0RldmVsb3BtZW50L3JlYWt0b3IvcGFja2FnZXMvcmVha3Rvci9zcmMvYWN0aW9ucy9jb250ZW50R2VuZXJhdGlvbi50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge3Bvc3R9IGZyb20gJ0BubGFicy9yaXAtaHVudGVyJztcblxuaW1wb3J0IHtDb25maWd9IGZyb20gJy4uL2NvbmZpZy5qcyc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgQ29udGVudEdlbmVyYXRpb25Db25maWcge1xuICBjbGF1ZGVLZXk/OiBzdHJpbmc7XG4gIGNsYXVkZU1vZGVsPzogc3RyaW5nO1xuICBnZW1pbmlJbWFnZU1vZGVsPzogc3RyaW5nO1xuICBnZW1pbmlLZXk/OiBzdHJpbmc7XG4gIGdlbWluaU1vZGVsPzogc3RyaW5nO1xuICBvcGVuYWlLZXk/OiBzdHJpbmc7XG4gIG9wZW5haU1vZGVsPzogc3RyaW5nO1xufVxuZXhwb3J0IGludGVyZmFjZSBDb250ZW50R2VuZXJhdGlvbk1lc3NhZ2Uge1xuICBjb250ZW50OiBzdHJpbmc7XG4gIHJvbGU6ICdhc3Npc3RhbnQnIHwgJ2RldmVsb3BlcicgfCAnc3lzdGVtJyB8ICd1c2VyJztcbn1cbmV4cG9ydCB0eXBlIENvbnRlbnRHZW5lcmF0aW9uUmVzcG9uc2VGb3JtYXQgPSB7dHlwZTogJ2pzb25fb2JqZWN0JyB8ICd0ZXh0J30gfCB7XG4gIGRlc2NyaXB0aW9uPzogc3RyaW5nO1xuICBuYW1lOiBzdHJpbmc7XG4gIHNjaGVtYTogUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gIHN0cmljdD86IGJvb2xlYW47XG4gIHR5cGU6ICdqc29uX3NjaGVtYSc7XG59O1xuZXhwb3J0IHR5cGUgQ29udGVudEdlbmVyYXRpb25SZWFzb25pbmdFZmZvcnQgPSAnbm9uZScgfCAnbWluaW1hbCcgfCAnbG93JyB8ICdtZWRpdW0nIHwgJ2hpZ2gnIHwgJ3hoaWdoJyB8ICdtYXgnO1xuXG5leHBvcnQgaW50ZXJmYWNlIENvbnRlbnRHZW5lcmF0aW9uSW5wdXQge1xuICBhc3BlY3RSYXRpbz86IHN0cmluZztcbiAgaW1hZ2VzPzoge2J5dGVzOiBCdWZmZXI7IG1pbWU6IHN0cmluZ31bXTtcbiAgbWF4VG9rZW5zPzogbnVtYmVyO1xuICBtZXNzYWdlcz86IENvbnRlbnRHZW5lcmF0aW9uTWVzc2FnZVtdO1xuICBtb2RhbGl0eT86ICdpbWFnZScgfCAndGV4dCc7XG4gIG1vZGVsPzogc3RyaW5nO1xuICBwcm9tcHQ/OiBzdHJpbmc7XG4gIHByb3ZpZGVyOiAnY2xhdWRlJyB8ICdnZW1pbmknIHwgJ29wZW5haSc7XG4gIHJlYXNvbmluZ0VmZm9ydD86IENvbnRlbnRHZW5lcmF0aW9uUmVhc29uaW5nRWZmb3J0O1xuICByZXNwb25zZUZvcm1hdD86IENvbnRlbnRHZW5lcmF0aW9uUmVzcG9uc2VGb3JtYXQ7XG4gIHNlYXJjaD86IGJvb2xlYW47XG4gIHN5c3RlbT86IHN0cmluZztcbiAgdGltZW91dE1zPzogbnVtYmVyO1xufVxuZXhwb3J0IGludGVyZmFjZSBHZW5lcmF0ZWRDb250ZW50IHtcbiAgaW1hZ2U/OiB7Ynl0ZXM6IEJ1ZmZlcjsgbWltZTogJ2ltYWdlL2pwZWcnIHwgJ2ltYWdlL3BuZyd9O1xuICBzZWFyY2hTdWdnZXN0aW9uc0h0bWw/OiBzdHJpbmc7XG4gIHNvdXJjZXM6IHt0aXRsZTogc3RyaW5nOyB1cmw6IHN0cmluZ31bXTtcbiAgdGV4dDogc3RyaW5nO1xufVxuLyoqIEEgY29uZmlybWVkIHJlamVjdGlvbiBpcyBkaXN0aW5jdCBmcm9tIGFuIHVua25vd24gcGFpZCBzdWJtaXNzaW9uIG91dGNvbWUuICovXG5leHBvcnQgY2xhc3MgQ29udGVudEdlbmVyYXRpb25SZWplY3RlZEVycm9yIGV4dGVuZHMgRXJyb3Ige31cbi8qKiBBbiBhY2NlcHRlZCBnZW5lcmF0aW9uIGRpZCBub3QgcHJvZHVjZSB1c2FibGUgb3V0cHV0OyBkbyBub3QgYXV0b21hdGljYWxseSByZXN1Ym1pdCBpdC4gKi9cbmV4cG9ydCBjbGFzcyBDb250ZW50R2VuZXJhdGlvblJlc3BvbnNlRXJyb3IgZXh0ZW5kcyBFcnJvciB7fVxuXG5pbnRlcmZhY2UgR2VtaW5pUGFydCB7aW5saW5lRGF0YT86IHtkYXRhOiBzdHJpbmc7IG1pbWVUeXBlOiBzdHJpbmd9OyB0ZXh0Pzogc3RyaW5nOyB0aG91Z2h0PzogYm9vbGVhbn1cbmludGVyZmFjZSBHZW1pbmlSZXNwb25zZSB7XG4gIGNhbmRpZGF0ZXM/OiB7XG4gICAgY29udGVudD86IHtwYXJ0cz86IEdlbWluaVBhcnRbXX07XG4gICAgZmluaXNoUmVhc29uPzogc3RyaW5nO1xuICAgIGdyb3VuZGluZ01ldGFkYXRhPzoge1xuICAgICAgZ3JvdW5kaW5nQ2h1bmtzPzoge3dlYj86IHt0aXRsZT86IHN0cmluZzsgdXJpPzogc3RyaW5nfX1bXTtcbiAgICAgIHNlYXJjaEVudHJ5UG9pbnQ/OiB7cmVuZGVyZWRDb250ZW50Pzogc3RyaW5nfTtcbiAgICB9O1xuICB9W107XG4gIGVycm9yPzoge2NvZGU/OiBudW1iZXJ9O1xuICBwcm9tcHRGZWVkYmFjaz86IHtibG9ja1JlYXNvbj86IHN0cmluZ307XG59XG5cbi8qKiBTaW5nbGUgc3VibWlzc2lvbiB0aHJvdWdoIFJpcC1IdW50ZXI7IGNhbGxlcnMgb3duIGR1cmFibGUgam9icyBhbmQgcmVjb25jaWxpYXRpb24uICovXG5leHBvcnQgY29uc3QgZ2VuZXJhdGVDb250ZW50ID0gYXN5bmMgKFxuICBpbnB1dDogQ29udGVudEdlbmVyYXRpb25JbnB1dCxcbiAgY29uZmlnOiBDb250ZW50R2VuZXJhdGlvbkNvbmZpZyA9IENvbmZpZy5nZXQ8Q29udGVudEdlbmVyYXRpb25Db25maWc+KCdjb250ZW50R2VuZXJhdGlvbicpIHx8IHt9XG4pOiBQcm9taXNlPEdlbmVyYXRlZENvbnRlbnQ+ID0+IHtcbiAgaWYoIVsnY2xhdWRlJywgJ2dlbWluaScsICdvcGVuYWknXS5pbmNsdWRlcyhpbnB1dC5wcm92aWRlcikpIHtcbiAgICB0aHJvdyBuZXcgQ29udGVudEdlbmVyYXRpb25SZWplY3RlZEVycm9yKCdBIHN1cHBvcnRlZCBwcm92aWRlciBpcyByZXF1aXJlZC4nKTtcbiAgfVxuICBpZihpbnB1dC5tZXNzYWdlcyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgaWYoaW5wdXQucHJvbXB0ICE9PSB1bmRlZmluZWQgfHwgIUFycmF5LmlzQXJyYXkoaW5wdXQubWVzc2FnZXMpIHx8ICFpbnB1dC5tZXNzYWdlcy5sZW5ndGggfHwgaW5wdXQubWVzc2FnZXMuc29tZSgobWVzc2FnZSkgPT5cbiAgICAgICFtZXNzYWdlIHx8ICFbJ2Fzc2lzdGFudCcsICdkZXZlbG9wZXInLCAnc3lzdGVtJywgJ3VzZXInXS5pbmNsdWRlcyhtZXNzYWdlLnJvbGUpIHx8IHR5cGVvZiBtZXNzYWdlLmNvbnRlbnQgIT09ICdzdHJpbmcnIHx8ICFtZXNzYWdlLmNvbnRlbnQudHJpbSgpKSkge1xuICAgICAgdGhyb3cgbmV3IENvbnRlbnRHZW5lcmF0aW9uUmVqZWN0ZWRFcnJvcignU3VwcGx5IGVpdGhlciBhIG5vbi1lbXB0eSBwcm9tcHQgb3Igbm9uLWVtcHR5IHRleHQgbWVzc2FnZXMgd2l0aCBzdXBwb3J0ZWQgcm9sZXMuJyk7XG4gICAgfVxuICB9IGVsc2UgaWYodHlwZW9mIGlucHV0LnByb21wdCAhPT0gJ3N0cmluZycgfHwgIWlucHV0LnByb21wdC50cmltKCkpIHtcbiAgICB0aHJvdyBuZXcgQ29udGVudEdlbmVyYXRpb25SZWplY3RlZEVycm9yKCdBIG5vbi1lbXB0eSBwcm9tcHQgaXMgcmVxdWlyZWQuJyk7XG4gIH1cbiAgaWYoaW5wdXQucHJvdmlkZXIgIT09ICdvcGVuYWknICYmIChpbnB1dC5tZXNzYWdlcyAhPT0gdW5kZWZpbmVkIHx8IGlucHV0LnJlYXNvbmluZ0VmZm9ydCAhPT0gdW5kZWZpbmVkIHx8IGlucHV0LnJlc3BvbnNlRm9ybWF0ICE9PSB1bmRlZmluZWQpKSB7XG4gICAgdGhyb3cgbmV3IENvbnRlbnRHZW5lcmF0aW9uUmVqZWN0ZWRFcnJvcignTWVzc2FnZXMsIHJlYXNvbmluZyBlZmZvcnQsIGFuZCByZXNwb25zZSBmb3JtYXQgYXJlIGN1cnJlbnRseSBzdXBwb3J0ZWQgb25seSBieSBPcGVuQUkuJyk7XG4gIH1cbiAgaWYoaW5wdXQudGltZW91dE1zICE9PSB1bmRlZmluZWQgJiYgKCFOdW1iZXIuaXNJbnRlZ2VyKGlucHV0LnRpbWVvdXRNcykgfHwgaW5wdXQudGltZW91dE1zIDwgMSB8fCBpbnB1dC50aW1lb3V0TXMgPiAyXzE0N180ODNfNjQ3KSkge1xuICAgIHRocm93IG5ldyBDb250ZW50R2VuZXJhdGlvblJlamVjdGVkRXJyb3IoJ3RpbWVvdXRNcyBtdXN0IGJlIGEgcG9zaXRpdmUgMzItYml0IGludGVnZXIuJyk7XG4gIH1cbiAgaWYoaW5wdXQucmVhc29uaW5nRWZmb3J0ICE9PSB1bmRlZmluZWQgJiYgIVsnbm9uZScsICdtaW5pbWFsJywgJ2xvdycsICdtZWRpdW0nLCAnaGlnaCcsICd4aGlnaCcsICdtYXgnXS5pbmNsdWRlcyhpbnB1dC5yZWFzb25pbmdFZmZvcnQpKSB7XG4gICAgdGhyb3cgbmV3IENvbnRlbnRHZW5lcmF0aW9uUmVqZWN0ZWRFcnJvcignVW5zdXBwb3J0ZWQgcmVhc29uaW5nIGVmZm9ydC4nKTtcbiAgfVxuICBjb25zdCBmb3JtYXQgPSBpbnB1dC5yZXNwb25zZUZvcm1hdDtcbiAgaWYoZm9ybWF0ICE9PSB1bmRlZmluZWQgJiYgKCFmb3JtYXQgfHwgIVsndGV4dCcsICdqc29uX29iamVjdCcsICdqc29uX3NjaGVtYSddLmluY2x1ZGVzKGZvcm1hdC50eXBlKSB8fCAoZm9ybWF0LnR5cGUgPT09ICdqc29uX3NjaGVtYScgJiYgKFxuICAgIHR5cGVvZiBmb3JtYXQubmFtZSAhPT0gJ3N0cmluZycgfHwgIS9eW2EtekEtWjAtOV8tXXsxLDY0fSQvLnRlc3QoZm9ybWF0Lm5hbWUpIHx8ICFmb3JtYXQuc2NoZW1hIHx8IHR5cGVvZiBmb3JtYXQuc2NoZW1hICE9PSAnb2JqZWN0JyB8fCBBcnJheS5pc0FycmF5KGZvcm1hdC5zY2hlbWEpXG4gICAgfHwgKGZvcm1hdC5zdHJpY3QgIT09IHVuZGVmaW5lZCAmJiB0eXBlb2YgZm9ybWF0LnN0cmljdCAhPT0gJ2Jvb2xlYW4nKVxuICApKSkpIHtcbiAgICB0aHJvdyBuZXcgQ29udGVudEdlbmVyYXRpb25SZWplY3RlZEVycm9yKCdJbnZhbGlkIHJlc3BvbnNlIGZvcm1hdC4gSlNPTiBzY2hlbWFzIHJlcXVpcmUgYSBuYW1lIGFuZCBzY2hlbWEgb2JqZWN0LicpO1xuICB9XG4gIGlmKGlucHV0Lm1heFRva2VucyAhPT0gdW5kZWZpbmVkICYmICghTnVtYmVyLmlzSW50ZWdlcihpbnB1dC5tYXhUb2tlbnMpIHx8IGlucHV0Lm1heFRva2VucyA8IDEpKSB7XG4gICAgdGhyb3cgbmV3IENvbnRlbnRHZW5lcmF0aW9uUmVqZWN0ZWRFcnJvcignbWF4VG9rZW5zIG11c3QgYmUgYSBwb3NpdGl2ZSBpbnRlZ2VyLicpO1xuICB9XG4gIGlmKGlucHV0LnByb3ZpZGVyICE9PSAnZ2VtaW5pJyAmJiAoaW5wdXQuaW1hZ2VzPy5sZW5ndGggfHwgaW5wdXQubW9kYWxpdHkgPT09ICdpbWFnZScgfHwgaW5wdXQuc2VhcmNoKSkge1xuICAgIHRocm93IG5ldyBDb250ZW50R2VuZXJhdGlvblJlamVjdGVkRXJyb3IoJ1RoaXMgcHJvdmlkZXIgb3BlcmF0aW9uIHN1cHBvcnRzIHRleHQgaW5wdXQgYW5kIG91dHB1dCBvbmx5LicpO1xuICB9XG4gIGNvbnN0IHtwcm9tcHQsIGltYWdlcyA9IFtdfSA9IGlucHV0O1xuICBpZihpbnB1dC5wcm92aWRlciA9PT0gJ2NsYXVkZScpIHtcbiAgICBpZighY29uZmlnLmNsYXVkZUtleSkge1xuICAgICAgdGhyb3cgbmV3IENvbnRlbnRHZW5lcmF0aW9uUmVqZWN0ZWRFcnJvcignQ2xhdWRlIGlzIG5vdCBjb25maWd1cmVkIG9uIHRoaXMgc2VydmVyLicpO1xuICAgIH1cbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHBvc3QoJ2h0dHBzOi8vYXBpLmFudGhyb3BpYy5jb20vdjEvbWVzc2FnZXMnLCB7XG4gICAgICBtYXhfdG9rZW5zOiBpbnB1dC5tYXhUb2tlbnMgPz8gNDA5NixcbiAgICAgIG1lc3NhZ2VzOiBbe2NvbnRlbnQ6IHByb21wdCwgcm9sZTogJ3VzZXInfV0sXG4gICAgICBtb2RlbDogaW5wdXQubW9kZWwgfHwgY29uZmlnLmNsYXVkZU1vZGVsIHx8ICdjbGF1ZGUtc29ubmV0LTUnLFxuICAgICAgc3lzdGVtOiBpbnB1dC5zeXN0ZW1cbiAgICB9LCB7Y2FjaGU6IGZhbHNlLCBoZWFkZXJzOiBuZXcgSGVhZGVycyh7J2FudGhyb3BpYy12ZXJzaW9uJzogJzIwMjMtMDYtMDEnLCAneC1hcGkta2V5JzogY29uZmlnLmNsYXVkZUtleX0pLCB0aW1lb3V0OiBpbnB1dC50aW1lb3V0TXMgPz8gMTIwXzAwMH0pIGFzIHtcbiAgICAgIGNvbnRlbnQ/OiB7dGV4dD86IHN0cmluZzsgdHlwZT86IHN0cmluZ31bXTtcbiAgICAgIGVycm9yPzoge3R5cGU/OiBzdHJpbmd9O1xuICAgICAgc3RvcF9yZWFzb24/OiBzdHJpbmc7XG4gICAgICB0eXBlPzogc3RyaW5nO1xuICAgIH07XG4gICAgaWYocmVzcG9uc2UuZXJyb3IgJiYgWydhdXRoZW50aWNhdGlvbl9lcnJvcicsICdpbnZhbGlkX3JlcXVlc3RfZXJyb3InLCAnbm90X2ZvdW5kX2Vycm9yJywgJ3Blcm1pc3Npb25fZXJyb3InXS5pbmNsdWRlcyhyZXNwb25zZS5lcnJvci50eXBlIHx8ICcnKSkge1xuICAgICAgdGhyb3cgbmV3IENvbnRlbnRHZW5lcmF0aW9uUmVqZWN0ZWRFcnJvcignQ2xhdWRlIHJlamVjdGVkIHRoZSByZXF1ZXN0LiBDaGVjayB0aGUgbW9kZWwgYW5kIGFjY291bnQgYWNjZXNzLicpO1xuICAgIH1cbiAgICBjb25zdCB0ZXh0ID0gcmVzcG9uc2UuY29udGVudD8uZmlsdGVyKChwYXJ0KSA9PiBwYXJ0LnR5cGUgPT09ICd0ZXh0JykubWFwKChwYXJ0KSA9PiBwYXJ0LnRleHQgfHwgJycpLmpvaW4oJ1xcbicpLnRyaW0oKTtcbiAgICBpZihyZXNwb25zZS5lcnJvciB8fCByZXNwb25zZS50eXBlICE9PSAnbWVzc2FnZScgfHwgcmVzcG9uc2Uuc3RvcF9yZWFzb24gIT09ICdlbmRfdHVybicgfHwgIXRleHQpIHtcbiAgICAgIHRocm93IG5ldyBDb250ZW50R2VuZXJhdGlvblJlc3BvbnNlRXJyb3IoJ0NsYXVkZSByZXNwb25zZSBjb3VsZCBub3QgYmUgY29uZmlybWVkLicpO1xuICAgIH1cbiAgICByZXR1cm4ge3NvdXJjZXM6IFtdLCB0ZXh0fTtcbiAgfVxuICBpZihpbnB1dC5wcm92aWRlciA9PT0gJ29wZW5haScpIHtcbiAgICBpZighY29uZmlnLm9wZW5haUtleSkge1xuICAgICAgdGhyb3cgbmV3IENvbnRlbnRHZW5lcmF0aW9uUmVqZWN0ZWRFcnJvcignT3BlbkFJIGlzIG5vdCBjb25maWd1cmVkIG9uIHRoaXMgc2VydmVyLicpO1xuICAgIH1cbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHBvc3QoJ2h0dHBzOi8vYXBpLm9wZW5haS5jb20vdjEvcmVzcG9uc2VzJywge1xuICAgICAgaW5wdXQ6IGlucHV0Lm1lc3NhZ2VzPy5tYXAoKG1lc3NhZ2UpID0+ICh7Y29udGVudDogbWVzc2FnZS5jb250ZW50LCByb2xlOiBtZXNzYWdlLnJvbGUgPT09ICdzeXN0ZW0nID8gJ2RldmVsb3BlcicgOiBtZXNzYWdlLnJvbGV9KSkgPz8gcHJvbXB0LFxuICAgICAgaW5zdHJ1Y3Rpb25zOiBpbnB1dC5zeXN0ZW0sXG4gICAgICBtYXhfb3V0cHV0X3Rva2VuczogaW5wdXQubWF4VG9rZW5zID8/IDQwOTYsXG4gICAgICBtb2RlbDogaW5wdXQubW9kZWwgfHwgY29uZmlnLm9wZW5haU1vZGVsIHx8ICdncHQtNi1hc3RyYScsXG4gICAgICAuLi4oaW5wdXQucmVhc29uaW5nRWZmb3J0ID8ge3JlYXNvbmluZzoge2VmZm9ydDogaW5wdXQucmVhc29uaW5nRWZmb3J0fX0gOiB7fSksXG4gICAgICBzdG9yZTogZmFsc2UsXG4gICAgICAuLi4oZm9ybWF0ID8ge3RleHQ6IHtmb3JtYXR9fSA6IHt9KSxcbiAgICAgIHRydW5jYXRpb246ICdkaXNhYmxlZCdcbiAgICB9LCB7Y2FjaGU6IGZhbHNlLCBoZWFkZXJzOiBuZXcgSGVhZGVycyh7QXV0aG9yaXphdGlvbjogYEJlYXJlciAke2NvbmZpZy5vcGVuYWlLZXl9YH0pLCB0aW1lb3V0OiBpbnB1dC50aW1lb3V0TXMgPz8gMTIwXzAwMH0pIGFzIHtcbiAgICAgIGVycm9yPzoge2NvZGU/OiBzdHJpbmc7IHR5cGU/OiBzdHJpbmd9O1xuICAgICAgb3V0cHV0Pzoge2NvbnRlbnQ/OiB7dGV4dD86IHN0cmluZzsgdHlwZT86IHN0cmluZ31bXTsgc3RhdHVzPzogc3RyaW5nOyB0eXBlPzogc3RyaW5nfVtdO1xuICAgICAgc3RhdHVzPzogc3RyaW5nO1xuICAgIH07XG4gICAgaWYocmVzcG9uc2UuZXJyb3IgJiYgWydpbnZhbGlkX3JlcXVlc3RfZXJyb3InLCAnYXV0aGVudGljYXRpb25fZXJyb3InLCAncGVybWlzc2lvbl9lcnJvciddLmluY2x1ZGVzKHJlc3BvbnNlLmVycm9yLnR5cGUgfHwgJycpKSB7XG4gICAgICB0aHJvdyBuZXcgQ29udGVudEdlbmVyYXRpb25SZWplY3RlZEVycm9yKCdPcGVuQUkgcmVqZWN0ZWQgdGhlIHJlcXVlc3QuIENoZWNrIHRoZSBtb2RlbCBhbmQgYWNjb3VudCBhY2Nlc3MuJyk7XG4gICAgfVxuICAgIGlmKHJlc3BvbnNlLmVycm9yIHx8IHJlc3BvbnNlLnN0YXR1cyAhPT0gJ2NvbXBsZXRlZCcgfHwgcmVzcG9uc2Uub3V0cHV0Py5zb21lKChpdGVtKSA9PiBpdGVtLnN0YXR1cyA9PT0gJ2luY29tcGxldGUnKSkge1xuICAgICAgdGhyb3cgbmV3IENvbnRlbnRHZW5lcmF0aW9uUmVzcG9uc2VFcnJvcignT3BlbkFJIHJlc3BvbnNlIGNvdWxkIG5vdCBiZSBjb25maXJtZWQ6IGdlbmVyYXRpb24gZGlkIG5vdCBjb21wbGV0ZS4nKTtcbiAgICB9XG4gICAgaWYocmVzcG9uc2Uub3V0cHV0Py5zb21lKChpdGVtKSA9PiBpdGVtLmNvbnRlbnQ/LnNvbWUoKHBhcnQpID0+IHBhcnQudHlwZSA9PT0gJ3JlZnVzYWwnKSkpIHtcbiAgICAgIHRocm93IG5ldyBDb250ZW50R2VuZXJhdGlvblJlc3BvbnNlRXJyb3IoJ09wZW5BSSBkZWNsaW5lZCB0aGUgcmVxdWVzdC4nKTtcbiAgICB9XG4gICAgaWYocmVzcG9uc2Uub3V0cHV0Py5zb21lKChpdGVtKSA9PiBpdGVtLnR5cGUgJiYgIVsnbWVzc2FnZScsICdyZWFzb25pbmcnXS5pbmNsdWRlcyhpdGVtLnR5cGUpKSkge1xuICAgICAgdGhyb3cgbmV3IENvbnRlbnRHZW5lcmF0aW9uUmVzcG9uc2VFcnJvcignT3BlbkFJIHJldHVybmVkIGFuIHVuc3VwcG9ydGVkIG91dHB1dCBpdGVtLicpO1xuICAgIH1cbiAgICBjb25zdCB0ZXh0ID0gcmVzcG9uc2Uub3V0cHV0Py5maWx0ZXIoKGl0ZW0pID0+IGl0ZW0udHlwZSA9PT0gJ21lc3NhZ2UnKS5mbGF0TWFwKChpdGVtKSA9PiBpdGVtLmNvbnRlbnQgfHwgW10pXG4gICAgICAuZmlsdGVyKChwYXJ0KSA9PiBwYXJ0LnR5cGUgPT09ICdvdXRwdXRfdGV4dCcpLm1hcCgocGFydCkgPT4gcGFydC50ZXh0IHx8ICcnKS5qb2luKCcnKS50cmltKCk7XG4gICAgaWYoIXRleHQpIHtcbiAgICAgIHRocm93IG5ldyBDb250ZW50R2VuZXJhdGlvblJlc3BvbnNlRXJyb3IoJ09wZW5BSSByZXR1cm5lZCBlbXB0eSBvdXRwdXQuJyk7XG4gICAgfVxuICAgIHJldHVybiB7c291cmNlczogW10sIHRleHR9O1xuICB9XG4gIGlmKCFjb25maWcuZ2VtaW5pS2V5KSB7XG4gICAgdGhyb3cgbmV3IENvbnRlbnRHZW5lcmF0aW9uUmVqZWN0ZWRFcnJvcignR2VtaW5pIGlzIG5vdCBjb25maWd1cmVkIG9uIHRoaXMgc2VydmVyLicpO1xuICB9XG4gIGNvbnN0IHBhcnRzOiB1bmtub3duW10gPSBbe3RleHQ6IHByb21wdH0sIC4uLmltYWdlcy5tYXAoKGltYWdlKSA9PiAoe2lubGluZURhdGE6IHtkYXRhOiBpbWFnZS5ieXRlcy50b1N0cmluZygnYmFzZTY0JyksIG1pbWVUeXBlOiBpbWFnZS5taW1lfX0pKV07XG4gIGNvbnN0IG1vZGVsID0gaW5wdXQubW9kZWwgfHwgKGlucHV0Lm1vZGFsaXR5ID09PSAnaW1hZ2UnID8gY29uZmlnLmdlbWluaUltYWdlTW9kZWwgfHwgJ2dlbWluaS0zLjEtZmxhc2gtaW1hZ2UnIDogY29uZmlnLmdlbWluaU1vZGVsIHx8ICdnZW1pbmktMy44LWZsYXNoJyk7XG4gIGlmKCEvXlthLXpBLVowLTkuXy1dKyQvLnRlc3QobW9kZWwpKSB7XG4gICAgdGhyb3cgbmV3IENvbnRlbnRHZW5lcmF0aW9uUmVqZWN0ZWRFcnJvcignSW52YWxpZCBHZW1pbmkgbW9kZWwgY29uZmlndXJhdGlvbi4nKTtcbiAgfVxuICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHBvc3QoYGh0dHBzOi8vZ2VuZXJhdGl2ZWxhbmd1YWdlLmdvb2dsZWFwaXMuY29tL3YxYmV0YS9tb2RlbHMvJHttb2RlbH06Z2VuZXJhdGVDb250ZW50YCwge1xuICAgIGNvbnRlbnRzOiBbe3BhcnRzLCByb2xlOiAndXNlcid9XSxcbiAgICAuLi4oaW5wdXQuc3lzdGVtID8ge3N5c3RlbUluc3RydWN0aW9uOiB7cGFydHM6IFt7dGV4dDogaW5wdXQuc3lzdGVtfV19fSA6IHt9KSxcbiAgICBnZW5lcmF0aW9uQ29uZmlnOiBpbnB1dC5tb2RhbGl0eSA9PT0gJ2ltYWdlJyA/IHsuLi4oaW5wdXQuYXNwZWN0UmF0aW8gPyB7aW1hZ2VDb25maWc6IHthc3BlY3RSYXRpbzogaW5wdXQuYXNwZWN0UmF0aW99fSA6IHt9KSwgcmVzcG9uc2VNb2RhbGl0aWVzOiBbJ1RFWFQnLCAnSU1BR0UnXX0gOiB7bWF4T3V0cHV0VG9rZW5zOiBpbnB1dC5tYXhUb2tlbnMgPz8gNDA5Nn0sXG4gICAgLi4uKGlucHV0LnNlYXJjaCA/IHt0b29sczogW3tnb29nbGVTZWFyY2g6IHt9fV19IDoge30pXG4gIH0sIHtjYWNoZTogZmFsc2UsIGhlYWRlcnM6IG5ldyBIZWFkZXJzKHsneC1nb29nLWFwaS1rZXknOiBjb25maWcuZ2VtaW5pS2V5fSksIHRpbWVvdXQ6IGlucHV0LnRpbWVvdXRNcyA/PyAxMjBfMDAwfSkgYXMgR2VtaW5pUmVzcG9uc2U7XG4gIGlmKHJlc3BvbnNlLmVycm9yICYmIFs0MDAsIDQwMSwgNDAzLCA0MDRdLmluY2x1ZGVzKHJlc3BvbnNlLmVycm9yLmNvZGUgfHwgMCkpIHtcbiAgICB0aHJvdyBuZXcgQ29udGVudEdlbmVyYXRpb25SZWplY3RlZEVycm9yKCdHZW1pbmkgcmVqZWN0ZWQgdGhlIHJlcXVlc3QuIENoZWNrIHRoZSByZWZlcmVuY2UgZm9ybWF0IGFuZCBtb2RlbCBhY2Nlc3MuJyk7XG4gIH1cbiAgaWYocmVzcG9uc2UucHJvbXB0RmVlZGJhY2s/LmJsb2NrUmVhc29uIHx8IHJlc3BvbnNlLmVycm9yIHx8ICFyZXNwb25zZS5jYW5kaWRhdGVzPy5sZW5ndGgpIHtcbiAgICB0aHJvdyBuZXcgQ29udGVudEdlbmVyYXRpb25SZXNwb25zZUVycm9yKCdHZW1pbmkgcmVzcG9uc2UgY291bGQgbm90IGJlIGNvbmZpcm1lZC4nKTtcbiAgfVxuICBjb25zdCBjYW5kaWRhdGUgPSByZXNwb25zZS5jYW5kaWRhdGVzWzBdITtcbiAgaWYoY2FuZGlkYXRlLmZpbmlzaFJlYXNvbiAhPT0gJ1NUT1AnKSB7XG4gICAgdGhyb3cgbmV3IENvbnRlbnRHZW5lcmF0aW9uUmVzcG9uc2VFcnJvcignR2VtaW5pIHJlc3BvbnNlIGNvdWxkIG5vdCBiZSBjb25maXJtZWQ6IGdlbmVyYXRpb24gZGlkIG5vdCBjb21wbGV0ZS4nKTtcbiAgfVxuICBjb25zdCBvdXRwdXQgPSAoY2FuZGlkYXRlLmNvbnRlbnQ/LnBhcnRzIHx8IFtdKS5maWx0ZXIoKHBhcnQpID0+ICFwYXJ0LnRob3VnaHQpO1xuICBjb25zdCBpbmxpbmUgPSBvdXRwdXQuZmluZCgocGFydCkgPT4gcGFydC5pbmxpbmVEYXRhKT8uaW5saW5lRGF0YTtcbiAgbGV0IGltYWdlOiBHZW5lcmF0ZWRDb250ZW50WydpbWFnZSddO1xuICBpZihpbmxpbmUgJiYgWydpbWFnZS9wbmcnLCAnaW1hZ2UvanBlZyddLmluY2x1ZGVzKGlubGluZS5taW1lVHlwZSkpIHtcbiAgICBjb25zdCBieXRlcyA9IEJ1ZmZlci5mcm9tKGlubGluZS5kYXRhLCAnYmFzZTY0Jyk7XG4gICAgaWYoIWJ5dGVzLmxlbmd0aCB8fCBieXRlcy5sZW5ndGggPiAyMCAqIDEwMjQgKiAxMDI0KSB7XG4gICAgICB0aHJvdyBuZXcgQ29udGVudEdlbmVyYXRpb25SZXNwb25zZUVycm9yKCdJbnZhbGlkIGltYWdlIG91dHB1dC4nKTtcbiAgICB9XG4gICAgaW1hZ2UgPSB7Ynl0ZXMsIG1pbWU6IGlubGluZS5taW1lVHlwZSBhcyAnaW1hZ2UvcG5nJyB8ICdpbWFnZS9qcGVnJ307XG4gIH1cbiAgY29uc3QgdGV4dCA9IG91dHB1dC5tYXAoKHBhcnQpID0+IHBhcnQudGV4dCB8fCAnJykuam9pbignXFxuJykudHJpbSgpO1xuICBpZihpbnB1dC5tb2RhbGl0eSA9PT0gJ2ltYWdlJyA/ICFpbWFnZSA6ICF0ZXh0KSB7XG4gICAgdGhyb3cgbmV3IENvbnRlbnRHZW5lcmF0aW9uUmVzcG9uc2VFcnJvcignVGhlIHJlcXVlc3RlZCBvdXRwdXQgd2FzIG5vdCByZXR1cm5lZC4nKTtcbiAgfVxuICBjb25zdCBzb3VyY2VzID0gKGNhbmRpZGF0ZS5ncm91bmRpbmdNZXRhZGF0YT8uZ3JvdW5kaW5nQ2h1bmtzIHx8IFtdKS5mbGF0TWFwKCh7d2VifSkgPT4ge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCB1cmwgPSBuZXcgVVJMKHdlYj8udXJpIHx8ICcnKTtcbiAgICAgIHJldHVybiB1cmwucHJvdG9jb2wgPT09ICdodHRwczonID8gW3t0aXRsZTogd2ViPy50aXRsZSB8fCB1cmwuaG9zdG5hbWUsIHVybDogdXJsLmhyZWZ9XSA6IFtdO1xuICAgIH0gY2F0Y2h7XG4gICAgICByZXR1cm4gW107XG4gICAgfVxuICB9KTtcbiAgcmV0dXJuIHtcbiAgICBpbWFnZSwgc2VhcmNoU3VnZ2VzdGlvbnNIdG1sOiBjYW5kaWRhdGUuZ3JvdW5kaW5nTWV0YWRhdGE/LnNlYXJjaEVudHJ5UG9pbnQ/LnJlbmRlcmVkQ29udGVudCwgc291cmNlcywgdGV4dFxuICB9O1xufTtcbiJdLCJuYW1lcyI6WyJwb3N0IiwiQ29uZmlnIiwiQ29udGVudEdlbmVyYXRpb25SZWplY3RlZEVycm9yIiwiRXJyb3IiLCJDb250ZW50R2VuZXJhdGlvblJlc3BvbnNlRXJyb3IiLCJnZW5lcmF0ZUNvbnRlbnQiLCJpbnB1dCIsImNvbmZpZyIsImdldCIsImluY2x1ZGVzIiwicHJvdmlkZXIiLCJtZXNzYWdlcyIsInVuZGVmaW5lZCIsInByb21wdCIsIkFycmF5IiwiaXNBcnJheSIsImxlbmd0aCIsInNvbWUiLCJtZXNzYWdlIiwicm9sZSIsImNvbnRlbnQiLCJ0cmltIiwicmVhc29uaW5nRWZmb3J0IiwicmVzcG9uc2VGb3JtYXQiLCJ0aW1lb3V0TXMiLCJOdW1iZXIiLCJpc0ludGVnZXIiLCJmb3JtYXQiLCJ0eXBlIiwibmFtZSIsInRlc3QiLCJzY2hlbWEiLCJzdHJpY3QiLCJtYXhUb2tlbnMiLCJpbWFnZXMiLCJtb2RhbGl0eSIsInNlYXJjaCIsImNsYXVkZUtleSIsInJlc3BvbnNlIiwibWF4X3Rva2VucyIsIm1vZGVsIiwiY2xhdWRlTW9kZWwiLCJzeXN0ZW0iLCJjYWNoZSIsImhlYWRlcnMiLCJIZWFkZXJzIiwidGltZW91dCIsImVycm9yIiwidGV4dCIsImZpbHRlciIsInBhcnQiLCJtYXAiLCJqb2luIiwic3RvcF9yZWFzb24iLCJzb3VyY2VzIiwib3BlbmFpS2V5IiwiaW5zdHJ1Y3Rpb25zIiwibWF4X291dHB1dF90b2tlbnMiLCJvcGVuYWlNb2RlbCIsInJlYXNvbmluZyIsImVmZm9ydCIsInN0b3JlIiwidHJ1bmNhdGlvbiIsIkF1dGhvcml6YXRpb24iLCJzdGF0dXMiLCJvdXRwdXQiLCJpdGVtIiwiZmxhdE1hcCIsImdlbWluaUtleSIsInBhcnRzIiwiaW1hZ2UiLCJpbmxpbmVEYXRhIiwiZGF0YSIsImJ5dGVzIiwidG9TdHJpbmciLCJtaW1lVHlwZSIsIm1pbWUiLCJnZW1pbmlJbWFnZU1vZGVsIiwiZ2VtaW5pTW9kZWwiLCJjb250ZW50cyIsInN5c3RlbUluc3RydWN0aW9uIiwiZ2VuZXJhdGlvbkNvbmZpZyIsImFzcGVjdFJhdGlvIiwiaW1hZ2VDb25maWciLCJyZXNwb25zZU1vZGFsaXRpZXMiLCJtYXhPdXRwdXRUb2tlbnMiLCJ0b29scyIsImdvb2dsZVNlYXJjaCIsImNvZGUiLCJwcm9tcHRGZWVkYmFjayIsImJsb2NrUmVhc29uIiwiY2FuZGlkYXRlcyIsImNhbmRpZGF0ZSIsImZpbmlzaFJlYXNvbiIsInRob3VnaHQiLCJpbmxpbmUiLCJmaW5kIiwiQnVmZmVyIiwiZnJvbSIsImdyb3VuZGluZ01ldGFkYXRhIiwiZ3JvdW5kaW5nQ2h1bmtzIiwid2ViIiwidXJsIiwiVVJMIiwidXJpIiwicHJvdG9jb2wiLCJ0aXRsZSIsImhvc3RuYW1lIiwiaHJlZiIsInNlYXJjaFN1Z2dlc3Rpb25zSHRtbCIsInNlYXJjaEVudHJ5UG9pbnQiLCJyZW5kZXJlZENvbnRlbnQiXSwibWFwcGluZ3MiOiJBQUFBLFNBQVFBLElBQUksUUFBTyxvQkFBb0I7QUFFdkMsU0FBUUMsTUFBTSxRQUFPLGVBQWU7QUE2Q3BDLCtFQUErRSxHQUMvRSxPQUFPLE1BQU1DLHVDQUF1Q0M7QUFBTztBQUMzRCw0RkFBNEYsR0FDNUYsT0FBTyxNQUFNQyx1Q0FBdUNEO0FBQU87QUFnQjNELHVGQUF1RixHQUN2RixPQUFPLE1BQU1FLGtCQUFrQixPQUM3QkMsT0FDQUMsU0FBa0NOLE9BQU9PLEdBQUcsQ0FBMEIsd0JBQXdCLENBQUMsQ0FBQztJQUVoRyxJQUFHLENBQUM7UUFBQztRQUFVO1FBQVU7S0FBUyxDQUFDQyxRQUFRLENBQUNILE1BQU1JLFFBQVEsR0FBRztRQUMzRCxN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
@@ -0,0 +1,14 @@
1
+ import type { DatabaseCredentialIdentity, DatabaseCredentialSecret } from '../types/databaseCredentials.types.js';
2
+ type Access = 'none' | 'ro' | 'rw';
3
+ type BeforeWrite = () => Promise<void>;
4
+ type Account = {
5
+ grants: Readonly<Record<string, Access>>;
6
+ identity: DatabaseCredentialIdentity;
7
+ managed: boolean;
8
+ };
9
+ export declare const inspectDatabaseAccount: (identity: DatabaseCredentialIdentity) => Promise<Account | undefined>;
10
+ export declare const createManagedDatabaseAccount: (secret: DatabaseCredentialSecret, beforeWrite?: BeforeWrite) => Promise<void>;
11
+ export declare const rotateManagedDatabaseAccountPassword: (secret: DatabaseCredentialSecret, beforeWrite?: BeforeWrite) => Promise<void>;
12
+ export declare const restrictDatabaseAccount: (secret: DatabaseCredentialSecret, beforeWrite?: BeforeWrite) => Promise<void>;
13
+ export declare const verifyDatabaseAccount: (secret: DatabaseCredentialSecret) => Promise<void>;
14
+ export {};