@restatedev/restate-sdk-cloudflare-workers 1.12.0 → 1.14.0

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 (36) hide show
  1. package/dist/endpoint/components.cjs +70 -12
  2. package/dist/endpoint/components.js +70 -12
  3. package/dist/endpoint/components.js.map +1 -1
  4. package/dist/endpoint/handlers/fetch.cjs +5 -3
  5. package/dist/endpoint/handlers/fetch.js +6 -4
  6. package/dist/endpoint/handlers/fetch.js.map +1 -1
  7. package/dist/endpoint/handlers/generic.cjs +11 -10
  8. package/dist/endpoint/handlers/generic.js +11 -10
  9. package/dist/endpoint/handlers/generic.js.map +1 -1
  10. package/dist/endpoint/handlers/lambda.cjs +6 -3
  11. package/dist/endpoint/handlers/lambda.js +7 -4
  12. package/dist/endpoint/handlers/lambda.js.map +1 -1
  13. package/dist/endpoint/handlers/preview.cjs +97 -0
  14. package/dist/endpoint/handlers/preview.js +98 -0
  15. package/dist/endpoint/handlers/preview.js.map +1 -0
  16. package/dist/endpoint/handlers/utils.cjs +26 -11
  17. package/dist/endpoint/handlers/utils.js +26 -12
  18. package/dist/endpoint/handlers/utils.js.map +1 -1
  19. package/dist/endpoint/node_endpoint.cjs +9 -6
  20. package/dist/endpoint/node_endpoint.js +9 -6
  21. package/dist/endpoint/node_endpoint.js.map +1 -1
  22. package/dist/io.cjs +7 -2
  23. package/dist/io.js +7 -2
  24. package/dist/io.js.map +1 -1
  25. package/dist/package.cjs +1 -1
  26. package/dist/package.js +1 -1
  27. package/dist/package.js.map +1 -1
  28. package/dist/promises.cjs +21 -10
  29. package/dist/promises.js +21 -10
  30. package/dist/promises.js.map +1 -1
  31. package/dist/types/rpc.d.cts +11 -0
  32. package/dist/types/rpc.d.cts.map +1 -1
  33. package/dist/types/rpc.d.ts +11 -0
  34. package/dist/types/rpc.d.ts.map +1 -1
  35. package/dist/types/rpc.js.map +1 -1
  36. package/package.json +4 -4
@@ -22,30 +22,63 @@ function handlerInputDiscovery(handler, defaultSerde) {
22
22
  }
23
23
  function handlerOutputDiscovery(handler, defaultSerde) {
24
24
  const serde$1 = handler.options?.output ?? defaultSerde;
25
+ const setContentTypeIfEmpty = handler.options?.setOutputContentTypeIfEmpty ?? false;
25
26
  let contentType = void 0;
26
27
  let jsonSchema = void 0;
27
28
  if (serde$1.jsonSchema) {
28
29
  jsonSchema = serde$1.jsonSchema;
29
30
  contentType = serde$1.contentType ?? "application/json";
30
31
  } else if (serde$1.contentType) contentType = serde$1.contentType;
31
- else return { setContentTypeIfEmpty: false };
32
+ else return { setContentTypeIfEmpty };
32
33
  return {
33
- setContentTypeIfEmpty: false,
34
+ setContentTypeIfEmpty,
34
35
  jsonSchema,
35
36
  contentType
36
37
  };
37
38
  }
38
39
  function createExecutionOptions(serviceOptions, handlerOptions) {
40
+ const defaultSerde = handlerOptions?.serde ?? serviceOptions?.serde ?? __restatedev_restate_sdk_core.serde.json;
39
41
  const hooks = [...serviceOptions?.hooks ?? [], ...handlerOptions?.hooks ?? []];
40
42
  return {
41
- defaultSerde: handlerOptions?.serde ?? serviceOptions?.serde,
43
+ defaultSerde,
42
44
  asTerminalError: handlerOptions?.asTerminalError ?? serviceOptions?.asTerminalError,
43
45
  hooks: hooks.length > 0 ? hooks : void 0,
44
46
  explicitCancellation: handlerOptions?.explicitCancellation ?? serviceOptions?.explicitCancellation
45
47
  };
46
48
  }
