@crvouga/mockingbird-service-postgres 3.11.0 → 3.12.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.
@@ -0,0 +1,52 @@
1
+ import { type DurabilityBackend, type DurableImage, type DurablePatch } from "./durability.js";
2
+ import type { DurabilityLifecycle } from "./durability-buffered.js";
3
+ /** Best effort only; browsers do not wait for asynchronous pagehide work. */
4
+ export declare const browserDurabilityLifecycle: DurabilityLifecycle;
5
+ export interface IndexedDBDurabilityOptions {
6
+ name?: string;
7
+ /** Inject for workers, tests or a different browser realm. */
8
+ indexedDB?: {
9
+ open(name: string, version?: number): unknown;
10
+ };
11
+ /** Default strict: acknowledgement follows the browser's durable commit. */
12
+ durability?: "default" | "strict" | "relaxed";
13
+ }
14
+ /** Binary pages, changed-page writes and revision checks in one IndexedDB transaction. */
15
+ export declare class IndexedDBDurabilityBackend implements DurabilityBackend {
16
+ private database;
17
+ private readonly factory;
18
+ private readonly name;
19
+ private readonly durability;
20
+ constructor(options?: IndexedDBDurabilityOptions);
21
+ private open;
22
+ load(key: string): Promise<DurableImage | undefined>;
23
+ commit(key: string, expectedRevision: number, patch: DurablePatch): Promise<number>;
24
+ /** Release this adapter's connection; does not delete any saved images. */
25
+ close(): Promise<void>;
26
+ }
27
+ export interface LocalStorageDurabilityOptions {
28
+ storage?: {
29
+ getItem(key: string): string | null;
30
+ setItem(key: string, value: string): void;
31
+ };
32
+ prefix?: string;
33
+ /** Inject navigator.locks for cross-tab compare-and-swap. Required for safe shared writers. */
34
+ locks?: {
35
+ request<T>(name: string, run: () => T | PromiseLike<T>): Promise<T>;
36
+ };
37
+ }
38
+ /**
39
+ * Small-image fallback. Each commit replaces one base64 image atomically. IndexedDB avoids
40
+ * this full-image encoding and synchronous main-thread IO and is preferred for performance.
41
+ * With no Web Locks support, use one writer per key (localStorage has no native CAS).
42
+ */
43
+ export declare class LocalStorageDurabilityBackend implements DurabilityBackend {
44
+ private readonly storage;
45
+ private readonly prefix;
46
+ private readonly locks;
47
+ constructor(options?: LocalStorageDurabilityOptions);
48
+ load(key: string): Promise<DurableImage | undefined>;
49
+ private read;
50
+ commit(key: string, expectedRevision: number, patch: DurablePatch): Promise<number>;
51
+ }
52
+ //# sourceMappingURL=durability-browser.d.ts.map
@@ -0,0 +1,65 @@
1
+ import { type DurabilityBackend, type DurabilityCodec, type Durable } from "./durability.js";
2
+ export interface DurabilityScheduler {
3
+ schedule(run: () => void, delayMs: number): unknown;
4
+ cancel(handle: unknown): void;
5
+ }
6
+ export interface DurabilityLifecycle {
7
+ subscribe(onSuspend: () => void): () => void;
8
+ }
9
+ export interface BufferedDurabilityObserver {
10
+ changed(): void;
11
+ exposed(): void;
12
+ assertWritable(): void;
13
+ /** An independently closed engine cannot keep a background persistence loop alive. */
14
+ closed?(): void;
15
+ }
16
+ export interface IncrementalCapture<Token> {
17
+ token: Token;
18
+ checkpoint: boolean;
19
+ /** Omit when the committed state has not changed. Bytes must be independently owned. */
20
+ bytes?: Uint8Array;
21
+ }
22
+ /** Engine port: capture physical committed state, never SQL text for replay. */
23
+ export interface IncrementalDurabilityCodec<T, Token> extends DurabilityCodec<T> {
24
+ decodeJournal(records: readonly Uint8Array[]): T;
25
+ /** Initialize comparison state after recovery without re-encoding the checkpoint. */
26
+ baseline?(value: T): Token;
27
+ capture(value: T, previous: Token | undefined, checkpoint: boolean): IncrementalCapture<Token>;
28
+ acknowledge(value: T, token: Token): void;
29
+ canCapture(value: T): boolean;
30
+ subscribe(value: T, observer: BufferedDurabilityObserver): () => void;
31
+ }
32
+ export interface BufferedDurabilityOptions {
33
+ /** First-change deadline, not a debounce. Default 1,000 ms; suspension can delay it. */
34
+ flushIntervalMs?: number;
35
+ scheduler?: DurabilityScheduler;
36
+ lifecycle?: DurabilityLifecycle;
37
+ onError?: (error: unknown) => void;
38
+ /** Default 256 successful delta batches. */
39
+ compactAfterBatches?: number;
40
+ /** Default max(4 MiB, checkpoint size). */
41
+ compactAfterBytes?: number;
42
+ }
43
+ export interface BufferedDurable<T> extends Durable<T> {
44
+ readonly pending: boolean;
45
+ readonly lastError: unknown;
46
+ }
47
+ export declare function isDurableJournal(bytes: Uint8Array): boolean;
48
+ /** A legacy immediate writer can retain a buffered image's richer checkpoint metadata. */
49
+ export declare function encodeDurableCheckpoint(record: Uint8Array): Uint8Array;
50
+ /** Undefined identifies an unchanged legacy image; malformed envelopes fail closed. */
51
+ export declare function readDurableJournal(bytes: Uint8Array): readonly Uint8Array[] | undefined;
52
+ /** Single-writer buffered persistence. Only the last append page is retained between saves. */
53
+ export declare function openBufferedDurable<T, Token>(options: BufferedDurabilityOptions & {
54
+ key: string;
55
+ backend: DurabilityBackend;
56
+ codec: IncrementalDurabilityCodec<T, Token>;
57
+ pageSize?: number;
58
+ }): Promise<BufferedDurable<T>>;
59
+ /** Pack engine-specific metadata alongside a standard SQLM/PGMM snapshot. */
60
+ export declare function packDurableRecord(metadata: unknown, snapshot: Uint8Array): Uint8Array;
61
+ export declare function unpackDurableRecord<Metadata>(bytes: Uint8Array): {
62
+ metadata: Metadata;
63
+ snapshot: Uint8Array;
64
+ };
65
+ //# sourceMappingURL=durability-buffered.d.ts.map
@@ -0,0 +1,78 @@
1
+ /** Atomic binary image port. Implementations must reject stale revisions without writing. */
2
+ export interface DurabilityBackend {
3
+ load(key: string): Promise<DurableImage | undefined>;
4
+ commit(key: string, expectedRevision: number, patch: DurablePatch): Promise<number>;
5
+ }
6
+ /**
7
+ * Give a Fetch emulator a durable acknowledgement boundary. Inject the handle's value into
8
+ * the service, then send every request through this wrapper. Requests serialize through the
9
+ * response's commit, so another request cannot mutate the database during a pending save.
10
+ */
11
+ export declare function withDurability<RequestType, ResponseType>(api: {
12
+ fetch(request: RequestType): Promise<ResponseType>;
13
+ }, durable: Pick<Durable<unknown>, "flush">): {
14
+ fetch(request: RequestType): Promise<ResponseType>;
15
+ };
16
+ export interface DurableImage {
17
+ revision: number;
18
+ bytes: Uint8Array;
19
+ pageSize: number;
20
+ }
21
+ export interface DurablePatch {
22
+ byteLength: number;
23
+ pageSize: number;
24
+ /** Only changed pages; data is owned by the caller until commit resolves. */
25
+ pages: readonly {
26
+ index: number;
27
+ bytes: Uint8Array;
28
+ }[];
29
+ }
30
+ /** A second writer changed the image. Reopen before writing; never silently overwrite it. */
31
+ export declare class DurabilityConflictError extends Error {
32
+ constructor();
33
+ }
34
+ /** An emulator owns its codec; storage adapters know nothing about SQL or service state. */
35
+ export interface DurabilityCodec<T> {
36
+ create(): T;
37
+ decode(bytes: Uint8Array): T;
38
+ encode(value: T): Uint8Array;
39
+ close?(value: T): void | Promise<void>;
40
+ }
41
+ export interface DurableOptions<T> {
42
+ backend: DurabilityBackend;
43
+ key: string;
44
+ codec: DurabilityCodec<T>;
45
+ /** Binary comparison/write granularity. Default 16 KiB. */
46
+ pageSize?: number;
47
+ }
48
+ export interface Durable<T> {
49
+ readonly value: T;
50
+ /** Capture and atomically save the current state. Resolve only after storage commits. */
51
+ flush(): Promise<void>;
52
+ /** Serialize a synchronous batch and save it with one encode and storage transaction. */
53
+ write<R>(run: (value: T) => R): Promise<R>;
54
+ /** Save before closing. A failed save leaves the handle open for retry. */
55
+ close(): Promise<void>;
56
+ }
57
+ /**
58
+ * Keeps the synchronous emulator hot path free of storage IO. Batch any number of mutations,
59
+ * then await flush(), or await write(batch). A successful synchronous mutation alone is not
60
+ * durable. No unload handlers, background timers or unhandled persistence failures.
61
+ */
62
+ export declare function openDurable<T>(options: DurableOptions<T>): Promise<Durable<T>>;
63
+ /** Apply a validated patch to an independently owned image. Also used by custom adapters. */
64
+ export declare function applyDurablePatch(previous: Uint8Array, patch: DurablePatch): Uint8Array;
65
+ /** Validate before starting storage writes so invalid custom patches cannot partially commit. */
66
+ export declare function validateDurablePatch(patch: DurablePatch): void;
67
+ /** Reject missing replacement/new pages before an adapter changes the saved image. */
68
+ export declare function validateDurableCommit(patch: DurablePatch, previous?: {
69
+ byteLength: number;
70
+ pageSize: number;
71
+ }): void;
72
+ /** Reference adapter for tests and server-side ephemeral use. */
73
+ export declare class MemoryDurabilityBackend implements DurabilityBackend {
74
+ private readonly images;
75
+ load(key: string): Promise<DurableImage | undefined>;
76
+ commit(key: string, expectedRevision: number, patch: DurablePatch): Promise<number>;
77
+ }
78
+ //# sourceMappingURL=durability.d.ts.map
@@ -0,0 +1,51 @@
1
+ type Key = string | number | bigint;
2
+ /**
3
+ * An insertion-ordered map for primitive storage keys with O(1) forks. Writes detach
4
+ * two small hash directories, one native hash bucket, and a path of 32-cell order pages.
5
+ * Values retain ordinary Map reference semantics: callers own value-level copy-on-write.
6
+ */
7
+ export declare class ForkMap<K extends Key, V> implements Map<K, V> {
8
+ private owner;
9
+ private index;
10
+ private order;
11
+ private shift;
12
+ private length;
13
+ private count;
14
+ private nextSequence;
15
+ private layout;
16
+ private cleared;
17
+ private version;
18
+ constructor(entries?: Iterable<readonly [K, V]>);
19
+ get size(): number;
20
+ get [Symbol.toStringTag](): string;
21
+ fork(): ForkMap<K, V>;
22
+ /** Visit changed hash buckets only. Values must be replaced, rather than mutated in place. */
23
+ changes(previous?: ForkMap<K, V>): Iterable<{
24
+ key: K;
25
+ value: V;
26
+ deleted: false;
27
+ } | {
28
+ key: K;
29
+ deleted: true;
30
+ }>;
31
+ get(key: K): V | undefined;
32
+ has(key: K): boolean;
33
+ set(key: K, value: V): this;
34
+ delete(key: K): boolean;
35
+ clear(): void;
36
+ entries(): MapIterator<[K, V]>;
37
+ keys(): MapIterator<K>;
38
+ values(): MapIterator<V>;
39
+ [Symbol.iterator](): MapIterator<[K, V]>;
40
+ forEach(callback: (value: V, key: K, map: Map<K, V>) => void, thisArg?: unknown): void;
41
+ private find;
42
+ private bucket;
43
+ private writableBucket;
44
+ private copyBucket;
45
+ private leaf;
46
+ private writeOrder;
47
+ private compact;
48
+ private iterate;
49
+ }
50
+ export {};
51
+ //# sourceMappingURL=fork-map.d.ts.map
@@ -0,0 +1,4 @@
1
+ export * from "./durability.js"
2
+ export * from "./durability-browser.js"
3
+ export * from "./durability-buffered.js"
4
+ export { ForkMap } from "./fork-map.js"
@@ -0,0 +1,17 @@
1
+ import type { FetchAPI, FetchHandler } from "./index.js";
2
+ /** Trusted mount metadata stays on the Request, never in a spoofable HTTP header. */
3
+ export declare const requestBaseUrl: (request: Request) => string;
4
+ export declare const forwardMountContext: (source: Request, target: Request) => Request;
5
+ export type MountedAPI = FetchAPI & {
6
+ readonly prefix: string;
7
+ GET: FetchHandler;
8
+ POST: FetchHandler;
9
+ PUT: FetchHandler;
10
+ PATCH: FetchHandler;
11
+ DELETE: FetchHandler;
12
+ HEAD: FetchHandler;
13
+ OPTIONS: FetchHandler;
14
+ };
15
+ /** Embed a native API under an application's origin without owning another listener or state. */
16
+ export declare function mount(api: FetchAPI, path: string, relativePath?: (request: Request) => string): MountedAPI;
17
+ //# sourceMappingURL=mount.d.ts.map
@@ -0,0 +1,80 @@
1
+ /** A stable identifier for a point in a {@link Timeline}. */
2
+ export type CheckpointId = string;
3
+ /** An immutable node in a timeline's checkpoint DAG. */
4
+ export type Checkpoint<T> = Readonly<{
5
+ id: CheckpointId;
6
+ branch: string;
7
+ parent: CheckpointId | null;
8
+ /** Logical time supplied by the timeline's injected clock. */
9
+ at: number;
10
+ value: T;
11
+ }>;
12
+ export type TimelineOptions = {
13
+ /** Logical clock used to stamp checkpoints. Defaults to a deterministic counter. */
14
+ now?: () => number;
15
+ /** Maximum retained checkpoints. Branch heads are never collected. Default 1,000. */
16
+ maxCheckpoints?: number;
17
+ /** Customize deterministic checkpoint IDs. */
18
+ id?: (sequence: number) => CheckpointId;
19
+ };
20
+ export type CommitOptions = {
21
+ branch?: string;
22
+ /** Parent checkpoint. Defaults to the selected branch's current head. */
23
+ parent?: CheckpointId | null;
24
+ };
25
+ export type ForkOptions = {
26
+ /** Checkpoint to fork from. Defaults to the main branch's head. */
27
+ from?: CheckpointId;
28
+ };
29
+ /**
30
+ * Small, storage-agnostic checkpoint DAG shared by service runtimes. Its values may be immutable
31
+ * records, namespace images, or copy-on-write SQL engine snapshots.
32
+ *
33
+ * Values are retained by reference. Engines can therefore use persistent/COW snapshots while
34
+ * simpler services can use immutable values. IDs and GC order are deterministic, and all IO
35
+ * (the logical clock) is injected.
36
+ */
37
+ export declare class Timeline<T> {
38
+ readonly maxCheckpoints: number;
39
+ private readonly now;
40
+ private readonly makeId;
41
+ private readonly nodes;
42
+ private readonly heads;
43
+ /** Unreferenced nodes in the exact order they became collectible. */
44
+ private readonly evictable;
45
+ /** Branch heads plus explicit retainers. Absent means zero. */
46
+ private readonly references;
47
+ private readonly explicitPins;
48
+ private sequence;
49
+ constructor(options?: TimelineOptions);
50
+ /** Capture a new immutable value and move `branch` to it. */
51
+ commit(value: T, options?: CommitOptions): Checkpoint<T>;
52
+ /** Create a branch pointer without copying its checkpoint value. */
53
+ fork(branch: string, options?: ForkOptions): Checkpoint<T> | undefined;
54
+ /** Move a branch pointer to an existing checkpoint. */
55
+ checkout(branch: string, id: CheckpointId): Checkpoint<T>;
56
+ get(id: CheckpointId): Checkpoint<T>;
57
+ head(branch?: string): Checkpoint<T> | undefined;
58
+ hasBranch(branch: string): boolean;
59
+ branches(): Readonly<Record<string, CheckpointId>>;
60
+ checkpoints(): readonly Checkpoint<T>[];
61
+ /** Number of retained checkpoints without allocating an array. */
62
+ get size(): number;
63
+ /** Pin a checkpoint independently of branch heads (used by compatibility snapshot handles). */
64
+ retain(id: CheckpointId): Checkpoint<T>;
65
+ /** Release one explicit pin. Branch heads remain pinned until moved or deleted. */
66
+ release(id: CheckpointId): boolean;
67
+ deleteBranch(branch: string): boolean;
68
+ /**
69
+ * Deterministically discard oldest unpinned checkpoints. Collection is O(number removed):
70
+ * commits never scan pinned nodes or the retained history. Parents are metadata rather than a
71
+ * storage dependency, so a retained node remains usable after pruning.
72
+ */
73
+ gc(max?: number): CheckpointId[];
74
+ private collect;
75
+ private moveHead;
76
+ private addReference;
77
+ private removeReference;
78
+ private assertBranch;
79
+ }
80
+ //# sourceMappingURL=timeline.d.ts.map
@@ -100,6 +100,16 @@ export interface TriggerMeta {
100
100
  funcArgs: string[];
101
101
  }
