@famgia/omnify-cli 2.0.10 → 2.0.11

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.js CHANGED
@@ -1102,8 +1102,8 @@ function registerDiffCommand(program) {
1102
1102
  }
1103
1103
 
1104
1104
  // src/commands/generate.ts
1105
- import { existsSync as existsSync8, mkdirSync as mkdirSync3, writeFileSync as writeFileSync4, readdirSync as readdirSync2 } from "fs";
1106
- import { resolve as resolve8, dirname as dirname6, relative } from "path";
1105
+ import { existsSync as existsSync9, mkdirSync as mkdirSync3, writeFileSync as writeFileSync5, readdirSync as readdirSync2 } from "fs";
1106
+ import { resolve as resolve9, dirname as dirname6, relative } from "path";
1107
1107
  import {
1108
1108
  loadSchemas as loadSchemas3,
1109
1109
  mergePartialSchemas as mergePartialSchemas3,
@@ -1138,17 +1138,19 @@ import { generateTypeScript, generateAIGuides as generateTypescriptAIGuides, sho
1138
1138
  // src/guides/index.ts
1139
1139
  import { existsSync as existsSync7, writeFileSync as writeFileSync3, mkdirSync as mkdirSync2, readdirSync, readFileSync as readFileSync3 } from "fs";
1140
1140
  import { resolve as resolve7, dirname as dirname5, join } from "path";
1141
- import "url";
1142
- var CLAUDE_MD = `# Omnify Project
1141
+ var OMNIFY_SECTION_START = "<!-- OMNIFY_SECTION_START -->";
1142
+ var OMNIFY_SECTION_END = "<!-- OMNIFY_SECTION_END -->";
1143
+ var OMNIFY_SECTION = `${OMNIFY_SECTION_START}
1144
+ ## Omnify Schema System
1143
1145
 
1144
1146
  This project uses **Omnify** for schema-driven code generation.
1145
1147
 
1146
- ## Quick Reference
1148
+ ### Quick Reference
1147
1149
 
1148
1150
  - **Schema Guide**: @.claude/omnify/guides/omnify/schema-guide.md
1149
1151
  - **Config Guide**: @.claude/omnify/guides/omnify/config-guide.md
1150
1152
 
1151
- ## Commands
1153
+ ### Commands
1152
1154
 
1153
1155
  \`\`\`bash
1154
1156
  npx omnify generate # Generate code from schemas
@@ -1156,41 +1158,52 @@ npx omnify validate # Validate schemas
1156
1158
  php artisan migrate # Run database migrations
1157
1159
  \`\`\`
1158
1160
 
1159
- ## Critical Rules
1161
+ ### Critical Rules
1160
1162
 
1161
- ### \u26D4 DO NOT EDIT Auto-Generated Files
1163
+ #### \u26D4 DO NOT EDIT Auto-Generated Files
1162
1164
  - \`database/migrations/omnify/**\` - Regenerated on \`npx omnify generate\`
1163
1165
  - \`app/Models/OmnifyBase/**\` - Base models (extend, don't edit)
1164
1166
  - \`app/Http/Requests/OmnifyBase/**\` - Base requests
1165
1167
  - \`app/Http/Resources/OmnifyBase/**\` - Base resources
1166
1168
 
1167
- ### \u2705 Schema-First Workflow
1169
+ #### \u2705 Schema-First Workflow
1168
1170
  1. Edit YAML schema in \`schemas/\`
1169
1171
  2. Run \`npx omnify generate\`
1170
1172
  3. Run \`php artisan migrate\`
1171
1173
 
1172
1174
  **NEVER use \`php artisan make:migration\`** - Always use schemas!
1175
+ ${OMNIFY_SECTION_END}`;
1176
+ function updateClaudeMd(rootDir) {
1177
+ const claudeMdPath = resolve7(rootDir, "CLAUDE.md");
1178
+ if (!existsSync7(claudeMdPath)) {
1179
+ writeFileSync3(claudeMdPath, `# Project Documentation
1173
1180
 
1174
- ## Documentation Structure
1175
-
1176
- \`\`\`
1177
- .claude/
1178
- \u251C\u2500\u2500 CLAUDE.md # This file (root pointer)
1179
- \u251C\u2500\u2500 rules/ # Claude Code rules (path-specific)
1180
- \u2502 \u2514\u2500\u2500 omnify/*.md
1181
- \u2514\u2500\u2500 omnify/ # Detailed guides
1182
- \u251C\u2500\u2500 guides/
1183
- \u2502 \u251C\u2500\u2500 omnify/ # Schema & config docs
1184
- \u2502 \u251C\u2500\u2500 laravel/ # Laravel patterns
1185
- \u2502 \u2514\u2500\u2500 react/ # React patterns
1186
- \u251C\u2500\u2500 workflows/ # Step-by-step workflows
1187
- \u2514\u2500\u2500 agents/ # AI agent prompts
1188
- \`\`\`
1189
-
1190
- ## Individual Preferences
1191
-
1192
- Add your personal preferences in \`CLAUDE.local.md\` (gitignored).
1193
- `;
1181
+ ${OMNIFY_SECTION}
1182
+ `);
1183
+ return true;
1184
+ }
1185
+ const currentContent = readFileSync3(claudeMdPath, "utf8");
1186
+ const hasOmnifySection = currentContent.includes(OMNIFY_SECTION_START);
1187
+ if (hasOmnifySection) {
1188
+ const regex = new RegExp(
1189
+ `${escapeRegExp(OMNIFY_SECTION_START)}[\\s\\S]*?${escapeRegExp(OMNIFY_SECTION_END)}`,
1190
+ "g"
1191
+ );
1192
+ const newContent = currentContent.replace(regex, OMNIFY_SECTION);
1193
+ if (newContent !== currentContent) {
1194
+ writeFileSync3(claudeMdPath, newContent);
1195
+ return true;
1196
+ }
1197
+ return false;
1198
+ } else {
1199
+ const newContent = currentContent.trimEnd() + "\n\n" + OMNIFY_SECTION + "\n";
1200
+ writeFileSync3(claudeMdPath, newContent);
1201
+ return true;
1202
+ }
1203
+ }
1204
+ function escapeRegExp(string) {
1205
+ return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
1206
+ }
1194
1207
  function copyOmnifyGuides(rootDir) {
1195
1208
  let filesWritten = 0;
1196
1209
  const omnifyPkgPaths = [
@@ -1245,20 +1258,141 @@ function copyOmnifyGuides(rootDir) {
1245
1258
  }
1246
1259
  function generateAIGuides(rootDir, _plugins) {
1247
1260
  let filesWritten = 0;
1248
- const claudeMdPath = resolve7(rootDir, "CLAUDE.md");
1249
- writeFileSync3(claudeMdPath, CLAUDE_MD);
1250
- filesWritten++;
1261
+ if (updateClaudeMd(rootDir)) {
1262
+ filesWritten++;
1263
+ }
1251
1264
  filesWritten += copyOmnifyGuides(rootDir);
1252
1265
  return filesWritten;
1253
1266
  }
1254
1267
 
1268
+ // src/version-lock/index.ts
1269
+ import { readFileSync as readFileSync4, writeFileSync as writeFileSync4, existsSync as existsSync8 } from "fs";
1270
+ import { resolve as resolve8 } from "path";
1271
+ var VERSION_LOCK_FILE = ".omnify-versions.lock";
1272
+ function readVersionLock(rootDir) {
1273
+ const lockPath = resolve8(rootDir, VERSION_LOCK_FILE);
1274
+ if (!existsSync8(lockPath)) {
1275
+ return null;
1276
+ }
1277
+ try {
1278
+ const content = readFileSync4(lockPath, "utf-8");
1279
+ return JSON.parse(content);
1280
+ } catch {
1281
+ return null;
1282
+ }
1283
+ }
1284
+ function writeVersionLock(rootDir, lock) {
1285
+ const lockPath = resolve8(rootDir, VERSION_LOCK_FILE);
1286
+ const content = JSON.stringify(lock, null, 2);
1287
+ writeFileSync4(lockPath, content + "\n");
1288
+ }
1289
+ function parseVersion(version) {
1290
+ const cleanVersion = version.replace(/^v/, "");
1291
+ const match = cleanVersion.match(/^(\d+)\.(\d+)\.(\d+)/);
1292
+ if (!match) {
1293
+ return null;
1294
+ }
1295
+ return {
1296
+ major: parseInt(match[1], 10),
1297
+ minor: parseInt(match[2], 10),
1298
+ patch: parseInt(match[3], 10)
1299
+ };
1300
+ }
1301
+ function compareVersions(a, b) {
1302
+ const parsedA = parseVersion(a);
1303
+ const parsedB = parseVersion(b);
1304
+ if (!parsedA || !parsedB) {
1305
+ return 0;
1306
+ }
1307
+ if (parsedA.major !== parsedB.major) {
1308
+ return parsedA.major > parsedB.major ? 1 : -1;
1309
+ }
1310
+ if (parsedA.minor !== parsedB.minor) {
1311
+ return parsedA.minor > parsedB.minor ? 1 : -1;
1312
+ }
1313
+ if (parsedA.patch !== parsedB.patch) {
1314
+ return parsedA.patch > parsedB.patch ? 1 : -1;
1315
+ }
1316
+ return 0;
1317
+ }
1318
+ function checkPluginVersions(plugins, lockFile) {
1319
+ const mismatches = [];
1320
+ const newPlugins = [];
1321
+ const lockedVersions = /* @__PURE__ */ new Map();
1322
+ for (const entry of lockFile.plugins) {
1323
+ lockedVersions.set(entry.name, entry.version);
1324
+ }
1325
+ for (const plugin of plugins) {
1326
+ const lockedVersion = lockedVersions.get(plugin.name);
1327
+ if (!lockedVersion) {
1328
+ newPlugins.push(plugin.name);
1329
+ continue;
1330
+ }
1331
+ const comparison = compareVersions(plugin.version, lockedVersion);
1332
+ if (comparison < 0) {
1333
+ mismatches.push({
1334
+ name: plugin.name,
1335
+ required: lockedVersion,
1336
+ installed: plugin.version
1337
+ });
1338
+ }
1339
+ }
1340
+ return {
1341
+ valid: mismatches.length === 0,
1342
+ mismatches,
1343
+ newPlugins
1344
+ };
1345
+ }
1346
+ function updateVersionLock(rootDir, plugins, cliVersion) {
1347
+ const now = (/* @__PURE__ */ new Date()).toISOString();
1348
+ const existingLock = readVersionLock(rootDir);
1349
+ const existingEntries = /* @__PURE__ */ new Map();
1350
+ if (existingLock) {
1351
+ for (const entry of existingLock.plugins) {
1352
+ existingEntries.set(entry.name, entry);
1353
+ }
1354
+ }
1355
+ const pluginEntries = [];
1356
+ for (const plugin of plugins) {
1357
+ const existing = existingEntries.get(plugin.name);
1358
+ if (!existing || compareVersions(plugin.version, existing.version) > 0) {
1359
+ pluginEntries.push({
1360
+ name: plugin.name,
1361
+ version: plugin.version,
1362
+ updatedAt: now
1363
+ });
1364
+ } else {
1365
+ pluginEntries.push(existing);
1366
+ }
1367
+ }
1368
+ pluginEntries.sort((a, b) => a.name.localeCompare(b.name));
1369
+ const lock = {
1370
+ version: 1,
1371
+ cliVersion,
1372
+ plugins: pluginEntries,
1373
+ updatedAt: now
1374
+ };
1375
+ writeVersionLock(rootDir, lock);
1376
+ return lock;
1377
+ }
1378
+ function getCliVersion() {
1379
+ try {
1380
+ const pkgPath = new URL("../../package.json", import.meta.url);
1381
+ const pkgContent = readFileSync4(pkgPath, "utf-8");
1382
+ const pkg = JSON.parse(pkgContent);
1383
+ return pkg.version;
1384
+ } catch {
1385
+ return "unknown";
1386
+ }
1387
+ }
1388
+
1255
1389
  // src/commands/generate.ts
1256
1390
  function hasPluginGenerators(plugins) {
1257
1391
  return plugins.some((p) => p.generators && p.generators.length > 0);
1258
1392
  }
1259
1393
  function getExistingMigrationTables(migrationsDir) {
1260
1394
  const existingTables = /* @__PURE__ */ new Set();
1261
- if (!existsSync8(migrationsDir)) {
1395
+ if (!existsSync9(migrationsDir)) {
1262
1396
  return existingTables;
1263
1397
  }
1264
1398
  try {
@@ -1451,17 +1585,17 @@ function schemaChangeToVersionChange(change) {
1451
1585
  function writeGeneratorOutputs(outputs, rootDir) {
1452
1586
  const counts = { migrations: 0, types: 0, models: 0, factories: 0, other: 0 };
1453
1587
  for (const output of outputs) {
1454
- const filePath = resolve8(rootDir, output.path);
1588
+ const filePath = resolve9(rootDir, output.path);
1455
1589
  const dir = dirname6(filePath);
1456
- if (!existsSync8(dir)) {
1590
+ if (!existsSync9(dir)) {
1457
1591
  mkdirSync3(dir, { recursive: true });
1458
1592
  logger.debug(`Created directory: ${dir}`);
1459
1593
  }
1460
- if (output.skipIfExists && existsSync8(filePath)) {
1594
+ if (output.skipIfExists && existsSync9(filePath)) {
1461
1595
  logger.debug(`Skipped (exists): ${output.path}`);
1462
1596
  continue;
1463
1597
  }
1464
- writeFileSync4(filePath, output.content);
1598
+ writeFileSync5(filePath, output.content);
1465
1599
  logger.debug(`Created: ${output.path}`);
1466
1600
  if (output.type === "migration") counts.migrations++;
1467
1601
  else if (output.type === "type") counts.types++;
@@ -1471,7 +1605,7 @@ function writeGeneratorOutputs(outputs, rootDir) {
1471
1605
  }
1472
1606
  return counts;
1473
1607
  }
1474
- async function runPluginGeneration(plugins, schemas, rootDir, verbose, changes) {
1608
+ async function runPluginGeneration(plugins, schemas, rootDir, verbose, changes, localeConfig) {
1475
1609
  const pluginManager = new PluginManager({
1476
1610
  cwd: rootDir,
1477
1611
  verbose,
@@ -1480,7 +1614,8 @@ async function runPluginGeneration(plugins, schemas, rootDir, verbose, changes)
1480
1614
  info: (msg) => logger.info(msg),
1481
1615
  warn: (msg) => logger.warn(msg),
1482
1616
  error: (msg) => logger.error(msg)
1483
- }
1617
+ },
1618
+ localeConfig
1484
1619
  });
1485
1620
  for (const plugin of plugins) {
1486
1621
  await pluginManager.register(plugin);
@@ -1517,8 +1652,8 @@ function runDirectGeneration(schemas, config, rootDir, options, changes) {
1517
1652
  }
1518
1653
  if (!options.typesOnly && config.output.laravel) {
1519
1654
  logger.step("Generating Laravel migrations...");
1520
- const migrationsDir = resolve8(rootDir, config.output.laravel.migrationsPath);
1521
- if (!existsSync8(migrationsDir)) {
1655
+ const migrationsDir = resolve9(rootDir, config.output.laravel.migrationsPath);
1656
+ if (!existsSync9(migrationsDir)) {
1522
1657
  mkdirSync3(migrationsDir, { recursive: true });
1523
1658
  logger.debug(`Created directory: ${migrationsDir}`);
1524
1659
  }
@@ -1540,8 +1675,8 @@ function runDirectGeneration(schemas, config, rootDir, options, changes) {
1540
1675
  logger.debug(`Skipped CREATE for ${tableName} (already exists)`);
1541
1676
  continue;
1542
1677
  }
1543
- const filePath = resolve8(migrationsDir, migration.fileName);
1544
- writeFileSync4(filePath, migration.content);
1678
+ const filePath = resolve9(migrationsDir, migration.fileName);
1679
+ writeFileSync5(filePath, migration.content);
1545
1680
  logger.debug(`Created: ${migration.fileName}`);
1546
1681
  migrationsGenerated++;
1547
1682
  }
@@ -1549,8 +1684,8 @@ function runDirectGeneration(schemas, config, rootDir, options, changes) {
1549
1684
  if (alterChanges.length > 0) {
1550
1685
  const alterMigrations = generateMigrationsFromChanges(alterChanges);
1551
1686
  for (const migration of alterMigrations) {
1552
- const filePath = resolve8(migrationsDir, migration.fileName);
1553
- writeFileSync4(filePath, migration.content);
1687
+ const filePath = resolve9(migrationsDir, migration.fileName);
1688
+ writeFileSync5(filePath, migration.content);
1554
1689
  logger.debug(`Created: ${migration.fileName}`);
1555
1690
  migrationsGenerated++;
1556
1691
  }
@@ -1561,12 +1696,12 @@ function runDirectGeneration(schemas, config, rootDir, options, changes) {
1561
1696
  logger.step("Generating Laravel models...");
1562
1697
  const modelsPath = config.output.laravel.modelsPath;
1563
1698
  const baseModelsPath = config.output.laravel.baseModelsPath ?? `${modelsPath}/OmnifyBase`;
1564
- const modelsDir = resolve8(rootDir, modelsPath);
1565
- const baseModelsDir = resolve8(rootDir, baseModelsPath);
1566
- if (!existsSync8(modelsDir)) {
1699
+ const modelsDir = resolve9(rootDir, modelsPath);
1700
+ const baseModelsDir = resolve9(rootDir, baseModelsPath);
1701
+ if (!existsSync9(modelsDir)) {
1567
1702
  mkdirSync3(modelsDir, { recursive: true });
1568
1703
  }
1569
- if (!existsSync8(baseModelsDir)) {
1704
+ if (!existsSync9(baseModelsDir)) {
1570
1705
  mkdirSync3(baseModelsDir, { recursive: true });
1571
1706
  }
1572
1707
  const providersPath = config.output.laravel.providersPath ?? "app/Providers";
@@ -1577,16 +1712,16 @@ function runDirectGeneration(schemas, config, rootDir, options, changes) {
1577
1712
  customTypes: customTypesMap
1578
1713
  });
1579
1714
  for (const model of models) {
1580
- const filePath = resolve8(rootDir, getModelPath(model));
1715
+ const filePath = resolve9(rootDir, getModelPath(model));
1581
1716
  const fileDir = dirname6(filePath);
1582
- if (!existsSync8(fileDir)) {
1717
+ if (!existsSync9(fileDir)) {
1583
1718
  mkdirSync3(fileDir, { recursive: true });
1584
1719
  }
1585
- if (!model.overwrite && existsSync8(filePath)) {
1720
+ if (!model.overwrite && existsSync9(filePath)) {
1586
1721
  logger.debug(`Skipped (exists): ${getModelPath(model)}`);
1587
1722
  continue;
1588
1723
  }
1589
- writeFileSync4(filePath, model.content);
1724
+ writeFileSync5(filePath, model.content);
1590
1725
  logger.debug(`Created: ${getModelPath(model)}`);
1591
1726
  modelsGenerated++;
1592
1727
  }
@@ -1595,24 +1730,24 @@ function runDirectGeneration(schemas, config, rootDir, options, changes) {
1595
1730
  if (!options.typesOnly && config.output.laravel?.factoriesPath) {
1596
1731
  logger.step("Generating Laravel factories...");
1597
1732
  const factoriesPath = config.output.laravel.factoriesPath;
1598
- const factoriesDir = resolve8(rootDir, factoriesPath);
1599
- if (!existsSync8(factoriesDir)) {
1733
+ const factoriesDir = resolve9(rootDir, factoriesPath);
1734
+ if (!existsSync9(factoriesDir)) {
1600
1735
  mkdirSync3(factoriesDir, { recursive: true });
1601
1736
  }
1602
1737
  const factories = generateFactories(schemas, {
1603
1738
  factoryPath: factoriesPath
1604
1739
  });
1605
1740
  for (const factory of factories) {
1606
- const filePath = resolve8(rootDir, getFactoryPath(factory));
1741
+ const filePath = resolve9(rootDir, getFactoryPath(factory));
1607
1742
  const fileDir = dirname6(filePath);
1608
- if (!existsSync8(fileDir)) {
1743
+ if (!existsSync9(fileDir)) {
1609
1744
  mkdirSync3(fileDir, { recursive: true });
1610
1745
  }
1611
- if (!factory.overwrite && existsSync8(filePath)) {
1746
+ if (!factory.overwrite && existsSync9(filePath)) {
1612
1747
  logger.debug(`Skipped (exists): ${getFactoryPath(factory)}`);
1613
1748
  continue;
1614
1749
  }
1615
- writeFileSync4(filePath, factory.content);
1750
+ writeFileSync5(filePath, factory.content);
1616
1751
  logger.debug(`Created: ${getFactoryPath(factory)}`);
1617
1752
  factoriesGenerated++;
1618
1753
  }
@@ -1621,32 +1756,32 @@ function runDirectGeneration(schemas, config, rootDir, options, changes) {
1621
1756
  if (!options.migrationsOnly && config.output.typescript) {
1622
1757
  logger.step("Generating TypeScript types...");
1623
1758
  const tsConfig = config.output.typescript;
1624
- const basePath = resolve8(rootDir, tsConfig.path);
1625
- const schemasDir = resolve8(basePath, tsConfig.schemasDir ?? "schemas");
1626
- const enumDir = resolve8(basePath, tsConfig.enumDir ?? "enum");
1627
- const omnifyBaseDir = resolve8(rootDir, "node_modules/@omnify-base");
1628
- const pluginEnumDir = resolve8(omnifyBaseDir, "enum");
1629
- const baseSchemasDir = resolve8(omnifyBaseDir, "schemas");
1759
+ const basePath = resolve9(rootDir, tsConfig.path);
1760
+ const schemasDir = resolve9(basePath, tsConfig.schemasDir ?? "schemas");
1761
+ const enumDir = resolve9(basePath, tsConfig.enumDir ?? "enum");
1762
+ const omnifyBaseDir = resolve9(rootDir, "node_modules/@omnify-base");
1763
+ const pluginEnumDir = resolve9(omnifyBaseDir, "enum");
1764
+ const baseSchemasDir = resolve9(omnifyBaseDir, "schemas");
1630
1765
  const enumImportPrefix = relative(schemasDir, enumDir).replace(/\\/g, "/");
1631
- if (!existsSync8(schemasDir)) {
1766
+ if (!existsSync9(schemasDir)) {
1632
1767
  mkdirSync3(schemasDir, { recursive: true });
1633
1768
  logger.debug(`Created directory: ${schemasDir}`);
1634
1769
  }
1635
- if (!existsSync8(enumDir)) {
1770
+ if (!existsSync9(enumDir)) {
1636
1771
  mkdirSync3(enumDir, { recursive: true });
1637
1772
  logger.debug(`Created directory: ${enumDir}`);
1638
1773
  }
1639
- if (!existsSync8(pluginEnumDir)) {
1774
+ if (!existsSync9(pluginEnumDir)) {
1640
1775
  mkdirSync3(pluginEnumDir, { recursive: true });
1641
1776
  logger.debug(`Created directory: ${pluginEnumDir}`);
1642
1777
  }
1643
- if (!existsSync8(baseSchemasDir)) {
1778
+ if (!existsSync9(baseSchemasDir)) {
1644
1779
  mkdirSync3(baseSchemasDir, { recursive: true });
1645
1780
  logger.debug(`Created directory: ${baseSchemasDir}`);
1646
1781
  }
1647
- const omnifyPkgJson = resolve8(omnifyBaseDir, "package.json");
1648
- if (!existsSync8(omnifyPkgJson)) {
1649
- writeFileSync4(omnifyPkgJson, JSON.stringify({
1782
+ const omnifyPkgJson = resolve9(omnifyBaseDir, "package.json");
1783
+ if (!existsSync9(omnifyPkgJson)) {
1784
+ writeFileSync5(omnifyPkgJson, JSON.stringify({
1650
1785
  name: "@omnify-base",
1651
1786
  version: "0.0.0",
1652
1787
  private: true,
@@ -1683,16 +1818,16 @@ function runDirectGeneration(schemas, config, rootDir, options, changes) {
1683
1818
  } else {
1684
1819
  outputDir = schemasDir;
1685
1820
  }
1686
- const filePath = resolve8(outputDir, outputFilePath);
1821
+ const filePath = resolve9(outputDir, outputFilePath);
1687
1822
  const fileDir = dirname6(filePath);
1688
- if (!existsSync8(fileDir)) {
1823
+ if (!existsSync9(fileDir)) {
1689
1824
  mkdirSync3(fileDir, { recursive: true });
1690
1825
  }
1691
- if (!file.overwrite && existsSync8(filePath)) {
1826
+ if (!file.overwrite && existsSync9(filePath)) {
1692
1827
  logger.debug(`Skipped (exists): ${file.filePath}`);
1693
1828
  continue;
1694
1829
  }
1695
- writeFileSync4(filePath, file.content);
1830
+ writeFileSync5(filePath, file.content);
1696
1831
  logger.debug(`Created: ${file.filePath}`);
1697
1832
  typesGenerated++;
1698
1833
  }
@@ -1722,7 +1857,49 @@ async function runGenerate(options) {
1722
1857
  const { config, configPath } = await loadConfig();
1723
1858
  const rootDir = configPath ? dirname6(configPath) : process.cwd();
1724
1859
  validateConfig(config, rootDir);
1725
- const schemaPath = resolve8(rootDir, config.schemasDir);
1860
+ if (config.plugins.length > 0) {
1861
+ const versionLock = readVersionLock(rootDir);
1862
+ if (versionLock) {
1863
+ logger.debug("Checking plugin versions against lock file...");
1864
+ const versionCheck = checkPluginVersions(config.plugins, versionLock);
1865
+ if (!versionCheck.valid) {
1866
+ logger.newline();
1867
+ logger.error("\u{1F512} PLUGIN VERSION MISMATCH");
1868
+ logger.error("");
1869
+ logger.error("The following plugins are older than required by the version lock:");
1870
+ logger.newline();
1871
+ for (const mismatch of versionCheck.mismatches) {
1872
+ logger.error(` \u2022 ${mismatch.name}`);
1873
+ logger.error(` Required: ${mismatch.required}`);
1874
+ logger.error(` Installed: ${mismatch.installed}`);
1875
+ }
1876
+ logger.newline();
1877
+ logger.error(`Version lock file: ${VERSION_LOCK_FILE}`);
1878
+ logger.newline();
1879
+ logger.info("To fix this, upgrade the outdated plugins:");
1880
+ logger.info("");
1881
+ for (const mismatch of versionCheck.mismatches) {
1882
+ logger.info(` npm install ${mismatch.name}@latest`);
1883
+ }
1884
+ logger.newline();
1885
+ logger.info("Or if you intentionally want to use older versions, delete the lock file:");
1886
+ logger.info(` rm ${VERSION_LOCK_FILE}`);
1887
+ logger.newline();
1888
+ throw new OmnifyError4(
1889
+ "Plugin version mismatch: installed versions are older than lock file requirements",
1890
+ "E501",
1891
+ void 0,
1892
+ "Upgrade plugins or delete the version lock file to regenerate it."
1893
+ );
1894
+ }
1895
+ if (versionCheck.newPlugins.length > 0) {
1896
+ logger.debug(`New plugins detected: ${versionCheck.newPlugins.join(", ")}`);
1897
+ }
1898
+ } else {
1899
+ logger.debug(`No version lock file found (${VERSION_LOCK_FILE})`);
1900
+ }
1901
+ }
1902
+ const schemaPath = resolve9(rootDir, config.schemasDir);
1726
1903
  logger.step(`Loading schemas from ${schemaPath}`);
1727
1904
  let schemas = await loadSchemas3(schemaPath);
1728
1905
  logger.debug(`Found ${Object.keys(schemas).length} schema(s) in main directory`);
@@ -1731,9 +1908,9 @@ async function runGenerate(options) {
1731
1908
  if (additionalPaths.length > 0) {
1732
1909
  logger.step(`Loading schemas from ${additionalPaths.length} additional path(s)`);
1733
1910
  for (const entry of additionalPaths) {
1734
- const absolutePath = resolve8(rootDir, entry.path);
1911
+ const absolutePath = resolve9(rootDir, entry.path);
1735
1912
  logger.debug(` Checking: ${entry.path} \u2192 ${absolutePath}`);
1736
- if (existsSync8(absolutePath)) {
1913
+ if (existsSync9(absolutePath)) {
1737
1914
  let packageSchemas = await loadSchemas3(absolutePath, { skipPartialResolution: true });
1738
1915
  if (entry.output) {
1739
1916
  const schemasWithOutput = {};
@@ -1788,12 +1965,12 @@ async function runGenerate(options) {
1788
1965
  process.exit(2);
1789
1966
  }
1790
1967
  logger.step("Checking for changes...");
1791
- const lockPath = resolve8(rootDir, config.lockFilePath);
1968
+ const lockPath = resolve9(rootDir, config.lockFilePath);
1792
1969
  const existingLock = await readLockFile(lockPath);
1793
1970
  const currentSnapshots = await buildSchemaSnapshots(schemas);
1794
1971
  const v2Lock = existingLock && isLockFileV2(existingLock) ? existingLock : null;
1795
1972
  const comparison = compareSchemasDeep(currentSnapshots, v2Lock);
1796
- const chainFilePath = resolve8(rootDir, VERSION_CHAIN_FILE);
1973
+ const chainFilePath = resolve9(rootDir, VERSION_CHAIN_FILE);
1797
1974
  const versionChain = await readVersionChain(chainFilePath);
1798
1975
  if (versionChain && comparison.hasChanges) {
1799
1976
  const schemaActions = [];
@@ -1830,7 +2007,7 @@ async function runGenerate(options) {
1830
2007
  }
1831
2008
  }
1832
2009
  if (existingLock && config.output.laravel?.migrationsPath) {
1833
- const migrationsDir = resolve8(rootDir, config.output.laravel.migrationsPath);
2010
+ const migrationsDir = resolve9(rootDir, config.output.laravel.migrationsPath);
1834
2011
  const migrationValidation = await validateMigrations(existingLock, migrationsDir);
1835
2012
  if (!migrationValidation.valid) {
1836
2013
  logger.newline();
@@ -1890,7 +2067,7 @@ async function runGenerate(options) {
1890
2067
  const alterMigrations = toRegenerate.filter((m) => m.type === "alter" || m.type === "drop");
1891
2068
  if (createMigrations.length > 0) {
1892
2069
  logger.info(`Regenerating ${createMigrations.length} missing CREATE migration(s) with original timestamps...`);
1893
- const migrationsDir2 = resolve8(rootDir, config.output.laravel.migrationsPath);
2070
+ const migrationsDir2 = resolve9(rootDir, config.output.laravel.migrationsPath);
1894
2071
  const customTypesMap2 = /* @__PURE__ */ new Map();
1895
2072
  for (const plugin of config.plugins) {
1896
2073
  if (plugin.types) {
@@ -1912,8 +2089,8 @@ async function runGenerate(options) {
1912
2089
  customTypes: customTypesMap2
1913
2090
  });
1914
2091
  for (const mig of regenerated) {
1915
- const filePath = resolve8(migrationsDir2, migData.fileName);
1916
- writeFileSync4(filePath, mig.content);
2092
+ const filePath = resolve9(migrationsDir2, migData.fileName);
2093
+ writeFileSync5(filePath, mig.content);
1917
2094
  logger.success(` Regenerated: ${migData.fileName}`);
1918
2095
  }
1919
2096
  }
@@ -1969,7 +2146,8 @@ async function runGenerate(options) {
1969
2146
  schemas,
1970
2147
  rootDir,
1971
2148
  options.verbose ?? false,
1972
- comparison.changes
2149
+ comparison.changes,
2150
+ config.locale
1973
2151
  );
1974
2152
  migrationsGenerated = counts.migrations;
1975
2153
  typesGenerated = counts.types;
@@ -1991,32 +2169,32 @@ async function runGenerate(options) {
1991
2169
  if (!options.migrationsOnly && config.output.typescript && typesGenerated === 0) {
1992
2170
  logger.step("Generating TypeScript types...");
1993
2171
  const tsConfig2 = config.output.typescript;
1994
- const basePath2 = resolve8(rootDir, tsConfig2.path);
1995
- const schemasDir2 = resolve8(basePath2, tsConfig2.schemasDir ?? "schemas");
1996
- const enumDir2 = resolve8(basePath2, tsConfig2.enumDir ?? "enum");
1997
- const omnifyBaseDir2 = resolve8(rootDir, "node_modules/@omnify-base");
1998
- const pluginEnumDir2 = resolve8(omnifyBaseDir2, "enum");
1999
- const baseSchemasDir2 = resolve8(omnifyBaseDir2, "schemas");
2172
+ const basePath2 = resolve9(rootDir, tsConfig2.path);
2173
+ const schemasDir2 = resolve9(basePath2, tsConfig2.schemasDir ?? "schemas");
2174
+ const enumDir2 = resolve9(basePath2, tsConfig2.enumDir ?? "enum");
2175
+ const omnifyBaseDir2 = resolve9(rootDir, "node_modules/@omnify-base");
2176
+ const pluginEnumDir2 = resolve9(omnifyBaseDir2, "enum");
2177
+ const baseSchemasDir2 = resolve9(omnifyBaseDir2, "schemas");
2000
2178
  const enumImportPrefix2 = relative(schemasDir2, enumDir2).replace(/\\/g, "/");
2001
- if (!existsSync8(schemasDir2)) {
2179
+ if (!existsSync9(schemasDir2)) {
2002
2180
  mkdirSync3(schemasDir2, { recursive: true });
2003
2181
  logger.debug(`Created directory: ${schemasDir2}`);
2004
2182
  }
2005
- if (!existsSync8(enumDir2)) {
2183
+ if (!existsSync9(enumDir2)) {
2006
2184
  mkdirSync3(enumDir2, { recursive: true });
2007
2185
  logger.debug(`Created directory: ${enumDir2}`);
2008
2186
  }
2009
- if (!existsSync8(pluginEnumDir2)) {
2187
+ if (!existsSync9(pluginEnumDir2)) {
2010
2188
  mkdirSync3(pluginEnumDir2, { recursive: true });
2011
2189
  logger.debug(`Created directory: ${pluginEnumDir2}`);
2012
2190
  }
2013
- if (!existsSync8(baseSchemasDir2)) {
2191
+ if (!existsSync9(baseSchemasDir2)) {
2014
2192
  mkdirSync3(baseSchemasDir2, { recursive: true });
2015
2193
  logger.debug(`Created directory: ${baseSchemasDir2}`);
2016
2194
  }
2017
- const omnifyPkgJson2 = resolve8(omnifyBaseDir2, "package.json");
2018
- if (!existsSync8(omnifyPkgJson2)) {
2019
- writeFileSync4(omnifyPkgJson2, JSON.stringify({
2195
+ const omnifyPkgJson2 = resolve9(omnifyBaseDir2, "package.json");
2196
+ if (!existsSync9(omnifyPkgJson2)) {
2197
+ writeFileSync5(omnifyPkgJson2, JSON.stringify({
2020
2198
  name: "@omnify-base",
2021
2199
  version: "0.0.0",
2022
2200
  private: true,
@@ -2053,16 +2231,16 @@ async function runGenerate(options) {
2053
2231
  } else {
2054
2232
  outputDir2 = schemasDir2;
2055
2233
  }
2056
- const filePath = resolve8(outputDir2, outputFilePath2);
2234
+ const filePath = resolve9(outputDir2, outputFilePath2);
2057
2235
  const fileDir = dirname6(filePath);
2058
- if (!existsSync8(fileDir)) {
2236
+ if (!existsSync9(fileDir)) {
2059
2237
  mkdirSync3(fileDir, { recursive: true });
2060
2238
  }
2061
- if (!file.overwrite && existsSync8(filePath)) {
2239
+ if (!file.overwrite && existsSync9(filePath)) {
2062
2240
  logger.debug(`Skipped (exists): ${file.filePath}`);
2063
2241
  continue;
2064
2242
  }
2065
- writeFileSync4(filePath, file.content);
2243
+ writeFileSync5(filePath, file.content);
2066
2244
  logger.debug(`Created: ${file.filePath}`);
2067
2245
  typesGenerated++;
2068
2246
  }
@@ -2132,6 +2310,15 @@ async function runGenerate(options) {
2132
2310
  } catch (guideError) {
2133
2311
  logger.debug(`Could not generate AI guides: ${guideError.message}`);
2134
2312
  }
2313
+ if (config.plugins.length > 0) {
2314
+ try {
2315
+ const cliVersion = getCliVersion();
2316
+ const updatedLock = updateVersionLock(rootDir, config.plugins, cliVersion);
2317
+ logger.debug(`Updated version lock: ${updatedLock.plugins.length} plugin(s)`);
2318
+ } catch (lockError) {
2319
+ logger.debug(`Could not update version lock: ${lockError.message}`);
2320
+ }
2321
+ }
2135
2322
  logger.newline();
2136
2323
  logger.success("Generation complete!");
2137
2324
  if (migrationsGenerated > 0 && config.output.laravel) {
@@ -2161,13 +2348,19 @@ function registerGenerateCommand(program) {
2161
2348
  });
2162
2349
  }
2163
2350
  export {
2351
+ VERSION_LOCK_FILE,
2352
+ checkPluginVersions,
2164
2353
  defineConfig,
2354
+ getCliVersion,
2165
2355
  loadConfig,
2166
2356
  logger,
2357
+ readVersionLock,
2167
2358
  registerDiffCommand,
2168
2359
  registerGenerateCommand,
2169
2360
  registerInitCommand,
2170
2361
  registerValidateCommand,
2171
- runInit
2362
+ runInit,
2363
+ updateVersionLock,
2364
+ writeVersionLock
2172
2365
  };
2173
2366
  //# sourceMappingURL=index.js.map