orez-lite 0.9.7

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.
Files changed (190) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +12 -0
  3. package/dist/browser/generated/sqlite3-browser.wasm +0 -0
  4. package/dist/browser/generated/sync_wasm.js +922 -0
  5. package/dist/browser/generated/sync_wasm_bg.wasm +0 -0
  6. package/dist/browser/host.d.ts +10 -0
  7. package/dist/browser/host.d.ts.map +1 -0
  8. package/dist/browser/host.js +496 -0
  9. package/dist/browser/host.js.map +1 -0
  10. package/dist/browser/idb-snapshot.d.ts +11 -0
  11. package/dist/browser/idb-snapshot.d.ts.map +1 -0
  12. package/dist/browser/idb-snapshot.js +122 -0
  13. package/dist/browser/idb-snapshot.js.map +1 -0
  14. package/dist/browser/index.d.ts +5 -0
  15. package/dist/browser/index.d.ts.map +1 -0
  16. package/dist/browser/index.js +5 -0
  17. package/dist/browser/index.js.map +1 -0
  18. package/dist/browser/message-port.d.ts +7 -0
  19. package/dist/browser/message-port.d.ts.map +1 -0
  20. package/dist/browser/message-port.js +188 -0
  21. package/dist/browser/message-port.js.map +1 -0
  22. package/dist/browser/sqlite-adapter.d.ts +53 -0
  23. package/dist/browser/sqlite-adapter.d.ts.map +1 -0
  24. package/dist/browser/sqlite-adapter.js +126 -0
  25. package/dist/browser/sqlite-adapter.js.map +1 -0
  26. package/dist/browser/types.d.ts +52 -0
  27. package/dist/browser/types.d.ts.map +1 -0
  28. package/dist/browser/types.js +2 -0
  29. package/dist/browser/types.js.map +1 -0
  30. package/dist/cf-deploy/bundle.d.ts +18 -0
  31. package/dist/cf-deploy/bundle.d.ts.map +1 -0
  32. package/dist/cf-deploy/bundle.js +273 -0
  33. package/dist/cf-deploy/bundle.js.map +1 -0
  34. package/dist/cf-deploy/config.d.ts +12 -0
  35. package/dist/cf-deploy/config.d.ts.map +1 -0
  36. package/dist/cf-deploy/config.js +11 -0
  37. package/dist/cf-deploy/config.js.map +1 -0
  38. package/dist/cf-deploy/index.d.ts +10 -0
  39. package/dist/cf-deploy/index.d.ts.map +1 -0
  40. package/dist/cf-deploy/index.js +12 -0
  41. package/dist/cf-deploy/index.js.map +1 -0
  42. package/dist/cf-deploy/leaves.d.ts +8 -0
  43. package/dist/cf-deploy/leaves.d.ts.map +1 -0
  44. package/dist/cf-deploy/leaves.js +66 -0
  45. package/dist/cf-deploy/leaves.js.map +1 -0
  46. package/dist/cf-deploy/migration.d.ts +27 -0
  47. package/dist/cf-deploy/migration.d.ts.map +1 -0
  48. package/dist/cf-deploy/migration.js +734 -0
  49. package/dist/cf-deploy/migration.js.map +1 -0
  50. package/dist/cf-deploy/nativeMigrations.d.ts +24 -0
  51. package/dist/cf-deploy/nativeMigrations.d.ts.map +1 -0
  52. package/dist/cf-deploy/nativeMigrations.js +185 -0
  53. package/dist/cf-deploy/nativeMigrations.js.map +1 -0
  54. package/dist/cf-deploy/prune.d.ts +14 -0
  55. package/dist/cf-deploy/prune.d.ts.map +1 -0
  56. package/dist/cf-deploy/prune.js +235 -0
  57. package/dist/cf-deploy/prune.js.map +1 -0
  58. package/dist/cf-deploy/readiness.d.ts +11 -0
  59. package/dist/cf-deploy/readiness.d.ts.map +1 -0
  60. package/dist/cf-deploy/readiness.js +56 -0
  61. package/dist/cf-deploy/readiness.js.map +1 -0
  62. package/dist/cf-deploy/sources.d.ts +3 -0
  63. package/dist/cf-deploy/sources.d.ts.map +1 -0
  64. package/dist/cf-deploy/sources.js +24 -0
  65. package/dist/cf-deploy/sources.js.map +1 -0
  66. package/dist/cf-deploy/wrangler.d.ts +9 -0
  67. package/dist/cf-deploy/wrangler.d.ts.map +1 -0
  68. package/dist/cf-deploy/wrangler.js +48 -0
  69. package/dist/cf-deploy/wrangler.js.map +1 -0
  70. package/dist/cf-do/application-sql.d.ts +49 -0
  71. package/dist/cf-do/application-sql.d.ts.map +1 -0
  72. package/dist/cf-do/application-sql.js +124 -0
  73. package/dist/cf-do/application-sql.js.map +1 -0
  74. package/dist/cf-do/cdc.d.ts +155 -0
  75. package/dist/cf-do/cdc.d.ts.map +1 -0
  76. package/dist/cf-do/cdc.js +723 -0
  77. package/dist/cf-do/cdc.js.map +1 -0
  78. package/dist/cf-do/cursor-pull.d.ts +27 -0
  79. package/dist/cf-do/cursor-pull.d.ts.map +1 -0
  80. package/dist/cf-do/cursor-pull.js +78 -0
  81. package/dist/cf-do/cursor-pull.js.map +1 -0
  82. package/dist/cf-do/lite-data-worker.d.ts +171 -0
  83. package/dist/cf-do/lite-data-worker.d.ts.map +1 -0
  84. package/dist/cf-do/lite-data-worker.js +685 -0
  85. package/dist/cf-do/lite-data-worker.js.map +1 -0
  86. package/dist/cf-do/namespace-backup.d.ts +85 -0
  87. package/dist/cf-do/namespace-backup.d.ts.map +1 -0
  88. package/dist/cf-do/namespace-backup.js +470 -0
  89. package/dist/cf-do/namespace-backup.js.map +1 -0
  90. package/dist/cf-do/row-undo.d.ts +36 -0
  91. package/dist/cf-do/row-undo.d.ts.map +1 -0
  92. package/dist/cf-do/row-undo.js +221 -0
  93. package/dist/cf-do/row-undo.js.map +1 -0
  94. package/dist/cf-do/tx-journal.d.ts +118 -0
  95. package/dist/cf-do/tx-journal.d.ts.map +1 -0
  96. package/dist/cf-do/tx-journal.js +717 -0
  97. package/dist/cf-do/tx-journal.js.map +1 -0
  98. package/dist/cf-do/watermark.d.ts +29 -0
  99. package/dist/cf-do/watermark.d.ts.map +1 -0
  100. package/dist/cf-do/watermark.js +105 -0
  101. package/dist/cf-do/watermark.js.map +1 -0
  102. package/dist/cf-do/worker.d.ts +282 -0
  103. package/dist/cf-do/worker.d.ts.map +1 -0
  104. package/dist/cf-do/worker.js +1999 -0
  105. package/dist/cf-do/worker.js.map +1 -0
  106. package/dist/client.d.ts +2 -0
  107. package/dist/client.d.ts.map +1 -0
  108. package/dist/client.js +2 -0
  109. package/dist/client.js.map +1 -0
  110. package/dist/cloudflare-build.d.ts +9 -0
  111. package/dist/cloudflare-build.d.ts.map +1 -0
  112. package/dist/cloudflare-build.js +9 -0
  113. package/dist/cloudflare-build.js.map +1 -0
  114. package/dist/cloudflare-bun-wasm-loader.d.ts +2 -0
  115. package/dist/cloudflare-bun-wasm-loader.d.ts.map +1 -0
  116. package/dist/cloudflare-bun-wasm-loader.js +2 -0
  117. package/dist/cloudflare-bun-wasm-loader.js.map +1 -0
  118. package/dist/cloudflare-query-compiler.d.ts +2 -0
  119. package/dist/cloudflare-query-compiler.d.ts.map +1 -0
  120. package/dist/cloudflare-query-compiler.js +2 -0
  121. package/dist/cloudflare-query-compiler.js.map +1 -0
  122. package/dist/cloudflare-runtime.d.ts +15 -0
  123. package/dist/cloudflare-runtime.d.ts.map +1 -0
  124. package/dist/cloudflare-runtime.js +11 -0
  125. package/dist/cloudflare-runtime.js.map +1 -0
  126. package/dist/cloudflare-sync.d.ts +3 -0
  127. package/dist/cloudflare-sync.d.ts.map +1 -0
  128. package/dist/cloudflare-sync.js +3 -0
  129. package/dist/cloudflare-sync.js.map +1 -0
  130. package/dist/cloudflare-transaction-query.d.ts +2 -0
  131. package/dist/cloudflare-transaction-query.d.ts.map +1 -0
  132. package/dist/cloudflare-transaction-query.js +2 -0
  133. package/dist/cloudflare-transaction-query.js.map +1 -0
  134. package/dist/cloudflare-vite-wasm-loader.d.ts +2 -0
  135. package/dist/cloudflare-vite-wasm-loader.d.ts.map +1 -0
  136. package/dist/cloudflare-vite-wasm-loader.js +2 -0
  137. package/dist/cloudflare-vite-wasm-loader.js.map +1 -0
  138. package/dist/cloudflare.d.ts +3 -0
  139. package/dist/cloudflare.d.ts.map +1 -0
  140. package/dist/cloudflare.js +3 -0
  141. package/dist/cloudflare.js.map +1 -0
  142. package/dist/do-sql-tracking.d.ts +114 -0
  143. package/dist/do-sql-tracking.d.ts.map +1 -0
  144. package/dist/do-sql-tracking.js +280 -0
  145. package/dist/do-sql-tracking.js.map +1 -0
  146. package/dist/index.d.ts +4 -0
  147. package/dist/index.d.ts.map +1 -0
  148. package/dist/index.js +3 -0
  149. package/dist/index.js.map +1 -0
  150. package/dist/wake.d.ts +22 -0
  151. package/dist/wake.d.ts.map +1 -0
  152. package/dist/wake.js +114 -0
  153. package/dist/wake.js.map +1 -0
  154. package/dist/worker/cf-do-shim.d.ts +53 -0
  155. package/dist/worker/cf-do-shim.d.ts.map +1 -0
  156. package/dist/worker/cf-do-shim.js +66 -0
  157. package/dist/worker/cf-do-shim.js.map +1 -0
  158. package/dist/zero-http/encrypted-column-codec.d.ts +46 -0
  159. package/dist/zero-http/encrypted-column-codec.d.ts.map +1 -0
  160. package/dist/zero-http/encrypted-column-codec.js +676 -0
  161. package/dist/zero-http/encrypted-column-codec.js.map +1 -0
  162. package/dist/zero-http/encrypted-column-conformance.d.ts +7 -0
  163. package/dist/zero-http/encrypted-column-conformance.d.ts.map +1 -0
  164. package/dist/zero-http/encrypted-column-conformance.js +161 -0
  165. package/dist/zero-http/encrypted-column-conformance.js.map +1 -0
  166. package/dist/zero-http/fixture-schema.d.ts +127 -0
  167. package/dist/zero-http/fixture-schema.d.ts.map +1 -0
  168. package/dist/zero-http/fixture-schema.js +56 -0
  169. package/dist/zero-http/fixture-schema.js.map +1 -0
  170. package/dist/zero-http/mount.d.ts +71 -0
  171. package/dist/zero-http/mount.d.ts.map +1 -0
  172. package/dist/zero-http/mount.js +594 -0
  173. package/dist/zero-http/mount.js.map +1 -0
  174. package/dist/zero-http/payload-codec.d.ts +91 -0
  175. package/dist/zero-http/payload-codec.d.ts.map +1 -0
  176. package/dist/zero-http/payload-codec.js +10 -0
  177. package/dist/zero-http/payload-codec.js.map +1 -0
  178. package/dist/zero-http/server.d.ts +16 -0
  179. package/dist/zero-http/server.d.ts.map +1 -0
  180. package/dist/zero-http/server.js +270 -0
  181. package/dist/zero-http/server.js.map +1 -0
  182. package/dist/zero-http/test-harness.d.ts +32 -0
  183. package/dist/zero-http/test-harness.d.ts.map +1 -0
  184. package/dist/zero-http/test-harness.js +77 -0
  185. package/dist/zero-http/test-harness.js.map +1 -0
  186. package/dist/zero-http/transport.d.ts +71 -0
  187. package/dist/zero-http/transport.d.ts.map +1 -0
  188. package/dist/zero-http/transport.js +1106 -0
  189. package/dist/zero-http/transport.js.map +1 -0
  190. package/package.json +116 -0
