@relaybus/core 0.4.0 → 0.5.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 +5 -0
- package/dist/{chunk-J76M7XTS.cjs → chunk-2E6NSHGE.cjs} +27 -2
- package/dist/chunk-2E6NSHGE.cjs.map +1 -0
- package/dist/{chunk-NOR5JHVN.js → chunk-6PQ673MW.js} +23 -3
- package/dist/chunk-6PQ673MW.js.map +1 -0
- package/dist/index.cjs +567 -215
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +111 -11
- package/dist/index.d.ts +111 -11
- package/dist/index.js +418 -89
- package/dist/index.js.map +1 -1
- package/dist/internal/index.cjs +218 -49
- package/dist/internal/index.cjs.map +1 -1
- package/dist/internal/index.d.cts +45 -2
- package/dist/internal/index.d.ts +45 -2
- package/dist/internal/index.js +188 -21
- package/dist/internal/index.js.map +1 -1
- package/dist/{transport-DIFdeXQY.d.cts → transport-CXoZgh5u.d.cts} +77 -2
- package/dist/{transport-DIFdeXQY.d.ts → transport-CXoZgh5u.d.ts} +77 -2
- package/package.json +1 -1
- package/dist/chunk-J76M7XTS.cjs.map +0 -1
- package/dist/chunk-NOR5JHVN.js.map +0 -1
package/dist/internal/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { PositiveInteger, ConfigurationError, assertEventType, DeliveryLeaseIdentity } from '../chunk-
|
|
2
|
-
export { CompositeKey, DeliveryLeaseIdentity, LeaseSettlement, Milliseconds, PositiveInteger, schedule, sleep } from '../chunk-
|
|
1
|
+
import { PositiveInteger, ConfigurationError, assertEventType, WireTypesUnsupportedError, WireTypeCollisionError, DeliveryLeaseIdentity } from '../chunk-6PQ673MW.js';
|
|
2
|
+
export { CompositeKey, DeliveryLeaseIdentity, LeaseSettlement, Milliseconds, PositiveInteger, schedule, sleep } from '../chunk-6PQ673MW.js';
|
|
3
3
|
|
|
4
4
|
// src/internal/validation.ts
|
|
5
5
|
function assertPositiveInteger(value, name) {
|
|
@@ -89,6 +89,93 @@ function writeStructuredCloudEvent(envelope, { time, data }) {
|
|
|
89
89
|
return `${JSON.stringify(attributes).slice(0, -1)},"data":${data}}`;
|
|
90
90
|
}
|
|
91
91
|
|
|
92
|
+
// src/internal/json-envelope-wire-types.ts
|
|
93
|
+
function compileWireTypes(wireTypes, { fixed }) {
|
|
94
|
+
if (wireTypes === void 0) {
|
|
95
|
+
return { wireTypes: /* @__PURE__ */ new Map(), eventTypes: /* @__PURE__ */ new Map() };
|
|
96
|
+
}
|
|
97
|
+
if (!isJsonObject(wireTypes) || fixed) {
|
|
98
|
+
throw new ConfigurationError(
|
|
99
|
+
"jsonEnvelope wireTypes must be an object of event type to wire name, with a type at { body } or { header }"
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
const entries = Object.entries(wireTypes);
|
|
103
|
+
const eventTypes = /* @__PURE__ */ new Map();
|
|
104
|
+
for (const [type, wire] of entries) {
|
|
105
|
+
assertEventType(type);
|
|
106
|
+
if (typeof wire !== "string" || wire.length === 0 || eventTypes.has(wire)) {
|
|
107
|
+
throw new ConfigurationError(
|
|
108
|
+
`jsonEnvelope wireTypes needs a non-empty wire name for '${type}' that no other type uses`
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
eventTypes.set(wire, type);
|
|
112
|
+
}
|
|
113
|
+
return { wireTypes: new Map(entries), eventTypes };
|
|
114
|
+
}
|
|
115
|
+
function wireTypeOf(envelope, { plan, failures }) {
|
|
116
|
+
const wire = plan.wireTypes.get(envelope.type);
|
|
117
|
+
if (wire !== void 0) {
|
|
118
|
+
return wire;
|
|
119
|
+
}
|
|
120
|
+
const other = plan.eventTypes.get(envelope.type);
|
|
121
|
+
if (other !== void 0) {
|
|
122
|
+
throw failures.unencodable(
|
|
123
|
+
`Event ${envelope.id} has type '${envelope.type}', which wireTypes uses as the wire name of '${other}'`
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
return envelope.type;
|
|
127
|
+
}
|
|
128
|
+
function eventTypeOf(wire, { plan, failures }) {
|
|
129
|
+
const type = plan.eventTypes.get(wire);
|
|
130
|
+
if (type !== void 0) {
|
|
131
|
+
return type;
|
|
132
|
+
}
|
|
133
|
+
try {
|
|
134
|
+
assertEventType(wire);
|
|
135
|
+
} catch (error) {
|
|
136
|
+
throw failures.invalid(`The event type is not a valid event type: ${error.message}`);
|
|
137
|
+
}
|
|
138
|
+
return wire;
|
|
139
|
+
}
|
|
140
|
+
function withDeclaredWireTypes(codec, {
|
|
141
|
+
wireTypes,
|
|
142
|
+
transport
|
|
143
|
+
}) {
|
|
144
|
+
if (codec.withWireTypes === void 0) {
|
|
145
|
+
throw new WireTypesUnsupportedError(
|
|
146
|
+
`The codec of transport '${transport}' cannot map event types to wire names; use jsonEnvelope with a type at { body } or { header }`
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
return codec.withWireTypes(wireTypes);
|
|
150
|
+
}
|
|
151
|
+
function mergeWireTypes(mapping, declared) {
|
|
152
|
+
if (isJsonObject(mapping.type) && "fixed" in mapping.type) {
|
|
153
|
+
throw new WireTypesUnsupportedError(
|
|
154
|
+
"A jsonEnvelope with a fixed type writes no type, so it has no wire names to declare"
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
const merged = new Map(Object.entries(mapping.wireTypes ?? {}));
|
|
158
|
+
for (const [type, wire] of Object.entries(declared)) {
|
|
159
|
+
assertDeclarable(merged, { type, wire });
|
|
160
|
+
merged.set(type, wire);
|
|
161
|
+
}
|
|
162
|
+
return Object.fromEntries(merged);
|
|
163
|
+
}
|
|
164
|
+
function assertDeclarable(wireTypes, { type, wire }) {
|
|
165
|
+
const current = wireTypes.get(type);
|
|
166
|
+
if (current !== void 0 && current !== wire) {
|
|
167
|
+
throw new WireTypeCollisionError(
|
|
168
|
+
`Event type '${type}' has the wire name '${current}' in the wireTypes of the codec and '${wire}' from a route or catalog`
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
const owner = [...wireTypes].find(([other, name]) => name === wire && other !== type);
|
|
172
|
+
if (owner !== void 0) {
|
|
173
|
+
throw new WireTypeCollisionError(
|
|
174
|
+
`Event types '${owner[0]}' and '${type}' share the wire name '${wire}' in the codec and a route or catalog`
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
92
179
|
// src/internal/json-envelope-plan.ts
|
|
93
180
|
var OPTIONAL_NAMES = [
|
|
94
181
|
"key",
|
|
@@ -115,8 +202,9 @@ function compile(mapping, transportIds) {
|
|
|
115
202
|
if (topLevelHeaders && payload === void 0) {
|
|
116
203
|
throw new ConfigurationError("jsonEnvelope headers 'top-level-fields' needs a body payload");
|
|
117
204
|
}
|
|
205
|
+
const type = compileType(mapping.type);
|
|
118
206
|
const plan = {
|
|
119
|
-
type
|
|
207
|
+
type,
|
|
120
208
|
id: compileId(mapping.id, transportIds),
|
|
121
209
|
idWhenMissing: isJsonObject(mapping.id) && "whenMissing" in mapping.id,
|
|
122
210
|
optional,
|
|
@@ -126,6 +214,8 @@ function compile(mapping, transportIds) {
|
|
|
126
214
|
topLevelNames: /* @__PURE__ */ new Set(),
|
|
127
215
|
mappedHeaders: /* @__PURE__ */ new Set(),
|
|
128
216
|
timeFormat: compileTimeFormat(mapping.occurredAt),
|
|
217
|
+
otherFields: compileOtherFields(mapping, payload !== void 0),
|
|
218
|
+
...compileWireTypes(mapping.wireTypes, { fixed: "fixed" in type }),
|
|
129
219
|
...compileExtras(mapping, payload !== void 0)
|
|
130
220
|
};
|
|
131
221
|
return assertDisjoint(plan);
|
|
@@ -159,6 +249,20 @@ function compileExtras(mapping, hasBody) {
|
|
|
159
249
|
bodyOrder
|
|
160
250
|
};
|
|
161
251
|
}
|
|
252
|
+
function compileOtherFields(mapping, hasBody) {
|
|
253
|
+
const otherFields = mapping.otherFields;
|
|
254
|
+
if (otherFields === void 0) {
|
|
255
|
+
return void 0;
|
|
256
|
+
}
|
|
257
|
+
if (!hasBody) {
|
|
258
|
+
throw new ConfigurationError("jsonEnvelope otherFields needs a body payload");
|
|
259
|
+
}
|
|
260
|
+
const field = isJsonObject(otherFields) ? otherFields["payloadField"] : void 0;
|
|
261
|
+
if (typeof field !== "string" || field.length === 0) {
|
|
262
|
+
throw new ConfigurationError("jsonEnvelope otherFields must be { payloadField: '<name>' }");
|
|
263
|
+
}
|
|
264
|
+
return field;
|
|
265
|
+
}
|
|
162
266
|
function compileType(type) {
|
|
163
267
|
if (isJsonObject(type) && typeof type["fixed"] === "string") {
|
|
164
268
|
assertEventType(type["fixed"]);
|
|
@@ -268,6 +372,56 @@ function assertCompatiblePaths(path, other) {
|
|
|
268
372
|
}
|
|
269
373
|
}
|
|
270
374
|
|
|
375
|
+
// src/internal/json-envelope-other-fields.ts
|
|
376
|
+
function unusedFields(body, { plan }) {
|
|
377
|
+
return Object.entries(body).filter(
|
|
378
|
+
([name, value]) => !plan.topLevelNames.has(name) && !(plan.topLevelHeaders && typeof value === "string")
|
|
379
|
+
);
|
|
380
|
+
}
|
|
381
|
+
function withOtherFields(payload, { body, context }) {
|
|
382
|
+
const field = context.plan.otherFields;
|
|
383
|
+
if (field === void 0) {
|
|
384
|
+
return payload;
|
|
385
|
+
}
|
|
386
|
+
const fields = unusedFields(body, context);
|
|
387
|
+
if (!isJsonObject(payload) && fields.length === 0) {
|
|
388
|
+
return payload;
|
|
389
|
+
}
|
|
390
|
+
if (!isJsonObject(payload) || Object.hasOwn(payload, field)) {
|
|
391
|
+
throw context.failures.invalid(
|
|
392
|
+
`otherFields keeps the unused top-level fields under the payload field '${field}', but the payload is not an object without that field`
|
|
393
|
+
);
|
|
394
|
+
}
|
|
395
|
+
return Object.fromEntries([...Object.entries(payload), [field, Object.fromEntries(fields)]]);
|
|
396
|
+
}
|
|
397
|
+
function splitOtherFields(envelope, context) {
|
|
398
|
+
const field = context.plan.otherFields;
|
|
399
|
+
const { payload } = envelope;
|
|
400
|
+
if (field === void 0 || !isJsonObject(payload) || !Object.hasOwn(payload, field)) {
|
|
401
|
+
return { payload, fields: [] };
|
|
402
|
+
}
|
|
403
|
+
const others = payload[field];
|
|
404
|
+
if (!isJsonObject(others)) {
|
|
405
|
+
throw context.failures.unencodable(
|
|
406
|
+
`Event ${envelope.id} has a payload field '${field}' that is not an object of top-level fields`
|
|
407
|
+
);
|
|
408
|
+
}
|
|
409
|
+
const fields = Object.entries(others);
|
|
410
|
+
const refused = fields.find((entry) => isRefused(entry, context));
|
|
411
|
+
if (refused !== void 0) {
|
|
412
|
+
throw context.failures.unencodable(
|
|
413
|
+
`Event ${envelope.id} keeps a top-level field '${refused[0]}' under '${field}' that the mapping reads as another value`
|
|
414
|
+
);
|
|
415
|
+
}
|
|
416
|
+
return {
|
|
417
|
+
payload: Object.fromEntries(Object.entries(payload).filter(([name]) => name !== field)),
|
|
418
|
+
fields
|
|
419
|
+
};
|
|
420
|
+
}
|
|
421
|
+
function isRefused([name, value], { plan }) {
|
|
422
|
+
return plan.topLevelNames.has(name) || plan.topLevelHeaders && typeof value === "string";
|
|
423
|
+
}
|
|
424
|
+
|
|
271
425
|
// src/internal/json-envelope-read.ts
|
|
272
426
|
var RFC3339_PATTERN = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})$/i;
|
|
273
427
|
var EPOCH_PATTERN = /^\d+$/;
|
|
@@ -304,13 +458,8 @@ function readType(message, { plan, failures }) {
|
|
|
304
458
|
return plan.type.fixed;
|
|
305
459
|
}
|
|
306
460
|
const location = plan.type;
|
|
307
|
-
const
|
|
308
|
-
|
|
309
|
-
assertEventType(type);
|
|
310
|
-
} catch (error) {
|
|
311
|
-
throw failures.invalid(`The event type is not a valid event type: ${error.message}`);
|
|
312
|
-
}
|
|
313
|
-
return type;
|
|
461
|
+
const wire = requireText(readText(message, { location, failures }), { location, failures });
|
|
462
|
+
return eventTypeOf(wire, { plan, failures });
|
|
314
463
|
}
|
|
315
464
|
function readPayload(body, { plan, failures }) {
|
|
316
465
|
if (plan.payload === void 0) {
|
|
@@ -320,7 +469,10 @@ function readPayload(body, { plan, failures }) {
|
|
|
320
469
|
if (payload === void 0) {
|
|
321
470
|
throw failures.invalid(`The message has no payload at '${plan.payload.join(".")}'`);
|
|
322
471
|
}
|
|
323
|
-
return payload
|
|
472
|
+
return withOtherFields(payload, {
|
|
473
|
+
body,
|
|
474
|
+
context: { plan, failures }
|
|
475
|
+
});
|
|
324
476
|
}
|
|
325
477
|
function readEventHeaders(message, plan) {
|
|
326
478
|
if (plan.topLevelHeaders) {
|
|
@@ -410,7 +562,7 @@ function writeMessage(envelope, { plan, failures }) {
|
|
|
410
562
|
};
|
|
411
563
|
const typeAt = typeLocation(envelope, { plan, failures });
|
|
412
564
|
if (typeAt !== void 0) {
|
|
413
|
-
put(typeAt, envelope
|
|
565
|
+
put(typeAt, wireTypeOf(envelope, { plan, failures }));
|
|
414
566
|
}
|
|
415
567
|
if (plan.id !== void 0) {
|
|
416
568
|
put(plan.id, envelope.id);
|
|
@@ -421,12 +573,8 @@ function writeMessage(envelope, { plan, failures }) {
|
|
|
421
573
|
put(location, value);
|
|
422
574
|
}
|
|
423
575
|
}
|
|
424
|
-
const body = writeBody(envelope, { plan, root });
|
|
425
|
-
if (plan.topLevelHeaders) {
|
|
426
|
-
spreadHeaders(envelope, { plan, failures, root: body });
|
|
427
|
-
}
|
|
428
576
|
return {
|
|
429
|
-
body,
|
|
577
|
+
body: writeBody(envelope, { plan, failures, root }),
|
|
430
578
|
headers: Object.fromEntries([
|
|
431
579
|
...eventHeaderEntries(envelope, { plan, failures }),
|
|
432
580
|
...headers,
|
|
@@ -463,11 +611,12 @@ function optionalValues(envelope, { plan, failures }) {
|
|
|
463
611
|
["causationId", envelope.causationId]
|
|
464
612
|
];
|
|
465
613
|
}
|
|
466
|
-
function writeBody(envelope, { plan, root }) {
|
|
614
|
+
function writeBody(envelope, { plan, failures, root }) {
|
|
615
|
+
const { payload, fields } = splitOtherFields(envelope, { plan, failures });
|
|
467
616
|
if (plan.payload === void 0) {
|
|
468
|
-
return
|
|
617
|
+
return payload;
|
|
469
618
|
}
|
|
470
|
-
setAt(root, { path: plan.payload, value:
|
|
619
|
+
setAt(root, { path: plan.payload, value: payload });
|
|
471
620
|
if (plan.headers !== void 0) {
|
|
472
621
|
setAt(root, {
|
|
473
622
|
path: plan.headers,
|
|
@@ -477,6 +626,10 @@ function writeBody(envelope, { plan, root }) {
|
|
|
477
626
|
for (const { path, value } of plan.extraBody) {
|
|
478
627
|
setAt(root, { path, value: typeof value === "function" ? value(envelope) : value });
|
|
479
628
|
}
|
|
629
|
+
if (plan.topLevelHeaders) {
|
|
630
|
+
spreadHeaders(envelope, { plan, failures, root });
|
|
631
|
+
}
|
|
632
|
+
spreadOtherFields(envelope, { failures, fields, root });
|
|
480
633
|
return ordered(root, plan.bodyOrder);
|
|
481
634
|
}
|
|
482
635
|
function spreadHeaders(envelope, { plan, failures, root }) {
|
|
@@ -489,6 +642,20 @@ function spreadHeaders(envelope, { plan, failures, root }) {
|
|
|
489
642
|
setAt(root, { path: [name], value });
|
|
490
643
|
}
|
|
491
644
|
}
|
|
645
|
+
function spreadOtherFields(envelope, {
|
|
646
|
+
failures,
|
|
647
|
+
fields,
|
|
648
|
+
root
|
|
649
|
+
}) {
|
|
650
|
+
for (const [name, value] of fields) {
|
|
651
|
+
if (Object.hasOwn(root, name)) {
|
|
652
|
+
throw failures.unencodable(
|
|
653
|
+
`Event ${envelope.id} keeps a top-level field '${name}' that an event header also writes`
|
|
654
|
+
);
|
|
655
|
+
}
|
|
656
|
+
setAt(root, { path: [name], value });
|
|
657
|
+
}
|
|
658
|
+
}
|
|
492
659
|
function timeValue(text, { envelope, format }) {
|
|
493
660
|
const milliseconds = envelope.occurredAt.getTime();
|
|
494
661
|
if (format === "epoch-millis") {
|
|
@@ -746,6 +913,6 @@ var NonEmptyText = class _NonEmptyText {
|
|
|
746
913
|
}
|
|
747
914
|
};
|
|
748
915
|
|
|
749
|
-
export { BoundedInteger, DecodedEventReader, ExponentialBackoff, HandedOutLedger, LaneLeaseTokenFormat, NonEmptyText, OwnerSerializedClaims, SubscribingTransport, assertPositiveInteger, createCloudEventReaders, createJsonEnvelopeFormat, fromHeader, fromPayloadField, isJsonObject, mediaTypeOf, observeRejection, writeStructuredCloudEvent };
|
|
916
|
+
export { BoundedInteger, DecodedEventReader, ExponentialBackoff, HandedOutLedger, LaneLeaseTokenFormat, NonEmptyText, OwnerSerializedClaims, SubscribingTransport, assertPositiveInteger, createCloudEventReaders, createJsonEnvelopeFormat, fromHeader, fromPayloadField, isJsonObject, mediaTypeOf, mergeWireTypes, observeRejection, withDeclaredWireTypes, writeStructuredCloudEvent };
|
|
750
917
|
//# sourceMappingURL=index.js.map
|
|
751
918
|
//# sourceMappingURL=index.js.map
|