@dxos/functions 0.5.3-main.7cd4303 → 0.5.3-main.7e64682

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 (62) hide show
  1. package/dist/lib/browser/chunk-CMMH5BA6.mjs +86 -0
  2. package/dist/lib/browser/chunk-CMMH5BA6.mjs.map +7 -0
  3. package/dist/lib/browser/index.mjs +390 -336
  4. package/dist/lib/browser/index.mjs.map +4 -4
  5. package/dist/lib/browser/meta.json +1 -1
  6. package/dist/lib/browser/types.mjs +14 -0
  7. package/dist/lib/browser/types.mjs.map +7 -0
  8. package/dist/lib/node/chunk-3C2FP4J4.cjs +103 -0
  9. package/dist/lib/node/chunk-3C2FP4J4.cjs.map +7 -0
  10. package/dist/lib/node/index.cjs +393 -333
  11. package/dist/lib/node/index.cjs.map +4 -4
  12. package/dist/lib/node/meta.json +1 -1
  13. package/dist/lib/node/types.cjs +35 -0
  14. package/dist/lib/node/types.cjs.map +7 -0
  15. package/dist/types/src/browser/index.d.ts +2 -0
  16. package/dist/types/src/browser/index.d.ts.map +1 -0
  17. package/dist/types/src/{registry → function}/function-registry.d.ts +4 -4
  18. package/dist/types/src/function/function-registry.d.ts.map +1 -0
  19. package/dist/types/src/function/function-registry.test.d.ts.map +1 -0
  20. package/dist/types/src/function/index.d.ts.map +1 -0
  21. package/dist/types/src/handler.d.ts.map +1 -1
  22. package/dist/types/src/index.d.ts +1 -1
  23. package/dist/types/src/index.d.ts.map +1 -1
  24. package/dist/types/src/runtime/dev-server.d.ts +1 -1
  25. package/dist/types/src/runtime/dev-server.d.ts.map +1 -1
  26. package/dist/types/src/runtime/scheduler.d.ts +2 -1
  27. package/dist/types/src/runtime/scheduler.d.ts.map +1 -1
  28. package/dist/types/src/testing/setup.d.ts.map +1 -1
  29. package/dist/types/src/trigger/trigger-registry.d.ts +2 -5
  30. package/dist/types/src/trigger/trigger-registry.d.ts.map +1 -1
  31. package/dist/types/src/trigger/type/subscription-trigger.d.ts.map +1 -1
  32. package/dist/types/src/trigger/type/timer-trigger.d.ts.map +1 -1
  33. package/dist/types/src/trigger/type/webhook-trigger.d.ts.map +1 -1
  34. package/dist/types/src/trigger/type/websocket-trigger.d.ts.map +1 -1
  35. package/dist/types/src/types.d.ts +67 -43
  36. package/dist/types/src/types.d.ts.map +1 -1
  37. package/package.json +31 -18
  38. package/schema/functions.json +23 -9
  39. package/src/browser/index.ts +5 -0
  40. package/src/{registry → function}/function-registry.test.ts +10 -10
  41. package/src/function/function-registry.ts +90 -0
  42. package/src/index.ts +1 -1
  43. package/src/runtime/dev-server.test.ts +2 -2
  44. package/src/runtime/dev-server.ts +8 -9
  45. package/src/runtime/scheduler.test.ts +15 -10
  46. package/src/runtime/scheduler.ts +26 -13
  47. package/src/testing/functions-integration.test.ts +2 -1
  48. package/src/testing/setup.ts +8 -10
  49. package/src/trigger/trigger-registry.test.ts +88 -45
  50. package/src/trigger/trigger-registry.ts +66 -31
  51. package/src/trigger/type/subscription-trigger.ts +30 -17
  52. package/src/trigger/type/timer-trigger.ts +4 -3
  53. package/src/trigger/type/webhook-trigger.ts +3 -2
  54. package/src/trigger/type/websocket-trigger.ts +4 -3
  55. package/src/types.ts +48 -37
  56. package/dist/types/src/registry/function-registry.d.ts.map +0 -1
  57. package/dist/types/src/registry/function-registry.test.d.ts.map +0 -1
  58. package/dist/types/src/registry/index.d.ts.map +0 -1
  59. package/src/registry/function-registry.ts +0 -84
  60. /package/dist/types/src/{registry → function}/function-registry.test.d.ts +0 -0
  61. /package/dist/types/src/{registry → function}/index.d.ts +0 -0
  62. /package/src/{registry → function}/index.ts +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"timer-trigger.d.ts","sourceRoot":"","sources":["../../../../../src/trigger/type/timer-trigger.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAA6C,KAAK,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAErG,eAAO,MAAM,kBAAkB,EAAE,cAAc,CAAC,YAAY,CA8B3D,CAAC"}
