@dxos/functions 0.5.3-main.37bbd91 → 0.5.3-main.3b535c7

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 (95) hide show
  1. package/dist/lib/browser/index.mjs +471 -825
  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 +461 -805
  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 +12 -33
  8. package/dist/types/src/handler.d.ts.map +1 -1
  9. package/dist/types/src/index.d.ts +0 -2
  10. package/dist/types/src/index.d.ts.map +1 -1
  11. package/dist/types/src/runtime/dev-server.d.ts +13 -16
  12. package/dist/types/src/runtime/dev-server.d.ts.map +1 -1
  13. package/dist/types/src/runtime/scheduler.d.ts +27 -13
  14. package/dist/types/src/runtime/scheduler.d.ts.map +1 -1
  15. package/dist/types/src/types.d.ts +101 -143
  16. package/dist/types/src/types.d.ts.map +1 -1
  17. package/package.json +15 -33
  18. package/schema/functions.json +104 -140
  19. package/src/handler.ts +31 -54
  20. package/src/index.ts +0 -2
  21. package/src/runtime/dev-server.ts +53 -104
  22. package/src/runtime/scheduler.test.ts +73 -56
  23. package/src/runtime/scheduler.ts +271 -87
  24. package/src/types.ts +32 -59
  25. package/dist/lib/browser/chunk-366QG6IX.mjs +0 -81
  26. package/dist/lib/browser/chunk-366QG6IX.mjs.map +0 -7
  27. package/dist/lib/browser/types.mjs +0 -12
  28. package/dist/lib/browser/types.mjs.map +0 -7
  29. package/dist/lib/node/chunk-3VSJ57ZZ.cjs +0 -97
  30. package/dist/lib/node/chunk-3VSJ57ZZ.cjs.map +0 -7
  31. package/dist/lib/node/types.cjs +0 -33
  32. package/dist/lib/node/types.cjs.map +0 -7
  33. package/dist/types/src/function/function-registry.d.ts +0 -24
  34. package/dist/types/src/function/function-registry.d.ts.map +0 -1
  35. package/dist/types/src/function/function-registry.test.d.ts +0 -2
  36. package/dist/types/src/function/function-registry.test.d.ts.map +0 -1
  37. package/dist/types/src/function/index.d.ts +0 -2
  38. package/dist/types/src/function/index.d.ts.map +0 -1
  39. package/dist/types/src/runtime/dev-server.test.d.ts +0 -2
  40. package/dist/types/src/runtime/dev-server.test.d.ts.map +0 -1
  41. package/dist/types/src/testing/functions-integration.test.d.ts +0 -2
  42. package/dist/types/src/testing/functions-integration.test.d.ts.map +0 -1
  43. package/dist/types/src/testing/index.d.ts +0 -4
  44. package/dist/types/src/testing/index.d.ts.map +0 -1
  45. package/dist/types/src/testing/setup.d.ts +0 -5
  46. package/dist/types/src/testing/setup.d.ts.map +0 -1
  47. package/dist/types/src/testing/test/handler.d.ts +0 -4
  48. package/dist/types/src/testing/test/handler.d.ts.map +0 -1
  49. package/dist/types/src/testing/test/index.d.ts +0 -3
  50. package/dist/types/src/testing/test/index.d.ts.map +0 -1
  51. package/dist/types/src/testing/types.d.ts +0 -9
  52. package/dist/types/src/testing/types.d.ts.map +0 -1
  53. package/dist/types/src/testing/util.d.ts +0 -3
  54. package/dist/types/src/testing/util.d.ts.map +0 -1
  55. package/dist/types/src/trigger/index.d.ts +0 -2
  56. package/dist/types/src/trigger/index.d.ts.map +0 -1
  57. package/dist/types/src/trigger/trigger-registry.d.ts +0 -40
  58. package/dist/types/src/trigger/trigger-registry.d.ts.map +0 -1
  59. package/dist/types/src/trigger/trigger-registry.test.d.ts +0 -2
  60. package/dist/types/src/trigger/trigger-registry.test.d.ts.map +0 -1
  61. package/dist/types/src/trigger/type/index.d.ts +0 -5
  62. package/dist/types/src/trigger/type/index.d.ts.map +0 -1
  63. package/dist/types/src/trigger/type/subscription-trigger.d.ts +0 -4
  64. package/dist/types/src/trigger/type/subscription-trigger.d.ts.map +0 -1
  65. package/dist/types/src/trigger/type/timer-trigger.d.ts +0 -4
  66. package/dist/types/src/trigger/type/timer-trigger.d.ts.map +0 -1
  67. package/dist/types/src/trigger/type/webhook-trigger.d.ts +0 -4
  68. package/dist/types/src/trigger/type/webhook-trigger.d.ts.map +0 -1
  69. package/dist/types/src/trigger/type/websocket-trigger.d.ts +0 -13
  70. package/dist/types/src/trigger/type/websocket-trigger.d.ts.map +0 -1
  71. package/dist/types/src/util.d.ts +0 -15
  72. package/dist/types/src/util.d.ts.map +0 -1
  73. package/dist/types/src/util.test.d.ts +0 -2
  74. package/dist/types/src/util.test.d.ts.map +0 -1
  75. package/src/function/function-registry.test.ts +0 -105
  76. package/src/function/function-registry.ts +0 -90
  77. package/src/function/index.ts +0 -5
  78. package/src/runtime/dev-server.test.ts +0 -60
  79. package/src/testing/functions-integration.test.ts +0 -99
  80. package/src/testing/index.ts +0 -7
  81. package/src/testing/setup.ts +0 -45
  82. package/src/testing/test/handler.ts +0 -15
  83. package/src/testing/test/index.ts +0 -7
  84. package/src/testing/types.ts +0 -9
  85. package/src/testing/util.ts +0 -16
  86. package/src/trigger/index.ts +0 -5
  87. package/src/trigger/trigger-registry.test.ts +0 -255
  88. package/src/trigger/trigger-registry.ts +0 -189
  89. package/src/trigger/type/index.ts +0 -8
  90. package/src/trigger/type/subscription-trigger.ts +0 -80
  91. package/src/trigger/type/timer-trigger.ts +0 -44
  92. package/src/trigger/type/webhook-trigger.ts +0 -47
  93. package/src/trigger/type/websocket-trigger.ts +0 -91
  94. package/src/util.test.ts +0 -43
  95. package/src/util.ts +0 -48
