@openfn/ws-worker 0.8.1 → 1.1.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.
package/dist/index.js CHANGED
@@ -1,3 +1,110 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropNames = Object.getOwnPropertyNames;
3
+ var __esm = (fn, res) => function __init() {
4
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
5
+ };
6
+ var __export = (target, all) => {
7
+ for (var name2 in all)
8
+ __defProp(target, name2, { get: all[name2], enumerable: true });
9
+ };
10
+
11
+ // package.json
12
+ var package_exports = {};
13
+ __export(package_exports, {
14
+ author: () => author,
15
+ bin: () => bin,
16
+ default: () => package_default,
17
+ dependencies: () => dependencies,
18
+ description: () => description,
19
+ devDependencies: () => devDependencies,
20
+ files: () => files,
21
+ license: () => license,
22
+ main: () => main,
23
+ name: () => name,
24
+ scripts: () => scripts,
25
+ type: () => type,
26
+ version: () => version
27
+ });
28
+ var name, version, description, main, type, scripts, bin, author, license, dependencies, devDependencies, files, package_default;
29
+ var init_package = __esm({
30
+ "package.json"() {
31
+ name = "@openfn/ws-worker";
32
+ version = "1.1.0";
33
+ description = "A Websocket Worker to connect Lightning to a Runtime Engine";
34
+ main = "dist/index.js";
35
+ type = "module";
36
+ scripts = {
37
+ test: "pnpm ava --serial",
38
+ "test:types": "pnpm tsc --noEmit --project tsconfig.json",
39
+ build: "tsup --config tsup.config.js",
40
+ "build:watch": "pnpm build --watch",
41
+ start: "ts-node-esm --transpile-only src/start.ts",
42
+ "start:prod": "node dist/start.js",
43
+ "start:watch": "nodemon -e ts,js --watch ../runtime-manager/dist --watch ./src --exec 'pnpm start'",
44
+ pack: "pnpm pack --pack-destination ../../dist"
45
+ };
46
+ bin = {
47
+ worker: "dist/start.js"
48
+ };
49
+ author = "Open Function Group <admin@openfn.org>";
50
+ license = "ISC";
51
+ dependencies = {
52
+ "@koa/router": "^12.0.0",
53
+ "@openfn/engine-multi": "workspace:*",
54
+ "@openfn/lexicon": "workspace:^",
55
+ "@openfn/logger": "workspace:*",
56
+ "@openfn/runtime": "workspace:*",
57
+ "@types/koa-logger": "^3.1.2",
58
+ "@types/ws": "^8.5.6",
59
+ "fast-safe-stringify": "^2.1.1",
60
+ figures: "^5.0.0",
61
+ "human-id": "^4.1.0",
62
+ jose: "^4.14.6",
63
+ koa: "^2.13.4",
64
+ "koa-bodyparser": "^4.4.0",
65
+ "koa-logger": "^3.2.1",
66
+ phoenix: "1.7.10",
67
+ ws: "^8.14.1"
68
+ };
69
+ devDependencies = {
70
+ "@openfn/lightning-mock": "workspace:*",
71
+ "@types/koa": "^2.13.5",
72
+ "@types/koa-bodyparser": "^4.3.10",
73
+ "@types/koa__router": "^12.0.1",
74
+ "@types/node": "^18.15.3",
75
+ "@types/nodemon": "1.19.3",
76
+ "@types/phoenix": "^1.6.2",
77
+ "@types/yargs": "^17.0.12",
78
+ ava: "5.1.0",
79
+ nodemon: "3.0.1",
80
+ "ts-node": "^10.9.1",
81
+ tslib: "^2.4.0",
82
+ tsup: "^6.2.3",
83
+ typescript: "^4.6.4",
84
+ yargs: "^17.6.2"
85
+ };
86
+ files = [
87
+ "dist",
88
+ "README.md",
89
+ "CHANGELOG.md"
90
+ ];
91
+ package_default = {
92
+ name,
93
+ version,
94
+ description,
95
+ main,
96
+ type,
97
+ scripts,
98
+ bin,
99
+ author,
100
+ license,
101
+ dependencies,
102
+ devDependencies,
103
+ files
104
+ };
105
+ }
106
+ });
107
+
1
108
  // src/server.ts
2
109
  import { EventEmitter as EventEmitter2 } from "node:events";
