@dxos/functions 0.5.3-main.6f2dfea → 0.5.3-main.77c09ab
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 +772 -477
- 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 +759 -470
- 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 +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 +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 -111
- 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/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 +42 -25
- package/src/runtime/scheduler.test.ts +59 -75
- package/src/runtime/scheduler.ts +79 -299
- 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 -52
|
@@ -1,53 +1,134 @@
|
|
|
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
|
-
return ({ event, context, ...rest }) => {
|
|
101
|
+
return ({ event: { data }, context, ...rest }) => {
|
|
24
102
|
const { client } = context;
|
|
25
|
-
const space =
|
|
26
|
-
const objects = space
|
|
27
|
-
if (!!
|
|
28
|
-
|
|
29
|
-
|
|
103
|
+
const space = data.spaceKey ? client.spaces.get(PublicKey2.from(data.spaceKey)) : void 0;
|
|
104
|
+
const objects = space ? data.objects?.map((id) => space.db.getObjectById(id)).filter(nonNullable) : [];
|
|
105
|
+
if (!!data.spaceKey && !space) {
|
|
106
|
+
log2.warn("invalid space", {
|
|
107
|
+
data
|
|
30
108
|
}, {
|
|
31
|
-
F:
|
|
32
|
-
L:
|
|
109
|
+
F: __dxlog_file2,
|
|
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:
|
|
42
|
-
L:
|
|
119
|
+
F: __dxlog_file2,
|
|
120
|
+
L: 93,
|
|
43
121
|
S: void 0,
|
|
44
122
|
C: (f, a) => f(...a)
|
|
45
123
|
});
|
|
46
124
|
}
|
|
47
125
|
return handler({
|
|
48
126
|
event: {
|
|
49
|
-
|
|
50
|
-
|
|
127
|
+
data: {
|
|
128
|
+
...data,
|
|
129
|
+
space,
|
|
130
|
+
objects
|
|
131
|
+
}
|
|
51
132
|
},
|
|
52
133
|
context,
|
|
53
134
|
...rest
|
|
@@ -59,18 +140,32 @@ var subscriptionHandler = (handler) => {
|
|
|
59
140
|
import express from "express";
|
|
60
141
|
import { getPort } from "get-port-please";
|
|
61
142
|
import { join } from "@dxos/node-std/path";
|
|
62
|
-
import { Event, Trigger } from "@dxos/async";
|
|
143
|
+
import { Event as Event2, Trigger } from "@dxos/async";
|
|
144
|
+
import { Context } from "@dxos/context";
|
|
63
145
|
import { invariant } from "@dxos/invariant";
|
|
64
|
-
import { log as
|
|
65
|
-
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";
|
|
66
148
|
var DevServer = class {
|
|
67
|
-
|
|
68
|
-
constructor(_client, _options) {
|
|
149
|
+
constructor(_client, _functionsRegistry, _options) {
|
|
69
150
|
this._client = _client;
|
|
151
|
+
this._functionsRegistry = _functionsRegistry;
|
|
70
152
|
this._options = _options;
|
|
153
|
+
this._ctx = createContext();
|
|
71
154
|
this._handlers = {};
|
|
72
155
|
this._seq = 0;
|
|
73
|
-
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
|
+
});
|
|
74
169
|
}
|
|
75
170
|
get stats() {
|
|
76
171
|
return {
|
|
@@ -79,8 +174,8 @@ var DevServer = class {
|
|
|
79
174
|
}
|
|
80
175
|
get endpoint() {
|
|
81
176
|
invariant(this._port, void 0, {
|
|
82
|
-
F:
|
|
83
|
-
L:
|
|
177
|
+
F: __dxlog_file3,
|
|
178
|
+
L: 64,
|
|
84
179
|
S: this,
|
|
85
180
|
A: [
|
|
86
181
|
"this._port",
|
|
@@ -95,23 +190,9 @@ var DevServer = class {
|
|
|
95
190
|
get functions() {
|
|
96
191
|
return Object.values(this._handlers);
|
|
97
192
|
}
|
|
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
193
|
async start() {
|
|
113
194
|
invariant(!this._server, void 0, {
|
|
114
|
-
F:
|
|
195
|
+
F: __dxlog_file3,
|
|
115
196
|
L: 77,
|
|
116
197
|
S: this,
|
|
117
198
|
A: [
|
|
@@ -119,22 +200,23 @@ var DevServer = class {
|
|
|
119
200
|
""
|
|
120
201
|
]
|
|
121
202
|
});
|
|
122
|
-
|
|
123
|
-
F:
|
|
203
|
+
log3.info("starting...", void 0, {
|
|
204
|
+
F: __dxlog_file3,
|
|
124
205
|
L: 78,
|
|
125
206
|
S: this,
|
|
126
207
|
C: (f, a) => f(...a)
|
|
127
208
|
});
|
|
209
|
+
this._ctx = createContext();
|
|
128
210
|
const app = express();
|
|
129
211
|
app.use(express.json());
|
|
130
212
|
app.post("/:path", async (req, res) => {
|
|
131
213
|
const { path: path2 } = req.params;
|
|
132
214
|
try {
|
|
133
|
-
|
|
215
|
+
log3.info("calling", {
|
|
134
216
|
path: path2
|
|
135
217
|
}, {
|
|
136
|
-
F:
|
|
137
|
-
L:
|
|
218
|
+
F: __dxlog_file3,
|
|
219
|
+
L: 88,
|
|
138
220
|
S: this,
|
|
139
221
|
C: (f, a) => f(...a)
|
|
140
222
|
});
|
|
@@ -145,9 +227,9 @@ var DevServer = class {
|
|
|
145
227
|
res.statusCode = await this.invoke("/" + path2, req.body);
|
|
146
228
|
res.end();
|
|
147
229
|
} catch (err) {
|
|
148
|
-
|
|
149
|
-
F:
|
|
150
|
-
L:
|
|
230
|
+
log3.catch(err, void 0, {
|
|
231
|
+
F: __dxlog_file3,
|
|
232
|
+
L: 98,
|
|
151
233
|
S: this,
|
|
152
234
|
C: (f, a) => f(...a)
|
|
153
235
|
});
|
|
@@ -166,64 +248,61 @@ var DevServer = class {
|
|
|
166
248
|
this._server = app.listen(this._port);
|
|
167
249
|
try {
|
|
168
250
|
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
|
-
}))
|
|
251
|
+
endpoint: this.endpoint
|
|
174
252
|
});
|
|
175
|
-
|
|
253
|
+
log3.info("registered", {
|
|
176
254
|
endpoint
|
|
177
255
|
}, {
|
|
178
|
-
F:
|
|
256
|
+
F: __dxlog_file3,
|
|
179
257
|
L: 113,
|
|
180
258
|
S: this,
|
|
181
259
|
C: (f, a) => f(...a)
|
|
182
260
|
});
|
|
183
261
|
this._proxy = endpoint;
|
|
184
262
|
this._functionServiceRegistration = registrationId;
|
|
263
|
+
await this._functionsRegistry.open(this._ctx);
|
|
185
264
|
} catch (err) {
|
|
186
265
|
await this.stop();
|
|
187
266
|
throw new Error("FunctionRegistryService not available (check plugin is configured).");
|
|
188
267
|
}
|
|
189
|
-
|
|
268
|
+
log3.info("started", {
|
|
190
269
|
port: this._port
|
|
191
270
|
}, {
|
|
192
|
-
F:
|
|
193
|
-
L:
|
|
271
|
+
F: __dxlog_file3,
|
|
272
|
+
L: 124,
|
|
194
273
|
S: this,
|
|
195
274
|
C: (f, a) => f(...a)
|
|
196
275
|
});
|
|
197
276
|
}
|
|
198
277
|
async stop() {
|
|
199
278
|
invariant(this._server, void 0, {
|
|
200
|
-
F:
|
|
201
|
-
L:
|
|
279
|
+
F: __dxlog_file3,
|
|
280
|
+
L: 128,
|
|
202
281
|
S: this,
|
|
203
282
|
A: [
|
|
204
283
|
"this._server",
|
|
205
284
|
""
|
|
206
285
|
]
|
|
207
286
|
});
|
|
208
|
-
|
|
209
|
-
F:
|
|
210
|
-
L:
|
|
287
|
+
log3.info("stopping...", void 0, {
|
|
288
|
+
F: __dxlog_file3,
|
|
289
|
+
L: 129,
|
|
211
290
|
S: this,
|
|
212
291
|
C: (f, a) => f(...a)
|
|
213
292
|
});
|
|
214
293
|
const trigger = new Trigger();
|
|
215
294
|
this._server.close(async () => {
|
|
216
|
-
|
|
217
|
-
F:
|
|
218
|
-
L:
|
|
295
|
+
log3.info("server stopped", void 0, {
|
|
296
|
+
F: __dxlog_file3,
|
|
297
|
+
L: 133,
|
|
219
298
|
S: this,
|
|
220
299
|
C: (f, a) => f(...a)
|
|
221
300
|
});
|
|
222
301
|
try {
|
|
223
302
|
if (this._functionServiceRegistration) {
|
|
224
303
|
invariant(this._client.services.services.FunctionRegistryService, void 0, {
|
|
225
|
-
F:
|
|
226
|
-
L:
|
|
304
|
+
F: __dxlog_file3,
|
|
305
|
+
L: 136,
|
|
227
306
|
S: this,
|
|
228
307
|
A: [
|
|
229
308
|
"this._client.services.services.FunctionRegistryService",
|
|
@@ -233,11 +312,11 @@ var DevServer = class {
|
|
|
233
312
|
await this._client.services.services.FunctionRegistryService.unregister({
|
|
234
313
|
registrationId: this._functionServiceRegistration
|
|
235
314
|
});
|
|
236
|
-
|
|
315
|
+
log3.info("unregistered", {
|
|
237
316
|
registrationId: this._functionServiceRegistration
|
|
238
317
|
}, {
|
|
239
|
-
F:
|
|
240
|
-
L:
|
|
318
|
+
F: __dxlog_file3,
|
|
319
|
+
L: 141,
|
|
241
320
|
S: this,
|
|
242
321
|
C: (f, a) => f(...a)
|
|
243
322
|
});
|
|
@@ -252,9 +331,9 @@ var DevServer = class {
|
|
|
252
331
|
await trigger.wait();
|
|
253
332
|
this._port = void 0;
|
|
254
333
|
this._server = void 0;
|
|
255
|
-
|
|
256
|
-
F:
|
|
257
|
-
L:
|
|
334
|
+
log3.info("stopped", void 0, {
|
|
335
|
+
F: __dxlog_file3,
|
|
336
|
+
L: 155,
|
|
258
337
|
S: this,
|
|
259
338
|
C: (f, a) => f(...a)
|
|
260
339
|
});
|
|
@@ -262,15 +341,15 @@ var DevServer = class {
|
|
|
262
341
|
/**
|
|
263
342
|
* Load function.
|
|
264
343
|
*/
|
|
265
|
-
async _load(def, force
|
|
266
|
-
const {
|
|
344
|
+
async _load(def, force) {
|
|
345
|
+
const { uri, route, handler } = def;
|
|
267
346
|
const filePath = join(this._options.baseDir, handler);
|
|
268
|
-
|
|
269
|
-
|
|
347
|
+
log3.info("loading", {
|
|
348
|
+
uri,
|
|
270
349
|
force
|
|
271
350
|
}, {
|
|
272
|
-
F:
|
|
273
|
-
L:
|
|
351
|
+
F: __dxlog_file3,
|
|
352
|
+
L: 164,
|
|
274
353
|
S: this,
|
|
275
354
|
C: (f, a) => f(...a)
|
|
276
355
|
});
|
|
@@ -281,37 +360,66 @@ var DevServer = class {
|
|
|
281
360
|
}
|
|
282
361
|
const module = __require(filePath);
|
|
283
362
|
if (typeof module.default !== "function") {
|
|
284
|
-
throw new Error(`Handler must export default function: ${
|
|
363
|
+
throw new Error(`Handler must export default function: ${uri}`);
|
|
285
364
|
}
|
|
286
|
-
this._handlers[
|
|
365
|
+
this._handlers[route] = {
|
|
287
366
|
def,
|
|
288
367
|
handler: module.default
|
|
289
368
|
};
|
|
290
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
|
+
}
|
|
291
397
|
/**
|
|
292
398
|
* Invoke function.
|
|
293
399
|
*/
|
|
294
400
|
async invoke(path2, data) {
|
|
295
401
|
const seq = ++this._seq;
|
|
296
402
|
const now = Date.now();
|
|
297
|
-
|
|
403
|
+
log3.info("req", {
|
|
298
404
|
seq,
|
|
299
405
|
path: path2
|
|
300
406
|
}, {
|
|
301
|
-
F:
|
|
302
|
-
L:
|
|
407
|
+
F: __dxlog_file3,
|
|
408
|
+
L: 204,
|
|
303
409
|
S: this,
|
|
304
410
|
C: (f, a) => f(...a)
|
|
305
411
|
});
|
|
306
|
-
const statusCode = await this._invoke(path2,
|
|
307
|
-
|
|
412
|
+
const statusCode = await this._invoke(path2, {
|
|
413
|
+
data
|
|
414
|
+
});
|
|
415
|
+
log3.info("res", {
|
|
308
416
|
seq,
|
|
309
417
|
path: path2,
|
|
310
418
|
statusCode,
|
|
311
419
|
duration: Date.now() - now
|
|
312
420
|
}, {
|
|
313
|
-
F:
|
|
314
|
-
L:
|
|
421
|
+
F: __dxlog_file3,
|
|
422
|
+
L: 207,
|
|
315
423
|
S: this,
|
|
316
424
|
C: (f, a) => f(...a)
|
|
317
425
|
});
|
|
@@ -321,8 +429,8 @@ var DevServer = class {
|
|
|
321
429
|
async _invoke(path2, event) {
|
|
322
430
|
const { handler } = this._handlers[path2] ?? {};
|
|
323
431
|
invariant(handler, `invalid path: ${path2}`, {
|
|
324
|
-
F:
|
|
325
|
-
L:
|
|
432
|
+
F: __dxlog_file3,
|
|
433
|
+
L: 214,
|
|
326
434
|
S: this,
|
|
327
435
|
A: [
|
|
328
436
|
"handler",
|
|
@@ -348,123 +456,120 @@ var DevServer = class {
|
|
|
348
456
|
return statusCode;
|
|
349
457
|
}
|
|
350
458
|
};
|
|
459
|
+
var createContext = () => new Context({
|
|
460
|
+
name: "DevServer"
|
|
461
|
+
});
|
|
351
462
|
|
|
352
463
|
// 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
464
|
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";
|
|
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";
|
|
366
469
|
var Scheduler = class {
|
|
367
|
-
constructor(
|
|
368
|
-
this.
|
|
369
|
-
this.
|
|
470
|
+
constructor(functions, triggers, _options = {}) {
|
|
471
|
+
this.functions = functions;
|
|
472
|
+
this.triggers = triggers;
|
|
370
473
|
this._options = _options;
|
|
371
|
-
this.
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
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
|
+
});
|
|
378
482
|
}
|
|
379
483
|
async start() {
|
|
380
|
-
this.
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
await this.mount(new Context(), space, trigger);
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
});
|
|
484
|
+
await this._ctx.dispose();
|
|
485
|
+
this._ctx = createContext2();
|
|
486
|
+
await this.functions.open(this._ctx);
|
|
487
|
+
await this.triggers.open(this._ctx);
|
|
388
488
|
}
|
|
389
489
|
async stop() {
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
490
|
+
await this._ctx.dispose();
|
|
491
|
+
await this.functions.close();
|
|
492
|
+
await this.triggers.close();
|
|
393
493
|
}
|
|
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
|
-
]
|
|
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);
|
|
411
502
|
});
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
log3("mount", {
|
|
419
|
-
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", {
|
|
420
509
|
trigger
|
|
421
510
|
}, {
|
|
422
|
-
F:
|
|
423
|
-
L:
|
|
511
|
+
F: __dxlog_file4,
|
|
512
|
+
L: 78,
|
|
424
513
|
S: this,
|
|
425
514
|
C: (f, a) => f(...a)
|
|
426
515
|
});
|
|
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();
|
|
516
|
+
return;
|
|
453
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
|
+
});
|
|
454
556
|
}
|
|
455
|
-
|
|
456
|
-
|
|
557
|
+
async _execFunction(def, trigger, { data, meta }) {
|
|
558
|
+
let status = 0;
|
|
457
559
|
try {
|
|
458
|
-
|
|
560
|
+
const payload = Object.assign({}, meta && {
|
|
561
|
+
meta
|
|
562
|
+
}, data);
|
|
459
563
|
const { endpoint, callback } = this._options;
|
|
460
564
|
if (endpoint) {
|
|
461
|
-
const url = path.join(endpoint, def.
|
|
462
|
-
|
|
463
|
-
function: def.
|
|
464
|
-
url
|
|
565
|
+
const url = path.join(endpoint, def.route);
|
|
566
|
+
log4.info("exec", {
|
|
567
|
+
function: def.uri,
|
|
568
|
+
url,
|
|
569
|
+
triggerType: trigger.spec.type
|
|
465
570
|
}, {
|
|
466
|
-
F:
|
|
467
|
-
L:
|
|
571
|
+
F: __dxlog_file4,
|
|
572
|
+
L: 113,
|
|
468
573
|
S: this,
|
|
469
574
|
C: (f, a) => f(...a)
|
|
470
575
|
});
|
|
@@ -473,360 +578,550 @@ var Scheduler = class {
|
|
|
473
578
|
headers: {
|
|
474
579
|
"Content-Type": "application/json"
|
|
475
580
|
},
|
|
476
|
-
body: JSON.stringify(
|
|
581
|
+
body: JSON.stringify(payload)
|
|
477
582
|
});
|
|
478
583
|
status = response.status;
|
|
479
584
|
} else if (callback) {
|
|
480
|
-
|
|
481
|
-
function: def.
|
|
585
|
+
log4.info("exec", {
|
|
586
|
+
function: def.uri
|
|
482
587
|
}, {
|
|
483
|
-
F:
|
|
484
|
-
L:
|
|
588
|
+
F: __dxlog_file4,
|
|
589
|
+
L: 124,
|
|
485
590
|
S: this,
|
|
486
591
|
C: (f, a) => f(...a)
|
|
487
592
|
});
|
|
488
|
-
status = await callback(
|
|
593
|
+
status = await callback(payload) ?? 200;
|
|
489
594
|
}
|
|
490
595
|
if (status && status >= 400) {
|
|
491
596
|
throw new Error(`Response: ${status}`);
|
|
492
597
|
}
|
|
493
|
-
|
|
494
|
-
function: def.
|
|
598
|
+
log4.info("done", {
|
|
599
|
+
function: def.uri,
|
|
495
600
|
status
|
|
496
601
|
}, {
|
|
497
|
-
F:
|
|
498
|
-
L:
|
|
602
|
+
F: __dxlog_file4,
|
|
603
|
+
L: 134,
|
|
499
604
|
S: this,
|
|
500
605
|
C: (f, a) => f(...a)
|
|
501
606
|
});
|
|
502
|
-
return status;
|
|
503
607
|
} catch (err) {
|
|
504
|
-
|
|
505
|
-
function: def.
|
|
608
|
+
log4.error("error", {
|
|
609
|
+
function: def.uri,
|
|
506
610
|
error: err.message
|
|
507
611
|
}, {
|
|
508
|
-
F:
|
|
509
|
-
L:
|
|
612
|
+
F: __dxlog_file4,
|
|
613
|
+
L: 136,
|
|
510
614
|
S: this,
|
|
511
615
|
C: (f, a) => f(...a)
|
|
512
616
|
});
|
|
513
|
-
|
|
617
|
+
status = 500;
|
|
514
618
|
}
|
|
619
|
+
return status;
|
|
515
620
|
}
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
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
|
|
526
683
|
}, {
|
|
527
|
-
F:
|
|
528
|
-
L:
|
|
529
|
-
S:
|
|
684
|
+
F: __dxlog_file5,
|
|
685
|
+
L: 57,
|
|
686
|
+
S: void 0,
|
|
530
687
|
C: (f, a) => f(...a)
|
|
531
688
|
});
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
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)
|
|
536
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)
|
|
537
779
|
});
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
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
|
|
552
805
|
}, {
|
|
553
|
-
F:
|
|
554
|
-
L:
|
|
555
|
-
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,
|
|
556
824
|
C: (f, a) => f(...a)
|
|
557
825
|
});
|
|
558
|
-
|
|
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
|
+
}
|
|
559
873
|
}
|
|
560
874
|
});
|
|
561
|
-
|
|
562
|
-
|
|
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,
|
|
887
|
+
C: (f, a) => f(...a)
|
|
888
|
+
});
|
|
889
|
+
await sleep(wait * 1e3);
|
|
890
|
+
}
|
|
891
|
+
}
|
|
563
892
|
}
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
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", {
|
|
569
923
|
space: space.key,
|
|
570
924
|
trigger
|
|
571
925
|
}, {
|
|
572
|
-
F:
|
|
573
|
-
L:
|
|
926
|
+
F: __dxlog_file9,
|
|
927
|
+
L: 72,
|
|
574
928
|
S: this,
|
|
575
929
|
C: (f, a) => f(...a)
|
|
576
930
|
});
|
|
577
|
-
const
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
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
|
+
]
|
|
944
|
+
});
|
|
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
|
+
}
|
|
953
|
+
}
|
|
954
|
+
/**
|
|
955
|
+
* Loads triggers from the manifest into the space.
|
|
956
|
+
*/
|
|
957
|
+
async register(space, manifest) {
|
|
958
|
+
log9("register", {
|
|
959
|
+
space: space.key
|
|
960
|
+
}, {
|
|
961
|
+
F: __dxlog_file9,
|
|
962
|
+
L: 93,
|
|
963
|
+
S: this,
|
|
964
|
+
C: (f, a) => f(...a)
|
|
965
|
+
});
|
|
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
|
+
];
|
|
581
982
|
}
|
|
582
|
-
|
|
583
|
-
|
|
983
|
+
return create2(FunctionTrigger, trigger, {
|
|
984
|
+
keys
|
|
584
985
|
});
|
|
585
|
-
res.end();
|
|
586
|
-
});
|
|
587
|
-
const port = await getPort2({
|
|
588
|
-
random: true
|
|
589
986
|
});
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
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)
|
|
593
993
|
}, {
|
|
594
|
-
F:
|
|
595
|
-
L:
|
|
994
|
+
F: __dxlog_file9,
|
|
995
|
+
L: 120,
|
|
596
996
|
S: this,
|
|
597
997
|
C: (f, a) => f(...a)
|
|
598
998
|
});
|
|
599
|
-
trigger.port = port;
|
|
600
|
-
});
|
|
601
|
-
ctx.onDispose(() => {
|
|
602
|
-
server.close();
|
|
603
999
|
});
|
|
1000
|
+
if (added.length > 0) {
|
|
1001
|
+
await space.db.flush();
|
|
1002
|
+
}
|
|
604
1003
|
}
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
async _createWebsocket(ctx, space, def, trigger, options = {
|
|
610
|
-
retryDelay: 2,
|
|
611
|
-
maxAttempts: 5
|
|
612
|
-
}) {
|
|
613
|
-
log3.info("websocket", {
|
|
614
|
-
space: space.key,
|
|
615
|
-
trigger
|
|
616
|
-
}, {
|
|
617
|
-
F: __dxlog_file3,
|
|
618
|
-
L: 252,
|
|
1004
|
+
async _open() {
|
|
1005
|
+
log9.info("open...", void 0, {
|
|
1006
|
+
F: __dxlog_file9,
|
|
1007
|
+
L: 129,
|
|
619
1008
|
S: this,
|
|
620
1009
|
C: (f, a) => f(...a)
|
|
621
1010
|
});
|
|
622
|
-
const
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
ws = new WebSocket(url);
|
|
627
|
-
Object.assign(ws, {
|
|
628
|
-
onopen: () => {
|
|
629
|
-
log3.info("opened", {
|
|
630
|
-
url
|
|
631
|
-
}, {
|
|
632
|
-
F: __dxlog_file3,
|
|
633
|
-
L: 262,
|
|
634
|
-
S: this,
|
|
635
|
-
C: (f, a) => f(...a)
|
|
636
|
-
});
|
|
637
|
-
if (trigger.init) {
|
|
638
|
-
ws.send(new TextEncoder().encode(JSON.stringify(trigger.init)));
|
|
639
|
-
}
|
|
640
|
-
open.wake(true);
|
|
641
|
-
},
|
|
642
|
-
// TODO(burdon): Config retry if server closes?
|
|
643
|
-
onclose: (event) => {
|
|
644
|
-
log3.info("closed", {
|
|
645
|
-
url,
|
|
646
|
-
code: event.code
|
|
647
|
-
}, {
|
|
648
|
-
F: __dxlog_file3,
|
|
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
|
-
}
|
|
1011
|
+
const spaceListSubscription = this._client.spaces.subscribe(async (spaces) => {
|
|
1012
|
+
for (const space of spaces) {
|
|
1013
|
+
if (this._triggersBySpaceKey.has(space.key)) {
|
|
1014
|
+
continue;
|
|
682
1015
|
}
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
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
|
|
692
1027
|
}, {
|
|
693
|
-
F:
|
|
694
|
-
L:
|
|
1028
|
+
F: __dxlog_file9,
|
|
1029
|
+
L: 146,
|
|
695
1030
|
S: this,
|
|
696
1031
|
C: (f, a) => f(...a)
|
|
697
1032
|
});
|
|
698
|
-
await
|
|
699
|
-
|
|
1033
|
+
await this._handleRemovedTriggers(space, current, registered);
|
|
1034
|
+
this._handleNewTriggers(space, current, registered);
|
|
1035
|
+
}));
|
|
700
1036
|
}
|
|
701
|
-
}
|
|
702
|
-
|
|
703
|
-
|
|
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)
|
|
704
1044
|
});
|
|
705
1045
|
}
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
log3.info("subscription", {
|
|
711
|
-
space: space.key,
|
|
712
|
-
trigger
|
|
713
|
-
}, {
|
|
714
|
-
F: __dxlog_file3,
|
|
715
|
-
L: 311,
|
|
1046
|
+
async _close(_) {
|
|
1047
|
+
log9.info("close...", void 0, {
|
|
1048
|
+
F: __dxlog_file9,
|
|
1049
|
+
L: 159,
|
|
716
1050
|
S: this,
|
|
717
1051
|
C: (f, a) => f(...a)
|
|
718
1052
|
});
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
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)
|
|
725
1059
|
});
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
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,
|
|
734
1076
|
S: this,
|
|
735
1077
|
C: (f, a) => f(...a)
|
|
736
1078
|
});
|
|
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
|
-
}
|
|
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);
|
|
766
1093
|
}
|
|
767
|
-
}
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
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);
|
|
773
1114
|
}
|
|
774
1115
|
};
|
|
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
1116
|
export {
|
|
827
1117
|
DevServer,
|
|
1118
|
+
FUNCTION_SCHEMA,
|
|
1119
|
+
FunctionDef,
|
|
828
1120
|
FunctionManifestSchema,
|
|
1121
|
+
FunctionRegistry,
|
|
1122
|
+
FunctionTrigger,
|
|
829
1123
|
Scheduler,
|
|
1124
|
+
TriggerRegistry,
|
|
830
1125
|
subscriptionHandler
|
|
831
1126
|
};
|
|
832
1127
|
//# sourceMappingURL=index.mjs.map
|