@dxos/functions 0.5.3-main.6e12b97 → 0.5.3-main.6f2dfea
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/browser/index.mjs +422 -663
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node/index.cjs +419 -648
- package/dist/lib/node/index.cjs.map +4 -4
- package/dist/lib/node/meta.json +1 -1
- package/dist/types/src/handler.d.ts +12 -32
- package/dist/types/src/handler.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +0 -2
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/runtime/dev-server.d.ts +10 -7
- package/dist/types/src/runtime/dev-server.d.ts.map +1 -1
- package/dist/types/src/runtime/scheduler.d.ts +59 -10
- package/dist/types/src/runtime/scheduler.d.ts.map +1 -1
- package/dist/types/src/testing/test/handler.d.ts +0 -1
- package/dist/types/src/testing/test/handler.d.ts.map +1 -1
- package/dist/types/src/types.d.ts +112 -118
- package/dist/types/src/types.d.ts.map +1 -1
- package/package.json +13 -16
- package/schema/functions.json +103 -122
- package/src/handler.ts +27 -50
- package/src/index.ts +0 -2
- package/src/runtime/dev-server.test.ts +35 -15
- package/src/runtime/dev-server.ts +22 -40
- package/src/runtime/scheduler.test.ts +75 -54
- package/src/runtime/scheduler.ts +300 -67
- package/src/testing/test/handler.ts +2 -8
- package/src/types.ts +40 -56
- package/dist/types/src/registry/function-registry.d.ts +0 -24
- package/dist/types/src/registry/function-registry.d.ts.map +0 -1
- package/dist/types/src/registry/function-registry.test.d.ts +0 -2
- package/dist/types/src/registry/function-registry.test.d.ts.map +0 -1
- package/dist/types/src/registry/index.d.ts +0 -2
- package/dist/types/src/registry/index.d.ts.map +0 -1
- package/dist/types/src/testing/functions-integration.test.d.ts +0 -2
- package/dist/types/src/testing/functions-integration.test.d.ts.map +0 -1
- package/dist/types/src/testing/index.d.ts +0 -4
- package/dist/types/src/testing/index.d.ts.map +0 -1
- package/dist/types/src/testing/setup.d.ts +0 -5
- package/dist/types/src/testing/setup.d.ts.map +0 -1
- package/dist/types/src/testing/types.d.ts +0 -9
- package/dist/types/src/testing/types.d.ts.map +0 -1
- package/dist/types/src/testing/util.d.ts +0 -3
- package/dist/types/src/testing/util.d.ts.map +0 -1
- package/dist/types/src/trigger/index.d.ts +0 -2
- package/dist/types/src/trigger/index.d.ts.map +0 -1
- package/dist/types/src/trigger/trigger-registry.d.ts +0 -40
- package/dist/types/src/trigger/trigger-registry.d.ts.map +0 -1
- package/dist/types/src/trigger/trigger-registry.test.d.ts +0 -2
- package/dist/types/src/trigger/trigger-registry.test.d.ts.map +0 -1
- package/dist/types/src/trigger/type/index.d.ts +0 -5
- package/dist/types/src/trigger/type/index.d.ts.map +0 -1
- package/dist/types/src/trigger/type/subscription-trigger.d.ts +0 -4
- package/dist/types/src/trigger/type/subscription-trigger.d.ts.map +0 -1
- package/dist/types/src/trigger/type/timer-trigger.d.ts +0 -4
- package/dist/types/src/trigger/type/timer-trigger.d.ts.map +0 -1
- package/dist/types/src/trigger/type/webhook-trigger.d.ts +0 -4
- package/dist/types/src/trigger/type/webhook-trigger.d.ts.map +0 -1
- package/dist/types/src/trigger/type/websocket-trigger.d.ts +0 -13
- package/dist/types/src/trigger/type/websocket-trigger.d.ts.map +0 -1
- package/src/registry/function-registry.test.ts +0 -105
- package/src/registry/function-registry.ts +0 -84
- package/src/registry/index.ts +0 -5
- package/src/testing/functions-integration.test.ts +0 -99
- package/src/testing/index.ts +0 -7
- package/src/testing/setup.ts +0 -45
- package/src/testing/types.ts +0 -9
- package/src/testing/util.ts +0 -16
- package/src/trigger/index.ts +0 -5
- package/src/trigger/trigger-registry.test.ts +0 -229
- package/src/trigger/trigger-registry.ts +0 -176
- package/src/trigger/type/index.ts +0 -8
- package/src/trigger/type/subscription-trigger.ts +0 -73
- package/src/trigger/type/timer-trigger.ts +0 -44
- package/src/trigger/type/webhook-trigger.ts +0 -47
- package/src/trigger/type/websocket-trigger.ts +0 -91
package/src/handler.ts
CHANGED
|
@@ -8,61 +8,38 @@ import { type EchoReactiveObject } from '@dxos/echo-schema';
|
|
|
8
8
|
import { log } from '@dxos/log';
|
|
9
9
|
import { nonNullable } from '@dxos/util';
|
|
10
10
|
|
|
11
|
-
//
|
|
12
|
-
// https://docs.aws.amazon.com/lambda/latest/dg/typescript-handler.html
|
|
11
|
+
// Lambda-like function definitions.
|
|
13
12
|
// https://www.serverless.com/framework/docs/providers/aws/guide/serverless.yml/#functions
|
|
14
13
|
// https://www.npmjs.com/package/aws-lambda
|
|
14
|
+
// https://docs.aws.amazon.com/lambda/latest/dg/typescript-handler.html
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
context: FunctionContext;
|
|
21
|
-
event: FunctionEvent<TData, TMeta>;
|
|
22
|
-
response: FunctionResponse;
|
|
23
|
-
}) => Promise<FunctionResponse | void>;
|
|
16
|
+
// TODO(burdon): No response?
|
|
17
|
+
export interface Response {
|
|
18
|
+
status(code: number): Response;
|
|
19
|
+
}
|
|
24
20
|
|
|
25
|
-
/**
|
|
26
|
-
* Function context.
|
|
27
|
-
*/
|
|
28
21
|
export interface FunctionContext {
|
|
29
22
|
// TODO(burdon): Limit access to individual space.
|
|
30
23
|
client: Client;
|
|
31
24
|
// TODO(burdon): Replace with storage service abstraction.
|
|
32
25
|
dataDir?: string;
|
|
26
|
+
// Data passed to function invocation.
|
|
27
|
+
data?: any;
|
|
33
28
|
}
|
|
34
29
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Metadata from trigger.
|
|
44
|
-
*/
|
|
45
|
-
export type FunctionEventMeta<TMeta = {}> = {
|
|
46
|
-
meta: TMeta;
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Function response.
|
|
51
|
-
*/
|
|
52
|
-
export interface FunctionResponse {
|
|
53
|
-
status(code: number): FunctionResponse;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
//
|
|
57
|
-
// Subscription utils.
|
|
58
|
-
//
|
|
30
|
+
// TODO(burdon): Model after http request. Ref Lambda/OpenFaaS.
|
|
31
|
+
export type FunctionHandler<T extends {}> = (params: {
|
|
32
|
+
event: T;
|
|
33
|
+
context: FunctionContext;
|
|
34
|
+
response: Response;
|
|
35
|
+
}) => Promise<Response | void>;
|
|
59
36
|
|
|
60
|
-
export type
|
|
37
|
+
export type RawSubscriptionEvent = {
|
|
61
38
|
spaceKey?: string;
|
|
62
39
|
objects?: string[];
|
|
63
40
|
};
|
|
64
41
|
|
|
65
|
-
export type
|
|
42
|
+
export type SubscriptionEvent = {
|
|
66
43
|
space?: Space;
|
|
67
44
|
objects?: EchoReactiveObject<any>[];
|
|
68
45
|
};
|
|
@@ -77,22 +54,22 @@ export type SubscriptionData = {
|
|
|
77
54
|
*
|
|
78
55
|
* NOTE: Get space key from devtools or `dx space list --json`
|
|
79
56
|
*/
|
|
80
|
-
export const subscriptionHandler =
|
|
81
|
-
handler: FunctionHandler<
|
|
82
|
-
): FunctionHandler<
|
|
83
|
-
return ({ event
|
|
57
|
+
export const subscriptionHandler = (
|
|
58
|
+
handler: FunctionHandler<SubscriptionEvent>,
|
|
59
|
+
): FunctionHandler<RawSubscriptionEvent> => {
|
|
60
|
+
return ({ event, context, ...rest }) => {
|
|
84
61
|
const { client } = context;
|
|
85
|
-
const space =
|
|
86
|
-
const objects =
|
|
87
|
-
|
|
88
|
-
|
|
62
|
+
const space = event.spaceKey ? client.spaces.get(PublicKey.from(event.spaceKey)) : undefined;
|
|
63
|
+
const objects =
|
|
64
|
+
space &&
|
|
65
|
+
event.objects?.map<EchoReactiveObject<any> | undefined>((id) => space!.db.getObjectById(id)).filter(nonNullable);
|
|
89
66
|
|
|
90
|
-
if (!!
|
|
91
|
-
log.warn('invalid space', {
|
|
67
|
+
if (!!event.spaceKey && !space) {
|
|
68
|
+
log.warn('invalid space', { event });
|
|
92
69
|
} else {
|
|
93
70
|
log.info('handler', { space: space?.key.truncate(), objects: objects?.length });
|
|
94
71
|
}
|
|
95
72
|
|
|
96
|
-
return handler({ event: {
|
|
73
|
+
return handler({ event: { space, objects }, context, ...rest });
|
|
97
74
|
};
|
|
98
75
|
};
|
package/src/index.ts
CHANGED
|
@@ -5,14 +5,12 @@
|
|
|
5
5
|
import { expect } from 'chai';
|
|
6
6
|
import path from 'path';
|
|
7
7
|
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
8
|
+
import { FunctionsPlugin } from '@dxos/agent';
|
|
9
|
+
import { Client, Config } from '@dxos/client';
|
|
10
10
|
import { TestBuilder } from '@dxos/client/testing';
|
|
11
|
-
import { describe, test } from '@dxos/test';
|
|
11
|
+
import { describe, openAndClose, test } from '@dxos/test';
|
|
12
12
|
|
|
13
13
|
import { DevServer } from './dev-server';
|
|
14
|
-
import { FunctionRegistry } from '../registry';
|
|
15
|
-
import { createFunctionRuntime } from '../testing';
|
|
16
14
|
import { type FunctionManifest } from '../types';
|
|
17
15
|
|
|
18
16
|
describe('dev server', () => {
|
|
@@ -20,10 +18,35 @@ describe('dev server', () => {
|
|
|
20
18
|
let testBuilder: TestBuilder;
|
|
21
19
|
before(async () => {
|
|
22
20
|
testBuilder = new TestBuilder();
|
|
23
|
-
|
|
21
|
+
const config = new Config({
|
|
22
|
+
runtime: {
|
|
23
|
+
agent: {
|
|
24
|
+
plugins: [
|
|
25
|
+
{
|
|
26
|
+
id: 'dxos.org/agent/plugin/functions',
|
|
27
|
+
config: {
|
|
28
|
+
port: 8080,
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
],
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
const services = testBuilder.createLocalClientServices();
|
|
37
|
+
client = new Client({ config, services });
|
|
38
|
+
|
|
39
|
+
await client.initialize();
|
|
40
|
+
await client.halo.createIdentity();
|
|
41
|
+
testBuilder.ctx.onDispose(() => client.destroy());
|
|
42
|
+
|
|
43
|
+
// TODO(burdon): Better way to configure plugin? (Rationalize chess.test).
|
|
44
|
+
const functionsPlugin = new FunctionsPlugin();
|
|
45
|
+
await functionsPlugin.initialize({ client, clientServices: services });
|
|
46
|
+
await openAndClose(functionsPlugin);
|
|
47
|
+
|
|
24
48
|
expect(client.services.services.FunctionRegistryService).to.exist;
|
|
25
49
|
});
|
|
26
|
-
|
|
27
50
|
after(async () => {
|
|
28
51
|
await testBuilder.destroy();
|
|
29
52
|
});
|
|
@@ -32,19 +55,18 @@ describe('dev server', () => {
|
|
|
32
55
|
const manifest: FunctionManifest = {
|
|
33
56
|
functions: [
|
|
34
57
|
{
|
|
35
|
-
|
|
36
|
-
|
|
58
|
+
id: 'example.com/function/test',
|
|
59
|
+
path: 'test',
|
|
37
60
|
handler: 'test',
|
|
38
61
|
},
|
|
39
62
|
],
|
|
40
63
|
};
|
|
41
64
|
|
|
42
|
-
const
|
|
43
|
-
|
|
65
|
+
const server = new DevServer(client, {
|
|
66
|
+
manifest,
|
|
44
67
|
baseDir: path.join(__dirname, '../testing'),
|
|
45
68
|
});
|
|
46
|
-
|
|
47
|
-
await registry.register(space, manifest);
|
|
69
|
+
await server.initialize();
|
|
48
70
|
await server.start();
|
|
49
71
|
|
|
50
72
|
// TODO(burdon): Doesn't shut down cleanly.
|
|
@@ -52,8 +74,6 @@ describe('dev server', () => {
|
|
|
52
74
|
testBuilder.ctx.onDispose(() => server.stop());
|
|
53
75
|
expect(server).to.exist;
|
|
54
76
|
|
|
55
|
-
await waitForCondition({ condition: () => server.functions.length > 0 });
|
|
56
|
-
|
|
57
77
|
await server.invoke('test', {});
|
|
58
78
|
expect(server.stats.seq).to.eq(1);
|
|
59
79
|
});
|
|
@@ -9,15 +9,14 @@ import { join } from 'node:path';
|
|
|
9
9
|
|
|
10
10
|
import { Event, Trigger } from '@dxos/async';
|
|
11
11
|
import { type Client } from '@dxos/client';
|
|
12
|
-
import { Context } from '@dxos/context';
|
|
13
12
|
import { invariant } from '@dxos/invariant';
|
|
14
13
|
import { log } from '@dxos/log';
|
|
15
14
|
|
|
16
|
-
import { type FunctionContext, type
|
|
17
|
-
import { type
|
|
18
|
-
import { type FunctionDef } from '../types';
|
|
15
|
+
import { type FunctionContext, type FunctionHandler, type Response } from '../handler';
|
|
16
|
+
import { type FunctionDef, type FunctionManifest } from '../types';
|
|
19
17
|
|
|
20
18
|
export type DevServerOptions = {
|
|
19
|
+
manifest: FunctionManifest;
|
|
21
20
|
baseDir: string;
|
|
22
21
|
port?: number;
|
|
23
22
|
reload?: boolean;
|
|
@@ -28,8 +27,6 @@ export type DevServerOptions = {
|
|
|
28
27
|
* Functions dev server provides a local HTTP server for testing functions.
|
|
29
28
|
*/
|
|
30
29
|
export class DevServer {
|
|
31
|
-
private _ctx = createContext();
|
|
32
|
-
|
|
33
30
|
// Function handlers indexed by name (URL path).
|
|
34
31
|
private readonly _handlers: Record<string, { def: FunctionDef; handler: FunctionHandler<any> }> = {};
|
|
35
32
|
|
|
@@ -44,15 +41,8 @@ export class DevServer {
|
|
|
44
41
|
// prettier-ignore
|
|
45
42
|
constructor(
|
|
46
43
|
private readonly _client: Client,
|
|
47
|
-
private readonly _functionsRegistry: FunctionRegistry,
|
|
48
44
|
private readonly _options: DevServerOptions,
|
|
49
|
-
) {
|
|
50
|
-
this._functionsRegistry.onFunctionsRegistered.on(async ({ newFunctions }) => {
|
|
51
|
-
newFunctions.forEach((def) => this._load(def));
|
|
52
|
-
await this._safeUpdateRegistration();
|
|
53
|
-
log('new functions loaded', { newFunctions });
|
|
54
|
-
});
|
|
55
|
-
}
|
|
45
|
+
) {}
|
|
56
46
|
|
|
57
47
|
get stats() {
|
|
58
48
|
return {
|
|
@@ -73,10 +63,19 @@ export class DevServer {
|
|
|
73
63
|
return Object.values(this._handlers);
|
|
74
64
|
}
|
|
75
65
|
|
|
66
|
+
async initialize() {
|
|
67
|
+
for (const def of this._options.manifest.functions) {
|
|
68
|
+
try {
|
|
69
|
+
await this._load(def);
|
|
70
|
+
} catch (err) {
|
|
71
|
+
log.error('parsing function (check manifest)', err);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
76
|
async start() {
|
|
77
77
|
invariant(!this._server);
|
|
78
78
|
log.info('starting...');
|
|
79
|
-
this._ctx = createContext();
|
|
80
79
|
|
|
81
80
|
// TODO(burdon): Move to hono.
|
|
82
81
|
const app = express();
|
|
@@ -108,14 +107,12 @@ export class DevServer {
|
|
|
108
107
|
// Register functions.
|
|
109
108
|
const { registrationId, endpoint } = await this._client.services.services.FunctionRegistryService!.register({
|
|
110
109
|
endpoint: this.endpoint,
|
|
110
|
+
functions: this.functions.map(({ def: { id, path } }) => ({ id, path })),
|
|
111
111
|
});
|
|
112
112
|
|
|
113
113
|
log.info('registered', { endpoint });
|
|
114
114
|
this._proxy = endpoint;
|
|
115
115
|
this._functionServiceRegistration = registrationId;
|
|
116
|
-
|
|
117
|
-
// Open after registration, so that it can be updated with the list of function definitions.
|
|
118
|
-
await this._functionsRegistry.open(this._ctx);
|
|
119
116
|
} catch (err: any) {
|
|
120
117
|
await this.stop();
|
|
121
118
|
throw new Error('FunctionRegistryService not available (check plugin is configured).');
|
|
@@ -159,9 +156,9 @@ export class DevServer {
|
|
|
159
156
|
* Load function.
|
|
160
157
|
*/
|
|
161
158
|
private async _load(def: FunctionDef, force = false) {
|
|
162
|
-
const {
|
|
159
|
+
const { id, path, handler } = def;
|
|
163
160
|
const filePath = join(this._options.baseDir, handler);
|
|
164
|
-
log.info('loading', {
|
|
161
|
+
log.info('loading', { id, force });
|
|
165
162
|
|
|
166
163
|
// Remove from cache.
|
|
167
164
|
if (force) {
|
|
@@ -172,26 +169,13 @@ export class DevServer {
|
|
|
172
169
|
});
|
|
173
170
|
}
|
|
174
171
|
|
|
175
|
-
// TODO(burdon): Import types.
|
|
176
172
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
177
173
|
const module = require(filePath);
|
|
178
174
|
if (typeof module.default !== 'function') {
|
|
179
|
-
throw new Error(`Handler must export default function: ${
|
|
175
|
+
throw new Error(`Handler must export default function: ${id}`);
|
|
180
176
|
}
|
|
181
177
|
|
|
182
|
-
this._handlers[
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
private async _safeUpdateRegistration(): Promise<void> {
|
|
186
|
-
invariant(this._functionServiceRegistration);
|
|
187
|
-
try {
|
|
188
|
-
await this._client.services.services.FunctionRegistryService!.updateRegistration({
|
|
189
|
-
registrationId: this._functionServiceRegistration,
|
|
190
|
-
functions: this.functions.map(({ def: { id, route } }) => ({ id, route })),
|
|
191
|
-
});
|
|
192
|
-
} catch (e) {
|
|
193
|
-
log.catch(e);
|
|
194
|
-
}
|
|
178
|
+
this._handlers[path] = { def, handler: module.default };
|
|
195
179
|
}
|
|
196
180
|
|
|
197
181
|
/**
|
|
@@ -202,14 +186,14 @@ export class DevServer {
|
|
|
202
186
|
const now = Date.now();
|
|
203
187
|
|
|
204
188
|
log.info('req', { seq, path });
|
|
205
|
-
const statusCode = await this._invoke(path,
|
|
189
|
+
const statusCode = await this._invoke(path, data);
|
|
206
190
|
|
|
207
191
|
log.info('res', { seq, path, statusCode, duration: Date.now() - now });
|
|
208
192
|
this.update.emit(statusCode);
|
|
209
193
|
return statusCode;
|
|
210
194
|
}
|
|
211
195
|
|
|
212
|
-
private async _invoke(path: string, event:
|
|
196
|
+
private async _invoke(path: string, event: any) {
|
|
213
197
|
const { handler } = this._handlers[path] ?? {};
|
|
214
198
|
invariant(handler, `invalid path: ${path}`);
|
|
215
199
|
|
|
@@ -219,7 +203,7 @@ export class DevServer {
|
|
|
219
203
|
};
|
|
220
204
|
|
|
221
205
|
let statusCode = 200;
|
|
222
|
-
const response:
|
|
206
|
+
const response: Response = {
|
|
223
207
|
status: (code: number) => {
|
|
224
208
|
statusCode = code;
|
|
225
209
|
return response;
|
|
@@ -230,5 +214,3 @@ export class DevServer {
|
|
|
230
214
|
return statusCode;
|
|
231
215
|
}
|
|
232
216
|
}
|
|
233
|
-
|
|
234
|
-
const createContext = () => new Context({ name: 'DevServer' });
|
|
@@ -6,43 +6,40 @@ import { expect } from 'chai';
|
|
|
6
6
|
import WebSocket from 'ws';
|
|
7
7
|
|
|
8
8
|
import { Trigger } from '@dxos/async';
|
|
9
|
-
import {
|
|
9
|
+
import { Client } from '@dxos/client';
|
|
10
10
|
import { TestBuilder } from '@dxos/client/testing';
|
|
11
|
-
import { create } from '@dxos/echo-schema';
|
|
11
|
+
import { create, S, TypedObject } from '@dxos/echo-schema';
|
|
12
12
|
import { describe, test } from '@dxos/test';
|
|
13
13
|
|
|
14
|
-
import { Scheduler
|
|
15
|
-
import {
|
|
16
|
-
import { createInitializedClients, TestType, triggerWebhook } from '../testing';
|
|
17
|
-
import { TriggerRegistry } from '../trigger';
|
|
18
|
-
import { type FunctionManifest } from '../types';
|
|
14
|
+
import { Scheduler } from './scheduler';
|
|
15
|
+
import { type FunctionManifest, type WebhookTrigger } from '../types';
|
|
19
16
|
|
|
20
17
|
// TODO(burdon): Test we can add and remove triggers.
|
|
21
18
|
describe('scheduler', () => {
|
|
22
|
-
let testBuilder: TestBuilder;
|
|
23
19
|
let client: Client;
|
|
24
20
|
before(async () => {
|
|
25
|
-
testBuilder = new TestBuilder();
|
|
26
|
-
client = (
|
|
21
|
+
const testBuilder = new TestBuilder();
|
|
22
|
+
client = new Client({ services: testBuilder.createLocalClientServices() });
|
|
23
|
+
await client.initialize();
|
|
24
|
+
await client.halo.createIdentity();
|
|
27
25
|
});
|
|
28
26
|
after(async () => {
|
|
29
|
-
await
|
|
27
|
+
await client.destroy();
|
|
30
28
|
});
|
|
31
29
|
|
|
32
30
|
test('timer', async () => {
|
|
33
31
|
const manifest: FunctionManifest = {
|
|
34
32
|
functions: [
|
|
35
33
|
{
|
|
36
|
-
|
|
37
|
-
|
|
34
|
+
id: 'example.com/function/test',
|
|
35
|
+
path: '/test',
|
|
38
36
|
handler: 'test',
|
|
39
37
|
},
|
|
40
38
|
],
|
|
41
39
|
triggers: [
|
|
42
40
|
{
|
|
43
41
|
function: 'example.com/function/test',
|
|
44
|
-
|
|
45
|
-
type: 'timer',
|
|
42
|
+
timer: {
|
|
46
43
|
cron: '0/1 * * * * *', // Every 1s.
|
|
47
44
|
},
|
|
48
45
|
},
|
|
@@ -51,13 +48,18 @@ describe('scheduler', () => {
|
|
|
51
48
|
|
|
52
49
|
let count = 0;
|
|
53
50
|
const done = new Trigger();
|
|
54
|
-
const scheduler =
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
51
|
+
const scheduler = new Scheduler(client, manifest, {
|
|
52
|
+
callback: async () => {
|
|
53
|
+
if (++count === 3) {
|
|
54
|
+
done.wake();
|
|
55
|
+
}
|
|
56
|
+
},
|
|
58
57
|
});
|
|
59
|
-
|
|
58
|
+
|
|
60
59
|
await scheduler.start();
|
|
60
|
+
after(async () => {
|
|
61
|
+
await scheduler.stop();
|
|
62
|
+
});
|
|
61
63
|
|
|
62
64
|
await done.wait({ timeout: 5_000 });
|
|
63
65
|
expect(count).to.equal(3);
|
|
@@ -67,16 +69,15 @@ describe('scheduler', () => {
|
|
|
67
69
|
const manifest: FunctionManifest = {
|
|
68
70
|
functions: [
|
|
69
71
|
{
|
|
70
|
-
|
|
71
|
-
|
|
72
|
+
id: 'example.com/function/test',
|
|
73
|
+
path: '/test',
|
|
72
74
|
handler: 'test',
|
|
73
75
|
},
|
|
74
76
|
],
|
|
75
77
|
triggers: [
|
|
76
78
|
{
|
|
77
79
|
function: 'example.com/function/test',
|
|
78
|
-
|
|
79
|
-
type: 'webhook',
|
|
80
|
+
webhook: {
|
|
80
81
|
method: 'GET',
|
|
81
82
|
},
|
|
82
83
|
},
|
|
@@ -84,14 +85,23 @@ describe('scheduler', () => {
|
|
|
84
85
|
};
|
|
85
86
|
|
|
86
87
|
const done = new Trigger();
|
|
87
|
-
const scheduler =
|
|
88
|
-
|
|
88
|
+
const scheduler = new Scheduler(client, manifest, {
|
|
89
|
+
callback: async () => {
|
|
90
|
+
done.wake();
|
|
91
|
+
},
|
|
89
92
|
});
|
|
90
|
-
|
|
91
|
-
await scheduler.register(space, manifest);
|
|
93
|
+
|
|
92
94
|
await scheduler.start();
|
|
95
|
+
after(async () => {
|
|
96
|
+
await scheduler.stop();
|
|
97
|
+
});
|
|
93
98
|
|
|
94
|
-
setTimeout(
|
|
99
|
+
setTimeout(() => {
|
|
100
|
+
const mount: WebhookTrigger = scheduler.mounts.find(
|
|
101
|
+
(mount) => mount.function === 'example.com/function/test',
|
|
102
|
+
)!.webhook!;
|
|
103
|
+
void fetch(`http://localhost:${mount.port}`);
|
|
104
|
+
});
|
|
95
105
|
|
|
96
106
|
await done.wait();
|
|
97
107
|
});
|
|
@@ -100,16 +110,15 @@ describe('scheduler', () => {
|
|
|
100
110
|
const manifest: FunctionManifest = {
|
|
101
111
|
functions: [
|
|
102
112
|
{
|
|
103
|
-
|
|
104
|
-
|
|
113
|
+
id: 'example.com/function/test',
|
|
114
|
+
path: '/test',
|
|
105
115
|
handler: 'test',
|
|
106
116
|
},
|
|
107
117
|
],
|
|
108
118
|
triggers: [
|
|
109
119
|
{
|
|
110
120
|
function: 'example.com/function/test',
|
|
111
|
-
|
|
112
|
-
type: 'websocket',
|
|
121
|
+
websocket: {
|
|
113
122
|
// url: 'https://hub.dxos.network/api/mailbox/test',
|
|
114
123
|
url: 'http://localhost:8081',
|
|
115
124
|
init: {
|
|
@@ -121,11 +130,16 @@ describe('scheduler', () => {
|
|
|
121
130
|
};
|
|
122
131
|
|
|
123
132
|
const done = new Trigger();
|
|
124
|
-
const scheduler =
|
|
125
|
-
|
|
133
|
+
const scheduler = new Scheduler(client, manifest, {
|
|
134
|
+
callback: async (data) => {
|
|
135
|
+
done.wake();
|
|
136
|
+
},
|
|
126
137
|
});
|
|
127
|
-
|
|
138
|
+
|
|
128
139
|
await scheduler.start();
|
|
140
|
+
after(async () => {
|
|
141
|
+
await scheduler.stop();
|
|
142
|
+
});
|
|
129
143
|
|
|
130
144
|
// Test server.
|
|
131
145
|
setTimeout(() => {
|
|
@@ -143,20 +157,29 @@ describe('scheduler', () => {
|
|
|
143
157
|
});
|
|
144
158
|
|
|
145
159
|
test('subscription', async () => {
|
|
160
|
+
class TestType extends TypedObject({ typename: 'example.com/type/Test', version: '0.1.0' })({
|
|
161
|
+
title: S.string,
|
|
162
|
+
}) {}
|
|
163
|
+
client.addSchema(TestType);
|
|
164
|
+
|
|
146
165
|
const manifest: FunctionManifest = {
|
|
147
166
|
functions: [
|
|
148
167
|
{
|
|
149
|
-
|
|
150
|
-
|
|
168
|
+
id: 'example.com/function/test',
|
|
169
|
+
path: '/test',
|
|
151
170
|
handler: 'test',
|
|
152
171
|
},
|
|
153
172
|
],
|
|
154
173
|
triggers: [
|
|
155
174
|
{
|
|
156
175
|
function: 'example.com/function/test',
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
filter: [
|
|
176
|
+
subscription: {
|
|
177
|
+
spaceKey: client.spaces.default.key.toHex(),
|
|
178
|
+
filter: [
|
|
179
|
+
{
|
|
180
|
+
type: TestType.typename,
|
|
181
|
+
},
|
|
182
|
+
],
|
|
160
183
|
},
|
|
161
184
|
},
|
|
162
185
|
],
|
|
@@ -164,14 +187,20 @@ describe('scheduler', () => {
|
|
|
164
187
|
|
|
165
188
|
let count = 0;
|
|
166
189
|
const done = new Trigger();
|
|
167
|
-
const scheduler =
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
190
|
+
const scheduler = new Scheduler(client, manifest, {
|
|
191
|
+
callback: async () => {
|
|
192
|
+
if (++count === 2) {
|
|
193
|
+
done.wake();
|
|
194
|
+
}
|
|
195
|
+
},
|
|
171
196
|
});
|
|
172
|
-
|
|
197
|
+
|
|
173
198
|
await scheduler.start();
|
|
199
|
+
after(async () => {
|
|
200
|
+
await scheduler.stop();
|
|
201
|
+
});
|
|
174
202
|
|
|
203
|
+
// TODO(burdon): Query for Expando?
|
|
175
204
|
setTimeout(() => {
|
|
176
205
|
const space = client.spaces.default;
|
|
177
206
|
const object = create(TestType, { title: 'Hello world!' });
|
|
@@ -180,12 +209,4 @@ describe('scheduler', () => {
|
|
|
180
209
|
|
|
181
210
|
await done.wait();
|
|
182
211
|
});
|
|
183
|
-
|
|
184
|
-
const createScheduler = (callback: SchedulerOptions['callback']) => {
|
|
185
|
-
const scheduler = new Scheduler(new FunctionRegistry(client), new TriggerRegistry(client), { callback });
|
|
186
|
-
after(async () => {
|
|
187
|
-
await scheduler.stop();
|
|
188
|
-
});
|
|
189
|
-
return scheduler;
|
|
190
|
-
};
|
|
191
212
|
});
|