@dxos/functions 0.3.8-next.f4e0086 → 0.3.9-main.14901ff

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -50,7 +50,7 @@ runtime:
50
50
  Start functions in dev mode (from the related package):
51
51
 
52
52
  ```bash
53
- dx function dev-server -r ts-node/register --verbose
53
+ dx function dev -r ts-node/register --verbose
54
54
  ```
55
55
 
56
56
  > NOTE: `-r ts-node/register` configures native TypesScript support.
@@ -61,7 +61,7 @@ Install `nodemon` to support live reloading:
61
61
  npm i -g nodemon
62
62
 
63
63
  nodemon -w ./src -e ts --exec $(git rev-parse --show-toplevel)/packages/devtools/cli/bin/dev \
64
- function dev-server -r ts-node/register --verbose
64
+ function dev -r ts-node/register --verbose
65
65
  ```
66
66
 
67
67
  ## Invoking functions
@@ -9,53 +9,46 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
9
9
 
10
10
  // packages/core/functions/src/runtime/dev-server.ts
11
11
  import express from "express";
12
+ import { getPort } from "get-port-please";
12
13
  import { join } from "@dxos/node-std/path";
13
- import { getPortPromise } from "portfinder";
14
14
  import { Trigger } from "@dxos/async";
15
+ import { invariant } from "@dxos/invariant";
15
16
  import { log } from "@dxos/log";
16
17
  var __dxlog_file = "/home/runner/work/dxos/dxos/packages/core/functions/src/runtime/dev-server.ts";
17
- var DEFAULT_PORT = 7001;
18
18
  var DevServer = class {
19
19
  // prettier-ignore
20
20
  constructor(_client, _options) {
21
21
  this._client = _client;
22
22
  this._options = _options;
23
23
  this._handlers = {};
24
- }
25
- get port() {
26
- return this._port;
24
+ this._seq = 0;
27
25
  }
28
26
  get endpoint() {
29
- return this._port ? `http://localhost:${this._port}` : void 0;
27
+ invariant(this._port, void 0, {
28
+ F: __dxlog_file,
29
+ L: 45,
30
+ S: this,
31
+ A: [
32
+ "this._port",
33
+ ""
34
+ ]
35
+ });
36
+ return `http://localhost:${this._port}`;
37
+ }
38
+ get proxy() {
39
+ return this._proxy;
30
40
  }
31
41
  get functions() {
32
42
  return Object.values(this._handlers);
33
43
  }
