@dxos/functions 0.5.3-main.3456876 → 0.5.3-main.37bbd91
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/chunk-366QG6IX.mjs +81 -0
- package/dist/lib/browser/chunk-366QG6IX.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +712 -490
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/types.mjs +12 -0
- package/dist/lib/browser/types.mjs.map +7 -0
- package/dist/lib/node/chunk-3VSJ57ZZ.cjs +97 -0
- package/dist/lib/node/chunk-3VSJ57ZZ.cjs.map +7 -0
- package/dist/lib/node/index.cjs +695 -483
- package/dist/lib/node/index.cjs.map +4 -4
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node/types.cjs +33 -0
- package/dist/lib/node/types.cjs.map +7 -0
- package/dist/types/src/function/function-registry.d.ts +24 -0
- package/dist/types/src/function/function-registry.d.ts.map +1 -0
- package/dist/types/src/function/function-registry.test.d.ts +2 -0
- package/dist/types/src/function/function-registry.test.d.ts.map +1 -0
- package/dist/types/src/function/index.d.ts +2 -0
- package/dist/types/src/function/index.d.ts.map +1 -0
- package/dist/types/src/handler.d.ts +32 -12
- package/dist/types/src/handler.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +2 -0
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/runtime/dev-server.d.ts +7 -10
- package/dist/types/src/runtime/dev-server.d.ts.map +1 -1
- package/dist/types/src/runtime/scheduler.d.ts +11 -59
- package/dist/types/src/runtime/scheduler.d.ts.map +1 -1
- package/dist/types/src/testing/functions-integration.test.d.ts +2 -0
- package/dist/types/src/testing/functions-integration.test.d.ts.map +1 -0
- package/dist/types/src/testing/index.d.ts +4 -0
- package/dist/types/src/testing/index.d.ts.map +1 -0
- package/dist/types/src/testing/setup.d.ts +5 -0
- package/dist/types/src/testing/setup.d.ts.map +1 -0
- package/dist/types/src/testing/test/handler.d.ts +1 -0
- package/dist/types/src/testing/test/handler.d.ts.map +1 -1
- package/dist/types/src/testing/types.d.ts +9 -0
- package/dist/types/src/testing/types.d.ts.map +1 -0
- package/dist/types/src/testing/util.d.ts +3 -0
- package/dist/types/src/testing/util.d.ts.map +1 -0
- package/dist/types/src/trigger/index.d.ts +2 -0
- package/dist/types/src/trigger/index.d.ts.map +1 -0
- package/dist/types/src/trigger/trigger-registry.d.ts +40 -0
- package/dist/types/src/trigger/trigger-registry.d.ts.map +1 -0
- package/dist/types/src/trigger/trigger-registry.test.d.ts +2 -0
- package/dist/types/src/trigger/trigger-registry.test.d.ts.map +1 -0
- package/dist/types/src/trigger/type/index.d.ts +5 -0
- package/dist/types/src/trigger/type/index.d.ts.map +1 -0
- package/dist/types/src/trigger/type/subscription-trigger.d.ts +4 -0
- package/dist/types/src/trigger/type/subscription-trigger.d.ts.map +1 -0
- package/dist/types/src/trigger/type/timer-trigger.d.ts +4 -0
- package/dist/types/src/trigger/type/timer-trigger.d.ts.map +1 -0
- package/dist/types/src/trigger/type/webhook-trigger.d.ts +4 -0
- package/dist/types/src/trigger/type/webhook-trigger.d.ts.map +1 -0
- package/dist/types/src/trigger/type/websocket-trigger.d.ts +13 -0
- package/dist/types/src/trigger/type/websocket-trigger.d.ts.map +1 -0
- package/dist/types/src/types.d.ts +131 -111
- package/dist/types/src/types.d.ts.map +1 -1
- package/dist/types/src/util.d.ts +15 -0
- package/dist/types/src/util.d.ts.map +1 -0
- package/dist/types/src/util.test.d.ts +2 -0
- package/dist/types/src/util.test.d.ts.map +1 -0
- package/package.json +30 -14
- package/schema/functions.json +140 -112
- package/src/function/function-registry.test.ts +105 -0
- package/src/function/function-registry.ts +90 -0
- package/src/function/index.ts +5 -0
- package/src/handler.ts +50 -27
- package/src/index.ts +2 -0
- package/src/runtime/dev-server.test.ts +15 -35
- package/src/runtime/dev-server.ts +41 -24
- package/src/runtime/scheduler.test.ts +54 -75
- package/src/runtime/scheduler.ts +75 -300
- package/src/testing/functions-integration.test.ts +99 -0
- package/src/testing/index.ts +7 -0
- package/src/testing/setup.ts +45 -0
- package/src/testing/test/handler.ts +8 -2
- package/src/testing/types.ts +9 -0
- package/src/testing/util.ts +16 -0
- package/src/trigger/index.ts +5 -0
- package/src/trigger/trigger-registry.test.ts +255 -0
- package/src/trigger/trigger-registry.ts +189 -0
- package/src/trigger/type/index.ts +8 -0
- package/src/trigger/type/subscription-trigger.ts +80 -0
- package/src/trigger/type/timer-trigger.ts +44 -0
- package/src/trigger/type/webhook-trigger.ts +47 -0
- package/src/trigger/type/websocket-trigger.ts +91 -0
- package/src/types.ts +58 -40
- package/src/util.test.ts +43 -0
- package/src/util.ts +48 -0
|
@@ -1,53 +1,147 @@
|
|
|
1
1
|
import "@dxos/node-std/globals";
|
|
2
|
-
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
3
|
-
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
4
|
-
}) : x)(function(x) {
|
|
5
|
-
if (typeof require !== "undefined")
|
|
6
|
-
return require.apply(this, arguments);
|
|
7
|
-
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
8
|
-
});
|
|
9
|
-
|
|
10
|
-
// inject-globals:@inject-globals
|
|
11
2
|
import {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
3
|
+
FunctionDef,
|
|
4
|
+
FunctionManifestSchema,
|
|
5
|
+
FunctionTrigger,
|
|
6
|
+
__require
|
|
7
|
+
} from "./chunk-366QG6IX.mjs";
|
|
16
8
|
|
|
17
|
-
// packages/core/functions/src/
|
|
18
|
-
import {
|
|
9
|
+
// packages/core/functions/src/function/function-registry.ts
|
|
10
|
+
import { Event } from "@dxos/async";
|
|
11
|
+
import { create, Filter } from "@dxos/client/echo";
|
|
12
|
+
import { Resource } from "@dxos/context";
|
|
13
|
+
import { PublicKey } from "@dxos/keys";
|
|
19
14
|
import { log } from "@dxos/log";
|
|
15
|
+
import { ComplexMap } from "@dxos/util";
|
|
16
|
+
|
|
17
|
+
// packages/core/functions/src/util.ts
|
|
18
|
+
var diff = (previous, next, comparator) => {
|
|
19
|
+
const remaining = [
|
|
20
|
+
...previous
|
|
21
|
+
];
|
|
22
|
+
const result = {
|
|
23
|
+
added: [],
|
|
24
|
+
updated: [],
|
|
25
|
+
removed: remaining
|
|
26
|
+
};
|
|
27
|
+
for (const object of next) {
|
|
28
|
+
const index = remaining.findIndex((item) => comparator(item, object));
|
|
29
|
+
if (index === -1) {
|
|
30
|
+
result.added.push(object);
|
|
31
|
+
} else {
|
|
32
|
+
result.updated.push(remaining[index]);
|
|
33
|
+
remaining.splice(index, 1);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return result;
|
|
37
|
+
};
|
|
38
|
+
var intersection = (a, b, comparator) => a.filter((a2) => b.find((b2) => comparator(a2, b2)) !== void 0);
|
|
39
|
+
|
|
40
|
+
// packages/core/functions/src/function/function-registry.ts
|
|
41
|
+
var __dxlog_file = "/home/runner/work/dxos/dxos/packages/core/functions/src/function/function-registry.ts";
|
|
42
|
+
var FunctionRegistry = class extends Resource {
|
|
43
|
+
constructor(_client) {
|
|
44
|
+
super();
|
|
45
|
+
this._client = _client;
|
|
46
|
+
this._functionBySpaceKey = new ComplexMap(PublicKey.hash);
|
|
47
|
+
this.registered = new Event();
|
|
48
|
+
}
|
|
49
|
+
getFunctions(space) {
|
|
50
|
+
return this._functionBySpaceKey.get(space.key) ?? [];
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Loads function definitions from the manifest into the space.
|
|
54
|
+
* We first load all the definitions from the space to deduplicate by functionId.
|
|
55
|
+
*/
|
|
56
|
+
async register(space, functions) {
|
|
57
|
+
log("register", {
|
|
58
|
+
space: space.key,
|
|
59
|
+
functions: functions?.length ?? 0
|
|
60
|
+
}, {
|
|
61
|
+
F: __dxlog_file,
|
|
62
|
+
L: 39,
|
|
63
|
+
S: this,
|
|
64
|
+
C: (f, a) => f(...a)
|
|
65
|
+
});
|
|
66
|
+
if (!functions?.length) {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
if (!space.db.graph.runtimeSchemaRegistry.hasSchema(FunctionDef)) {
|
|
70
|
+
space.db.graph.runtimeSchemaRegistry.registerSchema(FunctionDef);
|
|
71
|
+
}
|
|
72
|
+
const { objects: existing } = await space.db.query(Filter.schema(FunctionDef)).run();
|
|
73
|
+
const { added, removed } = diff(existing, functions, (a, b) => a.uri === b.uri);
|
|
74
|
+
added.forEach((def) => space.db.add(create(FunctionDef, def)));
|
|
75
|
+
removed.forEach((def) => space.db.remove(def));
|
|
76
|
+
}
|
|
77
|
+
async _open() {
|
|
78
|
+
const spacesSubscription = this._client.spaces.subscribe(async (spaces) => {
|
|
79
|
+
for (const space of spaces) {
|
|
80
|
+
if (this._functionBySpaceKey.has(space.key)) {
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
const registered = [];
|
|
84
|
+
this._functionBySpaceKey.set(space.key, registered);
|
|
85
|
+
await space.waitUntilReady();
|
|
86
|
+
if (this._ctx.disposed) {
|
|
87
|
+
break;
|
|
88
|
+
}
|
|
89
|
+
this._ctx.onDispose(space.db.query(Filter.schema(FunctionDef)).subscribe(({ objects }) => {
|
|
90
|
+
const { added } = diff(registered, objects, (a, b) => a.uri === b.uri);
|
|
91
|
+
if (added.length > 0) {
|
|
92
|
+
registered.push(...added);
|
|
93
|
+
this.registered.emit({
|
|
94
|
+
space,
|
|
95
|
+
added
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
}));
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
this._ctx.onDispose(() => spacesSubscription.unsubscribe());
|
|
102
|
+
}
|
|
103
|
+
async _close(_) {
|
|
104
|
+
this._functionBySpaceKey.clear();
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
// packages/core/functions/src/handler.ts
|
|
109
|
+
import { PublicKey as PublicKey2 } from "@dxos/client";
|
|
110
|
+
import { log as log2 } from "@dxos/log";
|
|
20
111
|
import { nonNullable } from "@dxos/util";
|
|
21
|
-
var
|
|
112
|
+
var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/core/functions/src/handler.ts";
|
|
22
113
|
var subscriptionHandler = (handler) => {
|
|
23
|
-
return ({ event, context, ...rest }) => {
|
|
114
|
+
return ({ event: { data }, context, ...rest }) => {
|
|
24
115
|
const { client } = context;
|
|
25
|
-
const space =
|
|
26
|
-
const objects = space
|
|
27
|
-
if (!!
|
|
28
|
-
|
|
29
|
-
|
|
116
|
+
const space = data.spaceKey ? client.spaces.get(PublicKey2.from(data.spaceKey)) : void 0;
|
|
117
|
+
const objects = space ? data.objects?.map((id) => space.db.getObjectById(id)).filter(nonNullable) : [];
|
|
118
|
+
if (!!data.spaceKey && !space) {
|
|
119
|
+
log2.warn("invalid space", {
|
|
120
|
+
data
|
|
30
121
|
}, {
|
|
31
|
-
F:
|
|
32
|
-
L:
|
|
122
|
+
F: __dxlog_file2,
|
|
123
|
+
L: 91,
|
|
33
124
|
S: void 0,
|
|
34
125
|
C: (f, a) => f(...a)
|
|
35
126
|
});
|
|
36
127
|
} else {
|
|
37
|
-
|
|
128
|
+
log2.info("handler", {
|
|
38
129
|
space: space?.key.truncate(),
|
|
39
130
|
objects: objects?.length
|
|
40
131
|
}, {
|
|
41
|
-
F:
|
|
42
|
-
L:
|
|
132
|
+
F: __dxlog_file2,
|
|
133
|
+
L: 93,
|
|
43
134
|
S: void 0,
|
|
44
135
|
C: (f, a) => f(...a)
|
|
45
136
|
});
|
|
46
137
|
}
|
|
47
138
|
return handler({
|
|
48
139
|
event: {
|
|
49
|
-
|
|
50
|
-
|
|
140
|
+
data: {
|
|
141
|
+
...data,
|
|
142
|
+
space,
|
|
143
|
+
objects
|
|
144
|
+
}
|
|
51
145
|
},
|
|
52
146
|
context,
|
|
53
147
|
...rest
|
|
@@ -59,18 +153,32 @@ var subscriptionHandler = (handler) => {
|
|
|
59
153
|
import express from "express";
|
|
60
154
|
import { getPort } from "get-port-please";
|
|
61
155
|
import { join } from "@dxos/node-std/path";
|
|
62
|
-
import { Event, Trigger } from "@dxos/async";
|
|
156
|
+
import { Event as Event2, Trigger } from "@dxos/async";
|
|
157
|
+
import { Context } from "@dxos/context";
|
|
63
158
|
import { invariant } from "@dxos/invariant";
|
|
64
|
-
import { log as
|
|
65
|
-
var
|
|
159
|
+
import { log as log3 } from "@dxos/log";
|
|
160
|
+
var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/core/functions/src/runtime/dev-server.ts";
|
|
66
161
|
var DevServer = class {
|
|
67
|
-
|
|
68
|
-
constructor(_client, _options) {
|
|
162
|
+
constructor(_client, _functionsRegistry, _options) {
|
|
69
163
|
this._client = _client;
|
|
164
|
+
this._functionsRegistry = _functionsRegistry;
|
|
70
165
|
this._options = _options;
|
|
166
|
+
this._ctx = createContext();
|
|
71
167
|
this._handlers = {};
|
|
72
168
|
this._seq = 0;
|
|
73
|
-
this.update = new
|
|
169
|
+
this.update = new Event2();
|
|
170
|
+
this._functionsRegistry.registered.on(async ({ added }) => {
|
|
171
|
+
added.forEach((def) => this._load(def));
|
|
172
|
+
await this._safeUpdateRegistration();
|
|
173
|
+
log3("new functions loaded", {
|
|
174
|
+
added
|
|
175
|
+
}, {
|
|
176
|
+
F: __dxlog_file3,
|
|
177
|
+
L: 52,
|
|
178
|
+
S: this,
|
|
179
|
+
C: (f, a) => f(...a)
|
|
180
|
+
});
|
|
181
|
+
});
|
|
74
182
|
}
|
|
75
183
|
get stats() {
|
|
76
184
|
return {
|
|
@@ -79,8 +187,8 @@ var DevServer = class {
|
|
|
79
187
|
}
|
|
80
188
|
get endpoint() {
|
|
81
189
|
invariant(this._port, void 0, {
|
|
82
|
-
F:
|
|
83
|
-
L:
|
|
190
|
+
F: __dxlog_file3,
|
|
191
|
+
L: 63,
|
|
84
192
|
S: this,
|
|
85
193
|
A: [
|
|
86
194
|
"this._port",
|
|
@@ -95,45 +203,32 @@ var DevServer = class {
|
|
|
95
203
|
get functions() {
|
|
96
204
|
return Object.values(this._handlers);
|
|
97
205
|
}
|
|
98
|
-
async initialize() {
|
|
99
|
-
for (const def of this._options.manifest.functions) {
|
|
100
|
-
try {
|
|
101
|
-
await this._load(def);
|
|
102
|
-
} catch (err) {
|
|
103
|
-
log2.error("parsing function (check manifest)", err, {
|
|
104
|
-
F: __dxlog_file2,
|
|
105
|
-
L: 71,
|
|
106
|
-
S: this,
|
|
107
|
-
C: (f, a) => f(...a)
|
|
108
|
-
});
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
206
|
async start() {
|
|
113
207
|
invariant(!this._server, void 0, {
|
|
114
|
-
F:
|
|
115
|
-
L:
|
|
208
|
+
F: __dxlog_file3,
|
|
209
|
+
L: 76,
|
|
116
210
|
S: this,
|
|
117
211
|
A: [
|
|
118
212
|
"!this._server",
|
|
119
213
|
""
|
|
120
214
|
]
|
|
121
215
|
});
|
|
122
|
-
|
|
123
|
-
F:
|
|
124
|
-
L:
|
|
216
|
+
log3.info("starting...", void 0, {
|
|
217
|
+
F: __dxlog_file3,
|
|
218
|
+
L: 77,
|
|
125
219
|
S: this,
|
|
126
220
|
C: (f, a) => f(...a)
|
|
127
221
|
});
|
|
222
|
+
this._ctx = createContext();
|
|
128
223
|
const app = express();
|
|
129
224
|
app.use(express.json());
|
|
130
225
|
app.post("/:path", async (req, res) => {
|
|
131
226
|
const { path: path2 } = req.params;
|
|
132
227
|
try {
|
|
133
|
-
|
|
228
|
+
log3.info("calling", {
|
|
134
229
|
path: path2
|
|
135
230
|
}, {
|
|
136
|
-
F:
|
|
231
|
+
F: __dxlog_file3,
|
|
137
232
|
L: 87,
|
|
138
233
|
S: this,
|
|
139
234
|
C: (f, a) => f(...a)
|
|
@@ -145,8 +240,8 @@ var DevServer = class {
|
|
|
145
240
|
res.statusCode = await this.invoke("/" + path2, req.body);
|
|
146
241
|
res.end();
|
|
147
242
|
} catch (err) {
|
|
148
|
-
|
|
149
|
-
F:
|
|
243
|
+
log3.catch(err, void 0, {
|
|
244
|
+
F: __dxlog_file3,
|
|
150
245
|
L: 97,
|
|
151
246
|
S: this,
|
|
152
247
|
C: (f, a) => f(...a)
|
|
@@ -166,64 +261,61 @@ var DevServer = class {
|
|
|
166
261
|
this._server = app.listen(this._port);
|
|
167
262
|
try {
|
|
168
263
|
const { registrationId, endpoint } = await this._client.services.services.FunctionRegistryService.register({
|
|
169
|
-
endpoint: this.endpoint
|
|
170
|
-
functions: this.functions.map(({ def: { id, path: path2 } }) => ({
|
|
171
|
-
id,
|
|
172
|
-
path: path2
|
|
173
|
-
}))
|
|
264
|
+
endpoint: this.endpoint
|
|
174
265
|
});
|
|
175
|
-
|
|
266
|
+
log3.info("registered", {
|
|
176
267
|
endpoint
|
|
177
268
|
}, {
|
|
178
|
-
F:
|
|
179
|
-
L:
|
|
269
|
+
F: __dxlog_file3,
|
|
270
|
+
L: 112,
|
|
180
271
|
S: this,
|
|
181
272
|
C: (f, a) => f(...a)
|
|
182
273
|
});
|
|
183
274
|
this._proxy = endpoint;
|
|
184
275
|
this._functionServiceRegistration = registrationId;
|
|
276
|
+
await this._functionsRegistry.open(this._ctx);
|
|
185
277
|
} catch (err) {
|
|
186
278
|
await this.stop();
|
|
187
279
|
throw new Error("FunctionRegistryService not available (check plugin is configured).");
|
|
188
280
|
}
|
|
189
|
-
|
|
281
|
+
log3.info("started", {
|
|
190
282
|
port: this._port
|
|
191
283
|
}, {
|
|
192
|
-
F:
|
|
193
|
-
L:
|
|
284
|
+
F: __dxlog_file3,
|
|
285
|
+
L: 123,
|
|
194
286
|
S: this,
|
|
195
287
|
C: (f, a) => f(...a)
|
|
196
288
|
});
|
|
197
289
|
}
|
|
198
290
|
async stop() {
|
|
199
291
|
invariant(this._server, void 0, {
|
|
200
|
-
F:
|
|
201
|
-
L:
|
|
292
|
+
F: __dxlog_file3,
|
|
293
|
+
L: 127,
|
|
202
294
|
S: this,
|
|
203
295
|
A: [
|
|
204
296
|
"this._server",
|
|
205
297
|
""
|
|
206
298
|
]
|
|
207
299
|
});
|
|
208
|
-
|
|
209
|
-
F:
|
|
210
|
-
L:
|
|
300
|
+
log3.info("stopping...", void 0, {
|
|
301
|
+
F: __dxlog_file3,
|
|
302
|
+
L: 128,
|
|
211
303
|
S: this,
|
|
212
304
|
C: (f, a) => f(...a)
|
|
213
305
|
});
|
|
214
306
|
const trigger = new Trigger();
|
|
215
307
|
this._server.close(async () => {
|
|
216
|
-
|
|
217
|
-
F:
|
|
218
|
-
L:
|
|
308
|
+
log3.info("server stopped", void 0, {
|
|
309
|
+
F: __dxlog_file3,
|
|
310
|
+
L: 132,
|
|
219
311
|
S: this,
|
|
220
312
|
C: (f, a) => f(...a)
|
|
221
313
|
});
|
|
222
314
|
try {
|
|
223
315
|
if (this._functionServiceRegistration) {
|
|
224
316
|
invariant(this._client.services.services.FunctionRegistryService, void 0, {
|
|
225
|
-
F:
|
|
226
|
-
L:
|
|
317
|
+
F: __dxlog_file3,
|
|
318
|
+
L: 135,
|
|
227
319
|
S: this,
|
|
228
320
|
A: [
|
|
229
321
|
"this._client.services.services.FunctionRegistryService",
|
|
@@ -233,11 +325,11 @@ var DevServer = class {
|
|
|
233
325
|
await this._client.services.services.FunctionRegistryService.unregister({
|
|
234
326
|
registrationId: this._functionServiceRegistration
|
|
235
327
|
});
|
|
236
|
-
|
|
328
|
+
log3.info("unregistered", {
|
|
237
329
|
registrationId: this._functionServiceRegistration
|
|
238
330
|
}, {
|
|
239
|
-
F:
|
|
240
|
-
L:
|
|
331
|
+
F: __dxlog_file3,
|
|
332
|
+
L: 140,
|
|
241
333
|
S: this,
|
|
242
334
|
C: (f, a) => f(...a)
|
|
243
335
|
});
|
|
@@ -252,9 +344,9 @@ var DevServer = class {
|
|
|
252
344
|
await trigger.wait();
|
|
253
345
|
this._port = void 0;
|
|
254
346
|
this._server = void 0;
|
|
255
|
-
|
|
256
|
-
F:
|
|
257
|
-
L:
|
|
347
|
+
log3.info("stopped", void 0, {
|
|
348
|
+
F: __dxlog_file3,
|
|
349
|
+
L: 154,
|
|
258
350
|
S: this,
|
|
259
351
|
C: (f, a) => f(...a)
|
|
260
352
|
});
|
|
@@ -262,15 +354,15 @@ var DevServer = class {
|
|
|
262
354
|
/**
|
|
263
355
|
* Load function.
|
|
264
356
|
*/
|
|
265
|
-
async _load(def, force
|
|
266
|
-
const {
|
|
357
|
+
async _load(def, force) {
|
|
358
|
+
const { uri, route, handler } = def;
|
|
267
359
|
const filePath = join(this._options.baseDir, handler);
|
|
268
|
-
|
|
269
|
-
|
|
360
|
+
log3.info("loading", {
|
|
361
|
+
uri,
|
|
270
362
|
force
|
|
271
363
|
}, {
|
|
272
|
-
F:
|
|
273
|
-
L:
|
|
364
|
+
F: __dxlog_file3,
|
|
365
|
+
L: 163,
|
|
274
366
|
S: this,
|
|
275
367
|
C: (f, a) => f(...a)
|
|
276
368
|
});
|
|
@@ -281,37 +373,66 @@ var DevServer = class {
|
|
|
281
373
|
}
|
|
282
374
|
const module = __require(filePath);
|
|
283
375
|
if (typeof module.default !== "function") {
|
|
284
|
-
throw new Error(`Handler must export default function: ${
|
|
376
|
+
throw new Error(`Handler must export default function: ${uri}`);
|
|
285
377
|
}
|
|
286
|
-
this._handlers[
|
|
378
|
+
this._handlers[route] = {
|
|
287
379
|
def,
|
|
288
380
|
handler: module.default
|
|
289
381
|
};
|
|
290
382
|
}
|
|
383
|
+
async _safeUpdateRegistration() {
|
|
384
|
+
invariant(this._functionServiceRegistration, void 0, {
|
|
385
|
+
F: __dxlog_file3,
|
|
386
|
+
L: 185,
|
|
387
|
+
S: this,
|
|
388
|
+
A: [
|
|
389
|
+
"this._functionServiceRegistration",
|
|
390
|
+
""
|
|
391
|
+
]
|
|
392
|
+
});
|
|
393
|
+
try {
|
|
394
|
+
await this._client.services.services.FunctionRegistryService.updateRegistration({
|
|
395
|
+
registrationId: this._functionServiceRegistration,
|
|
396
|
+
functions: this.functions.map(({ def: { id, route } }) => ({
|
|
397
|
+
id,
|
|
398
|
+
route
|
|
399
|
+
}))
|
|
400
|
+
});
|
|
401
|
+
} catch (e) {
|
|
402
|
+
log3.catch(e, void 0, {
|
|
403
|
+
F: __dxlog_file3,
|
|
404
|
+
L: 192,
|
|
405
|
+
S: this,
|
|
406
|
+
C: (f, a) => f(...a)
|
|
407
|
+
});
|
|
408
|
+
}
|
|
409
|
+
}
|
|
291
410
|
/**
|
|
292
411
|
* Invoke function.
|
|
293
412
|
*/
|
|
294
413
|
async invoke(path2, data) {
|
|
295
414
|
const seq = ++this._seq;
|
|
296
415
|
const now = Date.now();
|
|
297
|
-
|
|
416
|
+
log3.info("req", {
|
|
298
417
|
seq,
|
|
299
418
|
path: path2
|
|
300
419
|
}, {
|
|
301
|
-
F:
|
|
302
|
-
L:
|
|
420
|
+
F: __dxlog_file3,
|
|
421
|
+
L: 203,
|
|
303
422
|
S: this,
|
|
304
423
|
C: (f, a) => f(...a)
|
|
305
424
|
});
|
|
306
|
-
const statusCode = await this._invoke(path2,
|
|
307
|
-
|
|
425
|
+
const statusCode = await this._invoke(path2, {
|
|
426
|
+
data
|
|
427
|
+
});
|
|
428
|
+
log3.info("res", {
|
|
308
429
|
seq,
|
|
309
430
|
path: path2,
|
|
310
431
|
statusCode,
|
|
311
432
|
duration: Date.now() - now
|
|
312
433
|
}, {
|
|
313
|
-
F:
|
|
314
|
-
L:
|
|
434
|
+
F: __dxlog_file3,
|
|
435
|
+
L: 206,
|
|
315
436
|
S: this,
|
|
316
437
|
C: (f, a) => f(...a)
|
|
317
438
|
});
|
|
@@ -321,8 +442,8 @@ var DevServer = class {
|
|
|
321
442
|
async _invoke(path2, event) {
|
|
322
443
|
const { handler } = this._handlers[path2] ?? {};
|
|
323
444
|
invariant(handler, `invalid path: ${path2}`, {
|
|
324
|
-
F:
|
|
325
|
-
L:
|
|
445
|
+
F: __dxlog_file3,
|
|
446
|
+
L: 213,
|
|
326
447
|
S: this,
|
|
327
448
|
A: [
|
|
328
449
|
"handler",
|
|
@@ -348,123 +469,104 @@ var DevServer = class {
|
|
|
348
469
|
return statusCode;
|
|
349
470
|
}
|
|
350
471
|
};
|
|
472
|
+
var createContext = () => new Context({
|
|
473
|
+
name: "DevServer"
|
|
474
|
+
});
|
|
351
475
|
|
|
352
476
|
// packages/core/functions/src/runtime/scheduler.ts
|
|
353
|
-
import { CronJob } from "cron";
|
|
354
|
-
import { getPort as getPort2 } from "get-port-please";
|
|
355
|
-
import http from "@dxos/node-std/http";
|
|
356
477
|
import path from "@dxos/node-std/path";
|
|
357
|
-
import
|
|
358
|
-
import {
|
|
359
|
-
import {
|
|
360
|
-
|
|
361
|
-
import { Context } from "@dxos/context";
|
|
362
|
-
import { invariant as invariant2 } from "@dxos/invariant";
|
|
363
|
-
import { log as log3 } from "@dxos/log";
|
|
364
|
-
import { ComplexMap } from "@dxos/util";
|
|
365
|
-
var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/core/functions/src/runtime/scheduler.ts";
|
|
478
|
+
import { Mutex } from "@dxos/async";
|
|
479
|
+
import { Context as Context2 } from "@dxos/context";
|
|
480
|
+
import { log as log4 } from "@dxos/log";
|
|
481
|
+
var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/core/functions/src/runtime/scheduler.ts";
|
|
366
482
|
var Scheduler = class {
|
|
367
|
-
constructor(
|
|
368
|
-
this.
|
|
369
|
-
this.
|
|
483
|
+
constructor(functions, triggers, _options = {}) {
|
|
484
|
+
this.functions = functions;
|
|
485
|
+
this.triggers = triggers;
|
|
370
486
|
this._options = _options;
|
|
371
|
-
this.
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
487
|
+
this._ctx = createContext2();
|
|
488
|
+
this._callMutex = new Mutex();
|
|
489
|
+
this.functions.registered.on(async ({ space, added }) => {
|
|
490
|
+
await this._safeActivateTriggers(space, this.triggers.getInactiveTriggers(space), added);
|
|
491
|
+
});
|
|
492
|
+
this.triggers.registered.on(async ({ space, triggers: triggers2 }) => {
|
|
493
|
+
await this._safeActivateTriggers(space, triggers2, this.functions.getFunctions(space));
|
|
494
|
+
});
|
|
378
495
|
}
|
|
379
496
|
async start() {
|
|
380
|
-
this.
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
await this.mount(new Context(), space, trigger);
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
});
|
|
497
|
+
await this._ctx.dispose();
|
|
498
|
+
this._ctx = createContext2();
|
|
499
|
+
await this.functions.open(this._ctx);
|
|
500
|
+
await this.triggers.open(this._ctx);
|
|
388
501
|
}
|
|
389
502
|
async stop() {
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
503
|
+
await this._ctx.dispose();
|
|
504
|
+
await this.functions.close();
|
|
505
|
+
await this.triggers.close();
|
|
393
506
|
}
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
const def = this._manifest.functions.find((config) => config.id === trigger.function);
|
|
403
|
-
invariant2(def, `Function not found: ${trigger.function}`, {
|
|
404
|
-
F: __dxlog_file3,
|
|
405
|
-
L: 83,
|
|
406
|
-
S: this,
|
|
407
|
-
A: [
|
|
408
|
-
"def",
|
|
409
|
-
"`Function not found: ${trigger.function}`"
|
|
410
|
-
]
|
|
507
|
+
// TODO(burdon): Remove and update registries directly.
|
|
508
|
+
async register(space, manifest) {
|
|
509
|
+
await this.functions.register(space, manifest.functions);
|
|
510
|
+
await this.triggers.register(space, manifest);
|
|
511
|
+
}
|
|
512
|
+
async _safeActivateTriggers(space, triggers, functions) {
|
|
513
|
+
const mountTasks = triggers.map((trigger) => {
|
|
514
|
+
return this.activate(space, functions, trigger);
|
|
411
515
|
});
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
space: space.key,
|
|
420
|
-
trigger
|
|
516
|
+
await Promise.all(mountTasks).catch(log4.catch);
|
|
517
|
+
}
|
|
518
|
+
async activate(space, functions, fnTrigger) {
|
|
519
|
+
const definition = functions.find((def) => def.uri === fnTrigger.function);
|
|
520
|
+
if (!definition) {
|
|
521
|
+
log4.info("function is not found for trigger", {
|
|
522
|
+
fnTrigger
|
|
421
523
|
}, {
|
|
422
|
-
F:
|
|
423
|
-
L:
|
|
524
|
+
F: __dxlog_file4,
|
|
525
|
+
L: 78,
|
|
424
526
|
S: this,
|
|
425
527
|
C: (f, a) => f(...a)
|
|
426
528
|
});
|
|
427
|
-
|
|
428
|
-
return;
|
|
429
|
-
}
|
|
430
|
-
if (trigger.timer) {
|
|
431
|
-
await this._createTimer(ctx, space, def, trigger.timer);
|
|
432
|
-
}
|
|
433
|
-
if (trigger.webhook) {
|
|
434
|
-
await this._createWebhook(ctx, space, def, trigger.webhook);
|
|
435
|
-
}
|
|
436
|
-
if (trigger.websocket) {
|
|
437
|
-
await this._createWebsocket(ctx, space, def, trigger.websocket);
|
|
438
|
-
}
|
|
439
|
-
if (trigger.subscription) {
|
|
440
|
-
await this._createSubscription(ctx, space, def, trigger.subscription);
|
|
441
|
-
}
|
|
442
|
-
}
|
|
443
|
-
}
|
|
444
|
-
async unmount(id, spaceKey) {
|
|
445
|
-
const key = {
|
|
446
|
-
id,
|
|
447
|
-
spaceKey
|
|
448
|
-
};
|
|
449
|
-
const { ctx } = this._mounts.get(key) ?? {};
|
|
450
|
-
if (ctx) {
|
|
451
|
-
this._mounts.delete(key);
|
|
452
|
-
await ctx.dispose();
|
|
529
|
+
return;
|
|
453
530
|
}
|
|
531
|
+
await this.triggers.activate({
|
|
532
|
+
space
|
|
533
|
+
}, fnTrigger, async (args) => {
|
|
534
|
+
return this._callMutex.executeSynchronized(() => {
|
|
535
|
+
return this._execFunction(definition, fnTrigger, {
|
|
536
|
+
meta: fnTrigger.meta,
|
|
537
|
+
data: {
|
|
538
|
+
...args,
|
|
539
|
+
spaceKey: space.key
|
|
540
|
+
}
|
|
541
|
+
});
|
|
542
|
+
});
|
|
543
|
+
});
|
|
544
|
+
log4("activated trigger", {
|
|
545
|
+
space: space.key,
|
|
546
|
+
trigger: fnTrigger
|
|
547
|
+
}, {
|
|
548
|
+
F: __dxlog_file4,
|
|
549
|
+
L: 91,
|
|
550
|
+
S: this,
|
|
551
|
+
C: (f, a) => f(...a)
|
|
552
|
+
});
|
|
454
553
|
}
|
|
455
|
-
|
|
456
|
-
|
|
554
|
+
async _execFunction(def, trigger, { data, meta }) {
|
|
555
|
+
let status = 0;
|
|
457
556
|
try {
|
|
458
|
-
|
|
557
|
+
const payload = Object.assign({}, meta && {
|
|
558
|
+
meta
|
|
559
|
+
}, data);
|
|
459
560
|
const { endpoint, callback } = this._options;
|
|
460
561
|
if (endpoint) {
|
|
461
|
-
const url = path.join(endpoint, def.
|
|
462
|
-
|
|
463
|
-
function: def.
|
|
464
|
-
url
|
|
562
|
+
const url = path.join(endpoint, def.route);
|
|
563
|
+
log4.info("exec", {
|
|
564
|
+
function: def.uri,
|
|
565
|
+
url,
|
|
566
|
+
triggerType: trigger.spec.type
|
|
465
567
|
}, {
|
|
466
|
-
F:
|
|
467
|
-
L:
|
|
568
|
+
F: __dxlog_file4,
|
|
569
|
+
L: 108,
|
|
468
570
|
S: this,
|
|
469
571
|
C: (f, a) => f(...a)
|
|
470
572
|
});
|
|
@@ -473,360 +575,480 @@ var Scheduler = class {
|
|
|
473
575
|
headers: {
|
|
474
576
|
"Content-Type": "application/json"
|
|
475
577
|
},
|
|
476
|
-
body: JSON.stringify(
|
|
578
|
+
body: JSON.stringify(payload)
|
|
477
579
|
});
|
|
478
580
|
status = response.status;
|
|
479
581
|
} else if (callback) {
|
|
480
|
-
|
|
481
|
-
function: def.
|
|
582
|
+
log4.info("exec", {
|
|
583
|
+
function: def.uri
|
|
482
584
|
}, {
|
|
483
|
-
F:
|
|
484
|
-
L:
|
|
585
|
+
F: __dxlog_file4,
|
|
586
|
+
L: 119,
|
|
485
587
|
S: this,
|
|
486
588
|
C: (f, a) => f(...a)
|
|
487
589
|
});
|
|
488
|
-
status = await callback(
|
|
590
|
+
status = await callback(payload) ?? 200;
|
|
489
591
|
}
|
|
490
592
|
if (status && status >= 400) {
|
|
491
593
|
throw new Error(`Response: ${status}`);
|
|
492
594
|
}
|
|
493
|
-
|
|
494
|
-
function: def.
|
|
595
|
+
log4.info("done", {
|
|
596
|
+
function: def.uri,
|
|
495
597
|
status
|
|
496
598
|
}, {
|
|
497
|
-
F:
|
|
498
|
-
L:
|
|
599
|
+
F: __dxlog_file4,
|
|
600
|
+
L: 129,
|
|
499
601
|
S: this,
|
|
500
602
|
C: (f, a) => f(...a)
|
|
501
603
|
});
|
|
502
|
-
return status;
|
|
503
604
|
} catch (err) {
|
|
504
|
-
|
|
505
|
-
function: def.
|
|
605
|
+
log4.error("error", {
|
|
606
|
+
function: def.uri,
|
|
506
607
|
error: err.message
|
|
507
608
|
}, {
|
|
508
|
-
F:
|
|
509
|
-
L:
|
|
609
|
+
F: __dxlog_file4,
|
|
610
|
+
L: 131,
|
|
510
611
|
S: this,
|
|
511
612
|
C: (f, a) => f(...a)
|
|
512
613
|
});
|
|
513
|
-
|
|
614
|
+
status = 500;
|
|
514
615
|
}
|
|
616
|
+
return status;
|
|
515
617
|
}
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
618
|
+
};
|
|
619
|
+
var createContext2 = () => new Context2({
|
|
620
|
+
name: "FunctionScheduler"
|
|
621
|
+
});
|
|
622
|
+
|
|
623
|
+
// packages/core/functions/src/trigger/trigger-registry.ts
|
|
624
|
+
import { Event as Event3 } from "@dxos/async";
|
|
625
|
+
import { create as create2, Filter as Filter3, getMeta } from "@dxos/client/echo";
|
|
626
|
+
import { Context as Context3, Resource as Resource2 } from "@dxos/context";
|
|
627
|
+
import { ECHO_ATTR_META, foreignKey, foreignKeyEquals, splitMeta } from "@dxos/echo-schema";
|
|
628
|
+
import { invariant as invariant2 } from "@dxos/invariant";
|
|
629
|
+
import { PublicKey as PublicKey3 } from "@dxos/keys";
|
|
630
|
+
import { log as log9 } from "@dxos/log";
|
|
631
|
+
import { ComplexMap as ComplexMap2 } from "@dxos/util";
|
|
632
|
+
|
|
633
|
+
// packages/core/functions/src/trigger/type/subscription-trigger.ts
|
|
634
|
+
import { TextV0Type } from "@braneframe/types";
|
|
635
|
+
import { debounce, UpdateScheduler } from "@dxos/async";
|
|
636
|
+
import { createSubscription, Filter as Filter2, getAutomergeObjectCore } from "@dxos/echo-db";
|
|
637
|
+
import { log as log5 } from "@dxos/log";
|
|
638
|
+
var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/core/functions/src/trigger/type/subscription-trigger.ts";
|
|
639
|
+
var createSubscriptionTrigger = async (ctx, triggerCtx, spec, callback) => {
|
|
640
|
+
const objectIds = /* @__PURE__ */ new Set();
|
|
641
|
+
const task = new UpdateScheduler(ctx, async () => {
|
|
642
|
+
if (objectIds.size > 0) {
|
|
643
|
+
const objects = Array.from(objectIds);
|
|
644
|
+
objectIds.clear();
|
|
645
|
+
await callback({
|
|
646
|
+
objects
|
|
647
|
+
});
|
|
648
|
+
}
|
|
649
|
+
}, {
|
|
650
|
+
maxFrequency: 4
|
|
651
|
+
});
|
|
652
|
+
const subscriptions = [];
|
|
653
|
+
const subscription = createSubscription(({ added, updated }) => {
|
|
654
|
+
const sizeBefore = objectIds.size;
|
|
655
|
+
for (const object of added) {
|
|
656
|
+
objectIds.add(object.id);
|
|
657
|
+
}
|
|
658
|
+
for (const object of updated) {
|
|
659
|
+
objectIds.add(object.id);
|
|
660
|
+
}
|
|
661
|
+
if (objectIds.size > sizeBefore) {
|
|
662
|
+
log5.info("updated", {
|
|
663
|
+
added: added.length,
|
|
664
|
+
updated: updated.length
|
|
665
|
+
}, {
|
|
666
|
+
F: __dxlog_file5,
|
|
667
|
+
L: 45,
|
|
668
|
+
S: void 0,
|
|
669
|
+
C: (f, a) => f(...a)
|
|
670
|
+
});
|
|
671
|
+
task.trigger();
|
|
672
|
+
}
|
|
673
|
+
});
|
|
674
|
+
subscriptions.push(() => subscription.unsubscribe());
|
|
675
|
+
const { filter, options: { deep, delay } = {} } = spec;
|
|
676
|
+
const update = ({ objects }) => {
|
|
677
|
+
subscription.update(objects);
|
|
678
|
+
if (deep) {
|
|
679
|
+
log5.info("update", {
|
|
680
|
+
objects: objects.length
|
|
681
|
+
}, {
|
|
682
|
+
F: __dxlog_file5,
|
|
683
|
+
L: 59,
|
|
684
|
+
S: void 0,
|
|
685
|
+
C: (f, a) => f(...a)
|
|
686
|
+
});
|
|
687
|
+
for (const object of objects) {
|
|
688
|
+
const content = object.content;
|
|
689
|
+
if (content instanceof TextV0Type) {
|
|
690
|
+
subscriptions.push(getAutomergeObjectCore(content).updates.on(debounce(() => subscription.update([
|
|
691
|
+
object
|
|
692
|
+
]), 1e3)));
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
};
|
|
697
|
+
const query = triggerCtx.space.db.query(Filter2.or(filter.map(({ type, props }) => Filter2.typename(type, props))));
|
|
698
|
+
subscriptions.push(query.subscribe(delay ? debounce(update, delay) : update));
|
|
699
|
+
ctx.onDispose(() => {
|
|
700
|
+
subscriptions.forEach((unsubscribe) => unsubscribe());
|
|
701
|
+
});
|
|
702
|
+
};
|
|
703
|
+
|
|
704
|
+
// packages/core/functions/src/trigger/type/timer-trigger.ts
|
|
705
|
+
import { CronJob } from "cron";
|
|
706
|
+
import { DeferredTask } from "@dxos/async";
|
|
707
|
+
import { log as log6 } from "@dxos/log";
|
|
708
|
+
var __dxlog_file6 = "/home/runner/work/dxos/dxos/packages/core/functions/src/trigger/type/timer-trigger.ts";
|
|
709
|
+
var createTimerTrigger = async (ctx, triggerContext, spec, callback) => {
|
|
710
|
+
const task = new DeferredTask(ctx, async () => {
|
|
711
|
+
await callback({});
|
|
712
|
+
});
|
|
713
|
+
let last = 0;
|
|
714
|
+
let run = 0;
|
|
715
|
+
const job = CronJob.from({
|
|
716
|
+
cronTime: spec.cron,
|
|
717
|
+
runOnInit: false,
|
|
718
|
+
onTick: () => {
|
|
719
|
+
const now = Date.now();
|
|
720
|
+
const delta = last ? now - last : 0;
|
|
721
|
+
last = now;
|
|
722
|
+
run++;
|
|
723
|
+
log6.info("tick", {
|
|
724
|
+
space: triggerContext.space.key.truncate(),
|
|
725
|
+
count: run,
|
|
726
|
+
delta
|
|
727
|
+
}, {
|
|
728
|
+
F: __dxlog_file6,
|
|
729
|
+
L: 37,
|
|
730
|
+
S: void 0,
|
|
731
|
+
C: (f, a) => f(...a)
|
|
732
|
+
});
|
|
733
|
+
task.schedule();
|
|
734
|
+
}
|
|
735
|
+
});
|
|
736
|
+
job.start();
|
|
737
|
+
ctx.onDispose(() => job.stop());
|
|
738
|
+
};
|
|
739
|
+
|
|
740
|
+
// packages/core/functions/src/trigger/type/webhook-trigger.ts
|
|
741
|
+
import { getPort as getPort2 } from "get-port-please";
|
|
742
|
+
import http from "@dxos/node-std/http";
|
|
743
|
+
import { log as log7 } from "@dxos/log";
|
|
744
|
+
var __dxlog_file7 = "/home/runner/work/dxos/dxos/packages/core/functions/src/trigger/type/webhook-trigger.ts";
|
|
745
|
+
var createWebhookTrigger = async (ctx, _, spec, callback) => {
|
|
746
|
+
const server = http.createServer(async (req, res) => {
|
|
747
|
+
if (req.method !== spec.method) {
|
|
748
|
+
res.statusCode = 405;
|
|
749
|
+
return res.end();
|
|
750
|
+
}
|
|
751
|
+
res.statusCode = await callback({});
|
|
752
|
+
res.end();
|
|
753
|
+
});
|
|
754
|
+
const port = await getPort2({
|
|
755
|
+
random: true
|
|
756
|
+
});
|
|
757
|
+
server.listen(port, () => {
|
|
758
|
+
log7.info("started webhook", {
|
|
759
|
+
port
|
|
526
760
|
}, {
|
|
527
|
-
F:
|
|
528
|
-
L:
|
|
529
|
-
S:
|
|
761
|
+
F: __dxlog_file7,
|
|
762
|
+
L: 40,
|
|
763
|
+
S: void 0,
|
|
530
764
|
C: (f, a) => f(...a)
|
|
531
765
|
});
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
766
|
+
spec.port = port;
|
|
767
|
+
});
|
|
768
|
+
ctx.onDispose(() => {
|
|
769
|
+
server.close();
|
|
770
|
+
});
|
|
771
|
+
};
|
|
772
|
+
|
|
773
|
+
// packages/core/functions/src/trigger/type/websocket-trigger.ts
|
|
774
|
+
import WebSocket from "ws";
|
|
775
|
+
import { sleep, Trigger as Trigger2 } from "@dxos/async";
|
|
776
|
+
import { log as log8 } from "@dxos/log";
|
|
777
|
+
var __dxlog_file8 = "/home/runner/work/dxos/dxos/packages/core/functions/src/trigger/type/websocket-trigger.ts";
|
|
778
|
+
var createWebsocketTrigger = async (ctx, triggerCtx, spec, callback, options = {
|
|
779
|
+
retryDelay: 2,
|
|
780
|
+
maxAttempts: 5
|
|
781
|
+
}) => {
|
|
782
|
+
const { url, init } = spec;
|
|
783
|
+
let ws;
|
|
784
|
+
for (let attempt = 1; attempt <= options.maxAttempts; attempt++) {
|
|
785
|
+
const open = new Trigger2();
|
|
786
|
+
ws = new WebSocket(url);
|
|
787
|
+
Object.assign(ws, {
|
|
788
|
+
onopen: () => {
|
|
789
|
+
log8.info("opened", {
|
|
790
|
+
url
|
|
552
791
|
}, {
|
|
553
|
-
F:
|
|
554
|
-
L:
|
|
555
|
-
S:
|
|
792
|
+
F: __dxlog_file8,
|
|
793
|
+
L: 39,
|
|
794
|
+
S: void 0,
|
|
795
|
+
C: (f, a) => f(...a)
|
|
796
|
+
});
|
|
797
|
+
if (spec.init) {
|
|
798
|
+
ws.send(new TextEncoder().encode(JSON.stringify(init)));
|
|
799
|
+
}
|
|
800
|
+
open.wake(true);
|
|
801
|
+
},
|
|
802
|
+
onclose: (event) => {
|
|
803
|
+
log8.info("closed", {
|
|
804
|
+
url,
|
|
805
|
+
code: event.code
|
|
806
|
+
}, {
|
|
807
|
+
F: __dxlog_file8,
|
|
808
|
+
L: 48,
|
|
809
|
+
S: void 0,
|
|
810
|
+
C: (f, a) => f(...a)
|
|
811
|
+
});
|
|
812
|
+
if (event.code === 1006) {
|
|
813
|
+
setTimeout(async () => {
|
|
814
|
+
log8.info(`reconnecting in ${options.retryDelay}s...`, {
|
|
815
|
+
url
|
|
816
|
+
}, {
|
|
817
|
+
F: __dxlog_file8,
|
|
818
|
+
L: 53,
|
|
819
|
+
S: void 0,
|
|
820
|
+
C: (f, a) => f(...a)
|
|
821
|
+
});
|
|
822
|
+
await createWebsocketTrigger(ctx, triggerCtx, spec, callback, options);
|
|
823
|
+
}, options.retryDelay * 1e3);
|
|
824
|
+
}
|
|
825
|
+
open.wake(false);
|
|
826
|
+
},
|
|
827
|
+
onerror: (event) => {
|
|
828
|
+
log8.catch(event.error, {
|
|
829
|
+
url
|
|
830
|
+
}, {
|
|
831
|
+
F: __dxlog_file8,
|
|
832
|
+
L: 62,
|
|
833
|
+
S: void 0,
|
|
556
834
|
C: (f, a) => f(...a)
|
|
557
835
|
});
|
|
558
|
-
|
|
836
|
+
},
|
|
837
|
+
onmessage: async (event) => {
|
|
838
|
+
try {
|
|
839
|
+
log8.info("message", void 0, {
|
|
840
|
+
F: __dxlog_file8,
|
|
841
|
+
L: 67,
|
|
842
|
+
S: void 0,
|
|
843
|
+
C: (f, a) => f(...a)
|
|
844
|
+
});
|
|
845
|
+
const data = JSON.parse(new TextDecoder().decode(event.data));
|
|
846
|
+
await callback({
|
|
847
|
+
data
|
|
848
|
+
});
|
|
849
|
+
} catch (err) {
|
|
850
|
+
log8.catch(err, {
|
|
851
|
+
url
|
|
852
|
+
}, {
|
|
853
|
+
F: __dxlog_file8,
|
|
854
|
+
L: 71,
|
|
855
|
+
S: void 0,
|
|
856
|
+
C: (f, a) => f(...a)
|
|
857
|
+
});
|
|
858
|
+
}
|
|
559
859
|
}
|
|
560
860
|
});
|
|
561
|
-
|
|
562
|
-
|
|
861
|
+
const isOpen = await open.wait();
|
|
862
|
+
if (isOpen) {
|
|
863
|
+
break;
|
|
864
|
+
} else {
|
|
865
|
+
const wait = Math.pow(attempt, 2) * options.retryDelay;
|
|
866
|
+
if (attempt < options.maxAttempts) {
|
|
867
|
+
log8.warn(`failed to connect; trying again in ${wait}s`, {
|
|
868
|
+
attempt
|
|
869
|
+
}, {
|
|
870
|
+
F: __dxlog_file8,
|
|
871
|
+
L: 82,
|
|
872
|
+
S: void 0,
|
|
873
|
+
C: (f, a) => f(...a)
|
|
874
|
+
});
|
|
875
|
+
await sleep(wait * 1e3);
|
|
876
|
+
}
|
|
877
|
+
}
|
|
563
878
|
}
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
879
|
+
ctx.onDispose(() => {
|
|
880
|
+
ws?.close();
|
|
881
|
+
});
|
|
882
|
+
};
|
|
883
|
+
|
|
884
|
+
// packages/core/functions/src/trigger/trigger-registry.ts
|
|
885
|
+
var __dxlog_file9 = "/home/runner/work/dxos/dxos/packages/core/functions/src/trigger/trigger-registry.ts";
|
|
886
|
+
var triggerHandlers = {
|
|
887
|
+
subscription: createSubscriptionTrigger,
|
|
888
|
+
timer: createTimerTrigger,
|
|
889
|
+
webhook: createWebhookTrigger,
|
|
890
|
+
websocket: createWebsocketTrigger
|
|
891
|
+
};
|
|
892
|
+
var TriggerRegistry = class extends Resource2 {
|
|
893
|
+
constructor(_client, _options) {
|
|
894
|
+
super();
|
|
895
|
+
this._client = _client;
|
|
896
|
+
this._options = _options;
|
|
897
|
+
this._triggersBySpaceKey = new ComplexMap2(PublicKey3.hash);
|
|
898
|
+
this.registered = new Event3();
|
|
899
|
+
this.removed = new Event3();
|
|
900
|
+
}
|
|
901
|
+
getActiveTriggers(space) {
|
|
902
|
+
return this._getTriggers(space, (t) => t.activationCtx != null);
|
|
903
|
+
}
|
|
904
|
+
getInactiveTriggers(space) {
|
|
905
|
+
return this._getTriggers(space, (t) => t.activationCtx == null);
|
|
906
|
+
}
|
|
907
|
+
async activate(triggerCtx, trigger, callback) {
|
|
908
|
+
log9("activate", {
|
|
909
|
+
space: triggerCtx.space.key,
|
|
570
910
|
trigger
|
|
571
911
|
}, {
|
|
572
|
-
F:
|
|
573
|
-
L:
|
|
912
|
+
F: __dxlog_file9,
|
|
913
|
+
L: 75,
|
|
574
914
|
S: this,
|
|
575
915
|
C: (f, a) => f(...a)
|
|
576
916
|
});
|
|
577
|
-
const
|
|
578
|
-
|
|
579
|
-
res.statusCode = 405;
|
|
580
|
-
return res.end();
|
|
581
|
-
}
|
|
582
|
-
res.statusCode = await this._execFunction(def, {
|
|
583
|
-
spaceKey: space.key
|
|
584
|
-
});
|
|
585
|
-
res.end();
|
|
586
|
-
});
|
|
587
|
-
const port = await getPort2({
|
|
588
|
-
random: true
|
|
917
|
+
const activationCtx = new Context3({
|
|
918
|
+
name: `trigger_${trigger.function}`
|
|
589
919
|
});
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
});
|
|
601
|
-
ctx.onDispose(() => {
|
|
602
|
-
server.close();
|
|
920
|
+
this._ctx.onDispose(() => activationCtx.dispose());
|
|
921
|
+
const registeredTrigger = this._triggersBySpaceKey.get(triggerCtx.space.key)?.find((reg) => reg.trigger.id === trigger.id);
|
|
922
|
+
invariant2(registeredTrigger, `Trigger is not registered: ${trigger.function}`, {
|
|
923
|
+
F: __dxlog_file9,
|
|
924
|
+
L: 81,
|
|
925
|
+
S: this,
|
|
926
|
+
A: [
|
|
927
|
+
"registeredTrigger",
|
|
928
|
+
"`Trigger is not registered: ${trigger.function}`"
|
|
929
|
+
]
|
|
603
930
|
});
|
|
931
|
+
registeredTrigger.activationCtx = activationCtx;
|
|
932
|
+
try {
|
|
933
|
+
const options = this._options?.[trigger.spec.type];
|
|
934
|
+
await triggerHandlers[trigger.spec.type](activationCtx, triggerCtx, trigger.spec, callback, options);
|
|
935
|
+
} catch (err) {
|
|
936
|
+
delete registeredTrigger.activationCtx;
|
|
937
|
+
throw err;
|
|
938
|
+
}
|
|
604
939
|
}
|
|
605
940
|
/**
|
|
606
|
-
*
|
|
607
|
-
* NOTE: The port must be unique, so the same hook cannot be used for multiple spaces.
|
|
941
|
+
* Loads triggers from the manifest into the space.
|
|
608
942
|
*/
|
|
609
|
-
async
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
}) {
|
|
613
|
-
log3.info("websocket", {
|
|
614
|
-
space: space.key,
|
|
615
|
-
trigger
|
|
943
|
+
async register(space, manifest) {
|
|
944
|
+
log9("register", {
|
|
945
|
+
space: space.key
|
|
616
946
|
}, {
|
|
617
|
-
F:
|
|
618
|
-
L:
|
|
947
|
+
F: __dxlog_file9,
|
|
948
|
+
L: 97,
|
|
619
949
|
S: this,
|
|
620
950
|
C: (f, a) => f(...a)
|
|
621
951
|
});
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
L: 272,
|
|
650
|
-
S: this,
|
|
651
|
-
C: (f, a) => f(...a)
|
|
652
|
-
});
|
|
653
|
-
open.wake(false);
|
|
654
|
-
},
|
|
655
|
-
onerror: (event) => {
|
|
656
|
-
log3.catch(event.error, {
|
|
657
|
-
url
|
|
658
|
-
}, {
|
|
659
|
-
F: __dxlog_file3,
|
|
660
|
-
L: 277,
|
|
661
|
-
S: this,
|
|
662
|
-
C: (f, a) => f(...a)
|
|
663
|
-
});
|
|
664
|
-
},
|
|
665
|
-
onmessage: async (event) => {
|
|
666
|
-
try {
|
|
667
|
-
const data = JSON.parse(new TextDecoder().decode(event.data));
|
|
668
|
-
await this._execFunction(def, {
|
|
669
|
-
spaceKey: space.key,
|
|
670
|
-
data
|
|
671
|
-
});
|
|
672
|
-
} catch (err) {
|
|
673
|
-
log3.catch(err, {
|
|
674
|
-
url
|
|
675
|
-
}, {
|
|
676
|
-
F: __dxlog_file3,
|
|
677
|
-
L: 285,
|
|
678
|
-
S: this,
|
|
679
|
-
C: (f, a) => f(...a)
|
|
680
|
-
});
|
|
681
|
-
}
|
|
952
|
+
if (!manifest.triggers?.length) {
|
|
953
|
+
return;
|
|
954
|
+
}
|
|
955
|
+
if (!space.db.graph.runtimeSchemaRegistry.hasSchema(FunctionTrigger)) {
|
|
956
|
+
space.db.graph.runtimeSchemaRegistry.registerSchema(FunctionTrigger);
|
|
957
|
+
}
|
|
958
|
+
const { objects: existing } = await space.db.query(Filter3.schema(FunctionTrigger)).run();
|
|
959
|
+
const { added, removed } = diff(existing, manifest.triggers, (a, b) => {
|
|
960
|
+
const keys = b[ECHO_ATTR_META]?.keys ?? [
|
|
961
|
+
foreignKey("manifest", [
|
|
962
|
+
b.function,
|
|
963
|
+
b.spec.type
|
|
964
|
+
].join("-"))
|
|
965
|
+
];
|
|
966
|
+
return intersection(getMeta(a)?.keys ?? [], keys, foreignKeyEquals).length > 0;
|
|
967
|
+
});
|
|
968
|
+
added.forEach((trigger) => {
|
|
969
|
+
const { meta, object } = splitMeta(trigger);
|
|
970
|
+
space.db.add(create2(FunctionTrigger, object, meta));
|
|
971
|
+
});
|
|
972
|
+
removed.forEach((trigger) => space.db.remove(trigger));
|
|
973
|
+
}
|
|
974
|
+
async _open() {
|
|
975
|
+
const spaceListSubscription = this._client.spaces.subscribe(async (spaces) => {
|
|
976
|
+
for (const space of spaces) {
|
|
977
|
+
if (this._triggersBySpaceKey.has(space.key)) {
|
|
978
|
+
continue;
|
|
682
979
|
}
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
const wait = Math.pow(attempt, 2) * options.retryDelay;
|
|
689
|
-
if (attempt < options.maxAttempts) {
|
|
690
|
-
log3.warn(`failed to connect; trying again in ${wait}s`, {
|
|
691
|
-
attempt
|
|
692
|
-
}, {
|
|
693
|
-
F: __dxlog_file3,
|
|
694
|
-
L: 296,
|
|
695
|
-
S: this,
|
|
696
|
-
C: (f, a) => f(...a)
|
|
697
|
-
});
|
|
698
|
-
await sleep(wait * 1e3);
|
|
980
|
+
const registered = [];
|
|
981
|
+
this._triggersBySpaceKey.set(space.key, registered);
|
|
982
|
+
await space.waitUntilReady();
|
|
983
|
+
if (this._ctx.disposed) {
|
|
984
|
+
break;
|
|
699
985
|
}
|
|
986
|
+
const functionsSubscription = space.db.query(Filter3.schema(FunctionTrigger)).subscribe(async (triggers) => {
|
|
987
|
+
await this._handleRemovedTriggers(space, triggers.objects, registered);
|
|
988
|
+
this._handleNewTriggers(space, triggers.objects, registered);
|
|
989
|
+
});
|
|
990
|
+
this._ctx.onDispose(functionsSubscription);
|
|
700
991
|
}
|
|
701
|
-
}
|
|
702
|
-
ctx.onDispose(() => {
|
|
703
|
-
ws?.close();
|
|
704
992
|
});
|
|
993
|
+
this._ctx.onDispose(() => spaceListSubscription.unsubscribe());
|
|
705
994
|
}
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
trigger
|
|
713
|
-
}, {
|
|
714
|
-
F: __dxlog_file3,
|
|
715
|
-
L: 311,
|
|
716
|
-
S: this,
|
|
717
|
-
C: (f, a) => f(...a)
|
|
995
|
+
async _close(_) {
|
|
996
|
+
this._triggersBySpaceKey.clear();
|
|
997
|
+
}
|
|
998
|
+
_handleNewTriggers(space, allTriggers, registered) {
|
|
999
|
+
const newTriggers = allTriggers.filter((candidate) => {
|
|
1000
|
+
return registered.find((reg) => reg.trigger.id === candidate.id) == null;
|
|
718
1001
|
});
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
1002
|
+
if (newTriggers.length > 0) {
|
|
1003
|
+
const newRegisteredTriggers = newTriggers.map((trigger) => ({
|
|
1004
|
+
trigger
|
|
1005
|
+
}));
|
|
1006
|
+
registered.push(...newRegisteredTriggers);
|
|
1007
|
+
log9("registered new triggers", () => ({
|
|
722
1008
|
spaceKey: space.key,
|
|
723
|
-
|
|
724
|
-
})
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
const subscription = createSubscription(({ added, updated }) => {
|
|
728
|
-
log3.info("updated", {
|
|
729
|
-
added: added.length,
|
|
730
|
-
updated: updated.length
|
|
731
|
-
}, {
|
|
732
|
-
F: __dxlog_file3,
|
|
733
|
-
L: 321,
|
|
1009
|
+
functions: newTriggers.map((t) => t.function)
|
|
1010
|
+
}), {
|
|
1011
|
+
F: __dxlog_file9,
|
|
1012
|
+
L: 159,
|
|
734
1013
|
S: this,
|
|
735
1014
|
C: (f, a) => f(...a)
|
|
736
1015
|
});
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
objects: objects.length
|
|
752
|
-
}, {
|
|
753
|
-
F: __dxlog_file3,
|
|
754
|
-
L: 342,
|
|
755
|
-
S: this,
|
|
756
|
-
C: (f, a) => f(...a)
|
|
757
|
-
});
|
|
758
|
-
for (const object of objects) {
|
|
759
|
-
const content = object.content;
|
|
760
|
-
if (content instanceof TextV0Type) {
|
|
761
|
-
subscriptions.push(getAutomergeObjectCore(content).updates.on(debounce(() => subscription.update([
|
|
762
|
-
object
|
|
763
|
-
]), 1e3)));
|
|
764
|
-
}
|
|
765
|
-
}
|
|
1016
|
+
this.registered.emit({
|
|
1017
|
+
space,
|
|
1018
|
+
triggers: newTriggers
|
|
1019
|
+
});
|
|
1020
|
+
}
|
|
1021
|
+
}
|
|
1022
|
+
async _handleRemovedTriggers(space, allTriggers, registered) {
|
|
1023
|
+
const removed = [];
|
|
1024
|
+
for (let i = registered.length - 1; i >= 0; i--) {
|
|
1025
|
+
const wasRemoved = allTriggers.find((trigger) => trigger.id === registered[i].trigger.id) == null;
|
|
1026
|
+
if (wasRemoved) {
|
|
1027
|
+
const unregistered = registered.splice(i, 1)[0];
|
|
1028
|
+
await unregistered.activationCtx?.dispose();
|
|
1029
|
+
removed.push(unregistered.trigger);
|
|
766
1030
|
}
|
|
767
|
-
}
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
1031
|
+
}
|
|
1032
|
+
if (removed.length > 0) {
|
|
1033
|
+
this.removed.emit({
|
|
1034
|
+
space,
|
|
1035
|
+
triggers: removed
|
|
1036
|
+
});
|
|
1037
|
+
}
|
|
1038
|
+
}
|
|
1039
|
+
_getTriggers(space, predicate) {
|
|
1040
|
+
const allSpaceTriggers = this._triggersBySpaceKey.get(space.key) ?? [];
|
|
1041
|
+
return allSpaceTriggers.filter(predicate).map((trigger) => trigger.trigger);
|
|
773
1042
|
}
|
|
774
1043
|
};
|
|
775
|
-
|
|
776
|
-
// packages/core/functions/src/types.ts
|
|
777
|
-
import * as S from "@effect/schema/Schema";
|
|
778
|
-
var TimerTriggerSchema = S.struct({
|
|
779
|
-
cron: S.string
|
|
780
|
-
});
|
|
781
|
-
var WebhookTriggerSchema = S.mutable(S.struct({
|
|
782
|
-
method: S.string,
|
|
783
|
-
// Assigned port.
|
|
784
|
-
port: S.optional(S.number)
|
|
785
|
-
}));
|
|
786
|
-
var WebsocketTriggerSchema = S.struct({
|
|
787
|
-
url: S.string,
|
|
788
|
-
init: S.optional(S.record(S.string, S.any))
|
|
789
|
-
});
|
|
790
|
-
var SubscriptionTriggerSchema = S.struct({
|
|
791
|
-
spaceKey: S.optional(S.string),
|
|
792
|
-
// TODO(burdon): Define query DSL.
|
|
793
|
-
filter: S.array(S.struct({
|
|
794
|
-
type: S.string,
|
|
795
|
-
props: S.optional(S.record(S.string, S.any))
|
|
796
|
-
})),
|
|
797
|
-
options: S.optional(S.struct({
|
|
798
|
-
// Watch changes to object (not just creation).
|
|
799
|
-
deep: S.optional(S.boolean),
|
|
800
|
-
// Debounce changes (delay in ms).
|
|
801
|
-
delay: S.optional(S.number)
|
|
802
|
-
}))
|
|
803
|
-
});
|
|
804
|
-
var FunctionTriggerSchema = S.struct({
|
|
805
|
-
function: S.string.pipe(S.description("Function ID/URI.")),
|
|
806
|
-
// Context passed to function.
|
|
807
|
-
context: S.optional(S.record(S.string, S.any)),
|
|
808
|
-
// Triggers.
|
|
809
|
-
timer: S.optional(TimerTriggerSchema),
|
|
810
|
-
webhook: S.optional(WebhookTriggerSchema),
|
|
811
|
-
websocket: S.optional(WebsocketTriggerSchema),
|
|
812
|
-
subscription: S.optional(SubscriptionTriggerSchema)
|
|
813
|
-
});
|
|
814
|
-
var FunctionDefSchema = S.struct({
|
|
815
|
-
id: S.string,
|
|
816
|
-
// name: S.string,
|
|
817
|
-
description: S.optional(S.string),
|
|
818
|
-
path: S.string,
|
|
819
|
-
// TODO(burdon): NPM/GitHub/Docker/CF URL?
|
|
820
|
-
handler: S.string
|
|
821
|
-
});
|
|
822
|
-
var FunctionManifestSchema = S.struct({
|
|
823
|
-
functions: S.mutable(S.array(FunctionDefSchema)),
|
|
824
|
-
triggers: S.optional(S.mutable(S.array(FunctionTriggerSchema)))
|
|
825
|
-
});
|
|
826
1044
|
export {
|
|
827
1045
|
DevServer,
|
|
1046
|
+
FunctionDef,
|
|
828
1047
|
FunctionManifestSchema,
|
|
1048
|
+
FunctionRegistry,
|
|
1049
|
+
FunctionTrigger,
|
|
829
1050
|
Scheduler,
|
|
1051
|
+
TriggerRegistry,
|
|
830
1052
|
subscriptionHandler
|
|
831
1053
|
};
|
|
832
1054
|
//# sourceMappingURL=index.mjs.map
|