@famgia/omnify-cli 2.0.10 → 2.0.12

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
@@ -30,14 +30,20 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // src/index.ts
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
+ VERSION_LOCK_FILE: () => VERSION_LOCK_FILE,
34
+ checkPluginVersions: () => checkPluginVersions,
33
35
  defineConfig: () => defineConfig,
36
+ getCliVersion: () => getCliVersion,
34
37
  loadConfig: () => loadConfig,
35
38
  logger: () => logger,
39
+ readVersionLock: () => readVersionLock,
36
40
  registerDiffCommand: () => registerDiffCommand,
37
41
  registerGenerateCommand: () => registerGenerateCommand,
38
42
  registerInitCommand: () => registerInitCommand,
39
43
  registerValidateCommand: () => registerValidateCommand,
40
- runInit: () => runInit
44
+ runInit: () => runInit,
45
+ updateVersionLock: () => updateVersionLock,
46
+ writeVersionLock: () => writeVersionLock
41
47
  });
42
48
  module.exports = __toCommonJS(index_exports);
43
49
 
@@ -1135,8 +1141,8 @@ function registerDiffCommand(program) {
1135
1141
  }
1136
1142
 
1137
1143
  // src/commands/generate.ts
1138
- var import_node_fs8 = require("fs");
1139
- var import_node_path8 = require("path");
1144
+ var import_node_fs9 = require("fs");
1145
+ var import_node_path9 = require("path");
1140
1146
  var import_omnify_core5 = require("@famgia/omnify-core");
1141
1147
  var import_omnify_atlas2 = require("@famgia/omnify-atlas");
1142
1148
  var import_omnify_laravel = require("@famgia/omnify-laravel");
@@ -1145,17 +1151,19 @@ var import_omnify_typescript = require("@famgia/omnify-typescript");
1145
1151
  // src/guides/index.ts
1146
1152
  var import_node_fs7 = require("fs");
1147
1153
  var import_node_path7 = require("path");
1148
- var import_node_url = require("url");
1149
- var CLAUDE_MD = `# Omnify Project
1154
+ var OMNIFY_SECTION_START = "<!-- OMNIFY_SECTION_START -->";
1155
+ var OMNIFY_SECTION_END = "<!-- OMNIFY_SECTION_END -->";
1156
+ var OMNIFY_SECTION = `${OMNIFY_SECTION_START}
1157
+ ## Omnify Schema System
1150
1158
 
1151
1159
  This project uses **Omnify** for schema-driven code generation.
1152
1160
 
1153
- ## Quick Reference
1161
+ ### Quick Reference
1154
1162
 
1155
1163
  - **Schema Guide**: @.claude/omnify/guides/omnify/schema-guide.md
1156
1164
  - **Config Guide**: @.claude/omnify/guides/omnify/config-guide.md
1157
1165
 
1158
- ## Commands
1166
+ ### Commands
1159
1167
 
