@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.
- package/dist/endpoint/components.cjs +70 -12
- package/dist/endpoint/components.js +70 -12
- package/dist/endpoint/components.js.map +1 -1
- package/dist/endpoint/handlers/fetch.cjs +5 -3
- package/dist/endpoint/handlers/fetch.js +6 -4
- package/dist/endpoint/handlers/fetch.js.map +1 -1
- package/dist/endpoint/handlers/generic.cjs +11 -10
- package/dist/endpoint/handlers/generic.js +11 -10
- package/dist/endpoint/handlers/generic.js.map +1 -1
- package/dist/endpoint/handlers/lambda.cjs +6 -3
- package/dist/endpoint/handlers/lambda.js +7 -4
- package/dist/endpoint/handlers/lambda.js.map +1 -1
- package/dist/endpoint/handlers/preview.cjs +97 -0
- package/dist/endpoint/handlers/preview.js +98 -0
- package/dist/endpoint/handlers/preview.js.map +1 -0
- package/dist/endpoint/handlers/utils.cjs +26 -11
- package/dist/endpoint/handlers/utils.js +26 -12
- package/dist/endpoint/handlers/utils.js.map +1 -1
- package/dist/endpoint/node_endpoint.cjs +9 -6
- package/dist/endpoint/node_endpoint.js +9 -6
- package/dist/endpoint/node_endpoint.js.map +1 -1
- package/dist/io.cjs +7 -2
- package/dist/io.js +7 -2
- package/dist/io.js.map +1 -1
- package/dist/package.cjs +1 -1
- package/dist/package.js +1 -1
- package/dist/package.js.map +1 -1
- package/dist/promises.cjs +21 -10
- package/dist/promises.js +21 -10
- package/dist/promises.js.map +1 -1
- package/dist/types/rpc.d.cts +11 -0
- package/dist/types/rpc.d.cts.map +1 -1
- package/dist/types/rpc.d.ts +11 -0
- package/dist/types/rpc.d.ts.map +1 -1
- package/dist/types/rpc.js.map +1 -1
- 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
|
|
32
|
+
else return { setContentTypeIfEmpty };
|
|
32
33
|
return {
|
|
33
|
-
setContentTypeIfEmpty
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
30
|
+
else return { setContentTypeIfEmpty };
|
|
30
31
|
return {
|
|
31
|
-
setContentTypeIfEmpty
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
26
|
-
status:
|
|
27
|
-
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
|
|
26
|
-
status:
|
|
27
|
-
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 {
|
|
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"}
|