@dxos/functions 0.3.5-main.fa2fc5b → 0.3.5-next.5910692

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.
@@ -127,7 +127,7 @@ var DevServer = class {
127
127
  // packages/core/functions/src/runtime/trigger-manager.ts
128
128
  import { DeferredTask } from "@dxos/async";
129
129
  import { Context } from "@dxos/context";
130
- import { Filter, createSubscription } from "@dxos/echo-schema";
130
+ import { createSubscription } from "@dxos/echo-schema";
131
131
  import { invariant } from "@dxos/invariant";
132
132
  import { log as log2 } from "@dxos/log";
133
133
  import { ComplexMap } from "@dxos/util";
@@ -138,7 +138,6 @@ var TriggerManager = class {
138
138
  this._triggers = _triggers;
139
139
  this._invokeOptions = _invokeOptions;
140
140
  this._mounts = new ComplexMap(({ name, spaceKey }) => `${spaceKey.toHex()}:${name}`);
141
- this._queries = /* @__PURE__ */ new Set();
142
141
  }
143
142
  async start() {
144
143
  this._client.spaces.subscribe(async (spaces) => {
@@ -171,7 +170,7 @@ var TriggerManager = class {
171
170
  trigger
172
171
  }, {
173
172
  F: __dxlog_file2,
174
- L: 60,
173
+ L: 58,
175
174
  S: this,
176
175
  C: (f, a) => f(...a)
177
176
  });
@@ -200,23 +199,22 @@ var TriggerManager = class {
200
199
  count
201
200
  }, {
202
201
  F: __dxlog_file2,
203
- L: 84,
202
+ L: 82,
204
203
  S: this,
205
204
  C: (f, a) => f(...a)
206
205
  });
207
206
  task.schedule();
208
207
  count++;
209
208
  });
210
- const query = space.db.query(Filter.typename(trigger.subscription.type, trigger.subscription.props));
211
- this._queries.add(query);
209
+ ctx.onDispose(() => subscription.unsubscribe());
210
+ const query = space.db.query({
211
+ "@type": trigger.subscription.type,
212
+ ...trigger.subscription.props
213
+ });
212
214
  const unsubscribe = query.subscribe(({ objects }) => {
213
215
  subscription.update(objects);
214
- }, true);
215
- ctx.onDispose(() => {
216
- subscription.unsubscribe();
217
- unsubscribe();
218
- this._queries.delete(query);
219
216
  });
217
+ ctx.onDispose(() => unsubscribe());
220
218
  }
221
219
  }
