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