@dxos/functions 0.3.8-main.152ec6f → 0.3.8-main.1b6c849

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.
@@ -29,7 +29,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
29
29
  var node_exports = {};
30
30
  __export(node_exports, {
31
31
  DevServer: () => DevServer,
32
- TriggerManager: () => TriggerManager
32
+ Scheduler: () => Scheduler
33
33
  });
34
34
  module.exports = __toCommonJS(node_exports);
35
35
  var import_express = __toESM(require("express"));
@@ -38,6 +38,7 @@ var import_node_path = require("node:path");
38
38
  var import_async = require("@dxos/async");
39
39
  var import_invariant = require("@dxos/invariant");
40
40
  var import_log = require("@dxos/log");
41
+ var import_cron = require("cron");
41
42
  var import_async2 = require("@dxos/async");
42
43
  var import_context = require("@dxos/context");
43
44
  var import_echo_schema = require("@dxos/echo-schema");
@@ -58,11 +59,12 @@ var DevServer = class {
58
59
  this._client = _client;
59
60
  this._options = _options;
60
61
  this._handlers = {};
62
+ this._seq = 0;
61
63
  }
62
64
  get endpoint() {
63
65
  (0, import_invariant.invariant)(this._port, void 0, {
64
66
  F: __dxlog_file,
65
- L: 43,
67
+ L: 45,
66
68
  S: this,
67
69
  A: [
68
70
  "this._port",
@@ -79,29 +81,12 @@ var DevServer = class {
79
81
  }
80
82
  async initialize() {
81
83
  for (const def of this._options.manifest.functions) {
82
- const { id, path, handler: dir } = def;
83
84
  try {
84
- const module2 = __require((0, import_node_path.join)(this._options.directory, dir));
85
- const handler = module2.default;
86
- if (typeof handler !== "function") {
87
- throw new Error(`Handler must export default function: ${id}`);
88
- }
89
- if (this._handlers[path]) {
90
- import_log.log.warn(`Function already registered: ${id}`, void 0, {
91
- F: __dxlog_file,
92
- L: 67,
93
- S: this,
94
- C: (f, a) => f(...a)
95
- });
96
- }
97
- this._handlers[path] = {
98
- def,
99
- handler
100
- };
85
+ await this._load(def);
101
86
  } catch (err) {
102
87
  import_log.log.error("parsing function (check manifest)", err, {
103
88
  F: __dxlog_file,
104
- L: 72,
89
+ L: 62,
105
90
  S: this,
106
91
  C: (f, a) => f(...a)
107
92
  });
@@ -113,46 +98,23 @@ var DevServer = class {
113
98
  app.use(import_express.default.json());
114
99
  app.post("/:name", async (req, res) => {
115
100
  const { name } = req.params;
116
- const response = {
117
- status: (code) => {
118
- res.statusCode = code;
119
- return response;
120
- },
121
- succeed: (result = {}) => {
122
- res.end(JSON.stringify(result));
123
- return response;
124
- }
125
- };
126
- const context = {
127
- client: this._client,
128
- status: response.status.bind(response)
129
- };
130
- void (async () => {
131
- try {
132
- (0, import_log.log)(`invoking: ${name}`, void 0, {
133
- F: __dxlog_file,
134
- L: 103,
135
- S: this,
136
- C: (f, a) => f(...a)
137
- });
138
- const { handler } = this._handlers[name];
139
- const response2 = await handler({
140
- context,
141
- event: req.body
142
- });
143
- (0, import_log.log)("done", {
144
- response: response2
145
- }, {
146
- F: __dxlog_file,
147
- L: 106,
148
- S: this,
149
- C: (f, a) => f(...a)
150
- });
151
- } catch (err) {
152
- res.statusCode = 500;
153
- res.end(err.message);
101
+ try {
102
+ if (this._options.reload) {
103
+ const { def } = this._handlers[name];
104
+ await this._load(def, true);
154
105
  }
155
- })();
106
+ res.statusCode = await this._invoke(name, req.body);
107
+ res.end();
108
+ } catch (err) {
109
+ import_log.log.error(err, void 0, {
110
+ F: __dxlog_file,
111
+ L: 82,
112
+ S: this,
113
+ C: (f, a) => f(...a)
114
+ });
115
+ res.statusCode = 500;
116
+ res.end();
117
+ }
156
118
  });
157
119
  this._port = await (0, import_get_port_please.getPort)({
158
120
  port: 7200,
@@ -165,8 +127,8 @@ var DevServer = class {
165
127
  try {
166
128
  const { registrationId, endpoint } = await this._client.services.services.FunctionRegistryService.register({
167
129
  endpoint: this.endpoint,
168
- functions: this.functions.map(({ def: { path } }) => ({
169
- name: path
130
+ functions: this.functions.map(({ def: { name } }) => ({
131
+ name
170
132
  }))
171
133
  });
172
134
  import_log.log.info("registered", {
@@ -174,7 +136,7 @@ var DevServer = class {
174
136
  endpoint
175
137
  }, {
176
138
  F: __dxlog_file,
177
- L: 126,
139
+ L: 98,
178
140
  S: this,
179
141
  C: (f, a) => f(...a)
180
142
  });
@@ -196,7 +158,7 @@ var DevServer = class {
196
158
  registrationId: this._registrationId
197
159
  }, {
198
160
  F: __dxlog_file,
199
- L: 143,
161
+ L: 115,
200
162
  S: this,
201
163
  C: (f, a) => f(...a)
202
164
  });
@@ -209,15 +171,84 @@ var DevServer = class {
209
171
  this._port = void 0;
210
172
  this._server = void 0;
211
173
  }
174
+ /**
175
+ * Load function.
176
+ */
177
+ async _load(def, flush = false) {
178
+ const { id, name, handler } = def;
179
+ const path = (0, import_node_path.join)(this._options.directory, handler);
180
+ import_log.log.info("loading", {
181
+ id
182
+ }, {
183
+ F: __dxlog_file,
184
+ L: 134,
185
+ S: this,
186
+ C: (f, a) => f(...a)
187
+ });
188
+ if (flush) {
189
+ Object.keys(__require.cache).filter((key) => key.startsWith(path)).forEach((key) => delete __require.cache[key]);
190
+ }
191
+ const module2 = __require(path);
192
+ if (typeof module2.default !== "function") {
193
+ throw new Error(`Handler must export default function: ${id}`);
194
+ }
195
+ this._handlers[name] = {
196
+ def,
197
+ handler: module2.default
198
+ };
199
+ }
200
+ /**
201
+ * Invoke function handler.
202
+ */
203
+ async _invoke(name, event) {
204
+ const seq = ++this._seq;
205
+ const now = Date.now();
206
+ import_log.log.info("req", {
207
+ seq,
208
+ name
209
+ }, {
210
+ F: __dxlog_file,
211
+ L: 159,
212
+ S: this,
213
+ C: (f, a) => f(...a)
214
+ });
215
+ const { handler } = this._handlers[name];
216
+ const context = {
217
+ client: this._client
218
+ };
219
+ let statusCode = 200;
220
+ const response = {
221
+ status: (code) => {
222
+ statusCode = code;
223
+ return response;
224
+ }
225
+ };
226
+ await handler({
227
+ context,
228
+ event,
229
+ response
230
+ });
231
+ import_log.log.info("res", {
232
+ seq,
233
+ name,
234
+ statusCode,
235
+ duration: Date.now() - now
236
+ }, {
237
+ F: __dxlog_file,
238
+ L: 175,
239
+ S: this,
240
+ C: (f, a) => f(...a)
241
+ });
242
+ return statusCode;
243
+ }
212
244
  };
213
- var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/core/functions/src/runtime/trigger-manager.ts";
214
- var TriggerManager = class {
215
- constructor(_client, _manifest, _invokeOptions) {
245
+ var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/core/functions/src/runtime/scheduler.ts";
246
+ var Scheduler = class {
247
+ constructor(_client, _manifest, _options) {
216
248
  this._client = _client;
217
249
  this._manifest = _manifest;
218
- this._invokeOptions = _invokeOptions;
219
- this._mounts = new import_util.ComplexMap(({ name, spaceKey }) => `${spaceKey.toHex()}:${name}`);
220
- this._queries = /* @__PURE__ */ new Set();
250
+ this._options = _options;
251
+ this._mounts = new import_util.ComplexMap(({ id, spaceKey }) => `${spaceKey.toHex()}:${id}`);
221
252
  }
222
253
  async start() {
223
254
  this._client.spaces.subscribe(async (spaces) => {
@@ -230,22 +261,22 @@ var TriggerManager = class {
230
261
  });
231
262
  }
232
263
  async stop() {
233
- for (const { name, spaceKey } of this._mounts.keys()) {
234
- await this.unmount(name, spaceKey);
264
+ for (const { id, spaceKey } of this._mounts.keys()) {
265
+ await this.unmount(id, spaceKey);
235
266
  }
236
267
  }
237
268
  async mount(ctx, space, trigger) {
238
269
  const key = {
239
- name: trigger.function,
270
+ id: trigger.function,
240
271
  spaceKey: space.key
241
272
  };
242
- const config = this._manifest.functions.find((config2) => config2.id === trigger.function);
243
- (0, import_invariant2.invariant)(config, `Function not found: ${trigger.function}`, {
273
+ const def = this._manifest.functions.find((config) => config.id === trigger.function);
274
+ (0, import_invariant2.invariant)(def, `Function not found: ${trigger.function}`, {
244
275
  F: __dxlog_file2,
245
- L: 57,
276
+ L: 59,
246
277
  S: this,
247
278
  A: [
248
- "config",
279
+ "def",
249
280
  "`Function not found: ${trigger.function}`"
250
281
  ]
251
282
  });
@@ -260,57 +291,55 @@ var TriggerManager = class {
260
291
  trigger
261
292
  }, {
262
293
  F: __dxlog_file2,
263
- L: 61,
294
+ L: 64,
264
295
  S: this,
265
296
  C: (f, a) => f(...a)
266
297
  });
267
298
  if (ctx.disposed) {
268
299
  return;
269
300
  }
270
- const objectIds = /* @__PURE__ */ new Set();
271
- const task = new import_async2.DeferredTask(ctx, async () => {
272
- await this.execFunction(this._invokeOptions, config.path, {
273
- space: space.key,
274
- objects: Array.from(objectIds)
301
+ if (trigger.schedule) {
302
+ const task = new import_async2.DeferredTask(ctx, async () => {
303
+ await this.execFunction(def, {
304
+ space: space.key
305
+ });
275
306
  });
276
- });
277
- let count = 0;
278
- const subscription = (0, import_echo_schema.createSubscription)(({ added, updated }) => {
279
- for (const object of added) {
280
- objectIds.add(object.id);
281
- }
282
- for (const object of updated) {
283
- objectIds.add(object.id);
284
- }
285
- (0, import_log2.log)("updated", {
286
- trigger,
287
- space: space.key,
288
- objects: objectIds.size,
289
- count
290
- }, {
291
- F: __dxlog_file2,
292
- L: 84,
293
- S: this,
294
- C: (f, a) => f(...a)
307
+ const job = new import_cron.CronJob(trigger.schedule, () => task.schedule());
308
+ job.start();
309
+ ctx.onDispose(() => job.stop());
310
+ }
311
+ if (trigger.subscription) {
312
+ const objectIds = /* @__PURE__ */ new Set();
313
+ const task = new import_async2.DeferredTask(ctx, async () => {
314
+ await this.execFunction(def, {
315
+ space: space.key,
316
+ objects: Array.from(objectIds)
317
+ });
295
318
  });
296
- task.schedule();
297
- count++;
298
- });
299
- const query = space.db.query(import_echo_schema.Filter.typename(trigger.subscription.type, trigger.subscription.props));
300
- this._queries.add(query);
301
- const unsubscribe = query.subscribe(({ objects }) => {
302
- subscription.update(objects);
303
- }, true);
304
- ctx.onDispose(() => {
305
- subscription.unsubscribe();
306
- unsubscribe();
307
- this._queries.delete(query);
308
- });
319
+ const subscription = (0, import_echo_schema.createSubscription)(({ added, updated }) => {
320
+ for (const object of added) {
321
+ objectIds.add(object.id);
322
+ }
323
+ for (const object of updated) {
324
+ objectIds.add(object.id);
325
+ }
326
+ task.schedule();
327
+ });
328
+ const { type, props } = trigger.subscription;
329
+ const query = space.db.query(import_echo_schema.Filter.typename(type, props));
330
+ const unsubscribe = query.subscribe(({ objects }) => {
331
+ subscription.update(objects);
332
+ }, true);
333
+ ctx.onDispose(() => {
334
+ subscription.unsubscribe();
335
+ unsubscribe();
336
+ });
337
+ }
309
338
  }
310
339
  }
311
- async unmount(name, spaceKey) {
340
+ async unmount(id, spaceKey) {
312
341
  const key = {
313
- name,
342
+ id,
314
343
  spaceKey
315
344
  };
316
345
  const { ctx } = this._mounts.get(key) ?? {};
@@ -319,50 +348,39 @@ var TriggerManager = class {
319
348
  await ctx.dispose();
320
349
  }
321
350
  }
322
- async execFunction(options, functionName, data) {
323
- const { endpoint } = options;
324
- (0, import_invariant2.invariant)(endpoint, "Missing endpoint", {
325
- F: __dxlog_file2,
326
- L: 120,
327
- S: this,
328
- A: [
329
- "endpoint",
330
- "'Missing endpoint'"
331
- ]
332
- });
351
+ async execFunction(def, data) {
333
352
  try {
334
- (0, import_log2.log)("invoke", {
335
- function: functionName
353
+ (0, import_log2.log)("request", {
354
+ function: def.id
336
355
  }, {
337
356
  F: __dxlog_file2,
338
- L: 123,
357
+ L: 130,
339
358
  S: this,
340
359
  C: (f, a) => f(...a)
341
360
  });
342
- const url = `${endpoint}/${functionName}`;
343
- const res = await fetch(url, {
361
+ const response = await fetch(`${this._options.endpoint}/${def.name}`, {
344
362
  method: "POST",
345
- body: JSON.stringify(data),
346
363
  headers: {
347
364
  "Content-Type": "application/json"
348
- }
365
+ },
366
+ body: JSON.stringify(data)
349
367
  });
350
368
  (0, import_log2.log)("result", {
351
- function: functionName,
352
- result: await res.json()
369
+ function: def.id,
370
+ result: response.status
353
371
  }, {
354
372
  F: __dxlog_file2,
355
- L: 133,
373
+ L: 140,
356
374
  S: this,
357
375
  C: (f, a) => f(...a)
358
376
  });
359
377
  } catch (err) {
360
378
  import_log2.log.error("error", {
361
- function: functionName,
379
+ function: def.id,
362
380
  error: err.message
363
381
  }, {
364
382
  F: __dxlog_file2,
365
- L: 135,
383
+ L: 142,
366
384
  S: this,
367
385
  C: (f, a) => f(...a)
368
386
  });
@@ -372,6 +390,6 @@ var TriggerManager = class {
372
390
  // Annotate the CommonJS export names for ESM import in node:
373
391
  0 && (module.exports = {
374
392
  DevServer,
375
- TriggerManager
393
+ Scheduler
376
394
  });
377
395
  //# sourceMappingURL=index.cjs.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 { 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};\n\n/**\n * Functions dev server provides a local HTTP server for testing functions.\n */\n// TODO(burdon): Reconcile with agent/functions dev dispatcher.\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 private _proxy?: string;\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 const { id, path, handler: dir } = def;\n try {\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const module = require(join(this._options.directory, dir));\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[path]) {\n log.warn(`Function already registered: ${id}`);\n }\n\n this._handlers[path] = { 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('/:name', async (req, res) => {\n const { name } = 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: ${name}`);\n const { handler } = this._handlers[name];\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 // TODO(burdon): Push down port management to agent.\n this._port = await getPort({ port: 7200, portRange: [7200, 7299] });\n this._server = app.listen(this._port);\n\n // TODO(burdon): Test during initialization.\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: { path } }) => ({ name: path })),\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// 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};\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.path, {\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 } = options;\n invariant(endpoint, 'Missing endpoint');\n\n try {\n log('invoke', { function: functionName });\n const url = `${endpoint}/${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": ["import_async", "import_invariant", "import_log", "DevServer", "constructor", "_client", "_options", "_handlers", "endpoint", "invariant", "_port", "proxy", "_proxy", "functions", "Object", "values", "initialize", "def", "manifest", "id", "path", "handler", "dir", "module", "require", "join", "directory", "default", "Error", "log", "warn", "err", "error", "start", "app", "express", "use", "json", "post", "req", "res", "name", "params", "response", "status", "code", "statusCode", "succeed", "result", "end", "JSON", "stringify", "context", "client", "bind", "event", "body", "message", "getPort", "port", "portRange", "_server", "listen", "registrationId", "services", "FunctionRegistryService", "register", "map", "info", "_registrationId", "stop", "trigger", "Trigger", "close", "unregister", "undefined", "wake", "wait", "TriggerManager", "_manifest", "_invokeOptions", "_mounts", "ComplexMap", "spaceKey", "toHex", "_queries", "Set", "spaces", "subscribe", "space", "waitUntilReady", "triggers", "mount", "Context", "keys", "unmount", "ctx", "key", "function", "config", "find", "exists", "get", "set", "disposed", "objectIds", "task", "DeferredTask", "execFunction", "objects", "Array", "from", "count", "subscription", "createSubscription", "added", "updated", "object", "add", "size", "schedule", "query", "db", "Filter", "typename", "type", "props", "unsubscribe", "update", "onDispose", "delete", "dispose", "options", "functionName", "data", "url", "fetch", "method", "headers"]
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.error(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 { DeferredTask } from '@dxos/async';\nimport { type Client, type PublicKey } from '@dxos/client';\nimport { type 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 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('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 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\n const { type, props } = trigger.subscription;\n const query = space.db.query(Filter.typename(type, props));\n const unsubscribe = query.subscribe(({ objects }) => {\n subscription.update(objects);\n }, true);\n\n ctx.onDispose(() => {\n subscription.unsubscribe();\n 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": ["import_async", "import_invariant", "import_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", "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", "Scheduler", "_manifest", "_mounts", "ComplexMap", "spaceKey", "toHex", "spaces", "subscribe", "space", "waitUntilReady", "triggers", "mount", "Context", "unmount", "ctx", "function", "find", "config", "exists", "get", "set", "disposed", "schedule", "task", "DeferredTask", "execFunction", "job", "CronJob", "onDispose", "subscription", "objectIds", "Set", "objects", "Array", "from", "createSubscription", "added", "updated", "object", "add", "type", "props", "query", "db", "Filter", "typename", "unsubscribe", "update", "delete", "dispose", "data", "fetch", "method", "headers", "JSON", "stringify", "result", "message"]
7
7
  }
@@ -1 +1 @@
1
- {"inputs":{"packages/core/functions/src/handler.ts":{"bytes":1109,"imports":[],"format":"esm"},"packages/core/functions/src/manifest.ts":{"bytes":1346,"imports":[],"format":"esm"},"packages/core/functions/src/runtime/dev-server.ts":{"bytes":17196,"imports":[{"path":"express","kind":"import-statement","external":true},{"path":"get-port-please","kind":"import-statement","external":true},{"path":"node:path","kind":"import-statement","external":true},{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/invariant","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"<runtime>","kind":"import-statement","external":true}],"format":"esm"},"packages/core/functions/src/runtime/trigger-manager.ts":{"bytes":16867,"imports":[{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/context","kind":"import-statement","external":true},{"path":"@dxos/echo-schema","kind":"import-statement","external":true},{"path":"@dxos/invariant","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true}],"format":"esm"},"packages/core/functions/src/runtime/index.ts":{"bytes":584,"imports":[{"path":"packages/core/functions/src/runtime/dev-server.ts","kind":"import-statement","original":"./dev-server"},{"path":"packages/core/functions/src/runtime/trigger-manager.ts","kind":"import-statement","original":"./trigger-manager"}],"format":"esm"},"packages/core/functions/src/index.ts":{"bytes":637,"imports":[{"path":"packages/core/functions/src/handler.ts","kind":"import-statement","original":"./handler"},{"path":"packages/core/functions/src/manifest.ts","kind":"import-statement","original":"./manifest"},{"path":"packages/core/functions/src/runtime/index.ts","kind":"import-statement","original":"./runtime"}],"format":"esm"}},"outputs":{"packages/core/functions/dist/lib/node/index.cjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":15787},"packages/core/functions/dist/lib/node/index.cjs":{"imports":[{"path":"express","kind":"import-statement","external":true},{"path":"get-port-please","kind":"import-statement","external":true},{"path":"node:path","kind":"import-statement","external":true},{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/invariant","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/context","kind":"import-statement","external":true},{"path":"@dxos/echo-schema","kind":"import-statement","external":true},{"path":"@dxos/invariant","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true}],"exports":["DevServer","TriggerManager"],"entryPoint":"packages/core/functions/src/index.ts","inputs":{"packages/core/functions/src/index.ts":{"bytesInOutput":0},"packages/core/functions/src/runtime/dev-server.ts":{"bytesInOutput":4373},"packages/core/functions/src/runtime/index.ts":{"bytesInOutput":0},"packages/core/functions/src/runtime/trigger-manager.ts":{"bytesInOutput":4463}},"bytes":9395}}}
1
+ {"inputs":{"packages/core/functions/src/handler.ts":{"bytes":1313,"imports":[],"format":"esm"},"packages/core/functions/src/manifest.ts":{"bytes":1735,"imports":[],"format":"esm"},"packages/core/functions/src/runtime/dev-server.ts":{"bytes":18553,"imports":[{"path":"express","kind":"import-statement","external":true},{"path":"get-port-please","kind":"import-statement","external":true},{"path":"node:path","kind":"import-statement","external":true},{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/invariant","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"<runtime>","kind":"import-statement","external":true}],"format":"esm"},"packages/core/functions/src/runtime/scheduler.ts":{"bytes":16641,"imports":[{"path":"cron","kind":"import-statement","external":true},{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/context","kind":"import-statement","external":true},{"path":"@dxos/echo-schema","kind":"import-statement","external":true},{"path":"@dxos/invariant","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true}],"format":"esm"},"packages/core/functions/src/runtime/index.ts":{"bytes":566,"imports":[{"path":"packages/core/functions/src/runtime/dev-server.ts","kind":"import-statement","original":"./dev-server"},{"path":"packages/core/functions/src/runtime/scheduler.ts","kind":"import-statement","original":"./scheduler"}],"format":"esm"},"packages/core/functions/src/index.ts":{"bytes":637,"imports":[{"path":"packages/core/functions/src/handler.ts","kind":"import-statement","original":"./handler"},{"path":"packages/core/functions/src/manifest.ts","kind":"import-statement","original":"./manifest"},{"path":"packages/core/functions/src/runtime/index.ts","kind":"import-statement","original":"./runtime"}],"format":"esm"}},"outputs":{"packages/core/functions/dist/lib/node/index.cjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":16608},"packages/core/functions/dist/lib/node/index.cjs":{"imports":[{"path":"express","kind":"import-statement","external":true},{"path":"get-port-please","kind":"import-statement","external":true},{"path":"node:path","kind":"import-statement","external":true},{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/invariant","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"cron","kind":"import-statement","external":true},{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/context","kind":"import-statement","external":true},{"path":"@dxos/echo-schema","kind":"import-statement","external":true},{"path":"@dxos/invariant","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true}],"exports":["DevServer","Scheduler"],"entryPoint":"packages/core/functions/src/index.ts","inputs":{"packages/core/functions/src/index.ts":{"bytesInOutput":0},"packages/core/functions/src/runtime/dev-server.ts":{"bytesInOutput":4729},"packages/core/functions/src/runtime/index.ts":{"bytesInOutput":0},"packages/core/functions/src/runtime/scheduler.ts":{"bytesInOutput":4189}},"bytes":9466}}}
@@ -1,18 +1,14 @@
1
1
  import { type Client } from '@dxos/client';
2
2
  export interface Response {
3
3
  status(code: number): Response;
4
- succeed(data?: object): Response;
5
4
  }
6
5
  export interface FunctionContext {
7
6
  client: Client;
8
- status(code: number): Response;
9
7
  }
10
- /**
11
- * Function handler.
12
- */
13
8
  export type FunctionHandler<T extends {}> = (params: {
14
- context: FunctionContext;
15
9
  event: T;
10
+ context: FunctionContext;
11
+ response: Response;
16
12
  }) => Promise<Response | void>;
17
13
  export type FunctionSubscriptionEvent = {
18
14
  space: string;
@@ -1 +1 @@
1
- {"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../../src/handler.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,cAAc,CAAC;AAE3C,MAAM,WAAW,QAAQ;IACvB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,CAAC;IAC/B,OAAO,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC;CAClC;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,CAAC;CAChC;AAED;;GAEG;AACH,MAAM,MAAM,eAAe,CAAC,CAAC,SAAS,EAAE,IAAI,CAAC,MAAM,EAAE;IACnD,OAAO,EAAE,eAAe,CAAC;IACzB,KAAK,EAAE,CAAC,CAAC;CACV,KAAK,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAAC;AAG/B,MAAM,MAAM,yBAAyB,GAAG;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB,CAAC"}
1
+ {"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../../src/handler.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,cAAc,CAAC;AAG3C,MAAM,WAAW,QAAQ;IACvB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,CAAC;CAChC;AAGD,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;CAChB;AAID,MAAM,MAAM,eAAe,CAAC,CAAC,SAAS,EAAE,IAAI,CAAC,MAAM,EAAE;IACnD,KAAK,EAAE,CAAC,CAAC;IACT,OAAO,EAAE,eAAe,CAAC;IACzB,QAAQ,EAAE,QAAQ,CAAC;CACpB,KAAK,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAAC;AAE/B,MAAM,MAAM,yBAAyB,GAAG;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB,CAAC"}
@@ -1,6 +1,6 @@
1
1
  export type FunctionDef = {
2
2
  id: string;
3
- path: string;
3
+ name: string;
4
4
  handler: string;
5
5
  description?: string;
6
6
  };
@@ -12,7 +12,8 @@ export type TriggerSubscription = {
12
12
  };
13
13
  export type FunctionTrigger = {
14
14
  function: string;
15
- subscription: TriggerSubscription;
15
+ schedule?: string;
16
+ subscription?: TriggerSubscription;
16
17
  };
17
18
  /**
18
19
  * Function manifest file.
@@ -1 +1 @@
1
- {"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../../src/manifest.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,WAAW,GAAG;IAExB,EAAE,EAAE,MAAM,CAAC;IAEX,IAAI,EAAE,MAAM,CAAC;IAEb,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB,CAAC;AAKF,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,mBAAmB,CAAC;CACnC,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC7B,SAAS,EAAE,WAAW,EAAE,CAAC;IACzB,QAAQ,EAAE,eAAe,EAAE,CAAC;CAC7B,CAAC"}
1
+ {"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../../src/manifest.ts"],"names":[],"mappings":"AAOA,MAAM,MAAM,WAAW,GAAG;IAExB,EAAE,EAAE,MAAM,CAAC;IAEX,IAAI,EAAE,MAAM,CAAC;IAEb,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB,CAAC;AAKF,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,mBAAmB,CAAC;CACpC,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC7B,SAAS,EAAE,WAAW,EAAE,CAAC;IACzB,QAAQ,EAAE,eAAe,EAAE,CAAC;CAC7B,CAAC"}