@famgia/omnify-cli 2.0.15 → 2.0.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -1128,6 +1128,9 @@ import {
1128
1128
  isLockFileV2,
1129
1129
  validateMigrations,
1130
1130
  getMigrationsToRegenerate,
1131
+ addEnhancedMigrationRecord,
1132
+ extractTimestampFromFilename,
1133
+ extractTableNameFromFilename,
1131
1134
  VERSION_CHAIN_FILE,
1132
1135
  readVersionChain,
1133
1136
  checkBulkLockViolation
@@ -1591,6 +1594,7 @@ function schemaChangeToVersionChange(change) {
1591
1594
  }
1592
1595
  function writeGeneratorOutputs(outputs, rootDir) {
1593
1596
  const counts = { migrations: 0, types: 0, models: 0, factories: 0, other: 0 };
1597
+ const migrationRecords = [];
1594
1598
  for (const output of outputs) {
1595
1599
  const filePath = resolve9(rootDir, output.path);
1596
1600
  const dir = dirname6(filePath);
@@ -1604,13 +1608,34 @@ function writeGeneratorOutputs(outputs, rootDir) {
1604
1608
  }
1605
1609
  writeFileSync5(filePath, output.content);
1606
1610
  logger.debug(`Created: ${output.path}`);
1607
- if (output.type === "migration") counts.migrations++;
1608
- else if (output.type === "type") counts.types++;
1611
+ if (output.type === "migration") {
1612
+ counts.migrations++;
1613
+ const fileName = output.path.split("/").pop() ?? output.path;
1614
+ const timestamp = extractTimestampFromFilename(fileName);
1615
+ const metaTableName = output.metadata?.tableName;
1616
+ const tableName = metaTableName ?? extractTableNameFromFilename(fileName);
1617
+ const migrationType = output.metadata?.migrationType;
1618
+ const schemaName = output.metadata?.schemaName;
1619
+ const pathParts = output.path.split("/");
1620
+ pathParts.pop();
1621
+ const outputPath = pathParts.join("/");
1622
+ if (timestamp && tableName) {
1623
+ migrationRecords.push({
1624
+ fileName,
1625
+ timestamp,
1626
+ tableName,
1627
+ type: migrationType ?? "create",
1628
+ schemas: schemaName ? [schemaName] : [],
1629
+ content: output.content,
1630
+ outputPath
1631
+ });
1632
+ }
1633
+ } else if (output.type === "type") counts.types++;
1609
1634
  else if (output.type === "model") counts.models++;
1610
1635
  else if (output.type === "factory") counts.factories++;
1611
1636
  else counts.other++;
1612
1637
  }
1613
- return counts;
1638
+ return { ...counts, migrationRecords };
1614
1639
  }
1615
1640
  async function runPluginGeneration(plugins, schemas, rootDir, verbose, changes, localeConfig) {
1616
1641
  const pluginManager = new PluginManager({
@@ -1641,6 +1666,7 @@ function runDirectGeneration(schemas, config, rootDir, options, changes) {
1641
1666
  let typesGenerated = 0;
1642
1667
  let modelsGenerated = 0;
1643
1668
  let factoriesGenerated = 0;
1669
+ const migrationRecords = [];
1644
1670
  const customTypesMap = /* @__PURE__ */ new Map();
1645
1671
  for (const plugin of config.plugins) {
1646
1672
  if (plugin.types) {
@@ -1686,6 +1712,18 @@ function runDirectGeneration(schemas, config, rootDir, options, changes) {
1686
1712
  writeFileSync5(filePath, migration.content);
1687
1713
  logger.debug(`Created: ${migration.fileName}`);
1688
1714
  migrationsGenerated++;
1715
+ const timestamp = extractTimestampFromFilename(migration.fileName);
1716
+ if (timestamp && tableName) {
1717
+ migrationRecords.push({
1718
+ fileName: migration.fileName,
1719
+ timestamp,
1720
+ tableName,
1721
+ type: "create",
1722
+ schemas: migration.schemaName ? [migration.schemaName] : [],
1723
+ content: migration.content,
1724
+ outputPath: config.output.laravel.migrationsPath
1725
+ });
1726
+ }
1689
1727
  }
1690
1728
  }
1691
1729
  if (alterChanges.length > 0) {
@@ -1695,6 +1733,19 @@ function runDirectGeneration(schemas, config, rootDir, options, changes) {
1695
1733
  writeFileSync5(filePath, migration.content);
1696
1734
  logger.debug(`Created: ${migration.fileName}`);
1697
1735
  migrationsGenerated++;
1736
+ const timestamp = extractTimestampFromFilename(migration.fileName);
1737
+ const tableName = migration.tables[0];
1738
+ if (timestamp && tableName) {
1739
+ migrationRecords.push({
1740
+ fileName: migration.fileName,
1741
+ timestamp,
1742
+ tableName,
1743
+ type: migration.type,
1744
+ schemas: [],
1745
+ content: migration.content,
1746
+ outputPath: config.output.laravel.migrationsPath
1747
+ });
1748
+ }
1698
1749
  }
1699
1750
  }
1700
1751
  logger.success(`Generated ${migrationsGenerated} migration(s)`);
@@ -1855,7 +1906,7 @@ function runDirectGeneration(schemas, config, rootDir, options, changes) {
1855
1906
  logger.success("Auto-configured @omnify-base/* path in tsconfig.json");
1856
1907
  }
1857
1908
  }
1858
- return { migrations: migrationsGenerated, types: typesGenerated, models: modelsGenerated, factories: factoriesGenerated };
1909
+ return { migrations: migrationsGenerated, types: typesGenerated, models: modelsGenerated, factories: factoriesGenerated, migrationRecords };
1859
1910
  }
1860
1911
  async function runGenerate(options) {
1861
1912
  logger.setVerbose(options.verbose ?? false);
@@ -2015,7 +2066,7 @@ async function runGenerate(options) {
2015
2066
  }
2016
2067
  if (existingLock && config.output.laravel?.migrationsPath) {
2017
2068
  const migrationsDir = resolve9(rootDir, config.output.laravel.migrationsPath);
2018
- const migrationValidation = await validateMigrations(existingLock, migrationsDir);
2069
+ const migrationValidation = await validateMigrations(existingLock, migrationsDir, rootDir);
2019
2070
  if (!migrationValidation.valid) {
2020
2071
  logger.newline();
2021
2072
  logger.warn("Migration file issues detected:");
@@ -2074,7 +2125,7 @@ async function runGenerate(options) {
2074
2125
  const alterMigrations = toRegenerate.filter((m) => m.type === "alter" || m.type === "drop");
2075
2126
  if (createMigrations.length > 0) {
2076
2127
  logger.info(`Regenerating ${createMigrations.length} missing CREATE migration(s) with original timestamps...`);
2077
- const migrationsDir2 = resolve9(rootDir, config.output.laravel.migrationsPath);
2128
+ const defaultMigrationsDir = resolve9(rootDir, config.output.laravel.migrationsPath);
2078
2129
  const customTypesMap2 = /* @__PURE__ */ new Map();
2079
2130
  for (const plugin of config.plugins) {
2080
2131
  if (plugin.types) {
@@ -2095,11 +2146,20 @@ async function runGenerate(options) {
2095
2146
  timestamp: migData.timestamp,
2096
2147
  customTypes: customTypesMap2
2097
2148
  });
2098
- for (const mig of regenerated) {
2099
- const filePath = resolve9(migrationsDir2, migData.fileName);
2100
- writeFileSync5(filePath, mig.content);
2101
- logger.success(` Regenerated: ${migData.fileName}`);
2149
+ const matchingMig = regenerated.find((mig) => {
2150
+ return mig.tables.includes(migData.tableName);
2151
+ });
2152
+ if (!matchingMig) {
2153
+ logger.warn(` Cannot regenerate ${migData.fileName}: migration for table '${migData.tableName}' not found`);
2154
+ continue;
2102
2155
  }
2156
+ const targetDir = migData.outputPath ? resolve9(rootDir, migData.outputPath) : defaultMigrationsDir;
2157
+ if (!existsSync9(targetDir)) {
2158
+ mkdirSync3(targetDir, { recursive: true });
2159
+ }
2160
+ const filePath = resolve9(targetDir, migData.fileName);
2161
+ writeFileSync5(filePath, matchingMig.content);
2162
+ logger.success(` Regenerated: ${migData.fileName}`);
2103
2163
  }
2104
2164
  }
2105
2165
  if (alterMigrations.length > 0) {
@@ -2129,6 +2189,7 @@ async function runGenerate(options) {
2129
2189
  let typesGenerated = 0;
2130
2190
  let modelsGenerated = 0;
2131
2191
  let factoriesGenerated = 0;
2192
+ let allMigrationRecords = [];
2132
2193
  const usePlugins = hasPluginGenerators(config.plugins);
2133
2194
  const customTypesMap = /* @__PURE__ */ new Map();
2134
2195
  for (const plugin of config.plugins) {
@@ -2158,6 +2219,7 @@ async function runGenerate(options) {
2158
2219
  );
2159
2220
  migrationsGenerated = counts.migrations;
2160
2221
  typesGenerated = counts.types;
2222
+ allMigrationRecords = counts.migrationRecords;
2161
2223
  if (counts.migrations > 0) {
2162
2224
  logger.success(`Generated ${counts.migrations} migration(s)`);
2163
2225
  }
@@ -2283,9 +2345,24 @@ async function runGenerate(options) {
2283
2345
  typesGenerated = counts.types;
2284
2346
  modelsGenerated = counts.models;
2285
2347
  factoriesGenerated = counts.factories;
2348
+ allMigrationRecords = counts.migrationRecords;
2286
2349
  }
2287
2350
  logger.step("Updating lock file...");
2288
- const newLockFile = updateLockFile(existingLock, currentSnapshots, config.database.driver);
2351
+ let newLockFile = updateLockFile(existingLock, currentSnapshots, config.database.driver);
2352
+ if (allMigrationRecords.length > 0) {
2353
+ logger.debug(`Adding ${allMigrationRecords.length} migration(s) to lock file...`);
2354
+ for (const record of allMigrationRecords) {
2355
+ newLockFile = addEnhancedMigrationRecord(newLockFile, {
2356
+ fileName: record.fileName,
2357
+ timestamp: record.timestamp,
2358
+ tableName: record.tableName,
2359
+ type: record.type,
2360
+ schemas: record.schemas,
2361
+ content: record.content,
2362
+ outputPath: record.outputPath
2363
+ });
2364
+ }
2365
+ }
2289
2366
  await writeLockFile(lockPath, newLockFile);
2290
2367
  logger.debug(`Updated: ${config.lockFilePath}`);
2291
2368
  if (comparison.hasChanges) {
@@ -3279,12 +3356,31 @@ async function runAIGuides(options) {
3279
3356
  } catch {
3280
3357
  logger.debug("No omnify.config.ts found, using defaults");
3281
3358
  }
3282
- let categories = getAvailableCategories();
3359
+ const availableCategories = getAvailableCategories();
3360
+ let categories = availableCategories;
3283
3361
  if (options.categories) {
3284
- categories = options.categories.split(",").map((c) => c.trim());
3362
+ const requestedCategories = options.categories.split(",").map((c) => c.trim());
3363
+ const invalidCategories = requestedCategories.filter(
3364
+ (c) => !availableCategories.includes(c)
3365
+ );
3366
+ if (invalidCategories.length > 0) {
3367
+ logger.error(`Invalid category: ${invalidCategories.join(", ")}`);
3368
+ logger.error(`Available categories: ${availableCategories.join(", ")}`);
3369
+ throw new Error(`Invalid category: ${invalidCategories.join(", ")}`);
3370
+ }
3371
+ categories = requestedCategories;
3285
3372
  logger.debug(`Categories (from CLI): ${categories.join(", ")}`);
3286
3373
  } else if (configAiGuides?.categories) {
3287
- categories = [...configAiGuides.categories];
3374
+ const invalidCategories = configAiGuides.categories.filter(
3375
+ (c) => !availableCategories.includes(c)
3376
+ );
3377
+ if (invalidCategories.length > 0) {
3378
+ logger.warn(`Invalid category in config: ${invalidCategories.join(", ")}`);
3379
+ logger.warn(`Available categories: ${availableCategories.join(", ")}`);
3380
+ }
3381
+ categories = configAiGuides.categories.filter(
3382
+ (c) => availableCategories.includes(c)
3383
+ );
3288
3384
  logger.debug(`Categories (from config): ${categories.join(", ")}`);
3289
3385
  }
3290
3386
  let adapters;