@@ -1,24 +1,27 @@
1
1
  {
2
2
  "$schema": "http://json-schema.org/draft-07/schema#",
3
3
  "type": "object",
4
- "required": [],
4
+ "required": [
5
+ "functions",
6
+ "triggers"
7
+ ],
5
8
  "properties": {
6
9
  "functions": {
7
10
  "type": "array",
8
11
  "items": {
9
12
  "type": "object",
10
13
  "required": [
11
- "uri",
12
- "route",
14
+ "id",
15
+ "name",
13
16
  "handler"
14
17
  ],
15
18
  "properties": {
16
- "uri": {
19
+ "id": {
17
20
  "type": "string",
18
21
  "description": "a string",
19
22
  "title": "string"
20
23
  },
21
- "route": {
24
+ "name": {
22
25
  "type": "string",
23
26
  "description": "a string",
24
27
  "title": "string"
@@ -42,165 +45,126 @@
42
45
  "items": {
43
46
  "type": "object",
44
47
  "required": [
45
- "function",
46
- "spec"
48
+ "function"
47
49
  ],
48
50
  "properties": {
49
51
  "function": {
50
52
  "type": "string",
51
- "description": "Function URI.",
53
+ "description": "Function ID/URI.",
52
54
  "title": "string"
53
55
  },
54
- "meta": {
55
- "$ref": "#/$defs/object"
56
+ "timer": {
57
+ "type": "object",
58
+ "required": [
59
+ "cron"
60
+ ],
61
+ "properties": {
62
+ "cron": {
63
+ "type": "string",
64
+ "description": "a string",
65
+ "title": "string"
66
+ }
67
+ },
68
+ "additionalProperties": false
69
+ },
70
+ "webhook": {
71
+ "type": "object",
72
+ "required": [
73
+ "port"
74
+ ],
75
+ "properties": {
76
+ "port": {
77
+ "type": "number",
78
+ "description": "a number",
79
+ "title": "number"
80
+ }
81
+ },
82
+ "additionalProperties": false
56
83
  },
57
- "spec": {
58
- "anyOf": [
59
- {
84
+ "websocket": {
85
+ "type": "object",
86
+ "required": [
87
+ "url"
88
+ ],
89
+ "properties": {
90
+ "url": {
91
+ "type": "string",
92
+ "description": "a string",
93
+ "title": "string"
94
+ },
95
+ "init": {
60
96
  "type": "object",
61
- "required": [
62
- "type",
63
- "cron"
64
- ],
65
- "properties": {
66
- "type": {
67
- "const": "timer"
97
+ "required": [],
98
+ "properties": {},
99
+ "additionalProperties": {
100
+ "$id": "/schemas/any",
101
+ "title": "any"
102
+ }
103
+ }
104
+ },
105
+ "additionalProperties": false
106
+ },
107
+ "subscription": {
108
+ "type": "object",
109
+ "required": [
110
+ "filter"
111
+ ],
112
+ "properties": {
113
+ "spaceKey": {
114
+ "type": "string",
115
+ "description": "a string",
116
+ "title": "string"
117
+ },
118
+ "filter": {
119
+ "type": "array",
120
+ "items": {
121
+ "type": "object",
122
+ "required": [
123
+ "type"
124
+ ],
125
+ "properties": {
126
+ "type": {
127
+ "type": "string",
128
+ "description": "a string",
129
+ "title": "string"
130
+ },
131
+ "props": {
132
+ "type": "object",
133
+ "required": [],
134
+ "properties": {},
135
+ "additionalProperties": {
136
+ "$id": "/schemas/any",
137
+ "title": "any"
138
+ }
139
+ }
68
140
  },
69
- "cron": {
70
- "type": "string",
71
- "description": "a string",
72
- "title": "string"
73
- }
74
- },
75
- "additionalProperties": false
141
+ "additionalProperties": false
142
+ }
76
143
  },
77
- {
144
+ "options": {
78
145
  "type": "object",
79
- "required": [
80
- "type",
81
- "method"
82
- ],
146
+ "required": [],
83
147
  "properties": {
84
- "type": {
85
- "const": "webhook"
148
+ "deep": {
149
+ "type": "boolean",
150
+ "description": "a boolean",
151
+ "title": "boolean"
86
152
  },
87
- "method": {
88
- "type": "string",
89
- "description": "a string",
90
- "title": "string"
91
- },
92
- "port": {
153
+ "delay": {
93
154
  "type": "number",
94
155
  "description": "a number",
95
156
  "title": "number"
96
157
  }
97
158
  },
98
159
  "additionalProperties": false
99
- },
100
- {
101
- "type": "object",
102
- "required": [
103
- "type",
104
- "url"
105
- ],
106
- "properties": {
107
- "type": {
108
- "const": "websocket"
109
- },
110
- "url": {
111
- "type": "string",
112
- "description": "a string",
113
- "title": "string"
114
- },
115
- "init": {
116
- "type": "object",
117
- "required": [],
118
- "properties": {},
119
- "additionalProperties": {
120
- "$id": "/schemas/any",
121
- "title": "any"
122
- }
123
- }
124
- },
125
- "additionalProperties": false
126
- },
127
- {
128
- "type": "object",
129
- "required": [
130
- "type",
131
- "filter"
132
- ],
133
- "properties": {
134
- "type": {
135
- "const": "subscription"
136
- },
137
- "filter": {
138
- "type": "array",
139
- "items": {
140
- "type": "object",
141
- "required": [
142
- "type"
143
- ],
144
- "properties": {
145
- "type": {
146
- "type": "string",
147
- "description": "a string",
148
- "title": "string"
149
- },
150
- "props": {
151
- "type": "object",
152
- "required": [],
153
- "properties": {},
154
- "additionalProperties": {
155
- "$id": "/schemas/any",
156
- "title": "any"
157
- }
158
- }
159
- },
160
- "additionalProperties": false
161
- }
162
- },
163
- "options": {
164
- "type": "object",
165
- "required": [],
166
- "properties": {
167
- "deep": {
168
- "type": "boolean",
169
- "description": "a boolean",
170
- "title": "boolean"
171
- },
172
- "delay": {
173
- "type": "number",
174
- "description": "a number",
175
- "title": "number"
176
- }
177
- },
178
- "additionalProperties": false
179
- }
180
- },
181
- "additionalProperties": false
182
160
  }
183
- ]
161
+ },
162
+ "additionalProperties": false
184
163
  }
185
164
  },
186
165
  "additionalProperties": false
187
166
  }
188
167
  }
189
168
  },
190
- "additionalProperties": false,
191
- "$defs": {
192
- "object": {
193
- "$id": "/schemas/object",
194
- "oneOf": [
195
- {
196
- "type": "object"
197
- },
198
- {
199
- "type": "array"
200
- }
201
- ],
202
- "description": "an object in the TypeScript meaning, i.e. the `object` type",
203
- "title": "object"
204
- }
205
- }
169
+ "additionalProperties": false
206
170
  }
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
- // 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
11
+ // TODO(burdon): Context?
12
+ // Lambda-like function definitions.
13
+ // See: https://www.serverless.com/framework/docs/providers/aws/guide/serverless.yml/#functions
14
14
  // https://www.npmjs.com/package/aws-lambda
15
+ // https://docs.aws.amazon.com/lambda/latest/dg/typescript-handler.html
15
16
 
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>;
17
+ // TODO(burdon): No response?
18
+ export interface Response {
19
+ status(code: number): Response;
20
+ }
24
21
 
25
- /**
26
- * Function context.
27
- */
22
+ // TODO(burdon): Limit access to individual space?
28
23
  export interface FunctionContext {
29
- // TODO(burdon): Limit access to individual space.
30
24
  client: Client;
31
- // TODO(burdon): Replace with storage service abstraction.
32
25
  dataDir?: string;
33
26
  }
34
27
 
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
- //
28
+ // TODO(burdon): Model after http request. Ref Lambda/OpenFaaS.
29
+ // https://docs.aws.amazon.com/lambda/latest/dg/typescript-handler.html
30
+ export type FunctionHandler<T extends {}> = (params: {
31
+ event: T;
32
+ context: FunctionContext;
33
+ response: Response;
34
+ }) => Promise<Response | void>;
59
35
 
60
- export type RawSubscriptionData = {
61
- spaceKey?: string;
36
+ export type FunctionSubscriptionEvent = {
37
+ space?: string; // TODO(burdon): Convert to PublicKey.
62
38
  objects?: string[];
63
39
  };
64
40
 
65
- export type SubscriptionData = {
41
+ // TODO(burdon): ???
42
+ export type FunctionSubscriptionEvent2 = {
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 = <TMeta>(
81
- handler: FunctionHandler<SubscriptionData, TMeta>,
82
- ): FunctionHandler<RawSubscriptionData, TMeta> => {
83
- return ({ event: { data }, context, ...rest }) => {
57
+ export const subscriptionHandler = (
58
+ handler: FunctionHandler<FunctionSubscriptionEvent2>,
59
+ ): FunctionHandler<FunctionSubscriptionEvent> => {
60
+ return ({ event, context, ...rest }) => {
84
61
  const { client } = context;
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
- : [];
62
+ const space = event.space ? client.spaces.get(PublicKey.from(event.space)) : undefined;
63
+ const objects =
64
+ space &&
65
+ event.objects?.map<EchoReactiveObject<any> | undefined>((id) => space!.db.getObjectById(id)).filter(nonNullable);
89
66
 
90
- if (!!data.spaceKey && !space) {
91
- log.warn('invalid space', { data });
67
+ if (!!event.space && !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: { data: { ...data, space, objects } }, context, ...rest });
73
+ return handler({ event: { space, objects }, context, ...rest });
97
74
  };
98
75
  };
package/src/index.ts CHANGED
@@ -2,8 +2,6 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
- export * from './function';
6
5
  export * from './handler';
7
6
  export * from './runtime';
8
- export * from './trigger';
9
7
  export * from './types';
@@ -7,19 +7,18 @@ import { getPort } from 'get-port-please';
7
7
  import type http from 'http';
8
8
  import { join } from 'node:path';
9
9
 
10
- import { Event, Trigger } from '@dxos/async';
10
+ import { 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 FunctionRegistry } from '../function';
17
- import { type FunctionContext, type FunctionEvent, type FunctionHandler, type FunctionResponse } from '../handler';
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 = {
21
- baseDir: string;
22
19
  port?: number;
20
+ directory: string;
21
+ manifest: FunctionManifest;
23
22
  reload?: boolean;
24
23
  dataDir?: string;
25
24
  };
@@ -28,36 +27,20 @@ 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
 
36
33
  private _server?: http.Server;
37
34
  private _port?: number;
38
- private _functionServiceRegistration?: string;
35
+ private _registrationId?: string;
39
36
  private _proxy?: string;
40
37
  private _seq = 0;
41
38
 
42
- public readonly update = new Event<number>();
43
-
39
+ // prettier-ignore
44
40
  constructor(
45
41
  private readonly _client: Client,
46
- private readonly _functionsRegistry: FunctionRegistry,
47
42
  private readonly _options: DevServerOptions,
48
- ) {
49
- this._functionsRegistry.registered.on(async ({ added }) => {
50
- added.forEach((def) => this._load(def));
51
- await this._safeUpdateRegistration();
52
- log('new functions loaded', { added });
53
- });
54
- }
55
-
56
- get stats() {
57
- return {
58
- seq: this._seq,
59
- };
60
- }
43
+ ) {}
61
44
 
62
45
  get endpoint() {
63
46
  invariant(this._port);
@@ -72,26 +55,30 @@ export class DevServer {
72
55
  return Object.values(this._handlers);
73
56
  }
74
57
 
75
- async start() {
76
- invariant(!this._server);
77
- log.info('starting...');
78
- this._ctx = createContext();
58
+ async initialize() {
59
+ for (const def of this._options.manifest.functions) {
60
+ try {
61
+ await this._load(def);
62
+ } catch (err) {
63
+ log.error('parsing function (check manifest)', err);
64
+ }
65
+ }
66
+ }
79
67
 
80
- // TODO(burdon): Move to hono.
68
+ async start() {
81
69
  const app = express();
82
70
  app.use(express.json());
83
71
 
84
- app.post('/:path', async (req, res) => {
85
- const { path } = req.params;
72
+ app.post('/:name', async (req, res) => {
73
+ const { name } = req.params;
86
74
  try {
87
- log.info('calling', { path });
75
+ log.info('calling', { name });
88
76
  if (this._options.reload) {
89
- const { def } = this._handlers['/' + path];
77
+ const { def } = this._handlers[name];
90
78
  await this._load(def, true);
91
79
  }
92
80
 
93
- // TODO(burdon): Get function context.
94
- res.statusCode = await this.invoke('/' + path, req.body);
81
+ res.statusCode = await this._invoke(name, req.body);
95
82
  res.end();
96
83
  } catch (err: any) {
97
84
  log.catch(err);
@@ -107,110 +94,72 @@ export class DevServer {
107
94
  // Register functions.
108
95
  const { registrationId, endpoint } = await this._client.services.services.FunctionRegistryService!.register({
109
96
  endpoint: this.endpoint,
97
+ functions: this.functions.map(({ def: { name } }) => ({ name })),
110
98
  });
111
99
 
112
- log.info('registered', { endpoint });
100
+ log.info('registered', { registrationId, endpoint });
101
+ this._registrationId = registrationId;
113
102
  this._proxy = endpoint;
114
- this._functionServiceRegistration = registrationId;
115
-
116
- // Open after registration, so that it can be updated with the list of function definitions.
117
- await this._functionsRegistry.open(this._ctx);
118
103
  } catch (err: any) {
119
104
  await this.stop();
120
105
  throw new Error('FunctionRegistryService not available (check plugin is configured).');
121
106
  }
122
-
123
- log.info('started', { port: this._port });
124
107
  }
125
108
 
126
109
  async stop() {
127
- invariant(this._server);
128
- log.info('stopping...');
129
-
130
110
  const trigger = new Trigger();
131
- this._server.close(async () => {
132
- log.info('server stopped');
133
- try {
134
- if (this._functionServiceRegistration) {
135
- invariant(this._client.services.services.FunctionRegistryService);
136
- await this._client.services.services.FunctionRegistryService.unregister({
137
- registrationId: this._functionServiceRegistration,
138
- });
139
-
140
- log.info('unregistered', { registrationId: this._functionServiceRegistration });
141
- this._functionServiceRegistration = undefined;
142
- this._proxy = undefined;
143
- }
111
+ this._server?.close(async () => {
112
+ if (this._registrationId) {
113
+ await this._client.services.services.FunctionRegistryService!.unregister({
114
+ registrationId: this._registrationId,
115
+ });
144
116
 
145
- trigger.wake();
146
- } catch (err) {
147
- trigger.throw(err as Error);
117
+ log.info('unregistered', { registrationId: this._registrationId });
118
+ this._registrationId = undefined;
119
+ this._proxy = undefined;
148
120
  }
121
+
122
+ trigger.wake();
149
123
  });
150
124
 
151
125
  await trigger.wait();
152
126
  this._port = undefined;
153
127
  this._server = undefined;
154
- log.info('stopped');
155
128
  }
156
129
 
157
130
  /**
158
131
  * Load function.
159
132
  */
160
- private async _load(def: FunctionDef, force?: boolean | undefined) {
161
- const { uri, route, handler } = def;
162
- const filePath = join(this._options.baseDir, handler);
163
- log.info('loading', { uri, force });
133
+ private async _load(def: FunctionDef, flush = false) {
134
+ const { id, name, handler } = def;
135
+ const path = join(this._options.directory, handler);
136
+ log.info('loading', { id });
164
137
 
165
138
  // Remove from cache.
166
- if (force) {
139
+ if (flush) {
167
140
  Object.keys(require.cache)
168
- .filter((key) => key.startsWith(filePath))
169
- .forEach((key) => {
170
- delete require.cache[key];
171
- });
141
+ .filter((key) => key.startsWith(path))
142
+ .forEach((key) => delete require.cache[key]);
172
143
  }
173
144
 
174
- // TODO(burdon): Import types.
175
145
  // eslint-disable-next-line @typescript-eslint/no-var-requires
176
- const module = require(filePath);
146
+ const module = require(path);
177
147
  if (typeof module.default !== 'function') {
178
- throw new Error(`Handler must export default function: ${uri}`);
148
+ throw new Error(`Handler must export default function: ${id}`);
179
149
  }
180
150
 
181
- this._handlers[route] = { def, handler: module.default };
182
- }
183
-
184
- private async _safeUpdateRegistration(): Promise<void> {
185
- invariant(this._functionServiceRegistration);
186
- try {
187
- await this._client.services.services.FunctionRegistryService!.updateRegistration({
188
- registrationId: this._functionServiceRegistration,
189
- functions: this.functions.map(({ def: { id, route } }) => ({ id, route })),
190
- });
191
- } catch (e) {
192
- log.catch(e);
193
- }
151
+ this._handlers[name] = { def, handler: module.default };
194
152
  }
195
153
 
196
154
  /**
197
- * Invoke function.
155
+ * Invoke function handler.
198
156
  */
199
- public async invoke(path: string, data: any): Promise<number> {
157
+ private async _invoke(name: string, event: any) {
200
158
  const seq = ++this._seq;
201
159
  const now = Date.now();
202
160
 
203
- log.info('req', { seq, path });
204
- const statusCode = await this._invoke(path, { data });
205
-
206
- log.info('res', { seq, path, statusCode, duration: Date.now() - now });
207
- this.update.emit(statusCode);
208
- return statusCode;
209
- }
210
-
211
- private async _invoke(path: string, event: FunctionEvent) {
212
- const { handler } = this._handlers[path] ?? {};
213
- invariant(handler, `invalid path: ${path}`);
161
+ log.info('req', { seq, name });
162
+ const { handler } = this._handlers[name];
214
163
 
215
164
  const context: FunctionContext = {
216
165
  client: this._client,
@@ -218,7 +167,7 @@ export class DevServer {
218
167
  };
219
168
 
220
169
  let statusCode = 200;
221
- const response: FunctionResponse = {
170
+ const response: Response = {
222
171
  status: (code: number) => {
223
172
  statusCode = code;
224
173
  return response;
@@ -226,8 +175,8 @@ export class DevServer {
226
175
  };
227
176
 
228
177
  await handler({ context, event, response });
178
+ log.info('res', { seq, name, statusCode, duration: Date.now() - now });
179
+
229
180
  return statusCode;
230
181
  }
231
182
  }
232
-
233
- const createContext = () => new Context({ name: 'DevServer' });