@blokjs/trigger-worker 0.4.0 → 0.6.1

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 (37) hide show
  1. package/__tests__/integration/nats-adapter.real-nats.test.ts +116 -0
  2. package/__tests__/integration/pgboss-adapter.real-pg.test.ts +164 -0
  3. package/__tests__/integration/rabbitmq-adapter.real-rabbitmq.test.ts +179 -0
  4. package/__tests__/integration/sqs-adapter.real-sqs.test.ts +228 -0
  5. package/dist/WorkerTrigger.d.ts +37 -1
  6. package/dist/WorkerTrigger.js +142 -21
  7. package/dist/adapters/InMemoryAdapter.js +10 -5
  8. package/dist/adapters/KafkaAdapter.d.ts +62 -0
  9. package/dist/adapters/KafkaAdapter.js +236 -0
  10. package/dist/adapters/NATSAdapter.js +3 -3
  11. package/dist/adapters/PgBossAdapter.d.ts +56 -0
  12. package/dist/adapters/PgBossAdapter.js +251 -0
  13. package/dist/adapters/RabbitMQAdapter.d.ts +51 -0
  14. package/dist/adapters/RabbitMQAdapter.js +241 -0
  15. package/dist/adapters/RedisStreamsAdapter.d.ts +64 -0
  16. package/dist/adapters/RedisStreamsAdapter.js +240 -0
  17. package/dist/adapters/SQSAdapter.d.ts +61 -0
  18. package/dist/adapters/SQSAdapter.js +269 -0
  19. package/dist/adapters/factory.d.ts +34 -0
  20. package/dist/adapters/factory.js +103 -0
  21. package/dist/index.d.ts +21 -4
  22. package/dist/index.js +24 -4
  23. package/package.json +23 -5
  24. package/src/WorkerTrigger.ts +153 -22
  25. package/src/adapters/InMemoryAdapter.ts +9 -5
  26. package/src/adapters/KafkaAdapter.ts +277 -0
  27. package/src/adapters/NATSAdapter.ts +4 -2
  28. package/src/adapters/PgBossAdapter.ts +293 -0
  29. package/src/adapters/RabbitMQAdapter.ts +285 -0
  30. package/src/adapters/RedisStreamsAdapter.ts +286 -0
  31. package/src/adapters/SQSAdapter.ts +306 -0
  32. package/src/adapters/factory.test.ts +89 -0
  33. package/src/adapters/factory.ts +111 -0
  34. package/src/adapters/new-adapters.test.ts +130 -0
  35. package/src/index.ts +30 -4
  36. package/template/package.json +6 -6
  37. package/template/src/workflows/jobs/process-job.ts +37 -35
