@famgia/omnify-cli 0.0.110 → 0.0.112

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
@@ -722,6 +722,7 @@ var import_omnify_typescript = require("@famgia/omnify-typescript");
722
722
  // src/guides/index.ts
723
723
  var import_node_fs3 = require("fs");
724
724
  var import_node_path5 = require("path");
725
+ var import_node_url = require("url");
725
726
  var CLAUDE_MD = `## Omnify
726
727
 
727
728
  This project uses Omnify for schema-driven code generation.
@@ -738,6 +739,58 @@ This project uses Omnify for schema-driven code generation.
738
739
  - \`npx omnify generate\` - Generate code from schemas
739
740
  - \`npx omnify validate\` - Validate schemas
740
741
  `;
742
+ function copyOmnifyGuides(rootDir) {
743
+ let filesWritten = 0;
744
+ const omnifyPkgPaths = [
745
+ (0, import_node_path5.resolve)(rootDir, "node_modules", "@famgia", "omnify", "stubs", "ai-guides", "omnify"),
746
+ (0, import_node_path5.resolve)(rootDir, "node_modules", ".pnpm", "@famgia+omnify@*", "node_modules", "@famgia", "omnify", "stubs", "ai-guides", "omnify")
747
+ ];
748
+ let stubsDir = null;
749
+ for (const pkgPath of omnifyPkgPaths) {
750
+ if (pkgPath.includes("*")) {
751
+ const parentDir = (0, import_node_path5.dirname)((0, import_node_path5.dirname)(pkgPath));
752
+ if ((0, import_node_fs3.existsSync)(parentDir)) {
753
+ const entries = (0, import_node_fs3.readdirSync)(parentDir);
754
+ for (const entry of entries) {
755
+ if (entry.startsWith("@famgia+omnify@")) {
756
+ const testPath = (0, import_node_path5.join)(parentDir, entry, "node_modules", "@famgia", "omnify", "stubs", "ai-guides", "omnify");
757
+ if ((0, import_node_fs3.existsSync)(testPath)) {
758
+ stubsDir = testPath;
759
+ break;
760
+ }
761
+ }
762
+ }
763
+ }
764
+ } else if ((0, import_node_fs3.existsSync)(pkgPath)) {
765
+ stubsDir = pkgPath;
766
+ break;
767
+ }
768
+ }
769
+ if (!stubsDir) {
770
+ try {
771
+ const omnifyPath = (0, import_node_path5.dirname)(require.resolve("@famgia/omnify/package.json", { paths: [rootDir] }));
772
+ const testPath = (0, import_node_path5.join)(omnifyPath, "stubs", "ai-guides", "omnify");
773
+ if ((0, import_node_fs3.existsSync)(testPath)) {
774
+ stubsDir = testPath;
775
+ }
776
+ } catch {
777
+ }
778
+ }
779
+ if (!stubsDir) {
780
+ return 0;
781
+ }
782
+ const destDir = (0, import_node_path5.resolve)(rootDir, ".claude", "omnify", "guides", "omnify");
783
+ (0, import_node_fs3.mkdirSync)(destDir, { recursive: true });
784
+ const files = (0, import_node_fs3.readdirSync)(stubsDir).filter((f) => f.endsWith(".stub"));
785
+ for (const file of files) {
786
+ const srcPath = (0, import_node_path5.join)(stubsDir, file);
787
+ const destPath = (0, import_node_path5.join)(destDir, file.replace(".stub", ""));
788
+ const content = (0, import_node_fs3.readFileSync)(srcPath, "utf8");
789
+ (0, import_node_fs3.writeFileSync)(destPath, content);
790
+ filesWritten++;
791
+ }
792
+ return filesWritten;
793
+ }
741
794
  function generateAIGuides(rootDir, _plugins) {
742
795
  let filesWritten = 0;
743
796
  const claudeMdPath = (0, import_node_path5.resolve)(rootDir, "CLAUDE.md");
@@ -745,6 +798,7 @@ function generateAIGuides(rootDir, _plugins) {
745
798
  (0, import_node_fs3.writeFileSync)(claudeMdPath, CLAUDE_MD);
746
799
  filesWritten++;
747
800
  }
801
+ filesWritten += copyOmnifyGuides(rootDir);
748
802
  return filesWritten;
749
803
  }
750
804
 