@@ -0,0 +1,734 @@
1
+ const SENTINEL_LOWER = 'nspfx';
2
+ const SENTINEL_PASCAL = 'Nspfx';
3
+ function applyPrefix(template, cfg) {
4
+ const pascalName = cfg.name.charAt(0).toUpperCase() + cfg.name.slice(1);
5
+ return template
6
+ .split(SENTINEL_PASCAL)
7
+ .join(pascalName)
8
+ .split(SENTINEL_LOWER)
9
+ .join(cfg.name);
10
+ }
11
+ export function buildMigrationModuleSource(cfg, parts) {
12
+ const runCloudflareMigrations = applyPrefix('runNspfxCloudflareMigrations', cfg);
13
+ const migrationTableName = applyPrefix('__nspfx_cf_migrations', cfg);
14
+ if (parts.mode === 'noop') {
15
+ return `export const SCHEMA_VERSION = ${JSON.stringify(parts.schemaVersion)}
16
+ export async function ${runCloudflareMigrations}() {}
17
+ export { ${runCloudflareMigrations} as runCloudflareMigrations }
18
+ export const orezAppSchema = {
19
+ version: SCHEMA_VERSION,
20
+ schema: { tables: {}, relationships: {} },
21
+ publicTables: [],
22
+ migrate: ${runCloudflareMigrations},
23
+ }
24
+ `;
25
+ }
26
+ if (parts.mode === 'native') {
27
+ const applicationSqlGlobal = applyPrefix('__nspfx_cf_application_sql_client', cfg);
28
+ return `import { schema } from ${JSON.stringify(parts.schemaImportSpecifier)}
29
+
30
+ export const SCHEMA_VERSION = ${JSON.stringify(parts.schemaVersion)}
31
+
32
+ const nativeSqlStatements = ${JSON.stringify(parts.nativeSqlStatements)}
33
+ const configuredPublicTables = ${JSON.stringify(parts.publicTables ?? [])}
34
+ const expectedTables = ${JSON.stringify(parts.expectedTables ?? [])}
35
+ const migrationTable = ${JSON.stringify(migrationTableName)}
36
+
37
+ function quoteIdentifier(value) {
38
+ return '"' + String(value).replaceAll('"', '""') + '"'
39
+ }
40
+
41
+ function schemaMetadataStatements() {
42
+ return Object.values(schema.tables || {})
43
+ .filter((table) => table && typeof table.name === 'string')
44
+ .map((table) => {
45
+ const publicName = table.name.startsWith('public.')
46
+ ? table.name
47
+ : 'public.' + table.name
48
+ const registration = resolvedPublicTables.find(
49
+ (candidate) => candidate.publicTable === publicName,
50
+ )
51
+ return {
52
+ sql: 'INSERT OR REPLACE INTO _zero_schema_tables (name, schema_json) VALUES (?, ?)',
53
+ params: [
54
+ table.name.replace(/^public\\./, ''),
55
+ JSON.stringify({
56
+ columns: table.columns,
57
+ primaryKey: table.primaryKey,
58
+ physicalName:
59
+ (registration && registration.table) ||
60
+ table.serverName ||
61
+ table.name.replace(/^public\\./, ''),
62
+ }),
63
+ ],
64
+ }
65
+ })
66
+ }
67
+
68
+ function publicTables() {
69
+ if (configuredPublicTables.length) return configuredPublicTables
70
+ return Object.values(schema.tables || {})
71
+ .filter((table) => table && typeof table.name === 'string')
72
+ .map((table) => {
73
+ const publicTable = table.name.startsWith('public.') ? table.name : 'public.' + table.name
74
+ return { table: publicTable.replace(/^public\\./, ''), publicTable }
75
+ })
76
+ }
77
+
78
+ const resolvedPublicTables = publicTables()
79
+
80
+ async function shouldSkipStatement(tx, statement) {
81
+ if (statement.skipIfTableMissing) {
82
+ const tempRows = await tx.query(
83
+ 'PRAGMA table_info(' + quoteIdentifier(statement.skipIfTableMissing) + ')',
84
+ )
85
+ if (tempRows.length === 0) return true
86
+ }
87
+ const condition = statement.skipIfColumnExists || statement.skipIfColumnMissing
88
+ if (!condition) return false
89
+ const rows = await tx.query('PRAGMA table_info(' + quoteIdentifier(condition.table) + ')')
90
+ const hasColumn = rows.some((row) => row && row.name === condition.column)
91
+ return statement.skipIfColumnExists ? hasColumn : !hasColumn
92
+ }
93
+
94
+ function normalizeSqlType(value) {
95
+ return String(value).trim().toLowerCase().replaceAll(/\\s+/g, ' ')
96
+ }
97
+
98
+ // every table's columns in ONE round trip. this used to be a PRAGMA
99
+ // table_info per expected table in the shape assert plus another per ledgered
100
+ // ADD COLUMN in the reconcile — order 125 sequential DO calls, all of them
101
+ // holding the namespace's exclusive application-SQL session while concurrent
102
+ // readers spin in the 25ms acquire retry. healing paths force this run on
103
+ // EVERY request for an unseeded project, so its cost lands on exactly the
104
+ // population it exists to repair (the 2026-07-21 outage shape).
105
+ //
106
+ // one behaviour difference from the PRAGMAs this replaced: lookups here are
107
+ // case-EXACT, because the keys come from sqlite_master.name, while
108
+ // PRAGMA table_info resolves a table name case-insensitively. No statement in
109
+ // the current set mismatches, but a hand-written repair migration that spelled
110
+ // a table name in a different case would read as a missing column, resurrect,
111
+ // and then die on "duplicate column name". Match sqlite_master's spelling.
112
+ async function readLiveColumns(tx) {
113
+ // exclude protected/internal tables from the scan. once a Durable Object has
114
+ // used its KV API, _cf_KV is listed in sqlite_master but the platform
115
+ // authorizer refuses pragma_table_info on it, and one denied row fails the
116
+ // WHOLE statement with SQLITE_AUTH (verified 2026-07-24 against a real DO:
117
+ // scan passes without _cf_KV, fails the moment storage.put creates it, and
118
+ // passes again with this filter). every prod namespace DO has _cf_KV, so the
119
+ // unfiltered scan broke every migration session. caret escape on purpose:
120
+ // this whole function body is emitted through a template literal, where a
121
+ // literal backslash would need quadruple escaping.
122
+ const rows = await tx.query(
123
+ 'SELECT m.name AS tableName, p.name AS columnName, p.type AS columnType,' +
124
+ ' p."notnull" AS columnNotNull, p.pk AS columnPk' +
125
+ " FROM sqlite_master m JOIN pragma_table_info(m.name) p WHERE m.type = 'table'" +
126
+ " AND m.name NOT LIKE '^_cf^_%' ESCAPE '^'" +
127
+ " AND m.name NOT LIKE 'sqlite^_%' ESCAPE '^'",
128
+ )
129
+ const tables = new Map()
130
+ for (const row of rows) {
131
+ let columns = tables.get(row.tableName)
132
+ if (!columns) {
133
+ columns = []
134
+ tables.set(row.tableName, columns)
135
+ }
136
+ columns.push({
137
+ name: row.columnName,
138
+ notnull: row.columnNotNull,
139
+ pk: row.columnPk,
140
+ type: row.columnType,
141
+ })
142
+ }
143
+ return tables
144
+ }
145
+
146
+ async function assertExpectedSchema(tx) {
147
+ const liveColumns = await readLiveColumns(tx)
148
+ // two passes on purpose. reporting only the FIRST missing table makes an
149
+ // operator fix them one deploy at a time, and a per-column mismatch later in
150
+ // the list would throw before the missing-table set was even known. collect
151
+ // every absent table first and report them together.
152
+ const present = []
153
+ const missingTables = []
154
+ for (const expectedTable of expectedTables) {
155
+ const actualColumns = liveColumns.get(expectedTable.name) || []
156
+ if (actualColumns.length === 0) missingTables.push(expectedTable.name)
157
+ else present.push({ actualColumns, expectedTable })
158
+ }
159
+ if (missingTables.length > 0) {
160
+ throw new Error(
161
+ 'application SQLite schema mismatch: missing table' +
162
+ (missingTables.length > 1 ? 's' : '') +
163
+ ' ' +
164
+ missingTables.join(', '),
165
+ )
166
+ }
167
+
168
+ for (const { actualColumns, expectedTable } of present) {
169
+ const actualByName = new Map(actualColumns.map((column) => [column.name, column]))
170
+ const missing = expectedTable.columns
171
+ .filter((column) => !actualByName.has(column.name))
172
+ .map((column) => column.name)
173
+ if (missing.length > 0) {
174
+ throw new Error(
175
+ 'application SQLite schema mismatch for ' + expectedTable.name +
176
+ ': missing [' + missing.join(', ') + ']',
177
+ )
178
+ }
179
+
180
+ const expectedPrimaryKey = expectedTable.columns
181
+ .filter((column) => column.primaryKeyOrder > 0)
182
+ .sort((left, right) => left.primaryKeyOrder - right.primaryKeyOrder)
183
+ .map((column) => column.name)
184
+ const actualPrimaryKey = actualColumns
185
+ .filter((column) => Number(column.pk) > 0)
186
+ .sort((left, right) => Number(left.pk) - Number(right.pk))
187
+ .map((column) => column.name)
188
+ let equivalentPrimaryKeyIndex = false
189
+ if (
190
+ expectedPrimaryKey.length > 0 &&
191
+ (actualPrimaryKey.length !== expectedPrimaryKey.length ||
192
+ actualPrimaryKey.some((column, index) => column !== expectedPrimaryKey[index]))
193
+ ) {
194
+ const indexes = await tx.query(
195
+ 'PRAGMA index_list(' + quoteIdentifier(expectedTable.name) + ')',
196
+ )
197
+ for (const index of indexes) {
198
+ if (Number(index.unique) === 0 || Number(index.partial) !== 0) continue
199
+ const columns = (await tx.query(
200
+ 'PRAGMA index_info(' + quoteIdentifier(index.name) + ')',
201
+ ))
202
+ .sort((left, right) => Number(left.seqno) - Number(right.seqno))
203
+ .map((column) => column.name)
204
+ if (
205
+ columns.length === expectedPrimaryKey.length &&
206
+ columns.every((column, index) => column === expectedPrimaryKey[index])
207
+ ) {
208
+ equivalentPrimaryKeyIndex = true
209
+ break
210
+ }
211
+ }
212
+ }
213
+
214
+ for (const expected of expectedTable.columns) {
215
+ const actual = actualByName.get(expected.name)
216
+ if (!actual) continue
217
+ const actualType = normalizeSqlType(actual.type)
218
+ const compatibleLegacyTimestamp =
219
+ expected.sqlType === 'timestamp' &&
220
+ (actualType === 'text' || actualType === 'real')
221
+ const compatibleLegacyNumber =
222
+ expected.sqlType === 'integer' &&
223
+ (actualType === 'real' || actualType === 'text')
224
+ if (
225
+ actualType !== expected.sqlType &&
226
+ !compatibleLegacyTimestamp &&
227
+ !compatibleLegacyNumber
228
+ ) {
229
+ throw new Error(
230
+ 'application SQLite schema mismatch for ' + expectedTable.name + '.' + expected.name +
231
+ ': expected ' + expected.sqlType + ', found ' + (actualType || '(untyped)'),
232
+ )
233
+ }
234
+
235
+ const actualNotNull = Number(actual.notnull) !== 0 || Number(actual.pk) !== 0
236
+ if (actualNotNull !== expected.notNull) {
237
+ if (expected.notNull && !actualNotNull) {
238
+ const nullRows = await tx.query(
239
+ 'SELECT 1 FROM ' + quoteIdentifier(expectedTable.name) +
240
+ ' WHERE ' + quoteIdentifier(expected.name) + ' IS NULL LIMIT 1',
241
+ )
242
+ if (nullRows.length === 0) continue
243
+ }
244
+ throw new Error(
245
+ 'application SQLite schema mismatch for ' + expectedTable.name + '.' + expected.name +
246
+ ': expected ' + (expected.notNull ? 'NOT NULL' : 'nullable') +
247
+ ', found ' + (actualNotNull ? 'NOT NULL' : 'nullable'),
248
+ )
249
+ }
250
+ if (Number(actual.pk) !== expected.primaryKeyOrder && !equivalentPrimaryKeyIndex) {
251
+ throw new Error(
252
+ 'application SQLite schema mismatch for ' + expectedTable.name + '.' + expected.name +
253
+ ': expected primary-key position ' + expected.primaryKeyOrder +
254
+ ', found ' + actual.pk,
255
+ )
256
+ }
257
+ }
258
+ }
259
+ }
260
+
261
+ function hashMigrationSql(sql) {
262
+ let h = 2166136261
263
+ for (let i = 0; i < sql.length; i++) {
264
+ h ^= sql.charCodeAt(i)
265
+ h = Math.imul(h, 16777619)
266
+ }
267
+ return (h >>> 0).toString(36)
268
+ }
269
+
270
+ // a run killed mid-transaction (client abort, isolate eviction) rolls its DDL
271
+ // back but keeps its ledger rows: the ledger is not a CDC-registered table, so
272
+ // the DO's row undo never captures it. those phantom rows made every later run
273
+ // skip statements whose effects no longer exist, permanently wedging the
274
+ // namespace (2026-07-23 provisioning incident). before trusting the ledger,
275
+ // delete entries whose effect is verifiably absent so their statements re-run
276
+ // in order. a standalone DROP TABLE never re-runs: its effect IS absence.
277
+ //
278
+ // what this does NOT detect, stated plainly rather than as a reassurance:
279
+ // - DML. a backfill re-runs only when its target table is gone entirely (the
280
+ // same pass recreates it first). undone on a surviving table it is
281
+ // invisible in schema and stays skipped, unlogged. the current set holds 50
282
+ // UPDATE, 10 INSERT INTO and 6 DELETE FROM statements. this cannot wedge a
283
+ // namespace, it leaves stale data behind a correct-looking schema.
284
+ // - an EXTRA column. assertExpectedSchema catches a missing table, a missing
285
+ // column, a type change and a NOT NULL change, but not a surplus one, so a
286
+ // ledgered ALTER TABLE ... DROP COLUMN whose effect rolled back is neither
287
+ // resurrected nor flagged.
288
+ // - a column a later statement in the SAME file renames away. the
289
+ // x__rebuild scratch columns in 20260723140000_declare_epoch_ms_integer
290
+ // are added, copied, then renamed over the original, so the ADD COLUMN rule
291
+ // always reads them as missing and re-adds them on a perfectly healthy
292
+ // namespace. surplus columns, so assertExpectedSchema stays quiet. this
293
+ // predates the block work and is not fixed here.
294
+ // - a rebuild block that changes only nullability, defaults or foreign keys
295
+ // without changing the column SET. its rollback leaves a table this pass
296
+ // reads as landed. it does not silently pass: assertExpectedSchema fails
297
+ // the run on the nullability difference, so the namespace reports loudly
298
+ // instead of self-repairing.
299
+ async function reconcilePhantomLedger(tx, applied) {
300
+ if (applied.size === 0) return
301
+ const schemaRows = await tx.query(
302
+ "SELECT name, type FROM sqlite_master WHERE type IN ('table', 'index')",
303
+ )
304
+ const tables = new Set()
305
+ const indexes = new Set()
306
+ for (const row of schemaRows) {
307
+ if (row.type === 'table') tables.add(row.name)
308
+ else indexes.add(row.name)
309
+ }
310
+ const liveColumns = await readLiveColumns(tx)
311
+ // a drizzle rebuild block (CREATE __new_<t> / INSERT..SELECT / DROP <t> /
312
+ // RENAME) is ONE unit. its statements are individually meaningless, so they
313
+ // resurrect together or not at all — including the DROP, which is the only
314
+ // way the RENAME can land on a re-run. the honest evidence that the block
315
+ // landed is <t> carrying the rebuilt COLUMN SET: a rolled-back block leaves
316
+ // the ORIGINAL <t> in place, so judging it by table name reads every wedged
317
+ // namespace as healthy and silently repairs nothing.
318
+ const blockKey = (item) => item.id.split(':')[0] + '::' + item.rebuildTarget
319
+ const blockLanded = new Map()
320
+ for (const statement of nativeSqlStatements) {
321
+ if (!statement || typeof statement !== 'object') continue
322
+ if (!statement.rebuildTarget || !statement.rebuildColumns) continue
323
+ const key = blockKey(statement)
324
+ if (blockLanded.has(key)) continue
325
+ const actualNames = new Set(
326
+ (liveColumns.get(statement.rebuildTarget) || []).map((column) => column.name),
327
+ )
328
+ // a superset test, not equality: a later migration legitimately adds
329
+ // columns to <t>, and treating that as "not landed" would drop a live
330
+ // table and rebuild it from a shape that no longer has them.
331
+ blockLanded.set(
332
+ key,
333
+ actualNames.size > 0 &&
334
+ statement.rebuildColumns.every((column) => actualNames.has(column)),
335
+ )
336
+ }
337
+ // the tables a resurrecting block will DROP and recreate this pass.
338
+ const rebuiltTables = new Set()
339
+ for (const statement of nativeSqlStatements) {
340
+ if (!statement || typeof statement !== 'object' || !statement.rebuildTarget) continue
341
+ if (blockLanded.get(blockKey(statement)) === false) {
342
+ rebuiltTables.add(statement.rebuildTarget)
343
+ }
344
+ }
345
+ const resurrect = new Set()
346
+ for (const [index, statement] of nativeSqlStatements.entries()) {
347
+ const item = typeof statement === 'string'
348
+ ? { id: 'statement-' + index, sql: statement }
349
+ : statement
350
+ if (!item || typeof item.sql !== 'string' || !item.sql.trim()) continue
351
+ const baseId = typeof item.id === 'string' && item.id ? item.id : 'statement-' + index
352
+ let ledgered = false
353
+ for (const id of applied) {
354
+ if (id === baseId || id.startsWith(baseId + ':')) {
355
+ ledgered = true
356
+ break
357
+ }
358
+ }
359
+ if (!ledgered) continue
360
+ // block members bypass the per-statement rules entirely: their effect is
361
+ // the block's effect, judged once above.
362
+ if (item.rebuildTarget) {
363
+ if (blockLanded.get(blockKey(item)) === false) resurrect.add(baseId)
364
+ continue
365
+ }
366
+ const sql = item.sql.trim()
367
+ let match
368
+ let missing = false
369
+ if ((match = /^CREATE TABLE\\s+(?:IF NOT EXISTS\\s+)?[\`"]?(\\w+)/i.exec(sql))) {
370
+ missing = !tables.has(match[1])
371
+ } else if ((match = /^CREATE (?:UNIQUE )?INDEX\\s+(?:IF NOT EXISTS\\s+)?[\`"]?(\\w+)[\`"]?\\s+ON\\s+[\`"]?(\\w+)/i.exec(sql))) {
372
+ // the index set was sampled BEFORE this pass drops and rebuilds <t>, so
373
+ // "the index exists" is stale evidence for any table a resurrecting
374
+ // block is about to DROP: the drop takes its indexes with it and the
375
+ // trailing CREATE INDEXes stay ledgered, leaving the rebuilt table
376
+ // bare. that silently removed the UNIQUE index invite redemption's
377
+ // ON CONFLICT target needs.
378
+ missing = !indexes.has(match[1]) || rebuiltTables.has(match[2])
379
+ } else if ((match = /^ALTER TABLE\\s+[\`"]?(\\w+)[\`"]?\\s+RENAME TO\\s+[\`"]?(\\w+)/i.exec(sql))) {
380
+ missing = !tables.has(match[2])
381
+ } else if ((match = /^ALTER TABLE\\s+[\`"]?(\\w+)[\`"]?\\s+ADD\\s+(?:COLUMN\\s+)?[\`"]?(\\w+)/i.exec(sql))) {
382
+ const columns = liveColumns.get(match[1])
383
+ missing = !columns || !columns.some((column) => column.name === match[2])
384
+ } else if ((match = /^(?:INSERT INTO|UPDATE|DELETE FROM|ALTER TABLE)\\s+[\`"]?(\\w+)/i.exec(sql))) {
385
+ missing = !tables.has(match[1])
386
+ }
387
+ if (missing) resurrect.add(baseId)
388
+ }
389
+ if (resurrect.size === 0) return
390
+ // a resurrected rebuild block must re-run with its sibling PRAGMA
391
+ // foreign_keys toggles, or the block re-executes under FK enforcement.
392
+ const resurrectedFiles = new Set(
393
+ [...resurrect].map((baseId) => baseId.split(':')[0]),
394
+ )
395
+ for (const [index, statement] of nativeSqlStatements.entries()) {
396
+ const item = typeof statement === 'string'
397
+ ? { id: 'statement-' + index, sql: statement }
398
+ : statement
399
+ if (!item || typeof item.sql !== 'string') continue
400
+ if (!/^\\s*PRAGMA\\b/i.test(item.sql.trim())) continue
401
+ const baseId = typeof item.id === 'string' && item.id ? item.id : 'statement-' + index
402
+ if (resurrectedFiles.has(baseId.split(':')[0])) resurrect.add(baseId)
403
+ }
404
+ console.warn(
405
+ '[orez-migrations] resurrecting ' + resurrect.size +
406
+ ' phantom ledger entries: ' + [...resurrect].join(', '),
407
+ )
408
+ // clear a leftover __new_<t> before the block replays, but ONLY when <t> is
409
+ // also present. both present means the previous run died before its DROP, so
410
+ // __new_<t> is a stale partial copy and the resurrected INSERT..SELECT would
411
+ // fail on rows already in it ("UNIQUE constraint failed: __new_<t>.id").
412
+ // <t> ABSENT is the opposite case and must not be touched: there the DROP did
413
+ // land, __new_<t> holds the only copy of the rows, and the replay recreates an
414
+ // empty <t>, copies nothing out of it, drops it and renames __new_<t> over it.
415
+ for (const table of rebuiltTables) {
416
+ if (!tables.has(table) || !tables.has('__new_' + table)) continue
417
+ await tx.exec('DROP TABLE IF EXISTS ' + quoteIdentifier('__new_' + table))
418
+ }
419
+ for (const baseId of resurrect) {
420
+ for (const id of [...applied]) {
421
+ if (id !== baseId && !id.startsWith(baseId + ':')) continue
422
+ await tx.exec(
423
+ 'DELETE FROM ' + quoteIdentifier(migrationTable) + ' WHERE id = ?',
424
+ [id],
425
+ )
426
+ applied.delete(id)
427
+ }
428
+ }
429
+ }
430
+
431
+ async function applyNativeSchema(tx, instance) {
432
+ await tx.exec(
433
+ 'CREATE TABLE IF NOT EXISTS ' + quoteIdentifier(migrationTable) +
434
+ ' (id TEXT PRIMARY KEY, applied_at INTEGER NOT NULL)',
435
+ )
436
+ const appliedRows = await tx.query('SELECT id FROM ' + quoteIdentifier(migrationTable))
437
+ const applied = new Set(appliedRows.map((row) => row.id))
438
+ await reconcilePhantomLedger(tx, applied)
439
+ // register BEFORE the statements, not only after them. a cdc trigger whose
440
+ // _orez_cdc_tables row is missing is invisible to beginSchemaChange, which
441
+ // skips unregistered tables, so it never suspends capture and the next
442
+ // DROP/RENAME COLUMN on that table dies on the surviving trigger. ensureTable
443
+ // reads that orphan as changed (its registration lookup returns nothing),
444
+ // drops the stale triggers and rewrites the row, so registering first is what
445
+ // lets the DDL below suspend capture at all. the pass after the statements
446
+ // still runs and still owns publication; this one only heals. on a fresh
447
+ // namespace every table is absent, ensureTable returns false for each, and
448
+ // this is a no-op beyond creating the cdc bookkeeping tables early.
449
+ await tx.registerTables(publicTables())
450
+ const appliedIds = [...applied]
451
+ const appliedStatementIds = new Set()
452
+ const supersededStatementIds = new Set()
453
+ for (const [index, statement] of nativeSqlStatements.entries()) {
454
+ const item = typeof statement === 'string'
455
+ ? { id: 'statement-' + index, sql: statement }
456
+ : statement
457
+ if (!item || typeof item.sql !== 'string' || !item.sql.trim()) continue
458
+ const baseId = typeof item.id === 'string' && item.id ? item.id : 'statement-' + index
459
+ if (
460
+ applied.has(baseId) ||
461
+ appliedIds.some((appliedId) => appliedId.startsWith(baseId + ':'))
462
+ ) {
463
+ appliedStatementIds.add(baseId)
464
+ }
465
+ for (const id of Array.isArray(item.supersedes) ? item.supersedes : []) {
466
+ supersededStatementIds.add(id)
467
+ }
468
+ }
469
+ // CREATE TABLE IF NOT EXISTS is a SILENT NO-OP against a table that already
470
+ // exists in an older shape, so every column that only ever appears inside a
471
+ // CREATE definition is unreachable on a namespace whose table predates it,
472
+ // and the first index over such a column fails the whole run forever (prod
473
+ // 2026-07-26: 217 namespaces, ~2k billed rows per retry, for two days).
474
+ //
475
+ // this belongs here and not in the phantom-ledger pass, which is where it was
476
+ // tried first and did nothing: that pass only considers LEDGERED statements,
477
+ // and the ledger entry for a failing run's CREATE is deleted again by the
478
+ // failure compensation below, so at the start of every retry the CREATE is
479
+ // unledgered and the pass skipped it. converging here is independent of
480
+ // ledger state, which is the only thing that made it reachable at all.
481
+ for (const [index, statement] of nativeSqlStatements.entries()) {
482
+ const item = typeof statement === 'string' ? null : statement
483
+ if (!item || !Array.isArray(item.declaredColumns)) continue
484
+ if (typeof item.sql !== 'string') continue
485
+ const created = /^CREATE TABLE\\s+(?:IF NOT EXISTS\\s+)?[\`"]?(\\w+)/i.exec(item.sql.trim())
486
+ if (!created) continue
487
+ const baseId = typeof item.id === 'string' && item.id ? item.id : 'statement-' + index
488
+ if (supersededStatementIds.has(baseId)) continue
489
+ // PRAGMA, not the bulk sqlite_master scan: it resolves the table the same
490
+ // way the statements do, and no rows means the table is genuinely absent,
491
+ // so the CREATE below builds it correctly and there is nothing to converge.
492
+ const liveRows = await tx.query(
493
+ 'PRAGMA table_info(' + quoteIdentifier(created[1]) + ')',
494
+ )
495
+ if (liveRows.length === 0) continue
496
+ const live = new Set(liveRows.map((column) => String((column && column.name) ?? '')))
497
+ for (const column of item.declaredColumns) {
498
+ if (!column || typeof column.name !== 'string') continue
499
+ if (live.has(column.name)) continue
500
+ let definition = String(column.definition || '').trim()
501
+ if (!definition) continue
502
+ // sqlite refuses ADD COLUMN for these shapes; leave them to
503
+ // assertExpectedSchema, which reports the namespace loudly.
504
+ if (/\\bPRIMARY KEY\\b|\\bUNIQUE\\b/i.test(definition)) continue
505
+ if (/\\bNOT NULL\\b/i.test(definition) && /\\bREFERENCES\\b/i.test(definition)) continue
506
+ // a NOT NULL column with no default is skipped rather than given a
507
+ // synthesised one. sqlite would accept ADD COLUMN ... NOT NULL DEFAULT '',
508
+ // and every existing row would silently take that placeholder — inventing
509
+ // data the migration author never wrote, on a table that already holds
510
+ // real rows. the honest outcome is the loud one: assertExpectedSchema
511
+ // names the column and the namespace reports instead of self-repairing.
512
+ // no column that wedged production is of this shape.
513
+ if (/\\bNOT NULL\\b/i.test(definition) && !/\\bDEFAULT\\b/i.test(definition)) continue
514
+ console.warn(
515
+ '[orez-migrations] converging ' + created[1] + '.' + column.name +
516
+ ' declared by ' + baseId,
517
+ )
518
+ await tx.exec(
519
+ 'ALTER TABLE ' + quoteIdentifier(created[1]) + ' ADD COLUMN ' + definition,
520
+ )
521
+ }
522
+ }
523
+ // the ledger table is treated as replication bookkeeping by the DO backend,
524
+ // so its writes are NOT covered by the transaction rollback: an aborted run
525
+ // used to leave every already-recorded statement marked applied while its
526
+ // data and DDL effects were undone, and later runs then skipped work that
527
+ // never happened. compensate explicitly: on failure, delete the rows this
528
+ // run inserted before rethrowing.
529
+ const insertedThisRun = []
530
+ try {
531
+ for (const [index, statement] of nativeSqlStatements.entries()) {
532
+ const item = typeof statement === 'string'
533
+ ? { id: 'statement-' + index, sql: statement }
534
+ : statement
535
+ if (!item || typeof item.sql !== 'string' || !item.sql.trim()) continue
536
+ // a statement that is only sql comments (a supersession-anchor
537
+ // migration) has nothing to execute.
538
+ if (!item.sql.split('\\n').some((line) => {
539
+ const trimmed = line.trim()
540
+ return trimmed.length > 0 && !trimmed.startsWith('--')
541
+ })) continue
542
+ const baseId = typeof item.id === 'string' && item.id ? item.id : 'statement-' + index
543
+ if (supersededStatementIds.has(baseId)) continue
544
+ const id = baseId + ':' + hashMigrationSql(item.sql)
545
+ // migration statement ids are immutable execution identities. the SQL hash
546
+ // records which source version ran, but editing an old migration must never
547
+ // make destructive SQL run again under the same id.
548
+ if (appliedStatementIds.has(baseId)) continue
549
+ if (!(await shouldSkipStatement(tx, item))) {
550
+ try {
551
+ await tx.exec(item.sql, Array.isArray(item.params) ? item.params : [])
552
+ } catch (error) {
553
+ // a bare sqlite message ("no such table: x") names neither the failing
554
+ // statement nor which of its siblings the ledger already recorded, and
555
+ // that ledger state is the only thing that explains a half-applied
556
+ // table-recreate block. the live column list of the target table is
557
+ // the other half of that story for DDL chains.
558
+ const file = baseId.split(':')[0]
559
+ const siblings = [...applied].filter((appliedId) => appliedId.startsWith(file))
560
+ let tableInfo = ''
561
+ // CREATE INDEX belongs here as much as the DML shapes: "no such
562
+ // column" on an index names a column the target table is missing,
563
+ // and the table's real column list is the whole diagnosis. it also
564
+ // has to come BEFORE the ledger list, which runs to hundreds of ids
565
+ // and truncated every trailing byte of this off the stored error.
566
+ const target =
567
+ /(?:UPDATE|ALTER TABLE|DELETE FROM|INSERT INTO)\\s+[\`"]?(\\w+)/i.exec(item.sql) ||
568
+ /^CREATE\\s+(?:UNIQUE\\s+)?INDEX\\s+(?:IF NOT EXISTS\\s+)?[\`"]?\\w+[\`"]?\\s+ON\\s+[\`"]?(\\w+)/i.exec(item.sql)
569
+ if (target) {
570
+ try {
571
+ const columns = await tx.query('PRAGMA table_info(' + quoteIdentifier(target[1]) + ')')
572
+ tableInfo = ' | table_info(' + target[1] + '): ' +
573
+ (columns.map((column) => column.name + ':' + column.type).join(', ') ||
574
+ '(no columns)')
575
+ } catch (infoError) {
576
+ tableInfo = ' | table_info(' + target[1] + ') failed: ' +
577
+ ((infoError && infoError.message) || String(infoError))
578
+ }
579
+ }
580
+ throw new Error(
581
+ 'migration statement ' + baseId + ' failed on instance ' + instance + ': ' +
582
+ (error && error.message ? error.message : String(error)) +
583
+ ' | sql: ' + item.sql.replace(/\\s+/g, ' ').slice(0, 160) +
584
+ tableInfo +
585
+ ' | ledger for ' + file + ': ' + (siblings.join(', ') || '(none)'),
586
+ { cause: error },
587
+ )
588
+ }
589
+ }
590
+ if (!applied.has(id)) {
591
+ await tx.exec(
592
+ 'INSERT INTO ' + quoteIdentifier(migrationTable) + ' (id, applied_at) VALUES (?, ?)',
593
+ [id, Date.now()],
594
+ )
595
+ applied.add(id)
596
+ appliedStatementIds.add(baseId)
597
+ insertedThisRun.push(id)
598
+ }
599
+ }
600
+ } catch (error) {
601
+ for (const insertedId of insertedThisRun) {
602
+ try {
603
+ await tx.exec(
604
+ 'DELETE FROM ' + quoteIdentifier(migrationTable) + ' WHERE id = ?',
605
+ [insertedId],
606
+ )
607
+ } catch {}
608
+ }
609
+ throw error
610
+ }
611
+ await assertExpectedSchema(tx)
612
+ await tx.exec(
613
+ 'CREATE TABLE IF NOT EXISTS _zero_schema_tables (name TEXT PRIMARY KEY, schema_json TEXT NOT NULL)',
614
+ )
615
+ try {
616
+ for (const statement of schemaMetadataStatements()) {
617
+ await tx.exec(statement.sql, statement.params)
618
+ }
619
+ await tx.registerTables(publicTables())
620
+ } catch (error) {
621
+ // publication runs against every registered table, so a table this schema
622
+ // no longer has still gets queried here. without the label the error is
623
+ // indistinguishable from a migration statement failing.
624
+ throw new Error(
625
+ 'schema publication failed on instance ' + instance + ': ' +
626
+ (error && error.message ? error.message : String(error)),
627
+ { cause: error },
628
+ )
629
+ }
630
+ }
631
+
632
+ // what the namespace actually looks like, for a failure message. the single
633
+ // most expensive missing fact when a namespace is wedged is whether the table
634
+ // the error names is genuinely absent or merely unreachable — a whole day went
635
+ // into guessing that on 2026-07-23 because nothing ever said.
636
+ //
637
+ // runs on the error path only, in its own session, and must never throw: a
638
+ // namespace too broken to answer is exactly the case it exists to describe.
639
+ async function liveSchemaSummary(client) {
640
+ try {
641
+ let summary = ''
642
+ await client.transaction(() => {
643
+ throw new Error('native schema migration does not use queryAst')
644
+ }, async (tx) => {
645
+ const rows = await tx.query(
646
+ "SELECT name FROM sqlite_master WHERE type = 'table'" +
647
+ " AND name NOT LIKE '^_cf^_%' ESCAPE '^'" +
648
+ " AND name NOT LIKE 'sqlite^_%' ESCAPE '^' ORDER BY name",
649
+ )
650
+ const present = new Set(rows.map((row) => row.name))
651
+ const missing = expectedTables
652
+ .map((table) => table.name)
653
+ .filter((name) => !present.has(name))
654
+ summary =
655
+ ' | live tables: ' + present.size +
656
+ (missing.length ? ', MISSING expected: ' + missing.join(', ') : ', none missing')
657
+ })
658
+ return summary
659
+ } catch (error) {
660
+ return ' | live schema unreadable: ' + (error && error.message ? error.message : String(error))
661
+ }
662
+ }
663
+
664
+ // \`client\` lets a caller that is ALREADY inside the durable object hand in an
665
+ // in-process client (ZeroDO#applicationSqlLocalClient) instead of one that
666
+ // round-trips per statement. it is a parameter rather than another global
667
+ // because durable object instances share an isolate, so a global bound to one
668
+ // instance would be read by another.
669
+ export async function ${runCloudflareMigrations}({
670
+ schemaOnly = false,
671
+ registrationOnly = false,
672
+ instance = 'singleton',
673
+ client: providedClient,
674
+ } = {}) {
675
+ if (schemaOnly && registrationOnly) {
676
+ throw new Error('schemaOnly and registrationOnly are mutually exclusive')
677
+ }
678
+ let client = providedClient
679
+ if (!client) {
680
+ const createClient = globalThis.${applicationSqlGlobal}
681
+ if (typeof createClient !== 'function') {
682
+ throw new Error('Cloudflare application SQLite client is not initialized')
683
+ }
684
+ client = createClient(instance)
685
+ }
686
+ if (registrationOnly) {
687
+ await client.registerTables(resolvedPublicTables)
688
+ return { tables: resolvedPublicTables.map((table) => table.publicTable) }
689
+ }
690
+ // the statement loop labels its own failures; acquiring the session and
691
+ // committing sit OUTSIDE every try/catch in applyNativeSchema, so a Durable
692
+ // Object SQL error raised there arrives bare. the schema barrier hands that
693
+ // string straight back as a 503 body, which is the entire diagnosis budget a
694
+ // wedged namespace gets — prod has answered \`no such table: main.user:
695
+ // SQLITE_ERROR\` since 2026-07-23 and it names neither the phase that raised
696
+ // it nor whether that table is really gone. the phantom-ledger reconcile
697
+ // heals a dropped table correctly (verified against a real durable object),
698
+ // so what is left is only reachable through a message that says more.
699
+ let phase = 'session-acquire'
700
+ try {
701
+ await client.transaction(() => {
702
+ throw new Error('native schema migration does not use queryAst')
703
+ }, async (tx) => {
704
+ phase = 'reconcile'
705
+ await applyNativeSchema(tx, instance)
706
+ phase = 'commit'
707
+ })
708
+ } catch (error) {
709
+ throw new Error(
710
+ 'schema migration failed on instance ' + instance + ' during ' + phase + ': ' +
711
+ (error && error.message ? error.message : String(error)) +
712
+ (await liveSchemaSummary(client)),
713
+ { cause: error },
714
+ )
715
+ }
716
+ return {
717
+ tables: resolvedPublicTables.map((table) => table.publicTable),
718
+ ...(schemaOnly ? { schemaOnly: true } : null),
719
+ }
720
+ }
721
+
722
+ export { ${runCloudflareMigrations} as runCloudflareMigrations }
723
+ export const orezAppSchema = {
724
+ version: SCHEMA_VERSION,
725
+ schema,
726
+ publicTables: resolvedPublicTables,
727
+ migrate: ${runCloudflareMigrations},
728
+ }
729
+ `;
730
+ }
731
+ const exhaustive = parts;
732
+ throw new TypeError(`unsupported Cloudflare migration mode: ${String(exhaustive)}`);
733
+ }
734
+ //# sourceMappingURL=migration.js.map