@@ -0,0 +1,61 @@
1
+ /**
2
+ * SQSAdapter — v0.7 PR 5 — Worker adapter backed by AWS SQS via
3
+ * `@aws-sdk/client-sqs`. Polls a queue URL (the `queue` field) with
4
+ * long-polling; processes messages with manual delete (ACK).
5
+ *
6
+ * Semantics:
7
+ * - **Long polling**: `WaitTimeSeconds=20` by default — minimises
8
+ * poll cost. `concurrency` controls how many parallel
9
+ * `ReceiveMessage` loops run.
10
+ * - **Visibility timeout**: configured via `timeout` (ms → s).
11
+ * Messages reappear after this if the worker doesn't delete them.
12
+ * - **Retries**: SQS handles retries automatically via redrive
13
+ * policy on the queue itself. The adapter doesn't simulate
14
+ * retries client-side — set `MaxReceiveCount` on the queue's
15
+ * redrive policy and a DLQ via `deadLetterQueue`.
16
+ * - **FIFO support**: when the queue URL ends with `.fifo`, the
17
+ * adapter passes `MessageGroupId` from `dedupId` or a default.
18
+ *
19
+ * Requires `@aws-sdk/client-sqs` as a peer dependency:
20
+ *
21
+ * bun add @aws-sdk/client-sqs
22
+ *
23
+ * Environment variables (standard AWS SDK):
24
+ * - `AWS_REGION` — default `us-east-1`.
25
+ * - `AWS_ACCESS_KEY_ID` — credentials (or use a profile).
26
+ * - `AWS_SECRET_ACCESS_KEY`
27
+ * - `SQS_ENDPOINT_URL` — for local SQS (LocalStack / ElasticMQ).
28
+ */
29
+ import type { WorkerTriggerOpts } from "@blokjs/helper";
30
+ import type { WorkerAdapter, WorkerJob, WorkerQueueStats } from "../WorkerTrigger";
31
+ export interface SQSConfig {
32
+ region: string;
33
+ endpoint?: string;
34
+ waitTimeSeconds: number;
35
+ maxNumberOfMessages: number;
36
+ }
37
+ export declare class SQSAdapter implements WorkerAdapter {
38
+ readonly provider: "sqs";
39
+ private readonly config;
40
+ private client;
41
+ private commands;
42
+ private runners;
43
+ private connected;
44
+ private stats;
45
+ constructor(config?: Partial<SQSConfig>);
46
+ connect(): Promise<void>;
47
+ disconnect(): Promise<void>;
48
+ process(config: WorkerTriggerOpts, handler: (job: WorkerJob) => Promise<void>): Promise<void>;
49
+ private runConsumerLoop;
50
+ addJob(queue: string, data: unknown, opts?: {
51
+ priority?: number;
52
+ delay?: number;
53
+ retries?: number;
54
+ timeout?: number;
55
+ jobId?: string;
56
+ }): Promise<string>;
57
+ stopProcessing(queue: string): Promise<void>;
58
+ isConnected(): boolean;
59
+ healthCheck(): Promise<boolean>;
60
+ getQueueStats(queue: string): Promise<WorkerQueueStats>;
61
+ }
@@ -0,0 +1,269 @@
1
+ /**
2
+ * SQSAdapter — v0.7 PR 5 — Worker adapter backed by AWS SQS via
3
+ * `@aws-sdk/client-sqs`. Polls a queue URL (the `queue` field) with
4
+ * long-polling; processes messages with manual delete (ACK).
5
+ *
6
+ * Semantics:
7
+ * - **Long polling**: `WaitTimeSeconds=20` by default — minimises
8
+ * poll cost. `concurrency` controls how many parallel
9
+ * `ReceiveMessage` loops run.
10
+ * - **Visibility timeout**: configured via `timeout` (ms → s).
11
+ * Messages reappear after this if the worker doesn't delete them.
12
+ * - **Retries**: SQS handles retries automatically via redrive
13
+ * policy on the queue itself. The adapter doesn't simulate
14
+ * retries client-side — set `MaxReceiveCount` on the queue's
15
+ * redrive policy and a DLQ via `deadLetterQueue`.
16
+ * - **FIFO support**: when the queue URL ends with `.fifo`, the
17
+ * adapter passes `MessageGroupId` from `dedupId` or a default.
18
+ *
19
+ * Requires `@aws-sdk/client-sqs` as a peer dependency:
20
+ *
21
+ * bun add @aws-sdk/client-sqs
22
+ *
23
+ * Environment variables (standard AWS SDK):
24
+ * - `AWS_REGION` — default `us-east-1`.
25
+ * - `AWS_ACCESS_KEY_ID` — credentials (or use a profile).
26
+ * - `AWS_SECRET_ACCESS_KEY`
27
+ * - `SQS_ENDPOINT_URL` — for local SQS (LocalStack / ElasticMQ).
28
+ */
29
+ import { v4 as uuid } from "uuid";
30
+ export class SQSAdapter {
31
+ provider = "sqs";
32
+ config;
33
+ // biome-ignore lint/suspicious/noExplicitAny: @aws-sdk/client-sqs client + command types are loose.
34
+ client = null;
35
+ // biome-ignore lint/suspicious/noExplicitAny: same as above.
36
+ commands = null;
37
+ runners = new Map();
38
+ connected = false;
39
+ stats = new Map();
40
+ constructor(config) {
41
+ this.config = {
42
+ region: config?.region ?? process.env.AWS_REGION ?? "us-east-1",
43
+ endpoint: config?.endpoint ?? process.env.SQS_ENDPOINT_URL,
44
+ waitTimeSeconds: config?.waitTimeSeconds ?? 20,
45
+ maxNumberOfMessages: config?.maxNumberOfMessages ?? 10,
46
+ };
47
+ }
48
+ async connect() {
49
+ if (this.connected)
50
+ return;
51
+ try {
52
+ // biome-ignore lint/suspicious/noExplicitAny: peer dep
53
+ const sdk = await import("@aws-sdk/client-sqs");
54
+ this.client = new sdk.SQSClient({ region: this.config.region, endpoint: this.config.endpoint });
55
+ this.commands = sdk;
56
+ this.connected = true;
57
+ }
58
+ catch (err) {
59
+ throw new Error(`[blok][sqs] connect failed: ${err.message}. Install @aws-sdk/client-sqs as a peer dependency: bun add @aws-sdk/client-sqs`);
60
+ }
61
+ }
62
+ async disconnect() {
63
+ if (!this.connected)
64
+ return;
65
+ for (const runner of this.runners.values())
66
+ runner.stop = true;
67
+ // Wait for in-flight loops to drain — up to 500ms each.
68
+ const drainDeadline = Date.now() + 2000;
69
+ while (Date.now() < drainDeadline) {
70
+ let active = 0;
71
+ for (const r of this.runners.values())
72
+ active += r.loops;
73
+ if (active === 0)
74
+ break;
75
+ await new Promise((r) => setTimeout(r, 50));
76
+ }
77
+ this.runners.clear();
78
+ try {
79
+ this.client?.destroy?.();
80
+ }
81
+ catch {
82
+ /* ignore */
83
+ }
84
+ this.client = null;
85
+ this.connected = false;
86
+ }
87
+ async process(config, handler) {
88
+ if (!this.connected)
89
+ throw new Error("[blok][sqs] not connected. Call connect() first.");
90
+ const runner = { stop: false, loops: 0 };
91
+ this.runners.set(config.queue, runner);
92
+ this.stats.set(config.queue, { completed: 0, failed: 0, active: 0 });
93
+ const stats = this.stats.get(config.queue);
94
+ const concurrency = Math.max(1, config.concurrency ?? 1);
95
+ for (let i = 0; i < concurrency; i += 1) {
96
+ void this.runConsumerLoop(config, handler, runner, stats);
97
+ }
98
+ }
99
+ async runConsumerLoop(config, handler, runner, stats) {
100
+ runner.loops += 1;
101
+ try {
102
+ while (!runner.stop) {
103
+ let response = {};
104
+ try {
105
+ response = await this.client.send(new this.commands.ReceiveMessageCommand({
106
+ QueueUrl: config.queue,
107
+ MaxNumberOfMessages: Math.min(10, this.config.maxNumberOfMessages),
108
+ WaitTimeSeconds: this.config.waitTimeSeconds,
109
+ VisibilityTimeout: typeof config.timeout === "number" ? Math.ceil(config.timeout / 1000) : 30,
110
+ AttributeNames: ["All"],
111
+ MessageAttributeNames: ["All"],
112
+ }));
113
+ }
114
+ catch (err) {
115
+ // Transient — back off briefly then retry.
116
+ await new Promise((r) => setTimeout(r, 1000));
117
+ continue;
118
+ }
119
+ const messages = response.Messages ?? [];
120
+ for (const m of messages) {
121
+ if (runner.stop)
122
+ break;
123
+ stats.active += 1;
124
+ // Tracks whether the message has already been settled via
125
+ // the WorkerJob API (`complete` / `fail`). Declared OUTSIDE
126
+ // the try so the catch arm can read it and skip its own
127
+ // nack/fail bookkeeping when the handler explicitly
128
+ // settled. Without this flag we'd double-delete the
129
+ // receipt handle AND a `fail()` call would be silently
130
+ // overruled by the wrapper deleting the message anyway.
131
+ // Caught by the real-broker integration test in
132
+ // `__tests__/integration/sqs-adapter.real-sqs.test.ts`.
133
+ let settled = false;
134
+ try {
135
+ const payloadString = m.Body ?? "";
136
+ let data;
137
+ try {
138
+ data = payloadString.length > 0 ? JSON.parse(payloadString) : null;
139
+ }
140
+ catch {
141
+ data = payloadString;
142
+ }
143
+ const headers = {};
144
+ for (const [k, v] of Object.entries(m.MessageAttributes ?? {})) {
145
+ if (typeof v.StringValue === "string")
146
+ headers[k] = v.StringValue;
147
+ }
148
+ const job = {
149
+ id: m.MessageId ?? `${config.queue}:${uuid()}`,
150
+ data,
151
+ headers,
152
+ queue: config.queue,
153
+ priority: config.priority ?? 0,
154
+ attempts: Number.parseInt(m.Attributes?.ApproximateReceiveCount ?? "1", 10) - 1,
155
+ maxRetries: config.retries ?? 0,
156
+ createdAt: new Date(),
157
+ timeout: config.timeout,
158
+ raw: m,
159
+ complete: async () => {
160
+ if (settled)
161
+ return;
162
+ if (m.ReceiptHandle) {
163
+ await this.client.send(new this.commands.DeleteMessageCommand({
164
+ QueueUrl: config.queue,
165
+ ReceiptHandle: m.ReceiptHandle,
166
+ }));
167
+ }
168
+ stats.completed += 1;
169
+ settled = true;
170
+ },
171
+ fail: async (_err) => {
172
+ if (settled)
173
+ return;
174
+ stats.failed += 1;
175
+ // No DeleteMessage call — visibility timeout
176
+ // expires and SQS returns the message to the
177
+ // queue automatically. DLQ takeover happens via
178
+ // the queue's RedrivePolicy + MaxReceiveCount.
179
+ settled = true;
180
+ },
181
+ };
182
+ await handler(job);
183
+ if (!settled && config.ack !== false && m.ReceiptHandle) {
184
+ await this.client.send(new this.commands.DeleteMessageCommand({ QueueUrl: config.queue, ReceiptHandle: m.ReceiptHandle }));
185
+ stats.completed += 1;
186
+ settled = true;
187
+ }
188
+ }
189
+ catch {
190
+ if (!settled) {
191
+ stats.failed += 1;
192
+ // Leave the message in flight — SQS visibility
193
+ // timeout expiry returns it to the queue.
194
+ }
195
+ }
196
+ finally {
197
+ stats.active = Math.max(0, stats.active - 1);
198
+ }
199
+ }
200
+ }
201
+ }
202
+ finally {
203
+ runner.loops -= 1;
204
+ }
205
+ }
206
+ async addJob(queue, data, opts) {
207
+ if (!this.connected)
208
+ throw new Error("[blok][sqs] not connected. Call connect() first.");
209
+ const messageId = opts?.jobId ?? uuid();
210
+ const isFifo = queue.endsWith(".fifo");
211
+ const params = {
212
+ QueueUrl: queue,
213
+ MessageBody: typeof data === "string" ? data : JSON.stringify(data),
214
+ };
215
+ if (isFifo) {
216
+ params.MessageGroupId = opts?.jobId ?? "default";
217
+ params.MessageDeduplicationId = messageId;
218
+ }
219
+ if (typeof opts?.delay === "number" && opts.delay > 0) {
220
+ params.DelaySeconds = Math.min(900, Math.ceil(opts.delay / 1000));
221
+ }
222
+ const result = await this.client.send(new this.commands.SendMessageCommand(params));
223
+ return result.MessageId ?? messageId;
224
+ }
225
+ async stopProcessing(queue) {
226
+ const runner = this.runners.get(queue);
227
+ if (runner)
228
+ runner.stop = true;
229
+ }
230
+ isConnected() {
231
+ return this.connected;
232
+ }
233
+ async healthCheck() {
234
+ if (!this.connected)
235
+ return false;
236
+ try {
237
+ // ListQueues is a cheap permission probe.
238
+ await this.client.send(new this.commands.ListQueuesCommand({ MaxResults: 1 }));
239
+ return true;
240
+ }
241
+ catch {
242
+ return false;
243
+ }
244
+ }
245
+ async getQueueStats(queue) {
246
+ const counters = this.stats.get(queue) ?? { completed: 0, failed: 0, active: 0 };
247
+ let waiting = 0;
248
+ let delayed = 0;
249
+ try {
250
+ const result = await this.client.send(new this.commands.GetQueueAttributesCommand({
251
+ QueueUrl: queue,
252
+ AttributeNames: ["ApproximateNumberOfMessages", "ApproximateNumberOfMessagesDelayed"],
253
+ }));
254
+ waiting = Number.parseInt(result.Attributes?.ApproximateNumberOfMessages ?? "0", 10);
255
+ delayed = Number.parseInt(result.Attributes?.ApproximateNumberOfMessagesDelayed ?? "0", 10);
256
+ }
257
+ catch {
258
+ /* ignore */
259
+ }
260
+ return {
261
+ waiting,
262
+ active: counters.active,
263
+ completed: counters.completed,
264
+ failed: counters.failed,
265
+ delayed,
266
+ };
267
+ }
268
+ }
269
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiU1FTQWRhcHRlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9hZGFwdGVycy9TUVNBZGFwdGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0EyQkc7QUFHSCxPQUFPLEVBQUUsRUFBRSxJQUFJLElBQUksRUFBRSxNQUFNLE1BQU0sQ0FBQztBQTZCbEMsTUFBTSxPQUFPLFVBQVU7SUFDYixRQUFRLEdBQUcsS0FBYyxDQUFDO0lBQ2xCLE1BQU0sQ0FBWTtJQUNuQyxvR0FBb0c7SUFDNUYsTUFBTSxHQUFRLElBQUksQ0FBQztJQUMzQiw2REFBNkQ7SUFDckQsUUFBUSxHQUFRLElBQUksQ0FBQztJQUNyQixPQUFPLEdBQTZCLElBQUksR0FBRyxFQUFFLENBQUM7SUFDOUMsU0FBUyxHQUFHLEtBQUssQ0FBQztJQUNsQixLQUFLLEdBQW9DLElBQUksR0FBRyxFQUFFLENBQUM7SUFFM0QsWUFBWSxNQUEyQjtRQUN0QyxJQUFJLENBQUMsTUFBTSxHQUFHO1lBQ2IsTUFBTSxFQUFFLE1BQU0sRUFBRSxNQUFNLElBQUksT0FBTyxDQUFDLEdBQUcsQ0FBQyxVQUFVLElBQUksV0FBVztZQUMvRCxRQUFRLEVBQUUsTUFBTSxFQUFFLFFBQVEsSUFBSSxPQUFPLENBQUMsR0FBRyxDQUFDLGdCQUFnQjtZQUMxRCxlQUFlLEVBQUUsTUFBTSxFQUFFLGVBQWUsSUFBSSxFQUFFO1lBQzlDLG1CQUFtQixFQUFFLE1BQU0sRUFBRSxtQkFBbUIsSUFBSSxFQUFFO1NBQ3RELENBQUM7SUFDSCxDQUFDO0lBRUQsS0FBSyxDQUFDLE9BQU87UUFDWixJQUFJLElBQUksQ0FBQyxTQUFTO1lBQUUsT0FBTztRQUMzQixJQUFJLENBQUM7WUFDSix1REFBdUQ7WUFDdkQsTUFBTSxHQUFHLEdBQVEsTUFBTSxNQUFNLENBQUMscUJBQXFCLENBQUMsQ0FBQztZQUNyRCxJQUFJLENBQUMsTUFBTSxHQUFHLElBQUks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O1FBQzdGLENBQUM7UUFBQyxNQUFNLENBQUM7WUFDUixZQUFZO1FBQ2IsQ0FBQztRQUNELE9BQU87WUFDTixPQUFPO1lBQ1AsTUFBTSxFQUFFLFFBQVEsQ0FBQyxNQUFNO1lBQ3ZCLFNBQVMsRUFBRSxRQUFRLENBQUMsU0FBUztZQUM3QixNQUFNLEVBQUUsUUFBUSxDQUFDLE1BQU07WUFDdkIsT0FBTztTQUNQLENBQUM7SUFDSCxDQUFDO0NBQ0QiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIFNRU0FkYXB0ZXIg4oCUIHYwLjcgUFIgNSDigJQgV29ya2VyIGFkYXB0ZXIgYmFja2VkIGJ5IEFXUyBTUVMgdmlhXG4gKiBgQGF3cy1zZGsvY2xpZW50LXNxc2AuIFBvbGxzIGEgcXVldWUgVVJMICh0aGUgYHF1ZXVlYCBmaWVsZCkgd2l0aFxuICogbG9uZy1wb2xsaW5nOyBwcm9jZXNzZXMgbWVzc2FnZXMgd2l0aCBtYW51YWwgZGVsZXRlIChBQ0spLlxuICpcbiAqIFNlbWFudGljczpcbiAqICAgLSAqKkxvbmcgcG9sbGluZyoqOiBgV2FpdFRpbWVTZWNvbmRzPTIwYCBieSBkZWZhdWx0IOKAlCBtaW5pbWlzZXNcbiAqICAgICBwb2xsIGNvc3QuIGBjb25jdXJyZW5jeWAgY29udHJvbHMgaG93IG1hbnkgcGFyYWxsZWxcbiAqICAgICBgUmVjZWl2ZU1lc3NhZ2VgIGxvb3BzIHJ1bi5cbiAqICAgLSAqKlZpc2liaWxpdHkgdGltZW91dCoqOiBjb25maWd1cmVkIHZpYSBgdGltZW91dGAgKG1zIOKGkiBzKS5cbiAqICAgICBNZXNzYWdlcyByZWFwcGVhciBhZnRlciB0aGlzIGlmIHRoZSB3b3JrZXIgZG9lc24ndCBkZWxldGUgdGhlbS5cbiAqICAgLSAqKlJldHJpZXMqKjogU1FTIGhhbmRsZXMgcmV0cmllcyBhdXRvbWF0aWNhbGx5IHZpYSByZWRyaXZlXG4gKiAgICAgcG9saWN5IG9uIHRoZSBxdWV1ZSBpdHNlbGYuIFRoZSBhZGFwdGVyIGRvZXNuJ3Qgc2ltdWxhdGVcbiAqICAgICByZXRyaWVzIGNsaWVudC1zaWRlIOKAlCBzZXQgYE1heFJlY2VpdmVDb3VudGAgb24gdGhlIHF1ZXVlJ3NcbiAqICAgICByZWRyaXZlIHBvbGljeSBhbmQgYSBETFEgdmlhIGBkZWFkTGV0dGVyUXVldWVgLlxuICogICAtICoqRklGTyBzdXBwb3J0Kio6IHdoZW4gdGhlIHF1ZXVlIFVSTCBlbmRzIHdpdGggYC5maWZvYCwgdGhlXG4gKiAgICAgYWRhcHRlciBwYXNzZXMgYE1lc3NhZ2VHcm91cElkYCBmcm9tIGBkZWR1cElkYCBvciBhIGRlZmF1bHQuXG4gKlxuICogUmVxdWlyZXMgYEBhd3Mtc2RrL2NsaWVudC1zcXNgIGFzIGEgcGVlciBkZXBlbmRlbmN5OlxuICpcbiAqICAgICBidW4gYWRkIEBhd3Mtc2RrL2NsaWVudC1zcXNcbiAqXG4gKiBFbnZpcm9ubWVudCB2YXJpYWJsZXMgKHN0YW5kYXJkIEFXUyBTREspOlxuICogICAtIGBBV1NfUkVHSU9OYCAgICAgICAgICAgICAg4oCUIGRlZmF1bHQgYHVzLWVhc3QtMWAuXG4gKiAgIC0gYEFXU19BQ0NFU1NfS0VZX0lEYCAgICAgICDigJQgY3JlZGVudGlhbHMgKG9yIHVzZSBhIHByb2ZpbGUpLlxuICogICAtIGBBV1NfU0VDUkVUX0FDQ0VTU19LRVlgXG4gKiAgIC0gYFNRU19FTkRQT0lOVF9VUkxgICAgICAgICDigJQgZm9yIGxvY2FsIFNRUyAoTG9jYWxTdGFjayAvIEVsYXN0aWNNUSkuXG4gKi9cblxuaW1wb3J0IHR5cGUgeyBXb3JrZXJUcmlnZ2VyT3B0cyB9IGZyb20gXCJAYmxva2pzL2hlbHBlclwiO1xuaW1wb3J0IHsgdjQgYXMgdXVpZCB9IGZyb20gXCJ1dWlkXCI7XG5pbXBvcnQgdHlwZSB7IFdvcmtlckFkYXB0ZXIsIFdvcmtlckpvYiwgV29ya2VyUXVldWVTdGF0cyB9IGZyb20gXCIuLi9Xb3JrZXJUcmlnZ2VyXCI7XG5cbmV4cG9ydCBpbnRlcmZhY2UgU1FTQ29uZmlnIHtcblx0cmVnaW9uOiBzdHJpbmc7XG5cdGVuZHBvaW50Pzogc3RyaW5nO1xuXHR3YWl0VGltZVNlY29uZHM6IG51bWJlcjtcblx0bWF4TnVtYmVyT2ZNZXNzYWdlczogbnVtYmVyO1xufVxuXG5pbnRlcmZhY2UgU3FzTWVzc2FnZSB7XG5cdE1lc3NhZ2VJZD86IHN0cmluZztcblx0UmVjZWlwdEhhbmRsZT86IHN0cmluZztcblx0Qm9keT86IHN0cmluZztcblx0QXR0cmlidXRlcz86IFJlY29yZDxzdHJpbmcsIHN0cmluZz47XG5cdE1lc3NhZ2VBdHRyaWJ1dGVzPzogUmVjb3JkPHN0cmluZywgeyBTdHJpbmdWYWx1ZT86IHN0cmluZyB9Pjtcbn1cblxuaW50ZXJmYWNlIFF1ZXVlUnVubmVyIHtcblx0c3RvcDogYm9vbGVhbjtcblx0bG9vcHM6IG51bWJlcjtcbn1cblxuaW50ZXJmYWNlIFF1ZXVlU3RhdHNDb3VudGVycyB7XG5cdGNvbXBsZXRlZDogbnVtYmVyO1xuXHRmYWlsZWQ6IG51bWJlcjtcblx0YWN0aXZlOiBudW1iZXI7XG59XG5cbmV4cG9ydCBjbGFzcyBTUVNBZGFwdGVyIGltcGxlbWVudHMgV29ya2VyQWRhcHRlciB7XG5cdHJlYWRvbmx5IHByb3ZpZGVyID0gXCJzcXNcIiBhcyBjb25zdDtcblx0cHJpdmF0ZSByZWFkb25seSBjb25maWc6IFNRU0NvbmZpZztcblx0Ly8gYmlvbWUtaWdub3JlIGxpbnQvc3VzcGljaW91cy9ub0V4cGxpY2l0QW55OiBAYXdzLXNkay9jbGllbnQtc3FzIGNsaWVudCArIGNvbW1hbmQgdHlwZXMgYXJlIGxvb3NlLlxuXHRwcml2YXRlIGNsaWVudDogYW55ID0gbnVsbDtcblx0Ly8gYmlvbWUtaWdub3JlIGxpbnQvc3VzcGljaW91cy9ub0V4cGxpY2l0QW55OiBzYW1lIGFzIGFib3ZlLlxuXHRwcml2YXRlIGNvbW1hbmRzOiBhbnkgPSBudWxsO1xuXHRwcml2YXRlIHJ1bm5lcnM6IE1hcDxzdHJpbmcsIFF1ZXVlUnVubmVyPiA9IG5ldyBNYXAoKTtcblx0cHJpdmF0ZSBjb25uZWN0ZWQgPSBmYWxzZTtcblx0cHJpdmF0ZSBzdGF0czogTWFwPHN0cmluZywgUXVldWVTdGF0c0NvdW50ZXJzPiA9IG5ldyBNYXAoKTtcblxuXHRjb25zdHJ1Y3Rvcihjb25maWc/OiBQYXJ0aWFsPFNRU0NvbmZpZz4pIHtcblx0XHR0aGlzLmNvbmZpZyA9IHtcblx0XHRcdHJlZ2lvbjogY29uZmlnPy5yZWdpb24gPz8gcHJvY2Vzcy5lbnYuQVdTX1JFR0lPTiA/PyBcInVzLWVhc3QtMVwiLFxuXHRcdFx0ZW5kcG9pbnQ6IGNvbmZpZz8uZW5kcG9pbnQgPz8gcHJvY2Vzcy5lbnYuU1FTX0VORFBPSU5UX1VSTCxcblx0XHRcdHdhaXRUaW1lU2Vjb25kczogY29uZmlnPy53YWl0VGltZVNlY29uZHMgPz8gMjAsXG5cdFx0XHRtYXhOdW1iZXJPZk1lc3NhZ2VzOiBjb25maWc/Lm1heE51bWJlck9mTWVzc2FnZXMgPz8gMTAsXG5cdFx0fTtcblx0fVxuXG5cdGFzeW5jIGNvbm5lY3QoKTogUHJvbWlzZTx2b2lkPiB7XG5cdFx0aWYgKHRoaXMuY29ubmVjdGVkKSByZXR1cm47XG5cdFx0dHJ5IHtcblx0XHRcdC8vIGJpb21lLWlnbm9yZSBsaW50L3N1c3BpY2lvdXMvbm9FeHBsaWNpdEFueTogcGVlciBkZXBcblx0XHRcdGNvbnN0IHNkazogYW55ID0gYXdhaXQgaW1wb3J0KFwiQGF3cy1zZGsvY2xpZW50LXNxc1wiKTtcblx0XHRcdHRoaXMuY2xpZW50ID0gbmV3IHNkay5TUVNDbGllbnQoeyByZWdpb246IHRoaXMuY29uZmlnLnJlZ2lvbiwgZW5kcG9pbnQ6IHRoaXMuY29uZmlnLmVuZHBvaW50IH0pO1xuXHRcdFx0dGhpcy5jb21tYW5kcyA9IHNkaztcblx0XHRcdHRoaXMuY29ubmVjdGVkID0gdHJ1ZTtcblx0XHR9IGNhdGNoIChlcnIpIHtcblx0XHRcdHRocm93IG5ldyBFcnJvcihcblx0XHRcdFx0YFtibG9rXVtzcXNdIGNvbm5lY3QgZmFpbGVkOiAkeyhlcnIgYXMgRXJyb3IpLm1lc3NhZ2V9LiBJbnN0YWxsIEBhd3Mtc2RrL2NsaWVudC1zcXMgYXMgYSBwZWVyIGRlcGVuZGVuY3k6IGJ1biBhZGQgQGF3cy1zZGsvY2xpZW50LXNxc2AsXG5cdFx0XHQpO1xuXHRcdH1cblx0fVxuXG5cdGFzeW5jIGRpc2Nvbm5lY3QoKTogUHJvbWlzZTx2b2lkPiB7XG5cdFx0aWYgKCF0aGlzLmNvbm5lY3RlZCkgcmV0dXJuO1xuXHRcdGZvciAoY29uc3QgcnVubmVyIG9mIHRoaXMucnVubmVycy52YWx1ZXMoKSkgcnVubmVyLnN0b3AgPSB0cnVlO1xuXHRcdC8vIFdhaXQgZm9yIGluLWZsaWdodCBsb29wcyB0byBkcmFpbiDigJQgdXAgdG8gNTAwbXMgZWFjaC5cblx0XHRjb25zdCBkcmFpbkRlYWRsaW5lID0gRGF0ZS5ub3coKSArIDIwMDA7XG5cdFx0d2hpbGUgKERhdGUubm93KCkgPCBkcmFpbkRlYWRsaW5lKSB7XG5cdFx0XHRsZXQgYWN0aXZlID0gMDtcblx0XHRcdGZvciAoY29uc3QgciBvZiB0aGlzLnJ1bm5lcnMudmFsdWVzKCkpIGFjdGl2ZSArPSByLmxvb3BzO1xuXHRcdFx0aWYgKGFjdGl2ZSA9PT0gMCkgYnJlYWs7XG5cdFx0XHRhd2FpdCBuZXcgUHJvbWlzZSgocikgPT4gc2V0VGltZW91dChyLCA1MCkpO1xuXHRcdH1cblx0XHR0aGlzLnJ1bm5lcnMuY2xlYXIoKTtcblx0XHR0cnkge1xuXHRcdFx0dGhpcy5jbGllbnQ/LmRlc3Ryb3k/LigpO1xuXHRcdH0gY2F0Y2gge1xuXHRcdFx0LyogaWdub3JlICovXG5cdFx0fVxuXHRcdHRoaXMuY2xpZW50ID0gbnVsbDtcblx0XHR0aGlzLmNvbm5lY3RlZCA9IGZhbHNlO1xuXHR9XG5cblx0YXN5bmMgcHJvY2Vzcyhjb25maWc6IFdvcmtlclRyaWdnZXJPcHRzLCBoYW5kbGVyOiAoam9iOiBXb3JrZXJKb2IpID0+IFByb21pc2U8dm9pZD4pOiBQcm9taXNlPHZvaWQ+IHtcblx0XHRpZiAoIXRoaXMuY29ubmVjdGVkKSB0aHJvdyBuZXcgRXJyb3IoXCJbYmxva11bc3FzXSBub3QgY29ubmVjdGVkLiBDYWxsIGNvbm5lY3QoKSBmaXJzdC5cIik7XG5cdFx0Y29uc3QgcnVubmVyOiBRdWV1ZVJ1bm5lciA9IHsgc3RvcDogZmFsc2UsIGxvb3BzOiAwIH07XG5cdFx0dGhpcy5ydW5uZXJzLnNldChjb25maWcucXVldWUsIHJ1bm5lcik7XG5cdFx0dGhpcy5zdGF0cy5zZXQoY29uZmlnLnF1ZXVlLCB7IGNvbXBsZXRlZDogMCwgZmFpbGVkOiAwLCBhY3RpdmU6IDAgfSk7XG5cdFx0Y29uc3Qgc3RhdHMgPSB0aGlzLnN0YXRzLmdldChjb25maWcucXVldWUpIGFzIFF1ZXVlU3RhdHNDb3VudGVycztcblxuXHRcdGNvbnN0IGNvbmN1cnJlbmN5ID0gTWF0aC5tYXgoMSwgY29uZmlnLmNvbmN1cnJlbmN5ID8/IDEpO1xuXHRcdGZvciAobGV0IGkgPSAwOyBpIDwgY29uY3VycmVuY3k7IGkgKz0gMSkge1xuXHRcdFx0dm9pZCB0aGlzLnJ1bkNvbnN1bWVyTG9vcChjb25maWcsIGhhbmRsZXIsIHJ1bm5lciwgc3RhdHMpO1xuXHRcdH1cblx0fVxuXG5cdHByaXZhdGUgYXN5bmMgcnVuQ29uc3VtZXJMb29wKFxuXHRcdGNvbmZpZzogV29ya2VyVHJpZ2dlck9wdHMsXG5cdFx0aGFuZGxlcjogKGpvYjogV29ya2VySm9iKSA9PiBQcm9taXNlPHZvaWQ+LFxuXHRcdHJ1bm5lcjogUXVldWVSdW5uZXIsXG5cdFx0c3RhdHM6IFF1ZXVlU3RhdHNDb3VudGVycyxcblx0KTogUHJvbWlzZTx2b2lkPiB7XG5cdFx0cnVubmVyLmxvb3BzICs9IDE7XG5cdFx0dHJ5IHtcblx0XHRcdHdoaWxlICghcnVubmVyLnN0b3ApIHtcblx0XHRcdFx0bGV0IHJlc3BvbnNlOiB7IE1lc3NhZ2VzPzogU3FzTWVzc2FnZVtdIH0gPSB7fTtcblx0XHRcdFx0dHJ5IHtcblx0XHRcdFx0XHRyZXNwb25zZSA9IGF3YWl0IHRoaXMuY2xpZW50LnNlbmQoXG5cdFx0XHRcdFx0XHRuZXcgdGhpcy5jb21tYW5kcy5SZWNlaXZlTWVzc2FnZUNvbW1hbmQoe1xuXHRcdFx0XHRcdFx0XHRRdWV1ZVVybDogY29uZmlnLnF1ZXVlLFxuXHRcdFx0XHRcdFx0XHRNYXhOdW1iZXJPZk1lc3NhZ2VzOiBNYXRoLm1pbigxMCwgdGhpcy5jb25maWcubWF4TnVtYmVyT2ZNZXNzYWdlcyksXG5cdFx0XHRcdFx0XHRcdFdhaXRUaW1lU2Vjb25kczogdGhpcy5jb25maWcud2FpdFRpbWVTZWNvbmRzLFxuXHRcdFx0XHRcdFx0XHRWaXNpYmlsaXR5VGltZW91dDogdHlwZW9mIGNvbmZpZy50aW1lb3V0ID09PSBcIm51bWJlclwiID8gTWF0aC5jZWlsKGNvbmZpZy50aW1lb3V0IC8gMTAwMCkgOiAzMCxcblx0XHRcdFx0XHRcdFx0QXR0cmlidXRlTmFtZXM6IFtcIkFsbFwiXSxcblx0XHRcdFx0XHRcdFx0TWVzc2FnZUF0dHJpYnV0ZU5hbWVzOiBbXCJBbGxcIl0sXG5cdFx0XHRcdFx0XHR9KSxcblx0XHRcdFx0XHQpO1xuXHRcdFx0XHR9IGNhdGNoIChlcnIpIHtcblx0XHRcdFx0XHQvLyBUcmFuc2llbnQg4oCUIGJhY2sgb2ZmIGJyaWVmbHkgdGhlbiByZXRyeS5cblx0XHRcdFx0XHRhd2FpdCBuZXcgUHJvbWlzZSgocikgPT4gc2V0VGltZW91dChyLCAxMDAwKSk7XG5cdFx0XHRcdFx0Y29udGludWU7XG5cdFx0XHRcdH1cblx0XHRcdFx0Y29uc3QgbWVzc2FnZXMgPSByZXNwb25zZS5NZXNzYWdlcyA/PyBbXTtcblx0XHRcdFx0Zm9yIChjb25zdCBtIG9mIG1lc3NhZ2VzKSB7XG5cdFx0XHRcdFx0aWYgKHJ1bm5lci5zdG9wKSBicmVhaztcblx0XHRcdFx0XHRzdGF0cy5hY3RpdmUgKz0gMTtcblx0XHRcdFx0XHQvLyBUcmFja3Mgd2hldGhlciB0aGUgbWVzc2FnZSBoYXMgYWxyZWFkeSBiZWVuIHNldHRsZWQgdmlhXG5cdFx0XHRcdFx0Ly8gdGhlIFdvcmtlckpvYiBBUEkgKGBjb21wbGV0ZWAgLyBgZmFpbGApLiBEZWNsYXJlZCBPVVRTSURFXG5cdFx0XHRcdFx0Ly8gdGhlIHRyeSBzbyB0aGUgY2F0Y2ggYXJtIGNhbiByZWFkIGl0IGFuZCBza2lwIGl0cyBvd25cblx0XHRcdFx0XHQvLyBuYWNrL2ZhaWwgYm9va2tlZXBpbmcgd2hlbiB0aGUgaGFuZGxlciBleHBsaWNpdGx5XG5cdFx0XHRcdFx0Ly8gc2V0dGxlZC4gV2l0aG91dCB0aGlzIGZsYWcgd2UnZCBkb3VibGUtZGVsZXRlIHRoZVxuXHRcdFx0XHRcdC8vIHJlY2VpcHQgaGFuZGxlIEFORCBhIGBmYWlsKClgIGNhbGwgd291bGQgYmUgc2lsZW50bHlcblx0XHRcdFx0XHQvLyBvdmVycnVsZWQgYnkgdGhlIHdyYXBwZXIgZGVsZXRpbmcgdGhlIG1lc3NhZ2UgYW55d2F5LlxuXHRcdFx0XHRcdC8vIENhdWdodCBieSB0aGUgcmVhbC1icm9rZXIgaW50ZWdyYXRpb24gdGVzdCBpblxuXHRcdFx0XHRcdC8vIGBfX3Rlc3RzX18vaW50ZWdyYXRpb24vc3FzLWFkYXB0ZXIucmVhbC1zcXMudGVzdC50c2AuXG5cdFx0XHRcdFx0bGV0IHNldHRsZWQgPSBmYWxzZTtcblx0XHRcdFx0XHR0cnkge1xuXHRcdFx0XHRcdFx0Y29uc3QgcGF5bG9hZFN0cmluZyA9IG0uQm9keSA/PyBcIlwiO1xuXHRcdFx0XHRcdFx0bGV0IGRhdGE6IHVua25vd247XG5cdFx0XHRcdFx0XHR0cnkge1xuXHRcdFx0XHRcdFx0XHRkYXRhID0gcGF5bG9hZFN0cmluZy5sZW5ndGggPiAwID8gSlNPTi5wYXJzZShwYXlsb2FkU3RyaW5nKSA6IG51bGw7XG5cdFx0XHRcdFx0XHR9IGNhdGNoIHtcblx0XHRcdFx0XHRcdFx0ZGF0YSA9IHBheWxvYWRTdHJpbmc7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRjb25zdCBoZWFkZXJzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge307XG5cdFx0XHRcdFx0XHRmb3IgKGNvbnN0IFtrLCB2XSBvZiBPYmplY3QuZW50cmllcyhtLk1lc3NhZ2VBdHRyaWJ1dGVzID8/IHt9KSkge1xuXHRcdFx0XHRcdFx0XHRpZiAodHlwZW9mIHYuU3RyaW5nVmFsdWUgPT09IFwic3RyaW5nXCIpIGhlYWRlcnNba10gPSB2LlN0cmluZ1ZhbHVlO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0Y29uc3Qgam9iOiBXb3JrZXJKb2IgPSB7XG5cdFx0XHRcdFx0XHRcdGlkOiBtLk1lc3NhZ2VJZCA/PyBgJHtjb25maWcucXVldWV9OiR7dXVpZCgpfWAsXG5cdFx0XHRcdFx0XHRcdGRhdGEsXG5cdFx0XHRcdFx0XHRcdGhlYWRlcnMsXG5cdFx0XHRcdFx0XHRcdHF1ZXVlOiBjb25maWcucXVldWUsXG5cdFx0XHRcdFx0XHRcdHByaW9yaXR5OiBjb25maWcucHJpb3JpdHkgPz8gMCxcblx0XHRcdFx0XHRcdFx0YXR0ZW1wdHM6IE51bWJlci5wYXJzZUludChtLkF0dHJpYnV0ZXM/LkFwcHJveGltYXRlUmVjZWl2ZUNvdW50ID8/IFwiMVwiLCAxMCkgLSAxLFxuXHRcdFx0XHRcdFx0XHRtYXhSZXRyaWVzOiBjb25maWcucmV0cmllcyA/PyAwLFxuXHRcdFx0XHRcdFx0XHRjcmVhdGVkQXQ6IG5ldyBEYXRlKCksXG5cdFx0XHRcdFx0XHRcdHRpbWVvdXQ6IGNvbmZpZy50aW1lb3V0LFxuXHRcdFx0XHRcdFx0XHRyYXc6IG0sXG5cdFx0XHRcdFx0XHRcdGNvbXBsZXRlOiBhc3luYyAoKSA9PiB7XG5cdFx0XHRcdFx0XHRcdFx0aWYgKHNldHRsZWQpIHJldHVybjtcblx0XHRcdFx0XHRcdFx0XHRpZiAobS5SZWNlaXB0SGFuZGxlKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRhd2FpdCB0aGlzLmNsaWVudC5zZW5kKFxuXHRcdFx0XHRcdFx0XHRcdFx0XHRuZXcgdGhpcy5jb21tYW5kcy5EZWxldGVNZXNzYWdlQ29tbWFuZCh7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0UXVldWVVcmw6IGNvbmZpZy5xdWV1ZSxcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRSZWNlaXB0SGFuZGxlOiBtLlJlY2VpcHRIYW5kbGUsXG5cdFx0XHRcdFx0XHRcdFx0XHRcdH0pLFxuXHRcdFx0XHRcdFx0XHRcdFx0KTtcblx0XHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdFx0c3RhdHMuY29tcGxldGVkICs9IDE7XG5cdFx0XHRcdFx0XHRcdFx0c2V0dGxlZCA9IHRydWU7XG5cdFx0XHRcdFx0XHRcdH0sXG5cdFx0XHRcdFx0XHRcdGZhaWw6IGFzeW5jIChfZXJyOiBFcnJvcikgPT4ge1xuXHRcdFx0XHRcdFx0XHRcdGlmIChzZXR0bGVkKSByZXR1cm47XG5cdFx0XHRcdFx0XHRcdFx0c3RhdHMuZmFpbGVkICs9IDE7XG5cdFx0XHRcdFx0XHRcdFx0Ly8gTm8gRGVsZXRlTWVzc2FnZSBjYWxsIOKAlCB2aXNpYmlsaXR5IHRpbWVvdXRcblx0XHRcdFx0XHRcdFx0XHQvLyBleHBpcmVzIGFuZCBTUVMgcmV0dXJucyB0aGUgbWVzc2FnZSB0byB0aGVcblx0XHRcdFx0XHRcdFx0XHQvLyBxdWV1ZSBhdXRvbWF0aWNhbGx5LiBETFEgdGFrZW92ZXIgaGFwcGVucyB2aWFcblx0XHRcdFx0XHRcdFx0XHQvLyB0aGUgcXVldWUncyBSZWRyaXZlUG9saWN5ICsgTWF4UmVjZWl2ZUNvdW50LlxuXHRcdFx0XHRcdFx0XHRcdHNldHRsZWQgPSB0cnVlO1xuXHRcdFx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdFx0fTtcblx0XHRcdFx0XHRcdGF3YWl0IGhhbmRsZXIoam9iKTtcblx0XHRcdFx0XHRcdGlmICghc2V0dGxlZCAmJiBjb25maWcuYWNrICE9PSBmYWxzZSAmJiBtLlJlY2VpcHRIYW5kbGUpIHtcblx0XHRcdFx0XHRcdFx0YXdhaXQgdGhpcy5jbGllbnQuc2VuZChcblx0XHRcdFx0XHRcdFx0XHRuZXcgdGhpcy5jb21tYW5kcy5EZWxldGVNZXNzYWdlQ29tbWFuZCh7IFF1ZXVlVXJsOiBjb25maWcucXVldWUsIFJlY2VpcHRIYW5kbGU6IG0uUmVjZWlwdEhhbmRsZSB9KSxcblx0XHRcdFx0XHRcdFx0KTtcblx0XHRcdFx0XHRcdFx0c3RhdHMuY29tcGxldGVkICs9IDE7XG5cdFx0XHRcdFx0XHRcdHNldHRsZWQgPSB0cnVlO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH0gY2F0Y2gge1xuXHRcdFx0XHRcdFx0aWYgKCFzZXR0bGVkKSB7XG5cdFx0XHRcdFx0XHRcdHN0YXRzLmZhaWxlZCArPSAxO1xuXHRcdFx0XHRcdFx0XHQvLyBMZWF2ZSB0aGUgbWVzc2FnZSBpbiBmbGlnaHQg4oCUIFNRUyB2aXNpYmlsaXR5XG5cdFx0XHRcdFx0XHRcdC8vIHRpbWVvdXQgZXhwaXJ5IHJldHVybnMgaXQgdG8gdGhlIHF1ZXVlLlxuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH0gZmluYWxseSB7XG5cdFx0XHRcdFx0XHRzdGF0cy5hY3RpdmUgPSBNYXRoLm1heCgwLCBzdGF0cy5hY3RpdmUgLSAxKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9IGZpbmFsbHkge1xuXHRcdFx0cnVubmVyLmxvb3BzIC09IDE7XG5cdFx0fVxuXHR9XG5cblx0YXN5bmMgYWRkSm9iKFxuXHRcdHF1ZXVlOiBzdHJpbmcsXG5cdFx0ZGF0YTogdW5rbm93bixcblx0XHRvcHRzPzogeyBwcmlvcml0eT86IG51bWJlcjsgZGVsYXk/OiBudW1iZXI7IHJldHJpZXM/OiBudW1iZXI7IHRpbWVvdXQ/OiBudW1iZXI7IGpvYklkPzogc3RyaW5nIH0sXG5cdCk6IFByb21pc2U8c3RyaW5nPiB7XG5cdFx0aWYgKCF0aGlzLmNvbm5lY3RlZCkgdGhyb3cgbmV3IEVycm9yKFwiW2Jsb2tdW3Nxc10gbm90IGNvbm5lY3RlZC4gQ2FsbCBjb25uZWN0KCkgZmlyc3QuXCIpO1xuXHRcdGNvbnN0IG1lc3NhZ2VJZCA9IG9wdHM/LmpvYklkID8/IHV1aWQoKTtcblx0XHRjb25zdCBpc0ZpZm8gPSBxdWV1ZS5lbmRzV2l0aChcIi5maWZvXCIpO1xuXHRcdGNvbnN0IHBhcmFtczogUmVjb3JkPHN0cmluZywgdW5rbm93bj4gPSB7XG5cdFx0XHRRdWV1ZVVybDogcXVldWUsXG5cdFx0XHRNZXNzYWdlQm9keTogdHlwZW9mIGRhdGEgPT09IFwic3RyaW5nXCIgPyBkYXRhIDogSlNPTi5zdHJpbmdpZnkoZGF0YSksXG5cdFx0fTtcblx0XHRpZiAoaXNGaWZvKSB7XG5cdFx0XHRwYXJhbXMuTWVzc2FnZUdyb3VwSWQgPSBvcHRzPy5qb2JJZCA/PyBcImRlZmF1bHRcIjtcblx0XHRcdHBhcmFtcy5NZXNzYWdlRGVkdXBsaWNhdGlvbklkID0gbWVzc2FnZUlkO1xuXHRcdH1cblx0XHRpZiAodHlwZW9mIG9wdHM/LmRlbGF5ID09PSBcIm51bWJlclwiICYmIG9wdHMuZGVsYXkgPiAwKSB7XG5cdFx0XHRwYXJhbXMuRGVsYXlTZWNvbmRzID0gTWF0aC5taW4oOTAwLCBNYXRoLmNlaWwob3B0cy5kZWxheSAvIDEwMDApKTtcblx0XHR9XG5cdFx0Y29uc3QgcmVzdWx0ID0gYXdhaXQgdGhpcy5jbGllbnQuc2VuZChuZXcgdGhpcy5jb21tYW5kcy5TZW5kTWVzc2FnZUNvbW1hbmQocGFyYW1zKSk7XG5cdFx0cmV0dXJuIChyZXN1bHQuTWVzc2FnZUlkIGFzIHN0cmluZykgPz8gbWVzc2FnZUlkO1xuXHR9XG5cblx0YXN5bmMgc3RvcFByb2Nlc3NpbmcocXVldWU6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuXHRcdGNvbnN0IHJ1bm5lciA9IHRoaXMucnVubmVycy5nZXQocXVldWUpO1xuXHRcdGlmIChydW5uZXIpIHJ1bm5lci5zdG9wID0gdHJ1ZTtcblx0fVxuXG5cdGlzQ29ubmVjdGVkKCk6IGJvb2xlYW4ge1xuXHRcdHJldHVybiB0aGlzLmNvbm5lY3RlZDtcblx0fVxuXG5cdGFzeW5jIGhlYWx0aENoZWNrKCk6IFByb21pc2U8Ym9vbGVhbj4ge1xuXHRcdGlmICghdGhpcy5jb25uZWN0ZWQpIHJldHVybiBmYWxzZTtcblx0XHR0cnkge1xuXHRcdFx0Ly8gTGlzdFF1ZXVlcyBpcyBhIGNoZWFwIHBlcm1pc3Npb24gcHJvYmUuXG5cdFx0XHRhd2FpdCB0aGlzLmNsaWVudC5zZW5kKG5ldyB0aGlzLmNvbW1hbmRzLkxpc3RRdWV1ZXNDb21tYW5kKHsgTWF4UmVzdWx0czogMSB9KSk7XG5cdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHR9IGNhdGNoIHtcblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHR9XG5cdH1cblxuXHRhc3luYyBnZXRRdWV1ZVN0YXRzKHF1ZXVlOiBzdHJpbmcpOiBQcm9taXNlPFdvcmtlclF1ZXVlU3RhdHM+IHtcblx0XHRjb25zdCBjb3VudGVycyA9IHRoaXMuc3RhdHMuZ2V0KHF1ZXVlKSA/PyB7IGNvbXBsZXRlZDogMCwgZmFpbGVkOiAwLCBhY3RpdmU6IDAgfTtcblx0XHRsZXQgd2FpdGluZyA9IDA7XG5cdFx0bGV0IGRlbGF5ZWQgPSAwO1xuXHRcdHRyeSB7XG5cdFx0XHRjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLmNsaWVudC5zZW5kKFxuXHRcdFx0XHRuZXcgdGhpcy5jb21tYW5kcy5HZXRRdWV1ZUF0dHJpYnV0ZXNDb21tYW5kKHtcblx0XHRcdFx0XHRRdWV1ZVVybDogcXVldWUsXG5cdFx0XHRcdFx0QXR0cmlidXRlTmFtZXM6IFtcIkFwcHJveGltYXRlTnVtYmVyT2ZNZXNzYWdlc1wiLCBcIkFwcHJveGltYXRlTnVtYmVyT2ZNZXNzYWdlc0RlbGF5ZWRcIl0sXG5cdFx0XHRcdH0pLFxuXHRcdFx0KTtcblx0XHRcdHdhaXRpbmcgPSBOdW1iZXIucGFyc2VJbnQocmVzdWx0LkF0dHJpYnV0ZXM/LkFwcHJveGltYXRlTnVtYmVyT2ZNZXNzYWdlcyA/PyBcIjBcIiwgMTApO1xuXHRcdFx0ZGVsYXllZCA9IE51bWJlci5wYXJzZUludChyZXN1bHQuQXR0cmlidXRlcz8uQXBwcm94aW1hdGVOdW1iZXJPZk1lc3NhZ2VzRGVsYXllZCA/PyBcIjBcIiwgMTApO1xuXHRcdH0gY2F0Y2gge1xuXHRcdFx0LyogaWdub3JlICovXG5cdFx0fVxuXHRcdHJldHVybiB7XG5cdFx0XHR3YWl0aW5nLFxuXHRcdFx0YWN0aXZlOiBjb3VudGVycy5hY3RpdmUsXG5cdFx0XHRjb21wbGV0ZWQ6IGNvdW50ZXJzLmNvbXBsZXRlZCxcblx0XHRcdGZhaWxlZDogY291bnRlcnMuZmFpbGVkLFxuXHRcdFx0ZGVsYXllZCxcblx0XHR9O1xuXHR9XG59XG4iXX0=
@@ -0,0 +1,34 @@
1
+ /**
2
+ * v0.7 PR 5 — adapter factory.
3
+ *
4
+ * Resolves a `provider` string to a concrete `WorkerAdapter` instance.
5
+ * Used by the `WorkerTrigger` (to pick the right adapter per workflow
6
+ * based on `trigger.worker.provider`) and by the `@blokjs/worker-publish`
7
+ * helper node (to enqueue jobs from any workflow without bundling all
8
+ * broker clients).
9
+ *
10
+ * Provider resolution order:
11
+ * 1. Explicit `provider` field on the workflow (highest priority).
12
+ * 2. `BLOK_WORKER_ADAPTER` env var (per Q7 resolution in the plan).
13
+ * 3. `"in-memory"` fallback (zero-infra default for dev/tests).
14
+ *
15
+ * Each adapter beyond `in-memory` lazy-imports its broker SDK on first
16
+ * use (BullMQ does this today). Workflows that don't use a given
17
+ * provider don't pay the install or import cost.
18
+ */
19
+ import type { WorkerProvider } from "@blokjs/helper";
20
+ import type { WorkerAdapter } from "../WorkerTrigger";
21
+ /**
22
+ * Resolve the effective provider for a workflow. The trigger's
23
+ * `provider` field always wins; otherwise fall back to the
24
+ * `BLOK_WORKER_ADAPTER` env var; otherwise `"in-memory"`.
25
+ */
26
+ export declare function resolveProvider(provider?: WorkerProvider): WorkerProvider;
27
+ /**
28
+ * Construct an adapter for the named provider. Throws a clear error
29
+ * for unknown names — keeps the schema validation and runtime
30
+ * behaviour in sync (the Zod enum catches typos at workflow load).
31
+ */
32
+ export declare function createWorkerAdapter(provider: WorkerProvider): WorkerAdapter;
33
+ export declare function getOrCreateAdapter(provider: WorkerProvider): WorkerAdapter;
34
+ export declare function _resetAdapterPoolForTests(): void;
@@ -0,0 +1,103 @@
1
+ /**
2
+ * v0.7 PR 5 — adapter factory.
3
+ *
4
+ * Resolves a `provider` string to a concrete `WorkerAdapter` instance.
5
+ * Used by the `WorkerTrigger` (to pick the right adapter per workflow
6
+ * based on `trigger.worker.provider`) and by the `@blokjs/worker-publish`
7
+ * helper node (to enqueue jobs from any workflow without bundling all
8
+ * broker clients).
9
+ *
10
+ * Provider resolution order:
11
+ * 1. Explicit `provider` field on the workflow (highest priority).
12
+ * 2. `BLOK_WORKER_ADAPTER` env var (per Q7 resolution in the plan).
13
+ * 3. `"in-memory"` fallback (zero-infra default for dev/tests).
14
+ *
15
+ * Each adapter beyond `in-memory` lazy-imports its broker SDK on first
16
+ * use (BullMQ does this today). Workflows that don't use a given
17
+ * provider don't pay the install or import cost.
18
+ */
19
+ import { BullMQAdapter } from "./BullMQAdapter";
20
+ import { InMemoryAdapter } from "./InMemoryAdapter";
21
+ import { KafkaAdapter } from "./KafkaAdapter";
22
+ import { NATSWorkerAdapter } from "./NATSAdapter";
23
+ import { PgBossAdapter } from "./PgBossAdapter";
24
+ import { RabbitMQAdapter } from "./RabbitMQAdapter";
25
+ import { RedisStreamsAdapter } from "./RedisStreamsAdapter";
26
+ import { SQSAdapter } from "./SQSAdapter";
27
+ /**
28
+ * Resolve the effective provider for a workflow. The trigger's
29
+ * `provider` field always wins; otherwise fall back to the
30
+ * `BLOK_WORKER_ADAPTER` env var; otherwise `"in-memory"`.
31
+ */
32
+ export function resolveProvider(provider) {
33
+ if (provider)
34
+ return provider;
35
+ const envValue = process.env.BLOK_WORKER_ADAPTER;
36
+ if (envValue && isWorkerProvider(envValue))
37
+ return envValue;
38
+ return "in-memory";
39
+ }
40
+ function isWorkerProvider(value) {
41
+ return (value === "in-memory" ||
42
+ value === "nats" ||
43
+ value === "bullmq" ||
44
+ value === "kafka" ||
45
+ value === "rabbitmq" ||
46
+ value === "sqs" ||
47
+ value === "redis" ||
48
+ value === "pg-boss");
49
+ }
50
+ /**
51
+ * Construct an adapter for the named provider. Throws a clear error
52
+ * for unknown names — keeps the schema validation and runtime
53
+ * behaviour in sync (the Zod enum catches typos at workflow load).
54
+ */
55
+ export function createWorkerAdapter(provider) {
56
+ switch (provider) {
57
+ case "in-memory":
58
+ return new InMemoryAdapter();
59
+ case "nats":
60
+ return new NATSWorkerAdapter();
61
+ case "bullmq":
62
+ return new BullMQAdapter();
63
+ case "kafka":
64
+ return new KafkaAdapter();
65
+ case "rabbitmq":
66
+ return new RabbitMQAdapter();
67
+ case "sqs":
68
+ return new SQSAdapter();
69
+ case "redis":
70
+ return new RedisStreamsAdapter();
71
+ case "pg-boss":
72
+ return new PgBossAdapter();
73
+ default: {
74
+ const exhaustive = provider;
75
+ throw new Error(`[blok][worker] unknown provider "${exhaustive}". Check WorkerProviderSchema.`);
76
+ }
77
+ }
78
+ }
79
+ /**
80
+ * Process-singleton adapter pool — one instance per provider. The
81
+ * trigger calls `getOrCreateAdapter("kafka")` once per workflow, and
82
+ * subsequent workflows on the same provider share the broker
83
+ * connection. Adapters are connected lazily — `getOrCreateAdapter`
84
+ * never connects on its own; the caller calls `adapter.connect()`.
85
+ *
86
+ * Reset via `_resetAdapterPoolForTests()` between vitest suites.
87
+ */
88
+ const pool = new Map();
89
+ export function getOrCreateAdapter(provider) {
90
+ let adapter = pool.get(provider);
91
+ if (!adapter) {
92
+ adapter = createWorkerAdapter(provider);
93
+ pool.set(provider, adapter);
94
+ }
95
+ return adapter;
96
+ }
97
+ export function _resetAdapterPoolForTests() {
98
+ for (const adapter of pool.values()) {
99
+ void adapter.disconnect?.().catch(() => { });
100
+ }
101
+ pool.clear();
102
+ }
103
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmFjdG9yeS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9hZGFwdGVycy9mYWN0b3J5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7OztHQWlCRztBQUlILE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUNoRCxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFDcEQsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQzlDLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUNsRCxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDaEQsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBQ3BELE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQzVELE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFFMUM7Ozs7R0FJRztBQUNILE1BQU0sVUFBVSxlQUFlLENBQUMsUUFBeUI7SUFDeEQsSUFBSSxRQUFRO1FBQUUsT0FBTyxRQUFRLENBQUM7SUFDOUIsTUFBTSxRQUFRLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FBQyxtQkFBbUIsQ0FBQztJQUNqRCxJQUFJLFFBQVEsSUFBSSxnQkFBZ0IsQ0FBQyxRQUFRLENBQUM7UUFBRSxPQUFPLFFBQVEsQ0FBQztJQUM1RCxPQUFPLFdBQVcsQ0FBQztBQUNwQixDQUFDO0FBRUQsU0FBUyxnQkFBZ0IsQ0FBQyxLQUFhO0lBQ3RDLE9BQU8sQ0FDTixLQUFLLEtBQUssV0FBVztRQUNyQixLQUFLLEtBQUssTUFBTTtRQUNoQixLQUFLLEtBQUssUUFBUTtRQUNsQixLQUFLLEtBQUssT0FBTztRQUNqQixLQUFLLEtBQUssVUFBVTtRQUNwQixLQUFLLEtBQUssS0FBSztRQUNmLEtBQUssS0FBSyxPQUFPO1FBQ2pCLEtBQUssS0FBSyxTQUFTLENBQ25CLENBQUM7QUFDSCxDQUFDO0FBRUQ7Ozs7R0FJRztBQUNILE1BQU0sVUFBVSxtQkFBbUIsQ0FBQyxRQUF3QjtJQUMzRCxRQUFRLFFBQVEsRUFBRSxDQUFDO1FBQ2xCLEtBQUssV0FBVztZQUNmLE9BQU8sSUFBSSxlQUFlLEVBQUUsQ0FBQztRQUM5QixLQUFLLE1BQU07WUFDVixPQUFPLElBQUksaUJBQWlCLEVBQUUsQ0FBQztRQUNoQyxLQUFLLFFBQVE7WUFDWixPQUFPLElBQUksYUFBYSxFQUFFLENBQUM7UUFDNUIsS0FBSyxPQUFPO1lBQ1gsT0FBTyxJQUFJLFlBQVksRUFBRSxDQUFDO1FBQzNCLEtBQUssVUFBVTtZQUNkLE9BQU8sSUFBSSxlQUFlLEVBQUUsQ0FBQztRQUM5QixLQUFLLEtBQUs7WUFDVCxPQUFPLElBQUksVUFBVSxFQUFFLENBQUM7UUFDekIsS0FBSyxPQUFPO1lBQ1gsT0FBTyxJQUFJLG1CQUFtQixFQUFFLENBQUM7UUFDbEMsS0FBSyxTQUFTO1lBQ2IsT0FBTyxJQUFJLGFBQWEsRUFBRSxDQUFDO1FBQzVCLE9BQU8sQ0FBQyxDQUFDLENBQUM7WUFDVCxNQUFNLFVBQVUsR0FBVSxRQUFRLENBQUM7WUFDbkMsTUFBTSxJQUFJLEtBQUssQ0FBQyxvQ0FBb0MsVUFBb0IsZ0NBQWdDLENBQUMsQ0FBQztRQUMzRyxDQUFDO0lBQ0YsQ0FBQztBQUNGLENBQUM7QUFFRDs7Ozs7Ozs7R0FRRztBQUNILE1BQU0sSUFBSSxHQUF1QyxJQUFJLEdBQUcsRUFBRSxDQUFDO0FBRTNELE1BQU0sVUFBVSxrQkFBa0IsQ0FBQyxRQUF3QjtJQUMxRCxJQUFJLE9BQU8sR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBQ2pDLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUNkLE9BQU8sR0FBRyxtQkFBbUIsQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUN4QyxJQUFJLENBQUMsR0FBRyxDQUFDLFFBQVEsRUFBRSxPQUFPLENBQUMsQ0FBQztJQUM3QixDQUFDO0lBQ0QsT0FBTyxPQUFPLENBQUM7QUFDaEIsQ0FBQztBQUVELE1BQU0sVUFBVSx5QkFBeUI7SUFDeEMsS0FBSyxNQUFNLE9BQU8sSUFBSSxJQUFJLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQztRQUNyQyxLQUFLLE9BQU8sQ0FBQyxVQUFVLEVBQUUsRUFBRSxDQUFDLEtBQUssQ0FBQyxHQUFHLEVBQUUsR0FBRSxDQUFDLENBQUMsQ0FBQztJQUM3QyxDQUFDO0lBQ0QsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO0FBQ2QsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogdjAuNyBQUiA1IOKAlCBhZGFwdGVyIGZhY3RvcnkuXG4gKlxuICogUmVzb2x2ZXMgYSBgcHJvdmlkZXJgIHN0cmluZyB0byBhIGNvbmNyZXRlIGBXb3JrZXJBZGFwdGVyYCBpbnN0YW5jZS5cbiAqIFVzZWQgYnkgdGhlIGBXb3JrZXJUcmlnZ2VyYCAodG8gcGljayB0aGUgcmlnaHQgYWRhcHRlciBwZXIgd29ya2Zsb3dcbiAqIGJhc2VkIG9uIGB0cmlnZ2VyLndvcmtlci5wcm92aWRlcmApIGFuZCBieSB0aGUgYEBibG9ranMvd29ya2VyLXB1Ymxpc2hgXG4gKiBoZWxwZXIgbm9kZSAodG8gZW5xdWV1ZSBqb2JzIGZyb20gYW55IHdvcmtmbG93IHdpdGhvdXQgYnVuZGxpbmcgYWxsXG4gKiBicm9rZXIgY2xpZW50cykuXG4gKlxuICogUHJvdmlkZXIgcmVzb2x1dGlvbiBvcmRlcjpcbiAqICAgMS4gRXhwbGljaXQgYHByb3ZpZGVyYCBmaWVsZCBvbiB0aGUgd29ya2Zsb3cgKGhpZ2hlc3QgcHJpb3JpdHkpLlxuICogICAyLiBgQkxPS19XT1JLRVJfQURBUFRFUmAgZW52IHZhciAocGVyIFE3IHJlc29sdXRpb24gaW4gdGhlIHBsYW4pLlxuICogICAzLiBgXCJpbi1tZW1vcnlcImAgZmFsbGJhY2sgKHplcm8taW5mcmEgZGVmYXVsdCBmb3IgZGV2L3Rlc3RzKS5cbiAqXG4gKiBFYWNoIGFkYXB0ZXIgYmV5b25kIGBpbi1tZW1vcnlgIGxhenktaW1wb3J0cyBpdHMgYnJva2VyIFNESyBvbiBmaXJzdFxuICogdXNlIChCdWxsTVEgZG9lcyB0aGlzIHRvZGF5KS4gV29ya2Zsb3dzIHRoYXQgZG9uJ3QgdXNlIGEgZ2l2ZW5cbiAqIHByb3ZpZGVyIGRvbid0IHBheSB0aGUgaW5zdGFsbCBvciBpbXBvcnQgY29zdC5cbiAqL1xuXG5pbXBvcnQgdHlwZSB7IFdvcmtlclByb3ZpZGVyIH0gZnJvbSBcIkBibG9ranMvaGVscGVyXCI7XG5pbXBvcnQgdHlwZSB7IFdvcmtlckFkYXB0ZXIgfSBmcm9tIFwiLi4vV29ya2VyVHJpZ2dlclwiO1xuaW1wb3J0IHsgQnVsbE1RQWRhcHRlciB9IGZyb20gXCIuL0J1bGxNUUFkYXB0ZXJcIjtcbmltcG9ydCB7IEluTWVtb3J5QWRhcHRlciB9IGZyb20gXCIuL0luTWVtb3J5QWRhcHRlclwiO1xuaW1wb3J0IHsgS2Fma2FBZGFwdGVyIH0gZnJvbSBcIi4vS2Fma2FBZGFwdGVyXCI7XG5pbXBvcnQgeyBOQVRTV29ya2VyQWRhcHRlciB9IGZyb20gXCIuL05BVFNBZGFwdGVyXCI7XG5pbXBvcnQgeyBQZ0Jvc3NBZGFwdGVyIH0gZnJvbSBcIi4vUGdCb3NzQWRhcHRlclwiO1xuaW1wb3J0IHsgUmFiYml0TVFBZGFwdGVyIH0gZnJvbSBcIi4vUmFiYml0TVFBZGFwdGVyXCI7XG5pbXBvcnQgeyBSZWRpc1N0cmVhbXNBZGFwdGVyIH0gZnJvbSBcIi4vUmVkaXNTdHJlYW1zQWRhcHRlclwiO1xuaW1wb3J0IHsgU1FTQWRhcHRlciB9IGZyb20gXCIuL1NRU0FkYXB0ZXJcIjtcblxuLyoqXG4gKiBSZXNvbHZlIHRoZSBlZmZlY3RpdmUgcHJvdmlkZXIgZm9yIGEgd29ya2Zsb3cuIFRoZSB0cmlnZ2VyJ3NcbiAqIGBwcm92aWRlcmAgZmllbGQgYWx3YXlzIHdpbnM7IG90aGVyd2lzZSBmYWxsIGJhY2sgdG8gdGhlXG4gKiBgQkxPS19XT1JLRVJfQURBUFRFUmAgZW52IHZhcjsgb3RoZXJ3aXNlIGBcImluLW1lbW9yeVwiYC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlc29sdmVQcm92aWRlcihwcm92aWRlcj86IFdvcmtlclByb3ZpZGVyKTogV29ya2VyUHJvdmlkZXIge1xuXHRpZiAocHJvdmlkZXIpIHJldHVybiBwcm92aWRlcjtcblx0Y29uc3QgZW52VmFsdWUgPSBwcm9jZXNzLmVudi5CTE9LX1dPUktFUl9BREFQVEVSO1xuXHRpZiAoZW52VmFsdWUgJiYgaXNXb3JrZXJQcm92aWRlcihlbnZWYWx1ZSkpIHJldHVybiBlbnZWYWx1ZTtcblx0cmV0dXJuIFwiaW4tbWVtb3J5XCI7XG59XG5cbmZ1bmN0aW9uIGlzV29ya2VyUHJvdmlkZXIodmFsdWU6IHN0cmluZyk6IHZhbHVlIGlzIFdvcmtlclByb3ZpZGVyIHtcblx0cmV0dXJuIChcblx0XHR2YWx1ZSA9PT0gXCJpbi1tZW1vcnlcIiB8fFxuXHRcdHZhbHVlID09PSBcIm5hdHNcIiB8fFxuXHRcdHZhbHVlID09PSBcImJ1bGxtcVwiIHx8XG5cdFx0dmFsdWUgPT09IFwia2Fma2FcIiB8fFxuXHRcdHZhbHVlID09PSBcInJhYmJpdG1xXCIgfHxcblx0XHR2YWx1ZSA9PT0gXCJzcXNcIiB8fFxuXHRcdHZhbHVlID09PSBcInJlZGlzXCIgfHxcblx0XHR2YWx1ZSA9PT0gXCJwZy1ib3NzXCJcblx0KTtcbn1cblxuLyoqXG4gKiBDb25zdHJ1Y3QgYW4gYWRhcHRlciBmb3IgdGhlIG5hbWVkIHByb3ZpZGVyLiBUaHJvd3MgYSBjbGVhciBlcnJvclxuICogZm9yIHVua25vd24gbmFtZXMg4oCUIGtlZXBzIHRoZSBzY2hlbWEgdmFsaWRhdGlvbiBhbmQgcnVudGltZVxuICogYmVoYXZpb3VyIGluIHN5bmMgKHRoZSBab2QgZW51bSBjYXRjaGVzIHR5cG9zIGF0IHdvcmtmbG93IGxvYWQpLlxuICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlV29ya2VyQWRhcHRlcihwcm92aWRlcjogV29ya2VyUHJvdmlkZXIpOiBXb3JrZXJBZGFwdGVyIHtcblx0c3dpdGNoIChwcm92aWRlcikge1xuXHRcdGNhc2UgXCJpbi1tZW1vcnlcIjpcblx0XHRcdHJldHVybiBuZXcgSW5NZW1vcnlBZGFwdGVyKCk7XG5cdFx0Y2FzZSBcIm5hdHNcIjpcblx0XHRcdHJldHVybiBuZXcgTkFUU1dvcmtlckFkYXB0ZXIoKTtcblx0XHRjYXNlIFwiYnVsbG1xXCI6XG5cdFx0XHRyZXR1cm4gbmV3IEJ1bGxNUUFkYXB0ZXIoKTtcblx0XHRjYXNlIFwia2Fma2FcIjpcblx0XHRcdHJldHVybiBuZXcgS2Fma2FBZGFwdGVyKCk7XG5cdFx0Y2FzZSBcInJhYmJpdG1xXCI6XG5cdFx0XHRyZXR1cm4gbmV3IFJhYmJpdE1RQWRhcHRlcigpO1xuXHRcdGNhc2UgXCJzcXNcIjpcblx0XHRcdHJldHVybiBuZXcgU1FTQWRhcHRlcigpO1xuXHRcdGNhc2UgXCJyZWRpc1wiOlxuXHRcdFx0cmV0dXJuIG5ldyBSZWRpc1N0cmVhbXNBZGFwdGVyKCk7XG5cdFx0Y2FzZSBcInBnLWJvc3NcIjpcblx0XHRcdHJldHVybiBuZXcgUGdCb3NzQWRhcHRlcigpO1xuXHRcdGRlZmF1bHQ6IHtcblx0XHRcdGNvbnN0IGV4aGF1c3RpdmU6IG5ldmVyID0gcHJvdmlkZXI7XG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoYFtibG9rXVt3b3JrZXJdIHVua25vd24gcHJvdmlkZXIgXCIke2V4aGF1c3RpdmUgYXMgc3RyaW5nfVwiLiBDaGVjayBXb3JrZXJQcm92aWRlclNjaGVtYS5gKTtcblx0XHR9XG5cdH1cbn1cblxuLyoqXG4gKiBQcm9jZXNzLXNpbmdsZXRvbiBhZGFwdGVyIHBvb2wg4oCUIG9uZSBpbnN0YW5jZSBwZXIgcHJvdmlkZXIuIFRoZVxuICogdHJpZ2dlciBjYWxscyBgZ2V0T3JDcmVhdGVBZGFwdGVyKFwia2Fma2FcIilgIG9uY2UgcGVyIHdvcmtmbG93LCBhbmRcbiAqIHN1YnNlcXVlbnQgd29ya2Zsb3dzIG9uIHRoZSBzYW1lIHByb3ZpZGVyIHNoYXJlIHRoZSBicm9rZXJcbiAqIGNvbm5lY3Rpb24uIEFkYXB0ZXJzIGFyZSBjb25uZWN0ZWQgbGF6aWx5IOKAlCBgZ2V0T3JDcmVhdGVBZGFwdGVyYFxuICogbmV2ZXIgY29ubmVjdHMgb24gaXRzIG93bjsgdGhlIGNhbGxlciBjYWxscyBgYWRhcHRlci5jb25uZWN0KClgLlxuICpcbiAqIFJlc2V0IHZpYSBgX3Jlc2V0QWRhcHRlclBvb2xGb3JUZXN0cygpYCBiZXR3ZWVuIHZpdGVzdCBzdWl0ZXMuXG4gKi9cbmNvbnN0IHBvb2w6IE1hcDxXb3JrZXJQcm92aWRlciwgV29ya2VyQWRhcHRlcj4gPSBuZXcgTWFwKCk7XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRPckNyZWF0ZUFkYXB0ZXIocHJvdmlkZXI6IFdvcmtlclByb3ZpZGVyKTogV29ya2VyQWRhcHRlciB7XG5cdGxldCBhZGFwdGVyID0gcG9vbC5nZXQocHJvdmlkZXIpO1xuXHRpZiAoIWFkYXB0ZXIpIHtcblx0XHRhZGFwdGVyID0gY3JlYXRlV29ya2VyQWRhcHRlcihwcm92aWRlcik7XG5cdFx0cG9vbC5zZXQocHJvdmlkZXIsIGFkYXB0ZXIpO1xuXHR9XG5cdHJldHVybiBhZGFwdGVyO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gX3Jlc2V0QWRhcHRlclBvb2xGb3JUZXN0cygpOiB2b2lkIHtcblx0Zm9yIChjb25zdCBhZGFwdGVyIG9mIHBvb2wudmFsdWVzKCkpIHtcblx0XHR2b2lkIGFkYXB0ZXIuZGlzY29ubmVjdD8uKCkuY2F0Y2goKCkgPT4ge30pO1xuXHR9XG5cdHBvb2wuY2xlYXIoKTtcbn1cbiJdfQ==
package/dist/index.d.ts CHANGED
@@ -10,9 +10,20 @@
10
10
  * - Delayed job scheduling