1
+ {"version":3,"file":"timer-trigger.d.ts","sourceRoot":"","sources":["../../../../../src/trigger/type/timer-trigger.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAwB,KAAK,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAEhF,eAAO,MAAM,kBAAkB,EAAE,cAAc,CAAC,YAAY,CA8B3D,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"webhook-trigger.d.ts","sourceRoot":"","sources":["../../../../../src/trigger/type/webhook-trigger.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAA6C,KAAK,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAErG,eAAO,MAAM,oBAAoB,EAAE,cAAc,CAAC,cAAc,CAiC/D,CAAC"}
1
+ {"version":3,"file":"webhook-trigger.d.ts","sourceRoot":"","sources":["../../../../../src/trigger/type/webhook-trigger.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAwB,KAAK,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAEhF,eAAO,MAAM,oBAAoB,EAAE,cAAc,CAAC,cAAc,CAiC/D,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"websocket-trigger.d.ts","sourceRoot":"","sources":["../../../../../src/trigger/type/websocket-trigger.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAA6C,KAAK,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAErG,UAAU,uBAAuB;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;GAGG;AACH,eAAO,MAAM,sBAAsB,EAAE,cAAc,CAAC,gBAAgB,EAAE,uBAAuB,CAoE5F,CAAC"}
1
+ {"version":3,"file":"websocket-trigger.d.ts","sourceRoot":"","sources":["../../../../../src/trigger/type/websocket-trigger.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAwB,KAAK,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAEhF,UAAU,uBAAuB;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;GAGG;AACH,eAAO,MAAM,sBAAsB,EAAE,cAAc,CAAC,gBAAgB,EAAE,uBAAuB,CAoE5F,CAAC"}
@@ -6,7 +6,7 @@ import { S } from '@dxos/echo-schema';
6
6
  * https://www.typescriptlang.org/docs/handbook/2/narrowing.html#discriminated-unions
7
7
  */
8
8
  export type FunctionTriggerType = 'subscription' | 'timer' | 'webhook' | 'websocket';
9
- declare const SubscriptionTriggerSchema: S.struct<{
9
+ declare const SubscriptionTriggerSchema: S.mutable<S.struct<{
10
10
  type: S.literal<["subscription"]>;
11
11
  filter: S.array<S.struct<{
12
12
  type: S.$string;
@@ -23,12 +23,12 @@ declare const SubscriptionTriggerSchema: S.struct<{
23
23
  readonly deep?: boolean | undefined;
24
24
  readonly delay?: number | undefined;
25
25
  } | undefined, never>;
26
- }>;
26
+ }>>;
27
27
  export type SubscriptionTrigger = S.Schema.Type<typeof SubscriptionTriggerSchema>;
28
- declare const TimerTriggerSchema: S.struct<{
28
+ declare const TimerTriggerSchema: S.mutable<S.struct<{
29
29
  type: S.literal<["timer"]>;
30
30
  cron: S.$string;
31
- }>;
31
+ }>>;
32
32
  export type TimerTrigger = S.Schema.Type<typeof TimerTriggerSchema>;
33
33
  declare const WebhookTriggerSchema: S.mutable<S.struct<{
34
34
  type: S.literal<["webhook"]>;
@@ -36,7 +36,7 @@ declare const WebhookTriggerSchema: S.mutable<S.struct<{
36
36
  port: S.PropertySignature<"?:", number | undefined, never, "?:", number | undefined, never>;
37
37
  }>>;
38
38
  export type WebhookTrigger = S.Schema.Type<typeof WebhookTriggerSchema>;
39
- declare const WebsocketTriggerSchema: S.struct<{
39
+ declare const WebsocketTriggerSchema: S.mutable<S.struct<{
40
40
  type: S.literal<["websocket"]>;
41
41
  url: S.$string;
42
42
  init: S.PropertySignature<"?:", {
@@ -44,7 +44,7 @@ declare const WebsocketTriggerSchema: S.struct<{
44
44
  } | undefined, never, "?:", {
45
45
  readonly [x: string]: any;
46
46
  } | undefined, never>;
47
- }>;
47
+ }>>;
48
48
  export type WebsocketTrigger = S.Schema.Type<typeof WebsocketTriggerSchema>;
49
49
  export type TriggerSpec = TimerTrigger | WebhookTrigger | WebsocketTrigger | SubscriptionTrigger;
50
50
  declare const FunctionDef_base: import("@dxos/echo-schema").EchoSchemaClass<{
@@ -62,32 +62,33 @@ export declare class FunctionDef extends FunctionDef_base {
62
62
  }
63
63
  declare const FunctionTrigger_base: import("@dxos/echo-schema").EchoSchemaClass<{
64
64
  function: string;
65
+ enabled?: boolean | undefined;
65
66
  meta?: {
66
- readonly [x: string]: any;
67
+ [x: string]: any;
67
68
  } | undefined;
68
69
  spec: {
69
- readonly filter: readonly {
70
+ filter: readonly {
70
71
  readonly type: string;
71
72
  readonly props?: {
72
73
  readonly [x: string]: any;
73
74
  } | undefined;
74
75
  }[];
75
- readonly type: "subscription";
76
- readonly options?: {
76
+ type: "subscription";
77
+ options?: {
77
78
  readonly deep?: boolean | undefined;
78
79
  readonly delay?: number | undefined;
79
80
  } | undefined;
80
81
  } | {
81
- readonly type: "timer";
82
- readonly cron: string;
82
+ type: "timer";
83
+ cron: string;
83
84
  } | {
84
85
  port?: number | undefined;
85
86
  type: "webhook";
86
87
  method: string;
87
88
  } | {
88
- readonly type: "websocket";
89
- readonly url: string;
90
- readonly init?: {
89
+ type: "websocket";
90
+ url: string;
91
+ init?: {
91
92
  readonly [x: string]: any;
92
93
  } | undefined;
93
94
  };
@@ -100,89 +101,112 @@ export declare class FunctionTrigger extends FunctionTrigger_base {
100
101
  * Function manifest file.
101
102
  */
102
103
  export declare const FunctionManifestSchema: S.struct<{
103
- functions: S.PropertySignature<"?:", Omit<{
104
+ functions: S.PropertySignature<"?:", ({
104
105
  handler: string;
105
106
  uri: string;
106
107
  description?: string | undefined;
107
108
  route: string;
108
109
  } & {
109
- id: string;
110
- }, "id">[] | undefined, never, "?:", Omit<{
110
+ "@meta"?: {
111
+ readonly keys: {
112
+ readonly id: string;
113
+ readonly source: string;
114
+ }[];
115
+ } | undefined;
116
+ })[] | undefined, never, "?:", ({
111
117
  handler: string;
112
118
  uri: string;
113
119
  description?: string | undefined;
114
120
  route: string;
115
121
  } & {
116
- id: string;
117
- }, "id">[] | undefined, never>;
118
- triggers: S.PropertySignature<"?:", Omit<{
122
+ "@meta"?: {
123
+ readonly keys: {
124
+ readonly id: string;
125
+ readonly source: string;
126
+ }[];
127
+ } | undefined;
128
+ })[] | undefined, never>;
129
+ triggers: S.PropertySignature<"?:", ({
119
130
  function: string;
131
+ enabled?: boolean | undefined;
120
132
  meta?: {
121
- readonly [x: string]: any;
133
+ [x: string]: any;
122
134
  } | undefined;
123
135
  spec: {
124
- readonly filter: readonly {
136
+ filter: readonly {
125
137
  readonly type: string;
126
138
  readonly props?: {
127
139
  readonly [x: string]: any;
128
140
  } | undefined;
129
141
  }[];
130
- readonly type: "subscription";
131
- readonly options?: {
142
+ type: "subscription";
143
+ options?: {
132
144
  readonly deep?: boolean | undefined;
133
145
  readonly delay?: number | undefined;
134
146
  } | undefined;
135
147
  } | {
136
- readonly type: "timer";
137
- readonly cron: string;
148
+ type: "timer";
149
+ cron: string;
138
150
  } | {
139
151
  port?: number | undefined;
140
152
  type: "webhook";
141
153
  method: string;
142
154
  } | {
143
- readonly type: "websocket";
144
- readonly url: string;
145
- readonly init?: {
155
+ type: "websocket";
156
+ url: string;
157
+ init?: {
146
158
  readonly [x: string]: any;
147
159
  } | undefined;
148
160
  };
149
161
  } & {
150
- id: string;
151
- }, "id">[] | undefined, never, "?:", Omit<{
162
+ "@meta"?: {
163
+ readonly keys: {
164
+ readonly id: string;
165
+ readonly source: string;
166
+ }[];
167
+ } | undefined;
168
+ })[] | undefined, never, "?:", ({
152
169
  function: string;
170
+ enabled?: boolean | undefined;
153
171
  meta?: {
154
- readonly [x: string]: any;
172
+ [x: string]: any;
155
173
  } | undefined;
156
174
  spec: {
157
- readonly filter: readonly {
175
+ filter: readonly {
158
176
  readonly type: string;
159
177
  readonly props?: {
160
178
  readonly [x: string]: any;
161
179
  } | undefined;
162
180
  }[];
163
- readonly type: "subscription";
164
- readonly options?: {
181
+ type: "subscription";
182
+ options?: {
165
183
  readonly deep?: boolean | undefined;
166
184
  readonly delay?: number | undefined;
167
185
  } | undefined;
168
186
  } | {
169
- readonly type: "timer";
170
- readonly cron: string;
187
+ type: "timer";
188
+ cron: string;
171
189
  } | {
172
190
  port?: number | undefined;
173
191
  type: "webhook";
174
192
  method: string;
175
193
  } | {
176
- readonly type: "websocket";
177
- readonly url: string;
178
- readonly init?: {
194
+ type: "websocket";
195
+ url: string;
196
+ init?: {
179
197
  readonly [x: string]: any;
180
198
  } | undefined;
181
199
  };
182
200
  } & {
183
- id: string;
184
- }, "id">[] | undefined, never>;
201
+ "@meta"?: {
202
+ readonly keys: {
203
+ readonly id: string;
204
+ readonly source: string;
205
+ }[];
206
+ } | undefined;
207
+ })[] | undefined, never>;
185
208
  }>;
186
209
  export type FunctionManifest = S.Schema.Type<typeof FunctionManifestSchema>;
210
+ export declare const FUNCTION_SCHEMA: (typeof FunctionDef | typeof FunctionTrigger)[];
187
211
  export {};
188
212
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/types.ts"],"names":[],"mappings":"AAIA,OAAO,EAAO,CAAC,EAAe,MAAM,mBAAmB,CAAC;AAKxD;;;;;GAKG;AACH,MAAM,MAAM,mBAAmB,GAAG,cAAc,GAAG,OAAO,GAAG,SAAS,GAAG,WAAW,CAAC;AAErF,QAAA,MAAM,yBAAyB;;;;;;;;;;;;;;;;;EAiB7B,CAAC;AACH,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,yBAAyB,CAAC,CAAC;AAElF,QAAA,MAAM,kBAAkB;;;EAGtB,CAAC;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAEpE,QAAA,MAAM,oBAAoB;;;;GAOzB,CAAC;AACF,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAExE,QAAA,MAAM,sBAAsB;;;;;;;;EAI1B,CAAC;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAQ5E,MAAM,MAAM,WAAW,GAAG,YAAY,GAAG,cAAc,GAAG,gBAAgB,GAAG,mBAAmB,CAAC;;;;;;;;;AAEjG;;GAEG;AACH,qBAAa,WAAY,SAAQ,gBAS/B;CAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEL,qBAAa,eAAgB,SAAQ,oBAQnC;CAAG;AAEL;;GAEG;AACH,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAGjC,CAAC;AAEH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,sBAAsB,CAAC,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/types.ts"],"names":[],"mappings":"AAIA,OAAO,EAAa,CAAC,EAAe,MAAM,mBAAmB,CAAC;AAE9D;;;;;GAKG;AACH,MAAM,MAAM,mBAAmB,GAAG,cAAc,GAAG,OAAO,GAAG,SAAS,GAAG,WAAW,CAAC;AAErF,QAAA,MAAM,yBAAyB;;;;;;;;;;;;;;;;;GAmB9B,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,yBAAyB,CAAC,CAAC;AAElF,QAAA,MAAM,kBAAkB;;;GAKvB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAEpE,QAAA,MAAM,oBAAoB;;;;GAOzB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAExE,QAAA,MAAM,sBAAsB;;;;;;;;GAM3B,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAS5E,MAAM,MAAM,WAAW,GAAG,YAAY,GAAG,cAAc,GAAG,gBAAgB,GAAG,mBAAmB,CAAC;;;;;;;;;AAEjG;;GAEG;AACH,qBAAa,WAAY,SAAQ,gBAQ/B;CAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEL,qBAAa,eAAgB,SAAQ,oBASnC;CAAG;AAEL;;GAEG;AACH,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAGjC,CAAC;AAEH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAG5E,eAAO,MAAM,eAAe,iDAAiC,CAAC"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@dxos/functions",
3
- "version": "0.5.3-main.7cd4303",
4
- "description": "Functions SDK and runtime.",
3
+ "version": "0.5.3-main.7e64682",
4
+ "description": "Functions API and runtime.",
5
5
  "homepage": "https://dxos.org",
6
6
  "bugs": "https://github.com/dxos/dxos/issues",
7
7
  "license": "MIT",
@@ -10,10 +10,24 @@
10
10
  ".": {
11
11
  "browser": "./dist/lib/browser/index.mjs",
12
12
  "node": "./dist/lib/node/index.cjs",
13
- "default": "./dist/lib/node/index.cjs"
13
+ "default": "./dist/lib/node/index.cjs",
14
+ "types": "./dist/types/src/index.d.ts"
15
+ },
16
+ "./types": {
17
+ "browser": "./dist/lib/browser/types.mjs",
18
+ "node": "./dist/lib/node/types.cjs",
19
+ "default": "./dist/lib/node/types.cjs",
20
+ "types": "./dist/types/src/types.d.ts"
14
21
  }
15
22
  },
16
23
  "types": "dist/types/src/index.d.ts",
24
+ "typesVersions": {
25
+ "*": {
26
+ "types": [
27
+ "dist/types/src/types.d.ts"
28
+ ]
29
+ }
30
+ },
17
31
  "files": [
18
32
  "dist",
19
33
  "schema",
@@ -26,29 +40,28 @@
26
40
  "express": "^4.19.2",
27
41
  "get-port-please": "^3.1.1",
28
42
  "ws": "^8.14.2",
29
- "@braneframe/types": "0.5.3-main.7cd4303",
30
- "@dxos/async": "0.5.3-main.7cd4303",
31
- "@dxos/context": "0.5.3-main.7cd4303",
32
- "@dxos/echo-db": "0.5.3-main.7cd4303",
33
- "@dxos/client": "0.5.3-main.7cd4303",
34
- "@dxos/echo-schema": "0.5.3-main.7cd4303",
35
- "@dxos/invariant": "0.5.3-main.7cd4303",
36
- "@dxos/keys": "0.5.3-main.7cd4303",
37
- "@dxos/node-std": "0.5.3-main.7cd4303",
38
- "@dxos/log": "0.5.3-main.7cd4303",
39
- "@dxos/protocols": "0.5.3-main.7cd4303",
40
- "@dxos/util": "0.5.3-main.7cd4303"
43
+ "@braneframe/types": "0.5.3-main.7e64682",
44
+ "@dxos/async": "0.5.3-main.7e64682",
45
+ "@dxos/client": "0.5.3-main.7e64682",
46
+ "@dxos/context": "0.5.3-main.7e64682",
47
+ "@dxos/echo-db": "0.5.3-main.7e64682",
48
+ "@dxos/echo-schema": "0.5.3-main.7e64682",
49
+ "@dxos/invariant": "0.5.3-main.7e64682",
50
+ "@dxos/keys": "0.5.3-main.7e64682",
51
+ "@dxos/log": "0.5.3-main.7e64682",
52
+ "@dxos/protocols": "0.5.3-main.7e64682",
53
+ "@dxos/node-std": "0.5.3-main.7e64682",
54
+ "@dxos/util": "0.5.3-main.7e64682"
41
55
  },
42
56
  "devDependencies": {
43
57
  "@types/express": "^4.17.17",
44
58
  "@types/ws": "^7.4.0",
45
- "@dxos/agent": "0.5.3-main.7cd4303"
59
+ "@dxos/agent": "0.5.3-main.7e64682"
46
60
  },
47
61
  "publishConfig": {
48
62
  "access": "public"
49
63
  },
50
64
  "scripts": {
51
- "gen-schema": "ts-node ./tools/schema.ts",
52
- "prebuild": "pnpm gen-schema"
65
+ "gen-schema": "ts-node ./tools/schema.ts"
53
66
  }
54
67
  }
@@ -48,17 +48,16 @@
48
48
  "properties": {
49
49
  "function": {
50
50
  "type": "string",
51
- "description": "Function ID/URI.",
51
+ "description": "Function URI.",
52
52
  "title": "string"
53
53
  },
54
+ "enabled": {
55
+ "type": "boolean",
56
+ "description": "a boolean",
57
+ "title": "boolean"
58
+ },
54
59
  "meta": {
55
- "type": "object",
56
- "required": [],
57
- "properties": {},
58
- "additionalProperties": {
59
- "$id": "/schemas/any",
60
- "title": "any"
61
- }
60
+ "$ref": "#/$defs/object"
62
61
  },
63
62
  "spec": {
64
63
  "anyOf": [
@@ -193,5 +192,20 @@
193
192
  }
194
193
  }
195
194
  },
196
- "additionalProperties": false
195
+ "additionalProperties": false,
196
+ "$defs": {
197
+ "object": {
198
+ "$id": "/schemas/object",
199
+ "oneOf": [
200
+ {
201
+ "type": "object"
202
+ },
203
+ {
204
+ "type": "array"
205
+ }
206
+ ],
207
+ "description": "an object in the TypeScript meaning, i.e. the `object` type",
208
+ "title": "object"
209
+ }
210
+ }
197
211
  }
@@ -0,0 +1,5 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ export * from '../types';
@@ -44,7 +44,7 @@ describe('function registry', () => {
44
44
  const client = (await createInitializedClients(testBuilder))[0];
45
45
  const registry = createRegistry(client);
46
46
  const space = await client.spaces.create();
47
- await registry.register(space, testManifest);
47
+ await registry.register(space, testManifest.functions);
48
48
  const { objects: definitions } = await space.db.query(Filter.schema(FunctionDef)).run();
49
49
  expect(definitions.length).to.eq(1);
50
50
  expect(definitions[0].uri).to.eq(testManifest.functions?.[0]?.uri);
@@ -54,8 +54,8 @@ describe('function registry', () => {
54
54
  const client = (await createInitializedClients(testBuilder))[0];
55
55
  const registry = createRegistry(client);
56
56
  const space = await client.spaces.create();
57
- const existing = space.db.add(create(FunctionDef, { ...testManifest.functions![0] }));
58
- await registry.register(space, testManifest);
57
+ const existing = space.db.add(create(FunctionDef, testManifest.functions![0]));
58
+ await registry.register(space, testManifest.functions);
59
59
  const { objects: definitions } = await space.db.query(Filter.schema(FunctionDef)).run();
60
60
  expect(definitions.length).to.eq(1);
61
61
  expect(definitions[0].uri).to.eq(existing.uri);
@@ -67,12 +67,12 @@ describe('function registry', () => {
67
67
  const client = (await createInitializedClients(testBuilder))[0];
68
68
  const registry = createRegistry(client);
69
69
  const space = await client.spaces.create();
70
- const definitions = range(3, () => create(FunctionDef, { ...testManifest.functions![0] }));
70
+ const definitions = range(3, () => create(FunctionDef, testManifest.functions![0]));
71
71
  definitions.forEach((def) => space.db.add(def));
72
72
 
73
73
  const functionRegistered = new Trigger<FunctionDef[]>();
74
- registry.onFunctionsRegistered.on((fn) => {
75
- functionRegistered.wake(fn.newFunctions);
74
+ registry.registered.on((fn) => {
75
+ functionRegistered.wake(fn.added);
76
76
  });
77
77
  void registry.open(ctx);
78
78
  const functions = await functionRegistered.wait();
@@ -86,12 +86,12 @@ describe('function registry', () => {
86
86
  const space = await client.spaces.create();
87
87
 
88
88
  const functionRegistered = new Trigger<FunctionDef>();
89
- registry.onFunctionsRegistered.on((fn) => {
90
- expect(fn.newFunctions.length).to.eq(1);
91
- functionRegistered.wake(fn.newFunctions[0]);
89
+ registry.registered.on((fn) => {
90
+ expect(fn.added.length).to.eq(1);
91
+ functionRegistered.wake(fn.added[0]);
92
92
  });
93
93
  await registry.open(ctx);
94
- await registry.register(space, testManifest);
94
+ await registry.register(space, testManifest.functions);
95
95
  const registered = await functionRegistered.wait();
96
96
  expect(registered.uri).to.eq(testManifest.functions![0].uri);
97
97
  });
@@ -0,0 +1,90 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import { Event } from '@dxos/async';
6
+ import { type Client } from '@dxos/client';
7
+ import { create, Filter, type Space } from '@dxos/client/echo';
8
+ import { type Context, Resource } from '@dxos/context';
9
+ import { PublicKey } from '@dxos/keys';
10
+ import { log } from '@dxos/log';
11
+ import { ComplexMap, diff } from '@dxos/util';
12
+
13
+ import { FunctionDef, type FunctionManifest } from '../types';
14
+
15
+ export type FunctionsRegisteredEvent = {
16
+ space: Space;
17
+ added: FunctionDef[];
18
+ };
19
+
20
+ export class FunctionRegistry extends Resource {
21
+ private readonly _functionBySpaceKey = new ComplexMap<PublicKey, FunctionDef[]>(PublicKey.hash);
22
+
23
+ public readonly registered = new Event<FunctionsRegisteredEvent>();
24
+
25
+ constructor(private readonly _client: Client) {
26
+ super();
27
+ }
28
+
29
+ public getFunctions(space: Space): FunctionDef[] {
30
+ return this._functionBySpaceKey.get(space.key) ?? [];
31
+ }
32
+
33
+ /**
34
+ * Loads function definitions from the manifest into the space.
35
+ * We first load all the definitions from the space to deduplicate by functionId.
36
+ */
37
+ public async register(space: Space, functions: FunctionManifest['functions']): Promise<void> {
38
+ log('register', { space: space.key, functions: functions?.length ?? 0 });
39
+ if (!functions?.length) {
40
+ return;
41
+ }
42
+ if (!space.db.graph.runtimeSchemaRegistry.hasSchema(FunctionDef)) {
43
+ space.db.graph.runtimeSchemaRegistry.registerSchema(FunctionDef);
44
+ }
45
+
46
+ // Sync definitions.
47
+ const { objects: existing } = await space.db.query(Filter.schema(FunctionDef)).run();
48
+ const { added } = diff(existing, functions, (a, b) => a.uri === b.uri);
49
+ // TODO(burdon): Update existing templates.
50
+ added.forEach((def) => space.db.add(create(FunctionDef, def)));
51
+ }
52
+
53
+ protected override async _open(): Promise<void> {
54
+ log.info('opening...');
55
+ const spacesSubscription = this._client.spaces.subscribe(async (spaces) => {
56
+ for (const space of spaces) {
57
+ if (this._functionBySpaceKey.has(space.key)) {
58
+ continue;
59
+ }
60
+
61
+ const registered: FunctionDef[] = [];
62
+ this._functionBySpaceKey.set(space.key, registered);
63
+ await space.waitUntilReady();
64
+ if (this._ctx.disposed) {
65
+ break;
66
+ }
67
+
68
+ // Subscribe to updates.
69
+ this._ctx.onDispose(
70
+ space.db.query(Filter.schema(FunctionDef)).subscribe(({ objects }) => {
71
+ const { added } = diff(registered, objects, (a, b) => a.uri === b.uri);
72
+ // TODO(burdon): Update and remove.
73
+ if (added.length > 0) {
74
+ registered.push(...added);
75
+ this.registered.emit({ space, added });
76
+ }
77
+ }),
78
+ );
79
+ }
80
+ });
81
+
82
+ // TODO(burdon): API: Normalize unsubscribe methods.
83
+ this._ctx.onDispose(() => spacesSubscription.unsubscribe());
84
+ }
85
+
86
+ protected override async _close(_: Context): Promise<void> {
87
+ log.info('closing...');
88
+ this._functionBySpaceKey.clear();
89
+ }
90
+ }
package/src/index.ts CHANGED
@@ -2,8 +2,8 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
+ export * from './function';
5
6
  export * from './handler';
6
- export * from './registry';
7
7
  export * from './runtime';
8
8
  export * from './trigger';
9
9
  export * from './types';
@@ -11,7 +11,7 @@ import { TestBuilder } from '@dxos/client/testing';
11
11
  import { describe, test } from '@dxos/test';
12
12
 
13
13
  import { DevServer } from './dev-server';
14
- import { FunctionRegistry } from '../registry';
14
+ import { FunctionRegistry } from '../function';
15
15
  import { createFunctionRuntime } from '../testing';
16
16
  import { type FunctionManifest } from '../types';
17
17
 
@@ -44,7 +44,7 @@ describe('dev server', () => {
44
44
  baseDir: path.join(__dirname, '../testing'),
45
45
  });
46
46
  const space = await client.spaces.create();
47
- await registry.register(space, manifest);
47
+ await registry.register(space, manifest.functions);
48
48
  await server.start();
49
49
 
50
50
  // TODO(burdon): Doesn't shut down cleanly.
@@ -13,8 +13,8 @@ import { Context } from '@dxos/context';
13
13
  import { invariant } from '@dxos/invariant';
14
14
  import { log } from '@dxos/log';
15
15
 
16
+ import { type FunctionRegistry } from '../function';
16
17
  import { type FunctionContext, type FunctionEvent, type FunctionHandler, type FunctionResponse } from '../handler';
17
- import { type FunctionRegistry } from '../registry';
18
18
  import { type FunctionDef } from '../types';
19
19
 
20
20
  export type DevServerOptions = {
@@ -41,16 +41,16 @@ export class DevServer {
41
41
 
42
42
  public readonly update = new Event<number>();
43
43
 
44
- // prettier-ignore
45
44
  constructor(
46
45
  private readonly _client: Client,
47
46
  private readonly _functionsRegistry: FunctionRegistry,
48
47
  private readonly _options: DevServerOptions,
49
48
  ) {
50
- this._functionsRegistry.onFunctionsRegistered.on(async ({ newFunctions }) => {
51
- newFunctions.forEach((def) => this._load(def));
49
+ // TODO(burdon): Add/remove listener in start/stop.
50
+ this._functionsRegistry.registered.on(async ({ added }) => {
51
+ added.forEach((def) => this._load(def));
52
52
  await this._safeUpdateRegistration();
53
- log('new functions loaded', { newFunctions });
53
+ log('new functions loaded', { added });
54
54
  });
55
55
  }
56
56
 
@@ -158,7 +158,7 @@ export class DevServer {
158
158
  /**
159
159
  * Load function.
160
160
  */
161
- private async _load(def: FunctionDef, force = false) {
161
+ private async _load(def: FunctionDef, force?: boolean | undefined) {
162
162
  const { uri, route, handler } = def;
163
163
  const filePath = join(this._options.baseDir, handler);
164
164
  log.info('loading', { uri, force });
@@ -189,8 +189,8 @@ export class DevServer {
189
189
  registrationId: this._functionServiceRegistration,
190
190
  functions: this.functions.map(({ def: { id, route } }) => ({ id, route })),
191
191
  });
192
- } catch (e) {
193
- log.catch(e);
192
+ } catch (err) {
193
+ log.catch(err);
194
194
  }
195
195
  }
196
196
 
@@ -212,7 +212,6 @@ export class DevServer {
212
212
  private async _invoke(path: string, event: FunctionEvent) {
213
213
  const { handler } = this._handlers[path] ?? {};
214
214
  invariant(handler, `invalid path: ${path}`);
215
-
216
215
  const context: FunctionContext = {
217
216
  client: this._client,
218
217
  dataDir: this._options.dataDir,