@famgia/omnify-cli 0.0.4 → 0.0.6

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/index.cjs CHANGED
@@ -1,4 +1,3 @@
1
- #!/usr/bin/env node
2
1
  "use strict";
3
2
  var __create = Object.create;
4
3
  var __defProp = Object.defineProperty;
@@ -32,19 +31,177 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
32
31
  var index_exports = {};
33
32
  __export(index_exports, {
34
33
  defineConfig: () => defineConfig,
35
- loadConfig: () => loadConfig
34
+ loadConfig: () => loadConfig,
35
+ logger: () => logger,
36
+ registerDiffCommand: () => registerDiffCommand,
37
+ registerGenerateCommand: () => registerGenerateCommand,
38
+ registerInitCommand: () => registerInitCommand,
39
+ registerValidateCommand: () => registerValidateCommand,
40
+ runInit: () => runInit
36
41
  });
37
42
  module.exports = __toCommonJS(index_exports);
38
- var import_commander = require("commander");
39
- var import_omnify_core6 = require("@famgia/omnify-core");
40
43
 
41
- // src/commands/init.ts
44
+ // src/config/loader.ts
42
45
  var import_node_fs = require("fs");
43
46
  var import_node_path = require("path");
47
+ var import_jiti = require("jiti");
48
+ var import_omnify_core = require("@famgia/omnify-core");
49
+ var CONFIG_FILES = [
50
+ "omnify.config.ts",
51
+ "omnify.config.js",
52
+ "omnify.config.mjs",
53
+ "omnify.config.cjs"
54
+ ];
55
+ function findConfigFile(startDir) {
56
+ const cwd = (0, import_node_path.resolve)(startDir);
57
+ for (const filename of CONFIG_FILES) {
58
+ const configPath = (0, import_node_path.resolve)(cwd, filename);
59
+ if ((0, import_node_fs.existsSync)(configPath)) {
60
+ return configPath;
61
+ }
62
+ }
63
+ return null;
64
+ }
65
+ async function loadConfigFile(configPath) {
66
+ const jiti = (0, import_jiti.createJiti)(configPath, {
67
+ interopDefault: true,
68
+ moduleCache: false
69
+ });
70
+ try {
71
+ const module2 = await jiti.import(configPath);
72
+ const config = module2;
73
+ if ("default" in config) {
74
+ return config.default;
75
+ }
76
+ return config;
77
+ } catch (error) {
78
+ const message = error instanceof Error ? error.message : String(error);
79
+ throw (0, import_omnify_core.configError)(
80
+ `Failed to load config file: ${message}. Check your omnify.config.ts for syntax errors.`,
81
+ "E002"
82
+ );
83
+ }
84
+ }
85
+ async function resolvePlugins(plugins, configPath) {
86
+ if (!plugins || plugins.length === 0) {
87
+ return [];
88
+ }
89
+ const resolved = [];
90
+ const configDir = configPath ? (0, import_node_path.dirname)(configPath) : process.cwd();
91
+ for (const plugin of plugins) {
92
+ if (typeof plugin === "string") {
93
+ const jiti = (0, import_jiti.createJiti)(configDir, {
94
+ interopDefault: true,
95
+ moduleCache: false
96
+ });
97
+ try {
98
+ const module2 = await jiti.import(plugin);
99
+ const loadedPlugin = module2.default ?? module2;
100
+ resolved.push(loadedPlugin);
101
+ } catch (error) {
102
+ const message = error instanceof Error ? error.message : String(error);
103
+ throw (0, import_omnify_core.configError)(
104
+ `Failed to load plugin '${plugin}': ${message}. Ensure the plugin is installed: npm install ${plugin}`,
105
+ "E301"
106
+ );
107
+ }
108
+ } else {
109
+ resolved.push(plugin);
110
+ }
111
+ }
112
+ return resolved;
113
+ }
114
+ async function resolveConfig(userConfig, configPath) {
115
+ const plugins = await resolvePlugins(userConfig.plugins, configPath);
116
+ const databaseConfig = {
117
+ driver: userConfig.database.driver,
118
+ enableFieldComments: userConfig.database.enableFieldComments ?? false
119
+ };
120
+ const database = userConfig.database.devUrl !== void 0 ? { ...databaseConfig, devUrl: userConfig.database.devUrl } : databaseConfig;
121
+ const laravelConfig = {
122
+ migrationsPath: userConfig.output?.laravel?.migrationsPath ?? "database/migrations"
123
+ };
124
+ const laravel = buildLaravelConfig(laravelConfig, userConfig.output?.laravel);
125
+ const typescript = {
126
+ path: userConfig.output?.typescript?.path ?? "types",
127
+ singleFile: userConfig.output?.typescript?.singleFile ?? true,
128
+ generateEnums: userConfig.output?.typescript?.generateEnums ?? true,
129
+ generateRelationships: userConfig.output?.typescript?.generateRelationships ?? true
130
+ };
131
+ const result = {
132
+ schemasDir: userConfig.schemasDir ?? "./schemas",
133
+ database,
134
+ output: {
135
+ laravel,
136
+ typescript
137
+ },
138
+ plugins,
139
+ verbose: userConfig.verbose ?? false,
140
+ lockFilePath: userConfig.lockFilePath ?? ".omnify.lock"
141
+ };
142
+ return result;
143
+ }
144
+ function buildLaravelConfig(base, userLaravel) {
145
+ const config = { ...base };
146
+ if (userLaravel?.modelsPath !== void 0) {
147
+ config.modelsPath = userLaravel.modelsPath;
148
+ }
149
+ if (userLaravel?.modelsNamespace !== void 0) {
150
+ config.modelsNamespace = userLaravel.modelsNamespace;
151
+ }
152
+ if (userLaravel?.factoriesPath !== void 0) {
153
+ config.factoriesPath = userLaravel.factoriesPath;
154
+ }
155
+ if (userLaravel?.enumsPath !== void 0) {
156
+ config.enumsPath = userLaravel.enumsPath;
157
+ }
158
+ if (userLaravel?.enumsNamespace !== void 0) {
159
+ config.enumsNamespace = userLaravel.enumsNamespace;
160
+ }
161
+ return config;
162
+ }
163
+ function validateConfig(config, rootDir) {
164
+ const schemaPath = (0, import_node_path.resolve)(rootDir, config.schemasDir);
165
+ if (!(0, import_node_fs.existsSync)(schemaPath)) {
166
+ throw (0, import_omnify_core.configError)(
167
+ `Schema directory not found: ${schemaPath}. Create the '${config.schemasDir}' directory or update schemasDir in config.`,
168
+ "E002"
169
+ );
170
+ }
171
+ }
172
+ function requireDevUrl(config) {
173
+ if (!config.database.devUrl) {
174
+ throw (0, import_omnify_core.configError)(
175
+ `database.devUrl is required for diff and generate operations. Add devUrl to your database config, e.g., "mysql://root@localhost:3306/omnify_dev"`,
176
+ "E003"
177
+ );
178
+ }
179
+ }
180
+ async function loadConfig(startDir = process.cwd()) {
181
+ const cwd = (0, import_node_path.resolve)(startDir);
182
+ const configPath = findConfigFile(cwd);
183
+ if (configPath) {
184
+ const userConfig = await loadConfigFile(configPath);
185
+ const config = await resolveConfig(userConfig, configPath);
186
+ return {
187
+ config,
188
+ configPath
189
+ };
190
+ }
191
+ throw (0, import_omnify_core.configNotFoundError)((0, import_node_path.resolve)(cwd, "omnify.config.ts"));
192
+ }
193
+ function defineConfig(config) {
194
+ return config;
195
+ }
196
+
197
+ // src/commands/init.ts
198
+ var import_node_fs2 = require("fs");
199
+ var import_node_path2 = require("path");
200
+ var import_prompts = require("@inquirer/prompts");
44
201
 