11
11
  * - Queue statistics and monitoring
12
12
  *
13
- * Adapters:
14
- * - BullMQ (Redis-backed, production)
15
- * - InMemory (development/testing)
13
+ * Adapters (v0.7+):
14
+ * - BullMQ Redis-backed, ops-style queues (`bullmq` peer dep)
15
+ * - InMemory development / tests (no peer deps)
16
+ * - NATS — JetStream durable streams (`nats` peer dep)
17
+ * - Kafka — high-throughput streaming (`kafkajs` peer dep)
18
+ * - RabbitMQ — reliable enterprise queues (`amqplib` peer dep)
19
+ * - SQS — AWS cloud queues (`@aws-sdk/client-sqs` peer dep)
20
+ * - Redis Streams — when Redis is already in stack (`ioredis` peer dep)
21
+ * - pg-boss — no extra infra (`pg-boss` peer dep)
22
+ *
23
+ * v0.7+ — pick the adapter per workflow via `trigger.worker.provider`.
24
+ * `BLOK_WORKER_ADAPTER` env var sets the default. Subclasses can still
25
+ * set `protected adapter` directly for back-compat with the pre-v0.7
26
+ * single-adapter pattern.
16
27
  *
17
28
  * @example BullMQ
18
29
  * ```typescript
@@ -53,5 +64,11 @@
53
64
  export { WorkerTrigger, type WorkerAdapter, type WorkerJob, type WorkerQueueStats, } from "./WorkerTrigger";
54
65
  export { BullMQAdapter, type BullMQConfig } from "./adapters/BullMQAdapter";
55
66
  export { InMemoryAdapter } from "./adapters/InMemoryAdapter";
67
+ export { KafkaAdapter, type KafkaConfig } from "./adapters/KafkaAdapter";
56
68
  export { NATSWorkerAdapter, type NATSWorkerConfig } from "./adapters/NATSAdapter";
57
- export type { WorkerTriggerOpts } from "@blokjs/helper";
69
+ export { PgBossAdapter, type PgBossConfig } from "./adapters/PgBossAdapter";
70
+ export { RabbitMQAdapter, type RabbitMQConfig } from "./adapters/RabbitMQAdapter";
71
+ export { RedisStreamsAdapter, type RedisStreamsConfig } from "./adapters/RedisStreamsAdapter";
72
+ export { SQSAdapter, type SQSConfig } from "./adapters/SQSAdapter";
73
+ export { _resetAdapterPoolForTests, createWorkerAdapter, getOrCreateAdapter, resolveProvider, } from "./adapters/factory";
74
+ export type { WorkerProvider, WorkerTriggerOpts } from "@blokjs/helper";
package/dist/index.js CHANGED
@@ -10,9 +10,20 @@
10
10
  * - Delayed job scheduling
11
11
  * - Queue statistics and monitoring
12
12
  *
13
- * Adapters:
14
- * - BullMQ (Redis-backed, production)
15
- * - InMemory (development/testing)
13
+ * Adapters (v0.7+):
14
+ * - BullMQ Redis-backed, ops-style queues (`bullmq` peer dep)
15
+ * - InMemory development / tests (no peer deps)
16
+ * - NATS — JetStream durable streams (`nats` peer dep)
17
+ * - Kafka — high-throughput streaming (`kafkajs` peer dep)
18
+ * - RabbitMQ — reliable enterprise queues (`amqplib` peer dep)
19
+ * - SQS — AWS cloud queues (`@aws-sdk/client-sqs` peer dep)
20
+ * - Redis Streams — when Redis is already in stack (`ioredis` peer dep)
21
+ * - pg-boss — no extra infra (`pg-boss` peer dep)
22
+ *
23
+ * v0.7+ — pick the adapter per workflow via `trigger.worker.provider`.
24
+ * `BLOK_WORKER_ADAPTER` env var sets the default. Subclasses can still
25
+ * set `protected adapter` directly for back-compat with the pre-v0.7
26
+ * single-adapter pattern.
16
27
  *
17
28
  * @example BullMQ
18
29
  * ```typescript