222
220
  async unmount(name, spaceKey) {
@@ -234,7 +232,7 @@ var TriggerManager = class {
234
232
  const { endpoint, runtime } = options;
235
233
  invariant(endpoint, "Missing endpoint", {
236
234
  F: __dxlog_file2,
237
- L: 120,
235
+ L: 119,
238
236
  S: this,
239
237
  A: [
240
238
  "endpoint",
@@ -243,7 +241,7 @@ var TriggerManager = class {
243
241
  });
244
242
  invariant(runtime, "Missing runtime", {
245
243
  F: __dxlog_file2,
246
- L: 121,
244
+ L: 120,
247
245
  S: this,
248
246
  A: [
249
247
  "runtime",
@@ -255,7 +253,7 @@ var TriggerManager = class {
255
253
  function: functionName
256
254
  }, {
257
255
  F: __dxlog_file2,
258
- L: 124,
256
+ L: 123,
259
257
  S: this,
260
258
  C: (f, a) => f(...a)
261
259
  });
@@ -272,7 +270,7 @@ var TriggerManager = class {
272
270
  result: await res.json()
273
271
  }, {
274
272
  F: __dxlog_file2,
275
- L: 134,
273
+ L: 133,
276
274
  S: this,
277
275
  C: (f, a) => f(...a)
278
276
  });
@@ -282,7 +280,7 @@ var TriggerManager = class {
282
280
  error: err.message
283
281
  }, {
284
282
  F: __dxlog_file2,
285
- L: 136,
283
+ L: 135,
286
284
  S: this,
287
285
  C: (f, a) => f(...a)
288
286
  });
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/runtime/dev-server.ts", "../../../src/runtime/trigger-manager.ts"],
4
- "sourcesContent": ["//\n// Copyright 2023 DXOS.org\n//\n\nimport express from 'express';\nimport type http from 'http';\nimport { join } from 'node:path';\nimport { getPortPromise } from 'portfinder';\n\nimport { Trigger } from '@dxos/async';\nimport { type Client } from '@dxos/client';\nimport { log } from '@dxos/log';\n\nimport { type FunctionContext, type FunctionHandler, type 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 */\n// TODO(burdon): Not secure.\nexport class DevServer {\n private readonly _functionHandlers: 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._functionHandlers);\n }\n\n async initialize() {\n for (const [name, _] of Object.entries(this._options.manifest.functions)) {\n try {\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const module = require(join(this._options.directory, name));\n const handler = module.default;\n if (typeof handler !== 'function') {\n throw new Error(`Handler must export default function: ${name}`);\n }\n\n this._functionHandlers[name] = 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._functionHandlers[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": ["express", "join", "getPortPromise", "Trigger", "log", "DEFAULT_PORT", "DevServer", "constructor", "_client", "_options", "_functionHandlers", "port", "_port", "endpoint", "undefined", "functions", "Object", "keys", "initialize", "name", "_", "entries", "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", "_registrationId", "stop", "trigger", "Trigger", "close", "unregister", "wake", "wait", "DeferredTask", "Context", "Filter", "createSubscription", "invariant", "log", "ComplexMap", "TriggerManager", "constructor", "_client", "_triggers", "_invokeOptions", "_mounts", "name", "spaceKey", "toHex", "_queries", "Set", "start", "spaces", "subscribe", "space", "waitUntilReady", "trigger", "mount", "stop", "keys", "unmount", "ctx", "key", "function", "exists", "get", "set", "disposed", "objectIds", "task", "invokeFunction", "objects", "Array", "from", "count", "subscription", "added", "updated", "object", "add", "id", "size", "schedule", "query", "db", "typename", "type", "props", "unsubscribe", "update", "onDispose", "delete", "dispose", "options", "functionName", "data", "endpoint", "runtime", "url", "res", "fetch", "method", "body", "JSON", "stringify", "headers", "result", "json", "err", "error", "message"]
4
+ "sourcesContent": ["//\n// Copyright 2023 DXOS.org\n//\n\nimport express from 'express';\nimport type http from 'http';\nimport { join } from 'node:path';\nimport { getPortPromise } from 'portfinder';\n\nimport { Trigger } from '@dxos/async';\nimport { type Client } from '@dxos/client';\nimport { log } from '@dxos/log';\n\nimport { type FunctionContext, type FunctionHandler, type 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 */\n// TODO(burdon): Not secure.\nexport class DevServer {\n private readonly _functionHandlers: 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._functionHandlers);\n }\n\n async initialize() {\n for (const [name, _] of Object.entries(this._options.manifest.functions)) {\n try {\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const module = require(join(this._options.directory, name));\n const handler = module.default;\n if (typeof handler !== 'function') {\n throw new Error(`Handler must export default function: ${name}`);\n }\n\n this._functionHandlers[name] = 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._functionHandlers[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 { Space } from '@dxos/client/echo';\nimport { Context } from '@dxos/context';\nimport { 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 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\n ctx.onDispose(() => subscription.unsubscribe());\n\n // TODO(burdon): DSL for query (replace props).\n const query = space.db.query({ '@type': trigger.subscription.type, ...trigger.subscription.props });\n const unsubscribe = query.subscribe(({ objects }) => {\n subscription.update(objects);\n });\n\n // TODO(burdon): Option to trigger on first subscription.\n // TODO(burdon): After restart not triggered.\n\n ctx.onDispose(() => unsubscribe());\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": ["express", "join", "getPortPromise", "Trigger", "log", "DEFAULT_PORT", "DevServer", "constructor", "_client", "_options", "_functionHandlers", "port", "_port", "endpoint", "undefined", "functions", "Object", "keys", "initialize", "name", "_", "entries", "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", "_registrationId", "stop", "trigger", "Trigger", "close", "unregister", "wake", "wait", "DeferredTask", "Context", "createSubscription", "invariant", "log", "ComplexMap", "TriggerManager", "constructor", "_client", "_triggers", "_invokeOptions", "_mounts", "name", "spaceKey", "toHex", "start", "spaces", "subscribe", "space", "waitUntilReady", "trigger", "mount", "stop", "keys", "unmount", "ctx", "key", "function", "exists", "get", "set", "disposed", "objectIds", "Set", "task", "invokeFunction", "objects", "Array", "from", "count", "subscription", "added", "updated", "object", "add", "id", "size", "schedule", "onDispose", "unsubscribe", "query", "db", "type", "props", "update", "delete", "dispose", "options", "functionName", "data", "endpoint", "runtime", "url", "res", "fetch", "method", "body", "JSON", "stringify", "headers", "result", "json", "err", "error", "message"]
7
7
  }
@@ -1 +1 @@
1
- {"inputs":{"packages/core/functions/src/function.ts":{"bytes":1782,"imports":[],"format":"esm"},"packages/core/functions/src/runtime/dev-server.ts":{"bytes":14331,"imports":[{"path":"express","kind":"import-statement","external":true},{"path":"@dxos/node-std/path","kind":"import-statement","external":true},{"path":"portfinder","kind":"import-statement","external":true},{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"<runtime>","kind":"import-statement","external":true}],"format":"esm"},"packages/core/functions/src/runtime/trigger-manager.ts":{"bytes":16478,"imports":[{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/context","kind":"import-statement","external":true},{"path":"@dxos/echo-schema","kind":"import-statement","external":true},{"path":"@dxos/invariant","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true}],"format":"esm"},"packages/core/functions/src/runtime/index.ts":{"bytes":584,"imports":[{"path":"packages/core/functions/src/runtime/dev-server.ts","kind":"import-statement","original":"./dev-server"},{"path":"packages/core/functions/src/runtime/trigger-manager.ts","kind":"import-statement","original":"./trigger-manager"}],"format":"esm"},"packages/core/functions/src/index.ts":{"bytes":550,"imports":[{"path":"packages/core/functions/src/function.ts","kind":"import-statement","original":"./function"},{"path":"packages/core/functions/src/runtime/index.ts","kind":"import-statement","original":"./runtime"}],"format":"esm"}},"outputs":{"packages/core/functions/dist/lib/browser/index.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":14657},"packages/core/functions/dist/lib/browser/index.mjs":{"imports":[{"path":"express","kind":"import-statement","external":true},{"path":"@dxos/node-std/path","kind":"import-statement","external":true},{"path":"portfinder","kind":"import-statement","external":true},{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/context","kind":"import-statement","external":true},{"path":"@dxos/echo-schema","kind":"import-statement","external":true},{"path":"@dxos/invariant","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true}],"exports":["DevServer","TriggerManager"],"entryPoint":"packages/core/functions/src/index.ts","inputs":{"packages/core/functions/src/index.ts":{"bytesInOutput":0},"packages/core/functions/src/runtime/dev-server.ts":{"bytesInOutput":3304},"packages/core/functions/src/runtime/index.ts":{"bytesInOutput":0},"packages/core/functions/src/runtime/trigger-manager.ts":{"bytesInOutput":4320}},"bytes":8216}}}
1
+ {"inputs":{"packages/core/functions/src/function.ts":{"bytes":1782,"imports":[],"format":"esm"},"packages/core/functions/src/runtime/dev-server.ts":{"bytes":14331,"imports":[{"path":"express","kind":"import-statement","external":true},{"path":"@dxos/node-std/path","kind":"import-statement","external":true},{"path":"portfinder","kind":"import-statement","external":true},{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"<runtime>","kind":"import-statement","external":true}],"format":"esm"},"packages/core/functions/src/runtime/trigger-manager.ts":{"bytes":16297,"imports":[{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/context","kind":"import-statement","external":true},{"path":"@dxos/echo-schema","kind":"import-statement","external":true},{"path":"@dxos/invariant","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true}],"format":"esm"},"packages/core/functions/src/runtime/index.ts":{"bytes":584,"imports":[{"path":"packages/core/functions/src/runtime/dev-server.ts","kind":"import-statement","original":"./dev-server"},{"path":"packages/core/functions/src/runtime/trigger-manager.ts","kind":"import-statement","original":"./trigger-manager"}],"format":"esm"},"packages/core/functions/src/index.ts":{"bytes":550,"imports":[{"path":"packages/core/functions/src/function.ts","kind":"import-statement","original":"./function"},{"path":"packages/core/functions/src/runtime/index.ts","kind":"import-statement","original":"./runtime"}],"format":"esm"}},"outputs":{"packages/core/functions/dist/lib/browser/index.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":14507},"packages/core/functions/dist/lib/browser/index.mjs":{"imports":[{"path":"express","kind":"import-statement","external":true},{"path":"@dxos/node-std/path","kind":"import-statement","external":true},{"path":"portfinder","kind":"import-statement","external":true},{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/context","kind":"import-statement","external":true},{"path":"@dxos/echo-schema","kind":"import-statement","external":true},{"path":"@dxos/invariant","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true}],"exports":["DevServer","TriggerManager"],"entryPoint":"packages/core/functions/src/index.ts","inputs":{"packages/core/functions/src/index.ts":{"bytesInOutput":0},"packages/core/functions/src/runtime/dev-server.ts":{"bytesInOutput":3304},"packages/core/functions/src/runtime/index.ts":{"bytesInOutput":0},"packages/core/functions/src/runtime/trigger-manager.ts":{"bytesInOutput":4211}},"bytes":8107}}}
@@ -166,7 +166,6 @@ var TriggerManager = class {
166
166
  this._triggers = _triggers;
167
167
  this._invokeOptions = _invokeOptions;
168
168
  this._mounts = new import_util.ComplexMap(({ name, spaceKey }) => `${spaceKey.toHex()}:${name}`);
169
- this._queries = /* @__PURE__ */ new Set();
170
169
  }
171
170
  async start() {
172
171
  this._client.spaces.subscribe(async (spaces) => {
@@ -199,7 +198,7 @@ var TriggerManager = class {
199
198
  trigger
200
199
  }, {
201
200
  F: __dxlog_file2,
202
- L: 60,
201
+ L: 58,
203
202
  S: this,
204
203
  C: (f, a) => f(...a)
205
204
  });
@@ -228,23 +227,22 @@ var TriggerManager = class {
228
227
  count
229
228
  }, {
230
229
  F: __dxlog_file2,
231
- L: 84,
230
+ L: 82,
232
231
  S: this,
233
232
  C: (f, a) => f(...a)
234
233
  });
235
234
  task.schedule();
236
235
  count++;
237
236
  });
238
- const query = space.db.query(import_echo_schema.Filter.typename(trigger.subscription.type, trigger.subscription.props));
239
- this._queries.add(query);
237
+ ctx.onDispose(() => subscription.unsubscribe());
238
+ const query = space.db.query({
239
+ "@type": trigger.subscription.type,
240
+ ...trigger.subscription.props
241
+ });
240
242
  const unsubscribe = query.subscribe(({ objects }) => {
241
243
  subscription.update(objects);
242
- }, true);
243
- ctx.onDispose(() => {
244
- subscription.unsubscribe();
245
- unsubscribe();
246
- this._queries.delete(query);
247
244
  });
245
+ ctx.onDispose(() => unsubscribe());
248
246
  }
249
247
  }
