@3lineas/d1-orm 1.0.7 → 1.0.9

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