@temporalio/client 1.4.3 → 1.5.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.
Files changed (57) hide show
  1. package/lib/async-completion-client.d.ts +5 -32
  2. package/lib/async-completion-client.js +6 -20
  3. package/lib/async-completion-client.js.map +1 -1
  4. package/lib/base-client.d.ts +53 -0
  5. package/lib/base-client.js +45 -0
  6. package/lib/base-client.js.map +1 -0
  7. package/lib/client.d.ts +12 -52
  8. package/lib/client.js +30 -49
  9. package/lib/client.js.map +1 -1
  10. package/lib/connection.d.ts +9 -9
  11. package/lib/connection.js +4 -3
  12. package/lib/connection.js.map +1 -1
  13. package/lib/errors.d.ts +0 -1
  14. package/lib/errors.js +1 -3
  15. package/lib/errors.js.map +1 -1
  16. package/lib/helpers.d.ts +3 -0
  17. package/lib/helpers.js +63 -0
  18. package/lib/helpers.js.map +1 -0
  19. package/lib/index.d.ts +2 -0
  20. package/lib/index.js +2 -0
  21. package/lib/index.js.map +1 -1
  22. package/lib/interceptors.d.ts +46 -10
  23. package/lib/iterators-utils.d.ts +31 -0
  24. package/lib/iterators-utils.js +80 -0
  25. package/lib/iterators-utils.js.map +1 -0
  26. package/lib/schedule-client.d.ts +175 -0
  27. package/lib/schedule-client.js +383 -0
  28. package/lib/schedule-client.js.map +1 -0
  29. package/lib/schedule-helpers.d.ts +20 -0
  30. package/lib/schedule-helpers.js +290 -0
  31. package/lib/schedule-helpers.js.map +1 -0
  32. package/lib/schedule-types.d.ts +691 -0
  33. package/lib/schedule-types.js +74 -0
  34. package/lib/schedule-types.js.map +1 -0
  35. package/lib/types.d.ts +8 -3
  36. package/lib/types.js.map +1 -1
  37. package/lib/workflow-client.d.ts +76 -59
  38. package/lib/workflow-client.js +87 -101
  39. package/lib/workflow-client.js.map +1 -1
  40. package/lib/workflow-options.d.ts +5 -1
  41. package/lib/workflow-options.js.map +1 -1
  42. package/package.json +7 -5
  43. package/src/async-completion-client.ts +16 -55
  44. package/src/base-client.ts +84 -0
  45. package/src/client.ts +41 -93
  46. package/src/connection.ts +12 -11
  47. package/src/errors.ts +0 -1
  48. package/src/helpers.ts +75 -0
  49. package/src/index.ts +2 -0
  50. package/src/interceptors.ts +54 -10
  51. package/src/iterators-utils.ts +116 -0
  52. package/src/schedule-client.ts +541 -0
  53. package/src/schedule-helpers.ts +414 -0
  54. package/src/schedule-types.ts +866 -0
  55. package/src/types.ts +12 -3
  56. package/src/workflow-client.ts +178 -180
  57. package/src/workflow-options.ts +12 -1
package/src/types.ts CHANGED
@@ -1,6 +1,7 @@
1
+ import type * as grpc from '@grpc/grpc-js';
1
2
  import type { SearchAttributes } from '@temporalio/common';
2
3
  import * as proto from '@temporalio/proto';
3
- import type * as grpc from '@grpc/grpc-js';
4
+ import { Replace } from '@temporalio/common/lib/type-helpers';
4
5
 