45
202
  // src/output/logger.ts
46
203
  var import_picocolors = __toESM(require("picocolors"), 1);
47
- var import_omnify_core = require("@famgia/omnify-core");
204
+ var import_omnify_core2 = require("@famgia/omnify-core");
48
205
  var Logger = class {
49
206
  _verbose;
50
207
  _quiet;
@@ -153,21 +310,21 @@ var Logger = class {
153
310
  * Format and log an OmnifyError.
154
311
  */
155
312
  formatError(error) {
156
- const formatted = (0, import_omnify_core.formatError)(error, { color: true });
313
+ const formatted = (0, import_omnify_core2.formatError)(error, { color: true });
157
314
  console.error(formatted);
158
315
  }
159
316
  /**
160
317
  * Get exit code for an error.
161
318
  */
162
319
  getExitCode(error) {
163
- return (0, import_omnify_core.getExitCode)(error);
320
+ return (0, import_omnify_core2.getExitCode)(error);
164
321
  }
165
322
  };
166
323
  var logger = new Logger();
167
324
 
168
325
  // src/commands/init.ts
169
326
  var EXAMPLE_SCHEMA = `# Example User schema
170
- # See https://omnify.dev/docs/schemas for documentation
327
+ # See https://github.com/famgia/omnify for documentation
171
328
 
172
329
  name: User
173
330
  displayName: User Account
@@ -192,78 +349,193 @@ options:
192
349
  timestamps: true
193
350
  softDelete: true
194
351
  `;
195
- var EXAMPLE_CONFIG = `import { defineConfig } from '@famgia/omnify-cli';
352
+ function generateConfig(config) {
353
+ const imports = [`import { defineConfig } from '@famgia/omnify';`];
354
+ const plugins = [];
355
+ if (config.migrationTool === "laravel") {
356
+ imports.push(`import laravel from '@famgia/omnify-laravel/plugin';`);
357
+ plugins.push(` laravel({
358
+ migrationsPath: '${config.migrationsPath}',
359
+ typesPath: '${config.typesPath}',
360
+ singleFile: true,
361
+ generateMigrations: true,
362
+ generateTypes: ${config.generateTypes},
363
+ }),`);
364
+ }
365
+ if (config.migrationTool === "prisma") {
366
+ plugins.push(` // Prisma plugin coming soon!
367
+ // prisma({ schemaPath: 'prisma/schema.prisma' }),`);
368
+ }
369
+ if (config.migrationTool === "drizzle") {
370
+ plugins.push(` // Drizzle plugin coming soon!
371
+ // drizzle({ schemaPath: 'src/db/schema.ts' }),`);
372
+ }
373
+ if (config.migrationTool === "none" && config.generateTypes) {
374
+ imports.push(`import laravel from '@famgia/omnify-laravel/plugin';`);
375
+ plugins.push(` laravel({
376
+ typesPath: '${config.typesPath}',
377
+ generateMigrations: false,
378
+ generateTypes: true,
379
+ }),`);
380
+ }
381
+ const dbUrlExamples = {
382
+ mysql: "mysql://root:password@localhost:3306/omnify_dev",
383
+ postgres: "postgres://postgres:password@localhost:5432/omnify_dev",
384
+ sqlite: "sqlite://./omnify_dev.db"
385
+ };
386
+ return `${imports.join("\n")}
196
387
 
197
388
  export default defineConfig({
198
389
  // Schema files location
199
- schemasDir: './schemas',
390
+ schemasDir: '${config.schemasDir}',
391
+
392
+ // Lock file for tracking schema changes
393
+ lockFilePath: './omnify.lock',
200
394
 
201
395
  // Database configuration
202
396
  database: {
203
- driver: 'mysql',
204
- // Development database URL for Atlas diff operations
205
- // devUrl: 'mysql://root@localhost:3306/omnify_dev',
206
- },
207
-
208
- // Output configuration
209
- output: {
210
- laravel: {
211
- migrationsPath: 'database/migrations',
212
- },
213
- typescript: {
214
- path: 'types',
215
- singleFile: true,
216
- },
397
+ driver: '${config.database}',
398
+ // REQUIRED: Set your development database URL
399
+ // devUrl: '${dbUrlExamples[config.database]}',
217
400
  },
218
401
 
219
- // Plugins for custom types
402
+ // Generator plugins
220
403
  plugins: [
221
- // '@famgia/omnify-japan',
404
+ ${plugins.join("\n\n")}
222
405
  ],
223
406
  });
224
407
  `;
