nanodb-orm 0.0.4 → 0.0.5

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 (41) hide show
  1. package/README.md +379 -39
  2. package/dist/cli.d.ts +84 -1
  3. package/dist/cli.d.ts.map +1 -1
  4. package/dist/cli.js +227 -149
  5. package/dist/cli.js.map +1 -1
  6. package/dist/core/connection.d.ts +6 -0
  7. package/dist/core/connection.d.ts.map +1 -1
  8. package/dist/core/connection.js +17 -3
  9. package/dist/core/connection.js.map +1 -1
  10. package/dist/index.d.ts +206 -13
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +222 -50
  13. package/dist/index.js.map +1 -1
  14. package/dist/init.d.ts +114 -62
  15. package/dist/init.d.ts.map +1 -1
  16. package/dist/init.js +79 -44
  17. package/dist/init.js.map +1 -1
  18. package/dist/types/index.d.ts +176 -38
  19. package/dist/types/index.d.ts.map +1 -1
  20. package/dist/types/index.js +3 -0
  21. package/dist/types/index.js.map +1 -1
  22. package/dist/utils/migrations.d.ts +2 -2
  23. package/dist/utils/migrations.d.ts.map +1 -1
  24. package/dist/utils/migrations.js +53 -48
  25. package/dist/utils/migrations.js.map +1 -1
  26. package/dist/utils/schema-introspection.d.ts +4 -4
  27. package/dist/utils/schema-introspection.d.ts.map +1 -1
  28. package/dist/utils/schema-introspection.js +0 -3
  29. package/dist/utils/schema-introspection.js.map +1 -1
  30. package/dist/utils/seeds.d.ts +2 -2
  31. package/dist/utils/seeds.d.ts.map +1 -1
  32. package/dist/utils/seeds.js +10 -1
  33. package/dist/utils/seeds.js.map +1 -1
  34. package/dist/utils/sync.d.ts.map +1 -1
  35. package/dist/utils/sync.js +11 -2
  36. package/dist/utils/sync.js.map +1 -1
  37. package/dist/utils/transactions.d.ts +58 -2
  38. package/dist/utils/transactions.d.ts.map +1 -1
  39. package/dist/utils/transactions.js +89 -8
  40. package/dist/utils/transactions.js.map +1 -1
  41. package/package.json +1 -1
package/README.md CHANGED
@@ -1,15 +1,15 @@
1
1
  # nanodb-orm
2
2
 
3
- A lightweight, schema-agnostic ORM wrapper for Drizzle ORM with automatic migrations, schema introspection, CLI tools, and support for SQLite/Turso databases.
3
+ A lightweight ORM wrapper for Drizzle ORM with automatic migrations, schema introspection, CLI tools, and support for SQLite/Turso databases.
4
4
 
5
5
  ## Features
6
6
 
7
+ - **TypeScript First** — Full type inference from schema to queries
7
8
  - **Auto-Migrations** — Automatically creates and updates database schemas from Drizzle tables
8
9
  - **Schema Introspection** — Comprehensive schema analysis and validation
9
10
  - **Multi-Database** — Works with local SQLite and remote Turso databases
10
11
  - **Transactions** — Full transaction support with automatic rollback
11
12
  - **CLI Tools** — Built-in commands including Drizzle Studio integration
12
- - **Type Safe** — Full TypeScript support with proper type inference
13
13
  - **Plugin System** — Extensible with hooks for audit, validation, transformations
14
14
  - **Minimal** — ~1K lines of code, zero bloat
15
15
 
@@ -54,65 +54,136 @@ npx nanodb studio
54
54
 
