@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.
- package/CHANGELOG.md +14 -0
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.js +1 -1
- package/dist/src/schema-sql.d.ts +11 -0
- package/dist/src/schema-sql.js +24 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +2 -2
- package/run-tests.sh +0 -0
- package/src/index.ts +35 -0
- package/src/migration-identifiers.test.ts +142 -0
- package/src/migration-identifiers.ts +321 -0
- package/src/postgres/index.ts +4 -0
- package/src/postgres/postgres-migrator.ts +81 -0
- package/src/schema-sql.test.ts +92 -0
- package/src/schema-sql.ts +179 -0
- package/src/sql-migrator.ts +219 -0
- package/src/sqlite/index.ts +8 -0
- package/src/sqlite/sqlite-migrator.ts +49 -0
- package/src/sqlite/sqlite-runtime-bun.ts +83 -0
- package/src/sqlite/sqlite-runtime-node.ts +118 -0
- package/src/sqlite/sqlite-runtime.ts +41 -0
- package/tsconfig.json +13 -0
|
@@ -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
|
+
}
|