250
248
  async unmount(name, spaceKey) {
@@ -262,7 +260,7 @@ var TriggerManager = class {
262
260
  const { endpoint, runtime } = options;
263
261
  (0, import_invariant.invariant)(endpoint, "Missing endpoint", {
264
262
  F: __dxlog_file2,
265
- L: 120,
263
+ L: 119,
266
264
  S: this,
267
265
  A: [
268
266
  "endpoint",
@@ -271,7 +269,7 @@ var TriggerManager = class {
271
269
  });
272
270
  (0, import_invariant.invariant)(runtime, "Missing runtime", {
273
271
  F: __dxlog_file2,
274
- L: 121,
272
+ L: 120,
275
273
  S: this,
276
274
  A: [
277
275
  "runtime",
@@ -283,7 +281,7 @@ var TriggerManager = class {
283
281
  function: functionName
284
282
  }, {
285
283
  F: __dxlog_file2,
286
- L: 124,
284
+ L: 123,
287
285
  S: this,
288
286
  C: (f, a) => f(...a)
289
287
  });
@@ -300,7 +298,7 @@ var TriggerManager = class {
300
298
  result: await res.json()
301
299
  }, {
302
300
  F: __dxlog_file2,
303
- L: 134,
301
+ L: 133,
304
302
  S: this,
305
303
  C: (f, a) => f(...a)
306
304
  });
@@ -310,7 +308,7 @@ var TriggerManager = class {
310
308
  error: err.message
311
309
  }, {
312
310
  F: __dxlog_file2,
313
- L: 136,
311
+ L: 135,
314
312
  S: this,
315
313
  C: (f, a) => f(...a)
316
314
  });
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
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 */\n// TODO(burdon): Not secure.\nexport class DevServer {\n private readonly _functionHandlers: 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._functionHandlers);\n }\n\n async initialize() {\n for (const [name, _] of Object.entries(this._options.manifest.functions)) {\n try {\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const module = require(join(this._options.directory, name));\n const handler = module.default;\n if (typeof handler !== 'function') {\n throw new Error(`Handler must export default function: ${name}`);\n }\n\n this._functionHandlers[name] = 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._functionHandlers[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", "_functionHandlers", "port", "_port", "endpoint", "undefined", "functions", "Object", "keys", "initialize", "name", "_", "entries", "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", "_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"]
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 */\n// TODO(burdon): Not secure.\nexport class DevServer {\n private readonly _functionHandlers: 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._functionHandlers);\n }\n\n async initialize() {\n for (const [name, _] of Object.entries(this._options.manifest.functions)) {\n try {\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const module = require(join(this._options.directory, name));\n const handler = module.default;\n if (typeof handler !== 'function') {\n throw new Error(`Handler must export default function: ${name}`);\n }\n\n this._functionHandlers[name] = 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._functionHandlers[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 { Space } from '@dxos/client/echo';\nimport { Context } from '@dxos/context';\nimport { 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 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\n ctx.onDispose(() => subscription.unsubscribe());\n\n // TODO(burdon): DSL for query (replace props).\n const query = space.db.query({ '@type': trigger.subscription.type, ...trigger.subscription.props });\n const unsubscribe = query.subscribe(({ objects }) => {\n subscription.update(objects);\n });\n\n // TODO(burdon): Option to trigger on first subscription.\n // TODO(burdon): After restart not triggered.\n\n ctx.onDispose(() => unsubscribe());\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", "_functionHandlers", "port", "_port", "endpoint", "undefined", "functions", "Object", "keys", "initialize", "name", "_", "entries", "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", "_registrationId", "stop", "trigger", "Trigger", "close", "unregister", "wake", "wait", "import_async", "import_log", "TriggerManager", "constructor", "_client", "_triggers", "_invokeOptions", "_mounts", "ComplexMap", "name", "spaceKey", "toHex", "start", "spaces", "subscribe", "space", "waitUntilReady", "trigger", "mount", "Context", "stop", "keys", "unmount", "ctx", "key", "function", "exists", "get", "set", "log", "disposed", "objectIds", "Set", "task", "DeferredTask", "invokeFunction", "objects", "Array", "from", "count", "subscription", "createSubscription", "added", "updated", "object", "add", "id", "size", "schedule", "onDispose", "unsubscribe", "query", "db", "type", "props", "update", "delete", "dispose", "options", "functionName", "data", "endpoint", "runtime", "invariant", "url", "res", "fetch", "method", "body", "JSON", "stringify", "headers", "result", "json", "err", "error", "message"]
7
7
  }
@@ -1 +1 @@
1
- {"inputs":{"packages/core/functions/src/function.ts":{"bytes":1782,"imports":[],"format":"esm"},"packages/core/functions/src/runtime/dev-server.ts":{"bytes":14331,"imports":[{"path":"express","kind":"import-statement","external":true},{"path":"node:path","kind":"import-statement","external":true},{"path":"portfinder","kind":"import-statement","external":true},{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true}],"format":"esm"},"packages/core/functions/src/runtime/trigger-manager.ts":{"bytes":16478,"imports":[{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/context","kind":"import-statement","external":true},{"path":"@dxos/echo-schema","kind":"import-statement","external":true},{"path":"@dxos/invariant","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true}],"format":"esm"},"packages/core/functions/src/runtime/index.ts":{"bytes":584,"imports":[{"path":"packages/core/functions/src/runtime/dev-server.ts","kind":"import-statement","original":"./dev-server"},{"path":"packages/core/functions/src/runtime/trigger-manager.ts","kind":"import-statement","original":"./trigger-manager"}],"format":"esm"},"packages/core/functions/src/index.ts":{"bytes":550,"imports":[{"path":"packages/core/functions/src/function.ts","kind":"import-statement","original":"./function"},{"path":"packages/core/functions/src/runtime/index.ts","kind":"import-statement","original":"./runtime"}],"format":"esm"}},"outputs":{"packages/core/functions/dist/lib/node/index.cjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":14720},"packages/core/functions/dist/lib/node/index.cjs":{"imports":[{"path":"express","kind":"require-call","external":true},{"path":"node:path","kind":"require-call","external":true},{"path":"portfinder","kind":"require-call","external":true},{"path":"@dxos/async","kind":"require-call","external":true},{"path":"@dxos/log","kind":"require-call","external":true},{"path":"@dxos/async","kind":"require-call","external":true},{"path":"@dxos/context","kind":"require-call","external":true},{"path":"@dxos/echo-schema","kind":"require-call","external":true},{"path":"@dxos/invariant","kind":"require-call","external":true},{"path":"@dxos/log","kind":"require-call","external":true},{"path":"@dxos/util","kind":"require-call","external":true}],"exports":[],"entryPoint":"packages/core/functions/src/index.ts","inputs":{"packages/core/functions/src/index.ts":{"bytesInOutput":163},"packages/core/functions/src/runtime/dev-server.ts":{"bytesInOutput":3456},"packages/core/functions/src/runtime/index.ts":{"bytesInOutput":0},"packages/core/functions/src/runtime/trigger-manager.ts":{"bytesInOutput":4525}},"bytes":9850}}}
1
+ {"inputs":{"packages/core/functions/src/function.ts":{"bytes":1782,"imports":[],"format":"esm"},"packages/core/functions/src/runtime/dev-server.ts":{"bytes":14331,"imports":[{"path":"express","kind":"import-statement","external":true},{"path":"node:path","kind":"import-statement","external":true},{"path":"portfinder","kind":"import-statement","external":true},{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true}],"format":"esm"},"packages/core/functions/src/runtime/trigger-manager.ts":{"bytes":16297,"imports":[{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/context","kind":"import-statement","external":true},{"path":"@dxos/echo-schema","kind":"import-statement","external":true},{"path":"@dxos/invariant","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true}],"format":"esm"},"packages/core/functions/src/runtime/index.ts":{"bytes":584,"imports":[{"path":"packages/core/functions/src/runtime/dev-server.ts","kind":"import-statement","original":"./dev-server"},{"path":"packages/core/functions/src/runtime/trigger-manager.ts","kind":"import-statement","original":"./trigger-manager"}],"format":"esm"},"packages/core/functions/src/index.ts":{"bytes":550,"imports":[{"path":"packages/core/functions/src/function.ts","kind":"import-statement","original":"./function"},{"path":"packages/core/functions/src/runtime/index.ts","kind":"import-statement","original":"./runtime"}],"format":"esm"}},"outputs":{"packages/core/functions/dist/lib/node/index.cjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":14578},"packages/core/functions/dist/lib/node/index.cjs":{"imports":[{"path":"express","kind":"require-call","external":true},{"path":"node:path","kind":"require-call","external":true},{"path":"portfinder","kind":"require-call","external":true},{"path":"@dxos/async","kind":"require-call","external":true},{"path":"@dxos/log","kind":"require-call","external":true},{"path":"@dxos/async","kind":"require-call","external":true},{"path":"@dxos/context","kind":"require-call","external":true},{"path":"@dxos/echo-schema","kind":"require-call","external":true},{"path":"@dxos/invariant","kind":"require-call","external":true},{"path":"@dxos/log","kind":"require-call","external":true},{"path":"@dxos/util","kind":"require-call","external":true}],"exports":[],"entryPoint":"packages/core/functions/src/index.ts","inputs":{"packages/core/functions/src/index.ts":{"bytesInOutput":163},"packages/core/functions/src/runtime/dev-server.ts":{"bytesInOutput":3456},"packages/core/functions/src/runtime/index.ts":{"bytesInOutput":0},"packages/core/functions/src/runtime/trigger-manager.ts":{"bytesInOutput":4405}},"bytes":9730}}}
@@ -9,7 +9,6 @@ export declare class TriggerManager {
9
9
  private readonly _triggers;
10
10
  private readonly _invokeOptions;
11
11
  private readonly _mounts;
12
- private readonly _queries;
13
12
  constructor(_client: Client, _triggers: FunctionTrigger[], _invokeOptions: InvokeOptions);
14
13
  start(): Promise<void>;
15
14
  stop(): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"trigger-manager.d.ts","sourceRoot":"","sources":["../../../../src/runtime/trigger-manager.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,KAAK,MAAM,EAAkB,MAAM,cAAc,CAAC;AAQ3D,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,aAAa,CAAC;AAGnD,MAAM,MAAM,aAAa,GAAG;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,qBAAa,cAAc;IASvB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,cAAc;IAVjC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAGiC;IAEzD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAoB;gBAG1B,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,eAAe,EAAE,EAC5B,cAAc,EAAE,aAAa;IAG1C,KAAK;IAaL,IAAI;YAMI,KAAK;YAsDL,OAAO;YASP,cAAc;CAqB7B"}
1
+ {"version":3,"file":"trigger-manager.d.ts","sourceRoot":"","sources":["../../../../src/runtime/trigger-manager.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,KAAK,MAAM,EAAkB,MAAM,cAAc,CAAC;AAQ3D,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,aAAa,CAAC;AAGnD,MAAM,MAAM,aAAa,GAAG;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,qBAAa,cAAc;IAOvB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,cAAc;IARjC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAGiC;gBAGtC,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,eAAe,EAAE,EAC5B,cAAc,EAAE,aAAa;IAG1C,KAAK;IAaL,IAAI;YAMI,KAAK;YAuDL,OAAO;YASP,cAAc;CAqB7B"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dxos/functions",
3
- "version": "0.3.5-main.fa2fc5b",
3
+ "version": "0.3.5-next.5910692",
4
4
  "description": "Functions SDK and runtime.",
5
5
  "homepage": "https://dxos.org",
6
6
  "bugs": "https://github.com/dxos/dxos/issues",
@@ -21,14 +21,14 @@
21
21
  "dependencies": {
22
22
  "express": "^4.17.1",
23
23
  "portfinder": "^1.0.32",
24
- "@dxos/async": "0.3.5-main.fa2fc5b",
25
- "@dxos/client": "0.3.5-main.fa2fc5b",
26
- "@dxos/context": "0.3.5-main.fa2fc5b",
27
- "@dxos/echo-schema": "0.3.5-main.fa2fc5b",
28
- "@dxos/invariant": "0.3.5-main.fa2fc5b",
29
- "@dxos/log": "0.3.5-main.fa2fc5b",
30
- "@dxos/node-std": "0.3.5-main.fa2fc5b",
31
- "@dxos/util": "0.3.5-main.fa2fc5b"
24
+ "@dxos/async": "0.3.5-next.5910692",
25
+ "@dxos/context": "0.3.5-next.5910692",
26
+ "@dxos/client": "0.3.5-next.5910692",
27
+ "@dxos/invariant": "0.3.5-next.5910692",
28
+ "@dxos/node-std": "0.3.5-next.5910692",
29
+ "@dxos/util": "0.3.5-next.5910692",
30
+ "@dxos/log": "0.3.5-next.5910692",
31
+ "@dxos/echo-schema": "0.3.5-next.5910692"
32
32
  },
33
33
  "devDependencies": {
34
34
  "@types/express": "^4.17.17"
@@ -4,9 +4,9 @@
4
4
 
5
5
  import { DeferredTask } from '@dxos/async';
6
6
  import { type Client, type PublicKey } from '@dxos/client';
7
- import type { Query, Space } from '@dxos/client/echo';
7
+ import type { Space } from '@dxos/client/echo';
8
8
  import { Context } from '@dxos/context';
9
- import { Filter, createSubscription } from '@dxos/echo-schema';
9
+ import { createSubscription } from '@dxos/echo-schema';
10
10
  import { invariant } from '@dxos/invariant';
11
11
  import { log } from '@dxos/log';
12
12
  import { ComplexMap } from '@dxos/util';
@@ -25,8 +25,6 @@ export class TriggerManager {
25
25
  { ctx: Context; trigger: FunctionTrigger }
26
26
  >(({ name, spaceKey }) => `${spaceKey.toHex()}:${name}`);
27
27
 
28
- private readonly _queries = new Set<Query>();
29
-
30
28
  constructor(
31
29
  private readonly _client: Client,
32
30
  private readonly _triggers: FunctionTrigger[],
@@ -91,18 +89,19 @@ export class TriggerManager {
91
89
  task.schedule();
92
90
  count++;
93
91
  });
92
+
93
+ ctx.onDispose(() => subscription.unsubscribe());
94
+
94
95
  // TODO(burdon): DSL for query (replace props).
95
- const query = space.db.query(Filter.typename(trigger.subscription.type, trigger.subscription.props));
96
- this._queries.add(query);
96
+ const query = space.db.query({ '@type': trigger.subscription.type, ...trigger.subscription.props });
97
97
  const unsubscribe = query.subscribe(({ objects }) => {
98
98
  subscription.update(objects);
99
- }, true);
100
-
101
- ctx.onDispose(() => {
102
- subscription.unsubscribe();
103
- unsubscribe();
104
- this._queries.delete(query);
105
99
  });
100
+
101
+ // TODO(burdon): Option to trigger on first subscription.
102
+ // TODO(burdon): After restart not triggered.
103
+
104
+ ctx.onDispose(() => unsubscribe());
106
105
  }
107
106
  }
108
107