@relaybus/core 0.2.0 → 0.3.1
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 +120 -8
- package/dist/chunk-J76M7XTS.cjs +323 -0
- package/dist/chunk-J76M7XTS.cjs.map +1 -0
- package/dist/chunk-NOR5JHVN.js +295 -0
- package/dist/chunk-NOR5JHVN.js.map +1 -0
- package/dist/index.cjs +2775 -1625
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +321 -471
- package/dist/index.d.ts +321 -471
- package/dist/index.js +2712 -1625
- package/dist/index.js.map +1 -1
- package/dist/internal/index.cjs +662 -0
- package/dist/internal/index.cjs.map +1 -0
- package/dist/internal/index.d.cts +438 -0
- package/dist/internal/index.d.ts +438 -0
- package/dist/internal/index.js +617 -0
- package/dist/internal/index.js.map +1 -0
- package/dist/transport-BlfzIBZD.d.cts +535 -0
- package/dist/transport-BlfzIBZD.d.ts +535 -0
- package/package.json +18 -1
|
@@ -0,0 +1,662 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunkJ76M7XTS_cjs = require('../chunk-J76M7XTS.cjs');
|
|
4
|
+
|
|
5
|
+
// src/internal/validation.ts
|
|
6
|
+
function assertPositiveInteger(value, name) {
|
|
7
|
+
return chunkJ76M7XTS_cjs.PositiveInteger.of(value, name);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// src/internal/field-extractors.ts
|
|
11
|
+
function fromHeader(name) {
|
|
12
|
+
if (name.length === 0) {
|
|
13
|
+
throw new chunkJ76M7XTS_cjs.ConfigurationError("fromHeader needs a header name");
|
|
14
|
+
}
|
|
15
|
+
return (message) => Object.hasOwn(message.headers, name) ? message.headers[name] : void 0;
|
|
16
|
+
}
|
|
17
|
+
function fromPayloadField(path) {
|
|
18
|
+
const segments = path.split(".");
|
|
19
|
+
if (segments.some((segment) => segment.length === 0)) {
|
|
20
|
+
throw new chunkJ76M7XTS_cjs.ConfigurationError(
|
|
21
|
+
`fromPayloadField needs a dotted path of non-empty names, received '${path}'`
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
return (message) => {
|
|
25
|
+
let value = message.payload;
|
|
26
|
+
for (const segment of segments) {
|
|
27
|
+
if (typeof value !== "object" || value === null || !Object.hasOwn(value, segment)) {
|
|
28
|
+
return void 0;
|
|
29
|
+
}
|
|
30
|
+
value = value[segment];
|
|
31
|
+
}
|
|
32
|
+
if (typeof value === "string") {
|
|
33
|
+
return value;
|
|
34
|
+
}
|
|
35
|
+
return Number.isSafeInteger(value) ? String(value) : void 0;
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// src/internal/cloudevents.ts
|
|
40
|
+
function mediaTypeOf(contentType) {
|
|
41
|
+
return typeof contentType === "string" ? contentType.split(";")[0].trim().toLowerCase() : void 0;
|
|
42
|
+
}
|
|
43
|
+
function isJsonObject(value) {
|
|
44
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
45
|
+
}
|
|
46
|
+
function createCloudEventReaders(invalid) {
|
|
47
|
+
const optionalAttribute = (body, name) => {
|
|
48
|
+
const value = body[name];
|
|
49
|
+
if (value !== void 0 && typeof value !== "string") {
|
|
50
|
+
throw invalid(`Attribute '${name}' must be a string`);
|
|
51
|
+
}
|
|
52
|
+
return value;
|
|
53
|
+
};
|
|
54
|
+
return {
|
|
55
|
+
optionalAttribute,
|
|
56
|
+
requiredAttribute: (body, name) => {
|
|
57
|
+
const value = optionalAttribute(body, name);
|
|
58
|
+
if (value === void 0 || value.length === 0) {
|
|
59
|
+
throw invalid(`Attribute '${name}' is missing or empty`);
|
|
60
|
+
}
|
|
61
|
+
return value;
|
|
62
|
+
},
|
|
63
|
+
assertValidType: (type, label) => {
|
|
64
|
+
try {
|
|
65
|
+
chunkJ76M7XTS_cjs.assertEventType(type);
|
|
66
|
+
} catch (error) {
|
|
67
|
+
throw invalid(`${label} is not a valid event type: ${error.message}`);
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
assertJsonDataContentType: (dataContentType) => {
|
|
71
|
+
const mediaType = mediaTypeOf(dataContentType);
|
|
72
|
+
if (mediaType !== void 0 && mediaType !== "application/json" && mediaType !== "text/json" && !mediaType.endsWith("+json")) {
|
|
73
|
+
throw invalid(`datacontenttype must be JSON, received '${dataContentType}'`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
function writeStructuredCloudEvent(envelope, { time, data }) {
|
|
79
|
+
const attributes = {
|
|
80
|
+
specversion: "1.0",
|
|
81
|
+
id: envelope.id,
|
|
82
|
+
type: envelope.type,
|
|
83
|
+
source: envelope.source,
|
|
84
|
+
time,
|
|
85
|
+
datacontenttype: "application/json",
|
|
86
|
+
...envelope.key === null ? {} : { subject: envelope.key },
|
|
87
|
+
...envelope.correlationId === null ? {} : { correlationid: envelope.correlationId },
|
|
88
|
+
...envelope.causationId === null ? {} : { causationid: envelope.causationId }
|
|
89
|
+
};
|
|
90
|
+
return `${JSON.stringify(attributes).slice(0, -1)},"data":${data}}`;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// src/internal/json-envelope-plan.ts
|
|
94
|
+
var OPTIONAL_NAMES = [
|
|
95
|
+
"key",
|
|
96
|
+
"source",
|
|
97
|
+
"occurredAt",
|
|
98
|
+
"correlationId",
|
|
99
|
+
"causationId"
|
|
100
|
+
];
|
|
101
|
+
var ARRAY_INDEX = /^(?:0|[1-9]\d*)$/;
|
|
102
|
+
function compile(mapping, transportIds) {
|
|
103
|
+
if (!isJsonObject(mapping)) {
|
|
104
|
+
throw new chunkJ76M7XTS_cjs.ConfigurationError("jsonEnvelope needs a mapping object");
|
|
105
|
+
}
|
|
106
|
+
const optional = {};
|
|
107
|
+
for (const name of OPTIONAL_NAMES) {
|
|
108
|
+
const field = mapping[name];
|
|
109
|
+
if (field !== void 0) {
|
|
110
|
+
optional[name] = toLocation(field, name);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
const plan = {
|
|
114
|
+
type: compileType(mapping.type),
|
|
115
|
+
id: compileId(mapping.id, transportIds),
|
|
116
|
+
optional,
|
|
117
|
+
payload: compilePayload(mapping.payload),
|
|
118
|
+
headers: compileHeaders(mapping.headers),
|
|
119
|
+
mappedHeaders: /* @__PURE__ */ new Set()
|
|
120
|
+
};
|
|
121
|
+
return assertDisjoint(plan);
|
|
122
|
+
}
|
|
123
|
+
function compileType(type) {
|
|
124
|
+
if (isJsonObject(type) && typeof type["fixed"] === "string") {
|
|
125
|
+
chunkJ76M7XTS_cjs.assertEventType(type["fixed"]);
|
|
126
|
+
return { fixed: type["fixed"] };
|
|
127
|
+
}
|
|
128
|
+
if (type === void 0) {
|
|
129
|
+
throw new chunkJ76M7XTS_cjs.ConfigurationError("jsonEnvelope needs a type: { body }, { header } or { fixed }");
|
|
130
|
+
}
|
|
131
|
+
return toLocation(type, "type");
|
|
132
|
+
}
|
|
133
|
+
function compileId(id, transportIds) {
|
|
134
|
+
if (typeof id === "string" && transportIds.includes(id)) {
|
|
135
|
+
return void 0;
|
|
136
|
+
}
|
|
137
|
+
if (!isJsonObject(id)) {
|
|
138
|
+
throw new chunkJ76M7XTS_cjs.ConfigurationError(
|
|
139
|
+
`jsonEnvelope needs an id: { body }, { header } or one of ${transportIds.map((name) => `'${name}'`).join(", ")}`
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
return toLocation(id, "id");
|
|
143
|
+
}
|
|
144
|
+
function compilePayload(payload) {
|
|
145
|
+
if (payload === "whole-body") {
|
|
146
|
+
return void 0;
|
|
147
|
+
}
|
|
148
|
+
if (!isJsonObject(payload) || typeof payload["body"] !== "string") {
|
|
149
|
+
throw new chunkJ76M7XTS_cjs.ConfigurationError(
|
|
150
|
+
"jsonEnvelope needs a payload: { body: '<path>' } or 'whole-body'"
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
return toPath(payload["body"], "payload");
|
|
154
|
+
}
|
|
155
|
+
function compileHeaders(headers) {
|
|
156
|
+
if (headers === void 0 || headers === "message-headers") {
|
|
157
|
+
return void 0;
|
|
158
|
+
}
|
|
159
|
+
if (!isJsonObject(headers) || typeof headers["body"] !== "string") {
|
|
160
|
+
throw new chunkJ76M7XTS_cjs.ConfigurationError(
|
|
161
|
+
"jsonEnvelope headers must be { body: '<path>' } or 'message-headers'"
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
return toPath(headers["body"], "headers");
|
|
165
|
+
}
|
|
166
|
+
function toLocation(field, label) {
|
|
167
|
+
if (isJsonObject(field) && typeof field["header"] === "string" && field["header"].length > 0) {
|
|
168
|
+
return { label, header: field["header"] };
|
|
169
|
+
}
|
|
170
|
+
if (isJsonObject(field) && typeof field["body"] === "string") {
|
|
171
|
+
return { label, path: toPath(field["body"], label) };
|
|
172
|
+
}
|
|
173
|
+
throw new chunkJ76M7XTS_cjs.ConfigurationError(
|
|
174
|
+
`jsonEnvelope ${label} must be { body: '<path>' } or { header: '<name>' }`
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
function toPath(path, label) {
|
|
178
|
+
const segments = path.split(".");
|
|
179
|
+
if (segments.some((segment) => segment.length === 0)) {
|
|
180
|
+
throw new chunkJ76M7XTS_cjs.ConfigurationError(
|
|
181
|
+
`jsonEnvelope ${label} needs a dotted path of non-empty names, received '${path}'`
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
return segments;
|
|
185
|
+
}
|
|
186
|
+
function assertDisjoint(plan) {
|
|
187
|
+
const locations = [plan.type, plan.id, ...Object.values(plan.optional)].filter(
|
|
188
|
+
(location) => location !== void 0 && !("fixed" in location)
|
|
189
|
+
);
|
|
190
|
+
const headers = locations.flatMap((location) => "header" in location ? [location.header] : []);
|
|
191
|
+
const duplicate = headers.find((name, index) => headers.indexOf(name) !== index);
|
|
192
|
+
if (duplicate !== void 0) {
|
|
193
|
+
throw new chunkJ76M7XTS_cjs.ConfigurationError(`jsonEnvelope maps header '${duplicate}' twice`);
|
|
194
|
+
}
|
|
195
|
+
const paths = [
|
|
196
|
+
...locations.flatMap((location) => "path" in location ? [location.path] : []),
|
|
197
|
+
...[plan.payload, plan.headers].filter((path) => path !== void 0)
|
|
198
|
+
];
|
|
199
|
+
assertNoNestedPaths(paths);
|
|
200
|
+
return { ...plan, mappedHeaders: new Set(headers) };
|
|
201
|
+
}
|
|
202
|
+
function assertNoNestedPaths(paths) {
|
|
203
|
+
paths.forEach((path, index) => {
|
|
204
|
+
for (const other of paths.slice(index + 1)) {
|
|
205
|
+
assertCompatiblePaths(path, other);
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
function assertCompatiblePaths(path, other) {
|
|
210
|
+
const parting = path.findIndex((segment, position) => segment !== other[position]);
|
|
211
|
+
const both = `'${path.join(".")}' and '${other.join(".")}'`;
|
|
212
|
+
if (parting === -1 || parting === other.length) {
|
|
213
|
+
throw new chunkJ76M7XTS_cjs.ConfigurationError(`jsonEnvelope body paths ${both} overlap`);
|
|
214
|
+
}
|
|
215
|
+
if (ARRAY_INDEX.test(path[parting]) !== ARRAY_INDEX.test(other[parting])) {
|
|
216
|
+
throw new chunkJ76M7XTS_cjs.ConfigurationError(`jsonEnvelope body paths ${both} mix an array index and a name`);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// src/internal/json-envelope-read.ts
|
|
221
|
+
var RFC3339_PATTERN = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})$/i;
|
|
222
|
+
function readMessage(message, context) {
|
|
223
|
+
const { plan, failures } = context;
|
|
224
|
+
if (plan.payload !== void 0 && !isJsonObject(message.body)) {
|
|
225
|
+
throw failures.invalid("The message body must be a JSON object");
|
|
226
|
+
}
|
|
227
|
+
const read = (location) => location === void 0 ? void 0 : readText(message, { location, failures });
|
|
228
|
+
const fields = {
|
|
229
|
+
id: plan.id === void 0 ? void 0 : requireText(read(plan.id), { location: plan.id, failures }),
|
|
230
|
+
type: readType(message, context),
|
|
231
|
+
payload: readPayload(message.body, context),
|
|
232
|
+
key: read(plan.optional.key),
|
|
233
|
+
source: read(plan.optional.source),
|
|
234
|
+
headers: readEventHeaders(message, plan),
|
|
235
|
+
correlationId: read(plan.optional.correlationId) ?? null,
|
|
236
|
+
causationId: read(plan.optional.causationId) ?? null,
|
|
237
|
+
occurredAt: readTime(read(plan.optional.occurredAt), failures)
|
|
238
|
+
};
|
|
239
|
+
return Object.fromEntries(
|
|
240
|
+
Object.entries(fields).filter((entry) => entry[1] !== void 0)
|
|
241
|
+
);
|
|
242
|
+
}
|
|
243
|
+
function readType(message, { plan, failures }) {
|
|
244
|
+
if ("fixed" in plan.type) {
|
|
245
|
+
return plan.type.fixed;
|
|
246
|
+
}
|
|
247
|
+
const location = plan.type;
|
|
248
|
+
const type = requireText(readText(message, { location, failures }), { location, failures });
|
|
249
|
+
try {
|
|
250
|
+
chunkJ76M7XTS_cjs.assertEventType(type);
|
|
251
|
+
} catch (error) {
|
|
252
|
+
throw failures.invalid(`The event type is not a valid event type: ${error.message}`);
|
|
253
|
+
}
|
|
254
|
+
return type;
|
|
255
|
+
}
|
|
256
|
+
function readPayload(body, { plan, failures }) {
|
|
257
|
+
if (plan.payload === void 0) {
|
|
258
|
+
return body;
|
|
259
|
+
}
|
|
260
|
+
const payload = valueAt(body, plan.payload);
|
|
261
|
+
if (payload === void 0) {
|
|
262
|
+
throw failures.invalid(`The message has no payload at '${plan.payload.join(".")}'`);
|
|
263
|
+
}
|
|
264
|
+
return payload;
|
|
265
|
+
}
|
|
266
|
+
function readEventHeaders(message, plan) {
|
|
267
|
+
if (plan.headers === void 0) {
|
|
268
|
+
return Object.fromEntries(
|
|
269
|
+
Object.entries(message.headers).filter(([name]) => !plan.mappedHeaders.has(name))
|
|
270
|
+
);
|
|
271
|
+
}
|
|
272
|
+
const headers = valueAt(message.body, plan.headers);
|
|
273
|
+
return isJsonObject(headers) ? Object.fromEntries(
|
|
274
|
+
Object.entries(headers).filter(
|
|
275
|
+
(entry) => typeof entry[1] === "string"
|
|
276
|
+
)
|
|
277
|
+
) : {};
|
|
278
|
+
}
|
|
279
|
+
function readTime(text, failures) {
|
|
280
|
+
if (text === void 0) {
|
|
281
|
+
return void 0;
|
|
282
|
+
}
|
|
283
|
+
const time = new Date(text);
|
|
284
|
+
if (!RFC3339_PATTERN.test(text) || Number.isNaN(time.getTime())) {
|
|
285
|
+
throw failures.invalid(`The event time is not an RFC 3339 timestamp: '${text}'`);
|
|
286
|
+
}
|
|
287
|
+
return time;
|
|
288
|
+
}
|
|
289
|
+
function readText(message, { location, failures }) {
|
|
290
|
+
const value = "header" in location ? Object.hasOwn(message.headers, location.header) ? message.headers[location.header] : void 0 : valueAt(message.body, location.path);
|
|
291
|
+
if (value === void 0 || value === null || value === "") {
|
|
292
|
+
return void 0;
|
|
293
|
+
}
|
|
294
|
+
if (typeof value === "string") {
|
|
295
|
+
return value;
|
|
296
|
+
}
|
|
297
|
+
if (typeof value === "number" && Number.isSafeInteger(value)) {
|
|
298
|
+
return String(value);
|
|
299
|
+
}
|
|
300
|
+
throw failures.invalid(`The ${location.label} at ${describe(location)} must be a string`);
|
|
301
|
+
}
|
|
302
|
+
function requireText(value, { location, failures }) {
|
|
303
|
+
if (value === void 0) {
|
|
304
|
+
throw failures.invalid(`The message has no ${location.label} at ${describe(location)}`);
|
|
305
|
+
}
|
|
306
|
+
return value;
|
|
307
|
+
}
|
|
308
|
+
function describe(location) {
|
|
309
|
+
return "header" in location ? `header '${location.header}'` : `'${location.path.join(".")}'`;
|
|
310
|
+
}
|
|
311
|
+
function valueAt(body, path) {
|
|
312
|
+
let value = body;
|
|
313
|
+
for (const segment of path) {
|
|
314
|
+
if (typeof value !== "object" || value === null || !Object.hasOwn(value, segment)) {
|
|
315
|
+
return void 0;
|
|
316
|
+
}
|
|
317
|
+
value = value[segment];
|
|
318
|
+
}
|
|
319
|
+
return value;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
// src/internal/json-envelope-write.ts
|
|
323
|
+
var MAXIMUM_RFC3339_YEAR = 9999;
|
|
324
|
+
function writeMessage(envelope, { plan, failures }) {
|
|
325
|
+
const root = {};
|
|
326
|
+
const headers = [];
|
|
327
|
+
const put = (location, value) => {
|
|
328
|
+
if ("header" in location) {
|
|
329
|
+
headers.push([location.header, value]);
|
|
330
|
+
} else {
|
|
331
|
+
setAt(root, { path: location.path, value });
|
|
332
|
+
}
|
|
333
|
+
};
|
|
334
|
+
if ("fixed" in plan.type) {
|
|
335
|
+
if (envelope.type !== plan.type.fixed) {
|
|
336
|
+
throw failures.unencodable(
|
|
337
|
+
`Event ${envelope.id} has type '${envelope.type}', but this route carries only '${plan.type.fixed}'`
|
|
338
|
+
);
|
|
339
|
+
}
|
|
340
|
+
} else {
|
|
341
|
+
put(plan.type, envelope.type);
|
|
342
|
+
}
|
|
343
|
+
if (plan.id !== void 0) {
|
|
344
|
+
put(plan.id, envelope.id);
|
|
345
|
+
}
|
|
346
|
+
for (const [name, value] of optionalValues(envelope, failures)) {
|
|
347
|
+
const location = plan.optional[name];
|
|
348
|
+
if (location !== void 0 && value !== null) {
|
|
349
|
+
put(location, value);
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
return {
|
|
353
|
+
body: writeBody(envelope, { plan, root }),
|
|
354
|
+
headers: Object.fromEntries([...eventHeaderEntries(envelope, { plan, failures }), ...headers])
|
|
355
|
+
};
|
|
356
|
+
}
|
|
357
|
+
function optionalValues(envelope, failures) {
|
|
358
|
+
return [
|
|
359
|
+
["key", envelope.key],
|
|
360
|
+
["source", envelope.source],
|
|
361
|
+
["occurredAt", formatTime(envelope, failures)],
|
|
362
|
+
["correlationId", envelope.correlationId],
|
|
363
|
+
["causationId", envelope.causationId]
|
|
364
|
+
];
|
|
365
|
+
}
|
|
366
|
+
function writeBody(envelope, { plan, root }) {
|
|
367
|
+
if (plan.payload === void 0) {
|
|
368
|
+
return envelope.payload;
|
|
369
|
+
}
|
|
370
|
+
setAt(root, { path: plan.payload, value: envelope.payload });
|
|
371
|
+
if (plan.headers !== void 0) {
|
|
372
|
+
setAt(root, {
|
|
373
|
+
path: plan.headers,
|
|
374
|
+
value: Object.fromEntries(Object.entries(envelope.headers))
|
|
375
|
+
});
|
|
376
|
+
}
|
|
377
|
+
return root;
|
|
378
|
+
}
|
|
379
|
+
function eventHeaderEntries(envelope, { plan, failures }) {
|
|
380
|
+
if (plan.headers !== void 0) {
|
|
381
|
+
return [];
|
|
382
|
+
}
|
|
383
|
+
const entries = Object.entries(envelope.headers);
|
|
384
|
+
const taken = entries.find(([name]) => plan.mappedHeaders.has(name));
|
|
385
|
+
if (taken !== void 0) {
|
|
386
|
+
throw failures.unencodable(
|
|
387
|
+
`Event ${envelope.id} has a header '${taken[0]}', which the mapping uses for another field`
|
|
388
|
+
);
|
|
389
|
+
}
|
|
390
|
+
return entries;
|
|
391
|
+
}
|
|
392
|
+
function formatTime(envelope, failures) {
|
|
393
|
+
const year = envelope.occurredAt.getUTCFullYear();
|
|
394
|
+
if (Number.isNaN(year) || year < 0 || year > MAXIMUM_RFC3339_YEAR) {
|
|
395
|
+
throw failures.unencodable(
|
|
396
|
+
`Event ${envelope.id} has an occurredAt that is not an RFC 3339 instant (invalid date or year outside 0..9999)`
|
|
397
|
+
);
|
|
398
|
+
}
|
|
399
|
+
return envelope.occurredAt.toISOString();
|
|
400
|
+
}
|
|
401
|
+
function setAt(root, { path, value }) {
|
|
402
|
+
let container = root;
|
|
403
|
+
for (const [index, segment] of path.slice(0, -1).entries()) {
|
|
404
|
+
if (!Object.hasOwn(container, segment)) {
|
|
405
|
+
defineValue(container, {
|
|
406
|
+
name: segment,
|
|
407
|
+
value: ARRAY_INDEX.test(path[index + 1]) ? [] : {}
|
|
408
|
+
});
|
|
409
|
+
}
|
|
410
|
+
container = container[segment];
|
|
411
|
+
}
|
|
412
|
+
defineValue(container, { name: path.at(-1), value });
|
|
413
|
+
}
|
|
414
|
+
function defineValue(target, { name, value }) {
|
|
415
|
+
Object.defineProperty(target, name, {
|
|
416
|
+
value,
|
|
417
|
+
enumerable: true,
|
|
418
|
+
writable: true,
|
|
419
|
+
configurable: true
|
|
420
|
+
});
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
// src/internal/json-envelope.ts
|
|
424
|
+
function createJsonEnvelopeFormat(mapping, {
|
|
425
|
+
transportIds,
|
|
426
|
+
failures
|
|
427
|
+
}) {
|
|
428
|
+
const plan = compile(mapping, transportIds);
|
|
429
|
+
return {
|
|
430
|
+
write: (envelope) => writeMessage(envelope, { plan, failures }),
|
|
431
|
+
read: (message) => readMessage(message, { plan, failures })
|
|
432
|
+
};
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
// src/store-kit/handed-out-ledger.ts
|
|
436
|
+
var HandedOutLedger = class {
|
|
437
|
+
#entries = /* @__PURE__ */ new Map();
|
|
438
|
+
register(lease, entry) {
|
|
439
|
+
this.#entries.set(chunkJ76M7XTS_cjs.DeliveryLeaseIdentity.of(lease.deliveryId, lease.leaseToken), entry);
|
|
440
|
+
}
|
|
441
|
+
/** Whether the claim with this identity ({@link DeliveryLeaseIdentity.of}) is handed out. */
|
|
442
|
+
has(identity) {
|
|
443
|
+
return this.#entries.has(identity);
|
|
444
|
+
}
|
|
445
|
+
forget(lease) {
|
|
446
|
+
this.#entries.delete(chunkJ76M7XTS_cjs.DeliveryLeaseIdentity.of(lease.deliveryId, lease.leaseToken));
|
|
447
|
+
}
|
|
448
|
+
/** Forgets every entry `settled` says is settled. */
|
|
449
|
+
forgetWhere(settled) {
|
|
450
|
+
for (const [identity, entry] of this.#entries) {
|
|
451
|
+
if (settled(entry, identity)) {
|
|
452
|
+
this.#entries.delete(identity);
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
/** The entries handed out to `owner`. */
|
|
457
|
+
entriesOf(owner) {
|
|
458
|
+
return [...this.#entries.values()].filter((entry) => entry.owner === owner);
|
|
459
|
+
}
|
|
460
|
+
};
|
|
461
|
+
|
|
462
|
+
// src/store-kit/owner-serialized-claims.ts
|
|
463
|
+
var OwnerSerializedClaims = class {
|
|
464
|
+
/** The last claim of each owner still running; the next one waits for it. */
|
|
465
|
+
#queues = /* @__PURE__ */ new Map();
|
|
466
|
+
claim(request) {
|
|
467
|
+
if (this.claimsNothing(request)) {
|
|
468
|
+
return Promise.resolve([]);
|
|
469
|
+
}
|
|
470
|
+
return this.#serialized(request.leaseOwner, () => this.claimInTurn(request));
|
|
471
|
+
}
|
|
472
|
+
/** Whether the request cannot claim anything: no handlers, or a limit that is not above 0. */
|
|
473
|
+
claimsNothing(request) {
|
|
474
|
+
return request.handlers.length === 0 || !(request.limit > 0);
|
|
475
|
+
}
|
|
476
|
+
#serialized(owner, work) {
|
|
477
|
+
const previous = this.#queues.get(owner) ?? Promise.resolve();
|
|
478
|
+
const run = previous.then(work, work);
|
|
479
|
+
const tail = run.then(
|
|
480
|
+
() => void 0,
|
|
481
|
+
() => void 0
|
|
482
|
+
);
|
|
483
|
+
this.#queues.set(owner, tail);
|
|
484
|
+
void tail.then(() => {
|
|
485
|
+
if (this.#queues.get(owner) === tail) {
|
|
486
|
+
this.#queues.delete(owner);
|
|
487
|
+
}
|
|
488
|
+
});
|
|
489
|
+
return run;
|
|
490
|
+
}
|
|
491
|
+
};
|
|
492
|
+
|
|
493
|
+
// src/transport-kit/decoded-event-reader.ts
|
|
494
|
+
function observeRejection(value) {
|
|
495
|
+
if (typeof value === "object" && value !== null && "then" in value) {
|
|
496
|
+
Promise.resolve(value).catch(() => void 0);
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
var DecodedEventReader = class {
|
|
500
|
+
/**
|
|
501
|
+
* Fills the fields a decoder left out and guards against a decoder that returned no object,
|
|
502
|
+
* which would otherwise surface as a retried `TypeError` instead of a malformed message.
|
|
503
|
+
*/
|
|
504
|
+
complete(decoded, message) {
|
|
505
|
+
if (typeof decoded !== "object" || decoded === null) {
|
|
506
|
+
throw this.invalid("The decoder must return an event object synchronously");
|
|
507
|
+
}
|
|
508
|
+
if ("then" in decoded) {
|
|
509
|
+
observeRejection(decoded);
|
|
510
|
+
throw this.invalid("The decoder must return an event object synchronously");
|
|
511
|
+
}
|
|
512
|
+
const event = decoded;
|
|
513
|
+
return {
|
|
514
|
+
id: event.id,
|
|
515
|
+
type: event.type,
|
|
516
|
+
source: event.source ?? this.defaultSource(message),
|
|
517
|
+
key: event.key === void 0 ? this.defaultKey(message) : event.key,
|
|
518
|
+
payload: event.payload,
|
|
519
|
+
headers: event.headers ?? {},
|
|
520
|
+
correlationId: event.correlationId ?? null,
|
|
521
|
+
causationId: event.causationId ?? null,
|
|
522
|
+
occurredAt: event.occurredAt ?? this.defaultTime(message)
|
|
523
|
+
};
|
|
524
|
+
}
|
|
525
|
+
/** The text an option gives for `plain`; undefined when it gives none or `''`. */
|
|
526
|
+
text(option, { plain, name }) {
|
|
527
|
+
const value = typeof option === "function" ? option(plain) : option;
|
|
528
|
+
if (value === void 0 || value === null) {
|
|
529
|
+
return void 0;
|
|
530
|
+
}
|
|
531
|
+
if (typeof value !== "string") {
|
|
532
|
+
observeRejection(value);
|
|
533
|
+
throw this.invalid(`The ${name} option returned ${typeof value}, expected a string`);
|
|
534
|
+
}
|
|
535
|
+
return value.length === 0 ? void 0 : value;
|
|
536
|
+
}
|
|
537
|
+
};
|
|
538
|
+
|
|
539
|
+
// src/transport-kit/subscribing-transport.ts
|
|
540
|
+
var SubscribingTransport = class {
|
|
541
|
+
/**
|
|
542
|
+
* Subscribes to `destinations`. Not async itself: the subscription's own promise is returned
|
|
543
|
+
* as it is, so its checks reject rather than throw.
|
|
544
|
+
*/
|
|
545
|
+
// eslint-disable-next-line relaybus/max-two-params -- the Transport.subscribe signature
|
|
546
|
+
subscribe(destinations, onMessage, hooks) {
|
|
547
|
+
return this.openSubscription({ destinations, onMessage, hooks });
|
|
548
|
+
}
|
|
549
|
+
};
|
|
550
|
+
|
|
551
|
+
// src/values/bounded-integer.ts
|
|
552
|
+
var BoundedInteger = class {
|
|
553
|
+
/** Returns `value` when it is an integer within the bounds, else throws a {@link ConfigurationError}. */
|
|
554
|
+
static of(value, { name, minimum, maximum }) {
|
|
555
|
+
if (!Number.isInteger(value) || value < minimum || value > maximum) {
|
|
556
|
+
throw new chunkJ76M7XTS_cjs.ConfigurationError(
|
|
557
|
+
`${name} must be an integer from ${minimum} to ${maximum}, received ${value}`
|
|
558
|
+
);
|
|
559
|
+
}
|
|
560
|
+
return value;
|
|
561
|
+
}
|
|
562
|
+
};
|
|
563
|
+
|
|
564
|
+
// src/values/exponential-backoff.ts
|
|
565
|
+
var ExponentialBackoff = class {
|
|
566
|
+
initialMs;
|
|
567
|
+
maxMs;
|
|
568
|
+
constructor({ initialMs, maxMs }) {
|
|
569
|
+
this.initialMs = initialMs;
|
|
570
|
+
this.maxMs = maxMs;
|
|
571
|
+
}
|
|
572
|
+
/** The delay after failed attempt `attempt` (1-based). */
|
|
573
|
+
delayFor(attempt) {
|
|
574
|
+
return Math.min(this.initialMs * 2 ** (attempt - 1), this.maxMs);
|
|
575
|
+
}
|
|
576
|
+
};
|
|
577
|
+
|
|
578
|
+
// src/values/lane-lease-token.ts
|
|
579
|
+
var LANE_DIGITS = 3;
|
|
580
|
+
var LaneLeaseTokenFormat = class {
|
|
581
|
+
#pattern;
|
|
582
|
+
#laneCount;
|
|
583
|
+
constructor(limits) {
|
|
584
|
+
this.#laneCount = limits.laneCount;
|
|
585
|
+
this.#pattern = new RegExp(
|
|
586
|
+
`^(\\d{1,${LANE_DIGITS}}):(\\d{1,${limits.epochDigits}}):(\\d{1,${limits.claimsDigits}})$`
|
|
587
|
+
);
|
|
588
|
+
}
|
|
589
|
+
format(lane, { epoch, claims }) {
|
|
590
|
+
return `${lane}:${epoch}:${claims}`;
|
|
591
|
+
}
|
|
592
|
+
/** The parts of `token`; undefined when the store cannot have issued it. */
|
|
593
|
+
parse(token) {
|
|
594
|
+
const match = this.#pattern.exec(token);
|
|
595
|
+
if (match === null || Number(match[1]) >= this.#laneCount) {
|
|
596
|
+
return void 0;
|
|
597
|
+
}
|
|
598
|
+
return { lane: Number(match[1]), epoch: match[2], claims: Number(match[3]) };
|
|
599
|
+
}
|
|
600
|
+
};
|
|
601
|
+
|
|
602
|
+
// src/values/non-empty-text.ts
|
|
603
|
+
var NonEmptyText = class _NonEmptyText {
|
|
604
|
+
static of(value, name) {
|
|
605
|
+
if (value.length === 0) {
|
|
606
|
+
throw new chunkJ76M7XTS_cjs.ConfigurationError(`${name} must not be empty`);
|
|
607
|
+
}
|
|
608
|
+
return value;
|
|
609
|
+
}
|
|
610
|
+
/** Like {@link NonEmptyText.of}, for an option that may be left out. */
|
|
611
|
+
static optional(value, name) {
|
|
612
|
+
return value === void 0 ? void 0 : _NonEmptyText.of(value, name);
|
|
613
|
+
}
|
|
614
|
+
};
|
|
615
|
+
|
|
616
|
+
Object.defineProperty(exports, "CompositeKey", {
|
|
617
|
+
enumerable: true,
|
|
618
|
+
get: function () { return chunkJ76M7XTS_cjs.CompositeKey; }
|
|
619
|
+
});
|
|
620
|
+
Object.defineProperty(exports, "DeliveryLeaseIdentity", {
|
|
621
|
+
enumerable: true,
|
|
622
|
+
get: function () { return chunkJ76M7XTS_cjs.DeliveryLeaseIdentity; }
|
|
623
|
+
});
|
|
624
|
+
Object.defineProperty(exports, "LeaseSettlement", {
|
|
625
|
+
enumerable: true,
|
|
626
|
+
get: function () { return chunkJ76M7XTS_cjs.LeaseSettlement; }
|
|
627
|
+
});
|
|
628
|
+
Object.defineProperty(exports, "Milliseconds", {
|
|
629
|
+
enumerable: true,
|
|
630
|
+
get: function () { return chunkJ76M7XTS_cjs.Milliseconds; }
|
|
631
|
+
});
|
|
632
|
+
Object.defineProperty(exports, "PositiveInteger", {
|
|
633
|
+
enumerable: true,
|
|
634
|
+
get: function () { return chunkJ76M7XTS_cjs.PositiveInteger; }
|
|
635
|
+
});
|
|
636
|
+
Object.defineProperty(exports, "schedule", {
|
|
637
|
+
enumerable: true,
|
|
638
|
+
get: function () { return chunkJ76M7XTS_cjs.schedule; }
|
|
639
|
+
});
|
|
640
|
+
Object.defineProperty(exports, "sleep", {
|
|
641
|
+
enumerable: true,
|
|
642
|
+
get: function () { return chunkJ76M7XTS_cjs.sleep; }
|
|
643
|
+
});
|
|
644
|
+
exports.BoundedInteger = BoundedInteger;
|
|
645
|
+
exports.DecodedEventReader = DecodedEventReader;
|
|
646
|
+
exports.ExponentialBackoff = ExponentialBackoff;
|
|
647
|
+
exports.HandedOutLedger = HandedOutLedger;
|
|
648
|
+
exports.LaneLeaseTokenFormat = LaneLeaseTokenFormat;
|
|
649
|
+
exports.NonEmptyText = NonEmptyText;
|
|
650
|
+
exports.OwnerSerializedClaims = OwnerSerializedClaims;
|
|
651
|
+
exports.SubscribingTransport = SubscribingTransport;
|
|
652
|
+
exports.assertPositiveInteger = assertPositiveInteger;
|
|
653
|
+
exports.createCloudEventReaders = createCloudEventReaders;
|
|
654
|
+
exports.createJsonEnvelopeFormat = createJsonEnvelopeFormat;
|
|
655
|
+
exports.fromHeader = fromHeader;
|
|
656
|
+
exports.fromPayloadField = fromPayloadField;
|
|
657
|
+
exports.isJsonObject = isJsonObject;
|
|
658
|
+
exports.mediaTypeOf = mediaTypeOf;
|
|
659
|
+
exports.observeRejection = observeRejection;
|
|
660
|
+
exports.writeStructuredCloudEvent = writeStructuredCloudEvent;
|
|
661
|
+
//# sourceMappingURL=index.cjs.map
|
|
662
|
+
//# sourceMappingURL=index.cjs.map
|