orez 0.4.71 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +42 -1
- package/dist/cf-do/cdc.d.ts +148 -0
- package/dist/cf-do/cdc.d.ts.map +1 -0
- package/dist/cf-do/cdc.js +719 -0
- package/dist/cf-do/cdc.js.map +1 -0
- package/dist/cf-do/row-undo.d.ts +36 -0
- package/dist/cf-do/row-undo.d.ts.map +1 -0
- package/dist/cf-do/row-undo.js +209 -0
- package/dist/cf-do/row-undo.js.map +1 -0
- package/dist/cf-do/tx-journal.d.ts +32 -10
- package/dist/cf-do/tx-journal.d.ts.map +1 -1
- package/dist/cf-do/tx-journal.js +148 -31
- package/dist/cf-do/tx-journal.js.map +1 -1
- package/dist/cf-do/watermark.d.ts +7 -0
- package/dist/cf-do/watermark.d.ts.map +1 -1
- package/dist/cf-do/watermark.js +9 -0
- package/dist/cf-do/watermark.js.map +1 -1
- package/dist/cf-do/worker.d.ts +19 -1
- package/dist/cf-do/worker.d.ts.map +1 -1
- package/dist/cf-do/worker.js +218 -46
- package/dist/cf-do/worker.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +1 -0
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +35 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +1 -0
- package/dist/config.js.map +1 -1
- package/dist/do-sql-tracking.d.ts +2 -0
- package/dist/do-sql-tracking.d.ts.map +1 -1
- package/dist/do-sql-tracking.js +11 -1
- package/dist/do-sql-tracking.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +146 -40
- package/dist/index.js.map +1 -1
- package/dist/pg-proxy-do-backend.d.ts +8 -0
- package/dist/pg-proxy-do-backend.d.ts.map +1 -1
- package/dist/pg-proxy-do-backend.js +301 -47
- package/dist/pg-proxy-do-backend.js.map +1 -1
- package/dist/pg-proxy.d.ts +22 -1
- package/dist/pg-proxy.d.ts.map +1 -1
- package/dist/pg-proxy.js +63 -1
- package/dist/pg-proxy.js.map +1 -1
- package/dist/pg-sqlite-compiler/index.d.ts.map +1 -1
- package/dist/pg-sqlite-compiler/index.js +9 -1
- package/dist/pg-sqlite-compiler/index.js.map +1 -1
- package/dist/pg-sqlite-compiler/passes/datetime.d.ts +2 -0
- package/dist/pg-sqlite-compiler/passes/datetime.d.ts.map +1 -1
- package/dist/pg-sqlite-compiler/passes/datetime.js +20 -18
- package/dist/pg-sqlite-compiler/passes/datetime.js.map +1 -1
- package/dist/pg-sqlite-compiler/passes/index.d.ts.map +1 -1
- package/dist/pg-sqlite-compiler/passes/index.js +4 -0
- package/dist/pg-sqlite-compiler/passes/index.js.map +1 -1
- package/dist/pg-sqlite-compiler/passes/row-json.d.ts +3 -0
- package/dist/pg-sqlite-compiler/passes/row-json.d.ts.map +1 -0
- package/dist/pg-sqlite-compiler/passes/row-json.js +230 -0
- package/dist/pg-sqlite-compiler/passes/row-json.js.map +1 -0
- package/dist/pg-sqlite-compiler/passes/schema.d.ts.map +1 -1
- package/dist/pg-sqlite-compiler/passes/schema.js +16 -1
- package/dist/pg-sqlite-compiler/passes/schema.js.map +1 -1
- package/dist/pg-sqlite-compiler/passes/string-functions.d.ts +11 -0
- package/dist/pg-sqlite-compiler/passes/string-functions.d.ts.map +1 -0
- package/dist/pg-sqlite-compiler/passes/string-functions.js +37 -0
- package/dist/pg-sqlite-compiler/passes/string-functions.js.map +1 -0
- package/dist/worker/local-sql-backend.d.ts.map +1 -1
- package/dist/worker/local-sql-backend.js +114 -13
- package/dist/worker/local-sql-backend.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -186,7 +186,48 @@ All options are optional with sensible defaults.
|
|
|
186
186
|
| on-db-ready | `--on-db-ready=CMD` | `onDbReady: 'CMD'` or `onDbReady: fn` | after db + proxy ready, before zero |
|
|
187
187
|
| on-healthy | `--on-healthy=CMD` | `onHealthy: 'CMD'` or `onHealthy: fn` | after all services ready |
|
|
188
188
|
|
|
189
|
-
Shell commands receive env vars: `DATABASE_URL`, `OREZ_PG_PORT`, `OREZ_ZERO_PORT`.
|
|
189
|
+
Shell commands receive env vars: `DATABASE_URL`, `OREZ_PG_PORT`, `OREZ_ZERO_PORT`.
|
|
190
|
+
On the PGlite backend, change-tracking triggers are re-installed after
|
|
191
|
+
`onDbReady`.
|
|
192
|
+
|
|
193
|
+
#### Startup blocking and the callback context
|
|
194
|
+
|
|
195
|
+
`onDbReady` runs before zero-cache. On the PGlite and DO proxy backends, shell
|
|
196
|
+
hooks and context-aware callbacks hold every ordinary PG client at connection
|
|
197
|
+
startup until `onDbReady` returns, so an early application `SELECT` can't race
|
|
198
|
+
schema provisioning (or monopolize the shared DB mutex while a migration is
|
|
199
|
+
still creating tables).
|
|
200
|
+
|
|
201
|
+
- **Shell command:** receives the tagged connection strings via
|
|
202
|
+
`ZERO_UPSTREAM_DB` / `ZERO_CVR_DB` / `ZERO_CHANGE_DB` / `DATABASE_URL`, plus
|
|
203
|
+
`PGAPPNAME`. Connecting with any of these bypasses the barrier.
|
|
204
|
+
- **Context-aware callback:** declare a context parameter to opt into the
|
|
205
|
+
barrier and receive its privileged connection strings:
|
|
206
|
+
|
|
207
|
+
```typescript
|
|
208
|
+
onDbReady: async (ctx) => {
|
|
209
|
+
// ctx.upstreamConnectionString / cvrConnectionString / cdbConnectionString
|
|
210
|
+
// are tagged so they bypass the startup barrier; ctx.applicationName is the
|
|
211
|
+
// tag itself (for clients that set application_name separately), and
|
|
212
|
+
// ctx.pgPort is the proxy port.
|
|
213
|
+
const sql = postgres(ctx.upstreamConnectionString)
|
|
214
|
+
await sql`CREATE TABLE ...`
|
|
215
|
+
await sql.end()
|
|
216
|
+
}
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
A context-aware callback **must** provision through one of these privileged
|
|
220
|
+
connections. An ordinary (untagged) connection is held by the same barrier;
|
|
221
|
+
if the hook does that accidentally, the connection fails after a bounded wait
|
|
222
|
+
with an error pointing back to `HookContext` instead of hanging forever. Both
|
|
223
|
+
the hook and barrier default to a 30-second deadline; set
|
|
224
|
+
`onDbReadyTimeoutMs` higher for a legitimately longer migration.
|
|
225
|
+
|
|
226
|
+
- **Legacy callback:** a zero-argument callback (`onDbReady: async () => { ... }`)
|
|
227
|
+
does not opt into the barrier. It keeps the behavior from orez v0.4.73 and
|
|
228
|
+
earlier, including the ability to open its existing ordinary proxy connection.
|
|
229
|
+
Callback arity is the runtime contract, so callbacks that need the context
|
|
230
|
+
should declare `ctx` without a default value or rest-parameter wrapper.
|
|
190
231
|
|
|
191
232
|
## Vite Plugin
|
|
192
233
|
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import type { DurableSqlStorage } from './watermark.js';
|
|
2
|
+
/** Bump whenever the generated trigger bodies or buffer shape change. */
|
|
3
|
+
export declare const CDC_SCHEMA_VERSION = 2;
|
|
4
|
+
export interface CdcTableRegistration {
|
|
5
|
+
/** Physical, flattened SQLite table name. */
|
|
6
|
+
physicalTableName: string;
|
|
7
|
+
/** Schema-qualified identity exposed in `_zero_changes`. */
|
|
8
|
+
tableName: string;
|
|
9
|
+
/** Optional known column list. The live SQLite schema remains authoritative. */
|
|
10
|
+
columns?: string[];
|
|
11
|
+
/** False captures before/after images for transaction rollback only. */
|
|
12
|
+
publish?: boolean;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* A row image in storage-journal form: one tagged string per column, carrying
|
|
16
|
+
* the value's SQLite storage class and an exact, lossless payload. This is the
|
|
17
|
+
* undo encoding, deliberately separate from the Zero wire encoding that
|
|
18
|
+
* `journalToWire` derives.
|
|
19
|
+
*/
|
|
20
|
+
export type JournalRecord = Record<string, string>;
|
|
21
|
+
export interface CapturedRowChange {
|
|
22
|
+
physicalTableName: string;
|
|
23
|
+
tableName: string;
|
|
24
|
+
op: 'INSERT' | 'UPDATE' | 'DELETE';
|
|
25
|
+
/** Zero wire image (JSON-safe; blobs as postgres bytea text). */
|
|
26
|
+
rowData: Record<string, unknown> | null;
|
|
27
|
+
oldData: Record<string, unknown> | null;
|
|
28
|
+
/** Lossless storage-journal image used only for undo. */
|
|
29
|
+
rowJournal: JournalRecord | null;
|
|
30
|
+
oldJournal: JournalRecord | null;
|
|
31
|
+
/** Exact decimal rowid text, or null for WITHOUT ROWID tables. */
|
|
32
|
+
newRowid: string | null;
|
|
33
|
+
oldRowid: string | null;
|
|
34
|
+
/** Omitted for normal published changes; false means rollback-only. */
|
|
35
|
+
publish?: boolean;
|
|
36
|
+
}
|
|
37
|
+
export interface SuspendedCdcTable {
|
|
38
|
+
physicalTableName: string;
|
|
39
|
+
tableName: string;
|
|
40
|
+
publish?: boolean;
|
|
41
|
+
}
|
|
42
|
+
/** Stable-identity and writability metadata read from the live SQLite schema. */
|
|
43
|
+
export interface TableIdentity {
|
|
44
|
+
/** rowid alias usable in SQL, or null for a WITHOUT ROWID table. */
|
|
45
|
+
rowidAlias: string | null;
|
|
46
|
+
/** The INTEGER PRIMARY KEY column, which *is* the rowid, when one exists. */
|
|
47
|
+
rowidColumn: string | null;
|
|
48
|
+
/** Declared primary-key columns in key order. */
|
|
49
|
+
keyColumns: string[];
|
|
50
|
+
/** Columns undo may write. Excludes generated columns. */
|
|
51
|
+
writableColumns: string[];
|
|
52
|
+
/** Every column captured in a row image, generated columns included. */
|
|
53
|
+
columns: string[];
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Rebuild the exact SQLite value for an undo statement. Integers and reals go
|
|
57
|
+
* back through CAST so the full int64 range and every double survive without
|
|
58
|
+
* depending on the driver's numeric binding.
|
|
59
|
+
*/
|
|
60
|
+
export declare function journalValueSqlBinding(encoded: string): {
|
|
61
|
+
expr: string;
|
|
62
|
+
params: unknown[];
|
|
63
|
+
};
|
|
64
|
+
export declare function parseJournalRecord(value: unknown): JournalRecord | null;
|
|
65
|
+
/**
|
|
66
|
+
* Read stable-identity metadata from the live schema. Returns null when the
|
|
67
|
+
* table cannot be undone row-by-row (no rowid and no primary key), which keeps
|
|
68
|
+
* capture off it entirely so the caller falls back to table snapshots.
|
|
69
|
+
*/
|
|
70
|
+
export declare function tableIdentity(sql: DurableSqlStorage, table: string): TableIdentity | null;
|
|
71
|
+
export interface TriggerDefinition {
|
|
72
|
+
name: string;
|
|
73
|
+
sql: string;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Drop every trigger on these tables and return their definitions.
|
|
77
|
+
*
|
|
78
|
+
* A restore must not fire the table's own business triggers. Undoing an INSERT
|
|
79
|
+
* with a DELETE would run its AFTER DELETE trigger and write side effects the
|
|
80
|
+
* original transaction never made, and if that side effect lands on a captured
|
|
81
|
+
* table, its CDC trigger stages a phantom change on top. Dropping only the
|
|
82
|
+
* generated CDC triggers leaves both holes open, so every trigger goes.
|
|
83
|
+
*/
|
|
84
|
+
export declare function suspendTriggers(sql: DurableSqlStorage, tables: Iterable<string>): TriggerDefinition[];
|
|
85
|
+
/** Recreate triggers suspended for a restore, verbatim. */
|
|
86
|
+
export declare function restoreTriggers(sql: DurableSqlStorage, triggers: TriggerDefinition[]): void;
|
|
87
|
+
/** The columns a restore is allowed to write. Empty when the table is gone. */
|
|
88
|
+
export declare function writableColumns(sql: DurableSqlStorage, table: string): string[];
|
|
89
|
+
/**
|
|
90
|
+
* Transactional logical-row capture for the authoritative SQLite database.
|
|
91
|
+
*
|
|
92
|
+
* Generated AFTER triggers write full before/after row images to a staging
|
|
93
|
+
* table in the same SQLite statement as the application write. The owner
|
|
94
|
+
* drains that staging table before its storage transaction returns and moves
|
|
95
|
+
* the rows to either `_zero_changes` or `_zero_pending_changes`. Consequently
|
|
96
|
+
* a failed statement or storage transaction cannot leave an orphaned change.
|
|
97
|
+
*
|
|
98
|
+
* Every mutator of the in-memory registration cache runs inside the owner's
|
|
99
|
+
* storage transaction, so the cache can outlive an abort that rolled its SQLite
|
|
100
|
+
* side back. `reload()` re-derives the whole cache from SQLite and MUST be
|
|
101
|
+
* called on any aborted transaction; see `atomically` in worker.ts.
|
|
102
|
+
*/
|
|
103
|
+
export declare class TransactionalCdc {
|
|
104
|
+
#private;
|
|
105
|
+
private readonly sql;
|
|
106
|
+
constructor(sql: DurableSqlStorage);
|
|
107
|
+
get active(): boolean;
|
|
108
|
+
/** Force the next per-table ensure to re-read SQLite's live schema. */
|
|
109
|
+
invalidateSchema(): void;
|
|
110
|
+
/**
|
|
111
|
+
* Re-derive every cached decision from SQLite. Called after an aborted
|
|
112
|
+
* storage transaction, where SQLite rolled back the trigger and metadata
|
|
113
|
+
* writes but this object still remembers making them. Without it a table can
|
|
114
|
+
* stay "registered and verified" in memory with no trigger on disk, and every
|
|
115
|
+
* later write to it is silently uncaptured.
|
|
116
|
+
*/
|
|
117
|
+
reload(): void;
|
|
118
|
+
private loadRegistrations;
|
|
119
|
+
private ensureTables;
|
|
120
|
+
private tableExists;
|
|
121
|
+
private triggersExist;
|
|
122
|
+
private registered;
|
|
123
|
+
capturesTable(tableName: string): boolean;
|
|
124
|
+
/** True when a DDL statement must atomically suspend and rebuild CDC triggers. */
|
|
125
|
+
capturesSchemaChange(sql: string): boolean;
|
|
126
|
+
private dropTriggers;
|
|
127
|
+
/**
|
|
128
|
+
* Drop generated triggers before SQLite rewrites a captured table. SQLite
|
|
129
|
+
* refuses DROP/RENAME COLUMN while any trigger still references the old row
|
|
130
|
+
* shape. The caller must run this, the DDL, and finishSchemaChange in one
|
|
131
|
+
* storage transaction so capture is never observably disabled.
|
|
132
|
+
*/
|
|
133
|
+
beginSchemaChange(sql: string): SuspendedCdcTable[];
|
|
134
|
+
/** Re-introspect changed tables and rebuild their triggers from the live shape. */
|
|
135
|
+
finishSchemaChange(suspended: SuspendedCdcTable[]): void;
|
|
136
|
+
private installTriggers;
|
|
137
|
+
/**
|
|
138
|
+
* Ensure one table is captured. Returns false when the table does not exist
|
|
139
|
+
* or cannot be undone row-by-row, which leaves the caller on its table
|
|
140
|
+
* snapshot path rather than capturing changes it could never roll back.
|
|
141
|
+
*/
|
|
142
|
+
ensureTable(registration: CdcTableRegistration, refresh?: boolean): boolean;
|
|
143
|
+
/** Replace the captured-table set with the caller's authoritative list. */
|
|
144
|
+
syncTables(registrations: CdcTableRegistration[]): void;
|
|
145
|
+
/** Drain all changes captured by the just-completed SQLite statement. */
|
|
146
|
+
drain(): CapturedRowChange[];
|
|
147
|
+
}
|
|
148
|
+
//# sourceMappingURL=cdc.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cdc.d.ts","sourceRoot":"","sources":["../../src/cf-do/cdc.ts"],"names":[],"mappings":"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"}
|