@dxos/functions 0.5.2 → 0.5.3-main.088a2c8

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.
Files changed (38) hide show
  1. package/dist/lib/browser/index.mjs +492 -146
  2. package/dist/lib/browser/index.mjs.map +4 -4
  3. package/dist/lib/browser/meta.json +1 -1
  4. package/dist/lib/node/index.cjs +488 -143
  5. package/dist/lib/node/index.cjs.map +4 -4
  6. package/dist/lib/node/meta.json +1 -1
  7. package/dist/types/src/handler.d.ts +33 -12
  8. package/dist/types/src/handler.d.ts.map +1 -1
  9. package/dist/types/src/index.d.ts +1 -1
  10. package/dist/types/src/index.d.ts.map +1 -1
  11. package/dist/types/src/runtime/dev-server.d.ts +17 -6
  12. package/dist/types/src/runtime/dev-server.d.ts.map +1 -1
  13. package/dist/types/src/runtime/dev-server.test.d.ts +2 -0
  14. package/dist/types/src/runtime/dev-server.test.d.ts.map +1 -0
  15. package/dist/types/src/runtime/scheduler.d.ts +55 -7
  16. package/dist/types/src/runtime/scheduler.d.ts.map +1 -1
  17. package/dist/types/src/testing/test/handler.d.ts +3 -0
  18. package/dist/types/src/testing/test/handler.d.ts.map +1 -0
  19. package/dist/types/src/testing/test/index.d.ts +3 -0
  20. package/dist/types/src/testing/test/index.d.ts.map +1 -0
  21. package/dist/types/src/types.d.ts +182 -0
  22. package/dist/types/src/types.d.ts.map +1 -0
  23. package/dist/types/tools/schema.d.ts +2 -0
  24. package/dist/types/tools/schema.d.ts.map +1 -0
  25. package/package.json +20 -11
  26. package/schema/functions.json +183 -0
  27. package/src/handler.ts +56 -26
  28. package/src/index.ts +1 -1
  29. package/src/runtime/dev-server.test.ts +80 -0
  30. package/src/runtime/dev-server.ts +74 -40
  31. package/src/runtime/scheduler.test.ts +163 -9
  32. package/src/runtime/scheduler.ts +228 -64
  33. package/src/testing/test/handler.ts +9 -0
  34. package/src/testing/test/index.ts +7 -0
  35. package/src/types.ts +87 -0
  36. package/dist/types/src/manifest.d.ts +0 -26
  37. package/dist/types/src/manifest.d.ts.map +0 -1
  38. package/src/manifest.ts +0 -42
