@dxos/functions 0.1.58-next.ffb4cc4 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/browser/index.mjs +5 -4
- package/dist/lib/browser/index.mjs.map +2 -2
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node/index.cjs +5 -4
- package/dist/lib/node/index.cjs.map +2 -2
- package/dist/lib/node/meta.json +1 -1
- package/dist/types/src/runtime/dev-server.d.ts.map +1 -1
- package/package.json +9 -9
- package/src/runtime/dev-server.ts +1 -0
|
@@ -13,9 +13,10 @@ import { join } from "@dxos/node-std/path";
|
|
|
13
13
|
import { getPortPromise } from "portfinder";
|
|
14
14
|
import { Trigger } from "@dxos/async";
|
|
15
15
|
import { log } from "@dxos/log";
|
|
16
|
-
var __dxlog_file = "/
|
|
16
|
+
var __dxlog_file = "/mnt/ramdisk/work/packages/core/functions/src/runtime/dev-server.ts";
|
|
17
17
|
var DEFAULT_PORT = 7e3;
|
|
18
18
|
var DevServer = class {
|
|
19
|
+
// prettier-ignore
|
|
19
20
|
constructor(_client, _options) {
|
|
20
21
|
this._client = _client;
|
|
21
22
|
this._options = _options;
|
|
@@ -42,7 +43,7 @@ var DevServer = class {
|
|
|
42
43
|
} catch (err) {
|
|
43
44
|
log.error("parsing function (check functions.yml manifest)", err, {
|
|
44
45
|
F: __dxlog_file,
|
|
45
|
-
L:
|
|
46
|
+
L: 63,
|
|
46
47
|
S: this,
|
|
47
48
|
C: (f, a) => f(...a)
|
|
48
49
|
});
|
|
@@ -59,7 +60,7 @@ var DevServer = class {
|
|
|
59
60
|
data: req.body
|
|
60
61
|
}, {
|
|
61
62
|
F: __dxlog_file,
|
|
62
|
-
L:
|
|
63
|
+
L: 74,
|
|
63
64
|
S: this,
|
|
64
65
|
C: (f, a) => f(...a)
|
|
65
66
|
});
|
|
@@ -127,7 +128,7 @@ import { createSubscription } from "@dxos/echo-schema";
|
|
|
127
128
|
import { invariant } from "@dxos/invariant";
|
|
128
129
|
import { log as log2 } from "@dxos/log";
|
|
129
130
|
import { ComplexMap } from "@dxos/util";
|
|
130
|
-
var __dxlog_file2 = "/
|
|
131
|
+
var __dxlog_file2 = "/mnt/ramdisk/work/packages/core/functions/src/runtime/trigger-manager.ts";
|
|
131
132
|
var TriggerManager = class {
|
|
132
133
|
constructor(_client, _triggers, _invokeOptions) {
|
|
133
134
|
this._client = _client;
|
|
@@ -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 http from 'http';\nimport { join } from 'node:path';\nimport { getPortPromise } from 'portfinder';\n\nimport { Trigger } from '@dxos/async';\nimport { Client } from '@dxos/client';\nimport { log } from '@dxos/log';\n\nimport { FunctionContext, FunctionHandler, FunctionsManifest, 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 _functionHandlers: Record<string, FunctionHandler> = {};\n\n private _server?: http.Server;\n private _port?: number;\n private _registrationId?: string;\n\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 await this._functionHandlers[functionName](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 { Client, 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 { 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): 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": ";;;;;;;;;;AAIA,OAAOA,aAAa;AAEpB,SAASC,YAAY;AACrB,SAASC,sBAAsB;AAE/B,SAASC,eAAe;AAExB,SAASC,WAAW;;AAIpB,IAAMC,eAAe;AAUd,IAAMC,YAAN,MAAMA
|
|
4
|
+
"sourcesContent": ["//\n// Copyright 2023 DXOS.org\n//\n\nimport express from 'express';\nimport http from 'http';\nimport { join } from 'node:path';\nimport { getPortPromise } from 'portfinder';\n\nimport { Trigger } from '@dxos/async';\nimport { Client } from '@dxos/client';\nimport { log } from '@dxos/log';\n\nimport { FunctionContext, FunctionHandler, FunctionsManifest, 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 _functionHandlers: Record<string, FunctionHandler> = {};\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 await this._functionHandlers[functionName](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 { Client, 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 { 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): 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
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", "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":
|
|
1
|
+
{"inputs":{"packages/core/functions/src/function.ts":{"bytes":1412,"imports":[],"format":"esm"},"packages/core/functions/src/runtime/dev-server.ts":{"bytes":13911,"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":16149,"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":574,"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":540,"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":14300},"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":3249},"packages/core/functions/src/runtime/index.ts":{"bytesInOutput":0},"packages/core/functions/src/runtime/trigger-manager.ts":{"bytesInOutput":4201}},"bytes":8042}}}
|
package/dist/lib/node/index.cjs
CHANGED
|
@@ -41,9 +41,10 @@ var import_node_path = require("node:path");
|
|
|
41
41
|
var import_portfinder = require("portfinder");
|
|
42
42
|
var import_async = require("@dxos/async");
|
|
43
43
|
var import_log = require("@dxos/log");
|
|
44
|
-
var __dxlog_file = "/
|
|
44
|
+
var __dxlog_file = "/mnt/ramdisk/work/packages/core/functions/src/runtime/dev-server.ts";
|
|
45
45
|
var DEFAULT_PORT = 7e3;
|
|
46
46
|
var DevServer = class {
|
|
47
|
+
// prettier-ignore
|
|
47
48
|
constructor(_client, _options) {
|
|
48
49
|
this._client = _client;
|
|
49
50
|
this._options = _options;
|
|
@@ -70,7 +71,7 @@ var DevServer = class {
|
|
|
70
71
|
} catch (err) {
|
|
71
72
|
import_log.log.error("parsing function (check functions.yml manifest)", err, {
|
|
72
73
|
F: __dxlog_file,
|
|
73
|
-
L:
|
|
74
|
+
L: 63,
|
|
74
75
|
S: this,
|
|
75
76
|
C: (f, a) => f(...a)
|
|
76
77
|
});
|
|
@@ -87,7 +88,7 @@ var DevServer = class {
|
|
|
87
88
|
data: req.body
|
|
88
89
|
}, {
|
|
89
90
|
F: __dxlog_file,
|
|
90
|
-
L:
|
|
91
|
+
L: 74,
|
|
91
92
|
S: this,
|
|
92
93
|
C: (f, a) => f(...a)
|
|
93
94
|
});
|
|
@@ -155,7 +156,7 @@ var import_echo_schema = require("@dxos/echo-schema");
|
|
|
155
156
|
var import_invariant = require("@dxos/invariant");
|
|
156
157
|
var import_log2 = require("@dxos/log");
|
|
157
158
|
var import_util = require("@dxos/util");
|
|
158
|
-
var __dxlog_file2 = "/
|
|
159
|
+
var __dxlog_file2 = "/mnt/ramdisk/work/packages/core/functions/src/runtime/trigger-manager.ts";
|
|
159
160
|
var TriggerManager = class {
|
|
160
161
|
constructor(_client, _triggers, _invokeOptions) {
|
|
161
162
|
this._client = _client;
|
|
@@ -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 http from 'http';\nimport { join } from 'node:path';\nimport { getPortPromise } from 'portfinder';\n\nimport { Trigger } from '@dxos/async';\nimport { Client } from '@dxos/client';\nimport { log } from '@dxos/log';\n\nimport { FunctionContext, FunctionHandler, FunctionsManifest, 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 _functionHandlers: Record<string, FunctionHandler> = {};\n\n private _server?: http.Server;\n private _port?: number;\n private _registrationId?: string;\n\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 await this._functionHandlers[functionName](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 { Client, 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 { 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): 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": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;;;;;;;;ACIA,qBAAoB;AAEpB,uBAAqB;AACrB,wBAA+B;AAE/B,mBAAwB;AAExB,iBAAoB;;AAIpB,IAAMA,eAAe;AAUd,IAAMC,YAAN,MAAMA
|
|
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 http from 'http';\nimport { join } from 'node:path';\nimport { getPortPromise } from 'portfinder';\n\nimport { Trigger } from '@dxos/async';\nimport { Client } from '@dxos/client';\nimport { log } from '@dxos/log';\n\nimport { FunctionContext, FunctionHandler, FunctionsManifest, 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 _functionHandlers: Record<string, FunctionHandler> = {};\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 await this._functionHandlers[functionName](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 { Client, 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 { 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): 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
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", "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
|
}
|
package/dist/lib/node/meta.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"inputs":{"packages/core/functions/src/function.ts":{"bytes":
|
|
1
|
+
{"inputs":{"packages/core/functions/src/function.ts":{"bytes":1412,"imports":[],"format":"esm"},"packages/core/functions/src/runtime/dev-server.ts":{"bytes":13911,"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":16149,"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":574,"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":540,"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":14371},"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":3401},"packages/core/functions/src/runtime/index.ts":{"bytesInOutput":0},"packages/core/functions/src/runtime/trigger-manager.ts":{"bytesInOutput":4395}},"bytes":9665}}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dev-server.d.ts","sourceRoot":"","sources":["../../../../src/runtime/dev-server.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAGtC,OAAO,EAAoC,iBAAiB,EAAY,MAAM,aAAa,CAAC;AAI5F,MAAM,MAAM,gBAAgB,GAAG;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,iBAAiB,CAAC;CAC7B,CAAC;AAEF;;GAEG;AACH,qBAAa,SAAS;
|
|
1
|
+
{"version":3,"file":"dev-server.d.ts","sourceRoot":"","sources":["../../../../src/runtime/dev-server.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAGtC,OAAO,EAAoC,iBAAiB,EAAY,MAAM,aAAa,CAAC;AAI5F,MAAM,MAAM,gBAAgB,GAAG;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,iBAAiB,CAAC;CAC7B,CAAC;AAEF;;GAEG;AACH,qBAAa,SAAS;IASlB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAT3B,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAuC;IAEzE,OAAO,CAAC,OAAO,CAAC,CAAc;IAC9B,OAAO,CAAC,KAAK,CAAC,CAAS;IACvB,OAAO,CAAC,eAAe,CAAC,CAAS;gBAId,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,gBAAgB;IAG7C,IAAI,IAAI,uBAEP;IAED,IAAI,QAAQ,uBAEX;IAED,IAAI,SAAS,aAEZ;IAEK,UAAU;IAiBV,KAAK;IAmDL,IAAI;CAiBX"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dxos/functions",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
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.
|
|
25
|
-
"@dxos/client": "0.
|
|
26
|
-
"@dxos/context": "0.
|
|
27
|
-
"@dxos/echo-schema": "0.
|
|
28
|
-
"@dxos/invariant": "0.
|
|
29
|
-
"@dxos/log": "0.
|
|
30
|
-
"@dxos/node-std": "0.
|
|
31
|
-
"@dxos/util": "0.
|
|
24
|
+
"@dxos/async": "0.2.0",
|
|
25
|
+
"@dxos/client": "0.2.0",
|
|
26
|
+
"@dxos/context": "0.2.0",
|
|
27
|
+
"@dxos/echo-schema": "0.2.0",
|
|
28
|
+
"@dxos/invariant": "0.2.0",
|
|
29
|
+
"@dxos/log": "0.2.0",
|
|
30
|
+
"@dxos/node-std": "0.2.0",
|
|
31
|
+
"@dxos/util": "0.2.0"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
34
|
"@types/express": "^4.17.17"
|