orez 0.1.4 → 0.1.6
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 +4 -4
- package/dist/admin/server.d.ts.map +1 -1
- package/dist/admin/server.js +1 -0
- package/dist/admin/server.js.map +1 -1
- package/dist/admin/ui.d.ts.map +1 -1
- package/dist/admin/ui.js +12 -0
- package/dist/admin/ui.js.map +1 -1
- package/dist/cli.js +5 -5
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +44 -64
- package/dist/index.js.map +1 -1
- package/dist/log.d.ts +1 -1
- package/dist/log.d.ts.map +1 -1
- package/dist/log.js +2 -2
- package/dist/log.js.map +1 -1
- package/dist/sqlite-mode/apply-mode.d.ts +49 -0
- package/dist/sqlite-mode/apply-mode.d.ts.map +1 -0
- package/dist/sqlite-mode/apply-mode.js +190 -0
- package/dist/sqlite-mode/apply-mode.js.map +1 -0
- package/dist/sqlite-mode/index.d.ts +14 -0
- package/dist/sqlite-mode/index.d.ts.map +1 -0
- package/dist/sqlite-mode/index.js +14 -0
- package/dist/sqlite-mode/index.js.map +1 -0
- package/dist/sqlite-mode/resolve-mode.d.ts +24 -0
- package/dist/sqlite-mode/resolve-mode.d.ts.map +1 -0
- package/dist/sqlite-mode/resolve-mode.js +61 -0
- package/dist/sqlite-mode/resolve-mode.js.map +1 -0
- package/dist/sqlite-mode/shim-template.d.ts +20 -0
- package/dist/sqlite-mode/shim-template.d.ts.map +1 -0
- package/dist/sqlite-mode/shim-template.js +144 -0
- package/dist/sqlite-mode/shim-template.js.map +1 -0
- package/dist/sqlite-mode/types.d.ts +16 -0
- package/dist/sqlite-mode/types.d.ts.map +1 -0
- package/dist/sqlite-mode/types.js +17 -0
- package/dist/sqlite-mode/types.js.map +1 -0
- package/package.json +3 -2
- package/src/admin/server.ts +1 -0
- package/src/admin/ui.ts +12 -0
- package/src/cli.ts +5 -5
- package/src/index.ts +79 -63
- package/src/log.ts +2 -2
- package/src/shim/hooks.mjs +42 -18
- package/src/sqlite-mode/apply-mode.ts +224 -0
- package/src/sqlite-mode/index.ts +14 -0
- package/src/sqlite-mode/resolve-mode.ts +71 -0
- package/src/sqlite-mode/shim-template.ts +158 -0
- package/src/sqlite-mode/sqlite-mode.test.ts +421 -0
- package/src/sqlite-mode/types.ts +29 -0
|
@@ -0,0 +1,421 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* sqlite-mode tests - mode resolution, shim generation, and mode transitions
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs'
|
|
6
|
+
import { tmpdir } from 'node:os'
|
|
7
|
+
import { join } from 'node:path'
|
|
8
|
+
|
|
9
|
+
import { afterEach, beforeEach, describe, expect, it } from 'vitest'
|
|
10
|
+
|
|
11
|
+
import {
|
|
12
|
+
applySqliteMode,
|
|
13
|
+
backupOriginal,
|
|
14
|
+
cleanupShim,
|
|
15
|
+
getShimMode,
|
|
16
|
+
hasBackup,
|
|
17
|
+
restoreOriginal,
|
|
18
|
+
} from './apply-mode.js'
|
|
19
|
+
import { resolveSqliteMode, resolveSqliteModeConfig } from './resolve-mode.js'
|
|
20
|
+
import { generateCjsShim, generateEsmShim } from './shim-template.js'
|
|
21
|
+
import { BACKUP_MARKER, JOURNAL_MODE } from './types.js'
|
|
22
|
+
|
|
23
|
+
describe('sqlite mode types', () => {
|
|
24
|
+
it('journal_mode is wal2 for both modes (required by zero-cache)', () => {
|
|
25
|
+
expect(JOURNAL_MODE.native).toBe('wal2')
|
|
26
|
+
expect(JOURNAL_MODE.wasm).toBe('wal2')
|
|
27
|
+
})
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
describe('sqlite mode resolution', () => {
|
|
31
|
+
it('resolves wasm mode when disableWasmSqlite is false', () => {
|
|
32
|
+
expect(resolveSqliteMode(false)).toBe('wasm')
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
it('resolves native mode when disableWasmSqlite is true', () => {
|
|
36
|
+
expect(resolveSqliteMode(true)).toBe('native')
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
it('returns config with mode for native', () => {
|
|
40
|
+
const config = resolveSqliteModeConfig(true)
|
|
41
|
+
expect(config).not.toBeNull()
|
|
42
|
+
expect(config?.mode).toBe('native')
|
|
43
|
+
})
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
describe('shim template generation', () => {
|
|
47
|
+
it('generates cjs shim with correct journal_mode for wasm', () => {
|
|
48
|
+
const shim = generateCjsShim({
|
|
49
|
+
mode: 'wasm',
|
|
50
|
+
bedrockPath: '/path/to/bedrock',
|
|
51
|
+
})
|
|
52
|
+
expect(shim).toContain("db.pragma('journal_mode = wal2')")
|
|
53
|
+
expect(shim).toContain('// mode: wasm')
|
|
54
|
+
expect(shim).toContain('orez sqlite shim')
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
it('generates cjs shim with correct journal_mode for native', () => {
|
|
58
|
+
const shim = generateCjsShim({
|
|
59
|
+
mode: 'native',
|
|
60
|
+
bedrockPath: '/path/to/bedrock',
|
|
61
|
+
})
|
|
62
|
+
expect(shim).toContain("db.pragma('journal_mode = wal2')")
|
|
63
|
+
expect(shim).toContain('// mode: native')
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
it('generates esm shim with correct journal_mode for wasm', () => {
|
|
67
|
+
const shim = generateEsmShim({
|
|
68
|
+
mode: 'wasm',
|
|
69
|
+
bedrockPath: '/path/to/bedrock',
|
|
70
|
+
})
|
|
71
|
+
expect(shim).toContain("db.pragma('journal_mode = wal2')")
|
|
72
|
+
expect(shim).toContain('// mode: wasm')
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
it('includes common pragmas in both shim types', () => {
|
|
76
|
+
const cjs = generateCjsShim({ mode: 'wasm', bedrockPath: '/path' })
|
|
77
|
+
const esm = generateEsmShim({ mode: 'wasm', bedrockPath: '/path' })
|
|
78
|
+
|
|
79
|
+
for (const shim of [cjs, esm]) {
|
|
80
|
+
expect(shim).toContain("db.pragma('busy_timeout = 30000')")
|
|
81
|
+
expect(shim).toContain("db.pragma('synchronous = normal')")
|
|
82
|
+
}
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
it('includes api polyfills in generated shims', () => {
|
|
86
|
+
const shim = generateCjsShim({ mode: 'wasm', bedrockPath: '/path' })
|
|
87
|
+
|
|
88
|
+
expect(shim).toContain('Database.prototype.unsafeMode')
|
|
89
|
+
expect(shim).toContain('Database.prototype.defaultSafeIntegers')
|
|
90
|
+
expect(shim).toContain('Database.prototype.serialize')
|
|
91
|
+
expect(shim).toContain('Database.prototype.backup')
|
|
92
|
+
expect(shim).toContain('SP.scanStatus')
|
|
93
|
+
expect(shim).toContain('SP.scanStatusV2')
|
|
94
|
+
expect(shim).toContain('SQLITE_SCANSTAT_NLOOP')
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
it('includes pragma wrapper to skip optimize', () => {
|
|
98
|
+
const shim = generateCjsShim({ mode: 'wasm', bedrockPath: '/path' })
|
|
99
|
+
expect(shim).toContain("str.trim().toLowerCase().startsWith('optimize')")
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
it('includes tracing when enabled', () => {
|
|
103
|
+
const withTracing = generateCjsShim({
|
|
104
|
+
mode: 'wasm',
|
|
105
|
+
bedrockPath: '/path',
|
|
106
|
+
includeTracing: true,
|
|
107
|
+
})
|
|
108
|
+
const withoutTracing = generateCjsShim({
|
|
109
|
+
mode: 'wasm',
|
|
110
|
+
bedrockPath: '/path',
|
|
111
|
+
includeTracing: false,
|
|
112
|
+
})
|
|
113
|
+
|
|
114
|
+
expect(withTracing).toContain('_zero.changeLog')
|
|
115
|
+
expect(withoutTracing).not.toContain('_zero.changeLog')
|
|
116
|
+
})
|
|
117
|
+
})
|
|
118
|
+
|
|
119
|
+
describe('shim backup/restore lifecycle', () => {
|
|
120
|
+
let testDir: string
|
|
121
|
+
let mockPackageDir: string
|
|
122
|
+
let mockIndexPath: string
|
|
123
|
+
|
|
124
|
+
const originalContent = `'use strict';
|
|
125
|
+
// original @rocicorp/zero-sqlite3 content
|
|
126
|
+
module.exports = require('better-sqlite3');
|
|
127
|
+
`
|
|
128
|
+
|
|
129
|
+
beforeEach(() => {
|
|
130
|
+
testDir = join(
|
|
131
|
+
tmpdir(),
|
|
132
|
+
`orez-test-${Date.now()}-${Math.random().toString(36).slice(2)}`
|
|
133
|
+
)
|
|
134
|
+
mockPackageDir = join(testDir, 'node_modules', '@rocicorp', 'zero-sqlite3', 'lib')
|
|
135
|
+
mkdirSync(mockPackageDir, { recursive: true })
|
|
136
|
+
mockIndexPath = join(mockPackageDir, 'index.js')
|
|
137
|
+
|
|
138
|
+
// create mock package.json
|
|
139
|
+
writeFileSync(
|
|
140
|
+
join(testDir, 'node_modules', '@rocicorp', 'zero-sqlite3', 'package.json'),
|
|
141
|
+
JSON.stringify({ name: '@rocicorp/zero-sqlite3', main: 'lib/index.js' })
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
// create original index.js
|
|
145
|
+
writeFileSync(mockIndexPath, originalContent)
|
|
146
|
+
})
|
|
147
|
+
|
|
148
|
+
afterEach(() => {
|
|
149
|
+
rmSync(testDir, { recursive: true, force: true })
|
|
150
|
+
})
|
|
151
|
+
|
|
152
|
+
it('backups original file before shimming', () => {
|
|
153
|
+
expect(hasBackup(mockIndexPath)).toBe(false)
|
|
154
|
+
expect(backupOriginal(mockIndexPath)).toBe(true)
|
|
155
|
+
expect(hasBackup(mockIndexPath)).toBe(true)
|
|
156
|
+
|
|
157
|
+
const backupContent = readFileSync(mockIndexPath + BACKUP_MARKER, 'utf-8')
|
|
158
|
+
expect(backupContent).toBe(originalContent)
|
|
159
|
+
})
|
|
160
|
+
|
|
161
|
+
it('does not re-backup if backup already exists', () => {
|
|
162
|
+
backupOriginal(mockIndexPath)
|
|
163
|
+
const backupPath = mockIndexPath + BACKUP_MARKER
|
|
164
|
+
|
|
165
|
+
// modify original (simulate shim)
|
|
166
|
+
writeFileSync(mockIndexPath, 'shimmed content')
|
|
167
|
+
|
|
168
|
+
// backup should not overwrite existing backup
|
|
169
|
+
expect(backupOriginal(mockIndexPath)).toBe(true)
|
|
170
|
+
expect(readFileSync(backupPath, 'utf-8')).toBe(originalContent)
|
|
171
|
+
})
|
|
172
|
+
|
|
173
|
+
it('restores original from backup', () => {
|
|
174
|
+
backupOriginal(mockIndexPath)
|
|
175
|
+
writeFileSync(mockIndexPath, 'shimmed content')
|
|
176
|
+
|
|
177
|
+
expect(restoreOriginal(mockIndexPath)).toBe(true)
|
|
178
|
+
expect(readFileSync(mockIndexPath, 'utf-8')).toBe(originalContent)
|
|
179
|
+
expect(hasBackup(mockIndexPath)).toBe(false)
|
|
180
|
+
})
|
|
181
|
+
|
|
182
|
+
it('returns false when no backup to restore', () => {
|
|
183
|
+
expect(restoreOriginal(mockIndexPath)).toBe(false)
|
|
184
|
+
})
|
|
185
|
+
|
|
186
|
+
it('getShimMode returns null for unshimmed file', () => {
|
|
187
|
+
expect(getShimMode(mockIndexPath)).toBeNull()
|
|
188
|
+
})
|
|
189
|
+
|
|
190
|
+
it('getShimMode returns mode for shimmed file', () => {
|
|
191
|
+
const shimContent = generateCjsShim({
|
|
192
|
+
mode: 'wasm',
|
|
193
|
+
bedrockPath: '/path/to/bedrock',
|
|
194
|
+
})
|
|
195
|
+
writeFileSync(mockIndexPath, shimContent)
|
|
196
|
+
|
|
197
|
+
expect(getShimMode(mockIndexPath)).toBe('wasm')
|
|
198
|
+
})
|
|
199
|
+
|
|
200
|
+
it('cleanupShim restores original if backup exists', () => {
|
|
201
|
+
backupOriginal(mockIndexPath)
|
|
202
|
+
writeFileSync(mockIndexPath, 'shimmed')
|
|
203
|
+
|
|
204
|
+
cleanupShim(
|
|
205
|
+
join(testDir, 'node_modules', '@rocicorp', 'zero-sqlite3', 'lib', 'index.js')
|
|
206
|
+
)
|
|
207
|
+
|
|
208
|
+
expect(readFileSync(mockIndexPath, 'utf-8')).toBe(originalContent)
|
|
209
|
+
})
|
|
210
|
+
})
|
|
211
|
+
|
|
212
|
+
describe('mode transitions', () => {
|
|
213
|
+
let testDir: string
|
|
214
|
+
let mockPackageDir: string
|
|
215
|
+
let mockIndexPath: string
|
|
216
|
+
|
|
217
|
+
const originalContent = `'use strict';
|
|
218
|
+
// original @rocicorp/zero-sqlite3
|
|
219
|
+
module.exports = require('better-sqlite3');
|
|
220
|
+
`
|
|
221
|
+
|
|
222
|
+
beforeEach(() => {
|
|
223
|
+
testDir = join(
|
|
224
|
+
tmpdir(),
|
|
225
|
+
`orez-test-${Date.now()}-${Math.random().toString(36).slice(2)}`
|
|
226
|
+
)
|
|
227
|
+
mockPackageDir = join(testDir, 'node_modules', '@rocicorp', 'zero-sqlite3', 'lib')
|
|
228
|
+
mkdirSync(mockPackageDir, { recursive: true })
|
|
229
|
+
mockIndexPath = join(mockPackageDir, 'index.js')
|
|
230
|
+
|
|
231
|
+
writeFileSync(
|
|
232
|
+
join(testDir, 'node_modules', '@rocicorp', 'zero-sqlite3', 'package.json'),
|
|
233
|
+
JSON.stringify({ name: '@rocicorp/zero-sqlite3', main: 'lib/index.js' })
|
|
234
|
+
)
|
|
235
|
+
writeFileSync(mockIndexPath, originalContent)
|
|
236
|
+
})
|
|
237
|
+
|
|
238
|
+
afterEach(() => {
|
|
239
|
+
rmSync(testDir, { recursive: true, force: true })
|
|
240
|
+
})
|
|
241
|
+
|
|
242
|
+
it('native -> wasm -> native preserves original', () => {
|
|
243
|
+
// start in native mode (no shim)
|
|
244
|
+
expect(getShimMode(mockIndexPath)).toBeNull()
|
|
245
|
+
|
|
246
|
+
// switch to wasm mode
|
|
247
|
+
const wasmResult = applySqliteMode({
|
|
248
|
+
mode: 'wasm',
|
|
249
|
+
bedrockPath: '/path/to/bedrock',
|
|
250
|
+
zeroSqlitePath: mockIndexPath,
|
|
251
|
+
})
|
|
252
|
+
expect(wasmResult.success).toBe(true)
|
|
253
|
+
expect(getShimMode(mockIndexPath)).toBe('wasm')
|
|
254
|
+
expect(hasBackup(mockIndexPath)).toBe(true)
|
|
255
|
+
|
|
256
|
+
// switch back to native mode
|
|
257
|
+
const nativeResult = applySqliteMode({
|
|
258
|
+
mode: 'native',
|
|
259
|
+
zeroSqlitePath: mockIndexPath,
|
|
260
|
+
})
|
|
261
|
+
expect(nativeResult.success).toBe(true)
|
|
262
|
+
expect(getShimMode(mockIndexPath)).toBeNull()
|
|
263
|
+
expect(readFileSync(mockIndexPath, 'utf-8')).toBe(originalContent)
|
|
264
|
+
expect(hasBackup(mockIndexPath)).toBe(false)
|
|
265
|
+
})
|
|
266
|
+
|
|
267
|
+
it('wasm -> native -> wasm works correctly', () => {
|
|
268
|
+
// start in wasm mode
|
|
269
|
+
applySqliteMode({
|
|
270
|
+
mode: 'wasm',
|
|
271
|
+
bedrockPath: '/path/to/bedrock',
|
|
272
|
+
zeroSqlitePath: mockIndexPath,
|
|
273
|
+
})
|
|
274
|
+
expect(getShimMode(mockIndexPath)).toBe('wasm')
|
|
275
|
+
const wasmContent = readFileSync(mockIndexPath, 'utf-8')
|
|
276
|
+
|
|
277
|
+
// switch to native
|
|
278
|
+
applySqliteMode({
|
|
279
|
+
mode: 'native',
|
|
280
|
+
zeroSqlitePath: mockIndexPath,
|
|
281
|
+
})
|
|
282
|
+
expect(getShimMode(mockIndexPath)).toBeNull()
|
|
283
|
+
|
|
284
|
+
// switch back to wasm
|
|
285
|
+
applySqliteMode({
|
|
286
|
+
mode: 'wasm',
|
|
287
|
+
bedrockPath: '/path/to/bedrock',
|
|
288
|
+
zeroSqlitePath: mockIndexPath,
|
|
289
|
+
})
|
|
290
|
+
expect(getShimMode(mockIndexPath)).toBe('wasm')
|
|
291
|
+
|
|
292
|
+
// shim should have same journal_mode
|
|
293
|
+
const newWasmContent = readFileSync(mockIndexPath, 'utf-8')
|
|
294
|
+
expect(newWasmContent).toContain('journal_mode = wal2')
|
|
295
|
+
})
|
|
296
|
+
|
|
297
|
+
it('multiple wasm applies are idempotent', () => {
|
|
298
|
+
applySqliteMode({
|
|
299
|
+
mode: 'wasm',
|
|
300
|
+
bedrockPath: '/path/to/bedrock',
|
|
301
|
+
zeroSqlitePath: mockIndexPath,
|
|
302
|
+
})
|
|
303
|
+
const firstShim = readFileSync(mockIndexPath, 'utf-8')
|
|
304
|
+
|
|
305
|
+
// apply again
|
|
306
|
+
applySqliteMode({
|
|
307
|
+
mode: 'wasm',
|
|
308
|
+
bedrockPath: '/path/to/bedrock',
|
|
309
|
+
zeroSqlitePath: mockIndexPath,
|
|
310
|
+
})
|
|
311
|
+
const secondShim = readFileSync(mockIndexPath, 'utf-8')
|
|
312
|
+
|
|
313
|
+
expect(firstShim).toBe(secondShim)
|
|
314
|
+
expect(hasBackup(mockIndexPath)).toBe(true)
|
|
315
|
+
})
|
|
316
|
+
|
|
317
|
+
it('does not backup shimmed content', () => {
|
|
318
|
+
// apply wasm shim
|
|
319
|
+
applySqliteMode({
|
|
320
|
+
mode: 'wasm',
|
|
321
|
+
bedrockPath: '/path/to/bedrock',
|
|
322
|
+
zeroSqlitePath: mockIndexPath,
|
|
323
|
+
})
|
|
324
|
+
|
|
325
|
+
// manually delete backup to simulate corruption
|
|
326
|
+
const backupPath = mockIndexPath + BACKUP_MARKER
|
|
327
|
+
rmSync(backupPath)
|
|
328
|
+
|
|
329
|
+
// try to backup again - should fail because file is shimmed
|
|
330
|
+
expect(backupOriginal(mockIndexPath)).toBe(false)
|
|
331
|
+
})
|
|
332
|
+
|
|
333
|
+
it('wasm re-apply is idempotent even without backup', () => {
|
|
334
|
+
// apply wasm shim first
|
|
335
|
+
applySqliteMode({
|
|
336
|
+
mode: 'wasm',
|
|
337
|
+
bedrockPath: '/path/to/bedrock',
|
|
338
|
+
zeroSqlitePath: mockIndexPath,
|
|
339
|
+
})
|
|
340
|
+
|
|
341
|
+
// delete backup to simulate corruption
|
|
342
|
+
const backupPath = mockIndexPath + BACKUP_MARKER
|
|
343
|
+
rmSync(backupPath)
|
|
344
|
+
|
|
345
|
+
// re-applying same wasm mode should succeed (idempotent)
|
|
346
|
+
const result = applySqliteMode({
|
|
347
|
+
mode: 'wasm',
|
|
348
|
+
bedrockPath: '/path/to/bedrock',
|
|
349
|
+
zeroSqlitePath: mockIndexPath,
|
|
350
|
+
})
|
|
351
|
+
expect(result.success).toBe(true)
|
|
352
|
+
})
|
|
353
|
+
|
|
354
|
+
it('wasm shim fails on unshimmed file if backup cannot be created', () => {
|
|
355
|
+
// manually write a shimmed file without backup (simulates external corruption)
|
|
356
|
+
const shimContent = generateCjsShim({ mode: 'native', bedrockPath: '/path' })
|
|
357
|
+
writeFileSync(mockIndexPath, shimContent)
|
|
358
|
+
|
|
359
|
+
// try to apply wasm shim - should fail because file is shimmed but no backup
|
|
360
|
+
const result = applySqliteMode({
|
|
361
|
+
mode: 'wasm',
|
|
362
|
+
bedrockPath: '/path/to/bedrock',
|
|
363
|
+
zeroSqlitePath: mockIndexPath,
|
|
364
|
+
})
|
|
365
|
+
expect(result.success).toBe(false)
|
|
366
|
+
expect(result.error).toContain('no backup')
|
|
367
|
+
})
|
|
368
|
+
|
|
369
|
+
it('native mode fails if shimmed with no backup', () => {
|
|
370
|
+
// apply wasm shim first
|
|
371
|
+
applySqliteMode({
|
|
372
|
+
mode: 'wasm',
|
|
373
|
+
bedrockPath: '/path/to/bedrock',
|
|
374
|
+
zeroSqlitePath: mockIndexPath,
|
|
375
|
+
})
|
|
376
|
+
|
|
377
|
+
// delete backup to simulate corruption
|
|
378
|
+
const backupPath = mockIndexPath + BACKUP_MARKER
|
|
379
|
+
rmSync(backupPath)
|
|
380
|
+
|
|
381
|
+
// try to restore native - should fail
|
|
382
|
+
const result = applySqliteMode({
|
|
383
|
+
mode: 'native',
|
|
384
|
+
zeroSqlitePath: mockIndexPath,
|
|
385
|
+
})
|
|
386
|
+
expect(result.success).toBe(false)
|
|
387
|
+
expect(result.error).toContain('no backup')
|
|
388
|
+
})
|
|
389
|
+
})
|
|
390
|
+
|
|
391
|
+
describe('shim contract tests', () => {
|
|
392
|
+
it('wasm shim sets journal_mode = wal2', () => {
|
|
393
|
+
const shim = generateCjsShim({ mode: 'wasm', bedrockPath: '/path' })
|
|
394
|
+
expect(shim).toContain("db.pragma('journal_mode = wal2')")
|
|
395
|
+
})
|
|
396
|
+
|
|
397
|
+
it('native shim sets journal_mode = wal2', () => {
|
|
398
|
+
const shim = generateCjsShim({ mode: 'native', bedrockPath: '/path' })
|
|
399
|
+
expect(shim).toContain("db.pragma('journal_mode = wal2')")
|
|
400
|
+
})
|
|
401
|
+
|
|
402
|
+
it('both modes set busy_timeout and synchronous', () => {
|
|
403
|
+
for (const mode of ['wasm', 'native'] as const) {
|
|
404
|
+
const shim = generateCjsShim({ mode, bedrockPath: '/path' })
|
|
405
|
+
expect(shim).toContain("db.pragma('busy_timeout = 30000')")
|
|
406
|
+
expect(shim).toContain("db.pragma('synchronous = normal')")
|
|
407
|
+
}
|
|
408
|
+
})
|
|
409
|
+
|
|
410
|
+
it('shim exports Database and SqliteError', () => {
|
|
411
|
+
const shim = generateCjsShim({ mode: 'wasm', bedrockPath: '/path' })
|
|
412
|
+
expect(shim).toContain('module.exports = Database')
|
|
413
|
+
expect(shim).toContain('module.exports.SqliteError = SqliteError')
|
|
414
|
+
})
|
|
415
|
+
|
|
416
|
+
it('esm shim exports default and named SqliteError', () => {
|
|
417
|
+
const shim = generateEsmShim({ mode: 'wasm', bedrockPath: '/path' })
|
|
418
|
+
expect(shim).toContain('export default Database')
|
|
419
|
+
expect(shim).toContain('export { SqliteError }')
|
|
420
|
+
})
|
|
421
|
+
})
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* sqlite mode types and constants
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export type SqliteMode = 'native' | 'wasm'
|
|
6
|
+
|
|
7
|
+
export interface SqliteModeConfig {
|
|
8
|
+
mode: SqliteMode
|
|
9
|
+
// path to bedrock-sqlite for wasm mode
|
|
10
|
+
bedrockPath?: string
|
|
11
|
+
// path to @rocicorp/zero-sqlite3 package
|
|
12
|
+
zeroSqlitePath?: string
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// journal mode - zero-cache requires wal2 for replica sync (BEGIN CONCURRENT)
|
|
16
|
+
// both modes use wal2 now - bedrock-sqlite wasm should support it
|
|
17
|
+
export const JOURNAL_MODE: Record<SqliteMode, string> = {
|
|
18
|
+
native: 'wal2',
|
|
19
|
+
wasm: 'wal2',
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// common pragmas shared by both modes
|
|
23
|
+
export const COMMON_PRAGMAS = {
|
|
24
|
+
busy_timeout: '30000',
|
|
25
|
+
synchronous: 'normal',
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// backup file marker for identifying orez-shimmed packages
|
|
29
|
+
export const BACKUP_MARKER = '.orez-backup'
|