@nlabs/reaktor 1.10.0 → 1.12.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 (43) hide show
  1. package/README.md +4 -0
  2. package/docs/GENERATION.md +135 -0
  3. package/lib/actions/contentGeneration.d.ts +30 -1
  4. package/lib/actions/contentGeneration.js +103 -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 +3 -0
  14. package/lib/actions/index.js +4 -1
  15. package/lib/actions/openaiResponseSession.d.ts +60 -0
  16. package/lib/actions/openaiResponseSession.js +248 -0
  17. package/lib/actions/videoGeneration.d.ts +5 -1
  18. package/lib/actions/videoGeneration.js +13 -2
  19. package/lib/adapters/higgsfieldAdapter.d.ts +21 -15
  20. package/lib/adapters/higgsfieldAdapter.js +24 -11
  21. package/lib/adapters/higgsfieldModelCatalog.d.ts +10 -0
  22. package/lib/adapters/higgsfieldModelCatalog.js +5363 -0
  23. package/lib/adapters/higgsfieldModels.d.ts +2 -0
  24. package/lib/adapters/higgsfieldModels.js +37 -0
  25. package/lib/index.d.ts +4 -0
  26. package/lib/index.js +4 -1
  27. package/lib/objectTypes/contentGeneration.js +26 -3
  28. package/lib/objectTypes/imageGeneration.js +3 -2
  29. package/lib/objectTypes/videoGeneration.js +2 -1
  30. package/lib/types/databaseCredentials.types.d.ts +30 -0
  31. package/lib/types/databaseCredentials.types.js +3 -0
  32. package/lib/types/index.d.ts +1 -0
  33. package/lib/types/index.js +2 -1
  34. package/lib/utils/databaseCredentials.d.ts +5 -0
  35. package/lib/utils/databaseCredentials.js +100 -0
  36. package/lib/utils/generationCallback.d.ts +23 -0
  37. package/lib/utils/generationCallback.js +49 -0
  38. package/lib/utils/index.d.ts +3 -0
  39. package/lib/utils/index.js +4 -1
  40. package/lib/utils/secretDatabase.d.ts +8 -0
  41. package/lib/utils/secretDatabase.js +153 -0
  42. package/lib/utils/testUtils.js +10 -2
  43. package/package.json +12 -10