102
102
  export declare class TableData {
103
+ #private;
104
+ durableNextId: number;
105
+ durableEpoch: object | undefined;
106
+ durableUnsafe: boolean;
107
+ private durableIds;
108
+ enableDurabilityTracking(ids?: readonly number[], nextId?: number): void;
109
+ durableRowId(row: Datum[]): number;
110
+ disableDurabilityTracking(): void;
111
+ recordDurableRow(row: Datum[], previous?: Datum[]): void;
112
+ recordDurableDelete(row: Datum[]): void;
103
113
  name: string;
104
114
  schema: string;
105
115
  columns: ColumnMeta[];
@@ -119,9 +129,16 @@ export declare class TableData {
119
129
  shareCount: number;
120
130
  /** Derived unique/btree index maps; null until built or invalidated. */
121
131
  indexStores: Map<string, import("../indexes/index.js").IndexStore> | null;
132
+ /** DML replaces tuples; DDL must detach them before changing cells in place. */
133
+ private tuplesShared;
122
134
  constructor(schema: string, name: string, columns: ColumnMeta[], oid: number, temp?: boolean);
123
135
  rowCount(): number;
124
136
  rowAt(index: number): Datum[];
137
+ /** Replace an existing tuple without copying the array of unchanged row references. */
138
+ replaceRow(index: number, row: Datum[]): void;
139
+ private materializedRows;
140
+ private nativeRows;
141
+ private setNativeRows;
125
142
  /** All rows for scans; materializes slab once into `rows` when needed. */
126
143
  allRows(): Datum[][];
127
144
  attachSlab(slab: ColumnarSlab): void;
@@ -132,7 +149,12 @@ export declare class TableData {
132
149
  freeze(): void;
133
150
  thaw(): void;
134
151
  columnIndex(name: string): number;
152
+ private cloneMetadata;
135
153
  clone(): TableData;
154
+ /** DML creates new tuple arrays; retain existing tuples and xmin bindings until DDL. */
155
+ cloneForDml(): TableData;
156
+ /** A live DML fork can be unfrozen while its unchanged tuples still belong to history. */
157
+ ownTuples(): void;
136
158
  /** Independent writable copy (row tuples copied so ALTER COLUMN is isolated). */
137
159
  cloneForWrite(): TableData;
138
160
  }
@@ -324,6 +346,7 @@ export declare class DatabaseState {
324
346
  freezeShared(): void;
325
347
  thawShared(): void;
326
348
  ensureWritableTable(table: TableData): TableData;
349
+ ensureWritableTableForDml(table: TableData): TableData;
327
350
  ensureWritableSequence(seq: SequenceData): SequenceData;
328
351
  ensureWritableView(view: ViewData): ViewData;
329
352
  ensureWritableEnum(en: EnumData): EnumData;