@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 +54 -7
- package/dist/index.d.mts +20 -5
- package/dist/index.d.ts +20 -5
- package/dist/index.js +67 -14
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +67 -14
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
*
|
|
6726
|
-
*
|
|
6727
|
-
*
|
|
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): (
|
|
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
|
-
|
|
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
|
-
*
|
|
6726
|
-
*
|
|
6727
|
-
*
|
|
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): (
|
|
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(
|
|
41520
|
-
|
|
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
|
-
|
|
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
|
-
|
|
41594
|
-
|
|
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(
|
|
41650
|
+
resolvedInputSchema = generateSchemaFromClass(
|
|
41651
|
+
options.inputType
|
|
41652
|
+
);
|
|
41609
41653
|
}
|
|
41610
41654
|
if (options.outputType) {
|
|
41611
|
-
resolvedOutputSchema = generateSchemaFromClass(
|
|
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(
|
|
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
|