@dxos/functions 0.5.3-main.f9b873d → 0.5.3-main.fffc127

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 (62) hide show
  1. package/dist/lib/browser/chunk-4D4I3YMJ.mjs +86 -0
  2. package/dist/lib/browser/chunk-4D4I3YMJ.mjs.map +7 -0
  3. package/dist/lib/browser/index.mjs +390 -336
  4. package/dist/lib/browser/index.mjs.map +4 -4
  5. package/dist/lib/browser/meta.json +1 -1
  6. package/dist/lib/browser/types.mjs +14 -0
  7. package/dist/lib/browser/types.mjs.map +7 -0
  8. package/dist/lib/node/chunk-3UYUR5N5.cjs +103 -0
  9. package/dist/lib/node/chunk-3UYUR5N5.cjs.map +7 -0
  10. package/dist/lib/node/index.cjs +393 -333
  11. package/dist/lib/node/index.cjs.map +4 -4
  12. package/dist/lib/node/meta.json +1 -1
  13. package/dist/lib/node/types.cjs +35 -0
  14. package/dist/lib/node/types.cjs.map +7 -0
  15. package/dist/types/src/browser/index.d.ts +2 -0
  16. package/dist/types/src/browser/index.d.ts.map +1 -0
  17. package/dist/types/src/{registry → function}/function-registry.d.ts +4 -4
  18. package/dist/types/src/function/function-registry.d.ts.map +1 -0
  19. package/dist/types/src/function/function-registry.test.d.ts.map +1 -0
  20. package/dist/types/src/function/index.d.ts.map +1 -0
  21. package/dist/types/src/handler.d.ts.map +1 -1
  22. package/dist/types/src/index.d.ts +1 -1
  23. package/dist/types/src/index.d.ts.map +1 -1
  24. package/dist/types/src/runtime/dev-server.d.ts +1 -1
  25. package/dist/types/src/runtime/dev-server.d.ts.map +1 -1
  26. package/dist/types/src/runtime/scheduler.d.ts +2 -1
  27. package/dist/types/src/runtime/scheduler.d.ts.map +1 -1
  28. package/dist/types/src/testing/setup.d.ts.map +1 -1
  29. package/dist/types/src/trigger/trigger-registry.d.ts +2 -5
  30. package/dist/types/src/trigger/trigger-registry.d.ts.map +1 -1
  31. package/dist/types/src/trigger/type/subscription-trigger.d.ts.map +1 -1
  32. package/dist/types/src/trigger/type/timer-trigger.d.ts.map +1 -1
  33. package/dist/types/src/trigger/type/webhook-trigger.d.ts.map +1 -1
  34. package/dist/types/src/trigger/type/websocket-trigger.d.ts.map +1 -1
  35. package/dist/types/src/types.d.ts +70 -43
  36. package/dist/types/src/types.d.ts.map +1 -1
  37. package/package.json +31 -18
  38. package/schema/functions.json +23 -9
  39. package/src/browser/index.ts +5 -0
  40. package/src/{registry → function}/function-registry.test.ts +10 -10
  41. package/src/function/function-registry.ts +90 -0
  42. package/src/index.ts +1 -1
  43. package/src/runtime/dev-server.test.ts +2 -2
  44. package/src/runtime/dev-server.ts +8 -9
  45. package/src/runtime/scheduler.test.ts +15 -10
  46. package/src/runtime/scheduler.ts +26 -13
  47. package/src/testing/functions-integration.test.ts +2 -1
  48. package/src/testing/setup.ts +8 -10
  49. package/src/trigger/trigger-registry.test.ts +88 -45
  50. package/src/trigger/trigger-registry.ts +66 -31
  51. package/src/trigger/type/subscription-trigger.ts +30 -17
  52. package/src/trigger/type/timer-trigger.ts +4 -3
  53. package/src/trigger/type/webhook-trigger.ts +3 -2
  54. package/src/trigger/type/websocket-trigger.ts +4 -3
  55. package/src/types.ts +51 -37
  56. package/dist/types/src/registry/function-registry.d.ts.map +0 -1
  57. package/dist/types/src/registry/function-registry.test.d.ts.map +0 -1
  58. package/dist/types/src/registry/index.d.ts.map +0 -1
  59. package/src/registry/function-registry.ts +0 -84
  60. /package/dist/types/src/{registry → function}/function-registry.test.d.ts +0 -0
  61. /package/dist/types/src/{registry → function}/index.d.ts +0 -0
  62. /package/src/{registry → function}/index.ts +0 -0
