@dxos/functions 0.3.7 → 0.3.8-main.598e316
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 +71 -41
- package/dist/lib/browser/index.mjs.map +3 -3
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node/index.cjs +71 -41
- package/dist/lib/node/index.cjs.map +3 -3
- package/dist/lib/node/meta.json +1 -1
- package/dist/types/src/{function.d.ts → handler.d.ts} +8 -23
- package/dist/types/src/handler.d.ts.map +1 -0
- package/dist/types/src/index.d.ts +2 -1
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/manifest.d.ts +24 -0
- package/dist/types/src/manifest.d.ts.map +1 -0
- package/dist/types/src/runtime/dev-server.d.ts +7 -3
- package/dist/types/src/runtime/dev-server.d.ts.map +1 -1
- package/dist/types/src/runtime/trigger-manager.d.ts +4 -4
- package/dist/types/src/runtime/trigger-manager.d.ts.map +1 -1
- package/package.json +9 -9
- package/src/handler.ts +29 -0
- package/src/index.ts +2 -1
- package/src/manifest.ts +36 -0
- package/src/runtime/dev-server.ts +28 -19
- package/src/runtime/trigger-manager.ts +7 -6
- package/dist/types/src/function.d.ts.map +0 -1
- package/src/function.ts +0 -51
|
@@ -13,8 +13,8 @@ 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 = "/home/
|
|
17
|
-
var DEFAULT_PORT =
|
|
16
|
+
var __dxlog_file = "/home/runner/work/dxos/dxos/packages/core/functions/src/runtime/dev-server.ts";
|
|
17
|
+
var DEFAULT_PORT = 7001;
|
|
18
18
|
var DevServer = class {
|
|
19
19
|
// prettier-ignore
|
|
20
20
|
constructor(_client, _options) {
|
|
@@ -29,21 +29,33 @@ var DevServer = class {
|
|
|
29
29
|
return this._port ? `http://localhost:${this._port}` : void 0;
|
|
30
30
|
}
|
|
31
31
|
get functions() {
|
|
32
|
-
return Object.
|
|
32
|
+
return Object.values(this._handlers);
|
|
33
33
|
}
|
|
34
34
|
async initialize() {
|
|
35
|
-
for (const
|
|
35
|
+
for (const def of this._options.manifest.functions) {
|
|
36
|
+
const { id, endpoint, handler: path } = def;
|
|
36
37
|
try {
|
|
37
|
-
const module = __require(join(this._options.directory,
|
|
38
|
+
const module = __require(join(this._options.directory, path));
|
|
38
39
|
const handler = module.default;
|
|
39
40
|
if (typeof handler !== "function") {
|
|
40
41
|
throw new Error(`Handler must export default function: ${id}`);
|
|
41
42
|
}
|
|
42
|
-
this._handlers[
|
|
43
|
+
if (this._handlers[endpoint]) {
|
|
44
|
+
log.warn(`Function already registered: ${id}`, void 0, {
|
|
45
|
+
F: __dxlog_file,
|
|
46
|
+
L: 64,
|
|
47
|
+
S: this,
|
|
48
|
+
C: (f, a) => f(...a)
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
this._handlers[endpoint] = {
|
|
52
|
+
def,
|
|
53
|
+
handler
|
|
54
|
+
};
|
|
43
55
|
} catch (err) {
|
|
44
|
-
log.error("parsing function (check
|
|
56
|
+
log.error("parsing function (check manifest)", err, {
|
|
45
57
|
F: __dxlog_file,
|
|
46
|
-
L:
|
|
58
|
+
L: 69,
|
|
47
59
|
S: this,
|
|
48
60
|
C: (f, a) => f(...a)
|
|
49
61
|
});
|
|
@@ -53,36 +65,44 @@ var DevServer = class {
|
|
|
53
65
|
async start() {
|
|
54
66
|
const app = express();
|
|
55
67
|
app.use(express.json());
|
|
56
|
-
app.post("/:
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
function: functionName,
|
|
60
|
-
data: req.body
|
|
61
|
-
}, {
|
|
62
|
-
F: __dxlog_file,
|
|
63
|
-
L: 74,
|
|
64
|
-
S: this,
|
|
65
|
-
C: (f, a) => f(...a)
|
|
66
|
-
});
|
|
67
|
-
const builder = {
|
|
68
|
+
app.post("/:endpoint", async (req, res) => {
|
|
69
|
+
const { endpoint } = req.params;
|
|
70
|
+
const response = {
|
|
68
71
|
status: (code) => {
|
|
69
72
|
res.statusCode = code;
|
|
70
|
-
return
|
|
73
|
+
return response;
|
|
71
74
|
},
|
|
72
75
|
succeed: (result = {}) => {
|
|
73
76
|
res.end(JSON.stringify(result));
|
|
74
|
-
return
|
|
77
|
+
return response;
|
|
75
78
|
}
|
|
76
79
|
};
|
|
77
80
|
const context = {
|
|
78
81
|
client: this._client,
|
|
79
|
-
status:
|
|
82
|
+
status: response.status.bind(response)
|
|
80
83
|
};
|
|
81
84
|
void (async () => {
|
|
82
85
|
try {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
+
log("invoking", {
|
|
87
|
+
endpoint
|
|
88
|
+
}, {
|
|
89
|
+
F: __dxlog_file,
|
|
90
|
+
L: 100,
|
|
91
|
+
S: this,
|
|
92
|
+
C: (f, a) => f(...a)
|
|
93
|
+
});
|
|
94
|
+
const { handler } = this._handlers[endpoint];
|
|
95
|
+
const response2 = await handler({
|
|
96
|
+
context,
|
|
97
|
+
event: req.body
|
|
98
|
+
});
|
|
99
|
+
log("done", {
|
|
100
|
+
response: response2
|
|
101
|
+
}, {
|
|
102
|
+
F: __dxlog_file,
|
|
103
|
+
L: 103,
|
|
104
|
+
S: this,
|
|
105
|
+
C: (f, a) => f(...a)
|
|
86
106
|
});
|
|
87
107
|
} catch (err) {
|
|
88
108
|
res.statusCode = 500;
|
|
@@ -97,8 +117,8 @@ var DevServer = class {
|
|
|
97
117
|
try {
|
|
98
118
|
const { registrationId } = await this._client.services.services.FunctionRegistryService.register({
|
|
99
119
|
endpoint: this.endpoint,
|
|
100
|
-
functions: this.functions.map((
|
|
101
|
-
name
|
|
120
|
+
functions: this.functions.map(({ def: { endpoint } }) => ({
|
|
121
|
+
name: endpoint
|
|
102
122
|
}))
|
|
103
123
|
});
|
|
104
124
|
this._registrationId = registrationId;
|
|
@@ -131,11 +151,11 @@ import { Filter, createSubscription } from "@dxos/echo-schema";
|
|
|
131
151
|
import { invariant } from "@dxos/invariant";
|
|
132
152
|
import { log as log2 } from "@dxos/log";
|
|
133
153
|
import { ComplexMap } from "@dxos/util";
|
|
134
|
-
var __dxlog_file2 = "/home/
|
|
154
|
+
var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/core/functions/src/runtime/trigger-manager.ts";
|
|
135
155
|
var TriggerManager = class {
|
|
136
|
-
constructor(_client,
|
|
156
|
+
constructor(_client, _manifest, _invokeOptions) {
|
|
137
157
|
this._client = _client;
|
|
138
|
-
this.
|
|
158
|
+
this._manifest = _manifest;
|
|
139
159
|
this._invokeOptions = _invokeOptions;
|
|
140
160
|
this._mounts = new ComplexMap(({ name, spaceKey }) => `${spaceKey.toHex()}:${name}`);
|
|
141
161
|
this._queries = /* @__PURE__ */ new Set();
|
|
@@ -144,7 +164,7 @@ var TriggerManager = class {
|
|
|
144
164
|
this._client.spaces.subscribe(async (spaces) => {
|
|
145
165
|
for (const space of spaces) {
|
|
146
166
|
await space.waitUntilReady();
|
|
147
|
-
for (const trigger of this.
|
|
167
|
+
for (const trigger of this._manifest.triggers ?? []) {
|
|
148
168
|
await this.mount(new Context(), space, trigger);
|
|
149
169
|
}
|
|
150
170
|
}
|
|
@@ -160,6 +180,16 @@ var TriggerManager = class {
|
|
|
160
180
|
name: trigger.function,
|
|
161
181
|
spaceKey: space.key
|
|
162
182
|
};
|
|
183
|
+
const config = this._manifest.functions.find((config2) => config2.id === trigger.function);
|
|
184
|
+
invariant(config, `Function not found: ${trigger.function}`, {
|
|
185
|
+
F: __dxlog_file2,
|
|
186
|
+
L: 58,
|
|
187
|
+
S: this,
|
|
188
|
+
A: [
|
|
189
|
+
"config",
|
|
190
|
+
"`Function not found: ${trigger.function}`"
|
|
191
|
+
]
|
|
192
|
+
});
|
|
163
193
|
const exists = this._mounts.get(key);
|
|
164
194
|
if (!exists) {
|
|
165
195
|
this._mounts.set(key, {
|
|
@@ -171,7 +201,7 @@ var TriggerManager = class {
|
|
|
171
201
|
trigger
|
|
172
202
|
}, {
|
|
173
203
|
F: __dxlog_file2,
|
|
174
|
-
L:
|
|
204
|
+
L: 62,
|
|
175
205
|
S: this,
|
|
176
206
|
C: (f, a) => f(...a)
|
|
177
207
|
});
|
|
@@ -180,7 +210,7 @@ var TriggerManager = class {
|
|
|
180
210
|
}
|
|
181
211
|
const objectIds = /* @__PURE__ */ new Set();
|
|
182
212
|
const task = new DeferredTask(ctx, async () => {
|
|
183
|
-
await this.
|
|
213
|
+
await this.execFunction(this._invokeOptions, config.endpoint, {
|
|
184
214
|
space: space.key,
|
|
185
215
|
objects: Array.from(objectIds)
|
|
186
216
|
});
|
|
@@ -200,7 +230,7 @@ var TriggerManager = class {
|
|
|
200
230
|
count
|
|
201
231
|
}, {
|
|
202
232
|
F: __dxlog_file2,
|
|
203
|
-
L:
|
|
233
|
+
L: 85,
|
|
204
234
|
S: this,
|
|
205
235
|
C: (f, a) => f(...a)
|
|
206
236
|
});
|
|
@@ -230,11 +260,11 @@ var TriggerManager = class {
|
|
|
230
260
|
await ctx.dispose();
|
|
231
261
|
}
|
|
232
262
|
}
|
|
233
|
-
async
|
|
263
|
+
async execFunction(options, functionName, data) {
|
|
234
264
|
const { endpoint, runtime } = options;
|
|
235
265
|
invariant(endpoint, "Missing endpoint", {
|
|
236
266
|
F: __dxlog_file2,
|
|
237
|
-
L:
|
|
267
|
+
L: 121,
|
|
238
268
|
S: this,
|
|
239
269
|
A: [
|
|
240
270
|
"endpoint",
|
|
@@ -243,7 +273,7 @@ var TriggerManager = class {
|
|
|
243
273
|
});
|
|
244
274
|
invariant(runtime, "Missing runtime", {
|
|
245
275
|
F: __dxlog_file2,
|
|
246
|
-
L:
|
|
276
|
+
L: 122,
|
|
247
277
|
S: this,
|
|
248
278
|
A: [
|
|
249
279
|
"runtime",
|
|
@@ -255,7 +285,7 @@ var TriggerManager = class {
|
|
|
255
285
|
function: functionName
|
|
256
286
|
}, {
|
|
257
287
|
F: __dxlog_file2,
|
|
258
|
-
L:
|
|
288
|
+
L: 125,
|
|
259
289
|
S: this,
|
|
260
290
|
C: (f, a) => f(...a)
|
|
261
291
|
});
|
|
@@ -272,7 +302,7 @@ var TriggerManager = class {
|
|
|
272
302
|
result: await res.json()
|
|
273
303
|
}, {
|
|
274
304
|
F: __dxlog_file2,
|
|
275
|
-
L:
|
|
305
|
+
L: 135,
|
|
276
306
|
S: this,
|
|
277
307
|
C: (f, a) => f(...a)
|
|
278
308
|
});
|
|
@@ -282,7 +312,7 @@ var TriggerManager = class {
|
|
|
282
312
|
error: err.message
|
|
283
313
|
}, {
|
|
284
314
|
F: __dxlog_file2,
|
|
285
|
-
L:
|
|
315
|
+
L: 137,
|
|
286
316
|
S: this,
|
|
287
317
|
C: (f, a) => f(...a)
|
|
288
318
|
});
|
|
@@ -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
|
|
5
|
-
"mappings": ";;;;;;;;;;AAIA,OAAOA,aAAa;AAEpB,SAASC,YAAY;AACrB,SAASC,sBAAsB;AAE/B,SAASC,eAAe;AAExB,SAASC,WAAW;;
|
|
6
|
-
"names": ["express", "join", "getPortPromise", "Trigger", "log", "DEFAULT_PORT", "DevServer", "constructor", "_client", "_options", "_handlers", "port", "_port", "endpoint", "undefined", "functions", "Object", "
|
|
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 Response } from '../handler';\nimport { type FunctionDef, type FunctionManifest } from '../manifest';\n\nconst DEFAULT_PORT = 7001;\n\nexport type DevServerOptions = {\n directory: string;\n manifest: FunctionManifest;\n};\n\n/**\n * Functions dev server provides a local HTTP server for testing functions.\n */\nexport class DevServer {\n private readonly _handlers: Record<string, { def: FunctionDef; handler: 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.values(this._handlers);\n }\n\n async initialize() {\n for (const def of this._options.manifest.functions) {\n const { id, endpoint, handler: path } = def;\n try {\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const module = require(join(this._options.directory, path));\n const handler = module.default;\n if (typeof handler !== 'function') {\n throw new Error(`Handler must export default function: ${id}`);\n }\n\n if (this._handlers[endpoint]) {\n log.warn(`Function already registered: ${id}`);\n }\n\n this._handlers[endpoint] = { def, handler };\n } catch (err) {\n log.error('parsing function (check manifest)', err);\n }\n }\n }\n\n async start() {\n const app = express();\n app.use(express.json());\n\n app.post('/:endpoint', async (req, res) => {\n const { endpoint } = req.params;\n\n const response: Response = {\n status: (code: number) => {\n res.statusCode = code;\n return response;\n },\n\n succeed: (result = {}) => {\n res.end(JSON.stringify(result));\n return response;\n },\n };\n\n const context: FunctionContext = {\n client: this._client,\n status: response.status.bind(response),\n };\n\n void (async () => {\n try {\n log('invoking', { endpoint });\n const { handler } = this._handlers[endpoint];\n const response = await handler({ context, event: req.body });\n log('done', { response });\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(({ def: { endpoint } }) => ({ name: endpoint })), // TODO(burdon): Change proto name => id.\n });\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 FunctionManifest, type FunctionTrigger } from '../manifest';\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 _manifest: FunctionManifest,\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._manifest.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 config = this._manifest.functions.find((config) => config.id === trigger.function);\n invariant(config, `Function not found: ${trigger.function}`);\n const exists = this._mounts.get(key);\n if (!exists) {\n this._mounts.set(key, { ctx, trigger });\n log('mount', { space: space.key, trigger });\n if (ctx.disposed) {\n return;\n }\n\n // 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.execFunction(this._invokeOptions, config.endpoint, {\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 execFunction(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", "_handlers", "port", "_port", "endpoint", "undefined", "functions", "Object", "values", "initialize", "def", "manifest", "id", "handler", "path", "module", "require", "join", "directory", "default", "Error", "log", "warn", "err", "error", "start", "app", "express", "use", "json", "post", "req", "res", "params", "response", "status", "code", "statusCode", "succeed", "result", "end", "JSON", "stringify", "context", "client", "bind", "event", "body", "message", "getPortPromise", "startPort", "_server", "listen", "registrationId", "services", "FunctionRegistryService", "register", "map", "name", "_registrationId", "stop", "trigger", "Trigger", "close", "unregister", "wake", "wait", "DeferredTask", "Context", "Filter", "createSubscription", "invariant", "log", "ComplexMap", "TriggerManager", "constructor", "_client", "_manifest", "_invokeOptions", "_mounts", "name", "spaceKey", "toHex", "_queries", "Set", "start", "spaces", "subscribe", "space", "waitUntilReady", "trigger", "triggers", "mount", "stop", "keys", "unmount", "ctx", "key", "function", "config", "functions", "find", "id", "exists", "get", "set", "disposed", "objectIds", "task", "execFunction", "endpoint", "objects", "Array", "from", "count", "subscription", "added", "updated", "object", "add", "size", "schedule", "query", "db", "typename", "type", "props", "unsubscribe", "update", "onDispose", "delete", "dispose", "options", "functionName", "data", "runtime", "url", "res", "fetch", "method", "body", "JSON", "stringify", "headers", "result", "json", "err", "error", "message"]
|
|
7
7
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"inputs":{"packages/core/functions/src/
|
|
1
|
+
{"inputs":{"packages/core/functions/src/handler.ts":{"bytes":1109,"imports":[],"format":"esm"},"packages/core/functions/src/manifest.ts":{"bytes":1358,"imports":[],"format":"esm"},"packages/core/functions/src/runtime/dev-server.ts":{"bytes":15536,"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":17315,"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":637,"imports":[{"path":"packages/core/functions/src/handler.ts","kind":"import-statement","original":"./handler"},{"path":"packages/core/functions/src/manifest.ts","kind":"import-statement","original":"./manifest"},{"path":"packages/core/functions/src/runtime/index.ts","kind":"import-statement","original":"./runtime"}],"format":"esm"}},"outputs":{"packages/core/functions/dist/lib/browser/index.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":15421},"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":3815},"packages/core/functions/src/runtime/index.ts":{"bytesInOutput":0},"packages/core/functions/src/runtime/trigger-manager.ts":{"bytesInOutput":4642}},"bytes":9049}}}
|
package/dist/lib/node/index.cjs
CHANGED
|
@@ -41,8 +41,8 @@ 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 = "/home/
|
|
45
|
-
var DEFAULT_PORT =
|
|
44
|
+
var __dxlog_file = "/home/runner/work/dxos/dxos/packages/core/functions/src/runtime/dev-server.ts";
|
|
45
|
+
var DEFAULT_PORT = 7001;
|
|
46
46
|
var DevServer = class {
|
|
47
47
|
// prettier-ignore
|
|
48
48
|
constructor(_client, _options) {
|
|
@@ -57,21 +57,33 @@ var DevServer = class {
|
|
|
57
57
|
return this._port ? `http://localhost:${this._port}` : void 0;
|
|
58
58
|
}
|
|
59
59
|
get functions() {
|
|
60
|
-
return Object.
|
|
60
|
+
return Object.values(this._handlers);
|
|
61
61
|
}
|
|
62
62
|
async initialize() {
|
|
63
|
-
for (const
|
|
63
|
+
for (const def of this._options.manifest.functions) {
|
|
64
|
+
const { id, endpoint, handler: path } = def;
|
|
64
65
|
try {
|
|
65
|
-
const module2 = require((0, import_node_path.join)(this._options.directory,
|
|
66
|
+
const module2 = require((0, import_node_path.join)(this._options.directory, path));
|
|
66
67
|
const handler = module2.default;
|
|
67
68
|
if (typeof handler !== "function") {
|
|
68
69
|
throw new Error(`Handler must export default function: ${id}`);
|
|
69
70
|
}
|
|
70
|
-
this._handlers[
|
|
71
|
+
if (this._handlers[endpoint]) {
|
|
72
|
+
import_log.log.warn(`Function already registered: ${id}`, void 0, {
|
|
73
|
+
F: __dxlog_file,
|
|
74
|
+
L: 64,
|
|
75
|
+
S: this,
|
|
76
|
+
C: (f, a) => f(...a)
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
this._handlers[endpoint] = {
|
|
80
|
+
def,
|
|
81
|
+
handler
|
|
82
|
+
};
|
|
71
83
|
} catch (err) {
|
|
72
|
-
import_log.log.error("parsing function (check
|
|
84
|
+
import_log.log.error("parsing function (check manifest)", err, {
|
|
73
85
|
F: __dxlog_file,
|
|
74
|
-
L:
|
|
86
|
+
L: 69,
|
|
75
87
|
S: this,
|
|
76
88
|
C: (f, a) => f(...a)
|
|
77
89
|
});
|
|
@@ -81,36 +93,44 @@ var DevServer = class {
|
|
|
81
93
|
async start() {
|
|
82
94
|
const app = (0, import_express.default)();
|
|
83
95
|
app.use(import_express.default.json());
|
|
84
|
-
app.post("/:
|
|
85
|
-
const
|
|
86
|
-
|
|
87
|
-
function: functionName,
|
|
88
|
-
data: req.body
|
|
89
|
-
}, {
|
|
90
|
-
F: __dxlog_file,
|
|
91
|
-
L: 74,
|
|
92
|
-
S: this,
|
|
93
|
-
C: (f, a) => f(...a)
|
|
94
|
-
});
|
|
95
|
-
const builder = {
|
|
96
|
+
app.post("/:endpoint", async (req, res) => {
|
|
97
|
+
const { endpoint } = req.params;
|
|
98
|
+
const response = {
|
|
96
99
|
status: (code) => {
|
|
97
100
|
res.statusCode = code;
|
|
98
|
-
return
|
|
101
|
+
return response;
|
|
99
102
|
},
|
|
100
103
|
succeed: (result = {}) => {
|
|
101
104
|
res.end(JSON.stringify(result));
|
|
102
|
-
return
|
|
105
|
+
return response;
|
|
103
106
|
}
|
|
104
107
|
};
|
|
105
108
|
const context = {
|
|
106
109
|
client: this._client,
|
|
107
|
-
status:
|
|
110
|
+
status: response.status.bind(response)
|
|
108
111
|
};
|
|
109
112
|
void (async () => {
|
|
110
113
|
try {
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
+
(0, import_log.log)("invoking", {
|
|
115
|
+
endpoint
|
|
116
|
+
}, {
|
|
117
|
+
F: __dxlog_file,
|
|
118
|
+
L: 100,
|
|
119
|
+
S: this,
|
|
120
|
+
C: (f, a) => f(...a)
|
|
121
|
+
});
|
|
122
|
+
const { handler } = this._handlers[endpoint];
|
|
123
|
+
const response2 = await handler({
|
|
124
|
+
context,
|
|
125
|
+
event: req.body
|
|
126
|
+
});
|
|
127
|
+
(0, import_log.log)("done", {
|
|
128
|
+
response: response2
|
|
129
|
+
}, {
|
|
130
|
+
F: __dxlog_file,
|
|
131
|
+
L: 103,
|
|
132
|
+
S: this,
|
|
133
|
+
C: (f, a) => f(...a)
|
|
114
134
|
});
|
|
115
135
|
} catch (err) {
|
|
116
136
|
res.statusCode = 500;
|
|
@@ -125,8 +145,8 @@ var DevServer = class {
|
|
|
125
145
|
try {
|
|
126
146
|
const { registrationId } = await this._client.services.services.FunctionRegistryService.register({
|
|
127
147
|
endpoint: this.endpoint,
|
|
128
|
-
functions: this.functions.map((
|
|
129
|
-
name
|
|
148
|
+
functions: this.functions.map(({ def: { endpoint } }) => ({
|
|
149
|
+
name: endpoint
|
|
130
150
|
}))
|
|
131
151
|
});
|
|
132
152
|
this._registrationId = registrationId;
|
|
@@ -159,11 +179,11 @@ var import_echo_schema = require("@dxos/echo-schema");
|
|
|
159
179
|
var import_invariant = require("@dxos/invariant");
|
|
160
180
|
var import_log2 = require("@dxos/log");
|
|
161
181
|
var import_util = require("@dxos/util");
|
|
162
|
-
var __dxlog_file2 = "/home/
|
|
182
|
+
var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/core/functions/src/runtime/trigger-manager.ts";
|
|
163
183
|
var TriggerManager = class {
|
|
164
|
-
constructor(_client,
|
|
184
|
+
constructor(_client, _manifest, _invokeOptions) {
|
|
165
185
|
this._client = _client;
|
|
166
|
-
this.
|
|
186
|
+
this._manifest = _manifest;
|
|
167
187
|
this._invokeOptions = _invokeOptions;
|
|
168
188
|
this._mounts = new import_util.ComplexMap(({ name, spaceKey }) => `${spaceKey.toHex()}:${name}`);
|
|
169
189
|
this._queries = /* @__PURE__ */ new Set();
|
|
@@ -172,7 +192,7 @@ var TriggerManager = class {
|
|
|
172
192
|
this._client.spaces.subscribe(async (spaces) => {
|
|
173
193
|
for (const space of spaces) {
|
|
174
194
|
await space.waitUntilReady();
|
|
175
|
-
for (const trigger of this.
|
|
195
|
+
for (const trigger of this._manifest.triggers ?? []) {
|
|
176
196
|
await this.mount(new import_context.Context(), space, trigger);
|
|
177
197
|
}
|
|
178
198
|
}
|
|
@@ -188,6 +208,16 @@ var TriggerManager = class {
|
|
|
188
208
|
name: trigger.function,
|
|
189
209
|
spaceKey: space.key
|
|
190
210
|
};
|
|
211
|
+
const config = this._manifest.functions.find((config2) => config2.id === trigger.function);
|
|
212
|
+
(0, import_invariant.invariant)(config, `Function not found: ${trigger.function}`, {
|
|
213
|
+
F: __dxlog_file2,
|
|
214
|
+
L: 58,
|
|
215
|
+
S: this,
|
|
216
|
+
A: [
|
|
217
|
+
"config",
|
|
218
|
+
"`Function not found: ${trigger.function}`"
|
|
219
|
+
]
|
|
220
|
+
});
|
|
191
221
|
const exists = this._mounts.get(key);
|
|
192
222
|
if (!exists) {
|
|
193
223
|
this._mounts.set(key, {
|
|
@@ -199,7 +229,7 @@ var TriggerManager = class {
|
|
|
199
229
|
trigger
|
|
200
230
|
}, {
|
|
201
231
|
F: __dxlog_file2,
|
|
202
|
-
L:
|
|
232
|
+
L: 62,
|
|
203
233
|
S: this,
|
|
204
234
|
C: (f, a) => f(...a)
|
|
205
235
|
});
|
|
@@ -208,7 +238,7 @@ var TriggerManager = class {
|
|
|
208
238
|
}
|
|
209
239
|
const objectIds = /* @__PURE__ */ new Set();
|
|
210
240
|
const task = new import_async2.DeferredTask(ctx, async () => {
|
|
211
|
-
await this.
|
|
241
|
+
await this.execFunction(this._invokeOptions, config.endpoint, {
|
|
212
242
|
space: space.key,
|
|
213
243
|
objects: Array.from(objectIds)
|
|
214
244
|
});
|
|
@@ -228,7 +258,7 @@ var TriggerManager = class {
|
|
|
228
258
|
count
|
|
229
259
|
}, {
|
|
230
260
|
F: __dxlog_file2,
|
|
231
|
-
L:
|
|
261
|
+
L: 85,
|
|
232
262
|
S: this,
|
|
233
263
|
C: (f, a) => f(...a)
|
|
234
264
|
});
|
|
@@ -258,11 +288,11 @@ var TriggerManager = class {
|
|
|
258
288
|
await ctx.dispose();
|
|
259
289
|
}
|
|
260
290
|
}
|
|
261
|
-
async
|
|
291
|
+
async execFunction(options, functionName, data) {
|
|
262
292
|
const { endpoint, runtime } = options;
|
|
263
293
|
(0, import_invariant.invariant)(endpoint, "Missing endpoint", {
|
|
264
294
|
F: __dxlog_file2,
|
|
265
|
-
L:
|
|
295
|
+
L: 121,
|
|
266
296
|
S: this,
|
|
267
297
|
A: [
|
|
268
298
|
"endpoint",
|
|
@@ -271,7 +301,7 @@ var TriggerManager = class {
|
|
|
271
301
|
});
|
|
272
302
|
(0, import_invariant.invariant)(runtime, "Missing runtime", {
|
|
273
303
|
F: __dxlog_file2,
|
|
274
|
-
L:
|
|
304
|
+
L: 122,
|
|
275
305
|
S: this,
|
|
276
306
|
A: [
|
|
277
307
|
"runtime",
|
|
@@ -283,7 +313,7 @@ var TriggerManager = class {
|
|
|
283
313
|
function: functionName
|
|
284
314
|
}, {
|
|
285
315
|
F: __dxlog_file2,
|
|
286
|
-
L:
|
|
316
|
+
L: 125,
|
|
287
317
|
S: this,
|
|
288
318
|
C: (f, a) => f(...a)
|
|
289
319
|
});
|
|
@@ -300,7 +330,7 @@ var TriggerManager = class {
|
|
|
300
330
|
result: await res.json()
|
|
301
331
|
}, {
|
|
302
332
|
F: __dxlog_file2,
|
|
303
|
-
L:
|
|
333
|
+
L: 135,
|
|
304
334
|
S: this,
|
|
305
335
|
C: (f, a) => f(...a)
|
|
306
336
|
});
|
|
@@ -310,7 +340,7 @@ var TriggerManager = class {
|
|
|
310
340
|
error: err.message
|
|
311
341
|
}, {
|
|
312
342
|
F: __dxlog_file2,
|
|
313
|
-
L:
|
|
343
|
+
L: 137,
|
|
314
344
|
S: this,
|
|
315
345
|
C: (f, a) => f(...a)
|
|
316
346
|
});
|
|
@@ -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 './
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;;;;;;;;ACIA,qBAAoB;AAEpB,uBAAqB;AACrB,wBAA+B;AAE/B,mBAAwB;AAExB,iBAAoB;;
|
|
6
|
-
"names": ["DEFAULT_PORT", "DevServer", "constructor", "_client", "_options", "_handlers", "port", "_port", "endpoint", "undefined", "functions", "Object", "
|
|
4
|
+
"sourcesContent": ["//\n// Copyright 2023 DXOS.org\n//\n\nexport * from './handler';\nexport * from './manifest';\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 Response } from '../handler';\nimport { type FunctionDef, type FunctionManifest } from '../manifest';\n\nconst DEFAULT_PORT = 7001;\n\nexport type DevServerOptions = {\n directory: string;\n manifest: FunctionManifest;\n};\n\n/**\n * Functions dev server provides a local HTTP server for testing functions.\n */\nexport class DevServer {\n private readonly _handlers: Record<string, { def: FunctionDef; handler: 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.values(this._handlers);\n }\n\n async initialize() {\n for (const def of this._options.manifest.functions) {\n const { id, endpoint, handler: path } = def;\n try {\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const module = require(join(this._options.directory, path));\n const handler = module.default;\n if (typeof handler !== 'function') {\n throw new Error(`Handler must export default function: ${id}`);\n }\n\n if (this._handlers[endpoint]) {\n log.warn(`Function already registered: ${id}`);\n }\n\n this._handlers[endpoint] = { def, handler };\n } catch (err) {\n log.error('parsing function (check manifest)', err);\n }\n }\n }\n\n async start() {\n const app = express();\n app.use(express.json());\n\n app.post('/:endpoint', async (req, res) => {\n const { endpoint } = req.params;\n\n const response: Response = {\n status: (code: number) => {\n res.statusCode = code;\n return response;\n },\n\n succeed: (result = {}) => {\n res.end(JSON.stringify(result));\n return response;\n },\n };\n\n const context: FunctionContext = {\n client: this._client,\n status: response.status.bind(response),\n };\n\n void (async () => {\n try {\n log('invoking', { endpoint });\n const { handler } = this._handlers[endpoint];\n const response = await handler({ context, event: req.body });\n log('done', { response });\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(({ def: { endpoint } }) => ({ name: endpoint })), // TODO(burdon): Change proto name => id.\n });\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 FunctionManifest, type FunctionTrigger } from '../manifest';\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 _manifest: FunctionManifest,\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._manifest.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 config = this._manifest.functions.find((config) => config.id === trigger.function);\n invariant(config, `Function not found: ${trigger.function}`);\n const exists = this._mounts.get(key);\n if (!exists) {\n this._mounts.set(key, { ctx, trigger });\n log('mount', { space: space.key, trigger });\n if (ctx.disposed) {\n return;\n }\n\n // 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.execFunction(this._invokeOptions, config.endpoint, {\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 execFunction(options: InvokeOptions, functionName: string, data: any) {\n const { endpoint, runtime } = options;\n invariant(endpoint, 'Missing endpoint');\n invariant(runtime, 'Missing runtime');\n\n try {\n log('invoke', { function: functionName });\n const url = `${endpoint}/${runtime}/${functionName}`;\n const res = await fetch(url, {\n method: 'POST',\n body: JSON.stringify(data),\n headers: {\n 'Content-Type': 'application/json',\n },\n });\n\n log('result', { function: functionName, result: await res.json() });\n } catch (err: any) {\n log.error('error', { function: functionName, error: err.message });\n }\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["DEFAULT_PORT", "DevServer", "constructor", "_client", "_options", "_handlers", "port", "_port", "endpoint", "undefined", "functions", "Object", "values", "initialize", "def", "manifest", "id", "handler", "path", "module", "require", "join", "directory", "default", "Error", "log", "warn", "err", "error", "start", "app", "express", "use", "json", "post", "req", "res", "params", "response", "status", "code", "statusCode", "succeed", "result", "end", "JSON", "stringify", "context", "client", "bind", "event", "body", "message", "getPortPromise", "startPort", "_server", "listen", "registrationId", "services", "FunctionRegistryService", "register", "map", "name", "_registrationId", "stop", "trigger", "Trigger", "close", "unregister", "wake", "wait", "import_async", "import_log", "TriggerManager", "constructor", "_client", "_manifest", "_invokeOptions", "_mounts", "ComplexMap", "name", "spaceKey", "toHex", "_queries", "Set", "start", "spaces", "subscribe", "space", "waitUntilReady", "trigger", "triggers", "mount", "Context", "stop", "keys", "unmount", "ctx", "key", "function", "config", "functions", "find", "id", "invariant", "exists", "get", "set", "log", "disposed", "objectIds", "task", "DeferredTask", "execFunction", "endpoint", "objects", "Array", "from", "count", "subscription", "createSubscription", "added", "updated", "object", "add", "size", "schedule", "query", "db", "Filter", "typename", "type", "props", "unsubscribe", "update", "onDispose", "delete", "dispose", "options", "functionName", "data", "runtime", "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/
|
|
1
|
+
{"inputs":{"packages/core/functions/src/handler.ts":{"bytes":1109,"imports":[],"format":"esm"},"packages/core/functions/src/manifest.ts":{"bytes":1358,"imports":[],"format":"esm"},"packages/core/functions/src/runtime/dev-server.ts":{"bytes":15536,"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":17315,"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":637,"imports":[{"path":"packages/core/functions/src/handler.ts","kind":"import-statement","original":"./handler"},{"path":"packages/core/functions/src/manifest.ts","kind":"import-statement","original":"./manifest"},{"path":"packages/core/functions/src/runtime/index.ts","kind":"import-statement","original":"./runtime"}],"format":"esm"}},"outputs":{"packages/core/functions/dist/lib/node/index.cjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":15521},"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":3994},"packages/core/functions/src/runtime/index.ts":{"bytesInOutput":0},"packages/core/functions/src/runtime/trigger-manager.ts":{"bytesInOutput":4869}},"bytes":10732}}}
|
|
@@ -7,30 +7,15 @@ export interface FunctionContext {
|
|
|
7
7
|
client: Client;
|
|
8
8
|
status(code: number): Response;
|
|
9
9
|
}
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
};
|
|
10
|
+
/**
|
|
11
|
+
* Function handler.
|
|
12
|
+
*/
|
|
14
13
|
export type FunctionHandler<T extends {}> = (params: {
|
|
15
|
-
event: T;
|
|
16
14
|
context: FunctionContext;
|
|
15
|
+
event: T;
|
|
17
16
|
}) => Promise<Response | void>;
|
|
18
|
-
export type
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
};
|
|
22
|
-
export type FunctionConfig = {
|
|
23
|
-
id: string;
|
|
24
|
-
description?: string;
|
|
25
|
-
};
|
|
26
|
-
export type FunctionTrigger = {
|
|
27
|
-
function: string;
|
|
28
|
-
subscription: TriggerSubscription;
|
|
29
|
-
};
|
|
30
|
-
export type TriggerSubscription = {
|
|
31
|
-
type: string;
|
|
32
|
-
spaceKey: string;
|
|
33
|
-
props?: Record<string, any>;
|
|
34
|
-
nested?: string[];
|
|
17
|
+
export type FunctionSubscriptionEvent = {
|
|
18
|
+
space: string;
|
|
19
|
+
objects: string[];
|
|
35
20
|
};
|
|
36
|
-
//# sourceMappingURL=
|
|
21
|
+
//# sourceMappingURL=handler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../../src/handler.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,cAAc,CAAC;AAE3C,MAAM,WAAW,QAAQ;IACvB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,CAAC;IAC/B,OAAO,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC;CAClC;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,CAAC;CAChC;AAED;;GAEG;AACH,MAAM,MAAM,eAAe,CAAC,CAAC,SAAS,EAAE,IAAI,CAAC,MAAM,EAAE;IACnD,OAAO,EAAE,eAAe,CAAC;IACzB,KAAK,EAAE,CAAC,CAAC;CACV,KAAK,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAAC;AAG/B,MAAM,MAAM,yBAAyB,GAAG;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAIA,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAIA,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export type FunctionDef = {
|
|
2
|
+
id: string;
|
|
3
|
+
endpoint: string;
|
|
4
|
+
handler: string;
|
|
5
|
+
description?: string;
|
|
6
|
+
};
|
|
7
|
+
export type TriggerSubscription = {
|
|
8
|
+
type: string;
|
|
9
|
+
spaceKey: string;
|
|
10
|
+
props?: Record<string, any>;
|
|
11
|
+
nested?: string[];
|
|
12
|
+
};
|
|
13
|
+
export type FunctionTrigger = {
|
|
14
|
+
function: string;
|
|
15
|
+
subscription: TriggerSubscription;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Function manifest file.
|
|
19
|
+
*/
|
|
20
|
+
export type FunctionManifest = {
|
|
21
|
+
functions: FunctionDef[];
|
|
22
|
+
triggers: FunctionTrigger[];
|
|
23
|
+
};
|
|
24
|
+
//# sourceMappingURL=manifest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../../src/manifest.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,WAAW,GAAG;IAExB,EAAE,EAAE,MAAM,CAAC;IAEX,QAAQ,EAAE,MAAM,CAAC;IAEjB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB,CAAC;AAKF,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,mBAAmB,CAAC;CACnC,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC7B,SAAS,EAAE,WAAW,EAAE,CAAC;IACzB,QAAQ,EAAE,eAAe,EAAE,CAAC;CAC7B,CAAC"}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { type Client } from '@dxos/client';
|
|
2
|
-
import { type
|
|
2
|
+
import { type FunctionHandler } from '../handler';
|
|
3
|
+
import { type FunctionDef, type FunctionManifest } from '../manifest';
|
|
3
4
|
export type DevServerOptions = {
|
|
4
5
|
directory: string;
|
|
5
|
-
manifest:
|
|
6
|
+
manifest: FunctionManifest;
|
|
6
7
|
};
|
|
7
8
|
/**
|
|
8
9
|
* Functions dev server provides a local HTTP server for testing functions.
|
|
@@ -17,7 +18,10 @@ export declare class DevServer {
|
|
|
17
18
|
constructor(_client: Client, _options: DevServerOptions);
|
|
18
19
|
get port(): number | undefined;
|
|
19
20
|
get endpoint(): string | undefined;
|
|
20
|
-
get functions():
|
|
21
|
+
get functions(): {
|
|
22
|
+
def: FunctionDef;
|
|
23
|
+
handler: FunctionHandler<any>;
|
|
24
|
+
}[];
|
|
21
25
|
initialize(): Promise<void>;
|
|
22
26
|
start(): Promise<void>;
|
|
23
27
|
stop(): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dev-server.d.ts","sourceRoot":"","sources":["../../../../src/runtime/dev-server.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,cAAc,CAAC;AAG3C,OAAO,
|
|
1
|
+
{"version":3,"file":"dev-server.d.ts","sourceRoot":"","sources":["../../../../src/runtime/dev-server.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,cAAc,CAAC;AAG3C,OAAO,EAAwB,KAAK,eAAe,EAAiB,MAAM,YAAY,CAAC;AACvF,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAItE,MAAM,MAAM,gBAAgB,GAAG;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,gBAAgB,CAAC;CAC5B,CAAC;AAEF;;GAEG;AACH,qBAAa,SAAS;IASlB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAT3B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA2E;IAErG,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;;;QAEZ;IAEK,UAAU;IAsBV,KAAK;IAuDL,IAAI;CAiBX"}
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
import { type Client } from '@dxos/client';
|
|
2
|
-
import { type
|
|
2
|
+
import { type FunctionManifest } from '../manifest';
|
|
3
3
|
export type InvokeOptions = {
|
|
4
4
|
endpoint: string;
|
|
5
5
|
runtime: string;
|
|
6
6
|
};
|
|
7
7
|
export declare class TriggerManager {
|
|
8
8
|
private readonly _client;
|
|
9
|
-
private readonly
|
|
9
|
+
private readonly _manifest;
|
|
10
10
|
private readonly _invokeOptions;
|
|
11
11
|
private readonly _mounts;
|
|
12
12
|
private readonly _queries;
|
|
13
|
-
constructor(_client: Client,
|
|
13
|
+
constructor(_client: Client, _manifest: FunctionManifest, _invokeOptions: InvokeOptions);
|
|
14
14
|
start(): Promise<void>;
|
|
15
15
|
stop(): Promise<void>;
|
|
16
16
|
private mount;
|
|
17
17
|
private unmount;
|
|
18
|
-
private
|
|
18
|
+
private execFunction;
|
|
19
19
|
}
|
|
20
20
|
//# sourceMappingURL=trigger-manager.d.ts.map
|
|
@@ -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,
|
|
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,gBAAgB,EAAwB,MAAM,aAAa,CAAC;AAG1E,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,gBAAgB,EAC3B,cAAc,EAAE,aAAa;IAG1C,KAAK;IAaL,IAAI;YAMI,KAAK;YAuDL,OAAO;YASP,YAAY;CAqB3B"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dxos/functions",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.8-main.598e316",
|
|
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.
|
|
25
|
-
"@dxos/client": "0.3.
|
|
26
|
-
"@dxos/context": "0.3.
|
|
27
|
-
"@dxos/echo-schema": "0.3.
|
|
28
|
-
"@dxos/invariant": "0.3.
|
|
29
|
-
"@dxos/log": "0.3.
|
|
30
|
-
"@dxos/node-std": "0.3.
|
|
31
|
-
"@dxos/util": "0.3.
|
|
24
|
+
"@dxos/async": "0.3.8-main.598e316",
|
|
25
|
+
"@dxos/client": "0.3.8-main.598e316",
|
|
26
|
+
"@dxos/context": "0.3.8-main.598e316",
|
|
27
|
+
"@dxos/echo-schema": "0.3.8-main.598e316",
|
|
28
|
+
"@dxos/invariant": "0.3.8-main.598e316",
|
|
29
|
+
"@dxos/log": "0.3.8-main.598e316",
|
|
30
|
+
"@dxos/node-std": "0.3.8-main.598e316",
|
|
31
|
+
"@dxos/util": "0.3.8-main.598e316"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
34
|
"@types/express": "^4.17.17"
|
package/src/handler.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2023 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { type Client } from '@dxos/client';
|
|
6
|
+
|
|
7
|
+
export interface Response {
|
|
8
|
+
status(code: number): Response;
|
|
9
|
+
succeed(data?: object): Response;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface FunctionContext {
|
|
13
|
+
client: Client;
|
|
14
|
+
status(code: number): Response;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Function handler.
|
|
19
|
+
*/
|
|
20
|
+
export type FunctionHandler<T extends {}> = (params: {
|
|
21
|
+
context: FunctionContext;
|
|
22
|
+
event: T;
|
|
23
|
+
}) => Promise<Response | void>;
|
|
24
|
+
|
|
25
|
+
// TODO(burdon): Types.
|
|
26
|
+
export type FunctionSubscriptionEvent = {
|
|
27
|
+
space: string;
|
|
28
|
+
objects: string[];
|
|
29
|
+
};
|
package/src/index.ts
CHANGED
package/src/manifest.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2023 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
export type FunctionDef = {
|
|
6
|
+
// FQ function name.
|
|
7
|
+
id: string;
|
|
8
|
+
// HTTP endpoint.
|
|
9
|
+
endpoint: string;
|
|
10
|
+
// Path of handler.
|
|
11
|
+
handler: string;
|
|
12
|
+
description?: string;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export type TriggerSubscription = {
|
|
16
|
+
type: string;
|
|
17
|
+
spaceKey: string;
|
|
18
|
+
props?: Record<string, any>;
|
|
19
|
+
nested?: string[];
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
// TODO(burdon): Generalize binding.
|
|
23
|
+
// https://www.npmjs.com/package/aws-lambda
|
|
24
|
+
// https://docs.aws.amazon.com/lambda/latest/dg/typescript-handler.html
|
|
25
|
+
export type FunctionTrigger = {
|
|
26
|
+
function: string;
|
|
27
|
+
subscription: TriggerSubscription;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Function manifest file.
|
|
32
|
+
*/
|
|
33
|
+
export type FunctionManifest = {
|
|
34
|
+
functions: FunctionDef[];
|
|
35
|
+
triggers: FunctionTrigger[];
|
|
36
|
+
};
|
|
@@ -11,20 +11,21 @@ import { Trigger } from '@dxos/async';
|
|
|
11
11
|
import { type Client } from '@dxos/client';
|
|
12
12
|
import { log } from '@dxos/log';
|
|
13
13
|
|
|
14
|
-
import { type FunctionContext, type FunctionHandler, type
|
|
14
|
+
import { type FunctionContext, type FunctionHandler, type Response } from '../handler';
|
|
15
|
+
import { type FunctionDef, type FunctionManifest } from '../manifest';
|
|
15
16
|
|
|
16
|
-
const DEFAULT_PORT =
|
|
17
|
+
const DEFAULT_PORT = 7001;
|
|
17
18
|
|
|
18
19
|
export type DevServerOptions = {
|
|
19
20
|
directory: string;
|
|
20
|
-
manifest:
|
|
21
|
+
manifest: FunctionManifest;
|
|
21
22
|
};
|
|
22
23
|
|
|
23
24
|
/**
|
|
24
25
|
* Functions dev server provides a local HTTP server for testing functions.
|
|
25
26
|
*/
|
|
26
27
|
export class DevServer {
|
|
27
|
-
private readonly _handlers: Record<string, FunctionHandler<any
|
|
28
|
+
private readonly _handlers: Record<string, { def: FunctionDef; handler: FunctionHandler<any> }> = {};
|
|
28
29
|
|
|
29
30
|
private _server?: http.Server;
|
|
30
31
|
private _port?: number;
|
|
@@ -45,22 +46,27 @@ export class DevServer {
|
|
|
45
46
|
}
|
|
46
47
|
|
|
47
48
|
get functions() {
|
|
48
|
-
return Object.
|
|
49
|
+
return Object.values(this._handlers);
|
|
49
50
|
}
|
|
50
51
|
|
|
51
52
|
async initialize() {
|
|
52
|
-
for (const
|
|
53
|
+
for (const def of this._options.manifest.functions) {
|
|
54
|
+
const { id, endpoint, handler: path } = def;
|
|
53
55
|
try {
|
|
54
56
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
55
|
-
const module = require(join(this._options.directory,
|
|
57
|
+
const module = require(join(this._options.directory, path));
|
|
56
58
|
const handler = module.default;
|
|
57
59
|
if (typeof handler !== 'function') {
|
|
58
60
|
throw new Error(`Handler must export default function: ${id}`);
|
|
59
61
|
}
|
|
60
62
|
|
|
61
|
-
this._handlers[
|
|
63
|
+
if (this._handlers[endpoint]) {
|
|
64
|
+
log.warn(`Function already registered: ${id}`);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
this._handlers[endpoint] = { def, handler };
|
|
62
68
|
} catch (err) {
|
|
63
|
-
log.error('parsing function (check
|
|
69
|
+
log.error('parsing function (check manifest)', err);
|
|
64
70
|
}
|
|
65
71
|
}
|
|
66
72
|
}
|
|
@@ -69,30 +75,32 @@ export class DevServer {
|
|
|
69
75
|
const app = express();
|
|
70
76
|
app.use(express.json());
|
|
71
77
|
|
|
72
|
-
app.post('/:
|
|
73
|
-
const
|
|
74
|
-
log('invoke', { function: functionName, data: req.body });
|
|
78
|
+
app.post('/:endpoint', async (req, res) => {
|
|
79
|
+
const { endpoint } = req.params;
|
|
75
80
|
|
|
76
|
-
const
|
|
81
|
+
const response: Response = {
|
|
77
82
|
status: (code: number) => {
|
|
78
83
|
res.statusCode = code;
|
|
79
|
-
return
|
|
84
|
+
return response;
|
|
80
85
|
},
|
|
86
|
+
|
|
81
87
|
succeed: (result = {}) => {
|
|
82
88
|
res.end(JSON.stringify(result));
|
|
83
|
-
return
|
|
89
|
+
return response;
|
|
84
90
|
},
|
|
85
91
|
};
|
|
86
92
|
|
|
87
93
|
const context: FunctionContext = {
|
|
88
94
|
client: this._client,
|
|
89
|
-
status:
|
|
95
|
+
status: response.status.bind(response),
|
|
90
96
|
};
|
|
91
97
|
|
|
92
98
|
void (async () => {
|
|
93
99
|
try {
|
|
94
|
-
|
|
95
|
-
|
|
100
|
+
log('invoking', { endpoint });
|
|
101
|
+
const { handler } = this._handlers[endpoint];
|
|
102
|
+
const response = await handler({ context, event: req.body });
|
|
103
|
+
log('done', { response });
|
|
96
104
|
} catch (err: any) {
|
|
97
105
|
res.statusCode = 500;
|
|
98
106
|
res.end(err.message);
|
|
@@ -108,8 +116,9 @@ export class DevServer {
|
|
|
108
116
|
try {
|
|
109
117
|
const { registrationId } = await this._client.services.services.FunctionRegistryService!.register({
|
|
110
118
|
endpoint: this.endpoint!,
|
|
111
|
-
functions: this.functions.map((
|
|
119
|
+
functions: this.functions.map(({ def: { endpoint } }) => ({ name: endpoint })), // TODO(burdon): Change proto name => id.
|
|
112
120
|
});
|
|
121
|
+
|
|
113
122
|
this._registrationId = registrationId;
|
|
114
123
|
} catch (err: any) {
|
|
115
124
|
await this.stop();
|
|
@@ -11,7 +11,7 @@ import { invariant } from '@dxos/invariant';
|
|
|
11
11
|
import { log } from '@dxos/log';
|
|
12
12
|
import { ComplexMap } from '@dxos/util';
|
|
13
13
|
|
|
14
|
-
import { type FunctionTrigger } from '../
|
|
14
|
+
import { type FunctionManifest, type FunctionTrigger } from '../manifest';
|
|
15
15
|
|
|
16
16
|
// TODO(burdon): Rename.
|
|
17
17
|
export type InvokeOptions = {
|
|
@@ -29,7 +29,7 @@ export class TriggerManager {
|
|
|
29
29
|
|
|
30
30
|
constructor(
|
|
31
31
|
private readonly _client: Client,
|
|
32
|
-
private readonly
|
|
32
|
+
private readonly _manifest: FunctionManifest,
|
|
33
33
|
private readonly _invokeOptions: InvokeOptions,
|
|
34
34
|
) {}
|
|
35
35
|
|
|
@@ -38,7 +38,7 @@ export class TriggerManager {
|
|
|
38
38
|
this._client.spaces.subscribe(async (spaces) => {
|
|
39
39
|
for (const space of spaces) {
|
|
40
40
|
await space.waitUntilReady();
|
|
41
|
-
for (const trigger of this.
|
|
41
|
+
for (const trigger of this._manifest.triggers ?? []) {
|
|
42
42
|
// TODO(burdon): New context? Shared?
|
|
43
43
|
await this.mount(new Context(), space, trigger);
|
|
44
44
|
}
|
|
@@ -54,6 +54,8 @@ export class TriggerManager {
|
|
|
54
54
|
|
|
55
55
|
private async mount(ctx: Context, space: Space, trigger: FunctionTrigger) {
|
|
56
56
|
const key = { name: trigger.function, spaceKey: space.key };
|
|
57
|
+
const config = this._manifest.functions.find((config) => config.id === trigger.function);
|
|
58
|
+
invariant(config, `Function not found: ${trigger.function}`);
|
|
57
59
|
const exists = this._mounts.get(key);
|
|
58
60
|
if (!exists) {
|
|
59
61
|
this._mounts.set(key, { ctx, trigger });
|
|
@@ -62,11 +64,10 @@ export class TriggerManager {
|
|
|
62
64
|
return;
|
|
63
65
|
}
|
|
64
66
|
|
|
65
|
-
// TODO(burdon): Trigger binding.
|
|
66
67
|
// TODO(burdon): Why DeferredTask? How to pass objectIds to function?
|
|
67
68
|
const objectIds = new Set<string>();
|
|
68
69
|
const task = new DeferredTask(ctx, async () => {
|
|
69
|
-
await this.
|
|
70
|
+
await this.execFunction(this._invokeOptions, config.endpoint, {
|
|
70
71
|
space: space.key,
|
|
71
72
|
objects: Array.from(objectIds),
|
|
72
73
|
});
|
|
@@ -115,7 +116,7 @@ export class TriggerManager {
|
|
|
115
116
|
}
|
|
116
117
|
}
|
|
117
118
|
|
|
118
|
-
private async
|
|
119
|
+
private async execFunction(options: InvokeOptions, functionName: string, data: any) {
|
|
119
120
|
const { endpoint, runtime } = options;
|
|
120
121
|
invariant(endpoint, 'Missing endpoint');
|
|
121
122
|
invariant(runtime, 'Missing runtime');
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"function.d.ts","sourceRoot":"","sources":["../../../src/function.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,cAAc,CAAC;AAE3C,MAAM,WAAW,QAAQ;IACvB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,CAAC;IAC/B,OAAO,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC;CAClC;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,CAAC;CAChC;AAMD,MAAM,MAAM,yBAAyB,GAAG;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,eAAe,CAAC,CAAC,SAAS,EAAE,IAAI,CAAC,MAAM,EAAE;IACnD,KAAK,EAAE,CAAC,CAAC;IACT,OAAO,EAAE,eAAe,CAAC;CAC1B,KAAK,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAAC;AAE/B,MAAM,MAAM,iBAAiB,GAAG;IAC9B,SAAS,EAAE,cAAc,EAAE,CAAC;IAC5B,QAAQ,EAAE,eAAe,EAAE,CAAC;CAC7B,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,mBAAmB,CAAC;CACnC,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB,CAAC"}
|
package/src/function.ts
DELETED
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Copyright 2023 DXOS.org
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
import { type Client } from '@dxos/client';
|
|
6
|
-
|
|
7
|
-
export interface Response {
|
|
8
|
-
status(code: number): Response;
|
|
9
|
-
succeed(data?: object): Response;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export interface FunctionContext {
|
|
13
|
-
client: Client;
|
|
14
|
-
status(code: number): Response;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
// https://www.npmjs.com/package/aws-lambda
|
|
18
|
-
// https://docs.aws.amazon.com/lambda/latest/dg/typescript-handler.html
|
|
19
|
-
|
|
20
|
-
// TODO(burdon): Types.
|
|
21
|
-
export type FunctionSubscriptionEvent = {
|
|
22
|
-
space: string;
|
|
23
|
-
objects: string[];
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
export type FunctionHandler<T extends {}> = (params: {
|
|
27
|
-
event: T;
|
|
28
|
-
context: FunctionContext;
|
|
29
|
-
}) => Promise<Response | void>;
|
|
30
|
-
|
|
31
|
-
export type FunctionsManifest = {
|
|
32
|
-
functions: FunctionConfig[];
|
|
33
|
-
triggers: FunctionTrigger[];
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
export type FunctionConfig = {
|
|
37
|
-
id: string;
|
|
38
|
-
description?: string;
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
export type FunctionTrigger = {
|
|
42
|
-
function: string;
|
|
43
|
-
subscription: TriggerSubscription;
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
export type TriggerSubscription = {
|
|
47
|
-
type: string;
|
|
48
|
-
spaceKey: string;
|
|
49
|
-
props?: Record<string, any>;
|
|
50
|
-
nested?: string[];
|
|
51
|
-
};
|