@@ -0,0 +1,182 @@
1
+ import * as S from '@effect/schema/Schema';
2
+ declare const TimerTriggerSchema: S.struct<{
3
+ cron: S.$string;
4
+ }>;
5
+ declare const WebhookTriggerSchema: S.mutable<S.struct<{
6
+ method: S.$string;
7
+ port: S.PropertySignature<"?:", number | undefined, never, "?:", number | undefined, never>;
8
+ }>>;
9
+ declare const WebsocketTriggerSchema: S.struct<{
10
+ url: S.$string;
11
+ init: S.PropertySignature<"?:", {
12
+ readonly [x: string]: any;
13
+ } | undefined, never, "?:", {
14
+ readonly [x: string]: any;
15
+ } | undefined, never>;
16
+ }>;
17
+ declare const SubscriptionTriggerSchema: S.struct<{
18
+ spaceKey: S.PropertySignature<"?:", string | undefined, never, "?:", string | undefined, never>;
19
+ filter: S.array<S.struct<{
20
+ type: S.$string;
21
+ props: S.PropertySignature<"?:", {
22
+ readonly [x: string]: any;
23
+ } | undefined, never, "?:", {
24
+ readonly [x: string]: any;
25
+ } | undefined, never>;
26
+ }>>;
27
+ options: S.PropertySignature<"?:", {
28
+ readonly deep?: boolean | undefined;
29
+ readonly delay?: number | undefined;
30
+ } | undefined, never, "?:", {
31
+ readonly deep?: boolean | undefined;
32
+ readonly delay?: number | undefined;
33
+ } | undefined, never>;
34
+ }>;
35
+ declare const FunctionTriggerSchema: S.struct<{
36
+ function: S.$string;
37
+ meta: S.PropertySignature<"?:", {
38
+ readonly [x: string]: any;
39
+ } | undefined, never, "?:", {
40
+ readonly [x: string]: any;
41
+ } | undefined, never>;
42
+ timer: S.PropertySignature<"?:", {
43
+ readonly cron: string;
44
+ } | undefined, never, "?:", {
45
+ readonly cron: string;
46
+ } | undefined, never>;
47
+ webhook: S.PropertySignature<"?:", {
48
+ port?: number | undefined;
49
+ method: string;
50
+ } | undefined, never, "?:", {
51
+ method: string;
52
+ port?: number | undefined;
53
+ } | undefined, never>;
54
+ websocket: S.PropertySignature<"?:", {
55
+ readonly url: string;
56
+ readonly init?: {
57
+ readonly [x: string]: any;
58
+ } | undefined;
59
+ } | undefined, never, "?:", {
60
+ readonly url: string;
61
+ readonly init?: {
62
+ readonly [x: string]: any;
63
+ } | undefined;
64
+ } | undefined, never>;
65
+ subscription: S.PropertySignature<"?:", {
66
+ readonly filter: readonly {
67
+ readonly type: string;
68
+ readonly props?: {
69
+ readonly [x: string]: any;
70
+ } | undefined;
71
+ }[];
72
+ readonly spaceKey?: string | undefined;
73
+ readonly options?: {
74
+ readonly deep?: boolean | undefined;
75
+ readonly delay?: number | undefined;
76
+ } | undefined;
77
+ } | undefined, never, "?:", {
78
+ readonly filter: readonly {
79
+ readonly type: string;
80
+ readonly props?: {
81
+ readonly [x: string]: any;
82
+ } | undefined;
83
+ }[];
84
+ readonly spaceKey?: string | undefined;
85
+ readonly options?: {
86
+ readonly deep?: boolean | undefined;
87
+ readonly delay?: number | undefined;
88
+ } | undefined;
89
+ } | undefined, never>;
90
+ }>;
91
+ export type FunctionTrigger = S.Schema.Type<typeof FunctionTriggerSchema>;
92
+ export type TimerTrigger = S.Schema.Type<typeof TimerTriggerSchema>;
93
+ export type WebhookTrigger = S.Schema.Type<typeof WebhookTriggerSchema>;
94
+ export type WebsocketTrigger = S.Schema.Type<typeof WebsocketTriggerSchema>;
95
+ export type SubscriptionTrigger = S.Schema.Type<typeof SubscriptionTriggerSchema>;
96
+ /**
97
+ * Function definition.
98
+ */
99
+ declare const FunctionDefSchema: S.struct<{
100
+ id: S.$string;
101
+ description: S.PropertySignature<"?:", string | undefined, never, "?:", string | undefined, never>;
102
+ path: S.$string;
103
+ handler: S.$string;
104
+ }>;
105
+ export type FunctionDef = S.Schema.Type<typeof FunctionDefSchema>;
106
+ /**
107
+ * Function manifest file.
108
+ */
109
+ export declare const FunctionManifestSchema: S.struct<{
110
+ functions: S.mutable<S.array<S.struct<{
111
+ id: S.$string;
112
+ description: S.PropertySignature<"?:", string | undefined, never, "?:", string | undefined, never>;
113
+ path: S.$string;
114
+ handler: S.$string;
115
+ }>>>;
116
+ triggers: S.PropertySignature<"?:", {
117
+ readonly function: string;
118
+ readonly meta?: {
119
+ readonly [x: string]: any;
120
+ } | undefined;
121
+ readonly timer?: {
122
+ readonly cron: string;
123
+ } | undefined;
124
+ readonly webhook?: {
125
+ port?: number | undefined;
126
+ method: string;
127
+ } | undefined;
128
+ readonly websocket?: {
129
+ readonly url: string;
130
+ readonly init?: {
131
+ readonly [x: string]: any;
132
+ } | undefined;
133
+ } | undefined;
134
+ readonly subscription?: {
135
+ readonly filter: readonly {
136
+ readonly type: string;
137
+ readonly props?: {
138
+ readonly [x: string]: any;
139
+ } | undefined;
140
+ }[];
141
+ readonly spaceKey?: string | undefined;
142
+ readonly options?: {
143
+ readonly deep?: boolean | undefined;
144
+ readonly delay?: number | undefined;
145
+ } | undefined;
146
+ } | undefined;
147
+ }[] | undefined, never, "?:", {
148
+ readonly function: string;
149
+ readonly meta?: {
150
+ readonly [x: string]: any;
151
+ } | undefined;
152
+ readonly timer?: {
153
+ readonly cron: string;
154
+ } | undefined;
155
+ readonly webhook?: {
156
+ method: string;
157
+ port?: number | undefined;
158
+ } | undefined;
159
+ readonly websocket?: {
160
+ readonly url: string;
161
+ readonly init?: {
162
+ readonly [x: string]: any;
163
+ } | undefined;
164
+ } | undefined;
165
+ readonly subscription?: {
166
+ readonly filter: readonly {
167
+ readonly type: string;
168
+ readonly props?: {
169
+ readonly [x: string]: any;
170
+ } | undefined;
171
+ }[];
172
+ readonly spaceKey?: string | undefined;
173
+ readonly options?: {
174
+ readonly deep?: boolean | undefined;
175
+ readonly delay?: number | undefined;
176
+ } | undefined;
177
+ } | undefined;
178
+ }[] | undefined, never>;
179
+ }>;
180
+ export type FunctionManifest = S.Schema.Type<typeof FunctionManifestSchema>;
181
+ export {};
182
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/types.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,CAAC,MAAM,uBAAuB,CAAC;AAE3C,QAAA,MAAM,kBAAkB;;EAEtB,CAAC;AAEH,QAAA,MAAM,oBAAoB;;;GAMzB,CAAC;AAEF,QAAA,MAAM,sBAAsB;;;;;;;EAG1B,CAAC;AAEH,QAAA,MAAM,yBAAyB;;;;;;;;;;;;;;;;;EAiB7B,CAAC;AAEH,QAAA,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAWzB,CAAC;AAEH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAE1E,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,kBAAkB,CAAC,CAAC;AACpE,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,oBAAoB,CAAC,CAAC;AACxE,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAC5E,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,yBAAyB,CAAC,CAAC;AAElF;;GAEG;AAEH,QAAA,MAAM,iBAAiB;;;;;EAQrB,CAAC;AAEH,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAElE;;GAEG;AACH,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAGjC,CAAC;AAEH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,sBAAsB,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../tools/schema.ts"],"names":[],"mappings":""}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dxos/functions",
3
- "version": "0.5.2",
3
+ "version": "0.5.3-main.088a2c8",
4
4
  "description": "Functions SDK and runtime.",