3
110
  import Koa from "koa";
@@ -10,8 +117,8 @@ import { createMockLogger as createMockLogger2 } from "@openfn/logger";
10
117
  // src/events.ts
11
118
  var CLAIM = "claim";
12
119
  var GET_PLAN = "fetch:plan";
13
- var GET_CREDENTIAL = "fetch:credential";
14
120
  var GET_DATACLIP = "fetch:dataclip";
121
+ var GET_CREDENTIAL = "fetch:credential";
15
122
  var RUN_START = "run:start";
16
123
  var RUN_COMPLETE = "run:complete";
17
124
  var RUN_LOG = "run:log";
@@ -35,6 +142,7 @@ var destroy = async (app, logger) => {
35
142
  await waitForRuns(app, logger);
36
143
  await app.engine.destroy();
37
144
  app.socket?.disconnect();
145
+ logger.info("Server closed....");
38
146
  resolve();
39
147
  })
40
148
  ]);
@@ -59,6 +167,7 @@ var waitForRuns = (app, logger) => new Promise((resolve) => {
59
167
  log();
60
168
  app.events.on(INTERNAL_RUN_COMPLETE, onRunComplete);
61
169
  } else {
170
+ logger.debug("No active rns detected");
62
171
  resolve();
63
172
  }
64
173
  });
