rulesync 0.15.0 → 0.17.0

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
@@ -368,14 +368,20 @@ var import_gray_matter = __toESM(require("gray-matter"));
368
368
  async function parseRulesFromDirectory(aiRulesDir) {
369
369
  const ruleFiles = await findFiles(aiRulesDir);
370
370
  const rules = [];
371
+ const errors = [];
371
372
  for (const filepath of ruleFiles) {
372
373
  try {
373
374
  const rule = await parseRuleFile(filepath);
374
375
  rules.push(rule);
375
376
  } catch (error) {
376
- console.warn(`Failed to parse rule file ${filepath}:`, error);
377
+ const errorMessage = error instanceof Error ? error.message : String(error);
378
+ errors.push(`Failed to parse rule file ${filepath}: ${errorMessage}`);
377
379
  }
378
380
  }
381
+ if (errors.length > 0) {
382
+ throw new Error(`Validation errors found:
383
+ ${errors.join("\n")}`);
384
+ }
379
385
  return rules;
380
386
  }
381
387
  async function parseRuleFile(filepath) {
@@ -393,14 +399,36 @@ async function parseRuleFile(filepath) {
393
399
  }
394
400
  function validateFrontmatter(data, filepath) {
395
401
  if (!data || typeof data !== "object") {
396
- throw new Error(`Invalid frontmatter in ${filepath}: must be an object`);
402
+ if (!data) {
403
+ throw new Error(
404
+ `Missing frontmatter in ${filepath}: file must contain YAML frontmatter with required fields (root, targets, description, globs)`
405
+ );
406
+ }
407
+ throw new Error(`Invalid frontmatter in ${filepath}: frontmatter must be a valid YAML object`);
397
408
  }
398
409
  const obj = data;
410
+ if (Object.keys(obj).length === 0) {
411
+ throw new Error(
412
+ `Missing frontmatter in ${filepath}: file must contain YAML frontmatter with required fields (root, targets, description, globs)`
413
+ );
414
+ }
415
+ if (obj.root === void 0) {
416
+ throw new Error(`Missing required field "root" in ${filepath}: must be true or false`);
417
+ }
399
418
  if (typeof obj.root !== "boolean") {
400
- throw new Error(`Invalid root in ${filepath}: must be a boolean`);
419
+ throw new Error(
420
+ `Invalid "root" field in ${filepath}: must be a boolean (true or false), got ${typeof obj.root}`
421
+ );
422
+ }
423
+ if (obj.targets === void 0) {
424
+ throw new Error(
425
+ `Missing required field "targets" in ${filepath}: must be an array like ["*"] or ["copilot", "cursor"]`
426
+ );
401
427
  }
402
428
  if (!Array.isArray(obj.targets)) {
403
- throw new Error(`Invalid targets in ${filepath}: must be an array`);
429
+ throw new Error(
430
+ `Invalid "targets" field in ${filepath}: must be an array, got ${typeof obj.targets}`
431
+ );
404
432
  }
405
433
  const validTargets = ["copilot", "cursor", "cline", "claude", "roo", "*"];
406
434
  for (const target of obj.targets) {
@@ -410,15 +438,31 @@ function validateFrontmatter(data, filepath) {
410
438
  );
411
439
  }
412
440
  }
441
+ if (obj.description === void 0) {
442
+ throw new Error(
443
+ `Missing required field "description" in ${filepath}: must be a descriptive string`
444
+ );
445
+ }
413
446
  if (!obj.description || typeof obj.description !== "string") {
414
- throw new Error(`Invalid description in ${filepath}: must be a non-empty string`);
447
+ throw new Error(
448
+ `Invalid "description" field in ${filepath}: must be a non-empty string, got ${typeof obj.description}`
449
+ );
450
+ }
451
+ if (obj.globs === void 0) {
452
+ throw new Error(
453
+ `Missing required field "globs" in ${filepath}: must be an array of file patterns like ["**/*.ts"]`
454
+ );
415
455
  }
416
456
  if (!Array.isArray(obj.globs)) {
417
- throw new Error(`Invalid globs in ${filepath}: must be an array`);
457
+ throw new Error(
458
+ `Invalid "globs" field in ${filepath}: must be an array, got ${typeof obj.globs}`
459
+ );
418
460
  }
419
461
  for (const glob of obj.globs) {
420
462
  if (typeof glob !== "string") {
421
- throw new Error(`Invalid glob in ${filepath}: all globs must be strings`);
463
+ throw new Error(
464
+ `Invalid glob pattern in ${filepath}: all globs must be strings, got ${typeof glob}`
465
+ );
422
466
  }
423
467
  }
424
468
  }
@@ -569,7 +613,15 @@ var gitignoreCommand = async () => {
569
613
  ".clinerules/",
570
614
  "CLAUDE.md",
571
615
  ".claude/memories/",
572
- ".roo/rules/"
616
+ ".roo/rules/",
617
+ "# Support for --base-dir option (any depth)",
618
+ "**/.github/copilot-instructions.md",
619
+ "**/.github/instructions/",
620
+ "**/.cursor/rules/",
621
+ "**/.clinerules/",
622
+ "**/CLAUDE.md",
623
+ "**/.claude/memories/",
624
+ "**/.roo/rules/"
573
625
  ];
574
626
  let gitignoreContent = "";
