@hotmeshio/hotmesh 0.0.17 → 0.0.19

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 (54) hide show
  1. package/build/modules/utils.d.ts +3 -0
  2. package/build/modules/utils.js +17 -1
  3. package/build/package.json +1 -1
  4. package/build/services/activities/activity.d.ts +4 -12
  5. package/build/services/activities/activity.js +14 -156
  6. package/build/services/activities/hook.d.ts +20 -0
  7. package/build/services/activities/hook.js +124 -0
  8. package/build/services/activities/index.d.ts +2 -0
  9. package/build/services/activities/index.js +2 -0
  10. package/build/services/collator/index.js +0 -1
  11. package/build/services/compiler/deployer.d.ts +2 -0
  12. package/build/services/compiler/deployer.js +29 -2
  13. package/build/services/durable/client.d.ts +8 -1
  14. package/build/services/durable/client.js +54 -40
  15. package/build/services/durable/factory.js +11 -10
  16. package/build/services/durable/search.d.ts +15 -0
  17. package/build/services/durable/search.js +45 -0
  18. package/build/services/durable/worker.d.ts +6 -1
  19. package/build/services/durable/worker.js +34 -30
  20. package/build/services/durable/workflow.d.ts +2 -0
  21. package/build/services/durable/workflow.js +11 -28
  22. package/build/services/engine/index.d.ts +7 -2
  23. package/build/services/engine/index.js +2 -1
  24. package/build/services/store/clients/ioredis.d.ts +1 -0
  25. package/build/services/store/clients/ioredis.js +12 -0
  26. package/build/services/store/clients/redis.d.ts +1 -0
  27. package/build/services/store/clients/redis.js +3 -0
  28. package/build/services/store/index.d.ts +1 -0
  29. package/build/services/telemetry/index.js +2 -1
  30. package/build/types/activity.d.ts +6 -3
  31. package/build/types/durable.d.ts +12 -1
  32. package/build/types/hook.d.ts +1 -0
  33. package/build/types/index.d.ts +2 -2
  34. package/modules/utils.ts +17 -0
  35. package/package.json +1 -1
  36. package/services/activities/activity.ts +15 -167
  37. package/services/activities/hook.ts +149 -0
  38. package/services/activities/index.ts +2 -0
  39. package/services/collator/index.ts +0 -1
  40. package/services/compiler/deployer.ts +32 -2
  41. package/services/durable/client.ts +58 -43
  42. package/services/durable/factory.ts +11 -10
  43. package/services/durable/search.ts +54 -0
  44. package/services/durable/worker.ts +36 -32
  45. package/services/durable/workflow.ts +14 -30
  46. package/services/engine/index.ts +8 -4
  47. package/services/store/clients/ioredis.ts +13 -0
  48. package/services/store/clients/redis.ts +4 -0
  49. package/services/store/index.ts +1 -0
  50. package/services/telemetry/index.ts +2 -1
  51. package/types/activity.ts +7 -2
  52. package/types/durable.ts +10 -0
  53. package/types/hook.ts +1 -0
  54. package/types/index.ts +2 -0
