@nanobpm/urban 0.88.1 → 0.90.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.
@@ -97,6 +97,18 @@ function fakeSdkClient(overrides: Partial<NanoSdkClient> = {}): NanoSdkClient &
97
97
  calls.push("searchIncidents");
98
98
  return { items: [] };
99
99
  },
100
+ async searchVariables() {
101
+ calls.push("searchVariables");
102
+ return { items: [] };
103
+ },
104
+ async searchJobs() {
105
+ calls.push("searchJobs");
106
+ return { items: [] };
107
+ },
108
+ async getProcessDefinitionXml() {
109
+ calls.push("getProcessDefinitionXml");
110
+ return "";
111
+ },
100
112
  async resolveIncident(input) {
101
113
  calls.push("resolveIncident");
102
114
  return { ...input };
@@ -303,6 +315,72 @@ test("searchUserTasks surfaces the resolved form linkage", async () => {
303
315
  ]);
304
316
  });
305
317
 
318
+ test("searchUserTasks normalizes the process-instance key selectors and drops blank ones", async () => {
319
+ // Guards the selector-normalization defect class: a padded selector (`" 42 "`) must reach the
320
+ // engine trimmed (so it matches the normalized keys the adapter surfaces), a blank/whitespace-only
321
+ // selector must be *dropped* (not forwarded as a present filter that silently matches nothing),
322
+ // and unrelated selectors must pass through untouched — mirroring `searchProcessInstances`.
323
+ let input: { filter?: Record<string, unknown> } | undefined;
324
+ const client = fakeSdkClient({
325
+ searchUserTasks: async (i) => {
326
+ input = i;
327
+ return { items: [] };
328
+ },
329
+ });
330
+ const engine = new SdkEngineClient(client);
331
+ await engine.searchUserTasks({
332
+ processInstanceKey: " 42 ", // padded → trimmed to "42"
333
+ parentProcessInstanceKey: " ", // whitespace-only → dropped
334
+ rootProcessInstanceKey: "", // blank → dropped
335
+ assignee: "alice", // unrelated selector passes through unchanged
336
+ });
337
+ const filter = input?.filter ?? {};
338
+ assert.equal(filter.processInstanceKey, "42", "padded key selector is trimmed");
339
+ assert.equal("parentProcessInstanceKey" in filter, false, "whitespace-only parent selector is dropped");
340
+ assert.equal("rootProcessInstanceKey" in filter, false, "blank root selector is dropped");
341
+ assert.equal(filter.assignee, "alice", "unrelated selectors pass through unchanged");
342
+ });
343
+
344
+ test("searchUserTasks surfaces the process-instance linkage keys and drops blank ones", async () => {
345
+ // Guards the linkage-output defect class: the three linkage keys the engine reports on a task
346
+ // (processInstanceKey/parentProcessInstanceKey/rootProcessInstanceKey) must be surfaced on the
347
+ // returned `UserTaskSummary`, normalized through the same presence rule — a padded value trimmed,
348
+ // a blank/whitespace-only value omitted rather than surfaced as an empty string.
349
+ const client = fakeSdkClient({
350
+ searchUserTasks: async () => ({
351
+ items: [
352
+ {
353
+ userTaskKey: 1,
354
+ elementId: "a",
355
+ processInstanceKey: 10,
356
+ parentProcessInstanceKey: 20,
357
+ rootProcessInstanceKey: 30,
358
+ },
359
+ {
360
+ userTaskKey: 2,
361
+ elementId: "b",
362
+ processInstanceKey: " 11 ", // padded → trimmed
363
+ parentProcessInstanceKey: " ", // whitespace-only → omitted
364
+ rootProcessInstanceKey: "", // blank → omitted
365
+ },
366
+ ],
367
+ }),
368
+ });
369
+ const engine = new SdkEngineClient(client);
370
+ const tasks = await engine.searchUserTasks();
371
+ assert.deepEqual(tasks, [
372
+ {
373
+ userTaskKey: "1",
374
+ elementId: "a",
375
+ variables: undefined,
376
+ processInstanceKey: "10",
377
+ parentProcessInstanceKey: "20",
378
+ rootProcessInstanceKey: "30",
379
+ },
380
+ { userTaskKey: "2", elementId: "b", variables: undefined, processInstanceKey: "11" },
381
+ ]);
382
+ });
383
+
306
384
  test("getForm resolves by formKey and parses the serialized schema", async () => {
307
385
  let seen: unknown;
308
386
  const schema = { type: "default", schemaVersion: 18, components: [{ type: "textfield", key: "name" }] };
@@ -474,6 +552,64 @@ test("searchProcessInstances skips keyless and unrecognized-state rows", async (
474
552
  assert.deepEqual(out, [{ processInstanceKey: "10", state: "COMPLETED" }]);
475
553
  });
476
554
 
555
+ test("searchProcessInstances normalizes the parent/root key selectors and drops blank ones", async () => {
556
+ // Guards the request-mapping defect class for the reduced path's parent/root selectors: a padded
557
+ // selector must be trimmed, a blank/whitespace-only selector must be dropped rather than sent as
558
+ // an empty filter that matches nothing — mirroring `searchUserTasks` (No Drift Surfaces).
559
+ let seenInput: { filter?: Record<string, unknown> } | undefined;
560
+ const client = fakeSdkClient({
561
+ searchProcessInstances: async (input) => {
562
+ seenInput = input;
563
+ return { items: [] };
564
+ },
565
+ });
566
+ const engine = new SdkEngineClient(client);
567
+ await engine.searchProcessInstances({
568
+ parentProcessInstanceKey: " 42 ", // padded → trimmed to "42"
569
+ rootProcessInstanceKey: " ", // whitespace-only → dropped
570
+ });
571
+ const filter = seenInput?.filter ?? {};
572
+ assert.equal(filter.parentProcessInstanceKey, "42", "padded parent selector is trimmed");
573
+ assert.equal("rootProcessInstanceKey" in filter, false, "whitespace-only root selector is dropped");
574
+ // A selector-only search carries no key `$in` and no page cap.
575
+ assert.deepEqual(seenInput, { filter: { parentProcessInstanceKey: "42" } });
576
+ });
577
+
578
+ test("searchProcessInstances surfaces the parent/root linkage keys and drops blank ones", async () => {
579
+ // Guards the linkage-output defect class: the parent/root keys the engine reports on an instance
580
+ // must be surfaced on the returned `ProcessInstanceSnapshot`, normalized through the same presence
581
+ // rule — a padded value trimmed, a blank/whitespace-only value omitted rather than an empty string.
582
+ const client = fakeSdkClient({
583
+ searchProcessInstances: async () => ({
584
+ items: [
585
+ {
586
+ processInstanceKey: 10,
587
+ state: "ACTIVE",
588
+ parentProcessInstanceKey: 20,
589
+ rootProcessInstanceKey: 30,
590
+ },
591
+ {
592
+ processInstanceKey: " 11 ", // padded → trimmed
593
+ state: "COMPLETED",
594
+ parentProcessInstanceKey: " ", // whitespace-only → omitted
595
+ rootProcessInstanceKey: "", // blank → omitted
596
+ },
597
+ ],
598
+ }),
599
+ });
600
+ const engine = new SdkEngineClient(client);
601
+ const out = await engine.searchProcessInstances();
602
+ assert.deepEqual(out, [
603
+ {
604
+ processInstanceKey: "10",
605
+ state: "ACTIVE",
606
+ parentProcessInstanceKey: "20",
607
+ rootProcessInstanceKey: "30",
608
+ },
609
+ { processInstanceKey: "11", state: "COMPLETED" },
610
+ ]);
611
+ });
612
+
477
613
  test("normalizeProcessInstanceState maps the terminal set and rejects others", () => {
478
614
  assert.equal(normalizeProcessInstanceState("ACTIVE"), "ACTIVE");
479
615
  assert.equal(normalizeProcessInstanceState("completed"), "COMPLETED");
@@ -24,12 +24,16 @@ import type {
24
24
  IncidentFilter,
25
25
  IncidentState,
26
26
  IncidentSummary,
27
+ JobFilter,
27
28
  JobHandler,
29
+ JobSummary,
28
30
  ProcessInstanceSnapshot,
29
31
  ProcessInstanceState,
30
32
  UserTaskState,
31
33
  UserTaskSummary,
32
34
  UserTaskFilter,
35
+ VariableFilter,
36
+ VariableSummary,
33
37
  WorkerSubscription,
34
38
  } from "../core/host.ts";
35
39
  import { assertDeployedWaitStateType, isBpmnError } from "../core/host.ts";
@@ -360,6 +364,99 @@ export function mapIncidentRow(
360
364
  };
361
365
  }
362
366
 
367
+ /** Map one engine variable row onto a {@link VariableSummary}, or `undefined` when the row is
368
+ * malformed (missing the `variableKey`, owning `processInstanceKey`, or `name` — the identity a
369
+ * caller needs). `value` is the engine's serialized JSON value (a string); a non-string value is
370
+ * JSON-encoded so the field is always a string a caller can `JSON.parse`. `scopeKey` falls back to
371
+ * the process-instance key for a process-level variable that omits it. `isTruncated` is the
372
+ * engine's large-value-clipped flag, defaulting to `false`. The single source of truth
373
+ * `searchVariables` extracts through. */
374
+ export function mapVariableRow(
375
+ row: Record<string, unknown>,
376
+ log: Log,
377
+ ): VariableSummary | undefined {
378
+ const variableKey = presentEngineKey(row.variableKey);
379
+ if (variableKey === undefined) {
380
+ log("warn", "skipping variable with no variableKey in engine response");
381
+ return undefined;
382
+ }
383
+ const processInstanceKey = presentEngineKey(row.processInstanceKey);
384
+ if (processInstanceKey === undefined) {
385
+ log("warn", "skipping variable with no processInstanceKey in engine response", {
386
+ variableKey,
387
+ });
388
+ return undefined;
389
+ }
390
+ const name = presentText(row.name);
391
+ if (name === undefined) {
392
+ log("warn", "skipping variable with no name in engine response", { variableKey });
393
+ return undefined;
394
+ }
395
+ // A process-level variable is scoped to the process instance itself; the engine may omit
396
+ // `scopeKey` for it, so fall back to the process-instance key rather than dropping the row.
397
+ const scopeKey = presentEngineKey(row.scopeKey) ?? processInstanceKey;
398
+ // The engine serializes `value` as a JSON string. Keep a string as-is; encode any other type
399
+ // (an object/array/number a permissive engine might inline) so the field is always a string the
400
+ // caller can `JSON.parse`.
401
+ const value = typeof row.value === "string" ? row.value : JSON.stringify(row.value ?? null);
402
+ return {
403
+ variableKey,
404
+ name,
405
+ value,
406
+ scopeKey,
407
+ processInstanceKey,
408
+ isTruncated: row.isTruncated === true,
409
+ };
410
+ }
411
+
412
+ /** Map one engine job row onto a {@link JobSummary}, or `undefined` when the row is malformed
413
+ * (missing the `jobKey`, `type`, or owning `processInstanceKey`). `worker`/`retries`/`elementId`/
414
+ * `deadline` are best-effort diagnostics: present when the engine reports them, omitted otherwise
415
+ * — an unset `worker` is the "queued, not leased" signal, so it must be absent rather than `""`.
416
+ * `state` is passed through as a bare string (the engine's job-state enum is broad). The single
417
+ * source of truth `searchJobs` extracts through. */
418
+ export function mapJobRow(
419
+ row: Record<string, unknown>,
420
+ log: Log,
421
+ ): JobSummary | undefined {
422
+ const jobKey = presentEngineKey(row.jobKey);
423
+ if (jobKey === undefined) {
424
+ log("warn", "skipping job with no jobKey in engine response");
425
+ return undefined;
426
+ }
427
+ const type = presentText(row.type);
428
+ if (type === undefined) {
429
+ log("warn", "skipping job with no type in engine response", { jobKey });
430
+ return undefined;
431
+ }
432
+ const processInstanceKey = presentEngineKey(row.processInstanceKey);
433
+ if (processInstanceKey === undefined) {
434
+ log("warn", "skipping job with no processInstanceKey in engine response", { jobKey });
435
+ return undefined;
436
+ }
437
+ const state = presentText(row.state);
438
+ if (state === undefined) {
439
+ log("warn", "skipping job with no state in engine response", { jobKey });
440
+ return undefined;
441
+ }
442
+ const worker = presentText(row.worker);
443
+ const retries = typeof row.retries === "number" && Number.isFinite(row.retries)
444
+ ? row.retries
445
+ : undefined;
446
+ const elementId = presentText(row.elementId);
447
+ const deadline = presentText(row.deadline);
448
+ return {
449
+ jobKey,
450
+ type,
451
+ state,
452
+ processInstanceKey,
453
+ ...(worker ? { worker } : {}),
454
+ ...(retries !== undefined ? { retries } : {}),
455
+ ...(elementId ? { elementId } : {}),
456
+ ...(deadline ? { deadline } : {}),
457
+ };
458
+ }
459
+
363
460
  /** A job as delivered to a nano-sdk job handler: the frame fields plus the
364
461
  * acknowledgement actions the handler must call. */
365
462
  export interface NanoSdkActivatedJob {
@@ -463,6 +560,21 @@ export interface NanoSdkClient {
463
560
  consistency?: unknown,
464
561
  options?: unknown,
465
562
  ): Promise<Record<string, unknown>>;
563
+ searchVariables(
564
+ input: { filter?: Record<string, unknown>; page?: Record<string, unknown> },
565
+ consistency?: unknown,
566
+ options?: unknown,
567
+ ): Promise<Record<string, unknown>>;
568
+ searchJobs(
569
+ input: { filter?: Record<string, unknown>; page?: Record<string, unknown> },
570
+ consistency?: unknown,
571
+ options?: unknown,
572
+ ): Promise<Record<string, unknown>>;
573
+ getProcessDefinitionXml(
574
+ input: { processDefinitionKey: string },
575
+ consistency?: unknown,
576
+ options?: unknown,
577
+ ): Promise<unknown>;
466
578
  resolveIncident(
467
579
  input: { incidentKey: string },
468
580
  options?: unknown,
@@ -565,8 +677,19 @@ export class SdkEngineClient implements EngineClient {
565
677
  }): Promise<UserTaskSummary[]> {
566
678
  // User tasks are an eventually consistent read; ask for zero-wait consistency so
567
679
  // the search reflects what is currently visible without blocking.
680
+ // Normalize the process-instance key selectors through the shared presence rule so a
681
+ // blank/whitespace-only selector is *dropped* rather than forwarded as a present filter that
682
+ // silently matches nothing, and a padded key (`" 123 "`) matches the normalized keys we
683
+ // surface — mirroring `WasmEngineClient` (which normalizes via `presentKey`) and
684
+ // `searchProcessInstances` below (No Drift Surfaces).
685
+ const f: Record<string, unknown> = { ...(filter ?? {}) };
686
+ for (const sel of ["processInstanceKey", "parentProcessInstanceKey", "rootProcessInstanceKey"] as const) {
687
+ const normalized = presentEngineKey(filter?.[sel]);
688
+ if (normalized) f[sel] = normalized;
689
+ else delete f[sel];
690
+ }
568
691
  const body = await this.client.searchUserTasks(
569
- { filter: { ...(filter ?? {}) } },
692
+ { filter: f },
570
693
  { consistency: { waitUpToMs: 0 } },
571
694
  );
572
695
  const items = Array.isArray(body.items) ? body.items.filter(isRecord) : [];
@@ -579,10 +702,16 @@ export class SdkEngineClient implements EngineClient {
579
702
  // The engine resolves a `formId="X"` linkage to the latest deployed form's key at
580
703
  // task creation, so `formKey` (not a form id) is the linkage it reports on the task;
581
704
  // no `resolveFormKeyByFormId` resolver is passed because the gateway already resolved it.
705
+ const processInstanceKey = presentEngineKey(it.processInstanceKey);
706
+ const parentProcessInstanceKey = presentEngineKey(it.parentProcessInstanceKey);
707
+ const rootProcessInstanceKey = presentEngineKey(it.rootProcessInstanceKey);
582
708
  return [{
583
709
  userTaskKey: String(userTaskKey),
584
710
  elementId: typeof it.elementId === "string" ? it.elementId : undefined,
585
711
  variables: isRecord(it.variables) ? it.variables : undefined,
712
+ ...(processInstanceKey ? { processInstanceKey } : {}),
713
+ ...(parentProcessInstanceKey ? { parentProcessInstanceKey } : {}),
714
+ ...(rootProcessInstanceKey ? { rootProcessInstanceKey } : {}),
586
715
  ...pickFormLinkage(it),
587
716
  }];
588
717
  });
@@ -651,11 +780,26 @@ export class SdkEngineClient implements EngineClient {
651
780
  async searchProcessInstances(filter?: {
652
781
  processInstanceKeys?: string[];
653
782
  state?: ProcessInstanceState;
783
+ parentProcessInstanceKey?: string;
784
+ rootProcessInstanceKey?: string;
654
785
  }): Promise<ProcessInstanceSnapshot[]> {
655
786
  const f: Record<string, unknown> = {};
656
787
  if (filter?.state) f.state = filter.state;
657
- const keys = filter?.processInstanceKeys?.filter((k) => k != null && k !== "");
788
+ // Normalize each requested key through the shared presence rule (drop blank/whitespace-only
789
+ // entries, trim padded ones like `" 123 "`) so the `$in` filter carries only present keys that
790
+ // match the normalized keys we surface — mirroring `WasmEngineClient` and the selector
791
+ // handling above (No Drift Surfaces).
792
+ const keys = filter?.processInstanceKeys
793
+ ?.map((k) => presentEngineKey(k))
794
+ .filter((k): k is string => k !== undefined);
658
795
  if (keys && keys.length > 0) f.processInstanceKey = { $in: keys };
796
+ // Parent/root selectors let the reduced path query a subject's native descendants
797
+ // server-side. Normalize each through the shared presence rule so a blank selector is
798
+ // dropped rather than sent as an empty filter that would match nothing.
799
+ const parentProcessInstanceKey = presentEngineKey(filter?.parentProcessInstanceKey);
800
+ if (parentProcessInstanceKey) f.parentProcessInstanceKey = parentProcessInstanceKey;
801
+ const rootProcessInstanceKey = presentEngineKey(filter?.rootProcessInstanceKey);
802
+ if (rootProcessInstanceKey) f.rootProcessInstanceKey = rootProcessInstanceKey;
659
803
  // A process-instance search is an eventually consistent read; ask for zero-wait
660
804
  // consistency so it reflects what is currently visible without blocking. Cap the page
661
805
  // to the number of keys asked for (each key matches at most one instance), so a bounded
@@ -667,20 +811,33 @@ export class SdkEngineClient implements EngineClient {
667
811
  );
668
812
  const items = Array.isArray(body.items) ? body.items.filter(isRecord) : [];
669
813
  return items.flatMap((it) => {
670
- const key = it.processInstanceKey;
671
- if (key == null || key === "") {
814
+ // Normalize the surfaced primary key through the shared presence rule (trim padded,
815
+ // drop blank/whitespace-only) so it matches the normalized parent/root linkage keys
816
+ // and the `searchUserTasks` mapping — the surfaced process-instance key must not drift
817
+ // between the two reduced-path searches (No Drift Surfaces).
818
+ const processInstanceKey = presentEngineKey(it.processInstanceKey);
819
+ if (!processInstanceKey) {
672
820
  this.log("warn", "skipping process instance with no key in engine response");
673
821
  return [];
674
822
  }
675
823
  const state = normalizeProcessInstanceState(it.state);
676
824
  if (!state) {
677
825
  this.log("warn", "skipping process instance with unrecognized state", {
678
- processInstanceKey: String(key),
826
+ processInstanceKey,
679
827
  state: String(it.state),
680
828
  });
681
829
  return [];
682
830
  }
683
- return [{ processInstanceKey: String(key), state }];
831
+ const processDefinitionKey = presentEngineKey(it.processDefinitionKey);
832
+ const parentProcessInstanceKey = presentEngineKey(it.parentProcessInstanceKey);
833
+ const rootProcessInstanceKey = presentEngineKey(it.rootProcessInstanceKey);
834
+ return [{
835
+ processInstanceKey,
836
+ state,
837
+ ...(processDefinitionKey ? { processDefinitionKey } : {}),
838
+ ...(parentProcessInstanceKey ? { parentProcessInstanceKey } : {}),
839
+ ...(rootProcessInstanceKey ? { rootProcessInstanceKey } : {}),
840
+ }];
684
841
  });
685
842
  }
686
843
 
@@ -784,6 +941,82 @@ export class SdkEngineClient implements EngineClient {
784
941
  });
785
942
  }
786
943
 
944
+ async searchVariables(filter?: VariableFilter): Promise<VariableSummary[]> {
945
+ // Same shape as `searchIncidents`: build the engine filter from the transport-agnostic
946
+ // selectors, read at zero-wait consistency (a variable search is eventually consistent), and
947
+ // map each row through the single `mapVariableRow` gate, dropping malformed rows.
948
+ const f: Record<string, unknown> = {};
949
+ const processInstanceKey = presentEngineKey(filter?.processInstanceKey);
950
+ if (processInstanceKey) f.processInstanceKey = processInstanceKey;
951
+ const scopeKey = presentEngineKey(filter?.scopeKey);
952
+ if (scopeKey) f.scopeKey = scopeKey;
953
+ const name = filter?.name?.trim();
954
+ if (name) f.name = name;
955
+ const body = await this.client.searchVariables(
956
+ { filter: f },
957
+ { consistency: { waitUpToMs: 0 } },
958
+ );
959
+ const items = Array.isArray(body.items) ? body.items.filter(isRecord) : [];
960
+ return items.flatMap((it) => {
961
+ const mapped = mapVariableRow(it, this.log);
962
+ return mapped ? [mapped] : [];
963
+ });
964
+ }
965
+
966
+ async searchJobs(filter?: JobFilter): Promise<JobSummary[]> {
967
+ // Same shape as `searchIncidents`: build the engine filter from the transport-agnostic
968
+ // selectors, read at zero-wait consistency (a job search is eventually consistent), and map
969
+ // each row through the single `mapJobRow` gate, dropping malformed rows.
970
+ const f: Record<string, unknown> = {};
971
+ const processInstanceKey = presentEngineKey(filter?.processInstanceKey);
972
+ if (processInstanceKey) f.processInstanceKey = processInstanceKey;
973
+ const state = filter?.state?.trim();
974
+ if (state) f.state = state;
975
+ const type = filter?.type?.trim();
976
+ if (type) f.type = type;
977
+ const elementId = filter?.elementId?.trim();
978
+ if (elementId) f.elementId = elementId;
979
+ const worker = filter?.worker?.trim();
980
+ if (worker) f.worker = worker;
981
+ const body = await this.client.searchJobs(
982
+ { filter: f },
983
+ { consistency: { waitUpToMs: 0 } },
984
+ );
985
+ const items = Array.isArray(body.items) ? body.items.filter(isRecord) : [];
986
+ return items.flatMap((it) => {
987
+ const mapped = mapJobRow(it, this.log);
988
+ return mapped ? [mapped] : [];
989
+ });
990
+ }
991
+
992
+ async getProcessDefinitionXml(
993
+ processDefinitionKey: string,
994
+ ): Promise<string | null> {
995
+ // A blank key can never address a definition — short-circuit to null rather than issue a
996
+ // `GET /v2/process-definitions//xml` with an empty segment. Normalize a padded-but-valid key so
997
+ // `" 5 "` addresses the same definition, mirroring `getElementInstance`.
998
+ const key = presentEngineKey(processDefinitionKey);
999
+ if (key === undefined) return null;
1000
+ let xml: unknown;
1001
+ try {
1002
+ xml = await this.client.getProcessDefinitionXml(
1003
+ { processDefinitionKey: key },
1004
+ { consistency: { waitUpToMs: 0 } },
1005
+ );
1006
+ } catch (err) {
1007
+ // A 404 (no such definition) is an expected "not found", not a fault — mirror `getForm`/
1008
+ // `getElementInstance`, which treat a failed fetch as absence (null) rather than propagating.
1009
+ this.log("warn", "getProcessDefinitionXml: engine fetch failed", {
1010
+ processDefinitionKey: key,
1011
+ err: err instanceof Error ? err.message : String(err),
1012
+ });
1013
+ return null;
1014
+ }
1015
+ // The endpoint returns the raw BPMN XML as a string (204 → empty). Treat a blank/absent body
1016
+ // as "no XML" (null) so a caller distinguishes "have it" from "don't".
1017
+ return typeof xml === "string" && xml.trim() !== "" ? xml : null;
1018
+ }
1019
+
787
1020
  async resolveIncident(input: { incidentKey: string }): Promise<void> {
788
1021
  await this.client.resolveIncident({
789
1022
  incidentKey: requireEngineKey(input.incidentKey, "incidentKey"),
@@ -100,13 +100,17 @@ export type {
100
100
  EngineIncidentState,
101
101
  IncidentFilter,
102
102
  IncidentSummary,
103
+ JobFilter,
103
104
  JobHandler,
105
+ JobSummary,
104
106
  ProcessInstanceSnapshot,
105
107
  ProcessInstanceState,
106
108
  SqliteDb,
107
109
  UserTaskState,
108
110
  UserTaskSummary,
109
111
  UserTaskFilter,
112
+ VariableFilter,
113
+ VariableSummary,
110
114
  WatchHandle,
111
115
  WorkerSubscription,
112
116
  } from "./core/host.ts";