@ku6epxboctuk/sqlite-up 0.0.0-stage → 0.6.1
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/LICENSE +23 -0
- package/README.md +453 -2
- package/dist/errors.d.ts +26 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/index.d.ts +111 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +533 -0
- package/dist/index.js.map +1 -0
- package/dist/providers/better-sqlite3.d.ts +18 -0
- package/dist/providers/better-sqlite3.d.ts.map +1 -0
- package/dist/providers/bun-sql.d.ts +11 -0
- package/dist/providers/bun-sql.d.ts.map +1 -0
- package/dist/providers/bun-sqlite.d.ts +17 -0
- package/dist/providers/bun-sqlite.d.ts.map +1 -0
- package/dist/providers/index.d.ts +12 -0
- package/dist/providers/index.d.ts.map +1 -0
- package/dist/providers/manual-transaction.d.ts +7 -0
- package/dist/providers/manual-transaction.d.ts.map +1 -0
- package/dist/providers/node-sqlite.d.ts +17 -0
- package/dist/providers/node-sqlite.d.ts.map +1 -0
- package/dist/providers/types.d.ts +15 -0
- package/dist/providers/types.d.ts.map +1 -0
- package/dist/types.d.ts +201 -0
- package/dist/types.d.ts.map +1 -0
- package/package.json +79 -4
package/LICENSE
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
Copyright (c) 2026 Sandrino Di Mattia
|
|
2
|
+
Copyright (c) 2026 Ku6epXBOCTuK (fork modifications)
|
|
3
|
+
|
|
4
|
+
Permission is hereby granted, free of charge, to any person
|
|
5
|
+
obtaining a copy of this software and associated documentation
|
|
6
|
+
files (the "Software"), to deal in the Software without
|
|
7
|
+
restriction, including without limitation the rights to use,
|
|
8
|
+
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the
|
|
10
|
+
Software is furnished to do so, subject to the following
|
|
11
|
+
conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be
|
|
14
|
+
included in all copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
|
18
|
+
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
20
|
+
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
21
|
+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
22
|
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
23
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,454 @@
|
|
|
1
|
-
#
|
|
1
|
+
# sqlite-up
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://badge.fury.io/js/@ku6epxboctuk%2Fsqlite-up)
|
|
4
|
+
[](https://www.typescriptlang.org/)
|
|
5
|
+
[](https://opensource.org/licenses/MIT)
|
|
6
|
+
|
|
7
|
+
A lightweight SQLite migration system for Node.js and Bun, built with TypeScript. Manage your SQLite database schema changes with ease and confidence.
|
|
8
|
+
|
|
9
|
+
> **Fork notice** — published as `@ku6epxboctuk/sqlite-up`, forked from [sandrinodimattia/sqlite-up](https://github.com/sandrinodimattia/sqlite-up) at 0.6.0.
|
|
10
|
+
> Change vs upstream: migration modules are loaded through `pathToFileURL(...)`, so `migrationsDir` can be an absolute Windows path
|
|
11
|
+
> (`C:\...`). Upstream fails with `ERR_UNSUPPORTED_ESM_URL_SCHEME` on Windows. No API changes.
|
|
12
|
+
|
|
13
|
+
## Features
|
|
14
|
+
|
|
15
|
+
- 🚀 Modern TypeScript-first API
|
|
16
|
+
- 🔒 Concurrency-safe with database locking
|
|
17
|
+
- ⚡️ Lightweight and fast
|
|
18
|
+
- 🔄 Supports migrations and rollbacks
|
|
19
|
+
- 📊 Migration status tracking
|
|
20
|
+
- 🔐 Transaction-safe migrations
|
|
21
|
+
- 🧩 Works with Node 24+ `node:sqlite`, Bun `bun:sqlite`, Bun `SQL`, optional `better-sqlite3`, and compatible SQLite clients
|
|
22
|
+
|
|
23
|
+
## Installation
|
|
24
|
+
|
|
25
|
+
Requires Node.js 24+ or Bun.
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npm install @ku6epxboctuk/sqlite-up
|
|
29
|
+
# or
|
|
30
|
+
yarn add @ku6epxboctuk/sqlite-up
|
|
31
|
+
# or
|
|
32
|
+
pnpm add @ku6epxboctuk/sqlite-up
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Quick Start
|
|
36
|
+
|
|
37
|
+
1. Create a migrations directory:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
mkdir migrations
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
2. Create your first migration file `migrations/001_create_users.ts`:
|
|
44
|
+
|
|
45
|
+
```typescript
|
|
46
|
+
import type { SqliteDatabase } from '@ku6epxboctuk/sqlite-up';
|
|
47
|
+
|
|
48
|
+
export const up = async (db: SqliteDatabase): Promise<void> => {
|
|
49
|
+
await db.exec(`
|
|
50
|
+
CREATE TABLE users (
|
|
51
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
52
|
+
email TEXT NOT NULL UNIQUE,
|
|
53
|
+
name TEXT NOT NULL,
|
|
54
|
+
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
|
55
|
+
)
|
|
56
|
+
`);
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export const down = async (db: SqliteDatabase): Promise<void> => {
|
|
60
|
+
await db.exec('DROP TABLE users');
|
|
61
|
+
};
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
3. Use the migrator in your code:
|
|
65
|
+
|
|
66
|
+
```typescript
|
|
67
|
+
import { DatabaseSync } from 'node:sqlite';
|
|
68
|
+
import { Migrator } from '@ku6epxboctuk/sqlite-up';
|
|
69
|
+
|
|
70
|
+
async function main() {
|
|
71
|
+
const db = new DatabaseSync('myapp.db');
|
|
72
|
+
|
|
73
|
+
const migrator = new Migrator({
|
|
74
|
+
db,
|
|
75
|
+
migrationsDir: './migrations',
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
// Run all pending migrations
|
|
79
|
+
const result = await migrator.apply();
|
|
80
|
+
if (result.success) {
|
|
81
|
+
console.log('Applied migrations:', result.appliedMigrations);
|
|
82
|
+
} else {
|
|
83
|
+
console.error('Migration failed:', result.error);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
main().catch(console.error);
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### Bun
|
|
91
|
+
|
|
92
|
+
The same migrator accepts Bun's synchronous `bun:sqlite` database:
|
|
93
|
+
|
|
94
|
+
```typescript
|
|
95
|
+
import { Database } from 'bun:sqlite';
|
|
96
|
+
import { Migrator } from '@ku6epxboctuk/sqlite-up';
|
|
97
|
+
|
|
98
|
+
const db = new Database('myapp.db', { create: true });
|
|
99
|
+
const migrator = new Migrator({
|
|
100
|
+
db,
|
|
101
|
+
migrationsDir: './migrations',
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
await migrator.apply();
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
It also accepts Bun's Promise-based `SQL` SQLite client:
|
|
108
|
+
|
|
109
|
+
```typescript
|
|
110
|
+
import { SQL } from 'bun';
|
|
111
|
+
import { Migrator } from '@ku6epxboctuk/sqlite-up';
|
|
112
|
+
|
|
113
|
+
const sql = new SQL('sqlite://myapp.db');
|
|
114
|
+
const migrator = new Migrator({
|
|
115
|
+
db: sql,
|
|
116
|
+
migrationsDir: './migrations',
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
await migrator.apply();
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
When using Bun `SQL`, write migration files as `async` functions and `await` database calls.
|
|
123
|
+
|
|
124
|
+
### better-sqlite3
|
|
125
|
+
|
|
126
|
+
If your project already uses `better-sqlite3`, pass its database instance directly. `@ku6epxboctuk/sqlite-up` does not install it or require it as a peer dependency, so install `better-sqlite3` in your application if you use this provider.
|
|
127
|
+
|
|
128
|
+
```typescript
|
|
129
|
+
import Database from 'better-sqlite3';
|
|
130
|
+
import { Migrator } from '@ku6epxboctuk/sqlite-up';
|
|
131
|
+
|
|
132
|
+
const db = new Database('myapp.db');
|
|
133
|
+
const migrator = new Migrator({
|
|
134
|
+
db,
|
|
135
|
+
migrationsDir: './migrations',
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
await migrator.apply();
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
## API Reference
|
|
142
|
+
|
|
143
|
+
### `Migrator`
|
|
144
|
+
|
|
145
|
+
The main class for managing migrations.
|
|
146
|
+
|
|
147
|
+
#### Constructor Options
|
|
148
|
+
|
|
149
|
+
```typescript
|
|
150
|
+
interface MigratorOptions {
|
|
151
|
+
db: MigratorDatabase; // Node DatabaseSync, Bun Database, Bun SQL, better-sqlite3, or compatible SQLite instance
|
|
152
|
+
migrationsDir: string; // Directory containing migration files
|
|
153
|
+
migrationsTable?: string; // Optional: Table name for tracking migrations (default: 'schema_migrations')
|
|
154
|
+
migrationsLockTable?: string; // Optional: Table name for migration locks (default: 'schema_migrations_lock')
|
|
155
|
+
fileExtensions?: string[]; // Optional: File extensions to look for (default: ['ts', 'js']). Note: .d.ts files are always ignored
|
|
156
|
+
}
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
#### Methods
|
|
160
|
+
|
|
161
|
+
##### `apply()`
|
|
162
|
+
|
|
163
|
+
Apply all pending migrations.
|
|
164
|
+
|
|
165
|
+
```typescript
|
|
166
|
+
const migrator = new Migrator({
|
|
167
|
+
db,
|
|
168
|
+
migrationsDir: './migrations',
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
// Run all pending migrations
|
|
172
|
+
const result = await migrator.apply();
|
|
173
|
+
if (result.success) {
|
|
174
|
+
console.log('Applied migrations:', result.appliedMigrations);
|
|
175
|
+
} else {
|
|
176
|
+
console.error('Migration failed:', result.error);
|
|
177
|
+
}
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
##### `rollback()`
|
|
181
|
+
|
|
182
|
+
Rollback the most recent batch of migrations.
|
|
183
|
+
|
|
184
|
+
```typescript
|
|
185
|
+
// Rollback the last batch of migrations
|
|
186
|
+
const result = await migrator.rollback();
|
|
187
|
+
if (result.success) {
|
|
188
|
+
console.log('Rolled back:', result.appliedMigrations);
|
|
189
|
+
} else {
|
|
190
|
+
console.error('Rollback failed:', result.error);
|
|
191
|
+
}
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
##### `status()`
|
|
195
|
+
|
|
196
|
+
Get the status of all migrations. Shows which migrations have been applied and which are pending.
|
|
197
|
+
|
|
198
|
+
```typescript
|
|
199
|
+
const status = await migrator.status();
|
|
200
|
+
console.log('Migration Status:', status);
|
|
201
|
+
// Example output:
|
|
202
|
+
// Migration Status: {
|
|
203
|
+
// currentBatch: 1,
|
|
204
|
+
// pending: 0,
|
|
205
|
+
// applied: [
|
|
206
|
+
// {
|
|
207
|
+
// name: '001_users_table.ts',
|
|
208
|
+
// executed_at: '2025-01-22T12:29:22.402Z',
|
|
209
|
+
// batch: 1
|
|
210
|
+
// },
|
|
211
|
+
// {
|
|
212
|
+
// name: '002_add_age.ts',
|
|
213
|
+
// executed_at: '2025-01-22T12:29:22.406Z',
|
|
214
|
+
// batch: 1
|
|
215
|
+
// }
|
|
216
|
+
// ]
|
|
217
|
+
// }
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
##### `plan()`
|
|
221
|
+
|
|
222
|
+
Plan the pending migrations without applying them. Returns the next batch number and the list of pending migration names in order.
|
|
223
|
+
|
|
224
|
+
```typescript
|
|
225
|
+
const plan = await migrator.plan();
|
|
226
|
+
console.log('Migration Plan:', plan);
|
|
227
|
+
// Example output:
|
|
228
|
+
// Migration Plan: {
|
|
229
|
+
// nextBatch: 2,
|
|
230
|
+
// pendingMigrations: ['003_add_email_index.ts']
|
|
231
|
+
// }
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
##### Events
|
|
235
|
+
|
|
236
|
+
The migrator extends EventEmitter and emits events during migration:
|
|
237
|
+
|
|
238
|
+
```typescript
|
|
239
|
+
// Listen for migration events
|
|
240
|
+
migrator.on('migration:applied', function (name: string, batch: number): void {
|
|
241
|
+
console.log(`✅ Migration Applied: "${name}" in batch ${batch}`);
|
|
242
|
+
});
|
|
243
|
+
migrator.on('migration:rollback', function (name: string, batch: number): void {
|
|
244
|
+
console.log(`🔄 Migration Rolled Back: "${name}" from batch ${batch}`);
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
// Run migrations after setting up listeners
|
|
248
|
+
await migrator.apply();
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
##### Transaction Safety
|
|
252
|
+
|
|
253
|
+
All pending migrations in one `apply()` call run in a single transaction. If any part of a migration fails, the entire batch is rolled back:
|
|
254
|
+
|
|
255
|
+
```typescript
|
|
256
|
+
import type { SqliteDatabase } from '@ku6epxboctuk/sqlite-up';
|
|
257
|
+
|
|
258
|
+
export const up = async (db: SqliteDatabase): Promise<void> => {
|
|
259
|
+
// Both operations will be in the same transaction
|
|
260
|
+
await db.exec('CREATE TABLE users (id INTEGER PRIMARY KEY)');
|
|
261
|
+
await db.exec('CREATE INDEX idx_user_id ON users(id)');
|
|
262
|
+
|
|
263
|
+
// If any operation fails, the entire migration is rolled back
|
|
264
|
+
// and the database remains in its previous state
|
|
265
|
+
};
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
For synchronous SQLite clients such as Node `DatabaseSync`, Bun `Database`, `better-sqlite3`, and compatible `exec`/`prepare` clients, `@ku6epxboctuk/sqlite-up` uses explicit `BEGIN IMMEDIATE` transactions so async migration functions are still awaited before commit or rollback. For Bun `SQL`, `@ku6epxboctuk/sqlite-up` uses Bun SQL's native async transaction support when available.
|
|
269
|
+
|
|
270
|
+
## Migration Files
|
|
271
|
+
|
|
272
|
+
Migration files should be TypeScript or JavaScript files that export `up` and `down` functions:
|
|
273
|
+
|
|
274
|
+
```typescript
|
|
275
|
+
import type { SqliteDatabase } from '@ku6epxboctuk/sqlite-up';
|
|
276
|
+
|
|
277
|
+
export const up = async (db: SqliteDatabase): Promise<void> => {
|
|
278
|
+
// Migration code here
|
|
279
|
+
};
|
|
280
|
+
|
|
281
|
+
export const down = async (db: SqliteDatabase): Promise<void> => {
|
|
282
|
+
// Rollback code here
|
|
283
|
+
};
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
Files should be named using the format: `XXX_description.ts` where XXX is a sequence number (e.g., `001_`, `002_`).
|
|
287
|
+
|
|
288
|
+
The migrator loads migration files with dynamic `import()`. Bun can load TypeScript migrations directly. In Node.js, run your migration script with a TypeScript runtime such as `tsx`, or compile migrations to JavaScript and use `.js` migration files. You can also customize loaded extensions with `fileExtensions`; `.d.ts` files are always ignored.
|
|
289
|
+
|
|
290
|
+
### Providing Context
|
|
291
|
+
|
|
292
|
+
A second argument can be provided to migration file functions in order to supply your own context. Context should be passed in `apply` or `rollback`.
|
|
293
|
+
|
|
294
|
+
To enforce type correctness, type the `Migrator` and use `satisfies` in your migration files:
|
|
295
|
+
|
|
296
|
+
```typescript
|
|
297
|
+
import type { SqliteDatabase, Migration } from '@ku6epxboctuk/sqlite-up';
|
|
298
|
+
|
|
299
|
+
interface MyContext {
|
|
300
|
+
foo: string;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
export const up: Migration<MyContext>['up'] = async (db: SqliteDatabase, ctx: MyContext): Promise<void> => {
|
|
304
|
+
// Migration code here
|
|
305
|
+
// context is passed as ctx
|
|
306
|
+
};
|
|
307
|
+
|
|
308
|
+
export const down: Migration<MyContext>['down'] = async (db: SqliteDatabase, ctx: MyContext): Promise<void> => {
|
|
309
|
+
// Rollback code here
|
|
310
|
+
// context is passed as ctx
|
|
311
|
+
};
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
```typescript
|
|
315
|
+
import { DatabaseSync } from 'node:sqlite';
|
|
316
|
+
import { Migrator } from '@ku6epxboctuk/sqlite-up';
|
|
317
|
+
|
|
318
|
+
async function main() {
|
|
319
|
+
const db = new DatabaseSync('myapp.db');
|
|
320
|
+
|
|
321
|
+
const migrator = new Migrator<MyContext>({
|
|
322
|
+
db,
|
|
323
|
+
migrationsDir: './migrations',
|
|
324
|
+
});
|
|
325
|
+
|
|
326
|
+
const result = await migrator.apply({ foo: 'bar' });
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
main().catch(console.error);
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
## Error Handling
|
|
333
|
+
|
|
334
|
+
```typescript
|
|
335
|
+
import {
|
|
336
|
+
MigrationError, // Base error class
|
|
337
|
+
MigrationFileError, // Issues with migration files
|
|
338
|
+
MigrationLockError, // Locking-related errors
|
|
339
|
+
MigrationExecutionError, // Errors during migration execution
|
|
340
|
+
} from '@ku6epxboctuk/sqlite-up';
|
|
341
|
+
|
|
342
|
+
const result = await migrator.apply();
|
|
343
|
+
|
|
344
|
+
if (!result.success) {
|
|
345
|
+
if (result.error instanceof MigrationLockError) {
|
|
346
|
+
console.error('Migration failed, a different process is holding the lock:', result.error.message);
|
|
347
|
+
} else {
|
|
348
|
+
console.error('Migration failed:', result.error?.message);
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
The library provides specific error classes for different scenarios:
|
|
354
|
+
|
|
355
|
+
- `MigrationError` - Base error class
|
|
356
|
+
- `MigrationFileError` - Issues with migration files
|
|
357
|
+
- `MigrationExecutionError` - Errors during migration execution
|
|
358
|
+
- `MigrationLockError` - Lock-related errors
|
|
359
|
+
|
|
360
|
+
## Examples
|
|
361
|
+
|
|
362
|
+
Check out the [examples directory](https://github.com/Ku6epXBOCTuK/sqlite-up/tree/main/examples) for complete working examples.
|
|
363
|
+
|
|
364
|
+
## FAQ
|
|
365
|
+
|
|
366
|
+
### When running migrations as part of Vitest I get `TypeError: Unknown file extension ".ts"`
|
|
367
|
+
|
|
368
|
+
This happens when a migration file is dynamically imported at runtime but the process loading it is not configured to handle TypeScript. Vitest can transform test files, but dynamically imported migration files may still need to be inside Vitest's transform path or loaded through a TypeScript-aware runtime.
|
|
369
|
+
|
|
370
|
+
If your tests use TypeScript migration files, run the tests with Vitest as the test runner and keep the migrations in a location Vitest can transform. If the migrations are generated into a temporary directory or loaded by a helper process that runs plain Node.js, either write the test migrations as `.js` files or run that helper through a TypeScript loader such as `tsx` or `ts-node/esm`.
|
|
371
|
+
|
|
372
|
+
```bash
|
|
373
|
+
pnpm exec vitest run
|
|
374
|
+
|
|
375
|
+
# or, for a standalone migration helper used by tests
|
|
376
|
+
pnpm exec tsx migrate.ts
|
|
377
|
+
|
|
378
|
+
# or, with ts-node's ESM loader
|
|
379
|
+
node --loader ts-node/esm migrate.ts
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
If you prefer to register the ESM loader from Vitest setup, add a setup file:
|
|
383
|
+
|
|
384
|
+
```typescript
|
|
385
|
+
import { defineConfig } from 'vitest/config';
|
|
386
|
+
|
|
387
|
+
export default defineConfig({
|
|
388
|
+
test: {
|
|
389
|
+
environment: 'node',
|
|
390
|
+
setupFiles: ['./vitest.setup.ts'],
|
|
391
|
+
},
|
|
392
|
+
});
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
Then register the TypeScript loader in `vitest.setup.ts`:
|
|
396
|
+
|
|
397
|
+
```typescript
|
|
398
|
+
import { register } from 'node:module';
|
|
399
|
+
import { pathToFileURL } from 'node:url';
|
|
400
|
+
|
|
401
|
+
register('ts-node/esm', pathToFileURL('./'));
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
### Why do I get `TypeError: Unknown file extension ".ts"` in Node.js?
|
|
405
|
+
|
|
406
|
+
`@ku6epxboctuk/sqlite-up` loads migrations with dynamic `import()`, so Node.js needs a loader that understands TypeScript migration files. Run your migration entry point with a TypeScript runtime such as `tsx`, use an ESM loader such as `ts-node/esm`, or compile migrations to JavaScript before running them with plain Node.js.
|
|
407
|
+
|
|
408
|
+
```bash
|
|
409
|
+
pnpm exec tsx migrate.ts
|
|
410
|
+
# or
|
|
411
|
+
node --loader ts-node/esm migrate.ts
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
For production deployments that run plain Node.js, prefer compiled `.js` migrations and point `migrationsDir` at the compiled migration output.
|
|
415
|
+
|
|
416
|
+
## Contributing
|
|
417
|
+
|
|
418
|
+
### Development
|
|
419
|
+
|
|
420
|
+
```bash
|
|
421
|
+
# Install dependencies
|
|
422
|
+
pnpm install
|
|
423
|
+
|
|
424
|
+
# Run tests
|
|
425
|
+
pnpm test
|
|
426
|
+
|
|
427
|
+
# Run Bun provider tests
|
|
428
|
+
pnpm test:bun
|
|
429
|
+
|
|
430
|
+
# Run tests with coverage
|
|
431
|
+
pnpm test:coverage
|
|
432
|
+
|
|
433
|
+
# Type check
|
|
434
|
+
pnpm typecheck
|
|
435
|
+
|
|
436
|
+
# Build the project
|
|
437
|
+
pnpm build
|
|
438
|
+
|
|
439
|
+
# Check formatting and lint rules
|
|
440
|
+
pnpm check
|
|
441
|
+
|
|
442
|
+
# Apply safe and unsafe Biome fixes locally
|
|
443
|
+
pnpm check:fix
|
|
444
|
+
|
|
445
|
+
# Lint the code
|
|
446
|
+
pnpm lint
|
|
447
|
+
|
|
448
|
+
# Format the code
|
|
449
|
+
pnpm format
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
## License
|
|
453
|
+
|
|
454
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base error class for all sqlite-up errors
|
|
3
|
+
*/
|
|
4
|
+
export declare class MigrationError extends Error {
|
|
5
|
+
readonly cause?: Error | undefined;
|
|
6
|
+
constructor(message: string, cause?: Error | undefined);
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Thrown when there's an issue with migration files
|
|
10
|
+
*/
|
|
11
|
+
export declare class MigrationFileError extends MigrationError {
|
|
12
|
+
constructor(message: string, cause?: Error);
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Thrown when there's a locking issue
|
|
16
|
+
*/
|
|
17
|
+
export declare class MigrationLockError extends MigrationError {
|
|
18
|
+
constructor(message: string, cause?: Error);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Thrown when there's an issue during migration execution
|
|
22
|
+
*/
|
|
23
|
+
export declare class MigrationExecutionError extends MigrationError {
|
|
24
|
+
constructor(message: string, cause?: Error);
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,qBAAa,cAAe,SAAQ,KAAK;aAGrB,KAAK,CAAC,EAAE,KAAK;gBAD7B,OAAO,EAAE,MAAM,EACC,KAAK,CAAC,EAAE,KAAK,YAAA;CAKhC;AAED;;GAEG;AACH,qBAAa,kBAAmB,SAAQ,cAAc;gBACxC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK;CAI3C;AAED;;GAEG;AACH,qBAAa,kBAAmB,SAAQ,cAAc;gBACxC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK;CAI3C;AAED;;GAEG;AACH,qBAAa,uBAAwB,SAAQ,cAAc;gBAC7C,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK;CAI3C"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { EventEmitter } from 'node:events';
|
|
2
|
+
import type { ContextArg, MigrationPlan, MigrationResult, MigrationStatus, MigratorOptions } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Migration provider for SQLite databases.
|
|
5
|
+
* @example
|
|
6
|
+
* const db = new DatabaseSync('database.db');
|
|
7
|
+
* const migrator = new Migrator({ db, migrationsDir: 'migrations' });
|
|
8
|
+
* await migrator.apply();
|
|
9
|
+
*/
|
|
10
|
+
export declare class Migrator<T = undefined> extends EventEmitter {
|
|
11
|
+
/**
|
|
12
|
+
* Driver-specific provider normalized to the sqlite-up database surface.
|
|
13
|
+
*/
|
|
14
|
+
private provider;
|
|
15
|
+
/**
|
|
16
|
+
* Database handle used by migrations and internal bookkeeping queries.
|
|
17
|
+
*/
|
|
18
|
+
private db;
|
|
19
|
+
/**
|
|
20
|
+
* Directory where migration modules are loaded from.
|
|
21
|
+
*/
|
|
22
|
+
private migrationsDir;
|
|
23
|
+
/**
|
|
24
|
+
* Table that records successfully applied migrations.
|
|
25
|
+
*/
|
|
26
|
+
private migrationsTable;
|
|
27
|
+
/**
|
|
28
|
+
* Table that stores the single-row migration lock.
|
|
29
|
+
*/
|
|
30
|
+
private lockTable;
|
|
31
|
+
/**
|
|
32
|
+
* Migration modules loaded from disk in execution order.
|
|
33
|
+
*/
|
|
34
|
+
private migrations;
|
|
35
|
+
/**
|
|
36
|
+
* Whether internal tables and migration files have already been initialized.
|
|
37
|
+
*/
|
|
38
|
+
private initialized;
|
|
39
|
+
/**
|
|
40
|
+
* File extensions considered when loading migration modules.
|
|
41
|
+
*/
|
|
42
|
+
private fileExtensions;
|
|
43
|
+
constructor(options: MigratorOptions);
|
|
44
|
+
/**
|
|
45
|
+
* Ensures the `schema_migrations` and `schema_migrations_lock` tables exist,
|
|
46
|
+
* and loads migration files from the migrations directory.
|
|
47
|
+
*/
|
|
48
|
+
private init;
|
|
49
|
+
/**
|
|
50
|
+
* Initializes the `schema_migrations` and `schema_migrations_lock` tables.
|
|
51
|
+
*/
|
|
52
|
+
private initTables;
|
|
53
|
+
/**
|
|
54
|
+
* Load migration files from the `migrationsDir`.
|
|
55
|
+
* Migration files must export { up, down }.
|
|
56
|
+
* The migrations are loaded in alphabetical order.
|
|
57
|
+
*/
|
|
58
|
+
private loadMigrationsFromDirectory;
|
|
59
|
+
/**
|
|
60
|
+
* Acquire a lock to prevent concurrent migrations.
|
|
61
|
+
* Throws an error if the lock is already held.
|
|
62
|
+
*/
|
|
63
|
+
private acquireLock;
|
|
64
|
+
/**
|
|
65
|
+
* Release the migration lock.
|
|
66
|
+
*/
|
|
67
|
+
private releaseLock;
|
|
68
|
+
/**
|
|
69
|
+
* Get the highest batch number.
|
|
70
|
+
*/
|
|
71
|
+
private getCurrentBatch;
|
|
72
|
+
/**
|
|
73
|
+
* Insert a record for an applied migration.
|
|
74
|
+
*/
|
|
75
|
+
private recordMigration;
|
|
76
|
+
/**
|
|
77
|
+
* Delete a record for a migration that is being rolled back.
|
|
78
|
+
*/
|
|
79
|
+
private removeMigration;
|
|
80
|
+
/**
|
|
81
|
+
* Run SQL operations in a transaction.
|
|
82
|
+
* @param fn The function to run in the transaction.
|
|
83
|
+
*/
|
|
84
|
+
private runTransaction;
|
|
85
|
+
/**
|
|
86
|
+
* Apply all pending migrations in a single batch.
|
|
87
|
+
* Returns the names of applied migrations.
|
|
88
|
+
*/
|
|
89
|
+
apply(...args: ContextArg<T>): Promise<MigrationResult>;
|
|
90
|
+
/**
|
|
91
|
+
* Roll back the most recent batch of migrations.
|
|
92
|
+
* Returns the names of rolled back migrations.
|
|
93
|
+
*/
|
|
94
|
+
rollback(...args: ContextArg<T>): Promise<MigrationResult>;
|
|
95
|
+
/**
|
|
96
|
+
* Get the status of migrations.
|
|
97
|
+
* Returns:
|
|
98
|
+
* - currentBatch: the highest batch number applied
|
|
99
|
+
* - pending: number of migrations not yet applied
|
|
100
|
+
* - applied: list of all applied migrations
|
|
101
|
+
*/
|
|
102
|
+
status(): Promise<MigrationStatus>;
|
|
103
|
+
/**
|
|
104
|
+
* Plan the pending migrations without applying them.
|
|
105
|
+
* Returns the next batch number and the list of pending migration names in order.
|
|
106
|
+
*/
|
|
107
|
+
plan(): Promise<MigrationPlan>;
|
|
108
|
+
}
|
|
109
|
+
export { MigrationError, MigrationExecutionError, MigrationFileError, MigrationLockError, } from './errors.js';
|
|
110
|
+
export type { BunSqliteDatabase, ContextArg, MaybePromise, Migration, MigrationPlan, MigrationRecord, MigrationResult, MigrationStatus, MigratorDatabase, MigratorOptions, SqliteDatabase, SqliteRunResult, SqliteStatement, SqliteTransaction, } from './types.js';
|
|
111
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAM3C,OAAO,KAAK,EACV,UAAU,EAGV,aAAa,EAEb,eAAe,EACf,eAAe,EACf,eAAe,EAEhB,MAAM,YAAY,CAAC;AAEpB;;;;;;GAMG;AACH,qBAAa,QAAQ,CAAC,CAAC,GAAG,SAAS,CAAE,SAAQ,YAAY;IACvD;;OAEG;IACH,OAAO,CAAC,QAAQ,CAAiB;IAEjC;;OAEG;IACH,OAAO,CAAC,EAAE,CAAiB;IAE3B;;OAEG;IACH,OAAO,CAAC,aAAa,CAAS;IAE9B;;OAEG;IACH,OAAO,CAAC,eAAe,CAAS;IAEhC;;OAEG;IACH,OAAO,CAAC,SAAS,CAAS;IAE1B;;OAEG;IACH,OAAO,CAAC,UAAU,CAAsB;IAExC;;OAEG;IACH,OAAO,CAAC,WAAW,CAAS;IAE5B;;OAEG;IACH,OAAO,CAAC,cAAc,CAAW;gBAErB,OAAO,EAAE,eAAe;IAWpC;;;OAGG;YACW,IAAI;IAWlB;;OAEG;YACW,UAAU;IA8BxB;;;;OAIG;YACW,2BAA2B;IA6CzC;;;OAGG;YACW,WAAW;IAsBzB;;OAEG;YACW,WAAW;IAQzB;;OAEG;YACW,eAAe;IAO7B;;OAEG;YACW,eAAe;IAY7B;;OAEG;YACW,eAAe;IAW7B;;;OAGG;YACW,cAAc;IAI5B;;;OAGG;IACG,KAAK,CAAC,GAAG,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,eAAe,CAAC;IAyE7D;;;OAGG;IACG,QAAQ,CAAC,GAAG,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,eAAe,CAAC;IAsFhE;;;;;;OAMG;IACG,MAAM,IAAI,OAAO,CAAC,eAAe,CAAC;IA+BxC;;;OAGG;IACG,IAAI,IAAI,OAAO,CAAC,aAAa,CAAC;CAwBrC;AAED,OAAO,EACL,cAAc,EACd,uBAAuB,EACvB,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,aAAa,CAAC;AACrB,YAAY,EACV,iBAAiB,EACjB,UAAU,EACV,YAAY,EACZ,SAAS,EACT,aAAa,EACb,eAAe,EACf,eAAe,EACf,eAAe,EACf,gBAAgB,EAChB,eAAe,EACf,cAAc,EACd,eAAe,EACf,eAAe,EACf,iBAAiB,GAClB,MAAM,YAAY,CAAC"}
|