5
6
  export interface WorkflowExecution {
6
7
  workflowId: string;
@@ -11,6 +12,7 @@ export type GetWorkflowExecutionHistoryRequest =
11
12
  proto.temporal.api.workflowservice.v1.IGetWorkflowExecutionHistoryRequest;
12
13
  export type DescribeWorkflowExecutionResponse =
13
14
  proto.temporal.api.workflowservice.v1.IDescribeWorkflowExecutionResponse;
15
+ export type RawWorkflowExecutionInfo = proto.temporal.api.workflow.v1.IWorkflowExecutionInfo;
14
16
  export type TerminateWorkflowExecutionResponse =
15
17
  proto.temporal.api.workflowservice.v1.ITerminateWorkflowExecutionResponse;
16
18
  export type RequestCancelWorkflowExecutionResponse =
@@ -27,7 +29,7 @@ export type WorkflowExecutionStatusName =
27
29
  | 'TIMED_OUT'
28
30
  | 'UNKNOWN'; // UNKNOWN is reserved for future enum values
29
31
 
30
- export interface WorkflowExecutionDescription {
32
+ export interface WorkflowExecutionInfo {
31
33
  type: string;
32
34
  workflowId: string;
33
35
  runId: string;
@@ -40,9 +42,16 @@ export interface WorkflowExecutionDescription {
40
42
  memo?: Record<string, unknown>;
41
43
  searchAttributes: SearchAttributes;
42
44
  parentExecution?: Required<proto.temporal.api.common.v1.IWorkflowExecution>;
43
- raw: DescribeWorkflowExecutionResponse;
45
+ raw: RawWorkflowExecutionInfo;
44
46
  }
45
47
 
48
+ export type WorkflowExecutionDescription = Replace<
49
+ WorkflowExecutionInfo,
50
+ {
51
+ raw: DescribeWorkflowExecutionResponse;
52
+ }
53
+ >;
54
+
46
55
  export type WorkflowService = proto.temporal.api.workflowservice.v1.WorkflowService;
47
56
  export const { WorkflowService } = proto.temporal.api.workflowservice.v1;
48
57
  export type OperatorService = proto.temporal.api.operatorservice.v1.OperatorService;
@@ -1,55 +1,39 @@
1
1
  import { status as grpcStatus } from '@grpc/grpc-js';
2
+ import { v4 as uuid4 } from 'uuid';
2
3
  import {
4
+ BaseWorkflowHandle,
3
5
  CancelledFailure,
4
- DataConverter,
5
- LoadedDataConverter,
6
- mapFromPayloads,
6
+ compileRetryPolicy,
7
7
  mapToPayloads,
8
+ HistoryAndWorkflowId,
9
+ QueryDefinition,
8
10
  RetryState,
9
11
  searchAttributePayloadConverter,
12
+ SignalDefinition,
10
13
  TerminatedFailure,
11
14
  TimeoutFailure,
12
15
  TimeoutType,
16
+ WithWorkflowArgs,
17
+ Workflow,
18
+ WorkflowExecutionAlreadyStartedError,
19
+ WorkflowNotFoundError,
20
+ WorkflowResultType,
13
21
  } from '@temporalio/common';
22
+ import { composeInterceptors } from '@temporalio/common/lib/interceptors';
23
+ import { History } from '@temporalio/common/lib/proto-utils';
14
24
  import {
15
25
  decodeArrayFromPayloads,
16
26
  decodeFromPayloadsAtIndex,
17
- decodeMapFromPayloads,
18
27
  decodeOptionalFailureToOptionalError,
19
28
  encodeMapToPayloads,
20
29
  encodeToPayloads,
21
30
  filterNullAndUndefined,
22
- isLoadedDataConverter,
23
- loadDataConverter,
24
31
  } from '@temporalio/common/lib/internal-non-workflow';
25
- import {
26
- BaseWorkflowHandle,
27
- compileRetryPolicy,
28
- QueryDefinition,
29
- SearchAttributes,
30
- SignalDefinition,
31
- WithWorkflowArgs,
32
- Workflow,
33
- WorkflowNotFoundError,
34
- WorkflowResultType,
35
- } from '@temporalio/common';
36
- import { optionalTsToDate, tsToDate } from '@temporalio/common/lib/time';
37
- import { composeInterceptors } from '@temporalio/common/lib/interceptors';
38
- import { Replace } from '@temporalio/common/lib/type-helpers';
39
32
  import { temporal } from '@temporalio/proto';
40
- import os from 'os';
41
- import { v4 as uuid4 } from 'uuid';
42
- import { Connection } from './connection';
43
- import {
44
- isServerErrorResponse,
45
- ServiceError,
46
- WorkflowContinuedAsNewError,
47
- WorkflowExecutionAlreadyStartedError,
48
- WorkflowFailedError,
49
- } from './errors';
33
+ import { isServerErrorResponse, ServiceError, WorkflowContinuedAsNewError, WorkflowFailedError } from './errors';
50
34
  import {
51
35
  WorkflowCancelInput,
52
- WorkflowClientCallsInterceptor,
36
+ WorkflowClientInterceptor,
53
37
  WorkflowClientInterceptors,
54
38
  WorkflowDescribeInput,
55
39
  WorkflowQueryInput,
@@ -59,19 +43,31 @@ import {
59
43
  WorkflowTerminateInput,
60
44
  } from './interceptors';
61
45
  import {
62
- ConnectionLike,
63
46
  DescribeWorkflowExecutionResponse,
64
47
  GetWorkflowExecutionHistoryRequest,
65
- Metadata,
66
48
  RequestCancelWorkflowExecutionResponse,
67
49
  StartWorkflowExecutionRequest,
68
50
  TerminateWorkflowExecutionResponse,
69
51
  WorkflowExecution,
70
52
  WorkflowExecutionDescription,
71
- WorkflowExecutionStatusName,
53
+ WorkflowExecutionInfo,
72
54
  WorkflowService,
73
55
  } from './types';
74
- import { compileWorkflowOptions, WorkflowOptions, WorkflowSignalWithStartOptions } from './workflow-options';
56
+ import {
57
+ compileWorkflowOptions,
58
+ WorkflowOptions,
59
+ WorkflowSignalWithStartOptions,
60
+ WorkflowStartOptions,
61
+ } from './workflow-options';
62
+ import { executionInfoFromRaw } from './helpers';
63
+ import {
64
+ BaseClient,
65
+ BaseClientOptions,
66
+ defaultBaseClientOptions,
67
+ LoadedWithDefaults,
68
+ WithDefaults,
69
+ } from './base-client';
70
+ import { mapAsyncIterable } from './iterators-utils';
75
71
 
76
72
  /**
77
73
  * A client side handle to a single Workflow instance.
@@ -138,6 +134,11 @@ export interface WorkflowHandle<T extends Workflow = Workflow> extends BaseWorkf
138
134
  */
139
135
  describe(): Promise<WorkflowExecutionDescription>;
140
136
 
137
+ /**
138
+ * Return a workflow execution's history
139
+ */
140
+ fetchHistory(): Promise<History>;
141
+
141
142
  /**
142
143
  * Readonly accessor to the underlying WorkflowClient
143
144
  */
@@ -169,41 +170,14 @@ export interface WorkflowHandleWithSignaledRunId<T extends Workflow = Workflow>
169
170
  readonly signaledRunId: string;
170
171
  }
171
172
 
172
- export interface WorkflowClientOptions {
173
- /**
174
- * {@link DataConverter} or {@link LoadedDataConverter} to use for serializing and deserializing payloads
175
- */
176
- dataConverter?: DataConverter | LoadedDataConverter;
177
-
173
+ export interface WorkflowClientOptions extends BaseClientOptions {
178
174
  /**
179
175
  * Used to override and extend default Connection functionality
180
176
  *
181
177
  * Useful for injecting auth headers and tracing Workflow executions
182
178
  */
183
- interceptors?: WorkflowClientInterceptors;
184
-
185
- /**
186
- * Identity to report to the server
187
- *
188
- * @default `${process.pid}@${os.hostname()}`
189
- */
190
- identity?: string;
191
-
192
- /**
193
- * Connection to use to communicate with the server.
194
- *
195
- * By default `WorkflowClient` connects to localhost.
196
- *
197
- * Connections are expensive to construct and should be reused.
198
- */
199
- connection?: ConnectionLike;
200
-
201
- /**
202
- * Server namespace
203
- *
204
- * @default default
205
- */
206
- namespace?: string;
179
+ // eslint-disable-next-line deprecation/deprecation
180
+ interceptors?: WorkflowClientInterceptors | WorkflowClientInterceptor[];
207
181
 
208
182
  /**
209
183
  * Should a query be rejected by closed and failed workflows
@@ -213,23 +187,12 @@ export interface WorkflowClientOptions {
213
187
  queryRejectCondition?: temporal.api.enums.v1.QueryRejectCondition;
214
188
  }
215
189
 
216
- export type WorkflowClientOptionsWithDefaults = Replace<
217
- Required<WorkflowClientOptions>,
218
- {
219
- connection?: ConnectionLike;
220
- }
221
- >;
222
- export type LoadedWorkflowClientOptions = WorkflowClientOptionsWithDefaults & {
223
- loadedDataConverter: LoadedDataConverter;
224
- };
190
+ export type LoadedWorkflowClientOptions = LoadedWithDefaults<WorkflowClientOptions>;
225
191
 
226
- export function defaultWorkflowClientOptions(): WorkflowClientOptionsWithDefaults {
192
+ function defaultWorkflowClientOptions(): WithDefaults<WorkflowClientOptions> {
227
193
  return {
228
- dataConverter: {},
229
- // The equivalent in Java is ManagementFactory.getRuntimeMXBean().getName()
230
- identity: `${process.pid}@${os.hostname()}`,
231
- interceptors: {},
232
- namespace: 'default',
194
+ ...defaultBaseClientOptions(),
195
+ interceptors: [],
233
196
  queryRejectCondition: temporal.api.enums.v1.QueryRejectCondition.QUERY_REJECT_CONDITION_UNSPECIFIED,
234
197
  };
235
198
  }
@@ -279,7 +242,7 @@ export interface GetWorkflowHandleOptions extends WorkflowResultOptions {
279
242
  interface WorkflowHandleOptions extends GetWorkflowHandleOptions {
280
243
  workflowId: string;
281
244
  runId?: string;
282
- interceptors: WorkflowClientCallsInterceptor[];
245
+ interceptors: WorkflowClientInterceptor[];
283
246
  /**
284
247
  * A runId to use for getting the workflow's result.
285
248
  *
@@ -291,9 +254,58 @@ interface WorkflowHandleOptions extends GetWorkflowHandleOptions {
291
254
  }
292
255
 
293
256
  /**
294
- * Options for starting a Workflow
257
+ * An iterable list of WorkflowExecution, as returned by {@link WorkflowClient.list}.
258
+ */
259
+ interface AsyncWorkflowListIterable extends AsyncIterable<WorkflowExecutionInfo> {
260
+ /**
261
+ * Return an iterable of histories corresponding to this iterable's WorkflowExecutions.
262
+ * Workflow histories will be fetched concurrently.
263
+ *
264
+ * Useful in batch replaying
265
+ */
266
+ intoHistories: (intoHistoriesOptions?: IntoHistoriesOptions) => AsyncIterable<HistoryAndWorkflowId>;
267
+ }
268
+
269
+ /**
270
+ * Options for {@link WorkflowClient.list}
271
+ */
272
+ export interface ListOptions {
273
+ /**
274
+ * Maximum number of results to fetch per page.
275
+ *
276
+ * @default depends on server config, typically 1000
277
+ */
278
+ pageSize?: number;
279
+ /**
280
+ * Query string for matching and ordering the results
281
+ */
282
+ query?: string;
283
+ }
284
+
285
+ /**
286
+ * Options for {@link WorkflowClient.list().intoHistories()}
295
287
  */
296
- export type WorkflowStartOptions<T extends Workflow = Workflow> = WithWorkflowArgs<T, WorkflowOptions>;
288
+ export interface IntoHistoriesOptions {
289
+ /**
290
+ * Maximum number of workflow histories to download concurrently.
291
+ *
292
+ * @default 5
293
+ */
294
+ concurrency?: number;
295
+
296
+ /**
297
+ * Maximum number of workflow histories to buffer ahead, ready for consumption.
298
+ *
299
+ * It is recommended to set `bufferLimit` to a rasonnably low number if it is expected that the
300
+ * iterable may be stopped before reaching completion (for example, when implementing a fail fast
301
+ * bach replay test).
302
+ *
303
+ * Ignored unless `concurrency > 1`. No limit applies if set to `undefined`.
304
+ *
305
+ * @default unlimited
306
+ */
307
+ bufferLimit?: number;
308
+ }
297
309
 
298
310
  /**
299
311
  * Client for starting Workflow executions and creating Workflow handles.
@@ -301,18 +313,15 @@ export type WorkflowStartOptions<T extends Workflow = Workflow> = WithWorkflowAr
301
313
  * Typically this client should not be instantiated directly, instead create the high level {@link Client} and use
302
314
  * {@link Client.workflow} to interact with Workflows.
303
315
  */
304
- export class WorkflowClient {
316
+ export class WorkflowClient extends BaseClient {
305
317
  public readonly options: LoadedWorkflowClientOptions;
306
- public readonly connection: ConnectionLike;
307
318
 
308
319
  constructor(options?: WorkflowClientOptions) {
309
- this.connection = options?.connection ?? Connection.lazy();
310
- const dataConverter = options?.dataConverter;
311
- const loadedDataConverter = isLoadedDataConverter(dataConverter) ? dataConverter : loadDataConverter(dataConverter);
320
+ super(options);
312
321
  this.options = {
313
322
  ...defaultWorkflowClientOptions(),
314
323
  ...filterNullAndUndefined(options ?? {}),
315
- loadedDataConverter,
324
+ loadedDataConverter: this.dataConverter,
316
325
  };
317
326
  }
318
327
 
@@ -326,28 +335,6 @@ export class WorkflowClient {
326
335
  return this.connection.workflowService;
327
336
  }
328
337
 
329
- protected get dataConverter(): LoadedDataConverter {
330
- return this.options.loadedDataConverter;
331
- }
332
-
333
- /**
334
- * Set the deadline for any service requests executed in `fn`'s scope.
335
- */
336
- async withDeadline<R>(deadline: number | Date, fn: () => Promise<R>): Promise<R> {
337
- return await this.connection.withDeadline(deadline, fn);
338
- }
339
-
340
- /**
341
- * Set metadata for any service requests executed in `fn`'s scope.
342
- *
343
- * @returns returned value of `fn`
344
- *
345
- * @see {@link Connection.withMetadata}
346
- */
347
- async withMetadata<R>(metadata: Metadata, fn: () => Promise<R>): Promise<R> {
348
- return await this.connection.withMetadata(metadata, fn);
349
- }
350
-
351
338
  /**
352
339
  * Start a new Workflow execution.
353
340
  *
@@ -356,7 +343,7 @@ export class WorkflowClient {
356
343
  protected async _start<T extends Workflow>(
357
344
  workflowTypeOrFunc: string | T,
358
345
  options: WithWorkflowArgs<T, WorkflowOptions>,
359
- interceptors: WorkflowClientCallsInterceptor[]
346
+ interceptors: WorkflowClientInterceptor[]
360
347
  ): Promise<string> {
361
348
  const workflowType = typeof workflowTypeOrFunc === 'string' ? workflowTypeOrFunc : workflowTypeOrFunc.name;
362
349
  assertRequiredWorkflowOptions(options);
@@ -380,7 +367,7 @@ export class WorkflowClient {
380
367
  protected async _signalWithStart<T extends Workflow, SA extends any[]>(
381
368
  workflowTypeOrFunc: string | T,
382
369
  options: WithWorkflowArgs<T, WorkflowSignalWithStartOptions<SA>>,
383
- interceptors: WorkflowClientCallsInterceptor[]
370
+ interceptors: WorkflowClientInterceptor[]
384
371
  ): Promise<string> {
385
372
  const workflowType = typeof workflowTypeOrFunc === 'string' ? workflowTypeOrFunc : workflowTypeOrFunc.name;
386
373
  const { signal, signalArgs, ...rest } = options;
@@ -412,8 +399,7 @@ export class WorkflowClient {
412
399
  options: WorkflowStartOptions<T>
413
400
  ): Promise<WorkflowHandleWithFirstExecutionRunId<T>> {
414
401
  const { workflowId } = options;
415
- // Cast is needed because it's impossible to deduce the type in this situation
416
- const interceptors = (this.options.interceptors.calls ?? []).map((ctor) => ctor({ workflowId }));
402
+ const interceptors = this.getOrMakeInterceptors(workflowId);
417
403
  const runId = await this._start(workflowTypeOrFunc, { ...options, workflowId }, interceptors);
418
404
  // runId is not used in handles created with `start*` calls because these
419
405
  // handles should allow interacting with the workflow if it continues as new.
@@ -440,7 +426,7 @@ export class WorkflowClient {
440
426
  options: WithWorkflowArgs<WorkflowFn, WorkflowSignalWithStartOptions<SignalArgs>>
441
427
  ): Promise<WorkflowHandleWithSignaledRunId<WorkflowFn>> {
442
428
  const { workflowId } = options;
443
- const interceptors = (this.options.interceptors.calls ?? []).map((ctor) => ctor({ workflowId }));
429
+ const interceptors = this.getOrMakeInterceptors(workflowId);
444
430
  const runId = await this._signalWithStart(workflowTypeOrFunc, options, interceptors);
445
431
  // runId is not used in handles created with `start*` calls because these
446
432
  // handles should allow interacting with the workflow if it continues as new.
@@ -466,7 +452,7 @@ export class WorkflowClient {
466
452
  options: WorkflowStartOptions<T>
467
453
  ): Promise<WorkflowResultType<T>> {
468
454
  const { workflowId } = options;
469
- const interceptors = (this.options.interceptors.calls ?? []).map((ctor) => ctor({ workflowId }));
455
+ const interceptors = this.getOrMakeInterceptors(workflowId);
470
456
  await this._start(workflowTypeOrFunc, options, interceptors);
471
457
  return await this.result(workflowId, undefined, {
472
458
  ...options,
@@ -855,38 +841,25 @@ export class WorkflowClient {
855
841
  const raw = await fn({
856
842
  workflowExecution: { workflowId, runId },
857
843
  });
858
- return {
859
- /* eslint-disable @typescript-eslint/no-non-null-assertion */
860
- type: raw.workflowExecutionInfo!.type!.name!,
861
- workflowId: raw.workflowExecutionInfo!.execution!.workflowId!,
862
- runId: raw.workflowExecutionInfo!.execution!.runId!,
863
- taskQueue: raw.workflowExecutionInfo!.taskQueue!,
864
- status: {
865
- code: raw.workflowExecutionInfo!.status!,
866
- name: workflowStatusCodeToName(raw.workflowExecutionInfo!.status!),
867
- },
868
- // Safe to convert to number, max history length is 50k, which is much less than Number.MAX_SAFE_INTEGER
869
- historyLength: raw.workflowExecutionInfo!.historyLength!.toNumber(),
870
- startTime: tsToDate(raw.workflowExecutionInfo!.startTime!),
871
- executionTime: optionalTsToDate(raw.workflowExecutionInfo!.executionTime),
872
- closeTime: optionalTsToDate(raw.workflowExecutionInfo!.closeTime),
873
- memo: await decodeMapFromPayloads(this.client.dataConverter, raw.workflowExecutionInfo!.memo?.fields),
874
- searchAttributes: Object.fromEntries(
875
- Object.entries(
876
- mapFromPayloads(
877
- searchAttributePayloadConverter,
878
- raw.workflowExecutionInfo!.searchAttributes?.indexedFields ?? {}
879
- ) as SearchAttributes
880
- ).filter(([_, v]) => v && v.length > 0) // Filter out empty arrays returned by pre 1.18 servers
881
- ),
882
- parentExecution: raw.workflowExecutionInfo?.parentExecution
883
- ? {
884
- workflowId: raw.workflowExecutionInfo.parentExecution.workflowId!,
885
- runId: raw.workflowExecutionInfo.parentExecution.runId!,
886
- }
887
- : undefined,
888
- raw,
889
- };
844
+ const info = await executionInfoFromRaw(raw.workflowExecutionInfo ?? {}, this.client.dataConverter);
845
+ (info as unknown as WorkflowExecutionDescription).raw = raw;
846
+ return info;
847
+ },
848
+ async fetchHistory() {
849
+ let nextPageToken: Uint8Array | undefined = undefined;
850
+ const events = Array<temporal.api.history.v1.IHistoryEvent>();
851
+ for (;;) {
852
+ const response: temporal.api.workflowservice.v1.GetWorkflowExecutionHistoryResponse =
853
+ await this.client.workflowService.getWorkflowExecutionHistory({
854
+ nextPageToken,
855
+ namespace: this.client.options.namespace,
856
+ execution: { workflowId, runId },
857
+ });
858
+ events.push(...(response.history?.events ?? []));
859
+ nextPageToken = response.nextPageToken;
860
+ if (nextPageToken == null || nextPageToken.length === 0) break;
861
+ }
862
+ return temporal.api.history.v1.History.create({ events });
890
863
  },
891
864
  async signal<Args extends any[]>(def: SignalDefinition<Args> | string, ...args: Args): Promise<void> {
892
865
  const next = this.client._signalWorkflowHandler.bind(this.client);
@@ -935,7 +908,7 @@ export class WorkflowClient {
935
908
  runId?: string,
936
909
  options?: GetWorkflowHandleOptions
937
910
  ): WorkflowHandle<T> {
938
- const interceptors = (this.options.interceptors.calls ?? []).map((ctor) => ctor({ workflowId, runId }));
911
+ const interceptors = this.getOrMakeInterceptors(workflowId, runId);
939
912
 
940
913
  return this._createWorkflowHandle({
941
914
  workflowId,
@@ -946,6 +919,61 @@ export class WorkflowClient {
946
919
  followRuns: options?.followRuns ?? true,
947
920
  });
948
921
  }
922
+
923
+ protected async *_list(options?: ListOptions): AsyncIterable<WorkflowExecutionInfo> {
924
+ let nextPageToken: Uint8Array = Buffer.alloc(0);
925
+ for (;;) {
926
+ const response = await this.workflowService.listWorkflowExecutions({
927
+ namespace: this.options.namespace,
928
+ query: options?.query,
929
+ nextPageToken,
930
+ pageSize: options?.pageSize,
931
+ });
932
+ // Not decoding memo payloads concurrently even though we could have to keep the lazy nature of this iterator.
933
+ // Decoding is done for `memo` fields which tend to be small.
934
+ // We might decide to change that based on user feedback.
935
+ for (const raw of response.executions) {
936
+ yield await executionInfoFromRaw(raw, this.dataConverter);
937
+ }
938
+ nextPageToken = response.nextPageToken;
939
+ if (nextPageToken == null || nextPageToken.length === 0) break;
940
+ }
941
+ }
942
+
943
+ /**
944
+ * List workflows by given `query`.
945
+ *
946
+ * ⚠️ To use advanced query functionality, as of the 1.18 server release, you must use Elasticsearch based visibility.
947
+ *
948
+ * More info on the concept of "visibility" and the query syntax on the Temporal documentation site:
949
+ * https://docs.temporal.io/visibility
950
+ */
951
+ public list(options?: ListOptions): AsyncWorkflowListIterable {
952
+ return {
953
+ [Symbol.asyncIterator]: () => this._list(options)[Symbol.asyncIterator](),
954
+ intoHistories: (intoHistoriesOptions?: IntoHistoriesOptions) => {
955
+ return mapAsyncIterable(
956
+ this._list(options),
957
+ async ({ workflowId, runId }) => ({
958
+ workflowId,
959
+ history: await this.getHandle(workflowId, runId)
960
+ .fetchHistory()
961
+ .catch((_) => undefined),
962
+ }),
963
+ { concurrency: intoHistoriesOptions?.concurrency ?? 5 }
964
+ );
965
+ },
966
+ };
967
+ }
968
+
969
+ protected getOrMakeInterceptors(workflowId: string, runId?: string): WorkflowClientInterceptor[] {
970
+ if (typeof this.options.interceptors === 'object' && 'calls' in this.options.interceptors) {
971
+ // eslint-disable-next-line deprecation/deprecation
972
+ const factories = (this.options.interceptors as WorkflowClientInterceptors).calls ?? [];
973
+ return factories.map((ctor) => ctor({ workflowId, runId }));
974
+ }
975
+ return Array.isArray(this.options.interceptors) ? (this.options.interceptors as WorkflowClientInterceptor[]) : [];
976
+ }
949
977
  }
950
978
 
951
979
  export class QueryRejectedError extends Error {
@@ -961,33 +989,3 @@ export class QueryNotRegisteredError extends Error {
961
989
  super(message);
962
990
  }
963
991
  }
964
-
965
- function workflowStatusCodeToName(code: temporal.api.enums.v1.WorkflowExecutionStatus): WorkflowExecutionStatusName {
966
- return workflowStatusCodeToNameInternal(code) ?? 'UNKNOWN';
967
- }
968
-
969
- /**
970
- * Intentionally leave out `default` branch to get compilation errors when new values are added
971
- */
972
- function workflowStatusCodeToNameInternal(
973
- code: temporal.api.enums.v1.WorkflowExecutionStatus
974
- ): WorkflowExecutionStatusName {
975
- switch (code) {
976
- case temporal.api.enums.v1.WorkflowExecutionStatus.WORKFLOW_EXECUTION_STATUS_UNSPECIFIED:
977
- return 'UNSPECIFIED';
978
- case temporal.api.enums.v1.WorkflowExecutionStatus.WORKFLOW_EXECUTION_STATUS_RUNNING:
979
- return 'RUNNING';
980
- case temporal.api.enums.v1.WorkflowExecutionStatus.WORKFLOW_EXECUTION_STATUS_FAILED:
981
- return 'FAILED';
982
- case temporal.api.enums.v1.WorkflowExecutionStatus.WORKFLOW_EXECUTION_STATUS_TIMED_OUT:
983
- return 'TIMED_OUT';
984
- case temporal.api.enums.v1.WorkflowExecutionStatus.WORKFLOW_EXECUTION_STATUS_CANCELED:
985
- return 'CANCELLED';
986
- case temporal.api.enums.v1.WorkflowExecutionStatus.WORKFLOW_EXECUTION_STATUS_TERMINATED:
987
- return 'TERMINATED';
988
- case temporal.api.enums.v1.WorkflowExecutionStatus.WORKFLOW_EXECUTION_STATUS_COMPLETED:
989
- return 'COMPLETED';
990
- case temporal.api.enums.v1.WorkflowExecutionStatus.WORKFLOW_EXECUTION_STATUS_CONTINUED_AS_NEW:
991
- return 'CONTINUED_AS_NEW';
992
- }
993
- }
@@ -1,4 +1,10 @@
1
- import { CommonWorkflowOptions, SignalDefinition, WithCompiledWorkflowOptions } from '@temporalio/common';
1
+ import {
2
+ CommonWorkflowOptions,
3
+ SignalDefinition,
4
+ WithCompiledWorkflowOptions,
5
+ WithWorkflowArgs,
6
+ Workflow,
7
+ } from '@temporalio/common';
2
8
 
3
9
  export * from '@temporalio/common/lib/workflow-options';
4
10
 
@@ -60,3 +66,8 @@ export interface WorkflowSignalWithStartOptionsWithArgs<SignalArgs extends any[]
60
66
  */
61
67
  signalArgs: SignalArgs;
62
68
  }
69
+
70
+ /**
71
+ * Options for starting a Workflow
72
+ */
73
+ export type WorkflowStartOptions<T extends Workflow = Workflow> = WithWorkflowArgs<T, WorkflowOptions>;