@dxos/functions 0.3.7 → 0.3.8-main.0ab6c73

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.
@@ -26,52 +26,67 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
26
26
  mod
27
27
  ));
28
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
-
30
- // packages/core/functions/src/index.ts
31
- var src_exports = {};
32
- __export(src_exports, {
29
+ var node_exports = {};
30
+ __export(node_exports, {
33
31
  DevServer: () => DevServer,
34
- TriggerManager: () => TriggerManager
32
+ Scheduler: () => Scheduler
35
33
  });
36
- module.exports = __toCommonJS(src_exports);
37
-
38
- // packages/core/functions/src/runtime/dev-server.ts
34
+ module.exports = __toCommonJS(node_exports);
39
35
  var import_express = __toESM(require("express"));
36
+ var import_get_port_please = require("get-port-please");
40
37
  var import_node_path = require("node:path");
41
- var import_portfinder = require("portfinder");
42
38
  var import_async = require("@dxos/async");
39
+ var import_invariant = require("@dxos/invariant");
43
40
  var import_log = require("@dxos/log");
44
- var __dxlog_file = "/home/circleci/project/packages/core/functions/src/runtime/dev-server.ts";
45
- var DEFAULT_PORT = 7e3;
41
+ var import_cron = require("cron");
42
+ var import_async2 = require("@dxos/async");
43
+ var import_context = require("@dxos/context");
44
+ var import_echo_schema = require("@dxos/echo-schema");
45
+ var import_invariant2 = require("@dxos/invariant");
46
+ var import_log2 = require("@dxos/log");
47
+ var import_util = require("@dxos/util");
48
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
49
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
50
+ }) : x)(function(x) {
51
+ if (typeof require !== "undefined")
52
+ return require.apply(this, arguments);
53
+ throw Error('Dynamic require of "' + x + '" is not supported');
54
+ });
55
+ var __dxlog_file = "/home/runner/work/dxos/dxos/packages/core/functions/src/runtime/dev-server.ts";
46
56
  var DevServer = class {
47
57
  // prettier-ignore
48
58
  constructor(_client, _options) {
49
59
  this._client = _client;
50
60
  this._options = _options;
51
61
  this._handlers = {};
52
- }
53
- get port() {
54
- return this._port;
62
+ this._seq = 0;
55
63
  }
56
64
  get endpoint() {
57
- return this._port ? `http://localhost:${this._port}` : void 0;
65
+ (0, import_invariant.invariant)(this._port, void 0, {
66
+ F: __dxlog_file,
67
+ L: 45,
68
+ S: this,
69
+ A: [
70
+ "this._port",
71
+ ""
72
+ ]
73
+ });
74
+ return `http://localhost:${this._port}`;
75
+ }
76
+ get proxy() {
77
+ return this._proxy;
58
78
  }
59
79
  get functions() {
60
- return Object.keys(this._handlers);
80
+ return Object.values(this._handlers);
61
81
  }
62
82
  async initialize() {
63
- for (const { id } of this._options.manifest.functions) {
83
+ for (const def of this._options.manifest.functions) {
64
84
  try {
65
- const module2 = require((0, import_node_path.join)(this._options.directory, id));
66
- const handler = module2.default;
67
- if (typeof handler !== "function") {
68
- throw new Error(`Handler must export default function: ${id}`);
69
- }
70
- this._handlers[id] = handler;
85
+ await this._load(def);
71
86
  } catch (err) {
72
- import_log.log.error("parsing function (check functions.yml manifest)", err, {
87
+ import_log.log.error("parsing function (check manifest)", err, {
73
88
  F: __dxlog_file,
74
- L: 63,
89
+ L: 62,
75
90
  S: this,
76
91
  C: (f, a) => f(...a)
77
92
  });
@@ -81,58 +96,55 @@ var DevServer = class {
81
96
  async start() {
82
97
  const app = (0, import_express.default)();
83
98
  app.use(import_express.default.json());
84
- app.post("/:functionName", async (req, res) => {
85
- const functionName = req.params.functionName;
86
- (0, import_log.log)("invoke", {
87
- function: functionName,
88
- data: req.body
89
- }, {
90
- F: __dxlog_file,
91
- L: 74,
92
- S: this,
93
- C: (f, a) => f(...a)
94
- });
95
- const builder = {
96
- status: (code) => {
97
- res.statusCode = code;
98
- return builder;
99
- },
100
- succeed: (result = {}) => {
101
- res.end(JSON.stringify(result));
102
- return builder;
103
- }
104
- };
105
- const context = {
106
- client: this._client,
107
- status: builder.status.bind(builder)
108
- };
109
- void (async () => {
110
- try {
111
- await this._handlers[functionName]({
112
- event: req.body,
113
- context
114
- });
115
- } catch (err) {
116
- res.statusCode = 500;
117
- res.end(err.message);
99
+ app.post("/:name", async (req, res) => {
100
+ const { name } = req.params;
101
+ try {
102
+ if (this._options.reload) {
103
+ const { def } = this._handlers[name];
104
+ await this._load(def, true);
118
105
  }
119
- })();
106
+ res.statusCode = await this._invoke(name, req.body);
107
+ res.end();
108
+ } catch (err) {
109
+ import_log.log.error(err, void 0, {
110
+ F: __dxlog_file,
111
+ L: 82,
112
+ S: this,
113
+ C: (f, a) => f(...a)
114
+ });
115
+ res.statusCode = 500;
116
+ res.end();
117
+ }
120
118
  });
121
- this._port = await (0, import_portfinder.getPortPromise)({
122
- startPort: DEFAULT_PORT
119
+ this._port = await (0, import_get_port_please.getPort)({
120
+ port: 7200,
121
+ portRange: [
122
+ 7200,
123
+ 7299
124
+ ]
123
125
  });
124
126
  this._server = app.listen(this._port);
125
127
  try {
126
- const { registrationId } = await this._client.services.services.FunctionRegistryService.register({
128
+ const { registrationId, endpoint } = await this._client.services.services.FunctionRegistryService.register({
127
129
  endpoint: this.endpoint,
128
- functions: this.functions.map((name) => ({
130
+ functions: this.functions.map(({ def: { name } }) => ({
129
131
  name
130
132
  }))
131
133
  });
134
+ import_log.log.info("registered", {
135
+ registrationId,
136
+ endpoint
137
+ }, {
138
+ F: __dxlog_file,
139
+ L: 98,
140
+ S: this,
141
+ C: (f, a) => f(...a)
142
+ });
132
143
  this._registrationId = registrationId;
144
+ this._proxy = endpoint;
133
145
  } catch (err) {
134
146
  await this.stop();
135
- throw new Error("FunctionRegistryService not available; check config (agent.plugins.functions).");
147
+ throw new Error("FunctionRegistryService not available (check plugin is configured).");
136
148
  }
137
149
  }
138
150
  async stop() {
@@ -142,52 +154,132 @@ var DevServer = class {
142
154
  await this._client.services.services.FunctionRegistryService.unregister({
143
155
  registrationId: this._registrationId
144
156
  });
157
+ import_log.log.info("unregistered", {
158
+ registrationId: this._registrationId
159
+ }, {
160
+ F: __dxlog_file,
161
+ L: 115,
162
+ S: this,
163
+ C: (f, a) => f(...a)
164
+ });
145
165
  this._registrationId = void 0;
166
+ this._proxy = void 0;
146
167
  }
147
168
  trigger.wake();
148
169
  });
149
170
  await trigger.wait();
150
- this._server = void 0;
151
171
  this._port = void 0;
172
+ this._server = void 0;
173
+ }
174
+ /**
175
+ * Load function.
176
+ */
177
+ async _load(def, flush = false) {
178
+ const { id, name, handler } = def;
179
+ const path = (0, import_node_path.join)(this._options.directory, handler);
180
+ import_log.log.info("loading", {
181
+ id
182
+ }, {
183
+ F: __dxlog_file,
184
+ L: 134,
185
+ S: this,
186
+ C: (f, a) => f(...a)
187
+ });
188
+ if (flush) {
189
+ Object.keys(__require.cache).filter((key) => key.startsWith(path)).forEach((key) => delete __require.cache[key]);
190
+ }
191
+ const module2 = __require(path);
192
+ if (typeof module2.default !== "function") {
193
+ throw new Error(`Handler must export default function: ${id}`);
194
+ }
195
+ this._handlers[name] = {
196
+ def,
197
+ handler: module2.default
198
+ };
199
+ }
200
+ /**
201
+ * Invoke function handler.
202
+ */
203
+ async _invoke(name, event) {
204
+ const seq = ++this._seq;
205
+ const now = Date.now();
206
+ import_log.log.info("req", {
207
+ seq,
208
+ name
209
+ }, {
210
+ F: __dxlog_file,
211
+ L: 159,
212
+ S: this,
213
+ C: (f, a) => f(...a)
214
+ });
215
+ const { handler } = this._handlers[name];
216
+ const context = {
217
+ client: this._client
218
+ };
219
+ let statusCode = 200;
220
+ const response = {
221
+ status: (code) => {
222
+ statusCode = code;
223
+ return response;
224
+ }
225
+ };
226
+ await handler({
227
+ context,
228
+ event,
229
+ response
230
+ });
231
+ import_log.log.info("res", {
232
+ seq,
233
+ name,
234
+ statusCode,
235
+ duration: Date.now() - now
236
+ }, {
237
+ F: __dxlog_file,
238
+ L: 175,
239
+ S: this,
240
+ C: (f, a) => f(...a)
241
+ });
242
+ return statusCode;
152
243
  }
153
244
  };
154
-
155
- // packages/core/functions/src/runtime/trigger-manager.ts
156
- var import_async2 = require("@dxos/async");
157
- var import_context = require("@dxos/context");
158
- var import_echo_schema = require("@dxos/echo-schema");
159
- var import_invariant = require("@dxos/invariant");
160
- var import_log2 = require("@dxos/log");
161
- var import_util = require("@dxos/util");
162
- var __dxlog_file2 = "/home/circleci/project/packages/core/functions/src/runtime/trigger-manager.ts";
163
- var TriggerManager = class {
164
- constructor(_client, _triggers, _invokeOptions) {
245
+ var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/core/functions/src/runtime/scheduler.ts";
246
+ var Scheduler = class {
247
+ constructor(_client, _manifest, _options) {
165
248
  this._client = _client;
166
- this._triggers = _triggers;
167
- this._invokeOptions = _invokeOptions;
168
- this._mounts = new import_util.ComplexMap(({ name, spaceKey }) => `${spaceKey.toHex()}:${name}`);
169
- this._queries = /* @__PURE__ */ new Set();
249
+ this._manifest = _manifest;
250
+ this._options = _options;
251
+ this._mounts = new import_util.ComplexMap(({ id, spaceKey }) => `${spaceKey.toHex()}:${id}`);
170
252
  }
171
253
  async start() {
172
254
  this._client.spaces.subscribe(async (spaces) => {
173
255
  for (const space of spaces) {
174
256
  await space.waitUntilReady();
175
- for (const trigger of this._triggers) {
257
+ for (const trigger of this._manifest.triggers ?? []) {
176
258
  await this.mount(new import_context.Context(), space, trigger);
177
259
  }
178
260
  }
179
261
  });
180
262
  }
181
263
  async stop() {
182
- for (const { name, spaceKey } of this._mounts.keys()) {
183
- await this.unmount(name, spaceKey);
264
+ for (const { id, spaceKey } of this._mounts.keys()) {
265
+ await this.unmount(id, spaceKey);
184
266
  }
185
267
  }
186
268
  async mount(ctx, space, trigger) {
187
269
  const key = {
188
- name: trigger.function,
270
+ id: trigger.function,
189
271
  spaceKey: space.key
190
272
  };
273
+ const def = this._manifest.functions.find((config) => config.id === trigger.function);
274
+ (0, import_invariant2.invariant)(def, `Function not found: ${trigger.function}`, {
275
+ F: __dxlog_file2,
276
+ L: 59,
277
+ S: this,
278
+ A: [
279
+ "def",
280
+ "`Function not found: ${trigger.function}`"
281
+ ]
282
+ });
191
283
  const exists = this._mounts.get(key);
192
284
  if (!exists) {
193
285
  this._mounts.set(key, {
@@ -199,57 +291,55 @@ var TriggerManager = class {
199
291
  trigger
200
292
  }, {
201
293
  F: __dxlog_file2,
202
- L: 60,
294
+ L: 64,
203
295
  S: this,
204
296
  C: (f, a) => f(...a)
205
297
  });
206
298
  if (ctx.disposed) {
207
299
  return;
208
300
  }
209
- const objectIds = /* @__PURE__ */ new Set();
210
- const task = new import_async2.DeferredTask(ctx, async () => {
211
- await this.invokeFunction(this._invokeOptions, trigger.function, {
212
- space: space.key,
213
- objects: Array.from(objectIds)
301
+ if (trigger.schedule) {
302
+ const task = new import_async2.DeferredTask(ctx, async () => {
303
+ await this.execFunction(def, {
304
+ space: space.key
305
+ });
214
306
  });
215
- });
216
- let count = 0;
217
- const subscription = (0, import_echo_schema.createSubscription)(({ added, updated }) => {
218
- for (const object of added) {
219
- objectIds.add(object.id);
220
- }
221
- for (const object of updated) {
222
- objectIds.add(object.id);
223
- }
224
- (0, import_log2.log)("updated", {
225
- trigger,
226
- space: space.key,
227
- objects: objectIds.size,
228
- count
229
- }, {
230
- F: __dxlog_file2,
231
- L: 84,
232
- S: this,
233
- C: (f, a) => f(...a)
307
+ const job = new import_cron.CronJob(trigger.schedule, () => task.schedule());
308
+ job.start();
309
+ ctx.onDispose(() => job.stop());
310
+ }
311
+ if (trigger.subscription) {
312
+ const objectIds = /* @__PURE__ */ new Set();
313
+ const task = new import_async2.DeferredTask(ctx, async () => {
314
+ await this.execFunction(def, {
315
+ space: space.key,
316
+ objects: Array.from(objectIds)
317
+ });
234
318
  });
235
- task.schedule();
236
- count++;
237
- });
238
- const query = space.db.query(import_echo_schema.Filter.typename(trigger.subscription.type, trigger.subscription.props));
239
- this._queries.add(query);
240
- const unsubscribe = query.subscribe(({ objects }) => {
241
- subscription.update(objects);
242
- }, true);
243
- ctx.onDispose(() => {
244
- subscription.unsubscribe();
245
- unsubscribe();
246
- this._queries.delete(query);
247
- });
319
+ const subscription = (0, import_echo_schema.createSubscription)(({ added, updated }) => {
320
+ for (const object of added) {
321
+ objectIds.add(object.id);
322
+ }
323
+ for (const object of updated) {
324
+ objectIds.add(object.id);
325
+ }
326
+ task.schedule();
327
+ });
328
+ const { type, props } = trigger.subscription;
329
+ const query = space.db.query(import_echo_schema.Filter.typename(type, props));
330
+ const unsubscribe = query.subscribe(({ objects }) => {
331
+ subscription.update(objects);
332
+ }, true);
333
+ ctx.onDispose(() => {
334
+ subscription.unsubscribe();
335
+ unsubscribe();
336
+ });
337
+ }
248
338
  }
249
339
  }
250
- async unmount(name, spaceKey) {
340
+ async unmount(id, spaceKey) {
251
341
  const key = {
252
- name,
342
+ id,
253
343
  spaceKey
254
344
  };
255
345
  const { ctx } = this._mounts.get(key) ?? {};
@@ -258,59 +348,39 @@ var TriggerManager = class {
258
348
  await ctx.dispose();
259
349
  }
260
350
  }
261
- async invokeFunction(options, functionName, data) {
262
- const { endpoint, runtime } = options;
263
- (0, import_invariant.invariant)(endpoint, "Missing endpoint", {
264
- F: __dxlog_file2,
265
- L: 120,
266
- S: this,
267
- A: [
268
- "endpoint",
269
- "'Missing endpoint'"
270
- ]
271
- });
272
- (0, import_invariant.invariant)(runtime, "Missing runtime", {
273
- F: __dxlog_file2,
274
- L: 121,
275
- S: this,
276
- A: [
277
- "runtime",
278
- "'Missing runtime'"
279
- ]
280
- });
351
+ async execFunction(def, data) {
281
352
  try {
282
- (0, import_log2.log)("invoke", {
283
- function: functionName
353
+ (0, import_log2.log)("request", {
354
+ function: def.id
284
355
  }, {
285
356
  F: __dxlog_file2,
286
- L: 124,
357
+ L: 130,
287
358
  S: this,
288
359
  C: (f, a) => f(...a)
289
360
  });
290
- const url = `${endpoint}/${runtime}/${functionName}`;
291
- const res = await fetch(url, {
361
+ const response = await fetch(`${this._options.endpoint}/${def.name}`, {
292
362
  method: "POST",
293
- body: JSON.stringify(data),
294
363
  headers: {
295
364
  "Content-Type": "application/json"
296
- }
365
+ },
366
+ body: JSON.stringify(data)
297
367
  });
298
368
  (0, import_log2.log)("result", {
299
- function: functionName,
300
- result: await res.json()
369
+ function: def.id,
370
+ result: response.status
301
371
  }, {
302
372
  F: __dxlog_file2,
303
- L: 134,
373
+ L: 140,
304
374
  S: this,
305
375
  C: (f, a) => f(...a)
306
376
  });
307
377
  } catch (err) {
308
378
  import_log2.log.error("error", {
309
- function: functionName,
379
+ function: def.id,
310
380
  error: err.message
311
381
  }, {
312
382
  F: __dxlog_file2,
313
- L: 136,
383
+ L: 142,
314
384
  S: this,
315
385
  C: (f, a) => f(...a)
316
386
  });
@@ -320,6 +390,6 @@ var TriggerManager = class {
320
390
  // Annotate the CommonJS export names for ESM import in node:
321
391
  0 && (module.exports = {
322
392
  DevServer,
323
- TriggerManager
393
+ Scheduler
324
394
  });
325
395
  //# sourceMappingURL=index.cjs.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../../../src/index.ts", "../../../src/runtime/dev-server.ts", "../../../src/runtime/trigger-manager.ts"],
4
- "sourcesContent": ["//\n// Copyright 2023 DXOS.org\n//\n\nexport * from './function';\nexport * from './runtime';\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport express from 'express';\nimport type http from 'http';\nimport { join } from 'node:path';\nimport { getPortPromise } from 'portfinder';\n\nimport { Trigger } from '@dxos/async';\nimport { type Client } from '@dxos/client';\nimport { log } from '@dxos/log';\n\nimport { type FunctionContext, type FunctionHandler, type FunctionsManifest, type Response } from '../function';\n\nconst DEFAULT_PORT = 7000;\n\nexport type DevServerOptions = {\n directory: string;\n manifest: FunctionsManifest;\n};\n\n/**\n * Functions dev server provides a local HTTP server for testing functions.\n */\nexport class DevServer {\n private readonly _handlers: Record<string, FunctionHandler<any>> = {};\n\n private _server?: http.Server;\n private _port?: number;\n private _registrationId?: string;\n\n // prettier-ignore\n constructor(\n private readonly _client: Client,\n private readonly _options: DevServerOptions,\n ) {}\n\n get port() {\n return this._port;\n }\n\n get endpoint() {\n return this._port ? `http://localhost:${this._port}` : undefined;\n }\n\n get functions() {\n return Object.keys(this._handlers);\n }\n\n async initialize() {\n for (const { id } of this._options.manifest.functions) {\n try {\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const module = require(join(this._options.directory, id));\n const handler = module.default;\n if (typeof handler !== 'function') {\n throw new Error(`Handler must export default function: ${id}`);\n }\n\n this._handlers[id] = handler;\n } catch (err) {\n log.error('parsing function (check functions.yml manifest)', err);\n }\n }\n }\n\n async start() {\n const app = express();\n app.use(express.json());\n\n app.post('/:functionName', async (req, res) => {\n const functionName = req.params.functionName;\n log('invoke', { function: functionName, data: req.body });\n\n const builder: Response = {\n status: (code: number) => {\n res.statusCode = code;\n return builder;\n },\n succeed: (result = {}) => {\n res.end(JSON.stringify(result));\n return builder;\n },\n };\n\n const context: FunctionContext = {\n client: this._client,\n status: builder.status.bind(builder),\n };\n\n void (async () => {\n try {\n // TODO(burdon): Typed event handler.\n await this._handlers[functionName]({ event: req.body, context });\n } catch (err: any) {\n res.statusCode = 500;\n res.end(err.message);\n }\n })();\n });\n\n this._port = await getPortPromise({ startPort: DEFAULT_PORT });\n this._server = app.listen(this._port);\n\n // TODO(burdon): Check plugin is registered.\n // TypeError: Cannot read properties of undefined (reading 'register')\n try {\n const { registrationId } = await this._client.services.services.FunctionRegistryService!.register({\n endpoint: this.endpoint!,\n functions: this.functions.map((name) => ({ name })),\n });\n this._registrationId = registrationId;\n } catch (err: any) {\n await this.stop();\n throw new Error('FunctionRegistryService not available; check config (agent.plugins.functions).');\n }\n }\n\n async stop() {\n const trigger = new Trigger();\n this._server?.close(async () => {\n if (this._registrationId) {\n await this._client.services.services.FunctionRegistryService!.unregister({\n registrationId: this._registrationId,\n });\n this._registrationId = undefined;\n }\n\n trigger.wake();\n });\n\n await trigger.wait();\n this._server = undefined;\n this._port = undefined;\n }\n}\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { DeferredTask } from '@dxos/async';\nimport { type Client, type PublicKey } from '@dxos/client';\nimport type { Query, Space } from '@dxos/client/echo';\nimport { Context } from '@dxos/context';\nimport { Filter, createSubscription } from '@dxos/echo-schema';\nimport { invariant } from '@dxos/invariant';\nimport { log } from '@dxos/log';\nimport { ComplexMap } from '@dxos/util';\n\nimport { type FunctionTrigger } from '../function';\n\n// TODO(burdon): Rename.\nexport type InvokeOptions = {\n endpoint: string;\n runtime: string;\n};\n\nexport class TriggerManager {\n private readonly _mounts = new ComplexMap<\n { name: string; spaceKey: PublicKey },\n { ctx: Context; trigger: FunctionTrigger }\n >(({ name, spaceKey }) => `${spaceKey.toHex()}:${name}`);\n\n private readonly _queries = new Set<Query>();\n\n constructor(\n private readonly _client: Client,\n private readonly _triggers: FunctionTrigger[],\n private readonly _invokeOptions: InvokeOptions,\n ) {}\n\n async start() {\n // TODO(burdon): Make runtime configurable (via CLI)?\n this._client.spaces.subscribe(async (spaces) => {\n for (const space of spaces) {\n await space.waitUntilReady();\n for (const trigger of this._triggers) {\n // TODO(burdon): New context? Shared?\n await this.mount(new Context(), space, trigger);\n }\n }\n });\n }\n\n async stop() {\n for (const { name, spaceKey } of this._mounts.keys()) {\n await this.unmount(name, spaceKey);\n }\n }\n\n private async mount(ctx: Context, space: Space, trigger: FunctionTrigger) {\n const key = { name: trigger.function, spaceKey: space.key };\n const exists = this._mounts.get(key);\n if (!exists) {\n this._mounts.set(key, { ctx, trigger });\n log('mount', { space: space.key, trigger });\n if (ctx.disposed) {\n return;\n }\n\n // TODO(burdon): Trigger binding.\n // TODO(burdon): Why DeferredTask? How to pass objectIds to function?\n const objectIds = new Set<string>();\n const task = new DeferredTask(ctx, async () => {\n await this.invokeFunction(this._invokeOptions, trigger.function, {\n space: space.key,\n objects: Array.from(objectIds),\n });\n });\n\n let count = 0;\n const subscription = createSubscription(({ added, updated }) => {\n for (const object of added) {\n objectIds.add(object.id);\n }\n for (const object of updated) {\n objectIds.add(object.id);\n }\n\n log('updated', {\n trigger,\n space: space.key,\n objects: objectIds.size,\n count,\n });\n\n task.schedule();\n count++;\n });\n // TODO(burdon): DSL for query (replace props).\n const query = space.db.query(Filter.typename(trigger.subscription.type, trigger.subscription.props));\n this._queries.add(query);\n const unsubscribe = query.subscribe(({ objects }) => {\n subscription.update(objects);\n }, true);\n\n ctx.onDispose(() => {\n subscription.unsubscribe();\n unsubscribe();\n this._queries.delete(query);\n });\n }\n }\n\n private async unmount(name: string, spaceKey: PublicKey) {\n const key = { name, spaceKey };\n const { ctx } = this._mounts.get(key) ?? {};\n if (ctx) {\n this._mounts.delete(key);\n await ctx.dispose();\n }\n }\n\n private async invokeFunction(options: InvokeOptions, functionName: string, data: any) {\n const { endpoint, runtime } = options;\n invariant(endpoint, 'Missing endpoint');\n invariant(runtime, 'Missing runtime');\n\n try {\n log('invoke', { function: functionName });\n const url = `${endpoint}/${runtime}/${functionName}`;\n const res = await fetch(url, {\n method: 'POST',\n body: JSON.stringify(data),\n headers: {\n 'Content-Type': 'application/json',\n },\n });\n\n log('result', { function: functionName, result: await res.json() });\n } catch (err: any) {\n log.error('error', { function: functionName, error: err.message });\n }\n }\n}\n"],
5
- "mappings": "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",
6
- "names": ["DEFAULT_PORT", "DevServer", "constructor", "_client", "_options", "_handlers", "port", "_port", "endpoint", "undefined", "functions", "Object", "keys", "initialize", "id", "manifest", "module", "require", "join", "directory", "handler", "default", "Error", "err", "log", "error", "start", "app", "express", "use", "json", "post", "req", "res", "functionName", "params", "function", "data", "body", "builder", "status", "code", "statusCode", "succeed", "result", "end", "JSON", "stringify", "context", "client", "bind", "event", "message", "getPortPromise", "startPort", "_server", "listen", "registrationId", "services", "FunctionRegistryService", "register", "map", "name", "_registrationId", "stop", "trigger", "Trigger", "close", "unregister", "wake", "wait", "import_async", "import_log", "TriggerManager", "constructor", "_client", "_triggers", "_invokeOptions", "_mounts", "ComplexMap", "name", "spaceKey", "toHex", "_queries", "Set", "start", "spaces", "subscribe", "space", "waitUntilReady", "trigger", "mount", "Context", "stop", "keys", "unmount", "ctx", "key", "function", "exists", "get", "set", "log", "disposed", "objectIds", "task", "DeferredTask", "invokeFunction", "objects", "Array", "from", "count", "subscription", "createSubscription", "added", "updated", "object", "add", "id", "size", "schedule", "query", "db", "Filter", "typename", "type", "props", "unsubscribe", "update", "onDispose", "delete", "dispose", "options", "functionName", "data", "endpoint", "runtime", "invariant", "url", "res", "fetch", "method", "body", "JSON", "stringify", "headers", "result", "json", "err", "error", "message"]
3
+ "sources": ["../../../src/runtime/dev-server.ts", "../../../src/runtime/scheduler.ts"],
4
+ "sourcesContent": ["//\n// Copyright 2023 DXOS.org\n//\n\nimport express from 'express';\nimport { getPort } from 'get-port-please';\nimport type http from 'http';\nimport { join } from 'node:path';\n\nimport { Trigger } from '@dxos/async';\nimport { type Client } from '@dxos/client';\nimport { invariant } from '@dxos/invariant';\nimport { log } from '@dxos/log';\n\nimport { type FunctionContext, type FunctionHandler, type Response } from '../handler';\nimport { type FunctionDef, type FunctionManifest } from '../manifest';\n\nexport type DevServerOptions = {\n port?: number;\n directory: string;\n manifest: FunctionManifest;\n reload?: boolean;\n};\n\n/**\n * Functions dev server provides a local HTTP server for testing functions.\n */\nexport class DevServer {\n // Function handlers indexed by name (URL path).\n private readonly _handlers: Record<string, { def: FunctionDef; handler: FunctionHandler<any> }> = {};\n\n private _server?: http.Server;\n private _port?: number;\n private _registrationId?: string;\n private _proxy?: string;\n private _seq = 0;\n\n // prettier-ignore\n constructor(\n private readonly _client: Client,\n private readonly _options: DevServerOptions,\n ) {}\n\n get endpoint() {\n invariant(this._port);\n return `http://localhost:${this._port}`;\n }\n\n get proxy() {\n return this._proxy;\n }\n\n get functions() {\n return Object.values(this._handlers);\n }\n\n async initialize() {\n for (const def of this._options.manifest.functions) {\n try {\n await this._load(def);\n } catch (err) {\n log.error('parsing function (check manifest)', err);\n }\n }\n }\n\n async start() {\n const app = express();\n app.use(express.json());\n\n app.post('/:name', async (req, res) => {\n const { name } = req.params;\n try {\n if (this._options.reload) {\n const { def } = this._handlers[name];\n await this._load(def, true);\n }\n\n res.statusCode = await this._invoke(name, req.body);\n res.end();\n } catch (err: any) {\n log.error(err);\n res.statusCode = 500;\n res.end();\n }\n });\n\n this._port = await getPort({ port: 7200, portRange: [7200, 7299] });\n this._server = app.listen(this._port);\n\n try {\n // Register functions.\n const { registrationId, endpoint } = await this._client.services.services.FunctionRegistryService!.register({\n endpoint: this.endpoint,\n functions: this.functions.map(({ def: { name } }) => ({ name })),\n });\n\n log.info('registered', { registrationId, endpoint });\n this._registrationId = registrationId;\n this._proxy = endpoint;\n } catch (err: any) {\n await this.stop();\n throw new Error('FunctionRegistryService not available (check plugin is configured).');\n }\n }\n\n async stop() {\n const trigger = new Trigger();\n this._server?.close(async () => {\n if (this._registrationId) {\n await this._client.services.services.FunctionRegistryService!.unregister({\n registrationId: this._registrationId,\n });\n\n log.info('unregistered', { registrationId: this._registrationId });\n this._registrationId = undefined;\n this._proxy = undefined;\n }\n\n trigger.wake();\n });\n\n await trigger.wait();\n this._port = undefined;\n this._server = undefined;\n }\n\n /**\n * Load function.\n */\n private async _load(def: FunctionDef, flush = false) {\n const { id, name, handler } = def;\n const path = join(this._options.directory, handler);\n log.info('loading', { id });\n\n // Remove from cache.\n if (flush) {\n Object.keys(require.cache)\n .filter((key) => key.startsWith(path))\n .forEach((key) => delete require.cache[key]);\n }\n\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const module = require(path);\n if (typeof module.default !== 'function') {\n throw new Error(`Handler must export default function: ${id}`);\n }\n\n this._handlers[name] = { def, handler: module.default };\n }\n\n /**\n * Invoke function handler.\n */\n private async _invoke(name: string, event: any) {\n const seq = ++this._seq;\n const now = Date.now();\n\n log.info('req', { seq, name });\n const { handler } = this._handlers[name];\n\n const context: FunctionContext = {\n client: this._client,\n };\n\n let statusCode = 200;\n const response: Response = {\n status: (code: number) => {\n statusCode = code;\n return response;\n },\n };\n\n await handler({ context, event, response });\n log.info('res', { seq, name, statusCode, duration: Date.now() - now });\n\n return statusCode;\n }\n}\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { CronJob } from 'cron';\n\nimport { DeferredTask } from '@dxos/async';\nimport { type Client, type PublicKey } from '@dxos/client';\nimport { type Space } from '@dxos/client/echo';\nimport { Context } from '@dxos/context';\nimport { Filter, createSubscription } from '@dxos/echo-schema';\nimport { invariant } from '@dxos/invariant';\nimport { log } from '@dxos/log';\nimport { ComplexMap } from '@dxos/util';\n\nimport { type FunctionDef, type FunctionManifest, type FunctionTrigger } from '../manifest';\n\ntype SchedulerOptions = {\n endpoint: string;\n};\n\n/**\n * Functions scheduler.\n */\n// TODO(burdon): Create tests.\nexport class Scheduler {\n // Map of mounted functions.\n private readonly _mounts = new ComplexMap<\n { id: string; spaceKey: PublicKey },\n { ctx: Context; trigger: FunctionTrigger }\n >(({ id, spaceKey }) => `${spaceKey.toHex()}:${id}`);\n\n constructor(\n private readonly _client: Client,\n private readonly _manifest: FunctionManifest,\n private readonly _options: SchedulerOptions,\n ) {}\n\n async start() {\n this._client.spaces.subscribe(async (spaces) => {\n for (const space of spaces) {\n await space.waitUntilReady();\n for (const trigger of this._manifest.triggers ?? []) {\n await this.mount(new Context(), space, trigger);\n }\n }\n });\n }\n\n async stop() {\n for (const { id, spaceKey } of this._mounts.keys()) {\n await this.unmount(id, spaceKey);\n }\n }\n\n private async mount(ctx: Context, space: Space, trigger: FunctionTrigger) {\n const key = { id: trigger.function, spaceKey: space.key };\n const def = this._manifest.functions.find((config) => config.id === trigger.function);\n invariant(def, `Function not found: ${trigger.function}`);\n\n const exists = this._mounts.get(key);\n if (!exists) {\n this._mounts.set(key, { ctx, trigger });\n log('mount', { space: space.key, trigger });\n if (ctx.disposed) {\n return;\n }\n\n // Cron schedule.\n if (trigger.schedule) {\n const task = new DeferredTask(ctx, async () => {\n await this.execFunction(def, {\n space: space.key,\n });\n });\n\n // TODO(burdon): Check greater than 30s min (use cron-parser).\n const job = new CronJob(trigger.schedule, () => task.schedule());\n\n job.start();\n ctx.onDispose(() => job.stop());\n }\n\n // ECHO subscription.\n if (trigger.subscription) {\n const objectIds = new Set<string>();\n const task = new DeferredTask(ctx, async () => {\n await this.execFunction(def, {\n space: space.key,\n objects: Array.from(objectIds),\n });\n });\n\n const subscription = createSubscription(({ added, updated }) => {\n for (const object of added) {\n objectIds.add(object.id);\n }\n for (const object of updated) {\n objectIds.add(object.id);\n }\n\n task.schedule();\n });\n\n const { type, props } = trigger.subscription;\n const query = space.db.query(Filter.typename(type, props));\n const unsubscribe = query.subscribe(({ objects }) => {\n subscription.update(objects);\n }, true);\n\n ctx.onDispose(() => {\n subscription.unsubscribe();\n unsubscribe();\n });\n }\n }\n }\n\n private async unmount(id: string, spaceKey: PublicKey) {\n const key = { id, spaceKey };\n const { ctx } = this._mounts.get(key) ?? {};\n if (ctx) {\n this._mounts.delete(key);\n await ctx.dispose();\n }\n }\n\n private async execFunction(def: FunctionDef, data: any) {\n try {\n log('request', { function: def.id });\n const response = await fetch(`${this._options.endpoint}/${def.name}`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(data),\n });\n\n // const result = await response.json();\n log('result', { function: def.id, result: response.status });\n } catch (err: any) {\n log.error('error', { function: def.id, error: err.message });\n }\n }\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAIA,qBAAoB;AACpB,6BAAwB;AAExB,uBAAqB;AAErB,mBAAwB;AAExB,uBAA0B;AAC1B,iBAAoB;ACRpB,kBAAwB;AAExB,IAAAA,gBAA6B;AAG7B,qBAAwB;AACxB,yBAA2C;AAC3C,IAAAC,oBAA0B;AAC1B,IAAAC,cAAoB;AACpB,kBAA2B;;;;;;;;;ADcpB,IAAMC,YAAN,MAAMA;;EAWXC,YACmBC,SACAC,UACjB;mBAFiBD;oBACAC;SAXFC,YAAiF,CAAC;SAM3FC,OAAO;EAMZ;EAEH,IAAIC,WAAW;AACbC,oCAAU,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,uBAAIC,MAAM,qCAAqCF,KAAAA;;;;;;MACjD;IACF;EACF;EAEA,MAAMG,QAAQ;AACZ,UAAMC,UAAMC,eAAAA,SAAAA;AACZD,QAAIE,IAAID,eAAAA,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,uBAAIC,MAAMF,KAAAA,QAAAA;;;;;;AACVU,YAAII,aAAa;AACjBJ,YAAIO,IAAG;MACT;IACF,CAAA;AAEA,SAAK3B,QAAQ,UAAM4B,gCAAQ;MAAEC,MAAM;MAAMC,WAAW;QAAC;QAAM;;IAAM,CAAA;AACjE,SAAKC,UAAUjB,IAAIkB,OAAO,KAAKhC,KAAK;AAEpC,QAAI;AAEF,YAAM,EAAEiC,gBAAgBnC,SAAQ,IAAK,MAAM,KAAKJ,QAAQwC,SAASA,SAASC,wBAAyBC,SAAS;QAC1GtC,UAAU,KAAKA;QACfK,WAAW,KAAKA,UAAUkC,IAAI,CAAC,EAAE9B,KAAK,EAAEc,KAAI,EAAE,OAAQ;UAAEA;QAAK,EAAA;MAC/D,CAAA;AAEAV,qBAAI2B,KAAK,cAAc;QAAEL;QAAgBnC;MAAS,GAAA;;;;;;AAClD,WAAKyC,kBAAkBN;AACvB,WAAK/B,SAASJ;IAChB,SAASY,KAAU;AACjB,YAAM,KAAK8B,KAAI;AACf,YAAM,IAAIC,MAAM,qEAAA;IAClB;EACF;EAEA,MAAMD,OAAO;AACX,UAAME,UAAU,IAAIC,qBAAAA;AACpB,SAAKZ,SAASa,MAAM,YAAA;AAClB,UAAI,KAAKL,iBAAiB;AACxB,cAAM,KAAK7C,QAAQwC,SAASA,SAASC,wBAAyBU,WAAW;UACvEZ,gBAAgB,KAAKM;QACvB,CAAA;AAEA5B,uBAAI2B,KAAK,gBAAgB;UAAEL,gBAAgB,KAAKM;QAAgB,GAAA;;;;;;AAChE,aAAKA,kBAAkBO;AACvB,aAAK5C,SAAS4C;MAChB;AAEAJ,cAAQK,KAAI;IACd,CAAA;AAEA,UAAML,QAAQM,KAAI;AAClB,SAAKhD,QAAQ8C;AACb,SAAKf,UAAUe;EACjB;;;;EAKA,MAAcrC,MAAMF,KAAkB0C,QAAQ,OAAO;AACnD,UAAM,EAAEC,IAAI7B,MAAM8B,QAAO,IAAK5C;AAC9B,UAAM6C,WAAOC,uBAAK,KAAK1D,SAAS2D,WAAWH,OAAAA;AAC3CxC,mBAAI2B,KAAK,WAAW;MAAEY;IAAG,GAAA;;;;;;AAGzB,QAAID,OAAO;AACT7C,aAAOmD,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,UAASN,UAAQJ,IAAAA;AACvB,QAAI,OAAOU,QAAOC,YAAY,YAAY;AACxC,YAAM,IAAItB,MAAM,yCAAyCS,EAAAA,EAAI;IAC/D;AAEA,SAAKtD,UAAUyB,IAAAA,IAAQ;MAAEd;MAAK4C,SAASW,QAAOC;IAAQ;EACxD;;;;EAKA,MAActC,QAAQJ,MAAc2C,OAAY;AAC9C,UAAMC,MAAM,EAAE,KAAKpE;AACnB,UAAMqE,MAAMC,KAAKD,IAAG;AAEpBvD,mBAAI2B,KAAK,OAAO;MAAE2B;MAAK5C;IAAK,GAAA;;;;;;AAC5B,UAAM,EAAE8B,QAAO,IAAK,KAAKvD,UAAUyB,IAAAA;AAEnC,UAAM+C,UAA2B;MAC/BC,QAAQ,KAAK3E;IACf;AAEA,QAAI8B,aAAa;AACjB,UAAM8C,WAAqB;MACzBC,QAAQ,CAACC,SAAAA;AACPhD,qBAAagD;AACb,eAAOF;MACT;IACF;AAEA,UAAMnB,QAAQ;MAAEiB;MAASJ;MAAOM;IAAS,CAAA;AACzC3D,mBAAI2B,KAAK,OAAO;MAAE2B;MAAK5C;MAAMG;MAAYiD,UAAUN,KAAKD,IAAG,IAAKA;IAAI,GAAA;;;;;;AAEpE,WAAO1C;EACT;AACF;;ACzJO,IAAMkD,YAAN,MAAMA;EAOXjF,YACmBC,SACAiF,WACAhF,UACjB;mBAHiBD;qBACAiF;oBACAhF;SARFiF,UAAU,IAAIC,uBAG7B,CAAC,EAAE3B,IAAI4B,SAAQ,MAAO,GAAGA,SAASC,MAAK,CAAA,IAAM7B,EAAAA,EAAI;EAMhD;EAEH,MAAMrC,QAAQ;AACZ,SAAKnB,QAAQsF,OAAOC,UAAU,OAAOD,WAAAA;AACnC,iBAAWE,SAASF,QAAQ;AAC1B,cAAME,MAAMC,eAAc;AAC1B,mBAAWzC,WAAW,KAAKiC,UAAUS,YAAY,CAAA,GAAI;AACnD,gBAAM,KAAKC,MAAM,IAAIC,uBAAAA,GAAWJ,OAAOxC,OAAAA;QACzC;MACF;IACF,CAAA;EACF;EAEA,MAAMF,OAAO;AACX,eAAW,EAAEU,IAAI4B,SAAQ,KAAM,KAAKF,QAAQrB,KAAI,GAAI;AAClD,YAAM,KAAKgC,QAAQrC,IAAI4B,QAAAA;IACzB;EACF;EAEA,MAAcO,MAAMG,KAAcN,OAAcxC,SAA0B;AACxE,UAAMiB,MAAM;MAAET,IAAIR,QAAQ+C;MAAUX,UAAUI,MAAMvB;IAAI;AACxD,UAAMpD,MAAM,KAAKoE,UAAUxE,UAAUuF,KAAK,CAACC,WAAWA,OAAOzC,OAAOR,QAAQ+C,QAAQ;AACpF1F,0BAAAA,WAAUQ,KAAK,uBAAuBmC,QAAQ+C,QAAQ,IAAE;;;;;;;;;AAExD,UAAMG,SAAS,KAAKhB,QAAQiB,IAAIlC,GAAAA;AAChC,QAAI,CAACiC,QAAQ;AACX,WAAKhB,QAAQkB,IAAInC,KAAK;QAAE6B;QAAK9C;MAAQ,CAAA;AACrC/B,sBAAAA,KAAI,SAAS;QAAEuE,OAAOA,MAAMvB;QAAKjB;MAAQ,GAAA;;;;;;AACzC,UAAI8C,IAAIO,UAAU;AAChB;MACF;AAGA,UAAIrD,QAAQsD,UAAU;AACpB,cAAMC,OAAO,IAAIC,2BAAaV,KAAK,YAAA;AACjC,gBAAM,KAAKW,aAAa5F,KAAK;YAC3B2E,OAAOA,MAAMvB;UACf,CAAA;QACF,CAAA;AAGA,cAAMyC,MAAM,IAAIC,oBAAQ3D,QAAQsD,UAAU,MAAMC,KAAKD,SAAQ,CAAA;AAE7DI,YAAIvF,MAAK;AACT2E,YAAIc,UAAU,MAAMF,IAAI5D,KAAI,CAAA;MAC9B;AAGA,UAAIE,QAAQ6D,cAAc;AACxB,cAAMC,YAAY,oBAAIC,IAAAA;AACtB,cAAMR,OAAO,IAAIC,2BAAaV,KAAK,YAAA;AACjC,gBAAM,KAAKW,aAAa5F,KAAK;YAC3B2E,OAAOA,MAAMvB;YACb+C,SAASC,MAAMC,KAAKJ,SAAAA;UACtB,CAAA;QACF,CAAA;AAEA,cAAMD,mBAAeM,uCAAmB,CAAC,EAAEC,OAAOC,QAAO,MAAE;AACzD,qBAAWC,UAAUF,OAAO;AAC1BN,sBAAUS,IAAID,OAAO9D,EAAE;UACzB;AACA,qBAAW8D,UAAUD,SAAS;AAC5BP,sBAAUS,IAAID,OAAO9D,EAAE;UACzB;AAEA+C,eAAKD,SAAQ;QACf,CAAA;AAEA,cAAM,EAAEkB,MAAMC,MAAK,IAAKzE,QAAQ6D;AAChC,cAAMa,QAAQlC,MAAMmC,GAAGD,MAAME,0BAAOC,SAASL,MAAMC,KAAAA,CAAAA;AACnD,cAAMK,cAAcJ,MAAMnC,UAAU,CAAC,EAAEyB,QAAO,MAAE;AAC9CH,uBAAakB,OAAOf,OAAAA;QACtB,GAAG,IAAA;AAEHlB,YAAIc,UAAU,MAAA;AACZC,uBAAaiB,YAAW;AACxBA,sBAAAA;QACF,CAAA;MACF;IACF;EACF;EAEA,MAAcjC,QAAQrC,IAAY4B,UAAqB;AACrD,UAAMnB,MAAM;MAAET;MAAI4B;IAAS;AAC3B,UAAM,EAAEU,IAAG,IAAK,KAAKZ,QAAQiB,IAAIlC,GAAAA,KAAQ,CAAC;AAC1C,QAAI6B,KAAK;AACP,WAAKZ,QAAQ8C,OAAO/D,GAAAA;AACpB,YAAM6B,IAAImC,QAAO;IACnB;EACF;EAEA,MAAcxB,aAAa5F,KAAkBqH,MAAW;AACtD,QAAI;AACFjH,sBAAAA,KAAI,WAAW;QAAE8E,UAAUlF,IAAI2C;MAAG,GAAA;;;;;;AAClC,YAAMoB,WAAW,MAAMuD,MAAM,GAAG,KAAKlI,SAASG,QAAQ,IAAIS,IAAIc,IAAI,IAAI;QACpEyG,QAAQ;QACRC,SAAS;UACP,gBAAgB;QAClB;QACArG,MAAMsG,KAAKC,UAAUL,IAAAA;MACvB,CAAA;AAGAjH,sBAAAA,KAAI,UAAU;QAAE8E,UAAUlF,IAAI2C;QAAIgF,QAAQ5D,SAASC;MAAO,GAAA;;;;;;IAC5D,SAAS7D,KAAU;AACjBC,kBAAAA,IAAIC,MAAM,SAAS;QAAE6E,UAAUlF,IAAI2C;QAAItC,OAAOF,IAAIyH;MAAQ,GAAA;;;;;;IAC5D;EACF;AACF;",
6
+ "names": ["import_async", "import_invariant", "import_log", "DevServer", "constructor", "_client", "_options", "_handlers", "_seq", "endpoint", "invariant", "_port", "proxy", "_proxy", "functions", "Object", "values", "initialize", "def", "manifest", "_load", "err", "log", "error", "start", "app", "express", "use", "json", "post", "req", "res", "name", "params", "reload", "statusCode", "_invoke", "body", "end", "getPort", "port", "portRange", "_server", "listen", "registrationId", "services", "FunctionRegistryService", "register", "map", "info", "_registrationId", "stop", "Error", "trigger", "Trigger", "close", "unregister", "undefined", "wake", "wait", "flush", "id", "handler", "path", "join", "directory", "keys", "require", "cache", "filter", "key", "startsWith", "forEach", "module", "default", "event", "seq", "now", "Date", "context", "client", "response", "status", "code", "duration", "Scheduler", "_manifest", "_mounts", "ComplexMap", "spaceKey", "toHex", "spaces", "subscribe", "space", "waitUntilReady", "triggers", "mount", "Context", "unmount", "ctx", "function", "find", "config", "exists", "get", "set", "disposed", "schedule", "task", "DeferredTask", "execFunction", "job", "CronJob", "onDispose", "subscription", "objectIds", "Set", "objects", "Array", "from", "createSubscription", "added", "updated", "object", "add", "type", "props", "query", "db", "Filter", "typename", "unsubscribe", "update", "delete", "dispose", "data", "fetch", "method", "headers", "JSON", "stringify", "result", "message"]
7
7
  }