5
5
  "homepage": "https://dxos.org",
6
6
  "bugs": "https://github.com/dxos/dxos/issues",
@@ -16,27 +16,36 @@
16
16
  "types": "dist/types/src/index.d.ts",
17
17
  "files": [
18
18
  "dist",
19
+ "schema",
19
20
  "src"
20
21
  ],
21
22
  "dependencies": {
23
+ "@effect/schema": "^0.64.20",
22
24
  "@preact/signals-core": "^1.6.0",
23
25
  "cron": "^3.1.6",
26
+ "effect": "^2.4.19",
24
27
  "express": "^4.19.2",
25
28
  "get-port-please": "^3.1.1",
26
- "@braneframe/types": "0.5.2",
27
- "@dxos/async": "0.5.2",
28
- "@dxos/client": "0.5.2",
29
- "@dxos/context": "0.5.2",
30
- "@dxos/echo-schema": "0.5.2",
31
- "@dxos/invariant": "0.5.2",
32
- "@dxos/log": "0.5.2",
33
- "@dxos/node-std": "0.5.2",
34
- "@dxos/util": "0.5.2"
29
+ "ws": "^8.14.2",
30
+ "@braneframe/types": "0.5.3-main.088a2c8",
31
+ "@dxos/async": "0.5.3-main.088a2c8",
32
+ "@dxos/context": "0.5.3-main.088a2c8",
33
+ "@dxos/echo-schema": "0.5.3-main.088a2c8",
34
+ "@dxos/invariant": "0.5.3-main.088a2c8",
35
+ "@dxos/client": "0.5.3-main.088a2c8",
36
+ "@dxos/node-std": "0.5.3-main.088a2c8",
37
+ "@dxos/log": "0.5.3-main.088a2c8",
38
+ "@dxos/util": "0.5.3-main.088a2c8"
35
39
  },