575
627
  if ((0, import_node_fs.existsSync)(gitignorePath)) {
package/dist/index.mjs CHANGED
@@ -345,14 +345,20 @@ import matter from "gray-matter";
345
345
  async function parseRulesFromDirectory(aiRulesDir) {
346
346
  const ruleFiles = await findFiles(aiRulesDir);
347
347
  const rules = [];
348
+ const errors = [];
348
349
  for (const filepath of ruleFiles) {
349
350
  try {
350
351
  const rule = await parseRuleFile(filepath);
351
352
  rules.push(rule);
352
353
  } catch (error) {
353
- console.warn(`Failed to parse rule file ${filepath}:`, error);
354
+ const errorMessage = error instanceof Error ? error.message : String(error);
355
+ errors.push(`Failed to parse rule file ${filepath}: ${errorMessage}`);
354
356
  }
355
357
  }
358
+ if (errors.length > 0) {
359
+ throw new Error(`Validation errors found:
360
+ ${errors.join("\n")}`);
361
+ }
356
362
  return rules;
357
363
  }
358
364
  async function parseRuleFile(filepath) {
@@ -370,14 +376,36 @@ async function parseRuleFile(filepath) {
370
376
  }
371
377
  function validateFrontmatter(data, filepath) {
372
378
  if (!data || typeof data !== "object") {
373
- throw new Error(`Invalid frontmatter in ${filepath}: must be an object`);
379
+ if (!data) {
380
+ throw new Error(
381
+ `Missing frontmatter in ${filepath}: file must contain YAML frontmatter with required fields (root, targets, description, globs)`
382
+ );
383
+ }
384
+ throw new Error(`Invalid frontmatter in ${filepath}: frontmatter must be a valid YAML object`);
374
385
  }
375
386
  const obj = data;
387
+ if (Object.keys(obj).length === 0) {
388
+ throw new Error(
389
+ `Missing frontmatter in ${filepath}: file must contain YAML frontmatter with required fields (root, targets, description, globs)`
390
+ );
391
+ }
392
+ if (obj.root === void 0) {
393
+ throw new Error(`Missing required field "root" in ${filepath}: must be true or false`);
394
+ }
376
395
  if (typeof obj.root !== "boolean") {
377
- throw new Error(`Invalid root in ${filepath}: must be a boolean`);
396
+ throw new Error(
397
+ `Invalid "root" field in ${filepath}: must be a boolean (true or false), got ${typeof obj.root}`
398
+ );
399
+ }
400
+ if (obj.targets === void 0) {
401
+ throw new Error(
402
+ `Missing required field "targets" in ${filepath}: must be an array like ["*"] or ["copilot", "cursor"]`
403
+ );
378
404
  }
379
405
  if (!Array.isArray(obj.targets)) {
380
- throw new Error(`Invalid targets in ${filepath}: must be an array`);
406
+ throw new Error(
407
+ `Invalid "targets" field in ${filepath}: must be an array, got ${typeof obj.targets}`
408
+ );
381
409
  }
382
410
  const validTargets = ["copilot", "cursor", "cline", "claude", "roo", "*"];
383
411
  for (const target of obj.targets) {
@@ -387,15 +415,31 @@ function validateFrontmatter(data, filepath) {
387
415
  );
388
416
  }
389
417
  }
418
+ if (obj.description === void 0) {
419
+ throw new Error(
420
+ `Missing required field "description" in ${filepath}: must be a descriptive string`
421
+ );
422
+ }
390
423
  if (!obj.description || typeof obj.description !== "string") {
391
- throw new Error(`Invalid description in ${filepath}: must be a non-empty string`);
424
+ throw new Error(
425
+ `Invalid "description" field in ${filepath}: must be a non-empty string, got ${typeof obj.description}`
426
+ );
427
+ }
428
+ if (obj.globs === void 0) {
429
+ throw new Error(
430
+ `Missing required field "globs" in ${filepath}: must be an array of file patterns like ["**/*.ts"]`
431
+ );
392
432
  }
393
433
  if (!Array.isArray(obj.globs)) {
394
- throw new Error(`Invalid globs in ${filepath}: must be an array`);
434
+ throw new Error(
435
+ `Invalid "globs" field in ${filepath}: must be an array, got ${typeof obj.globs}`
436
+ );
395
437
  }
396
438
  for (const glob of obj.globs) {
397
439
  if (typeof glob !== "string") {
398
- throw new Error(`Invalid glob in ${filepath}: all globs must be strings`);
440
+ throw new Error(
441
+ `Invalid glob pattern in ${filepath}: all globs must be strings, got ${typeof glob}`
442
+ );
399
443
  }
400
444
  }
401
445
  }
@@ -546,7 +590,15 @@ var gitignoreCommand = async () => {
546
590
  ".clinerules/",
547
591
  "CLAUDE.md",
548
592
  ".claude/memories/",
549
- ".roo/rules/"
593
+ ".roo/rules/",
594
+ "# Support for --base-dir option (any depth)",
595
+ "**/.github/copilot-instructions.md",
596
+ "**/.github/instructions/",
597
+ "**/.cursor/rules/",
598
+ "**/.clinerules/",
599
+ "**/CLAUDE.md",
600
+ "**/.claude/memories/",
601
+ "**/.roo/rules/"
550
602
  ];
551
603
  let gitignoreContent = "";
552
604
  if (existsSync(gitignorePath)) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rulesync",
3
- "version": "0.15.0",
3
+ "version": "0.17.0",
4
4
  "description": "Unified AI rules management CLI tool that generates configuration files for various AI development tools",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",