@3lineas/d1-orm 1.0.5 → 1.0.7

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 CHANGED
@@ -208,6 +208,31 @@ pnpm orm migrate
208
208
 
209
209
  # Remote (Production)
210
210
  pnpm orm migrate --remote
211
+
212
+ # Run migrations and then seed
213
+ pnpm orm migrate --seed
214
+ ```
215
+
216
+ #### Reset Database
217
+
218
+ Drop all tables and re-run all migrations.
219
+
220
+ ```bash
221
+ pnpm orm migrate:fresh
222
+
223
+ # Reset and seed
224
+ pnpm orm migrate:fresh --seed
225
+ ```
226
+
227
+ #### Seed Database
228
+
229
+ Run seeders defined in `database/seeders`.
230
+
231
+ ```bash
232
+ pnpm orm db:seed
233
+
234
+ # Remote
235
+ pnpm orm db:seed --remote
211
236
  ```
212
237
 
213
238
  > **Note:** Local migrations require `wrangler` to be configured and running in your environment.
@@ -0,0 +1,147 @@
1
+ var __getOwnPropNames = Object.getOwnPropertyNames;
2
+ var __esm = (fn, res) => function __init() {
3
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
4
+ };
5
+ var __commonJS = (cb, mod) => function __require() {
6
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
7
+ };
8
+
9
+ // src/core/connection.ts
10
+ var Connection;
11
+ var init_connection = __esm({
12
+ "src/core/connection.ts"() {
13
+ "use strict";
14
+ Connection = class {
15
+ /**
16
+ * The underlying D1Database instance.
17
+ */
18
+ db;
19
+ /**
20
+ * Create a new Connection instance.
21
+ *
22
+ * @param database - The D1Database instance.
23
+ */
24
+ constructor(database) {
25
+ this.db = database;
26
+ }
27
+ /**
28
+ * Execute a SELECT statement.
29
+ *
30
+ * @param query - The SQL query string.
31
+ * @param bindings - The parameter bindings.
32
+ * @returns A promise that resolves to an array of results.
33
+ */
34
+ async select(query, bindings = []) {
35
+ const stmt = this.db.prepare(query).bind(...bindings);
36
+ const result = await stmt.all();
37
+ return result.results || [];
38
+ }
39
+ /**
40
+ * Execute an INSERT statement.
41
+ *
42
+ * @param query - The SQL query string.
43
+ * @param bindings - The parameter bindings.
44
+ * @returns A promise that resolves to true on success.
45
+ */
46
+ async insert(query, bindings = []) {
47
+ const stmt = this.db.prepare(query).bind(...bindings);
48
+ const result = await stmt.run();
49
+ return result.success;
50
+ }
51
+ /**
52
+ * Execute an UPDATE statement.
53
+ *
54
+ * @param query - The SQL query string.
55
+ * @param bindings - The parameter bindings.
56
+ * @returns A promise that resolves to true on success.
57
+ */
58
+ async update(query, bindings = []) {
59
+ const stmt = this.db.prepare(query).bind(...bindings);
60
+ const result = await stmt.run();
61
+ return result.success;
62
+ }
63
+ /**
64
+ * Execute a DELETE statement.
65
+ *
66
+ * @param query - The SQL query string.
67
+ * @param bindings - The parameter bindings.
68
+ * @returns A promise that resolves to true on success.
69
+ */
70
+ async delete(query, bindings = []) {
71
+ const stmt = this.db.prepare(query).bind(...bindings);
72
+ const result = await stmt.run();
73
+ return result.success;
74
+ }
75
+ /**
76
+ * Execute an arbitrary SQL statement.
77
+ *
78
+ * @param query - The SQL query string.
79
+ * @param bindings - The parameter bindings.
80
+ * @returns A promise that resolves to true on success.
81
+ */
82
+ async statement(query, bindings = []) {
83
+ const stmt = this.db.prepare(query).bind(...bindings);
84
+ const result = await stmt.run();
85
+ return result.success;
86
+ }
87
+ };
88
+ }
89
+ });
90
+
91
+ // src/core/database.ts
92
+ var Database;
93
+ var init_database = __esm({
94
+ "src/core/database.ts"() {
95
+ "use strict";
96
+ init_connection();
97
+ Database = class _Database {
98
+ /**
99
+ * The singleton instance of the Database.
100
+ */
101
+ static instance;
102
+ /**
103
+ * The active database connection.
104
+ */
105
+ connection;
106
+ /**
107
+ * Private constructor to enforce singleton pattern.
108
+ *
109
+ * @param d1 - The D1Database instance from Cloudflare.
110
+ */
111
+ constructor(d1) {
112
+ this.connection = new Connection(d1);
113
+ }
114
+ /**
115
+ * Setup the database connection.
116
+ *
117
+ * @param d1 - The D1Database instance from Cloudflare environment (env.DB).
118
+ */
119
+ static setup(d1) {
120
+ _Database.instance = new _Database(d1);
121
+ }
122
+ /**
123
+ * Get the singleton Database instance.
124
+ *
125
+ * @throws Error if setup() has not been called.
126
+ * @returns The Database instance.
127
+ */
128
+ static getInstance() {
129
+ if (!_Database.instance) {
130
+ throw new Error(
131
+ "Database not initialized. Call Database.setup(env.DB) first."
132
+ );
133
+ }
134
+ return _Database.instance;
135
+ }
136
+ };
137
+ }
138
+ });
139
+
140
+ export {
141
+ __esm,
142
+ __commonJS,
143
+ Connection,
144
+ init_connection,
145
+ Database,
146
+ init_database
147
+ };
package/dist/cli/index.js CHANGED
@@ -101,7 +101,7 @@ export const down = async () => {
101
101
  const seederContent = `import { User } from '${path.relative(
