orez-sync-cf-host 0.5.19 → 0.5.21
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 +49 -6
- package/dist/bun-wasm-loader.d.ts +1 -0
- package/dist/bun-wasm-loader.js +20 -0
- package/dist/config.d.ts +3 -0
- package/dist/config.js +93 -0
- package/{src → dist}/generated/sync_wasm_bg.wasm +0 -0
- package/dist/host.d.ts +12 -0
- package/dist/host.js +1512 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +4 -0
- package/dist/mutation-error.d.ts +9 -0
- package/dist/mutation-error.js +23 -0
- package/dist/node-wasm-loader.d.ts +1 -0
- package/dist/node-wasm-loader.js +22 -0
- package/dist/post-commit.d.ts +13 -0
- package/dist/post-commit.js +31 -0
- package/dist/query-compiler.d.ts +4 -0
- package/dist/query-compiler.js +4 -0
- package/dist/sql-storage-adapter.d.ts +69 -0
- package/dist/sql-storage-adapter.js +194 -0
- package/dist/transaction-query.d.ts +72 -0
- package/dist/transaction-query.js +379 -0
- package/dist/types.d.ts +159 -0
- package/dist/types.js +5 -0
- package/dist/vite-wasm-loader.d.ts +3 -0
- package/dist/vite-wasm-loader.js +24 -0
- package/dist/wasm.d.ts +1 -0
- package/dist/wasm.js +7 -0
- package/dist/write-safeguards.d.ts +53 -0
- package/dist/write-safeguards.js +186 -0
- package/package.json +59 -19
- package/src/bun-wasm-loader.ts +0 -16
- package/src/config.ts +0 -102
- package/src/harness-config.ts +0 -487
- package/src/harness-worker.ts +0 -33
- package/src/host.ts +0 -1958
- package/src/index.ts +0 -47
- package/src/ingest-harness-worker.ts +0 -535
- package/src/mutation-error.ts +0 -28
- package/src/platform-probe-worker.ts +0 -418
- package/src/post-commit.ts +0 -40
- package/src/query-compiler.ts +0 -16
- package/src/sql-storage-adapter.ts +0 -254
- package/src/transaction-query.ts +0 -494
- package/src/types.ts +0 -195
- package/src/wasm-platform.ts +0 -10
- package/src/wasm.ts +0 -34
- package/src/write-safeguards.ts +0 -248
- /package/{src → dist}/generated/package.json +0 -0
- /package/{src → dist}/generated/sync_wasm.d.ts +0 -0
- /package/{src → dist}/generated/sync_wasm.js +0 -0
- /package/{src → dist}/generated/sync_wasm_bg.wasm.d.ts +0 -0
|
@@ -1,254 +0,0 @@
|
|
|
1
|
-
import { executeTransactionQueryPlan } from './transaction-query.js'
|
|
2
|
-
import { trackBillableCursorRows } from './write-safeguards.js'
|
|
3
|
-
|
|
4
|
-
import type {
|
|
5
|
-
CompiledTransactionQueryPlan,
|
|
6
|
-
TransactionQueryBudget,
|
|
7
|
-
TransactionQueryFormat,
|
|
8
|
-
} from './transaction-query.js'
|
|
9
|
-
import type { MutatorSql, SyncSql } from './types.js'
|
|
10
|
-
|
|
11
|
-
type WireValue =
|
|
12
|
-
| { kind: 'null' }
|
|
13
|
-
| { kind: 'integer'; value: string }
|
|
14
|
-
| { kind: 'real'; value: number }
|
|
15
|
-
| { kind: 'text'; value: string }
|
|
16
|
-
| { kind: 'blob'; value: number[] }
|
|
17
|
-
|
|
18
|
-
type WireRow = { columns: string[]; values: WireValue[] }
|
|
19
|
-
|
|
20
|
-
interface JsSyncDb {
|
|
21
|
-
exec(sql: string, params: WireValue[]): void
|
|
22
|
-
query(sql: string, params: WireValue[]): WireRow[]
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export type AdapterStats = {
|
|
26
|
-
execCalls: number
|
|
27
|
-
queryCalls: number
|
|
28
|
-
sqlMs: number
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
// Match transaction control only as the statement itself. CREATE TRIGGER uses
|
|
32
|
-
// `... BEGIN ... END` for its body, which is valid DO SQL and not a transaction.
|
|
33
|
-
const TX_SQL = /^\s*(BEGIN|COMMIT|ROLLBACK|SAVEPOINT|RELEASE)(?=\s|;|$)/i
|
|
34
|
-
const NUMBERED_PARAMETER = /\?[0-9]+/
|
|
35
|
-
const MAX_SAFE = BigInt(Number.MAX_SAFE_INTEGER)
|
|
36
|
-
const MIN_SAFE = BigInt(Number.MIN_SAFE_INTEGER)
|
|
37
|
-
|
|
38
|
-
export function assertHostSql(sql: string): void {
|
|
39
|
-
if (TX_SQL.test(sql)) {
|
|
40
|
-
throw new TypeError('transaction SQL is host-owned and forbidden')
|
|
41
|
-
}
|
|
42
|
-
if (NUMBERED_PARAMETER.test(sql)) {
|
|
43
|
-
throw new TypeError('numbered parameters are forbidden; use positional ? bindings')
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
function decodeBinding(value: unknown, path = 'binding'): unknown {
|
|
48
|
-
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
49
|
-
throw new TypeError(`${path} must be a typed SQL value`)
|
|
50
|
-
}
|
|
51
|
-
const binding = value as { kind?: unknown; value?: unknown }
|
|
52
|
-
const keys = Object.keys(binding)
|
|
53
|
-
const assertValueShape = () => {
|
|
54
|
-
if (keys.length !== 2 || !keys.includes('kind') || !keys.includes('value')) {
|
|
55
|
-
throw new TypeError(`${path} must contain only kind and value`)
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
switch (binding.kind) {
|
|
59
|
-
case 'null':
|
|
60
|
-
if (keys.length !== 1 || keys[0] !== 'kind') {
|
|
61
|
-
throw new TypeError(`${path} null binding must contain only kind`)
|
|
62
|
-
}
|
|
63
|
-
return null
|
|
64
|
-
case 'integer': {
|
|
65
|
-
assertValueShape()
|
|
66
|
-
if (typeof binding.value !== 'string') {
|
|
67
|
-
throw new TypeError(`${path}.value must be an i64 decimal string`)
|
|
68
|
-
}
|
|
69
|
-
if (!/^-?\d+$/.test(binding.value)) {
|
|
70
|
-
throw new TypeError(`${path}.value must be an i64 decimal string`)
|
|
71
|
-
}
|
|
72
|
-
let exact: bigint
|
|
73
|
-
try {
|
|
74
|
-
exact = BigInt(binding.value)
|
|
75
|
-
} catch {
|
|
76
|
-
throw new TypeError(`${path}.value must be an i64 decimal string`)
|
|
77
|
-
}
|
|
78
|
-
if (exact < -(1n << 63n) || exact > (1n << 63n) - 1n) {
|
|
79
|
-
throw new TypeError(`${path}.value is outside the i64 range`)
|
|
80
|
-
}
|
|
81
|
-
// SqlStorage does not accept bigint. Safe values can use Number; unsafe
|
|
82
|
-
// values use decimal text and rely on the destination's INTEGER affinity.
|
|
83
|
-
return exact >= MIN_SAFE && exact <= MAX_SAFE ? Number(exact) : binding.value
|
|
84
|
-
}
|
|
85
|
-
case 'real': {
|
|
86
|
-
assertValueShape()
|
|
87
|
-
if (typeof binding.value !== 'number' || !Number.isFinite(binding.value)) {
|
|
88
|
-
throw new TypeError(`${path}.value must be a finite number`)
|
|
89
|
-
}
|
|
90
|
-
return binding.value
|
|
91
|
-
}
|
|
92
|
-
case 'text': {
|
|
93
|
-
assertValueShape()
|
|
94
|
-
if (typeof binding.value !== 'string') {
|
|
95
|
-
throw new TypeError(`${path}.value must be a string`)
|
|
96
|
-
}
|
|
97
|
-
return binding.value
|
|
98
|
-
}
|
|
99
|
-
case 'blob': {
|
|
100
|
-
assertValueShape()
|
|
101
|
-
if (
|
|
102
|
-
!Array.isArray(binding.value) ||
|
|
103
|
-
binding.value.some((byte) => !Number.isInteger(byte) || byte < 0 || byte > 255)
|
|
104
|
-
) {
|
|
105
|
-
throw new TypeError(`${path}.value must be an array of bytes`)
|
|
106
|
-
}
|
|
107
|
-
return Uint8Array.from(binding.value).buffer
|
|
108
|
-
}
|
|
109
|
-
default:
|
|
110
|
-
throw new TypeError(`${path}.kind must be null, integer, real, text, or blob`)
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
export function decodeSqlParams(value: unknown): unknown[] {
|
|
115
|
-
if (value === undefined) return []
|
|
116
|
-
if (!Array.isArray(value)) throw new TypeError('params must be an array')
|
|
117
|
-
return value.map((binding, index) => decodeBinding(binding, `params[${index}]`))
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
function encodeResult(value: unknown): WireValue {
|
|
121
|
-
if (value === null) return { kind: 'null' }
|
|
122
|
-
if (typeof value === 'number') {
|
|
123
|
-
return Number.isInteger(value)
|
|
124
|
-
? { kind: 'integer', value: String(value) }
|
|
125
|
-
: { kind: 'real', value }
|
|
126
|
-
}
|
|
127
|
-
if (typeof value === 'string') return { kind: 'text', value }
|
|
128
|
-
if (value instanceof ArrayBuffer) {
|
|
129
|
-
return { kind: 'blob', value: Array.from(new Uint8Array(value)) }
|
|
130
|
-
}
|
|
131
|
-
if (ArrayBuffer.isView(value)) {
|
|
132
|
-
return {
|
|
133
|
-
kind: 'blob',
|
|
134
|
-
value: Array.from(new Uint8Array(value.buffer, value.byteOffset, value.byteLength)),
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
throw new TypeError(
|
|
138
|
-
`unsupported SqlStorage result: ${Object.prototype.toString.call(value)}`
|
|
139
|
-
)
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
/**
|
|
143
|
-
* The sole JS SQL adapter used by wasm. It is synchronous, consumes every
|
|
144
|
-
* cursor before returning, accepts positional `?` only, and never starts or
|
|
145
|
-
* finishes a transaction.
|
|
146
|
-
*/
|
|
147
|
-
export class SqlStorageSyncDb implements JsSyncDb {
|
|
148
|
-
readonly stats: AdapterStats = { execCalls: 0, queryCalls: 0, sqlMs: 0 }
|
|
149
|
-
|
|
150
|
-
constructor(
|
|
151
|
-
private readonly sql: SqlStorage,
|
|
152
|
-
private readonly recordRowsWritten: (rows: number) => void = () => {}
|
|
153
|
-
) {}
|
|
154
|
-
|
|
155
|
-
resetStats(): void {
|
|
156
|
-
this.stats.execCalls = 0
|
|
157
|
-
this.stats.queryCalls = 0
|
|
158
|
-
this.stats.sqlMs = 0
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
exec(sql: string, params: WireValue[]): void {
|
|
162
|
-
assertHostSql(sql)
|
|
163
|
-
const start = performance.now()
|
|
164
|
-
trackBillableCursorRows(
|
|
165
|
-
this.sql.exec(sql, ...params.map((value) => decodeBinding(value))),
|
|
166
|
-
this.recordRowsWritten
|
|
167
|
-
)
|
|
168
|
-
this.stats.execCalls++
|
|
169
|
-
this.stats.sqlMs += performance.now() - start
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
query(sql: string, params: WireValue[]): WireRow[] {
|
|
173
|
-
assertHostSql(sql)
|
|
174
|
-
const start = performance.now()
|
|
175
|
-
const cursor = trackBillableCursorRows(
|
|
176
|
-
this.sql.exec(sql, ...params.map((value) => decodeBinding(value))),
|
|
177
|
-
this.recordRowsWritten
|
|
178
|
-
)
|
|
179
|
-
const columns = [...cursor.columnNames]
|
|
180
|
-
// A SqlStorage cursor must be fully consumed before any await. Returning a
|
|
181
|
-
// materialized array here makes that property structural.
|
|
182
|
-
const rows = Array.from(cursor.raw()).map((values) => ({
|
|
183
|
-
columns,
|
|
184
|
-
values: values.map(encodeResult),
|
|
185
|
-
}))
|
|
186
|
-
this.stats.queryCalls++
|
|
187
|
-
this.stats.sqlMs += performance.now() - start
|
|
188
|
-
return rows
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
/** Direct application SQL surface used for initialization and admin reads. */
|
|
193
|
-
export class SqlStorageDirect implements SyncSql {
|
|
194
|
-
constructor(
|
|
195
|
-
private readonly sql: SqlStorage,
|
|
196
|
-
private readonly recordRowsWritten: (rows: number) => void = () => {}
|
|
197
|
-
) {}
|
|
198
|
-
|
|
199
|
-
exec(sql: string, params: readonly unknown[] = []): void {
|
|
200
|
-
assertHostSql(sql)
|
|
201
|
-
trackBillableCursorRows(this.sql.exec(sql, ...params), this.recordRowsWritten)
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
query<Row extends Record<string, unknown> = Record<string, unknown>>(
|
|
205
|
-
sql: string,
|
|
206
|
-
params: readonly unknown[] = []
|
|
207
|
-
): Row[] {
|
|
208
|
-
assertHostSql(sql)
|
|
209
|
-
return trackBillableCursorRows(
|
|
210
|
-
this.sql.exec(sql, ...params),
|
|
211
|
-
this.recordRowsWritten
|
|
212
|
-
).toArray() as Row[]
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
/**
|
|
217
|
-
* Async-compatible consumer mutator surface. Each method fully completes and
|
|
218
|
-
* materializes its SqlStorage operation before its promise resolves, so an
|
|
219
|
-
* existing `await tx.query(...)` cannot carry a cursor across an await.
|
|
220
|
-
*/
|
|
221
|
-
export class SqlStorageMutatorTransaction implements MutatorSql {
|
|
222
|
-
constructor(
|
|
223
|
-
private readonly direct: SqlStorageDirect,
|
|
224
|
-
private readonly compileQuery: (
|
|
225
|
-
ast: unknown,
|
|
226
|
-
format: TransactionQueryFormat
|
|
227
|
-
) => CompiledTransactionQueryPlan,
|
|
228
|
-
private readonly queryBudget?: Partial<TransactionQueryBudget>
|
|
229
|
-
) {}
|
|
230
|
-
|
|
231
|
-
async exec(sql: string, params: readonly unknown[] = []): Promise<void> {
|
|
232
|
-
this.direct.exec(sql, params)
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
async query<Row extends Record<string, unknown> = Record<string, unknown>>(
|
|
236
|
-
sql: string,
|
|
237
|
-
params: readonly unknown[] = []
|
|
238
|
-
): Promise<Row[]> {
|
|
239
|
-
return this.direct.query<Row>(sql, params)
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
async queryAst<Result = unknown>(
|
|
243
|
-
ast: unknown,
|
|
244
|
-
format: TransactionQueryFormat,
|
|
245
|
-
queryName?: string
|
|
246
|
-
): Promise<Result> {
|
|
247
|
-
const compiled = this.compileQuery(ast, format)
|
|
248
|
-
return executeTransactionQueryPlan<Result>(
|
|
249
|
-
compiled,
|
|
250
|
-
(sql, params) => this.direct.query(sql, params),
|
|
251
|
-
{ queryName, budget: this.queryBudget }
|
|
252
|
-
)
|
|
253
|
-
}
|
|
254
|
-
}
|