@nanobpm/urban 0.53.0 → 0.55.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.
@@ -231,6 +231,24 @@ test("searchUserTasks forwards a caller-provided lifecycle state filter", async
231
231
  assert.equal(input?.filter?.processInstanceKey, "pi");
232
232
  });
233
233
 
234
+ test("openUserTasks pins state=CREATED onto the underlying search", async () => {
235
+ let input: { filter?: Record<string, unknown> } | undefined;
236
+ const client = fakeSdkClient({
237
+ searchUserTasks: async (i) => {
238
+ input = i;
239
+ return { items: [{ userTaskKey: 9, elementId: "approve" }] };
240
+ },
241
+ });
242
+ const engine = new SdkEngineClient(client);
243
+ const tasks = await engine.openUserTasks({ processInstanceKey: "pi" });
244
+ // openUserTasks is the safe accessor: it derives from searchUserTasks with state pinned to
245
+ // CREATED, so a completed/canceled task can never surface through it. The caller's other
246
+ // selectors pass through unchanged.
247
+ assert.equal(input?.filter?.state, "CREATED", "openUserTasks pins state=CREATED");
248
+ assert.equal(input?.filter?.processInstanceKey, "pi");
249
+ assert.deepEqual(tasks, [{ userTaskKey: "9", elementId: "approve", variables: undefined }]);
250
+ });
251
+
234
252
  test("searchUserTasks surfaces the resolved form linkage", async () => {
235
253
  const client = fakeSdkClient({
236
254
  searchUserTasks: async () => ({
@@ -20,6 +20,7 @@ import type {
20
20
  ProcessInstanceState,
21
21
  UserTaskState,
22
22
  UserTaskSummary,
23
+ UserTaskFilter,
23
24
  WorkerSubscription,
24
25
  } from "../core/host.ts";
25
26
  import { isBpmnError } from "../core/host.ts";
@@ -230,10 +231,7 @@ export class SdkEngineClient implements EngineClient {
230
231
  });
231
232
  }
232
233
 
233
- async searchUserTasks(filter?: {
234
- processInstanceKey?: string;
235
- assignee?: string;
236
- candidateGroup?: string;
234
+ async searchUserTasks(filter?: UserTaskFilter & {
237
235
  state?: UserTaskState;
238
236
  }): Promise<UserTaskSummary[]> {
239
237
  // User tasks are an eventually consistent read; ask for zero-wait consistency so
@@ -261,6 +259,13 @@ export class SdkEngineClient implements EngineClient {
261
259
  });
262
260
  }
263
261
 
262
+ /** The open (answerable) user tasks — `searchUserTasks` pinned to `state: "CREATED"`.
263
+ * The single safe accessor for reconcile/affordance paths (see `EngineClient.openUserTasks`);
264
+ * derives from `searchUserTasks` so the two cannot drift. */
265
+ openUserTasks(filter?: UserTaskFilter): Promise<UserTaskSummary[]> {
266
+ return this.searchUserTasks({ ...filter, state: "CREATED" });
267
+ }
268
+
264
269
  async getForm(input: { formKey?: string; formId?: string }): Promise<FormSchema | null> {
265
270
  // The engine addresses deployed forms by key (`GET /forms/{formKey}`). A user task's
266
271
  // `formKey` is the engine's resolution of its `formId` linkage to the latest deployed
@@ -95,6 +95,7 @@ export type {
95
95
  SqliteDb,
96
96
  UserTaskState,
97
97
  UserTaskSummary,
98
+ UserTaskFilter,
98
99
  WatchHandle,
99
100
  WorkerSubscription,
100
101
  } from "./core/host.ts";