snapback2 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +127 -0
- package/bin/snapback2.mjs +36 -0
- package/dist/api.d.ts +20 -0
- package/dist/assets.d.ts +34 -0
- package/dist/client-assets.d.ts +26 -0
- package/dist/client-offline.d.ts +94 -0
- package/dist/client-outbox.d.ts +58 -0
- package/dist/client-upload.d.ts +41 -0
- package/dist/client-wire.d.ts +41 -0
- package/dist/client.d.ts +12 -0
- package/dist/client.mjs +5 -0
- package/dist/client.mjs.map +7 -0
- package/dist/compiler-core.mjs +60 -0
- package/dist/compiler-core.mjs.map +7 -0
- package/dist/compiler-lib.d.ts +71 -0
- package/dist/compiler.mjs +5 -0
- package/dist/compiler.mjs.map +7 -0
- package/dist/drain.d.ts +33 -0
- package/dist/expo/files.d.ts +3 -0
- package/dist/expo/index.d.ts +16 -0
- package/dist/expo/token-store.d.ts +7 -0
- package/dist/expo/witness.d.ts +28 -0
- package/dist/expo/witness.mjs +2 -0
- package/dist/expo/witness.mjs.map +7 -0
- package/dist/expo.d.ts +4 -0
- package/dist/expo.mjs +9 -0
- package/dist/expo.mjs.map +7 -0
- package/dist/guide/auth.md +89 -0
- package/dist/guide/effects.md +52 -0
- package/dist/guide/families.json +446 -0
- package/dist/guide/grammar.md +52 -0
- package/dist/guide/live-query.md +27 -0
- package/dist/guide/offline.md +75 -0
- package/dist/guide/personas.md +15 -0
- package/dist/guide/quarry.md +297 -0
- package/dist/guide/testing.md +57 -0
- package/dist/index.d.ts +362 -0
- package/dist/index.mjs +2 -0
- package/dist/index.mjs.map +7 -0
- package/dist/offline-protocol.d.ts +180 -0
- package/dist/offline-schema.d.ts +1 -0
- package/dist/offline.d.ts +177 -0
- package/dist/react-core.d.ts +91 -0
- package/dist/react-core.mjs +2 -0
- package/dist/react-core.mjs.map +7 -0
- package/dist/react-native/components.d.ts +23 -0
- package/dist/react-native/files.d.ts +43 -0
- package/dist/react-native/source.d.ts +16 -0
- package/dist/react-native.d.ts +4 -0
- package/dist/react-native.mjs +2 -0
- package/dist/react-native.mjs.map +7 -0
- package/dist/react.d.ts +19 -0
- package/dist/react.mjs +2 -0
- package/dist/react.mjs.map +7 -0
- package/dist/sqlite-test.mjs +1720 -0
- package/dist/sqlite-test.mjs.map +7 -0
- package/dist/sse.d.ts +44 -0
- package/dist/store/byte-cache.d.ts +162 -0
- package/dist/store/canonical.d.ts +2 -0
- package/dist/store/indexeddb.d.ts +23 -0
- package/dist/store/locks.d.ts +11 -0
- package/dist/store/outbox.d.ts +113 -0
- package/dist/store/overlay-retirement.d.ts +17 -0
- package/dist/store/projection.d.ts +11 -0
- package/dist/store/range-store.d.ts +388 -0
- package/dist/store/sqlite-driver.conformance.d.ts +7 -0
- package/dist/store/sqlite-driver.d.ts +16 -0
- package/dist/store/sqlite-expo.d.ts +3 -0
- package/dist/store/sqlite.d.ts +31 -0
- package/dist/templates/chat/expo/App.tsx +29 -0
- package/dist/templates/chat/expo/app.json +11 -0
- package/dist/templates/chat/expo/index.js +3 -0
- package/dist/templates/chat/expo/shared/log.js +92 -0
- package/dist/templates/chat/expo/shared/log.ts +130 -0
- package/dist/templates/chat/expo/shared/offline.js +8 -0
- package/dist/templates/chat/expo/shared/offline.ts +9 -0
- package/dist/templates/chat/expo/src/Chat.tsx +23 -0
- package/dist/templates/chat/expo/src/Composer.tsx +23 -0
- package/dist/templates/chat/expo/src/MediaView.tsx +29 -0
- package/dist/templates/chat/expo/src/Witness.tsx +131 -0
- package/dist/templates/chat/expo/src/screens/Inbox.tsx +9 -0
- package/dist/templates/chat/expo/src/screens/Search.tsx +10 -0
- package/dist/templates/chat/expo/src/screens/Thread.tsx +22 -0
- package/dist/templates/chat/expo/src/witness-state.ts +68 -0
- package/dist/templates/chat/expo/tsconfig.json +5 -0
- package/dist/templates/chat/react/index.html +5 -0
- package/dist/templates/chat/react/shared/log.js +92 -0
- package/dist/templates/chat/react/shared/log.ts +130 -0
- package/dist/templates/chat/react/shared/offline.js +8 -0
- package/dist/templates/chat/react/shared/offline.ts +9 -0
- package/dist/templates/chat/react/src/App.tsx +36 -0
- package/dist/templates/chat/react/src/Composer.tsx +45 -0
- package/dist/templates/chat/react/src/Inbox.tsx +24 -0
- package/dist/templates/chat/react/src/Search.tsx +26 -0
- package/dist/templates/chat/react/src/Thread.tsx +126 -0
- package/dist/templates/chat/react/src/env.d.ts +1 -0
- package/dist/templates/chat/react/src/main.tsx +20 -0
- package/dist/templates/chat/shared/log.js +92 -0
- package/dist/templates/chat/shared/log.ts +130 -0
- package/dist/templates/chat/shared/offline.js +8 -0
- package/dist/templates/chat/shared/offline.ts +9 -0
- package/dist/templates/chat/snapback/deliveries.q +33 -0
- package/dist/templates/chat/snapback/delivery.ts +30 -0
- package/dist/templates/chat/snapback/feeds.q +14 -0
- package/dist/templates/chat/snapback/follows.q +11 -0
- package/dist/templates/chat/snapback/groups.q +40 -0
- package/dist/templates/chat/snapback/messages.q +32 -0
- package/dist/templates/chat/snapback/notifications.q +7 -0
- package/dist/templates/chat/snapback/posts.q +4 -0
- package/dist/templates/chat/snapback/profiles.q +17 -0
- package/dist/templates/chat/snapback/schema.q +136 -0
- package/dist/templates/chat/snapback/seed.ts +45 -0
- package/dist/templates/chat/snapback/tests/chat.test.ts +759 -0
- package/dist/templates/react/index.html +5 -0
- package/dist/templates/react/src/App.tsx +5 -0
- package/dist/templates/react/src/main.tsx +18 -0
- package/dist/templates/todos/snapback/schema.q +11 -0
- package/dist/templates/todos/snapback/seed.ts +10 -0
- package/dist/templates/todos/snapback/tests/todos.test.ts +13 -0
- package/dist/templates/todos/snapback/todos.q +6 -0
- package/dist/test-runner.mjs +8541 -0
- package/dist/test-runner.mjs.map +7 -0
- package/dist/test.d.ts +28 -0
- package/dist/test.mjs +8541 -0
- package/dist/test.mjs.map +7 -0
- package/dist/token-store.d.ts +3 -0
- package/dist/twin-hydrate.d.ts +43 -0
- package/dist/twin.d.ts +70 -0
- package/dist/types.d.ts +410 -0
- package/dist/witness-test.mjs +2 -0
- package/dist/witness-test.mjs.map +7 -0
- package/package.json +117 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,362 @@
|
|
|
1
|
+
declare module "snapback2" {
|
|
2
|
+
export type Json = null | boolean | number | string | Json[] | { [key: string]: Json };
|
|
3
|
+
/** Server-minted authority subject; deliberately distinct from application row IDs. */
|
|
4
|
+
export type Principal = string & { readonly __snapbackPrincipal: "Principal" };
|
|
5
|
+
export type Cursor = string & { readonly __snapbackCursor: "Cursor" };
|
|
6
|
+
export type Bytes = { readonly Bytes: string };
|
|
7
|
+
// @ref LLP 1006#1-the-move — the phantom kind keeps the two closed asset records nominal without adding JSON bytes.
|
|
8
|
+
export type ImageAsset = { readonly __asset: "image"; readonly id: string; readonly width: number; readonly height: number };
|
|
9
|
+
export type VideoAsset = { readonly __asset: "video"; readonly id: string; readonly width: number; readonly height: number; readonly duration: number };
|
|
10
|
+
export type SeedValue = null | boolean | number | string | Bytes | SeedValue[] | { [key: string]: SeedValue };
|
|
11
|
+
export type Decimal<S extends number> = number & {
|
|
12
|
+
readonly __decimalScale: S;
|
|
13
|
+
readonly __decimalBrand: unique symbol;
|
|
14
|
+
};
|
|
15
|
+
export type Money<C extends string, S extends number = 2> = Decimal<S> & {
|
|
16
|
+
readonly __moneyCurrency: C;
|
|
17
|
+
readonly __moneyBrand: unique symbol;
|
|
18
|
+
};
|
|
19
|
+
export type Column<T = unknown, Optional extends boolean = false> = {
|
|
20
|
+
readonly __value: T;
|
|
21
|
+
readonly __optional: Optional;
|
|
22
|
+
readonly __column: unique symbol;
|
|
23
|
+
};
|
|
24
|
+
export type Arg<T = unknown, Optional extends boolean = false> = Column<T, Optional>;
|
|
25
|
+
export type RowOfColumns<C extends Record<string, Column<any, any>>> =
|
|
26
|
+
{ id: string }
|
|
27
|
+
& { [K in keyof C as C[K] extends Column<any, true> ? never : K]: C[K] extends Column<infer T, any> ? T : never }
|
|
28
|
+
& { [K in keyof C as C[K] extends Column<any, true> ? K : never]?: C[K] extends Column<infer T, any> ? T : never };
|
|
29
|
+
export type Table<Row extends Record<string, any> = Record<string, any>> = {
|
|
30
|
+
readonly __row: Row;
|
|
31
|
+
readonly __table: unique symbol;
|
|
32
|
+
} & { readonly [index: string]: TableIndex<Row> };
|
|
33
|
+
export type TableIndex<Row extends Record<string, any> = Record<string, any>> = {
|
|
34
|
+
readonly __row: Row;
|
|
35
|
+
readonly __index: unique symbol;
|
|
36
|
+
};
|
|
37
|
+
export type Rule = { readonly __rule: unique symbol };
|
|
38
|
+
export type RuleTerm = { readonly __term: unique symbol };
|
|
39
|
+
export type Channel<A = unknown> = { readonly __args: A; readonly __channel: unique symbol };
|
|
40
|
+
export type Operation<Args, Result, Kind extends "query" | "mutation"> = {
|
|
41
|
+
readonly __args: Args;
|
|
42
|
+
readonly __result: Result;
|
|
43
|
+
readonly __kind: Kind;
|
|
44
|
+
};
|
|
45
|
+
export type Effect<Payload = Json, Result = Json> = {
|
|
46
|
+
readonly __payload: Payload;
|
|
47
|
+
readonly __result: Result;
|
|
48
|
+
readonly __effect: unique symbol;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export type ArgsOf<A extends Record<string, Arg<any, any>>> =
|
|
52
|
+
{ [K in keyof A as A[K] extends Arg<any, true> ? never : K]: A[K] extends Arg<infer T, any> ? T : never }
|
|
53
|
+
& { [K in keyof A as A[K] extends Arg<any, true> ? K : never]?: A[K] extends Arg<infer T, any> ? T : never };
|
|
54
|
+
export type Page<T> = Array<T>;
|
|
55
|
+
export type IndexableScalar = string | number | boolean | null | Bytes | Json;
|
|
56
|
+
export type WriteValue<T> = T extends Principal ? Principal : T extends Decimal<any> ? number : T extends string ? string : T extends Array<infer U> ? WriteValue<U>[] : T;
|
|
57
|
+
export type WriteRow<R extends Record<string, any>> = {
|
|
58
|
+
[K in keyof R]: WriteValue<R[K]> | (undefined extends R[K] ? null : never)
|
|
59
|
+
};
|
|
60
|
+
// @ref LLP 1001#1-store-storers — an update patch cannot rewrite the implicit storage identity.
|
|
61
|
+
export type WritePatch<R extends Record<string, any>> =
|
|
62
|
+
{ [K in Exclude<keyof R, "id">]?: WriteValue<R[K]> | (undefined extends R[K] ? null : never) } & { readonly id?: never };
|
|
63
|
+
export type Db = {
|
|
64
|
+
get<R extends Record<string, any>>(target: Table<R> | TableIndex<R>, key: unknown): R | null;
|
|
65
|
+
exists(target: Table<any> | TableIndex<any>, key: unknown): boolean;
|
|
66
|
+
scan<R extends Record<string, any>>(target: Table<R> | TableIndex<R>, prefix: unknown, options?: {
|
|
67
|
+
order?: "asc" | "desc";
|
|
68
|
+
take?: number;
|
|
69
|
+
/** Full post-prefix ordering tuple; scalar sugar needs one remaining column, the prefix may not name every column, and the index ends in id or is unique. Components are indexable scalars matching their column kinds; null is a universal pre-first sentinel. */
|
|
70
|
+
after?: readonly unknown[] | IndexableScalar;
|
|
71
|
+
/** Full post-prefix ordering tuple; scalar sugar needs one remaining column, the prefix may not name every column, and the index ends in id or is unique. Components are indexable scalars matching their column kinds; null is a universal pre-first sentinel. */
|
|
72
|
+
before?: readonly unknown[] | IndexableScalar;
|
|
73
|
+
range?: { gt?: unknown; gte?: unknown; lt?: unknown; lte?: unknown };
|
|
74
|
+
/** Internal Quarry lowering tag; not an authored TypeScript surface. */
|
|
75
|
+
mergeSite?: string;
|
|
76
|
+
/** Internal Quarry lowering tag; not an authored TypeScript surface. */
|
|
77
|
+
opaqueCursor?: boolean;
|
|
78
|
+
}): Page<R>;
|
|
79
|
+
insert<R extends Record<string, any>>(target: Table<R>, row: WriteRow<R>): R;
|
|
80
|
+
update<R extends Record<string, any>>(target: Table<R>, key: unknown, patch: WritePatch<R> | ((row: R) => WritePatch<R>)): void;
|
|
81
|
+
upsert<R extends Record<string, any>>(target: Table<R>, key: unknown, row: WriteRow<R> | ((row: R | null) => WriteRow<R>)): void;
|
|
82
|
+
delete(target: Table<any>, key: unknown): void;
|
|
83
|
+
require(condition: unknown, code?: string): void;
|
|
84
|
+
assert(condition: unknown): void;
|
|
85
|
+
};
|
|
86
|
+
export type Context<A extends Record<string, any> = Record<string, any>> = {
|
|
87
|
+
db: Db;
|
|
88
|
+
ctx: { viewer: Principal; now(): number; newId(): string; readonly readTime: number; readonly commitTime: number; [name: string]: any };
|
|
89
|
+
args: A;
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
export function schema<const S extends Record<string, unknown>>(value: S): { readonly __schema: S };
|
|
93
|
+
export function table<const C extends Record<string, Column<any, any>>>(value: {
|
|
94
|
+
columns: C;
|
|
95
|
+
/** Client treatment of rows hidden by a fresh authorized answer; Quarry supplies the default. */
|
|
96
|
+
retain?: "until-revoked" | "delivered-history";
|
|
97
|
+
indexes?: Record<string, { columns: ReadonlyArray<keyof C | "id">; unique?: boolean }>;
|
|
98
|
+
rules?: Partial<Record<"read" | "insert" | "update" | "delete", Rule>>;
|
|
99
|
+
constraints?: ReadonlyArray<unknown>;
|
|
100
|
+
}): Table<RowOfColumns<C>>;
|
|
101
|
+
export const t: {
|
|
102
|
+
cursor(): Arg<Cursor>;
|
|
103
|
+
id(): Column<string>;
|
|
104
|
+
principal(): Column<Principal>;
|
|
105
|
+
text(max: number): Column<string>;
|
|
106
|
+
bytes(max: number): Column<Bytes>;
|
|
107
|
+
image(max: number): Column<ImageAsset>;
|
|
108
|
+
video(max: number): Column<VideoAsset>;
|
|
109
|
+
int(): Column<number>;
|
|
110
|
+
bool(): Column<boolean>;
|
|
111
|
+
time(): Column<number>;
|
|
112
|
+
enum<const V extends readonly [string, ...string[]]>(variants: V): Column<V[number]>;
|
|
113
|
+
/** `t.decimal(scale)` declares a Decimal column; numeric literals assigned to it are whole units and are scaled by 10^scale. */
|
|
114
|
+
decimal<const S extends number>(scale: S): Column<Decimal<S>>;
|
|
115
|
+
/** `t.money(currency, scale)` declares a Money column; numeric literals assigned to it are whole units and are scaled by 10^scale. */
|
|
116
|
+
money<const C extends string>(currency: C): Column<Money<C, 2>>;
|
|
117
|
+
money<const C extends string, const S extends number>(currency: C, scale: S): Column<Money<C, S>>;
|
|
118
|
+
ref<R extends Record<string, any>>(target: Table<R>): Column<string>;
|
|
119
|
+
json<T extends Json = Json>(maxBytes: number): Column<T>;
|
|
120
|
+
optional<T>(value: Column<T, any>): Column<T, true>;
|
|
121
|
+
list<T>(value: Column<T, any>, options: { max: number }): Column<T[]>;
|
|
122
|
+
};
|
|
123
|
+
export const rule: {
|
|
124
|
+
public(reason: string): Rule;
|
|
125
|
+
allow(): Rule;
|
|
126
|
+
deny(): Rule;
|
|
127
|
+
eq(a: RuleTerm, b: RuleTerm): Rule;
|
|
128
|
+
ne(a: RuleTerm, b: RuleTerm): Rule;
|
|
129
|
+
and(...rules: Rule[]): Rule;
|
|
130
|
+
or(...rules: Rule[]): Rule;
|
|
131
|
+
not(value: Rule): Rule;
|
|
132
|
+
exists(table: Table<any>, index: string, key: RuleTerm[]): Rule;
|
|
133
|
+
created(table: Table<any>, index: string, key: RuleTerm[]): Rule;
|
|
134
|
+
system(): Rule;
|
|
135
|
+
viewerIs(field: string): Rule;
|
|
136
|
+
field(name: string): RuleTerm;
|
|
137
|
+
oldField(name: string): RuleTerm;
|
|
138
|
+
nextField(name: string): RuleTerm;
|
|
139
|
+
readonly viewer: RuleTerm;
|
|
140
|
+
literal(value: Json): RuleTerm;
|
|
141
|
+
};
|
|
142
|
+
export function channel<A extends Record<string, Arg<any, any>>>(value: {
|
|
143
|
+
args: A;
|
|
144
|
+
publish: Rule;
|
|
145
|
+
subscribe: Rule;
|
|
146
|
+
ttlMs: number;
|
|
147
|
+
}): Channel<ArgsOf<A>>;
|
|
148
|
+
export function query<A extends Record<string, Arg<any, any>>, R>(
|
|
149
|
+
args: A,
|
|
150
|
+
handler: (context: Context<ArgsOf<A>>) => R,
|
|
151
|
+
): Operation<ArgsOf<A>, R, "query">;
|
|
152
|
+
export function mutation<A extends Record<string, Arg<any, any>>, R>(
|
|
153
|
+
args: A,
|
|
154
|
+
handler: (context: Context<ArgsOf<A>>) => R,
|
|
155
|
+
): Operation<ArgsOf<A>, R, "mutation">;
|
|
156
|
+
export function effect<P extends Json, R extends Json>(value: {
|
|
157
|
+
grants: string[];
|
|
158
|
+
run: (payload: P, tools: { fetch: typeof fetch; meta: { id: string } }) => R | Promise<R>;
|
|
159
|
+
then?: Operation<{ outboxId: string; effect: string; result: Awaited<R> }, unknown, "mutation">;
|
|
160
|
+
}): Effect<P, Awaited<R>>;
|
|
161
|
+
export function emit<P extends Json>(target: Effect<P, any>, payload: P): void;
|
|
162
|
+
export function seed<const S extends { personas: string[]; rows: Record<string, SeedValue[]> }>(value: S): S;
|
|
163
|
+
|
|
164
|
+
export function range(start: number, end: number): number[];
|
|
165
|
+
/** `decimal(value, scale)` converts a value in whole units to the exact integer minor-unit wire value; for example, `decimal(2, 2)` is 200. */
|
|
166
|
+
export function decimal<const S extends number>(value: number, scale: S): Decimal<S>;
|
|
167
|
+
export function mentionTokens(value: string): string[];
|
|
168
|
+
/** Euclidean deterministic share: recipients are ordered by the runtime value order; empty, duplicate, or missing recipients refuse. */
|
|
169
|
+
export function deterministicShare<A extends number>(amount: A, recipients: unknown[], recipient: unknown): A extends Decimal<any> ? A : number;
|
|
170
|
+
export function concat(first: unknown, second: unknown, ...values: unknown[]): string;
|
|
171
|
+
export function max<const S extends number>(first: Decimal<S>, second: Decimal<S>, ...values: Decimal<S>[]): Decimal<S>;
|
|
172
|
+
export function max(first: number, second: number, ...values: number[]): number;
|
|
173
|
+
export function min<const S extends number>(first: Decimal<S>, second: Decimal<S>, ...values: Decimal<S>[]): Decimal<S>;
|
|
174
|
+
export function min(first: number, second: number, ...values: number[]): number;
|
|
175
|
+
/** Euclidean quotient and remainder; a zero divisor refuses with `E_DIV_ZERO`. */
|
|
176
|
+
export function divmod<A extends number>(value: A, divisor: number): { quotient: A extends Decimal<any> ? A : number; remainder: A extends Decimal<any> ? A : number };
|
|
177
|
+
/** Internal Quarry lowering helper for a bounded multi-prefix merge. */
|
|
178
|
+
export function mergeByIndex<T>(values: T[], fields: string[], order: "asc" | "desc", take: number, site: string, table: string): Page<T>;
|
|
179
|
+
export function recurse<T>(seed: unknown, step: (value: any) => T | null, options: { depth: number; fanout: number }): T[];
|
|
180
|
+
|
|
181
|
+
/** Exact pooled-row reference spelling. Application objects with `$row` are escaped on the wire. */
|
|
182
|
+
export type WireRowReference = {
|
|
183
|
+
$row: {
|
|
184
|
+
table: string;
|
|
185
|
+
id: string;
|
|
186
|
+
};
|
|
187
|
+
};
|
|
188
|
+
export type WireEscapedObject = {
|
|
189
|
+
$row: {
|
|
190
|
+
$value: Record<string, WireValue>;
|
|
191
|
+
};
|
|
192
|
+
};
|
|
193
|
+
export type WireValue = null | boolean | number | string | WireValue[] | {
|
|
194
|
+
[key: string]: WireValue;
|
|
195
|
+
} | WireRowReference | WireEscapedObject;
|
|
196
|
+
export interface DeliveryRow {
|
|
197
|
+
table: string;
|
|
198
|
+
id: string;
|
|
199
|
+
row: Record<string, WireValue>;
|
|
200
|
+
}
|
|
201
|
+
export interface DeliveryRange {
|
|
202
|
+
site: string;
|
|
203
|
+
table: string;
|
|
204
|
+
index: string;
|
|
205
|
+
prefix: WireValue[];
|
|
206
|
+
order: "Asc" | "Desc";
|
|
207
|
+
take: number;
|
|
208
|
+
after: WireValue | null;
|
|
209
|
+
before: WireValue | null;
|
|
210
|
+
gt: WireValue | null;
|
|
211
|
+
gte: WireValue | null;
|
|
212
|
+
lt: WireValue | null;
|
|
213
|
+
lte: WireValue | null;
|
|
214
|
+
ruleHash: string;
|
|
215
|
+
rowIds: string[];
|
|
216
|
+
stop: "Limit" | "Exhausted";
|
|
217
|
+
absence: boolean;
|
|
218
|
+
haloId?: string;
|
|
219
|
+
}
|
|
220
|
+
export interface DeliveryVerdict {
|
|
221
|
+
ruleHash: string;
|
|
222
|
+
/**
|
|
223
|
+
* The verdict's pinned inputs, digested as a wire fact:
|
|
224
|
+
* `sha256(canonical([table, index, key]))` — the JSON array of the rule
|
|
225
|
+
* input's table name, index name, and key values in wire encoding (ids and
|
|
226
|
+
* text as strings, integers as numbers, null as null, bytes as
|
|
227
|
+
* `{ "Bytes": hex }`), serialized with sorted object keys and no whitespace.
|
|
228
|
+
* A twin evaluating a rule computes it from the schema and the wire values it
|
|
229
|
+
* holds and looks the verdict up by `ruleHash` plus this digest; a replay
|
|
230
|
+
* trace's `inputsDigest` is the same value. A transaction-local created-row
|
|
231
|
+
* probe prefixes the array with `"created"`. Defined once in
|
|
232
|
+
* `snapback2-core/src/offline.rs` (`rule_inputs_digest`).
|
|
233
|
+
*/
|
|
234
|
+
pinnedInputsDigest: string;
|
|
235
|
+
principal: string;
|
|
236
|
+
authEpoch: number;
|
|
237
|
+
result: boolean;
|
|
238
|
+
}
|
|
239
|
+
export interface DeliveryReceipt {
|
|
240
|
+
ranges: DeliveryRange[];
|
|
241
|
+
absences: Array<[table: string, index: string, key: WireValue[]]>;
|
|
242
|
+
verdicts: DeliveryVerdict[];
|
|
243
|
+
}
|
|
244
|
+
export interface DeliveryAuthority {
|
|
245
|
+
principal: string;
|
|
246
|
+
authEpoch: number;
|
|
247
|
+
}
|
|
248
|
+
export interface DeliveryEnvelopeV1 {
|
|
249
|
+
protocol: 1;
|
|
250
|
+
generation: string;
|
|
251
|
+
schemaHash: string;
|
|
252
|
+
planHash: string;
|
|
253
|
+
authority: DeliveryAuthority;
|
|
254
|
+
state: "complete" | "capped" | "partial" | "denied";
|
|
255
|
+
reason?: string;
|
|
256
|
+
rule?: string;
|
|
257
|
+
data: WireValue;
|
|
258
|
+
next: string | null;
|
|
259
|
+
seq: number;
|
|
260
|
+
rows: DeliveryRow[];
|
|
261
|
+
receipt: DeliveryReceipt;
|
|
262
|
+
validator: string;
|
|
263
|
+
}
|
|
264
|
+
export interface DeliveryUnchanged {
|
|
265
|
+
state: "unchanged";
|
|
266
|
+
seq: number;
|
|
267
|
+
validator: string;
|
|
268
|
+
}
|
|
269
|
+
export type DeliveryMessage = DeliveryEnvelopeV1 | DeliveryUnchanged;
|
|
270
|
+
export type TaggedValue = "Null" | {
|
|
271
|
+
Bool: boolean;
|
|
272
|
+
} | {
|
|
273
|
+
Int: number;
|
|
274
|
+
} | {
|
|
275
|
+
String: string;
|
|
276
|
+
} | {
|
|
277
|
+
Id: string;
|
|
278
|
+
} | {
|
|
279
|
+
Bytes: string;
|
|
280
|
+
} | {
|
|
281
|
+
Row: Record<string, TaggedValue>;
|
|
282
|
+
} | {
|
|
283
|
+
Array: TaggedValue[];
|
|
284
|
+
} | {
|
|
285
|
+
Map: Record<string, TaggedValue>;
|
|
286
|
+
};
|
|
287
|
+
export interface EvaluatorClosureReceipt {
|
|
288
|
+
schema_hash: string;
|
|
289
|
+
rows: Array<{
|
|
290
|
+
table: string;
|
|
291
|
+
id: string;
|
|
292
|
+
row: TaggedValue;
|
|
293
|
+
}>;
|
|
294
|
+
ranges: Array<{
|
|
295
|
+
site: string;
|
|
296
|
+
table: string;
|
|
297
|
+
index: string;
|
|
298
|
+
prefix: TaggedValue[];
|
|
299
|
+
order: "Asc" | "Desc";
|
|
300
|
+
take: number;
|
|
301
|
+
after: TaggedValue | null;
|
|
302
|
+
before: TaggedValue | null;
|
|
303
|
+
gt: TaggedValue | null;
|
|
304
|
+
gte: TaggedValue | null;
|
|
305
|
+
lt: TaggedValue | null;
|
|
306
|
+
lte: TaggedValue | null;
|
|
307
|
+
rule_hash: string;
|
|
308
|
+
row_ids: string[];
|
|
309
|
+
stop: "Limit" | "Exhausted";
|
|
310
|
+
absence: boolean;
|
|
311
|
+
halo: {
|
|
312
|
+
table: string;
|
|
313
|
+
id: string;
|
|
314
|
+
row: TaggedValue;
|
|
315
|
+
} | null;
|
|
316
|
+
n2_key: null;
|
|
317
|
+
/** Members a later swap evicted from this page; absent when none (the goldens' bytes carry none). */
|
|
318
|
+
evicted_ids?: string[];
|
|
319
|
+
}>;
|
|
320
|
+
absences: Array<[string, string, TaggedValue[]]>;
|
|
321
|
+
verdicts: Array<{
|
|
322
|
+
rule_hash: string;
|
|
323
|
+
pinned_inputs_digest: string;
|
|
324
|
+
principal: string;
|
|
325
|
+
auth_epoch: number;
|
|
326
|
+
result: boolean;
|
|
327
|
+
}>;
|
|
328
|
+
}
|
|
329
|
+
export declare class DeliveryEnvelopeDecodeError extends TypeError {
|
|
330
|
+
readonly path: string;
|
|
331
|
+
constructor(path: string, detail: string);
|
|
332
|
+
}
|
|
333
|
+
export declare function decodeDeliveryEnvelope(json: unknown): DeliveryEnvelopeV1;
|
|
334
|
+
/** Decode either a full authority envelope or a conditional `unchanged` marker. */
|
|
335
|
+
export declare function decodeDeliveryMessage(json: unknown): DeliveryMessage;
|
|
336
|
+
export declare function encodeDeliveryEnvelope(envelope: DeliveryEnvelopeV1): string;
|
|
337
|
+
export declare function expandRows(envelope: DeliveryEnvelopeV1): WireValue;
|
|
338
|
+
/** Rebuild the evaluator's externally-tagged private receipt from the public pool. */
|
|
339
|
+
export declare function toClosureReceipt(envelope: DeliveryEnvelopeV1, schema: any): EvaluatorClosureReceipt;
|
|
340
|
+
export type DeliveryRangeExtent = {
|
|
341
|
+
stop: "Limit";
|
|
342
|
+
firstKey: WireValue[];
|
|
343
|
+
lastKey: WireValue[];
|
|
344
|
+
presentIds: string[];
|
|
345
|
+
} | {
|
|
346
|
+
stop: "Exhausted";
|
|
347
|
+
prefix: WireValue[];
|
|
348
|
+
bounds: Pick<DeliveryRange, "after" | "before" | "gt" | "gte" | "lt" | "lte">;
|
|
349
|
+
presentIds: string[];
|
|
350
|
+
};
|
|
351
|
+
/** Derive the rule-2 range extent solely from a delivery and its generation schema. */
|
|
352
|
+
export declare function deliveryRangeExtent(envelope: DeliveryEnvelopeV1, schema: any, range: DeliveryRange): DeliveryRangeExtent;
|
|
353
|
+
/** Tag one pooled wire row by its table's declared column types (the evaluator's private form). */
|
|
354
|
+
export declare function tagWireRow(schema: any, table: string, row: Record<string, WireValue>): TaggedValue;
|
|
355
|
+
/** Tag index key values (a prefix, a key, or a cursor position) by the index's column types from `offset`. */
|
|
356
|
+
export declare function tagWireIndexValues(schema: any, table: string, index: string, values: WireValue[], offset?: number): TaggedValue[];
|
|
357
|
+
/** Tag a range boundary (`after`, `before`, `gt`, …): an array is a position after the prefix, a scalar its first column. */
|
|
358
|
+
export declare function tagWireBoundary(schema: any, range: Pick<DeliveryRange, "table" | "index" | "prefix">, value: WireValue | null): TaggedValue | null;
|
|
359
|
+
/** Tag one wire value by a declared column or argument descriptor. */
|
|
360
|
+
export declare function tagWireValue(descriptor: unknown, value: WireValue, path: string): TaggedValue;
|
|
361
|
+
|
|
362
|
+
}
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var H=class extends Error{constructor(r,t,i=null){super(`${r}: ${t}`);this.code=r;this.authoredCode=i}};function te(e){I(e,["tables","maintains","channels","auth","effects"],"schema");let n={tables:S(e.tables??{},me),maintains:(e.maintains??[]).map(ye)};return e.channels!==void 0&&Object.keys(e.channels).length>0&&(n.channels=S(e.channels,he)),e.auth!==void 0&&e.auth!==null&&I(e.auth,["password","guests"],"auth"),e.auth!==void 0&&(e.auth.password||e.auth.guests)&&(n.auth={password:e.auth.password,guests:e.auth.guests}),e.effects!==void 0&&e.effects.length>0&&(n.effects=e.effects),JSON.stringify(n)}function I(e,n,r){if(typeof e!="object"||e===null||Array.isArray(e))throw new H("E_SCHEMA",`${r} must be an object`);let t=Object.keys(e).filter(i=>!n.includes(i));if(t.length>0)throw new H("E_SCHEMA",`unknown ${r} field ${t.join(", ")}: a schema shape newer than this evaluator`)}function w(e,n,r){I(e,n,r);let t={};for(let i of n)e[i]!==void 0&&(t[i]=e[i]);return t}function A(e){return Array.isArray(e)?e.map(A):typeof e!="object"||e===null?e:S(e,A)}function ye(e){return I(e,["kind","source","by","target","readable"],"maintain"),{kind:be(e.kind),source:e.source,by:e.by,target:e.target,readable:e.readable===null||e.readable===void 0?null:E(e.readable)}}function be(e){if(typeof e!="object"||e===null)return e;let[n,r]=O(e);return{[n]:n==="Sum"?w(r,["of"],"maintain.kind.Sum"):A(r)}}function me(e){return I(e,["columns","indexes","rules","constraints","retain"],"table"),{columns:S(e.columns??{},z),indexes:S(e.indexes??{},xe),rules:we(e.rules),constraints:(e.constraints??[]).map($e),retain:e.retain??"until-revoked"}}function xe(e){return w(e,["columns","unique"],"index")}function he(e){return I(e,["args","publish","subscribe","ttl_ms"],"channel"),{args:S(e.args??{},Q),publish:E(e.publish),subscribe:E(e.subscribe),ttl_ms:e.ttl_ms}}function we(e){return e==null?e:(I(e,["read","insert","update","delete"],"rules"),{read:E(e.read),insert:E(e.insert),update:E(e.update),delete:E(e.delete)})}function E(e){if(typeof e!="object"||e===null)return e;let[n,r]=O(e);switch(n){case"Eq":case"Ne":return{[n]:r.map(G)};case"And":case"Or":return{[n]:r.map(E)};case"Not":return{[n]:E(r)};case"Exists":case"Created":return{[n]:{...w(r,["table","index","key","provenance"],`rule.${n}`),key:r.key.map(G)}};case"Public":return{Public:w(r,["reason"],"rule.Public")};default:return{[n]:A(r)}}}function G(e){if(typeof e!="object"||e===null)return e;let[n,r]=O(e);return n==="Literal"?{Literal:X(r)}:n==="Field"||n==="OldField"||n==="NextField"?e:{[n]:A(r)}}function $e(e){if(typeof e!="object"||e===null)return e;let[n,r]=O(e),t=`constraint.${n}`;switch(n){case"Unique":return{Unique:w(r,["index"],t)};case"Cap":return{Cap:w(r,["by","max"],t)};case"Immutable":return{Immutable:w(r,["fields"],t)};case"Text":return I(r,["field","min","format"],t),{Text:{field:r.field,min:r.min??0,...r.format===void 0||r.format===null?{}:{format:r.format}}};case"FinalExistsOnInsert":return{FinalExistsOnInsert:{...w(r,["table","index","key"],t),key:r.key.map(G)}};default:return{[n]:A(r)}}}function z(e){if(typeof e!="object"||e===null)return e;let[n,r]=O(e);if(n==="Optional")return{Optional:z(r)};let t=`column.${n}`;if(n==="List")return{List:{...w(r,["of","max"],t),of:z(r.of)}};let i=ke[n];return{[n]:i===void 0?A(r):w(r,i,t)}}var ke={Text:["max"],Bytes:["max"],Image:["max"],Video:["max"],Enum:["variants"],Decimal:["scale"],Money:["currency","scale"],Ref:["table"],Json:["max_bytes"]};function Q(e){if(typeof e!="object"||e===null)return e;let[n,r]=O(e);return n==="Optional"?{Optional:Q(r)}:n==="List"?(I(r,["of","max"],"arg.List"),{List:{...r.of===null||r.of===void 0?{}:{of:Q(r.of)},max:r.max}}):z(e)}function X(e){if(typeof e=="string")return e;let[n,r]=O(e);return n==="Array"?{Array:r.map(X)}:n==="Row"||n==="Map"?{[n]:S(r,X)}:e}function S(e,n){let r=Object.create(null);for(let t of Object.keys(e).sort(Re))r[t]=n(e[t]);return r}function O(e){let n=Object.keys(e);if(n.length!==1)throw new Error("E_TRACE_SUBSET: malformed externally tagged IR");return[n[0],e[n[0]]]}function Re(e,n){let r=Array.from(e,i=>i.codePointAt(0)),t=Array.from(n,i=>i.codePointAt(0));for(let i=0;i<Math.min(r.length,t.length);i+=1)if(r[i]!==t[i])return r[i]-t[i];return r.length-t.length}function re(e){let n=Ee(e),r=n.length*8;for(n.push(128);n.length%64!==56;)n.push(0);let t=Math.floor(r/4294967296),i=r>>>0;for(let a=24;a>=0;a-=8)n.push(t>>>a&255);for(let a=24;a>=0;a-=8)n.push(i>>>a&255);let o=[1779033703,3144134277,1013904242,2773480762,1359893119,2600822924,528734635,1541459225],s=new Array(64);for(let a=0;a<n.length;a+=64){for(let f=0;f<16;f+=1){let h=a+f*4;s[f]=(n[h]<<24|n[h+1]<<16|n[h+2]<<8|n[h+3])>>>0}for(let f=16;f<64;f+=1){let h=s[f-15],C=s[f-2],N=$(h,7)^$(h,18)^h>>>3,K=$(C,17)^$(C,19)^C>>>10;s[f]=s[f-16]+N+s[f-7]+K>>>0}let[c,x,p,W,y,P,B,J]=o;for(let f=0;f<64;f+=1){let h=$(y,6)^$(y,11)^$(y,25),C=y&P^~y&B,N=J+h+C+Ie[f]+s[f]>>>0,K=$(c,2)^$(c,13)^$(c,22),pe=c&x^c&p^x&p,ge=K+pe>>>0;J=B,B=P,P=y,y=W+N>>>0,W=p,p=x,x=c,c=N+ge>>>0}o[0]=o[0]+c>>>0,o[1]=o[1]+x>>>0,o[2]=o[2]+p>>>0,o[3]=o[3]+W>>>0,o[4]=o[4]+y>>>0,o[5]=o[5]+P>>>0,o[6]=o[6]+B>>>0,o[7]=o[7]+J>>>0}return o.map(a=>a.toString(16).padStart(8,"0")).join("")}function $(e,n){return e>>>n|e<<32-n}function Ee(e){let n=[];for(let r of e){let t=r.codePointAt(0);t<=127?n.push(t):t<=2047?n.push(192|t>>6,128|t&63):t<=65535?n.push(224|t>>12,128|t>>6&63,128|t&63):n.push(240|t>>18,128|t>>12&63,128|t>>6&63,128|t&63)}return n}var Ie=[1116352408,1899447441,3049323471,3921009573,961987163,1508970993,2453635748,2870763221,3624381080,310598401,607225278,1426881987,1925078388,2162078206,2614888103,3248222580,3835390401,4022224774,264347078,604807628,770255983,1249150122,1555081692,1996064986,2554220882,2821834349,2952996808,3210313671,3336571891,3584528711,113926993,338241895,666307205,773529912,1294757372,1396182291,1695183700,1986661051,2177026350,2456956037,2730485921,2820302411,3259730800,3345764771,3516065817,3600352804,4094571909,275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,1747873779,1955562222,2024104815,2227730452,2361852424,2428436474,2756734187,3204031479,3329325298];function M(e){return re(te(e))}var j=class extends TypeError{constructor(r,t){super(`${r}: ${t}`);this.path=r;this.name="DeliveryEnvelopeDecodeError"}};function v(e){k(e,"$",["protocol","generation","schemaHash","planHash","authority","state","data","next","seq","rows","receipt","validator"],["reason","rule"]),e.protocol!==1&&u("$.protocol","unsupported delivery protocol"),D(e.generation,"$.generation"),D(e.schemaHash,"$.schemaHash"),D(e.planHash,"$.planHash"),k(e.authority,"$.authority",["principal","authEpoch"]),m(e.authority.principal,"$.authority.principal"),L(e.authority.authEpoch,"$.authority.authEpoch"),["complete","capped","partial","denied"].includes(String(e.state))||u("$.state","expected complete, capped, partial, or denied"),e.state==="partial"?m(e.reason,"$.reason"):e.reason!==void 0&&u("$.reason","is only valid for partial state"),e.state==="denied"?m(e.rule,"$.rule"):e.rule!==void 0&&u("$.rule","is only valid for denied state"),T(e.data,"$.data"),e.next!==null&&m(e.next,"$.next"),L(e.seq,"$.seq"),V(e.rows,"$.rows");let n=new Set;return e.rows.forEach((r,t)=>{k(r,`$.rows[${t}]`,["table","id","row"]),m(r.table,`$.rows[${t}].table`),m(r.id,`$.rows[${t}].id`),k(r.row,`$.rows[${t}].row`,[],[],!0),T(r.row,`$.rows[${t}].row`);let i=R(r.table,r.id);n.has(i)&&u(`$.rows[${t}]`,"duplicates a pooled row"),n.add(i)}),_e(e.receipt,n,e.authority),F(e.data,n,"$.data"),D(e.validator,"$.validator"),e}function Ve(e){return d(e)&&e.state==="unchanged"?(k(e,"$",["state","seq","validator"]),L(e.seq,"$.seq"),D(e.validator,"$.validator"),e):v(e)}function De(e){let n=v(e),r={protocol:n.protocol,generation:n.generation,schemaHash:n.schemaHash,planHash:n.planHash,authority:{principal:n.authority.principal,authEpoch:n.authority.authEpoch},state:n.state};return n.reason!==void 0&&(r.reason=n.reason),n.rule!==void 0&&(r.rule=n.rule),r.data=g(n.data),r.next=n.next,r.seq=n.seq,r.rows=[...n.rows].sort((t,i)=>ie(t.table,i.table)||ie(t.id,i.id)).map(t=>({table:t.table,id:t.id,row:g(t.row)})),r.receipt={ranges:n.receipt.ranges.map(t=>{let i={site:t.site,table:t.table,index:t.index,prefix:t.prefix.map(g),order:t.order,take:t.take,after:t.after===null?null:g(t.after),before:t.before===null?null:g(t.before),gt:t.gt===null?null:g(t.gt),gte:t.gte===null?null:g(t.gte),lt:t.lt===null?null:g(t.lt),lte:t.lte===null?null:g(t.lte),ruleHash:t.ruleHash,rowIds:[...t.rowIds],stop:t.stop,absence:t.absence};return t.haloId!==void 0&&(i.haloId=t.haloId),i}),absences:n.receipt.absences.map(([t,i,o])=>[t,i,o.map(g)]),verdicts:n.receipt.verdicts.map(t=>({ruleHash:t.ruleHash,pinnedInputsDigest:t.pinnedInputsDigest,principal:t.principal,authEpoch:t.authEpoch,result:t.result}))},r.validator=n.validator,JSON.stringify(r)}function Ae(e){let n=v(e),r=new Map(n.rows.map(i=>[R(i.table,i.id),i.row])),t=i=>{if(le(i)){let o=r.get(R(i.$row.table,i.$row.id));return o===void 0&&u("$.data",`references missing row ${i.$row.table}/${i.$row.id}`),b(o)}return ce(i)?Object.fromEntries(Object.entries(i.$row.$value).map(([o,s])=>[o,t(s)])):Array.isArray(i)?i.map(t):d(i)?Object.fromEntries(Object.entries(i).map(([o,s])=>[o,t(s)])):i};return t(n.data)}function Se(e,n){let r=v(e),t;try{t=M(n)}catch(s){u("schema",s instanceof Error?s.message:String(s))}t!==r.schemaHash&&u("schema",`hash ${t} does not match envelope schemaHash ${r.schemaHash}`);let i=new Map;for(let s of r.rows){let a={table:s.table,id:s.id,row:ae(n,s.table,s.row)};i.set(R(s.table,s.id),a)}let o=r.receipt.ranges.map(s=>({site:s.site,table:s.table,index:s.index,prefix:q(n,s.table,s.index,s.prefix,0),order:s.order,take:s.take,after:_(n,s,s.after),before:_(n,s,s.before),gt:_(n,s,s.gt),gte:_(n,s,s.gte),lt:_(n,s,s.lt),lte:_(n,s,s.lte),rule_hash:s.ruleHash,row_ids:[...s.rowIds],stop:s.stop,absence:s.absence,halo:s.haloId===void 0?null:b(i.get(R(s.table,s.haloId))??u(`$.receipt.ranges[${s.site}].haloId`,"references a missing pooled row")),n2_key:null}));return{schema_hash:r.schemaHash,rows:Array.from(i.values()).map(b),ranges:o,absences:r.receipt.absences.map(([s,a,c])=>[s,a,q(n,s,a,c,0)]),verdicts:r.receipt.verdicts.map(s=>({rule_hash:s.ruleHash,pinned_inputs_digest:s.pinnedInputsDigest,principal:s.principal,auth_epoch:s.authEpoch,result:s.result}))}}function Oe(e,n,r){let t=v(e),i=t.receipt.ranges.find(c=>c===r)??t.receipt.ranges.find(c=>c.site===r.site);i||u("$.receipt.ranges",`does not contain site ${r.site}`);let o=i.haloId===void 0?[...i.rowIds]:[...i.rowIds,i.haloId];if(i.stop==="Exhausted")return{stop:"Exhausted",prefix:b(i.prefix),bounds:{after:b(i.after),before:b(i.before),gt:b(i.gt),gte:b(i.gte),lt:b(i.lt),lte:b(i.lte)},presentIds:o};i.rowIds.length===0&&u(`$.receipt.ranges[${i.site}].rowIds`,"Limit extent needs a returned row");let s=new Map(t.rows.map(c=>[R(c.table,c.id),c])),a=c=>{let x=s.get(R(i.table,c));return ue(n,i.table,i.index).map(p=>(p in x.row||u(`$.rows.${i.table}/${c}.${p}`,"is required by the range index"),b(x.row[p])))};return{stop:"Limit",firstKey:a(i.rowIds[0]),lastKey:a(i.rowIds[i.rowIds.length-1]),presentIds:o}}function _e(e,n,r){k(e,"$.receipt",["ranges","absences","verdicts"]),V(e.ranges,"$.receipt.ranges"),e.ranges.forEach((t,i)=>{let o=`$.receipt.ranges[${i}]`;k(t,o,["site","table","index","prefix","order","take","after","before","gt","gte","lt","lte","ruleHash","rowIds","stop","absence"],["haloId"]);for(let a of["site","table","index","ruleHash"])m(t[a],`${o}.${a}`);D(t.ruleHash,`${o}.ruleHash`),V(t.prefix,`${o}.prefix`),t.prefix.forEach((a,c)=>T(a,`${o}.prefix[${c}]`)),["Asc","Desc"].includes(String(t.order))||u(`${o}.order`,"expected Asc or Desc"),L(t.take,`${o}.take`);for(let a of["after","before","gt","gte","lt","lte"])t[a]!==null&&T(t[a],`${o}.${a}`);V(t.rowIds,`${o}.rowIds`);let s=new Set;t.rowIds.forEach((a,c)=>{m(a,`${o}.rowIds[${c}]`),s.has(a)&&u(`${o}.rowIds[${c}]`,"duplicates a row id"),s.add(a),n.has(R(t.table,a))||u(`${o}.rowIds[${c}]`,"references a missing same-table pooled row")}),["Limit","Exhausted"].includes(String(t.stop))||u(`${o}.stop`,"expected Limit or Exhausted"),Z(t.absence,`${o}.absence`),t.haloId!==void 0&&(m(t.haloId,`${o}.haloId`),n.has(R(t.table,t.haloId))||u(`${o}.haloId`,"references a missing pooled row"))}),V(e.absences,"$.receipt.absences"),e.absences.forEach((t,i)=>{let o=`$.receipt.absences[${i}]`;V(t,o),t.length!==3&&u(o,"expected [table, index, key]"),m(t[0],`${o}[0]`),t[1]!=="byId"&&u(`${o}[1]`,"only primary byId absences may be delivered"),V(t[2],`${o}[2]`),t[2].forEach((s,a)=>T(s,`${o}[2][${a}]`))}),V(e.verdicts,"$.receipt.verdicts"),e.verdicts.forEach((t,i)=>{let o=`$.receipt.verdicts[${i}]`;k(t,o,["ruleHash","pinnedInputsDigest","principal","authEpoch","result"]),D(t.ruleHash,`${o}.ruleHash`),D(t.pinnedInputsDigest,`${o}.pinnedInputsDigest`),m(t.principal,`${o}.principal`),L(t.authEpoch,`${o}.authEpoch`),Z(t.result,`${o}.result`),t.principal!==r.principal&&u(`${o}.principal`,"does not match envelope authority"),t.authEpoch!==r.authEpoch&&u(`${o}.authEpoch`,"does not match envelope authority")})}function oe(e,n,r){return ae(e,n,r)}function ee(e,n,r,t,i=0){return q(e,n,r,t,i)}function se(e,n,r){return _(e,n,r)}function ae(e,n,r){let t=e?.tables?.[n]?.columns;d(t)||u(`schema.tables.${n}.columns`,"is missing");let i=Object.create(null);for(let[o,s]of Object.entries(r))o in t||u(`rows.${n}.${o}`,"is not a declared column"),i[o]=U(t[o],s,`rows.${n}.${o}`);return{Row:i}}function q(e,n,r,t,i){let o=ue(e,n,r);return t.map((s,a)=>{let c=o[i+a];return c===void 0&&u(`schema.tables.${n}.indexes.${r}`,"has too few columns"),U(e.tables[n].columns[c],s,`${n}.${r}[${i+a}]`)})}function _(e,n,r){return r===null?null:Array.isArray(r)?{Array:q(e,n.table,n.index,r,n.prefix.length)}:q(e,n.table,n.index,[r],n.prefix.length)[0]}function U(e,n,r){if(d(e)&&"Optional"in e)return n===null?"Null":U(e.Optional,n,r);if(n===null)return"Null";if(e==="Id"||e==="Principal"||d(e)&&"Ref"in e)return typeof n!="string"&&u(r,"expected id string"),{Id:n};if(d(e)&&("Text"in e||"Enum"in e))return typeof n!="string"&&u(r,"expected text string"),{String:n};if(["Int","Time"].includes(String(e))||d(e)&&("Decimal"in e||"Money"in e))return ne(n,r),{Int:n};if(e==="Bool")return Z(n,r),{Bool:n};if(d(e)&&"Bytes"in e){let t=d(n)&&"Bytes"in n?n.Bytes:void 0;return(!d(n)||Object.keys(n).length!==1||typeof t!="string"||!/^(?:[0-9a-f]{2})*$/.test(t))&&u(r,"expected canonical Bytes"),{Bytes:t}}if(d(e)&&"List"in e)return V(n,r),{Array:n.map((t,i)=>U(e.List.of,t,`${r}[${i}]`))};if(d(e)&&("Image"in e||"Video"in e)){k(n,r,[],[],!0);let t="Image"in e?"Image":"Video",i=Te[t],o=Object.keys(n);return(o.length!==Object.keys(i).length||o.some(s=>!(s in i)))&&u(r,`must contain exactly ${Object.keys(i).sort().join(", ")}`),{Map:Object.fromEntries(Object.entries(n).map(([s,a])=>[s,We(i[s],a,`${r}.${s}`)]))}}if(d(e)&&"Json"in e)return Y(n);u(r,"has an unsupported schema descriptor")}function Y(e){return e===null?"Null":typeof e=="boolean"?{Bool:e}:typeof e=="number"?{Int:e}:typeof e=="string"?{String:e}:Array.isArray(e)?{Array:e.map(Y)}:{Map:Object.fromEntries(Object.entries(e).map(([n,r])=>[n,Y(r)]))}}var Te={Image:{id:"String",width:"Int",height:"Int"},Video:{id:"String",width:"Int",height:"Int",duration:"Int"}};function We(e,n,r){return e==="String"?(typeof n!="string"&&u(r,"expected string"),{String:n}):(ne(n,r),{Int:n})}function ue(e,n,r){let t=e?.tables?.[n]?.indexes?.[r]?.columns;return(!Array.isArray(t)||!t.every(i=>typeof i=="string"))&&u(`schema.tables.${n}.indexes.${r}`,"is missing columns"),t}function F(e,n,r){if(le(e)){n.has(R(e.$row.table,e.$row.id))||u(r,"references a missing pooled row");return}if(ce(e)){for(let[t,i]of Object.entries(e.$row.$value))F(i,n,`${r}.$row.$value.${t}`);return}if(Array.isArray(e))e.forEach((t,i)=>F(t,n,`${r}[${i}]`));else if(d(e)){"$row"in e&&u(r,"has a malformed reserved $row value");for(let[t,i]of Object.entries(e))F(i,n,`${r}.${t}`)}}function g(e){if(Array.isArray(e))return e.map(g);if(d(e)){let n=e;return Object.fromEntries(Object.keys(n).sort().map(r=>[r,g(n[r])]))}return e}function T(e,n){if(!(e===null||typeof e=="boolean"||typeof e=="string")){if(typeof e=="number"){ne(e,n);return}if(Array.isArray(e)){e.forEach((r,t)=>T(r,`${n}[${t}]`));return}k(e,n,[],[],!0);for(let[r,t]of Object.entries(e))T(t,`${n}.${r}`)}}function le(e){return d(e)&&Object.keys(e).length===1&&d(e.$row)&&Object.keys(e.$row).sort().join(",")==="id,table"&&typeof e.$row.table=="string"&&typeof e.$row.id=="string"}function ce(e){return d(e)&&Object.keys(e).length===1&&d(e.$row)&&Object.keys(e.$row).length===1&&d(e.$row.$value)}function k(e,n,r,t=[],i=!1){d(e)||u(n,"expected object");for(let o of r)o in e||u(`${n}.${o}`,"is required");if(!i)for(let o of Object.keys(e))!r.includes(o)&&!t.includes(o)&&u(`${n}.${o}`,"is unknown")}function V(e,n){Array.isArray(e)||u(n,"expected array")}function m(e,n){(typeof e!="string"||e.length===0)&&u(n,"expected non-empty string")}function Z(e,n){typeof e!="boolean"&&u(n,"expected boolean")}function L(e,n){(!Number.isSafeInteger(e)||Number(e)<0)&&u(n,"expected non-negative safe integer")}function ne(e,n){Number.isSafeInteger(e)||u(n,"expected safe integer")}function D(e,n){(typeof e!="string"||!/^[0-9a-f]{64}$/.test(e))&&u(n,"expected lowercase SHA-256 digest")}function d(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)&&(Object.getPrototypeOf(e)===Object.prototype||Object.getPrototypeOf(e)===null)}function R(e,n){return`${e.length}:${e}${n}`}function ie(e,n){return e<n?-1:e>n?1:0}function b(e){return structuredClone(e)}function u(e,n){throw new j(e,n)}function fe(e){return`${e.table} ${e.id}`}var de=new WeakMap;function je(e){let n=typeof e=="object"&&e!==null?de.get(e):void 0;if(n!==void 0)return n;let r=M(e);return typeof e=="object"&&e!==null&&de.set(e,r),r}function ve(e,n,r){let t=je(n);if(r!==void 0&&r!==t)throw new j("schema",`hash ${t} does not match the held program's ${r}`);let i=new Map;for(let o of e.rows)i.set(fe(o),{table:o.table,id:o.id,row:oe(n,o.table,o.row)});return{schema_hash:t,rows:[...i.values()],ranges:e.ranges.map(o=>Ce(n,o,i)),absences:e.absences.map(([o,s,a])=>[o,s,ee(n,o,s,a,0)]),verdicts:e.verdicts.map(o=>{let s=o;return{rule_hash:String(s.ruleHash),pinned_inputs_digest:String(s.pinnedInputsDigest),principal:String(s.principal),auth_epoch:Number(s.authEpoch),result:s.result===!0}})}}function Ce(e,n,r){let t=o=>o==null?null:se(e,n,o),i=n.haloId===void 0?void 0:r.get(fe({table:n.table,id:n.haloId}));return{site:n.site,table:n.table,index:n.index,prefix:ee(e,n.table,n.index,n.prefix,0),order:n.order,take:n.take,after:t(n.after),before:t(n.before),gt:t(n.gt),gte:t(n.gte),lt:t(n.lt),lte:t(n.lte),rule_hash:n.ruleHash,row_ids:[...n.rowIds],stop:n.stop,absence:n.absence,halo:i===void 0?null:structuredClone(i),n2_key:null,...n.evictedIds===void 0||n.evictedIds.length===0?{}:{evicted_ids:[...n.evictedIds]}}}function l(e,n){return Object.freeze(n===void 0?{kind:e}:{kind:e,value:n})}function Xe(e){return l("schema",e)}function Ye(e){return l("table",e)}var Ze=Object.freeze({cursor:()=>l("cursor"),id:()=>l("id"),principal:()=>l("principal"),text:e=>l("text",{max:e}),bytes:e=>l("bytes",{max:e}),image:e=>l("image",{max:e}),video:e=>l("video",{max:e}),int:()=>l("int"),bool:()=>l("bool"),time:()=>l("time"),enum:e=>l("enum",{variants:e}),decimal:e=>l("decimal",{scale:e}),money:(e,n=2)=>l("money",{currency:e,scale:n}),ref:e=>l("ref",{target:e}),json:e=>l("json",{maxBytes:e}),optional:e=>l("optional",{value:e}),list:(e,n)=>l("list",{value:e,...n})}),He=l("viewer"),en=Object.freeze({public:e=>l("public",{reason:e}),allow:()=>l("allow"),deny:()=>l("deny"),eq:(e,n)=>l("eq",{left:e,right:n}),ne:(e,n)=>l("ne",{left:e,right:n}),and:(...e)=>l("and",e),or:(...e)=>l("or",e),not:e=>l("not",e),exists:(e,n,r)=>l("exists",{target:e,index:n,key:r}),created:(e,n,r)=>l("created",{target:e,index:n,key:r}),system:()=>l("system"),viewerIs:e=>l("viewerIs",{field:e}),field:e=>l("field",{name:e}),oldField:e=>l("oldField",{name:e}),nextField:e=>l("nextField",{name:e}),viewer:He,literal:e=>l("literal",e)});function nn(e){return l("channel",e)}function tn(e,n){return l("query",{args:e,handler:n})}function rn(e,n){return l("mutation",{args:e,handler:n})}function on(e){return l("effect",e)}function sn(e,n){return l("emit",{target:e,payload:n})}function an(e){return l("seed",e)}function un(e,n){return Array.from({length:Math.max(0,n-e)},(r,t)=>e+t)}function ln(e,n){if(!Number.isFinite(e)||!Number.isInteger(n)||n<0||n>12)throw new RangeError("decimal(value, scale) requires a finite number and an integer scale from 0 through 12");let r=/^([+-]?)(\d+)(?:\.(\d+))?(?:e([+-]?\d+))?$/i.exec(String(e));if(!r)throw new RangeError(`decimal cannot encode ${String(e)}`);let t=r[1]==="-",i=r[2],o=r[3]??"",s=Number(r[4]??0),a=`${i}${o}`,c=i.length+s,x=c<=0?"0":c>=a.length?`${a}${"0".repeat(c-a.length)}`:a.slice(0,c),p=c<=0?`${"0".repeat(-c)}${a}`:c>=a.length?"":a.slice(c);if(p.length>n)throw new RangeError(`${String(e)} has ${p.length} fractional digits, scale ${n}`);let W=`${x}${p.padEnd(n,"0")}`,y=Number(t?`-${W}`:W);if(!Number.isSafeInteger(y))throw new RangeError("decimal minor units exceed the safe integer wire range");return y}function cn(e){return e.split(" ").filter(n=>n.startsWith("@"))}function dn(e,n,r){let t=n.indexOf(r);return Math.floor(e/n.length)+(t>=0&&t<e%n.length?1:0)}function fn(...e){return e.join("")}var pn=Math.max,gn=Math.min;function yn(e,n){return{quotient:Math.floor(e/n),remainder:e%n}}function bn(e,n,r,t,i,o){throw new Error("snapback2: authored program descriptors are inert")}function mn(){throw new Error("snapback2: authored program descriptors are inert")}export{j as DeliveryEnvelopeDecodeError,nn as channel,ve as closureFromCoverage,fn as concat,ln as decimal,v as decodeDeliveryEnvelope,Ve as decodeDeliveryMessage,Oe as deliveryRangeExtent,dn as deterministicShare,yn as divmod,on as effect,sn as emit,De as encodeDeliveryEnvelope,Ae as expandRows,pn as max,cn as mentionTokens,bn as mergeByIndex,gn as min,rn as mutation,tn as query,un as range,mn as recurse,en as rule,Xe as schema,M as schemaDigest,an as seed,Ze as t,Ye as table,Se as toClosureReceipt};
|
|
2
|
+
//# sourceMappingURL=index.mjs.map
|