@3lineas/d1-orm 1.0.7 → 1.0.8

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/dist/cli/index.js CHANGED
@@ -1,58 +1,33 @@
1
1
  #!/usr/bin/env node
2
- "use strict";
3
- var __create = Object.create;
4
- var __defProp = Object.defineProperty;
5
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
- var __getOwnPropNames = Object.getOwnPropertyNames;
7
- var __getProtoOf = Object.getPrototypeOf;
8
- var __hasOwnProp = Object.prototype.hasOwnProperty;
9
- var __copyProps = (to, from, except, desc) => {
10
- if (from && typeof from === "object" || typeof from === "function") {
11
- for (let key of __getOwnPropNames(from))
12
- if (!__hasOwnProp.call(to, key) && key !== except)
13
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
- }
15
- return to;
16
- };
17
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
18
- // If the importer is in node compatibility mode or this is not an ESM
19
- // file that has been converted to a CommonJS file using a Babel-
20
- // compatible transform (i.e. "__esModule" has not been set), then set
21
- // "default" to the CommonJS "module.exports" for node compatibility.
22
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
23
- mod
24
- ));
2
+ import {
3
+ Database
4
+ } from "../chunk-N3G6NOJP.js";
25
5
 
26
6
  // src/cli/commands/init.ts
27
- var fs = __toESM(require("fs"));
28
- var path = __toESM(require("path"));
29
- var readline = __toESM(require("readline"));
7
+ import * as fs from "fs";
8
+ import * as path from "path";
9
+ import * as p from "@clack/prompts";
30
10
  async function init() {
31
- const rl = readline.createInterface({
32
- input: process.stdin,
33
- output: process.stdout
34
- });
35
- const question = (query) => {
36
- return new Promise((resolve) => {
37
- rl.question(query, resolve);
38
- });
39
- };
40
- console.log("Initializing D1 ORM...");
41
- const defaultModelsPath = "src/models";
42
- const userModelsPath = await question(
43
- `Where would you like to install your models? (default: ${defaultModelsPath}): `
44
- ) || defaultModelsPath;
45
- rl.close();
46
- const folders = [userModelsPath, "database/migrations", "database/seeders"];
11
+ p.intro("Initializing D1 ORM...");
12
+ const s = p.spinner();
13
+ s.start("Scanning project structure...");
14
+ const srcPath = path.join(process.cwd(), "src");
15
+ const useSrc = fs.existsSync(srcPath) && fs.lstatSync(srcPath).isDirectory();
16
+ const baseDatabasePath = useSrc ? "src/database" : "database";
17
+ const modelsPath = path.join(baseDatabasePath, "models");
18
+ const migrationsPath = path.join(baseDatabasePath, "migrations");
19
+ const seedersPath = path.join(baseDatabasePath, "seeders");
20
+ const folders = [modelsPath, migrationsPath, seedersPath];
47
21
  folders.forEach((folder) => {
48
22
  const fullPath = path.join(process.cwd(), folder);
49
23
  if (!fs.existsSync(fullPath)) {
50
24
  fs.mkdirSync(fullPath, { recursive: true });
51
- console.log(`Created directory: ${folder}`);
25
+ p.log.step(`Created directory: ${folder}`);
52
26
  } else {
53
- console.log(`Directory already exists: ${folder}`);
27
+ p.log.info(`Directory already exists: ${folder}`);
54
28
  }
55
29
  });
30
+ s.message("Generating example files...");
56
31
  const userModelContent = `import { Model } from '@3lineas/d1-orm';
57
32
 
58
33
  export class User extends Model {
@@ -66,10 +41,10 @@ export class User extends Model {
66
41
  declare updated_at: string;
67
42
  }
68
43
  `;
69
- const userModelPath = path.join(process.cwd(), userModelsPath, "User.ts");
44
+ const userModelPath = path.join(process.cwd(), modelsPath, "User.ts");
70
45
  if (!fs.existsSync(userModelPath)) {
71
46
  fs.writeFileSync(userModelPath, userModelContent);
72
- console.log(`Created model: ${userModelPath}`);
47
+ p.log.step(`Created model: ${modelsPath}/User.ts`);
73
48
  }
74
49
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[-:]/g, "").split(".")[0].replace("T", "_");
75
50
  const migrationName = `${timestamp}_create_users_table.ts`;
