@raybase/record-mount 0.0.1 → 0.3.3
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/LICENSE +21 -0
- package/README.md +432 -2
- package/dist/body.d.ts +165 -0
- package/dist/body.d.ts.map +1 -0
- package/dist/body.js +538 -0
- package/dist/body.js.map +1 -0
- package/dist/client.d.ts +132 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +376 -0
- package/dist/client.js.map +1 -0
- package/dist/contract.d.ts +261 -0
- package/dist/contract.d.ts.map +1 -0
- package/dist/contract.js +83 -0
- package/dist/contract.js.map +1 -0
- package/dist/errors.d.ts +41 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +81 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/dist/mount.d.ts +219 -0
- package/dist/mount.d.ts.map +1 -0
- package/dist/mount.js +372 -0
- package/dist/mount.js.map +1 -0
- package/dist/testing.d.ts +149 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +764 -0
- package/dist/testing.js.map +1 -0
- package/package.json +34 -8
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The record door's wire contract, declared here.
|
|
3
|
+
*
|
|
4
|
+
* These types are OURS. They are written against the record door's
|
|
5
|
+
* published wire contract, and this package imports nothing from any
|
|
6
|
+
* particular door's implementation — a client that compiled against its
|
|
7
|
+
* service's source would not be a client; it would be a fork of the
|
|
8
|
+
* service. The pin is `RECORD_DOOR_CONTRACT_VERSION` and a door answers it
|
|
9
|
+
* from `version()`, so drift between these declarations and a deployed
|
|
10
|
+
* door is detected at runtime rather than assumed away.
|
|
11
|
+
*
|
|
12
|
+
* Nothing in this module runs. It holds shapes and two constants so both
|
|
13
|
+
* halves of the seam — the client and the test double — compile against
|
|
14
|
+
* one description.
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* The contract version this package speaks. Fail-closed: a client bound to
|
|
18
|
+
* a door serving anything else refuses `contract_mismatch` and nothing
|
|
19
|
+
* proceeds.
|
|
20
|
+
*
|
|
21
|
+
* It moves when the shape a consumer compiles against changes in a way that
|
|
22
|
+
* breaks EITHER direction of the seam — a verb added or removed, an argument
|
|
23
|
+
* or return shape altered, a taxonomy code appearing on a verb that could not
|
|
24
|
+
* raise it. It does not move for an implementation change behind an unchanged
|
|
25
|
+
* shape.
|
|
26
|
+
*
|
|
27
|
+
* **The rule, refined when `RecordDoorVersion.writes` was added (2026-08-30).**
|
|
28
|
+
* An ADDITIVE OPTIONAL field with defined absence semantics does not move the
|
|
29
|
+
* pin, because both directions stay compatible: an old client reading a new
|
|
30
|
+
* door ignores the field, and a new client reading an old door reads absence
|
|
31
|
+
* as "undeclared" and falls back to behavior it can observe. `writes` is
|
|
32
|
+
* exactly that — its absence means "this door predates the declaration", and
|
|
33
|
+
* the client degrades toward `unknown`, never toward a confident answer.
|
|
34
|
+
*
|
|
35
|
+
* Bumping to "2" for it would have been the expensive lie: the pin is
|
|
36
|
+
* fail-closed, so every door currently deployed would refuse every consumer at
|
|
37
|
+
* once, and this package cannot execute that flag day — the doors are deployed
|
|
38
|
+
* by the consumer organization, not by this repository, and nothing here can
|
|
39
|
+
* roll them forward. A version bump a package cannot land is an outage wearing
|
|
40
|
+
* a migration.
|
|
41
|
+
*
|
|
42
|
+
* The pin still moves for anything that breaks either direction: a required
|
|
43
|
+
* field, a changed meaning for an existing field, a removed verb, a widened
|
|
44
|
+
* return a consumer must handle.
|
|
45
|
+
*/
|
|
46
|
+
export declare const RECORD_DOOR_CONTRACT_VERSION = "1";
|
|
47
|
+
/**
|
|
48
|
+
* A record id. The contract's own scheme is `<prefix>-<yyyy-mm-dd>-<slug>`,
|
|
49
|
+
* but the prefix vocabulary belongs to the consumer's schema domain, not to
|
|
50
|
+
* this package — so the type is a string and the *shape* is checked by
|
|
51
|
+
* whatever descriptor the consumer supplies.
|
|
52
|
+
*/
|
|
53
|
+
export type RecordId = string;
|
|
54
|
+
/**
|
|
55
|
+
* The envelope, as the door returns it. `type` is the family the id's
|
|
56
|
+
* prefix names; which families exist is the consumer's business.
|
|
57
|
+
*/
|
|
58
|
+
export type RecordEnvelope = {
|
|
59
|
+
id: RecordId;
|
|
60
|
+
type: string;
|
|
61
|
+
created?: string;
|
|
62
|
+
ts?: string;
|
|
63
|
+
by: string;
|
|
64
|
+
status?: string;
|
|
65
|
+
disposition?: string;
|
|
66
|
+
refs: RecordId[];
|
|
67
|
+
case?: string;
|
|
68
|
+
due?: string;
|
|
69
|
+
kind?: string;
|
|
70
|
+
severity?: string;
|
|
71
|
+
decided?: string;
|
|
72
|
+
"decided-by"?: string;
|
|
73
|
+
body_sha256: string;
|
|
74
|
+
head_seq: number;
|
|
75
|
+
};
|
|
76
|
+
/** One applied event on a record. */
|
|
77
|
+
export type RecordEvent = {
|
|
78
|
+
record: RecordId;
|
|
79
|
+
seq: number;
|
|
80
|
+
kind: "transition" | "note";
|
|
81
|
+
from?: string;
|
|
82
|
+
to?: string;
|
|
83
|
+
by: string;
|
|
84
|
+
ts: string;
|
|
85
|
+
fields?: Record<string, unknown>;
|
|
86
|
+
};
|
|
87
|
+
/**
|
|
88
|
+
* The read model's unit: the envelope plus the two derived columns a list
|
|
89
|
+
* UI would otherwise open a body for. `headline` is never empty;
|
|
90
|
+
* `head_ts` is null for a record with no events.
|
|
91
|
+
*
|
|
92
|
+
* `headline` is UNTRUSTED TEXT. The door strips control characters, ANSI
|
|
93
|
+
* escapes and the Unicode bidi controls before capping the line, and it
|
|
94
|
+
* deliberately does NOT strip markup — escaping is the renderer's act, at
|
|
95
|
+
* render time, unconditionally. This package never renders; it passes the
|
|
96
|
+
* string through, and a consumer that interpolates it into HTML without
|
|
97
|
+
* escaping has the bug.
|
|
98
|
+
*/
|
|
99
|
+
export type RecordRow = RecordEnvelope & {
|
|
100
|
+
headline: string;
|
|
101
|
+
head_ts: string | null;
|
|
102
|
+
};
|
|
103
|
+
/**
|
|
104
|
+
* The closed error taxonomy. A consumer switches on this once.
|
|
105
|
+
*
|
|
106
|
+
* `unavailable` is the only retryable code. `contract_mismatch` is raised
|
|
107
|
+
* by the client and never crosses the wire.
|
|
108
|
+
*/
|
|
109
|
+
export type RecordErrorCode = "invalid_id" | "invalid_record" | "conflict" | "not_found" | "stale" | "illegal_transition" | "invalid_event" | "invalid_query" | "invalid_cursor" | "invalid_prefix" | "forbidden" | "corrupt" | "unavailable" | "no_serializer" | "invalid_binding" | "contract_mismatch";
|
|
110
|
+
/** Every code in the taxonomy, as data — for exhaustiveness checks. */
|
|
111
|
+
export declare const RECORD_ERROR_CODES: readonly ["invalid_id", "invalid_record", "conflict", "not_found", "stale", "illegal_transition", "invalid_event", "invalid_query", "invalid_cursor", "invalid_prefix", "forbidden", "corrupt", "unavailable", "no_serializer", "invalid_binding", "contract_mismatch"];
|
|
112
|
+
/** The one code a caller may sensibly retry. */
|
|
113
|
+
export declare const RECORD_RETRYABLE_ERROR_CODES: readonly RecordErrorCode[];
|
|
114
|
+
export type RecordDoorRefusal = {
|
|
115
|
+
code: RecordErrorCode;
|
|
116
|
+
detail: Record<string, unknown>;
|
|
117
|
+
message: string;
|
|
118
|
+
};
|
|
119
|
+
/** The result envelope every door verb answers with. */
|
|
120
|
+
export type RecordResult<T> = ({
|
|
121
|
+
ok: true;
|
|
122
|
+
} & T) | {
|
|
123
|
+
ok: false;
|
|
124
|
+
error: RecordDoorRefusal;
|
|
125
|
+
};
|
|
126
|
+
/** The exact-match filter vocabulary. It grows by amending the contract. */
|
|
127
|
+
export declare const RECORD_EXACT_FILTERS: readonly ["family", "status", "disposition", "by", "case", "kind", "severity"];
|
|
128
|
+
/** The two filters the read model's `list` widens to an explicit OR-set. */
|
|
129
|
+
export declare const RECORD_SET_FILTERS: readonly ["status", "disposition"];
|
|
130
|
+
export type RecordRange = {
|
|
131
|
+
gte?: string;
|
|
132
|
+
lte?: string;
|
|
133
|
+
};
|
|
134
|
+
/** The substrate's query: exact-match filters, two ranges, keyset paging. */
|
|
135
|
+
export type RecordQuery = {
|
|
136
|
+
family?: string;
|
|
137
|
+
status?: string;
|
|
138
|
+
disposition?: string;
|
|
139
|
+
by?: string;
|
|
140
|
+
case?: string;
|
|
141
|
+
kind?: string;
|
|
142
|
+
severity?: string;
|
|
143
|
+
ts?: RecordRange;
|
|
144
|
+
due?: RecordRange;
|
|
145
|
+
order?: "asc" | "desc";
|
|
146
|
+
limit?: number;
|
|
147
|
+
cursor?: string;
|
|
148
|
+
};
|
|
149
|
+
/**
|
|
150
|
+
* The read model's query: the substrate's, with `status` and `disposition`
|
|
151
|
+
* accepting an OR-set. Nothing else widens — an array on any other filter
|
|
152
|
+
* refuses `invalid_query`, and so does an empty set.
|
|
153
|
+
*/
|
|
154
|
+
export type RecordListQuery = Omit<RecordQuery, "status" | "disposition"> & {
|
|
155
|
+
status?: string | string[];
|
|
156
|
+
disposition?: string | string[];
|
|
157
|
+
};
|
|
158
|
+
/** What `count` may group by: the two lifecycle columns, nothing else. */
|
|
159
|
+
export declare const RECORD_COUNT_GROUPS: readonly ["status", "disposition"];
|
|
160
|
+
export type RecordCountGroup = (typeof RECORD_COUNT_GROUPS)[number];
|
|
161
|
+
/**
|
|
162
|
+
* What `version()` answers: the door's identity, plus the one capability a
|
|
163
|
+
* client cannot otherwise observe across an RPC seam.
|
|
164
|
+
*
|
|
165
|
+
* `writes` is the entrypoint's own declaration: `true` for a write door (it
|
|
166
|
+
* carries `append` and `transition`), `false` for a read door (it does not).
|
|
167
|
+
* **Absent means undeclared** — a door built before this field existed — and a
|
|
168
|
+
* client reading absence must degrade toward `unknown`, never toward `true`.
|
|
169
|
+
*
|
|
170
|
+
* It exists because property presence is not observable on a Cloudflare RPC
|
|
171
|
+
* service-binding stub: the stub answers EVERY property access with a
|
|
172
|
+
* callable, so `typeof stub.append === "function"` is true against a read
|
|
173
|
+
* door. The runtime still refuses the missing method when the call is made —
|
|
174
|
+
* the wall holds — but the refusal arrives as a bare `TypeError` rather than
|
|
175
|
+
* as this package's typed one, and no mount-time check can fire. A declared
|
|
176
|
+
* capability is the only thing that crosses the seam as data.
|
|
177
|
+
*/
|
|
178
|
+
export type RecordDoorVersion = {
|
|
179
|
+
deployment: string;
|
|
180
|
+
contract: string;
|
|
181
|
+
writes?: boolean;
|
|
182
|
+
};
|
|
183
|
+
export type RecordGetResult = {
|
|
184
|
+
envelope: RecordEnvelope;
|
|
185
|
+
body: string;
|
|
186
|
+
events: RecordEvent[];
|
|
187
|
+
};
|
|
188
|
+
export type RecordQueryResult = {
|
|
189
|
+
envelopes: RecordEnvelope[];
|
|
190
|
+
cursor?: string;
|
|
191
|
+
};
|
|
192
|
+
export type RecordAppendResult = {
|
|
193
|
+
id: RecordId;
|
|
194
|
+
created: boolean;
|
|
195
|
+
};
|
|
196
|
+
export type RecordTransitionResult = {
|
|
197
|
+
seq: number;
|
|
198
|
+
};
|
|
199
|
+
export type RecordMaterializeEntry = {
|
|
200
|
+
path: string;
|
|
201
|
+
bytes: Uint8Array;
|
|
202
|
+
};
|
|
203
|
+
export type RecordMaterializePage = {
|
|
204
|
+
entries: RecordMaterializeEntry[];
|
|
205
|
+
cursor?: string;
|
|
206
|
+
};
|
|
207
|
+
export type RecordListResult = {
|
|
208
|
+
rows: RecordRow[];
|
|
209
|
+
cursor?: string;
|
|
210
|
+
};
|
|
211
|
+
export type RecordCountResult = {
|
|
212
|
+
groups: Array<{
|
|
213
|
+
value: string | null;
|
|
214
|
+
count: number;
|
|
215
|
+
}>;
|
|
216
|
+
total: number;
|
|
217
|
+
};
|
|
218
|
+
export type RecordReverseRefsResult = {
|
|
219
|
+
rows: RecordRow[];
|
|
220
|
+
};
|
|
221
|
+
/** The event a `transition` carries. */
|
|
222
|
+
export type RecordTransitionEvent = {
|
|
223
|
+
by: string;
|
|
224
|
+
ts?: string;
|
|
225
|
+
fields?: Record<string, unknown>;
|
|
226
|
+
};
|
|
227
|
+
/**
|
|
228
|
+
* The bound entrypoint, structurally — what `env.<BINDING>` is on a
|
|
229
|
+
* consumer Worker.
|
|
230
|
+
*
|
|
231
|
+
* `append` and `transition` are optional because a READ door genuinely
|
|
232
|
+
* lacks them: the contract makes the read door refuse writes STRUCTURALLY
|
|
233
|
+
* (the methods are absent, and the runtime answers its own TypeError
|
|
234
|
+
* before any policy code runs). Which door a Worker holds is deploy
|
|
235
|
+
* configuration, not something code can change.
|
|
236
|
+
*
|
|
237
|
+
* **Absence is real but not visible across an RPC service binding.** A
|
|
238
|
+
* Cloudflare RPC stub answers every property access with a callable, so this
|
|
239
|
+
* type's optionality describes the door, not what a client can see: `typeof
|
|
240
|
+
* stub.append === "function"` holds against a read door and tells the caller
|
|
241
|
+
* nothing. The wall is the call itself, which the runtime refuses. What
|
|
242
|
+
* crosses as data is `RecordDoorVersion.writes`.
|
|
243
|
+
*/
|
|
244
|
+
export type RecordDoorStub = {
|
|
245
|
+
version(): Promise<RecordResult<RecordDoorVersion>>;
|
|
246
|
+
get(id: RecordId): Promise<RecordResult<RecordGetResult>>;
|
|
247
|
+
query(q: RecordQuery): Promise<RecordResult<RecordQueryResult>>;
|
|
248
|
+
materialize(prefix: string, cursor?: string): Promise<RecordResult<RecordMaterializePage>>;
|
|
249
|
+
list(q: RecordListQuery): Promise<RecordResult<RecordListResult>>;
|
|
250
|
+
count(args: {
|
|
251
|
+
family?: string;
|
|
252
|
+
groupBy: RecordCountGroup;
|
|
253
|
+
}): Promise<RecordResult<RecordCountResult>>;
|
|
254
|
+
reverseRefs(id: RecordId, opts?: {
|
|
255
|
+
limit?: number;
|
|
256
|
+
order?: "asc" | "desc";
|
|
257
|
+
}): Promise<RecordResult<RecordReverseRefsResult>>;
|
|
258
|
+
append?(body: string | Uint8Array): Promise<RecordResult<RecordAppendResult>>;
|
|
259
|
+
transition?(id: RecordId, expected: string, next: string, event: RecordTransitionEvent): Promise<RecordResult<RecordTransitionResult>>;
|
|
260
|
+
};
|
|
261
|
+
//# sourceMappingURL=contract.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"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"}
|
package/dist/contract.js
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The record door's wire contract, declared here.
|
|
3
|
+
*
|
|
4
|
+
* These types are OURS. They are written against the record door's
|
|
5
|
+
* published wire contract, and this package imports nothing from any
|
|
6
|
+
* particular door's implementation — a client that compiled against its
|
|
7
|
+
* service's source would not be a client; it would be a fork of the
|
|
8
|
+
* service. The pin is `RECORD_DOOR_CONTRACT_VERSION` and a door answers it
|
|
9
|
+
* from `version()`, so drift between these declarations and a deployed
|
|
10
|
+
* door is detected at runtime rather than assumed away.
|
|
11
|
+
*
|
|
12
|
+
* Nothing in this module runs. It holds shapes and two constants so both
|
|
13
|
+
* halves of the seam — the client and the test double — compile against
|
|
14
|
+
* one description.
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* The contract version this package speaks. Fail-closed: a client bound to
|
|
18
|
+
* a door serving anything else refuses `contract_mismatch` and nothing
|
|
19
|
+
* proceeds.
|
|
20
|
+
*
|
|
21
|
+
* It moves when the shape a consumer compiles against changes in a way that
|
|
22
|
+
* breaks EITHER direction of the seam — a verb added or removed, an argument
|
|
23
|
+
* or return shape altered, a taxonomy code appearing on a verb that could not
|
|
24
|
+
* raise it. It does not move for an implementation change behind an unchanged
|
|
25
|
+
* shape.
|
|
26
|
+
*
|
|
27
|
+
* **The rule, refined when `RecordDoorVersion.writes` was added (2026-08-30).**
|
|
28
|
+
* An ADDITIVE OPTIONAL field with defined absence semantics does not move the
|
|
29
|
+
* pin, because both directions stay compatible: an old client reading a new
|
|
30
|
+
* door ignores the field, and a new client reading an old door reads absence
|
|
31
|
+
* as "undeclared" and falls back to behavior it can observe. `writes` is
|
|
32
|
+
* exactly that — its absence means "this door predates the declaration", and
|
|
33
|
+
* the client degrades toward `unknown`, never toward a confident answer.
|
|
34
|
+
*
|
|
35
|
+
* Bumping to "2" for it would have been the expensive lie: the pin is
|
|
36
|
+
* fail-closed, so every door currently deployed would refuse every consumer at
|
|
37
|
+
* once, and this package cannot execute that flag day — the doors are deployed
|
|
38
|
+
* by the consumer organization, not by this repository, and nothing here can
|
|
39
|
+
* roll them forward. A version bump a package cannot land is an outage wearing
|
|
40
|
+
* a migration.
|
|
41
|
+
*
|
|
42
|
+
* The pin still moves for anything that breaks either direction: a required
|
|
43
|
+
* field, a changed meaning for an existing field, a removed verb, a widened
|
|
44
|
+
* return a consumer must handle.
|
|
45
|
+
*/
|
|
46
|
+
export const RECORD_DOOR_CONTRACT_VERSION = "1";
|
|
47
|
+
/** Every code in the taxonomy, as data — for exhaustiveness checks. */
|
|
48
|
+
export const RECORD_ERROR_CODES = [
|
|
49
|
+
"invalid_id",
|
|
50
|
+
"invalid_record",
|
|
51
|
+
"conflict",
|
|
52
|
+
"not_found",
|
|
53
|
+
"stale",
|
|
54
|
+
"illegal_transition",
|
|
55
|
+
"invalid_event",
|
|
56
|
+
"invalid_query",
|
|
57
|
+
"invalid_cursor",
|
|
58
|
+
"invalid_prefix",
|
|
59
|
+
"forbidden",
|
|
60
|
+
"corrupt",
|
|
61
|
+
"unavailable",
|
|
62
|
+
"no_serializer",
|
|
63
|
+
"invalid_binding",
|
|
64
|
+
"contract_mismatch"
|
|
65
|
+
];
|
|
66
|
+
/** The one code a caller may sensibly retry. */
|
|
67
|
+
export const RECORD_RETRYABLE_ERROR_CODES = ["unavailable"];
|
|
68
|
+
// --- Queries ---------------------------------------------------------------
|
|
69
|
+
/** The exact-match filter vocabulary. It grows by amending the contract. */
|
|
70
|
+
export const RECORD_EXACT_FILTERS = [
|
|
71
|
+
"family",
|
|
72
|
+
"status",
|
|
73
|
+
"disposition",
|
|
74
|
+
"by",
|
|
75
|
+
"case",
|
|
76
|
+
"kind",
|
|
77
|
+
"severity"
|
|
78
|
+
];
|
|
79
|
+
/** The two filters the read model's `list` widens to an explicit OR-set. */
|
|
80
|
+
export const RECORD_SET_FILTERS = ["status", "disposition"];
|
|
81
|
+
/** What `count` may group by: the two lifecycle columns, nothing else. */
|
|
82
|
+
export const RECORD_COUNT_GROUPS = ["status", "disposition"];
|
|
83
|
+
//# sourceMappingURL=contract.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contract.js","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,MAAM,CAAC,MAAM,4BAA4B,GAAG,GAAG,CAAC;AAsFhD,uEAAuE;AACvE,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,YAAY;IACZ,gBAAgB;IAChB,UAAU;IACV,WAAW;IACX,OAAO;IACP,oBAAoB;IACpB,eAAe;IACf,eAAe;IACf,gBAAgB;IAChB,gBAAgB;IAChB,WAAW;IACX,SAAS;IACT,aAAa;IACb,eAAe;IACf,iBAAiB;IACjB,mBAAmB;CAC0B,CAAC;AAEhD,gDAAgD;AAChD,MAAM,CAAC,MAAM,4BAA4B,GAA+B,CAAC,aAAa,CAAC,CAAC;AAWxF,8EAA8E;AAE9E,4EAA4E;AAC5E,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,QAAQ;IACR,QAAQ;IACR,aAAa;IACb,IAAI;IACJ,MAAM;IACN,MAAM;IACN,UAAU;CACF,CAAC;AAEX,4EAA4E;AAC5E,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,QAAQ,EAAE,aAAa,CAAU,CAAC;AA8BrE,0EAA0E;AAC1E,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,QAAQ,EAAE,aAAa,CAAU,CAAC"}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The closed error class a consumer switches on, and the envelope
|
|
3
|
+
* unwrapper that produces it.
|
|
4
|
+
*
|
|
5
|
+
* Rehydration is real work, not ceremony. A class instance crossing a
|
|
6
|
+
* service binding arrives with its constructor gone — `instanceof` on the
|
|
7
|
+
* far side is false for anything the door could have thrown — so the door
|
|
8
|
+
* answers a result ENVELOPE and the client turns `{ok:false, error}` back
|
|
9
|
+
* into a typed throw on this side of the seam. Data crosses; types do not.
|
|
10
|
+
*/
|
|
11
|
+
import type { RecordErrorCode, RecordResult } from "./contract.js";
|
|
12
|
+
/**
|
|
13
|
+
* A refusal from the record door, typed. `code` is the closed taxonomy;
|
|
14
|
+
* `detail` is the per-code payload the contract pins.
|
|
15
|
+
*
|
|
16
|
+
* `detail` is operator-facing and may name ids, actors and grants. A mount
|
|
17
|
+
* that echoes a whole `detail` into an end-user response is disclosing
|
|
18
|
+
* more than it means to — `code` and `message` are the caller-facing half.
|
|
19
|
+
*/
|
|
20
|
+
export declare class RecordDoorError extends Error {
|
|
21
|
+
readonly code: RecordErrorCode;
|
|
22
|
+
readonly detail: Record<string, unknown>;
|
|
23
|
+
constructor(code: RecordErrorCode, detail: Record<string, unknown>, message?: string);
|
|
24
|
+
/** Whether a caller may sensibly try this call again. */
|
|
25
|
+
get retryable(): boolean;
|
|
26
|
+
}
|
|
27
|
+
/** Typed constructor, so a code and its message are built in one place. */
|
|
28
|
+
export declare function recordDoorError(code: RecordErrorCode, detail: Record<string, unknown>, message?: string): RecordDoorError;
|
|
29
|
+
/** Whether an unknown value is one of this package's typed refusals. */
|
|
30
|
+
export declare function isRecordDoorError(value: unknown): value is RecordDoorError;
|
|
31
|
+
/**
|
|
32
|
+
* The envelope, unwrapped. `{ok:true, …}` becomes the payload;
|
|
33
|
+
* `{ok:false, …}` becomes a throw of the same code, detail and message the
|
|
34
|
+
* door refused with.
|
|
35
|
+
*
|
|
36
|
+
* A reply that is neither is the seam itself misbehaving. It refuses as
|
|
37
|
+
* `unavailable` rather than being coerced into a success — a malformed
|
|
38
|
+
* reply read as data is how a store outage becomes silent corruption.
|
|
39
|
+
*/
|
|
40
|
+
export declare function rehydrateRecordResult<T>(reply: RecordResult<T>): T;
|
|
41
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,KAAK,EAAqB,eAAe,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAItF;;;;;;;GAOG;AACH,qBAAa,eAAgB,SAAQ,KAAK;IACxC,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC;IAC/B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;gBAE7B,IAAI,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,EAAE,MAAM;IAOpF,yDAAyD;IACzD,IAAI,SAAS,IAAI,OAAO,CAEvB;CACF;AAED,2EAA2E;AAC3E,wBAAgB,eAAe,CAC7B,IAAI,EAAE,eAAe,EACrB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,OAAO,CAAC,EAAE,MAAM,GACf,eAAe,CAEjB;AAED,wEAAwE;AACxE,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,eAAe,CAE1E;AAED;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,CAAC,CA4BlE"}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The closed error class a consumer switches on, and the envelope
|
|
3
|
+
* unwrapper that produces it.
|
|
4
|
+
*
|
|
5
|
+
* Rehydration is real work, not ceremony. A class instance crossing a
|
|
6
|
+
* service binding arrives with its constructor gone — `instanceof` on the
|
|
7
|
+
* far side is false for anything the door could have thrown — so the door
|
|
8
|
+
* answers a result ENVELOPE and the client turns `{ok:false, error}` back
|
|
9
|
+
* into a typed throw on this side of the seam. Data crosses; types do not.
|
|
10
|
+
*/
|
|
11
|
+
import { RECORD_ERROR_CODES, RECORD_RETRYABLE_ERROR_CODES } from "./contract.js";
|
|
12
|
+
const KNOWN_CODES = new Set(RECORD_ERROR_CODES);
|
|
13
|
+
/**
|
|
14
|
+
* A refusal from the record door, typed. `code` is the closed taxonomy;
|
|
15
|
+
* `detail` is the per-code payload the contract pins.
|
|
16
|
+
*
|
|
17
|
+
* `detail` is operator-facing and may name ids, actors and grants. A mount
|
|
18
|
+
* that echoes a whole `detail` into an end-user response is disclosing
|
|
19
|
+
* more than it means to — `code` and `message` are the caller-facing half.
|
|
20
|
+
*/
|
|
21
|
+
export class RecordDoorError extends Error {
|
|
22
|
+
code;
|
|
23
|
+
detail;
|
|
24
|
+
constructor(code, detail, message) {
|
|
25
|
+
super(message ?? `${code}: ${JSON.stringify(detail)}`);
|
|
26
|
+
this.name = "RecordDoorError";
|
|
27
|
+
this.code = code;
|
|
28
|
+
this.detail = detail;
|
|
29
|
+
}
|
|
30
|
+
/** Whether a caller may sensibly try this call again. */
|
|
31
|
+
get retryable() {
|
|
32
|
+
return RECORD_RETRYABLE_ERROR_CODES.includes(this.code);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
/** Typed constructor, so a code and its message are built in one place. */
|
|
36
|
+
export function recordDoorError(code, detail, message) {
|
|
37
|
+
return new RecordDoorError(code, detail, message);
|
|
38
|
+
}
|
|
39
|
+
/** Whether an unknown value is one of this package's typed refusals. */
|
|
40
|
+
export function isRecordDoorError(value) {
|
|
41
|
+
return value instanceof RecordDoorError;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* The envelope, unwrapped. `{ok:true, …}` becomes the payload;
|
|
45
|
+
* `{ok:false, …}` becomes a throw of the same code, detail and message the
|
|
46
|
+
* door refused with.
|
|
47
|
+
*
|
|
48
|
+
* A reply that is neither is the seam itself misbehaving. It refuses as
|
|
49
|
+
* `unavailable` rather than being coerced into a success — a malformed
|
|
50
|
+
* reply read as data is how a store outage becomes silent corruption.
|
|
51
|
+
*/
|
|
52
|
+
export function rehydrateRecordResult(reply) {
|
|
53
|
+
if (reply !== null && typeof reply === "object" && reply.ok === true) {
|
|
54
|
+
const { ok: _ok, ...payload } = reply;
|
|
55
|
+
return payload;
|
|
56
|
+
}
|
|
57
|
+
const error = reply?.error;
|
|
58
|
+
if (error === undefined || error === null || typeof error.code !== "string") {
|
|
59
|
+
throw recordDoorError("unavailable", {
|
|
60
|
+
cause: `the record door returned a reply that is neither ok nor a typed refusal: ${safeJson(reply)}`
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
if (!KNOWN_CODES.has(error.code)) {
|
|
64
|
+
// A code outside the closed set means the door is speaking a taxonomy
|
|
65
|
+
// this build does not know. That is a contract problem wearing an
|
|
66
|
+
// error, and guessing at it would be a fallback (the contract pin is
|
|
67
|
+
// the migration). Refuse loudly, keeping the unknown code visible.
|
|
68
|
+
throw recordDoorError("contract_mismatch", { expected: [...KNOWN_CODES].join("|"), served: error.code }, `the record door refused with '${error.code}', which is not in this build's error taxonomy — ` +
|
|
69
|
+
"the bound door speaks a contract this client does not");
|
|
70
|
+
}
|
|
71
|
+
throw new RecordDoorError(error.code, (error.detail ?? {}), typeof error.message === "string" ? error.message : error.code);
|
|
72
|
+
}
|
|
73
|
+
function safeJson(value) {
|
|
74
|
+
try {
|
|
75
|
+
return JSON.stringify(value) ?? String(value);
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
return String(value);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,kBAAkB,EAAE,4BAA4B,EAAE,MAAM,eAAe,CAAC;AAGjF,MAAM,WAAW,GAAG,IAAI,GAAG,CAAS,kBAAkB,CAAC,CAAC;AAExD;;;;;;;GAOG;AACH,MAAM,OAAO,eAAgB,SAAQ,KAAK;IAC/B,IAAI,CAAkB;IACtB,MAAM,CAA0B;IAEzC,YAAY,IAAqB,EAAE,MAA+B,EAAE,OAAgB;QAClF,KAAK,CAAC,OAAO,IAAI,GAAG,IAAI,KAAK,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACvD,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;QAC9B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAED,yDAAyD;IACzD,IAAI,SAAS;QACX,OAAO,4BAA4B,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1D,CAAC;CACF;AAED,2EAA2E;AAC3E,MAAM,UAAU,eAAe,CAC7B,IAAqB,EACrB,MAA+B,EAC/B,OAAgB;IAEhB,OAAO,IAAI,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;AACpD,CAAC;AAED,wEAAwE;AACxE,MAAM,UAAU,iBAAiB,CAAC,KAAc;IAC9C,OAAO,KAAK,YAAY,eAAe,CAAC;AAC1C,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,qBAAqB,CAAI,KAAsB;IAC7D,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAK,KAA0B,CAAC,EAAE,KAAK,IAAI,EAAE,CAAC;QAC3F,MAAM,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,OAAO,EAAE,GAAG,KAA+C,CAAC;QAChF,OAAO,OAAY,CAAC;IACtB,CAAC;IACD,MAAM,KAAK,GAAI,KAAmE,EAAE,KAAK,CAAC;IAC1F,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC5E,MAAM,eAAe,CAAC,aAAa,EAAE;YACnC,KAAK,EAAE,4EAA4E,QAAQ,CAAC,KAAK,CAAC,EAAE;SACrG,CAAC,CAAC;IACL,CAAC;IACD,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACjC,sEAAsE;QACtE,kEAAkE;QAClE,qEAAqE;QACrE,mEAAmE;QACnE,MAAM,eAAe,CACnB,mBAAmB,EACnB,EAAE,QAAQ,EAAE,CAAC,GAAG,WAAW,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,IAAI,EAAE,EAC5D,iCAAiC,KAAK,CAAC,IAAI,mDAAmD;YAC5F,uDAAuD,CAC1D,CAAC;IACJ,CAAC;IACD,MAAM,IAAI,eAAe,CACvB,KAAK,CAAC,IAAuB,EAC7B,CAAC,KAAK,CAAC,MAAM,IAAI,EAAE,CAA4B,EAC/C,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAC/D,CAAC;AACJ,CAAC;AAED,SAAS,QAAQ,CAAC,KAAc;IAC9B,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC;IAChD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;IACvB,CAAC;AACH,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@raybase/record-mount` — mount an external append-only record layer into
|
|
3
|
+
* a Raybase app.
|
|
4
|
+
*
|
|
5
|
+
* Three things, in the order an app meets them: `openRecordDoor` turns a
|
|
6
|
+
* declared service binding into a typed client pinned to the wire contract;
|
|
7
|
+
* `defineRecordMount` puts the app's two authorization gates in front of it;
|
|
8
|
+
* `createRecordBodyComposer` builds the canonical bytes a filing needs.
|
|
9
|
+
*
|
|
10
|
+
* The in-memory door double lives at `@raybase/record-mount/testing` — a
|
|
11
|
+
* separate entry point so a production bundle never carries it.
|
|
12
|
+
*/
|
|
13
|
+
export { RECORD_DOOR_CONTRACT_VERSION, RECORD_COUNT_GROUPS, RECORD_ERROR_CODES, RECORD_EXACT_FILTERS, RECORD_RETRYABLE_ERROR_CODES, RECORD_SET_FILTERS } from "./contract.js";
|
|
14
|
+
export type { RecordAppendResult, RecordCountGroup, RecordCountResult, RecordDoorRefusal, RecordDoorStub, RecordDoorVersion, RecordEnvelope, RecordErrorCode, RecordEvent, RecordGetResult, RecordId, RecordListQuery, RecordListResult, RecordMaterializeEntry, RecordMaterializePage, RecordQuery, RecordQueryResult, RecordRange, RecordResult, RecordReverseRefsResult, RecordRow, RecordTransitionEvent, RecordTransitionResult } from "./contract.js";
|
|
15
|
+
export { RecordDoorError, isRecordDoorError, recordDoorError, rehydrateRecordResult } from "./errors.js";
|
|
16
|
+
export { openRecordDoor } from "./client.js";
|
|
17
|
+
export type { OpenRecordDoorOptions, RecordDoorClient } from "./client.js";
|
|
18
|
+
export { RECORD_ID_PATTERN, createRecordBodyComposer, mintRecordId, parseRecordFrontmatter, recordProseOf } from "./body.js";
|
|
19
|
+
export type { RecordBodyComposer, RecordFamilyDescriptor, RecordFieldDescriptor, RecordFieldRender } from "./body.js";
|
|
20
|
+
export { allowAnyAuthenticated, defineRecordMount, denyAllRecords } from "./mount.js";
|
|
21
|
+
export type { DefineRecordMountOptions, RecordMount, RecordMountAuth, RecordReadPolicy, RecordReadVerb, RecordUnfilteredRead, RecordViewer } from "./mount.js";
|
|
22
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EACL,4BAA4B,EAC5B,mBAAmB,EACnB,kBAAkB,EAClB,oBAAoB,EACpB,4BAA4B,EAC5B,kBAAkB,EACnB,MAAM,eAAe,CAAC;AACvB,YAAY,EACV,kBAAkB,EAClB,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,EACjB,cAAc,EACd,iBAAiB,EACjB,cAAc,EACd,eAAe,EACf,WAAW,EACX,eAAe,EACf,QAAQ,EACR,eAAe,EACf,gBAAgB,EAChB,sBAAsB,EACtB,qBAAqB,EACrB,WAAW,EACX,iBAAiB,EACjB,WAAW,EACX,YAAY,EACZ,uBAAuB,EACvB,SAAS,EACT,qBAAqB,EACrB,sBAAsB,EACvB,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,eAAe,EACf,iBAAiB,EACjB,eAAe,EACf,qBAAqB,EACtB,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,YAAY,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE3E,OAAO,EACL,iBAAiB,EACjB,wBAAwB,EACxB,YAAY,EACZ,sBAAsB,EACtB,aAAa,EACd,MAAM,WAAW,CAAC;AACnB,YAAY,EACV,kBAAkB,EAClB,sBAAsB,EACtB,qBAAqB,EACrB,iBAAiB,EAClB,MAAM,WAAW,CAAC;AAEnB,OAAO,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACtF,YAAY,EACV,wBAAwB,EACxB,WAAW,EACX,eAAe,EACf,gBAAgB,EAChB,cAAc,EACd,oBAAoB,EACpB,YAAY,EACb,MAAM,YAAY,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@raybase/record-mount` — mount an external append-only record layer into
|
|
3
|
+
* a Raybase app.
|
|
4
|
+
*
|
|
5
|
+
* Three things, in the order an app meets them: `openRecordDoor` turns a
|
|
6
|
+
* declared service binding into a typed client pinned to the wire contract;
|
|
7
|
+
* `defineRecordMount` puts the app's two authorization gates in front of it;
|
|
8
|
+
* `createRecordBodyComposer` builds the canonical bytes a filing needs.
|
|
9
|
+
*
|
|
10
|
+
* The in-memory door double lives at `@raybase/record-mount/testing` — a
|
|
11
|
+
* separate entry point so a production bundle never carries it.
|
|
12
|
+
*/
|
|
13
|
+
export { RECORD_DOOR_CONTRACT_VERSION, RECORD_COUNT_GROUPS, RECORD_ERROR_CODES, RECORD_EXACT_FILTERS, RECORD_RETRYABLE_ERROR_CODES, RECORD_SET_FILTERS } from "./contract.js";
|
|
14
|
+
export { RecordDoorError, isRecordDoorError, recordDoorError, rehydrateRecordResult } from "./errors.js";
|
|
15
|
+
export { openRecordDoor } from "./client.js";
|
|
16
|
+
export { RECORD_ID_PATTERN, createRecordBodyComposer, mintRecordId, parseRecordFrontmatter, recordProseOf } from "./body.js";
|
|
17
|
+
export { allowAnyAuthenticated, defineRecordMount, denyAllRecords } from "./mount.js";
|
|
18
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EACL,4BAA4B,EAC5B,mBAAmB,EACnB,kBAAkB,EAClB,oBAAoB,EACpB,4BAA4B,EAC5B,kBAAkB,EACnB,MAAM,eAAe,CAAC;AA2BvB,OAAO,EACL,eAAe,EACf,iBAAiB,EACjB,eAAe,EACf,qBAAqB,EACtB,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAG7C,OAAO,EACL,iBAAiB,EACjB,wBAAwB,EACxB,YAAY,EACZ,sBAAsB,EACtB,aAAa,EACd,MAAM,WAAW,CAAC;AAQnB,OAAO,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC"}
|