@dxos/functions 0.3.9-main.f27ec14 → 0.3.9-next.4584ca9
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/dist/lib/browser/index.mjs +134 -82
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node/index.cjs +130 -86
- package/dist/lib/node/index.cjs.map +4 -4
- package/dist/lib/node/meta.json +1 -1
- package/dist/types/src/handler.d.ts +10 -2
- package/dist/types/src/handler.d.ts.map +1 -1
- package/dist/types/src/manifest.d.ts +1 -1
- package/dist/types/src/manifest.d.ts.map +1 -1
- package/dist/types/src/runtime/dev-server.d.ts +1 -0
- package/dist/types/src/runtime/dev-server.d.ts.map +1 -1
- package/dist/types/src/runtime/scheduler.d.ts +8 -3
- package/dist/types/src/runtime/scheduler.d.ts.map +1 -1
- package/dist/types/src/runtime/scheduler.test.d.ts +2 -0
- package/dist/types/src/runtime/scheduler.test.d.ts.map +1 -0
- package/package.json +9 -9
- package/src/handler.ts +29 -3
- package/src/manifest.ts +2 -2
- package/src/runtime/dev-server.ts +3 -1
- package/src/runtime/scheduler.test.ts +57 -0
- package/src/runtime/scheduler.ts +96 -73
- package/dist/types/src/function.test.d.ts +0 -2
- package/dist/types/src/function.test.d.ts.map +0 -1
- package/src/function.test.ts +0 -7
|
@@ -7,6 +7,33 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
|
|
|
7
7
|
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
8
8
|
});
|
|
9
9
|
|
|
10
|
+
// inject-globals:@inject-globals
|
|
11
|
+
import {
|
|
12
|
+
global,
|
|
13
|
+
Buffer as Buffer2,
|
|
14
|
+
process
|
|
15
|
+
} from "@dxos/node-std/inject-globals";
|
|
16
|
+
|
|
17
|
+
// packages/core/functions/src/handler.ts
|
|
18
|
+
import { PublicKey } from "@dxos/client";
|
|
19
|
+
import { isTypedObject } from "@dxos/echo-schema";
|
|
20
|
+
import { nonNullable } from "@dxos/util";
|
|
21
|
+
var subscriptionHandler = (handler) => {
|
|
22
|
+
return ({ event, context, ...rest }) => {
|
|
23
|
+
const { client } = context;
|
|
24
|
+
const space = event.space ? client.spaces.get(PublicKey.from(event.space)) : void 0;
|
|
25
|
+
const objects = space && event.objects?.map((id) => space.db.getObjectById(id)).filter(nonNullable).filter(isTypedObject);
|
|
26
|
+
return handler({
|
|
27
|
+
event: {
|
|
28
|
+
space,
|
|
29
|
+
objects
|
|
30
|
+
},
|
|
31
|
+
context,
|
|
32
|
+
...rest
|
|
33
|
+
});
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
|
|
10
37
|
// packages/core/functions/src/runtime/dev-server.ts
|
|
11
38
|
import express from "express";
|
|
12
39
|
import { getPort } from "get-port-please";
|
|
@@ -26,7 +53,7 @@ var DevServer = class {
|
|
|
26
53
|
get endpoint() {
|
|
27
54
|
invariant(this._port, void 0, {
|
|
28
55
|
F: __dxlog_file,
|
|
29
|
-
L:
|
|
56
|
+
L: 46,
|
|
30
57
|
S: this,
|
|
31
58
|
A: [
|
|
32
59
|
"this._port",
|
|
@@ -48,7 +75,7 @@ var DevServer = class {
|
|
|
48
75
|
} catch (err) {
|
|
49
76
|
log.error("parsing function (check manifest)", err, {
|
|
50
77
|
F: __dxlog_file,
|
|
51
|
-
L:
|
|
78
|
+
L: 63,
|
|
52
79
|
S: this,
|
|
53
80
|
C: (f, a) => f(...a)
|
|
54
81
|
});
|
|
@@ -70,7 +97,7 @@ var DevServer = class {
|
|
|
70
97
|
} catch (err) {
|
|
71
98
|
log.catch(err, void 0, {
|
|
72
99
|
F: __dxlog_file,
|
|
73
|
-
L:
|
|
100
|
+
L: 83,
|
|
74
101
|
S: this,
|
|
75
102
|
C: (f, a) => f(...a)
|
|
76
103
|
});
|
|
@@ -79,6 +106,7 @@ var DevServer = class {
|
|
|
79
106
|
}
|
|
80
107
|
});
|
|
81
108
|
this._port = await getPort({
|
|
109
|
+
host: "localhost",
|
|
82
110
|
port: 7200,
|
|
83
111
|
portRange: [
|
|
84
112
|
7200,
|
|
@@ -98,7 +126,7 @@ var DevServer = class {
|
|
|
98
126
|
endpoint
|
|
99
127
|
}, {
|
|
100
128
|
F: __dxlog_file,
|
|
101
|
-
L:
|
|
129
|
+
L: 99,
|
|
102
130
|
S: this,
|
|
103
131
|
C: (f, a) => f(...a)
|
|
104
132
|
});
|
|
@@ -120,7 +148,7 @@ var DevServer = class {
|
|
|
120
148
|
registrationId: this._registrationId
|
|
121
149
|
}, {
|
|
122
150
|
F: __dxlog_file,
|
|
123
|
-
L:
|
|
151
|
+
L: 116,
|
|
124
152
|
S: this,
|
|
125
153
|
C: (f, a) => f(...a)
|
|
126
154
|
});
|
|
@@ -143,7 +171,7 @@ var DevServer = class {
|
|
|
143
171
|
id
|
|
144
172
|
}, {
|
|
145
173
|
F: __dxlog_file,
|
|
146
|
-
L:
|
|
174
|
+
L: 135,
|
|
147
175
|
S: this,
|
|
148
176
|
C: (f, a) => f(...a)
|
|
149
177
|
});
|
|
@@ -170,13 +198,14 @@ var DevServer = class {
|
|
|
170
198
|
name
|
|
171
199
|
}, {
|
|
172
200
|
F: __dxlog_file,
|
|
173
|
-
L:
|
|
201
|
+
L: 160,
|
|
174
202
|
S: this,
|
|
175
203
|
C: (f, a) => f(...a)
|
|
176
204
|
});
|
|
177
205
|
const { handler } = this._handlers[name];
|
|
178
206
|
const context = {
|
|
179
|
-
client: this._client
|
|
207
|
+
client: this._client,
|
|
208
|
+
dataDir: this._options.dataDir
|
|
180
209
|
};
|
|
181
210
|
let statusCode = 200;
|
|
182
211
|
const response = {
|
|
@@ -197,7 +226,7 @@ var DevServer = class {
|
|
|
197
226
|
duration: Date.now() - now
|
|
198
227
|
}, {
|
|
199
228
|
F: __dxlog_file,
|
|
200
|
-
L:
|
|
229
|
+
L: 177,
|
|
201
230
|
S: this,
|
|
202
231
|
C: (f, a) => f(...a)
|
|
203
232
|
});
|
|
@@ -216,7 +245,7 @@ import { log as log2 } from "@dxos/log";
|
|
|
216
245
|
import { ComplexMap } from "@dxos/util";
|
|
217
246
|
var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/core/functions/src/runtime/scheduler.ts";
|
|
218
247
|
var Scheduler = class {
|
|
219
|
-
constructor(_client, _manifest, _options) {
|
|
248
|
+
constructor(_client, _manifest, _options = {}) {
|
|
220
249
|
this._client = _client;
|
|
221
250
|
this._manifest = _manifest;
|
|
222
251
|
this._options = _options;
|
|
@@ -245,7 +274,7 @@ var Scheduler = class {
|
|
|
245
274
|
const def = this._manifest.functions.find((config) => config.id === trigger.function);
|
|
246
275
|
invariant2(def, `Function not found: ${trigger.function}`, {
|
|
247
276
|
F: __dxlog_file2,
|
|
248
|
-
L:
|
|
277
|
+
L: 63,
|
|
249
278
|
S: this,
|
|
250
279
|
A: [
|
|
251
280
|
"def",
|
|
@@ -258,12 +287,12 @@ var Scheduler = class {
|
|
|
258
287
|
ctx,
|
|
259
288
|
trigger
|
|
260
289
|
});
|
|
261
|
-
log2
|
|
290
|
+
log2("mount", {
|
|
262
291
|
space: space.key,
|
|
263
292
|
trigger
|
|
264
293
|
}, {
|
|
265
294
|
F: __dxlog_file2,
|
|
266
|
-
L:
|
|
295
|
+
L: 69,
|
|
267
296
|
S: this,
|
|
268
297
|
C: (f, a) => f(...a)
|
|
269
298
|
});
|
|
@@ -271,63 +300,10 @@ var Scheduler = class {
|
|
|
271
300
|
return;
|
|
272
301
|
}
|
|
273
302
|
if (trigger.schedule) {
|
|
274
|
-
|
|
275
|
-
await this.execFunction(def, {
|
|
276
|
-
space: space.key
|
|
277
|
-
});
|
|
278
|
-
});
|
|
279
|
-
const job = new CronJob(trigger.schedule, () => task.schedule());
|
|
280
|
-
job.start();
|
|
281
|
-
ctx.onDispose(() => job.stop());
|
|
303
|
+
this._createTimer(ctx, space, def, trigger);
|
|
282
304
|
}
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
const task = new DeferredTask(ctx, async () => {
|
|
286
|
-
await this.execFunction(def, {
|
|
287
|
-
space: space.key,
|
|
288
|
-
objects: Array.from(objectIds)
|
|
289
|
-
});
|
|
290
|
-
});
|
|
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
|
-
});
|
|
305
|
+
for (const triggerSubscription of trigger.subscriptions ?? []) {
|
|
306
|
+
this._createSubscription(ctx, space, def, triggerSubscription);
|
|
331
307
|
}
|
|
332
308
|
}
|
|
333
309
|
}
|
|
@@ -342,29 +318,104 @@ var Scheduler = class {
|
|
|
342
318
|
await ctx.dispose();
|
|
343
319
|
}
|
|
344
320
|
}
|
|
345
|
-
|
|
321
|
+
_createTimer(ctx, space, def, trigger) {
|
|
322
|
+
const task = new DeferredTask(ctx, async () => {
|
|
323
|
+
await this._execFunction(def, {
|
|
324
|
+
space: space.key
|
|
325
|
+
});
|
|
326
|
+
});
|
|
327
|
+
invariant2(trigger.schedule, void 0, {
|
|
328
|
+
F: __dxlog_file2,
|
|
329
|
+
L: 103,
|
|
330
|
+
S: this,
|
|
331
|
+
A: [
|
|
332
|
+
"trigger.schedule",
|
|
333
|
+
""
|
|
334
|
+
]
|
|
335
|
+
});
|
|
336
|
+
const job = new CronJob(trigger.schedule, () => task.schedule());
|
|
337
|
+
job.start();
|
|
338
|
+
ctx.onDispose(() => job.stop());
|
|
339
|
+
}
|
|
340
|
+
_createSubscription(ctx, space, def, triggerSubscription) {
|
|
341
|
+
const objectIds = /* @__PURE__ */ new Set();
|
|
342
|
+
const task = new DeferredTask(ctx, async () => {
|
|
343
|
+
await this._execFunction(def, {
|
|
344
|
+
space: space.key,
|
|
345
|
+
objects: Array.from(objectIds)
|
|
346
|
+
});
|
|
347
|
+
});
|
|
348
|
+
const subscriptions = [];
|
|
349
|
+
const subscription = createSubscription(({ added, updated }) => {
|
|
350
|
+
for (const object of added) {
|
|
351
|
+
objectIds.add(object.id);
|
|
352
|
+
}
|
|
353
|
+
for (const object of updated) {
|
|
354
|
+
objectIds.add(object.id);
|
|
355
|
+
}
|
|
356
|
+
task.schedule();
|
|
357
|
+
});
|
|
358
|
+
subscriptions.push(() => subscription.unsubscribe());
|
|
359
|
+
const { type, props, deep, delay } = triggerSubscription;
|
|
360
|
+
const update = ({ objects }) => {
|
|
361
|
+
subscription.update(objects);
|
|
362
|
+
if (deep) {
|
|
363
|
+
log2.info("update", {
|
|
364
|
+
type,
|
|
365
|
+
deep,
|
|
366
|
+
objects: objects.length
|
|
367
|
+
}, {
|
|
368
|
+
F: __dxlog_file2,
|
|
369
|
+
L: 139,
|
|
370
|
+
S: this,
|
|
371
|
+
C: (f, a) => f(...a)
|
|
372
|
+
});
|
|
373
|
+
for (const object of objects) {
|
|
374
|
+
const content = object.content;
|
|
375
|
+
if (content instanceof TextObject) {
|
|
376
|
+
subscriptions.push(content[subscribe](debounce(() => subscription.update([
|
|
377
|
+
object
|
|
378
|
+
]), 1e3)));
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
};
|
|
383
|
+
const query = space.db.query(Filter.typename(type, props));
|
|
384
|
+
subscriptions.push(query.subscribe(delay ? debounce(update, delay * 1e3) : update));
|
|
385
|
+
ctx.onDispose(() => {
|
|
386
|
+
subscriptions.forEach((unsubscribe) => unsubscribe());
|
|
387
|
+
});
|
|
388
|
+
}
|
|
389
|
+
async _execFunction(def, data) {
|
|
346
390
|
try {
|
|
347
391
|
log2("request", {
|
|
348
392
|
function: def.id
|
|
349
393
|
}, {
|
|
350
394
|
F: __dxlog_file2,
|
|
351
|
-
L:
|
|
395
|
+
L: 161,
|
|
352
396
|
S: this,
|
|
353
397
|
C: (f, a) => f(...a)
|
|
354
398
|
});
|
|
355
|
-
const
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
399
|
+
const { endpoint, callback } = this._options;
|
|
400
|
+
let status = 0;
|
|
401
|
+
if (endpoint) {
|
|
402
|
+
const response = await fetch(`${this._options.endpoint}/${def.name}`, {
|
|
403
|
+
method: "POST",
|
|
404
|
+
headers: {
|
|
405
|
+
"Content-Type": "application/json"
|
|
406
|
+
},
|
|
407
|
+
body: JSON.stringify(data)
|
|
408
|
+
});
|
|
409
|
+
status = response.status;
|
|
410
|
+
} else if (callback) {
|
|
411
|
+
status = await callback(data);
|
|
412
|
+
}
|
|
362
413
|
log2("result", {
|
|
363
414
|
function: def.id,
|
|
364
|
-
result:
|
|
415
|
+
result: status
|
|
365
416
|
}, {
|
|
366
417
|
F: __dxlog_file2,
|
|
367
|
-
L:
|
|
418
|
+
L: 180,
|
|
368
419
|
S: this,
|
|
369
420
|
C: (f, a) => f(...a)
|
|
370
421
|
});
|
|
@@ -374,7 +425,7 @@ var Scheduler = class {
|
|
|
374
425
|
error: err.message
|
|
375
426
|
}, {
|
|
376
427
|
F: __dxlog_file2,
|
|
377
|
-
L:
|
|
428
|
+
L: 182,
|
|
378
429
|
S: this,
|
|
379
430
|
C: (f, a) => f(...a)
|
|
380
431
|
});
|
|
@@ -383,6 +434,7 @@ var Scheduler = class {
|
|
|
383
434
|
};
|
|
384
435
|
export {
|
|
385
436
|
DevServer,
|
|
386
|
-
Scheduler
|
|
437
|
+
Scheduler,
|
|
438
|
+
subscriptionHandler
|
|
387
439
|
};
|
|
388
440
|
//# sourceMappingURL=index.mjs.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
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": "
|
|
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", "
|
|
3
|
+
"sources": ["../../../src/handler.ts", "../../../src/runtime/dev-server.ts", "../../../src/runtime/scheduler.ts"],
|
|
4
|
+
"sourcesContent": ["//\n// Copyright 2023 DXOS.org\n//\n\nimport { type Client, PublicKey } from '@dxos/client';\nimport { type Space } from '@dxos/client/echo';\nimport { isTypedObject, type TypedObject } from '@dxos/echo-schema';\nimport { nonNullable } from '@dxos/util';\n\n// TODO(burdon): No response?\nexport interface Response {\n status(code: number): Response;\n}\n\n// TODO(burdon): Limit access to individual space?\nexport interface FunctionContext {\n client: Client;\n dataDir?: string;\n}\n\n// TODO(burdon): Model after http request. Ref Lambda/OpenFaaS.\n// https://docs.aws.amazon.com/lambda/latest/dg/typescript-handler.html\nexport type FunctionHandler<T extends {}> = (params: {\n event: T;\n context: FunctionContext;\n response: Response;\n}) => Promise<Response | void>;\n\nexport type FunctionSubscriptionEvent = {\n space?: string; // TODO(burdon): Convert to PublicKey.\n objects?: string[];\n};\n\nexport type FunctionSubscriptionEvent2 = {\n space?: Space;\n objects?: TypedObject[];\n};\n\nexport const subscriptionHandler = (\n handler: FunctionHandler<FunctionSubscriptionEvent2>,\n): FunctionHandler<FunctionSubscriptionEvent> => {\n return ({ event, context, ...rest }) => {\n const { client } = context;\n const space = event.space ? client.spaces.get(PublicKey.from(event.space)) : undefined;\n const objects =\n space &&\n event.objects\n ?.map<TypedObject | undefined>((id) => space!.db.getObjectById(id))\n .filter(nonNullable)\n .filter(isTypedObject);\n\n return handler({ event: { space, objects }, context, ...rest });\n };\n};\n", "//\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 dataDir?: string;\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({ host: 'localhost', 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 dataDir: this._options.dataDir,\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 FunctionSubscriptionEvent } from '../handler';\nimport { type FunctionDef, type FunctionManifest, type FunctionTrigger, type TriggerSubscription } from '../manifest';\n\ntype Callback = (data: FunctionSubscriptionEvent) => Promise<number>;\n\ntype SchedulerOptions = {\n endpoint?: string;\n callback?: Callback;\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 // Currently supports only one trigger declaration per 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 // Timer.\n if (trigger.schedule) {\n this._createTimer(ctx, space, def, trigger);\n }\n\n // Subscription.\n for (const triggerSubscription of trigger.subscriptions ?? []) {\n this._createSubscription(ctx, space, def, triggerSubscription);\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 _createTimer(ctx: Context, space: Space, def: FunctionDef, trigger: FunctionTrigger) {\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 invariant(trigger.schedule);\n const job = new CronJob(trigger.schedule, () => task.schedule());\n\n job.start();\n ctx.onDispose(() => job.stop());\n }\n\n private _createSubscription(ctx: Context, space: Space, def: FunctionDef, triggerSubscription: TriggerSubscription) {\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 } = triggerSubscription;\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 private async _execFunction(def: FunctionDef, data: any) {\n try {\n log('request', { function: def.id });\n const { endpoint, callback } = this._options;\n let status = 0;\n if (endpoint) {\n // TODO(burdon): Move out of scheduler (generalize as callback).\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 status = response.status;\n } else if (callback) {\n status = await callback(data);\n }\n\n // const result = await response.json();\n log('result', { function: def.id, result: 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": ["PublicKey", "isTypedObject", "nonNullable", "subscriptionHandler", "handler", "event", "context", "rest", "client", "space", "spaces", "get", "PublicKey", "from", "undefined", "objects", "map", "id", "db", "getObjectById", "filter", "nonNullable", "isTypedObject", "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", "host", "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", "dataDir", "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", "disposed", "schedule", "_createTimer", "triggerSubscription", "subscriptions", "_createSubscription", "delete", "dispose", "task", "_execFunction", "job", "onDispose", "objectIds", "Set", "objects", "Array", "from", "subscription", "added", "updated", "object", "add", "push", "unsubscribe", "type", "props", "deep", "delay", "update", "info", "length", "content", "query", "db", "typename", "forEach", "data", "endpoint", "callback", "status", "response", "fetch", "name", "method", "headers", "body", "JSON", "stringify", "result", "err", "error", "message"]
|
|
7
7
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"inputs":{"packages/core/functions/src/handler.ts":{"bytes":
|
|
1
|
+
{"inputs":{"inject-globals:@inject-globals":{"bytes":384,"imports":[{"path":"@dxos/node-std/inject-globals","kind":"import-statement","external":true}],"format":"esm"},"packages/core/functions/src/handler.ts":{"bytes":4072,"imports":[{"path":"@dxos/client","kind":"import-statement","external":true},{"path":"@dxos/echo-schema","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true},{"path":"@inject-globals","kind":"import-statement","external":true}],"format":"esm"},"packages/core/functions/src/manifest.ts":{"bytes":1863,"imports":[{"path":"@inject-globals","kind":"import-statement","external":true}],"format":"esm"},"packages/core/functions/src/runtime/dev-server.ts":{"bytes":18840,"imports":[{"path":"express","kind":"import-statement","external":true},{"path":"get-port-please","kind":"import-statement","external":true},{"path":"@dxos/node-std/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":"@inject-globals","kind":"import-statement","external":true},{"path":"<runtime>","kind":"import-statement","external":true}],"format":"esm"},"packages/core/functions/src/runtime/scheduler.ts":{"bytes":22471,"imports":[{"path":"cron","kind":"import-statement","external":true},{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/client/echo","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},{"path":"@inject-globals","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"},{"path":"@inject-globals","kind":"import-statement","external":true}],"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"},{"path":"@inject-globals","kind":"import-statement","external":true}],"format":"esm"}},"outputs":{"packages/core/functions/dist/lib/browser/index.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":21917},"packages/core/functions/dist/lib/browser/index.mjs":{"imports":[{"path":"@dxos/node-std/inject-globals","kind":"import-statement","external":true},{"path":"@dxos/client","kind":"import-statement","external":true},{"path":"@dxos/echo-schema","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true},{"path":"express","kind":"import-statement","external":true},{"path":"get-port-please","kind":"import-statement","external":true},{"path":"@dxos/node-std/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/client/echo","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","subscriptionHandler"],"entryPoint":"packages/core/functions/src/index.ts","inputs":{"inject-globals:@inject-globals":{"bytesInOutput":90},"packages/core/functions/src/handler.ts":{"bytesInOutput":589},"packages/core/functions/src/index.ts":{"bytesInOutput":0},"packages/core/functions/src/runtime/dev-server.ts":{"bytesInOutput":4802},"packages/core/functions/src/runtime/index.ts":{"bytesInOutput":0},"packages/core/functions/src/runtime/scheduler.ts":{"bytesInOutput":5475}},"bytes":11638}}}
|