1160
1168
  \`\`\`bash
1161
1169
  npx omnify generate # Generate code from schemas
@@ -1163,41 +1171,52 @@ npx omnify validate # Validate schemas
1163
1171
  php artisan migrate # Run database migrations
1164
1172
  \`\`\`
1165
1173
 
1166
- ## Critical Rules
1174
+ ### Critical Rules
1167
1175
 
1168
- ### \u26D4 DO NOT EDIT Auto-Generated Files
1176
+ #### \u26D4 DO NOT EDIT Auto-Generated Files
1169
1177
  - \`database/migrations/omnify/**\` - Regenerated on \`npx omnify generate\`
1170
1178
  - \`app/Models/OmnifyBase/**\` - Base models (extend, don't edit)
1171
1179
  - \`app/Http/Requests/OmnifyBase/**\` - Base requests
1172
1180
  - \`app/Http/Resources/OmnifyBase/**\` - Base resources
1173
1181
 
1174
- ### \u2705 Schema-First Workflow
1182
+ #### \u2705 Schema-First Workflow
1175
1183
  1. Edit YAML schema in \`schemas/\`
1176
1184
  2. Run \`npx omnify generate\`
1177
1185
  3. Run \`php artisan migrate\`
1178
1186
 
1179
1187
  **NEVER use \`php artisan make:migration\`** - Always use schemas!
1188
+ ${OMNIFY_SECTION_END}`;
1189
+ function updateClaudeMd(rootDir) {
1190
+ const claudeMdPath = (0, import_node_path7.resolve)(rootDir, "CLAUDE.md");
1191
+ if (!(0, import_node_fs7.existsSync)(claudeMdPath)) {
1192
+ (0, import_node_fs7.writeFileSync)(claudeMdPath, `# Project Documentation
1180
1193
 
1181
- ## Documentation Structure
1182
-
1183
- \`\`\`
1184
- .claude/
1185
- \u251C\u2500\u2500 CLAUDE.md # This file (root pointer)
1186
- \u251C\u2500\u2500 rules/ # Claude Code rules (path-specific)
1187
- \u2502 \u2514\u2500\u2500 omnify/*.md
1188
- \u2514\u2500\u2500 omnify/ # Detailed guides
1189
- \u251C\u2500\u2500 guides/
1190
- \u2502 \u251C\u2500\u2500 omnify/ # Schema & config docs
1191
- \u2502 \u251C\u2500\u2500 laravel/ # Laravel patterns
1192
- \u2502 \u2514\u2500\u2500 react/ # React patterns
1193
- \u251C\u2500\u2500 workflows/ # Step-by-step workflows
1194
- \u2514\u2500\u2500 agents/ # AI agent prompts
1195
- \`\`\`
1196
-
1197
- ## Individual Preferences
1198
-
1199
- Add your personal preferences in \`CLAUDE.local.md\` (gitignored).
1200
- `;
1194
+ ${OMNIFY_SECTION}
1195
+ `);
1196
+ return true;
1197
+ }
1198
+ const currentContent = (0, import_node_fs7.readFileSync)(claudeMdPath, "utf8");
1199
+ const hasOmnifySection = currentContent.includes(OMNIFY_SECTION_START);
1200
+ if (hasOmnifySection) {
1201
+ const regex = new RegExp(
1202
+ `${escapeRegExp(OMNIFY_SECTION_START)}[\\s\\S]*?${escapeRegExp(OMNIFY_SECTION_END)}`,
1203
+ "g"
1204
+ );
1205
+ const newContent = currentContent.replace(regex, OMNIFY_SECTION);
1206
+ if (newContent !== currentContent) {
1207
+ (0, import_node_fs7.writeFileSync)(claudeMdPath, newContent);
1208
+ return true;
1209
+ }
1210
+ return false;
1211
+ } else {
1212
+ const newContent = currentContent.trimEnd() + "\n\n" + OMNIFY_SECTION + "\n";
1213
+ (0, import_node_fs7.writeFileSync)(claudeMdPath, newContent);
1214
+ return true;
1215
+ }
1216
+ }
1217
+ function escapeRegExp(string) {
1218
+ return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
1219
+ }
1201
1220
  function copyOmnifyGuides(rootDir) {
1202
1221
  let filesWritten = 0;
1203
1222
  const omnifyPkgPaths = [
@@ -1252,24 +1271,146 @@ function copyOmnifyGuides(rootDir) {
1252
1271
  }
1253
1272
  function generateAIGuides(rootDir, _plugins) {
1254
1273
  let filesWritten = 0;
1255
- const claudeMdPath = (0, import_node_path7.resolve)(rootDir, "CLAUDE.md");
1256
- (0, import_node_fs7.writeFileSync)(claudeMdPath, CLAUDE_MD);
1257
- filesWritten++;
1274
+ if (updateClaudeMd(rootDir)) {
1275
+ filesWritten++;
1276
+ }
1258
1277
  filesWritten += copyOmnifyGuides(rootDir);
1259
1278
  return filesWritten;
1260
1279
  }
1261
1280
 
1281
+ // src/version-lock/index.ts
1282
+ var import_node_fs8 = require("fs");
1283
+ var import_node_path8 = require("path");
1284
+ var import_meta = {};
1285
+ var VERSION_LOCK_FILE = ".omnify-versions.lock";
1286
+ function readVersionLock(rootDir) {
1287
+ const lockPath = (0, import_node_path8.resolve)(rootDir, VERSION_LOCK_FILE);
1288
+ if (!(0, import_node_fs8.existsSync)(lockPath)) {
1289
+ return null;
1290
+ }
1291
+ try {
1292
+ const content = (0, import_node_fs8.readFileSync)(lockPath, "utf-8");
1293
+ return JSON.parse(content);
1294
+ } catch {
1295
+ return null;
1296
+ }
1297
+ }
1298
+ function writeVersionLock(rootDir, lock) {
1299
+ const lockPath = (0, import_node_path8.resolve)(rootDir, VERSION_LOCK_FILE);
1300
+ const content = JSON.stringify(lock, null, 2);
1301
+ (0, import_node_fs8.writeFileSync)(lockPath, content + "\n");
1302
+ }
1303
+ function parseVersion(version) {
1304
+ const cleanVersion = version.replace(/^v/, "");
1305
+ const match = cleanVersion.match(/^(\d+)\.(\d+)\.(\d+)/);
1306
+ if (!match) {
1307
+ return null;
1308
+ }
1309
+ return {
1310
+ major: parseInt(match[1], 10),
1311
+ minor: parseInt(match[2], 10),
1312
+ patch: parseInt(match[3], 10)
1313
+ };
1314
+ }
1315
+ function compareVersions(a, b) {
1316
+ const parsedA = parseVersion(a);
1317
+ const parsedB = parseVersion(b);
1318
+ if (!parsedA || !parsedB) {
1319
+ return 0;
1320
+ }
1321
+ if (parsedA.major !== parsedB.major) {
1322
+ return parsedA.major > parsedB.major ? 1 : -1;
1323
+ }
1324
+ if (parsedA.minor !== parsedB.minor) {
1325
+ return parsedA.minor > parsedB.minor ? 1 : -1;
1326
+ }
1327
+ if (parsedA.patch !== parsedB.patch) {
1328
+ return parsedA.patch > parsedB.patch ? 1 : -1;
1329
+ }
1330
+ return 0;
1331
+ }
1332
+ function checkPluginVersions(plugins, lockFile) {
1333
+ const mismatches = [];
1334
+ const newPlugins = [];
1335
+ const lockedVersions = /* @__PURE__ */ new Map();
1336
+ for (const entry of lockFile.plugins) {
1337
+ lockedVersions.set(entry.name, entry.version);
1338
+ }
1339
+ for (const plugin of plugins) {
1340
+ const lockedVersion = lockedVersions.get(plugin.name);
1341
+ if (!lockedVersion) {
1342
+ newPlugins.push(plugin.name);
1343
+ continue;
1344
+ }
1345
+ const comparison = compareVersions(plugin.version, lockedVersion);
1346
+ if (comparison < 0) {
1347
+ mismatches.push({
1348
+ name: plugin.name,
1349
+ required: lockedVersion,
1350
+ installed: plugin.version
1351
+ });
1352
+ }
1353
+ }
1354
+ return {
1355
+ valid: mismatches.length === 0,
1356
+ mismatches,
1357
+ newPlugins
1358
+ };
1359
+ }
1360
+ function updateVersionLock(rootDir, plugins, cliVersion) {
1361
+ const now = (/* @__PURE__ */ new Date()).toISOString();
1362
+ const existingLock = readVersionLock(rootDir);
1363
+ const existingEntries = /* @__PURE__ */ new Map();
1364
+ if (existingLock) {
1365
+ for (const entry of existingLock.plugins) {
1366
+ existingEntries.set(entry.name, entry);
1367
+ }
1368
+ }
1369
+ const pluginEntries = [];
1370
+ for (const plugin of plugins) {
1371
+ const existing = existingEntries.get(plugin.name);
1372
+ if (!existing || compareVersions(plugin.version, existing.version) > 0) {
1373
+ pluginEntries.push({
1374
+ name: plugin.name,
1375
+ version: plugin.version,
1376
+ updatedAt: now
1377
+ });
1378
+ } else {
1379
+ pluginEntries.push(existing);
1380
+ }
1381
+ }
1382
+ pluginEntries.sort((a, b) => a.name.localeCompare(b.name));
1383
+ const lock = {
1384
+ version: 1,
1385
+ cliVersion,
1386
+ plugins: pluginEntries,
1387
+ updatedAt: now
1388
+ };
1389
+ writeVersionLock(rootDir, lock);
1390
+ return lock;
1391
+ }
1392
+ function getCliVersion() {
1393
+ try {
1394
+ const pkgPath = new URL("../../package.json", import_meta.url);
1395
+ const pkgContent = (0, import_node_fs8.readFileSync)(pkgPath, "utf-8");
1396
+ const pkg = JSON.parse(pkgContent);
1397
+ return pkg.version;
1398
+ } catch {
1399
+ return "unknown";
1400
+ }
1401
+ }
1402
+
1262
1403
  // src/commands/generate.ts
1263
1404
  function hasPluginGenerators(plugins) {
1264
1405
  return plugins.some((p) => p.generators && p.generators.length > 0);
1265
1406
  }
1266
1407
  function getExistingMigrationTables(migrationsDir) {
1267
1408
  const existingTables = /* @__PURE__ */ new Set();
1268
- if (!(0, import_node_fs8.existsSync)(migrationsDir)) {
1409
+ if (!(0, import_node_fs9.existsSync)(migrationsDir)) {
1269
1410
  return existingTables;
1270
1411
  }
1271
1412
  try {
1272
- const files = (0, import_node_fs8.readdirSync)(migrationsDir);
1413
+ const files = (0, import_node_fs9.readdirSync)(migrationsDir);
1273
1414
  const createMigrationPattern = /^\d{4}_\d{2}_\d{2}_\d{6}_create_(.+)_table\.php$/;
1274
1415
  for (const file of files) {
1275
1416
  const match = file.match(createMigrationPattern);
@@ -1458,17 +1599,17 @@ function schemaChangeToVersionChange(change) {
1458
1599
  function writeGeneratorOutputs(outputs, rootDir) {
1459
1600
  const counts = { migrations: 0, types: 0, models: 0, factories: 0, other: 0 };
1460
1601
  for (const output of outputs) {
1461
- const filePath = (0, import_node_path8.resolve)(rootDir, output.path);
1462
- const dir = (0, import_node_path8.dirname)(filePath);
1463
- if (!(0, import_node_fs8.existsSync)(dir)) {
1464
- (0, import_node_fs8.mkdirSync)(dir, { recursive: true });
1602
+ const filePath = (0, import_node_path9.resolve)(rootDir, output.path);
1603
+ const dir = (0, import_node_path9.dirname)(filePath);
1604
+ if (!(0, import_node_fs9.existsSync)(dir)) {
1605
+ (0, import_node_fs9.mkdirSync)(dir, { recursive: true });
1465
1606
  logger.debug(`Created directory: ${dir}`);
1466
1607
  }
1467
- if (output.skipIfExists && (0, import_node_fs8.existsSync)(filePath)) {
1608
+ if (output.skipIfExists && (0, import_node_fs9.existsSync)(filePath)) {
1468
1609
  logger.debug(`Skipped (exists): ${output.path}`);
1469
1610
  continue;
1470
1611
  }
1471
- (0, import_node_fs8.writeFileSync)(filePath, output.content);
1612
+ (0, import_node_fs9.writeFileSync)(filePath, output.content);
1472
1613
  logger.debug(`Created: ${output.path}`);
1473
1614
  if (output.type === "migration") counts.migrations++;
1474
1615
  else if (output.type === "type") counts.types++;
@@ -1478,7 +1619,7 @@ function writeGeneratorOutputs(outputs, rootDir) {
1478
1619
  }
1479
1620
  return counts;
1480
1621
  }
1481
- async function runPluginGeneration(plugins, schemas, rootDir, verbose, changes) {
1622
+ async function runPluginGeneration(plugins, schemas, rootDir, verbose, changes, localeConfig) {
1482
1623
  const pluginManager = new import_omnify_core5.PluginManager({
1483
1624
  cwd: rootDir,
1484
1625
  verbose,
@@ -1487,7 +1628,8 @@ async function runPluginGeneration(plugins, schemas, rootDir, verbose, changes)
1487
1628
  info: (msg) => logger.info(msg),
1488
1629
  warn: (msg) => logger.warn(msg),
1489
1630
  error: (msg) => logger.error(msg)
1490
- }
1631
+ },
1632
+ localeConfig
1491
1633
  });
1492
1634
  for (const plugin of plugins) {
1493
1635
  await pluginManager.register(plugin);
@@ -1524,9 +1666,9 @@ function runDirectGeneration(schemas, config, rootDir, options, changes) {
1524
1666
  }
1525
1667
  if (!options.typesOnly && config.output.laravel) {
1526
1668
  logger.step("Generating Laravel migrations...");
1527
- const migrationsDir = (0, import_node_path8.resolve)(rootDir, config.output.laravel.migrationsPath);
1528
- if (!(0, import_node_fs8.existsSync)(migrationsDir)) {
1529
- (0, import_node_fs8.mkdirSync)(migrationsDir, { recursive: true });
1669
+ const migrationsDir = (0, import_node_path9.resolve)(rootDir, config.output.laravel.migrationsPath);
1670
+ if (!(0, import_node_fs9.existsSync)(migrationsDir)) {
1671
+ (0, import_node_fs9.mkdirSync)(migrationsDir, { recursive: true });
1530
1672
  logger.debug(`Created directory: ${migrationsDir}`);
1531
1673
  }
1532
1674
  const addedSchemaNames = new Set(
@@ -1547,8 +1689,8 @@ function runDirectGeneration(schemas, config, rootDir, options, changes) {
1547
1689
  logger.debug(`Skipped CREATE for ${tableName} (already exists)`);
1548
1690
  continue;
1549
1691
  }
1550
- const filePath = (0, import_node_path8.resolve)(migrationsDir, migration.fileName);
1551
- (0, import_node_fs8.writeFileSync)(filePath, migration.content);
1692
+ const filePath = (0, import_node_path9.resolve)(migrationsDir, migration.fileName);
1693
+ (0, import_node_fs9.writeFileSync)(filePath, migration.content);
1552
1694
  logger.debug(`Created: ${migration.fileName}`);
1553
1695
  migrationsGenerated++;
1554
1696
  }
@@ -1556,8 +1698,8 @@ function runDirectGeneration(schemas, config, rootDir, options, changes) {
1556
1698
  if (alterChanges.length > 0) {
1557
1699
  const alterMigrations = (0, import_omnify_laravel.generateMigrationsFromChanges)(alterChanges);
1558
1700
  for (const migration of alterMigrations) {
1559
- const filePath = (0, import_node_path8.resolve)(migrationsDir, migration.fileName);
1560
- (0, import_node_fs8.writeFileSync)(filePath, migration.content);
1701
+ const filePath = (0, import_node_path9.resolve)(migrationsDir, migration.fileName);
1702
+ (0, import_node_fs9.writeFileSync)(filePath, migration.content);
1561
1703
  logger.debug(`Created: ${migration.fileName}`);
1562
1704
  migrationsGenerated++;
1563
1705
  }
@@ -1568,13 +1710,13 @@ function runDirectGeneration(schemas, config, rootDir, options, changes) {
1568
1710
  logger.step("Generating Laravel models...");
1569
1711
  const modelsPath = config.output.laravel.modelsPath;
1570
1712
  const baseModelsPath = config.output.laravel.baseModelsPath ?? `${modelsPath}/OmnifyBase`;
1571
- const modelsDir = (0, import_node_path8.resolve)(rootDir, modelsPath);
1572
- const baseModelsDir = (0, import_node_path8.resolve)(rootDir, baseModelsPath);
1573
- if (!(0, import_node_fs8.existsSync)(modelsDir)) {
1574
- (0, import_node_fs8.mkdirSync)(modelsDir, { recursive: true });
1713
+ const modelsDir = (0, import_node_path9.resolve)(rootDir, modelsPath);
1714
+ const baseModelsDir = (0, import_node_path9.resolve)(rootDir, baseModelsPath);
1715
+ if (!(0, import_node_fs9.existsSync)(modelsDir)) {
1716
+ (0, import_node_fs9.mkdirSync)(modelsDir, { recursive: true });
1575
1717
  }
1576
- if (!(0, import_node_fs8.existsSync)(baseModelsDir)) {
1577
- (0, import_node_fs8.mkdirSync)(baseModelsDir, { recursive: true });
1718
+ if (!(0, import_node_fs9.existsSync)(baseModelsDir)) {
1719
+ (0, import_node_fs9.mkdirSync)(baseModelsDir, { recursive: true });
1578
1720
  }
1579
1721
  const providersPath = config.output.laravel.providersPath ?? "app/Providers";
1580
1722
  const models = (0, import_omnify_laravel.generateModels)(schemas, {
@@ -1584,16 +1726,16 @@ function runDirectGeneration(schemas, config, rootDir, options, changes) {
1584
1726
  customTypes: customTypesMap
1585
1727
  });
1586
1728
  for (const model of models) {
1587
- const filePath = (0, import_node_path8.resolve)(rootDir, (0, import_omnify_laravel.getModelPath)(model));
1588
- const fileDir = (0, import_node_path8.dirname)(filePath);
1589
- if (!(0, import_node_fs8.existsSync)(fileDir)) {
1590
- (0, import_node_fs8.mkdirSync)(fileDir, { recursive: true });
1729
+ const filePath = (0, import_node_path9.resolve)(rootDir, (0, import_omnify_laravel.getModelPath)(model));
1730
+ const fileDir = (0, import_node_path9.dirname)(filePath);
1731
+ if (!(0, import_node_fs9.existsSync)(fileDir)) {
1732
+ (0, import_node_fs9.mkdirSync)(fileDir, { recursive: true });
1591
1733
  }
1592
- if (!model.overwrite && (0, import_node_fs8.existsSync)(filePath)) {
1734
+ if (!model.overwrite && (0, import_node_fs9.existsSync)(filePath)) {
1593
1735
  logger.debug(`Skipped (exists): ${(0, import_omnify_laravel.getModelPath)(model)}`);
1594
1736
  continue;
1595
1737
  }
1596
- (0, import_node_fs8.writeFileSync)(filePath, model.content);
1738
+ (0, import_node_fs9.writeFileSync)(filePath, model.content);
1597
1739
  logger.debug(`Created: ${(0, import_omnify_laravel.getModelPath)(model)}`);
1598
1740
  modelsGenerated++;
1599
1741
  }
@@ -1602,24 +1744,24 @@ function runDirectGeneration(schemas, config, rootDir, options, changes) {
1602
1744
  if (!options.typesOnly && config.output.laravel?.factoriesPath) {
1603
1745
  logger.step("Generating Laravel factories...");
1604
1746
  const factoriesPath = config.output.laravel.factoriesPath;
1605
- const factoriesDir = (0, import_node_path8.resolve)(rootDir, factoriesPath);
1606
- if (!(0, import_node_fs8.existsSync)(factoriesDir)) {
1607
- (0, import_node_fs8.mkdirSync)(factoriesDir, { recursive: true });
1747
+ const factoriesDir = (0, import_node_path9.resolve)(rootDir, factoriesPath);
1748
+ if (!(0, import_node_fs9.existsSync)(factoriesDir)) {
1749
+ (0, import_node_fs9.mkdirSync)(factoriesDir, { recursive: true });
1608
1750
  }
1609
1751
  const factories = (0, import_omnify_laravel.generateFactories)(schemas, {
1610
1752
  factoryPath: factoriesPath
1611
1753
  });
1612
1754
  for (const factory of factories) {
1613
- const filePath = (0, import_node_path8.resolve)(rootDir, (0, import_omnify_laravel.getFactoryPath)(factory));
1614
- const fileDir = (0, import_node_path8.dirname)(filePath);
1615
- if (!(0, import_node_fs8.existsSync)(fileDir)) {
1616
- (0, import_node_fs8.mkdirSync)(fileDir, { recursive: true });
1755
+ const filePath = (0, import_node_path9.resolve)(rootDir, (0, import_omnify_laravel.getFactoryPath)(factory));
1756
+ const fileDir = (0, import_node_path9.dirname)(filePath);
1757
+ if (!(0, import_node_fs9.existsSync)(fileDir)) {
1758
+ (0, import_node_fs9.mkdirSync)(fileDir, { recursive: true });
1617
1759
  }
1618
- if (!factory.overwrite && (0, import_node_fs8.existsSync)(filePath)) {
1760
+ if (!factory.overwrite && (0, import_node_fs9.existsSync)(filePath)) {
1619
1761
  logger.debug(`Skipped (exists): ${(0, import_omnify_laravel.getFactoryPath)(factory)}`);
1620
1762
  continue;
1621
1763
  }
1622
- (0, import_node_fs8.writeFileSync)(filePath, factory.content);
1764
+ (0, import_node_fs9.writeFileSync)(filePath, factory.content);
1623
1765
  logger.debug(`Created: ${(0, import_omnify_laravel.getFactoryPath)(factory)}`);
1624
1766
  factoriesGenerated++;
1625
1767
  }
@@ -1628,32 +1770,32 @@ function runDirectGeneration(schemas, config, rootDir, options, changes) {
1628
1770
  if (!options.migrationsOnly && config.output.typescript) {
1629
1771
  logger.step("Generating TypeScript types...");
1630
1772
  const tsConfig = config.output.typescript;
1631
- const basePath = (0, import_node_path8.resolve)(rootDir, tsConfig.path);
1632
- const schemasDir = (0, import_node_path8.resolve)(basePath, tsConfig.schemasDir ?? "schemas");
1633
- const enumDir = (0, import_node_path8.resolve)(basePath, tsConfig.enumDir ?? "enum");
1634
- const omnifyBaseDir = (0, import_node_path8.resolve)(rootDir, "node_modules/@omnify-base");
1635
- const pluginEnumDir = (0, import_node_path8.resolve)(omnifyBaseDir, "enum");
1636
- const baseSchemasDir = (0, import_node_path8.resolve)(omnifyBaseDir, "schemas");
1637
- const enumImportPrefix = (0, import_node_path8.relative)(schemasDir, enumDir).replace(/\\/g, "/");
1638
- if (!(0, import_node_fs8.existsSync)(schemasDir)) {
1639
- (0, import_node_fs8.mkdirSync)(schemasDir, { recursive: true });
1773
+ const basePath = (0, import_node_path9.resolve)(rootDir, tsConfig.path);
1774
+ const schemasDir = (0, import_node_path9.resolve)(basePath, tsConfig.schemasDir ?? "schemas");
1775
+ const enumDir = (0, import_node_path9.resolve)(basePath, tsConfig.enumDir ?? "enum");
1776
+ const omnifyBaseDir = (0, import_node_path9.resolve)(rootDir, "node_modules/@omnify-base");
1777
+ const pluginEnumDir = (0, import_node_path9.resolve)(omnifyBaseDir, "enum");
1778
+ const baseSchemasDir = (0, import_node_path9.resolve)(omnifyBaseDir, "schemas");
1779
+ const enumImportPrefix = (0, import_node_path9.relative)(schemasDir, enumDir).replace(/\\/g, "/");
1780
+ if (!(0, import_node_fs9.existsSync)(schemasDir)) {
1781
+ (0, import_node_fs9.mkdirSync)(schemasDir, { recursive: true });
1640
1782
  logger.debug(`Created directory: ${schemasDir}`);
1641
1783
  }
1642
- if (!(0, import_node_fs8.existsSync)(enumDir)) {
1643
- (0, import_node_fs8.mkdirSync)(enumDir, { recursive: true });
1784
+ if (!(0, import_node_fs9.existsSync)(enumDir)) {
1785
+ (0, import_node_fs9.mkdirSync)(enumDir, { recursive: true });
1644
1786
  logger.debug(`Created directory: ${enumDir}`);
1645
1787
  }
1646
- if (!(0, import_node_fs8.existsSync)(pluginEnumDir)) {
1647
- (0, import_node_fs8.mkdirSync)(pluginEnumDir, { recursive: true });
1788
+ if (!(0, import_node_fs9.existsSync)(pluginEnumDir)) {
1789
+ (0, import_node_fs9.mkdirSync)(pluginEnumDir, { recursive: true });
1648
1790
  logger.debug(`Created directory: ${pluginEnumDir}`);
1649
1791
  }
1650
- if (!(0, import_node_fs8.existsSync)(baseSchemasDir)) {
1651
- (0, import_node_fs8.mkdirSync)(baseSchemasDir, { recursive: true });
1792
+ if (!(0, import_node_fs9.existsSync)(baseSchemasDir)) {
1793
+ (0, import_node_fs9.mkdirSync)(baseSchemasDir, { recursive: true });
1652
1794
  logger.debug(`Created directory: ${baseSchemasDir}`);
1653
1795
  }
1654
- const omnifyPkgJson = (0, import_node_path8.resolve)(omnifyBaseDir, "package.json");
1655
- if (!(0, import_node_fs8.existsSync)(omnifyPkgJson)) {
1656
- (0, import_node_fs8.writeFileSync)(omnifyPkgJson, JSON.stringify({
1796
+ const omnifyPkgJson = (0, import_node_path9.resolve)(omnifyBaseDir, "package.json");
1797
+ if (!(0, import_node_fs9.existsSync)(omnifyPkgJson)) {
1798
+ (0, import_node_fs9.writeFileSync)(omnifyPkgJson, JSON.stringify({
1657
1799
  name: "@omnify-base",
1658
1800
  version: "0.0.0",
1659
1801
  private: true,
@@ -1690,16 +1832,16 @@ function runDirectGeneration(schemas, config, rootDir, options, changes) {
1690
1832
  } else {
1691
1833
  outputDir = schemasDir;
1692
1834
  }
1693
- const filePath = (0, import_node_path8.resolve)(outputDir, outputFilePath);
1694
- const fileDir = (0, import_node_path8.dirname)(filePath);
1695
- if (!(0, import_node_fs8.existsSync)(fileDir)) {
1696
- (0, import_node_fs8.mkdirSync)(fileDir, { recursive: true });
1835
+ const filePath = (0, import_node_path9.resolve)(outputDir, outputFilePath);
1836
+ const fileDir = (0, import_node_path9.dirname)(filePath);
1837
+ if (!(0, import_node_fs9.existsSync)(fileDir)) {
1838
+ (0, import_node_fs9.mkdirSync)(fileDir, { recursive: true });
1697
1839
  }
1698
- if (!file.overwrite && (0, import_node_fs8.existsSync)(filePath)) {
1840
+ if (!file.overwrite && (0, import_node_fs9.existsSync)(filePath)) {
1699
1841
  logger.debug(`Skipped (exists): ${file.filePath}`);
1700
1842
  continue;
1701
1843
  }
1702
- (0, import_node_fs8.writeFileSync)(filePath, file.content);
1844
+ (0, import_node_fs9.writeFileSync)(filePath, file.content);
1703
1845
  logger.debug(`Created: ${file.filePath}`);
1704
1846
  typesGenerated++;
1705
1847
  }
@@ -1727,9 +1869,51 @@ async function runGenerate(options) {
1727
1869
  logger.header("Generating Outputs");
1728
1870
  logger.debug("Loading configuration...");
1729
1871
  const { config, configPath } = await loadConfig();
1730
- const rootDir = configPath ? (0, import_node_path8.dirname)(configPath) : process.cwd();
1872
+ const rootDir = configPath ? (0, import_node_path9.dirname)(configPath) : process.cwd();
1731
1873
  validateConfig(config, rootDir);
1732
- const schemaPath = (0, import_node_path8.resolve)(rootDir, config.schemasDir);
1874
+ if (config.plugins.length > 0) {
1875
+ const versionLock = readVersionLock(rootDir);
1876
+ if (versionLock) {
1877
+ logger.debug("Checking plugin versions against lock file...");
1878
+ const versionCheck = checkPluginVersions(config.plugins, versionLock);
1879
+ if (!versionCheck.valid) {
1880
+ logger.newline();
1881
+ logger.error("\u{1F512} PLUGIN VERSION MISMATCH");
1882
+ logger.error("");
1883
+ logger.error("The following plugins are older than required by the version lock:");
1884
+ logger.newline();
1885
+ for (const mismatch of versionCheck.mismatches) {
1886
+ logger.error(` \u2022 ${mismatch.name}`);
1887
+ logger.error(` Required: ${mismatch.required}`);
1888
+ logger.error(` Installed: ${mismatch.installed}`);
1889
+ }
1890
+ logger.newline();
1891
+ logger.error(`Version lock file: ${VERSION_LOCK_FILE}`);
1892
+ logger.newline();
1893
+ logger.info("To fix this, upgrade the outdated plugins:");
1894
+ logger.info("");
1895
+ for (const mismatch of versionCheck.mismatches) {
1896
+ logger.info(` npm install ${mismatch.name}@latest`);
1897
+ }
1898
+ logger.newline();
1899
+ logger.info("Or if you intentionally want to use older versions, delete the lock file:");
1900
+ logger.info(` rm ${VERSION_LOCK_FILE}`);
1901
+ logger.newline();
1902
+ throw new import_omnify_core5.OmnifyError(
1903
+ "Plugin version mismatch: installed versions are older than lock file requirements",
1904
+ "E501",
1905
+ void 0,
1906
+ "Upgrade plugins or delete the version lock file to regenerate it."
1907
+ );
1908
+ }
1909
+ if (versionCheck.newPlugins.length > 0) {
1910
+ logger.debug(`New plugins detected: ${versionCheck.newPlugins.join(", ")}`);
1911
+ }
1912
+ } else {
1913
+ logger.debug(`No version lock file found (${VERSION_LOCK_FILE})`);
1914
+ }
1915
+ }
1916
+ const schemaPath = (0, import_node_path9.resolve)(rootDir, config.schemasDir);
1733
1917
  logger.step(`Loading schemas from ${schemaPath}`);
1734
1918
  let schemas = await (0, import_omnify_core5.loadSchemas)(schemaPath);
1735
1919
  logger.debug(`Found ${Object.keys(schemas).length} schema(s) in main directory`);
@@ -1738,9 +1922,9 @@ async function runGenerate(options) {
1738
1922
  if (additionalPaths.length > 0) {
1739
1923
  logger.step(`Loading schemas from ${additionalPaths.length} additional path(s)`);
1740
1924
  for (const entry of additionalPaths) {
1741
- const absolutePath = (0, import_node_path8.resolve)(rootDir, entry.path);
1925
+ const absolutePath = (0, import_node_path9.resolve)(rootDir, entry.path);
1742
1926
  logger.debug(` Checking: ${entry.path} \u2192 ${absolutePath}`);
1743
- if ((0, import_node_fs8.existsSync)(absolutePath)) {
1927
+ if ((0, import_node_fs9.existsSync)(absolutePath)) {
1744
1928
  let packageSchemas = await (0, import_omnify_core5.loadSchemas)(absolutePath, { skipPartialResolution: true });
1745
1929
  if (entry.output) {
1746
1930
  const schemasWithOutput = {};
@@ -1795,12 +1979,12 @@ async function runGenerate(options) {
1795
1979
  process.exit(2);
1796
1980
  }
1797
1981
  logger.step("Checking for changes...");
1798
- const lockPath = (0, import_node_path8.resolve)(rootDir, config.lockFilePath);
1982
+ const lockPath = (0, import_node_path9.resolve)(rootDir, config.lockFilePath);
1799
1983
  const existingLock = await (0, import_omnify_atlas2.readLockFile)(lockPath);
1800
1984
  const currentSnapshots = await (0, import_omnify_atlas2.buildSchemaSnapshots)(schemas);
1801
1985
  const v2Lock = existingLock && (0, import_omnify_atlas2.isLockFileV2)(existingLock) ? existingLock : null;
1802
1986
  const comparison = (0, import_omnify_atlas2.compareSchemasDeep)(currentSnapshots, v2Lock);
1803
- const chainFilePath = (0, import_node_path8.resolve)(rootDir, import_omnify_atlas2.VERSION_CHAIN_FILE);
1987
+ const chainFilePath = (0, import_node_path9.resolve)(rootDir, import_omnify_atlas2.VERSION_CHAIN_FILE);
1804
1988
  const versionChain = await (0, import_omnify_atlas2.readVersionChain)(chainFilePath);
1805
1989
  if (versionChain && comparison.hasChanges) {
1806
1990
  const schemaActions = [];
@@ -1837,7 +2021,7 @@ async function runGenerate(options) {
1837
2021
  }
1838
2022
  }
1839
2023
  if (existingLock && config.output.laravel?.migrationsPath) {
1840
- const migrationsDir = (0, import_node_path8.resolve)(rootDir, config.output.laravel.migrationsPath);
2024
+ const migrationsDir = (0, import_node_path9.resolve)(rootDir, config.output.laravel.migrationsPath);
1841
2025
  const migrationValidation = await (0, import_omnify_atlas2.validateMigrations)(existingLock, migrationsDir);
1842
2026
  if (!migrationValidation.valid) {
1843
2027
  logger.newline();
@@ -1897,7 +2081,7 @@ async function runGenerate(options) {
1897
2081
  const alterMigrations = toRegenerate.filter((m) => m.type === "alter" || m.type === "drop");
1898
2082
  if (createMigrations.length > 0) {
1899
2083
  logger.info(`Regenerating ${createMigrations.length} missing CREATE migration(s) with original timestamps...`);
1900
- const migrationsDir2 = (0, import_node_path8.resolve)(rootDir, config.output.laravel.migrationsPath);
2084
+ const migrationsDir2 = (0, import_node_path9.resolve)(rootDir, config.output.laravel.migrationsPath);
1901
2085
  const customTypesMap2 = /* @__PURE__ */ new Map();
1902
2086
  for (const plugin of config.plugins) {
1903
2087
  if (plugin.types) {
@@ -1919,8 +2103,8 @@ async function runGenerate(options) {
1919
2103
  customTypes: customTypesMap2
1920
2104
  });
1921
2105
  for (const mig of regenerated) {
1922
- const filePath = (0, import_node_path8.resolve)(migrationsDir2, migData.fileName);
1923
- (0, import_node_fs8.writeFileSync)(filePath, mig.content);
2106
+ const filePath = (0, import_node_path9.resolve)(migrationsDir2, migData.fileName);
2107
+ (0, import_node_fs9.writeFileSync)(filePath, mig.content);
1924
2108
  logger.success(` Regenerated: ${migData.fileName}`);
1925
2109
  }
1926
2110
  }
@@ -1976,7 +2160,8 @@ async function runGenerate(options) {
1976
2160
  schemas,
1977
2161
  rootDir,
1978
2162
  options.verbose ?? false,
1979
- comparison.changes
2163
+ comparison.changes,
2164
+ config.locale
1980
2165
  );
1981
2166
  migrationsGenerated = counts.migrations;
1982
2167
  typesGenerated = counts.types;
@@ -1998,32 +2183,32 @@ async function runGenerate(options) {
1998
2183
  if (!options.migrationsOnly && config.output.typescript && typesGenerated === 0) {
1999
2184
  logger.step("Generating TypeScript types...");
2000
2185
  const tsConfig2 = config.output.typescript;
2001
- const basePath2 = (0, import_node_path8.resolve)(rootDir, tsConfig2.path);
2002
- const schemasDir2 = (0, import_node_path8.resolve)(basePath2, tsConfig2.schemasDir ?? "schemas");
2003
- const enumDir2 = (0, import_node_path8.resolve)(basePath2, tsConfig2.enumDir ?? "enum");
2004
- const omnifyBaseDir2 = (0, import_node_path8.resolve)(rootDir, "node_modules/@omnify-base");
2005
- const pluginEnumDir2 = (0, import_node_path8.resolve)(omnifyBaseDir2, "enum");
2006
- const baseSchemasDir2 = (0, import_node_path8.resolve)(omnifyBaseDir2, "schemas");
2007
- const enumImportPrefix2 = (0, import_node_path8.relative)(schemasDir2, enumDir2).replace(/\\/g, "/");
2008
- if (!(0, import_node_fs8.existsSync)(schemasDir2)) {
2009
- (0, import_node_fs8.mkdirSync)(schemasDir2, { recursive: true });
2186
+ const basePath2 = (0, import_node_path9.resolve)(rootDir, tsConfig2.path);
2187
+ const schemasDir2 = (0, import_node_path9.resolve)(basePath2, tsConfig2.schemasDir ?? "schemas");
2188
+ const enumDir2 = (0, import_node_path9.resolve)(basePath2, tsConfig2.enumDir ?? "enum");
2189
+ const omnifyBaseDir2 = (0, import_node_path9.resolve)(rootDir, "node_modules/@omnify-base");
2190
+ const pluginEnumDir2 = (0, import_node_path9.resolve)(omnifyBaseDir2, "enum");
2191
+ const baseSchemasDir2 = (0, import_node_path9.resolve)(omnifyBaseDir2, "schemas");
2192
+ const enumImportPrefix2 = (0, import_node_path9.relative)(schemasDir2, enumDir2).replace(/\\/g, "/");
2193
+ if (!(0, import_node_fs9.existsSync)(schemasDir2)) {
2194
+ (0, import_node_fs9.mkdirSync)(schemasDir2, { recursive: true });
2010
2195
  logger.debug(`Created directory: ${schemasDir2}`);
2011
2196
  }
2012
- if (!(0, import_node_fs8.existsSync)(enumDir2)) {
2013
- (0, import_node_fs8.mkdirSync)(enumDir2, { recursive: true });
2197
+ if (!(0, import_node_fs9.existsSync)(enumDir2)) {
2198
+ (0, import_node_fs9.mkdirSync)(enumDir2, { recursive: true });
2014
2199
  logger.debug(`Created directory: ${enumDir2}`);
2015
2200
  }
2016
- if (!(0, import_node_fs8.existsSync)(pluginEnumDir2)) {
2017
- (0, import_node_fs8.mkdirSync)(pluginEnumDir2, { recursive: true });
2201
+ if (!(0, import_node_fs9.existsSync)(pluginEnumDir2)) {
2202
+ (0, import_node_fs9.mkdirSync)(pluginEnumDir2, { recursive: true });
2018
2203
  logger.debug(`Created directory: ${pluginEnumDir2}`);
2019
2204
  }
2020
- if (!(0, import_node_fs8.existsSync)(baseSchemasDir2)) {
2021
- (0, import_node_fs8.mkdirSync)(baseSchemasDir2, { recursive: true });
2205
+ if (!(0, import_node_fs9.existsSync)(baseSchemasDir2)) {
2206
+ (0, import_node_fs9.mkdirSync)(baseSchemasDir2, { recursive: true });
2022
2207
  logger.debug(`Created directory: ${baseSchemasDir2}`);
2023
2208
  }
2024
- const omnifyPkgJson2 = (0, import_node_path8.resolve)(omnifyBaseDir2, "package.json");
2025
- if (!(0, import_node_fs8.existsSync)(omnifyPkgJson2)) {
2026
- (0, import_node_fs8.writeFileSync)(omnifyPkgJson2, JSON.stringify({
2209
+ const omnifyPkgJson2 = (0, import_node_path9.resolve)(omnifyBaseDir2, "package.json");
2210
+ if (!(0, import_node_fs9.existsSync)(omnifyPkgJson2)) {
2211
+ (0, import_node_fs9.writeFileSync)(omnifyPkgJson2, JSON.stringify({
2027
2212
  name: "@omnify-base",
2028
2213
  version: "0.0.0",
2029
2214
  private: true,
@@ -2060,16 +2245,16 @@ async function runGenerate(options) {
2060
2245
  } else {
2061
2246
  outputDir2 = schemasDir2;
2062
2247
  }
2063
- const filePath = (0, import_node_path8.resolve)(outputDir2, outputFilePath2);
2064
- const fileDir = (0, import_node_path8.dirname)(filePath);
2065
- if (!(0, import_node_fs8.existsSync)(fileDir)) {
2066
- (0, import_node_fs8.mkdirSync)(fileDir, { recursive: true });
2248
+ const filePath = (0, import_node_path9.resolve)(outputDir2, outputFilePath2);
2249
+ const fileDir = (0, import_node_path9.dirname)(filePath);
2250
+ if (!(0, import_node_fs9.existsSync)(fileDir)) {
2251
+ (0, import_node_fs9.mkdirSync)(fileDir, { recursive: true });
2067
2252
  }
2068
- if (!file.overwrite && (0, import_node_fs8.existsSync)(filePath)) {
2253
+ if (!file.overwrite && (0, import_node_fs9.existsSync)(filePath)) {
2069
2254
  logger.debug(`Skipped (exists): ${file.filePath}`);
2070
2255
  continue;
2071
2256
  }
2072
- (0, import_node_fs8.writeFileSync)(filePath, file.content);
2257
+ (0, import_node_fs9.writeFileSync)(filePath, file.content);
2073
2258
  logger.debug(`Created: ${file.filePath}`);
2074
2259
  typesGenerated++;
2075
2260
  }
@@ -2139,6 +2324,15 @@ async function runGenerate(options) {
2139
2324
  } catch (guideError) {
2140
2325
  logger.debug(`Could not generate AI guides: ${guideError.message}`);
2141
2326
  }
2327
+ if (config.plugins.length > 0) {
2328
+ try {
2329
+ const cliVersion = getCliVersion();
2330
+ const updatedLock = updateVersionLock(rootDir, config.plugins, cliVersion);
2331
+ logger.debug(`Updated version lock: ${updatedLock.plugins.length} plugin(s)`);
2332
+ } catch (lockError) {
2333
+ logger.debug(`Could not update version lock: ${lockError.message}`);
2334
+ }
2335
+ }
2142
2336
  logger.newline();
2143
2337
  logger.success("Generation complete!");
2144
2338
  if (migrationsGenerated > 0 && config.output.laravel) {
@@ -2169,13 +2363,19 @@ function registerGenerateCommand(program) {
2169
2363
  }
2170
2364
  // Annotate the CommonJS export names for ESM import in node:
2171
2365
  0 && (module.exports = {
2366
+ VERSION_LOCK_FILE,
2367
+ checkPluginVersions,
2172
2368
  defineConfig,
2369
+ getCliVersion,
2173
2370
  loadConfig,
2174
2371
  logger,
2372
+ readVersionLock,
2175
2373
  registerDiffCommand,
2176
2374
  registerGenerateCommand,
2177
2375
  registerInitCommand,
2178
2376
  registerValidateCommand,
2179
- runInit
2377
+ runInit,
2378
+ updateVersionLock,
2379
+ writeVersionLock
2180
2380
  });
2181
2381
  //# sourceMappingURL=index.cjs.map