@@ -12,7 +12,7 @@ import { create } from '@dxos/echo-schema';
12
12
  import { describe, test } from '@dxos/test';
13
13
 
14
14
  import { Scheduler, type SchedulerOptions } from './scheduler';
15
- import { FunctionRegistry } from '../registry';
15
+ import { FunctionRegistry } from '../function';
16
16
  import { createInitializedClients, TestType, triggerWebhook } from '../testing';
17
17
  import { TriggerRegistry } from '../trigger';
18
18
  import { type FunctionManifest } from '../types';
@@ -29,6 +29,15 @@ describe('scheduler', () => {
29
29
  await testBuilder.destroy();
30
30
  });
31
31
 
32
+ const createScheduler = (callback: SchedulerOptions['callback']) => {
33
+ const scheduler = new Scheduler(new FunctionRegistry(client), new TriggerRegistry(client), { callback });
34
+ after(async () => {
35
+ await scheduler.stop();
36
+ });
37
+
38
+ return scheduler;
39
+ };
40
+
32
41
  test('timer', async () => {
33
42
  const manifest: FunctionManifest = {
34
43
  functions: [
@@ -41,6 +50,7 @@ describe('scheduler', () => {
41
50
  triggers: [
42
51
  {
43
52
  function: 'example.com/function/test',
53
+ enabled: true,
44
54
  spec: {
45
55
  type: 'timer',
46
56
  cron: '0/1 * * * * *', // Every 1s.
@@ -75,6 +85,7 @@ describe('scheduler', () => {
75
85
  triggers: [
76
86
  {
77
87
  function: 'example.com/function/test',
88
+ enabled: true,
78
89
  spec: {
79
90
  type: 'webhook',
80
91
  method: 'GET',
@@ -108,6 +119,7 @@ describe('scheduler', () => {
108
119
  triggers: [
109
120
  {
110
121
  function: 'example.com/function/test',
122
+ enabled: true,
111
123
  spec: {
112
124
  type: 'websocket',
113
125
  // url: 'https://hub.dxos.network/api/mailbox/test',
@@ -154,6 +166,7 @@ describe('scheduler', () => {
154
166
  triggers: [
155
167
  {
156
168
  function: 'example.com/function/test',
169
+ enabled: true,
157
170
  spec: {
158
171
  type: 'subscription',
159
172
  filter: [{ type: TestType.typename }],
@@ -165,7 +178,7 @@ describe('scheduler', () => {
165
178
  let count = 0;
166
179
  const done = new Trigger();
167
180
  const scheduler = createScheduler(async () => {
168
- if (++count === 2) {
181
+ if (++count === 1) {
169
182
  done.wake();
170
183
  }
171
184
  });
@@ -180,12 +193,4 @@ describe('scheduler', () => {
180
193
 
181
194
  await done.wait();
182
195
  });
183
-
184
- const createScheduler = (callback: SchedulerOptions['callback']) => {
185
- const scheduler = new Scheduler(new FunctionRegistry(client), new TriggerRegistry(client), { callback });
186
- after(async () => {
187
- await scheduler.stop();
188
- });
189
- return scheduler;
190
- };
191
196
  });
@@ -4,12 +4,13 @@
4
4
 
5
5
  import path from 'node:path';
6
6
 
7
+ import { Mutex } from '@dxos/async';
7
8
  import { type Space } from '@dxos/client/echo';
8
9
  import { Context } from '@dxos/context';
9
10
  import { log } from '@dxos/log';
10
11
 
12
+ import { type FunctionRegistry } from '../function';
11
13
  import { type FunctionEventMeta } from '../handler';
12
- import { type FunctionRegistry } from '../registry';
13
14
  import { type TriggerRegistry } from '../trigger';
14
15
  import { type FunctionDef, type FunctionManifest, type FunctionTrigger } from '../types';
15
16
 
@@ -26,13 +27,15 @@ export type SchedulerOptions = {
26
27
  export class Scheduler {
27
28
  private _ctx = createContext();
28
29
 
30
+ private readonly _functionUriToCallMutex = new Map<string, Mutex>();
31
+
29
32
  constructor(
30
33
  public readonly functions: FunctionRegistry,
31
34
  public readonly triggers: TriggerRegistry,
32
35
  private readonly _options: SchedulerOptions = {},
33
36
  ) {
34
- this.functions.onFunctionsRegistered.on(async ({ space, newFunctions }) => {
35
- await this._safeActivateTriggers(space, this.triggers.getInactiveTriggers(space), newFunctions);
37
+ this.functions.registered.on(async ({ space, added }) => {
38
+ await this._safeActivateTriggers(space, this.triggers.getInactiveTriggers(space), added);
36
39
  });
37
40
  this.triggers.registered.on(async ({ space, triggers }) => {
38
41
  await this._safeActivateTriggers(space, triggers, this.functions.getFunctions(space));
@@ -52,8 +55,9 @@ export class Scheduler {
52
55
  await this.triggers.close();
53
56
  }
54
57
 
58
+ // TODO(burdon): Remove and update registries directly.
55
59
  public async register(space: Space, manifest: FunctionManifest) {
56
- await this.functions.register(space, manifest);
60
+ await this.functions.register(space, manifest.functions);
57
61
  await this.triggers.register(space, manifest);
58
62
  }
59
63
 
@@ -68,24 +72,33 @@ export class Scheduler {
68
72
  await Promise.all(mountTasks).catch(log.catch);
69
73
  }
70
74
 
71
- private async activate(space: Space, functions: FunctionDef[], fnTrigger: FunctionTrigger) {
72
- const definition = functions.find((def) => def.uri === fnTrigger.function);
75
+ private async activate(space: Space, functions: FunctionDef[], trigger: FunctionTrigger) {
76
+ const definition = functions.find((def) => def.uri === trigger.function);
73
77
  if (!definition) {
74
- log.info('function is not found for trigger', { fnTrigger });
78
+ log.info('function is not found for trigger', { trigger });
75
79
  return;
76
80
  }
77
81
 
78
- await this.triggers.activate({ space }, fnTrigger, async (args) => {
79
- return this._execFunction(definition, {
80
- meta: fnTrigger.meta,
81
- data: { ...args, spaceKey: space.key },
82
+ await this.triggers.activate(space, trigger, async (args) => {
83
+ const mutex = this._functionUriToCallMutex.get(definition.uri) ?? new Mutex();
84
+ this._functionUriToCallMutex.set(definition.uri, mutex);
85
+
86
+ log.info('function triggered, waiting for mutex', { uri: definition.uri });
87
+ return mutex.executeSynchronized(() => {
88
+ log.info('mutex acquired', { uri: definition.uri });
89
+ return this._execFunction(definition, trigger, {
90
+ meta: trigger.meta ?? {},
91
+ data: { ...args, spaceKey: space.key },
92
+ });
82
93
  });
83
94
  });
84
- log('activated trigger', { space: space.key, trigger: fnTrigger });
95
+
96
+ log('activated trigger', { space: space.key, trigger });
85
97
  }
86
98
 
87
99
  private async _execFunction<TData, TMeta>(
88
100
  def: FunctionDef,
101
+ trigger: FunctionTrigger,
89
102
  { data, meta }: { data: TData; meta?: TMeta },
90
103
  ): Promise<number> {
91
104
  let status = 0;
@@ -97,7 +110,7 @@ export class Scheduler {
97
110
  if (endpoint) {
98
111
  // TODO(burdon): Move out of scheduler (generalize as callback).
99
112
  const url = path.join(endpoint, def.route);
100
- log.info('exec', { function: def.uri, url });
113
+ log.info('exec', { function: def.uri, url, triggerType: trigger.spec.type });
101
114
  const response = await fetch(url, {
102
115
  method: 'POST',
103
116
  headers: {
@@ -13,7 +13,7 @@ import { Invitation } from '@dxos/protocols/proto/dxos/client/services';
13
13
  import { describe, test } from '@dxos/test';
14
14
 
15
15
  import { setTestCallHandler } from './test/handler';
16
- import { FunctionRegistry } from '../registry';
16
+ import { FunctionRegistry } from '../function';
17
17
  import { DevServer, Scheduler } from '../runtime';
18
18
  import { createFunctionRuntime, createInitializedClients, TestType } from '../testing';
19
19
  import { TriggerRegistry } from '../trigger';
@@ -44,6 +44,7 @@ describe('functions e2e', () => {
44
44
  space.db.add(
45
45
  create(FunctionTrigger, {
46
46
  function: uri,
47
+ enabled: true,
47
48
  meta: triggerMeta,
48
49
  spec: {
49
50
  type: 'subscription',
@@ -10,16 +10,16 @@ import { range } from '@dxos/util';
10
10
  import { TestType } from './types';
11
11
  import { FunctionDef, FunctionTrigger } from '../types';
12
12
 
13
- // TODO(burdon): Create TestBuilder.
13
+ // TODO(burdon): Extend/wrap TestBuilder.
14
14
 
15
15
  export const createInitializedClients = async (testBuilder: TestBuilder, count: number = 1, config?: Config) => {
16
16
  const clients = range(count).map(() => new Client({ config, services: testBuilder.createLocalClientServices() }));
17
- testBuilder.ctx.onDispose(() => Promise.all(clients.map((c) => c.destroy())));
17
+ testBuilder.ctx.onDispose(() => Promise.all(clients.map((client) => client.destroy())));
18
18
  return Promise.all(
19
19
  clients.map(async (client, index) => {
20
20
  await client.initialize();
21
21
  await client.halo.createIdentity({ displayName: `Peer ${index}` });
22
- client.addSchema(TestType, FunctionDef, FunctionTrigger);
22
+ client.addSchema(FunctionDef, FunctionTrigger, TestType);
23
23
  return client;
24
24
  }),
25
25
  );
@@ -34,12 +34,10 @@ export const createFunctionRuntime = async (testBuilder: TestBuilder): Promise<C
34
34
  },
35
35
  });
36
36
 
37
- const client = (await createInitializedClients(testBuilder, 1, config))[0];
38
-
39
- // TODO(burdon): Better way to configure plugin? (Rationalize chess.test).
40
- const functionsPlugin = new FunctionsPlugin();
41
- await functionsPlugin.initialize({ client, clientServices: client.services });
42
- await functionsPlugin.open();
43
- testBuilder.ctx.onDispose(() => functionsPlugin.close());
37
+ const [client] = await createInitializedClients(testBuilder, 1, config);
38
+ const plugin = new FunctionsPlugin();
39
+ await plugin.initialize({ client, clientServices: client.services });
40
+ await plugin.open();
41
+ testBuilder.ctx.onDispose(() => plugin.close());
44
42
  return client;
45
43
  };
@@ -11,7 +11,7 @@ import { type Space } from '@dxos/client/echo';
11
11
  import { TestBuilder } from '@dxos/client/testing';
12
12
  import { Context } from '@dxos/context';
13
13
  import { Filter } from '@dxos/echo-db';
14
- import { create } from '@dxos/echo-schema';
14
+ import { create, splitMeta } from '@dxos/echo-schema';
15
15
  import { describe, test } from '@dxos/test';
16
16
  import { range } from '@dxos/util';
17
17
 
@@ -19,20 +19,42 @@ import { TriggerRegistry } from './trigger-registry';
19
19
  import { createInitializedClients, TestType, triggerWebhook } from '../testing';
20
20
  import { type FunctionManifest, FunctionTrigger } from '../types';
21
21
 
22
- const testManifest: FunctionManifest = {
22
+ const manifest: FunctionManifest = {
23
23
  triggers: [
24
24
  {
25
+ '@meta': {
26
+ keys: [
27
+ {
28
+ source: 'example.com',
29
+ id: 'trigger-1',
30
+ },
31
+ ],
32
+ },
25
33
  function: 'example.com/function/webhook-test',
34
+ enabled: true,
26
35
  spec: {
27
36
  type: 'webhook',
28
37
  method: 'GET',
29
38
  },
30
39
  },
31
40
  {
41
+ '@meta': {
42
+ keys: [
43
+ {
44
+ source: 'example.com',
45
+ id: 'trigger-2',
46
+ },
47
+ ],
48
+ },
32
49
  function: 'example.com/function/subscription-test',
50
+ enabled: true,
33
51
  spec: {
34
52
  type: 'subscription',
35
- filter: [{ type: TestType.typename }],
53
+ filter: [
54
+ {
55
+ type: TestType.typename,
56
+ },
57
+ ],
36
58
  },
37
59
  },
38
60
  ],
@@ -54,30 +76,44 @@ describe('trigger registry', () => {
54
76
 
55
77
  describe('register', () => {
56
78
  test('creates new triggers', async () => {
57
- const client = (await createInitializedClients(testBuilder))[0];
79
+ const [client] = await createInitializedClients(testBuilder);
58
80
  const registry = createRegistry(client);
59
81
  const space = await client.spaces.create();
60
- await registry.register(space, testManifest);
82
+ await registry.register(space, manifest);
61
83
  const { objects } = await space.db.query(Filter.schema(FunctionTrigger)).run();
62
- expect(objects.length).to.eq(testManifest.triggers?.length);
63
- const expected = testManifest.triggers?.map((t) => t.function).sort();
64
- expect(objects.map((o: FunctionTrigger) => o.function).sort()).to.deep.eq(expected);
84
+ expect(objects.length).to.eq(manifest.triggers?.length);
85
+
86
+ const expected = manifest.triggers?.map((trigger) => trigger.function).sort();
87
+ expect(objects.map((object: FunctionTrigger) => object.function).sort()).to.deep.eq(expected);
88
+ });
89
+
90
+ test('set meta', () => {
91
+ const trigger = create(FunctionTrigger, {
92
+ function: 'example.com/function/webhook-test',
93
+ spec: {
94
+ type: 'webhook',
95
+ method: 'GET',
96
+ },
97
+ });
98
+
99
+ (trigger.meta ??= {}).test = 100;
100
+ expect(trigger.meta.test).to.eq(100);
65
101
  });
66
102
  });
67
103
 
68
104
  describe('activate', () => {
69
105
  test('invokes the provided callback', async () => {
70
- const client = (await createInitializedClients(testBuilder))[0];
106
+ const [client] = await createInitializedClients(testBuilder);
71
107
  const space = await client.spaces.create();
72
108
  const registry = createRegistry(client);
73
- await registry.register(space, testManifest);
109
+ await registry.register(space, manifest);
74
110
  await registry.open(ctx);
75
- await waitHasInactiveTriggers(registry, space);
111
+ await waitForInactiveTriggers(registry, space);
76
112
 
77
113
  const callbackInvoked = new Trigger();
78
114
  const { objects: allTriggers } = await space.db.query(Filter.schema(FunctionTrigger)).run();
79
- const webhookTrigger = allTriggers.find((t: FunctionTrigger) => t.spec.type === 'webhook')!;
80
- await registry.activate({ space }, webhookTrigger, async () => {
115
+ const webhookTrigger = allTriggers.find((trigger: FunctionTrigger) => trigger.spec.type === 'webhook')!;
116
+ await registry.activate(space, webhookTrigger, async () => {
81
117
  callbackInvoked.wake();
82
118
  return 200;
83
119
  });
@@ -87,34 +123,37 @@ describe('trigger registry', () => {
87
123
  });
88
124
 
89
125
  test('removes from inactive list', async () => {
90
- const client = (await createInitializedClients(testBuilder))[0];
126
+ const [client] = await createInitializedClients(testBuilder);
91
127
  const space = await client.spaces.create();
92
128
  const registry = createRegistry(client);
93
- await registry.register(space, testManifest);
129
+ await registry.register(space, manifest);
94
130
  await registry.open(ctx);
95
- await waitHasInactiveTriggers(registry, space);
131
+ await waitForInactiveTriggers(registry, space);
96
132
 
97
133
  const inactiveTrigger = registry.getInactiveTriggers(space)[0];
98
- await registry.activate({ space }, inactiveTrigger, async () => 200);
134
+ await registry.activate(space, inactiveTrigger, async () => 200);
99
135
 
100
136
  const updatedInactiveList = registry.getInactiveTriggers(space);
101
- expect(updatedInactiveList.find((t: FunctionTrigger) => t.function === inactiveTrigger.function)).to.be.undefined;
137
+ expect(updatedInactiveList.find((trigger: FunctionTrigger) => trigger.function === inactiveTrigger.function)).to
138
+ .be.undefined;
102
139
  });
140
+
141
+ // TODO(burdon): Test enable/disable trigger.
103
142
  });
104
143
 
105
144
  describe('deactivate', () => {
106
145
  test('trigger object deletion deactivates a trigger', async () => {
107
- const client = (await createInitializedClients(testBuilder))[0];
146
+ const [client] = await createInitializedClients(testBuilder);
108
147
  const space = await client.spaces.create();
109
148
  const registry = createRegistry(client);
110
- await registry.register(space, testManifest);
149
+ await registry.register(space, manifest);
111
150
  await registry.open(ctx);
112
- await waitHasInactiveTriggers(registry, space);
151
+ await waitForInactiveTriggers(registry, space);
113
152
 
114
153
  const { objects: allTriggers } = await space.db.query(Filter.schema(FunctionTrigger)).run();
115
- const echoTrigger = allTriggers.find((t: FunctionTrigger) => t.spec.type === 'subscription')!;
154
+ const echoTrigger = allTriggers.find((trigger: FunctionTrigger) => trigger.spec.type === 'subscription')!;
116
155
  let count = 0;
117
- await registry.activate({ space }, echoTrigger, async () => {
156
+ await registry.activate(space, echoTrigger, async () => {
118
157
  count++;
119
158
  return 200;
120
159
  });
@@ -124,24 +163,23 @@ describe('trigger registry', () => {
124
163
  expect(count).to.eq(1);
125
164
 
126
165
  space.db.remove(echoTrigger);
127
-
128
166
  space.db.add(create(TestType, { title: '2' }));
129
167
  await sleep(20);
130
168
  expect(count).to.eq(1);
131
169
  });
132
170
 
133
171
  test('registry closing deactivates a trigger', async () => {
134
- const client = (await createInitializedClients(testBuilder))[0];
172
+ const [client] = await createInitializedClients(testBuilder);
135
173
  const space = await client.spaces.create();
136
174
  const registry = createRegistry(client);
137
- await registry.register(space, testManifest);
175
+ await registry.register(space, manifest);
138
176
  await registry.open(ctx);
139
- await waitHasInactiveTriggers(registry, space);
177
+ await waitForInactiveTriggers(registry, space);
140
178
 
141
179
  const { objects: allTriggers } = await space.db.query(Filter.schema(FunctionTrigger)).run();
142
- const echoTrigger = allTriggers.find((t: FunctionTrigger) => t.spec.type === 'subscription')!;
180
+ const echoTrigger = allTriggers.find((trigger: FunctionTrigger) => trigger.spec.type === 'subscription')!;
143
181
  let count = 0;
144
- await registry.activate({ space }, echoTrigger, async () => {
182
+ await registry.activate(space, echoTrigger, async () => {
145
183
  count++;
146
184
  return 200;
147
185
  });
@@ -156,23 +194,24 @@ describe('trigger registry', () => {
156
194
 
157
195
  describe('trigger events', () => {
158
196
  test('event fired when all registered when opened', async () => {
159
- const client = (await createInitializedClients(testBuilder))[0];
197
+ const [client] = await createInitializedClients(testBuilder);
160
198
  const registry = createRegistry(client);
161
- const triggers = createTriggersInSpace(client.spaces.default, 3);
199
+ const triggers = createTriggers(client.spaces.default, 3);
162
200
 
163
201
  const triggersRegistered = new Trigger<FunctionTrigger[]>();
164
202
  registry.registered.on((fn) => {
165
203
  expect(fn.space.key.toHex()).to.eq(client.spaces.default.key.toHex());
166
204
  triggersRegistered.wake(fn.triggers);
167
205
  });
206
+
168
207
  void registry.open(ctx);
169
208
  const functions = await triggersRegistered.wait();
170
- const expected = triggers.map((obj) => obj.id).sort();
209
+ const expected = triggers.map((object) => object.id).sort();
171
210
  expect(functions.map((fn) => fn.id).sort()).to.deep.eq(expected);
172
211
  });
173
212
 
174
213
  test('event fired when a new trigger is added', async () => {
175
- const client = (await createInitializedClients(testBuilder))[0];
214
+ const [client] = await createInitializedClients(testBuilder);
176
215
  const registry = createRegistry(client);
177
216
  const space = await client.spaces.create();
178
217
 
@@ -182,16 +221,16 @@ describe('trigger registry', () => {
182
221
  triggerRegistered.wake(fn.triggers[0]);
183
222
  });
184
223
  await registry.open(ctx);
185
- await registry.register(space, { triggers: testManifest?.triggers?.slice(0, 1) });
224
+ await registry.register(space, { triggers: manifest?.triggers?.slice(0, 1) });
186
225
  const registered = await triggerRegistered.wait();
187
- expect(registered.function).to.eq(testManifest.triggers![0].function);
226
+ expect(registered.function).to.eq(manifest.triggers![0].function);
188
227
  });
189
228
 
190
229
  test('event fired when a new trigger is removed', async () => {
191
- const client = (await createInitializedClients(testBuilder))[0];
230
+ const [client] = await createInitializedClients(testBuilder);
192
231
  const registry = createRegistry(client);
193
232
  const space = await client.spaces.create();
194
- const triggers = createTriggersInSpace(space, 3);
233
+ const triggers = createTriggers(space, 3);
195
234
 
196
235
  const triggerLoaded = new Trigger();
197
236
  registry.registered.on((fn) => triggerLoaded.wake());
@@ -201,7 +240,7 @@ describe('trigger registry', () => {
201
240
  expect(fn.triggers.length).to.eq(1);
202
241
  triggerRemoved.wake(fn.triggers[0]);
203
242
  });
204
- await registry.register(space, testManifest);
243
+ await registry.register(space, manifest);
205
244
  await registry.open(ctx);
206
245
  await triggerLoaded.wait();
207
246
 
@@ -211,19 +250,23 @@ describe('trigger registry', () => {
211
250
  });
212
251
  });
213
252
 
214
- const waitHasInactiveTriggers = async (registry: TriggerRegistry, space: Space) => {
215
- await waitForCondition({ condition: () => registry.getInactiveTriggers(space).length > 0 });
216
- };
217
-
218
253
  const createRegistry = (client: Client) => {
219
254
  const registry = new TriggerRegistry(client);
220
255
  ctx.onDispose(() => registry.close());
221
256
  return registry;
222
257
  };
223
258
 
224
- const createTriggersInSpace = (space: Space, count: number) => {
225
- const triggers = range(count, () => create(FunctionTrigger, { ...testManifest.triggers![0] }));
226
- triggers.forEach((def) => space.db.add(def));
259
+ const createTriggers = (space: Space, count: number) => {
260
+ const triggers = range(count, () => {
261
+ const { meta, object } = splitMeta(manifest.triggers![0]);
262
+ return create(FunctionTrigger, object, meta);
263
+ });
264
+
265
+ triggers.forEach((trigger) => space.db.add(trigger));
227
266
  return triggers;
228
267
  };
268
+
269
+ const waitForInactiveTriggers = async (registry: TriggerRegistry, space: Space) => {
270
+ await waitForCondition({ condition: () => registry.getInactiveTriggers(space).length > 0 });
271
+ };
229
272
  });