@pikku/migrator-sql 0.12.2 → 0.12.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,118 @@
1
+ import type {
2
+ SqliteRuntime,
3
+ SyncSqliteChanges,
4
+ SyncSqliteDatabase,
5
+ SyncSqliteStatement,
6
+ } from './sqlite-runtime.js'
7
+
8
+ interface NodeSqliteStatementShape {
9
+ reader?: boolean
10
+ all(...parameters: unknown[]): unknown[]
11
+ get(...parameters: unknown[]): unknown
12
+ iterate(...parameters: unknown[]): IterableIterator<unknown>
13
+ run(...parameters: unknown[]): {
14
+ changes: number | bigint
15
+ lastInsertRowid: number | bigint
16
+ }
17
+ }
18
+
19
+ interface NodeSqliteDatabaseShape {
20
+ exec(sql: string): void
21
+ prepare(sql: string): NodeSqliteStatementShape
22
+ close(): void
23
+ }
24
+
25
+ interface NodeSqliteModule {
26
+ DatabaseSync: new (filename?: string) => NodeSqliteDatabaseShape
27
+ }
28
+
29
+ class NodeSqliteStatement implements SyncSqliteStatement {
30
+ readonly reader: boolean
31
+
32
+ constructor(
33
+ private readonly stmt: NodeSqliteStatementShape,
34
+ sql: string
35
+ ) {
36
+ // node:sqlite StatementSync does not have a .reader property
37
+ // (that's a better-sqlite3 API). Fall back to SQL inspection when absent.
38
+ if (stmt.reader !== undefined) {
39
+ this.reader = Boolean(stmt.reader)
40
+ } else {
41
+ const upper = sql.trimStart().toUpperCase()
42
+ this.reader =
43
+ upper.startsWith('SELECT') ||
44
+ upper.startsWith('WITH') ||
45
+ upper.startsWith('PRAGMA') ||
46
+ upper.startsWith('EXPLAIN') ||
47
+ upper.startsWith('VALUES') ||
48
+ /\bRETURNING\b/.test(upper)
49
+ }
50
+ }
51
+
52
+ all(...parameters: unknown[]): unknown[] {
53
+ return this.stmt.all(...parameters) as unknown[]
54
+ }
55
+
56
+ get(...parameters: unknown[]): unknown | null {
57
+ return (this.stmt.get(...parameters) as unknown) ?? null
58
+ }
59
+
60
+ iterate(...parameters: unknown[]): IterableIterator<unknown> {
61
+ return this.stmt.iterate(...parameters) as IterableIterator<unknown>
62
+ }
63
+
64
+ run(...parameters: unknown[]): SyncSqliteChanges {
65
+ const result = this.stmt.run(...parameters)
66
+ return {
67
+ changes: result.changes,
68
+ lastInsertRowid: result.lastInsertRowid,
69
+ }
70
+ }
71
+ }
72
+
73
+ class NodeSqliteDatabase implements SyncSqliteDatabase {
74
+ constructor(private readonly db: NodeSqliteDatabaseShape) {}
75
+
76
+ exec(sql: string): void {
77
+ this.db.exec(sql)
78
+ }
79
+
80
+ prepare(sql: string): SyncSqliteStatement {
81
+ return new NodeSqliteStatement(this.db.prepare(sql), sql)
82
+ }
83
+
84
+ close(): void {
85
+ this.db.close()
86
+ }
87
+ }
88
+
89
+ async function importNodeSqlite(): Promise<NodeSqliteModule> {
90
+ const dynamicImport = new Function(
91
+ 'return import("node:sqlite")'
92
+ ) as () => Promise<NodeSqliteModule>
93
+ try {
94
+ return await dynamicImport()
95
+ } catch (error: any) {
96
+ // node ships node:sqlite unflagged only from 24. The raw failure is
97
+ // ERR_UNKNOWN_BUILTIN_MODULE, which reads like a broken install rather than
98
+ // a runtime that is simply too old — so say which it is and how to get past it.
99
+ if (error?.code === 'ERR_UNKNOWN_BUILTIN_MODULE') {
100
+ throw new Error(
101
+ `This needs node:sqlite, which Node ${process.versions.node} does not provide ` +
102
+ `(it is unflagged from Node 24). Either upgrade Node, or run the CLI on bun, ` +
103
+ `which has it: \`bunx --bun pikku <command>\`.`,
104
+ { cause: error }
105
+ )
106
+ }
107
+ throw error
108
+ }
109
+ }
110
+
111
+ export async function createNodeSqliteRuntime(): Promise<SqliteRuntime> {
112
+ const { DatabaseSync } = await importNodeSqlite()
113
+ return {
114
+ open(filename) {
115
+ return new NodeSqliteDatabase(new DatabaseSync(filename))
116
+ },
117
+ }
118
+ }
@@ -0,0 +1,41 @@
1
+ export interface SyncSqliteChanges {
2
+ changes: number | bigint
3
+ lastInsertRowid: number | bigint
4
+ }
5
+
6
+ export interface SyncSqliteStatement {
7
+ reader: boolean
8
+ all(...parameters: unknown[]): unknown[]
9
+ get(...parameters: unknown[]): unknown | null
10
+ iterate(...parameters: unknown[]): IterableIterator<unknown>
11
+ run(...parameters: unknown[]): SyncSqliteChanges
12
+ }
13
+
14
+ export interface SyncSqliteDatabase {
15
+ exec(sql: string): void
16
+ prepare(sql: string): SyncSqliteStatement
17
+ close(): void
18
+ }
19
+
20
+ export interface SqliteRuntime {
21
+ open(filename: string): SyncSqliteDatabase
22
+ }
23
+
24
+ let runtimePromise: Promise<SqliteRuntime> | undefined
25
+
26
+ export async function loadSqliteRuntime(): Promise<SqliteRuntime> {
27
+ runtimePromise ??= (async () => {
28
+ const isBunRuntime =
29
+ typeof (globalThis as { Bun?: unknown }).Bun !== 'undefined'
30
+
31
+ if (isBunRuntime) {
32
+ const { bunSqliteRuntime } = await import('./sqlite-runtime-bun.js')
33
+ return bunSqliteRuntime
34
+ }
35
+
36
+ const { createNodeSqliteRuntime } = await import('./sqlite-runtime-node.js')
37
+ return createNodeSqliteRuntime()
38
+ })()
39
+
40
+ return runtimePromise
41
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,13 @@
1
+ {
2
+ "extends": "../tsconfig.json",
3
+ "compilerOptions": {
4
+ "rootDir": ".",
5
+ "types": ["node", "bun"],
6
+ "module": "Node18",
7
+ "outDir": "dist",
8
+ "target": "esnext",
9
+ "declaration": true
10
+ },
11
+ "include": ["src/**/*.ts"],
12
+ "exclude": ["**/*.test.ts", "node_modules"]
13
+ }