34
44
  async initialize() {
35
45
  for (const def of this._options.manifest.functions) {
36
- const { id, endpoint, handler: path } = def;
37
46
  try {
38
- const module = __require(join(this._options.directory, path));
39
- const handler = module.default;
40
- if (typeof handler !== "function") {
41
- throw new Error(`Handler must export default function: ${id}`);
42
- }
43
- if (this._handlers[endpoint]) {
44
- log.warn(`Function already registered: ${id}`, void 0, {
45
- F: __dxlog_file,
46
- L: 64,
47
- S: this,
48
- C: (f, a) => f(...a)
49
- });
50
- }
51
- this._handlers[endpoint] = {
52
- def,
53
- handler
54
- };
47
+ await this._load(def);
55
48
  } catch (err) {
56
49
  log.error("parsing function (check manifest)", err, {
57
50
  F: __dxlog_file,
58
- L: 69,
51
+ L: 62,
59
52
  S: this,
60
53
  C: (f, a) => f(...a)
61
54
  });
@@ -65,66 +58,55 @@ var DevServer = class {
65
58
  async start() {
66
59
  const app = express();
67
60
  app.use(express.json());
68
- app.post("/:endpoint", async (req, res) => {
69
- const { endpoint } = req.params;
70
- const response = {
71
- status: (code) => {
72
- res.statusCode = code;
73
- return response;
74
- },
75
- succeed: (result = {}) => {
76
- res.end(JSON.stringify(result));
77
- return response;
78
- }
79
- };
80
- const context = {
81
- client: this._client,
82
- status: response.status.bind(response)
83
- };
84
- void (async () => {
85
- try {
86
- log("invoking", {
87
- endpoint
88
- }, {
89
- F: __dxlog_file,
90
- L: 100,
91
- S: this,
92
- C: (f, a) => f(...a)
93
- });
94
- const { handler } = this._handlers[endpoint];
95
- const response2 = await handler({
96
- context,
97
- event: req.body
98
- });
99
- log("done", {
100
- response: response2
101
- }, {
102
- F: __dxlog_file,
103
- L: 103,
104
- S: this,
105
- C: (f, a) => f(...a)
106
- });
107
- } catch (err) {
108
- res.statusCode = 500;
109
- res.end(err.message);
61
+ app.post("/:name", async (req, res) => {
62
+ const { name } = req.params;
63
+ try {
64
+ if (this._options.reload) {
65
+ const { def } = this._handlers[name];
66
+ await this._load(def, true);
110
67
  }
111
- })();
68
+ res.statusCode = await this._invoke(name, req.body);
69
+ res.end();
70
+ } catch (err) {
71
+ log.catch(err, void 0, {
72
+ F: __dxlog_file,
73
+ L: 82,
74
+ S: this,
75
+ C: (f, a) => f(...a)
76
+ });
77
+ res.statusCode = 500;
78
+ res.end();
79
+ }
112
80
  });
113
- this._port = await getPortPromise({
114
- startPort: DEFAULT_PORT
81
+ this._port = await getPort({
82
+ port: 7200,
83
+ portRange: [
84
+ 7200,
85
+ 7299
86
+ ]
115
87
  });
116
88
  this._server = app.listen(this._port);
117
89
  try {
118
- const { registrationId } = await this._client.services.services.FunctionRegistryService.register({
90
+ const { registrationId, endpoint } = await this._client.services.services.FunctionRegistryService.register({
119
91
  endpoint: this.endpoint,
120
- functions: this.functions.map(({ def: { endpoint } }) => ({
121
- name: endpoint
92
+ functions: this.functions.map(({ def: { name } }) => ({
93
+ name
122
94
  }))
123
95
  });
96
+ log.info("registered", {
97
+ registrationId,
98
+ endpoint
99
+ }, {
100
+ F: __dxlog_file,
101
+ L: 98,
102
+ S: this,
103
+ C: (f, a) => f(...a)
104
+ });
124
105
  this._registrationId = registrationId;
106
+ this._proxy = endpoint;
125
107
  } catch (err) {
126
108
  await this.stop();
127
- throw new Error("FunctionRegistryService not available; check config (agent.plugins.functions).");
109
+ throw new Error("FunctionRegistryService not available (check plugin is configured).");
128
110
  }
129
111
  }
130
112
  async stop() {
@@ -134,31 +116,111 @@ var DevServer = class {
134
116
  await this._client.services.services.FunctionRegistryService.unregister({
135
117
  registrationId: this._registrationId
136
118
  });
119
+ log.info("unregistered", {
120
+ registrationId: this._registrationId
121
+ }, {
122
+ F: __dxlog_file,
123
+ L: 115,
124
+ S: this,
125
+ C: (f, a) => f(...a)
126
+ });
137
127
  this._registrationId = void 0;
128
+ this._proxy = void 0;
138
129
  }
139
130
  trigger.wake();
140
131
  });
141
132
  await trigger.wait();
142
- this._server = void 0;
143
133
  this._port = void 0;
134
+ this._server = void 0;
135
+ }
136
+ /**
137
+ * Load function.
138
+ */
139
+ async _load(def, flush = false) {
140
+ const { id, name, handler } = def;
141
+ const path = join(this._options.directory, handler);
142
+ log.info("loading", {
143
+ id
144
+ }, {
145
+ F: __dxlog_file,
146
+ L: 134,
147
+ S: this,
148
+ C: (f, a) => f(...a)
149
+ });
150
+ if (flush) {
151
+ Object.keys(__require.cache).filter((key) => key.startsWith(path)).forEach((key) => delete __require.cache[key]);
152
+ }
153
+ const module = __require(path);
154
+ if (typeof module.default !== "function") {
155
+ throw new Error(`Handler must export default function: ${id}`);
156
+ }
157
+ this._handlers[name] = {
158
+ def,
159
+ handler: module.default
160
+ };
161
+ }
162
+ /**
163
+ * Invoke function handler.
164
+ */
165
+ async _invoke(name, event) {
166
+ const seq = ++this._seq;
167
+ const now = Date.now();
168
+ log.info("req", {
169
+ seq,
170
+ name
171
+ }, {
172
+ F: __dxlog_file,
173
+ L: 159,
174
+ S: this,
175
+ C: (f, a) => f(...a)
176
+ });
177
+ const { handler } = this._handlers[name];
178
+ const context = {
179
+ client: this._client
180
+ };
181
+ let statusCode = 200;
182
+ const response = {
183
+ status: (code) => {
184
+ statusCode = code;
185
+ return response;
186
+ }
187
+ };
188
+ await handler({
189
+ context,
190
+ event,
191
+ response
192
+ });
193
+ log.info("res", {
194
+ seq,
195
+ name,
196
+ statusCode,
197
+ duration: Date.now() - now
198
+ }, {
199
+ F: __dxlog_file,
200
+ L: 175,
201
+ S: this,
202
+ C: (f, a) => f(...a)
203
+ });
204
+ return statusCode;
144
205
  }
145
206
  };
146
207
 
147
- // packages/core/functions/src/runtime/trigger-manager.ts
148
- import { DeferredTask } from "@dxos/async";
208
+ // packages/core/functions/src/runtime/scheduler.ts
209
+ import { CronJob } from "cron";
210
+ import { debounce, DeferredTask } from "@dxos/async";
211
+ import { TextObject } from "@dxos/client/echo";
149
212
  import { Context } from "@dxos/context";
150
- import { Filter, createSubscription } from "@dxos/echo-schema";
151
- import { invariant } from "@dxos/invariant";
213
+ import { Filter, createSubscription, subscribe } from "@dxos/echo-schema";
214
+ import { invariant as invariant2 } from "@dxos/invariant";
152
215
  import { log as log2 } from "@dxos/log";
153
216
  import { ComplexMap } from "@dxos/util";
154
- var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/core/functions/src/runtime/trigger-manager.ts";
155
- var TriggerManager = class {
156
- constructor(_client, _manifest, _invokeOptions) {
217
+ var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/core/functions/src/runtime/scheduler.ts";
218
+ var Scheduler = class {
219
+ constructor(_client, _manifest, _options) {
157
220
  this._client = _client;
158
221
  this._manifest = _manifest;
159
- this._invokeOptions = _invokeOptions;
160
- this._mounts = new ComplexMap(({ name, spaceKey }) => `${spaceKey.toHex()}:${name}`);
161
- this._queries = /* @__PURE__ */ new Set();
222
+ this._options = _options;
223
+ this._mounts = new ComplexMap(({ id, spaceKey }) => `${spaceKey.toHex()}:${id}`);
162
224
  }
163
225
  async start() {
164
226
  this._client.spaces.subscribe(async (spaces) => {
@@ -171,22 +233,22 @@ var TriggerManager = class {
171
233
  });
172
234
  }
173
235
  async stop() {
174
- for (const { name, spaceKey } of this._mounts.keys()) {
175
- await this.unmount(name, spaceKey);
236
+ for (const { id, spaceKey } of this._mounts.keys()) {
237
+ await this.unmount(id, spaceKey);
176
238
  }
177
239
  }
178
240
  async mount(ctx, space, trigger) {
179
241
  const key = {
180
- name: trigger.function,
242
+ id: trigger.function,
181
243
  spaceKey: space.key
182
244
  };
183
- const config = this._manifest.functions.find((config2) => config2.id === trigger.function);
184
- invariant(config, `Function not found: ${trigger.function}`, {
245
+ const def = this._manifest.functions.find((config) => config.id === trigger.function);
246
+ invariant2(def, `Function not found: ${trigger.function}`, {
185
247
  F: __dxlog_file2,
186
- L: 58,
248
+ L: 59,
187
249
  S: this,
188
250
  A: [
189
- "config",
251
+ "def",
190
252
  "`Function not found: ${trigger.function}`"
191
253
  ]
192
254
  });
@@ -196,62 +258,82 @@ var TriggerManager = class {
196
258
  ctx,
197
259
  trigger
198
260
  });
199
- log2("mount", {
261
+ log2.info("mount", {
200
262
  space: space.key,
201
263
  trigger
202
264
  }, {
203
265
  F: __dxlog_file2,
204
- L: 62,
266
+ L: 64,
205
267
  S: this,
206
268
  C: (f, a) => f(...a)
207
269
  });
208
270
  if (ctx.disposed) {
209
271
  return;
210
272
  }
211
- const objectIds = /* @__PURE__ */ new Set();
212
- const task = new DeferredTask(ctx, async () => {
213
- await this.execFunction(this._invokeOptions, config.endpoint, {
214
- space: space.key,
215
- objects: Array.from(objectIds)
273
+ if (trigger.schedule) {
274
+ const task = new DeferredTask(ctx, async () => {
275
+ await this.execFunction(def, {
276
+ space: space.key
277
+ });
216
278
  });
217
- });
218
- let count = 0;
219
- const subscription = createSubscription(({ added, updated }) => {
220
- for (const object of added) {
221
- objectIds.add(object.id);
222
- }
223
- for (const object of updated) {
224
- objectIds.add(object.id);
225
- }
226
- log2("updated", {
227
- trigger,
228
- space: space.key,
229
- objects: objectIds.size,
230
- count
231
- }, {
232
- F: __dxlog_file2,
233
- L: 85,
234
- S: this,
235
- C: (f, a) => f(...a)
279
+ const job = new CronJob(trigger.schedule, () => task.schedule());
280
+ job.start();
281
+ ctx.onDispose(() => job.stop());
282
+ }
283
+ if (trigger.subscription) {
284
+ const objectIds = /* @__PURE__ */ new Set();
285
+ const task = new DeferredTask(ctx, async () => {
286
+ await this.execFunction(def, {
287
+ space: space.key,
288
+ objects: Array.from(objectIds)
289
+ });
236
290
  });
237
- task.schedule();
238
- count++;
239
- });
240
- const query = space.db.query(Filter.typename(trigger.subscription.type, trigger.subscription.props));
241
- this._queries.add(query);
242
- const unsubscribe = query.subscribe(({ objects }) => {
243
- subscription.update(objects);
244
- }, true);
245
- ctx.onDispose(() => {
246
- subscription.unsubscribe();
247
- unsubscribe();
248
- this._queries.delete(query);
249
- });
291
+ const subscriptions = [];
292
+ const subscription = createSubscription(({ added, updated }) => {
293
+ for (const object of added) {
294
+ objectIds.add(object.id);
295
+ }
296
+ for (const object of updated) {
297
+ objectIds.add(object.id);
298
+ }
299
+ task.schedule();
300
+ });
301
+ subscriptions.push(() => subscription.unsubscribe());
302
+ const { type, props, deep, delay } = trigger.subscription;
303
+ const update = ({ objects }) => {
304
+ subscription.update(objects);
305
+ if (deep) {
306
+ log2.info("update", {
307
+ type,
308
+ deep,
309
+ objects: objects.length
310
+ }, {
311
+ F: __dxlog_file2,
312
+ L: 114,
313
+ S: this,
314
+ C: (f, a) => f(...a)
315
+ });
316
+ for (const object of objects) {
317
+ const content = object.content;
318
+ if (content instanceof TextObject) {
319
+ subscriptions.push(content[subscribe](debounce(() => subscription.update([
320
+ object
321
+ ]), 1e3)));
322
+ }
323
+ }
324
+ }
325
+ };
326
+ const query = space.db.query(Filter.typename(type, props));
327
+ subscriptions.push(query.subscribe(delay ? debounce(update, delay * 1e3) : update));
328
+ ctx.onDispose(() => {
329
+ subscriptions.forEach((unsubscribe) => unsubscribe());
330
+ });
331
+ }
250
332
  }
251
333
  }
252
- async unmount(name, spaceKey) {
334
+ async unmount(id, spaceKey) {
253
335
  const key = {
254
- name,
336
+ id,
255
337
  spaceKey
256
338
  };
257
339
  const { ctx } = this._mounts.get(key) ?? {};
@@ -260,59 +342,39 @@ var TriggerManager = class {
260
342
  await ctx.dispose();
261
343
  }
262
344
  }
263
- async execFunction(options, functionName, data) {
264
- const { endpoint, runtime } = options;
265
- invariant(endpoint, "Missing endpoint", {
266
- F: __dxlog_file2,
267
- L: 121,
268
- S: this,
269
- A: [
270
- "endpoint",
271
- "'Missing endpoint'"
272
- ]
273
- });
274
- invariant(runtime, "Missing runtime", {
275
- F: __dxlog_file2,
276
- L: 122,
277
- S: this,
278
- A: [
279
- "runtime",
280
- "'Missing runtime'"
281
- ]
282
- });
345
+ async execFunction(def, data) {
283
346
  try {
284
- log2("invoke", {
285
- function: functionName
347
+ log2("request", {
348
+ function: def.id
286
349
  }, {
287
350
  F: __dxlog_file2,
288
- L: 125,
351
+ L: 147,
289
352
  S: this,
290
353
  C: (f, a) => f(...a)
291
354
  });
292
- const url = `${endpoint}/${runtime}/${functionName}`;
293
- const res = await fetch(url, {
355
+ const response = await fetch(`${this._options.endpoint}/${def.name}`, {
294
356
  method: "POST",
295
- body: JSON.stringify(data),
296
357
  headers: {
297
358
  "Content-Type": "application/json"
298
- }
359
+ },
360
+ body: JSON.stringify(data)
299
361
  });
300
362
  log2("result", {
301
- function: functionName,
302
- result: await res.json()
363
+ function: def.id,
364
+ result: response.status
303
365
  }, {
304
366
  F: __dxlog_file2,
305
- L: 135,
367
+ L: 157,
306
368
  S: this,
307
369
  C: (f, a) => f(...a)
308
370
  });
309
371
  } catch (err) {
310
372
  log2.error("error", {
311
- function: functionName,
373
+ function: def.id,
312
374
  error: err.message
313
375
  }, {
314
376
  F: __dxlog_file2,
315
- L: 137,
377
+ L: 159,
316
378
  S: this,
317
379
  C: (f, a) => f(...a)
318
380
  });
@@ -321,6 +383,6 @@ var TriggerManager = class {
321
383
  };
322
384
  export {
323
385
  DevServer,
324
- TriggerManager
386
+ Scheduler
325
387
  };
326
388
  //# sourceMappingURL=index.mjs.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../../../src/runtime/dev-server.ts", "../../../src/runtime/trigger-manager.ts"],
4
- "sourcesContent": ["//\n// Copyright 2023 DXOS.org\n//\n\nimport express from 'express';\nimport type http from 'http';\nimport { join } from 'node:path';\nimport { getPortPromise } from 'portfinder';\n\nimport { Trigger } from '@dxos/async';\nimport { type Client } from '@dxos/client';\nimport { log } from '@dxos/log';\n\nimport { type FunctionContext, type FunctionHandler, type Response } from '../handler';\nimport { type FunctionDef, type FunctionManifest } from '../manifest';\n\nconst DEFAULT_PORT = 7001;\n\nexport type DevServerOptions = {\n directory: string;\n manifest: FunctionManifest;\n};\n\n/**\n * Functions dev server provides a local HTTP server for testing functions.\n */\nexport class DevServer {\n private readonly _handlers: Record<string, { def: FunctionDef; handler: FunctionHandler<any> }> = {};\n\n private _server?: http.Server;\n private _port?: number;\n private _registrationId?: string;\n\n // prettier-ignore\n constructor(\n private readonly _client: Client,\n private readonly _options: DevServerOptions,\n ) {}\n\n get port() {\n return this._port;\n }\n\n get endpoint() {\n return this._port ? `http://localhost:${this._port}` : undefined;\n }\n\n get functions() {\n return Object.values(this._handlers);\n }\n\n async initialize() {\n for (const def of this._options.manifest.functions) {\n const { id, endpoint, handler: path } = def;\n try {\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const module = require(join(this._options.directory, path));\n const handler = module.default;\n if (typeof handler !== 'function') {\n throw new Error(`Handler must export default function: ${id}`);\n }\n\n if (this._handlers[endpoint]) {\n log.warn(`Function already registered: ${id}`);\n }\n\n this._handlers[endpoint] = { def, handler };\n } catch (err) {\n log.error('parsing function (check manifest)', err);\n }\n }\n }\n\n async start() {\n const app = express();\n app.use(express.json());\n\n app.post('/:endpoint', async (req, res) => {\n const { endpoint } = req.params;\n\n const response: Response = {\n status: (code: number) => {\n res.statusCode = code;\n return response;\n },\n\n succeed: (result = {}) => {\n res.end(JSON.stringify(result));\n return response;\n },\n };\n\n const context: FunctionContext = {\n client: this._client,\n status: response.status.bind(response),\n };\n\n void (async () => {\n try {\n log('invoking', { endpoint });\n const { handler } = this._handlers[endpoint];\n const response = await handler({ context, event: req.body });\n log('done', { response });\n } catch (err: any) {\n res.statusCode = 500;\n res.end(err.message);\n }\n })();\n });\n\n this._port = await getPortPromise({ startPort: DEFAULT_PORT });\n this._server = app.listen(this._port);\n\n // TODO(burdon): Check plugin is registered.\n // TypeError: Cannot read properties of undefined (reading 'register')\n try {\n const { registrationId } = await this._client.services.services.FunctionRegistryService!.register({\n endpoint: this.endpoint!,\n functions: this.functions.map(({ def: { endpoint } }) => ({ name: endpoint })), // TODO(burdon): Change proto name => id.\n });\n\n this._registrationId = registrationId;\n } catch (err: any) {\n await this.stop();\n throw new Error('FunctionRegistryService not available; check config (agent.plugins.functions).');\n }\n }\n\n async stop() {\n const trigger = new Trigger();\n this._server?.close(async () => {\n if (this._registrationId) {\n await this._client.services.services.FunctionRegistryService!.unregister({\n registrationId: this._registrationId,\n });\n this._registrationId = undefined;\n }\n\n trigger.wake();\n });\n\n await trigger.wait();\n this._server = undefined;\n this._port = undefined;\n }\n}\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { DeferredTask } from '@dxos/async';\nimport { type Client, type PublicKey } from '@dxos/client';\nimport type { Query, Space } from '@dxos/client/echo';\nimport { Context } from '@dxos/context';\nimport { Filter, createSubscription } from '@dxos/echo-schema';\nimport { invariant } from '@dxos/invariant';\nimport { log } from '@dxos/log';\nimport { ComplexMap } from '@dxos/util';\n\nimport { type FunctionManifest, type FunctionTrigger } from '../manifest';\n\n// TODO(burdon): Rename.\nexport type InvokeOptions = {\n endpoint: string;\n runtime: string;\n};\n\nexport class TriggerManager {\n private readonly _mounts = new ComplexMap<\n { name: string; spaceKey: PublicKey },\n { ctx: Context; trigger: FunctionTrigger }\n >(({ name, spaceKey }) => `${spaceKey.toHex()}:${name}`);\n\n private readonly _queries = new Set<Query>();\n\n constructor(\n private readonly _client: Client,\n private readonly _manifest: FunctionManifest,\n private readonly _invokeOptions: InvokeOptions,\n ) {}\n\n async start() {\n // TODO(burdon): Make runtime configurable (via CLI)?\n this._client.spaces.subscribe(async (spaces) => {\n for (const space of spaces) {\n await space.waitUntilReady();\n for (const trigger of this._manifest.triggers ?? []) {\n // TODO(burdon): New context? Shared?\n await this.mount(new Context(), space, trigger);\n }\n }\n });\n }\n\n async stop() {\n for (const { name, spaceKey } of this._mounts.keys()) {\n await this.unmount(name, spaceKey);\n }\n }\n\n private async mount(ctx: Context, space: Space, trigger: FunctionTrigger) {\n const key = { name: trigger.function, spaceKey: space.key };\n const config = this._manifest.functions.find((config) => config.id === trigger.function);\n invariant(config, `Function not found: ${trigger.function}`);\n const exists = this._mounts.get(key);\n if (!exists) {\n this._mounts.set(key, { ctx, trigger });\n log('mount', { space: space.key, trigger });\n if (ctx.disposed) {\n return;\n }\n\n // TODO(burdon): Why DeferredTask? How to pass objectIds to function?\n const objectIds = new Set<string>();\n const task = new DeferredTask(ctx, async () => {\n await this.execFunction(this._invokeOptions, config.endpoint, {\n space: space.key,\n objects: Array.from(objectIds),\n });\n });\n\n let count = 0;\n const subscription = createSubscription(({ added, updated }) => {\n for (const object of added) {\n objectIds.add(object.id);\n }\n for (const object of updated) {\n objectIds.add(object.id);\n }\n\n log('updated', {\n trigger,\n space: space.key,\n objects: objectIds.size,\n count,\n });\n\n task.schedule();\n count++;\n });\n // TODO(burdon): DSL for query (replace props).\n const query = space.db.query(Filter.typename(trigger.subscription.type, trigger.subscription.props));\n this._queries.add(query);\n const unsubscribe = query.subscribe(({ objects }) => {\n subscription.update(objects);\n }, true);\n\n ctx.onDispose(() => {\n subscription.unsubscribe();\n unsubscribe();\n this._queries.delete(query);\n });\n }\n }\n\n private async unmount(name: string, spaceKey: PublicKey) {\n const key = { name, spaceKey };\n const { ctx } = this._mounts.get(key) ?? {};\n if (ctx) {\n this._mounts.delete(key);\n await ctx.dispose();\n }\n }\n\n private async execFunction(options: InvokeOptions, functionName: string, data: any) {\n const { endpoint, runtime } = options;\n invariant(endpoint, 'Missing endpoint');\n invariant(runtime, 'Missing runtime');\n\n try {\n log('invoke', { function: functionName });\n const url = `${endpoint}/${runtime}/${functionName}`;\n const res = await fetch(url, {\n method: 'POST',\n body: JSON.stringify(data),\n headers: {\n 'Content-Type': 'application/json',\n },\n });\n\n log('result', { function: functionName, result: await res.json() });\n } catch (err: any) {\n log.error('error', { function: functionName, error: err.message });\n }\n }\n}\n"],
5
- "mappings": "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",
6
- "names": ["express", "join", "getPortPromise", "Trigger", "log", "DEFAULT_PORT", "DevServer", "constructor", "_client", "_options", "_handlers", "port", "_port", "endpoint", "undefined", "functions", "Object", "values", "initialize", "def", "manifest", "id", "handler", "path", "module", "require", "join", "directory", "default", "Error", "log", "warn", "err", "error", "start", "app", "express", "use", "json", "post", "req", "res", "params", "response", "status", "code", "statusCode", "succeed", "result", "end", "JSON", "stringify", "context", "client", "bind", "event", "body", "message", "getPortPromise", "startPort", "_server", "listen", "registrationId", "services", "FunctionRegistryService", "register", "map", "name", "_registrationId", "stop", "trigger", "Trigger", "close", "unregister", "wake", "wait", "DeferredTask", "Context", "Filter", "createSubscription", "invariant", "log", "ComplexMap", "TriggerManager", "constructor", "_client", "_manifest", "_invokeOptions", "_mounts", "name", "spaceKey", "toHex", "_queries", "Set", "start", "spaces", "subscribe", "space", "waitUntilReady", "trigger", "triggers", "mount", "stop", "keys", "unmount", "ctx", "key", "function", "config", "functions", "find", "id", "exists", "get", "set", "disposed", "objectIds", "task", "execFunction", "endpoint", "objects", "Array", "from", "count", "subscription", "added", "updated", "object", "add", "size", "schedule", "query", "db", "typename", "type", "props", "unsubscribe", "update", "onDispose", "delete", "dispose", "options", "functionName", "data", "runtime", "url", "res", "fetch", "method", "body", "JSON", "stringify", "headers", "result", "json", "err", "error", "message"]
3
+ "sources": ["../../../src/runtime/dev-server.ts", "../../../src/runtime/scheduler.ts"],
4
+ "sourcesContent": ["//\n// Copyright 2023 DXOS.org\n//\n\nimport express from 'express';\nimport { getPort } from 'get-port-please';\nimport type http from 'http';\nimport { join } from 'node:path';\n\nimport { Trigger } from '@dxos/async';\nimport { type Client } from '@dxos/client';\nimport { invariant } from '@dxos/invariant';\nimport { log } from '@dxos/log';\n\nimport { type FunctionContext, type FunctionHandler, type Response } from '../handler';\nimport { type FunctionDef, type FunctionManifest } from '../manifest';\n\nexport type DevServerOptions = {\n port?: number;\n directory: string;\n manifest: FunctionManifest;\n reload?: boolean;\n};\n\n/**\n * Functions dev server provides a local HTTP server for testing functions.\n */\nexport class DevServer {\n // Function handlers indexed by name (URL path).\n private readonly _handlers: Record<string, { def: FunctionDef; handler: FunctionHandler<any> }> = {};\n\n private _server?: http.Server;\n private _port?: number;\n private _registrationId?: string;\n private _proxy?: string;\n private _seq = 0;\n\n // prettier-ignore\n constructor(\n private readonly _client: Client,\n private readonly _options: DevServerOptions,\n ) {}\n\n get endpoint() {\n invariant(this._port);\n return `http://localhost:${this._port}`;\n }\n\n get proxy() {\n return this._proxy;\n }\n\n get functions() {\n return Object.values(this._handlers);\n }\n\n async initialize() {\n for (const def of this._options.manifest.functions) {\n try {\n await this._load(def);\n } catch (err) {\n log.error('parsing function (check manifest)', err);\n }\n }\n }\n\n async start() {\n const app = express();\n app.use(express.json());\n\n app.post('/:name', async (req, res) => {\n const { name } = req.params;\n try {\n if (this._options.reload) {\n const { def } = this._handlers[name];\n await this._load(def, true);\n }\n\n res.statusCode = await this._invoke(name, req.body);\n res.end();\n } catch (err: any) {\n log.catch(err);\n res.statusCode = 500;\n res.end();\n }\n });\n\n this._port = await getPort({ port: 7200, portRange: [7200, 7299] });\n this._server = app.listen(this._port);\n\n try {\n // Register functions.\n const { registrationId, endpoint } = await this._client.services.services.FunctionRegistryService!.register({\n endpoint: this.endpoint,\n functions: this.functions.map(({ def: { name } }) => ({ name })),\n });\n\n log.info('registered', { registrationId, endpoint });\n this._registrationId = registrationId;\n this._proxy = endpoint;\n } catch (err: any) {\n await this.stop();\n throw new Error('FunctionRegistryService not available (check plugin is configured).');\n }\n }\n\n async stop() {\n const trigger = new Trigger();\n this._server?.close(async () => {\n if (this._registrationId) {\n await this._client.services.services.FunctionRegistryService!.unregister({\n registrationId: this._registrationId,\n });\n\n log.info('unregistered', { registrationId: this._registrationId });\n this._registrationId = undefined;\n this._proxy = undefined;\n }\n\n trigger.wake();\n });\n\n await trigger.wait();\n this._port = undefined;\n this._server = undefined;\n }\n\n /**\n * Load function.\n */\n private async _load(def: FunctionDef, flush = false) {\n const { id, name, handler } = def;\n const path = join(this._options.directory, handler);\n log.info('loading', { id });\n\n // Remove from cache.\n if (flush) {\n Object.keys(require.cache)\n .filter((key) => key.startsWith(path))\n .forEach((key) => delete require.cache[key]);\n }\n\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const module = require(path);\n if (typeof module.default !== 'function') {\n throw new Error(`Handler must export default function: ${id}`);\n }\n\n this._handlers[name] = { def, handler: module.default };\n }\n\n /**\n * Invoke function handler.\n */\n private async _invoke(name: string, event: any) {\n const seq = ++this._seq;\n const now = Date.now();\n\n log.info('req', { seq, name });\n const { handler } = this._handlers[name];\n\n const context: FunctionContext = {\n client: this._client,\n };\n\n let statusCode = 200;\n const response: Response = {\n status: (code: number) => {\n statusCode = code;\n return response;\n },\n };\n\n await handler({ context, event, response });\n log.info('res', { seq, name, statusCode, duration: Date.now() - now });\n\n return statusCode;\n }\n}\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { CronJob } from 'cron';\n\nimport { debounce, DeferredTask } from '@dxos/async';\nimport { type Client, type PublicKey } from '@dxos/client';\nimport { type Space, TextObject } from '@dxos/client/echo';\nimport { Context } from '@dxos/context';\nimport { Filter, createSubscription, type Query, subscribe } from '@dxos/echo-schema';\nimport { invariant } from '@dxos/invariant';\nimport { log } from '@dxos/log';\nimport { ComplexMap } from '@dxos/util';\n\nimport { type FunctionDef, type FunctionManifest, type FunctionTrigger } from '../manifest';\n\ntype SchedulerOptions = {\n endpoint: string;\n};\n\n/**\n * Functions scheduler.\n */\n// TODO(burdon): Create tests.\nexport class Scheduler {\n // Map of mounted functions.\n private readonly _mounts = new ComplexMap<\n { id: string; spaceKey: PublicKey },\n { ctx: Context; trigger: FunctionTrigger }\n >(({ id, spaceKey }) => `${spaceKey.toHex()}:${id}`);\n\n constructor(\n private readonly _client: Client,\n private readonly _manifest: FunctionManifest,\n private readonly _options: SchedulerOptions,\n ) {}\n\n async start() {\n this._client.spaces.subscribe(async (spaces) => {\n for (const space of spaces) {\n await space.waitUntilReady();\n for (const trigger of this._manifest.triggers ?? []) {\n await this.mount(new Context(), space, trigger);\n }\n }\n });\n }\n\n async stop() {\n for (const { id, spaceKey } of this._mounts.keys()) {\n await this.unmount(id, spaceKey);\n }\n }\n\n private async mount(ctx: Context, space: Space, trigger: FunctionTrigger) {\n const key = { id: trigger.function, spaceKey: space.key };\n const def = this._manifest.functions.find((config) => config.id === trigger.function);\n invariant(def, `Function not found: ${trigger.function}`);\n\n const exists = this._mounts.get(key);\n if (!exists) {\n this._mounts.set(key, { ctx, trigger });\n log.info('mount', { space: space.key, trigger });\n if (ctx.disposed) {\n return;\n }\n\n // Cron schedule.\n if (trigger.schedule) {\n const task = new DeferredTask(ctx, async () => {\n await this.execFunction(def, {\n space: space.key,\n });\n });\n\n // TODO(burdon): Check greater than 30s min (use cron-parser).\n const job = new CronJob(trigger.schedule, () => task.schedule());\n\n job.start();\n ctx.onDispose(() => job.stop());\n }\n\n // ECHO subscription.\n if (trigger.subscription) {\n const objectIds = new Set<string>();\n const task = new DeferredTask(ctx, async () => {\n await this.execFunction(def, {\n space: space.key,\n objects: Array.from(objectIds),\n });\n });\n\n // TODO(burdon): Standardize subscription handles.\n const subscriptions: (() => void)[] = [];\n const subscription = createSubscription(({ added, updated }) => {\n for (const object of added) {\n objectIds.add(object.id);\n }\n for (const object of updated) {\n objectIds.add(object.id);\n }\n\n task.schedule();\n });\n subscriptions.push(() => subscription.unsubscribe());\n\n const { type, props, deep, delay } = trigger.subscription;\n const update = ({ objects }: Query) => {\n subscription.update(objects);\n\n // TODO(burdon): Hack to monitor changes to Document's text object.\n if (deep) {\n log.info('update', { type, deep, objects: objects.length });\n for (const object of objects) {\n const content = object.content;\n if (content instanceof TextObject) {\n subscriptions.push(content[subscribe](debounce(() => subscription.update([object]), 1_000)));\n }\n }\n }\n };\n\n // TODO(burdon): [Bug]: all callbacks are fired on the first mutation.\n // TODO(burdon): [Bug]: not updated when document is deleted (either top or hierarchically).\n const query = space.db.query(Filter.typename(type, props));\n subscriptions.push(query.subscribe(delay ? debounce(update, delay * 1_000) : update));\n\n ctx.onDispose(() => {\n subscriptions.forEach((unsubscribe) => unsubscribe());\n });\n }\n }\n }\n\n private async unmount(id: string, spaceKey: PublicKey) {\n const key = { id, spaceKey };\n const { ctx } = this._mounts.get(key) ?? {};\n if (ctx) {\n this._mounts.delete(key);\n await ctx.dispose();\n }\n }\n\n private async execFunction(def: FunctionDef, data: any) {\n try {\n log('request', { function: def.id });\n const response = await fetch(`${this._options.endpoint}/${def.name}`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(data),\n });\n\n // const result = await response.json();\n log('result', { function: def.id, result: response.status });\n } catch (err: any) {\n log.error('error', { function: def.id, error: err.message });\n }\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["express", "getPort", "join", "Trigger", "invariant", "log", "DevServer", "constructor", "_client", "_options", "_handlers", "_seq", "endpoint", "invariant", "_port", "proxy", "_proxy", "functions", "Object", "values", "initialize", "def", "manifest", "_load", "err", "log", "error", "start", "app", "express", "use", "json", "post", "req", "res", "name", "params", "reload", "statusCode", "_invoke", "body", "end", "catch", "getPort", "port", "portRange", "_server", "listen", "registrationId", "services", "FunctionRegistryService", "register", "map", "info", "_registrationId", "stop", "Error", "trigger", "Trigger", "close", "unregister", "undefined", "wake", "wait", "flush", "id", "handler", "path", "join", "directory", "keys", "require", "cache", "filter", "key", "startsWith", "forEach", "module", "default", "event", "seq", "now", "Date", "context", "client", "response", "status", "code", "duration", "CronJob", "debounce", "DeferredTask", "TextObject", "Context", "Filter", "createSubscription", "subscribe", "invariant", "log", "ComplexMap", "Scheduler", "constructor", "_client", "_manifest", "_options", "_mounts", "id", "spaceKey", "toHex", "start", "spaces", "space", "waitUntilReady", "trigger", "triggers", "mount", "stop", "keys", "unmount", "ctx", "key", "function", "def", "functions", "find", "config", "exists", "get", "set", "info", "disposed", "schedule", "task", "execFunction", "job", "onDispose", "subscription", "objectIds", "Set", "objects", "Array", "from", "subscriptions", "added", "updated", "object", "add", "push", "unsubscribe", "type", "props", "deep", "delay", "update", "length", "content", "query", "db", "typename", "forEach", "delete", "dispose", "data", "response", "fetch", "endpoint", "name", "method", "headers", "body", "JSON", "stringify", "result", "status", "err", "error", "message"]
7
7
  }