@@ -58,7 +58,7 @@ const getWorkflowYAML = (app: string, version: string) => {
58
58
  done: false
59
59
 
60
60
  a1:
61
- type: activity
61
+ type: hook
62
62
  cycle: true
63
63
  output:
64
64
  schema:
@@ -131,7 +131,7 @@ const getWorkflowYAML = (app: string, version: string) => {
131
131
  done: '{$self.output.data.done}'
132
132
 
133
133
  a2:
134
- type: activity
134
+ type: hook
135
135
  title: Wait for cleanup signal
136
136
  hook:
137
137
  type: object
@@ -247,7 +247,7 @@ const getWorkflowYAML = (app: string, version: string) => {
247
247
 
248
248
  a599:
249
249
  title: Sleep exponentially longer before retrying
250
- type: activity
250
+ type: hook
251
251
  sleep: '{a1.output.data.duration}'
252
252
 
253
253
  c599:
@@ -539,7 +539,7 @@ const getWorkflowYAML = (app: string, version: string) => {
539
539
  done: true
540
540
 
541
541
  s1a:
542
- type: activity
542
+ type: hook
543
543
  title: Wait for cleanup signal
544
544
  hook:
545
545
  type: object
@@ -559,6 +559,7 @@ const getWorkflowYAML = (app: string, version: string) => {
559
559
  hooks:
560
560
  ${app}.activity.awaken:
561
561
  - to: s1a
562
+ keep_alive: true
562
563
  conditions:
563
564
  match:
564
565
  - expected: '{t1a.output.data.workflowId}'
@@ -605,13 +606,13 @@ const getWorkflowYAML = (app: string, version: string) => {
605
606
  target: '{$self.input.data.parentWorkflowId}'
606
607
 
607
608
  a1s:
608
- type: activity
609
+ type: hook
609
610
  title: Sleep for a duration
610
611
  sleep: '{t1s.output.data.duration}'
611
612
  emit: true
612
613
 
613
614
  a2s:
614
- type: activity
615
+ type: hook
615
616
  title: Wait for cleanup signal
616
617
  hook:
617
618
  type: object
@@ -683,7 +684,7 @@ const getWorkflowYAML = (app: string, version: string) => {
683
684
 
684
685
  a1wc:
685
686
  title: Split signal data
686
- type: activity
687
+ type: hook
687
688
  cycle: true
688
689
  output:
689
690
  schema:
@@ -721,7 +722,7 @@ const getWorkflowYAML = (app: string, version: string) => {
721
722
  - ['{t1wc.output.data.signals}', 1]
722
723
  - ['{@array.slice}']
723
724
  a2wc:
724
- type: activity
725
+ type: hook
725
726
  output:
726
727
  schema:
727
728
  type: object
@@ -848,7 +849,7 @@ const getWorkflowYAML = (app: string, version: string) => {
848
849
  target: '{$self.input.data.parentWorkflowId}'
849
850
 
850
851
  a1ww:
851
- type: activity
852
+ type: hook
852
853
  title: Wait for custom signal
853
854
  emit: true
854
855
  hook:
@@ -863,7 +864,7 @@ const getWorkflowYAML = (app: string, version: string) => {
863
864
  signalId: '{t1ww.output.data.signalId}'
864
865
 
865
866
  a2ww:
866
- type: activity
867
+ type: hook
867
868
  title: Wait for cleanup signal
868
869
  hook:
869
870
  type: object
@@ -0,0 +1,54 @@
1
+ import { HotMeshService as HotMesh } from '../hotmesh'
2
+ import { RedisClient, RedisMulti } from '../../types/redis';
3
+ import { StoreService } from '../store';
4
+ import { KeyService, KeyType } from '../../modules/key';
5
+
6
+ export class Search {
7
+ jobId: string;
8
+ hotMeshClient: HotMesh;
9
+ store: StoreService<RedisClient, RedisMulti> | null;
10
+
11
+ safeKey(key:string): string {
12
+ //note: protect the execution namespace with a prefix,
13
+ //so its design never conflicts with the hotmesh keyspace
14
+ return `_${key}`;
15
+ }
16
+
17
+ constructor(workflowId: string, hotMeshClient: HotMesh) {
18
+ const keyParams = {
19
+ appId: hotMeshClient.appId,
20
+ jobId: ''
21
+ }
22
+ const hotMeshPrefix = KeyService.mintKey(hotMeshClient.namespace, KeyType.JOB_STATE, keyParams);
23
+ this.jobId = `${hotMeshPrefix}${workflowId}`;
24
+ this.hotMeshClient = hotMeshClient;
25
+ this.store = hotMeshClient.engine.store as StoreService<RedisClient, RedisMulti>;
26
+ }
27
+
28
+ async set(key: string, value: string): Promise<void> {
29
+ await this.store.exec('HSET', this.jobId, this.safeKey(key), value.toString());
30
+ }
31
+
32
+ async get(key: string): Promise<string> {
33
+ try {
34
+ return await this.store.exec('HGET',this.jobId, this.safeKey(key)) as string;
35
+ } catch (err) {
36
+ this.hotMeshClient.logger.error('durable-search-get-error', { err });
37
+ return '';
38
+ }
39
+ }
40
+
41
+ async del(key: string): Promise<void> {
42
+ await this.store.exec('HDEL', this.jobId, this.safeKey(key));
43
+ }
44
+
45
+ async incr(key: string, val: number): Promise<number> {
46
+ return Number(await this.store.exec('HINCRBYFLOAT', this.jobId, this.safeKey(key), val.toString()) as string);
47
+ }
48
+
49
+ async mult(key: string, val: number): Promise<number> {
50
+ const log = Math.log(val);
51
+ const logTotal = Number(await this.store.exec('HINCRBYFLOAT', this.jobId, this.safeKey(key), log.toString()) as string);
52
+ return Math.exp(logTotal);
53
+ }
54
+ }
@@ -15,43 +15,14 @@ import {
15
15
  Registry,
16
16
  WorkerConfig,
17
17
  WorkerOptions,
18
- WorkflowDataType } from "../../types/durable";
18
+ WorkflowDataType,
19
+ WorkflowSearchOptions} from "../../types/durable";
19
20
  import { RedisClass, RedisOptions } from '../../types/redis';
20
21
  import {
21
22
  StreamData,
22
23
  StreamDataResponse,
23
24
  StreamStatus } from '../../types/stream';
24
-
25
- /*
26
- Here is an example of how the methods in this file are used:
27
-
28
- ./worker.ts
29
-
30
- import { Durable } from '@hotmeshio/hotmesh';
31
- import Redis from 'ioredis'; //OR `import * as Redis from 'redis';`
32
-
33
- import * as workflows from './workflows';
34
-
35
- async function run() {
36
- const worker = await Durable.Worker.create({
37
- connection: {
38
- class: Redis,
39
- options: {
40
- host: 'localhost',
41
- port: 6379,
42
- },
43
- },
44
- taskQueue: 'hello-world',
45
- workflow: workflows.example,
46
- });
47
- await worker.run();
48
- }
49
-
50
- run().catch((err) => {
51
- console.error(err);
52
- process.exit(1);
53
- });
54
- */
25
+ import { KeyService, KeyType } from '../../modules/key';
55
26
 
56
27
  export class WorkerService {
57
28
  static activityRegistry: Registry = {}; //user's activities
@@ -112,6 +83,38 @@ export class WorkerService {
112
83
  return WorkerService.activityRegistry;
113
84
  }
114
85
 
86
+ /**
87
+ * For those deployments with a redis stack backend (with the FT module),
88
+ * this method will configure the search index for the workflow.
89
+ */
90
+ //todo: bind this to the Search service; update constructor to expect hotMeshClient as first param (id is optional
91
+ //refactor and delete other one as well)
92
+ static async configureSearchIndex(hotMeshClient: HotMesh, search?: WorkflowSearchOptions): Promise<void> {
93
+ if (search?.schema) {
94
+ const store = hotMeshClient.engine.store;
95
+ const schema: string[] = [];
96
+ for (const [key, value] of Object.entries(search.schema)) {
97
+ //prefix with a comma (avoids collisions with hotmesh reserved words)
98
+ schema.push(`_${key}`);
99
+ schema.push(value.type);
100
+ if (value.sortable) {
101
+ schema.push('SORTABLE');
102
+ }
103
+ }
104
+ try {
105
+ const keyParams = {
106
+ appId: hotMeshClient.appId,
107
+ jobId: ''
108
+ }
109
+ const hotMeshPrefix = KeyService.mintKey(hotMeshClient.namespace, KeyType.JOB_STATE, keyParams);
110
+ const prefixes = search.prefix.map((prefix) => `${hotMeshPrefix}${prefix}`);
111
+ await store.exec('FT.CREATE', `${search.index}`, 'ON', 'HASH', 'PREFIX', prefixes.length, ...prefixes, 'SCHEMA', ...schema);
112
+ } catch (err) {
113
+ hotMeshClient.engine.logger.info('durable-client-search-err', { err });
114
+ }
115
+ }
116
+ }
117
+
115
118
  static async create(config: WorkerConfig) {
116
119
  //always call `registerActivities` before `import`
117
120
  WorkerService.connection = config.connection;
@@ -125,6 +128,7 @@ export class WorkerService {
125
128
  const worker = new WorkerService();
126
129
  worker.activityRunner = await worker.initActivityWorker(config, activityTopic);
127
130
  worker.workflowRunner = await worker.initWorkflowWorker(config, workflowTopic, workflowFunction);
131
+ WorkerService.configureSearchIndex(worker.workflowRunner, config.search)
128
132
  await WorkerService.activateWorkflow(worker.workflowRunner);
129
133
  return worker;
130
134
  }
@@ -4,39 +4,11 @@ import { asyncLocalStorage } from './asyncLocalStorage';
4
4
  import { WorkerService } from './worker';
5
5
  import { ClientService as Client } from './client';
6
6
  import { ConnectionService as Connection } from './connection';
7
- import { ActivityConfig, ProxyType, WorkflowOptions } from "../../types/durable";
7
+ import { ActivityConfig, ProxyType, WorkflowConfig, WorkflowOptions, WorkflowSearchOptions } from "../../types/durable";
8
8
  import { JobOutput, JobState } from '../../types';
9
9
  import { ACTIVITY_PUBLISHES_TOPIC, ACTIVITY_SUBSCRIBES_TOPIC, SLEEP_SUBSCRIBES_TOPIC, WFS_SUBSCRIBES_TOPIC } from './factory';
10
10
  import { DurableIncompleteSignalError, DurableSleepError, DurableWaitForSignalError } from '../../modules/errors';
11
-
12
- /*
13
- `proxyActivities` returns a wrapped instance of the
14
- target activity, so that when the workflow calls a
15
- proxied activity, it is actually calling the proxy
16
- function, which in turn calls the activity function.
17
-
18
- Here is an example of how the methods in this file are used:
19
-
20
- ./workflows.ts
21
-
22
- import { Durable } from '@hotmeshio/hotmesh';
23
- import * as activities from './activities';
24
-
25
- const { greet } = Durable.workflow.proxyActivities<typeof activities>({
26
- activities: activities,
27
- startToCloseTimeout: '1 minute',
28
- retryPolicy: {
29
- initialInterval: '5 seconds', // Initial delay between retries
30
- maximumAttempts: 3, // Max number of retry attempts
31
- backoffCoefficient: 2.0, // Backoff factor for delay between retries: delay = initialInterval * (backoffCoefficient ^ retry_attempt)
32
- maximumInterval: '30 seconds', // Max delay between retries
33
- },
34
- });
35
-
36
- export async function example(name: string): Promise<string> {
37
- return await greet(name);
38
- }
39
- */
11
+ import { Search } from './search';
40
12
 
41
13
  export class WorkflowService {
42
14
 
@@ -97,6 +69,18 @@ export class WorkflowService {
97
69
  return proxy;
98
70
  }
99
71
 
72
+ static async search(): Promise<Search> {
73
+ const store = asyncLocalStorage.getStore();
74
+ if (!store) {
75
+ throw new Error('durable-store-not-found');
76
+ }
77
+ const workflowId = store.get('workflowId');
78
+ const workflowTopic = store.get('workflowTopic');
79
+
80
+ const hotMeshClient = await WorkerService.getHotMesh(workflowTopic);
81
+ return new Search(workflowId, hotMeshClient);
82
+ }
83
+
100
84
  static async sleep(duration: string): Promise<number> {
101
85
  const seconds = ms(duration) / 1000;
102
86
 
@@ -3,10 +3,13 @@ import {
3
3
  formatISODate,
4
4
  getSubscriptionTopic,
5
5
  identifyRedisType,
6
+ polyfill,
6
7
  restoreHierarchy } from '../../modules/utils';
7
8
  import Activities from '../activities';
8
- import { Activity } from '../activities/activity';
9
9
  import { Await } from '../activities/await';
10
+ import { Cycle } from '../activities/cycle';
11
+ import { Hook } from '../activities/hook';
12
+ import { Signal } from '../activities/signal';
10
13
  import { Worker } from '../activities/worker';
11
14
  import { Trigger } from '../activities/trigger';
12
15
  import { CompilerService } from '../compiler';
@@ -235,9 +238,10 @@ class EngineService {
235
238
  }
236
239
 
237
240
  // ************* METADATA/MODEL METHODS *************
238
- async initActivity(topic: string, data: JobData = {}, context?: JobState): Promise<Activity> {
241
+ async initActivity(topic: string, data: JobData = {}, context?: JobState): Promise<Await|Cycle|Hook|Signal|Trigger|Worker> {
239
242
  const [activityId, schema] = await this.getSchema(topic);
240
- const ActivityHandler = Activities[schema.type];
243
+ polyfill
244
+ const ActivityHandler = Activities[polyfill.resolveActivityType(schema.type)];
241
245
  if (ActivityHandler) {
242
246
  const utc = formatISODate(new Date());
243
247
  const metadata: ActivityMetadata = {
@@ -334,7 +338,7 @@ class EngineService {
334
338
  data: streamData.data,
335
339
  };
336
340
  if (streamData.type === StreamDataType.TIMEHOOK || streamData.type === StreamDataType.WEBHOOK || streamData.type === StreamDataType.TRANSITION) {
337
- const activityHandler = await this.initActivity(`.${streamData.metadata.aid}`, context.data, context as JobState) as Activity;
341
+ const activityHandler = await this.initActivity(`.${streamData.metadata.aid}`, context.data, context as JobState) as Hook;
338
342
  if (streamData.type === StreamDataType.TIMEHOOK) {
339
343
  await activityHandler.processTimeHookEvent(streamData.metadata.jid);
340
344
  } else if (streamData.type === StreamDataType.TRANSITION) {
@@ -5,6 +5,7 @@ import { Cache } from '../cache';
5
5
  import { StoreService } from '../index';
6
6
  import { RedisClientType, RedisMultiType } from '../../../types/ioredisclient';
7
7
  import { ReclaimedMessageType } from '../../../types/stream';
8
+ import { type } from 'os';
8
9
 
9
10
  class IORedisStoreService extends StoreService<RedisClientType, RedisMultiType> {
10
11
  redisClient: RedisClientType;
@@ -22,6 +23,18 @@ class IORedisStoreService extends StoreService<RedisClientType, RedisMultiType>
22
23
  return this.redisClient.multi();
23
24
  }
24
25
 
26
+ async exec(...args: any[]): Promise<string|string[]|string[][]> {
27
+ const response = await this.redisClient.call.apply(this.redisClient, args as any);
28
+ if (typeof response === 'string') {
29
+ return response as string;
30
+ } else if (Array.isArray(response)) {
31
+ if (Array.isArray(response[0])) {
32
+ return response as string[][];
33
+ }
34
+ return response as string[];
35
+ }
36
+ }
37
+
25
38
  hGetAllResult(result: any) {
26
39
  //ioredis response signature is [null, {}] or [null, null]
27
40
  return result[1];
@@ -50,6 +50,10 @@ class RedisStoreService extends StoreService<RedisClientType, RedisMultiType> {
50
50
  return multi as unknown as RedisMultiType;
51
51
  }
52
52
 
53
+ async exec(...args: any[]): Promise<string|string[]|string[][]> {
54
+ return await this.redisClient.sendCommand(args);
55
+ }
56
+
53
57
  async publish(keyType: KeyType.QUORUM, message: Record<string, any>, appId: string, engineId?: string): Promise<boolean> {
54
58
  const topic = this.mintKey(keyType, { appId, engineId });
55
59
  const status: number = await this.redisClient.publish(topic, JSON.stringify(message));
@@ -70,6 +70,7 @@ abstract class StoreService<T, U extends AbstractRedisClient> {
70
70
 
71
71
  //todo: standardize signatures and move concrete methods to this class
72
72
  abstract getMulti(): U;
73
+ abstract exec(...args: any[]): Promise<string|string[]|string[][]>;
73
74
  abstract publish(
74
75
  keyType: KeyType.QUORUM,
75
76
  message: Record<string, any>,
@@ -18,6 +18,7 @@ import {
18
18
  Context,
19
19
  context,
20
20
  SpanStatusCode } from '../../types/telemetry';
21
+ import { polyfill } from '../../modules/utils';
21
22
 
22
23
  class TelemetryService {
23
24
  span: Span;
@@ -253,7 +254,7 @@ class TelemetryService {
253
254
  if (config.type === 'trigger') {
254
255
  state[`${metadata.aid}/output/metadata/l1s`] = context['$self'].output.metadata.l1s;
255
256
  state[`${metadata.aid}/output/metadata/l2s`] = context['$self'].output.metadata.l2s;
256
- } else if (config.type === 'activity' && leg === 1) {
257
+ } else if (polyfill.resolveActivityType(config.type) === 'hook' && leg === 1) {
257
258
  //activities run non-duplexed and only have a single leg
258
259
  state[`${metadata.aid}/output/metadata/l1s`] = context['$self'].output.metadata.l1s;
259
260
  state[`${metadata.aid}/output/metadata/l2s`] = context['$self'].output.metadata.l1s;
package/types/activity.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { MetricTypes } from "./stats";
2
2
  import { StreamRetryPolicy } from "./stream";
3
3
 
4
- type ActivityExecutionType = 'trigger' | 'await' | 'worker' | 'activity' | 'emit' | 'iterate' | 'cycle' | 'signal';
4
+ type ActivityExecutionType = 'trigger' | 'await' | 'worker' | 'activity' | 'emit' | 'iterate' | 'cycle' | 'signal' | 'hook';
5
5
 
6
6
  type Consumes = Record<string, string[]>;
7
7
 
@@ -65,6 +65,10 @@ interface CycleActivity extends BaseActivity {
65
65
  ancestor: string; //ancestor activity id
66
66
  }
67
67
 
68
+ interface HookActivity extends BaseActivity {
69
+ type: 'hook';
70
+ }
71
+
68
72
  interface SignalActivity extends BaseActivity {
69
73
  type: 'signal'; //signal activities call hook/hookAll
70
74
  subtype: 'one' | 'all'; //trigger: hook(One) or hookAll
@@ -80,7 +84,7 @@ interface IterateActivity extends BaseActivity {
80
84
  type: 'iterate';
81
85
  }
82
86
 
83
- type ActivityType = BaseActivity | TriggerActivity | AwaitActivity | WorkerActivity | IterateActivity;
87
+ type ActivityType = BaseActivity | TriggerActivity | AwaitActivity | WorkerActivity | IterateActivity | HookActivity;
84
88
 
85
89
  type ActivityData = Record<string, any>;
86
90
  type ActivityMetadata = {
@@ -124,6 +128,7 @@ export {
124
128
  TriggerActivityStats,
125
129
  AwaitActivity,
126
130
  CycleActivity,
131
+ HookActivity,
127
132
  SignalActivity,
128
133
  BaseActivity,
129
134
  IterateActivity,
package/types/durable.ts CHANGED
@@ -7,6 +7,13 @@ type WorkflowConfig = {
7
7
  initialInterval?: string; //default 1s
8
8
  }
9
9
 
10
+ type WorkflowSearchOptions = {
11
+ index?: string; //FT index name (myapp:myindex)
12
+ prefix?: string[]; //FT prefixes (['myapp:myindex:prefix1', 'myapp:myindex:prefix2'])
13
+ schema?: Record<string, {type: 'TEXT' | 'NUMERIC' | 'TAG', sortable: boolean}>;
14
+ data?: Record<string, string>;
15
+ }
16
+
10
17
  type WorkflowOptions = {
11
18
  taskQueue: string;
12
19
  args: any[]; //input arguments to pass in
@@ -15,6 +22,7 @@ type WorkflowOptions = {
15
22
  parentWorkflowId?: string; //system reserved; the id of the parent; if present the flow will not self-clean until the parent that spawned it self-cleans
16
23
  workflowTrace?: string;
17
24
  workflowSpan?: string;
25
+ search?: WorkflowSearchOptions
18
26
  config?: WorkflowConfig;
19
27
  }
20
28
 
@@ -59,6 +67,7 @@ type WorkerConfig = {
59
67
  taskQueue: string; //`subscribes` in the YAML (e.g, 'hello-world')
60
68
  workflow: Function; //target function to run
61
69
  options?: WorkerOptions;
70
+ search?: WorkflowSearchOptions;
62
71
  }
63
72
 
64
73
  type WorkerOptions = {
@@ -101,6 +110,7 @@ export {
101
110
  WorkerConfig,
102
111
  WorkflowConfig,
103
112
  WorkerOptions,
113
+ WorkflowSearchOptions,
104
114
  WorkflowDataType,
105
115
  WorkflowOptions,
106
116
  };
package/types/hook.ts CHANGED
@@ -16,6 +16,7 @@ interface HookConditions {
16
16
 
17
17
  interface HookRule {
18
18
  to: string;
19
+ keep_alive?: boolean; //if true, the hook will not be deleted after use
19
20
  conditions: HookConditions;
20
21
  }
21
22
 
package/types/index.ts CHANGED
@@ -10,6 +10,7 @@ export {
10
10
  AwaitActivity,
11
11
  BaseActivity,
12
12
  CycleActivity,
13
+ HookActivity,
13
14
  WorkerActivity,
14
15
  IterateActivity,
15
16
  SignalActivity,
@@ -39,6 +40,7 @@ export {
39
40
  WorkflowConfig,
40
41
  WorkerConfig,
41
42
  WorkerOptions,
43
+ WorkflowSearchOptions,
42
44
  WorkflowDataType,
43
45
  WorkflowOptions,
44
46
  }from './durable'