36
40
  "devDependencies": {
37
- "@types/express": "^4.17.17"
41
+ "@types/express": "^4.17.17",
42
+ "@types/ws": "^7.4.0",
43
+ "@dxos/agent": "0.5.3-main.088a2c8"
38
44
  },
39
45
  "publishConfig": {
40
46
  "access": "public"
47
+ },
48
+ "scripts": {
49
+ "gen-schema": "ts-node ./tools/schema.ts"
41
50
  }
42
51
  }
@@ -0,0 +1,183 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "type": "object",
4
+ "required": [
5
+ "functions"
6
+ ],
7
+ "properties": {
8
+ "functions": {
9
+ "type": "array",
10
+ "items": {
11
+ "type": "object",
12
+ "required": [
13
+ "id",
14
+ "path",
15
+ "handler"
16
+ ],
17
+ "properties": {
18
+ "id": {
19
+ "type": "string",
20
+ "description": "a string",
21
+ "title": "string"
22
+ },
23
+ "path": {
24
+ "type": "string",
25
+ "description": "a string",
26
+ "title": "string"
27
+ },
28
+ "handler": {
29
+ "type": "string",
30
+ "description": "a string",
31
+ "title": "string"
32
+ },
33
+ "description": {
34
+ "type": "string",
35
+ "description": "a string",
36
+ "title": "string"
37
+ }
38
+ },
39
+ "additionalProperties": false
40
+ }
41
+ },
42
+ "triggers": {
43
+ "type": "array",
44
+ "items": {
45
+ "type": "object",
46
+ "required": [
47
+ "function"
48
+ ],
49
+ "properties": {
50
+ "function": {
51
+ "type": "string",
52
+ "description": "Function ID/URI.",
53
+ "title": "string"
54
+ },
55
+ "meta": {
56
+ "type": "object",
57
+ "required": [],
58
+ "properties": {},
59
+ "additionalProperties": {
60
+ "$id": "/schemas/any",
61
+ "title": "any"
62
+ }
63
+ },
64
+ "timer": {
65
+ "type": "object",
66
+ "required": [
67
+ "cron"
68
+ ],
69
+ "properties": {
70
+ "cron": {
71
+ "type": "string",
72
+ "description": "a string",
73
+ "title": "string"
74
+ }
75
+ },
76
+ "additionalProperties": false
77
+ },
78
+ "webhook": {
79
+ "type": "object",
80
+ "required": [
81
+ "method"
82
+ ],
83
+ "properties": {
84
+ "method": {
85
+ "type": "string",
86
+ "description": "a string",
87
+ "title": "string"
88
+ },
89
+ "port": {
90
+ "type": "number",
91
+ "description": "a number",
92
+ "title": "number"
93
+ }
94
+ },
95
+ "additionalProperties": false
96
+ },
97
+ "websocket": {
98
+ "type": "object",
99
+ "required": [
100
+ "url"
101
+ ],
102
+ "properties": {
103
+ "url": {
104
+ "type": "string",
105
+ "description": "a string",
106
+ "title": "string"
107
+ },
108
+ "init": {
109
+ "type": "object",
110
+ "required": [],
111
+ "properties": {},
112
+ "additionalProperties": {
113
+ "$id": "/schemas/any",
114
+ "title": "any"
115
+ }
116
+ }
117
+ },
118
+ "additionalProperties": false
119
+ },
120
+ "subscription": {
121
+ "type": "object",
122
+ "required": [
123
+ "filter"
124
+ ],
125
+ "properties": {
126
+ "spaceKey": {
127
+ "type": "string",
128
+ "description": "a string",
129
+ "title": "string"
130
+ },
131
+ "filter": {
132
+ "type": "array",
133
+ "items": {
134
+ "type": "object",
135
+ "required": [
136
+ "type"
137
+ ],
138
+ "properties": {
139
+ "type": {
140
+ "type": "string",
141
+ "description": "a string",
142
+ "title": "string"
143
+ },
144
+ "props": {
145
+ "type": "object",
146
+ "required": [],
147
+ "properties": {},
148
+ "additionalProperties": {
149
+ "$id": "/schemas/any",
150
+ "title": "any"
151
+ }
152
+ }
153
+ },
154
+ "additionalProperties": false
155
+ }
156
+ },
157
+ "options": {
158
+ "type": "object",
159
+ "required": [],
160
+ "properties": {
161
+ "deep": {
162
+ "type": "boolean",
163
+ "description": "a boolean",
164
+ "title": "boolean"
165
+ },
166
+ "delay": {
167
+ "type": "number",
168
+ "description": "a number",
169
+ "title": "number"
170
+ }
171
+ },
172
+ "additionalProperties": false
173
+ }
174
+ },
175
+ "additionalProperties": false
176
+ }
177
+ },
178
+ "additionalProperties": false
179
+ }
180
+ }
181
+ },
182
+ "additionalProperties": false
183
+ }
package/src/handler.ts CHANGED
@@ -8,31 +8,61 @@ import { type EchoReactiveObject } from '@dxos/echo-schema';
8
8
  import { log } from '@dxos/log';
