@kairos-es/core 1.0.0-alpha.2 → 1.0.0-alpha.4
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 +1 -1
- package/dist/cjs/ContractStore.js +11 -2
- package/dist/cjs/ContractStore.js.map +1 -1
- package/dist/cjs/Event.js +63 -3
- package/dist/cjs/Event.js.map +1 -1
- package/dist/cjs/Projection.js +15 -9
- package/dist/cjs/Projection.js.map +1 -1
- package/dist/cjs/Query.js +58 -2
- package/dist/cjs/Query.js.map +1 -1
- package/dist/cjs/inMemory.js +110 -40
- package/dist/cjs/inMemory.js.map +1 -1
- package/dist/dts/ContractStore.d.ts +4 -2
- package/dist/dts/ContractStore.d.ts.map +1 -1
- package/dist/dts/Event.d.ts +60 -1
- package/dist/dts/Event.d.ts.map +1 -1
- package/dist/dts/Projection.d.ts +1 -1
- package/dist/dts/Projection.d.ts.map +1 -1
- package/dist/dts/Query.d.ts +14 -0
- package/dist/dts/Query.d.ts.map +1 -1
- package/dist/dts/inMemory.d.ts.map +1 -1
- package/dist/esm/ContractStore.js +11 -2
- package/dist/esm/ContractStore.js.map +1 -1
- package/dist/esm/Event.js +62 -2
- package/dist/esm/Event.js.map +1 -1
- package/dist/esm/Projection.js +15 -9
- package/dist/esm/Projection.js.map +1 -1
- package/dist/esm/Query.js +55 -0
- package/dist/esm/Query.js.map +1 -1
- package/dist/esm/inMemory.js +111 -41
- package/dist/esm/inMemory.js.map +1 -1
- package/package.json +1 -1
- package/src/ContractStore.ts +20 -4
- package/src/Event.ts +63 -1
- package/src/Projection.ts +19 -8
- package/src/Query.ts +73 -0
- package/src/inMemory.ts +119 -47
package/dist/dts/Event.d.ts
CHANGED
|
@@ -73,13 +73,70 @@ export type ReadLimit = typeof ReadLimit.Type;
|
|
|
73
73
|
*/
|
|
74
74
|
export declare const EventType: Schema.brand<Schema.filter<typeof Schema.String>, "EventType">;
|
|
75
75
|
export type EventType = typeof EventType.Type;
|
|
76
|
+
/**
|
|
77
|
+
* An event's metadata: a flat bag of strings carrying the circumstances under
|
|
78
|
+
* which the event was RECORDED, never anything the business asserts (ADR-0017).
|
|
79
|
+
* Payload is what happened; metadata is the context of the recording — a
|
|
80
|
+
* `traceparent`, a correlation or causation id, a deployment revision.
|
|
81
|
+
*
|
|
82
|
+
* Values are strings, not `unknown`, for cross-engine parity rather than taste:
|
|
83
|
+
* both SQL engines carry the bag as a JSON document, and `JSON.stringify` drops
|
|
84
|
+
* `undefined`, throws on `bigint` and turns `NaN` into `null`, none of which the
|
|
85
|
+
* in-memory oracle does.
|
|
86
|
+
*
|
|
87
|
+
* The key schema carries no refinement, deliberately: a refinement on a
|
|
88
|
+
* `Schema.Record` key acts as a FILTER on decode, silently dropping a key that
|
|
89
|
+
* fails it rather than failing the decode. Constraining keys, if ever wanted,
|
|
90
|
+
* has to be a validating step of its own.
|
|
91
|
+
*
|
|
92
|
+
* Two engine limits a consumer must know, because the bag is typically filled
|
|
93
|
+
* from outside the application at a request edge. Postgres refuses a NUL
|
|
94
|
+
* character (U+0000) and an unpaired surrogate in any string it stores, so an
|
|
95
|
+
* event whose bag holds one fails to append there while the in-memory and
|
|
96
|
+
* SQLite engines accept it; sanitise untrusted values before they reach the
|
|
97
|
+
* bag. And key ORDER is not preserved: Postgres stores an object's keys in an
|
|
98
|
+
* order of its own, so compare bags as unordered and never rely on the order
|
|
99
|
+
* `Object.keys` returns.
|
|
100
|
+
*
|
|
101
|
+
* Metadata is never part of a `Query` or an `AppendCondition` — a store refuses
|
|
102
|
+
* either when it carries a key the grammar does not define, so a metadata
|
|
103
|
+
* predicate cannot be written and silently ignored — never reaches a codec's
|
|
104
|
+
* `tagsFor`, and no store offers a way to rewrite it once appended. ADR-0017
|
|
105
|
+
* owns why each of those is mechanical rather than preferential.
|
|
106
|
+
*
|
|
107
|
+
* ## The one home of the shape rule
|
|
108
|
+
*
|
|
109
|
+
* The bag is a JSON OBJECT whose every value is a STRING, and this schema is
|
|
110
|
+
* where that rule is stated. At runtime it is checked in ONE place, at write: the
|
|
111
|
+
* codec's `toEvent` decodes every bag through this schema and refuses one that
|
|
112
|
+
* fails on its own error channel, so a value smuggled past the type (through an
|
|
113
|
+
* `any`) stops there. The schema judges a bag's OWN enumerable keys, so an object
|
|
114
|
+
* that keeps its entries anywhere else — a `Map`, a `Date` — reads as the empty
|
|
115
|
+
* bag rather than failing. A store checks no values: an event built by hand and handed
|
|
116
|
+
* to `append` directly carries whatever it carries, and what each engine then does
|
|
117
|
+
* with a non-string value differs — one may store it and read it back differently
|
|
118
|
+
* from another, and a `bigint` makes a SQL engine's append fail. Each
|
|
119
|
+
* SQL engine keeps a container check of its own on read — the column must hold a
|
|
120
|
+
* JSON object — because that defends against a writer outside the library and is
|
|
121
|
+
* about the column, not the values. A VALUE check must never be added on read
|
|
122
|
+
* alone: it would make an event the store accepted unreadable for ever, so a
|
|
123
|
+
* value check belongs at write or nowhere.
|
|
124
|
+
*/
|
|
125
|
+
export declare const Metadata: Schema.Record$<typeof Schema.String, typeof Schema.String>;
|
|
126
|
+
export type Metadata = typeof Metadata.Type;
|
|
76
127
|
/**
|
|
77
128
|
* An event as stored: an opaque payload plus its type, tags, a
|
|
78
|
-
* producer-supplied `uuid`,
|
|
129
|
+
* producer-supplied `uuid`, producer-supplied `occurredAt` domain time, and its
|
|
130
|
+
* `metadata` bag.
|
|
79
131
|
*
|
|
80
132
|
* `data` is `Uint8Array` (opaque bytes); the store does not interpret it.
|
|
81
133
|
* `uuid` is producer-supplied to keep `core` deterministic (no RNG in core).
|
|
82
134
|
* `occurredAt` is informational only; ordering is by position alone.
|
|
135
|
+
* `metadata` mirrors `tags` rather than `data`: REQUIRED, with an empty bag
|
|
136
|
+
* legal. Required because an absent-versus-empty divergence between engines is
|
|
137
|
+
* invisible to `toEqual`, which ignores `undefined` properties, so an optional
|
|
138
|
+
* field could drift across the three engines with the round-trip suite green.
|
|
139
|
+
* Core only carries it; the codec's `toEvent` is where it is resolved.
|
|
83
140
|
*/
|
|
84
141
|
export declare const DcbEvent: Schema.Struct<{
|
|
85
142
|
type: Schema.brand<Schema.filter<typeof Schema.String>, "EventType">;
|
|
@@ -87,6 +144,7 @@ export declare const DcbEvent: Schema.Struct<{
|
|
|
87
144
|
tags: Schema.Array$<Schema.brand<Schema.filter<typeof Schema.String>, "Tag">>;
|
|
88
145
|
uuid: typeof Schema.UUID;
|
|
89
146
|
occurredAt: typeof Schema.DateTimeUtc;
|
|
147
|
+
metadata: Schema.Record$<typeof Schema.String, typeof Schema.String>;
|
|
90
148
|
}>;
|
|
91
149
|
export type DcbEvent = typeof DcbEvent.Type;
|
|
92
150
|
/** A persisted event: the event together with the position it was written at. */
|
|
@@ -97,6 +155,7 @@ export declare const SequencedEvent: Schema.Struct<{
|
|
|
97
155
|
tags: Schema.Array$<Schema.brand<Schema.filter<typeof Schema.String>, "Tag">>;
|
|
98
156
|
uuid: typeof Schema.UUID;
|
|
99
157
|
occurredAt: typeof Schema.DateTimeUtc;
|
|
158
|
+
metadata: Schema.Record$<typeof Schema.String, typeof Schema.String>;
|
|
100
159
|
}>;
|
|
101
160
|
position: Schema.brand<Schema.filter<typeof Schema.BigInt>, "Position">;
|
|
102
161
|
}>;
|
package/dist/dts/Event.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Event.d.ts","sourceRoot":"","sources":["../../src/Event.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAE/B;;;;;;;;GAQG;AACH,eAAO,MAAM,QAAQ,+DAGpB,CAAA;AACD,MAAM,MAAM,QAAQ,GAAG,OAAO,QAAQ,CAAC,IAAI,CAAA;AAE3C,8DAA8D;AAC9D,eAAO,MAAM,MAAM,EAAE,QAA4B,CAAA;AAEjD;;;;;GAKG;AACH,eAAO,MAAM,GAAG,0DAGf,CAAA;AACD,MAAM,MAAM,GAAG,GAAG,OAAO,GAAG,CAAC,IAAI,CAAA;AAEjC;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,GAAG,CAAA;CACtC;AAED,eAAO,MAAM,WAAW,GAAI,KAAK,MAAM,KAAG,WAiBzC,CAAA;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,SAAS,6DAGrB,CAAA;AACD,MAAM,MAAM,SAAS,GAAG,OAAO,SAAS,CAAC,IAAI,CAAA;AAE7C;;;GAGG;AACH,eAAO,MAAM,SAAS,gEAGrB,CAAA;AACD,MAAM,MAAM,SAAS,GAAG,OAAO,SAAS,CAAC,IAAI,CAAA;AAE7C
|
|
1
|
+
{"version":3,"file":"Event.d.ts","sourceRoot":"","sources":["../../src/Event.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAE/B;;;;;;;;GAQG;AACH,eAAO,MAAM,QAAQ,+DAGpB,CAAA;AACD,MAAM,MAAM,QAAQ,GAAG,OAAO,QAAQ,CAAC,IAAI,CAAA;AAE3C,8DAA8D;AAC9D,eAAO,MAAM,MAAM,EAAE,QAA4B,CAAA;AAEjD;;;;;GAKG;AACH,eAAO,MAAM,GAAG,0DAGf,CAAA;AACD,MAAM,MAAM,GAAG,GAAG,OAAO,GAAG,CAAC,IAAI,CAAA;AAEjC;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,GAAG,CAAA;CACtC;AAED,eAAO,MAAM,WAAW,GAAI,KAAK,MAAM,KAAG,WAiBzC,CAAA;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,SAAS,6DAGrB,CAAA;AACD,MAAM,MAAM,SAAS,GAAG,OAAO,SAAS,CAAC,IAAI,CAAA;AAE7C;;;GAGG;AACH,eAAO,MAAM,SAAS,gEAGrB,CAAA;AACD,MAAM,MAAM,SAAS,GAAG,OAAO,SAAS,CAAC,IAAI,CAAA;AAE7C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AACH,eAAO,MAAM,QAAQ,4DAGnB,CAAA;AACF,MAAM,MAAM,QAAQ,GAAG,OAAO,QAAQ,CAAC,IAAI,CAAA;AAE3C;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,QAAQ;;;;;;;EAOnB,CAAA;AACF,MAAM,MAAM,QAAQ,GAAG,OAAO,QAAQ,CAAC,IAAI,CAAA;AAE3C,iFAAiF;AACjF,eAAO,MAAM,cAAc;;;;;;;;;;EAGzB,CAAA;AACF,MAAM,MAAM,cAAc,GAAG,OAAO,cAAc,CAAC,IAAI,CAAA"}
|
package/dist/dts/Projection.d.ts
CHANGED
|
@@ -28,7 +28,7 @@ import type { SequencedEvent } from './Event.js';
|
|
|
28
28
|
import type { Query } from './Query.js';
|
|
29
29
|
/**
|
|
30
30
|
* An already-decoded event handed to a projection's fold: the sequenced wire
|
|
31
|
-
* envelope (position, type, tags, timings) plus the decoded `payload`.
|
|
31
|
+
* envelope (position, type, tags, timings, metadata) plus the decoded `payload`.
|
|
32
32
|
*
|
|
33
33
|
* Core does not decode — it only folds events another layer has already decoded
|
|
34
34
|
* — so `payload` is `unknown` at this layer. `@kairos-es/codec`'s builder emits
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Projection.d.ts","sourceRoot":"","sources":["../../src/Projection.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAC7C,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAWpC;;;;;;;GAOG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,SAAS,EAAE,cAAc,CAAA;IAClC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;CAC1B;AAED;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,UAAU,CAAC,CAAC;IAC3B,QAAQ,CAAC,YAAY,EAAE,CAAC,CAAA;IACxB,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAA;IACrB,QAAQ,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,YAAY,KAAK,CAAC,CAAA;CACtD;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,aAAa,CAAC,GAAG,CAAC,CAAC,GAAG,OAAO;IAC5C,QAAQ,CAAC,YAAY,EAAE,CAAC,CAAA;IACxB,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAA;IACrB,QAAQ,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,YAAY,KAAK,OAAO,CAAA;CAClE;AAED,eAAO,MAAM,aAAa;IACxB;;;;;;OAMG;kBACE,CAAC,cAAc,UAAU,CAAC,CAAC,CAAC,KAAG,aAAa,CAAC,CAAC,CAAC;CAE5C,CAAA;AAEV,oDAAoD;AACpD,MAAM,MAAM,OAAO,CAAC,CAAC,IAAI,CAAC,SAAS,aAAa,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK,CAAA;AAErE;;;GAGG;AACH,MAAM,MAAM,cAAc,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,IAAI;IACpE,QAAQ,EAAE,CAAC,IAAI,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;CACvC,CAAA;
|
|
1
|
+
{"version":3,"file":"Projection.d.ts","sourceRoot":"","sources":["../../src/Projection.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAC7C,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAWpC;;;;;;;GAOG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,SAAS,EAAE,cAAc,CAAA;IAClC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;CAC1B;AAED;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,UAAU,CAAC,CAAC;IAC3B,QAAQ,CAAC,YAAY,EAAE,CAAC,CAAA;IACxB,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAA;IACrB,QAAQ,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,YAAY,KAAK,CAAC,CAAA;CACtD;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,aAAa,CAAC,GAAG,CAAC,CAAC,GAAG,OAAO;IAC5C,QAAQ,CAAC,YAAY,EAAE,CAAC,CAAA;IACxB,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAA;IACrB,QAAQ,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,YAAY,KAAK,OAAO,CAAA;CAClE;AAED,eAAO,MAAM,aAAa;IACxB;;;;;;OAMG;kBACE,CAAC,cAAc,UAAU,CAAC,CAAC,CAAC,KAAG,aAAa,CAAC,CAAC,CAAC;CAE5C,CAAA;AAEV,oDAAoD;AACpD,MAAM,MAAM,OAAO,CAAC,CAAC,IAAI,CAAC,SAAS,aAAa,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK,CAAA;AAErE;;;GAGG;AACH,MAAM,MAAM,cAAc,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,IAAI;IACpE,QAAQ,EAAE,CAAC,IAAI,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;CACvC,CAAA;AAqBD;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,YAAY,GAAI,SAAS,aAAa,CAAC,KAAK,CAAC,KAAG,KAGT,CAAA;AAEpD;;;;;;;;;;GAUG;AACH,eAAO,MAAM,kBAAkB,GAAI,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,EACxE,aAAa,CAAC,KACb,UAAU,CAAC,cAAc,CAAC,CAAC,CAAC,CA0B9B,CAAA"}
|
package/dist/dts/Query.d.ts
CHANGED
|
@@ -61,6 +61,9 @@ export declare const matchesSequenced: (sequenced: SequencedEvent, query: Query)
|
|
|
61
61
|
* (`Query.ts` module docs) but which plain-data assembly — e.g. decision-model
|
|
62
62
|
* composition, `Projection.ts:31-36` — can still bypass.
|
|
63
63
|
*
|
|
64
|
+
* A query, or any of its items, carrying a key the grammar does not define is
|
|
65
|
+
* refused before anything else is judged (`unknownKeyFault` below says why).
|
|
66
|
+
*
|
|
64
67
|
* The servable grammar is exactly one of:
|
|
65
68
|
* - the wildcard (`items.length === 0`), which matches every event;
|
|
66
69
|
* - a *single* item (`items.length === 1`), any types/tags, including a
|
|
@@ -81,6 +84,17 @@ export declare const matchesSequenced: (sequenced: SequencedEvent, query: Query)
|
|
|
81
84
|
* engine" behaviour.
|
|
82
85
|
*/
|
|
83
86
|
export declare const assertServableQuery: (query: Query) => void;
|
|
87
|
+
/**
|
|
88
|
+
* The unknown-key half of `servableQueryFault`, on its own: the refusal of a key the
|
|
89
|
+
* grammar does not define on the envelope or on any item, or `undefined`.
|
|
90
|
+
*
|
|
91
|
+
* It is the same rule and not a second statement of it — `servableQueryFault` calls
|
|
92
|
+
* this first. It is exported because ONE caller has to tell the two halves apart:
|
|
93
|
+
* the codec's read ledger refuses an unservable SHAPE on its own error channel, and
|
|
94
|
+
* must not report an unknown key as one. An unknown key is not something a slice's
|
|
95
|
+
* tags can fix, so the ledger leaves it to the store, which refuses it as a defect.
|
|
96
|
+
*/
|
|
97
|
+
export declare const unknownQueryKeyFault: (query: Query) => string | undefined;
|
|
84
98
|
/**
|
|
85
99
|
* The servable grammar as a TOTAL function: the reason `query` cannot be served,
|
|
86
100
|
* or `undefined` when it can.
|
package/dist/dts/Query.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Query.d.ts","sourceRoot":"","sources":["../../src/Query.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,OAAO,EAAE,KAAK,IAAI,GAAG,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAC7C,OAAO,EAAE,KAAK,QAAQ,EAAE,SAAS,EAAE,KAAK,cAAc,EAAE,GAAG,EAAE,MAAM,SAAS,CAAA;AAE5E;;;GAGG;AACH,eAAO,MAAM,SAAS;;;EAGpB,CAAA;AACF,MAAM,MAAM,SAAS,GAAG,OAAO,SAAS,CAAC,IAAI,CAAA;AAE7C,iEAAiE;AACjE,eAAO,MAAM,KAAK;;;;;EAEhB,CAAA;AACF,MAAM,MAAM,KAAK,GAAG,OAAO,KAAK,CAAC,IAAI,CAAA;AAErC;;;GAGG;AACH,eAAO,MAAM,gBAAgB,GAAI,OAAO,QAAQ,EAAE,MAAM,SAAS,KAAG,OAOnE,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,YAAY,GAAI,OAAO,QAAQ,EAAE,OAAO,KAAK,KAAG,OAK5D,CAAA;AAED,qDAAqD;AACrD,eAAO,MAAM,gBAAgB,GAC3B,WAAW,cAAc,EACzB,OAAO,KAAK,KACX,OAA+C,CAAA;AAElD
|
|
1
|
+
{"version":3,"file":"Query.d.ts","sourceRoot":"","sources":["../../src/Query.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,OAAO,EAAE,KAAK,IAAI,GAAG,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAC7C,OAAO,EAAE,KAAK,QAAQ,EAAE,SAAS,EAAE,KAAK,cAAc,EAAE,GAAG,EAAE,MAAM,SAAS,CAAA;AAE5E;;;GAGG;AACH,eAAO,MAAM,SAAS;;;EAGpB,CAAA;AACF,MAAM,MAAM,SAAS,GAAG,OAAO,SAAS,CAAC,IAAI,CAAA;AAE7C,iEAAiE;AACjE,eAAO,MAAM,KAAK;;;;;EAEhB,CAAA;AACF,MAAM,MAAM,KAAK,GAAG,OAAO,KAAK,CAAC,IAAI,CAAA;AAErC;;;GAGG;AACH,eAAO,MAAM,gBAAgB,GAAI,OAAO,QAAQ,EAAE,MAAM,SAAS,KAAG,OAOnE,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,YAAY,GAAI,OAAO,QAAQ,EAAE,OAAO,KAAK,KAAG,OAK5D,CAAA;AAED,qDAAqD;AACrD,eAAO,MAAM,gBAAgB,GAC3B,WAAW,cAAc,EACzB,OAAO,KAAK,KACX,OAA+C,CAAA;AAElD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,eAAO,MAAM,mBAAmB,GAAI,OAAO,KAAK,KAAG,IAKlD,CAAA;AAkDD;;;;;;;;;GASG;AACH,eAAO,MAAM,oBAAoB,GAAI,OAAO,KAAK,KAAG,MAAM,GAAG,SAM1D,CAAA;AAEH;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,kBAAkB,GAAI,OAAO,KAAK,KAAG,MAAM,GAAG,SAsB1D,CAAA;AAED;;;;;;;;;GASG;AACH,MAAM,MAAM,kBAAkB,GAC1B;IAAE,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAA;CAAE,GAC7B;IACE,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAA;IACzB,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAC,qBAAqB,CAAC,SAAS,CAAC,CAAA;CACrD,GACD;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAA;CAAE,CAAA;AAE/B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,eAAO,MAAM,qBAAqB,GAAI,OAAO,KAAK,KAAG,kBAWpD,CAAA;AAoDD,iDAAiD;AACjD,eAAO,MAAM,KAAK;wBAlCF,KAAK;4BATC;QACpB,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC,GAAG,EAAE,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC,CAAA;QACpD,QAAQ,CAAC,KAAK,CAAC,EAAE,aAAa,CAAC,SAAS,CAAC,CAAA;KAC1C,KAAG,SAAS;yBAkCJ,SAAS,CAAC,SAAS,EAAE,GAAG,aAAa,CAAC,SAAS,CAAC,CAAC,KACvD,KAAK;0BAtBA,SAAS,CAAC,GAAG,EAAE,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC,UACnC,aAAa,CAAC,SAAS,CAAC,KAC/B,KAAK;4BAUC,SAAS,CAAC,SAAS,EAAE,GAAG,aAAa,CAAC,SAAS,CAAC,CAAC,KACvD,KAAK;CAoBE,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inMemory.d.ts","sourceRoot":"","sources":["../../src/inMemory.ts"],"names":[],"mappings":"AA2BA,OAAO,
|
|
1
|
+
{"version":3,"file":"inMemory.d.ts","sourceRoot":"","sources":["../../src/inMemory.ts"],"names":[],"mappings":"AA2BA,OAAO,EAAY,MAAM,EAAE,KAAK,EAAuB,MAAM,QAAQ,CAAA;AAIrE,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAuL/C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoDG;AACH,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;IAC3C,QAAQ,CAAC,YAAY,CAAC,EAAE,OAAO,CAAA;IAC/B,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAA;IACjC,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAC/B;AAuID,sEAAsE;AACtE,eAAO,MAAM,qBAAqB,EAAE,KAAK,CAAC,KAAK,CAAC,aAAa,CAG5D,CAAA;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,qBAAqB,GAChC,SAAS,oBAAoB,KAC5B,KAAK,CAAC,KAAK,CAAC,aAAa,CAC+C,CAAA"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Effect, Predicate, Schema, Stream } from 'effect';
|
|
2
|
+
import { AppendCondition } from "./AppendCondition.js";
|
|
2
3
|
import { assertAppendNotOwned } from "./AppendIsOwned.js";
|
|
3
4
|
import { ReadLimit } from "./Event.js";
|
|
4
5
|
import { assertServableQuery } from "./Query.js";
|
|
@@ -20,7 +21,7 @@ export const makeContractStore = raw => ({
|
|
|
20
21
|
}),
|
|
21
22
|
append: (events, condition) =>
|
|
22
23
|
// The ownership refusal runs FIRST and sits OUTSIDE the suspend, because it is
|
|
23
|
-
// the only one of append's
|
|
24
|
+
// the only one of append's checks that is EFFECTFUL: it consults a
|
|
24
25
|
// `Context.Tag` rather than inspecting the arguments. `Effect.flatMap` over an
|
|
25
26
|
// already-lazy effect defers it exactly as the suspend defers the throws below,
|
|
26
27
|
// so nothing runs at the call site either way; what it buys is that the
|
|
@@ -41,8 +42,16 @@ export const makeContractStore = raw => ({
|
|
|
41
42
|
if (events.length === 0) {
|
|
42
43
|
throw new Error('makeContractStore.append: the events batch is empty; append requires ' + 'at least one event (a NonEmptyReadonlyArray). An empty batch is a ' + 'plain-data caller bypassing the type — a defect, not a conflict.');
|
|
43
44
|
}
|
|
44
|
-
// A non-servable guard query is a defect in every engine
|
|
45
|
+
// A non-servable guard query is a defect in every engine, and so is a
|
|
46
|
+
// condition carrying a key `AppendCondition` does not define: an author
|
|
47
|
+
// who wrote one believes they added a condition, and every engine would
|
|
48
|
+
// ignore it. Known keys come off the schema, as `servableQueryFault`
|
|
49
|
+
// reads its own (`Query.ts` owns the argument).
|
|
45
50
|
if (condition !== undefined) {
|
|
51
|
+
const unknown = Object.keys(condition).find(key => !Object.hasOwn(AppendCondition.fields, key));
|
|
52
|
+
if (unknown !== undefined) {
|
|
53
|
+
throw new Error(`makeContractStore.append: the append condition carries the key ${JSON.stringify(unknown)}, ` + 'which `AppendCondition` does not define; an unknown key would be ' + 'silently ignored by every engine rather than honoured, so it is refused');
|
|
54
|
+
}
|
|
46
55
|
assertServableQuery(condition.failIfEventsMatch);
|
|
47
56
|
}
|
|
48
57
|
// Only `AppendConditionFailed` belongs on the contract error channel;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ContractStore.js","names":["Effect","Predicate","Schema","Stream","assertAppendNotOwned","ReadLimit","assertServableQuery","decodeReadLimit","decodeUnknownSync","makeContractStore","raw","read","query","options","suspend","limit","undefined","orDie","append","events","condition","flatMap","length","Error","failIfEventsMatch","catchAll","error","isTagged","fail","die","subscribe","after","unwrap","sync"],"sources":["../../src/ContractStore.ts"],"sourcesContent":[null],"mappings":"
|
|
1
|
+
{"version":3,"file":"ContractStore.js","names":["Effect","Predicate","Schema","Stream","AppendCondition","assertAppendNotOwned","ReadLimit","assertServableQuery","decodeReadLimit","decodeUnknownSync","makeContractStore","raw","read","query","options","suspend","limit","undefined","orDie","append","events","condition","flatMap","length","Error","unknown","Object","keys","find","key","hasOwn","fields","JSON","stringify","failIfEventsMatch","catchAll","error","isTagged","fail","die","subscribe","after","unwrap","sync"],"sources":["../../src/ContractStore.ts"],"sourcesContent":[null],"mappings":"AAqCA,SAASA,MAAM,EAAEC,SAAS,EAAEC,MAAM,EAAEC,MAAM,QAAQ,QAAQ;AAC1D,SAASC,eAAe,QAAQ,sBAAmB;AACnD,SAASC,oBAAoB,QAAQ,oBAAiB;AAGtD,SAASC,SAAS,QAAQ,YAAS;AAEnC,SAASC,mBAAmB,QAAoB,YAAS;AAEzD;AACA,MAAMC,eAAe,gBAAGN,MAAM,CAACO,iBAAiB,CAACH,SAAS,CAAC;AAwB3D;;;;AAIA,OAAO,MAAMI,iBAAiB,GAC5BC,GAAwB,KACG;EAC3BC,IAAI,EAAEA,CAACC,KAAK,EAAEC,OAAO,KACnBd,MAAM,CAACe,OAAO,CAAC,MAAK;IAClB;IACAR,mBAAmB,CAACM,KAAK,CAAC;IAC1B,IAAIC,OAAO,EAAEE,KAAK,KAAKC,SAAS,EAAE;MAChCT,eAAe,CAACM,OAAO,CAACE,KAAK,CAAC;IAChC;IACA;IACA,OAAOhB,MAAM,CAACkB,KAAK,CAACP,GAAG,CAACC,IAAI,CAACC,KAAK,EAAEC,OAAO,CAAC,CAAC;EAC/C,CAAC,CAAC;EAEJK,MAAM,EAAEA,CAACC,MAAM,EAAEC,SAAS;EACxB;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACArB,MAAM,CAACsB,OAAO,CAACjB,oBAAoB,EAAE,MACnCL,MAAM,CAACe,OAAO,CAAC,MAAK;IAClB;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA,IAAIK,MAAM,CAACG,MAAM,KAAK,CAAC,EAAE;MACvB,MAAM,IAAIC,KAAK,CACb,uEAAuE,GACrE,oEAAoE,GACpE,kEAAkE,CACrE;IACH;IACA;IACA;IACA;IACA;IACA;IACA,IAAIH,SAAS,KAAKJ,SAAS,EAAE;MAC3B,MAAMQ,OAAO,GAAGC,MAAM,CAACC,IAAI,CAACN,SAAS,CAAC,CAACO,IAAI,CACxCC,GAAG,IAAK,CAACH,MAAM,CAACI,MAAM,CAAC1B,eAAe,CAAC2B,MAAM,EAAEF,GAAG,CAAC,CACrD;MACD,IAAIJ,OAAO,KAAKR,SAAS,EAAE;QACzB,MAAM,IAAIO,KAAK,CACb,kEAAkEQ,IAAI,CAACC,SAAS,CAACR,OAAO,CAAC,IAAI,GAC3F,mEAAmE,GACnE,yEAAyE,CAC5E;MACH;MACAlB,mBAAmB,CAACc,SAAS,CAACa,iBAAiB,CAAC;IAClD;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA,OAAOlC,MAAM,CAACmC,QAAQ,CAACxB,GAAG,CAACQ,MAAM,CAACC,MAAM,EAAEC,SAAS,CAAC,EAAGe,KAAK,IAC1DnC,SAAS,CAACoC,QAAQ,CAAC,uBAAuB,CAAC,CAACD,KAAK,CAAC,GAC9CpC,MAAM,CAACsC,IAAI,CAACF,KAAK,CAAC,GAClBpC,MAAM,CAACuC,GAAG,CAACH,KAAK,CAAC,CACtB;EACH,CAAC,CAAC,CACH;EAEHI,SAAS,EAAEA,CAAC3B,KAAK,EAAE4B,KAAK;EACtB;EACA;EACA;EACA;EACAtC,MAAM,CAACuC,MAAM,CACX1C,MAAM,CAAC2C,IAAI,CAAC,MAAK;IACfpC,mBAAmB,CAACM,KAAK,CAAC;IAC1B,OAAOV,MAAM,CAACe,KAAK,CAACP,GAAG,CAAC6B,SAAS,CAAC3B,KAAK,EAAE4B,KAAK,CAAC,CAAC;EAClD,CAAC,CAAC;CAEP,CAAC","ignoreList":[]}
|
package/dist/esm/Event.js
CHANGED
|
@@ -58,20 +58,80 @@ export const ReadLimit = /*#__PURE__*/Schema.Int.pipe(/*#__PURE__*/Schema.greate
|
|
|
58
58
|
* in the name (e.g. `course-registered.v2`); only non-emptiness is enforced.
|
|
59
59
|
*/
|
|
60
60
|
export const EventType = /*#__PURE__*/Schema.String.pipe(/*#__PURE__*/Schema.nonEmptyString(), /*#__PURE__*/Schema.brand('EventType'));
|
|
61
|
+
/**
|
|
62
|
+
* An event's metadata: a flat bag of strings carrying the circumstances under
|
|
63
|
+
* which the event was RECORDED, never anything the business asserts (ADR-0017).
|
|
64
|
+
* Payload is what happened; metadata is the context of the recording — a
|
|
65
|
+
* `traceparent`, a correlation or causation id, a deployment revision.
|
|
66
|
+
*
|
|
67
|
+
* Values are strings, not `unknown`, for cross-engine parity rather than taste:
|
|
68
|
+
* both SQL engines carry the bag as a JSON document, and `JSON.stringify` drops
|
|
69
|
+
* `undefined`, throws on `bigint` and turns `NaN` into `null`, none of which the
|
|
70
|
+
* in-memory oracle does.
|
|
71
|
+
*
|
|
72
|
+
* The key schema carries no refinement, deliberately: a refinement on a
|
|
73
|
+
* `Schema.Record` key acts as a FILTER on decode, silently dropping a key that
|
|
74
|
+
* fails it rather than failing the decode. Constraining keys, if ever wanted,
|
|
75
|
+
* has to be a validating step of its own.
|
|
76
|
+
*
|
|
77
|
+
* Two engine limits a consumer must know, because the bag is typically filled
|
|
78
|
+
* from outside the application at a request edge. Postgres refuses a NUL
|
|
79
|
+
* character (U+0000) and an unpaired surrogate in any string it stores, so an
|
|
80
|
+
* event whose bag holds one fails to append there while the in-memory and
|
|
81
|
+
* SQLite engines accept it; sanitise untrusted values before they reach the
|
|
82
|
+
* bag. And key ORDER is not preserved: Postgres stores an object's keys in an
|
|
83
|
+
* order of its own, so compare bags as unordered and never rely on the order
|
|
84
|
+
* `Object.keys` returns.
|
|
85
|
+
*
|
|
86
|
+
* Metadata is never part of a `Query` or an `AppendCondition` — a store refuses
|
|
87
|
+
* either when it carries a key the grammar does not define, so a metadata
|
|
88
|
+
* predicate cannot be written and silently ignored — never reaches a codec's
|
|
89
|
+
* `tagsFor`, and no store offers a way to rewrite it once appended. ADR-0017
|
|
90
|
+
* owns why each of those is mechanical rather than preferential.
|
|
91
|
+
*
|
|
92
|
+
* ## The one home of the shape rule
|
|
93
|
+
*
|
|
94
|
+
* The bag is a JSON OBJECT whose every value is a STRING, and this schema is
|
|
95
|
+
* where that rule is stated. At runtime it is checked in ONE place, at write: the
|
|
96
|
+
* codec's `toEvent` decodes every bag through this schema and refuses one that
|
|
97
|
+
* fails on its own error channel, so a value smuggled past the type (through an
|
|
98
|
+
* `any`) stops there. The schema judges a bag's OWN enumerable keys, so an object
|
|
99
|
+
* that keeps its entries anywhere else — a `Map`, a `Date` — reads as the empty
|
|
100
|
+
* bag rather than failing. A store checks no values: an event built by hand and handed
|
|
101
|
+
* to `append` directly carries whatever it carries, and what each engine then does
|
|
102
|
+
* with a non-string value differs — one may store it and read it back differently
|
|
103
|
+
* from another, and a `bigint` makes a SQL engine's append fail. Each
|
|
104
|
+
* SQL engine keeps a container check of its own on read — the column must hold a
|
|
105
|
+
* JSON object — because that defends against a writer outside the library and is
|
|
106
|
+
* about the column, not the values. A VALUE check must never be added on read
|
|
107
|
+
* alone: it would make an event the store accepted unreadable for ever, so a
|
|
108
|
+
* value check belongs at write or nowhere.
|
|
109
|
+
*/
|
|
110
|
+
export const Metadata = /*#__PURE__*/Schema.Record({
|
|
111
|
+
key: Schema.String,
|
|
112
|
+
value: Schema.String
|
|
113
|
+
});
|
|
61
114
|
/**
|
|
62
115
|
* An event as stored: an opaque payload plus its type, tags, a
|
|
63
|
-
* producer-supplied `uuid`,
|
|
116
|
+
* producer-supplied `uuid`, producer-supplied `occurredAt` domain time, and its
|
|
117
|
+
* `metadata` bag.
|
|
64
118
|
*
|
|
65
119
|
* `data` is `Uint8Array` (opaque bytes); the store does not interpret it.
|
|
66
120
|
* `uuid` is producer-supplied to keep `core` deterministic (no RNG in core).
|
|
67
121
|
* `occurredAt` is informational only; ordering is by position alone.
|
|
122
|
+
* `metadata` mirrors `tags` rather than `data`: REQUIRED, with an empty bag
|
|
123
|
+
* legal. Required because an absent-versus-empty divergence between engines is
|
|
124
|
+
* invisible to `toEqual`, which ignores `undefined` properties, so an optional
|
|
125
|
+
* field could drift across the three engines with the round-trip suite green.
|
|
126
|
+
* Core only carries it; the codec's `toEvent` is where it is resolved.
|
|
68
127
|
*/
|
|
69
128
|
export const DcbEvent = /*#__PURE__*/Schema.Struct({
|
|
70
129
|
type: EventType,
|
|
71
130
|
data: Schema.Uint8ArrayFromSelf,
|
|
72
131
|
tags: /*#__PURE__*/Schema.Array(Tag),
|
|
73
132
|
uuid: Schema.UUID,
|
|
74
|
-
occurredAt: Schema.DateTimeUtc
|
|
133
|
+
occurredAt: Schema.DateTimeUtc,
|
|
134
|
+
metadata: Metadata
|
|
75
135
|
});
|
|
76
136
|
/** A persisted event: the event together with the position it was written at. */
|
|
77
137
|
export const SequencedEvent = /*#__PURE__*/Schema.Struct({
|
package/dist/esm/Event.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Event.js","names":["Schema","Position","BigInt","pipe","nonNegativeBigInt","brand","ORIGIN","make","Tag","String","pattern","identifier","tagIdentity","key","length","includes","Error","JSON","stringify","value","ReadLimit","Int","greaterThanOrEqualTo","EventType","nonEmptyString","DcbEvent","Struct","type","data","Uint8ArrayFromSelf","tags","Array","uuid","UUID","occurredAt","DateTimeUtc","SequencedEvent","event","position"],"sources":["../../src/Event.ts"],"sourcesContent":[null],"mappings":"AAAA;;;;;;;;AAQA,SAASA,MAAM,QAAQ,QAAQ;AAE/B;;;;;;;;;AASA,OAAO,MAAMC,QAAQ,gBAAGD,MAAM,CAACE,MAAM,CAACC,IAAI,cACxCH,MAAM,CAACI,iBAAiB,EAAE,eAC1BJ,MAAM,CAACK,KAAK,CAAC,UAAU,CAAC,CACzB;AAGD;AACA,OAAO,MAAMC,MAAM,gBAAaL,QAAQ,CAACM,IAAI,CAAC,EAAE,CAAC;AAEjD;;;;;;AAMA,OAAO,MAAMC,GAAG,gBAAGR,MAAM,CAACS,MAAM,CAACN,IAAI,cACnCH,MAAM,CAACU,OAAO,CAAC,WAAW,EAAE;EAAEC,UAAU,EAAE;AAAK,CAAE,CAAC,eAClDX,MAAM,CAACK,KAAK,CAAC,KAAK,CAAC,CACpB;AA8BD,OAAO,MAAMO,WAAW,GAAIC,GAAW,IAAiB;EACtD,IAAIA,GAAG,CAACC,MAAM,KAAK,CAAC,IAAID,GAAG,CAACE,QAAQ,CAAC,GAAG,CAAC,EAAE;IACzC,MAAM,IAAIC,KAAK,CACb,8DAA8DC,IAAI,CAACC,SAAS,CAACL,GAAG,CAAC,GAAG,CACrF;EACH;EACA,OAAO;IACLA,GAAG;IACHN,IAAI,EAAGY,KAAK,IAAI;MACd,IAAIA,KAAK,CAACL,MAAM,KAAK,CAAC,IAAIK,KAAK,CAACJ,QAAQ,CAAC,GAAG,CAAC,EAAE;QAC7C,MAAM,IAAIC,KAAK,CACb,eAAeC,IAAI,CAACC,SAAS,CAACL,GAAG,CAAC,2DAA2DI,IAAI,CAACC,SAAS,CAACC,KAAK,CAAC,GAAG,CACtH;MACH;MACA,OAAOX,GAAG,CAACD,IAAI,CAAC,GAAGM,GAAG,IAAIM,KAAK,EAAE,CAAC;IACpC;GACD;AACH,CAAC;AAED;;;;;;;;;;AAUA,OAAO,MAAMC,SAAS,gBAAGpB,MAAM,CAACqB,GAAG,CAAClB,IAAI,cACtCH,MAAM,CAACsB,oBAAoB,CAAC,CAAC,CAAC,eAC9BtB,MAAM,CAACK,KAAK,CAAC,WAAW,CAAC,CAC1B;AAGD;;;;AAIA,OAAO,MAAMkB,SAAS,gBAAGvB,MAAM,CAACS,MAAM,CAACN,IAAI,cACzCH,MAAM,CAACwB,cAAc,EAAE,eACvBxB,MAAM,CAACK,KAAK,CAAC,WAAW,CAAC,CAC1B;AAGD
|
|
1
|
+
{"version":3,"file":"Event.js","names":["Schema","Position","BigInt","pipe","nonNegativeBigInt","brand","ORIGIN","make","Tag","String","pattern","identifier","tagIdentity","key","length","includes","Error","JSON","stringify","value","ReadLimit","Int","greaterThanOrEqualTo","EventType","nonEmptyString","Metadata","Record","DcbEvent","Struct","type","data","Uint8ArrayFromSelf","tags","Array","uuid","UUID","occurredAt","DateTimeUtc","metadata","SequencedEvent","event","position"],"sources":["../../src/Event.ts"],"sourcesContent":[null],"mappings":"AAAA;;;;;;;;AAQA,SAASA,MAAM,QAAQ,QAAQ;AAE/B;;;;;;;;;AASA,OAAO,MAAMC,QAAQ,gBAAGD,MAAM,CAACE,MAAM,CAACC,IAAI,cACxCH,MAAM,CAACI,iBAAiB,EAAE,eAC1BJ,MAAM,CAACK,KAAK,CAAC,UAAU,CAAC,CACzB;AAGD;AACA,OAAO,MAAMC,MAAM,gBAAaL,QAAQ,CAACM,IAAI,CAAC,EAAE,CAAC;AAEjD;;;;;;AAMA,OAAO,MAAMC,GAAG,gBAAGR,MAAM,CAACS,MAAM,CAACN,IAAI,cACnCH,MAAM,CAACU,OAAO,CAAC,WAAW,EAAE;EAAEC,UAAU,EAAE;AAAK,CAAE,CAAC,eAClDX,MAAM,CAACK,KAAK,CAAC,KAAK,CAAC,CACpB;AA8BD,OAAO,MAAMO,WAAW,GAAIC,GAAW,IAAiB;EACtD,IAAIA,GAAG,CAACC,MAAM,KAAK,CAAC,IAAID,GAAG,CAACE,QAAQ,CAAC,GAAG,CAAC,EAAE;IACzC,MAAM,IAAIC,KAAK,CACb,8DAA8DC,IAAI,CAACC,SAAS,CAACL,GAAG,CAAC,GAAG,CACrF;EACH;EACA,OAAO;IACLA,GAAG;IACHN,IAAI,EAAGY,KAAK,IAAI;MACd,IAAIA,KAAK,CAACL,MAAM,KAAK,CAAC,IAAIK,KAAK,CAACJ,QAAQ,CAAC,GAAG,CAAC,EAAE;QAC7C,MAAM,IAAIC,KAAK,CACb,eAAeC,IAAI,CAACC,SAAS,CAACL,GAAG,CAAC,2DAA2DI,IAAI,CAACC,SAAS,CAACC,KAAK,CAAC,GAAG,CACtH;MACH;MACA,OAAOX,GAAG,CAACD,IAAI,CAAC,GAAGM,GAAG,IAAIM,KAAK,EAAE,CAAC;IACpC;GACD;AACH,CAAC;AAED;;;;;;;;;;AAUA,OAAO,MAAMC,SAAS,gBAAGpB,MAAM,CAACqB,GAAG,CAAClB,IAAI,cACtCH,MAAM,CAACsB,oBAAoB,CAAC,CAAC,CAAC,eAC9BtB,MAAM,CAACK,KAAK,CAAC,WAAW,CAAC,CAC1B;AAGD;;;;AAIA,OAAO,MAAMkB,SAAS,gBAAGvB,MAAM,CAACS,MAAM,CAACN,IAAI,cACzCH,MAAM,CAACwB,cAAc,EAAE,eACvBxB,MAAM,CAACK,KAAK,CAAC,WAAW,CAAC,CAC1B;AAGD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiDA,OAAO,MAAMoB,QAAQ,gBAAGzB,MAAM,CAAC0B,MAAM,CAAC;EACpCb,GAAG,EAAEb,MAAM,CAACS,MAAM;EAClBU,KAAK,EAAEnB,MAAM,CAACS;CACf,CAAC;AAGF;;;;;;;;;;;;;;AAcA,OAAO,MAAMkB,QAAQ,gBAAG3B,MAAM,CAAC4B,MAAM,CAAC;EACpCC,IAAI,EAAEN,SAAS;EACfO,IAAI,EAAE9B,MAAM,CAAC+B,kBAAkB;EAC/BC,IAAI,eAAEhC,MAAM,CAACiC,KAAK,CAACzB,GAAG,CAAC;EACvB0B,IAAI,EAAElC,MAAM,CAACmC,IAAI;EACjBC,UAAU,EAAEpC,MAAM,CAACqC,WAAW;EAC9BC,QAAQ,EAAEb;CACX,CAAC;AAGF;AACA,OAAO,MAAMc,cAAc,gBAAGvC,MAAM,CAAC4B,MAAM,CAAC;EAC1CY,KAAK,EAAEb,QAAQ;EACfc,QAAQ,EAAExC;CACX,CAAC","ignoreList":[]}
|
package/dist/esm/Projection.js
CHANGED
|
@@ -18,15 +18,21 @@ export const AnyProjection = {
|
|
|
18
18
|
*/
|
|
19
19
|
of: projection => projection
|
|
20
20
|
};
|
|
21
|
-
/**
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
21
|
+
/**
|
|
22
|
+
* Merge two queries by OR-ing their items; either wildcard yields a wildcard.
|
|
23
|
+
*
|
|
24
|
+
* Every other key on either envelope is carried into the result. The grammar's
|
|
25
|
+
* envelope has no key but `items`, so anything else is a key the store boundary
|
|
26
|
+
* refuses (`servableQueryFault`); a merge that rebuilt the envelope from `items`
|
|
27
|
+
* alone would drop that key before the boundary saw it, and a slice composed with
|
|
28
|
+
* another would then have its smuggled predicate ignored in silence — the outcome
|
|
29
|
+
* the refusal exists to prevent.
|
|
30
|
+
*/
|
|
31
|
+
const mergeQuery = (left, right) => ({
|
|
32
|
+
...left,
|
|
33
|
+
...right,
|
|
34
|
+
items: left.items.length === 0 || right.items.length === 0 ? WILDCARD.items : [...left.items, ...right.items]
|
|
35
|
+
});
|
|
30
36
|
/**
|
|
31
37
|
* OR-merge a list of queries into one. The empty list is the wildcard.
|
|
32
38
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Projection.js","names":["matchesSequenced","WILDCARD","items","AnyProjection","of","projection","mergeQuery","left","right","length","unionQueries","queries","reduce","acc","q","composeProjections","projections","keys","Object","initialState","fromEntries","map","key","mergedQuery","query","evolve","state","decoded","next","sequenced"],"sources":["../../src/Projection.ts"],"sourcesContent":[null],"mappings":"AA4BA,SAASA,gBAAgB,QAAQ,YAAS;AAE1C;AACA;AACA;AACA;AACA;AACA;AACA,MAAMC,QAAQ,GAAU;EAAEC,KAAK,EAAE;AAAE,CAAE;AAqDrC,OAAO,MAAMC,aAAa,GAAG;EAC3B;;;;;;;EAOAC,EAAE,EAAMC,UAAyB,IAC/BA;CACM;AAaV
|
|
1
|
+
{"version":3,"file":"Projection.js","names":["matchesSequenced","WILDCARD","items","AnyProjection","of","projection","mergeQuery","left","right","length","unionQueries","queries","reduce","acc","q","composeProjections","projections","keys","Object","initialState","fromEntries","map","key","mergedQuery","query","evolve","state","decoded","next","sequenced"],"sources":["../../src/Projection.ts"],"sourcesContent":[null],"mappings":"AA4BA,SAASA,gBAAgB,QAAQ,YAAS;AAE1C;AACA;AACA;AACA;AACA;AACA;AACA,MAAMC,QAAQ,GAAU;EAAEC,KAAK,EAAE;AAAE,CAAE;AAqDrC,OAAO,MAAMC,aAAa,GAAG;EAC3B;;;;;;;EAOAC,EAAE,EAAMC,UAAyB,IAC/BA;CACM;AAaV;;;;;;;;;;AAUA,MAAMC,UAAU,GAAGA,CAACC,IAAW,EAAEC,KAAY,MAAa;EACxD,GAAGD,IAAI;EACP,GAAGC,KAAK;EACRN,KAAK,EACHK,IAAI,CAACL,KAAK,CAACO,MAAM,KAAK,CAAC,IAAID,KAAK,CAACN,KAAK,CAACO,MAAM,KAAK,CAAC,GAC/CR,QAAQ,CAACC,KAAK,GACd,CAAC,GAAGK,IAAI,CAACL,KAAK,EAAE,GAAGM,KAAK,CAACN,KAAK;CACrC,CAAC;AAEF;;;;;;;;;;;;;;;AAeA,OAAO,MAAMQ,YAAY,GAAIC,OAA6B,IACxDA,OAAO,CAACF,MAAM,KAAK,CAAC,GAChBR,QAAQ,GACRU,OAAO,CAACC,MAAM,CAAC,CAACC,GAAG,EAAEC,CAAC,KAAKR,UAAU,CAACO,GAAG,EAAEC,CAAC,CAAC,CAAC;AAEpD;;;;;;;;;;;AAWA,OAAO,MAAMC,kBAAkB,GAC7BC,WAAc,IACmB;EACjC,MAAMC,IAAI,GAAGC,MAAM,CAACD,IAAI,CAACD,WAAW,CAAoC;EAExE,MAAMG,YAAY,GAAGD,MAAM,CAACE,WAAW,CACrCH,IAAI,CAACI,GAAG,CAAEC,GAAG,IAAK,CAACA,GAAG,EAAEN,WAAW,CAACM,GAAG,CAAC,CAACH,YAAY,CAAC,CAAC,CACnC;EAEtB,MAAMI,WAAW,GAAGb,YAAY,CAACO,IAAI,CAACI,GAAG,CAAEC,GAAG,IAAKN,WAAW,CAACM,GAAG,CAAC,CAACE,KAAK,CAAC,CAAC;EAE3E,OAAO;IACLL,YAAY;IACZK,KAAK,EAAED,WAAW;IAClBE,MAAM,EAAEA,CAACC,KAAK,EAAEC,OAAO,KAAI;MACzB,MAAMC,IAAI,GAAG;QAAE,GAAGF;MAAK,CAAuC;MAC9D,KAAK,MAAMJ,GAAG,IAAIL,IAAI,EAAE;QACtB,MAAMZ,UAAU,GAAGW,WAAW,CAACM,GAAG,CAAC;QACnC,IAAI,CAACtB,gBAAgB,CAAC2B,OAAO,CAACE,SAAS,EAAExB,UAAU,CAACmB,KAAK,CAAC,EAAE;UAC1D;QACF;QACAI,IAAI,CAACN,GAAG,CAAC,GAAGjB,UAAU,CAACoB,MAAM,CAACC,KAAK,CAACJ,GAAG,CAAC,EAAEK,OAAO,CAEhD;MACH;MACA,OAAOC,IAAI;IACb;GACD;AACH,CAAC","ignoreList":[]}
|
package/dist/esm/Query.js
CHANGED
|
@@ -68,6 +68,9 @@ export const matchesSequenced = (sequenced, query) => matchesQuery(sequenced.eve
|
|
|
68
68
|
* (`Query.ts` module docs) but which plain-data assembly — e.g. decision-model
|
|
69
69
|
* composition, `Projection.ts:31-36` — can still bypass.
|
|
70
70
|
*
|
|
71
|
+
* A query, or any of its items, carrying a key the grammar does not define is
|
|
72
|
+
* refused before anything else is judged (`unknownKeyFault` below says why).
|
|
73
|
+
*
|
|
71
74
|
* The servable grammar is exactly one of:
|
|
72
75
|
* - the wildcard (`items.length === 0`), which matches every event;
|
|
73
76
|
* - a *single* item (`items.length === 1`), any types/tags, including a
|
|
@@ -93,6 +96,54 @@ export const assertServableQuery = query => {
|
|
|
93
96
|
throw new Error(fault);
|
|
94
97
|
}
|
|
95
98
|
};
|
|
99
|
+
/**
|
|
100
|
+
* The refusal of a key `schemaFields` does not define, or `undefined` when `value`
|
|
101
|
+
* carries none. `where` names the level for the message.
|
|
102
|
+
*
|
|
103
|
+
* ## Why an unknown key is refused rather than ignored
|
|
104
|
+
*
|
|
105
|
+
* A `Query` is plain data, so nothing at runtime stops a caller adding a key the
|
|
106
|
+
* grammar does not have — a `metadata` predicate on an item is the one this repo
|
|
107
|
+
* expects, since metadata is the field an author most plausibly wants to filter on
|
|
108
|
+
* and must not (ADR-0017). Ignored, that key is a predicate the author believes they
|
|
109
|
+
* wrote and no engine honours, and on the append side it is worse: the Postgres
|
|
110
|
+
* guard embeds its match as literal plpgsql text that no type reaches, so a key a
|
|
111
|
+
* read path one day learned to honour would still be dropped by the guard, and the
|
|
112
|
+
* optimistic-concurrency check would escape in silence. Refusing every key the
|
|
113
|
+
* grammar does not define closes that route — a SMUGGLED key — at the one boundary
|
|
114
|
+
* every engine shares, before any engine could disagree. "Every key" means every
|
|
115
|
+
* key `Object.keys` returns: an own, enumerable, string key, which is what a plain
|
|
116
|
+
* object literal or a spread builds. A symbol key, a non-enumerable key or an
|
|
117
|
+
* inherited one is not judged, and no engine reads one either. Core's own query
|
|
118
|
+
* merge (`unionQueries`, `composeProjections`) carries an envelope's unknown key
|
|
119
|
+
* into the merged query rather than dropping it, so composing slices cannot launder
|
|
120
|
+
* a smuggled key past this check.
|
|
121
|
+
*
|
|
122
|
+
* It does not close the neighbouring one, and cannot: a field ADDED to the grammar's
|
|
123
|
+
* schema is a known key from that edit on and passes here, while the plpgsql guard
|
|
124
|
+
* still has to be taught it by hand. That exposure is the Postgres guard's, and its
|
|
125
|
+
* own comment in that engine's DDL says so.
|
|
126
|
+
*
|
|
127
|
+
* The known keys are read off the SCHEMA's own `fields` rather than listed here, so
|
|
128
|
+
* a field added to the grammar is admitted by the same edit that adds it. Only key
|
|
129
|
+
* NAMES are judged: an exact-optional key written as `undefined` is a known key and
|
|
130
|
+
* passes, because which values a key admits is the type's business, not this rule's.
|
|
131
|
+
*/
|
|
132
|
+
const unknownKeyFault = (where, value, schemaFields) => {
|
|
133
|
+
const unknown = Object.keys(value).find(key => !Object.hasOwn(schemaFields, key));
|
|
134
|
+
return unknown === undefined ? undefined : `assertServableQuery: ${where} carries the key ${JSON.stringify(unknown)}, which ` + 'the query grammar does not define; an unknown key would be silently ignored ' + 'by every engine rather than honoured, so it is refused';
|
|
135
|
+
};
|
|
136
|
+
/**
|
|
137
|
+
* The unknown-key half of `servableQueryFault`, on its own: the refusal of a key the
|
|
138
|
+
* grammar does not define on the envelope or on any item, or `undefined`.
|
|
139
|
+
*
|
|
140
|
+
* It is the same rule and not a second statement of it — `servableQueryFault` calls
|
|
141
|
+
* this first. It is exported because ONE caller has to tell the two halves apart:
|
|
142
|
+
* the codec's read ledger refuses an unservable SHAPE on its own error channel, and
|
|
143
|
+
* must not report an unknown key as one. An unknown key is not something a slice's
|
|
144
|
+
* tags can fix, so the ledger leaves it to the store, which refuses it as a defect.
|
|
145
|
+
*/
|
|
146
|
+
export const unknownQueryKeyFault = query => unknownKeyFault('a query', query, Query.fields) ?? query.items.reduce((fault, item) => fault ?? unknownKeyFault('a query item', item, QueryItem.fields), undefined);
|
|
96
147
|
/**
|
|
97
148
|
* The servable grammar as a TOTAL function: the reason `query` cannot be served,
|
|
98
149
|
* or `undefined` when it can.
|
|
@@ -114,6 +165,10 @@ export const assertServableQuery = query => {
|
|
|
114
165
|
* reason), so a fault is one exit route and one return type.
|
|
115
166
|
*/
|
|
116
167
|
export const servableQueryFault = query => {
|
|
168
|
+
const unknownKey = unknownQueryKeyFault(query);
|
|
169
|
+
if (unknownKey !== undefined) {
|
|
170
|
+
return unknownKey;
|
|
171
|
+
}
|
|
117
172
|
const {
|
|
118
173
|
items
|
|
119
174
|
} = query;
|
package/dist/esm/Query.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Query.js","names":["Array","Arr","Schema","EventType","Tag","QueryItem","Struct","types","tags","Query","items","matchesQueryItem","event","item","typeOk","length","includes","type","eventTags","Set","every","tag","has","matchesQuery","query","some","matchesSequenced","sequenced","assertServableQuery","fault","servableQueryFault","undefined","Error","classifyServableQuery","kind","only","isNonEmptyReadonlyArray","
|
|
1
|
+
{"version":3,"file":"Query.js","names":["Array","Arr","Schema","EventType","Tag","QueryItem","Struct","types","tags","Query","items","matchesQueryItem","event","item","typeOk","length","includes","type","eventTags","Set","every","tag","has","matchesQuery","query","some","matchesSequenced","sequenced","assertServableQuery","fault","servableQueryFault","undefined","Error","unknownKeyFault","where","value","schemaFields","unknown","Object","keys","find","key","hasOwn","JSON","stringify","unknownQueryKeyFault","fields","reduce","unknownKey","classifyServableQuery","kind","only","isNonEmptyReadonlyArray","all","or"],"sources":["../../src/Query.ts"],"sourcesContent":[null],"mappings":"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","ignoreList":[]}
|