@io-orkes/conductor-javascript 3.0.1 → 3.0.2

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/README.md CHANGED
@@ -77,7 +77,7 @@ await workflow.register();
77
77
 
78
78
  **Step 2: Write a worker**
79
79
 
80
- Workers are TypeScript functions decorated with `@worker` that poll Conductor for tasks and execute them.
80
+ Workers are TypeScript functions decorated with `@worker` that poll Conductor for tasks and execute them. The example below uses the legacy decorator style (standalone function). See [Workers](#workers) for the new TypeScript 5.0+ decorator style (class methods).
81
81
 
82
82
  ```typescript
83
83
  import { worker } from "@io-orkes/conductor-javascript";
@@ -215,30 +215,77 @@ All of these are type-safe, composable, and registered to the server as JSON —
215
215
 
216
216
  ## Workers
217
217
 
218
- Workers are TypeScript functions that execute Conductor tasks. Decorate any function with `@worker` to register it as a worker (auto-discovered by `TaskHandler`) and use it as a workflow task.
218
+ Workers are TypeScript functions that execute Conductor tasks. Decorate functions with `@worker` to register them as workers (auto-discovered by `TaskHandler`) and use them as workflow tasks.
219
+
220
+ The SDK supports **both** decorator styles:
221
+
222
+ ### Option 1: New decorators (TypeScript 5.0+)
223
+
224
+ Use class methods with the new Stage 3 decorators. No `experimentalDecorators` needed — remove it from your `tsconfig.json`.
225
+
226
+ ```typescript
227
+ import { worker, TaskHandler } from "@io-orkes/conductor-javascript";
228
+ import type { Task } from "@io-orkes/conductor-javascript";
229
+
230
+ class Workers {
231
+ @worker({ taskDefName: "greet", concurrency: 5, pollInterval: 100 })
232
+ async greet(task: Task) {
233
+ return {
234
+ status: "COMPLETED" as const,
235
+ outputData: { result: `Hello ${task.inputData?.name ?? "World"}` },
236
+ };
237
+ }
238
+
239
+ @worker({ taskDefName: "process_payment", domain: "payments" })
240
+ async processPayment(task: Task) {
241
+ const result = await paymentGateway.charge(task.inputData.customerId, task.inputData.amount);
242
+ return { status: "COMPLETED" as const, outputData: { transactionId: result.id } };
243
+ }
244
+ }
245
+
246
+ // Class definition triggers decorators — workers are registered
247
+ void new Workers();
248
+
249
+ const handler = new TaskHandler({ client, scanForDecorated: true });
250
+ await handler.startWorkers();
251
+ ```
252
+
253
+ ### Option 2: Legacy decorators (experimentalDecorators)
254
+
255
+ Use standalone functions. Add `"experimentalDecorators": true` to your `tsconfig.json`.
219
256
 
220
257
  ```typescript
221
258
  import { worker, TaskHandler } from "@io-orkes/conductor-javascript";
259
+ import type { Task } from "@io-orkes/conductor-javascript";
222
260
 
223
261
  @worker({ taskDefName: "greet", concurrency: 5, pollInterval: 100 })
224
262
  async function greet(task: Task) {
225
263
  return {
226
- status: "COMPLETED",
227
- outputData: { result: `Hello ${task.inputData.name}` },
264
+ status: "COMPLETED" as const,
265
+ outputData: { result: `Hello ${task.inputData?.name ?? "World"}` },
228
266
  };
229
267
  }
230
268
 
231
269
  @worker({ taskDefName: "process_payment", domain: "payments" })
232
270
  async function processPayment(task: Task) {
233
271
  const result = await paymentGateway.charge(task.inputData.customerId, task.inputData.amount);
234
- return { status: "COMPLETED", outputData: { transactionId: result.id } };
272
+ return { status: "COMPLETED" as const, outputData: { transactionId: result.id } };
235
273
  }
236
274
 
237
- // Auto-discover and start all decorated workers
238
275
  const handler = new TaskHandler({ client, scanForDecorated: true });
239
276
  await handler.startWorkers();
277
+ ```
278
+
279
+ ### tsconfig setup
240
280
 
241
- // Graceful shutdown
281
+ | Decorator style | tsconfig.json |
282
+ |-----------------|---------------|
283
+ | **New** (TypeScript 5.0+) | Omit `experimentalDecorators` — use class methods |
284
+ | **Legacy** | `"experimentalDecorators": true` — use standalone functions |
285
+
286
+ **Graceful shutdown:**
287
+
288
+ ```typescript
242
289
  process.on("SIGTERM", async () => {
243
290
  await handler.stopWorkers();
244
291
  process.exit(0);
package/dist/index.d.mts CHANGED
@@ -6322,7 +6322,16 @@ interface WorkerOptions {
6322
6322
  * }
6323
6323
  * ```
6324
6324
  */
6325
- declare function worker(options: WorkerOptions): (target: unknown, propertyKey?: string, descriptor?: PropertyDescriptor) => PropertyDescriptor | ((this: unknown, ...args: unknown[]) => unknown);
6325
+ /** Minimal context shape for Stage 3 method decorators (TypeScript 5.0+). */
6326
+ interface MethodDecoratorContext {
6327
+ kind: string;
6328
+ name: string | symbol;
6329
+ }
6330
+ type WorkerMethod = (task: Task) => Promise<Omit<TaskResult, "workflowInstanceId" | "taskId">>;
6331
+ declare function worker(options: WorkerOptions): {
6332
+ <T extends WorkerMethod>(value: T, context: MethodDecoratorContext): T | undefined;
6333
+ (target: object, propertyKey?: string, descriptor?: PropertyDescriptor): PropertyDescriptor | WorkerMethod | undefined;
6334
+ };
6326
6335
 
6327
6336
  /**
6328
6337
  * Registered worker metadata stored in the global registry.
@@ -6722,9 +6731,12 @@ interface SchemaFieldOptions {
6722
6731
  * When used with `generateSchemaFromClass()`, produces a JSON Schema draft-07
6723
6732
  * object from the decorated properties.
6724
6733
  *
6725
- * If `emitDecoratorMetadata` is enabled in tsconfig.json, the TypeScript type
6726
- * is automatically inferred for `string`, `number`, `boolean` — no need to
6727
- * specify `type` explicitly for those.
6734
+ * Supports both TypeScript 5.0+ (Stage 3) and legacy (experimentalDecorators)
6735
+ * decorator APIs.
6736
+ *
6737
+ * If `emitDecoratorMetadata` is enabled in tsconfig.json (legacy mode), the
6738
+ * TypeScript type is automatically inferred for `string`, `number`, `boolean` —
6739
+ * no need to specify `type` explicitly for those.
6728
6740
  *
6729
6741
  * @example
6730
6742
  * ```typescript
@@ -6742,7 +6754,10 @@ interface SchemaFieldOptions {
6742
6754
  * const schema = generateSchemaFromClass(OrderInput);
6743
6755
  * ```
6744
6756
  */
6745
- declare function schemaField(options?: SchemaFieldOptions): (target: object, propertyKey: string) => void;
6757
+ declare function schemaField(options?: SchemaFieldOptions): (targetOrValue: object | undefined, propertyKeyOrContext?: string | {
6758
+ kind: string;
6759
+ name: string | symbol;
6760
+ }) => ((initialValue: unknown) => unknown) | undefined;
6746
6761
  /**
6747
6762
  * Generate a JSON Schema (draft-07) from a class decorated with `@schemaField()`.
6748
6763
  *
package/dist/index.d.ts CHANGED
@@ -6322,7 +6322,16 @@ interface WorkerOptions {
6322
6322
  * }
6323
6323
  * ```
6324
6324
  */
6325
- declare function worker(options: WorkerOptions): (target: unknown, propertyKey?: string, descriptor?: PropertyDescriptor) => PropertyDescriptor | ((this: unknown, ...args: unknown[]) => unknown);
6325
+ /** Minimal context shape for Stage 3 method decorators (TypeScript 5.0+). */
6326
+ interface MethodDecoratorContext {
6327
+ kind: string;
6328
+ name: string | symbol;
6329
+ }
6330
+ type WorkerMethod = (task: Task) => Promise<Omit<TaskResult, "workflowInstanceId" | "taskId">>;
6331
+ declare function worker(options: WorkerOptions): {
6332
+ <T extends WorkerMethod>(value: T, context: MethodDecoratorContext): T | undefined;
6333
+ (target: object, propertyKey?: string, descriptor?: PropertyDescriptor): PropertyDescriptor | WorkerMethod | undefined;
6334
+ };
6326
6335
 
6327
6336
  /**
6328
6337
  * Registered worker metadata stored in the global registry.
@@ -6722,9 +6731,12 @@ interface SchemaFieldOptions {
6722
6731
  * When used with `generateSchemaFromClass()`, produces a JSON Schema draft-07
6723
6732
  * object from the decorated properties.
6724
6733
  *
6725
- * If `emitDecoratorMetadata` is enabled in tsconfig.json, the TypeScript type
6726
- * is automatically inferred for `string`, `number`, `boolean` — no need to
6727
- * specify `type` explicitly for those.
6734
+ * Supports both TypeScript 5.0+ (Stage 3) and legacy (experimentalDecorators)
6735
+ * decorator APIs.
6736
+ *
6737
+ * If `emitDecoratorMetadata` is enabled in tsconfig.json (legacy mode), the
6738
+ * TypeScript type is automatically inferred for `string`, `number`, `boolean` —
6739
+ * no need to specify `type` explicitly for those.
6728
6740
  *
6729
6741
  * @example
6730
6742
  * ```typescript
@@ -6742,7 +6754,10 @@ interface SchemaFieldOptions {
6742
6754
  * const schema = generateSchemaFromClass(OrderInput);
6743
6755
  * ```
6744
6756
  */
6745
- declare function schemaField(options?: SchemaFieldOptions): (target: object, propertyKey: string) => void;
6757
+ declare function schemaField(options?: SchemaFieldOptions): (targetOrValue: object | undefined, propertyKeyOrContext?: string | {
6758
+ kind: string;
6759
+ name: string | symbol;
6760
+ }) => ((initialValue: unknown) => unknown) | undefined;
6746
6761
  /**
6747
6762
  * Generate a JSON Schema (draft-07) from a class decorated with `@schemaField()`.
6748
6763
  *
package/dist/index.js CHANGED
@@ -41515,20 +41515,51 @@ var TaskHandler = class _TaskHandler {
41515
41515
 
41516
41516
  // src/sdk/worker/schema/decorators.ts
41517
41517
  var SCHEMA_METADATA_KEY = Symbol("conductor:schemaField");
41518
+ function isNewDecoratorContext(arg) {
41519
+ return typeof arg === "object" && arg !== null && "kind" in arg && typeof arg.kind === "string";
41520
+ }
41521
+ var schemaFieldProcessed = /* @__PURE__ */ new WeakMap();
41522
+ function storeSchemaFieldMetadata(cls, propertyKey, options, designType) {
41523
+ const existing = Reflect.getOwnMetadata(SCHEMA_METADATA_KEY, cls) ?? [];
41524
+ existing.push({
41525
+ ...options,
41526
+ propertyKey,
41527
+ designType
41528
+ });
41529
+ Reflect.defineMetadata(SCHEMA_METADATA_KEY, existing, cls);
41530
+ }
41518
41531
  function schemaField(options = {}) {
41519
- return function(target, propertyKey) {
41520
- const existing = Reflect.getOwnMetadata(SCHEMA_METADATA_KEY, target.constructor) ?? [];
41532
+ return function(targetOrValue, propertyKeyOrContext) {
41533
+ if (isNewDecoratorContext(propertyKeyOrContext)) {
41534
+ const propertyKey2 = String(propertyKeyOrContext.name);
41535
+ return function(initialValue) {
41536
+ const cls = this.constructor;
41537
+ const processed = schemaFieldProcessed.get(cls) ?? /* @__PURE__ */ new Set();
41538
+ if (!processed.has(propertyKey2)) {
41539
+ processed.add(propertyKey2);
41540
+ schemaFieldProcessed.set(cls, processed);
41541
+ let designType2;
41542
+ try {
41543
+ designType2 = Reflect.getMetadata(
41544
+ "design:type",
41545
+ this,
41546
+ propertyKey2
41547
+ );
41548
+ } catch {
41549
+ }
41550
+ storeSchemaFieldMetadata(cls, propertyKey2, options, designType2);
41551
+ }
41552
+ return initialValue;
41553
+ };
41554
+ }
41555
+ const target = targetOrValue;
41556
+ const propertyKey = propertyKeyOrContext;
41521
41557
  let designType;
41522
41558
  try {
41523
41559
  designType = Reflect.getMetadata("design:type", target, propertyKey);
41524
41560
  } catch {
41525
41561
  }
41526
- existing.push({
41527
- ...options,
41528
- propertyKey,
41529
- designType
41530
- });
41531
- Reflect.defineMetadata(SCHEMA_METADATA_KEY, existing, target.constructor);
41562
+ storeSchemaFieldMetadata(target.constructor, propertyKey, options, designType);
41532
41563
  };
41533
41564
  }
41534
41565
  function inferType(designType) {
@@ -41589,9 +41620,20 @@ function generateSchemaFromClass(cls) {
41589
41620
  }
41590
41621
 
41591
41622
  // src/sdk/worker/decorators/worker.ts
41623
+ function isNewDecoratorContext2(arg) {
41624
+ return typeof arg === "object" && arg !== null && "kind" in arg && typeof arg.kind === "string";
41625
+ }
41592
41626
  function worker(options) {
41593
- return function(target, propertyKey, descriptor) {
41594
- const executeFunction = descriptor?.value || target;
41627
+ function decorator(target, propertyKeyOrContext, descriptor) {
41628
+ let executeFunction;
41629
+ let isNewApi = false;
41630
+ if (isNewDecoratorContext2(propertyKeyOrContext)) {
41631
+ executeFunction = target;
41632
+ isNewApi = true;
41633
+ } else {
41634
+ const fn = descriptor?.value ?? target;
41635
+ executeFunction = fn;
41636
+ }
41595
41637
  if (typeof executeFunction !== "function") {
41596
41638
  throw new Error(
41597
41639
  `@worker decorator can only be applied to functions. Received: ${typeof executeFunction}`
@@ -41605,10 +41647,14 @@ function worker(options) {
41605
41647
  let resolvedInputSchema = options.inputSchema;
41606
41648
  let resolvedOutputSchema = options.outputSchema;
41607
41649
  if (options.inputType) {
41608
- resolvedInputSchema = generateSchemaFromClass(options.inputType);
41650
+ resolvedInputSchema = generateSchemaFromClass(
41651
+ options.inputType
41652
+ );
41609
41653
  }
41610
41654
  if (options.outputType) {
41611
- resolvedOutputSchema = generateSchemaFromClass(options.outputType);
41655
+ resolvedOutputSchema = generateSchemaFromClass(
41656
+ options.outputType
41657
+ );
41612
41658
  }
41613
41659
  const registeredWorker = {
41614
41660
  taskDefName: options.taskDefName,
@@ -41635,18 +41681,25 @@ function worker(options) {
41635
41681
  builderArgs.inputParameters ?? {}
41636
41682
  );
41637
41683
  }
41638
- return executeFunction.apply(this, args);
41684
+ return executeFunction.apply(
41685
+ this,
41686
+ args
41687
+ );
41639
41688
  };
41640
41689
  Object.defineProperty(dualModeFunction, "name", {
41641
41690
  value: executeFunction.name,
41642
41691
  configurable: true
41643
41692
  });
41693
+ if (isNewApi) {
41694
+ return dualModeFunction;
41695
+ }
41644
41696
  if (descriptor) {
41645
41697
  descriptor.value = dualModeFunction;
41646
41698
  return descriptor;
41647
41699
  }
41648
41700
  return dualModeFunction;
41649
- };
41701
+ }
41702
+ return decorator;
41650
41703
  }
41651
41704
 
41652
41705
  // src/sdk/worker/metrics/MetricsCollector.ts