49
+ const PREVIEW_METADATA_KEY_PREFIX = "dev.restate.serde.preview";
50
+ /**
51
+ * Service-scoped serde namespace.
52
+ *
53
+ * Today it is populated from handler inputs/outputs under `<handler>/input`
54
+ * and `<handler>/output`. Custom service-level serdes can be registered
55
+ * alongside them under any name.
56
+ */
57
+ var ServiceSerdeRegistry = class {
58
+ serdes = /* @__PURE__ */ new Map();
59
+ registerHandlerIO(handlerName, wrapper, executionOptions) {
60
+ this.serdes.set(`${handlerName}/input`, wrapper.options?.input ?? executionOptions.defaultSerde);
61
+ this.serdes.set(`${handlerName}/output`, wrapper.options?.output ?? executionOptions.defaultSerde);
62
+ }
63
+ resolve(name) {
64
+ return this.serdes.get(name);
65
+ }
66
+ previewMetadata() {
67
+ const metadata = {};
68
+ for (const [name, s] of this.serdes) if (s.preview) metadata[`${PREVIEW_METADATA_KEY_PREFIX}.${name}`] = "true";
69
+ return Object.keys(metadata).length > 0 ? metadata : void 0;
70
+ }
71
+ };
72
+ function mergeMetadata(baseMetadata, additionalMetadata) {
73
+ if (!baseMetadata && !additionalMetadata) return;
74
+ return {
75
+ ...baseMetadata ?? {},
76
+ ...additionalMetadata ?? {}
77
+ };
78
+ }
47
79
  var ServiceComponent = class {
48
80
  handlers = /* @__PURE__ */ new Map();
81
+ serdeRegistry = new ServiceSerdeRegistry();
49
82
  constructor(componentName, description, metadata, options) {
50
83
  this.componentName = componentName;
51
84
  this.description = description;
@@ -56,13 +89,15 @@ var ServiceComponent = class {
56
89
  return this.componentName;
57
90
  }
58
91
  add(name, handlerWrapper) {
59
- this.handlers.set(name, new ServiceHandler(name, handlerWrapper, this));
92
+ const handler = new ServiceHandler(name, handlerWrapper, this);
93
+ this.handlers.set(name, handler);
94
+ this.serdeRegistry.registerHandlerIO(name, handlerWrapper, handler.executionOptions);
60
95
  }
61
96
  discovery() {
62
97
  const handlers = [...this.handlers.entries()].map(([name, handler]) => {
63
98
  return {
64
99
  name,
65
- ...commonHandlerOptions(handler.handlerWrapper, handler.executionOptions.defaultSerde ?? __restatedev_restate_sdk_core.serde.json)
100
+ ...commonHandlerOptions(handler.handlerWrapper, handler.executionOptions.defaultSerde)
66
101
  };
67
102
  });
68
103
  return {
@@ -70,13 +105,16 @@ var ServiceComponent = class {
70
105
  ty: "SERVICE",
71
106
  handlers,
72
107
  documentation: this.description,
73
- metadata: this.metadata,
108
+ metadata: mergeMetadata(this.metadata, this.serdeRegistry.previewMetadata()),
74
109
  ...commonServiceOptions(this.options)
75
110
  };
76
111
  }
77
112
  handlerMatching(url) {
78
113
  return this.handlers.get(url.handlerName);
79
114
  }
115
+ serdeMatching(name) {
116
+ return this.serdeRegistry.resolve(name);
117
+ }
80
118
  };
81
119
  var ServiceHandler = class {
82
120
  executionOptions;
@@ -101,6 +139,7 @@ var ServiceHandler = class {
101
139
  };
102
140
  var VirtualObjectComponent = class {
103
141
  handlers = /* @__PURE__ */ new Map();
142
+ serdeRegistry = new ServiceSerdeRegistry();
104
143
  constructor(componentName, description, metadata, options) {
105
144
  this.componentName = componentName;
106
145
  this.description = description;
@@ -111,14 +150,16 @@ var VirtualObjectComponent = class {
111
150
  return this.componentName;
112
151
  }
113
152
  add(name, wrapper) {
114
- this.handlers.set(name, new VirtualObjectHandler(name, wrapper, this));
153
+ const handler = new VirtualObjectHandler(name, wrapper, this);
154
+ this.handlers.set(name, handler);
155
+ this.serdeRegistry.registerHandlerIO(name, wrapper, handler.executionOptions);
115
156
  }
116
157
  discovery() {
117
158
  const handlers = [...this.handlers.entries()].map(([name, handler]) => {
118
159
  return {
119
160
  name,
120
161
  ty: handler.kind() === require_rpc.HandlerKind.EXCLUSIVE ? "EXCLUSIVE" : "SHARED",
121
- ...commonHandlerOptions(handler.handlerWrapper, handler.executionOptions.defaultSerde ?? __restatedev_restate_sdk_core.serde.json)
162
+ ...commonHandlerOptions(handler.handlerWrapper, handler.executionOptions.defaultSerde)
122
163
  };
123
164
  });
124
165
  return {
@@ -126,13 +167,16 @@ var VirtualObjectComponent = class {
126
167
  ty: "VIRTUAL_OBJECT",
127
168
  handlers,
128
169
  documentation: this.description,
129
- metadata: this.metadata,
170
+ metadata: mergeMetadata(this.metadata, this.serdeRegistry.previewMetadata()),
130
171
  ...commonServiceOptions(this.options)
131
172
  };
132
173
  }
133
174
  handlerMatching(url) {
134
175
  return this.handlers.get(url.handlerName);
135
176
  }
177
+ serdeMatching(name) {
178
+ return this.serdeRegistry.resolve(name);
179
+ }
136
180
  };
137
181
  var VirtualObjectHandler = class {
138
182
  executionOptions;
@@ -157,6 +201,7 @@ var VirtualObjectHandler = class {
157
201
  };
158
202
  var WorkflowComponent = class {
159
203
  handlers = /* @__PURE__ */ new Map();
204
+ serdeRegistry = new ServiceSerdeRegistry();
160
205
  constructor(componentName, description, metadata, options) {
161
206
  this.componentName = componentName;
162
207
  this.description = description;
@@ -167,7 +212,9 @@ var WorkflowComponent = class {
167
212
  return this.componentName;
168
213
  }
169
214
  add(name, wrapper) {
170
- this.handlers.set(name, new WorkflowHandler(name, wrapper, this));
215
+ const handler = new WorkflowHandler(name, wrapper, this);
216
+ this.handlers.set(name, handler);
217
+ this.serdeRegistry.registerHandlerIO(name, wrapper, handler.executionOptions);
171
218
  }
172
219
  discovery() {
173
220
  const handlers = [...this.handlers.entries()].map(([name, handler]) => {
@@ -175,7 +222,7 @@ var WorkflowComponent = class {
175
222
  name,
176
223
  ty: handler.kind() === require_rpc.HandlerKind.WORKFLOW ? "WORKFLOW" : "SHARED",
177
224
  workflowCompletionRetention: handler.kind() === require_rpc.HandlerKind.WORKFLOW && this.options?.workflowRetention !== void 0 ? (0, __restatedev_restate_sdk_core.millisOrDurationToMillis)(this.options?.workflowRetention) : void 0,
178
- ...commonHandlerOptions(handler.handlerWrapper, handler.executionOptions.defaultSerde ?? __restatedev_restate_sdk_core.serde.json)
225
+ ...commonHandlerOptions(handler.handlerWrapper, handler.executionOptions.defaultSerde)
179
226
  };
180
227
  });
181
228
  return {
@@ -183,13 +230,16 @@ var WorkflowComponent = class {
183
230
  ty: "WORKFLOW",
184
231
  handlers,
185
232
  documentation: this.description,
186
- metadata: this.metadata,
233
+ metadata: mergeMetadata(this.metadata, this.serdeRegistry.previewMetadata()),
187
234
  ...commonServiceOptions(this.options)
188
235
  };
189
236
  }
190
237
  handlerMatching(url) {
191
238
  return this.handlers.get(url.handlerName);
192
239
  }
240
+ serdeMatching(name) {
241
+ return this.serdeRegistry.resolve(name);
242
+ }
193
243
  };
194
244
  var WorkflowHandler = class {
195
245
  executionOptions;
@@ -212,11 +262,19 @@ var WorkflowHandler = class {
212
262
  return this.handlerWrapper.invoke(context, input);
213
263
  }
214
264
  };
265
+ const PREVIEW_PATH_REGEX = /(?:^|\/)serdes\/(?<componentName>[^/]+)\/(?<operation>encode|decode)\/(?<serdeName>.+?)\/?$/;
215
266
  function parseUrlComponents(urlPath) {
216
267
  if (!urlPath) return {
217
268
  type: "unknown",
218
269
  path: ""
219
270
  };
271
+ const preview = PREVIEW_PATH_REGEX.exec(urlPath);
272
+ if (preview?.groups) return {
273
+ type: "preview",
274
+ componentName: preview.groups.componentName,
275
+ operation: preview.groups.operation,
276
+ serdeName: decodeURIComponent(preview.groups.serdeName)
277
+ };
220
278
  const fragments = urlPath.split("/");
221
279
  if (fragments.length >= 3 && fragments[fragments.length - 3] === "invoke") return {
222
280
  type: "invoke",
@@ -20,30 +20,63 @@ function handlerInputDiscovery(handler, defaultSerde) {
20
20
  }
21
21
  function handlerOutputDiscovery(handler, defaultSerde) {
22
22
  const serde$1 = handler.options?.output ?? defaultSerde;
23
+ const setContentTypeIfEmpty = handler.options?.setOutputContentTypeIfEmpty ?? false;
23
24
  let contentType = void 0;
24
25
  let jsonSchema = void 0;
25
26
  if (serde$1.jsonSchema) {
26
27
  jsonSchema = serde$1.jsonSchema;
27
28
  contentType = serde$1.contentType ?? "application/json";
28
29
  } else if (serde$1.contentType) contentType = serde$1.contentType;
29
- else return { setContentTypeIfEmpty: false };
30
+ else return { setContentTypeIfEmpty };
30
31
  return {
31
- setContentTypeIfEmpty: false,
32
+ setContentTypeIfEmpty,
32
33
  jsonSchema,
33
34
  contentType
34
35
  };
35
36
  }
36
37
  function createExecutionOptions(serviceOptions, handlerOptions) {
38
+ const defaultSerde = handlerOptions?.serde ?? serviceOptions?.serde ?? serde.json;
37
39
  const hooks = [...serviceOptions?.hooks ?? [], ...handlerOptions?.hooks ?? []];
38
40
  return {
39
- defaultSerde: handlerOptions?.serde ?? serviceOptions?.serde,
41
+ defaultSerde,
40
42
  asTerminalError: handlerOptions?.asTerminalError ?? serviceOptions?.asTerminalError,
41
43
  hooks: hooks.length > 0 ? hooks : void 0,
42
44
  explicitCancellation: handlerOptions?.explicitCancellation ?? serviceOptions?.explicitCancellation
43
45
  };
44
46
  }
47
+ const PREVIEW_METADATA_KEY_PREFIX = "dev.restate.serde.preview";
48
+ /**
49
+ * Service-scoped serde namespace.
50
+ *
51
+ * Today it is populated from handler inputs/outputs under `<handler>/input`
52
+ * and `<handler>/output`. Custom service-level serdes can be registered
53
+ * alongside them under any name.
54
+ */
55
+ var ServiceSerdeRegistry = class {
56
+ serdes = /* @__PURE__ */ new Map();
57
+ registerHandlerIO(handlerName, wrapper, executionOptions) {
58
+ this.serdes.set(`${handlerName}/input`, wrapper.options?.input ?? executionOptions.defaultSerde);
59
+ this.serdes.set(`${handlerName}/output`, wrapper.options?.output ?? executionOptions.defaultSerde);
60
+ }
61
+ resolve(name) {
62
+ return this.serdes.get(name);
63
+ }
64
+ previewMetadata() {
65
+ const metadata = {};
66
+ for (const [name, s] of this.serdes) if (s.preview) metadata[`${PREVIEW_METADATA_KEY_PREFIX}.${name}`] = "true";
67
+ return Object.keys(metadata).length > 0 ? metadata : void 0;
68
+ }
69
+ };
70
+ function mergeMetadata(baseMetadata, additionalMetadata) {
71
+ if (!baseMetadata && !additionalMetadata) return;
72
+ return {
73
+ ...baseMetadata ?? {},
74
+ ...additionalMetadata ?? {}
75
+ };
76
+ }
45
77
  var ServiceComponent = class {
46
78
  handlers = /* @__PURE__ */ new Map();
79
+ serdeRegistry = new ServiceSerdeRegistry();
47
80
  constructor(componentName, description, metadata, options) {
48
81
  this.componentName = componentName;
49
82
  this.description = description;
@@ -54,13 +87,15 @@ var ServiceComponent = class {
54
87
  return this.componentName;
55
88
  }
56
89
  add(name, handlerWrapper) {
57
- this.handlers.set(name, new ServiceHandler$1(name, handlerWrapper, this));
90
+ const handler = new ServiceHandler$1(name, handlerWrapper, this);
91
+ this.handlers.set(name, handler);
92
+ this.serdeRegistry.registerHandlerIO(name, handlerWrapper, handler.executionOptions);
58
93
  }
59
94
  discovery() {
60
95
  const handlers = [...this.handlers.entries()].map(([name, handler]) => {
61
96
  return {
62
97
  name,
63
- ...commonHandlerOptions(handler.handlerWrapper, handler.executionOptions.defaultSerde ?? serde.json)
98
+ ...commonHandlerOptions(handler.handlerWrapper, handler.executionOptions.defaultSerde)
64
99
  };
65
100
  });
66
101
  return {
@@ -68,13 +103,16 @@ var ServiceComponent = class {
68
103
  ty: "SERVICE",
69
104
  handlers,
70
105
  documentation: this.description,
71
- metadata: this.metadata,
106
+ metadata: mergeMetadata(this.metadata, this.serdeRegistry.previewMetadata()),
72
107
  ...commonServiceOptions(this.options)
73
108
  };
74
109
  }
75
110
  handlerMatching(url) {
76
111
  return this.handlers.get(url.handlerName);
77
112
  }
113
+ serdeMatching(name) {
114
+ return this.serdeRegistry.resolve(name);
115
+ }
78
116
  };
79
117
  var ServiceHandler$1 = class {
80
118
  executionOptions;
@@ -99,6 +137,7 @@ var ServiceHandler$1 = class {
99
137
  };
100
138
  var VirtualObjectComponent = class {
101
139
  handlers = /* @__PURE__ */ new Map();
140
+ serdeRegistry = new ServiceSerdeRegistry();
102
141
  constructor(componentName, description, metadata, options) {
103
142
  this.componentName = componentName;
104
143
  this.description = description;
@@ -109,14 +148,16 @@ var VirtualObjectComponent = class {
109
148
  return this.componentName;
110
149
  }
111
150
  add(name, wrapper) {
112
- this.handlers.set(name, new VirtualObjectHandler(name, wrapper, this));
151
+ const handler = new VirtualObjectHandler(name, wrapper, this);
152
+ this.handlers.set(name, handler);
153
+ this.serdeRegistry.registerHandlerIO(name, wrapper, handler.executionOptions);
113
154
  }
114
155
  discovery() {
115
156
  const handlers = [...this.handlers.entries()].map(([name, handler]) => {
116
157
  return {
117
158
  name,
118
159
  ty: handler.kind() === HandlerKind.EXCLUSIVE ? "EXCLUSIVE" : "SHARED",
119
- ...commonHandlerOptions(handler.handlerWrapper, handler.executionOptions.defaultSerde ?? serde.json)
160
+ ...commonHandlerOptions(handler.handlerWrapper, handler.executionOptions.defaultSerde)
120
161
  };
121
162
  });
122
163
  return {
@@ -124,13 +165,16 @@ var VirtualObjectComponent = class {
124
165
  ty: "VIRTUAL_OBJECT",
125
166
  handlers,
126
167
  documentation: this.description,
127
- metadata: this.metadata,
168
+ metadata: mergeMetadata(this.metadata, this.serdeRegistry.previewMetadata()),
128
169
  ...commonServiceOptions(this.options)
129
170
  };
130
171
  }
131
172
  handlerMatching(url) {
132
173
  return this.handlers.get(url.handlerName);
133
174
  }
175
+ serdeMatching(name) {
176
+ return this.serdeRegistry.resolve(name);
177
+ }
134
178
  };
135
179
  var VirtualObjectHandler = class {
136
180
  executionOptions;
@@ -155,6 +199,7 @@ var VirtualObjectHandler = class {
155
199
  };
156
200
  var WorkflowComponent = class {
157
201
  handlers = /* @__PURE__ */ new Map();
202
+ serdeRegistry = new ServiceSerdeRegistry();
158
203
  constructor(componentName, description, metadata, options) {
159
204
  this.componentName = componentName;
160
205
  this.description = description;
@@ -165,7 +210,9 @@ var WorkflowComponent = class {
165
210
  return this.componentName;
166
211
  }
167
212
  add(name, wrapper) {
168
- this.handlers.set(name, new WorkflowHandler$1(name, wrapper, this));
213
+ const handler = new WorkflowHandler$1(name, wrapper, this);
214
+ this.handlers.set(name, handler);
215
+ this.serdeRegistry.registerHandlerIO(name, wrapper, handler.executionOptions);
169
216
  }
170
217
  discovery() {
171
218
  const handlers = [...this.handlers.entries()].map(([name, handler]) => {
@@ -173,7 +220,7 @@ var WorkflowComponent = class {
173
220
  name,
174
221
  ty: handler.kind() === HandlerKind.WORKFLOW ? "WORKFLOW" : "SHARED",
175
222
  workflowCompletionRetention: handler.kind() === HandlerKind.WORKFLOW && this.options?.workflowRetention !== void 0 ? millisOrDurationToMillis(this.options?.workflowRetention) : void 0,
176
- ...commonHandlerOptions(handler.handlerWrapper, handler.executionOptions.defaultSerde ?? serde.json)
223
+ ...commonHandlerOptions(handler.handlerWrapper, handler.executionOptions.defaultSerde)
177
224
  };
178
225
  });
179
226
  return {
@@ -181,13 +228,16 @@ var WorkflowComponent = class {
181
228
  ty: "WORKFLOW",
182
229
  handlers,
183
230
  documentation: this.description,
184
- metadata: this.metadata,
231
+ metadata: mergeMetadata(this.metadata, this.serdeRegistry.previewMetadata()),
185
232
  ...commonServiceOptions(this.options)
186
233
  };
187
234
  }
188
235
  handlerMatching(url) {
189
236
  return this.handlers.get(url.handlerName);
190
237
  }
238
+ serdeMatching(name) {
239
+ return this.serdeRegistry.resolve(name);
240
+ }
191
241
  };
192
242
  var WorkflowHandler$1 = class {
193
243
  executionOptions;
@@ -210,11 +260,19 @@ var WorkflowHandler$1 = class {
210
260
  return this.handlerWrapper.invoke(context, input);
211
261
  }
212
262
  };
263
+ const PREVIEW_PATH_REGEX = /(?:^|\/)serdes\/(?<componentName>[^/]+)\/(?<operation>encode|decode)\/(?<serdeName>.+?)\/?$/;
213
264
  function parseUrlComponents(urlPath) {
214
265
  if (!urlPath) return {
215
266
  type: "unknown",
216
267
  path: ""
217
268
  };
269
+ const preview = PREVIEW_PATH_REGEX.exec(urlPath);
270
+ if (preview?.groups) return {
271
+ type: "preview",
272
+ componentName: preview.groups.componentName,
273
+ operation: preview.groups.operation,
274
+ serdeName: decodeURIComponent(preview.groups.serdeName)
275
+ };
218
276
  const fragments = urlPath.split("/");
219
277
  if (fragments.length >= 3 && fragments[fragments.length - 3] === "invoke") return {
220
278
  type: "invoke",
@@ -1 +1 @@
1
- {"version":3,"file":"components.js","names":["serde","componentName: string","description?: string","metadata?: Record<string, string>","options?: ServiceOptions","ServiceHandler","handlers: d.Handler[]","handlerName: string","handlerWrapper: HandlerWrapper","parent: ServiceComponent","options?: ObjectOptions","parent: VirtualObjectComponent","options?: WorkflowOptions","WorkflowHandler","parent: WorkflowComponent"],"sources":["../../src/endpoint/components.ts"],"sourcesContent":["/*\n * Copyright (c) 2023-2024 - Restate Software, Inc., Restate GmbH\n *\n * This file is part of the Restate SDK for Node.js/TypeScript,\n * which is released under the MIT license.\n *\n * You can find a copy of the license in file LICENSE in the root\n * directory of this repository or package, or at\n * https://github.com/restatedev/sdk-typescript/blob/main/LICENSE\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport type * as d from \"./discovery.js\";\nimport type { ContextImpl } from \"../context_impl.js\";\nimport type {\n HandlerWrapper,\n ObjectOptions,\n ServiceHandlerOpts,\n ServiceOptions,\n WorkflowOptions,\n} from \"../types/rpc.js\";\nimport { HandlerKind } from \"../types/rpc.js\";\nimport type { Serde } from \"@restatedev/restate-sdk-core\";\nimport { millisOrDurationToMillis, serde } from \"@restatedev/restate-sdk-core\";\nimport type { HooksProvider } from \"../hooks.js\";\nimport type { TerminalError } from \"../types/errors.js\";\n\n//\n// Interfaces\n//\nexport interface Component {\n name(): string;\n handlerMatching(url: InvokePathComponents): ComponentHandler | undefined;\n discovery(): d.Service;\n}\n\n/**\n * Execution-related options\n */\nexport interface ExecutionOptions {\n asTerminalError?: (error: any) => TerminalError | undefined;\n /**\n * Default serde to use for requests, responses, state, side effects, awakeables, promises. Used when no other serde is specified.\n */\n defaultSerde?: Serde<any>;\n hooks?: HooksProvider[];\n explicitCancellation?: boolean;\n}\n\nexport interface ComponentHandler {\n name(): string;\n component(): Component;\n invoke(context: ContextImpl, input: Uint8Array): Promise<Uint8Array>;\n kind(): HandlerKind;\n\n /**\n * Returns the execution options, already merged with different layers (endpoint -> service -> handler)\n */\n executionOptions: ExecutionOptions;\n}\n\n//\n// Service\n//\n\nfunction handlerInputDiscovery(\n handler: HandlerWrapper,\n defaultSerde: Serde<any>\n): d.InputPayload {\n const serde = handler.options?.input ?? defaultSerde;\n\n let contentType = undefined;\n let jsonSchema = undefined;\n\n if (serde.jsonSchema) {\n jsonSchema = serde.jsonSchema;\n contentType = handler.options?.accept ?? serde.contentType;\n } else if (handler.options?.accept) {\n contentType = handler.options?.accept;\n } else if (serde.contentType) {\n contentType = serde.contentType;\n } else {\n // no input information\n return {};\n }\n\n return {\n required: false,\n contentType,\n jsonSchema,\n };\n}\n\nfunction handlerOutputDiscovery(\n handler: HandlerWrapper,\n defaultSerde: Serde<any>\n): d.OutputPayload {\n const serde = handler.options?.output ?? defaultSerde;\n\n let contentType = undefined;\n let jsonSchema = undefined;\n\n if (serde.jsonSchema) {\n jsonSchema = serde.jsonSchema;\n contentType = serde.contentType ?? \"application/json\";\n } else if (serde.contentType) {\n contentType = serde.contentType;\n } else {\n // no input information\n return { setContentTypeIfEmpty: false };\n }\n\n return {\n setContentTypeIfEmpty: false,\n jsonSchema,\n contentType,\n };\n}\n\nfunction createExecutionOptions(\n serviceOptions?: ServiceOptions,\n handlerOptions?: ServiceHandlerOpts<unknown, unknown>\n): ExecutionOptions {\n // Service-level hooks run outermost, handler-level hooks run innermost.\n // Both are merged into a single list: service hooks first, then handler hooks.\n const hooks = [\n ...(serviceOptions?.hooks ?? []),\n ...(handlerOptions?.hooks ?? []),\n ];\n return {\n defaultSerde: handlerOptions?.serde ?? serviceOptions?.serde,\n asTerminalError:\n handlerOptions?.asTerminalError ?? serviceOptions?.asTerminalError,\n hooks: hooks.length > 0 ? hooks : undefined,\n explicitCancellation:\n handlerOptions?.explicitCancellation ??\n serviceOptions?.explicitCancellation,\n };\n}\n\nexport class ServiceComponent implements Component {\n private readonly handlers: Map<string, ServiceHandler> = new Map();\n\n constructor(\n private readonly componentName: string,\n public readonly description?: string,\n public readonly metadata?: Record<string, string>,\n public readonly options?: ServiceOptions\n ) {}\n\n name(): string {\n return this.componentName;\n }\n\n add(name: string, handlerWrapper: HandlerWrapper) {\n this.handlers.set(name, new ServiceHandler(name, handlerWrapper, this));\n }\n\n discovery(): d.Service {\n const handlers: d.Handler[] = [...this.handlers.entries()].map(\n ([name, handler]) => {\n return {\n name,\n ...commonHandlerOptions(\n handler.handlerWrapper,\n handler.executionOptions.defaultSerde ?? serde.json\n ),\n } satisfies d.Handler;\n }\n );\n\n return {\n name: this.componentName,\n ty: \"SERVICE\",\n handlers,\n documentation: this.description,\n metadata: this.metadata,\n ...commonServiceOptions(this.options),\n } satisfies d.Service;\n }\n\n handlerMatching(url: InvokePathComponents): ComponentHandler | undefined {\n return this.handlers.get(url.handlerName);\n }\n}\n\nexport class ServiceHandler implements ComponentHandler {\n readonly executionOptions: ExecutionOptions;\n\n constructor(\n private readonly handlerName: string,\n public readonly handlerWrapper: HandlerWrapper,\n private readonly parent: ServiceComponent\n ) {\n this.executionOptions = createExecutionOptions(\n this.parent.options,\n handlerWrapper.options\n );\n }\n\n name(): string {\n return this.handlerName;\n }\n\n component(): Component {\n return this.parent;\n }\n\n kind(): HandlerKind {\n return this.handlerWrapper.kind;\n }\n\n invoke(context: ContextImpl, input: Uint8Array): Promise<Uint8Array> {\n return this.handlerWrapper.invoke(context, input);\n }\n}\n\n//\n// Virtual Object\n//\n\nexport class VirtualObjectComponent implements Component {\n private readonly handlers: Map<string, VirtualObjectHandler> = new Map();\n\n constructor(\n public readonly componentName: string,\n public readonly description?: string,\n public readonly metadata?: Record<string, string>,\n public readonly options?: ObjectOptions\n ) {}\n\n name(): string {\n return this.componentName;\n }\n\n add(name: string, wrapper: HandlerWrapper) {\n this.handlers.set(name, new VirtualObjectHandler(name, wrapper, this));\n }\n\n discovery(): d.Service {\n const handlers: d.Handler[] = [...this.handlers.entries()].map(\n ([name, handler]) => {\n return {\n name,\n ty: handler.kind() === HandlerKind.EXCLUSIVE ? \"EXCLUSIVE\" : \"SHARED\",\n ...commonHandlerOptions(\n handler.handlerWrapper,\n handler.executionOptions.defaultSerde ?? serde.json\n ),\n } satisfies d.Handler;\n }\n );\n\n return {\n name: this.componentName,\n ty: \"VIRTUAL_OBJECT\",\n handlers,\n documentation: this.description,\n metadata: this.metadata,\n ...commonServiceOptions(this.options),\n } satisfies d.Service;\n }\n\n handlerMatching(url: InvokePathComponents): ComponentHandler | undefined {\n return this.handlers.get(url.handlerName);\n }\n}\n\nexport class VirtualObjectHandler implements ComponentHandler {\n readonly executionOptions: ExecutionOptions;\n\n constructor(\n private readonly handlerName: string,\n public readonly handlerWrapper: HandlerWrapper,\n private readonly parent: VirtualObjectComponent\n ) {\n this.executionOptions = createExecutionOptions(\n this.parent.options,\n handlerWrapper.options\n );\n }\n\n name(): string {\n return this.handlerName;\n }\n\n component(): Component {\n return this.parent;\n }\n\n kind(): HandlerKind {\n return this.handlerWrapper.kind;\n }\n\n invoke(context: ContextImpl, input: Uint8Array): Promise<Uint8Array> {\n return this.handlerWrapper.invoke(context, input);\n }\n}\n\n// Workflow\n\nexport class WorkflowComponent implements Component {\n private readonly handlers: Map<string, WorkflowHandler> = new Map();\n\n constructor(\n public readonly componentName: string,\n public readonly description?: string,\n public readonly metadata?: Record<string, string>,\n public readonly options?: WorkflowOptions\n ) {}\n\n name(): string {\n return this.componentName;\n }\n\n add(name: string, wrapper: HandlerWrapper) {\n this.handlers.set(name, new WorkflowHandler(name, wrapper, this));\n }\n\n discovery(): d.Service {\n const handlers: d.Handler[] = [...this.handlers.entries()].map(\n ([name, handler]) => {\n return {\n name,\n ty: handler.kind() === HandlerKind.WORKFLOW ? \"WORKFLOW\" : \"SHARED\",\n workflowCompletionRetention:\n handler.kind() === HandlerKind.WORKFLOW &&\n this.options?.workflowRetention !== undefined\n ? millisOrDurationToMillis(this.options?.workflowRetention)\n : undefined,\n ...commonHandlerOptions(\n handler.handlerWrapper,\n handler.executionOptions.defaultSerde ?? serde.json\n ),\n } satisfies d.Handler;\n }\n );\n\n return {\n name: this.componentName,\n ty: \"WORKFLOW\",\n handlers,\n documentation: this.description,\n metadata: this.metadata,\n ...commonServiceOptions(this.options),\n } satisfies d.Service;\n }\n\n handlerMatching(url: InvokePathComponents): ComponentHandler | undefined {\n return this.handlers.get(url.handlerName);\n }\n}\n\nexport class WorkflowHandler implements ComponentHandler {\n readonly executionOptions: ExecutionOptions;\n\n constructor(\n private readonly handlerName: string,\n public readonly handlerWrapper: HandlerWrapper,\n private readonly parent: WorkflowComponent\n ) {\n this.executionOptions = createExecutionOptions(\n this.parent.options,\n handlerWrapper.options\n );\n }\n\n name(): string {\n return this.handlerName;\n }\n component(): Component {\n return this.parent;\n }\n\n kind(): HandlerKind {\n return this.handlerWrapper.kind;\n }\n\n invoke(context: ContextImpl, input: Uint8Array): Promise<Uint8Array> {\n return this.handlerWrapper.invoke(context, input);\n }\n}\n\nexport type PathComponents =\n | InvokePathComponents\n | { type: \"discover\" }\n | { type: \"health\" }\n | { type: \"unknown\"; path: string };\n\nexport type InvokePathComponents = {\n type: \"invoke\";\n componentName: string;\n handlerName: string;\n};\n\nexport function parseUrlComponents(urlPath?: string): PathComponents {\n if (!urlPath) {\n return { type: \"unknown\", path: \"\" };\n }\n const fragments = urlPath.split(\"/\");\n if (fragments.length >= 3 && fragments[fragments.length - 3] === \"invoke\") {\n return {\n type: \"invoke\",\n componentName: fragments[fragments.length - 2]!,\n handlerName: fragments[fragments.length - 1]!,\n };\n }\n if (fragments.length > 0 && fragments[fragments.length - 1] === \"discover\") {\n return { type: \"discover\" };\n }\n if (fragments.length > 0 && fragments[fragments.length - 1] === \"health\") {\n return { type: \"health\" };\n }\n return { type: \"unknown\", path: urlPath };\n}\n\nfunction commonServiceOptions(\n options?: ServiceOptions | ObjectOptions | WorkflowOptions\n): Partial<d.Service> {\n return {\n journalRetention:\n options?.journalRetention !== undefined\n ? millisOrDurationToMillis(options.journalRetention)\n : undefined,\n idempotencyRetention:\n options?.idempotencyRetention !== undefined\n ? millisOrDurationToMillis(options.idempotencyRetention)\n : undefined,\n inactivityTimeout:\n options?.inactivityTimeout !== undefined\n ? millisOrDurationToMillis(options.inactivityTimeout)\n : undefined,\n abortTimeout:\n options?.abortTimeout !== undefined\n ? millisOrDurationToMillis(options.abortTimeout)\n : undefined,\n ingressPrivate: options?.ingressPrivate,\n enableLazyState:\n options !== undefined && \"enableLazyState\" in options\n ? options.enableLazyState\n : undefined,\n retryPolicyExponentiationFactor: options?.retryPolicy?.exponentiationFactor,\n retryPolicyInitialInterval:\n options?.retryPolicy?.initialInterval !== undefined\n ? millisOrDurationToMillis(options?.retryPolicy?.initialInterval)\n : undefined,\n retryPolicyMaxInterval:\n options?.retryPolicy?.maxInterval !== undefined\n ? millisOrDurationToMillis(options?.retryPolicy?.maxInterval)\n : undefined,\n retryPolicyMaxAttempts: options?.retryPolicy?.maxAttempts,\n retryPolicyOnMaxAttempts: (options?.retryPolicy?.onMaxAttempts === \"kill\"\n ? \"KILL\"\n : options?.retryPolicy?.onMaxAttempts === \"pause\"\n ? \"PAUSE\"\n : undefined) as d.RetryPolicyOnMaxAttempts,\n };\n}\n\nfunction commonHandlerOptions(\n wrapper: HandlerWrapper,\n defaultSerde: Serde<any>\n) {\n return {\n input: handlerInputDiscovery(wrapper, defaultSerde),\n output: handlerOutputDiscovery(wrapper, defaultSerde),\n journalRetention:\n wrapper.options?.journalRetention !== undefined\n ? millisOrDurationToMillis(wrapper.options?.journalRetention)\n : undefined,\n idempotencyRetention:\n wrapper.options?.idempotencyRetention !== undefined\n ? millisOrDurationToMillis(wrapper.options?.idempotencyRetention)\n : undefined,\n inactivityTimeout:\n wrapper.options?.inactivityTimeout !== undefined\n ? millisOrDurationToMillis(wrapper.options?.inactivityTimeout)\n : undefined,\n abortTimeout:\n wrapper.options?.abortTimeout !== undefined\n ? millisOrDurationToMillis(wrapper.options?.abortTimeout)\n : undefined,\n ingressPrivate: wrapper.options?.ingressPrivate,\n enableLazyState:\n wrapper.options !== undefined && \"enableLazyState\" in wrapper.options\n ? wrapper.options?.enableLazyState\n : undefined,\n retryPolicyExponentiationFactor:\n wrapper.options?.retryPolicy?.exponentiationFactor,\n retryPolicyInitialInterval:\n wrapper.options?.retryPolicy?.initialInterval !== undefined\n ? millisOrDurationToMillis(\n wrapper.options?.retryPolicy?.initialInterval\n )\n : undefined,\n retryPolicyMaxInterval:\n wrapper.options?.retryPolicy?.maxInterval !== undefined\n ? millisOrDurationToMillis(wrapper.options?.retryPolicy?.maxInterval)\n : undefined,\n retryPolicyMaxAttempts: wrapper.options?.retryPolicy?.maxAttempts,\n retryPolicyOnMaxAttempts: (wrapper.options?.retryPolicy?.onMaxAttempts ===\n \"kill\"\n ? \"KILL\"\n : wrapper.options?.retryPolicy?.onMaxAttempts === \"pause\"\n ? \"PAUSE\"\n : undefined) as d.RetryPolicyOnMaxAttempts1,\n\n documentation: wrapper.options?.description,\n metadata: wrapper.options?.metadata,\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"components.js","names":["serde","metadata: Record<string, string>","componentName: string","description?: string","metadata?: Record<string, string>","options?: ServiceOptions","ServiceHandler","handlers: d.Handler[]","handlerName: string","handlerWrapper: HandlerWrapper","parent: ServiceComponent","options?: ObjectOptions","parent: VirtualObjectComponent","options?: WorkflowOptions","WorkflowHandler","parent: WorkflowComponent"],"sources":["../../src/endpoint/components.ts"],"sourcesContent":["/*\n * Copyright (c) 2023-2024 - Restate Software, Inc., Restate GmbH\n *\n * This file is part of the Restate SDK for Node.js/TypeScript,\n * which is released under the MIT license.\n *\n * You can find a copy of the license in file LICENSE in the root\n * directory of this repository or package, or at\n * https://github.com/restatedev/sdk-typescript/blob/main/LICENSE\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport type * as d from \"./discovery.js\";\nimport type { ContextImpl } from \"../context_impl.js\";\nimport type {\n HandlerWrapper,\n ObjectOptions,\n ServiceHandlerOpts,\n ServiceOptions,\n WorkflowOptions,\n} from \"../types/rpc.js\";\nimport { HandlerKind } from \"../types/rpc.js\";\nimport type { Serde } from \"@restatedev/restate-sdk-core\";\nimport { millisOrDurationToMillis, serde } from \"@restatedev/restate-sdk-core\";\nimport type { HooksProvider } from \"../hooks.js\";\nimport type { TerminalError } from \"../types/errors.js\";\n\n//\n// Interfaces\n//\nexport interface Component {\n name(): string;\n handlerMatching(url: InvokePathComponents): ComponentHandler | undefined;\n serdeMatching(name: string): Serde<any> | undefined;\n discovery(): d.Service;\n}\n\n/**\n * Execution-related options\n */\nexport interface ExecutionOptions {\n asTerminalError?: (error: any) => TerminalError | undefined;\n /**\n * Default serde to use for requests, responses, state, side effects, awakeables, promises. Used when no other serde is specified.\n */\n defaultSerde: Serde<any>;\n hooks?: HooksProvider[];\n explicitCancellation?: boolean;\n}\n\nexport interface ComponentHandler {\n name(): string;\n component(): Component;\n invoke(context: ContextImpl, input: Uint8Array): Promise<Uint8Array>;\n kind(): HandlerKind;\n\n /**\n * Returns the execution options, already merged with different layers (endpoint -> service -> handler)\n */\n executionOptions: ExecutionOptions;\n}\n\n//\n// Service\n//\n\nfunction handlerInputDiscovery(\n handler: HandlerWrapper,\n defaultSerde: Serde<any>\n): d.InputPayload {\n const serde = handler.options?.input ?? defaultSerde;\n\n let contentType = undefined;\n let jsonSchema = undefined;\n\n if (serde.jsonSchema) {\n jsonSchema = serde.jsonSchema;\n contentType = handler.options?.accept ?? serde.contentType;\n } else if (handler.options?.accept) {\n contentType = handler.options?.accept;\n } else if (serde.contentType) {\n contentType = serde.contentType;\n } else {\n // no input information\n return {};\n }\n\n return {\n required: false,\n contentType,\n jsonSchema,\n };\n}\n\nfunction handlerOutputDiscovery(\n handler: HandlerWrapper,\n defaultSerde: Serde<any>\n): d.OutputPayload {\n const serde = handler.options?.output ?? defaultSerde;\n const setContentTypeIfEmpty =\n handler.options?.setOutputContentTypeIfEmpty ?? false;\n\n let contentType = undefined;\n let jsonSchema = undefined;\n\n if (serde.jsonSchema) {\n jsonSchema = serde.jsonSchema;\n contentType = serde.contentType ?? \"application/json\";\n } else if (serde.contentType) {\n contentType = serde.contentType;\n } else {\n // no input information\n return { setContentTypeIfEmpty };\n }\n\n return {\n setContentTypeIfEmpty,\n jsonSchema,\n contentType,\n };\n}\n\nfunction createExecutionOptions(\n serviceOptions?: ServiceOptions,\n handlerOptions?: ServiceHandlerOpts<unknown, unknown>\n): ExecutionOptions {\n const defaultSerde =\n handlerOptions?.serde ?? serviceOptions?.serde ?? serde.json;\n\n // Service-level hooks run outermost, handler-level hooks run innermost.\n // Both are merged into a single list: service hooks first, then handler hooks.\n const hooks = [\n ...(serviceOptions?.hooks ?? []),\n ...(handlerOptions?.hooks ?? []),\n ];\n return {\n defaultSerde,\n asTerminalError:\n handlerOptions?.asTerminalError ?? serviceOptions?.asTerminalError,\n hooks: hooks.length > 0 ? hooks : undefined,\n explicitCancellation:\n handlerOptions?.explicitCancellation ??\n serviceOptions?.explicitCancellation,\n };\n}\n\nconst PREVIEW_METADATA_KEY_PREFIX = \"dev.restate.serde.preview\";\n\n/**\n * Service-scoped serde namespace.\n *\n * Today it is populated from handler inputs/outputs under `<handler>/input`\n * and `<handler>/output`. Custom service-level serdes can be registered\n * alongside them under any name.\n */\nclass ServiceSerdeRegistry {\n private readonly serdes = new Map<string, Serde<unknown>>();\n\n registerHandlerIO(\n handlerName: string,\n wrapper: HandlerWrapper,\n executionOptions: ExecutionOptions\n ): void {\n this.serdes.set(\n `${handlerName}/input`,\n wrapper.options?.input ?? executionOptions.defaultSerde\n );\n this.serdes.set(\n `${handlerName}/output`,\n wrapper.options?.output ?? executionOptions.defaultSerde\n );\n }\n\n resolve(name: string): Serde<unknown> | undefined {\n return this.serdes.get(name);\n }\n\n previewMetadata(): Record<string, string> | undefined {\n const metadata: Record<string, string> = {};\n for (const [name, s] of this.serdes) {\n if (s.preview) {\n metadata[`${PREVIEW_METADATA_KEY_PREFIX}.${name}`] = \"true\";\n }\n }\n return Object.keys(metadata).length > 0 ? metadata : undefined;\n }\n}\n\nfunction mergeMetadata(\n baseMetadata?: Record<string, string>,\n additionalMetadata?: Record<string, string>\n): Record<string, string> | undefined {\n if (!baseMetadata && !additionalMetadata) {\n return undefined;\n }\n\n return {\n ...(baseMetadata ?? {}),\n ...(additionalMetadata ?? {}),\n };\n}\n\nexport class ServiceComponent implements Component {\n private readonly handlers: Map<string, ServiceHandler> = new Map();\n private readonly serdeRegistry = new ServiceSerdeRegistry();\n\n constructor(\n private readonly componentName: string,\n public readonly description?: string,\n public readonly metadata?: Record<string, string>,\n public readonly options?: ServiceOptions\n ) {}\n\n name(): string {\n return this.componentName;\n }\n\n add(name: string, handlerWrapper: HandlerWrapper) {\n const handler = new ServiceHandler(name, handlerWrapper, this);\n this.handlers.set(name, handler);\n this.serdeRegistry.registerHandlerIO(\n name,\n handlerWrapper,\n handler.executionOptions\n );\n }\n\n discovery(): d.Service {\n const handlers: d.Handler[] = [...this.handlers.entries()].map(\n ([name, handler]) => {\n return {\n name,\n ...commonHandlerOptions(\n handler.handlerWrapper,\n handler.executionOptions.defaultSerde\n ),\n } satisfies d.Handler;\n }\n );\n\n return {\n name: this.componentName,\n ty: \"SERVICE\",\n handlers,\n documentation: this.description,\n metadata: mergeMetadata(\n this.metadata,\n this.serdeRegistry.previewMetadata()\n ),\n ...commonServiceOptions(this.options),\n } satisfies d.Service;\n }\n\n handlerMatching(url: InvokePathComponents): ComponentHandler | undefined {\n return this.handlers.get(url.handlerName);\n }\n\n serdeMatching(name: string): Serde<any> | undefined {\n return this.serdeRegistry.resolve(name);\n }\n}\n\nexport class ServiceHandler implements ComponentHandler {\n readonly executionOptions: ExecutionOptions;\n\n constructor(\n private readonly handlerName: string,\n public readonly handlerWrapper: HandlerWrapper,\n private readonly parent: ServiceComponent\n ) {\n this.executionOptions = createExecutionOptions(\n this.parent.options,\n handlerWrapper.options\n );\n }\n\n name(): string {\n return this.handlerName;\n }\n\n component(): Component {\n return this.parent;\n }\n\n kind(): HandlerKind {\n return this.handlerWrapper.kind;\n }\n\n invoke(context: ContextImpl, input: Uint8Array): Promise<Uint8Array> {\n return this.handlerWrapper.invoke(context, input);\n }\n}\n\n//\n// Virtual Object\n//\n\nexport class VirtualObjectComponent implements Component {\n private readonly handlers: Map<string, VirtualObjectHandler> = new Map();\n private readonly serdeRegistry = new ServiceSerdeRegistry();\n\n constructor(\n public readonly componentName: string,\n public readonly description?: string,\n public readonly metadata?: Record<string, string>,\n public readonly options?: ObjectOptions\n ) {}\n\n name(): string {\n return this.componentName;\n }\n\n add(name: string, wrapper: HandlerWrapper) {\n const handler = new VirtualObjectHandler(name, wrapper, this);\n this.handlers.set(name, handler);\n this.serdeRegistry.registerHandlerIO(\n name,\n wrapper,\n handler.executionOptions\n );\n }\n\n discovery(): d.Service {\n const handlers: d.Handler[] = [...this.handlers.entries()].map(\n ([name, handler]) => {\n return {\n name,\n ty: handler.kind() === HandlerKind.EXCLUSIVE ? \"EXCLUSIVE\" : \"SHARED\",\n ...commonHandlerOptions(\n handler.handlerWrapper,\n handler.executionOptions.defaultSerde\n ),\n } satisfies d.Handler;\n }\n );\n\n return {\n name: this.componentName,\n ty: \"VIRTUAL_OBJECT\",\n handlers,\n documentation: this.description,\n metadata: mergeMetadata(\n this.metadata,\n this.serdeRegistry.previewMetadata()\n ),\n ...commonServiceOptions(this.options),\n } satisfies d.Service;\n }\n\n handlerMatching(url: InvokePathComponents): ComponentHandler | undefined {\n return this.handlers.get(url.handlerName);\n }\n\n serdeMatching(name: string): Serde<any> | undefined {\n return this.serdeRegistry.resolve(name);\n }\n}\n\nexport class VirtualObjectHandler implements ComponentHandler {\n readonly executionOptions: ExecutionOptions;\n\n constructor(\n private readonly handlerName: string,\n public readonly handlerWrapper: HandlerWrapper,\n private readonly parent: VirtualObjectComponent\n ) {\n this.executionOptions = createExecutionOptions(\n this.parent.options,\n handlerWrapper.options\n );\n }\n\n name(): string {\n return this.handlerName;\n }\n\n component(): Component {\n return this.parent;\n }\n\n kind(): HandlerKind {\n return this.handlerWrapper.kind;\n }\n\n invoke(context: ContextImpl, input: Uint8Array): Promise<Uint8Array> {\n return this.handlerWrapper.invoke(context, input);\n }\n}\n\n// Workflow\n\nexport class WorkflowComponent implements Component {\n private readonly handlers: Map<string, WorkflowHandler> = new Map();\n private readonly serdeRegistry = new ServiceSerdeRegistry();\n\n constructor(\n public readonly componentName: string,\n public readonly description?: string,\n public readonly metadata?: Record<string, string>,\n public readonly options?: WorkflowOptions\n ) {}\n\n name(): string {\n return this.componentName;\n }\n\n add(name: string, wrapper: HandlerWrapper) {\n const handler = new WorkflowHandler(name, wrapper, this);\n this.handlers.set(name, handler);\n this.serdeRegistry.registerHandlerIO(\n name,\n wrapper,\n handler.executionOptions\n );\n }\n\n discovery(): d.Service {\n const handlers: d.Handler[] = [...this.handlers.entries()].map(\n ([name, handler]) => {\n return {\n name,\n ty: handler.kind() === HandlerKind.WORKFLOW ? \"WORKFLOW\" : \"SHARED\",\n workflowCompletionRetention:\n handler.kind() === HandlerKind.WORKFLOW &&\n this.options?.workflowRetention !== undefined\n ? millisOrDurationToMillis(this.options?.workflowRetention)\n : undefined,\n ...commonHandlerOptions(\n handler.handlerWrapper,\n handler.executionOptions.defaultSerde\n ),\n } satisfies d.Handler;\n }\n );\n\n return {\n name: this.componentName,\n ty: \"WORKFLOW\",\n handlers,\n documentation: this.description,\n metadata: mergeMetadata(\n this.metadata,\n this.serdeRegistry.previewMetadata()\n ),\n ...commonServiceOptions(this.options),\n } satisfies d.Service;\n }\n\n handlerMatching(url: InvokePathComponents): ComponentHandler | undefined {\n return this.handlers.get(url.handlerName);\n }\n\n serdeMatching(name: string): Serde<any> | undefined {\n return this.serdeRegistry.resolve(name);\n }\n}\n\nexport class WorkflowHandler implements ComponentHandler {\n readonly executionOptions: ExecutionOptions;\n\n constructor(\n private readonly handlerName: string,\n public readonly handlerWrapper: HandlerWrapper,\n private readonly parent: WorkflowComponent\n ) {\n this.executionOptions = createExecutionOptions(\n this.parent.options,\n handlerWrapper.options\n );\n }\n\n name(): string {\n return this.handlerName;\n }\n component(): Component {\n return this.parent;\n }\n\n kind(): HandlerKind {\n return this.handlerWrapper.kind;\n }\n\n invoke(context: ContextImpl, input: Uint8Array): Promise<Uint8Array> {\n return this.handlerWrapper.invoke(context, input);\n }\n}\n\nexport type PathComponents =\n | InvokePathComponents\n | PreviewPathComponents\n | { type: \"discover\" }\n | { type: \"health\" }\n | { type: \"unknown\"; path: string };\n\nexport type InvokePathComponents = {\n type: \"invoke\";\n componentName: string;\n handlerName: string;\n};\n\nexport type PreviewPathComponents = {\n type: \"preview\";\n componentName: string;\n operation: \"decode\" | \"encode\";\n serdeName: string;\n};\n\n// Preview uses a regex so that `serdeName` can span multiple path segments\n// (built-ins are shaped as `<handler>/(input|output)`). The regex is anchored\n// with `(?:^|\\/)` so deployments mounted under a sub-path also work.\nconst PREVIEW_PATH_REGEX =\n /(?:^|\\/)serdes\\/(?<componentName>[^/]+)\\/(?<operation>encode|decode)\\/(?<serdeName>.+?)\\/?$/;\n\nexport function parseUrlComponents(urlPath?: string): PathComponents {\n if (!urlPath) {\n return { type: \"unknown\", path: \"\" };\n }\n\n const preview = PREVIEW_PATH_REGEX.exec(urlPath);\n if (preview?.groups) {\n return {\n type: \"preview\",\n componentName: preview.groups.componentName!,\n operation: preview.groups.operation as \"decode\" | \"encode\",\n serdeName: decodeURIComponent(preview.groups.serdeName!),\n };\n }\n\n const fragments = urlPath.split(\"/\");\n if (fragments.length >= 3 && fragments[fragments.length - 3] === \"invoke\") {\n return {\n type: \"invoke\",\n componentName: fragments[fragments.length - 2]!,\n handlerName: fragments[fragments.length - 1]!,\n };\n }\n if (fragments.length > 0 && fragments[fragments.length - 1] === \"discover\") {\n return { type: \"discover\" };\n }\n if (fragments.length > 0 && fragments[fragments.length - 1] === \"health\") {\n return { type: \"health\" };\n }\n return { type: \"unknown\", path: urlPath };\n}\n\nfunction commonServiceOptions(\n options?: ServiceOptions | ObjectOptions | WorkflowOptions\n): Partial<d.Service> {\n return {\n journalRetention:\n options?.journalRetention !== undefined\n ? millisOrDurationToMillis(options.journalRetention)\n : undefined,\n idempotencyRetention:\n options?.idempotencyRetention !== undefined\n ? millisOrDurationToMillis(options.idempotencyRetention)\n : undefined,\n inactivityTimeout:\n options?.inactivityTimeout !== undefined\n ? millisOrDurationToMillis(options.inactivityTimeout)\n : undefined,\n abortTimeout:\n options?.abortTimeout !== undefined\n ? millisOrDurationToMillis(options.abortTimeout)\n : undefined,\n ingressPrivate: options?.ingressPrivate,\n enableLazyState:\n options !== undefined && \"enableLazyState\" in options\n ? options.enableLazyState\n : undefined,\n retryPolicyExponentiationFactor: options?.retryPolicy?.exponentiationFactor,\n retryPolicyInitialInterval:\n options?.retryPolicy?.initialInterval !== undefined\n ? millisOrDurationToMillis(options?.retryPolicy?.initialInterval)\n : undefined,\n retryPolicyMaxInterval:\n options?.retryPolicy?.maxInterval !== undefined\n ? millisOrDurationToMillis(options?.retryPolicy?.maxInterval)\n : undefined,\n retryPolicyMaxAttempts: options?.retryPolicy?.maxAttempts,\n retryPolicyOnMaxAttempts: (options?.retryPolicy?.onMaxAttempts === \"kill\"\n ? \"KILL\"\n : options?.retryPolicy?.onMaxAttempts === \"pause\"\n ? \"PAUSE\"\n : undefined) as d.RetryPolicyOnMaxAttempts,\n };\n}\n\nfunction commonHandlerOptions(\n wrapper: HandlerWrapper,\n defaultSerde: Serde<any>\n) {\n return {\n input: handlerInputDiscovery(wrapper, defaultSerde),\n output: handlerOutputDiscovery(wrapper, defaultSerde),\n journalRetention:\n wrapper.options?.journalRetention !== undefined\n ? millisOrDurationToMillis(wrapper.options?.journalRetention)\n : undefined,\n idempotencyRetention:\n wrapper.options?.idempotencyRetention !== undefined\n ? millisOrDurationToMillis(wrapper.options?.idempotencyRetention)\n : undefined,\n inactivityTimeout:\n wrapper.options?.inactivityTimeout !== undefined\n ? millisOrDurationToMillis(wrapper.options?.inactivityTimeout)\n : undefined,\n abortTimeout:\n wrapper.options?.abortTimeout !== undefined\n ? millisOrDurationToMillis(wrapper.options?.abortTimeout)\n : undefined,\n ingressPrivate: wrapper.options?.ingressPrivate,\n enableLazyState:\n wrapper.options !== undefined && \"enableLazyState\" in wrapper.options\n ? wrapper.options?.enableLazyState\n : undefined,\n retryPolicyExponentiationFactor:\n wrapper.options?.retryPolicy?.exponentiationFactor,\n retryPolicyInitialInterval:\n wrapper.options?.retryPolicy?.initialInterval !== undefined\n ? millisOrDurationToMillis(\n wrapper.options?.retryPolicy?.initialInterval\n )\n : undefined,\n retryPolicyMaxInterval:\n wrapper.options?.retryPolicy?.maxInterval !== undefined\n ? millisOrDurationToMillis(wrapper.options?.retryPolicy?.maxInterval)\n : undefined,\n retryPolicyMaxAttempts: wrapper.options?.retryPolicy?.maxAttempts,\n retryPolicyOnMaxAttempts: (wrapper.options?.retryPolicy?.onMaxAttempts ===\n \"kill\"\n ? \"KILL\"\n : wrapper.options?.retryPolicy?.onMaxAttempts === \"pause\"\n ? \"PAUSE\"\n : undefined) as d.RetryPolicyOnMaxAttempts1,\n\n documentation: wrapper.options?.description,\n metadata: wrapper.options?.metadata,\n };\n}\n"],"mappings":"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"}
@@ -14,17 +14,19 @@ function fetcher(handler) {
14
14
  const inputReader = event.body ? event.body[Symbol.asyncIterator]() : require_utils.emptyInputReader();
15
15
  const transformStream = new TransformStream();
16
16
  const outputWriter = transformStream.writable.getWriter();
17
+ const { writeHead, head } = require_utils.captureHead();
17
18
  response.process({
18
19
  inputReader,
19
20
  outputWriter,
21
+ writeHead,
20
22
  abortSignal: event.signal
21
23
  }).catch((e) => {
22
24
  const error = require_errors.ensureError(e);
23
25
  (require_utils.tryCreateContextualLogger(handler.endpoint.loggerTransport, url, headers) ?? handler.endpoint.rlog).error("Unexpected error: " + (error.stack ?? error.message));
24
26
  });
25
- return Promise.resolve(new Response(transformStream.readable, {
26
- status: response.statusCode,
27
- headers: response.headers
27
+ return head.then((h) => new Response(transformStream.readable, {
28
+ status: h.statusCode,
29
+ headers: h.headers
28
30
  }));
29
31
  } };
30
32
  }
@@ -1,5 +1,5 @@
1
1
  import { ensureError } from "../../types/errors.js";
2
- import { emptyInputReader, tryCreateContextualLogger } from "./utils.js";
2
+ import { captureHead, emptyInputReader, tryCreateContextualLogger } from "./utils.js";
3
3
 
4
4
  //#region src/endpoint/handlers/fetch.ts
5
5
  function fetcher(handler) {
@@ -14,17 +14,19 @@ function fetcher(handler) {
14
14
  const inputReader = event.body ? event.body[Symbol.asyncIterator]() : emptyInputReader();
15
15
  const transformStream = new TransformStream();
16
16
  const outputWriter = transformStream.writable.getWriter();
17
+ const { writeHead, head } = captureHead();
17
18
  response.process({
18
19
  inputReader,
19
20
  outputWriter,
21
+ writeHead,
20
22
  abortSignal: event.signal
21
23
  }).catch((e) => {
22
24
  const error = ensureError(e);
23
25
  (tryCreateContextualLogger(handler.endpoint.loggerTransport, url, headers) ?? handler.endpoint.rlog).error("Unexpected error: " + (error.stack ?? error.message));
24
26
  });
25
- return Promise.resolve(new Response(transformStream.readable, {
26
- status: response.statusCode,
27
- headers: response.headers
27
+ return head.then((h) => new Response(transformStream.readable, {
28
+ status: h.statusCode,
29
+ headers: h.headers
28
30
  }));
29
31
  } };
30
32
  }
@@ -1 +1 @@
1
- {"version":3,"file":"fetch.js","names":[],"sources":["../../../src/endpoint/handlers/fetch.ts"],"sourcesContent":["/*\n * Copyright (c) 2023-2024 - Restate Software, Inc., Restate GmbH\n *\n * This file is part of the Restate SDK for Node.js/TypeScript,\n * which is released under the MIT license.\n *\n * You can find a copy of the license in file LICENSE in the root\n * directory of this repository or package, or at\n * https://github.com/restatedev/sdk-typescript/blob/main/LICENSE\n */\n\nimport { ensureError } from \"../../types/errors.js\";\nimport type { RestateHandler } from \"./types.js\";\nimport { emptyInputReader, tryCreateContextualLogger } from \"./utils.js\";\n\nexport function fetcher(handler: RestateHandler) {\n return {\n fetch: (event: Request, ...extraArgs: unknown[]): Promise<Response> => {\n const url = event.url;\n const headers = Object.fromEntries(event.headers.entries());\n\n const response = handler.handle({\n url,\n headers,\n extraArgs,\n });\n\n const inputReader = event.body\n ? event.body[Symbol.asyncIterator]()\n : emptyInputReader();\n\n // We use the TransformStream here to adapt writer -> reader\n const transformStream = new TransformStream<Uint8Array>();\n const outputWriter = transformStream.writable.getWriter();\n\n // Start processing, then return back the response\n response\n .process({\n inputReader,\n outputWriter,\n abortSignal: event.signal,\n })\n .catch((e) => {\n // handle should never throw\n const error = ensureError(e);\n const logger =\n tryCreateContextualLogger(\n handler.endpoint.loggerTransport,\n url,\n headers\n ) ?? handler.endpoint.rlog;\n logger.error(\"Unexpected error: \" + (error.stack ?? error.message));\n });\n\n return Promise.resolve(\n new Response(transformStream.readable, {\n status: response.statusCode,\n headers: response.headers,\n })\n );\n },\n };\n}\n"],"mappings":";;;;AAeA,SAAgB,QAAQ,SAAyB;AAC/C,QAAO,EACL,QAAQ,OAAgB,GAAG,cAA4C;EACrE,MAAM,MAAM,MAAM;EAClB,MAAM,UAAU,OAAO,YAAY,MAAM,QAAQ,SAAS,CAAC;EAE3D,MAAM,WAAW,QAAQ,OAAO;GAC9B;GACA;GACA;GACD,CAAC;EAEF,MAAM,cAAc,MAAM,OACtB,MAAM,KAAK,OAAO,gBAAgB,GAClC,kBAAkB;EAGtB,MAAM,kBAAkB,IAAI,iBAA6B;EACzD,MAAM,eAAe,gBAAgB,SAAS,WAAW;AAGzD,WACG,QAAQ;GACP;GACA;GACA,aAAa,MAAM;GACpB,CAAC,CACD,OAAO,MAAM;GAEZ,MAAM,QAAQ,YAAY,EAAE;AAO5B,IALE,0BACE,QAAQ,SAAS,iBACjB,KACA,QACD,IAAI,QAAQ,SAAS,MACjB,MAAM,wBAAwB,MAAM,SAAS,MAAM,SAAS;IACnE;AAEJ,SAAO,QAAQ,QACb,IAAI,SAAS,gBAAgB,UAAU;GACrC,QAAQ,SAAS;GACjB,SAAS,SAAS;GACnB,CAAC,CACH;IAEJ"}
1
+ {"version":3,"file":"fetch.js","names":[],"sources":["../../../src/endpoint/handlers/fetch.ts"],"sourcesContent":["/*\n * Copyright (c) 2023-2024 - Restate Software, Inc., Restate GmbH\n *\n * This file is part of the Restate SDK for Node.js/TypeScript,\n * which is released under the MIT license.\n *\n * You can find a copy of the license in file LICENSE in the root\n * directory of this repository or package, or at\n * https://github.com/restatedev/sdk-typescript/blob/main/LICENSE\n */\n\nimport { ensureError } from \"../../types/errors.js\";\nimport type { RestateHandler } from \"./types.js\";\nimport {\n captureHead,\n emptyInputReader,\n tryCreateContextualLogger,\n} from \"./utils.js\";\n\nexport function fetcher(handler: RestateHandler) {\n return {\n fetch: (event: Request, ...extraArgs: unknown[]): Promise<Response> => {\n const url = event.url;\n const headers = Object.fromEntries(event.headers.entries());\n\n // handle should never throw\n const response = handler.handle({\n url,\n headers,\n extraArgs,\n });\n\n const inputReader = event.body\n ? event.body[Symbol.asyncIterator]()\n : emptyInputReader();\n\n // We use the TransformStream here to adapt writer -> reader\n const transformStream = new TransformStream<Uint8Array>();\n const outputWriter = transformStream.writable.getWriter();\n\n const { writeHead, head } = captureHead();\n\n response\n .process({\n inputReader,\n outputWriter,\n writeHead,\n abortSignal: event.signal,\n })\n .catch((e) => {\n // Responses handle their own errors before rejecting; anything\n // reaching here is an unexpected failure — just log.\n const error = ensureError(e);\n const logger =\n tryCreateContextualLogger(\n handler.endpoint.loggerTransport,\n url,\n headers\n ) ?? handler.endpoint.rlog;\n logger.error(\"Unexpected error: \" + (error.stack ?? error.message));\n });\n\n return head.then(\n (h) =>\n new Response(transformStream.readable, {\n status: h.statusCode,\n headers: h.headers,\n })\n );\n },\n };\n}\n"],"mappings":";;;;AAmBA,SAAgB,QAAQ,SAAyB;AAC/C,QAAO,EACL,QAAQ,OAAgB,GAAG,cAA4C;EACrE,MAAM,MAAM,MAAM;EAClB,MAAM,UAAU,OAAO,YAAY,MAAM,QAAQ,SAAS,CAAC;EAG3D,MAAM,WAAW,QAAQ,OAAO;GAC9B;GACA;GACA;GACD,CAAC;EAEF,MAAM,cAAc,MAAM,OACtB,MAAM,KAAK,OAAO,gBAAgB,GAClC,kBAAkB;EAGtB,MAAM,kBAAkB,IAAI,iBAA6B;EACzD,MAAM,eAAe,gBAAgB,SAAS,WAAW;EAEzD,MAAM,EAAE,WAAW,SAAS,aAAa;AAEzC,WACG,QAAQ;GACP;GACA;GACA;GACA,aAAa,MAAM;GACpB,CAAC,CACD,OAAO,MAAM;GAGZ,MAAM,QAAQ,YAAY,EAAE;AAO5B,IALE,0BACE,QAAQ,SAAS,iBACjB,KACA,QACD,IAAI,QAAQ,SAAS,MACjB,MAAM,wBAAwB,MAAM,SAAS,MAAM,SAAS;IACnE;AAEJ,SAAO,KAAK,MACT,MACC,IAAI,SAAS,gBAAgB,UAAU;GACrC,QAAQ,EAAE;GACV,SAAS,EAAE;GACZ,CAAC,CACL;IAEJ"}