@@ -1207,6 +1261,68 @@ async function runGenerate(options) {
1207
1261
  const currentSnapshots = await (0, import_omnify_atlas2.buildSchemaSnapshots)(schemas);
1208
1262
  const v2Lock = existingLock && (0, import_omnify_atlas2.isLockFileV2)(existingLock) ? existingLock : null;
1209
1263
  const comparison = (0, import_omnify_atlas2.compareSchemasDeep)(currentSnapshots, v2Lock);
1264
+ if (existingLock && config.output.laravel?.migrationsPath) {
1265
+ const migrationsDir = (0, import_node_path6.resolve)(rootDir, config.output.laravel.migrationsPath);
1266
+ const migrationValidation = await (0, import_omnify_atlas2.validateMigrations)(existingLock, migrationsDir);
1267
+ if (!migrationValidation.valid) {
1268
+ logger.newline();
1269
+ logger.warn("Migration file issues detected:");
1270
+ if (migrationValidation.missingFiles.length > 0) {
1271
+ logger.error(` Missing files (${migrationValidation.missingFiles.length}):`);
1272
+ for (const file of migrationValidation.missingFiles) {
1273
+ logger.error(` - ${file}`);
1274
+ }
1275
+ }
1276
+ if (migrationValidation.modifiedFiles.length > 0) {
1277
+ logger.warn(` Modified files (${migrationValidation.modifiedFiles.length}):`);
1278
+ for (const file of migrationValidation.modifiedFiles) {
1279
+ logger.warn(` - ${file} (checksum mismatch)`);
1280
+ }
1281
+ }
1282
+ logger.newline();
1283
+ }
1284
+ if ((options.warnStale ?? true) && migrationValidation.staleFiles.length > 0) {
1285
+ logger.newline();
1286
+ logger.warn("\u26A0\uFE0F Stale migrations detected (old timestamp, not in lock file):");
1287
+ for (const file of migrationValidation.staleFiles) {
1288
+ logger.warn(` - ${file}`);
1289
+ }
1290
+ logger.warn(" These may be from merged branches. Review before running migrate.");
1291
+ logger.newline();
1292
+ }
1293
+ if (options.check) {
1294
+ logger.newline();
1295
+ logger.step("CI Check Mode Results:");
1296
+ logger.info(` Schemas: ${schemaCount}`);
1297
+ logger.info(` Tracked migrations: ${migrationValidation.totalTracked}`);
1298
+ logger.info(` Migrations on disk: ${migrationValidation.totalOnDisk}`);
1299
+ logger.info(` Schema changes: ${comparison.changes.length}`);
1300
+ const hasIssues = !migrationValidation.valid || comparison.hasChanges;
1301
+ if (hasIssues) {
1302
+ logger.newline();
1303
+ if (comparison.hasChanges) {
1304
+ logger.error('\u274C Schema changes detected - run "npx omnify generate" to update migrations');
1305
+ }
1306
+ if (migrationValidation.missingFiles.length > 0) {
1307
+ logger.error("\u274C Missing migration files - regenerate or restore from git");
1308
+ }
1309
+ if (migrationValidation.modifiedFiles.length > 0) {
1310
+ logger.warn("\u26A0\uFE0F Modified migration files - may cause inconsistencies");
1311
+ }
1312
+ process.exit(1);
1313
+ } else {
1314
+ logger.success("\u2705 All migrations in sync");
1315
+ return;
1316
+ }
1317
+ }
1318
+ if (migrationValidation.missingFiles.length > 0) {
1319
+ const toRegenerate = (0, import_omnify_atlas2.getMigrationsToRegenerate)(existingLock, migrationValidation.missingFiles);
1320
+ if (toRegenerate.length > 0) {
1321
+ logger.info(`Will regenerate ${toRegenerate.length} missing migration(s) with original timestamps.`);
1322
+ logger.warn("Auto-regeneration not yet implemented. Please restore from git or reset migrations.");
1323
+ }
1324
+ }
1325
+ }
1210
1326
  const skipMigrations = !comparison.hasChanges && !options.force;
1211
1327
  const pluginsHaveGenerators = config.plugins.some((p) => p.generators && p.generators.length > 0);
1212
1328
  const hasTypescriptOutput = !!config.output.typescript;
@@ -1378,7 +1494,7 @@ async function runGenerate(options) {
1378
1494
  }
1379
1495
  }
1380
1496
  function registerGenerateCommand(program) {
1381
- 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) => {
1497
+ 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").option("--check", "CI mode: check if migrations are in sync without generating (exits with code 1 if out of sync)").option("--no-warn-stale", "Disable stale migration warnings").action(async (options) => {
1382
1498
  try {
1383
1499
  await runGenerate(options);
1384
1500
  } catch (error) {