@@ -55,5 +66,14 @@ export { WorkerTrigger, } from "./WorkerTrigger";
55
66
  // Adapters
56
67
  export { BullMQAdapter } from "./adapters/BullMQAdapter";
57
68
  export { InMemoryAdapter } from "./adapters/InMemoryAdapter";
69
+ export { KafkaAdapter } from "./adapters/KafkaAdapter";
58
70
  export { NATSWorkerAdapter } from "./adapters/NATSAdapter";
59
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQW1ERztBQUVILGVBQWU7QUFDZixPQUFPLEVBQ04sYUFBYSxHQUliLE1BQU0saUJBQWlCLENBQUM7QUFFekIsV0FBVztBQUNYLE9BQU8sRUFBRSxhQUFhLEVBQXFCLE1BQU0sMEJBQTBCLENBQUM7QUFDNUUsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQzdELE9BQU8sRUFBRSxpQkFBaUIsRUFBeUIsTUFBTSx3QkFBd0IsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQGJsb2tqcy90cmlnZ2VyLXdvcmtlclxuICpcbiAqIFdvcmtlci1iYXNlZCB0cmlnZ2VyIGZvciBCbG9rIHdvcmtmbG93cy5cbiAqIFN1cHBvcnRzIGJhY2tncm91bmQgam9iIHByb2Nlc3Npbmcgd2l0aDpcbiAqIC0gQ29uZmlndXJhYmxlIGNvbmN1cnJlbmN5IHBlciBxdWV1ZVxuICogLSBBdXRvbWF0aWMgcmV0cmllcyB3aXRoIGV4cG9uZW50aWFsIGJhY2tvZmZcbiAqIC0gSm9iIHRpbWVvdXRzXG4gKiAtIFByaW9yaXR5LWJhc2VkIGpvYiBvcmRlcmluZ1xuICogLSBEZWxheWVkIGpvYiBzY2hlZHVsaW5nXG4gKiAtIFF1ZXVlIHN0YXRpc3RpY3MgYW5kIG1vbml0b3JpbmdcbiAqXG4gKiBBZGFwdGVyczpcbiAqIC0gQnVsbE1RIChSZWRpcy1iYWNrZWQsIHByb2R1Y3Rpb24pXG4gKiAtIEluTWVtb3J5IChkZXZlbG9wbWVudC90ZXN0aW5nKVxuICpcbiAqIEBleGFtcGxlIEJ1bGxNUVxuICogYGBgdHlwZXNjcmlwdFxuICogaW1wb3J0IHsgV29ya2VyVHJpZ2dlciwgQnVsbE1RQWRhcHRlciB9IGZyb20gXCJAYmxva2pzL3RyaWdnZXItd29ya2VyXCI7XG4gKlxuICogY2xhc3MgTXlXb3JrZXJUcmlnZ2VyIGV4dGVuZHMgV29ya2VyVHJpZ2dlciB7XG4gKiAgIHByb3RlY3RlZCBhZGFwdGVyID0gbmV3IEJ1bGxNUUFkYXB0ZXIoe1xuICogICAgIGhvc3Q6IFwibG9jYWxob3N0XCIsXG4gKiAgICAgcG9ydDogNjM3OSxcbiAqICAgfSk7XG4gKlxuICogICBwcm90ZWN0ZWQgbm9kZXMgPSBteU5vZGVzO1xuICogICBwcm90ZWN0ZWQgd29ya2Zsb3dzID0gbXlXb3JrZmxvd3M7XG4gKiB9XG4gKlxuICogY29uc3QgdHJpZ2dlciA9IG5ldyBNeVdvcmtlclRyaWdnZXIoKTtcbiAqIGF3YWl0IHRyaWdnZXIubGlzdGVuKCk7XG4gKlxuICogLy8gRGlzcGF0Y2ggYSBqb2JcbiAqIGF3YWl0IHRyaWdnZXIuZGlzcGF0Y2goXCJiYWNrZ3JvdW5kLWpvYnNcIiwgeyB1c2VySWQ6IFwiMTIzXCIgfSwge1xuICogICBwcmlvcml0eTogMTAsXG4gKiAgIHJldHJpZXM6IDMsXG4gKiAgIGRlbGF5OiA1MDAwLCAvLyBkZWxheSA1IHNlY29uZHNcbiAqIH0pO1xuICogYGBgXG4gKlxuICogQGV4YW1wbGUgSW5NZW1vcnkgKGRldmVsb3BtZW50KVxuICogYGBgdHlwZXNjcmlwdFxuICogaW1wb3J0IHsgV29ya2VyVHJpZ2dlciwgSW5NZW1vcnlBZGFwdGVyIH0gZnJvbSBcIkBibG9ranMvdHJpZ2dlci13b3JrZXJcIjtcbiAqXG4gKiBjbGFzcyBEZXZXb3JrZXJUcmlnZ2VyIGV4dGVuZHMgV29ya2VyVHJpZ2dlciB7XG4gKiAgIHByb3RlY3RlZCBhZGFwdGVyID0gbmV3IEluTWVtb3J5QWRhcHRlcigpO1xuICogICBwcm90ZWN0ZWQgbm9kZXMgPSBteU5vZGVzO1xuICogICBwcm90ZWN0ZWQgd29ya2Zsb3dzID0gbXlXb3JrZmxvd3M7XG4gKiB9XG4gKiBgYGBcbiAqL1xuXG4vLyBDb3JlIGV4cG9ydHNcbmV4cG9ydCB7XG5cdFdvcmtlclRyaWdnZXIsXG5cdHR5cGUgV29ya2VyQWRhcHRlcixcblx0dHlwZSBXb3JrZXJKb2IsXG5cdHR5cGUgV29ya2VyUXVldWVTdGF0cyxcbn0gZnJvbSBcIi4vV29ya2VyVHJpZ2dlclwiO1xuXG4vLyBBZGFwdGVyc1xuZXhwb3J0IHsgQnVsbE1RQWRhcHRlciwgdHlwZSBCdWxsTVFDb25maWcgfSBmcm9tIFwiLi9hZGFwdGVycy9CdWxsTVFBZGFwdGVyXCI7XG5leHBvcnQgeyBJbk1lbW9yeUFkYXB0ZXIgfSBmcm9tIFwiLi9hZGFwdGVycy9Jbk1lbW9yeUFkYXB0ZXJcIjtcbmV4cG9ydCB7IE5BVFNXb3JrZXJBZGFwdGVyLCB0eXBlIE5BVFNXb3JrZXJDb25maWcgfSBmcm9tIFwiLi9hZGFwdGVycy9OQVRTQWRhcHRlclwiO1xuXG4vLyBSZS1leHBvcnQgdHlwZXMgZnJvbSBoZWxwZXIgZm9yIGNvbnZlbmllbmNlXG5leHBvcnQgdHlwZSB7IFdvcmtlclRyaWdnZXJPcHRzIH0gZnJvbSBcIkBibG9ranMvaGVscGVyXCI7XG4iXX0=
71
+ export { PgBossAdapter } from "./adapters/PgBossAdapter";
72
+ export { RabbitMQAdapter } from "./adapters/RabbitMQAdapter";
73
+ export { RedisStreamsAdapter } from "./adapters/RedisStreamsAdapter";
74
+ export { SQSAdapter } from "./adapters/SQSAdapter";
75
+ // v0.7 PR 5 — factory + pool. Used by WorkerTrigger and exposed for
76
+ // helper nodes (`@blokjs/worker-publish`) that need to enqueue jobs
77
+ // from any workflow without bundling all broker SDKs.
78
+ export { _resetAdapterPoolForTests, createWorkerAdapter, getOrCreateAdapter, resolveProvider, } from "./adapters/factory";
79
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBOERHO0FBRUgsZUFBZTtBQUNmLE9BQU8sRUFDTixhQUFhLEdBSWIsTUFBTSxpQkFBaUIsQ0FBQztBQUV6QixXQUFXO0FBQ1gsT0FBTyxFQUFFLGFBQWEsRUFBcUIsTUFBTSwwQkFBMEIsQ0FBQztBQUM1RSxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFDN0QsT0FBTyxFQUFFLFlBQVksRUFBb0IsTUFBTSx5QkFBeUIsQ0FBQztBQUN6RSxPQUFPLEVBQUUsaUJBQWlCLEVBQXlCLE1BQU0sd0JBQXdCLENBQUM7QUFDbEYsT0FBTyxFQUFFLGFBQWEsRUFBcUIsTUFBTSwwQkFBMEIsQ0FBQztBQUM1RSxPQUFPLEVBQUUsZUFBZSxFQUF1QixNQUFNLDRCQUE0QixDQUFDO0FBQ2xGLE9BQU8sRUFBRSxtQkFBbUIsRUFBMkIsTUFBTSxnQ0FBZ0MsQ0FBQztBQUM5RixPQUFPLEVBQUUsVUFBVSxFQUFrQixNQUFNLHVCQUF1QixDQUFDO0FBRW5FLG9FQUFvRTtBQUNwRSxvRUFBb0U7QUFDcEUsc0RBQXNEO0FBQ3RELE9BQU8sRUFDTix5QkFBeUIsRUFDekIsbUJBQW1CLEVBQ25CLGtCQUFrQixFQUNsQixlQUFlLEdBQ2YsTUFBTSxvQkFBb0IsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQGJsb2tqcy90cmlnZ2VyLXdvcmtlclxuICpcbiAqIFdvcmtlci1iYXNlZCB0cmlnZ2VyIGZvciBCbG9rIHdvcmtmbG93cy5cbiAqIFN1cHBvcnRzIGJhY2tncm91bmQgam9iIHByb2Nlc3Npbmcgd2l0aDpcbiAqIC0gQ29uZmlndXJhYmxlIGNvbmN1cnJlbmN5IHBlciBxdWV1ZVxuICogLSBBdXRvbWF0aWMgcmV0cmllcyB3aXRoIGV4cG9uZW50aWFsIGJhY2tvZmZcbiAqIC0gSm9iIHRpbWVvdXRzXG4gKiAtIFByaW9yaXR5LWJhc2VkIGpvYiBvcmRlcmluZ1xuICogLSBEZWxheWVkIGpvYiBzY2hlZHVsaW5nXG4gKiAtIFF1ZXVlIHN0YXRpc3RpY3MgYW5kIG1vbml0b3JpbmdcbiAqXG4gKiBBZGFwdGVycyAodjAuNyspOlxuICogLSBCdWxsTVEgICAgICAgIOKAlCBSZWRpcy1iYWNrZWQsIG9wcy1zdHlsZSBxdWV1ZXMgKGBidWxsbXFgIHBlZXIgZGVwKVxuICogLSBJbk1lbW9yeSAgICAgIOKAlCBkZXZlbG9wbWVudCAvIHRlc3RzIChubyBwZWVyIGRlcHMpXG4gKiAtIE5BVFMgICAgICAgICAg4oCUIEpldFN0cmVhbSBkdXJhYmxlIHN0cmVhbXMgKGBuYXRzYCBwZWVyIGRlcClcbiAqIC0gS2Fma2EgICAgICAgICDigJQgaGlnaC10aHJvdWdocHV0IHN0cmVhbWluZyAoYGthZmthanNgIHBlZXIgZGVwKVxuICogLSBSYWJiaXRNUSAgICAgIOKAlCByZWxpYWJsZSBlbnRlcnByaXNlIHF1ZXVlcyAoYGFtcXBsaWJgIHBlZXIgZGVwKVxuICogLSBTUVMgICAgICAgICAgIOKAlCBBV1MgY2xvdWQgcXVldWVzIChgQGF3cy1zZGsvY2xpZW50LXNxc2AgcGVlciBkZXApXG4gKiAtIFJlZGlzIFN0cmVhbXMg4oCUIHdoZW4gUmVkaXMgaXMgYWxyZWFkeSBpbiBzdGFjayAoYGlvcmVkaXNgIHBlZXIgZGVwKVxuICogLSBwZy1ib3NzICAgICAgIOKAlCBubyBleHRyYSBpbmZyYSAoYHBnLWJvc3NgIHBlZXIgZGVwKVxuICpcbiAqIHYwLjcrIOKAlCBwaWNrIHRoZSBhZGFwdGVyIHBlciB3b3JrZmxvdyB2aWEgYHRyaWdnZXIud29ya2VyLnByb3ZpZGVyYC5cbiAqIGBCTE9LX1dPUktFUl9BREFQVEVSYCBlbnYgdmFyIHNldHMgdGhlIGRlZmF1bHQuIFN1YmNsYXNzZXMgY2FuIHN0aWxsXG4gKiBzZXQgYHByb3RlY3RlZCBhZGFwdGVyYCBkaXJlY3RseSBmb3IgYmFjay1jb21wYXQgd2l0aCB0aGUgcHJlLXYwLjdcbiAqIHNpbmdsZS1hZGFwdGVyIHBhdHRlcm4uXG4gKlxuICogQGV4YW1wbGUgQnVsbE1RXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBpbXBvcnQgeyBXb3JrZXJUcmlnZ2VyLCBCdWxsTVFBZGFwdGVyIH0gZnJvbSBcIkBibG9ranMvdHJpZ2dlci13b3JrZXJcIjtcbiAqXG4gKiBjbGFzcyBNeVdvcmtlclRyaWdnZXIgZXh0ZW5kcyBXb3JrZXJUcmlnZ2VyIHtcbiAqICAgcHJvdGVjdGVkIGFkYXB0ZXIgPSBuZXcgQnVsbE1RQWRhcHRlcih7XG4gKiAgICAgaG9zdDogXCJsb2NhbGhvc3RcIixcbiAqICAgICBwb3J0OiA2Mzc5LFxuICogICB9KTtcbiAqXG4gKiAgIHByb3RlY3RlZCBub2RlcyA9IG15Tm9kZXM7XG4gKiAgIHByb3RlY3RlZCB3b3JrZmxvd3MgPSBteVdvcmtmbG93cztcbiAqIH1cbiAqXG4gKiBjb25zdCB0cmlnZ2VyID0gbmV3IE15V29ya2VyVHJpZ2dlcigpO1xuICogYXdhaXQgdHJpZ2dlci5saXN0ZW4oKTtcbiAqXG4gKiAvLyBEaXNwYXRjaCBhIGpvYlxuICogYXdhaXQgdHJpZ2dlci5kaXNwYXRjaChcImJhY2tncm91bmQtam9ic1wiLCB7IHVzZXJJZDogXCIxMjNcIiB9LCB7XG4gKiAgIHByaW9yaXR5OiAxMCxcbiAqICAgcmV0cmllczogMyxcbiAqICAgZGVsYXk6IDUwMDAsIC8vIGRlbGF5IDUgc2Vjb25kc1xuICogfSk7XG4gKiBgYGBcbiAqXG4gKiBAZXhhbXBsZSBJbk1lbW9yeSAoZGV2ZWxvcG1lbnQpXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBpbXBvcnQgeyBXb3JrZXJUcmlnZ2VyLCBJbk1lbW9yeUFkYXB0ZXIgfSBmcm9tIFwiQGJsb2tqcy90cmlnZ2VyLXdvcmtlclwiO1xuICpcbiAqIGNsYXNzIERldldvcmtlclRyaWdnZXIgZXh0ZW5kcyBXb3JrZXJUcmlnZ2VyIHtcbiAqICAgcHJvdGVjdGVkIGFkYXB0ZXIgPSBuZXcgSW5NZW1vcnlBZGFwdGVyKCk7XG4gKiAgIHByb3RlY3RlZCBub2RlcyA9IG15Tm9kZXM7XG4gKiAgIHByb3RlY3RlZCB3b3JrZmxvd3MgPSBteVdvcmtmbG93cztcbiAqIH1cbiAqIGBgYFxuICovXG5cbi8vIENvcmUgZXhwb3J0c1xuZXhwb3J0IHtcblx0V29ya2VyVHJpZ2dlcixcblx0dHlwZSBXb3JrZXJBZGFwdGVyLFxuXHR0eXBlIFdvcmtlckpvYixcblx0dHlwZSBXb3JrZXJRdWV1ZVN0YXRzLFxufSBmcm9tIFwiLi9Xb3JrZXJUcmlnZ2VyXCI7XG5cbi8vIEFkYXB0ZXJzXG5leHBvcnQgeyBCdWxsTVFBZGFwdGVyLCB0eXBlIEJ1bGxNUUNvbmZpZyB9IGZyb20gXCIuL2FkYXB0ZXJzL0J1bGxNUUFkYXB0ZXJcIjtcbmV4cG9ydCB7IEluTWVtb3J5QWRhcHRlciB9IGZyb20gXCIuL2FkYXB0ZXJzL0luTWVtb3J5QWRhcHRlclwiO1xuZXhwb3J0IHsgS2Fma2FBZGFwdGVyLCB0eXBlIEthZmthQ29uZmlnIH0gZnJvbSBcIi4vYWRhcHRlcnMvS2Fma2FBZGFwdGVyXCI7XG5leHBvcnQgeyBOQVRTV29ya2VyQWRhcHRlciwgdHlwZSBOQVRTV29ya2VyQ29uZmlnIH0gZnJvbSBcIi4vYWRhcHRlcnMvTkFUU0FkYXB0ZXJcIjtcbmV4cG9ydCB7IFBnQm9zc0FkYXB0ZXIsIHR5cGUgUGdCb3NzQ29uZmlnIH0gZnJvbSBcIi4vYWRhcHRlcnMvUGdCb3NzQWRhcHRlclwiO1xuZXhwb3J0IHsgUmFiYml0TVFBZGFwdGVyLCB0eXBlIFJhYmJpdE1RQ29uZmlnIH0gZnJvbSBcIi4vYWRhcHRlcnMvUmFiYml0TVFBZGFwdGVyXCI7XG5leHBvcnQgeyBSZWRpc1N0cmVhbXNBZGFwdGVyLCB0eXBlIFJlZGlzU3RyZWFtc0NvbmZpZyB9IGZyb20gXCIuL2FkYXB0ZXJzL1JlZGlzU3RyZWFtc0FkYXB0ZXJcIjtcbmV4cG9ydCB7IFNRU0FkYXB0ZXIsIHR5cGUgU1FTQ29uZmlnIH0gZnJvbSBcIi4vYWRhcHRlcnMvU1FTQWRhcHRlclwiO1xuXG4vLyB2MC43IFBSIDUg4oCUIGZhY3RvcnkgKyBwb29sLiBVc2VkIGJ5IFdvcmtlclRyaWdnZXIgYW5kIGV4cG9zZWQgZm9yXG4vLyBoZWxwZXIgbm9kZXMgKGBAYmxva2pzL3dvcmtlci1wdWJsaXNoYCkgdGhhdCBuZWVkIHRvIGVucXVldWUgam9ic1xuLy8gZnJvbSBhbnkgd29ya2Zsb3cgd2l0aG91dCBidW5kbGluZyBhbGwgYnJva2VyIFNES3MuXG5leHBvcnQge1xuXHRfcmVzZXRBZGFwdGVyUG9vbEZvclRlc3RzLFxuXHRjcmVhdGVXb3JrZXJBZGFwdGVyLFxuXHRnZXRPckNyZWF0ZUFkYXB0ZXIsXG5cdHJlc29sdmVQcm92aWRlcixcbn0gZnJvbSBcIi4vYWRhcHRlcnMvZmFjdG9yeVwiO1xuXG4vLyBSZS1leHBvcnQgdHlwZXMgZnJvbSBoZWxwZXIgZm9yIGNvbnZlbmllbmNlXG5leHBvcnQgdHlwZSB7IFdvcmtlclByb3ZpZGVyLCBXb3JrZXJUcmlnZ2VyT3B0cyB9IGZyb20gXCJAYmxva2pzL2hlbHBlclwiO1xuIl19