@relaybus/core 0.1.0 → 0.3.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/README.md +302 -25
- package/dist/chunk-3OHMEMZA.cjs +205 -0
- package/dist/chunk-3OHMEMZA.cjs.map +1 -0
- package/dist/chunk-WS274DL3.js +183 -0
- package/dist/chunk-WS274DL3.js.map +1 -0
- package/dist/event-DCRTuYKI.d.cts +142 -0
- package/dist/event-DCRTuYKI.d.ts +142 -0
- package/dist/index.cjs +2183 -671
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +871 -247
- package/dist/index.d.ts +871 -247
- package/dist/index.js +2054 -605
- package/dist/index.js.map +1 -1
- package/dist/internal/index.cjs +444 -0
- package/dist/internal/index.cjs.map +1 -0
- package/dist/internal/index.d.cts +171 -0
- package/dist/internal/index.d.ts +171 -0
- package/dist/internal/index.js +425 -0
- package/dist/internal/index.js.map +1 -0
- package/package.json +37 -8
|
@@ -0,0 +1,444 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunk3OHMEMZA_cjs = require('../chunk-3OHMEMZA.cjs');
|
|
4
|
+
|
|
5
|
+
// src/internal/field-extractors.ts
|
|
6
|
+
function fromHeader(name) {
|
|
7
|
+
if (name.length === 0) {
|
|
8
|
+
throw new chunk3OHMEMZA_cjs.ConfigurationError("fromHeader needs a header name");
|
|
9
|
+
}
|
|
10
|
+
return (message) => Object.hasOwn(message.headers, name) ? message.headers[name] : void 0;
|
|
11
|
+
}
|
|
12
|
+
function fromPayloadField(path) {
|
|
13
|
+
const segments = path.split(".");
|
|
14
|
+
if (segments.some((segment) => segment.length === 0)) {
|
|
15
|
+
throw new chunk3OHMEMZA_cjs.ConfigurationError(
|
|
16
|
+
`fromPayloadField needs a dotted path of non-empty names, received '${path}'`
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
return (message) => {
|
|
20
|
+
let value = message.payload;
|
|
21
|
+
for (const segment of segments) {
|
|
22
|
+
if (typeof value !== "object" || value === null || !Object.hasOwn(value, segment)) {
|
|
23
|
+
return void 0;
|
|
24
|
+
}
|
|
25
|
+
value = value[segment];
|
|
26
|
+
}
|
|
27
|
+
if (typeof value === "string") {
|
|
28
|
+
return value;
|
|
29
|
+
}
|
|
30
|
+
return Number.isSafeInteger(value) ? String(value) : void 0;
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// src/internal/cloudevents.ts
|
|
35
|
+
function mediaTypeOf(contentType) {
|
|
36
|
+
return typeof contentType === "string" ? contentType.split(";")[0].trim().toLowerCase() : void 0;
|
|
37
|
+
}
|
|
38
|
+
function isJsonObject(value) {
|
|
39
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
40
|
+
}
|
|
41
|
+
function createCloudEventReaders(invalid) {
|
|
42
|
+
const optionalAttribute = (body, name) => {
|
|
43
|
+
const value = body[name];
|
|
44
|
+
if (value !== void 0 && typeof value !== "string") {
|
|
45
|
+
throw invalid(`Attribute '${name}' must be a string`);
|
|
46
|
+
}
|
|
47
|
+
return value;
|
|
48
|
+
};
|
|
49
|
+
return {
|
|
50
|
+
optionalAttribute,
|
|
51
|
+
requiredAttribute: (body, name) => {
|
|
52
|
+
const value = optionalAttribute(body, name);
|
|
53
|
+
if (value === void 0 || value.length === 0) {
|
|
54
|
+
throw invalid(`Attribute '${name}' is missing or empty`);
|
|
55
|
+
}
|
|
56
|
+
return value;
|
|
57
|
+
},
|
|
58
|
+
assertValidType: (type, label) => {
|
|
59
|
+
try {
|
|
60
|
+
chunk3OHMEMZA_cjs.assertEventType(type);
|
|
61
|
+
} catch (error) {
|
|
62
|
+
throw invalid(`${label} is not a valid event type: ${error.message}`);
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
assertJsonDataContentType: (dataContentType) => {
|
|
66
|
+
const mediaType = mediaTypeOf(dataContentType);
|
|
67
|
+
if (mediaType !== void 0 && mediaType !== "application/json" && mediaType !== "text/json" && !mediaType.endsWith("+json")) {
|
|
68
|
+
throw invalid(`datacontenttype must be JSON, received '${dataContentType}'`);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
function writeStructuredCloudEvent(envelope, { time, data }) {
|
|
74
|
+
const attributes = {
|
|
75
|
+
specversion: "1.0",
|
|
76
|
+
id: envelope.id,
|
|
77
|
+
type: envelope.type,
|
|
78
|
+
source: envelope.source,
|
|
79
|
+
time,
|
|
80
|
+
datacontenttype: "application/json",
|
|
81
|
+
...envelope.key === null ? {} : { subject: envelope.key },
|
|
82
|
+
...envelope.correlationId === null ? {} : { correlationid: envelope.correlationId },
|
|
83
|
+
...envelope.causationId === null ? {} : { causationid: envelope.causationId }
|
|
84
|
+
};
|
|
85
|
+
return `${JSON.stringify(attributes).slice(0, -1)},"data":${data}}`;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// src/internal/json-envelope.ts
|
|
89
|
+
var OPTIONAL_NAMES = [
|
|
90
|
+
"key",
|
|
91
|
+
"source",
|
|
92
|
+
"occurredAt",
|
|
93
|
+
"correlationId",
|
|
94
|
+
"causationId"
|
|
95
|
+
];
|
|
96
|
+
var MAXIMUM_RFC3339_YEAR = 9999;
|
|
97
|
+
var RFC3339_PATTERN = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})$/i;
|
|
98
|
+
var ARRAY_INDEX = /^(?:0|[1-9]\d*)$/;
|
|
99
|
+
function createJsonEnvelopeFormat(mapping, {
|
|
100
|
+
transportIds,
|
|
101
|
+
failures
|
|
102
|
+
}) {
|
|
103
|
+
const plan = compile(mapping, transportIds);
|
|
104
|
+
return {
|
|
105
|
+
write: (envelope) => writeMessage(envelope, { plan, failures }),
|
|
106
|
+
read: (message) => readMessage(message, { plan, failures })
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
function compile(mapping, transportIds) {
|
|
110
|
+
if (!isJsonObject(mapping)) {
|
|
111
|
+
throw new chunk3OHMEMZA_cjs.ConfigurationError("jsonEnvelope needs a mapping object");
|
|
112
|
+
}
|
|
113
|
+
const optional = {};
|
|
114
|
+
for (const name of OPTIONAL_NAMES) {
|
|
115
|
+
const field = mapping[name];
|
|
116
|
+
if (field !== void 0) {
|
|
117
|
+
optional[name] = toLocation(field, name);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
const plan = {
|
|
121
|
+
type: compileType(mapping.type),
|
|
122
|
+
id: compileId(mapping.id, transportIds),
|
|
123
|
+
optional,
|
|
124
|
+
payload: compilePayload(mapping.payload),
|
|
125
|
+
headers: compileHeaders(mapping.headers),
|
|
126
|
+
mappedHeaders: /* @__PURE__ */ new Set()
|
|
127
|
+
};
|
|
128
|
+
return assertDisjoint(plan);
|
|
129
|
+
}
|
|
130
|
+
function compileType(type) {
|
|
131
|
+
if (isJsonObject(type) && typeof type["fixed"] === "string") {
|
|
132
|
+
chunk3OHMEMZA_cjs.assertEventType(type["fixed"]);
|
|
133
|
+
return { fixed: type["fixed"] };
|
|
134
|
+
}
|
|
135
|
+
if (type === void 0) {
|
|
136
|
+
throw new chunk3OHMEMZA_cjs.ConfigurationError("jsonEnvelope needs a type: { body }, { header } or { fixed }");
|
|
137
|
+
}
|
|
138
|
+
return toLocation(type, "type");
|
|
139
|
+
}
|
|
140
|
+
function compileId(id, transportIds) {
|
|
141
|
+
if (typeof id === "string" && transportIds.includes(id)) {
|
|
142
|
+
return void 0;
|
|
143
|
+
}
|
|
144
|
+
if (!isJsonObject(id)) {
|
|
145
|
+
throw new chunk3OHMEMZA_cjs.ConfigurationError(
|
|
146
|
+
`jsonEnvelope needs an id: { body }, { header } or one of ${transportIds.map((name) => `'${name}'`).join(", ")}`
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
return toLocation(id, "id");
|
|
150
|
+
}
|
|
151
|
+
function compilePayload(payload) {
|
|
152
|
+
if (payload === "whole-body") {
|
|
153
|
+
return void 0;
|
|
154
|
+
}
|
|
155
|
+
if (!isJsonObject(payload) || typeof payload["body"] !== "string") {
|
|
156
|
+
throw new chunk3OHMEMZA_cjs.ConfigurationError(
|
|
157
|
+
"jsonEnvelope needs a payload: { body: '<path>' } or 'whole-body'"
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
return toPath(payload["body"], "payload");
|
|
161
|
+
}
|
|
162
|
+
function compileHeaders(headers) {
|
|
163
|
+
if (headers === void 0 || headers === "message-headers") {
|
|
164
|
+
return void 0;
|
|
165
|
+
}
|
|
166
|
+
if (!isJsonObject(headers) || typeof headers["body"] !== "string") {
|
|
167
|
+
throw new chunk3OHMEMZA_cjs.ConfigurationError(
|
|
168
|
+
"jsonEnvelope headers must be { body: '<path>' } or 'message-headers'"
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
return toPath(headers["body"], "headers");
|
|
172
|
+
}
|
|
173
|
+
function toLocation(field, label) {
|
|
174
|
+
if (isJsonObject(field) && typeof field["header"] === "string" && field["header"].length > 0) {
|
|
175
|
+
return { label, header: field["header"] };
|
|
176
|
+
}
|
|
177
|
+
if (isJsonObject(field) && typeof field["body"] === "string") {
|
|
178
|
+
return { label, path: toPath(field["body"], label) };
|
|
179
|
+
}
|
|
180
|
+
throw new chunk3OHMEMZA_cjs.ConfigurationError(
|
|
181
|
+
`jsonEnvelope ${label} must be { body: '<path>' } or { header: '<name>' }`
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
function toPath(path, label) {
|
|
185
|
+
const segments = path.split(".");
|
|
186
|
+
if (segments.some((segment) => segment.length === 0)) {
|
|
187
|
+
throw new chunk3OHMEMZA_cjs.ConfigurationError(
|
|
188
|
+
`jsonEnvelope ${label} needs a dotted path of non-empty names, received '${path}'`
|
|
189
|
+
);
|
|
190
|
+
}
|
|
191
|
+
return segments;
|
|
192
|
+
}
|
|
193
|
+
function assertDisjoint(plan) {
|
|
194
|
+
const locations = [plan.type, plan.id, ...Object.values(plan.optional)].filter(
|
|
195
|
+
(location) => location !== void 0 && !("fixed" in location)
|
|
196
|
+
);
|
|
197
|
+
const headers = locations.flatMap((location) => "header" in location ? [location.header] : []);
|
|
198
|
+
const duplicate = headers.find((name, index) => headers.indexOf(name) !== index);
|
|
199
|
+
if (duplicate !== void 0) {
|
|
200
|
+
throw new chunk3OHMEMZA_cjs.ConfigurationError(`jsonEnvelope maps header '${duplicate}' twice`);
|
|
201
|
+
}
|
|
202
|
+
const paths = [
|
|
203
|
+
...locations.flatMap((location) => "path" in location ? [location.path] : []),
|
|
204
|
+
...[plan.payload, plan.headers].filter((path) => path !== void 0)
|
|
205
|
+
];
|
|
206
|
+
assertNoNestedPaths(paths);
|
|
207
|
+
return { ...plan, mappedHeaders: new Set(headers) };
|
|
208
|
+
}
|
|
209
|
+
function assertNoNestedPaths(paths) {
|
|
210
|
+
paths.forEach((path, index) => {
|
|
211
|
+
for (const other of paths.slice(index + 1)) {
|
|
212
|
+
assertCompatiblePaths(path, other);
|
|
213
|
+
}
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
function assertCompatiblePaths(path, other) {
|
|
217
|
+
const parting = path.findIndex((segment, position) => segment !== other[position]);
|
|
218
|
+
const both = `'${path.join(".")}' and '${other.join(".")}'`;
|
|
219
|
+
if (parting === -1 || parting === other.length) {
|
|
220
|
+
throw new chunk3OHMEMZA_cjs.ConfigurationError(`jsonEnvelope body paths ${both} overlap`);
|
|
221
|
+
}
|
|
222
|
+
if (ARRAY_INDEX.test(path[parting]) !== ARRAY_INDEX.test(other[parting])) {
|
|
223
|
+
throw new chunk3OHMEMZA_cjs.ConfigurationError(`jsonEnvelope body paths ${both} mix an array index and a name`);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
function writeMessage(envelope, { plan, failures }) {
|
|
227
|
+
const root = {};
|
|
228
|
+
const headers = [];
|
|
229
|
+
const put = (location, value) => {
|
|
230
|
+
if ("header" in location) {
|
|
231
|
+
headers.push([location.header, value]);
|
|
232
|
+
} else {
|
|
233
|
+
setAt(root, { path: location.path, value });
|
|
234
|
+
}
|
|
235
|
+
};
|
|
236
|
+
if ("fixed" in plan.type) {
|
|
237
|
+
if (envelope.type !== plan.type.fixed) {
|
|
238
|
+
throw failures.unencodable(
|
|
239
|
+
`Event ${envelope.id} has type '${envelope.type}', but this route carries only '${plan.type.fixed}'`
|
|
240
|
+
);
|
|
241
|
+
}
|
|
242
|
+
} else {
|
|
243
|
+
put(plan.type, envelope.type);
|
|
244
|
+
}
|
|
245
|
+
if (plan.id !== void 0) {
|
|
246
|
+
put(plan.id, envelope.id);
|
|
247
|
+
}
|
|
248
|
+
for (const [name, value] of optionalValues(envelope, failures)) {
|
|
249
|
+
const location = plan.optional[name];
|
|
250
|
+
if (location !== void 0 && value !== null) {
|
|
251
|
+
put(location, value);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
return {
|
|
255
|
+
body: writeBody(envelope, { plan, root }),
|
|
256
|
+
headers: Object.fromEntries([...eventHeaderEntries(envelope, { plan, failures }), ...headers])
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
function optionalValues(envelope, failures) {
|
|
260
|
+
return [
|
|
261
|
+
["key", envelope.key],
|
|
262
|
+
["source", envelope.source],
|
|
263
|
+
["occurredAt", formatTime(envelope, failures)],
|
|
264
|
+
["correlationId", envelope.correlationId],
|
|
265
|
+
["causationId", envelope.causationId]
|
|
266
|
+
];
|
|
267
|
+
}
|
|
268
|
+
function writeBody(envelope, { plan, root }) {
|
|
269
|
+
if (plan.payload === void 0) {
|
|
270
|
+
return envelope.payload;
|
|
271
|
+
}
|
|
272
|
+
setAt(root, { path: plan.payload, value: envelope.payload });
|
|
273
|
+
if (plan.headers !== void 0) {
|
|
274
|
+
setAt(root, {
|
|
275
|
+
path: plan.headers,
|
|
276
|
+
value: Object.fromEntries(Object.entries(envelope.headers))
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
return root;
|
|
280
|
+
}
|
|
281
|
+
function eventHeaderEntries(envelope, { plan, failures }) {
|
|
282
|
+
if (plan.headers !== void 0) {
|
|
283
|
+
return [];
|
|
284
|
+
}
|
|
285
|
+
const entries = Object.entries(envelope.headers);
|
|
286
|
+
const taken = entries.find(([name]) => plan.mappedHeaders.has(name));
|
|
287
|
+
if (taken !== void 0) {
|
|
288
|
+
throw failures.unencodable(
|
|
289
|
+
`Event ${envelope.id} has a header '${taken[0]}', which the mapping uses for another field`
|
|
290
|
+
);
|
|
291
|
+
}
|
|
292
|
+
return entries;
|
|
293
|
+
}
|
|
294
|
+
function formatTime(envelope, failures) {
|
|
295
|
+
const year = envelope.occurredAt.getUTCFullYear();
|
|
296
|
+
if (Number.isNaN(year) || year < 0 || year > MAXIMUM_RFC3339_YEAR) {
|
|
297
|
+
throw failures.unencodable(
|
|
298
|
+
`Event ${envelope.id} has an occurredAt that is not an RFC 3339 instant (invalid date or year outside 0..9999)`
|
|
299
|
+
);
|
|
300
|
+
}
|
|
301
|
+
return envelope.occurredAt.toISOString();
|
|
302
|
+
}
|
|
303
|
+
function setAt(root, { path, value }) {
|
|
304
|
+
let container = root;
|
|
305
|
+
for (const [index, segment] of path.slice(0, -1).entries()) {
|
|
306
|
+
if (!Object.hasOwn(container, segment)) {
|
|
307
|
+
defineValue(container, {
|
|
308
|
+
name: segment,
|
|
309
|
+
value: ARRAY_INDEX.test(path[index + 1]) ? [] : {}
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
container = container[segment];
|
|
313
|
+
}
|
|
314
|
+
defineValue(container, { name: path.at(-1), value });
|
|
315
|
+
}
|
|
316
|
+
function defineValue(target, { name, value }) {
|
|
317
|
+
Object.defineProperty(target, name, {
|
|
318
|
+
value,
|
|
319
|
+
enumerable: true,
|
|
320
|
+
writable: true,
|
|
321
|
+
configurable: true
|
|
322
|
+
});
|
|
323
|
+
}
|
|
324
|
+
function readMessage(message, context) {
|
|
325
|
+
const { plan, failures } = context;
|
|
326
|
+
if (plan.payload !== void 0 && !isJsonObject(message.body)) {
|
|
327
|
+
throw failures.invalid("The message body must be a JSON object");
|
|
328
|
+
}
|
|
329
|
+
const read = (location) => location === void 0 ? void 0 : readText(message, { location, failures });
|
|
330
|
+
const fields = {
|
|
331
|
+
id: plan.id === void 0 ? void 0 : requireText(read(plan.id), { location: plan.id, failures }),
|
|
332
|
+
type: readType(message, context),
|
|
333
|
+
payload: readPayload(message.body, context),
|
|
334
|
+
key: read(plan.optional.key),
|
|
335
|
+
source: read(plan.optional.source),
|
|
336
|
+
headers: readEventHeaders(message, plan),
|
|
337
|
+
correlationId: read(plan.optional.correlationId) ?? null,
|
|
338
|
+
causationId: read(plan.optional.causationId) ?? null,
|
|
339
|
+
occurredAt: readTime(read(plan.optional.occurredAt), failures)
|
|
340
|
+
};
|
|
341
|
+
return Object.fromEntries(
|
|
342
|
+
Object.entries(fields).filter((entry) => entry[1] !== void 0)
|
|
343
|
+
);
|
|
344
|
+
}
|
|
345
|
+
function readType(message, { plan, failures }) {
|
|
346
|
+
if ("fixed" in plan.type) {
|
|
347
|
+
return plan.type.fixed;
|
|
348
|
+
}
|
|
349
|
+
const location = plan.type;
|
|
350
|
+
const type = requireText(readText(message, { location, failures }), { location, failures });
|
|
351
|
+
try {
|
|
352
|
+
chunk3OHMEMZA_cjs.assertEventType(type);
|
|
353
|
+
} catch (error) {
|
|
354
|
+
throw failures.invalid(`The event type is not a valid event type: ${error.message}`);
|
|
355
|
+
}
|
|
356
|
+
return type;
|
|
357
|
+
}
|
|
358
|
+
function readPayload(body, { plan, failures }) {
|
|
359
|
+
if (plan.payload === void 0) {
|
|
360
|
+
return body;
|
|
361
|
+
}
|
|
362
|
+
const payload = valueAt(body, plan.payload);
|
|
363
|
+
if (payload === void 0) {
|
|
364
|
+
throw failures.invalid(`The message has no payload at '${plan.payload.join(".")}'`);
|
|
365
|
+
}
|
|
366
|
+
return payload;
|
|
367
|
+
}
|
|
368
|
+
function readEventHeaders(message, plan) {
|
|
369
|
+
if (plan.headers === void 0) {
|
|
370
|
+
return Object.fromEntries(
|
|
371
|
+
Object.entries(message.headers).filter(([name]) => !plan.mappedHeaders.has(name))
|
|
372
|
+
);
|
|
373
|
+
}
|
|
374
|
+
const headers = valueAt(message.body, plan.headers);
|
|
375
|
+
return isJsonObject(headers) ? Object.fromEntries(
|
|
376
|
+
Object.entries(headers).filter(
|
|
377
|
+
(entry) => typeof entry[1] === "string"
|
|
378
|
+
)
|
|
379
|
+
) : {};
|
|
380
|
+
}
|
|
381
|
+
function readTime(text, failures) {
|
|
382
|
+
if (text === void 0) {
|
|
383
|
+
return void 0;
|
|
384
|
+
}
|
|
385
|
+
const time = new Date(text);
|
|
386
|
+
if (!RFC3339_PATTERN.test(text) || Number.isNaN(time.getTime())) {
|
|
387
|
+
throw failures.invalid(`The event time is not an RFC 3339 timestamp: '${text}'`);
|
|
388
|
+
}
|
|
389
|
+
return time;
|
|
390
|
+
}
|
|
391
|
+
function readText(message, { location, failures }) {
|
|
392
|
+
const value = "header" in location ? Object.hasOwn(message.headers, location.header) ? message.headers[location.header] : void 0 : valueAt(message.body, location.path);
|
|
393
|
+
if (value === void 0 || value === null || value === "") {
|
|
394
|
+
return void 0;
|
|
395
|
+
}
|
|
396
|
+
if (typeof value === "string") {
|
|
397
|
+
return value;
|
|
398
|
+
}
|
|
399
|
+
if (typeof value === "number" && Number.isSafeInteger(value)) {
|
|
400
|
+
return String(value);
|
|
401
|
+
}
|
|
402
|
+
throw failures.invalid(`The ${location.label} at ${describe(location)} must be a string`);
|
|
403
|
+
}
|
|
404
|
+
function requireText(value, { location, failures }) {
|
|
405
|
+
if (value === void 0) {
|
|
406
|
+
throw failures.invalid(`The message has no ${location.label} at ${describe(location)}`);
|
|
407
|
+
}
|
|
408
|
+
return value;
|
|
409
|
+
}
|
|
410
|
+
function describe(location) {
|
|
411
|
+
return "header" in location ? `header '${location.header}'` : `'${location.path.join(".")}'`;
|
|
412
|
+
}
|
|
413
|
+
function valueAt(body, path) {
|
|
414
|
+
let value = body;
|
|
415
|
+
for (const segment of path) {
|
|
416
|
+
if (typeof value !== "object" || value === null || !Object.hasOwn(value, segment)) {
|
|
417
|
+
return void 0;
|
|
418
|
+
}
|
|
419
|
+
value = value[segment];
|
|
420
|
+
}
|
|
421
|
+
return value;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
Object.defineProperty(exports, "assertPositiveInteger", {
|
|
425
|
+
enumerable: true,
|
|
426
|
+
get: function () { return chunk3OHMEMZA_cjs.assertPositiveInteger; }
|
|
427
|
+
});
|
|
428
|
+
Object.defineProperty(exports, "schedule", {
|
|
429
|
+
enumerable: true,
|
|
430
|
+
get: function () { return chunk3OHMEMZA_cjs.schedule; }
|
|
431
|
+
});
|
|
432
|
+
Object.defineProperty(exports, "sleep", {
|
|
433
|
+
enumerable: true,
|
|
434
|
+
get: function () { return chunk3OHMEMZA_cjs.sleep; }
|
|
435
|
+
});
|
|
436
|
+
exports.createCloudEventReaders = createCloudEventReaders;
|
|
437
|
+
exports.createJsonEnvelopeFormat = createJsonEnvelopeFormat;
|
|
438
|
+
exports.fromHeader = fromHeader;
|
|
439
|
+
exports.fromPayloadField = fromPayloadField;
|
|
440
|
+
exports.isJsonObject = isJsonObject;
|
|
441
|
+
exports.mediaTypeOf = mediaTypeOf;
|
|
442
|
+
exports.writeStructuredCloudEvent = writeStructuredCloudEvent;
|
|
443
|
+
//# sourceMappingURL=index.cjs.map
|
|
444
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/internal/field-extractors.ts","../../src/internal/cloudevents.ts","../../src/internal/json-envelope.ts"],"names":["ConfigurationError","assertEventType"],"mappings":"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","file":"index.cjs","sourcesContent":["import { ConfigurationError } from '../errors.js';\nimport type { EventHeaders } from '../event.js';\n\n/**\n * Reads one header of an incoming message, for the `type`, `id`, `key` or\n * `source` option of {@link plainJsonDecoder}. Header names are compared\n * exactly (Kafka and AMQP header names are case-sensitive). Returns undefined when the\n * header is absent, so the decoder falls back to its default.\n *\n * ```ts\n * plainJsonDecoder({ type: fromHeader('event-type'), id: fromHeader('message-id') })\n * ```\n */\nexport function fromHeader(\n name: string,\n): (message: { readonly headers: EventHeaders }) => string | undefined {\n if (name.length === 0) {\n throw new ConfigurationError('fromHeader needs a header name');\n }\n return (message) => (Object.hasOwn(message.headers, name) ? message.headers[name] : undefined);\n}\n\n/**\n * Reads a field of the JSON payload by a dotted path (`'meta.eventType'`), for\n * the `type`, `id`, `key` or `source` option of {@link plainJsonDecoder}. A\n * string is returned as is and a safe integer as its decimal text (numeric ids\n * are common). Anything else returns undefined so the decoder falls back to its\n * default: a missing field, and also a fraction or an integer beyond 2^53, which\n * JSON parsing may already have rounded, so two different ids could collide.\n *\n * ```ts\n * plainJsonDecoder({ type: fromPayloadField('eventType'), key: fromPayloadField('order.id') })\n * ```\n */\nexport function fromPayloadField(\n path: string,\n): (message: { readonly payload: unknown }) => string | undefined {\n const segments = path.split('.');\n if (segments.some((segment) => segment.length === 0)) {\n throw new ConfigurationError(\n `fromPayloadField needs a dotted path of non-empty names, received '${path}'`,\n );\n }\n return (message) => {\n let value = message.payload;\n for (const segment of segments) {\n if (typeof value !== 'object' || value === null || !Object.hasOwn(value, segment)) {\n return undefined;\n }\n value = (value as Record<string, unknown>)[segment];\n }\n if (typeof value === 'string') {\n return value;\n }\n return Number.isSafeInteger(value) ? String(value) : undefined;\n };\n}\n","import { assertEventType, type EventEnvelope } from '../event.js';\n\n/** The media type of a content type, without parameters and lower-cased; undefined for anything but a string. */\nexport function mediaTypeOf(contentType: unknown): string | undefined {\n return typeof contentType === 'string'\n ? contentType.split(';')[0]!.trim().toLowerCase()\n : undefined;\n}\n\nexport function isJsonObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/** Readers of structured CloudEvent attributes that fail with the error of the calling transport. */\nexport interface CloudEventReaders {\n readonly optionalAttribute: (body: Record<string, unknown>, name: string) => string | undefined;\n readonly requiredAttribute: (body: Record<string, unknown>, name: string) => string;\n readonly assertValidType: (type: string, label: string) => void;\n readonly assertJsonDataContentType: (dataContentType: string | undefined) => void;\n}\n\nexport function createCloudEventReaders(invalid: (reason: string) => Error): CloudEventReaders {\n const optionalAttribute = (body: Record<string, unknown>, name: string): string | undefined => {\n const value = body[name];\n if (value !== undefined && typeof value !== 'string') {\n throw invalid(`Attribute '${name}' must be a string`);\n }\n return value;\n };\n return {\n optionalAttribute,\n requiredAttribute: (body, name) => {\n const value = optionalAttribute(body, name);\n if (value === undefined || value.length === 0) {\n throw invalid(`Attribute '${name}' is missing or empty`);\n }\n return value;\n },\n assertValidType: (type, label) => {\n try {\n assertEventType(type);\n } catch (error) {\n throw invalid(`${label} is not a valid event type: ${(error as Error).message}`);\n }\n },\n assertJsonDataContentType: (dataContentType) => {\n const mediaType = mediaTypeOf(dataContentType);\n if (\n mediaType !== undefined &&\n mediaType !== 'application/json' &&\n mediaType !== 'text/json' &&\n !mediaType.endsWith('+json')\n ) {\n throw invalid(`datacontenttype must be JSON, received '${dataContentType}'`);\n }\n },\n };\n}\n\n/**\n * The JSON text of a CloudEvents 1.0 structured-mode event: the attributes (the key as `subject`,\n * correlation and causation ids as extension attributes), then `data`, the already serialized\n * payload, so the payload is serialized only once.\n */\nexport function writeStructuredCloudEvent(\n envelope: EventEnvelope,\n { time, data }: { readonly time: string; readonly data: string },\n): string {\n const attributes = {\n specversion: '1.0',\n id: envelope.id,\n type: envelope.type,\n source: envelope.source,\n time,\n datacontenttype: 'application/json',\n ...(envelope.key === null ? {} : { subject: envelope.key }),\n ...(envelope.correlationId === null ? {} : { correlationid: envelope.correlationId }),\n ...(envelope.causationId === null ? {} : { causationid: envelope.causationId }),\n };\n return `${JSON.stringify(attributes).slice(0, -1)},\"data\":${data}}`;\n}\n","import { ConfigurationError } from '../errors.js';\nimport { assertEventType, type EventEnvelope, type EventHeaders } from '../event.js';\nimport { isJsonObject } from './cloudevents.js';\n\n/**\n * A field of the JSON body, by dotted path: `'eventName'`, `'meta.correlationId'`. A segment that\n * is a whole number indexes an array: `'messageType.0'` is the first element of `messageType`.\n */\nexport type BodyField = { readonly body: string };\n/** A message header (Kafka record header, AMQP message header), by exact name. */\nexport type HeaderField = { readonly header: string };\n/** Where one envelope value lives on the wire. */\nexport type WireField = BodyField | HeaderField;\n/** The one event type every message of the route carries: written nowhere, used for every message read. */\nexport type FixedType = { readonly fixed: string };\n\ntype MappingFields<TField extends WireField, TTransportId extends string> = {\n /** Where the event type lives, or the one type of the route. Required. */\n readonly type: TField | FixedType;\n /**\n * Where the event id lives, or the transport's own message identity (see the transport's\n * mapping type). Required, so the inbox dedup key is always a deliberate choice. A message\n * whose mapped id is missing is malformed.\n */\n readonly id: TField | TTransportId;\n /** Ordering key. Default: the transport's own (the Kafka record key; none on RabbitMQ). */\n readonly key?: TField;\n /** Producing service. Default: the transport's own (Kafka topic; RabbitMQ `appId`, else the routing key). */\n readonly source?: TField;\n /** RFC 3339 time. Default: the transport's own (Kafka record timestamp; RabbitMQ `timestamp`, seconds). */\n readonly occurredAt?: TField;\n readonly correlationId?: TField;\n readonly causationId?: TField;\n /** Media type written with the message. Default `application/json`. Not checked on read. */\n readonly contentType?: string;\n};\n\n/**\n * A JSON object that wraps the payload with event metadata, such as\n * `{ \"eventName\": ..., \"messageId\": ..., \"data\": {...}, \"meta\": {...} }`.\n * Each value lives at a body path or in a header.\n */\nexport type BodyEnvelopeMapping<TTransportId extends string> = MappingFields<\n WireField,\n TTransportId\n> & {\n /** Body path of the payload. Required. */\n readonly payload: BodyField;\n /**\n * Event headers: a body path holding an object of strings, or `'message-headers'` (default),\n * every message header that no other field maps.\n */\n readonly headers?: BodyField | 'message-headers';\n};\n\n/**\n * The body is the payload itself, as a plain JSON producer writes it; every other value lives in\n * a header, so body paths are a compile error here.\n */\nexport type PayloadOnlyMapping<TTransportId extends string> = MappingFields<\n HeaderField,\n TTransportId\n> & {\n readonly payload: 'whole-body';\n /** Event headers: every message header that no other field maps. */\n readonly headers?: 'message-headers';\n};\n\n/** Where every envelope value lives in a JSON message. `type`, `id` and `payload` are required. */\nexport type JsonEnvelopeMapping<TTransportId extends string> =\n BodyEnvelopeMapping<TTransportId> | PayloadOnlyMapping<TTransportId>;\n\n/** A JSON message: the parsed body and the text headers. */\nexport type JsonWireMessage = { readonly body: unknown; readonly headers: EventHeaders };\n\n/** The values read from a message. An absent optional value is left to the transport's default. */\nexport type JsonEnvelopeFields = {\n readonly id?: string;\n readonly type: string;\n readonly payload: unknown;\n readonly key?: string;\n readonly source?: string;\n readonly headers: EventHeaders;\n readonly correlationId: string | null;\n readonly causationId: string | null;\n readonly occurredAt?: Date;\n};\n\n/** The errors of the calling transport. */\nexport type JsonEnvelopeFailures = {\n /** For a message that cannot be read: it goes to the invalid-message path. */\n readonly invalid: (reason: string) => Error;\n /** For an event that cannot be written: never retried. */\n readonly unencodable: (reason: string) => Error;\n};\n\n/** Writes and reads one mapping. Created once per codec; both methods are pure. */\nexport interface JsonEnvelopeFormat {\n /** The mapped headers and the body; the id is left out when the transport supplies it. */\n write(envelope: EventEnvelope): JsonWireMessage;\n read(message: JsonWireMessage): JsonEnvelopeFields;\n}\n\ntype Location =\n | { readonly label: string; readonly header: string }\n | { readonly label: string; readonly path: readonly string[] };\n\ntype OptionalName = 'key' | 'source' | 'occurredAt' | 'correlationId' | 'causationId';\nconst OPTIONAL_NAMES: readonly OptionalName[] = [\n 'key',\n 'source',\n 'occurredAt',\n 'correlationId',\n 'causationId',\n];\n\ntype Plan = {\n readonly type: Location | FixedType;\n /** Undefined when the transport supplies the id. */\n readonly id: Location | undefined;\n readonly optional: Readonly<Partial<Record<OptionalName, Location>>>;\n /** Undefined when the payload is the whole body. */\n readonly payload: readonly string[] | undefined;\n /** Undefined when event headers are the unmapped message headers. */\n readonly headers: readonly string[] | undefined;\n readonly mappedHeaders: ReadonlySet<string>;\n};\n\n/** RFC 3339 years have four digits. */\nconst MAXIMUM_RFC3339_YEAR = 9999;\nconst RFC3339_PATTERN = /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)?(?:Z|[+-]\\d{2}:\\d{2})$/i;\nconst ARRAY_INDEX = /^(?:0|[1-9]\\d*)$/;\n\n/**\n * Compiles `mapping` once. `transportIds` lists the transport's own id strategies.\n *\n * @throws ConfigurationError for a mapping that is incomplete, names a header twice, nests one\n * body path inside another or mixes array indexes and names under one body field.\n */\nexport function createJsonEnvelopeFormat(\n mapping: JsonEnvelopeMapping<string>,\n {\n transportIds,\n failures,\n }: { readonly transportIds: readonly string[]; readonly failures: JsonEnvelopeFailures },\n): JsonEnvelopeFormat {\n const plan = compile(mapping, transportIds);\n return {\n write: (envelope) => writeMessage(envelope, { plan, failures }),\n read: (message) => readMessage(message, { plan, failures }),\n };\n}\n\nfunction compile(mapping: JsonEnvelopeMapping<string>, transportIds: readonly string[]): Plan {\n if (!isJsonObject(mapping)) {\n throw new ConfigurationError('jsonEnvelope needs a mapping object');\n }\n const optional: Partial<Record<OptionalName, Location>> = {};\n for (const name of OPTIONAL_NAMES) {\n const field = mapping[name];\n if (field !== undefined) {\n optional[name] = toLocation(field, name);\n }\n }\n const plan: Plan = {\n type: compileType(mapping.type),\n id: compileId(mapping.id, transportIds),\n optional,\n payload: compilePayload(mapping.payload),\n headers: compileHeaders(mapping.headers),\n mappedHeaders: new Set(),\n };\n return assertDisjoint(plan);\n}\n\nfunction compileType(type: unknown): Location | FixedType {\n if (isJsonObject(type) && typeof type['fixed'] === 'string') {\n assertEventType(type['fixed']);\n return { fixed: type['fixed'] };\n }\n if (type === undefined) {\n throw new ConfigurationError('jsonEnvelope needs a type: { body }, { header } or { fixed }');\n }\n return toLocation(type, 'type');\n}\n\nfunction compileId(id: unknown, transportIds: readonly string[]): Location | undefined {\n if (typeof id === 'string' && transportIds.includes(id)) {\n return undefined;\n }\n if (!isJsonObject(id)) {\n throw new ConfigurationError(\n `jsonEnvelope needs an id: { body }, { header } or one of ${transportIds.map((name) => `'${name}'`).join(', ')}`,\n );\n }\n return toLocation(id, 'id');\n}\n\nfunction compilePayload(payload: unknown): readonly string[] | undefined {\n if (payload === 'whole-body') {\n return undefined;\n }\n if (!isJsonObject(payload) || typeof payload['body'] !== 'string') {\n throw new ConfigurationError(\n \"jsonEnvelope needs a payload: { body: '<path>' } or 'whole-body'\",\n );\n }\n return toPath(payload['body'], 'payload');\n}\n\nfunction compileHeaders(headers: unknown): readonly string[] | undefined {\n if (headers === undefined || headers === 'message-headers') {\n return undefined;\n }\n if (!isJsonObject(headers) || typeof headers['body'] !== 'string') {\n throw new ConfigurationError(\n \"jsonEnvelope headers must be { body: '<path>' } or 'message-headers'\",\n );\n }\n return toPath(headers['body'], 'headers');\n}\n\nfunction toLocation(field: unknown, label: string): Location {\n if (isJsonObject(field) && typeof field['header'] === 'string' && field['header'].length > 0) {\n return { label, header: field['header'] };\n }\n if (isJsonObject(field) && typeof field['body'] === 'string') {\n return { label, path: toPath(field['body'], label) };\n }\n throw new ConfigurationError(\n `jsonEnvelope ${label} must be { body: '<path>' } or { header: '<name>' }`,\n );\n}\n\nfunction toPath(path: string, label: string): readonly string[] {\n const segments = path.split('.');\n if (segments.some((segment) => segment.length === 0)) {\n throw new ConfigurationError(\n `jsonEnvelope ${label} needs a dotted path of non-empty names, received '${path}'`,\n );\n }\n return segments;\n}\n\n/** Collects the mapped headers and refuses overlapping locations, which would overwrite each other. */\nfunction assertDisjoint(plan: Plan): Plan {\n const locations = [plan.type, plan.id, ...Object.values(plan.optional)].filter(\n (location): location is Location => location !== undefined && !('fixed' in location),\n );\n const headers = locations.flatMap((location) => ('header' in location ? [location.header] : []));\n const duplicate = headers.find((name, index) => headers.indexOf(name) !== index);\n if (duplicate !== undefined) {\n throw new ConfigurationError(`jsonEnvelope maps header '${duplicate}' twice`);\n }\n const paths = [\n ...locations.flatMap((location) => ('path' in location ? [location.path] : [])),\n ...[plan.payload, plan.headers].filter((path) => path !== undefined),\n ];\n assertNoNestedPaths(paths);\n return { ...plan, mappedHeaders: new Set(headers) };\n}\n\nfunction assertNoNestedPaths(paths: readonly (readonly string[])[]): void {\n paths.forEach((path, index) => {\n for (const other of paths.slice(index + 1)) {\n assertCompatiblePaths(path, other);\n }\n });\n}\n\n/** Two body paths must part ways, and where they do, both index an array or both name a field. */\nfunction assertCompatiblePaths(path: readonly string[], other: readonly string[]): void {\n const parting = path.findIndex((segment, position) => segment !== other[position]);\n const both = `'${path.join('.')}' and '${other.join('.')}'`;\n if (parting === -1 || parting === other.length) {\n throw new ConfigurationError(`jsonEnvelope body paths ${both} overlap`);\n }\n if (ARRAY_INDEX.test(path[parting]!) !== ARRAY_INDEX.test(other[parting]!)) {\n throw new ConfigurationError(`jsonEnvelope body paths ${both} mix an array index and a name`);\n }\n}\n\ntype Context = { readonly plan: Plan; readonly failures: JsonEnvelopeFailures };\n\nfunction writeMessage(envelope: EventEnvelope, { plan, failures }: Context): JsonWireMessage {\n const root: Record<string, unknown> = {};\n const headers: [string, string][] = [];\n const put = (location: Location, value: string): void => {\n if ('header' in location) {\n headers.push([location.header, value]);\n } else {\n setAt(root, { path: location.path, value });\n }\n };\n if ('fixed' in plan.type) {\n if (envelope.type !== plan.type.fixed) {\n throw failures.unencodable(\n `Event ${envelope.id} has type '${envelope.type}', but this route carries only '${plan.type.fixed}'`,\n );\n }\n } else {\n put(plan.type, envelope.type);\n }\n if (plan.id !== undefined) {\n put(plan.id, envelope.id);\n }\n for (const [name, value] of optionalValues(envelope, failures)) {\n const location = plan.optional[name];\n if (location !== undefined && value !== null) {\n put(location, value);\n }\n }\n return {\n body: writeBody(envelope, { plan, root }),\n headers: Object.fromEntries([...eventHeaderEntries(envelope, { plan, failures }), ...headers]),\n };\n}\n\nfunction optionalValues(\n envelope: EventEnvelope,\n failures: JsonEnvelopeFailures,\n): [OptionalName, string | null][] {\n return [\n ['key', envelope.key],\n ['source', envelope.source],\n ['occurredAt', formatTime(envelope, failures)],\n ['correlationId', envelope.correlationId],\n ['causationId', envelope.causationId],\n ];\n}\n\nfunction writeBody(\n envelope: EventEnvelope,\n { plan, root }: { readonly plan: Plan; readonly root: Record<string, unknown> },\n): unknown {\n if (plan.payload === undefined) {\n return envelope.payload;\n }\n setAt(root, { path: plan.payload, value: envelope.payload });\n if (plan.headers !== undefined) {\n setAt(root, {\n path: plan.headers,\n value: Object.fromEntries(Object.entries(envelope.headers)),\n });\n }\n return root;\n}\n\n/** The event headers that travel as message headers; a name a mapped field uses is refused. */\nfunction eventHeaderEntries(\n envelope: EventEnvelope,\n { plan, failures }: Context,\n): [string, string][] {\n if (plan.headers !== undefined) {\n return [];\n }\n const entries = Object.entries(envelope.headers);\n const taken = entries.find(([name]) => plan.mappedHeaders.has(name));\n if (taken !== undefined) {\n throw failures.unencodable(\n `Event ${envelope.id} has a header '${taken[0]}', which the mapping uses for another field`,\n );\n }\n return entries;\n}\n\nfunction formatTime(envelope: EventEnvelope, failures: JsonEnvelopeFailures): string {\n const year = envelope.occurredAt.getUTCFullYear();\n if (Number.isNaN(year) || year < 0 || year > MAXIMUM_RFC3339_YEAR) {\n throw failures.unencodable(\n `Event ${envelope.id} has an occurredAt that is not an RFC 3339 instant (invalid date or year outside 0..9999)`,\n );\n }\n return envelope.occurredAt.toISOString();\n}\n\n/** Sets a value at a path, creating objects (arrays before an index segment) as own properties. */\nfunction setAt(\n root: Record<string, unknown>,\n { path, value }: { readonly path: readonly string[]; readonly value: unknown },\n): void {\n let container = root;\n for (const [index, segment] of path.slice(0, -1).entries()) {\n if (!Object.hasOwn(container, segment)) {\n defineValue(container, {\n name: segment,\n value: ARRAY_INDEX.test(path[index + 1]!) ? [] : {},\n });\n }\n container = container[segment] as Record<string, unknown>;\n }\n defineValue(container, { name: path.at(-1)!, value });\n}\n\n/** defineProperty, because assigning `__proto__` would set the prototype instead of a field. */\nfunction defineValue(\n target: Record<string, unknown>,\n { name, value }: { readonly name: string; readonly value: unknown },\n): void {\n Object.defineProperty(target, name, {\n value,\n enumerable: true,\n writable: true,\n configurable: true,\n });\n}\n\nfunction readMessage(message: JsonWireMessage, context: Context): JsonEnvelopeFields {\n const { plan, failures } = context;\n if (plan.payload !== undefined && !isJsonObject(message.body)) {\n throw failures.invalid('The message body must be a JSON object');\n }\n const read = (location: Location | undefined): string | undefined =>\n location === undefined ? undefined : readText(message, { location, failures });\n const fields: Record<string, unknown> = {\n id:\n plan.id === undefined\n ? undefined\n : requireText(read(plan.id), { location: plan.id, failures }),\n type: readType(message, context),\n payload: readPayload(message.body, context),\n key: read(plan.optional.key),\n source: read(plan.optional.source),\n headers: readEventHeaders(message, plan),\n correlationId: read(plan.optional.correlationId) ?? null,\n causationId: read(plan.optional.causationId) ?? null,\n occurredAt: readTime(read(plan.optional.occurredAt), failures),\n };\n return Object.fromEntries(\n Object.entries(fields).filter((entry) => entry[1] !== undefined),\n ) as JsonEnvelopeFields;\n}\n\nfunction readType(message: JsonWireMessage, { plan, failures }: Context): string {\n if ('fixed' in plan.type) {\n return plan.type.fixed;\n }\n const location = plan.type;\n const type = requireText(readText(message, { location, failures }), { location, failures });\n try {\n assertEventType(type);\n } catch (error) {\n throw failures.invalid(`The event type is not a valid event type: ${(error as Error).message}`);\n }\n return type;\n}\n\nfunction readPayload(body: unknown, { plan, failures }: Context): unknown {\n if (plan.payload === undefined) {\n return body;\n }\n const payload = valueAt(body, plan.payload);\n if (payload === undefined) {\n throw failures.invalid(`The message has no payload at '${plan.payload.join('.')}'`);\n }\n return payload;\n}\n\nfunction readEventHeaders(message: JsonWireMessage, plan: Plan): EventHeaders {\n if (plan.headers === undefined) {\n return Object.fromEntries(\n Object.entries(message.headers).filter(([name]) => !plan.mappedHeaders.has(name)),\n );\n }\n const headers = valueAt(message.body, plan.headers);\n return isJsonObject(headers)\n ? Object.fromEntries(\n Object.entries(headers).filter(\n (entry): entry is [string, string] => typeof entry[1] === 'string',\n ),\n )\n : {};\n}\n\nfunction readTime(text: string | undefined, failures: JsonEnvelopeFailures): Date | undefined {\n if (text === undefined) {\n return undefined;\n }\n const time = new Date(text);\n if (!RFC3339_PATTERN.test(text) || Number.isNaN(time.getTime())) {\n throw failures.invalid(`The event time is not an RFC 3339 timestamp: '${text}'`);\n }\n return time;\n}\n\n/** A string, or a safe integer as its decimal text; undefined when absent, null or empty. */\nfunction readText(\n message: JsonWireMessage,\n { location, failures }: { readonly location: Location; readonly failures: JsonEnvelopeFailures },\n): string | undefined {\n const value =\n 'header' in location\n ? Object.hasOwn(message.headers, location.header)\n ? message.headers[location.header]\n : undefined\n : valueAt(message.body, location.path);\n if (value === undefined || value === null || value === '') {\n return undefined;\n }\n if (typeof value === 'string') {\n return value;\n }\n if (typeof value === 'number' && Number.isSafeInteger(value)) {\n return String(value);\n }\n throw failures.invalid(`The ${location.label} at ${describe(location)} must be a string`);\n}\n\nfunction requireText(\n value: string | undefined,\n { location, failures }: { readonly location: Location; readonly failures: JsonEnvelopeFailures },\n): string {\n if (value === undefined) {\n throw failures.invalid(`The message has no ${location.label} at ${describe(location)}`);\n }\n return value;\n}\n\nfunction describe(location: Location): string {\n return 'header' in location ? `header '${location.header}'` : `'${location.path.join('.')}'`;\n}\n\nfunction valueAt(body: unknown, path: readonly string[]): unknown {\n let value = body;\n for (const segment of path) {\n if (typeof value !== 'object' || value === null || !Object.hasOwn(value, segment)) {\n return undefined;\n }\n value = (value as Record<string, unknown>)[segment];\n }\n return value;\n}\n"]}
|