102
102
  path.join(process.cwd(), "database/seeders"),
103
103
  path.join(process.cwd(), userModelsPath, "User")
104
- ).replace(/\\/g, "/")}';
104
+ ).replace(/\\/g, "/")}.ts';
105
105
 
106
106
  export const seed = async () => {
107
107
  await User.create({
@@ -268,7 +268,7 @@ async function makeSeeder(modelName, modelPath) {
268
268
  fs3.mkdirSync(seederDir, { recursive: true });
269
269
  }
270
270
  const relativeModelPath = path3.relative(seederDir, path3.join(process.cwd(), modelPath, modelName)).replace(/\\/g, "/");
271
- const template = `import { ${modelName} } from '${relativeModelPath}';
271
+ const template = `import { ${modelName} } from '${relativeModelPath}.ts';
272
272
 
273
273
  export const seed = async () => {
274
274
  // await ${modelName}.create({ ... });
@@ -283,20 +283,281 @@ export const seed = async () => {
283
283
  }
284
284
 
285
285
  // src/cli/commands/migrate.ts
286
+ var fs5 = __toESM(require("fs"));
287
+ var path5 = __toESM(require("path"));
288
+ var import_child_process2 = require("child_process");
289
+
290
+ // src/cli/commands/seed.ts
286
291
  var fs4 = __toESM(require("fs"));
287
292
  var path4 = __toESM(require("path"));
293
+
294
+ // src/core/connection.ts
295
+ var Connection = class {
296
+ /**
297
+ * The underlying D1Database instance.
298
+ */
299
+ db;
300
+ /**
301
+ * Create a new Connection instance.
302
+ *
303
+ * @param database - The D1Database instance.
304
+ */
305
+ constructor(database) {
306
+ this.db = database;
307
+ }
308
+ /**
309
+ * Execute a SELECT statement.
310
+ *
311
+ * @param query - The SQL query string.
312
+ * @param bindings - The parameter bindings.
313
+ * @returns A promise that resolves to an array of results.
314
+ */
315
+ async select(query, bindings = []) {
316
+ const stmt = this.db.prepare(query).bind(...bindings);
317
+ const result = await stmt.all();
318
+ return result.results || [];
319
+ }
320
+ /**
321
+ * Execute an INSERT statement.
322
+ *
323
+ * @param query - The SQL query string.
324
+ * @param bindings - The parameter bindings.
325
+ * @returns A promise that resolves to true on success.
326
+ */
327
+ async insert(query, bindings = []) {
328
+ const stmt = this.db.prepare(query).bind(...bindings);
329
+ const result = await stmt.run();
330
+ return result.success;
331
+ }
332
+ /**
333
+ * Execute an UPDATE statement.
334
+ *
335
+ * @param query - The SQL query string.
336
+ * @param bindings - The parameter bindings.
337
+ * @returns A promise that resolves to true on success.
338
+ */
339
+ async update(query, bindings = []) {
340
+ const stmt = this.db.prepare(query).bind(...bindings);
341
+ const result = await stmt.run();
342
+ return result.success;
343
+ }
344
+ /**
345
+ * Execute a DELETE statement.
346
+ *
347
+ * @param query - The SQL query string.
348
+ * @param bindings - The parameter bindings.
349
+ * @returns A promise that resolves to true on success.
350
+ */
351
+ async delete(query, bindings = []) {
352
+ const stmt = this.db.prepare(query).bind(...bindings);
353
+ const result = await stmt.run();
354
+ return result.success;
355
+ }
356
+ /**
357
+ * Execute an arbitrary SQL statement.
358
+ *
359
+ * @param query - The SQL query string.
360
+ * @param bindings - The parameter bindings.
361
+ * @returns A promise that resolves to true on success.
362
+ */
363
+ async statement(query, bindings = []) {
364
+ const stmt = this.db.prepare(query).bind(...bindings);
365
+ const result = await stmt.run();
366
+ return result.success;
367
+ }
368
+ };
369
+
370
+ // src/core/database.ts
371
+ var Database = class _Database {
372
+ /**
373
+ * The singleton instance of the Database.
374
+ */
375
+ static instance;
376
+ /**
377
+ * The active database connection.
378
+ */
379
+ connection;
380
+ /**
381
+ * Private constructor to enforce singleton pattern.
382
+ *
383
+ * @param d1 - The D1Database instance from Cloudflare.
384
+ */
385
+ constructor(d1) {
386
+ this.connection = new Connection(d1);
387
+ }
388
+ /**
389
+ * Setup the database connection.
390
+ *
391
+ * @param d1 - The D1Database instance from Cloudflare environment (env.DB).
392
+ */
393
+ static setup(d1) {
394
+ _Database.instance = new _Database(d1);
395
+ }
396
+ /**
397
+ * Get the singleton Database instance.
398
+ *
399
+ * @throws Error if setup() has not been called.
400
+ * @returns The Database instance.
401
+ */
402
+ static getInstance() {
403
+ if (!_Database.instance) {
404
+ throw new Error(
405
+ "Database not initialized. Call Database.setup(env.DB) first."
406
+ );
407
+ }
408
+ return _Database.instance;
409
+ }
410
+ };
411
+
412
+ // src/cli/cli-connection.ts
288
413
  var import_child_process = require("child_process");
414
+ var CLIConnection = class {
415
+ constructor(dbName = "DB", isRemote = false) {
416
+ this.dbName = dbName;
417
+ this.isRemote = isRemote;
418
+ }
419
+ prepare(query) {
420
+ return new CLIPREparedStatement(query, this.dbName, this.isRemote);
421
+ }
422
+ async dump() {
423
+ throw new Error("dump() is not supported in CLI mode.");
424
+ }
425
+ async batch(statements) {
426
+ const results = [];
427
+ for (const stmt of statements) {
428
+ results.push(await stmt.run());
429
+ }
430
+ return results;
431
+ }
432
+ async exec(query) {
433
+ const start = Date.now();
434
+ await this.executeWrangler(query);
435
+ return {
436
+ count: 1,
437
+ // Approximation
438
+ duration: Date.now() - start
439
+ };
440
+ }
441
+ executeWrangler(sql) {
442
+ const flag = this.isRemote ? "--remote" : "--local";
443
+ const command2 = `npx wrangler d1 execute ${this.dbName} --command "${sql.replace(/"/g, '\\"')}" ${flag} --json`;
444
+ try {
445
+ const output = (0, import_child_process.execSync)(command2, {
446
+ encoding: "utf-8",
447
+ stdio: ["ignore", "pipe", "inherit"]
448
+ });
449
+ const jsonStart = output.indexOf("[");
450
+ if (jsonStart !== -1) {
451
+ return JSON.parse(output.substring(jsonStart));
452
+ }
453
+ return null;
454
+ } catch (e) {
455
+ console.error(`Error executing wrangler command: ${command2}`);
456
+ throw e;
457
+ }
458
+ }
459
+ };
460
+ var CLIPREparedStatement = class {
461
+ constructor(query, dbName, isRemote) {
462
+ this.query = query;
463
+ this.dbName = dbName;
464
+ this.isRemote = isRemote;
465
+ }
466
+ bindings = [];
467
+ bind(...values) {
468
+ this.bindings = values;
469
+ return this;
470
+ }
471
+ resolveQuery() {
472
+ let sql = this.query;
473
+ this.bindings.forEach((value) => {
474
+ const formattedValue = typeof value === "string" ? `'${value.replace(/'/g, "''")}'` : value;
475
+ sql = sql.replace("?", String(formattedValue));
476
+ });
477
+ return sql;
478
+ }
479
+ async first(colName) {
480
+ const result = await this.all();
481
+ const firstRow = result.results[0] || null;
482
+ if (firstRow && colName) {
483
+ return firstRow[colName];
484
+ }
485
+ return firstRow;
486
+ }
487
+ async run() {
488
+ return this.all();
489
+ }
490
+ async all() {
491
+ const sql = this.resolveQuery();
492
+ const flag = this.isRemote ? "--remote" : "--local";
493
+ const command2 = `npx wrangler d1 execute ${this.dbName} --command "${sql.replace(/"/g, '\\"')}" ${flag} --json`;
494
+ try {
495
+ const output = (0, import_child_process.execSync)(command2, {
496
+ encoding: "utf-8",
497
+ stdio: ["ignore", "pipe", "pipe"]
498
+ });
499
+ const jsonStart = output.indexOf("[");
500
+ if (jsonStart !== -1) {
501
+ const results = JSON.parse(output.substring(jsonStart));
502
+ const primaryResult = results[0];
503
+ return {
504
+ results: primaryResult.results || [],
505
+ success: primaryResult.success ?? true,
506
+ meta: primaryResult.meta || {}
507
+ };
508
+ }
509
+ return { results: [], success: true, meta: {} };
510
+ } catch (e) {
511
+ return { results: [], success: false, meta: {}, error: e.message };
512
+ }
513
+ }
514
+ async raw() {
515
+ const result = await this.all();
516
+ return result.results;
517
+ }
518
+ };
519
+
520
+ // src/cli/commands/seed.ts
521
+ async function seed(args2) {
522
+ console.log("Seeding database...");
523
+ const seedersDir = path4.join(process.cwd(), "database/seeders");
524
+ if (!fs4.existsSync(seedersDir)) {
525
+ console.log("No seeders directory found.");
526
+ return;
527
+ }
528
+ const isRemote = args2.includes("--remote");
529
+ const dbName = "DB";
530
+ Database.setup(new CLIConnection(dbName, isRemote));
531
+ const files = fs4.readdirSync(seedersDir).filter((f) => f.endsWith(".ts") || f.endsWith(".js")).sort();
532
+ for (const file of files) {
533
+ console.log(`Running seeder: ${file}`);
534
+ const filePath = path4.join(seedersDir, file);
535
+ try {
536
+ const seeder = await import(filePath);
537
+ if (seeder.seed) {
538
+ await seeder.seed();
539
+ console.log(`Seeder ${file} completed successfully.`);
540
+ } else {
541
+ console.warn(`Seeder ${file} does not export a seed function.`);
542
+ }
543
+ } catch (error) {
544
+ console.error(`Error running seeder ${file}:`, error);
545
+ }
546
+ }
547
+ }
548
+
549
+ // src/cli/commands/migrate.ts
289
550
  async function migrate(args2) {
290
551
  console.log("Running migrations...");
291
- const migrationsDir = path4.join(process.cwd(), "database/migrations");
292
- if (!fs4.existsSync(migrationsDir)) {
552
+ const migrationsDir = path5.join(process.cwd(), "database/migrations");
553
+ if (!fs5.existsSync(migrationsDir)) {
293
554
  console.log("No migrations directory found.");
294
555
  return;
295
556
  }
296
- const files = fs4.readdirSync(migrationsDir).filter((f) => f.endsWith(".ts") || f.endsWith(".js")).sort();
557
+ const files = fs5.readdirSync(migrationsDir).filter((f) => f.endsWith(".ts") || f.endsWith(".js")).sort();
297
558
  for (const file of files) {
298
559
  console.log(`Processing migration: ${file}`);
299
- const filePath = path4.join(migrationsDir, file);
560
+ const filePath = path5.join(migrationsDir, file);
300
561
  try {
301
562
  const migration = await import(filePath);
302
563
  if (migration.up) {
@@ -308,7 +569,7 @@ async function migrate(args2) {
308
569
  try {
309
570
  const execCmd = `npx wrangler d1 execute ${dbName} --command "${sql.replace(/"/g, '\\"')}" ${command2}`;
310
571
  console.log(`Executing: ${execCmd}`);
311
- (0, import_child_process.execSync)(execCmd, { stdio: "inherit" });
572
+ (0, import_child_process2.execSync)(execCmd, { stdio: "inherit" });
312
573
  } catch (e) {
313
574
  console.error(`Failed to execute migration: ${file}`);
314
575
  throw e;
@@ -319,6 +580,41 @@ async function migrate(args2) {
319
580
  console.error(`Error processing migration ${file}:`, error);
320
581
  }
321
582
  }
583
+ if (args2.includes("--seed")) {
584
+ await seed(args2);
585
+ }
586
+ }
587
+
588
+ // src/cli/commands/migrate-fresh.ts
589
+ var import_child_process3 = require("child_process");
590
+ async function migrateFresh(args2) {
591
+ console.log("Dropping all tables...");
592
+ const isRemote = args2.includes("--remote");
593
+ const dbName = "DB";
594
+ const flag = isRemote ? "--remote" : "--local";
595
+ try {
596
+ const listTablesCmd = `npx wrangler d1 execute ${dbName} --command "SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' AND name NOT LIKE '_cf_%'" ${flag} --json`;
597
+ const output = (0, import_child_process3.execSync)(listTablesCmd, {
598
+ encoding: "utf-8",
599
+ stdio: ["ignore", "pipe", "inherit"]
600
+ });
601
+ const jsonStart = output.indexOf("[");
602
+ if (jsonStart !== -1) {
603
+ const results = JSON.parse(output.substring(jsonStart));
604
+ const tables = results[0]?.results || [];
605
+ if (tables.length > 0) {
606
+ const dropCommands = tables.map((t) => `DROP TABLE IF EXISTS ${t.name};`).join(" ");
607
+ const dropCmd = `npx wrangler d1 execute ${dbName} --command "${dropCommands}" ${flag}`;
608
+ console.log("Executing drop tables...");
609
+ (0, import_child_process3.execSync)(dropCmd, { stdio: "inherit" });
610
+ } else {
611
+ console.log("No tables found to drop.");
612
+ }
613
+ }
614
+ await migrate(args2);
615
+ } catch (error) {
616
+ console.error("Error during migrate:fresh:", error);
617
+ }
322
618
  }
323
619
 
324
620
  // src/cli/index.ts
@@ -336,13 +632,17 @@ switch (command) {
336
632
  makeMigration(param);
337
633
  break;
338
634
  case "migrate":
339
- const isLocal = args.includes("--local");
340
- const isRemote = args.includes("--remote");
341
635
  migrate(args);
342
636
  break;
637
+ case "migrate:fresh":
638
+ migrateFresh(args);
639
+ break;
640
+ case "db:seed":
641
+ seed(args);
642
+ break;
343
643
  default:
344
644
  console.log(
345
- "Available commands: init, make:model, make:migration, migrate"
645
+ "Available commands: init, make:model, make:migration, migrate, migrate:fresh, db:seed"
346
646
  );
347
647
  break;
348
648
  }
@@ -1,8 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
+ Database,
3
4
  __commonJS,
4
- __esm
5
- } from "../chunk-X6BYQHVC.mjs";
5
+ __esm,
6
+ init_database
7
+ } from "../chunk-5BBZKUNZ.mjs";
6
8
 
7
9
  // src/cli/commands/init.ts
8
10
  import * as fs from "fs";
@@ -82,7 +84,7 @@ export const down = async () => {
82
84
  const seederContent = `import { User } from '${path.relative(
83
85
  path.join(process.cwd(), "database/seeders"),
84
86
  path.join(process.cwd(), userModelsPath, "User")
85
- ).replace(/\\/g, "/")}';
87
+ ).replace(/\\/g, "/")}.ts';
86
88
 
87
89
  export const seed = async () => {
88
90
  await User.create({
@@ -257,7 +259,7 @@ async function makeSeeder(modelName, modelPath) {
257
259
  fs3.mkdirSync(seederDir, { recursive: true });
258
260
  }
259
261
  const relativeModelPath = path3.relative(seederDir, path3.join(process.cwd(), modelPath, modelName)).replace(/\\/g, "/");
260
- const template = `import { ${modelName} } from '${relativeModelPath}';
262
+ const template = `import { ${modelName} } from '${relativeModelPath}.ts';
261
263
 
262
264
  export const seed = async () => {
263
265
  // await ${modelName}.create({ ... });
@@ -277,21 +279,173 @@ var init_make_model = __esm({
277
279
  }
278
280
  });
279
281
 
280
- // src/cli/commands/migrate.ts
282
+ // src/cli/cli-connection.ts
283
+ import { execSync } from "child_process";
284
+ var CLIConnection, CLIPREparedStatement;
285
+ var init_cli_connection = __esm({
286
+ "src/cli/cli-connection.ts"() {
287
+ "use strict";
288
+ CLIConnection = class {
289
+ constructor(dbName = "DB", isRemote = false) {
290
+ this.dbName = dbName;
291
+ this.isRemote = isRemote;
292
+ }
293
+ prepare(query) {
294
+ return new CLIPREparedStatement(query, this.dbName, this.isRemote);
295
+ }
296
+ async dump() {
297
+ throw new Error("dump() is not supported in CLI mode.");
298
+ }
299
+ async batch(statements) {
300
+ const results = [];
301
+ for (const stmt of statements) {
302
+ results.push(await stmt.run());
303
+ }
304
+ return results;
305
+ }
306
+ async exec(query) {
307
+ const start = Date.now();
308
+ await this.executeWrangler(query);
309
+ return {
310
+ count: 1,
311
+ // Approximation
312
+ duration: Date.now() - start
313
+ };
314
+ }
315
+ executeWrangler(sql) {
316
+ const flag = this.isRemote ? "--remote" : "--local";
317
+ const command = `npx wrangler d1 execute ${this.dbName} --command "${sql.replace(/"/g, '\\"')}" ${flag} --json`;
318
+ try {
319
+ const output = execSync(command, {
320
+ encoding: "utf-8",
321
+ stdio: ["ignore", "pipe", "inherit"]
322
+ });
323
+ const jsonStart = output.indexOf("[");
324
+ if (jsonStart !== -1) {
325
+ return JSON.parse(output.substring(jsonStart));
326
+ }
327
+ return null;
328
+ } catch (e) {
329
+ console.error(`Error executing wrangler command: ${command}`);
330
+ throw e;
331
+ }
332
+ }
333
+ };
334
+ CLIPREparedStatement = class {
335
+ constructor(query, dbName, isRemote) {
336
+ this.query = query;
337
+ this.dbName = dbName;
338
+ this.isRemote = isRemote;
339
+ }
340
+ bindings = [];
341
+ bind(...values) {
342
+ this.bindings = values;
343
+ return this;
344
+ }
345
+ resolveQuery() {
346
+ let sql = this.query;
347
+ this.bindings.forEach((value) => {
348
+ const formattedValue = typeof value === "string" ? `'${value.replace(/'/g, "''")}'` : value;
349
+ sql = sql.replace("?", String(formattedValue));
350
+ });
351
+ return sql;
352
+ }
353
+ async first(colName) {
354
+ const result = await this.all();
355
+ const firstRow = result.results[0] || null;
356
+ if (firstRow && colName) {
357
+ return firstRow[colName];
358
+ }
359
+ return firstRow;
360
+ }
361
+ async run() {
362
+ return this.all();
363
+ }
364
+ async all() {
365
+ const sql = this.resolveQuery();
366
+ const flag = this.isRemote ? "--remote" : "--local";
367
+ const command = `npx wrangler d1 execute ${this.dbName} --command "${sql.replace(/"/g, '\\"')}" ${flag} --json`;
368
+ try {
369
+ const output = execSync(command, {
370
+ encoding: "utf-8",
371
+ stdio: ["ignore", "pipe", "pipe"]
372
+ });
373
+ const jsonStart = output.indexOf("[");
374
+ if (jsonStart !== -1) {
375
+ const results = JSON.parse(output.substring(jsonStart));
376
+ const primaryResult = results[0];
377
+ return {
378
+ results: primaryResult.results || [],
379
+ success: primaryResult.success ?? true,
380
+ meta: primaryResult.meta || {}
381
+ };
382
+ }
383
+ return { results: [], success: true, meta: {} };
384
+ } catch (e) {
385
+ return { results: [], success: false, meta: {}, error: e.message };
386
+ }
387
+ }
388
+ async raw() {
389
+ const result = await this.all();
390
+ return result.results;
391
+ }
392
+ };
393
+ }
394
+ });
395
+
396
+ // src/cli/commands/seed.ts
281
397
  import * as fs4 from "fs";
282
398
  import * as path4 from "path";
283
- import { execSync } from "child_process";
399
+ async function seed(args) {
400
+ console.log("Seeding database...");
401
+ const seedersDir = path4.join(process.cwd(), "database/seeders");
402
+ if (!fs4.existsSync(seedersDir)) {
403
+ console.log("No seeders directory found.");
404
+ return;
405
+ }
406
+ const isRemote = args.includes("--remote");
407
+ const dbName = "DB";
408
+ Database.setup(new CLIConnection(dbName, isRemote));
409
+ const files = fs4.readdirSync(seedersDir).filter((f) => f.endsWith(".ts") || f.endsWith(".js")).sort();
410
+ for (const file of files) {
411
+ console.log(`Running seeder: ${file}`);
412
+ const filePath = path4.join(seedersDir, file);
413
+ try {
414
+ const seeder = await import(filePath);
415
+ if (seeder.seed) {
416
+ await seeder.seed();
417
+ console.log(`Seeder ${file} completed successfully.`);
418
+ } else {
419
+ console.warn(`Seeder ${file} does not export a seed function.`);
420
+ }
421
+ } catch (error) {
422
+ console.error(`Error running seeder ${file}:`, error);
423
+ }
424
+ }
425
+ }
426
+ var init_seed = __esm({
427
+ "src/cli/commands/seed.ts"() {
428
+ "use strict";
429
+ init_database();
430
+ init_cli_connection();
431
+ }
432
+ });
433
+
434
+ // src/cli/commands/migrate.ts
435
+ import * as fs5 from "fs";
436
+ import * as path5 from "path";
437
+ import { execSync as execSync2 } from "child_process";
284
438
  async function migrate(args) {
285
439
  console.log("Running migrations...");
286
- const migrationsDir = path4.join(process.cwd(), "database/migrations");
287
- if (!fs4.existsSync(migrationsDir)) {
440
+ const migrationsDir = path5.join(process.cwd(), "database/migrations");
441
+ if (!fs5.existsSync(migrationsDir)) {
288
442
  console.log("No migrations directory found.");
289
443
  return;
290
444
  }
291
- const files = fs4.readdirSync(migrationsDir).filter((f) => f.endsWith(".ts") || f.endsWith(".js")).sort();
445
+ const files = fs5.readdirSync(migrationsDir).filter((f) => f.endsWith(".ts") || f.endsWith(".js")).sort();
292
446
  for (const file of files) {
293
447
  console.log(`Processing migration: ${file}`);
294
- const filePath = path4.join(migrationsDir, file);
448
+ const filePath = path5.join(migrationsDir, file);
295
449
  try {
296
450
  const migration = await import(filePath);
297
451
  if (migration.up) {
@@ -303,7 +457,7 @@ async function migrate(args) {
303
457
  try {
304
458
  const execCmd = `npx wrangler d1 execute ${dbName} --command "${sql.replace(/"/g, '\\"')}" ${command}`;
305
459
  console.log(`Executing: ${execCmd}`);
306
- execSync(execCmd, { stdio: "inherit" });
460
+ execSync2(execCmd, { stdio: "inherit" });
307
461
  } catch (e) {
308
462
  console.error(`Failed to execute migration: ${file}`);
309
463
  throw e;
@@ -314,10 +468,52 @@ async function migrate(args) {
314
468
  console.error(`Error processing migration ${file}:`, error);
315
469
  }
316
470
  }
471
+ if (args.includes("--seed")) {
472
+ await seed(args);
473
+ }
317
474
  }
318
475
  var init_migrate = __esm({
319
476
  "src/cli/commands/migrate.ts"() {
320
477
  "use strict";
478
+ init_seed();
479
+ }
480
+ });
481
+
482
+ // src/cli/commands/migrate-fresh.ts
483
+ import { execSync as execSync3 } from "child_process";
484
+ async function migrateFresh(args) {
485
+ console.log("Dropping all tables...");
486
+ const isRemote = args.includes("--remote");
487
+ const dbName = "DB";
488
+ const flag = isRemote ? "--remote" : "--local";
489
+ try {
490
+ const listTablesCmd = `npx wrangler d1 execute ${dbName} --command "SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' AND name NOT LIKE '_cf_%'" ${flag} --json`;
491
+ const output = execSync3(listTablesCmd, {
492
+ encoding: "utf-8",
493
+ stdio: ["ignore", "pipe", "inherit"]
494
+ });
495
+ const jsonStart = output.indexOf("[");
496
+ if (jsonStart !== -1) {
497
+ const results = JSON.parse(output.substring(jsonStart));
498
+ const tables = results[0]?.results || [];
499
+ if (tables.length > 0) {
500
+ const dropCommands = tables.map((t) => `DROP TABLE IF EXISTS ${t.name};`).join(" ");
501
+ const dropCmd = `npx wrangler d1 execute ${dbName} --command "${dropCommands}" ${flag}`;
502
+ console.log("Executing drop tables...");
503
+ execSync3(dropCmd, { stdio: "inherit" });
504
+ } else {
505
+ console.log("No tables found to drop.");
506
+ }
507
+ }
508
+ await migrate(args);
509
+ } catch (error) {
510
+ console.error("Error during migrate:fresh:", error);
511
+ }
512
+ }
513
+ var init_migrate_fresh = __esm({
514
+ "src/cli/commands/migrate-fresh.ts"() {
515
+ "use strict";
516
+ init_migrate();
321
517
  }
322
518
  });
323
519
 
@@ -328,6 +524,8 @@ var require_cli = __commonJS({
328
524
  init_make_model();
329
525
  init_make_migration();
330
526
  init_migrate();
527
+ init_migrate_fresh();
528
+ init_seed();
331
529
  var args = process.argv.slice(2);
332
530
  var command = args[0];
333
531
  var param = args[1];
@@ -342,13 +540,17 @@ var require_cli = __commonJS({
342
540
  makeMigration(param);
343
541
  break;
344
542
  case "migrate":
345
- const isLocal = args.includes("--local");
346
- const isRemote = args.includes("--remote");
347
543
  migrate(args);
348
544
  break;
545
+ case "migrate:fresh":
546
+ migrateFresh(args);
547
+ break;
548
+ case "db:seed":
549
+ seed(args);
550
+ break;
349
551
  default:
350
552
  console.log(
351
- "Available commands: init, make:model, make:migration, migrate"
553
+ "Available commands: init, make:model, make:migration, migrate, migrate:fresh, db:seed"
352
554
  );
353
555
  break;
354
556
  }
package/dist/index.mjs CHANGED
@@ -1,80 +1,12 @@
1
- import "./chunk-X6BYQHVC.mjs";
1
+ import {
2
+ Connection,
3
+ Database,
4
+ init_connection,
5
+ init_database
6
+ } from "./chunk-5BBZKUNZ.mjs";
2
7
 
3
- // src/core/connection.ts
4
- var Connection = class {
5
- /**
6
- * The underlying D1Database instance.
7
- */
8
- db;
9
- /**
10
- * Create a new Connection instance.
11
- *
12
- * @param database - The D1Database instance.
13
- */
14
- constructor(database) {
15
- this.db = database;
16
- }
17
- /**
18
- * Execute a SELECT statement.
19
- *
20
- * @param query - The SQL query string.
21
- * @param bindings - The parameter bindings.
22
- * @returns A promise that resolves to an array of results.
23
- */
24
- async select(query, bindings = []) {
25
- const stmt = this.db.prepare(query).bind(...bindings);
26
- const result = await stmt.all();
27
- return result.results || [];
28
- }
29
- /**
30
- * Execute an INSERT statement.
31
- *
32
- * @param query - The SQL query string.
33
- * @param bindings - The parameter bindings.
34
- * @returns A promise that resolves to true on success.
35
- */
36
- async insert(query, bindings = []) {
37
- const stmt = this.db.prepare(query).bind(...bindings);
38
- const result = await stmt.run();
39
- return result.success;
40
- }
41
- /**
42
- * Execute an UPDATE statement.
43
- *
44
- * @param query - The SQL query string.
45
- * @param bindings - The parameter bindings.
46
- * @returns A promise that resolves to true on success.
47
- */
48
- async update(query, bindings = []) {
49
- const stmt = this.db.prepare(query).bind(...bindings);
50
- const result = await stmt.run();
51
- return result.success;
52
- }
53
- /**
54
- * Execute a DELETE statement.
55
- *
56
- * @param query - The SQL query string.
57
- * @param bindings - The parameter bindings.
58
- * @returns A promise that resolves to true on success.
59
- */
60
- async delete(query, bindings = []) {
61
- const stmt = this.db.prepare(query).bind(...bindings);
62
- const result = await stmt.run();
63
- return result.success;
64
- }
65
- /**
66
- * Execute an arbitrary SQL statement.
67
- *
68
- * @param query - The SQL query string.
69
- * @param bindings - The parameter bindings.
70
- * @returns A promise that resolves to true on success.
71
- */
72
- async statement(query, bindings = []) {
73
- const stmt = this.db.prepare(query).bind(...bindings);
74
- const result = await stmt.run();
75
- return result.success;
76
- }
77
- };
8
+ // src/index.ts
9
+ init_connection();
78
10
 
79
11
  // src/core/query-builder.ts
80
12
  var QueryBuilder = class {
@@ -342,47 +274,11 @@ var ModelQueryBuilder = class extends QueryBuilder {
342
274
  }
343
275
  };
344
276
 
345
- // src/core/database.ts
346
- var Database = class _Database {
347
- /**
348
- * The singleton instance of the Database.
349
- */
350
- static instance;
351
- /**
352
- * The active database connection.
353
- */
354
- connection;
355
- /**
356
- * Private constructor to enforce singleton pattern.
357
- *
358
- * @param d1 - The D1Database instance from Cloudflare.
359
- */
360
- constructor(d1) {
361
- this.connection = new Connection(d1);
362
- }
363
- /**
364
- * Setup the database connection.
365
- *
366
- * @param d1 - The D1Database instance from Cloudflare environment (env.DB).
367
- */
368
- static setup(d1) {
369
- _Database.instance = new _Database(d1);
370
- }
371
- /**
372
- * Get the singleton Database instance.
373
- *
374
- * @throws Error if setup() has not been called.
375
- * @returns The Database instance.
376
- */
377
- static getInstance() {
378
- if (!_Database.instance) {
379
- throw new Error(
380
- "Database not initialized. Call Database.setup(env.DB) first."
381
- );
382
- }
383
- return _Database.instance;
384
- }
385
- };
277
+ // src/index.ts
278
+ init_database();
279
+
280
+ // src/models/model.ts
281
+ init_database();
386
282
 
387
283
  // src/core/relationships/relationship.ts
388
284
  var Relationship = class {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@3lineas/d1-orm",
3
- "version": "1.0.5",
3
+ "version": "1.0.7",
4
4
  "description": "A lightweight and powerful ORM for Cloudflare D1, inspired by Laravel Eloquent.",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -1,12 +0,0 @@
1
- var __getOwnPropNames = Object.getOwnPropertyNames;
2
- var __esm = (fn, res) => function __init() {
3
- return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
4
- };
5
- var __commonJS = (cb, mod) => function __require() {
6
- return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
7
- };
8
-
9
- export {
10
- __esm,
11
- __commonJS
12
- };