@dxos/functions 0.3.9-main.b7e6a67 → 0.3.9-main.c7cd0ec
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 +183 -109
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node/index.cjs +179 -113
- package/dist/lib/node/index.cjs.map +4 -4
- package/dist/lib/node/meta.json +1 -1
- package/dist/types/src/handler.d.ts +20 -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 +46 -3
- package/src/manifest.ts +2 -2
- package/src/runtime/dev-server.ts +4 -2
- package/src/runtime/scheduler.test.ts +57 -0
- package/src/runtime/scheduler.ts +99 -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,14 +7,63 @@ 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 { log } from "@dxos/log";
|
|
21
|
+
import { nonNullable } from "@dxos/util";
|
|
22
|
+
var __dxlog_file = "/home/runner/work/dxos/dxos/packages/core/functions/src/handler.ts";
|
|
23
|
+
var subscriptionHandler = (handler) => {
|
|
24
|
+
return ({ event, context, ...rest }) => {
|
|
25
|
+
const { client } = context;
|
|
26
|
+
const space = event.space ? client.spaces.get(PublicKey.from(event.space)) : void 0;
|
|
27
|
+
const objects = space && event.objects?.map((id) => space.db.getObjectById(id)).filter(nonNullable).filter(isTypedObject);
|
|
28
|
+
if (!!event.space && !space) {
|
|
29
|
+
log.warn("invalid space", {
|
|
30
|
+
event
|
|
31
|
+
}, {
|
|
32
|
+
F: __dxlog_file,
|
|
33
|
+
L: 64,
|
|
34
|
+
S: void 0,
|
|
35
|
+
C: (f, a) => f(...a)
|
|
36
|
+
});
|
|
37
|
+
} else {
|
|
38
|
+
log.info("handler", {
|
|
39
|
+
space: space?.key.truncate(),
|
|
40
|
+
objects: objects?.length
|
|
41
|
+
}, {
|
|
42
|
+
F: __dxlog_file,
|
|
43
|
+
L: 66,
|
|
44
|
+
S: void 0,
|
|
45
|
+
C: (f, a) => f(...a)
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
return handler({
|
|
49
|
+
event: {
|
|
50
|
+
space,
|
|
51
|
+
objects
|
|
52
|
+
},
|
|
53
|
+
context,
|
|
54
|
+
...rest
|
|
55
|
+
});
|
|
56
|
+
};
|
|
57
|
+
};
|
|
58
|
+
|
|
10
59
|
// packages/core/functions/src/runtime/dev-server.ts
|
|
11
60
|
import express from "express";
|
|
12
61
|
import { getPort } from "get-port-please";
|
|
13
62
|
import { join } from "@dxos/node-std/path";
|
|
14
63
|
import { Trigger } from "@dxos/async";
|
|
15
64
|
import { invariant } from "@dxos/invariant";
|
|
16
|
-
import { log } from "@dxos/log";
|
|
17
|
-
var
|
|
65
|
+
import { log as log2 } from "@dxos/log";
|
|
66
|
+
var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/core/functions/src/runtime/dev-server.ts";
|
|
18
67
|
var DevServer = class {
|
|
19
68
|
// prettier-ignore
|
|
20
69
|
constructor(_client, _options) {
|
|
@@ -25,8 +74,8 @@ var DevServer = class {
|
|
|
25
74
|
}
|
|
26
75
|
get endpoint() {
|
|
27
76
|
invariant(this._port, void 0, {
|
|
28
|
-
F:
|
|
29
|
-
L:
|
|
77
|
+
F: __dxlog_file2,
|
|
78
|
+
L: 46,
|
|
30
79
|
S: this,
|
|
31
80
|
A: [
|
|
32
81
|
"this._port",
|
|
@@ -46,9 +95,9 @@ var DevServer = class {
|
|
|
46
95
|
try {
|
|
47
96
|
await this._load(def);
|
|
48
97
|
} catch (err) {
|
|
49
|
-
|
|
50
|
-
F:
|
|
51
|
-
L:
|
|
98
|
+
log2.error("parsing function (check manifest)", err, {
|
|
99
|
+
F: __dxlog_file2,
|
|
100
|
+
L: 63,
|
|
52
101
|
S: this,
|
|
53
102
|
C: (f, a) => f(...a)
|
|
54
103
|
});
|
|
@@ -68,9 +117,9 @@ var DevServer = class {
|
|
|
68
117
|
res.statusCode = await this._invoke(name, req.body);
|
|
69
118
|
res.end();
|
|
70
119
|
} catch (err) {
|
|
71
|
-
|
|
72
|
-
F:
|
|
73
|
-
L:
|
|
120
|
+
log2.error(`Function failed: ${name}`, err, {
|
|
121
|
+
F: __dxlog_file2,
|
|
122
|
+
L: 83,
|
|
74
123
|
S: this,
|
|
75
124
|
C: (f, a) => f(...a)
|
|
76
125
|
});
|
|
@@ -79,6 +128,7 @@ var DevServer = class {
|
|
|
79
128
|
}
|
|
80
129
|
});
|
|
81
130
|
this._port = await getPort({
|
|
131
|
+
host: "localhost",
|
|
82
132
|
port: 7200,
|
|
83
133
|
portRange: [
|
|
84
134
|
7200,
|
|
@@ -93,12 +143,12 @@ var DevServer = class {
|
|
|
93
143
|
name
|
|
94
144
|
}))
|
|
95
145
|
});
|
|
96
|
-
|
|
146
|
+
log2.info("registered", {
|
|
97
147
|
registrationId,
|
|
98
148
|
endpoint
|
|
99
149
|
}, {
|
|
100
|
-
F:
|
|
101
|
-
L:
|
|
150
|
+
F: __dxlog_file2,
|
|
151
|
+
L: 99,
|
|
102
152
|
S: this,
|
|
103
153
|
C: (f, a) => f(...a)
|
|
104
154
|
});
|
|
@@ -116,11 +166,11 @@ var DevServer = class {
|
|
|
116
166
|
await this._client.services.services.FunctionRegistryService.unregister({
|
|
117
167
|
registrationId: this._registrationId
|
|
118
168
|
});
|
|
119
|
-
|
|
169
|
+
log2.info("unregistered", {
|
|
120
170
|
registrationId: this._registrationId
|
|
121
171
|
}, {
|
|
122
|
-
F:
|
|
123
|
-
L:
|
|
172
|
+
F: __dxlog_file2,
|
|
173
|
+
L: 116,
|
|
124
174
|
S: this,
|
|
125
175
|
C: (f, a) => f(...a)
|
|
126
176
|
});
|
|
@@ -139,11 +189,11 @@ var DevServer = class {
|
|
|
139
189
|
async _load(def, flush = false) {
|
|
140
190
|
const { id, name, handler } = def;
|
|
141
191
|
const path = join(this._options.directory, handler);
|
|
142
|
-
|
|
192
|
+
log2.info("loading", {
|
|
143
193
|
id
|
|
144
194
|
}, {
|
|
145
|
-
F:
|
|
146
|
-
L:
|
|
195
|
+
F: __dxlog_file2,
|
|
196
|
+
L: 135,
|
|
147
197
|
S: this,
|
|
148
198
|
C: (f, a) => f(...a)
|
|
149
199
|
});
|
|
@@ -165,18 +215,19 @@ var DevServer = class {
|
|
|
165
215
|
async _invoke(name, event) {
|
|
166
216
|
const seq = ++this._seq;
|
|
167
217
|
const now = Date.now();
|
|
168
|
-
|
|
218
|
+
log2.info("req", {
|
|
169
219
|
seq,
|
|
170
220
|
name
|
|
171
221
|
}, {
|
|
172
|
-
F:
|
|
173
|
-
L:
|
|
222
|
+
F: __dxlog_file2,
|
|
223
|
+
L: 160,
|
|
174
224
|
S: this,
|
|
175
225
|
C: (f, a) => f(...a)
|
|
176
226
|
});
|
|
177
227
|
const { handler } = this._handlers[name];
|
|
178
228
|
const context = {
|
|
179
|
-
client: this._client
|
|
229
|
+
client: this._client,
|
|
230
|
+
dataDir: this._options.dataDir
|
|
180
231
|
};
|
|
181
232
|
let statusCode = 200;
|
|
182
233
|
const response = {
|
|
@@ -190,14 +241,14 @@ var DevServer = class {
|
|
|
190
241
|
event,
|
|
191
242
|
response
|
|
192
243
|
});
|
|
193
|
-
|
|
244
|
+
log2.info("res", {
|
|
194
245
|
seq,
|
|
195
246
|
name,
|
|
196
247
|
statusCode,
|
|
197
248
|
duration: Date.now() - now
|
|
198
249
|
}, {
|
|
199
|
-
F:
|
|
200
|
-
L:
|
|
250
|
+
F: __dxlog_file2,
|
|
251
|
+
L: 177,
|
|
201
252
|
S: this,
|
|
202
253
|
C: (f, a) => f(...a)
|
|
203
254
|
});
|
|
@@ -212,11 +263,11 @@ import { TextObject } from "@dxos/client/echo";
|
|
|
212
263
|
import { Context } from "@dxos/context";
|
|
213
264
|
import { Filter, createSubscription, subscribe } from "@dxos/echo-schema";
|
|
214
265
|
import { invariant as invariant2 } from "@dxos/invariant";
|
|
215
|
-
import { log as
|
|
266
|
+
import { log as log3 } from "@dxos/log";
|
|
216
267
|
import { ComplexMap } from "@dxos/util";
|
|
217
|
-
var
|
|
268
|
+
var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/core/functions/src/runtime/scheduler.ts";
|
|
218
269
|
var Scheduler = class {
|
|
219
|
-
constructor(_client, _manifest, _options) {
|
|
270
|
+
constructor(_client, _manifest, _options = {}) {
|
|
220
271
|
this._client = _client;
|
|
221
272
|
this._manifest = _manifest;
|
|
222
273
|
this._options = _options;
|
|
@@ -244,8 +295,8 @@ var Scheduler = class {
|
|
|
244
295
|
};
|
|
245
296
|
const def = this._manifest.functions.find((config) => config.id === trigger.function);
|
|
246
297
|
invariant2(def, `Function not found: ${trigger.function}`, {
|
|
247
|
-
F:
|
|
248
|
-
L:
|
|
298
|
+
F: __dxlog_file3,
|
|
299
|
+
L: 63,
|
|
249
300
|
S: this,
|
|
250
301
|
A: [
|
|
251
302
|
"def",
|
|
@@ -258,12 +309,12 @@ var Scheduler = class {
|
|
|
258
309
|
ctx,
|
|
259
310
|
trigger
|
|
260
311
|
});
|
|
261
|
-
|
|
312
|
+
log3("mount", {
|
|
262
313
|
space: space.key,
|
|
263
314
|
trigger
|
|
264
315
|
}, {
|
|
265
|
-
F:
|
|
266
|
-
L:
|
|
316
|
+
F: __dxlog_file3,
|
|
317
|
+
L: 69,
|
|
267
318
|
S: this,
|
|
268
319
|
C: (f, a) => f(...a)
|
|
269
320
|
});
|
|
@@ -271,63 +322,10 @@ var Scheduler = class {
|
|
|
271
322
|
return;
|
|
272
323
|
}
|
|
273
324
|
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());
|
|
325
|
+
this._createTimer(ctx, space, def, trigger);
|
|
282
326
|
}
|
|
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
|
-
});
|
|
327
|
+
for (const triggerSubscription of trigger.subscriptions ?? []) {
|
|
328
|
+
this._createSubscription(ctx, space, def, triggerSubscription);
|
|
331
329
|
}
|
|
332
330
|
}
|
|
333
331
|
}
|
|
@@ -342,39 +340,114 @@ var Scheduler = class {
|
|
|
342
340
|
await ctx.dispose();
|
|
343
341
|
}
|
|
344
342
|
}
|
|
345
|
-
|
|
343
|
+
_createTimer(ctx, space, def, trigger) {
|
|
344
|
+
const task = new DeferredTask(ctx, async () => {
|
|
345
|
+
await this._execFunction(def, {
|
|
346
|
+
space: space.key
|
|
347
|
+
});
|
|
348
|
+
});
|
|
349
|
+
invariant2(trigger.schedule, void 0, {
|
|
350
|
+
F: __dxlog_file3,
|
|
351
|
+
L: 103,
|
|
352
|
+
S: this,
|
|
353
|
+
A: [
|
|
354
|
+
"trigger.schedule",
|
|
355
|
+
""
|
|
356
|
+
]
|
|
357
|
+
});
|
|
358
|
+
const job = new CronJob(trigger.schedule, () => task.schedule());
|
|
359
|
+
job.start();
|
|
360
|
+
ctx.onDispose(() => job.stop());
|
|
361
|
+
}
|
|
362
|
+
_createSubscription(ctx, space, def, triggerSubscription) {
|
|
363
|
+
const objectIds = /* @__PURE__ */ new Set();
|
|
364
|
+
const task = new DeferredTask(ctx, async () => {
|
|
365
|
+
await this._execFunction(def, {
|
|
366
|
+
space: space.key,
|
|
367
|
+
objects: Array.from(objectIds)
|
|
368
|
+
});
|
|
369
|
+
});
|
|
370
|
+
const subscriptions = [];
|
|
371
|
+
const subscription = createSubscription(({ added, updated }) => {
|
|
372
|
+
for (const object of added) {
|
|
373
|
+
objectIds.add(object.id);
|
|
374
|
+
}
|
|
375
|
+
for (const object of updated) {
|
|
376
|
+
objectIds.add(object.id);
|
|
377
|
+
}
|
|
378
|
+
task.schedule();
|
|
379
|
+
});
|
|
380
|
+
subscriptions.push(() => subscription.unsubscribe());
|
|
381
|
+
const { type, props, deep, delay } = triggerSubscription;
|
|
382
|
+
const update = ({ objects }) => {
|
|
383
|
+
subscription.update(objects);
|
|
384
|
+
if (deep) {
|
|
385
|
+
log3.info("update", {
|
|
386
|
+
type,
|
|
387
|
+
deep,
|
|
388
|
+
objects: objects.length
|
|
389
|
+
}, {
|
|
390
|
+
F: __dxlog_file3,
|
|
391
|
+
L: 142,
|
|
392
|
+
S: this,
|
|
393
|
+
C: (f, a) => f(...a)
|
|
394
|
+
});
|
|
395
|
+
for (const object of objects) {
|
|
396
|
+
const content = object.content;
|
|
397
|
+
if (content instanceof TextObject) {
|
|
398
|
+
subscriptions.push(content[subscribe](debounce(() => subscription.update([
|
|
399
|
+
object
|
|
400
|
+
]), 1e3)));
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
};
|
|
405
|
+
const query = space.db.query(Filter.typename(type, props));
|
|
406
|
+
subscriptions.push(query.subscribe(delay ? debounce(update, delay * 1e3) : update));
|
|
407
|
+
ctx.onDispose(() => {
|
|
408
|
+
subscriptions.forEach((unsubscribe) => unsubscribe());
|
|
409
|
+
});
|
|
410
|
+
}
|
|
411
|
+
async _execFunction(def, data) {
|
|
346
412
|
try {
|
|
347
|
-
|
|
413
|
+
log3("request", {
|
|
348
414
|
function: def.id
|
|
349
415
|
}, {
|
|
350
|
-
F:
|
|
351
|
-
L:
|
|
416
|
+
F: __dxlog_file3,
|
|
417
|
+
L: 164,
|
|
352
418
|
S: this,
|
|
353
419
|
C: (f, a) => f(...a)
|
|
354
420
|
});
|
|
355
|
-
const
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
421
|
+
const { endpoint, callback } = this._options;
|
|
422
|
+
let status = 0;
|
|
423
|
+
if (endpoint) {
|
|
424
|
+
const response = await fetch(`${this._options.endpoint}/${def.name}`, {
|
|
425
|
+
method: "POST",
|
|
426
|
+
headers: {
|
|
427
|
+
"Content-Type": "application/json"
|
|
428
|
+
},
|
|
429
|
+
body: JSON.stringify(data)
|
|
430
|
+
});
|
|
431
|
+
status = response.status;
|
|
432
|
+
} else if (callback) {
|
|
433
|
+
status = await callback(data);
|
|
434
|
+
}
|
|
435
|
+
log3("result", {
|
|
363
436
|
function: def.id,
|
|
364
|
-
result:
|
|
437
|
+
result: status
|
|
365
438
|
}, {
|
|
366
|
-
F:
|
|
367
|
-
L:
|
|
439
|
+
F: __dxlog_file3,
|
|
440
|
+
L: 183,
|
|
368
441
|
S: this,
|
|
369
442
|
C: (f, a) => f(...a)
|
|
370
443
|
});
|
|
371
444
|
} catch (err) {
|
|
372
|
-
|
|
445
|
+
log3.error("error", {
|
|
373
446
|
function: def.id,
|
|
374
447
|
error: err.message
|
|
375
448
|
}, {
|
|
376
|
-
F:
|
|
377
|
-
L:
|
|
449
|
+
F: __dxlog_file3,
|
|
450
|
+
L: 185,
|
|
378
451
|
S: this,
|
|
379
452
|
C: (f, a) => f(...a)
|
|
380
453
|
});
|
|
@@ -383,6 +456,7 @@ var Scheduler = class {
|
|
|
383
456
|
};
|
|
384
457
|
export {
|
|
385
458
|
DevServer,
|
|
386
|
-
Scheduler
|
|
459
|
+
Scheduler,
|
|
460
|
+
subscriptionHandler
|
|
387
461
|
};
|
|
388
462
|
//# 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", "
|
|
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 { log } from '@dxos/log';\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\n/**\n * Handler wrapper for subscription events; extracts space and objects.\n *\n * To test:\n * ```\n * curl -s -X POST -H \"Content-Type: application/json\" --data '{\"space\": \"0446...1cbb\"}' http://localhost:7100/dev/email-extractor\n * ```\n *\n * NOTE: Get space key from devtools or `dx space list --json`\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 if (!!event.space && !space) {\n log.warn('invalid space', { event });\n } else {\n log.info('handler', { space: space?.key.truncate(), objects: objects?.length });\n }\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.error(`Function failed: ${name}`, 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): Don't fire initially.\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 // TODO(burdon): Create queue. Only allow one invocation per trigger at a time?\n // TODO(burdon): Disable trigger if keeps failing.\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": ";;;;;;;;;;;;;;;;;AAIA,SAAsBA,iBAAiB;AAEvC,SAASC,qBAAuC;AAChD,SAASC,WAAW;AACpB,SAASC,mBAAmB;;AAyCrB,IAAMC,sBAAsB,CACjCC,YAAAA;AAEA,SAAO,CAAC,EAAEC,OAAOC,SAAS,GAAGC,KAAAA,MAAM;AACjC,UAAM,EAAEC,OAAM,IAAKF;AACnB,UAAMG,QAAQJ,MAAMI,QAAQD,OAAOE,OAAOC,IAAIZ,UAAUa,KAAKP,MAAMI,KAAK,CAAA,IAAKI;AAC7E,UAAMC,UACJL,SACAJ,MAAMS,SACFC,IAA6B,CAACC,OAAOP,MAAOQ,GAAGC,cAAcF,EAAAA,CAAAA,EAC9DG,OAAOjB,WAAAA,EACPiB,OAAOnB,aAAAA;AAEZ,QAAI,CAAC,CAACK,MAAMI,SAAS,CAACA,OAAO;AAC3BR,UAAImB,KAAK,iBAAiB;QAAEf;MAAM,GAAA;;;;;;IACpC,OAAO;AACLJ,UAAIoB,KAAK,WAAW;QAAEZ,OAAOA,OAAOa,IAAIC,SAAAA;QAAYT,SAASA,SAASU;MAAO,GAAA;;;;;;IAC/E;AAEA,WAAOpB,QAAQ;MAAEC,OAAO;QAAEI;QAAOK;MAAQ;MAAGR;MAAS,GAAGC;IAAK,CAAA;EAC/D;AACF;;;AClEA,OAAOkB,aAAa;AACpB,SAASC,eAAe;AAExB,SAASC,YAAY;AAErB,SAASC,eAAe;AAExB,SAASC,iBAAiB;AAC1B,SAASC,OAAAA,YAAW;;AAgBb,IAAMC,YAAN,MAAMA;;EAWXC,YACmBC,SACAC,UACjB;mBAFiBD;oBACAC;SAXFC,YAAiF,CAAC;SAM3FC,OAAO;EAMZ;EAEH,IAAIC,WAAW;AACbC,cAAU,KAAKC,OAAK,QAAA;;;;;;;;;AACpB,WAAO,oBAAoB,KAAKA,KAAK;EACvC;EAEA,IAAIC,QAAQ;AACV,WAAO,KAAKC;EACd;EAEA,IAAIC,YAAY;AACd,WAAOC,OAAOC,OAAO,KAAKT,SAAS;EACrC;EAEA,MAAMU,aAAa;AACjB,eAAWC,OAAO,KAAKZ,SAASa,SAASL,WAAW;AAClD,UAAI;AACF,cAAM,KAAKM,MAAMF,GAAAA;MACnB,SAASG,KAAK;AACZC,QAAAA,KAAIC,MAAM,qCAAqCF,KAAAA;;;;;;MACjD;IACF;EACF;EAEA,MAAMG,QAAQ;AACZ,UAAMC,MAAMC,QAAAA;AACZD,QAAIE,IAAID,QAAQE,KAAI,CAAA;AAEpBH,QAAII,KAAK,UAAU,OAAOC,KAAKC,QAAAA;AAC7B,YAAM,EAAEC,KAAI,IAAKF,IAAIG;AACrB,UAAI;AACF,YAAI,KAAK3B,SAAS4B,QAAQ;AACxB,gBAAM,EAAEhB,IAAG,IAAK,KAAKX,UAAUyB,IAAAA;AAC/B,gBAAM,KAAKZ,MAAMF,KAAK,IAAA;QACxB;AAEAa,YAAII,aAAa,MAAM,KAAKC,QAAQJ,MAAMF,IAAIO,IAAI;AAClDN,YAAIO,IAAG;MACT,SAASjB,KAAU;AACjBC,QAAAA,KAAIC,MAAM,oBAAoBS,IAAAA,IAAQX,KAAAA;;;;;;AACtCU,YAAII,aAAa;AACjBJ,YAAIO,IAAG;MACT;IACF,CAAA;AAEA,SAAK3B,QAAQ,MAAM4B,QAAQ;MAAEC,MAAM;MAAaC,MAAM;MAAMC,WAAW;QAAC;QAAM;;IAAM,CAAA;AACpF,SAAKC,UAAUlB,IAAImB,OAAO,KAAKjC,KAAK;AAEpC,QAAI;AAEF,YAAM,EAAEkC,gBAAgBpC,SAAQ,IAAK,MAAM,KAAKJ,QAAQyC,SAASA,SAASC,wBAAyBC,SAAS;QAC1GvC,UAAU,KAAKA;QACfK,WAAW,KAAKA,UAAUmC,IAAI,CAAC,EAAE/B,KAAK,EAAEc,KAAI,EAAE,OAAQ;UAAEA;QAAK,EAAA;MAC/D,CAAA;AAEAV,MAAAA,KAAI4B,KAAK,cAAc;QAAEL;QAAgBpC;MAAS,GAAA;;;;;;AAClD,WAAK0C,kBAAkBN;AACvB,WAAKhC,SAASJ;IAChB,SAASY,KAAU;AACjB,YAAM,KAAK+B,KAAI;AACf,YAAM,IAAIC,MAAM,qEAAA;IAClB;EACF;EAEA,MAAMD,OAAO;AACX,UAAME,UAAU,IAAIC,QAAAA;AACpB,SAAKZ,SAASa,MAAM,YAAA;AAClB,UAAI,KAAKL,iBAAiB;AACxB,cAAM,KAAK9C,QAAQyC,SAASA,SAASC,wBAAyBU,WAAW;UACvEZ,gBAAgB,KAAKM;QACvB,CAAA;AAEA7B,QAAAA,KAAI4B,KAAK,gBAAgB;UAAEL,gBAAgB,KAAKM;QAAgB,GAAA;;;;;;AAChE,aAAKA,kBAAkBO;AACvB,aAAK7C,SAAS6C;MAChB;AAEAJ,cAAQK,KAAI;IACd,CAAA;AAEA,UAAML,QAAQM,KAAI;AAClB,SAAKjD,QAAQ+C;AACb,SAAKf,UAAUe;EACjB;;;;EAKA,MAActC,MAAMF,KAAkB2C,QAAQ,OAAO;AACnD,UAAM,EAAEC,IAAI9B,MAAM+B,QAAO,IAAK7C;AAC9B,UAAM8C,OAAOC,KAAK,KAAK3D,SAAS4D,WAAWH,OAAAA;AAC3CzC,IAAAA,KAAI4B,KAAK,WAAW;MAAEY;IAAG,GAAA;;;;;;AAGzB,QAAID,OAAO;AACT9C,aAAOoD,KAAKC,UAAQC,KAAK,EACtBC,OAAO,CAACC,QAAQA,IAAIC,WAAWR,IAAAA,CAAAA,EAC/BS,QAAQ,CAACF,QAAQ,OAAOH,UAAQC,MAAME,GAAAA,CAAI;IAC/C;AAGA,UAAMG,SAASN,UAAQJ,IAAAA;AACvB,QAAI,OAAOU,OAAOC,YAAY,YAAY;AACxC,YAAM,IAAItB,MAAM,yCAAyCS,EAAAA,EAAI;IAC/D;AAEA,SAAKvD,UAAUyB,IAAAA,IAAQ;MAAEd;MAAK6C,SAASW,OAAOC;IAAQ;EACxD;;;;EAKA,MAAcvC,QAAQJ,MAAc4C,OAAY;AAC9C,UAAMC,MAAM,EAAE,KAAKrE;AACnB,UAAMsE,MAAMC,KAAKD,IAAG;AAEpBxD,IAAAA,KAAI4B,KAAK,OAAO;MAAE2B;MAAK7C;IAAK,GAAA;;;;;;AAC5B,UAAM,EAAE+B,QAAO,IAAK,KAAKxD,UAAUyB,IAAAA;AAEnC,UAAMgD,UAA2B;MAC/BC,QAAQ,KAAK5E;MACb6E,SAAS,KAAK5E,SAAS4E;IACzB;AAEA,QAAI/C,aAAa;AACjB,UAAMgD,WAAqB;MACzBC,QAAQ,CAACC,SAAAA;AACPlD,qBAAakD;AACb,eAAOF;MACT;IACF;AAEA,UAAMpB,QAAQ;MAAEiB;MAASJ;MAAOO;IAAS,CAAA;AACzC7D,IAAAA,KAAI4B,KAAK,OAAO;MAAE2B;MAAK7C;MAAMG;MAAYmD,UAAUP,KAAKD,IAAG,IAAKA;IAAI,GAAA;;;;;;AAEpE,WAAO3C;EACT;AACF;;;AChLA,SAASoD,eAAe;AAExB,SAASC,UAAUC,oBAAoB;AAEvC,SAAqBC,kBAAkB;AACvC,SAASC,eAAe;AACxB,SAASC,QAAQC,oBAAgCC,iBAAiB;AAClE,SAASC,aAAAA,kBAAiB;AAC1B,SAASC,OAAAA,YAAW;AACpB,SAASC,kBAAkB;;AAgBpB,IAAMC,YAAN,MAAMA;EAOXC,YACmBC,SACAC,WACAC,WAA6B,CAAC,GAC/C;mBAHiBF;qBACAC;oBACAC;SARFC,UAAU,IAAIN,WAG7B,CAAC,EAAEO,IAAIC,SAAQ,MAAO,GAAGA,SAASC,MAAK,CAAA,IAAMF,EAAAA,EAAI;EAMhD;EAEH,MAAMG,QAAQ;AACZ,SAAKP,QAAQQ,OAAOd,UAAU,OAAOc,WAAAA;AACnC,iBAAWC,SAASD,QAAQ;AAC1B,cAAMC,MAAMC,eAAc;AAC1B,mBAAWC,WAAW,KAAKV,UAAUW,YAAY,CAAA,GAAI;AACnD,gBAAM,KAAKC,MAAM,IAAItB,QAAAA,GAAWkB,OAAOE,OAAAA;QACzC;MACF;IACF,CAAA;EACF;EAEA,MAAMG,OAAO;AACX,eAAW,EAAEV,IAAIC,SAAQ,KAAM,KAAKF,QAAQY,KAAI,GAAI;AAClD,YAAM,KAAKC,QAAQZ,IAAIC,QAAAA;IACzB;EACF;EAEA,MAAcQ,MAAMI,KAAcR,OAAcE,SAA0B;AACxE,UAAMO,MAAM;MAAEd,IAAIO,QAAQQ;MAAUd,UAAUI,MAAMS;IAAI;AACxD,UAAME,MAAM,KAAKnB,UAAUoB,UAAUC,KAAK,CAACC,WAAWA,OAAOnB,OAAOO,QAAQQ,QAAQ;AACpFxB,IAAAA,WAAUyB,KAAK,uBAAuBT,QAAQQ,QAAQ,IAAE;;;;;;;;;AAGxD,UAAMK,SAAS,KAAKrB,QAAQsB,IAAIP,GAAAA;AAChC,QAAI,CAACM,QAAQ;AACX,WAAKrB,QAAQuB,IAAIR,KAAK;QAAED;QAAKN;MAAQ,CAAA;AACrCf,MAAAA,KAAI,SAAS;QAAEa,OAAOA,MAAMS;QAAKP;MAAQ,GAAA;;;;;;AACzC,UAAIM,IAAIU,UAAU;AAChB;MACF;AAGA,UAAIhB,QAAQiB,UAAU;AACpB,aAAKC,aAAaZ,KAAKR,OAAOW,KAAKT,OAAAA;MACrC;AAGA,iBAAWmB,uBAAuBnB,QAAQoB,iBAAiB,CAAA,GAAI;AAC7D,aAAKC,oBAAoBf,KAAKR,OAAOW,KAAKU,mBAAAA;MAC5C;IACF;EACF;EAEA,MAAcd,QAAQZ,IAAYC,UAAqB;AACrD,UAAMa,MAAM;MAAEd;MAAIC;IAAS;AAC3B,UAAM,EAAEY,IAAG,IAAK,KAAKd,QAAQsB,IAAIP,GAAAA,KAAQ,CAAC;AAC1C,QAAID,KAAK;AACP,WAAKd,QAAQ8B,OAAOf,GAAAA;AACpB,YAAMD,IAAIiB,QAAO;IACnB;EACF;EAEQL,aAAaZ,KAAcR,OAAcW,KAAkBT,SAA0B;AAC3F,UAAMwB,OAAO,IAAI9C,aAAa4B,KAAK,YAAA;AACjC,YAAM,KAAKmB,cAAchB,KAAK;QAC5BX,OAAOA,MAAMS;MACf,CAAA;IACF,CAAA;AAGAvB,IAAAA,WAAUgB,QAAQiB,UAAQ,QAAA;;;;;;;;;AAC1B,UAAMS,MAAM,IAAIlD,QAAQwB,QAAQiB,UAAU,MAAMO,KAAKP,SAAQ,CAAA;AAE7DS,QAAI9B,MAAK;AACTU,QAAIqB,UAAU,MAAMD,IAAIvB,KAAI,CAAA;EAC9B;EAEQkB,oBAAoBf,KAAcR,OAAcW,KAAkBU,qBAA0C;AAClH,UAAMS,YAAY,oBAAIC,IAAAA;AACtB,UAAML,OAAO,IAAI9C,aAAa4B,KAAK,YAAA;AACjC,YAAM,KAAKmB,cAAchB,KAAK;QAC5BX,OAAOA,MAAMS;QACbuB,SAASC,MAAMC,KAAKJ,SAAAA;MACtB,CAAA;IACF,CAAA;AAIA,UAAMR,gBAAgC,CAAA;AACtC,UAAMa,eAAenD,mBAAmB,CAAC,EAAEoD,OAAOC,QAAO,MAAE;AACzD,iBAAWC,UAAUF,OAAO;AAC1BN,kBAAUS,IAAID,OAAO3C,EAAE;MACzB;AACA,iBAAW2C,UAAUD,SAAS;AAC5BP,kBAAUS,IAAID,OAAO3C,EAAE;MACzB;AAEA+B,WAAKP,SAAQ;IACf,CAAA;AACAG,kBAAckB,KAAK,MAAML,aAAaM,YAAW,CAAA;AAIjD,UAAM,EAAEC,MAAMC,OAAOC,MAAMC,MAAK,IAAKxB;AACrC,UAAMyB,SAAS,CAAC,EAAEd,QAAO,MAAS;AAChCG,mBAAaW,OAAOd,OAAAA;AAGpB,UAAIY,MAAM;AACRzD,QAAAA,KAAI4D,KAAK,UAAU;UAAEL;UAAME;UAAMZ,SAASA,QAAQgB;QAAO,GAAA;;;;;;AACzD,mBAAWV,UAAUN,SAAS;AAC5B,gBAAMiB,UAAUX,OAAOW;AACvB,cAAIA,mBAAmBpE,YAAY;AACjCyC,0BAAckB,KAAKS,QAAQhE,SAAAA,EAAWN,SAAS,MAAMwD,aAAaW,OAAO;cAACR;aAAO,GAAG,GAAA,CAAA,CAAA;UACtF;QACF;MACF;IACF;AAIA,UAAMY,QAAQlD,MAAMmD,GAAGD,MAAMnE,OAAOqE,SAASV,MAAMC,KAAAA,CAAAA;AACnDrB,kBAAckB,KAAKU,MAAMjE,UAAU4D,QAAQlE,SAASmE,QAAQD,QAAQ,GAAA,IAASC,MAAAA,CAAAA;AAE7EtC,QAAIqB,UAAU,MAAA;AACZP,oBAAc+B,QAAQ,CAACZ,gBAAgBA,YAAAA,CAAAA;IACzC,CAAA;EACF;EAEA,MAAcd,cAAchB,KAAkB2C,MAAW;AACvD,QAAI;AACFnE,MAAAA,KAAI,WAAW;QAAEuB,UAAUC,IAAIhB;MAAG,GAAA;;;;;;AAClC,YAAM,EAAE4D,UAAUC,SAAQ,IAAK,KAAK/D;AACpC,UAAIgE,SAAS;AACb,UAAIF,UAAU;AAEZ,cAAMG,WAAW,MAAMC,MAAM,GAAG,KAAKlE,SAAS8D,QAAQ,IAAI5C,IAAIiD,IAAI,IAAI;UACpEC,QAAQ;UACRC,SAAS;YACP,gBAAgB;UAClB;UACAC,MAAMC,KAAKC,UAAUX,IAAAA;QACvB,CAAA;AAEAG,iBAASC,SAASD;MACpB,WAAWD,UAAU;AACnBC,iBAAS,MAAMD,SAASF,IAAAA;MAC1B;AAGAnE,MAAAA,KAAI,UAAU;QAAEuB,UAAUC,IAAIhB;QAAIuE,QAAQT;MAAO,GAAA;;;;;;IACnD,SAASU,KAAU;AACjBhF,MAAAA,KAAIiF,MAAM,SAAS;QAAE1D,UAAUC,IAAIhB;QAAIyE,OAAOD,IAAIE;MAAQ,GAAA;;;;;;IAC5D;EACF;AACF;",
|
|
6
|
+
"names": ["PublicKey", "isTypedObject", "log", "nonNullable", "subscriptionHandler", "handler", "event", "context", "rest", "client", "space", "spaces", "get", "from", "undefined", "objects", "map", "id", "db", "getObjectById", "filter", "warn", "info", "key", "truncate", "length", "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", "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":6074,"imports":[{"path":"@dxos/client","kind":"import-statement","external":true},{"path":"@dxos/echo-schema","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/manifest.ts":{"bytes":1863,"imports":[{"path":"@inject-globals","kind":"import-statement","external":true}],"format":"esm"},"packages/core/functions/src/runtime/dev-server.ts":{"bytes":18932,"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":22961,"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":22950},"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/log","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":1130},"packages/core/functions/src/index.ts":{"bytesInOutput":0},"packages/core/functions/src/runtime/dev-server.ts":{"bytesInOutput":4846},"packages/core/functions/src/runtime/index.ts":{"bytesInOutput":0},"packages/core/functions/src/runtime/scheduler.ts":{"bytesInOutput":5475}},"bytes":12223}}}
|