@@ -106,10 +215,22 @@ var tryWithBackoff = (fn, opts = {}) => {
106
215
  var try_with_backoff_default = tryWithBackoff;
107
216
 
108
217
  // src/api/claim.ts
218
+ import crypto from "node:crypto";
219
+ import * as jose from "jose";
109
220
  import { createMockLogger } from "@openfn/logger";
110
221
  var mockLogger = createMockLogger();
111
- var claim = (app, logger = mockLogger, maxWorkers = 5) => {
222
+ var verifyToken = async (token, publicKey) => {
223
+ const key = crypto.createPublicKey(publicKey);
224
+ const { payload } = await jose.jwtVerify(token, key, {
225
+ issuer: "Lightning"
226
+ });
227
+ if (payload) {
228
+ return true;
229
+ }
230
+ };
231
+ var claim = (app, logger = mockLogger, options = {}) => {
112
232
  return new Promise((resolve, reject) => {
233
+ const { maxWorkers = 5 } = options;
113
234
  const activeWorkers = Object.keys(app.workflows).length;
114
235
  if (activeWorkers >= maxWorkers) {
115
236
  return reject(new Error("Server at capacity"));
@@ -123,7 +244,21 @@ var claim = (app, logger = mockLogger, maxWorkers = 5) => {
123
244
  if (!runs?.length) {
124
245
  return reject(new Error("No runs returned"));
125
246
  }
126
- runs.forEach((run) => {
247
+ runs.forEach(async (run) => {
248
+ if (app.options?.runPublicKey) {
249
+ try {
250
+ await verifyToken(run.token, app.options.runPublicKey);
251
+ logger.debug("verified run token for", run.id);
252
+ } catch (e) {
253
+ logger.error("Error validating run token");
254
+ logger.error(e);
255
+ reject();
256
+ app.destroy();
257
+ return;
258
+ }
259
+ } else {
260
+ logger.debug("skipping run token validation for", run.id);
261
+ }
127
262
  logger.debug("starting run", run.id);
128
263
  app.execute(run);
129
264
  resolve();
@@ -144,10 +279,15 @@ var startWorkloop = (app, logger, minBackoff, maxBackoff, maxWorkers) => {
144
279
  let cancelled = false;
145
280
  const workLoop = () => {
146
281
  if (!cancelled) {
147
- promise = try_with_backoff_default(() => claim_default(app, logger, maxWorkers), {
148
- min: minBackoff,
149
- max: maxBackoff
150
- });
282
+ promise = try_with_backoff_default(
283
+ () => claim_default(app, logger, {
284
+ maxWorkers
285
+ }),
286
+ {
287
+ min: minBackoff,
288
+ max: maxBackoff
289
+ }
290
+ );
151
291
  promise.then(() => {
152
292
  if (!cancelled) {
153
293
  setTimeout(workLoop, minBackoff);
@@ -165,8 +305,8 @@ var startWorkloop = (app, logger, minBackoff, maxBackoff, maxWorkers) => {
165
305
  };
166
306
  var workloop_default = startWorkloop;
167
307
 
168
- // src/util/convert-run.ts
169
- import crypto from "node:crypto";
308
+ // src/util/convert-lightning-plan.ts
309
+ import crypto2 from "node:crypto";
170
310
  var conditions = {
171
311
  on_job_success: (upstreamId) => `Boolean(!state?.errors?.["${upstreamId}"] ?? true)`,
172
312
  on_job_failure: (upstreamId) => `Boolean(state?.errors && state.errors["${upstreamId}"])`,
@@ -186,19 +326,30 @@ var mapTriggerEdgeCondition = (edge) => {
186
326
  return true;
187
327
  return condition;
188
328
  };
189
- var mapOptions = (options) => {
190
- return options;
191
- };
192
- var convert_run_default = (run) => {
193
- const options = run.options || {};
329
+ var convert_lightning_plan_default = (run) => {
330
+ const runtimeOpts = {};
331
+ const engineOpts = {};
332
+ if (run.options) {
333
+ if (run.options.runTimeoutMs) {
334
+ engineOpts.runTimeoutMs = run.options.runTimeoutMs;
335
+ }
336
+ if (run.options.sanitize) {
337
+ engineOpts.sanitize = run.options.sanitize;
338
+ }
339
+ if (run.options.hasOwnProperty("output_dataclips")) {
340
+ engineOpts.outputDataclips = run.options.output_dataclips;
341
+ }
342
+ }
194
343
  const plan = {
195
- id: run.id
344
+ id: run.id,
345
+ options: runtimeOpts
196
346
  };
347
+ let initialState;
197
348
  if (run.dataclip_id) {
198
- plan.initialState = run.dataclip_id;
349
+ initialState = run.dataclip_id;
199
350
  }
200
351
  if (run.starting_node_id) {
201
- plan.start = run.starting_node_id;
352
+ runtimeOpts.start = run.starting_node_id;
202
353
  }
203
354
  const nodes = {};
204
355
  const edges = run.edges ?? [];
@@ -210,27 +361,33 @@ var convert_run_default = (run) => {
210
361
  };
211
362
  const connectedEdges = edges.filter((e) => e.source_trigger_id === id);
212
363
  if (connectedEdges.length) {
213
- nodes[id].next = connectedEdges.reduce((obj, edge) => {
214
- if (edge.enabled !== false) {
215
- obj[edge.target_job_id] = mapTriggerEdgeCondition(edge);
216
- }
217
- return obj;
218
- }, {});
364
+ nodes[id].next = connectedEdges.reduce(
365
+ (obj, edge) => {
366
+ if (edge.enabled !== false) {
367
+ obj[edge.target_job_id] = mapTriggerEdgeCondition(edge);
368
+ }
369
+ return obj;
370
+ },
371
+ {}
372
+ );
219
373
  } else {
220
374
  }
221
375
  });
222
376
  }
223
377
  if (run.jobs?.length) {
224
- run.jobs.forEach((job) => {
225
- const id = job.id || crypto.randomUUID();
226
- nodes[id] = {
378
+ run.jobs.forEach((step) => {
379
+ const id = step.id || crypto2.randomUUID();
380
+ const job = {
227
381
  id,
228
- configuration: job.credential || job.credential_id,
229
- expression: job.body,
230
- adaptor: job.adaptor
382
+ configuration: step.credential || step.credential_id,
383
+ expression: step.body,
384
+ adaptor: step.adaptor
231
385
  };
232
- if (job.state) {
233
- nodes[id].state = job.state;
386
+ if (step.name) {
387
+ job.name = step.name;
388
+ }
389
+ if (step.state) {
390
+ job.state = step.state;
234
391
  }
235
392
  const next = edges.filter((e) => e.source_job_id === id).reduce((obj, edge) => {
236
393
  const newEdge = {};
@@ -245,21 +402,32 @@ var convert_run_default = (run) => {
245
402
  return obj;
246
403
  }, {});
247
404
  if (Object.keys(next).length) {
248
- nodes[id].next = next;
405
+ job.next = next;
249
406
  }
407
+ nodes[id] = job;
250
408
  });
251
409
  }
252
- plan.jobs = Object.values(nodes);
410
+ plan.workflow = {
411
+ steps: Object.values(nodes)
412
+ };
413
+ if (run.name) {
414
+ plan.workflow.name = run.name;
415
+ }
253
416
  return {
254
417
  plan,
255
- options: mapOptions(options)
418
+ options: engineOpts,
419
+ input: initialState || {}
256
420
  };
257
421
  };
258
422
 
259
423
  // src/util/get-with-reply.ts
260
- var get_with_reply_default = (channel, event, payload) => new Promise((resolve) => {
424
+ var get_with_reply_default = (channel, event, payload) => new Promise((resolve, reject) => {
261
425
  channel.push(event, payload).receive("ok", (evt) => {
262
426
  resolve(evt);
427
+ }).receive("error", (e) => {
428
+ reject(e);
429
+ }).receive("timeout", (e) => {
430
+ reject(e);
263
431
  });
264
432
  });
265
433
 
@@ -273,19 +441,20 @@ var stringify_default = (obj) => stringify(obj, (_key, value) => {
273
441
  });
274
442
 
275
443
  // src/util/create-run-state.ts
276
- var create_run_state_default = (plan, options = {}) => {
444
+ var create_run_state_default = (plan, input) => {
277
445
  const state = {
278
- plan,
279
446
  lastDataclipId: "",
280
447
  dataclips: {},
281
448
  inputDataclips: {},
282
449
  reasons: {},
283
- options
450
+ plan,
451
+ input
284
452
  };
285
- if (typeof plan.initialState === "string") {
286
- let startNode = plan.jobs[0];
287
- if (plan.start) {
288
- startNode = plan.jobs.find(({ id }) => id === plan.start);
453
+ if (typeof input === "string") {
454
+ const jobs = plan.workflow.steps;
455
+ let startNode = jobs[0];
456
+ if (plan.options.start) {
457
+ startNode = jobs.find(({ id }) => id === plan.options.start);
289
458
  }
290
459
  const initialRuns = [];
291
460
  if (!startNode.expression) {
@@ -294,7 +463,7 @@ var create_run_state_default = (plan, options = {}) => {
294
463
  initialRuns.push(startNode.id);
295
464
  }
296
465
  initialRuns.forEach((id) => {
297
- state.inputDataclips[id] = plan.initialState;
466
+ state.inputDataclips[id] = input;
298
467
  });
299
468
  } else {
300
469
  }
@@ -328,8 +497,59 @@ var createThrottler = () => {
328
497
  };
329
498
  var throttle_default = createThrottler;
330
499
 
500
+ // src/events/run-start.ts
501
+ import { timestamp } from "@openfn/logger";
502
+
503
+ // src/util/versions.ts
504
+ import { mainSymbols } from "figures";
505
+ var { triangleRightSmall: t } = mainSymbols;
506
+ var versions_default = (versions) => {
507
+ let longest = "worker".length;
508
+ for (const v in versions) {
509
+ longest = Math.max(v.length, longest);
510
+ }
511
+ const { node, worker, compiler, runtime, engine, ...adaptors } = versions;
512
+ const prefix = (str2) => ` ${t} ${str2.padEnd(longest + 4, " ")}`;
513
+ let str = `Versions:
514
+ ${prefix("node.js")}${versions.node || "unknown"}
515
+ ${prefix("worker")}${versions.worker || "unknown"}`;
516
+ if (Object.keys(adaptors).length) {
517
+ let allAdaptors = Object.keys(adaptors);
518
+ str += "\n" + allAdaptors.sort().map(
519
+ (adaptorName) => `${prefix(adaptorName)}${adaptors[adaptorName].sort().join(", ")}`
520
+ ).join("\n");
521
+ }
522
+ return str;
523
+ };
524
+
525
+ // src/events/run-start.ts
526
+ init_package();
527
+ async function onRunStart(context, event) {
528
+ const { channel, state } = context;
529
+ const time = (timestamp() - BigInt(1e7)).toString();
530
+ const versionLogContext = {
531
+ ...context,
532
+ state: {
533
+ ...state,
534
+ activeStep: state.activeStep
535
+ }
536
+ };
537
+ const versions = {
538
+ worker: package_default.version,
539
+ ...event.versions
540
+ };
541
+ await sendEvent(channel, RUN_START, { versions });
542
+ const versionMessage = versions_default(versions);
543
+ await onJobLog(versionLogContext, {
544
+ time,
545
+ message: [versionMessage],
546
+ level: "info",
547
+ name: "VER"
548
+ });
549
+ }
550
+
331
551
  // src/events/step-complete.ts
332
- import crypto2 from "node:crypto";
552
+ import crypto3 from "node:crypto";
333
553
 
334
554
  // src/api/reasons.ts
335
555
  var calculateJobExitReason = (jobId, state = { data: {} }, error) => {
@@ -355,7 +575,7 @@ var isLeafNode = (state, job) => {
355
575
  };
356
576
  var calculateRunExitReason = (state) => {
357
577
  if (state.plan && state.reasons) {
358
- const leafJobReasons = state.plan.jobs.filter((job) => isLeafNode(state, job)).map(({ id }) => state.reasons[id]);
578
+ const leafJobReasons = state.plan.workflow.steps.filter((job) => isLeafNode(state, job)).map(({ id }) => state.reasons[id]);
359
579
  const fail = leafJobReasons.find((r) => r && r.reason === "fail");
360
580
  if (fail) {
361
581
  return fail;
@@ -365,8 +585,8 @@ var calculateRunExitReason = (state) => {
365
585
  };
366
586
 
367
587
  // src/events/step-complete.ts
368
- function onStepComplete({ channel, state }, event, error) {
369
- const dataclipId = crypto2.randomUUID();
588
+ function onStepComplete({ channel, state, options }, event, error) {
589
+ const dataclipId = crypto3.randomUUID();
370
590
  const step_id = state.activeStep;
371
591
  const job_id = state.activeJob;
372
592
  if (!state.dataclips) {
@@ -390,7 +610,6 @@ function onStepComplete({ channel, state }, event, error) {
390
610
  step_id,
391
611
  job_id,
392
612
  output_dataclip_id: dataclipId,
393
- output_dataclip: stringify_default(outputState),
394
613
  reason,
395
614
  error_message,
396
615
  error_type,
@@ -398,137 +617,24 @@ function onStepComplete({ channel, state }, event, error) {
398
617
  duration: event.duration,
399
618
  thread_id: event.threadId
400
619
  };
620
+ if (!options || options.outputDataclips !== false) {
621
+ evt.output_dataclip = stringify_default(outputState);
622
+ }
401
623
  return sendEvent(channel, STEP_COMPLETE, evt);
402
624
  }
403
625
 
404
626
  // src/events/step-start.ts
405
- import crypto3 from "node:crypto";
406
- import { timestamp } from "@openfn/logger";
407
-
408
- // package.json
409
- var package_default = {
410
- name: "@openfn/ws-worker",
411
- version: "0.8.1",
412
- description: "A Websocket Worker to connect Lightning to a Runtime Engine",
413
- main: "dist/index.js",
414
- type: "module",
415
- scripts: {
416
- test: "pnpm ava --serial",
417
- "test:types": "pnpm tsc --noEmit --project tsconfig.json",
418
- build: "tsup --config tsup.config.js",
419
- "build:watch": "pnpm build --watch",
420
- start: "ts-node-esm --transpile-only src/start.ts",
421
- "start:prod": "node dist/start.js",
422
- "start:watch": "nodemon -e ts,js --watch ../runtime-manager/dist --watch ./src --exec 'pnpm start'",
423
- pack: "pnpm pack --pack-destination ../../dist"
424
- },
425
- bin: {
426
- worker: "dist/start.js"
427
- },
428
- author: "Open Function Group <admin@openfn.org>",
429
- license: "ISC",
430
- dependencies: {
431
- "@koa/router": "^12.0.0",
432
- "@openfn/engine-multi": "workspace:*",
433
- "@openfn/logger": "workspace:*",
434
- "@openfn/runtime": "workspace:*",
435
- "@types/koa-logger": "^3.1.2",
436
- "@types/ws": "^8.5.6",
437
- "fast-safe-stringify": "^2.1.1",
438
- figures: "^5.0.0",
439
- "human-id": "^4.1.0",
440
- jose: "^4.14.6",
441
- koa: "^2.13.4",
442
- "koa-bodyparser": "^4.4.0",
443
- "koa-logger": "^3.2.1",
444
- phoenix: "^1.7.7",
445
- ws: "^8.14.1"
446
- },
447
- devDependencies: {
448
- "@openfn/lightning-mock": "workspace:*",
449
- "@types/koa": "^2.13.5",
450
- "@types/koa-bodyparser": "^4.3.10",
451
- "@types/koa__router": "^12.0.1",
452
- "@types/node": "^18.15.3",
453
- "@types/nodemon": "1.19.3",
454
- "@types/phoenix": "^1.6.2",
455
- "@types/yargs": "^17.0.12",
456
- ava: "5.1.0",
457
- nodemon: "3.0.1",
458
- "ts-node": "^10.9.1",
459
- tslib: "^2.4.0",
460
- tsup: "^6.2.3",
461
- typescript: "^4.6.4",
462
- yargs: "^17.6.2"
463
- },
464
- files: [
465
- "dist",
466
- "README.md",
467
- "CHANGELOG.md"
468
- ]
469
- };
470
-
471
- // src/util/versions.ts
472
- import { mainSymbols } from "figures";
473
- var { triangleRightSmall: t } = mainSymbols;
474
- var versions_default = (stepId, versions, adaptor) => {
475
- let longest = "compiler".length;
476
- for (const v in versions) {
477
- longest = Math.max(v.length, longest);
478
- }
479
- const { node, compiler, engine, worker, runtime, ...adaptors } = versions;
480
- const prefix = (str2) => ` ${t} ${str2.padEnd(longest + 4, " ")}`;
481
- let str = `Versions for step ${stepId}:
482
- ${prefix("node.js")}${versions.node || "unknown"}
483
- ${prefix("worker")}${versions.worker || "unknown"}
484
- ${prefix("engine")}${versions.engine || "unknown"}`;
485
- if (Object.keys(adaptors).length) {
486
- let allAdaptors = Object.keys(adaptors);
487
- if (adaptor) {
488
- allAdaptors = allAdaptors.filter((name) => adaptor.startsWith(name));
489
- }
490
- str += "\n" + allAdaptors.sort().map((adaptorName) => `${prefix(adaptorName)}${adaptors[adaptorName]}`).join("\n");
491
- }
492
- return str;
493
- };
494
-
495
- // src/events/step-start.ts
627
+ import crypto4 from "node:crypto";
496
628
  async function onStepStart(context, event) {
497
- const time = (timestamp() - BigInt(1e7)).toString();
498
629
  const { channel, state } = context;
499
- state.activeStep = crypto3.randomUUID();
630
+ state.activeStep = crypto4.randomUUID();
500
631
  state.activeJob = event.jobId;
501
- const job = state.plan.jobs.find(({ id }) => id === event.jobId);
502
632
  const input_dataclip_id = state.inputDataclips[event.jobId];
503
- const versions = {
504
- worker: package_default.version,
505
- ...event.versions
506
- };
507
- const versionLogContext = {
508
- ...context,
509
- state: {
510
- ...state,
511
- activeStep: state.activeStep
512
- }
513
- };
514
633
  await sendEvent(channel, STEP_START, {
515
634
  step_id: state.activeStep,
516
635
  job_id: state.activeJob,
517
- input_dataclip_id,
518
- versions
636
+ input_dataclip_id
519
637
  });
520
- const versionMessage = versions_default(
521
- versionLogContext.state.activeStep,
522
- versions,
523
- job?.adaptor
524
- );
525
- await onJobLog(versionLogContext, {
526
- time,
527
- message: [versionMessage],
528
- level: "info",
529
- name: "VER"
530
- });
531
- return;
532
638
  }
533
639
 
534
640
  // src/util/log-final-reason.ts
@@ -576,7 +682,7 @@ async function onRunError(context, event) {
576
682
  });
577
683
  onFinish({ reason });
578
684
  } catch (e) {
579
- logger.error("ERROR in workflow-error handler:", e.message);
685
+ logger.error("ERROR in run-error handler:", e.message);
580
686
  logger.error(e);
581
687
  onFinish({});
582
688
  }
@@ -591,11 +697,18 @@ var eventMap = {
591
697
  "workflow-log": RUN_LOG,
592
698
  "workflow-complete": RUN_COMPLETE
593
699
  };
594
- function execute(channel, engine, logger, plan, options = {}, onFinish = (_result) => {
700
+ function execute(channel, engine, logger, plan, input, options = {}, onFinish = (_result) => {
595
701
  }) {
596
702
  logger.info("executing ", plan.id);
597
- const state = create_run_state_default(plan, options);
598
- const context = { channel, state, logger, engine, onFinish };
703
+ const state = create_run_state_default(plan, input);
704
+ const context = {
705
+ channel,
706
+ state,
707
+ logger,
708
+ engine,
709
+ options,
710
+ onFinish
711
+ };
599
712
  const throttle = throttle_default();
600
713
  const addEvent = (eventName, handler) => {
601
714
  const wrappedFn = async (event) => {
@@ -616,7 +729,7 @@ function execute(channel, engine, logger, plan, options = {}, onFinish = (_resul
616
729
  };
617
730
  const listeners = Object.assign(
618
731
  {},
619
- addEvent("workflow-start", throttle(onWorkflowStart)),
732
+ addEvent("workflow-start", throttle(onRunStart)),
620
733
  addEvent("job-start", throttle(onStepStart)),
621
734
  addEvent("job-complete", throttle(onStepComplete)),
622
735
  addEvent("job-error", throttle(onJobError)),
@@ -628,17 +741,24 @@ function execute(channel, engine, logger, plan, options = {}, onFinish = (_resul
628
741
  const resolvers = {
629
742
  credential: (id) => loadCredential(channel, id)
630
743
  };
631
- Promise.resolve().then(async () => {
632
- if (typeof plan.initialState === "string") {
633
- logger.debug("loading dataclip", plan.initialState);
634
- plan.initialState = await loadDataclip(channel, plan.initialState);
635
- logger.success("dataclip loaded");
636
- logger.debug(plan.initialState);
744
+ setTimeout(async () => {
745
+ let loadedInput = input;
746
+ if (typeof input === "string") {
747
+ logger.debug("loading dataclip", input);
748
+ try {
749
+ loadedInput = await loadDataclip(channel, input);
750
+ logger.success("dataclip loaded");
751
+ } catch (e) {
752
+ return onRunError(context, {
753
+ workflowId: plan.id,
754
+ message: `Failed to load dataclip ${input}${e.message ? `: ${e.message}` : ""}`,
755
+ type: "DataClipError",
756
+ severity: "exception"
757
+ });
758
+ }
637
759
  }
638
- return plan;
639
- }).then(() => {
640
760
  try {
641
- engine.execute(plan, { resolvers, ...options });
761
+ engine.execute(plan, loadedInput, { resolvers, ...options });
642
762
  } catch (e) {
643
763
  onRunError(context, {
644
764
  workflowId: plan.id,
@@ -663,9 +783,6 @@ function onJobError(context, event) {
663
783
  return onStepComplete(context, event, event.error);
664
784
  }
665
785
  }
666
- function onWorkflowStart({ channel }, _event) {
667
- return sendEvent(channel, RUN_START);
668
- }
669
786
  function onJobLog({ channel, state }, event) {
670
787
  const timeInMicroseconds = BigInt(event.time) / BigInt(1e3);
671
788
  const log = {
@@ -707,9 +824,9 @@ var joinRunChannel = (socket, token, runId, logger) => {
707
824
  if (!didReceiveOk) {
708
825
  didReceiveOk = true;
709
826
  logger.success(`connected to ${channelName}`, e);
710
- const { plan, options } = await loadRun(channel);
827
+ const { plan, options, input } = await loadRun(channel);
711
828
  logger.debug("converted run as execution plan:", plan);
712
- resolve({ channel, plan, options });
829
+ resolve({ channel, plan, options, input });
713
830
  }
714
831
  }).receive("error", (err) => {
715
832
  logger.error(`error connecting to ${channelName}`, err);
@@ -720,16 +837,17 @@ var joinRunChannel = (socket, token, runId, logger) => {
720
837
  var run_default = joinRunChannel;
721
838
  async function loadRun(channel) {
722
839
  const runBody = await get_with_reply_default(channel, GET_PLAN);
723
- return convert_run_default(runBody);
840
+ return convert_lightning_plan_default(runBody);
724
841
  }
725
842
 
726
843
  // src/channels/worker-queue.ts
727
844
  import EventEmitter from "node:events";
728
845
  import { Socket as PhxSocket } from "phoenix";
729
846
  import { WebSocket } from "ws";
847
+ import { API_VERSION } from "@openfn/lexicon/lightning";
730
848
 
731
849
  // src/util/worker-token.ts
732
- import * as jose from "jose";
850
+ import * as jose2 from "jose";
733
851
  var alg = "HS256";
734
852
  var generateWorkerToken = async (secret, workerId, logger) => {
735
853
  if (!secret) {
@@ -744,7 +862,7 @@ var generateWorkerToken = async (secret, workerId, logger) => {
744
862
  const claims = {
745
863
  worker_id: workerId
746
864
  };
747
- const jwt = await new jose.SignJWT(claims).setProtectedHeader({ alg }).setIssuedAt().setIssuer("urn:example:issuer").setAudience("urn:example:audience").sign(encodedSecret);
865
+ const jwt = await new jose2.SignJWT(claims).setProtectedHeader({ alg }).setIssuedAt().setIssuer("urn:openfn:worker").sign(encodedSecret);
748
866
  return jwt;
749
867
  };
750
868
  var worker_token_default = generateWorkerToken;
@@ -752,9 +870,15 @@ var worker_token_default = generateWorkerToken;
752
870
  // src/channels/worker-queue.ts
753
871
  var connectToWorkerQueue = (endpoint, serverId, secret, logger, SocketConstructor = PhxSocket) => {
754
872
  const events = new EventEmitter();
755
- worker_token_default(secret, serverId, logger).then((token) => {
873
+ worker_token_default(secret, serverId, logger).then(async (token) => {
874
+ const pkg = await Promise.resolve().then(() => (init_package(), package_exports));
875
+ const params = {
876
+ token,
877
+ api_version: API_VERSION,
878
+ worker_version: pkg.default.version
879
+ };
756
880
  const socket = new SocketConstructor(endpoint, {
757
- params: { token },
881
+ params,
758
882
  transport: WebSocket
759
883
  });
760
884
  let didOpen = false;
@@ -793,6 +917,9 @@ var MAX_BACKOFF = 1e3 * 30;
793
917
  function connect(app, logger, options = {}) {
794
918
  logger.debug("Connecting to Lightning at", options.lightning);
795
919
  const onConnect = ({ socket, channel }) => {
920
+ if (app.destroyed) {
921
+ return;
922
+ }
796
923
  logger.success("Connected to Lightning at", options.lightning);
797
924
  app.socket = socket;
798
925
  app.queueChannel = channel;
@@ -827,6 +954,9 @@ function connect(app, logger, options = {}) {
827
954
  }
828
955
  };
829
956
  const onError = (e) => {
957
+ if (app.destroyed) {
958
+ return;
959
+ }
830
960
  logger.error(
831
961
  "CRITICAL ERROR: could not connect to lightning at",
832
962
  options.lightning
@@ -856,13 +986,15 @@ function createServer(engine, options = {}) {
856
986
  process.send?.("READY");
857
987
  router.get("/livez", healthcheck_default);
858
988
  router.get("/", healthcheck_default);
989
+ app.options = options || {};
859
990
  app.execute = async ({ id, token }) => {
860
991
  if (app.socket) {
861
992
  app.workflows[id] = true;
862
993
  const {
863
994
  channel: runChannel,
864
995
  plan,
865
- options: options2
996
+ options: options2,
997
+ input
866
998
  } = await run_default(app.socket, token, id, logger);
867
999
  const onFinish = () => {
868
1000
  delete app.workflows[id];
@@ -874,6 +1006,7 @@ function createServer(engine, options = {}) {
874
1006
  engine,
875
1007
  logger,
876
1008
  plan,
1009
+ input,
877
1010
  options2,
878
1011
  onFinish
879
1012
  );
@@ -884,7 +1017,9 @@ function createServer(engine, options = {}) {
884
1017
  };
885
1018
  router.post("/claim", async (ctx) => {
886
1019
  logger.info("triggering claim from POST request");
887
- return claim_default(app, logger, options.maxWorkflows).then(() => {
1020
+ return claim_default(app, logger, {
1021
+ maxWorkers: options.maxWorkflows
1022
+ }).then(() => {
888
1023
  logger.info("claim complete: 1 run claimed");
889
1024
  ctx.body = "complete";
890
1025
  ctx.status = 200;