408
+ }
225
409
  async function runInit(options) {
226
410
  const cwd = process.cwd();
227
- logger.header("Initializing Omnify Project");
228
- const configPath = (0, import_node_path.resolve)(cwd, "omnify.config.ts");
229
- if ((0, import_node_fs.existsSync)(configPath) && !options.force) {
411
+ logger.header("Omnify Project Setup");
412
+ logger.newline();
413
+ const configPath = (0, import_node_path2.resolve)(cwd, "omnify.config.ts");
414
+ if ((0, import_node_fs2.existsSync)(configPath) && !options.force) {
230
415
  logger.warn("omnify.config.ts already exists. Use --force to overwrite.");
231
416
  return;
232
417
  }
233
- const schemasDir = (0, import_node_path.resolve)(cwd, "schemas");
234
- if (!(0, import_node_fs.existsSync)(schemasDir)) {
235
- (0, import_node_fs.mkdirSync)(schemasDir, { recursive: true });
236
- logger.step("Created schemas/ directory");
237
- } else {
238
- logger.debug("schemas/ directory already exists");
239
- }
240
- const examplePath = (0, import_node_path.resolve)(schemasDir, "User.yaml");
241
- if (!(0, import_node_fs.existsSync)(examplePath) || options.force) {
242
- (0, import_node_fs.writeFileSync)(examplePath, EXAMPLE_SCHEMA);
243
- logger.step("Created example schema: schemas/User.yaml");
418
+ let config;
419
+ if (options.yes) {
420
+ config = {
421
+ database: "mysql",
422
+ migrationTool: "laravel",
423
+ generateTypes: true,
424
+ migrationsPath: "database/migrations",
425
+ typesPath: "resources/js/types",
426
+ schemasDir: "./schemas"
427
+ };
428
+ logger.info("Using default configuration...");
244
429
  } else {
245
- logger.debug("Example schema already exists");
430
+ logger.info("Answer a few questions to configure your project:\n");
431
+ const database = await (0, import_prompts.select)({
432
+ message: "Which database?",
433
+ choices: [
434
+ { name: "MySQL / MariaDB", value: "mysql" },
435
+ { name: "PostgreSQL", value: "postgres" },
436
+ { name: "SQLite", value: "sqlite" }
437
+ ],
438
+ default: "mysql"
439
+ });
440
+ const migrationTool = await (0, import_prompts.select)({
441
+ message: "Which migration tool?",
442
+ choices: [
443
+ { name: "Laravel (PHP)", value: "laravel" },
444
+ { name: "Prisma (coming soon)", value: "prisma", disabled: true },
445
+ { name: "Drizzle (coming soon)", value: "drizzle", disabled: true },
446
+ { name: "None (types only)", value: "none" }
447
+ ],
448
+ default: "laravel"
449
+ });
450
+ const generateTypes = await (0, import_prompts.confirm)({
451
+ message: "Generate TypeScript types?",
452
+ default: true
453
+ });
454
+ const defaultPaths = {
455
+ laravel: { migrations: "database/migrations", types: "resources/js/types" },
456
+ prisma: { migrations: "prisma/migrations", types: "src/types" },
457
+ drizzle: { migrations: "drizzle", types: "src/types" },
458
+ none: { migrations: "", types: "types" }
459
+ };
460
+ const defaults = defaultPaths[migrationTool];
461
+ let migrationsPath = defaults.migrations;
462
+ let typesPath = defaults.types;
463
+ if (migrationTool !== "none") {
464
+ migrationsPath = await (0, import_prompts.input)({
465
+ message: "Migrations output path:",
466
+ default: defaults.migrations
467
+ });
468
+ }
469
+ if (generateTypes) {
470
+ typesPath = await (0, import_prompts.input)({
471
+ message: "TypeScript types path:",
472
+ default: defaults.types
473
+ });
474
+ }
475
+ const schemasDir2 = await (0, import_prompts.input)({
476
+ message: "Schemas directory:",
477
+ default: "./schemas"
478
+ });
479
+ config = {
480
+ database,
481
+ migrationTool,
482
+ generateTypes,
483
+ migrationsPath,
484
+ typesPath,
485
+ schemasDir: schemasDir2
486
+ };
246
487
  }
247
- (0, import_node_fs.writeFileSync)(configPath, EXAMPLE_CONFIG);
248
- logger.step("Created omnify.config.ts");
249
488
  logger.newline();
250
- logger.success("Project initialized successfully!");
489
+ logger.step("Creating project files...");
490
+ const schemasDir = (0, import_node_path2.resolve)(cwd, config.schemasDir);
491
+ if (!(0, import_node_fs2.existsSync)(schemasDir)) {
492
+ (0, import_node_fs2.mkdirSync)(schemasDir, { recursive: true });
493
+ logger.debug(`Created ${config.schemasDir}/ directory`);
494
+ }
495
+ const examplePath = (0, import_node_path2.resolve)(schemasDir, "User.yaml");
496
+ if (!(0, import_node_fs2.existsSync)(examplePath) || options.force) {
497
+ (0, import_node_fs2.writeFileSync)(examplePath, EXAMPLE_SCHEMA);
498
+ logger.debug("Created example schema: User.yaml");
499
+ }
500
+ const configContent = generateConfig(config);
501
+ (0, import_node_fs2.writeFileSync)(configPath, configContent);
502
+ logger.debug("Created omnify.config.ts");
251
503
  logger.newline();
252
- logger.info("Next steps:");
504
+ logger.success("Project initialized!");
505
+ logger.newline();
506
+ const toolName = config.migrationTool === "laravel" ? "Laravel" : config.migrationTool === "prisma" ? "Prisma" : config.migrationTool === "drizzle" ? "Drizzle" : "None";
507
+ logger.info("Configuration:");
253
508
  logger.list([
254
- "Edit omnify.config.ts to configure your database",
255
- "Add your schema files to the schemas/ directory",
256
- 'Run "omnify validate" to check your schemas',
257
- 'Run "omnify diff" to preview changes',
258
- 'Run "omnify generate" to create migrations and types'
509
+ `Database: ${config.database}`,
510
+ `Migration tool: ${toolName}`,
511
+ `TypeScript types: ${config.generateTypes ? "Yes" : "No"}`
259
512
  ]);
513
+ logger.newline();
514
+ logger.info("Files created:");
515
+ logger.list(["omnify.config.ts", `${config.schemasDir}/User.yaml`]);
516
+ logger.newline();
517
+ logger.info("Next steps:");
518
+ logger.newline();
519
+ logger.step("1. Set database URL in omnify.config.ts");
520
+ logger.newline();
521
+ logger.step("2. Define schemas in " + config.schemasDir + "/");
522
+ logger.newline();
523
+ logger.step("3. Generate:");
524
+ logger.info(" npx omnify validate");
525
+ logger.info(" npx omnify generate");
526
+ logger.newline();
260
527
  }
261
- function registerInitCommand(program2) {
262
- program2.command("init").description("Initialize a new omnify project").option("-f, --force", "Overwrite existing files").action(async (options) => {
528
+ function registerInitCommand(program) {
529
+ program.command("init").description("Initialize a new omnify project").option("-f, --force", "Overwrite existing files").option("-y, --yes", "Use default configuration (skip prompts)").action(async (options) => {
263
530
  try {
264
531
  await runInit(options);
265
532
  } catch (error) {
266
533
  if (error instanceof Error) {
534
+ if (error.message.includes("User force closed")) {
535
+ logger.newline();
536
+ logger.info("Setup cancelled.");
537
+ process.exit(0);
538
+ }
267
539
  logger.error(error.message);
268
540
  }
269
541
  process.exit(1);
@@ -274,161 +546,6 @@ function registerInitCommand(program2) {
274
546
  // src/commands/validate.ts
275
547
  var import_node_path3 = require("path");
276
548
  var import_omnify_core3 = require("@famgia/omnify-core");
277
-
278
- // src/config/loader.ts
279
- var import_node_fs2 = require("fs");
280
- var import_node_path2 = require("path");
281
- var import_jiti = require("jiti");
282
- var import_omnify_core2 = require("@famgia/omnify-core");
283
- var CONFIG_FILES = [
284
- "omnify.config.ts",
285
- "omnify.config.js",
286
- "omnify.config.mjs",
287
- "omnify.config.cjs"
288
- ];
289
- function findConfigFile(startDir) {
290
- const cwd = (0, import_node_path2.resolve)(startDir);
291
- for (const filename of CONFIG_FILES) {
292
- const configPath = (0, import_node_path2.resolve)(cwd, filename);
293
- if ((0, import_node_fs2.existsSync)(configPath)) {
294
- return configPath;
295
- }
296
- }
297
- return null;
298
- }
299
- async function loadConfigFile(configPath) {
300
- const jiti = (0, import_jiti.createJiti)(configPath, {
301
- interopDefault: true,
302
- moduleCache: false
303
- });
304
- try {
305
- const module2 = await jiti.import(configPath);
306
- const config = module2;
307
- if ("default" in config) {
308
- return config.default;
309
- }
310
- return config;
311
- } catch (error) {
312
- const message = error instanceof Error ? error.message : String(error);
313
- throw (0, import_omnify_core2.configError)(
314
- `Failed to load config file: ${message}. Check your omnify.config.ts for syntax errors.`,
315
- "E002"
316
- );
317
- }
318
- }
319
- async function resolvePlugins(plugins, configPath) {
320
- if (!plugins || plugins.length === 0) {
321
- return [];
322
- }
323
- const resolved = [];
324
- const configDir = configPath ? (0, import_node_path2.dirname)(configPath) : process.cwd();
325
- for (const plugin of plugins) {
326
- if (typeof plugin === "string") {
327
- const jiti = (0, import_jiti.createJiti)(configDir, {
328
- interopDefault: true,
329
- moduleCache: false
330
- });
331
- try {
332
- const module2 = await jiti.import(plugin);
333
- const loadedPlugin = module2.default ?? module2;
334
- resolved.push(loadedPlugin);
335
- } catch (error) {
336
- const message = error instanceof Error ? error.message : String(error);
337
- throw (0, import_omnify_core2.configError)(
338
- `Failed to load plugin '${plugin}': ${message}. Ensure the plugin is installed: npm install ${plugin}`,
339
- "E301"
340
- );
341
- }
342
- } else {
343
- resolved.push(plugin);
344
- }
345
- }
346
- return resolved;
347
- }
348
- async function resolveConfig(userConfig, configPath) {
349
- const plugins = await resolvePlugins(userConfig.plugins, configPath);
350
- const databaseConfig = {
351
- driver: userConfig.database.driver,
352
- enableFieldComments: userConfig.database.enableFieldComments ?? false
353
- };
354
- const database = userConfig.database.devUrl !== void 0 ? { ...databaseConfig, devUrl: userConfig.database.devUrl } : databaseConfig;
355
- const laravelConfig = {
356
- migrationsPath: userConfig.output?.laravel?.migrationsPath ?? "database/migrations"
357
- };
358
- const laravel = buildLaravelConfig(laravelConfig, userConfig.output?.laravel);
359
- const typescript = {
360
- path: userConfig.output?.typescript?.path ?? "types",
361
- singleFile: userConfig.output?.typescript?.singleFile ?? true,
362
- generateEnums: userConfig.output?.typescript?.generateEnums ?? true,
363
- generateRelationships: userConfig.output?.typescript?.generateRelationships ?? true
364
- };
365
- const result = {
366
- schemasDir: userConfig.schemasDir ?? "./schemas",
367
- database,
368
- output: {
369
- laravel,
370
- typescript
371
- },
372
- plugins,
373
- verbose: userConfig.verbose ?? false,
374
- lockFilePath: userConfig.lockFilePath ?? ".omnify.lock"
375
- };
376
- return result;
377
- }
378
- function buildLaravelConfig(base, userLaravel) {
379
- const config = { ...base };
380
- if (userLaravel?.modelsPath !== void 0) {
381
- config.modelsPath = userLaravel.modelsPath;
382
- }
383
- if (userLaravel?.modelsNamespace !== void 0) {
384
- config.modelsNamespace = userLaravel.modelsNamespace;
385
- }
386
- if (userLaravel?.factoriesPath !== void 0) {
387
- config.factoriesPath = userLaravel.factoriesPath;
388
- }
389
- if (userLaravel?.enumsPath !== void 0) {
390
- config.enumsPath = userLaravel.enumsPath;
391
- }
392
- if (userLaravel?.enumsNamespace !== void 0) {
393
- config.enumsNamespace = userLaravel.enumsNamespace;
394
- }
395
- return config;
396
- }
397
- function validateConfig(config, rootDir) {
398
- const schemaPath = (0, import_node_path2.resolve)(rootDir, config.schemasDir);
399
- if (!(0, import_node_fs2.existsSync)(schemaPath)) {
400
- throw (0, import_omnify_core2.configError)(
401
- `Schema directory not found: ${schemaPath}. Create the '${config.schemasDir}' directory or update schemasDir in config.`,
402
- "E002"
403
- );
404
- }
405
- }
406
- function requireDevUrl(config) {
407
- if (!config.database.devUrl) {
408
- throw (0, import_omnify_core2.configError)(
409
- `database.devUrl is required for diff and generate operations. Add devUrl to your database config, e.g., "mysql://root@localhost:3306/omnify_dev"`,
410
- "E003"
411
- );
412
- }
413
- }
414
- async function loadConfig(startDir = process.cwd()) {
415
- const cwd = (0, import_node_path2.resolve)(startDir);
416
- const configPath = findConfigFile(cwd);
417
- if (configPath) {
418
- const userConfig = await loadConfigFile(configPath);
419
- const config = await resolveConfig(userConfig, configPath);
420
- return {
421
- config,
422
- configPath
423
- };
424
- }
425
- throw (0, import_omnify_core2.configNotFoundError)((0, import_node_path2.resolve)(cwd, "omnify.config.ts"));
426
- }
427
- function defineConfig(config) {
428
- return config;
429
- }
430
-
431
- // src/commands/validate.ts
432
549
  async function runValidate(options) {
433
550
  logger.setVerbose(options.verbose ?? false);
434
551
  logger.header("Validating Schemas");
@@ -466,8 +583,8 @@ async function runValidate(options) {
466
583
  process.exit(2);
467
584
  }
468
585
  }
469
- function registerValidateCommand(program2) {
470
- program2.command("validate").description("Validate schema files").option("-v, --verbose", "Show detailed output").action(async (options) => {
586
+ function registerValidateCommand(program) {
587
+ program.command("validate").description("Validate schema files").option("-v, --verbose", "Show detailed output").action(async (options) => {
471
588
  try {
472
589
  await runValidate(options);
473
590
  } catch (error) {
@@ -567,8 +684,8 @@ async function runDiff(options) {
567
684
  logger.newline();
568
685
  logger.info('Run "omnify generate" to create migrations');
569
686
  }
570
- function registerDiffCommand(program2) {
571
- program2.command("diff").description("Show pending schema changes").option("-v, --verbose", "Show detailed output").option("--check", "Exit with code 1 if changes exist (for CI)").action(async (options) => {
687
+ function registerDiffCommand(program) {
688
+ program.command("diff").description("Show pending schema changes").option("-v, --verbose", "Show detailed output").option("--check", "Exit with code 1 if changes exist (for CI)").action(async (options) => {
572
689
  try {
573
690
  await runDiff(options);
574
691
  } catch (error) {
@@ -590,6 +707,88 @@ var import_node_path5 = require("path");
590
707
  var import_omnify_core5 = require("@famgia/omnify-core");
591
708
  var import_omnify_atlas2 = require("@famgia/omnify-atlas");
592
709
  var import_omnify_laravel = require("@famgia/omnify-laravel");
710
+ function hasPluginGenerators(plugins) {
711
+ return plugins.some((p) => p.generators && p.generators.length > 0);
712
+ }
713
+ function writeGeneratorOutputs(outputs, rootDir) {
714
+ const counts = { migrations: 0, types: 0, other: 0 };
715
+ for (const output of outputs) {
716
+ const filePath = (0, import_node_path5.resolve)(rootDir, output.path);
717
+ const dir = (0, import_node_path5.dirname)(filePath);
718
+ if (!(0, import_node_fs3.existsSync)(dir)) {
719
+ (0, import_node_fs3.mkdirSync)(dir, { recursive: true });
720
+ logger.debug(`Created directory: ${dir}`);
721
+ }
722
+ (0, import_node_fs3.writeFileSync)(filePath, output.content);
723
+ logger.debug(`Created: ${output.path}`);
724
+ if (output.type === "migration") counts.migrations++;
725
+ else if (output.type === "type") counts.types++;
726
+ else counts.other++;
727
+ }
728
+ return counts;
729
+ }
730
+ async function runPluginGeneration(plugins, schemas, rootDir, verbose) {
731
+ const pluginManager = new import_omnify_core5.PluginManager({
732
+ cwd: rootDir,
733
+ verbose,
734
+ logger: {
735
+ debug: (msg) => logger.debug(msg),
736
+ info: (msg) => logger.info(msg),
737
+ warn: (msg) => logger.warn(msg),
738
+ error: (msg) => logger.error(msg)
739
+ }
740
+ });
741
+ for (const plugin of plugins) {
742
+ await pluginManager.register(plugin);
743
+ }
744
+ const result = await pluginManager.runGenerators(schemas);
745
+ if (!result.success) {
746
+ for (const error of result.errors) {
747
+ logger.error(`Generator ${error.generatorName} failed: ${error.message}`);
748
+ }
749
+ throw new Error("Generator execution failed");
750
+ }
751
+ return writeGeneratorOutputs(result.outputs, rootDir);
752
+ }
753
+ function runDirectGeneration(schemas, config, rootDir, options) {
754
+ let migrationsGenerated = 0;
755
+ let typesGenerated = 0;
756
+ if (!options.typesOnly && config.output.laravel) {
757
+ logger.step("Generating Laravel migrations...");
758
+ const migrationsDir = (0, import_node_path5.resolve)(rootDir, config.output.laravel.migrationsPath);
759
+ if (!(0, import_node_fs3.existsSync)(migrationsDir)) {
760
+ (0, import_node_fs3.mkdirSync)(migrationsDir, { recursive: true });
761
+ logger.debug(`Created directory: ${migrationsDir}`);
762
+ }
763
+ const migrations = (0, import_omnify_laravel.generateMigrations)(schemas);
764
+ for (const migration of migrations) {
765
+ const filePath = (0, import_node_path5.resolve)(migrationsDir, migration.fileName);
766
+ (0, import_node_fs3.writeFileSync)(filePath, migration.content);
767
+ logger.debug(`Created: ${migration.fileName}`);
768
+ migrationsGenerated++;
769
+ }
770
+ logger.success(`Generated ${migrationsGenerated} migration(s)`);
771
+ }
772
+ if (!options.migrationsOnly && config.output.typescript) {
773
+ logger.step("Generating TypeScript types...");
774
+ const typesDir = (0, import_node_path5.resolve)(rootDir, config.output.typescript.path);
775
+ if (!(0, import_node_fs3.existsSync)(typesDir)) {
776
+ (0, import_node_fs3.mkdirSync)(typesDir, { recursive: true });
777
+ logger.debug(`Created directory: ${typesDir}`);
778
+ }
779
+ const typeFiles = (0, import_omnify_laravel.generateTypeScript)(schemas, {
780
+ singleFile: config.output.typescript.singleFile
781
+ });
782
+ for (const file of typeFiles) {
783
+ const filePath = (0, import_node_path5.resolve)(typesDir, file.fileName);
784
+ (0, import_node_fs3.writeFileSync)(filePath, file.content);
785
+ logger.debug(`Created: ${file.fileName}`);
786
+ typesGenerated++;
787
+ }
788
+ logger.success(`Generated ${typesGenerated} TypeScript file(s)`);
789
+ }
790
+ return { migrations: migrationsGenerated, types: typesGenerated };
791
+ }
593
792
  async function runGenerate(options) {
594
793
  logger.setVerbose(options.verbose ?? false);
595
794
  logger.header("Generating Outputs");
@@ -632,54 +831,48 @@ async function runGenerate(options) {
632
831
  }
633
832
  let migrationsGenerated = 0;
634
833
  let typesGenerated = 0;
635
- if (!options.typesOnly) {
636
- logger.step("Generating Laravel migrations...");
637
- const migrationsDir = (0, import_node_path5.resolve)(rootDir, config.output.laravel.migrationsPath);
638
- if (!(0, import_node_fs3.existsSync)(migrationsDir)) {
639
- (0, import_node_fs3.mkdirSync)(migrationsDir, { recursive: true });
640
- logger.debug(`Created directory: ${migrationsDir}`);
641
- }
642
- const migrations = (0, import_omnify_laravel.generateMigrations)(schemas);
643
- for (const migration of migrations) {
644
- const filePath = (0, import_node_path5.resolve)(migrationsDir, migration.fileName);
645
- (0, import_node_fs3.writeFileSync)(filePath, migration.content);
646
- logger.debug(`Created: ${migration.fileName}`);
647
- migrationsGenerated++;
834
+ const usePlugins = hasPluginGenerators(config.plugins);
835
+ if (usePlugins) {
836
+ logger.step("Running plugin generators...");
837
+ const counts = await runPluginGeneration(
838
+ config.plugins,
839
+ schemas,
840
+ rootDir,
841
+ options.verbose ?? false
842
+ );
843
+ migrationsGenerated = counts.migrations;
844
+ typesGenerated = counts.types;
845
+ if (counts.migrations > 0) {
846
+ logger.success(`Generated ${counts.migrations} migration(s)`);
648
847
  }
649
- logger.success(`Generated ${migrationsGenerated} migration(s)`);
650
- }
651
- if (!options.migrationsOnly) {
652
- logger.step("Generating TypeScript types...");
653
- const typesDir = (0, import_node_path5.resolve)(rootDir, config.output.typescript.path);
654
- if (!(0, import_node_fs3.existsSync)(typesDir)) {
655
- (0, import_node_fs3.mkdirSync)(typesDir, { recursive: true });
656
- logger.debug(`Created directory: ${typesDir}`);
848
+ if (counts.types > 0) {
849
+ logger.success(`Generated ${counts.types} TypeScript file(s)`);
657
850
  }
658
- const typeFiles = (0, import_omnify_laravel.generateTypeScript)(schemas, {
659
- singleFile: config.output.typescript.singleFile
660
- });
661
- for (const file of typeFiles) {
662
- const filePath = (0, import_node_path5.resolve)(typesDir, file.fileName);
663
- (0, import_node_fs3.writeFileSync)(filePath, file.content);
664
- logger.debug(`Created: ${file.fileName}`);
665
- typesGenerated++;
851
+ if (counts.other > 0) {
852
+ logger.success(`Generated ${counts.other} other file(s)`);
666
853
  }
667
- logger.success(`Generated ${typesGenerated} TypeScript file(s)`);
854
+ } else {
855
+ const counts = runDirectGeneration(schemas, config, rootDir, options);
856
+ migrationsGenerated = counts.migrations;
857
+ typesGenerated = counts.types;
668
858
  }
669
859
  logger.step("Updating lock file...");
670
- await (0, import_omnify_atlas2.updateLockFile)(lockPath, schemas);
860
+ const existingLock = await (0, import_omnify_atlas2.readLockFile)(lockPath);
861
+ const schemaHashes = await (0, import_omnify_atlas2.buildSchemaHashes)(schemas);
862
+ const newLockFile = (0, import_omnify_atlas2.updateLockFile)(existingLock, schemaHashes, config.database.driver);
863
+ await (0, import_omnify_atlas2.writeLockFile)(lockPath, newLockFile);
671
864
  logger.debug(`Updated: ${config.lockFilePath}`);
672
865
  logger.newline();
673
866
  logger.success("Generation complete!");
674
- if (migrationsGenerated > 0) {
867
+ if (migrationsGenerated > 0 && config.output.laravel) {
675
868
  logger.info(` Migrations: ${config.output.laravel.migrationsPath}/`);
676
869
  }
677
- if (typesGenerated > 0) {
870
+ if (typesGenerated > 0 && config.output.typescript) {
678
871
  logger.info(` Types: ${config.output.typescript.path}/`);
679
872
  }
680
873
  }
681
- function registerGenerateCommand(program2) {
682
- program2.command("generate").description("Generate Laravel migrations and TypeScript types").option("-v, --verbose", "Show detailed output").option("--migrations-only", "Only generate migrations").option("--types-only", "Only generate TypeScript types").option("-f, --force", "Generate even if no changes detected").action(async (options) => {
874
+ function registerGenerateCommand(program) {
875
+ program.command("generate").description("Generate Laravel migrations and TypeScript types").option("-v, --verbose", "Show detailed output").option("--migrations-only", "Only generate migrations").option("--types-only", "Only generate TypeScript types").option("-f, --force", "Generate even if no changes detected").action(async (options) => {
683
876
  try {
684
877
  await runGenerate(options);
685
878
  } catch (error) {
@@ -694,39 +887,15 @@ function registerGenerateCommand(program2) {
694
887
  }
695
888
  });
696
889
  }
697
-
698
- // src/index.ts
699
- var VERSION = "0.0.1";
700
- var program = new import_commander.Command();
701
- program.name("omnify").description("Schema-first database migrations for Laravel and TypeScript").version(VERSION);
702
- registerInitCommand(program);
703
- registerValidateCommand(program);
704
- registerDiffCommand(program);
705
- registerGenerateCommand(program);
706
- process.on("uncaughtException", (error) => {
707
- if (error instanceof import_omnify_core6.OmnifyError) {
708
- logger.formatError(error);
709
- process.exit(logger.getExitCode(error));
710
- } else {
711
- logger.error(error.message);
712
- process.exit(1);
713
- }
714
- });
715
- process.on("unhandledRejection", (reason) => {
716
- if (reason instanceof import_omnify_core6.OmnifyError) {
717
- logger.formatError(reason);
718
- process.exit(logger.getExitCode(reason));
719
- } else if (reason instanceof Error) {
720
- logger.error(reason.message);
721
- } else {
722
- logger.error(String(reason));
723
- }
724
- process.exit(1);
725
- });
726
- program.parse();
727
890
  // Annotate the CommonJS export names for ESM import in node:
728
891
  0 && (module.exports = {
729
892
  defineConfig,
730
- loadConfig
893
+ loadConfig,
894
+ logger,
895
+ registerDiffCommand,
896
+ registerGenerateCommand,
897
+ registerInitCommand,
898
+ registerValidateCommand,
899
+ runInit
731
900
  });
732
901
  //# sourceMappingURL=index.cjs.map