package/README.md CHANGED
@@ -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,107 @@ 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).
150
+
151
+ ## Interactive OpenAI sessions (1.12.0)
152
+
153
+ `createOpenAIResponseSession(options, onEvent, config)` manages one Responses
154
+ WebSocket conversation. The caller supplies `model`, `max_output_tokens`, `input`,
155
+ optional instructions/reasoning/tool definitions, and explicit `apiKey`,
156
+ `timeoutMs`, and `maxToolCalls` in config. It does not read environment variables,
157
+ choose application prompts, authenticate end users, execute tools, or save results.
158
+ Applications own those policies and must authorize every tool they expose.
159
+
160
+ The returned handle offers `continue(text)`, `steer(text)`, `reasoning(effort)`,
161
+ `toolResult(callId, output)`, and idempotent `close()`. Pass an optional AbortSignal
162
+ as `config.signal` for local cancellation. Closing/aborting releases the timer,
163
+ discards queued tool results, and closes the connection; it does not roll back
164
+ external tools or guarantee that provider billing stops immediately. No requests
165
+ are automatically retried or replayed after errors or disconnection.
166
+
167
+ Provider events are forwarded to `onEvent`. Application-facing events are
168
+ `session.tool_call`, `session.tools_pending`, `session.reasoning.queued`,
169
+ `session.turn.completed`, and `session.error`. Only `session.turn.completed`
170
+ contains validated final text. Tool results are buffered while generating;
171
+ synchronous tools must all finish before a continuation. Steering waits for its
172
+ successor response and retains connection-local state. Storage and truncation are
173
+ disabled. `timeoutMs` bounds each turn and the following idle/tool-wait period.
174
+ An optional `config.connect` factory supports test sockets.
175
+
176
+ The TypeScript `generateContent` action also accepts multipart OpenAI messages:
177
+
178
+ ```ts
179
+ const result = await generateContent({
180
+ messages: [{
181
+ content: [
182
+ {text: 'Describe the visible colors.', type: 'text'},
183
+ {detail: 'auto', type: 'image', url: imageUrl}
184
+ ],
185
+ role: 'user'
186
+ }],
187
+ model,
188
+ provider: 'openai'
189
+ }, {openaiKey});
190
+ ```
191
+
192
+ Image URLs may be HTTP(S) URLs or base64 PNG/JPEG/WebP/GIF data URLs. Image parts
193
+ are accepted only in user messages. Other providers and the existing GraphQL
194
+ message input remain text-only for `messages`; Gemini's separate byte-image
195
+ input remains supported by the TypeScript action.
196
+
197
+ Protocol references: [WebSocket mode](https://developers.openai.com/api/docs/guides/websocket-mode)
198
+ and [mid-turn steering](https://developers.openai.com/api/docs/guides/steering).
@@ -7,6 +7,28 @@ export interface ContentGenerationConfig {
7
7
  openaiKey?: string;
8
8
  openaiModel?: string;
9
9
  }
10
+ export type ContentGenerationPart = {
11
+ text: string;
12
+ type: 'text';
13
+ } | {
14
+ detail?: 'auto' | 'high' | 'low';
15
+ type: 'image';
16
+ url: string;
17
+ };
18
+ export interface ContentGenerationMessage {
19
+ content: string | ContentGenerationPart[];
20
+ role: 'assistant' | 'developer' | 'system' | 'user';
21
+ }
22
+ export type ContentGenerationResponseFormat = {
23
+ type: 'json_object' | 'text';
24
+ } | {
25
+ description?: string;
26
+ name: string;
27
+ schema: Record<string, unknown>;
28
+ strict?: boolean;
29
+ type: 'json_schema';
30
+ };
31
+ export type ContentGenerationReasoningEffort = 'none' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'max';
10
32
  export interface ContentGenerationInput {
11
33
  aspectRatio?: string;
12
34
  images?: {
@@ -14,12 +36,16 @@ export interface ContentGenerationInput {
14
36
  mime: string;
15
37
  }[];
16
38
  maxTokens?: number;
39
+ messages?: ContentGenerationMessage[];
17
40
  modality?: 'image' | 'text';
18
41
  model?: string;
19
- prompt: string;
42
+ prompt?: string;
20
43
  provider: 'claude' | 'gemini' | 'openai';
44
+ reasoningEffort?: ContentGenerationReasoningEffort;
45
+ responseFormat?: ContentGenerationResponseFormat;
21
46
  search?: boolean;
22
47
  system?: string;
48
+ timeoutMs?: number;
23
49
  }
24
50
  export interface GeneratedContent {
25
51
  image?: {
@@ -36,5 +62,8 @@ export interface GeneratedContent {
36
62
  /** A confirmed rejection is distinct from an unknown paid submission outcome. */
37
63
  export declare class ContentGenerationRejectedError extends Error {
38
64
  }
65
+ /** An accepted generation did not produce usable output; do not automatically resubmit it. */
66
+ export declare class ContentGenerationResponseError extends Error {
67
+ }
39
68
  /** Single submission through Rip-Hunter; callers own durable jobs and reconciliation. */
40
69
  export declare const generateContent: (input: ContentGenerationInput, config?: ContentGenerationConfig) => Promise<GeneratedContent>;
@@ -2,13 +2,64 @@ 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
+ }
7
+ const validMessageContent = (message)=>{
8
+ if (typeof message.content === 'string') return !!message.content.trim();
9
+ return Array.isArray(message.content) && message.content.length > 0 && message.content.every((part)=>{
10
+ if (!part) return false;
11
+ if (part.type === 'text') return typeof part.text === 'string' && !!part.text.trim();
12
+ return part.type === 'image' && message.role === 'user' && typeof part.url === 'string' && /^(https?:\/\/[^\s]+|data:image\/(png|jpeg|webp|gif);base64,[A-Za-z0-9+/]+={0,2})$/.test(part.url) && (part.detail === undefined || [
13
+ 'auto',
14
+ 'high',
15
+ 'low'
16
+ ].includes(part.detail));
17
+ });
18
+ };
5
19
  /** Single submission through Rip-Hunter; callers own durable jobs and reconciliation. */ export const generateContent = async (input, config = Config.get('contentGeneration') || {})=>{
6
20
  if (![
7
21
  'claude',
8
22
  'gemini',
9
23
  'openai'
10
- ].includes(input.provider) || !input.prompt?.trim()) {
11
- throw new ContentGenerationRejectedError('A supported provider and non-empty prompt are required.');
24
+ ].includes(input.provider)) {
25
+ throw new ContentGenerationRejectedError('A supported provider is required.');
26
+ }
27
+ if (input.messages !== undefined) {
28
+ if (input.prompt !== undefined || !Array.isArray(input.messages) || !input.messages.length || input.messages.some((message)=>!message || ![
29
+ 'assistant',
30
+ 'developer',
31
+ 'system',
32
+ 'user'
33
+ ].includes(message.role) || !validMessageContent(message))) {
34
+ throw new ContentGenerationRejectedError('Supply either a non-empty prompt or non-empty text messages with supported roles.');
35
+ }
36
+ } else if (typeof input.prompt !== 'string' || !input.prompt.trim()) {
37
+ throw new ContentGenerationRejectedError('A non-empty prompt is required.');
38
+ }
39
+ if (input.provider !== 'openai' && (input.messages !== undefined || input.reasoningEffort !== undefined || input.responseFormat !== undefined)) {
40
+ throw new ContentGenerationRejectedError('Messages, reasoning effort, and response format are currently supported only by OpenAI.');
41
+ }
42
+ if (input.timeoutMs !== undefined && (!Number.isInteger(input.timeoutMs) || input.timeoutMs < 1 || input.timeoutMs > 2_147_483_647)) {
43
+ throw new ContentGenerationRejectedError('timeoutMs must be a positive 32-bit integer.');
44
+ }
45
+ if (input.reasoningEffort !== undefined && ![
46
+ 'none',
47
+ 'minimal',
48
+ 'low',
49
+ 'medium',
50
+ 'high',
51
+ 'xhigh',
52
+ 'max'
53
+ ].includes(input.reasoningEffort)) {
54
+ throw new ContentGenerationRejectedError('Unsupported reasoning effort.');
55
+ }
56
+ const format = input.responseFormat;
57
+ if (format !== undefined && (!format || ![
58
+ 'text',
59
+ 'json_object',
60
+ 'json_schema'
61
+ ].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'))) {
62
+ throw new ContentGenerationRejectedError('Invalid response format. JSON schemas require a name and schema object.');
12
63
  }
13
64
  if (input.maxTokens !== undefined && (!Number.isInteger(input.maxTokens) || input.maxTokens < 1)) {
14
65
  throw new ContentGenerationRejectedError('maxTokens must be a positive integer.');
@@ -37,7 +88,7 @@ import { Config } from '../config.js';
37
88
  'anthropic-version': '2023-06-01',
38
89
  'x-api-key': config.claudeKey
39
90
  }),
40
- timeout: 120_000
91
+ timeout: input.timeoutMs ?? 120_000
41
92
  });
42
93
  if (response.error && [
43
94
  'authentication_error',
@@ -49,7 +100,7 @@ import { Config } from '../config.js';
49
100
  }
50
101
  const text = response.content?.filter((part)=>part.type === 'text').map((part)=>part.text || '').join('\n').trim();
51
102
  if (response.error || response.type !== 'message' || response.stop_reason !== 'end_turn' || !text) {
52
- throw new Error('Claude response could not be confirmed.');
103
+ throw new ContentGenerationResponseError('Claude response could not be confirmed.');
53
104
  }
54
105
  return {
55
106
  sources: [],
@@ -61,17 +112,38 @@ import { Config } from '../config.js';
61
112
  throw new ContentGenerationRejectedError('OpenAI is not configured on this server.');
62
113
  }
63
114
  const response = await post('https://api.openai.com/v1/responses', {
64
- input: prompt,
115
+ input: input.messages?.map((message)=>({
116
+ content: typeof message.content === 'string' ? message.content : message.content.map((part)=>part.type === 'text' ? {
117
+ text: part.text,
118
+ type: 'input_text'
119
+ } : {
120
+ detail: part.detail ?? 'auto',
121
+ image_url: part.url,
122
+ type: 'input_image'
123
+ }),
124
+ role: message.role === 'system' ? 'developer' : message.role
125
+ })) ?? prompt,
65
126
  instructions: input.system,
66
127
  max_output_tokens: input.maxTokens ?? 4096,
67
128
  model: input.model || config.openaiModel || 'gpt-6-astra',
68
- store: false
129
+ ...input.reasoningEffort ? {
130
+ reasoning: {
131
+ effort: input.reasoningEffort
132
+ }
133
+ } : {},
134
+ store: false,
135
+ ...format ? {
136
+ text: {
137
+ format
138
+ }
139
+ } : {},
140
+ truncation: 'disabled'
69
141
  }, {
70
142
  cache: false,
71
143
  headers: new Headers({
72
144
  Authorization: `Bearer ${config.openaiKey}`
73
145
  }),
74
- timeout: 120_000
146
+ timeout: input.timeoutMs ?? 120_000
75
147
  });
76
148
  if (response.error && [
77
149
  'invalid_request_error',
@@ -80,9 +152,21 @@ import { Config } from '../config.js';
80
152
  ].includes(response.error.type || '')) {
81
153
  throw new ContentGenerationRejectedError('OpenAI rejected the request. Check the model and account access.');
82
154
  }
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.');
155
+ if (response.error || response.status !== 'completed' || response.output?.some((item)=>item.status === 'incomplete')) {
156
+ throw new ContentGenerationResponseError('OpenAI response could not be confirmed: generation did not complete.');
157
+ }
158
+ if (response.output?.some((item)=>item.content?.some((part)=>part.type === 'refusal'))) {
159
+ throw new ContentGenerationResponseError('OpenAI declined the request.');
160
+ }
161
+ if (response.output?.some((item)=>item.type && ![
162
+ 'message',
163
+ 'reasoning'
164
+ ].includes(item.type))) {
165
+ throw new ContentGenerationResponseError('OpenAI returned an unsupported output item.');
166
+ }
167
+ 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();
168
+ if (!text) {
169
+ throw new ContentGenerationResponseError('OpenAI returned empty output.');
86
170
  }
87
171
  return {
88
172
  sources: [],
@@ -148,7 +232,7 @@ import { Config } from '../config.js';
148
232
  headers: new Headers({
149
233
  'x-goog-api-key': config.geminiKey
150
234
  }),
151
- timeout: 120_000
235
+ timeout: input.timeoutMs ?? 120_000
152
236
  });
153
237
  if (response.error && [
154
238
  400,
@@ -158,10 +242,13 @@ import { Config } from '../config.js';
158
242
  ].includes(response.error.code || 0)) {
159
243
  throw new ContentGenerationRejectedError('Gemini rejected the request. Check the reference format and model access.');
160
244
  }
161
- if (response.error || !response.candidates?.length) {
162
- throw new Error('Gemini response could not be confirmed.');
245
+ if (response.promptFeedback?.blockReason || response.error || !response.candidates?.length) {
246
+ throw new ContentGenerationResponseError('Gemini response could not be confirmed.');
163
247
  }
164
248
  const candidate = response.candidates[0];
249
+ if (candidate.finishReason !== 'STOP') {
250
+ throw new ContentGenerationResponseError('Gemini response could not be confirmed: generation did not complete.');
251
+ }
165
252
  const output = (candidate.content?.parts || []).filter((part)=>!part.thought);
166
253
  const inline = output.find((part)=>part.inlineData)?.inlineData;
167
254
  let image;
@@ -171,7 +258,7 @@ import { Config } from '../config.js';
171
258
  ].includes(inline.mimeType)) {
172
259
  const bytes = Buffer.from(inline.data, 'base64');
173
260
  if (!bytes.length || bytes.length > 20 * 1024 * 1024) {
174
- throw new Error('Invalid image output.');
261
+ throw new ContentGenerationResponseError('Invalid image output.');
175
262
  }
176
263
  image = {
177
264
  bytes,
@@ -180,7 +267,7 @@ import { Config } from '../config.js';
180
267
  }
181
268
  const text = output.map((part)=>part.text || '').join('\n').trim();
182
269
  if (input.modality === 'image' ? !image : !text) {
183
- throw new Error('The requested output was not returned.');
270
+ throw new ContentGenerationResponseError('The requested output was not returned.');
184
271
  }
185
272
  const sources = (candidate.groundingMetadata?.groundingChunks || []).flatMap(({ web })=>{
186
273
  try {
@@ -203,4 +290,4 @@ import { Config } from '../config.js';
203
290
  };
204
291
  };
205
292
 
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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
293
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9Vc2Vycy9uaXRyb2c3L0RldmVsb3BtZW50L3JlYWt0b3IvcGFja2FnZXMvcmVha3Rvci9zcmMvYWN0aW9ucy9jb250ZW50R2VuZXJhdGlvbi50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge3Bvc3R9IGZyb20gJ0BubGFicy9yaXAtaHVudGVyJztcblxuaW1wb3J0IHtDb25maWd9IGZyb20gJy4uL2NvbmZpZy5qcyc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgQ29udGVudEdlbmVyYXRpb25Db25maWcge1xuICBjbGF1ZGVLZXk/OiBzdHJpbmc7XG4gIGNsYXVkZU1vZGVsPzogc3RyaW5nO1xuICBnZW1pbmlJbWFnZU1vZGVsPzogc3RyaW5nO1xuICBnZW1pbmlLZXk/OiBzdHJpbmc7XG4gIGdlbWluaU1vZGVsPzogc3RyaW5nO1xuICBvcGVuYWlLZXk/OiBzdHJpbmc7XG4gIG9wZW5haU1vZGVsPzogc3RyaW5nO1xufVxuZXhwb3J0IHR5cGUgQ29udGVudEdlbmVyYXRpb25QYXJ0ID0ge3RleHQ6IHN0cmluZzsgdHlwZTogJ3RleHQnfSB8IHtcbiAgZGV0YWlsPzogJ2F1dG8nIHwgJ2hpZ2gnIHwgJ2xvdyc7XG4gIHR5cGU6ICdpbWFnZSc7XG4gIHVybDogc3RyaW5nO1xufTtcbmV4cG9ydCBpbnRlcmZhY2UgQ29udGVudEdlbmVyYXRpb25NZXNzYWdlIHtcbiAgY29udGVudDogc3RyaW5nIHwgQ29udGVudEdlbmVyYXRpb25QYXJ0W107XG4gIHJvbGU6ICdhc3Npc3RhbnQnIHwgJ2RldmVsb3BlcicgfCAnc3lzdGVtJyB8ICd1c2VyJztcbn1cbmV4cG9ydCB0eXBlIENvbnRlbnRHZW5lcmF0aW9uUmVzcG9uc2VGb3JtYXQgPSB7dHlwZTogJ2pzb25fb2JqZWN0JyB8ICd0ZXh0J30gfCB7XG4gIGRlc2NyaXB0aW9uPzogc3RyaW5nO1xuICBuYW1lOiBzdHJpbmc7XG4gIHNjaGVtYTogUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gIHN0cmljdD86IGJvb2xlYW47XG4gIHR5cGU6ICdqc29uX3NjaGVtYSc7XG59O1xuZXhwb3J0IHR5cGUgQ29udGVudEdlbmVyYXRpb25SZWFzb25pbmdFZmZvcnQgPSAnbm9uZScgfCAnbWluaW1hbCcgfCAnbG93JyB8ICdtZWRpdW0nIHwgJ2hpZ2gnIHwgJ3hoaWdoJyB8ICdtYXgnO1xuXG5leHBvcnQgaW50ZXJmYWNlIENvbnRlbnRHZW5lcmF0aW9uSW5wdXQge1xuICBhc3BlY3RSYXRpbz86IHN0cmluZztcbiAgaW1hZ2VzPzoge2J5dGVzOiBCdWZmZXI7IG1pbWU6IHN0cmluZ31bXTtcbiAgbWF4VG9rZW5zPzogbnVtYmVyO1xuICBtZXNzYWdlcz86IENvbnRlbnRHZW5lcmF0aW9uTWVzc2FnZVtdO1xuICBtb2RhbGl0eT86ICdpbWFnZScgfCAndGV4dCc7XG4gIG1vZGVsPzogc3RyaW5nO1xuICBwcm9tcHQ/OiBzdHJpbmc7XG4gIHByb3ZpZGVyOiAnY2xhdWRlJyB8ICdnZW1pbmknIHwgJ29wZW5haSc7XG4gIHJlYXNvbmluZ0VmZm9ydD86IENvbnRlbnRHZW5lcmF0aW9uUmVhc29uaW5nRWZmb3J0O1xuICByZXNwb25zZUZvcm1hdD86IENvbnRlbnRHZW5lcmF0aW9uUmVzcG9uc2VGb3JtYXQ7XG4gIHNlYXJjaD86IGJvb2xlYW47XG4gIHN5c3RlbT86IHN0cmluZztcbiAgdGltZW91dE1zPzogbnVtYmVyO1xufVxuZXhwb3J0IGludGVyZmFjZSBHZW5lcmF0ZWRDb250ZW50IHtcbiAgaW1hZ2U/OiB7Ynl0ZXM6IEJ1ZmZlcjsgbWltZTogJ2ltYWdlL2pwZWcnIHwgJ2ltYWdlL3BuZyd9O1xuICBzZWFyY2hTdWdnZXN0aW9uc0h0bWw/OiBzdHJpbmc7XG4gIHNvdXJjZXM6IHt0aXRsZTogc3RyaW5nOyB1cmw6IHN0cmluZ31bXTtcbiAgdGV4dDogc3RyaW5nO1xufVxuLyoqIEEgY29uZmlybWVkIHJlamVjdGlvbiBpcyBkaXN0aW5jdCBmcm9tIGFuIHVua25vd24gcGFpZCBzdWJtaXNzaW9uIG91dGNvbWUuICovXG5leHBvcnQgY2xhc3MgQ29udGVudEdlbmVyYXRpb25SZWplY3RlZEVycm9yIGV4dGVuZHMgRXJyb3Ige31cbi8qKiBBbiBhY2NlcHRlZCBnZW5lcmF0aW9uIGRpZCBub3QgcHJvZHVjZSB1c2FibGUgb3V0cHV0OyBkbyBub3QgYXV0b21hdGljYWxseSByZXN1Ym1pdCBpdC4gKi9cbmV4cG9ydCBjbGFzcyBDb250ZW50R2VuZXJhdGlvblJlc3BvbnNlRXJyb3IgZXh0ZW5kcyBFcnJvciB7fVxuXG5pbnRlcmZhY2UgR2VtaW5pUGFydCB7aW5saW5lRGF0YT86IHtkYXRhOiBzdHJpbmc7IG1pbWVUeXBlOiBzdHJpbmd9OyB0ZXh0Pzogc3RyaW5nOyB0aG91Z2h0PzogYm9vbGVhbn1cbmludGVyZmFjZSBHZW1pbmlSZXNwb25zZSB7XG4gIGNhbmRpZGF0ZXM/OiB7XG4gICAgY29udGVudD86IHtwYXJ0cz86IEdlbWluaVBhcnRbXX07XG4gICAgZmluaXNoUmVhc29uPzogc3RyaW5nO1xuICAgIGdyb3VuZGluZ01ldGFkYXRhPzoge1xuICAgICAgZ3JvdW5kaW5nQ2h1bmtzPzoge3dlYj86IHt0aXRsZT86IHN0cmluZzsgdXJpPzogc3RyaW5nfX1bXTtcbiAgICAgIHNlYXJjaEVudHJ5UG9pbnQ/OiB7cmVuZGVyZWRDb250ZW50Pzogc3RyaW5nfTtcbiAgICB9O1xuICB9W107XG4gIGVycm9yPzoge2NvZGU/OiBudW1iZXJ9O1xuICBwcm9tcHRGZWVkYmFjaz86IHtibG9ja1JlYXNvbj86IHN0cmluZ307XG59XG5cbmNvbnN0IHZhbGlkTWVzc2FnZUNvbnRlbnQgPSAobWVzc2FnZTogQ29udGVudEdlbmVyYXRpb25NZXNzYWdlKTogYm9vbGVhbiA9PiB7XG4gIGlmKHR5cGVvZiBtZXNzYWdlLmNvbnRlbnQgPT09ICdzdHJpbmcnKSByZXR1cm4gISFtZXNzYWdlLmNvbnRlbnQudHJpbSgpO1xuICByZXR1cm4gQXJyYXkuaXNBcnJheShtZXNzYWdlLmNvbnRlbnQpICYmIG1lc3NhZ2UuY29udGVudC5sZW5ndGggPiAwICYmIG1lc3NhZ2UuY29udGVudC5ldmVyeSgocGFydCkgPT4ge1xuICAgIGlmKCFwYXJ0KSByZXR1cm4gZmFsc2U7XG4gICAgaWYocGFydC50eXBlID09PSAndGV4dCcpIHJldHVybiB0eXBlb2YgcGFydC50ZXh0ID09PSAnc3RyaW5nJyAmJiAhIXBhcnQudGV4dC50cmltKCk7XG4gICAgcmV0dXJuIHBhcnQudHlwZSA9PT0gJ2ltYWdlJyAmJiBtZXNzYWdlLnJvbGUgPT09ICd1c2VyJyAmJiB0eXBlb2YgcGFydC51cmwgPT09ICdzdHJpbmcnXG4gICAgICAmJiAvXihodHRwcz86XFwvXFwvW15cXHNdK3xkYXRhOmltYWdlXFwvKHBuZ3xqcGVnfHdlYnB8Z2lmKTtiYXNlNjQsW0EtWmEtejAtOSsvXSs9ezAsMn0pJC8udGVzdChwYXJ0LnVybClcbiAgICAgICYmIChwYXJ0LmRldGFpbCA9PT0gdW5kZWZpbmVkIHx8IFsnYXV0bycsICdoaWdoJywgJ2xvdyddLmluY2x1ZGVzKHBhcnQuZGV0YWlsKSk7XG4gIH0pO1xufTtcblxuLyoqIFNpbmdsZSBzdWJtaXNzaW9uIHRocm91Z2ggUmlwLUh1bnRlcjsgY2FsbGVycyBvd24gZHVyYWJsZSBqb2JzIGFuZCByZWNvbmNpbGlhdGlvbi4gKi9cbmV4cG9ydCBjb25zdCBnZW5lcmF0ZUNvbnRlbnQgPSBhc3luYyAoXG4gIGlucHV0OiBDb250ZW50R2VuZXJhdGlvbklucHV0LFxuICBjb25maWc6IENvbnRlbnRHZW5lcmF0aW9uQ29uZmlnID0gQ29uZmlnLmdldDxDb250ZW50R2VuZXJhdGlvbkNvbmZpZz4oJ2NvbnRlbnRHZW5lcmF0aW9uJykgfHwge31cbik6IFByb21pc2U8R2VuZXJhdGVkQ29udGVudD4gPT4ge1xuICBpZighWydjbGF1ZGUnLCAnZ2VtaW5pJywgJ29wZW5haSddLmluY2x1ZGVzKGlucHV0LnByb3ZpZGVyKSkge1xuICAgIHRocm93IG5ldyBDb250ZW50R2VuZXJhdGlvblJlamVjdGVkRXJyb3IoJ0Egc3VwcG9ydGVkIHByb3ZpZGVyIGlzIHJlcXVpcmVkLicpO1xuICB9XG4gIGlmKGlucHV0Lm1lc3NhZ2VzICE9PSB1bmRlZmluZWQpIHtcbiAgICBpZihpbnB1dC5wcm9tcHQgIT09IHVuZGVmaW5lZCB8fCAhQXJyYXkuaXNBcnJheShpbnB1dC5tZXNzYWdlcykgfHwgIWlucHV0Lm1lc3NhZ2VzLmxlbmd0aCB8fCBpbnB1dC5tZXNzYWdlcy5zb21lKChtZXNzYWdlKSA9PlxuICAgICAgIW1lc3NhZ2UgfHwgIVsnYXNzaXN0YW50JywgJ2RldmVsb3BlcicsICdzeXN0ZW0nLCAndXNlciddLmluY2x1ZGVzKG1lc3NhZ2Uucm9sZSkgfHwgIXZhbGlkTWVzc2FnZUNvbnRlbnQobWVzc2FnZSkpKSB7XG4gICAgICB0aHJvdyBuZXcgQ29udGVudEdlbmVyYXRpb25SZWplY3RlZEVycm9yKCdTdXBwbHkgZWl0aGVyIGEgbm9uLWVtcHR5IHByb21wdCBvciBub24tZW1wdHkgdGV4dCBtZXNzYWdlcyB3aXRoIHN1cHBvcnRlZCByb2xlcy4nKTtcbiAgICB9XG4gIH0gZWxzZSBpZih0eXBlb2YgaW5wdXQucHJvbXB0ICE9PSAnc3RyaW5nJyB8fCAhaW5wdXQucHJvbXB0LnRyaW0oKSkge1xuICAgIHRocm93IG5ldyBDb250ZW50R2VuZXJhdGlvblJlamVjdGVkRXJyb3IoJ0Egbm9uLWVtcHR5IHByb21wdCBpcyByZXF1aXJlZC4nKTtcbiAgfVxuICBpZihpbnB1dC5wcm92aWRlciAhPT0gJ29wZW5haScgJiYgKGlucHV0Lm1lc3NhZ2VzICE9PSB1bmRlZmluZWQgfHwgaW5wdXQucmVhc29uaW5nRWZmb3J0ICE9PSB1bmRlZmluZWQgfHwgaW5wdXQucmVzcG9uc2VGb3JtYXQgIT09IHVuZGVmaW5lZCkpIHtcbiAgICB0aHJvdyBuZXcgQ29udGVudEdlbmVyYXRpb25SZWplY3RlZEVycm9yKCdNZXNzYWdlcywgcmVhc29uaW5nIGVmZm9ydCwgYW5kIHJlc3BvbnNlIGZvcm1hdCBhcmUgY3VycmVudGx5IHN1cHBvcnRlZCBvbmx5IGJ5IE9wZW5BSS4nKTtcbiAgfVxuICBpZihpbnB1dC50aW1lb3V0TXMgIT09IHVuZGVmaW5lZCAmJiAoIU51bWJlci5pc0ludGVnZXIoaW5wdXQudGltZW91dE1zKSB8fCBpbnB1dC50aW1lb3V0TXMgPCAxIHx8IGlucHV0LnRpbWVvdXRNcyA+IDJfMTQ3XzQ4M182NDcpKSB7XG4gICAgdGhyb3cgbmV3IENvbnRlbnRHZW5lcmF0aW9uUmVqZWN0ZWRFcnJvcigndGltZW91dE1zIG11c3QgYmUgYSBwb3NpdGl2ZSAzMi1iaXQgaW50ZWdlci4nKTtcbiAgfVxuICBpZihpbnB1dC5yZWFzb25pbmdFZmZvcnQgIT09IHVuZGVmaW5lZCAmJiAhWydub25lJywgJ21pbmltYWwnLCAnbG93JywgJ21lZGl1bScsICdoaWdoJywgJ3hoaWdoJywgJ21heCddLmluY2x1ZGVzKGlucHV0LnJlYXNvbmluZ0VmZm9ydCkpIHtcbiAgICB0aHJvdyBuZXcgQ29udGVudEdlbmVyYXRpb25SZWplY3RlZEVycm9yKCdVbnN1cHBvcnRlZCByZWFzb25pbmcgZWZmb3J0LicpO1xuICB9XG4gIGNvbnN0IGZvcm1hdCA9IGlucHV0LnJlc3BvbnNlRm9ybWF0O1xuICBpZihmb3JtYXQgIT09IHVuZGVmaW5lZCAmJiAoIWZvcm1hdCB8fCAhWyd0ZXh0JywgJ2pzb25fb2JqZWN0JywgJ2pzb25fc2NoZW1hJ10uaW5jbHVkZXMoZm9ybWF0LnR5cGUpIHx8IChmb3JtYXQudHlwZSA9PT0gJ2pzb25fc2NoZW1hJyAmJiAoXG4gICAgdHlwZW9mIGZvcm1hdC5uYW1lICE9PSAnc3RyaW5nJyB8fCAhL15bYS16QS1aMC05Xy1dezEsNjR9JC8udGVzdChmb3JtYXQubmFtZSkgfHwgIWZvcm1hdC5zY2hlbWEgfHwgdHlwZW9mIGZvcm1hdC5zY2hlbWEgIT09ICdvYmplY3QnIHx8IEFycmF5LmlzQXJyYXkoZm9ybWF0LnNjaGVtYSlcbiAgICB8fCAoZm9ybWF0LnN0cmljdCAhPT0gdW5kZWZpbmVkICYmIHR5cGVvZiBmb3JtYXQuc3RyaWN0ICE9PSAnYm9vbGVhbicpXG4gICkpKSkge1xuICAgIHRocm93IG5ldyBDb250ZW50R2VuZXJhdGlvblJlamVjdGVkRXJyb3IoJ0ludmFsaWQgcmVzcG9uc2UgZm9ybWF0LiBKU09OIHNjaGVtYXMgcmVxdWlyZSBhIG5hbWUgYW5kIHNjaGVtYSBvYmplY3QuJyk7XG4gIH1cbiAgaWYoaW5wdXQubWF4VG9rZW5zICE9PSB1bmRlZmluZWQgJiYgKCFOdW1iZXIuaXNJbnRlZ2VyKGlucHV0Lm1heFRva2VucykgfHwgaW5wdXQubWF4VG9rZW5zIDwgMSkpIHtcbiAgICB0aHJvdyBuZXcgQ29udGVudEdlbmVyYXRpb25SZWplY3RlZEVycm9yKCdtYXhUb2tlbnMgbXVzdCBiZSBhIHBvc2l0aXZlIGludGVnZXIuJyk7XG4gIH1cbiAgaWYoaW5wdXQucHJvdmlkZXIgIT09ICdnZW1pbmknICYmIChpbnB1dC5pbWFnZXM/Lmxlbmd0aCB8fCBpbnB1dC5tb2RhbGl0eSA9PT0gJ2ltYWdlJyB8fCBpbnB1dC5zZWFyY2gpKSB7XG4gICAgdGhyb3cgbmV3IENvbnRlbnRHZW5lcmF0aW9uUmVqZWN0ZWRFcnJvcignVGhpcyBwcm92aWRlciBvcGVyYXRpb24gc3VwcG9ydHMgdGV4dCBpbnB1dCBhbmQgb3V0cHV0IG9ubHkuJyk7XG4gIH1cbiAgY29uc3Qge3Byb21wdCwgaW1hZ2VzID0gW119ID0gaW5wdXQ7XG4gIGlmKGlucHV0LnByb3ZpZGVyID09PSAnY2xhdWRlJykge1xuICAgIGlmKCFjb25maWcuY2xhdWRlS2V5KSB7XG4gICAgICB0aHJvdyBuZXcgQ29udGVudEdlbmVyYXRpb25SZWplY3RlZEVycm9yKCdDbGF1ZGUgaXMgbm90IGNvbmZpZ3VyZWQgb24gdGhpcyBzZXJ2ZXIuJyk7XG4gICAgfVxuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgcG9zdCgnaHR0cHM6Ly9hcGkuYW50aHJvcGljLmNvbS92MS9tZXNzYWdlcycsIHtcbiAgICAgIG1heF90b2tlbnM6IGlucHV0Lm1heFRva2VucyA/PyA0MDk2LFxuICAgICAgbWVzc2FnZXM6IFt7Y29udGVudDogcHJvbXB0LCByb2xlOiAndXNlcid9XSxcbiAgICAgIG1vZGVsOiBpbnB1dC5tb2RlbCB8fCBjb25maWcuY2xhdWRlTW9kZWwgfHwgJ2NsYXVkZS1zb25uZXQtNScsXG4gICAgICBzeXN0ZW06IGlucHV0LnN5c3RlbVxuICAgIH0sIHtjYWNoZTogZmFsc2UsIGhlYWRlcnM6IG5ldyBIZWFkZXJzKHsnYW50aHJvcGljLXZlcnNpb24nOiAnMjAyMy0wNi0wMScsICd4LWFwaS1rZXknOiBjb25maWcuY2xhdWRlS2V5fSksIHRpbWVvdXQ6IGlucHV0LnRpbWVvdXRNcyA/PyAxMjBfMDAwfSkgYXMge1xuICAgICAgY29udGVudD86IHt0ZXh0Pzogc3RyaW5nOyB0eXBlPzogc3RyaW5nfVtdO1xuICAgICAgZXJyb3I/OiB7dHlwZT86IHN0cmluZ307XG4gICAgICBzdG9wX3JlYXNvbj86IHN0cmluZztcbiAgICAgIHR5cGU/OiBzdHJpbmc7XG4gICAgfTtcbiAgICBpZihyZXNwb25zZS5lcnJvciAmJiBbJ2F1dGhlbnRpY2F0aW9uX2Vycm9yJywgJ2ludmFsaWRfcmVxdWVzdF9lcnJvcicsICdub3RfZm91bmRfZXJyb3InLCAncGVybWlzc2lvbl9lcnJvciddLmluY2x1ZGVzKHJlc3BvbnNlLmVycm9yLnR5cGUgfHwgJycpKSB7XG4gICAgICB0aHJvdyBuZXcgQ29udGVudEdlbmVyYXRpb25SZWplY3RlZEVycm9yKCdDbGF1ZGUgcmVqZWN0ZWQgdGhlIHJlcXVlc3QuIENoZWNrIHRoZSBtb2RlbCBhbmQgYWNjb3VudCBhY2Nlc3MuJyk7XG4gICAgfVxuICAgIGNvbnN0IHRleHQgPSByZXNwb25zZS5jb250ZW50Py5maWx0ZXIoKHBhcnQpID0+IHBhcnQudHlwZSA9PT0gJ3RleHQnKS5tYXAoKHBhcnQpID0+IHBhcnQudGV4dCB8fCAnJykuam9pbignXFxuJykudHJpbSgpO1xuICAgIGlmKHJlc3BvbnNlLmVycm9yIHx8IHJlc3BvbnNlLnR5cGUgIT09ICdtZXNzYWdlJyB8fCByZXNwb25zZS5zdG9wX3JlYXNvbiAhPT0gJ2VuZF90dXJuJyB8fCAhdGV4dCkge1xuICAgICAgdGhyb3cgbmV3IENvbnRlbnRHZW5lcmF0aW9uUmVzcG9uc2VFcnJvcignQ2xhdWRlIHJlc3BvbnNlIGNvdWxkIG5vdCBiZSBjb25maXJtZWQuJyk7XG4gICAgfVxuICAgIHJldHVybiB7c291cmNlczogW10sIHRleHR9O1xuICB9XG4gIGlmKGlucHV0LnByb3ZpZGVyID09PSAnb3BlbmFpJykge1xuICAgIGlmKCFjb25maWcub3BlbmFpS2V5KSB7XG4gICAgICB0aHJvdyBuZXcgQ29udGVudEdlbmVyYXRpb25SZWplY3RlZEVycm9yKCdPcGVuQUkgaXMgbm90IGNvbmZpZ3VyZWQgb24gdGhpcyBzZXJ2ZXIuJyk7XG4gICAgfVxuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgcG9zdCgnaHR0cHM6Ly9hcGkub3BlbmFpLmNvbS92MS9yZXNwb25zZXMnLCB7XG4gICAgICBpbnB1dDogaW5wdXQubWVzc2FnZXM/Lm1hcCgobWVzc2FnZSkgPT4gKHtjb250ZW50OiB0eXBlb2YgbWVzc2FnZS5jb250ZW50ID09PSAnc3RyaW5nJyA/IG1lc3NhZ2UuY29udGVudCA6IG1lc3NhZ2UuY29udGVudC5tYXAoKHBhcnQpID0+IHBhcnQudHlwZSA9PT0gJ3RleHQnXG4gICAgICAgID8ge3RleHQ6IHBhcnQudGV4dCwgdHlwZTogJ2lucHV0X3RleHQnfSA6IHtkZXRhaWw6IHBhcnQuZGV0YWlsID8/ICdhdXRvJywgaW1hZ2VfdXJsOiBwYXJ0LnVybCwgdHlwZTogJ2lucHV0X2ltYWdlJ30pLCByb2xlOiBtZXNzYWdlLnJvbGUgPT09ICdzeXN0ZW0nID8gJ2RldmVsb3BlcicgOiBtZXNzYWdlLnJvbGV9KSkgPz8gcHJvbXB0LFxuICAgICAgaW5zdHJ1Y3Rpb25zOiBpbnB1dC5zeXN0ZW0sXG4gICAgICBtYXhfb3V0cHV0X3Rva2VuczogaW5wdXQubWF4VG9rZW5zID8/IDQwOTYsXG4gICAgICBtb2RlbDogaW5wdXQubW9kZWwgfHwgY29uZmlnLm9wZW5haU1vZGVsIHx8ICdncHQtNi1hc3RyYScsXG4gICAgICAuLi4oaW5wdXQucmVhc29uaW5nRWZmb3J0ID8ge3JlYXNvbmluZzoge2VmZm9ydDogaW5wdXQucmVhc29uaW5nRWZmb3J0fX0gOiB7fSksXG4gICAgICBzdG9yZTogZmFsc2UsXG4gICAgICAuLi4oZm9ybWF0ID8ge3RleHQ6IHtmb3JtYXR9fSA6IHt9KSxcbiAgICAgIHRydW5jYXRpb246ICdkaXNhYmxlZCdcbiAgICB9LCB7Y2FjaGU6IGZhbHNlLCBoZWFkZXJzOiBuZXcgSGVhZGVycyh7QXV0aG9yaXphdGlvbjogYEJlYXJlciAke2NvbmZpZy5vcGVuYWlLZXl9YH0pLCB0aW1lb3V0OiBpbnB1dC50aW1lb3V0TXMgPz8gMTIwXzAwMH0pIGFzIHtcbiAgICAgIGVycm9yPzoge2NvZGU/OiBzdHJpbmc7IHR5cGU/OiBzdHJpbmd9O1xuICAgICAgb3V0cHV0Pzoge2NvbnRlbnQ/OiB7dGV4dD86IHN0cmluZzsgdHlwZT86IHN0cmluZ31bXTsgc3RhdHVzPzogc3RyaW5nOyB0eXBlPzogc3RyaW5nfVtdO1xuICAgICAgc3RhdHVzPzogc3RyaW5nO1xuICAgIH07XG4gICAgaWYocmVzcG9uc2UuZXJyb3IgJiYgWydpbnZhbGlkX3JlcXVlc3RfZXJyb3InLCAnYXV0aGVudGljYXRpb25fZXJyb3InLCAncGVybWlzc2lvbl9lcnJvciddLmluY2x1ZGVzKHJlc3BvbnNlLmVycm9yLnR5cGUgfHwgJycpKSB7XG4gICAgICB0aHJvdyBuZXcgQ29udGVudEdlbmVyYXRpb25SZWplY3RlZEVycm9yKCdPcGVuQUkgcmVqZWN0ZWQgdGhlIHJlcXVlc3QuIENoZWNrIHRoZSBtb2RlbCBhbmQgYWNjb3VudCBhY2Nlc3MuJyk7XG4gICAgfVxuICAgIGlmKHJlc3BvbnNlLmVycm9yIHx8IHJlc3BvbnNlLnN0YXR1cyAhPT0gJ2NvbXBsZXRlZCcgfHwgcmVzcG9uc2Uub3V0cHV0Py5zb21lKChpdGVtKSA9PiBpdGVtLnN0YXR1cyA9PT0gJ2luY29tcGxldGUnKSkge1xuICAgICAgdGhyb3cgbmV3IENvbnRlbnRHZW5lcmF0aW9uUmVzcG9uc2VFcnJvcignT3BlbkFJIHJlc3BvbnNlIGNvdWxkIG5vdCBiZSBjb25maXJtZWQ6IGdlbmVyYXRpb24gZGlkIG5vdCBjb21wbGV0ZS4nKTtcbiAgICB9XG4gICAgaWYocmVzcG9uc2Uub3V0cHV0Py5zb21lKChpdGVtKSA9PiBpdGVtLmNvbnRlbnQ/LnNvbWUoKHBhcnQpID0+IHBhcnQudHlwZSA9PT0gJ3JlZnVzYWwnKSkpIHtcbiAgICAgIHRocm93IG5ldyBDb250ZW50R2VuZXJhdGlvblJlc3BvbnNlRXJyb3IoJ09wZW5BSSBkZWNsaW5lZCB0aGUgcmVxdWVzdC4nKTtcbiAgICB9XG4gICAgaWYocmVzcG9uc2Uub3V0cHV0Py5zb21lKChpdGVtKSA9PiBpdGVtLnR5cGUgJiYgIVsnbWVzc2FnZScsICdyZWFzb25pbmcnXS5pbmNsdWRlcyhpdGVtLnR5cGUpKSkge1xuICAgICAgdGhyb3cgbmV3IENvbnRlbnRHZW5lcmF0aW9uUmVzcG9uc2VFcnJvcignT3BlbkFJIHJldHVybmVkIGFuIHVuc3VwcG9ydGVkIG91dHB1dCBpdGVtLicpO1xuICAgIH1cbiAgICBjb25zdCB0ZXh0ID0gcmVzcG9uc2Uub3V0cHV0Py5maWx0ZXIoKGl0ZW0pID0+IGl0ZW0udHlwZSA9PT0gJ21lc3NhZ2UnKS5mbGF0TWFwKChpdGVtKSA9PiBpdGVtLmNvbnRlbnQgfHwgW10pXG4gICAgICAuZmlsdGVyKChwYXJ0KSA9PiBwYXJ0LnR5cGUgPT09ICdvdXRwdXRfdGV4dCcpLm1hcCgocGFydCkgPT4gcGFydC50ZXh0IHx8ICcnKS5qb2luKCcnKS50cmltKCk7XG4gICAgaWYoIXRleHQpIHtcbiAgICAgIHRocm93IG5ldyBDb250ZW50R2VuZXJhdGlvblJlc3BvbnNlRXJyb3IoJ09wZW5BSSByZXR1cm5lZCBlbXB0eSBvdXRwdXQuJyk7XG4gICAgfVxuICAgIHJldHVybiB7c291cmNlczogW10sIHRleHR9O1xuICB9XG4gIGlmKCFjb25maWcuZ2VtaW5pS2V5KSB7XG4gICAgdGhyb3cgbmV3IENvbnRlbnRHZW5lcmF0aW9uUmVqZWN0ZWRFcnJvcignR2VtaW5pIGlzIG5vdCBjb25maWd1cmVkIG9uIHRoaXMgc2VydmVyLicpO1xuICB9XG4gIGNvbnN0IHBhcnRzOiB1bmtub3duW10gPSBbe3RleHQ6IHByb21wdH0sIC4uLmltYWdlcy5tYXAoKGltYWdlKSA9PiAoe2lubGluZURhdGE6IHtkYXRhOiBpbWFnZS5ieXRlcy50b1N0cmluZygnYmFzZTY0JyksIG1pbWVUeXBlOiBpbWFnZS5taW1lfX0pKV07XG4gIGNvbnN0IG1vZGVsID0gaW5wdXQubW9kZWwgfHwgKGlucHV0Lm1vZGFsaXR5ID09PSAnaW1hZ2UnID8gY29uZmlnLmdlbWluaUltYWdlTW9kZWwgfHwgJ2dlbWluaS0zLjEtZmxhc2gtaW1hZ2UnIDogY29uZmlnLmdlbWluaU1vZGVsIHx8ICdnZW1pbmktMy44LWZsYXNoJyk7XG4gIGlmKCEvXlthLXpBLVowLTkuXy1dKyQvLnRlc3QobW9kZWwpKSB7XG4gICAgdGhyb3cgbmV3IENvbnRlbnRHZW5lcmF0aW9uUmVqZWN0ZWRFcnJvcignSW52YWxpZCBHZW1pbmkgbW9kZWwgY29uZmlndXJhdGlvbi4nKTtcbiAgfVxuICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHBvc3QoYGh0dHBzOi8vZ2VuZXJhdGl2ZWxhbmd1YWdlLmdvb2dsZWFwaXMuY29tL3YxYmV0YS9tb2RlbHMvJHttb2RlbH06Z2VuZXJhdGVDb250ZW50YCwge1xuICAgIGNvbnRlbnRzOiBbe3BhcnRzLCByb2xlOiAndXNlcid9XSxcbiAgICAuLi4oaW5wdXQuc3lzdGVtID8ge3N5c3RlbUluc3RydWN0aW9uOiB7cGFydHM6IFt7dGV4dDogaW5wdXQuc3lzdGVtfV19fSA6IHt9KSxcbiAgICBnZW5lcmF0aW9uQ29uZmlnOiBpbnB1dC5tb2RhbGl0eSA9PT0gJ2ltYWdlJyA/IHsuLi4oaW5wdXQuYXNwZWN0UmF0aW8gPyB7aW1hZ2VDb25maWc6IHthc3BlY3RSYXRpbzogaW5wdXQuYXNwZWN0UmF0aW99fSA6IHt9KSwgcmVzcG9uc2VNb2RhbGl0aWVzOiBbJ1RFWFQnLCAnSU1BR0UnXX0gOiB7bWF4T3V0cHV0VG9rZW5zOiBpbnB1dC5tYXhUb2tlbnMgPz8gNDA5Nn0sXG4gICAgLi4uKGlucHV0LnNlYXJjaCA/IHt0b29sczogW3tnb29nbGVTZWFyY2g6IHt9fV19IDoge30pXG4gIH0sIHtjYWNoZTogZmFsc2UsIGhlYWRlcnM6IG5ldyBIZWFkZXJzKHsneC1nb29nLWFwaS1rZXknOiBjb25maWcuZ2VtaW5pS2V5fSksIHRpbWVvdXQ6IGlucHV0LnRpbWVvdXRNcyA/PyAxMjBfMDAwfSkgYXMgR2VtaW5pUmVzcG9uc2U7XG4gIGlmKHJlc3BvbnNlLmVycm9yICYmIFs0MDAsIDQwMSwgNDAzLCA0MDRdLmluY2x1ZGVzKHJlc3BvbnNlLmVycm9yLmNvZGUgfHwgMCkpIHtcbiAgICB0aHJvdyBuZXcgQ29udGVudEdlbmVyYXRpb25SZWplY3RlZEVycm9yKCdHZW1pbmkgcmVqZWN0ZWQgdGhlIHJlcXVlc3QuIENoZWNrIHRoZSByZWZlcmVuY2UgZm9ybWF0IGFuZCBtb2RlbCBhY2Nlc3MuJyk7XG4gIH1cbiAgaWYocmVzcG9uc2UucHJvbXB0RmVlZGJhY2s/LmJsb2NrUmVhc29uIHx8IHJlc3BvbnNlLmVycm9yIHx8ICFyZXNwb25zZS5jYW5kaWRhdGVzPy5sZW5ndGgpIHtcbiAgICB0aHJvdyBuZXcgQ29udGVudEdlbmVyYXRpb25SZXNwb25zZUVycm9yKCdHZW1pbmkgcmVzcG9uc2UgY291bGQgbm90IGJlIGNvbmZpcm1lZC4nKTtcbiAgfVxuICBjb25zdCBjYW5kaWRhdGUgPSByZXNwb25zZS5jYW5kaWRhdGVzWzBdITtcbiAgaWYoY2FuZGlkYXRlLmZpbmlzaFJlYXNvbiAhPT0gJ1NUT1AnKSB7XG4gICAgdGhyb3cgbmV3IENvbnRlbnRHZW5lcmF0aW9uUmVzcG9uc2VFcnJvcignR2VtaW5pIHJlc3BvbnNlIGNvdWxkIG5vdCBiZSBjb25maXJtZWQ6IGdlbmVyYXRpb24gZGlkIG5vdCBjb21wbGV0ZS4nKTtcbiAgfVxuICBjb25zdCBvdXRwdXQgPSAoY2FuZGlkYXRlLmNvbnRlbnQ/LnBhcnRzIHx8IFtdKS5maWx0ZXIoKHBhcnQpID0+ICFwYXJ0LnRob3VnaHQpO1xuICBjb25zdCBpbmxpbmUgPSBvdXRwdXQuZmluZCgocGFydCkgPT4gcGFydC5pbmxpbmVEYXRhKT8uaW5saW5lRGF0YTtcbiAgbGV0IGltYWdlOiBHZW5lcmF0ZWRDb250ZW50WydpbWFnZSddO1xuICBpZihpbmxpbmUgJiYgWydpbWFnZS9wbmcnLCAnaW1hZ2UvanBlZyddLmluY2x1ZGVzKGlubGluZS5taW1lVHlwZSkpIHtcbiAgICBjb25zdCBieXRlcyA9IEJ1ZmZlci5mcm9tKGlubGluZS5kYXRhLCAnYmFzZTY0Jyk7XG4gICAgaWYoIWJ5dGVzLmxlbmd0aCB8fCBieXRlcy5sZW5ndGggPiAyMCAqIDEwMjQgKiAxMDI0KSB7XG4gICAgICB0aHJvdyBuZXcgQ29udGVudEdlbmVyYXRpb25SZXNwb25zZUVycm9yKCdJbnZhbGlkIGltYWdlIG91dHB1dC4nKTtcbiAgICB9XG4gICAgaW1hZ2UgPSB7Ynl0ZXMsIG1pbWU6IGlubGluZS5taW1lVHlwZSBhcyAnaW1hZ2UvcG5nJyB8ICdpbWFnZS9qcGVnJ307XG4gIH1cbiAgY29uc3QgdGV4dCA9IG91dHB1dC5tYXAoKHBhcnQpID0+IHBhcnQudGV4dCB8fCAnJykuam9pbignXFxuJykudHJpbSgpO1xuICBpZihpbnB1dC5tb2RhbGl0eSA9PT0gJ2ltYWdlJyA/ICFpbWFnZSA6ICF0ZXh0KSB7XG4gICAgdGhyb3cgbmV3IENvbnRlbnRHZW5lcmF0aW9uUmVzcG9uc2VFcnJvcignVGhlIHJlcXVlc3RlZCBvdXRwdXQgd2FzIG5vdCByZXR1cm5lZC4nKTtcbiAgfVxuICBjb25zdCBzb3VyY2VzID0gKGNhbmRpZGF0ZS5ncm91bmRpbmdNZXRhZGF0YT8uZ3JvdW5kaW5nQ2h1bmtzIHx8IFtdKS5mbGF0TWFwKCh7d2VifSkgPT4ge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCB1cmwgPSBuZXcgVVJMKHdlYj8udXJpIHx8ICcnKTtcbiAgICAgIHJldHVybiB1cmwucHJvdG9jb2wgPT09ICdodHRwczonID8gW3t0aXRsZTogd2ViPy50aXRsZSB8fCB1cmwuaG9zdG5hbWUsIHVybDogdXJsLmhyZWZ9XSA6IFtdO1xuICAgIH0gY2F0Y2h7XG4gICAgICByZXR1cm4gW107XG4gICAgfVxuICB9KTtcbiAgcmV0dXJuIHtcbiAgICBpbWFnZSwgc2VhcmNoU3VnZ2VzdGlvbnNIdG1sOiBjYW5kaWRhdGUuZ3JvdW5kaW5nTWV0YWRhdGE/LnNlYXJjaEVudHJ5UG9pbnQ/LnJlbmRlcmVkQ29udGVudCwgc291cmNlcywgdGV4dFxuICB9O1xufTtcbiJdLCJuYW1lcyI6WyJwb3N0IiwiQ29uZmlnIiwiQ29udGVudEdlbmVyYXRpb25SZWplY3RlZEVycm9yIiwiRXJyb3IiLCJDb250ZW50R2VuZXJhdGlvblJlc3BvbnNlRXJyb3IiLCJ2YWxpZE1lc3NhZ2VDb250ZW50IiwibWVzc2FnZSIsImNvbnRlbnQiLCJ0cmltIiwiQXJyYXkiLCJpc0FycmF5IiwibGVuZ3RoIiwiZXZlcnkiLCJwYXJ0IiwidHlwZSIsInRleHQiLCJyb2xlIiwidXJsIiwidGVzdCIsImRldGFpbCIsInVuZGVmaW5lZCIsImluY2x1ZGVzIiwiZ2VuZXJhdGVDb250ZW50IiwiaW5wdXQiLCJjb25maWciLCJnZXQiLCJwcm92aWRlciIsIm1lc3NhZ2VzIiwicHJvbXB0Iiwic29tZSIsInJlYXNvbmluZ0VmZm9ydCIsInJlc3BvbnNlRm9ybWF0IiwidGltZW91dE1zIiwiTnVtYmVyIiwiaXNJbnRlZ2VyIiwiZm9ybWF0IiwibmFtZSIsInNjaGVtYSIsInN0cmljdCIsIm1heFRva2VucyIsImltYWdlcyIsIm1vZGFsaXR5Iiwic2VhcmNoIiwiY2xhdWRlS2V5IiwicmVzcG9uc2UiLCJtYXhfdG9rZW5zIiwibW9kZWwiLCJjbGF1ZGVNb2RlbCIsInN5c3RlbSIsImNhY2hlIiwiaGVhZGVycyIsIkhlYWRlcnMiLCJ0aW1lb3V0IiwiZXJyb3IiLCJmaWx0ZXIiLCJtYXAiLCJqb2luIiwic3RvcF9yZWFzb24iLCJzb3VyY2VzIiwib3BlbmFpS2V5IiwiaW1hZ2VfdXJsIiwiaW5zdHJ1Y3Rpb25zIiwibWF4X291dHB1dF90b2tlbnMiLCJvcGVuYWlNb2RlbCIsInJlYXNvbmluZyIsImVmZm9ydCIsInN0b3JlIiwidHJ1bmNhdGlvbiIsIkF1dGhvcml6YXRpb24iLCJzdGF0dXMiLCJvdXRwdXQiLCJpdGVtIiwiZmxhdE1hcCIsImdlbWluaUtleSIsInBhcnRzIiwiaW1hZ2UiLCJpbmxpbmVEYXRhIiwiZGF0YSIsImJ5dGVzIiwidG9TdHJpbmciLCJtaW1lVHlwZSIsIm1pbWUiLCJnZW1pbmlJbWFnZU1vZGVsIiwiZ2VtaW5pTW9kZWwiLCJjb250ZW50cyIsInN5c3RlbUluc3RydWN0aW9uIiwiZ2VuZXJhdGlvbkNvbmZpZyIsImFzcGVjdFJhdGlvIiwiaW1hZ2VDb25maWciLCJyZXNwb25zZU1vZGFsaXRpZXMiLCJtYXhPdXRwdXRUb2tlbnMiLCJ0b29scyIsImdvb2dsZVNlYXJjaCIsImNvZGUiLCJwcm9tcHRGZWVkYmFjayIsImJsb2NrUmVhc29uIiwiY2FuZGlkYXRlcyIsImNhbmRpZGF0ZSIsImZpbmlzaFJlYXNvbiIsInRob3VnaHQiLCJpbmxpbmUiLCJmaW5kIiwiQnVmZmVyIiwiZnJvbSIsImdyb3VuZGluZ01ldGFkYXRhIiwiZ3JvdW5kaW5nQ2h1bmtzIiwid2ViIiwiVVJMIiwidXJpIiwicHJvdG9jb2wiLCJ0aXRsZSIsImhvc3RuYW1lIiwiaHJlZiIsInNlYXJjaFN1Z2dlc3Rpb25zSHRtbCIsInNlYXJjaEVudHJ5UG9pbnQiLCJyZW5kZXJlZENvbnRlbnQiXSwibWFwcGluZ3MiOiJBQUFBLFNBQVFBLElBQUksUUFBTyxvQkFBb0I7QUFFdkMsU0FBUUMsTUFBTSxRQUFPLGVBQWU7QUFrRHBDLCtFQUErRSxHQUMvRSxPQUFPLE1BQU1DLHVDQUF1Q0M7QUFBTztBQUMzRCw0RkFBNEYsR0FD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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 {};