@dxos/functions 0.5.3-main.8b66fe2 → 0.5.3-main.8ffbbae

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 (87) hide show
  1. package/dist/lib/browser/index.mjs +493 -692
  2. package/dist/lib/browser/index.mjs.map +4 -4
  3. package/dist/lib/browser/meta.json +1 -1
  4. package/dist/lib/node/index.cjs +486 -675
  5. package/dist/lib/node/index.cjs.map +4 -4
  6. package/dist/lib/node/meta.json +1 -1
  7. package/dist/types/src/index.d.ts +0 -2
  8. package/dist/types/src/index.d.ts.map +1 -1
  9. package/dist/types/src/runtime/dev-server.d.ts +10 -7
  10. package/dist/types/src/runtime/dev-server.d.ts.map +1 -1
  11. package/dist/types/src/runtime/scheduler.d.ts +59 -11
  12. package/dist/types/src/runtime/scheduler.d.ts.map +1 -1
  13. package/dist/types/src/testing/test/handler.d.ts +0 -1
  14. package/dist/types/src/testing/test/handler.d.ts.map +1 -1
  15. package/dist/types/src/types.d.ts +111 -131
  16. package/dist/types/src/types.d.ts.map +1 -1
  17. package/package.json +14 -30
  18. package/schema/functions.json +116 -139
  19. package/src/index.ts +0 -2
  20. package/src/runtime/dev-server.test.ts +35 -15
  21. package/src/runtime/dev-server.ts +20 -37
  22. package/src/runtime/scheduler.test.ts +75 -54
  23. package/src/runtime/scheduler.ts +298 -66
  24. package/src/testing/test/handler.ts +2 -8
  25. package/src/types.ts +42 -58
  26. package/dist/lib/browser/chunk-366QG6IX.mjs +0 -81
  27. package/dist/lib/browser/chunk-366QG6IX.mjs.map +0 -7
  28. package/dist/lib/browser/types.mjs +0 -12
  29. package/dist/lib/browser/types.mjs.map +0 -7
  30. package/dist/lib/node/chunk-3VSJ57ZZ.cjs +0 -97
  31. package/dist/lib/node/chunk-3VSJ57ZZ.cjs.map +0 -7
  32. package/dist/lib/node/types.cjs +0 -33
  33. package/dist/lib/node/types.cjs.map +0 -7
  34. package/dist/types/src/function/function-registry.d.ts +0 -24
  35. package/dist/types/src/function/function-registry.d.ts.map +0 -1
  36. package/dist/types/src/function/function-registry.test.d.ts +0 -2
  37. package/dist/types/src/function/function-registry.test.d.ts.map +0 -1
  38. package/dist/types/src/function/index.d.ts +0 -2
  39. package/dist/types/src/function/index.d.ts.map +0 -1
  40. package/dist/types/src/testing/functions-integration.test.d.ts +0 -2
  41. package/dist/types/src/testing/functions-integration.test.d.ts.map +0 -1
  42. package/dist/types/src/testing/index.d.ts +0 -4
  43. package/dist/types/src/testing/index.d.ts.map +0 -1
  44. package/dist/types/src/testing/setup.d.ts +0 -5
  45. package/dist/types/src/testing/setup.d.ts.map +0 -1
  46. package/dist/types/src/testing/types.d.ts +0 -9
  47. package/dist/types/src/testing/types.d.ts.map +0 -1
  48. package/dist/types/src/testing/util.d.ts +0 -3
  49. package/dist/types/src/testing/util.d.ts.map +0 -1
  50. package/dist/types/src/trigger/index.d.ts +0 -2
  51. package/dist/types/src/trigger/index.d.ts.map +0 -1
  52. package/dist/types/src/trigger/trigger-registry.d.ts +0 -40
  53. package/dist/types/src/trigger/trigger-registry.d.ts.map +0 -1
  54. package/dist/types/src/trigger/trigger-registry.test.d.ts +0 -2
  55. package/dist/types/src/trigger/trigger-registry.test.d.ts.map +0 -1
  56. package/dist/types/src/trigger/type/index.d.ts +0 -5
  57. package/dist/types/src/trigger/type/index.d.ts.map +0 -1
  58. package/dist/types/src/trigger/type/subscription-trigger.d.ts +0 -4
  59. package/dist/types/src/trigger/type/subscription-trigger.d.ts.map +0 -1
  60. package/dist/types/src/trigger/type/timer-trigger.d.ts +0 -4
  61. package/dist/types/src/trigger/type/timer-trigger.d.ts.map +0 -1
  62. package/dist/types/src/trigger/type/webhook-trigger.d.ts +0 -4
  63. package/dist/types/src/trigger/type/webhook-trigger.d.ts.map +0 -1
  64. package/dist/types/src/trigger/type/websocket-trigger.d.ts +0 -13
  65. package/dist/types/src/trigger/type/websocket-trigger.d.ts.map +0 -1
  66. package/dist/types/src/util.d.ts +0 -15
  67. package/dist/types/src/util.d.ts.map +0 -1
  68. package/dist/types/src/util.test.d.ts +0 -2
  69. package/dist/types/src/util.test.d.ts.map +0 -1
  70. package/src/function/function-registry.test.ts +0 -105
  71. package/src/function/function-registry.ts +0 -90
  72. package/src/function/index.ts +0 -5
  73. package/src/testing/functions-integration.test.ts +0 -99
  74. package/src/testing/index.ts +0 -7
  75. package/src/testing/setup.ts +0 -45
  76. package/src/testing/types.ts +0 -9
  77. package/src/testing/util.ts +0 -16
  78. package/src/trigger/index.ts +0 -5
  79. package/src/trigger/trigger-registry.test.ts +0 -255
  80. package/src/trigger/trigger-registry.ts +0 -189
  81. package/src/trigger/type/index.ts +0 -8
  82. package/src/trigger/type/subscription-trigger.ts +0 -80
  83. package/src/trigger/type/timer-trigger.ts +0 -44
  84. package/src/trigger/type/webhook-trigger.ts +0 -47
  85. package/src/trigger/type/websocket-trigger.ts +0 -91
  86. package/src/util.test.ts +0 -43
  87. package/src/util.ts +0 -48