9
9
  import { nonNullable } from '@dxos/util';
10
10
 
11
- // TODO(burdon): No response?
12
- export interface Response {
13
- status(code: number): Response;
14
- }
11
+ // TODO(burdon): Model after http request. Ref Lambda/OpenFaaS.
12
+ // https://docs.aws.amazon.com/lambda/latest/dg/typescript-handler.html
13
+ // https://www.serverless.com/framework/docs/providers/aws/guide/serverless.yml/#functions
14
+ // https://www.npmjs.com/package/aws-lambda
15
+
16
+ /**
17
+ * Function handler.
18
+ */
19
+ export type FunctionHandler<TData = {}, TMeta = {}> = (params: {
20
+ context: FunctionContext;
21
+ event: FunctionEvent<TData, TMeta>;
22
+ response: FunctionResponse;
23
+ }) => Promise<FunctionResponse | void>;
15
24
 
16
- // TODO(burdon): Limit access to individual space?
25
+ /**
26
+ * Function context.
27
+ */
17
28
  export interface FunctionContext {
29
+ // TODO(burdon): Limit access to individual space.
18
30
  client: Client;
31
+ // TODO(burdon): Replace with storage service abstraction.
19
32
  dataDir?: string;
20
33
  }
21
34
 
22
- // TODO(burdon): Model after http request. Ref Lambda/OpenFaaS.
23
- // https://docs.aws.amazon.com/lambda/latest/dg/typescript-handler.html
24
- export type FunctionHandler<T extends {}> = (params: {
25
- event: T;
26
- context: FunctionContext;
27
- response: Response;
28
- }) => Promise<Response | void>;
35
+ /**
36
+ * Event payload.
37
+ */
38
+ export type FunctionEvent<TData = {}, TMeta = {}> = {
39
+ data: FunctionEventMeta<TMeta> & TData;
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
+ //
29
59
 
30
- export type FunctionSubscriptionEvent = {
31
- space?: string; // TODO(burdon): Convert to PublicKey.
60
+ export type RawSubscriptionData = {
61
+ spaceKey?: string;
32
62
  objects?: string[];
33
63
  };
34
64
 
35
- export type FunctionSubscriptionEvent2 = {
65
+ export type SubscriptionData = {
36
66
  space?: Space;
37
67
  objects?: EchoReactiveObject<any>[];
38
68
  };
@@ -47,22 +77,22 @@ export type FunctionSubscriptionEvent2 = {
47
77
  *
48
78
  * NOTE: Get space key from devtools or `dx space list --json`
49
79
  */
50
- export const subscriptionHandler = (
51
- handler: FunctionHandler<FunctionSubscriptionEvent2>,
52
- ): FunctionHandler<FunctionSubscriptionEvent> => {
53
- return ({ event, context, ...rest }) => {
80
+ export const subscriptionHandler = <TMeta>(
81
+ handler: FunctionHandler<SubscriptionData, TMeta>,
82
+ ): FunctionHandler<RawSubscriptionData, TMeta> => {
83
+ return ({ event: { data }, context, ...rest }) => {
54
84
  const { client } = context;
55
- const space = event.space ? client.spaces.get(PublicKey.from(event.space)) : undefined;
56
- const objects =
57
- space &&
58
- event.objects?.map<EchoReactiveObject<any> | undefined>((id) => space!.db.getObjectById(id)).filter(nonNullable);
85
+ const space = data.spaceKey ? client.spaces.get(PublicKey.from(data.spaceKey)) : undefined;
86
+ const objects = space
87
+ ? data.objects?.map<EchoReactiveObject<any> | undefined>((id) => space!.db.getObjectById(id)).filter(nonNullable)
88
+ : [];
59
89
 
60
- if (!!event.space && !space) {
61
- log.warn('invalid space', { event });
90
+ if (!!data.spaceKey && !space) {
91
+ log.warn('invalid space', { data });
62
92
  } else {
63
93
  log.info('handler', { space: space?.key.truncate(), objects: objects?.length });
64
94
  }
65
95
 
66
- return handler({ event: { space, objects }, context, ...rest });
96
+ return handler({ event: { data: { ...data, space, objects } }, context, ...rest });
67
97
  };
68
98
  };
package/src/index.ts CHANGED
@@ -3,5 +3,5 @@
3
3
  //
4
4
 
5
5
  export * from './handler';
6
- export * from './manifest';
7
6
  export * from './runtime';
7
+ export * from './types';
@@ -0,0 +1,80 @@
1
+ //
2
+ // Copyright 2023 DXOS.org
3
+ //
4
+
5
+ import { expect } from 'chai';
6
+ import path from 'path';
7
+
8
+ import { FunctionsPlugin } from '@dxos/agent';
9
+ import { Client, Config } from '@dxos/client';
10
+ import { TestBuilder } from '@dxos/client/testing';
11
+ import { describe, openAndClose, test } from '@dxos/test';
12
+
13
+ import { DevServer } from './dev-server';
14
+ import { type FunctionManifest } from '../types';
15
+
16
+ describe('dev server', () => {
17
+ let client: Client;
18
+ let testBuilder: TestBuilder;
19
+ before(async () => {
20
+ testBuilder = new TestBuilder();
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
+
48
+ expect(client.services.services.FunctionRegistryService).to.exist;
49
+ });
50
+ after(async () => {
51
+ await testBuilder.destroy();
52
+ });
53
+
54
+ test('start/stop', async () => {
55
+ const manifest: FunctionManifest = {
56
+ functions: [
57
+ {
58
+ id: 'example.com/function/test',
59
+ path: 'test',
60
+ handler: 'test',
61
+ },
62
+ ],
63
+ };
64
+
65
+ const server = new DevServer(client, {
66
+ manifest,
67
+ baseDir: path.join(__dirname, '../testing'),
68
+ });
69
+ await server.initialize();
70
+ await server.start();
71
+
72
+ // TODO(burdon): Doesn't shut down cleanly.
73
+ // Error: invariant violation [this._client.services.services.FunctionRegistryService]
74
+ testBuilder.ctx.onDispose(() => server.stop());
75
+ expect(server).to.exist;
76
+
77
+ await server.invoke('test', {});
78
+ expect(server.stats.seq).to.eq(1);
79
+ });
80
+ });