@@ -89,19 +64,16 @@ export const down = async () => {
89
64
  return Schema.dropIfExists('users');
90
65
  };
91
66
  `;
92
- const migrationPath = path.join(
67
+ const fullMigrationsPath = path.join(
93
68
  process.cwd(),
94
- "database/migrations",
69
+ migrationsPath,
95
70
  migrationName
96
71
  );
97
- if (!fs.existsSync(migrationPath)) {
98
- fs.writeFileSync(migrationPath, migrationContent);
99
- console.log(`Created migration: ${migrationPath}`);
100
- }
101
- const seederContent = `import { User } from '${path.relative(
102
- path.join(process.cwd(), "database/seeders"),
103
- path.join(process.cwd(), userModelsPath, "User")
104
- ).replace(/\\/g, "/")}.ts';
72
+ if (!fs.existsSync(fullMigrationsPath)) {
73
+ fs.writeFileSync(fullMigrationsPath, migrationContent);
74
+ p.log.step(`Created migration: ${migrationsPath}/${migrationName}`);
75
+ }
76
+ const seederContent = `import { User } from '../models/User.ts';
105
77
 
106
78
  export const seed = async () => {
107
79
  await User.create({
@@ -111,14 +83,23 @@ export const seed = async () => {
111
83
  });
112
84
  };
113
85
  `;
114
- const seederPath = path.join(
86
+ const fullSeederPath = path.join(process.cwd(), seedersPath, "UserSeeder.ts");
87
+ if (!fs.existsSync(fullSeederPath)) {
88
+ fs.writeFileSync(fullSeederPath, seederContent);
89
+ p.log.step(`Created seeder: ${seedersPath}/UserSeeder.ts`);
90
+ }
91
+ const configContent = `export default {
92
+ binding: 'DB', // Name of the D1 binding in wrangler.jsonc/toml
93
+ };
94
+ `;
95
+ const configFilePath = path.join(
115
96
  process.cwd(),
116
- "database/seeders",
117
- "UserSeeder.ts"
97
+ baseDatabasePath,
98
+ "config.ts"
118
99
  );
119
- if (!fs.existsSync(seederPath)) {
120
- fs.writeFileSync(seederPath, seederContent);
121
- console.log(`Created seeder: ${seederPath}`);
100
+ if (!fs.existsSync(configFilePath)) {
101
+ fs.writeFileSync(configFilePath, configContent);
102
+ p.log.step(`Created config: ${baseDatabasePath}/config.ts`);
122
103
  }
123
104
  const packageJsonPath = path.join(process.cwd(), "package.json");
124
105
  if (fs.existsSync(packageJsonPath)) {
@@ -130,43 +111,50 @@ export const seed = async () => {
130
111
  if (!packageJson.scripts.orm) {
131
112
  packageJson.scripts.orm = "d1-orm";
132
113
  fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2));
133
- console.log('Added "orm" script to package.json');
134
- } else {
135
- console.log('"orm" script already exists in package.json');
114
+ p.log.step('Added "orm" script to package.json');
136
115
  }
137
116
  } catch (e) {
138
- console.error("Failed to update package.json:", e);
117
+ p.log.error(`Failed to update package.json: ${e}`);
139
118
  }
140
119
  }
120
+ s.stop("Initialization complete!");
121
+ p.outro("D1 ORM is ready to use.");
141
122
  }
142
123
 
143
124
  // src/cli/commands/make-model.ts
144
- var fs3 = __toESM(require("fs"));
145
- var path3 = __toESM(require("path"));
146
- var p2 = __toESM(require("@clack/prompts"));
125
+ import * as fs3 from "fs";
126
+ import * as path3 from "path";
127
+ import * as p3 from "@clack/prompts";
147
128
 
148
129
  // src/cli/commands/make-migration.ts