55
55
  ![Drizzle Studio](https://orm.drizzle.team/images/drizzle-studio.png)
56
56
 
57
+ ## Import Styles
58
+
59
+ ```typescript
60
+ // Default import (recommended)
61
+ import nanodb from 'nanodb-orm';
62
+
63
+ const users = nanodb.schema.table('users', { ... });
64
+ const db = await nanodb.createDatabase({ tables: { users } });
65
+ await db.select().from(users).where(nanodb.query.eq(users.id, 1));
66
+ ```
67
+
68
+ ```typescript
69
+ // Named imports
70
+ import { createDatabase, schema, query } from 'nanodb-orm';
71
+ ```
72
+
73
+ ```typescript
74
+ // Individual imports (tree-shakeable)
75
+ import { createDatabase, table, integer, text, eq } from 'nanodb-orm';
76
+ ```
77
+
57
78
  ## Quick Start
58
79
 
59
80
  ### 1. Define Your Schema
60
81
 
61
82
  ```typescript
62
- import { table, integer, text } from 'nanodb-orm';
83
+ import nanodb from 'nanodb-orm';
63
84
 
64
- const users = table('users', {
65
- id: integer('id').primaryKey({ autoIncrement: true }),
66
- name: text('name').notNull(),
67
- email: text('email').unique().notNull(),
68
- age: integer('age'),
85
+ const users = nanodb.schema.table('users', {
86
+ id: nanodb.schema.integer('id').primaryKey({ autoIncrement: true }),
87
+ name: nanodb.schema.text('name').notNull(),
88
+ email: nanodb.schema.text('email').unique().notNull(),
89
+ age: nanodb.schema.integer('age'),
69
90
  });
70
91
 
71
- const posts = table('posts', {
72
- id: integer('id').primaryKey({ autoIncrement: true }),
73
- title: text('title').notNull(),
74
- userId: integer('userId').notNull(),
92
+ const posts = nanodb.schema.table('posts', {
93
+ id: nanodb.schema.integer('id').primaryKey({ autoIncrement: true }),
94
+ title: nanodb.schema.text('title').notNull(),
95
+ userId: nanodb.schema.integer('userId').notNull(),
75
96
  });
76
-
77
- const tables = { users, posts };
78
97
  ```
79
98
 
80
99
  ### 2. Create Database
81
100
 
82
101
  ```typescript
83
- import { createDatabase } from 'nanodb-orm';
84
-
85
- // One line: creates tables, runs migrations, seeds data, returns db
86
- const db = await createDatabase({
87
- tables,
102
+ const db = await nanodb.createDatabase({
103
+ tables: { users, posts },
88
104
  seedData: {
89
105
  users: [{ name: 'Alice', email: 'alice@example.com', age: 28 }],
90
106
  },
91
107
  });
92
108
 
93
- // Store db and use it everywhere - no need for getInstance() or getDb()
94
109
  export { db };
95
110
  ```
96
111
 
97
- ### 3. Query with Type Safety
112
+ ### 3. Query Your Data
98
113
 
99
114
  ```typescript
100
- import { eq, gte } from 'nanodb-orm';
101
-
102
115
  // SELECT
103
116
  const allUsers = await db.select().from(users);
104
- const adults = await db.select().from(users).where(gte(users.age, 18));
117
+ const adults = await db.select().from(users).where(nanodb.query.gte(users.age, 18));
105
118
 
106
119
  // INSERT
107
120
  await db.insert(users).values({ name: 'Bob', email: 'bob@example.com' });
108
121
 
109
122
  // UPDATE
110
- await db.update(users).set({ name: 'Robert' }).where(eq(users.email, 'bob@example.com'));
123
+ await db.update(users).set({ name: 'Robert' }).where(nanodb.query.eq(users.email, 'bob@example.com'));
111
124
 
112
125
  // DELETE
113
- await db.delete(users).where(eq(users.email, 'bob@example.com'));
126
+ await db.delete(users).where(nanodb.query.eq(users.email, 'bob@example.com'));
127
+ ```
128
+
129
+ ## Type Inference
130
+
131
+ nanodb-orm provides full type inference from your schema:
132
+
133
+ ```typescript
134
+ import {
135
+ createDatabase,
136
+ table,
137
+ integer,
138
+ text,
139
+ type SelectModel,
140
+ type InsertModel,
141
+ } from 'nanodb-orm';
142
+
143
+ const users = table('users', {
144
+ id: integer('id').primaryKey({ autoIncrement: true }),
145
+ name: text('name').notNull(),
146
+ email: text('email').notNull(),
147
+ age: integer('age'),
148
+ });
149
+
150
+ // Infer types directly from your table definitions
151
+ type User = SelectModel<typeof users>;
152
+ // { id: number; name: string; email: string; age: number | null }
153
+
154
+ type NewUser = InsertModel<typeof users>;
155
+ // { id?: number; name: string; email: string; age?: number | null }
156
+
157
+ // The database is fully typed
158
+ const db = await createDatabase({ tables: { users } });
159
+
160
+ // All operations are type-safe
161
+ const allUsers: User[] = await db.select().from(users);
162
+
163
+ // Seed data is type-checked at compile time
164
+ const db2 = await createDatabase({
165
+ tables: { users },
166
+ seedData: {
167
+ users: [
168
+ { name: 'Alice', email: 'alice@example.com' }, // ✓ Valid
169
+ // { name: 123 }, // ✗ TypeScript error!
170
+ ],
171
+ },
172
+ });
114
173
  ```
115
174
 
175
+ ### Available Type Utilities
176
+
177
+ | Type | Description |
178
+ |------|-------------|
179
+ | `SelectModel<T>` | Infer the row type (SELECT result) from a table |
180
+ | `InsertModel<T>` | Infer the insert type from a table (optional auto-generated columns) |
181
+ | `SchemaModels<S>` | Extract all row types from a schema object |
182
+ | `SchemaInsertModels<S>` | Extract all insert types from a schema |
183
+ | `NanoDatabase<S>` | The typed database instance |
184
+ | `Schema` | Type for schema objects |
185
+ | `AnyTable` | Type constraint for Drizzle tables |
186
+
116
187
  ## API Reference
117
188
 
118
189
  ### `createDatabase(config)`
@@ -122,7 +193,7 @@ Create and initialize database. Returns `db` with all utilities attached.
122
193
  ```typescript
123
194
  const db = await createDatabase({
124
195
  tables: { users, posts },
125
- seedData: { users: [...] },
196
+ seedData: { users: [...] }, // Type-checked against schema
126
197
  migrationConfig: {
127
198
  preserveData: true, // default: true
128
199
  autoMigrate: true, // default: true
@@ -149,7 +220,7 @@ await db.clearData(); // Delete all data (keep tables)
149
220
  ### Schema Introspection (from `db.schema`)
150
221
 
151
222
  ```typescript
152
- db.schema.tables(); // ['users', 'posts']
223
+ db.schema.tables(); // ['users', 'posts'] - typed as (keyof Schema)[]
153
224
  db.schema.getTable('users'); // { columns, primaryKey, indexes }
154
225
  db.schema.getColumns('users'); // ['id', 'name', 'email']
155
226
  await db.schema.validate(); // { isValid, missingTables, ... }
@@ -165,24 +236,31 @@ await db.migrations.validate(); // Validate schema vs DB
165
236
  await db.migrations.checkTables(); // { users: true, posts: true }
166
237
  ```
167
238
 
168
- ### `transaction(fn)`
239
+ ### `transaction(fn)` / `batch(statements)`
169
240
 
170
- Execute operations atomically.
241
+ Execute operations atomically. Uses Drizzle's native transaction when available (better for Turso).
171
242
 
172
243
  ```typescript
173
- import { transaction, sql } from 'nanodb-orm';
244
+ import nanodb from 'nanodb-orm';
174
245
 
175
- const result = await transaction(async (tx) => {
176
- await tx.run(sql`INSERT INTO users (name, email) VALUES ('Alice', 'alice@example.com')`);
177
- await tx.run(sql`INSERT INTO posts (title, userId) VALUES ('Hello', 1)`);
246
+ // Transaction with custom logic
247
+ const result = await nanodb.transaction(async (tx) => {
248
+ await tx.run(nanodb.query.sql`INSERT INTO users (name) VALUES ('Alice')`);
249
+ await tx.run(nanodb.query.sql`INSERT INTO posts (title, userId) VALUES ('Hello', 1)`);
178
250
  return { created: true };
179
251
  });
180
252
 
181
253
  if (result.success) {
182
- console.log(result.result);
254
+ console.log(result.result); // { created: true }
183
255
  } else {
184
256
  console.log('Rolled back:', result.error?.message);
185
257
  }
258
+
259
+ // Batch multiple statements (simpler for bulk operations)
260
+ const batchResult = await nanodb.batch([
261
+ nanodb.query.sql`INSERT INTO users (name) VALUES ('Bob')`,
262
+ nanodb.query.sql`INSERT INTO users (name) VALUES ('Carol')`,
263
+ ]);
186
264
  ```
187
265
 
188
266
  ### `parseDbError(error, context)`
@@ -193,10 +271,10 @@ Parse SQLite errors into user-friendly messages.
193
271
  import { parseDbError } from 'nanodb-orm';
194
272
 
195
273
  try {
196
- await db.run('INSERT INTO users ...');
274
+ await db.insert(users).values({ email: 'duplicate@example.com' });
197
275
  } catch (error) {
198
276
  const parsed = parseDbError(error, { table: 'users', operation: 'insert' });
199
- console.log(parsed.message); // "Column 'email' does not exist"
277
+ console.log(parsed.message); // "Duplicate value for unique column 'email'"
200
278
  }
201
279
  ```
202
280
 
@@ -282,6 +360,192 @@ await db.insert(users).values({ email: 'invalid' }); // throws error
282
360
  db.plugins.list(); // ['audit', 'slug', 'validation']
283
361
  ```
284
362
 
363
+ ## Best Practices
364
+
365
+ ### Recommended Project Structure
366
+
367
+ ```
368
+ db/
369
+ ├── schema.ts # Table definitions
370
+ ├── index.ts # Database instance export
371
+ ├── types.ts # Type aliases (SelectModel, InsertModel)
372
+ ├── plugins.ts # Custom plugins
373
+ └── seeds.ts # Seed data
374
+ ```
375
+
376
+ ### 1. Schema Order Matters
377
+
378
+ Define parent tables before children for correct seeding order:
379
+
380
+ ```typescript
381
+ // db/schema.ts
382
+ import nanodb from 'nanodb-orm';
383
+
384
+ // Parent tables first (no foreign keys)
385
+ export const users = nanodb.schema.table('users', {
386
+ id: nanodb.schema.integer('id').primaryKey({ autoIncrement: true }),
387
+ name: nanodb.schema.text('name').notNull(),
388
+ email: nanodb.schema.text('email').notNull().unique(),
389
+ });
390
+
391
+ export const categories = nanodb.schema.table('categories', {
392
+ id: nanodb.schema.integer('id').primaryKey({ autoIncrement: true }),
393
+ name: nanodb.schema.text('name').notNull(),
394
+ });
395
+
396
+ // Child tables after (have foreign keys)
397
+ export const posts = nanodb.schema.table('posts', {
398
+ id: nanodb.schema.integer('id').primaryKey({ autoIncrement: true }),
399
+ title: nanodb.schema.text('title').notNull(),
400
+ userId: nanodb.schema.integer('userId').notNull(), // FK to users
401
+ categoryId: nanodb.schema.integer('categoryId'), // FK to categories
402
+ });
403
+
404
+ // Order: parents → children
405
+ export const schema = { users, categories, posts };
406
+ ```
407
+
408
+ ### 2. Single Database Instance
409
+
410
+ ```typescript
411
+ // db/index.ts
412
+ import nanodb from 'nanodb-orm';
413
+ import { schema } from './schema';
414
+ import { seedData } from './seeds';
415
+
416
+ export const db = await nanodb.createDatabase({ tables: schema, seedData });
417
+ ```
418
+
419
+ ```typescript
420
+ // anywhere.ts
421
+ import { db } from './db';
422
+ import { users } from './db/schema';
423
+
424
+ const allUsers = await db.select().from(users);
425
+ ```
426
+
427
+ ### 3. Use Type Inference
428
+
429
+ ```typescript
430
+ // db/types.ts
431
+ import { type SelectModel, type InsertModel } from 'nanodb-orm';
432
+ import { users, posts } from './schema';
433
+
434
+ export type User = SelectModel<typeof users>;
435
+ export type NewUser = InsertModel<typeof users>;
436
+ export type Post = SelectModel<typeof posts>;
437
+
438
+ // Usage
439
+ async function createUser(data: NewUser): Promise<void> {
440
+ await db.insert(users).values(data); // TypeScript enforces shape
441
+ }
442
+ ```
443
+
444
+ ### 4. Prefer Grouped Imports
445
+
446
+ ```typescript
447
+ // ✅ Clean - default import
448
+ import nanodb from 'nanodb-orm';
449
+
450
+ const users = nanodb.schema.table('users', { ... });
451
+ await db.select().from(users).where(nanodb.query.eq(users.id, 1));
452
+
453
+ // ✅ Also good - grouped imports
454
+ import { schema, query, errors } from 'nanodb-orm';
455
+
456
+ // ❌ Avoid - many individual imports
457
+ import { table, integer, text, eq, gte, and, sql, count, ... } from 'nanodb-orm';
458
+ ```
459
+
460
+ ### 5. Handle Errors Gracefully
461
+
462
+ ```typescript
463
+ import { parseDbError, DatabaseError } from 'nanodb-orm';
464
+
465
+ try {
466
+ await db.insert(users).values({ email: 'duplicate@test.com' });
467
+ } catch (error) {
468
+ if (error instanceof DatabaseError) {
469
+ // Already formatted with context
470
+ console.log(error.message); // "UNIQUE constraint failed: users.email"
471
+ console.log(error.table); // "users"
472
+ } else {
473
+ const parsed = parseDbError(error, { table: 'users' });
474
+ console.log(parsed.format());
475
+ }
476
+ }
477
+ ```
478
+
479
+ ### 6. Use Transactions for Atomic Operations
480
+
481
+ ```typescript
482
+ import nanodb from 'nanodb-orm';
483
+
484
+ const result = await nanodb.transaction(async (tx) => {
485
+ await tx.run(nanodb.query.sql`INSERT INTO users (name) VALUES ('Alice')`);
486
+ await tx.run(nanodb.query.sql`INSERT INTO posts (title, userId) VALUES ('Hello', 1)`);
487
+ return { inserted: 2 };
488
+ });
489
+
490
+ if (!result.success) {
491
+ console.log('Rolled back:', result.error?.message);
492
+ }
493
+ ```
494
+
495
+ ### 7. Validate on Startup (Production)
496
+
497
+ ```typescript
498
+ import nanodb from 'nanodb-orm';
499
+
500
+ const db = await nanodb.createDatabase({ tables: schema });
501
+
502
+ if (process.env.NODE_ENV === 'production') {
503
+ const validation = await db.schema.validate();
504
+ if (!validation.isValid) {
505
+ throw new Error(`Schema mismatch: ${validation.missingTables.join(', ')}`);
506
+ }
507
+
508
+ const health = await db.healthCheck();
509
+ if (!health.healthy) {
510
+ console.warn('Database issues:', health.errors);
511
+ }
512
+ }
513
+ ```
514
+
515
+ ### 8. Keep Plugins Simple
516
+
517
+ ```typescript
518
+ // Good: focused, single responsibility
519
+ const timestampPlugin: NanoPlugin = {
520
+ name: 'timestamps',
521
+ beforeInsert: (_table, data) => ({
522
+ ...data,
523
+ createdAt: new Date().toISOString(),
524
+ }),
525
+ beforeUpdate: (_table, data) => ({
526
+ ...data,
527
+ updatedAt: new Date().toISOString(),
528
+ }),
529
+ };
530
+
531
+ // Avoid: complex business logic in hooks
532
+ ```
533
+
534
+ ### 9. Environment Configuration
535
+
536
+ ```bash
537
+ # .env
538
+ TURSO_CONNECTION_URL=libsql://your-db.turso.io
539
+ TURSO_AUTH_TOKEN=your-token
540
+ FORCE_LOCAL_DB=true # Use local SQLite
541
+ DATABASE_PATH=./data/app.db # Custom DB path
542
+ ```
543
+
544
+ nanodb-orm auto-detects the right database:
545
+ - **Turso**: when `TURSO_*` vars are set
546
+ - **Local**: when `FORCE_LOCAL_DB=true` or no Turso config
547
+ - **Test**: isolated `test.db` when `NODE_ENV=test`
548
+
285
549
  ## Configuration
286
550
 
287
551
  ### Environment Variables
@@ -291,14 +555,18 @@ db.plugins.list(); // ['audit', 'slug', 'validation']
291
555
  TURSO_CONNECTION_URL=libsql://your-db.turso.io
292
556
  TURSO_AUTH_TOKEN=your-token
293
557
 
294
- # Force local SQLite (for testing)
558
+ # Force local SQLite
295
559
  FORCE_LOCAL_DB=true
560
+
561
+ # Custom database path (works with FORCE_LOCAL_DB or as fallback)
562
+ DATABASE_PATH=./data/myapp.db
296
563
  ```
297
564
 
298
565
  ### Database Selection
299
566
 
300
567
  - **Turso** — Used when `TURSO_CONNECTION_URL` and `TURSO_AUTH_TOKEN` are set
301
- - **Local SQLite** — Fallback when Turso credentials are missing
568
+ - **Local SQLite** — Used when `FORCE_LOCAL_DB=true` or Turso credentials missing
569
+ - **Custom Path** — Set `DATABASE_PATH=./path/to/db.sqlite` for custom location
302
570
  - **Test Mode** — Isolated `test.db` when `NODE_ENV=test`
303
571
 
304
572
  ## Error Handling
@@ -331,6 +599,78 @@ Error output is clean and actionable:
331
599
  └────────────────────────────────────────────────
332
600
  ```
333
601
 
602
+ ## Exports
603
+
604
+ ```typescript
605
+ // Default export (recommended)
606
+ import nanodb from 'nanodb-orm';
607
+
608
+ nanodb.createDatabase // Main entry point
609
+ nanodb.transaction // Atomic operations
610
+ nanodb.schema // .table, .integer, .text, .real, .blob
611
+ nanodb.query // .eq, .gte, .and, .or, .sql, .count, ...
612
+ nanodb.errors // .DatabaseError, .parse
613
+ nanodb.cli // .studio, .setup, .reset, .status, .validate
614
+
615
+ // Types (named imports)
616
+ import { type SelectModel, type InsertModel, type NanoPlugin } from 'nanodb-orm';
617
+ ```
618
+
619
+ ## nanodb-orm vs Drizzle + Turso (Direct)
620
+
621
+ | Feature | nanodb-orm | Drizzle + Turso |
622
+ |---------|------------|-----------------|
623
+ | **Setup** | One-liner: `createDatabase({ tables })` | Manual: create client, drizzle, manage connection |
624
+ | **Migrations** | Automatic on startup | Manual: `drizzle-kit push/migrate` |
625
+ | **Seeding** | Built-in with `seedData` | Write seed scripts |
626
+ | **Type Safety** | ✅ Full (same as Drizzle) | ✅ Full |
627
+ | **Query API** | ✅ Same as Drizzle | ✅ Native Drizzle |
628
+ | **Plugins/Hooks** | ✅ beforeInsert, afterQuery, etc. | ❌ None |
629
+ | **Schema Introspection** | ✅ `db.schema.tables()` | ❌ Manual |
630
+ | **Health Checks** | ✅ `db.healthCheck()` | ❌ Manual |
631
+ | **CLI** | `npx nanodb studio/status/validate` | `npx drizzle-kit studio` only |
632
+ | **Error Parsing** | User-friendly messages | Raw SQLite errors |
633
+ | **Connection** | Auto-detects Turso vs local | Manual configuration |
634
+
635
+ ### When to Use What
636
+
637
+ | Use Case | Recommendation |
638
+ |----------|----------------|
639
+ | Quick prototyping | **nanodb-orm** |
640
+ | Need plugins/hooks | **nanodb-orm** |
641
+ | Want auto-migrations | **nanodb-orm** |
642
+ | New SQLite/Turso project | **nanodb-orm** |
643
+ | Maximum control | Drizzle directly |
644
+ | Complex migration strategies | Drizzle + drizzle-kit |
645
+ | Existing Drizzle project | Keep Drizzle |
646
+
647
+ ### Comparison
648
+
649
+ ```typescript
650
+ // nanodb-orm: 5 lines
651
+ import nanodb from 'nanodb-orm';
652
+
653
+ const users = nanodb.schema.table('users', { id: nanodb.schema.integer('id').primaryKey() });
654
+ const db = await nanodb.createDatabase({ tables: { users }, seedData: { users: [{ id: 1 }] } });
655
+ // Ready - tables created, seeded
656
+ ```
657
+
658
+ ```typescript
659
+ // Drizzle + Turso: More setup
660
+ import { drizzle } from 'drizzle-orm/libsql';
661
+ import { createClient } from '@libsql/client';
662
+ import { sqliteTable, integer } from 'drizzle-orm/sqlite-core';
663
+ import { migrate } from 'drizzle-orm/libsql/migrator';
664
+
665
+ const users = sqliteTable('users', { id: integer('id').primaryKey() });
666
+ const client = createClient({ url: process.env.TURSO_CONNECTION_URL!, authToken: process.env.TURSO_AUTH_TOKEN! });
667
+ const db = drizzle(client);
668
+ await migrate(db, { migrationsFolder: './drizzle' });
669
+ await db.insert(users).values([{ id: 1 }]);
670
+ ```
671
+
672
+ **nanodb-orm is a convenience layer** — it uses Drizzle under the hood and passes through all queries unchanged. You get Drizzle's full type safety plus automatic setup, plugins, and utilities.
673
+
334
674
  ## License
335
675
 
336
676
  MIT © Damilola Alao
package/dist/cli.d.ts CHANGED
@@ -9,5 +9,88 @@
9
9
  * status - Show database health and stats
10
10
  * validate - Validate schema against database
11
11
  */
12
- export {};
12
+ import { type ChildProcess } from 'child_process';
13
+ export interface StudioOptions {
14
+ /** Database file path (default: auto-detected or 'database.db') */
15
+ dbPath?: string | undefined;
16
+ /** Port for Drizzle Studio (default: 4983) */
17
+ port?: number | undefined;
18
+ /** Suppress console output */
19
+ silent?: boolean | undefined;
20
+ }
21
+ export interface StatusResult {
22
+ healthy: boolean;
23
+ schemaValid: boolean;
24
+ totalTables: number;
25
+ totalRecords: number;
26
+ tables: Record<string, number>;
27
+ errors: string[];
28
+ }
29
+ export interface ValidationResult {
30
+ isValid: boolean;
31
+ missingTables: string[];
32
+ extraTables: string[];
33
+ errors: string[];
34
+ }
35
+ /**
36
+ * Launch Drizzle Studio for visual database browsing.
37
+ *
38
+ * @example
39
+ * ```ts
40
+ * import { launchStudio } from 'nanodb-orm';
41
+ *
42
+ * // Launch with defaults
43
+ * await launchStudio();
44
+ *
45
+ * // Launch with options
46
+ * await launchStudio({ dbPath: './data/app.db', port: 3000 });
47
+ * ```
48
+ */
49
+ export declare function launchStudio(options?: StudioOptions): Promise<ChildProcess>;
50
+ /**
51
+ * Run database setup (initialize schema and seed data).
52
+ *
53
+ * @example
54
+ * ```ts
55
+ * import { runSetup } from 'nanodb-orm';
56
+ * await runSetup();
57
+ * ```
58
+ */
59
+ export declare function runSetup(silent?: boolean): Promise<void>;
60
+ /**
61
+ * Reset database (drop all tables and recreate with seed data).
62
+ *
63
+ * @example
64
+ * ```ts
65
+ * import { runReset } from 'nanodb-orm';
66
+ * await runReset();
67
+ * ```
68
+ */
69
+ export declare function runReset(silent?: boolean): Promise<void>;
70
+ /**
71
+ * Get database status and health information.
72
+ *
73
+ * @example
74
+ * ```ts
75
+ * import { getStatus } from 'nanodb-orm';
76
+ *
77
+ * const status = await getStatus();
78
+ * console.log(status.healthy, status.totalRecords);
79
+ * ```
80
+ */
81
+ export declare function getStatus(silent?: boolean): Promise<StatusResult>;
82
+ /**
83
+ * Validate schema against database.
84
+ *
85
+ * @example
86
+ * ```ts
87
+ * import { runValidate } from 'nanodb-orm';
88
+ *
89
+ * const result = await runValidate();
90
+ * if (!result.isValid) {
91
+ * console.log('Missing tables:', result.missingTables);
92
+ * }
93
+ * ```
94
+ */
95
+ export declare function runValidate(silent?: boolean): Promise<ValidationResult>;
13
96
  //# sourceMappingURL=cli.d.ts.map
package/dist/cli.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../cli.ts"],"names":[],"mappings":";AACA;;;;;;;;;GASG"}
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../cli.ts"],"names":[],"mappings":";AACA;;;;;;;;;GASG;AAEH,OAAO,EAAS,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AAQzD,MAAM,WAAW,aAAa;IAC5B,mEAAmE;IACnE,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,8CAA8C;IAC9C,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,8BAA8B;IAC9B,MAAM,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CAC9B;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,OAAO,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAMD;;;;;;;;;;;;;GAaG;AACH,wBAAsB,YAAY,CAAC,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,YAAY,CAAC,CA8CrF;AAED;;;;;;;;GAQG;AACH,wBAAsB,QAAQ,CAAC,MAAM,UAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAO5D;AAED;;;;;;;;GAQG;AACH,wBAAsB,QAAQ,CAAC,MAAM,UAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAO5D;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,SAAS,CAAC,MAAM,UAAQ,GAAG,OAAO,CAAC,YAAY,CAAC,CAsCrE;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,WAAW,CAAC,MAAM,UAAQ,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAsC3E"}