@dxos/functions 0.8.2-main.12df754 → 0.8.2-main.30e4dbb
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/bundler/index.mjs +0 -3
- package/dist/lib/browser/bundler/index.mjs.map +1 -1
- package/dist/lib/browser/edge/index.mjs +62 -7
- package/dist/lib/browser/edge/index.mjs.map +4 -4
- package/dist/lib/browser/index.mjs +370 -102
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node/bundler/index.cjs +0 -1
- package/dist/lib/node/bundler/index.cjs.map +1 -1
- package/dist/lib/node/edge/index.cjs +64 -5
- package/dist/lib/node/edge/index.cjs.map +4 -4
- package/dist/lib/node/index.cjs +382 -94
- package/dist/lib/node/index.cjs.map +4 -4
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node-esm/bundler/index.mjs +0 -1
- package/dist/lib/node-esm/bundler/index.mjs.map +1 -1
- package/dist/lib/node-esm/edge/index.mjs +63 -6
- package/dist/lib/node-esm/edge/index.mjs.map +4 -4
- package/dist/lib/node-esm/index.mjs +370 -100
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/types/src/bundler/bundler.d.ts.map +1 -1
- package/dist/types/src/edge/functions.d.ts +2 -3
- package/dist/types/src/edge/functions.d.ts.map +1 -1
- package/dist/types/src/edge/index.d.ts.map +1 -1
- package/dist/types/src/handler.d.ts +15 -64
- package/dist/types/src/handler.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +3 -3
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/schema.d.ts +57 -0
- package/dist/types/src/schema.d.ts.map +1 -0
- package/dist/types/src/trace.d.ts +148 -0
- package/dist/types/src/trace.d.ts.map +1 -0
- package/dist/types/src/translations.d.ts +2 -1
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/src/types.d.ts +407 -0
- package/dist/types/src/types.d.ts.map +1 -0
- package/dist/types/src/{types/url.d.ts → url.d.ts} +1 -1
- package/dist/types/src/url.d.ts.map +1 -0
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +20 -36
- package/src/edge/functions.ts +2 -4
- package/src/edge/index.ts +4 -0
- package/src/handler.ts +20 -122
- package/src/index.ts +4 -5
- package/src/schema.ts +53 -0
- package/src/{types/trace.ts → trace.ts} +33 -31
- package/src/translations.ts +1 -1
- package/src/types.ts +210 -0
- package/src/{types/url.ts → url.ts} +1 -1
- package/dist/lib/browser/chunk-2YE6S7XY.mjs +0 -360
- package/dist/lib/browser/chunk-2YE6S7XY.mjs.map +0 -7
- package/dist/lib/browser/chunk-7CHDHCV3.mjs +0 -482
- package/dist/lib/browser/chunk-7CHDHCV3.mjs.map +0 -7
- package/dist/lib/browser/chunk-LT4LR4VU.mjs +0 -72
- package/dist/lib/browser/chunk-LT4LR4VU.mjs.map +0 -7
- package/dist/lib/browser/chunk-XRCXIG74.mjs +0 -12
- package/dist/lib/browser/chunk-XRCXIG74.mjs.map +0 -7
- package/dist/lib/browser/testing/index.mjs +0 -670
- package/dist/lib/browser/testing/index.mjs.map +0 -7
- package/dist/lib/browser/types/index.mjs +0 -51
- package/dist/lib/browser/types/index.mjs.map +0 -7
- package/dist/lib/node/chunk-FBIUZ7SD.cjs +0 -496
- package/dist/lib/node/chunk-FBIUZ7SD.cjs.map +0 -7
- package/dist/lib/node/chunk-JEQ2X3Z6.cjs +0 -34
- package/dist/lib/node/chunk-JEQ2X3Z6.cjs.map +0 -7
- package/dist/lib/node/chunk-NXZNXVT3.cjs +0 -94
- package/dist/lib/node/chunk-NXZNXVT3.cjs.map +0 -7
- package/dist/lib/node/chunk-SV5NRE5L.cjs +0 -395
- package/dist/lib/node/chunk-SV5NRE5L.cjs.map +0 -7
- package/dist/lib/node/testing/index.cjs +0 -687
- package/dist/lib/node/testing/index.cjs.map +0 -7
- package/dist/lib/node/types/index.cjs +0 -72
- package/dist/lib/node/types/index.cjs.map +0 -7
- package/dist/lib/node-esm/chunk-3XMJFSID.mjs +0 -360
- package/dist/lib/node-esm/chunk-3XMJFSID.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-C6YINTWG.mjs +0 -482
- package/dist/lib/node-esm/chunk-C6YINTWG.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-DHGBFXSZ.mjs +0 -12
- package/dist/lib/node-esm/chunk-DHGBFXSZ.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-O2SXVYU5.mjs +0 -72
- package/dist/lib/node-esm/chunk-O2SXVYU5.mjs.map +0 -7
- package/dist/lib/node-esm/testing/index.mjs +0 -670
- package/dist/lib/node-esm/testing/index.mjs.map +0 -7
- package/dist/lib/node-esm/types/index.mjs +0 -51
- package/dist/lib/node-esm/types/index.mjs.map +0 -7
- package/dist/types/src/browser/index.d.ts +0 -2
- package/dist/types/src/browser/index.d.ts.map +0 -1
- package/dist/types/src/function/function-registry.d.ts +0 -25
- package/dist/types/src/function/function-registry.d.ts.map +0 -1
- package/dist/types/src/function/function-registry.test.d.ts +0 -2
- package/dist/types/src/function/function-registry.test.d.ts.map +0 -1
- package/dist/types/src/function/index.d.ts +0 -2
- package/dist/types/src/function/index.d.ts.map +0 -1
- package/dist/types/src/runtime/dev-server.d.ts +0 -52
- package/dist/types/src/runtime/dev-server.d.ts.map +0 -1
- package/dist/types/src/runtime/dev-server.test.d.ts +0 -2
- package/dist/types/src/runtime/dev-server.test.d.ts.map +0 -1
- package/dist/types/src/runtime/index.d.ts +0 -3
- package/dist/types/src/runtime/index.d.ts.map +0 -1
- package/dist/types/src/runtime/scheduler.d.ts +0 -34
- package/dist/types/src/runtime/scheduler.d.ts.map +0 -1
- package/dist/types/src/runtime/scheduler.test.d.ts +0 -2
- package/dist/types/src/runtime/scheduler.test.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 -5
- package/dist/types/src/testing/index.d.ts.map +0 -1
- package/dist/types/src/testing/manifest.d.ts +0 -3
- package/dist/types/src/testing/manifest.d.ts.map +0 -1
- package/dist/types/src/testing/plugin-init.d.ts +0 -6
- package/dist/types/src/testing/plugin-init.d.ts.map +0 -1
- package/dist/types/src/testing/setup.d.ts +0 -15
- package/dist/types/src/testing/setup.d.ts.map +0 -1
- package/dist/types/src/testing/test/handler.d.ts +0 -4
- package/dist/types/src/testing/test/handler.d.ts.map +0 -1
- package/dist/types/src/testing/test/index.d.ts +0 -3
- package/dist/types/src/testing/test/index.d.ts.map +0 -1
- package/dist/types/src/testing/types.d.ts +0 -10
- package/dist/types/src/testing/types.d.ts.map +0 -1
- package/dist/types/src/testing/util.d.ts +0 -5
- package/dist/types/src/testing/util.d.ts.map +0 -1
- package/dist/types/src/trigger/index.d.ts +0 -3
- package/dist/types/src/trigger/index.d.ts.map +0 -1
- package/dist/types/src/trigger/trigger-registry.d.ts +0 -38
- 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 -3
- 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/types/index.d.ts +0 -5
- package/dist/types/src/types/index.d.ts.map +0 -1
- package/dist/types/src/types/schema.d.ts +0 -53
- package/dist/types/src/types/schema.d.ts.map +0 -1
- package/dist/types/src/types/trace.d.ts +0 -146
- package/dist/types/src/types/trace.d.ts.map +0 -1
- package/dist/types/src/types/types.d.ts +0 -265
- package/dist/types/src/types/types.d.ts.map +0 -1
- package/dist/types/src/types/url.d.ts.map +0 -1
- package/dist/types/tools/schema.d.ts +0 -2
- package/dist/types/tools/schema.d.ts.map +0 -1
- package/schema/functions.json +0 -211
- package/src/browser/index.ts +0 -5
- package/src/function/function-registry.test.ts +0 -118
- package/src/function/function-registry.ts +0 -104
- package/src/function/index.ts +0 -5
- package/src/runtime/dev-server.test.ts +0 -79
- package/src/runtime/dev-server.ts +0 -240
- package/src/runtime/index.ts +0 -6
- package/src/runtime/scheduler.test.ts +0 -152
- package/src/runtime/scheduler.ts +0 -170
- package/src/testing/functions-integration.test.ts +0 -65
- package/src/testing/index.ts +0 -8
- package/src/testing/manifest.ts +0 -15
- package/src/testing/plugin-init.ts +0 -20
- package/src/testing/setup.ts +0 -109
- package/src/testing/test/handler.ts +0 -15
- package/src/testing/test/index.ts +0 -7
- package/src/testing/types.ts +0 -9
- package/src/testing/util.ts +0 -26
- package/src/trigger/index.ts +0 -6
- package/src/trigger/trigger-registry.test.ts +0 -278
- package/src/trigger/trigger-registry.ts +0 -218
- package/src/trigger/type/index.ts +0 -7
- package/src/trigger/type/subscription-trigger.ts +0 -84
- package/src/trigger/type/timer-trigger.ts +0 -48
- package/src/trigger/type/webhook-trigger.ts +0 -48
- package/src/types/index.ts +0 -8
- package/src/types/schema.ts +0 -46
- package/src/types/types.ts +0 -163
package/src/runtime/scheduler.ts
DELETED
|
@@ -1,170 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Copyright 2023 DXOS.org
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
import path from 'node:path';
|
|
6
|
-
|
|
7
|
-
import { Mutex } from '@dxos/async';
|
|
8
|
-
import { loadObjectReferences, type Space } from '@dxos/client/echo';
|
|
9
|
-
import { Context } from '@dxos/context';
|
|
10
|
-
import { Reference } from '@dxos/echo-protocol';
|
|
11
|
-
import { log } from '@dxos/log';
|
|
12
|
-
|
|
13
|
-
import { type FunctionRegistry } from '../function';
|
|
14
|
-
import { type FunctionEventMeta } from '../handler';
|
|
15
|
-
import { type TriggerCallback, type TriggerRegistry } from '../trigger';
|
|
16
|
-
import { type FunctionDef, type FunctionManifest, type FunctionTrigger } from '../types';
|
|
17
|
-
|
|
18
|
-
export type Callback = (data: any) => Promise<void | number>;
|
|
19
|
-
|
|
20
|
-
export type SchedulerOptions = {
|
|
21
|
-
endpoint?: string;
|
|
22
|
-
callback?: Callback;
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* The scheduler triggers function execution based on various trigger configurations.
|
|
27
|
-
* Functions are scheduled within the context of a specific space.
|
|
28
|
-
*/
|
|
29
|
-
export class Scheduler {
|
|
30
|
-
private _ctx = createContext();
|
|
31
|
-
|
|
32
|
-
private readonly _functionUriToCallMutex = new Map<string, Mutex>();
|
|
33
|
-
|
|
34
|
-
constructor(
|
|
35
|
-
public readonly functions: FunctionRegistry,
|
|
36
|
-
public readonly triggers: TriggerRegistry,
|
|
37
|
-
private readonly _options: SchedulerOptions = {},
|
|
38
|
-
) {
|
|
39
|
-
this.functions.registered.on(async ({ space, added }) => {
|
|
40
|
-
await this._safeActivateTriggers(space, this.triggers.getInactiveTriggers(space), added);
|
|
41
|
-
});
|
|
42
|
-
this.triggers.registered.on(async ({ space, triggers }) => {
|
|
43
|
-
await this._safeActivateTriggers(space, triggers, this.functions.getFunctions(space));
|
|
44
|
-
});
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
async start() {
|
|
48
|
-
await this._ctx.dispose();
|
|
49
|
-
this._ctx = createContext();
|
|
50
|
-
await this.functions.open(this._ctx);
|
|
51
|
-
await this.triggers.open(this._ctx);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
async stop() {
|
|
55
|
-
await this._ctx.dispose();
|
|
56
|
-
await this.functions.close();
|
|
57
|
-
await this.triggers.close();
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// TODO(burdon): Remove and update registries directly?
|
|
61
|
-
public async register(space: Space, manifest: FunctionManifest) {
|
|
62
|
-
await this.functions.register(space, manifest.functions);
|
|
63
|
-
await this.triggers.register(space, manifest);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
private async _safeActivateTriggers(
|
|
67
|
-
space: Space,
|
|
68
|
-
triggers: FunctionTrigger[],
|
|
69
|
-
functions: FunctionDef[],
|
|
70
|
-
): Promise<void> {
|
|
71
|
-
const mountTasks = triggers.map((trigger) => {
|
|
72
|
-
return this.activate(space, functions, trigger);
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
await Promise.all(mountTasks).catch(log.catch);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* Activate trigger.
|
|
80
|
-
*/
|
|
81
|
-
// TODO(burdon): How are triggers deactivated?
|
|
82
|
-
private async activate(space: Space, functions: FunctionDef[], trigger: FunctionTrigger) {
|
|
83
|
-
const definition = functions.find((def) => def.uri === trigger.function);
|
|
84
|
-
if (!definition) {
|
|
85
|
-
log.info('function is not found for trigger', { trigger });
|
|
86
|
-
return;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
const execFunction: TriggerCallback = async (args) => {
|
|
90
|
-
const mutex = this._functionUriToCallMutex.get(definition.uri) ?? new Mutex();
|
|
91
|
-
this._functionUriToCallMutex.set(definition.uri, mutex);
|
|
92
|
-
|
|
93
|
-
log.info('function triggered, waiting for mutex', { uri: definition.uri });
|
|
94
|
-
return mutex.executeSynchronized(async () => {
|
|
95
|
-
log.info('mutex acquired', { uri: definition.uri });
|
|
96
|
-
|
|
97
|
-
// Load potential references in meta properties to serialize.
|
|
98
|
-
await loadObjectReferences(trigger, (t) => Object.values(t.meta ?? {}));
|
|
99
|
-
const meta: FunctionTrigger['meta'] = {};
|
|
100
|
-
for (const [key, value] of Object.entries(trigger.meta ?? {})) {
|
|
101
|
-
if (value instanceof Reference) {
|
|
102
|
-
const object = await space.db.query({ id: value.objectId }).first();
|
|
103
|
-
if (object) {
|
|
104
|
-
meta[key] = object;
|
|
105
|
-
}
|
|
106
|
-
} else {
|
|
107
|
-
meta[key] = value;
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
return this._execFunction(definition, trigger, {
|
|
112
|
-
meta,
|
|
113
|
-
data: { ...args, spaceKey: space.key },
|
|
114
|
-
});
|
|
115
|
-
});
|
|
116
|
-
};
|
|
117
|
-
|
|
118
|
-
await this.triggers.activate(space, trigger, execFunction);
|
|
119
|
-
log('activated trigger', { space: space.key, trigger });
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
* Invoke function RPC.
|
|
124
|
-
*/
|
|
125
|
-
private async _execFunction<TData, TMeta>(
|
|
126
|
-
def: FunctionDef,
|
|
127
|
-
trigger: FunctionTrigger,
|
|
128
|
-
{ meta, data }: { meta?: TMeta; data: TData },
|
|
129
|
-
): Promise<number> {
|
|
130
|
-
let status = 0;
|
|
131
|
-
try {
|
|
132
|
-
// TODO(burdon): Pass in Space key (common context)?
|
|
133
|
-
const payload = Object.assign({}, meta && ({ meta } satisfies FunctionEventMeta<TMeta>), data);
|
|
134
|
-
|
|
135
|
-
const { endpoint, callback } = this._options;
|
|
136
|
-
if (endpoint) {
|
|
137
|
-
// TODO(burdon): Move out of scheduler (generalize as callback).
|
|
138
|
-
const url = path.join(endpoint, def.route);
|
|
139
|
-
log.info('exec', { function: def.uri, url, triggerType: trigger.spec?.type });
|
|
140
|
-
const response = await fetch(url, {
|
|
141
|
-
method: 'POST',
|
|
142
|
-
headers: {
|
|
143
|
-
'Content-Type': 'application/json',
|
|
144
|
-
},
|
|
145
|
-
body: JSON.stringify(payload),
|
|
146
|
-
});
|
|
147
|
-
|
|
148
|
-
status = response.status;
|
|
149
|
-
} else if (callback) {
|
|
150
|
-
log.info('exec', { function: def.uri });
|
|
151
|
-
status = (await callback(payload)) ?? 200;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
// Check errors.
|
|
155
|
-
if (status && status >= 400) {
|
|
156
|
-
throw new Error(`Response: ${status}`);
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
// const result = await response.json();
|
|
160
|
-
log.info('done', { function: def.uri, status });
|
|
161
|
-
} catch (err: any) {
|
|
162
|
-
log.error('error', { function: def.uri, error: err.message });
|
|
163
|
-
status = 500;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
return status;
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
const createContext = () => new Context({ name: 'FunctionScheduler' });
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Copyright 2024 DXOS.org
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
import { afterAll, beforeAll, describe, expect, test } from 'vitest';
|
|
6
|
-
|
|
7
|
-
import { Trigger } from '@dxos/async';
|
|
8
|
-
import { live } from '@dxos/client/echo';
|
|
9
|
-
import { TestBuilder } from '@dxos/client/testing';
|
|
10
|
-
|
|
11
|
-
import { initFunctionsPlugin } from './plugin-init';
|
|
12
|
-
import { setTestCallHandler } from './test/handler';
|
|
13
|
-
import { createInitializedClients, inviteMember, startFunctionsHost, TestType } from '../testing';
|
|
14
|
-
import { FunctionDef, FunctionTrigger, TriggerKind } from '../types';
|
|
15
|
-
|
|
16
|
-
// TODO(wittjosiah): Doesn't work in vitest.
|
|
17
|
-
describe.skip('functions e2e', () => {
|
|
18
|
-
let testBuilder: TestBuilder;
|
|
19
|
-
|
|
20
|
-
beforeAll(async () => {
|
|
21
|
-
testBuilder = new TestBuilder();
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
afterAll(async () => {
|
|
25
|
-
await testBuilder.destroy();
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
test('a function gets triggered in response to another peer object creations', async () => {
|
|
29
|
-
// TODO(burdon): Create builder pattern.
|
|
30
|
-
const functionRuntime = await startFunctionsHost(testBuilder, initFunctionsPlugin);
|
|
31
|
-
|
|
32
|
-
const app = (await createInitializedClients(testBuilder, 1))[0];
|
|
33
|
-
const space = await app.spaces.create();
|
|
34
|
-
await inviteMember(space, functionRuntime.client);
|
|
35
|
-
|
|
36
|
-
const uri = 'example.com/function/test';
|
|
37
|
-
space.db.add(live(FunctionDef, { uri, route: '/test', handler: 'test' }));
|
|
38
|
-
const triggerMeta: FunctionTrigger['meta'] = { name: 'DXOS' };
|
|
39
|
-
space.db.add(
|
|
40
|
-
live(FunctionTrigger, {
|
|
41
|
-
function: uri,
|
|
42
|
-
enabled: true,
|
|
43
|
-
meta: triggerMeta,
|
|
44
|
-
spec: {
|
|
45
|
-
type: TriggerKind.Subscription,
|
|
46
|
-
filter: { type: TestType.typename },
|
|
47
|
-
},
|
|
48
|
-
}),
|
|
49
|
-
);
|
|
50
|
-
|
|
51
|
-
const called = new Trigger<any>();
|
|
52
|
-
setTestCallHandler(async (args) => {
|
|
53
|
-
called.wake(args.event.data);
|
|
54
|
-
return args.response.status(200);
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
await functionRuntime.waitForActiveTriggers(space);
|
|
58
|
-
const addedObject = space.db.add(live(TestType, { title: '42' }));
|
|
59
|
-
|
|
60
|
-
const callArgs = await called.wait();
|
|
61
|
-
expect(callArgs.meta).to.deep.eq(triggerMeta);
|
|
62
|
-
expect(callArgs.objects).to.deep.eq([addedObject.id]);
|
|
63
|
-
expect(callArgs.spaceKey).to.eq(space.key.toHex());
|
|
64
|
-
});
|
|
65
|
-
});
|
package/src/testing/index.ts
DELETED
package/src/testing/manifest.ts
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Copyright 2024 DXOS.org
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
import type { FunctionManifest } from '../types';
|
|
6
|
-
|
|
7
|
-
export const testFunctionManifest: FunctionManifest = {
|
|
8
|
-
functions: [
|
|
9
|
-
{
|
|
10
|
-
uri: 'example.com/function/test',
|
|
11
|
-
route: 'test',
|
|
12
|
-
handler: 'test',
|
|
13
|
-
},
|
|
14
|
-
],
|
|
15
|
-
};
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Copyright 2024 DXOS.org
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
import { FunctionsPlugin } from '@dxos/agent';
|
|
6
|
-
import { type Client } from '@dxos/client';
|
|
7
|
-
|
|
8
|
-
import { type FunctionsPluginInitializer } from './setup';
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Deliberately in a non-exported file to keep @dxos/agent as a devDependency.
|
|
12
|
-
*/
|
|
13
|
-
export const initFunctionsPlugin: FunctionsPluginInitializer = async (client: Client) => {
|
|
14
|
-
const plugin = new FunctionsPlugin();
|
|
15
|
-
await plugin.initialize({ client, clientServices: client.services });
|
|
16
|
-
await plugin.open();
|
|
17
|
-
return {
|
|
18
|
-
close: () => plugin.close(),
|
|
19
|
-
};
|
|
20
|
-
};
|
package/src/testing/setup.ts
DELETED
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Copyright 2024 DXOS.org
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
import { getRandomPort } from 'get-port-please';
|
|
6
|
-
import path from 'node:path';
|
|
7
|
-
|
|
8
|
-
import { waitForCondition } from '@dxos/async';
|
|
9
|
-
import { Client, Config } from '@dxos/client';
|
|
10
|
-
import { type Space } from '@dxos/client/echo';
|
|
11
|
-
import { type TestBuilder } from '@dxos/client/testing';
|
|
12
|
-
import { range } from '@dxos/util';
|
|
13
|
-
|
|
14
|
-
import { TestType } from './types';
|
|
15
|
-
import { FunctionRegistry } from '../function';
|
|
16
|
-
import { DevServer, type DevServerOptions, Scheduler } from '../runtime';
|
|
17
|
-
import { TriggerRegistry } from '../trigger';
|
|
18
|
-
import { FunctionDef, FunctionTrigger } from '../types';
|
|
19
|
-
|
|
20
|
-
export type FunctionsPluginInitializer = (client: Client) => Promise<{ close: () => Promise<void> }>;
|
|
21
|
-
|
|
22
|
-
// TODO(burdon): Extend/wrap TestBuilder.
|
|
23
|
-
|
|
24
|
-
export const createInitializedClients = async (testBuilder: TestBuilder, count: number = 1, config?: Config) => {
|
|
25
|
-
const clients = range(count).map(
|
|
26
|
-
() =>
|
|
27
|
-
new Client({
|
|
28
|
-
config,
|
|
29
|
-
services: testBuilder.createLocalClientServices(),
|
|
30
|
-
types: [FunctionDef, FunctionTrigger, TestType],
|
|
31
|
-
}),
|
|
32
|
-
);
|
|
33
|
-
|
|
34
|
-
testBuilder.ctx.onDispose(() => Promise.all(clients.map((client) => client.destroy())));
|
|
35
|
-
return Promise.all(
|
|
36
|
-
clients.map(async (client, index) => {
|
|
37
|
-
await client.initialize();
|
|
38
|
-
await client.halo.createIdentity({ displayName: `Peer ${index}` });
|
|
39
|
-
await client.spaces.waitUntilReady();
|
|
40
|
-
return client;
|
|
41
|
-
}),
|
|
42
|
-
);
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
export const createFunctionRuntime = async (
|
|
46
|
-
testBuilder: TestBuilder,
|
|
47
|
-
pluginInitializer: FunctionsPluginInitializer,
|
|
48
|
-
): Promise<Client> => {
|
|
49
|
-
const functionsPort = await getRandomPort('127.0.0.1');
|
|
50
|
-
const config = new Config({
|
|
51
|
-
runtime: {
|
|
52
|
-
agent: {
|
|
53
|
-
plugins: [{ id: 'dxos.org/agent/plugin/functions', config: { port: functionsPort } }],
|
|
54
|
-
},
|
|
55
|
-
},
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
const [client] = await createInitializedClients(testBuilder, 1, config);
|
|
59
|
-
const plugin = await pluginInitializer(client);
|
|
60
|
-
testBuilder.ctx.onDispose(() => plugin.close());
|
|
61
|
-
return client;
|
|
62
|
-
};
|
|
63
|
-
|
|
64
|
-
export const startFunctionsHost = async (
|
|
65
|
-
testBuilder: TestBuilder,
|
|
66
|
-
pluginInitializer: FunctionsPluginInitializer,
|
|
67
|
-
options?: DevServerOptions,
|
|
68
|
-
) => {
|
|
69
|
-
const functionRuntime = await createFunctionRuntime(testBuilder, pluginInitializer);
|
|
70
|
-
const functionsRegistry = new FunctionRegistry(functionRuntime);
|
|
71
|
-
const devServer = await startDevServer(testBuilder, functionRuntime, functionsRegistry, options);
|
|
72
|
-
const scheduler = await startScheduler(testBuilder, functionRuntime, devServer, functionsRegistry);
|
|
73
|
-
return {
|
|
74
|
-
scheduler,
|
|
75
|
-
client: functionRuntime,
|
|
76
|
-
waitForActiveTriggers: async (space: Space) => {
|
|
77
|
-
await waitForCondition({ condition: () => scheduler.triggers.getActiveTriggers(space).length > 0 });
|
|
78
|
-
},
|
|
79
|
-
};
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
const startScheduler = async (
|
|
83
|
-
testBuilder: TestBuilder,
|
|
84
|
-
client: Client,
|
|
85
|
-
devServer: DevServer,
|
|
86
|
-
functionRegistry: FunctionRegistry,
|
|
87
|
-
) => {
|
|
88
|
-
const triggerRegistry = new TriggerRegistry(client);
|
|
89
|
-
const scheduler = new Scheduler(functionRegistry, triggerRegistry, { endpoint: devServer.endpoint });
|
|
90
|
-
await scheduler.start();
|
|
91
|
-
testBuilder.ctx.onDispose(() => scheduler.stop());
|
|
92
|
-
return scheduler;
|
|
93
|
-
};
|
|
94
|
-
|
|
95
|
-
const startDevServer = async (
|
|
96
|
-
testBuilder: TestBuilder,
|
|
97
|
-
client: Client,
|
|
98
|
-
functionRegistry: FunctionRegistry,
|
|
99
|
-
options?: { baseDir?: string },
|
|
100
|
-
) => {
|
|
101
|
-
const server = new DevServer(client, functionRegistry, {
|
|
102
|
-
baseDir: path.join(__dirname, '../testing'),
|
|
103
|
-
port: await getRandomPort('127.0.0.1'),
|
|
104
|
-
...options,
|
|
105
|
-
});
|
|
106
|
-
await server.start();
|
|
107
|
-
testBuilder.ctx.onDispose(() => server.stop());
|
|
108
|
-
return server;
|
|
109
|
-
};
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Copyright 2023 DXOS.org
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
import { type FunctionHandler } from '../../handler';
|
|
6
|
-
|
|
7
|
-
let callHandler: FunctionHandler<any> = async ({ response }) => response.status(200);
|
|
8
|
-
|
|
9
|
-
export const setTestCallHandler = (handler: FunctionHandler<any>) => {
|
|
10
|
-
callHandler = handler;
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
export const handler: FunctionHandler<any> = async (args) => {
|
|
14
|
-
return callHandler(args);
|
|
15
|
-
};
|
package/src/testing/types.ts
DELETED
package/src/testing/util.ts
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Copyright 2024 DXOS.org
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
import type { Client } from '@dxos/client';
|
|
6
|
-
import { Filter, type Space } from '@dxos/client/echo';
|
|
7
|
-
import { performInvitation } from '@dxos/client/testing';
|
|
8
|
-
import { invariant } from '@dxos/invariant';
|
|
9
|
-
import { Invitation } from '@dxos/protocols/proto/dxos/client/services';
|
|
10
|
-
|
|
11
|
-
import { FunctionTrigger } from '../types';
|
|
12
|
-
|
|
13
|
-
export const triggerWebhook = async (space: Space, uri: string) => {
|
|
14
|
-
const trigger = (
|
|
15
|
-
await space.db.query(Filter.schema(FunctionTrigger, (trigger: FunctionTrigger) => trigger.function === uri)).run()
|
|
16
|
-
).objects[0];
|
|
17
|
-
invariant(trigger.spec?.type === 'webhook');
|
|
18
|
-
void fetch(`http://localhost:${trigger.spec.port}`);
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
export const inviteMember = async (host: Space, guest: Client) => {
|
|
22
|
-
const [{ invitation: hostInvitation }] = await Promise.all(performInvitation({ host, guest: guest.spaces }));
|
|
23
|
-
if (hostInvitation?.state !== Invitation.State.SUCCESS) {
|
|
24
|
-
throw new Error(`Expected ${hostInvitation?.state} to be ${Invitation.State.SUCCESS}.`);
|
|
25
|
-
}
|
|
26
|
-
};
|