149
- var fs2 = __toESM(require("fs"));
150
- var path2 = __toESM(require("path"));
151
- var p = __toESM(require("@clack/prompts"));
130
+ import * as fs2 from "fs";
131
+ import * as path2 from "path";
132
+ import * as p2 from "@clack/prompts";
152
133
  async function makeMigration(name) {
134
+ const isStandalone = !name;
135
+ if (isStandalone) {
136
+ p2.intro("Creating a new migration...");
137
+ }
153
138
  let migrationName = name;
154
139
  if (!migrationName) {
155
- migrationName = await p.text({
140
+ migrationName = await p2.text({
156
141
  message: "What should the migration be named?",
157
142
  placeholder: "e.g. create_users_table",
158
143
  validate: (value) => {
159
144
  if (!value) return "Please enter a name.";
160
145
  }
161
146
  });
162
- if (p.isCancel(migrationName)) {
163
- p.cancel("Operation cancelled.");
147
+ if (p2.isCancel(migrationName)) {
148
+ p2.cancel("Operation cancelled.");
164
149
  return;
165
150
  }
166
151
  }
152
+ const srcMigrationsDir = path2.join(process.cwd(), "src/database/migrations");
153
+ const rootMigrationsDir = path2.join(process.cwd(), "database/migrations");
154
+ const migrationsDir = fs2.existsSync(srcMigrationsDir) ? "src/database/migrations" : "database/migrations";
167
155
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[-:]/g, "").split(".")[0].replace("T", "_");
168
156
  const filename = `${timestamp}_${migrationName}.ts`;
169
- const targetPath = path2.join(process.cwd(), "database/migrations", filename);
157
+ const targetPath = path2.join(process.cwd(), migrationsDir, filename);
170
158
  const template = `import { Blueprint, Schema } from '@3lineas/d1-orm';
171
159
 
172
160
  export const up = async () => {
@@ -180,36 +168,41 @@ export const down = async () => {
180
168
  return Schema.dropIfExists('${migrationName.replace("create_", "").replace("_table", "")}');
181
169
  };
182
170
  `;
183
- if (!fs2.existsSync(path2.join(process.cwd(), "database/migrations"))) {
184
- fs2.mkdirSync(path2.join(process.cwd(), "database/migrations"), {
171
+ if (!fs2.existsSync(path2.join(process.cwd(), migrationsDir))) {
172
+ fs2.mkdirSync(path2.join(process.cwd(), migrationsDir), {
185
173
  recursive: true
186
174
  });
187
175
  }
188
176
  if (fs2.existsSync(targetPath)) {
189
- p.log.error(`Migration ${filename} already exists.`);
177
+ p2.log.error(`Migration ${filename} already exists.`);
178
+ if (isStandalone) p2.outro("Process aborted.");
190
179
  return;
191
180
  }
192
181
  fs2.writeFileSync(targetPath, template);
193
- p.log.success(`Created migration: database/migrations/${filename}`);
182
+ p2.log.success(`Created migration: ${migrationsDir}/${filename}`);
183
+ if (isStandalone) {
184
+ p2.outro("Migration generated successfully!");
185
+ }
194
186
  }
195
187
 
196
188
  // src/cli/commands/make-model.ts
197
189
  async function makeModel(name) {
190
+ p3.intro("Creating a new model...");
198
191
  let modelName = name;
199
192
  if (!modelName) {
200
- modelName = await p2.text({
193
+ modelName = await p3.text({
201
194
  message: "What should the model be named?",
202
195
  placeholder: "e.g. Flight",
203
196
  validate: (value) => {
204
197
  if (!value) return "Please enter a name.";
205
198
  }
206
199
  });
207
- if (p2.isCancel(modelName)) {
208
- p2.cancel("Operation cancelled.");
200
+ if (p3.isCancel(modelName)) {
201
+ p3.cancel("Operation cancelled.");
209
202
  return;
210
203
  }
211
204
  }
212
- const modelPath = await findModelsPath() || "src/models";
205
+ const modelPath = await findModelsPath() || "src/database/models";
213
206
  const filename = `${modelName}.ts`;
214
207
  const targetPath = path3.join(process.cwd(), modelPath, filename);
215
208
  const template = `import { Model } from '@3lineas/d1-orm';
@@ -223,15 +216,16 @@ export class ${modelName} extends Model {
223
216
  }
224
217
  `;
225
218
  if (fs3.existsSync(targetPath)) {
226
- p2.log.error(`Model ${filename} already exists at ${modelPath}.`);
219
+ p3.log.error(`Model ${filename} already exists at ${modelPath}.`);
220
+ p3.outro("Process aborted.");
227
221
  return;
228
222
  }
229
223
  if (!fs3.existsSync(path3.join(process.cwd(), modelPath))) {
230
224
  fs3.mkdirSync(path3.join(process.cwd(), modelPath), { recursive: true });
231
225
  }
232
226
  fs3.writeFileSync(targetPath, template);
233
- p2.log.success(`Created model: ${modelPath}/${filename}`);
234
- const options = await p2.multiselect({
227
+ p3.log.success(`Created model: ${modelPath}/${filename}`);
228
+ const options = await p3.multiselect({
235
229
  message: "Would you like to create any of the following?",
236
230
  options: [
237
231
  { value: "migration", label: "Migration" },
@@ -239,8 +233,8 @@ export class ${modelName} extends Model {
239
233
  ],
240
234
  required: false
241
235
  });
242
- if (p2.isCancel(options)) {
243
- p2.cancel("Operation cancelled.");
236
+ if (p3.isCancel(options)) {
237
+ p3.cancel("Operation cancelled.");
244
238
  return;
245
239
  }
246
240
  if (options.includes("migration")) {
@@ -250,18 +244,25 @@ export class ${modelName} extends Model {
250
244
  if (options.includes("seeder")) {
251
245
  await makeSeeder(modelName, modelPath);
252
246
  }
247
+ p3.outro("Model generation complete!");
253
248
  }
254
249
  async function findModelsPath() {
255
- const packageJsonPath = path3.join(process.cwd(), "package.json");
256
- if (!fs3.existsSync(packageJsonPath)) return null;
257
- const commonPaths = ["src/models", "models", "app/Models"];
258
- for (const p3 of commonPaths) {
259
- if (fs3.existsSync(path3.join(process.cwd(), p3))) return p3;
250
+ const commonPaths = [
251
+ "src/database/models",
252
+ "database/models",
253
+ "src/models",
254
+ "models",
255
+ "app/Models"
256
+ ];
257
+ for (const p7 of commonPaths) {
258
+ if (fs3.existsSync(path3.join(process.cwd(), p7))) return p7;
260
259
  }
261
260
  return null;
262
261
  }
263
262
  async function makeSeeder(modelName, modelPath) {
264
- const seederDir = path3.join(process.cwd(), "database/seeders");
263
+ const srcPath = path3.join(process.cwd(), "src");
264
+ const useSrc = fs3.existsSync(srcPath) && fs3.lstatSync(srcPath).isDirectory();
265
+ const seederDir = useSrc ? path3.join(process.cwd(), "src/database/seeders") : path3.join(process.cwd(), "database/seeders");
265
266
  const seederName = `${modelName}Seeder.ts`;
266
267
  const targetPath = path3.join(seederDir, seederName);
267
268
  if (!fs3.existsSync(seederDir)) {
@@ -275,142 +276,84 @@ export const seed = async () => {
275
276
  };
276
277
  `;
277
278
  if (fs3.existsSync(targetPath)) {
278
- p2.log.warn(`Seeder ${seederName} already exists.`);
279
+ p3.log.warn(`Seeder ${seederName} already exists.`);
279
280
  return;
280
281
  }
281
282
  fs3.writeFileSync(targetPath, template);
282
- p2.log.success(`Created seeder: database/seeders/${seederName}`);
283
+ p3.log.success(`Created seeder: database/seeders/${seederName}`);
283
284
  }
284
285
 
285
286
  // 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");
287
+ import * as fs6 from "fs";
288
+ import * as path6 from "path";
289
+ import { execSync as execSync2 } from "child_process";
290
+ import * as p5 from "@clack/prompts";
289
291
 
290
- // src/cli/commands/seed.ts
291
- var fs4 = __toESM(require("fs"));
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
- }
292
+ // src/cli/utils/config.ts
293
+ import * as fs4 from "fs";
294
+ import * as path4 from "path";
295
+ var Config = class {
308
296
  /**
309
- * Execute a SELECT statement.
297
+ * Detect the D1 database binding from Wrangler configuration or d1-orm config.
310
298
  *
311
- * @param query - The SQL query string.
312
- * @param bindings - The parameter bindings.
313
- * @returns A promise that resolves to an array of results.
299
+ * @returns The binding name (e.g., "DB").
314
300
  */
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);
301
+ static getD1Binding() {
302
+ const srcConfig = path4.join(process.cwd(), "src/database/config.ts");
303
+ const rootConfig = path4.join(process.cwd(), "database/config.ts");
304
+ const configPath = fs4.existsSync(srcConfig) ? srcConfig : fs4.existsSync(rootConfig) ? rootConfig : null;
305
+ if (configPath) {
306
+ const content = fs4.readFileSync(configPath, "utf-8");
307
+ const match = content.match(/binding\s*:\s*["'](.+?)["']/);
308
+ if (match) return match[1];
309
+ }
310
+ const wranglerPaths = ["wrangler.jsonc", "wrangler.json", "wrangler.toml"];
311
+ for (const configName of wranglerPaths) {
312
+ const fullPath = path4.join(process.cwd(), configName);
313
+ if (fs4.existsSync(fullPath)) {
314
+ const content = fs4.readFileSync(fullPath, "utf-8");
315
+ if (configName.endsWith(".json") || configName.endsWith(".jsonc")) {
316
+ try {
317
+ const jsonStr = content.replace(/\/\/.*|\/\*[\s\S]*?\*\//g, "");
318
+ const config = JSON.parse(jsonStr);
319
+ const d1Databases = config.d1_databases;
320
+ if (Array.isArray(d1Databases) && d1Databases.length > 0) {
321
+ return d1Databases[0].binding || "DB";
322
+ }
323
+ } catch (e) {
324
+ }
325
+ }
326
+ if (configName.endsWith(".toml")) {
327
+ const match = content.match(/binding\s*=\s*["'](.+?)["']/);
328
+ if (match) return match[1];
329
+ }
330
+ }
331
+ }
332
+ return "DB";
395
333
  }
396
334
  /**
397
- * Get the singleton Database instance.
398
- *
399
- * @throws Error if setup() has not been called.
400
- * @returns The Database instance.
335
+ * Detect if the project is ESM.
401
336
  */
402
- static getInstance() {
403
- if (!_Database.instance) {
404
- throw new Error(
405
- "Database not initialized. Call Database.setup(env.DB) first."
406
- );
337
+ static isESM() {
338
+ const pkgPath = path4.join(process.cwd(), "package.json");
339
+ if (fs4.existsSync(pkgPath)) {
340
+ try {
341
+ const pkg = JSON.parse(fs4.readFileSync(pkgPath, "utf-8"));
342
+ return pkg.type === "module";
343
+ } catch (e) {
344
+ return false;
345
+ }
407
346
  }
408
- return _Database.instance;
347
+ return false;
409
348
  }
410
349
  };
411
350
 
351
+ // src/cli/commands/seed.ts
352
+ import * as fs5 from "fs";
353
+ import * as path5 from "path";
354
+
412
355
  // src/cli/cli-connection.ts
413
- var import_child_process = require("child_process");
356
+ import { execSync } from "child_process";
414
357
  var CLIConnection = class {
415
358
  constructor(dbName = "DB", isRemote = false) {
416
359
  this.dbName = dbName;
@@ -442,7 +385,7 @@ var CLIConnection = class {
442
385
  const flag = this.isRemote ? "--remote" : "--local";
443
386
  const command2 = `npx wrangler d1 execute ${this.dbName} --command "${sql.replace(/"/g, '\\"')}" ${flag} --json`;
444
387
  try {
445
- const output = (0, import_child_process.execSync)(command2, {
388
+ const output = execSync(command2, {
446
389
  encoding: "utf-8",
447
390
  stdio: ["ignore", "pipe", "inherit"]
448
391
  });
@@ -492,7 +435,7 @@ var CLIPREparedStatement = class {
492
435
  const flag = this.isRemote ? "--remote" : "--local";
493
436
  const command2 = `npx wrangler d1 execute ${this.dbName} --command "${sql.replace(/"/g, '\\"')}" ${flag} --json`;
494
437
  try {
495
- const output = (0, import_child_process.execSync)(command2, {
438
+ const output = execSync(command2, {
496
439
  encoding: "utf-8",
497
440
  stdio: ["ignore", "pipe", "pipe"]
498
441
  });
@@ -518,83 +461,126 @@ var CLIPREparedStatement = class {
518
461
  };
519
462
 
520
463
  // src/cli/commands/seed.ts
464
+ import * as p4 from "@clack/prompts";
521
465
  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.");
466
+ p4.intro("Seeding database...");
467
+ const srcSeedersDir = path5.join(process.cwd(), "src/database/seeders");
468
+ const rootSeedersDir = path5.join(process.cwd(), "database/seeders");
469
+ const seedersDir = fs5.existsSync(srcSeedersDir) ? srcSeedersDir : rootSeedersDir;
470
+ if (!fs5.existsSync(seedersDir)) {
471
+ p4.log.warn(
472
+ `No seeders directory found (checked ${srcSeedersDir} and ${rootSeedersDir}).`
473
+ );
474
+ p4.outro("Nothing to seed.");
526
475
  return;
527
476
  }
528
477
  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.`);
478
+ const dbName = Config.getD1Binding();
479
+ const s = p4.spinner();
480
+ s.start(`Initializing ORM (Binding: ${dbName})...`);
481
+ try {
482
+ const connection = new CLIConnection(dbName, isRemote);
483
+ Database.setup(connection);
484
+ s.stop(`ORM initialized successfully with binding "${dbName}".`);
485
+ const files = fs5.readdirSync(seedersDir).filter((f) => f.endsWith(".ts") || f.endsWith(".js")).sort();
486
+ if (files.length === 0) {
487
+ p4.log.info("No seeder files found.");
488
+ p4.outro("Seeding complete.");
489
+ return;
490
+ }
491
+ for (const file of files) {
492
+ s.start(`Running seeder: ${file}`);
493
+ const filePath = path5.join(seedersDir, file);
494
+ try {
495
+ const seeder = await import(filePath);
496
+ if (seeder.seed) {
497
+ await seeder.seed(Database.getInstance());
498
+ s.stop(`Completed: ${file}`);
499
+ } else {
500
+ s.stop(`Skipped: ${file} (no seed function)`, 1);
501
+ }
502
+ } catch (error) {
503
+ s.stop(`Failed: ${file}`, 1);
504
+ p4.log.error(`Error running seeder ${file}: ${error}`);
542
505
  }
543
- } catch (error) {
544
- console.error(`Error running seeder ${file}:`, error);
545
506
  }
507
+ p4.outro("Seeding completed successfully.");
508
+ } catch (error) {
509
+ s.stop("Initialization failed.", 1);
510
+ p4.log.error(`Seeding error: ${error}`);
546
511
  }
547
512
  }
548
513
 
549
514
  // src/cli/commands/migrate.ts
550
515
  async function migrate(args2) {
551
- console.log("Running migrations...");
552
- const migrationsDir = path5.join(process.cwd(), "database/migrations");
553
- if (!fs5.existsSync(migrationsDir)) {
554
- console.log("No migrations directory found.");
516
+ p5.intro("Running migrations...");
517
+ const srcMigrationsDir = path6.join(process.cwd(), "src/database/migrations");
518
+ const rootMigrationsDir = path6.join(process.cwd(), "database/migrations");
519
+ const migrationsDir = fs6.existsSync(srcMigrationsDir) ? srcMigrationsDir : rootMigrationsDir;
520
+ if (!fs6.existsSync(migrationsDir)) {
521
+ p5.log.warn(
522
+ `No migrations directory found (checked ${srcMigrationsDir} and ${rootMigrationsDir}).`
523
+ );
524
+ p5.outro("Nothing to migrate.");
555
525
  return;
556
526
  }
557
- const files = fs5.readdirSync(migrationsDir).filter((f) => f.endsWith(".ts") || f.endsWith(".js")).sort();
527
+ const files = fs6.readdirSync(migrationsDir).filter((f) => f.endsWith(".ts") || f.endsWith(".js")).sort();
528
+ if (files.length === 0) {
529
+ p5.log.info("No migration files found.");
530
+ p5.outro("Migrations complete.");
531
+ return;
532
+ }
533
+ const s = p5.spinner();
534
+ const dbName = Config.getD1Binding();
558
535
  for (const file of files) {
559
- console.log(`Processing migration: ${file}`);
560
- const filePath = path5.join(migrationsDir, file);
536
+ s.start(`Processing migration: ${file} (Binding: ${dbName})`);
537
+ const filePath = path6.join(migrationsDir, file);
561
538
  try {
562
539
  const migration = await import(filePath);
563
540
  if (migration.up) {
564
541
  const sql = await migration.up();
565
542
  if (sql) {
566
543
  const isRemote = args2.includes("--remote");
567
- const dbName = "DB";
568
544
  const command2 = isRemote ? "--remote" : "--local";
569
545
  try {
570
546
  const execCmd = `npx wrangler d1 execute ${dbName} --command "${sql.replace(/"/g, '\\"')}" ${command2}`;
571
- console.log(`Executing: ${execCmd}`);
572
- (0, import_child_process2.execSync)(execCmd, { stdio: "inherit" });
547
+ execSync2(execCmd, { stdio: "pipe" });
548
+ s.stop(`Migrated: ${file}`);
573
549
  } catch (e) {
574
- console.error(`Failed to execute migration: ${file}`);
550
+ s.stop(`Failed: ${file}`, 1);
551
+ p5.log.error(`Failed to execute migration: ${file}`);
575
552
  throw e;
576
553
  }
554
+ } else {
555
+ s.stop(`Skipped (no SQL): ${file}`);
577
556
  }
557
+ } else {
558
+ s.stop(`Skipped (no up function): ${file}`);
578
559
  }
579
560
  } catch (error) {
580
- console.error(`Error processing migration ${file}:`, error);
561
+ s.stop(`Error: ${file}`, 1);
562
+ p5.log.error(`Error processing migration ${file}: ${error}`);
581
563
  }
582
564
  }
565
+ p5.outro("All migrations executed.");
583
566
  if (args2.includes("--seed")) {
584
567
  await seed(args2);
585
568
  }
586
569
  }
587
570
 
588
571
  // src/cli/commands/migrate-fresh.ts
589
- var import_child_process3 = require("child_process");
572
+ import { execSync as execSync3 } from "child_process";
573
+ import * as p6 from "@clack/prompts";
590
574
  async function migrateFresh(args2) {
591
- console.log("Dropping all tables...");
575
+ p6.intro("Resetting database...");
592
576
  const isRemote = args2.includes("--remote");
593
- const dbName = "DB";
577
+ const dbName = Config.getD1Binding();
594
578
  const flag = isRemote ? "--remote" : "--local";
579
+ const s = p6.spinner();
580
+ s.start("Scanning for tables to drop...");
595
581
  try {
596
582
  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, {
583
+ const output = execSync3(listTablesCmd, {
598
584
  encoding: "utf-8",
599
585
  stdio: ["ignore", "pipe", "inherit"]
600
586
  });
@@ -603,17 +589,21 @@ async function migrateFresh(args2) {
603
589
  const results = JSON.parse(output.substring(jsonStart));
604
590
  const tables = results[0]?.results || [];
605
591
  if (tables.length > 0) {
592
+ s.message(`Dropping ${tables.length} tables...`);
606
593
  const dropCommands = tables.map((t) => `DROP TABLE IF EXISTS ${t.name};`).join(" ");
607
594
  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" });
595
+ execSync3(dropCmd, { stdio: "pipe" });
596
+ s.stop("All tables dropped successfully.");
610
597
  } else {
611
- console.log("No tables found to drop.");
598
+ s.stop("No tables found to drop.");
612
599
  }
600
+ } else {
601
+ s.stop("Unexpected output from wrangler while listing tables.", 1);
613
602
  }
614
603
  await migrate(args2);
615
604
  } catch (error) {
616
- console.error("Error during migrate:fresh:", error);
605
+ s.stop("Process failed.", 1);
606
+ p6.log.error(`Error during migrate:fresh: ${error}`);
617
607
  }
618
608
  }
619
609