@@ -1,24 +1,26 @@
1
1
  {
2
2
  "$schema": "http://json-schema.org/draft-07/schema#",
3
3
  "type": "object",
4
- "required": [],
4
+ "required": [
5
+ "functions"
6
+ ],
5
7
  "properties": {
6
8
  "functions": {
7
9
  "type": "array",
8
10
  "items": {
9
11
  "type": "object",
10
12
  "required": [
11
- "uri",
12
- "route",
13
+ "id",
14
+ "path",
13
15
  "handler"
14
16
  ],
15
17
  "properties": {
16
- "uri": {
18
+ "id": {
17
19
  "type": "string",
18
20
  "description": "a string",
19
21
  "title": "string"
20
22
  },
21
- "route": {
23
+ "path": {
22
24
  "type": "string",
23
25
  "description": "a string",
24
26
  "title": "string"
@@ -42,165 +44,140 @@
42
44
  "items": {
43
45
  "type": "object",
44
46
  "required": [
45
- "function",
46
- "spec"
47
+ "function"
47
48
  ],
48
49
  "properties": {
49
50
  "function": {
50
51
  "type": "string",
51
- "description": "Function URI.",
52
+ "description": "Function ID/URI.",
52
53
  "title": "string"
53
54
  },
54
55
  "meta": {
55
- "$ref": "#/$defs/object"
56
+ "type": "object",
57
+ "required": [],
58
+ "properties": {},
59
+ "additionalProperties": {
60
+ "$id": "/schemas/any",
61
+ "title": "any"
62
+ }
56
63
  },
57
- "spec": {
58
- "anyOf": [
59
- {
64
+ "timer": {
65
+ "type": "object",
66
+ "required": [
67
+ "cron"
68
+ ],
69
+ "properties": {
70
+ "cron": {
71
+ "type": "string",
72
+ "description": "a string",
73
+ "title": "string"
74
+ }
75
+ },
76
+ "additionalProperties": false
77
+ },
78
+ "webhook": {
79
+ "type": "object",
80
+ "required": [
81
+ "method"
82
+ ],
83
+ "properties": {
84
+ "method": {
85
+ "type": "string",
86
+ "description": "a string",
87
+ "title": "string"
88
+ },
89
+ "port": {
90
+ "type": "number",
91
+ "description": "a number",
92
+ "title": "number"
93
+ }
94
+ },
95
+ "additionalProperties": false
96
+ },
97
+ "websocket": {
98
+ "type": "object",
99
+ "required": [
100
+ "url"
101
+ ],
102
+ "properties": {
103
+ "url": {
104
+ "type": "string",
105
+ "description": "a string",
106
+ "title": "string"
107
+ },
108
+ "init": {
60
109
  "type": "object",
61
- "required": [
62
- "type",
63
- "cron"
64
- ],
65
- "properties": {
66
- "type": {
67
- "const": "timer"
110
+ "required": [],
111
+ "properties": {},
112
+ "additionalProperties": {
113
+ "$id": "/schemas/any",
114
+ "title": "any"
115
+ }
116
+ }
117
+ },
118
+ "additionalProperties": false
119
+ },
120
+ "subscription": {
121
+ "type": "object",
122
+ "required": [
123
+ "filter"
124
+ ],
125
+ "properties": {
126
+ "spaceKey": {
127
+ "type": "string",
128
+ "description": "a string",
129
+ "title": "string"
130
+ },
131
+ "filter": {
132
+ "type": "array",
133
+ "items": {
134
+ "type": "object",
135
+ "required": [
136
+ "type"
137
+ ],
138
+ "properties": {
139
+ "type": {
140
+ "type": "string",
141
+ "description": "a string",
142
+ "title": "string"
143
+ },
144
+ "props": {
145
+ "type": "object",
146
+ "required": [],
147
+ "properties": {},
148
+ "additionalProperties": {
149
+ "$id": "/schemas/any",
150
+ "title": "any"
151
+ }
152
+ }
68
153
  },
69
- "cron": {
70
- "type": "string",
71
- "description": "a string",
72
- "title": "string"
73
- }
74
- },
75
- "additionalProperties": false
154
+ "additionalProperties": false
155
+ }
76
156
  },
77
- {
157
+ "options": {
78
158
  "type": "object",
79
- "required": [
80
- "type",
81
- "method"
82
- ],
159
+ "required": [],
83
160
  "properties": {
84
- "type": {
85
- "const": "webhook"
86
- },
87
- "method": {
88
- "type": "string",
89
- "description": "a string",
90
- "title": "string"
161
+ "deep": {
162
+ "type": "boolean",
163
+ "description": "a boolean",
164
+ "title": "boolean"
91
165
  },
92
- "port": {
166
+ "delay": {
93
167
  "type": "number",
94
168
  "description": "a number",
95
169
  "title": "number"
96
170
  }
97
171
  },
98
172
  "additionalProperties": false
99
- },
100
- {
101
- "type": "object",
102
- "required": [
103
- "type",
104
- "url"
105
- ],
106
- "properties": {
107
- "type": {
108
- "const": "websocket"
109
- },
110
- "url": {
111
- "type": "string",
112
- "description": "a string",
113
- "title": "string"
114
- },
115
- "init": {
116
- "type": "object",
117
- "required": [],
118
- "properties": {},
119
- "additionalProperties": {
120
- "$id": "/schemas/any",
121
- "title": "any"
122
- }
123
- }
124
- },
125
- "additionalProperties": false
126
- },
127
- {
128
- "type": "object",
129
- "required": [
130
- "type",
131
- "filter"
132
- ],
133
- "properties": {
134
- "type": {
135
- "const": "subscription"
136
- },
137
- "filter": {
138
- "type": "array",
139
- "items": {
140
- "type": "object",
141
- "required": [
142
- "type"
143
- ],
144
- "properties": {
145
- "type": {
146
- "type": "string",
147
- "description": "a string",
148
- "title": "string"
149
- },
150
- "props": {
151
- "type": "object",
152
- "required": [],
153
- "properties": {},
154
- "additionalProperties": {
155
- "$id": "/schemas/any",
156
- "title": "any"
157
- }
158
- }
159
- },
160
- "additionalProperties": false
161
- }
162
- },
163
- "options": {
164
- "type": "object",
165
- "required": [],
166
- "properties": {
167
- "deep": {
168
- "type": "boolean",
169
- "description": "a boolean",
170
- "title": "boolean"
171
- },
172
- "delay": {
173
- "type": "number",
174
- "description": "a number",
175
- "title": "number"
176
- }
177
- },
178
- "additionalProperties": false
179
- }
180
- },
181
- "additionalProperties": false
182
173
  }
183
- ]
174
+ },
175
+ "additionalProperties": false
184
176
  }
185
177
  },
186
178
  "additionalProperties": false
187
179
  }
188
180
  }
189
181
  },
190
- "additionalProperties": false,
191
- "$defs": {
192
- "object": {
193
- "$id": "/schemas/object",
194
- "oneOf": [
195
- {
196
- "type": "object"
197
- },
198
- {
199
- "type": "array"
200
- }
201
- ],
202
- "description": "an object in the TypeScript meaning, i.e. the `object` type",
203
- "title": "object"
204
- }
205
- }
182
+ "additionalProperties": false
206
183
  }
package/src/index.ts CHANGED
@@ -2,8 +2,6 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
- export * from './function';
6
5
  export * from './handler';
7
6
  export * from './runtime';
8
- export * from './trigger';
9
7
  export * from './types';
@@ -5,14 +5,12 @@
5
5
  import { expect } from 'chai';
6
6
  import path from 'path';
7
7
 
8
- import { waitForCondition } from '@dxos/async';
9
- import { type Client } from '@dxos/client';
8
+ import { FunctionsPlugin } from '@dxos/agent';
9
+ import { Client, Config } from '@dxos/client';
10
10
  import { TestBuilder } from '@dxos/client/testing';
11
- import { describe, test } from '@dxos/test';
11
+ import { describe, openAndClose, test } from '@dxos/test';
12
12
 
13
13
  import { DevServer } from './dev-server';
14
- import { FunctionRegistry } from '../function';
15
- import { createFunctionRuntime } from '../testing';
16
14
  import { type FunctionManifest } from '../types';
17
15
 
18
16
  describe('dev server', () => {
@@ -20,10 +18,35 @@ describe('dev server', () => {
20
18
  let testBuilder: TestBuilder;
21
19
  before(async () => {
22
20
  testBuilder = new TestBuilder();
23
- client = await createFunctionRuntime(testBuilder);
21
+ const config = new Config({
22
+ runtime: {
23
+ agent: {
24
+ plugins: [
25
+ {
26
+ id: 'dxos.org/agent/plugin/functions',
27
+ config: {
28
+ port: 8080,
29
+ },
30
+ },
31
+ ],
32
+ },
33
+ },
34
+ });
35
+
36
+ const services = testBuilder.createLocalClientServices();
37
+ client = new Client({ config, services });
38
+
39
+ await client.initialize();
40
+ await client.halo.createIdentity();
41
+ testBuilder.ctx.onDispose(() => client.destroy());
42
+
43
+ // TODO(burdon): Better way to configure plugin? (Rationalize chess.test).
44
+ const functionsPlugin = new FunctionsPlugin();
45
+ await functionsPlugin.initialize({ client, clientServices: services });
46
+ await openAndClose(functionsPlugin);
47
+
24
48
  expect(client.services.services.FunctionRegistryService).to.exist;
25
49
  });
26
-
27
50
  after(async () => {
28
51
  await testBuilder.destroy();
29
52
  });
@@ -32,19 +55,18 @@ describe('dev server', () => {
32
55
  const manifest: FunctionManifest = {
33
56
  functions: [
34
57
  {
35
- uri: 'example.com/function/test',
36
- route: 'test',
58
+ id: 'example.com/function/test',
59
+ path: 'test',
37
60
  handler: 'test',
38
61
  },
39
62
  ],
40
63
  };
41
64
 
42
- const registry = new FunctionRegistry(client);
43
- const server = new DevServer(client, registry, {
65
+ const server = new DevServer(client, {
66
+ manifest,
44
67
  baseDir: path.join(__dirname, '../testing'),
45
68
  });
46
- const space = await client.spaces.create();
47
- await registry.register(space, manifest.functions);
69
+ await server.initialize();
48
70
  await server.start();
49
71
 
50
72
  // TODO(burdon): Doesn't shut down cleanly.
@@ -52,8 +74,6 @@ describe('dev server', () => {
52
74
  testBuilder.ctx.onDispose(() => server.stop());
53
75
  expect(server).to.exist;
54
76
 
55
- await waitForCondition({ condition: () => server.functions.length > 0 });
56
-
57
77
  await server.invoke('test', {});
58
78
  expect(server.stats.seq).to.eq(1);
59
79
  });
@@ -9,15 +9,14 @@ import { join } from 'node:path';
9
9
 
10
10
  import { Event, Trigger } from '@dxos/async';
11
11
  import { type Client } from '@dxos/client';
12
- import { Context } from '@dxos/context';
13
12
  import { invariant } from '@dxos/invariant';
14
13
  import { log } from '@dxos/log';
15
14
 
16
- import { type FunctionRegistry } from '../function';
17
15
  import { type FunctionContext, type FunctionEvent, type FunctionHandler, type FunctionResponse } from '../handler';
18
- import { type FunctionDef } from '../types';
16
+ import { type FunctionDef, type FunctionManifest } from '../types';
19
17
 
20
18
  export type DevServerOptions = {
19
+ manifest: FunctionManifest;
21
20
  baseDir: string;
22
21
  port?: number;
23
22
  reload?: boolean;
@@ -28,8 +27,6 @@ export type DevServerOptions = {
28
27
  * Functions dev server provides a local HTTP server for testing functions.
29
28
  */
30
29
  export class DevServer {
31
- private _ctx = createContext();
32
-
33
30
  // Function handlers indexed by name (URL path).
34
31
  private readonly _handlers: Record<string, { def: FunctionDef; handler: FunctionHandler<any> }> = {};
35
32
 
@@ -41,17 +38,11 @@ export class DevServer {
41
38
 
42
39
  public readonly update = new Event<number>();
43
40
 
41
+ // prettier-ignore
44
42
  constructor(
45
43
  private readonly _client: Client,
46
- private readonly _functionsRegistry: FunctionRegistry,
47
44
  private readonly _options: DevServerOptions,
48
- ) {
49
- this._functionsRegistry.registered.on(async ({ added }) => {
50
- added.forEach((def) => this._load(def));
51
- await this._safeUpdateRegistration();
52
- log('new functions loaded', { added });
53
- });
54
- }
45
+ ) {}
55
46
 
56
47
  get stats() {
57
48
  return {
@@ -72,10 +63,19 @@ export class DevServer {
72
63
  return Object.values(this._handlers);
73
64
  }
74
65
 
66
+ async initialize() {
67
+ for (const def of this._options.manifest.functions) {
68
+ try {
69
+ await this._load(def);
70
+ } catch (err) {
71
+ log.error('parsing function (check manifest)', err);
72
+ }
73
+ }
74
+ }
75
+
75
76
  async start() {
76
77
  invariant(!this._server);
77
78
  log.info('starting...');
78
- this._ctx = createContext();
79
79
 
80
80
  // TODO(burdon): Move to hono.
81
81
  const app = express();
@@ -107,14 +107,12 @@ export class DevServer {
107
107
  // Register functions.
108
108
  const { registrationId, endpoint } = await this._client.services.services.FunctionRegistryService!.register({
109
109
  endpoint: this.endpoint,
110
+ functions: this.functions.map(({ def: { id, path } }) => ({ id, path })),
110
111
  });
111
112
 
112
113
  log.info('registered', { endpoint });
113
114
  this._proxy = endpoint;
114
115
  this._functionServiceRegistration = registrationId;
115
-
116
- // Open after registration, so that it can be updated with the list of function definitions.
117
- await this._functionsRegistry.open(this._ctx);
118
116
  } catch (err: any) {
119
117
  await this.stop();
120
118
  throw new Error('FunctionRegistryService not available (check plugin is configured).');
@@ -157,10 +155,10 @@ export class DevServer {
157
155
  /**
158
156
  * Load function.
159
157
  */
160
- private async _load(def: FunctionDef, force?: boolean | undefined) {
161
- const { uri, route, handler } = def;
158
+ private async _load(def: FunctionDef, force = false) {
159
+ const { id, path, handler } = def;
162
160
  const filePath = join(this._options.baseDir, handler);
163
- log.info('loading', { uri, force });
161
+ log.info('loading', { id, force });
164
162
 
165
163
  // Remove from cache.
166
164
  if (force) {
@@ -171,26 +169,13 @@ export class DevServer {
171
169
  });
172
170
  }
173
171
 
174
- // TODO(burdon): Import types.
175
172
  // eslint-disable-next-line @typescript-eslint/no-var-requires
176
173
  const module = require(filePath);
177
174
  if (typeof module.default !== 'function') {
178
- throw new Error(`Handler must export default function: ${uri}`);
175
+ throw new Error(`Handler must export default function: ${id}`);
179
176
  }
180
177
 
181
- this._handlers[route] = { def, handler: module.default };
182
- }
183
-
184
- private async _safeUpdateRegistration(): Promise<void> {
185
- invariant(this._functionServiceRegistration);
186
- try {
187
- await this._client.services.services.FunctionRegistryService!.updateRegistration({
188
- registrationId: this._functionServiceRegistration,
189
- functions: this.functions.map(({ def: { id, route } }) => ({ id, route })),
190
- });
191
- } catch (e) {
192
- log.catch(e);
193
- }
178
+ this._handlers[path] = { def, handler: module.default };
194
179
  }
195
180
 
196
181
  /**
@@ -229,5 +214,3 @@ export class DevServer {
229
214
  return statusCode;
230
215
  }
231
216
  }
232
-
233
- const createContext = () => new Context({ name: 'DevServer' });