rulesync 8.1.0 → 8.2.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/{chunk-FLZZ3LEK.js → chunk-K4IN6URH.js} +187 -38
- package/dist/cli/index.cjs +199 -40
- package/dist/cli/index.js +13 -3
- package/dist/index.cjs +187 -38
- package/dist/index.js +1 -1
- package/package.json +5 -4
|
@@ -33,12 +33,13 @@ var FeaturesSchema = z.array(FeatureSchema);
|
|
|
33
33
|
var FeatureOptionsSchema = z.record(z.string(), z.unknown());
|
|
34
34
|
var FeatureValueSchema = z.union([z.boolean(), FeatureOptionsSchema]);
|
|
35
35
|
var PerFeatureConfigSchema = z.record(z.string(), FeatureValueSchema);
|
|
36
|
+
var PerTargetFeaturesValueSchema = z.union([
|
|
37
|
+
z.array(z.enum(ALL_FEATURES_WITH_WILDCARD)),
|
|
38
|
+
PerFeatureConfigSchema
|
|
39
|
+
]);
|
|
36
40
|
var RulesyncFeaturesSchema = z.union([
|
|
37
41
|
z.array(z.enum(ALL_FEATURES_WITH_WILDCARD)),
|
|
38
|
-
z.record(
|
|
39
|
-
z.string(),
|
|
40
|
-
z.union([z.array(z.enum(ALL_FEATURES_WITH_WILDCARD)), PerFeatureConfigSchema])
|
|
41
|
-
)
|
|
42
|
+
z.record(z.string(), PerTargetFeaturesValueSchema)
|
|
42
43
|
]);
|
|
43
44
|
var isFeatureValueEnabled = (value) => {
|
|
44
45
|
if (value === true) return true;
|
|
@@ -81,6 +82,14 @@ var ALL_TOOL_TARGETS_WITH_WILDCARD = [...ALL_TOOL_TARGETS, "*"];
|
|
|
81
82
|
var ToolTargetSchema = z2.enum(ALL_TOOL_TARGETS);
|
|
82
83
|
var ToolTargetsSchema = z2.array(ToolTargetSchema);
|
|
83
84
|
var RulesyncTargetsSchema = z2.array(z2.enum(ALL_TOOL_TARGETS_WITH_WILDCARD));
|
|
85
|
+
var RulesyncConfigTargetsObjectSchema = z2.record(z2.string(), PerTargetFeaturesValueSchema);
|
|
86
|
+
var RulesyncConfigTargetsSchema = z2.union([
|
|
87
|
+
RulesyncTargetsSchema,
|
|
88
|
+
RulesyncConfigTargetsObjectSchema
|
|
89
|
+
]);
|
|
90
|
+
var isRulesyncConfigTargetsObject = (value) => {
|
|
91
|
+
return !Array.isArray(value);
|
|
92
|
+
};
|
|
84
93
|
|
|
85
94
|
// src/config/config-resolver.ts
|
|
86
95
|
import { dirname as dirname2, join as join3, resolve as resolve2 } from "path";
|
|
@@ -338,7 +347,7 @@ var SourceEntrySchema = z3.object({
|
|
|
338
347
|
});
|
|
339
348
|
var ConfigParamsSchema = z3.object({
|
|
340
349
|
baseDirs: z3.array(z3.string()),
|
|
341
|
-
targets:
|
|
350
|
+
targets: RulesyncConfigTargetsSchema,
|
|
342
351
|
features: RulesyncFeaturesSchema,
|
|
343
352
|
verbose: z3.boolean(),
|
|
344
353
|
delete: z3.boolean(),
|
|
@@ -365,10 +374,42 @@ var CONFLICTING_TARGET_PAIRS = [
|
|
|
365
374
|
["claudecode", "claudecode-legacy"]
|
|
366
375
|
];
|
|
367
376
|
var LEGACY_TARGETS = ["augmentcode-legacy", "claudecode-legacy"];
|
|
377
|
+
var assertTargetsFeaturesExclusive = ({
|
|
378
|
+
targets,
|
|
379
|
+
features
|
|
380
|
+
}) => {
|
|
381
|
+
const targetsIsObject = targets !== void 0 && !Array.isArray(targets);
|
|
382
|
+
const featuresIsObject = features !== void 0 && !Array.isArray(features);
|
|
383
|
+
if (targetsIsObject && features !== void 0) {
|
|
384
|
+
throw new Error(
|
|
385
|
+
"Invalid config: when 'targets' is in object form, 'features' must be omitted. Declare per-target features inside the 'targets' object instead."
|
|
386
|
+
);
|
|
387
|
+
}
|
|
388
|
+
if (featuresIsObject && targets !== void 0) {
|
|
389
|
+
throw new Error(
|
|
390
|
+
"Invalid config: when 'features' is in object form, 'targets' must be omitted. Migrate to the 'targets' object form, e.g. `targets: { claudecode: [...] }`."
|
|
391
|
+
);
|
|
392
|
+
}
|
|
393
|
+
};
|
|
394
|
+
var assertTargetsOrFeaturesProvided = ({
|
|
395
|
+
targets,
|
|
396
|
+
features
|
|
397
|
+
}) => {
|
|
398
|
+
if (targets === void 0 && features === void 0) {
|
|
399
|
+
throw new Error("Invalid config: at least one of 'targets' or 'features' must be provided.");
|
|
400
|
+
}
|
|
401
|
+
};
|
|
368
402
|
var Config = class _Config {
|
|
369
403
|
baseDirs;
|
|
370
404
|
targets;
|
|
371
405
|
features;
|
|
406
|
+
/**
|
|
407
|
+
* Cached list of validated `ToolTarget` keys for the object form of
|
|
408
|
+
* `targets`. Populated in the constructor after `validateObjectFormTargetKeys`
|
|
409
|
+
* so `getTargets()` does not rebuild the `ALL_TOOL_TARGETS` set on every call.
|
|
410
|
+
* Undefined when `this.targets` is in array form.
|
|
411
|
+
*/
|
|
412
|
+
objectFormTargetKeys;
|
|
372
413
|
verbose;
|
|
373
414
|
delete;
|
|
374
415
|
global;
|
|
@@ -396,13 +437,19 @@ var Config = class _Config {
|
|
|
396
437
|
check,
|
|
397
438
|
sources
|
|
398
439
|
}) {
|
|
399
|
-
|
|
440
|
+
assertTargetsFeaturesExclusive({ targets, features });
|
|
441
|
+
assertTargetsOrFeaturesProvided({ targets, features });
|
|
442
|
+
const resolvedTargets = targets ?? [];
|
|
443
|
+
const resolvedFeatures = features ?? [];
|
|
444
|
+
this.validateObjectFormTargetKeys(resolvedTargets);
|
|
445
|
+
this.validateConflictingTargets(resolvedTargets);
|
|
400
446
|
if (dryRun && check) {
|
|
401
447
|
throw new Error("--dry-run and --check cannot be used together");
|
|
402
448
|
}
|
|
403
449
|
this.baseDirs = baseDirs;
|
|
404
|
-
this.targets =
|
|
405
|
-
this.features =
|
|
450
|
+
this.targets = resolvedTargets;
|
|
451
|
+
this.features = resolvedFeatures;
|
|
452
|
+
this.objectFormTargetKeys = isRulesyncConfigTargetsObject(resolvedTargets) ? _Config.filterValidToolTargets(Object.keys(resolvedTargets)) : void 0;
|
|
406
453
|
this.verbose = verbose;
|
|
407
454
|
this.delete = isDelete;
|
|
408
455
|
this.global = global ?? false;
|
|
@@ -415,11 +462,37 @@ var Config = class _Config {
|
|
|
415
462
|
this.check = check ?? false;
|
|
416
463
|
this.sources = sources ?? [];
|
|
417
464
|
}
|
|
465
|
+
/**
|
|
466
|
+
* Rejects unknown keys (and the special `*` key) in the object form of
|
|
467
|
+
* `targets`. For the array form this is already enforced at the Zod schema
|
|
468
|
+
* level via `z.enum(ALL_TOOL_TARGETS_WITH_WILDCARD)`; for the object form
|
|
469
|
+
* `z.record(z.string(), ...)` intentionally accepts any string key (to work
|
|
470
|
+
* around zod's `z.record(z.enum(...))` requiring ALL enum members), so
|
|
471
|
+
* runtime validation lives here instead.
|
|
472
|
+
*/
|
|
473
|
+
validateObjectFormTargetKeys(targets) {
|
|
474
|
+
if (Array.isArray(targets)) return;
|
|
475
|
+
const validTargets = new Set(ALL_TOOL_TARGETS);
|
|
476
|
+
for (const key of Object.keys(targets)) {
|
|
477
|
+
if (key === "*") {
|
|
478
|
+
throw new Error(
|
|
479
|
+
"Invalid target '*' in object form: wildcard is only supported in the array form `targets: ['*']`. Per-target options cannot be attached to a wildcard."
|
|
480
|
+
);
|
|
481
|
+
}
|
|
482
|
+
if (!validTargets.has(key)) {
|
|
483
|
+
throw new Error(`Unknown target '${key}'. Valid targets: ${ALL_TOOL_TARGETS.join(", ")}.`);
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
}
|
|
418
487
|
validateConflictingTargets(targets) {
|
|
488
|
+
const has = (target) => {
|
|
489
|
+
if (Array.isArray(targets)) {
|
|
490
|
+
return targets.includes(target);
|
|
491
|
+
}
|
|
492
|
+
return Object.prototype.hasOwnProperty.call(targets, target);
|
|
493
|
+
};
|
|
419
494
|
for (const [target1, target2] of CONFLICTING_TARGET_PAIRS) {
|
|
420
|
-
|
|
421
|
-
const hasTarget2 = targets.includes(target2);
|
|
422
|
-
if (hasTarget1 && hasTarget2) {
|
|
495
|
+
if (has(target1) && has(target2)) {
|
|
423
496
|
throw new Error(
|
|
424
497
|
`Conflicting targets: '${target1}' and '${target2}' cannot be used together. Please choose one.`
|
|
425
498
|
);
|
|
@@ -429,16 +502,45 @@ var Config = class _Config {
|
|
|
429
502
|
getBaseDirs() {
|
|
430
503
|
return this.baseDirs;
|
|
431
504
|
}
|
|
505
|
+
/**
|
|
506
|
+
* Filter an arbitrary string-key list down to the known `ToolTarget` set,
|
|
507
|
+
* skipping `*` (which is only meaningful as an array element, not a key).
|
|
508
|
+
*/
|
|
509
|
+
static filterValidToolTargets(keys) {
|
|
510
|
+
const validTargets = new Set(ALL_TOOL_TARGETS);
|
|
511
|
+
const result = [];
|
|
512
|
+
for (const key of keys) {
|
|
513
|
+
if (key === "*") continue;
|
|
514
|
+
if (!validTargets.has(key)) continue;
|
|
515
|
+
result.push(key);
|
|
516
|
+
}
|
|
517
|
+
return result;
|
|
518
|
+
}
|
|
432
519
|
getTargets() {
|
|
433
|
-
if (this.
|
|
520
|
+
if (this.objectFormTargetKeys !== void 0) {
|
|
521
|
+
return this.objectFormTargetKeys;
|
|
522
|
+
}
|
|
523
|
+
const arrayTargets = Array.isArray(this.targets) ? this.targets : [];
|
|
524
|
+
if (!Array.isArray(this.features)) {
|
|
525
|
+
return _Config.filterValidToolTargets(Object.keys(this.features));
|
|
526
|
+
}
|
|
527
|
+
if (arrayTargets.includes("*")) {
|
|
434
528
|
return ALL_TOOL_TARGETS.filter(
|
|
435
529
|
// eslint-disable-next-line no-type-assertion/no-type-assertion
|
|
436
530
|
(target) => !LEGACY_TARGETS.includes(target)
|
|
437
531
|
);
|
|
438
532
|
}
|
|
439
|
-
return
|
|
533
|
+
return arrayTargets.filter((target) => target !== "*");
|
|
440
534
|
}
|
|
441
535
|
getFeatures(target) {
|
|
536
|
+
if (isRulesyncConfigTargetsObject(this.targets)) {
|
|
537
|
+
if (target) {
|
|
538
|
+
const value = this.targets[target];
|
|
539
|
+
if (!value) return [];
|
|
540
|
+
return _Config.normalizeTargetFeatures(value);
|
|
541
|
+
}
|
|
542
|
+
return _Config.collectAllFeatures(Object.values(this.targets));
|
|
543
|
+
}
|
|
442
544
|
if (!Array.isArray(this.features)) {
|
|
443
545
|
const perTargetFeatures = this.features;
|
|
444
546
|
if (target) {
|
|
@@ -448,20 +550,7 @@ var Config = class _Config {
|
|
|
448
550
|
}
|
|
449
551
|
return _Config.normalizeTargetFeatures(targetFeatures);
|
|
450
552
|
}
|
|
451
|
-
|
|
452
|
-
for (const features of Object.values(perTargetFeatures)) {
|
|
453
|
-
if (!features) continue;
|
|
454
|
-
const normalized = _Config.normalizeTargetFeatures(features);
|
|
455
|
-
for (const feature of normalized) {
|
|
456
|
-
if (!allFeatures.includes(feature)) {
|
|
457
|
-
allFeatures.push(feature);
|
|
458
|
-
}
|
|
459
|
-
}
|
|
460
|
-
if (allFeatures.length === ALL_FEATURES.length) {
|
|
461
|
-
return allFeatures;
|
|
462
|
-
}
|
|
463
|
-
}
|
|
464
|
-
return allFeatures;
|
|
553
|
+
return _Config.collectAllFeatures(Object.values(perTargetFeatures));
|
|
465
554
|
}
|
|
466
555
|
if (this.features.includes("*")) {
|
|
467
556
|
return [...ALL_FEATURES];
|
|
@@ -489,23 +578,40 @@ var Config = class _Config {
|
|
|
489
578
|
}
|
|
490
579
|
return enabled;
|
|
491
580
|
}
|
|
581
|
+
/**
|
|
582
|
+
* Collect the union of features across all per-target values.
|
|
583
|
+
* Used when `getFeatures()` is called without a target in object mode.
|
|
584
|
+
*/
|
|
585
|
+
static collectAllFeatures(values) {
|
|
586
|
+
const allFeatures = [];
|
|
587
|
+
for (const value of values) {
|
|
588
|
+
if (!value) continue;
|
|
589
|
+
const normalized = _Config.normalizeTargetFeatures(value);
|
|
590
|
+
for (const feature of normalized) {
|
|
591
|
+
if (!allFeatures.includes(feature)) {
|
|
592
|
+
allFeatures.push(feature);
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
if (allFeatures.length === ALL_FEATURES.length) {
|
|
596
|
+
return allFeatures;
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
return allFeatures;
|
|
600
|
+
}
|
|
492
601
|
/**
|
|
493
602
|
* Returns the per-feature options object for a given target/feature, if any.
|
|
494
603
|
* Returns `undefined` when no per-feature options were provided or when the
|
|
495
604
|
* feature is not enabled for the given target.
|
|
496
605
|
*/
|
|
497
606
|
getFeatureOptions(target, feature) {
|
|
498
|
-
|
|
607
|
+
const value = isRulesyncConfigTargetsObject(this.targets) ? this.targets[target] : !Array.isArray(this.features) ? this.features[target] : void 0;
|
|
608
|
+
if (!value || Array.isArray(value)) {
|
|
499
609
|
return void 0;
|
|
500
610
|
}
|
|
501
|
-
const
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
const perFeature = targetFeatures;
|
|
506
|
-
const value = perFeature[feature];
|
|
507
|
-
if (value && typeof value === "object" && isFeatureValueEnabled(value)) {
|
|
508
|
-
return value;
|
|
611
|
+
const perFeature = value;
|
|
612
|
+
const featureValue = perFeature[feature];
|
|
613
|
+
if (featureValue && typeof featureValue === "object" && isFeatureValueEnabled(featureValue)) {
|
|
614
|
+
return featureValue;
|
|
509
615
|
}
|
|
510
616
|
return void 0;
|
|
511
617
|
}
|
|
@@ -513,6 +619,13 @@ var Config = class _Config {
|
|
|
513
619
|
* Check if per-target features configuration is being used.
|
|
514
620
|
*/
|
|
515
621
|
hasPerTargetFeatures() {
|
|
622
|
+
return isRulesyncConfigTargetsObject(this.targets) || !Array.isArray(this.features);
|
|
623
|
+
}
|
|
624
|
+
/**
|
|
625
|
+
* Returns true if the deprecated object form under `features` is in use.
|
|
626
|
+
* Callers can use this to emit a migration warning.
|
|
627
|
+
*/
|
|
628
|
+
hasDeprecatedFeaturesObjectForm() {
|
|
516
629
|
return !Array.isArray(this.features);
|
|
517
630
|
}
|
|
518
631
|
getVerbose() {
|
|
@@ -557,6 +670,17 @@ var Config = class _Config {
|
|
|
557
670
|
}
|
|
558
671
|
};
|
|
559
672
|
|
|
673
|
+
// src/config/deprecation-warnings.ts
|
|
674
|
+
var deprecationWarningEmitted = false;
|
|
675
|
+
var emitFeaturesObjectFormDeprecationWarning = () => {
|
|
676
|
+
if (deprecationWarningEmitted) return;
|
|
677
|
+
if (process.env.RULESYNC_SILENT_DEPRECATION) return;
|
|
678
|
+
deprecationWarningEmitted = true;
|
|
679
|
+
console.warn(
|
|
680
|
+
"[rulesync] DEPRECATED: 'features' object form is deprecated. Use the new 'targets' object form instead: `targets: { claudecode: { rules: true, ignore: { fileMode: 'local' } } }`. See https://github.com/dyoshikawa/rulesync/blob/main/docs/guide/configuration.md for the migration guide."
|
|
681
|
+
);
|
|
682
|
+
};
|
|
683
|
+
|
|
560
684
|
// src/config/config-resolver.ts
|
|
561
685
|
var getDefaults = () => ({
|
|
562
686
|
targets: ["agentsmd"],
|
|
@@ -583,6 +707,10 @@ var loadConfigFromFile = async (filePath) => {
|
|
|
583
707
|
const jsonData = parseJsonc(fileContent);
|
|
584
708
|
const parsed = ConfigFileSchema.parse(jsonData);
|
|
585
709
|
const { $schema: _schema, ...configParams } = parsed;
|
|
710
|
+
assertTargetsFeaturesExclusive({
|
|
711
|
+
targets: configParams.targets,
|
|
712
|
+
features: configParams.features
|
|
713
|
+
});
|
|
586
714
|
return configParams;
|
|
587
715
|
};
|
|
588
716
|
var mergeConfigs = (baseConfig, localConfig) => {
|
|
@@ -626,14 +754,35 @@ var ConfigResolver = class {
|
|
|
626
754
|
const localConfigPath = join3(configDir, RULESYNC_LOCAL_CONFIG_RELATIVE_FILE_PATH);
|
|
627
755
|
const localConfig = await loadConfigFromFile(localConfigPath);
|
|
628
756
|
const configByFile = mergeConfigs(baseConfig, localConfig);
|
|
757
|
+
try {
|
|
758
|
+
assertTargetsFeaturesExclusive({
|
|
759
|
+
targets: configByFile.targets,
|
|
760
|
+
features: configByFile.features
|
|
761
|
+
});
|
|
762
|
+
} catch (error) {
|
|
763
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
764
|
+
throw new Error(
|
|
765
|
+
`${detail} (detected after merging '${validatedConfigPath}' with '${localConfigPath}' \u2014 the two files combined produce the invalid combination; remove the conflicting field from one of them).`,
|
|
766
|
+
{ cause: error }
|
|
767
|
+
);
|
|
768
|
+
}
|
|
629
769
|
const resolvedGlobal = global ?? configByFile.global ?? getDefaults().global;
|
|
630
770
|
const resolvedSimulateCommands = simulateCommands ?? configByFile.simulateCommands ?? getDefaults().simulateCommands;
|
|
631
771
|
const resolvedSimulateSubagents = simulateSubagents ?? configByFile.simulateSubagents ?? getDefaults().simulateSubagents;
|
|
632
772
|
const resolvedSimulateSkills = simulateSkills ?? configByFile.simulateSkills ?? getDefaults().simulateSkills;
|
|
633
773
|
const resolvedGitignoreTargetsOnly = gitignoreTargetsOnly ?? configByFile.gitignoreTargetsOnly ?? getDefaults().gitignoreTargetsOnly;
|
|
774
|
+
const userProvidedFeatures = features ?? configByFile.features;
|
|
775
|
+
const userProvidedTargets = targets ?? configByFile.targets;
|
|
776
|
+
const targetsIsObject = userProvidedTargets !== void 0 && !Array.isArray(userProvidedTargets);
|
|
777
|
+
const featuresIsObject = userProvidedFeatures !== void 0 && !Array.isArray(userProvidedFeatures);
|
|
778
|
+
if (featuresIsObject) {
|
|
779
|
+
emitFeaturesObjectFormDeprecationWarning();
|
|
780
|
+
}
|
|
781
|
+
const resolvedFeatures = userProvidedFeatures ?? (targetsIsObject ? void 0 : getDefaults().features);
|
|
782
|
+
const resolvedTargets = userProvidedTargets ?? (featuresIsObject ? void 0 : getDefaults().targets);
|
|
634
783
|
const configParams = {
|
|
635
|
-
targets:
|
|
636
|
-
features:
|
|
784
|
+
targets: resolvedTargets,
|
|
785
|
+
features: resolvedFeatures,
|
|
637
786
|
verbose: verbose ?? configByFile.verbose ?? getDefaults().verbose,
|
|
638
787
|
delete: isDelete ?? configByFile.delete ?? getDefaults().delete,
|
|
639
788
|
baseDirs: getBaseDirsInLightOfGlobal({
|
package/dist/cli/index.cjs
CHANGED
|
@@ -44,12 +44,13 @@ var FeaturesSchema = import_mini.z.array(FeatureSchema);
|
|
|
44
44
|
var FeatureOptionsSchema = import_mini.z.record(import_mini.z.string(), import_mini.z.unknown());
|
|
45
45
|
var FeatureValueSchema = import_mini.z.union([import_mini.z.boolean(), FeatureOptionsSchema]);
|
|
46
46
|
var PerFeatureConfigSchema = import_mini.z.record(import_mini.z.string(), FeatureValueSchema);
|
|
47
|
+
var PerTargetFeaturesValueSchema = import_mini.z.union([
|
|
48
|
+
import_mini.z.array(import_mini.z.enum(ALL_FEATURES_WITH_WILDCARD)),
|
|
49
|
+
PerFeatureConfigSchema
|
|
50
|
+
]);
|
|
47
51
|
var RulesyncFeaturesSchema = import_mini.z.union([
|
|
48
52
|
import_mini.z.array(import_mini.z.enum(ALL_FEATURES_WITH_WILDCARD)),
|
|
49
|
-
import_mini.z.record(
|
|
50
|
-
import_mini.z.string(),
|
|
51
|
-
import_mini.z.union([import_mini.z.array(import_mini.z.enum(ALL_FEATURES_WITH_WILDCARD)), PerFeatureConfigSchema])
|
|
52
|
-
)
|
|
53
|
+
import_mini.z.record(import_mini.z.string(), PerTargetFeaturesValueSchema)
|
|
53
54
|
]);
|
|
54
55
|
var isFeatureValueEnabled = (value) => {
|
|
55
56
|
if (value === true) return true;
|
|
@@ -951,6 +952,14 @@ var ALL_TOOL_TARGETS_WITH_WILDCARD = [...ALL_TOOL_TARGETS, "*"];
|
|
|
951
952
|
var ToolTargetSchema = import_mini3.z.enum(ALL_TOOL_TARGETS);
|
|
952
953
|
var ToolTargetsSchema = import_mini3.z.array(ToolTargetSchema);
|
|
953
954
|
var RulesyncTargetsSchema = import_mini3.z.array(import_mini3.z.enum(ALL_TOOL_TARGETS_WITH_WILDCARD));
|
|
955
|
+
var RulesyncConfigTargetsObjectSchema = import_mini3.z.record(import_mini3.z.string(), PerTargetFeaturesValueSchema);
|
|
956
|
+
var RulesyncConfigTargetsSchema = import_mini3.z.union([
|
|
957
|
+
RulesyncTargetsSchema,
|
|
958
|
+
RulesyncConfigTargetsObjectSchema
|
|
959
|
+
]);
|
|
960
|
+
var isRulesyncConfigTargetsObject = (value) => {
|
|
961
|
+
return !Array.isArray(value);
|
|
962
|
+
};
|
|
954
963
|
|
|
955
964
|
// src/features/commands/rulesync-command.ts
|
|
956
965
|
var RulesyncCommandFrontmatterSchema = import_mini4.z.looseObject({
|
|
@@ -19994,7 +20003,7 @@ var SourceEntrySchema = import_mini69.z.object({
|
|
|
19994
20003
|
});
|
|
19995
20004
|
var ConfigParamsSchema = import_mini69.z.object({
|
|
19996
20005
|
baseDirs: import_mini69.z.array(import_mini69.z.string()),
|
|
19997
|
-
targets:
|
|
20006
|
+
targets: RulesyncConfigTargetsSchema,
|
|
19998
20007
|
features: RulesyncFeaturesSchema,
|
|
19999
20008
|
verbose: import_mini69.z.boolean(),
|
|
20000
20009
|
delete: import_mini69.z.boolean(),
|
|
@@ -20021,10 +20030,42 @@ var CONFLICTING_TARGET_PAIRS = [
|
|
|
20021
20030
|
["claudecode", "claudecode-legacy"]
|
|
20022
20031
|
];
|
|
20023
20032
|
var LEGACY_TARGETS = ["augmentcode-legacy", "claudecode-legacy"];
|
|
20033
|
+
var assertTargetsFeaturesExclusive = ({
|
|
20034
|
+
targets,
|
|
20035
|
+
features
|
|
20036
|
+
}) => {
|
|
20037
|
+
const targetsIsObject = targets !== void 0 && !Array.isArray(targets);
|
|
20038
|
+
const featuresIsObject = features !== void 0 && !Array.isArray(features);
|
|
20039
|
+
if (targetsIsObject && features !== void 0) {
|
|
20040
|
+
throw new Error(
|
|
20041
|
+
"Invalid config: when 'targets' is in object form, 'features' must be omitted. Declare per-target features inside the 'targets' object instead."
|
|
20042
|
+
);
|
|
20043
|
+
}
|
|
20044
|
+
if (featuresIsObject && targets !== void 0) {
|
|
20045
|
+
throw new Error(
|
|
20046
|
+
"Invalid config: when 'features' is in object form, 'targets' must be omitted. Migrate to the 'targets' object form, e.g. `targets: { claudecode: [...] }`."
|
|
20047
|
+
);
|
|
20048
|
+
}
|
|
20049
|
+
};
|
|
20050
|
+
var assertTargetsOrFeaturesProvided = ({
|
|
20051
|
+
targets,
|
|
20052
|
+
features
|
|
20053
|
+
}) => {
|
|
20054
|
+
if (targets === void 0 && features === void 0) {
|
|
20055
|
+
throw new Error("Invalid config: at least one of 'targets' or 'features' must be provided.");
|
|
20056
|
+
}
|
|
20057
|
+
};
|
|
20024
20058
|
var Config = class _Config {
|
|
20025
20059
|
baseDirs;
|
|
20026
20060
|
targets;
|
|
20027
20061
|
features;
|
|
20062
|
+
/**
|
|
20063
|
+
* Cached list of validated `ToolTarget` keys for the object form of
|
|
20064
|
+
* `targets`. Populated in the constructor after `validateObjectFormTargetKeys`
|
|
20065
|
+
* so `getTargets()` does not rebuild the `ALL_TOOL_TARGETS` set on every call.
|
|
20066
|
+
* Undefined when `this.targets` is in array form.
|
|
20067
|
+
*/
|
|
20068
|
+
objectFormTargetKeys;
|
|
20028
20069
|
verbose;
|
|
20029
20070
|
delete;
|
|
20030
20071
|
global;
|
|
@@ -20052,13 +20093,19 @@ var Config = class _Config {
|
|
|
20052
20093
|
check,
|
|
20053
20094
|
sources
|
|
20054
20095
|
}) {
|
|
20055
|
-
|
|
20096
|
+
assertTargetsFeaturesExclusive({ targets, features });
|
|
20097
|
+
assertTargetsOrFeaturesProvided({ targets, features });
|
|
20098
|
+
const resolvedTargets = targets ?? [];
|
|
20099
|
+
const resolvedFeatures = features ?? [];
|
|
20100
|
+
this.validateObjectFormTargetKeys(resolvedTargets);
|
|
20101
|
+
this.validateConflictingTargets(resolvedTargets);
|
|
20056
20102
|
if (dryRun && check) {
|
|
20057
20103
|
throw new Error("--dry-run and --check cannot be used together");
|
|
20058
20104
|
}
|
|
20059
20105
|
this.baseDirs = baseDirs;
|
|
20060
|
-
this.targets =
|
|
20061
|
-
this.features =
|
|
20106
|
+
this.targets = resolvedTargets;
|
|
20107
|
+
this.features = resolvedFeatures;
|
|
20108
|
+
this.objectFormTargetKeys = isRulesyncConfigTargetsObject(resolvedTargets) ? _Config.filterValidToolTargets(Object.keys(resolvedTargets)) : void 0;
|
|
20062
20109
|
this.verbose = verbose;
|
|
20063
20110
|
this.delete = isDelete;
|
|
20064
20111
|
this.global = global ?? false;
|
|
@@ -20071,11 +20118,37 @@ var Config = class _Config {
|
|
|
20071
20118
|
this.check = check ?? false;
|
|
20072
20119
|
this.sources = sources ?? [];
|
|
20073
20120
|
}
|
|
20121
|
+
/**
|
|
20122
|
+
* Rejects unknown keys (and the special `*` key) in the object form of
|
|
20123
|
+
* `targets`. For the array form this is already enforced at the Zod schema
|
|
20124
|
+
* level via `z.enum(ALL_TOOL_TARGETS_WITH_WILDCARD)`; for the object form
|
|
20125
|
+
* `z.record(z.string(), ...)` intentionally accepts any string key (to work
|
|
20126
|
+
* around zod's `z.record(z.enum(...))` requiring ALL enum members), so
|
|
20127
|
+
* runtime validation lives here instead.
|
|
20128
|
+
*/
|
|
20129
|
+
validateObjectFormTargetKeys(targets) {
|
|
20130
|
+
if (Array.isArray(targets)) return;
|
|
20131
|
+
const validTargets = new Set(ALL_TOOL_TARGETS);
|
|
20132
|
+
for (const key of Object.keys(targets)) {
|
|
20133
|
+
if (key === "*") {
|
|
20134
|
+
throw new Error(
|
|
20135
|
+
"Invalid target '*' in object form: wildcard is only supported in the array form `targets: ['*']`. Per-target options cannot be attached to a wildcard."
|
|
20136
|
+
);
|
|
20137
|
+
}
|
|
20138
|
+
if (!validTargets.has(key)) {
|
|
20139
|
+
throw new Error(`Unknown target '${key}'. Valid targets: ${ALL_TOOL_TARGETS.join(", ")}.`);
|
|
20140
|
+
}
|
|
20141
|
+
}
|
|
20142
|
+
}
|
|
20074
20143
|
validateConflictingTargets(targets) {
|
|
20144
|
+
const has = (target) => {
|
|
20145
|
+
if (Array.isArray(targets)) {
|
|
20146
|
+
return targets.includes(target);
|
|
20147
|
+
}
|
|
20148
|
+
return Object.prototype.hasOwnProperty.call(targets, target);
|
|
20149
|
+
};
|
|
20075
20150
|
for (const [target1, target2] of CONFLICTING_TARGET_PAIRS) {
|
|
20076
|
-
|
|
20077
|
-
const hasTarget2 = targets.includes(target2);
|
|
20078
|
-
if (hasTarget1 && hasTarget2) {
|
|
20151
|
+
if (has(target1) && has(target2)) {
|
|
20079
20152
|
throw new Error(
|
|
20080
20153
|
`Conflicting targets: '${target1}' and '${target2}' cannot be used together. Please choose one.`
|
|
20081
20154
|
);
|
|
@@ -20085,16 +20158,45 @@ var Config = class _Config {
|
|
|
20085
20158
|
getBaseDirs() {
|
|
20086
20159
|
return this.baseDirs;
|
|
20087
20160
|
}
|
|
20161
|
+
/**
|
|
20162
|
+
* Filter an arbitrary string-key list down to the known `ToolTarget` set,
|
|
20163
|
+
* skipping `*` (which is only meaningful as an array element, not a key).
|
|
20164
|
+
*/
|
|
20165
|
+
static filterValidToolTargets(keys) {
|
|
20166
|
+
const validTargets = new Set(ALL_TOOL_TARGETS);
|
|
20167
|
+
const result = [];
|
|
20168
|
+
for (const key of keys) {
|
|
20169
|
+
if (key === "*") continue;
|
|
20170
|
+
if (!validTargets.has(key)) continue;
|
|
20171
|
+
result.push(key);
|
|
20172
|
+
}
|
|
20173
|
+
return result;
|
|
20174
|
+
}
|
|
20088
20175
|
getTargets() {
|
|
20089
|
-
if (this.
|
|
20176
|
+
if (this.objectFormTargetKeys !== void 0) {
|
|
20177
|
+
return this.objectFormTargetKeys;
|
|
20178
|
+
}
|
|
20179
|
+
const arrayTargets = Array.isArray(this.targets) ? this.targets : [];
|
|
20180
|
+
if (!Array.isArray(this.features)) {
|
|
20181
|
+
return _Config.filterValidToolTargets(Object.keys(this.features));
|
|
20182
|
+
}
|
|
20183
|
+
if (arrayTargets.includes("*")) {
|
|
20090
20184
|
return ALL_TOOL_TARGETS.filter(
|
|
20091
20185
|
// eslint-disable-next-line no-type-assertion/no-type-assertion
|
|
20092
20186
|
(target) => !LEGACY_TARGETS.includes(target)
|
|
20093
20187
|
);
|
|
20094
20188
|
}
|
|
20095
|
-
return
|
|
20189
|
+
return arrayTargets.filter((target) => target !== "*");
|
|
20096
20190
|
}
|
|
20097
20191
|
getFeatures(target) {
|
|
20192
|
+
if (isRulesyncConfigTargetsObject(this.targets)) {
|
|
20193
|
+
if (target) {
|
|
20194
|
+
const value = this.targets[target];
|
|
20195
|
+
if (!value) return [];
|
|
20196
|
+
return _Config.normalizeTargetFeatures(value);
|
|
20197
|
+
}
|
|
20198
|
+
return _Config.collectAllFeatures(Object.values(this.targets));
|
|
20199
|
+
}
|
|
20098
20200
|
if (!Array.isArray(this.features)) {
|
|
20099
20201
|
const perTargetFeatures = this.features;
|
|
20100
20202
|
if (target) {
|
|
@@ -20104,20 +20206,7 @@ var Config = class _Config {
|
|
|
20104
20206
|
}
|
|
20105
20207
|
return _Config.normalizeTargetFeatures(targetFeatures);
|
|
20106
20208
|
}
|
|
20107
|
-
|
|
20108
|
-
for (const features of Object.values(perTargetFeatures)) {
|
|
20109
|
-
if (!features) continue;
|
|
20110
|
-
const normalized = _Config.normalizeTargetFeatures(features);
|
|
20111
|
-
for (const feature of normalized) {
|
|
20112
|
-
if (!allFeatures.includes(feature)) {
|
|
20113
|
-
allFeatures.push(feature);
|
|
20114
|
-
}
|
|
20115
|
-
}
|
|
20116
|
-
if (allFeatures.length === ALL_FEATURES.length) {
|
|
20117
|
-
return allFeatures;
|
|
20118
|
-
}
|
|
20119
|
-
}
|
|
20120
|
-
return allFeatures;
|
|
20209
|
+
return _Config.collectAllFeatures(Object.values(perTargetFeatures));
|
|
20121
20210
|
}
|
|
20122
20211
|
if (this.features.includes("*")) {
|
|
20123
20212
|
return [...ALL_FEATURES];
|
|
@@ -20145,23 +20234,40 @@ var Config = class _Config {
|
|
|
20145
20234
|
}
|
|
20146
20235
|
return enabled;
|
|
20147
20236
|
}
|
|
20237
|
+
/**
|
|
20238
|
+
* Collect the union of features across all per-target values.
|
|
20239
|
+
* Used when `getFeatures()` is called without a target in object mode.
|
|
20240
|
+
*/
|
|
20241
|
+
static collectAllFeatures(values) {
|
|
20242
|
+
const allFeatures = [];
|
|
20243
|
+
for (const value of values) {
|
|
20244
|
+
if (!value) continue;
|
|
20245
|
+
const normalized = _Config.normalizeTargetFeatures(value);
|
|
20246
|
+
for (const feature of normalized) {
|
|
20247
|
+
if (!allFeatures.includes(feature)) {
|
|
20248
|
+
allFeatures.push(feature);
|
|
20249
|
+
}
|
|
20250
|
+
}
|
|
20251
|
+
if (allFeatures.length === ALL_FEATURES.length) {
|
|
20252
|
+
return allFeatures;
|
|
20253
|
+
}
|
|
20254
|
+
}
|
|
20255
|
+
return allFeatures;
|
|
20256
|
+
}
|
|
20148
20257
|
/**
|
|
20149
20258
|
* Returns the per-feature options object for a given target/feature, if any.
|
|
20150
20259
|
* Returns `undefined` when no per-feature options were provided or when the
|
|
20151
20260
|
* feature is not enabled for the given target.
|
|
20152
20261
|
*/
|
|
20153
20262
|
getFeatureOptions(target, feature) {
|
|
20154
|
-
|
|
20155
|
-
|
|
20156
|
-
}
|
|
20157
|
-
const targetFeatures = this.features[target];
|
|
20158
|
-
if (!targetFeatures || Array.isArray(targetFeatures)) {
|
|
20263
|
+
const value = isRulesyncConfigTargetsObject(this.targets) ? this.targets[target] : !Array.isArray(this.features) ? this.features[target] : void 0;
|
|
20264
|
+
if (!value || Array.isArray(value)) {
|
|
20159
20265
|
return void 0;
|
|
20160
20266
|
}
|
|
20161
|
-
const perFeature =
|
|
20162
|
-
const
|
|
20163
|
-
if (
|
|
20164
|
-
return
|
|
20267
|
+
const perFeature = value;
|
|
20268
|
+
const featureValue = perFeature[feature];
|
|
20269
|
+
if (featureValue && typeof featureValue === "object" && isFeatureValueEnabled(featureValue)) {
|
|
20270
|
+
return featureValue;
|
|
20165
20271
|
}
|
|
20166
20272
|
return void 0;
|
|
20167
20273
|
}
|
|
@@ -20169,6 +20275,13 @@ var Config = class _Config {
|
|
|
20169
20275
|
* Check if per-target features configuration is being used.
|
|
20170
20276
|
*/
|
|
20171
20277
|
hasPerTargetFeatures() {
|
|
20278
|
+
return isRulesyncConfigTargetsObject(this.targets) || !Array.isArray(this.features);
|
|
20279
|
+
}
|
|
20280
|
+
/**
|
|
20281
|
+
* Returns true if the deprecated object form under `features` is in use.
|
|
20282
|
+
* Callers can use this to emit a migration warning.
|
|
20283
|
+
*/
|
|
20284
|
+
hasDeprecatedFeaturesObjectForm() {
|
|
20172
20285
|
return !Array.isArray(this.features);
|
|
20173
20286
|
}
|
|
20174
20287
|
getVerbose() {
|
|
@@ -20213,6 +20326,17 @@ var Config = class _Config {
|
|
|
20213
20326
|
}
|
|
20214
20327
|
};
|
|
20215
20328
|
|
|
20329
|
+
// src/config/deprecation-warnings.ts
|
|
20330
|
+
var deprecationWarningEmitted = false;
|
|
20331
|
+
var emitFeaturesObjectFormDeprecationWarning = () => {
|
|
20332
|
+
if (deprecationWarningEmitted) return;
|
|
20333
|
+
if (process.env.RULESYNC_SILENT_DEPRECATION) return;
|
|
20334
|
+
deprecationWarningEmitted = true;
|
|
20335
|
+
console.warn(
|
|
20336
|
+
"[rulesync] DEPRECATED: 'features' object form is deprecated. Use the new 'targets' object form instead: `targets: { claudecode: { rules: true, ignore: { fileMode: 'local' } } }`. See https://github.com/dyoshikawa/rulesync/blob/main/docs/guide/configuration.md for the migration guide."
|
|
20337
|
+
);
|
|
20338
|
+
};
|
|
20339
|
+
|
|
20216
20340
|
// src/config/config-resolver.ts
|
|
20217
20341
|
var getDefaults = () => ({
|
|
20218
20342
|
targets: ["agentsmd"],
|
|
@@ -20239,6 +20363,10 @@ var loadConfigFromFile = async (filePath) => {
|
|
|
20239
20363
|
const jsonData = (0, import_jsonc_parser4.parse)(fileContent);
|
|
20240
20364
|
const parsed = ConfigFileSchema.parse(jsonData);
|
|
20241
20365
|
const { $schema: _schema, ...configParams } = parsed;
|
|
20366
|
+
assertTargetsFeaturesExclusive({
|
|
20367
|
+
targets: configParams.targets,
|
|
20368
|
+
features: configParams.features
|
|
20369
|
+
});
|
|
20242
20370
|
return configParams;
|
|
20243
20371
|
};
|
|
20244
20372
|
var mergeConfigs = (baseConfig, localConfig) => {
|
|
@@ -20282,14 +20410,35 @@ var ConfigResolver = class {
|
|
|
20282
20410
|
const localConfigPath = (0, import_node_path134.join)(configDir, RULESYNC_LOCAL_CONFIG_RELATIVE_FILE_PATH);
|
|
20283
20411
|
const localConfig = await loadConfigFromFile(localConfigPath);
|
|
20284
20412
|
const configByFile = mergeConfigs(baseConfig, localConfig);
|
|
20413
|
+
try {
|
|
20414
|
+
assertTargetsFeaturesExclusive({
|
|
20415
|
+
targets: configByFile.targets,
|
|
20416
|
+
features: configByFile.features
|
|
20417
|
+
});
|
|
20418
|
+
} catch (error) {
|
|
20419
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
20420
|
+
throw new Error(
|
|
20421
|
+
`${detail} (detected after merging '${validatedConfigPath}' with '${localConfigPath}' \u2014 the two files combined produce the invalid combination; remove the conflicting field from one of them).`,
|
|
20422
|
+
{ cause: error }
|
|
20423
|
+
);
|
|
20424
|
+
}
|
|
20285
20425
|
const resolvedGlobal = global ?? configByFile.global ?? getDefaults().global;
|
|
20286
20426
|
const resolvedSimulateCommands = simulateCommands ?? configByFile.simulateCommands ?? getDefaults().simulateCommands;
|
|
20287
20427
|
const resolvedSimulateSubagents = simulateSubagents ?? configByFile.simulateSubagents ?? getDefaults().simulateSubagents;
|
|
20288
20428
|
const resolvedSimulateSkills = simulateSkills ?? configByFile.simulateSkills ?? getDefaults().simulateSkills;
|
|
20289
20429
|
const resolvedGitignoreTargetsOnly = gitignoreTargetsOnly ?? configByFile.gitignoreTargetsOnly ?? getDefaults().gitignoreTargetsOnly;
|
|
20430
|
+
const userProvidedFeatures = features ?? configByFile.features;
|
|
20431
|
+
const userProvidedTargets = targets ?? configByFile.targets;
|
|
20432
|
+
const targetsIsObject = userProvidedTargets !== void 0 && !Array.isArray(userProvidedTargets);
|
|
20433
|
+
const featuresIsObject = userProvidedFeatures !== void 0 && !Array.isArray(userProvidedFeatures);
|
|
20434
|
+
if (featuresIsObject) {
|
|
20435
|
+
emitFeaturesObjectFormDeprecationWarning();
|
|
20436
|
+
}
|
|
20437
|
+
const resolvedFeatures = userProvidedFeatures ?? (targetsIsObject ? void 0 : getDefaults().features);
|
|
20438
|
+
const resolvedTargets = userProvidedTargets ?? (featuresIsObject ? void 0 : getDefaults().targets);
|
|
20290
20439
|
const configParams = {
|
|
20291
|
-
targets:
|
|
20292
|
-
features:
|
|
20440
|
+
targets: resolvedTargets,
|
|
20441
|
+
features: resolvedFeatures,
|
|
20293
20442
|
verbose: verbose ?? configByFile.verbose ?? getDefaults().verbose,
|
|
20294
20443
|
delete: isDelete ?? configByFile.delete ?? getDefaults().delete,
|
|
20295
20444
|
baseDirs: getBaseDirsInLightOfGlobal({
|
|
@@ -22510,6 +22659,12 @@ async function importCommand(logger5, options) {
|
|
|
22510
22659
|
if (!options.targets) {
|
|
22511
22660
|
throw new CLIError("No tools found in --targets", ErrorCodes.IMPORT_FAILED);
|
|
22512
22661
|
}
|
|
22662
|
+
if (!Array.isArray(options.targets)) {
|
|
22663
|
+
throw new CLIError(
|
|
22664
|
+
"--targets object form is not supported on the command line",
|
|
22665
|
+
ErrorCodes.IMPORT_FAILED
|
|
22666
|
+
);
|
|
22667
|
+
}
|
|
22513
22668
|
if (options.targets.length > 1) {
|
|
22514
22669
|
throw new CLIError("Only one tool can be imported at a time", ErrorCodes.IMPORT_FAILED);
|
|
22515
22670
|
}
|
|
@@ -25210,7 +25365,11 @@ var resolveGitignoreTargets = async ({
|
|
|
25210
25365
|
}
|
|
25211
25366
|
const config = await ConfigResolver.resolve({});
|
|
25212
25367
|
if (config.getGitignoreTargetsOnly()) {
|
|
25213
|
-
|
|
25368
|
+
const targets = config.getTargets();
|
|
25369
|
+
if (targets.includes("agentsmd")) {
|
|
25370
|
+
return targets;
|
|
25371
|
+
}
|
|
25372
|
+
return [...targets, "agentsmd"];
|
|
25214
25373
|
}
|
|
25215
25374
|
return void 0;
|
|
25216
25375
|
};
|
|
@@ -25617,7 +25776,7 @@ function wrapCommand({
|
|
|
25617
25776
|
}
|
|
25618
25777
|
|
|
25619
25778
|
// src/cli/index.ts
|
|
25620
|
-
var getVersion = () => "8.
|
|
25779
|
+
var getVersion = () => "8.2.0";
|
|
25621
25780
|
function wrapCommand2(name, errorCode, handler) {
|
|
25622
25781
|
return wrapCommand({ name, errorCode, handler, getVersion });
|
|
25623
25782
|
}
|
package/dist/cli/index.js
CHANGED
|
@@ -73,7 +73,7 @@ import {
|
|
|
73
73
|
stringifyFrontmatter,
|
|
74
74
|
toPosixPath,
|
|
75
75
|
writeFileContent
|
|
76
|
-
} from "../chunk-
|
|
76
|
+
} from "../chunk-K4IN6URH.js";
|
|
77
77
|
|
|
78
78
|
// src/cli/index.ts
|
|
79
79
|
import { Command } from "commander";
|
|
@@ -1552,6 +1552,12 @@ async function importCommand(logger5, options) {
|
|
|
1552
1552
|
if (!options.targets) {
|
|
1553
1553
|
throw new CLIError("No tools found in --targets", ErrorCodes.IMPORT_FAILED);
|
|
1554
1554
|
}
|
|
1555
|
+
if (!Array.isArray(options.targets)) {
|
|
1556
|
+
throw new CLIError(
|
|
1557
|
+
"--targets object form is not supported on the command line",
|
|
1558
|
+
ErrorCodes.IMPORT_FAILED
|
|
1559
|
+
);
|
|
1560
|
+
}
|
|
1555
1561
|
if (options.targets.length > 1) {
|
|
1556
1562
|
throw new CLIError("Only one tool can be imported at a time", ErrorCodes.IMPORT_FAILED);
|
|
1557
1563
|
}
|
|
@@ -4106,7 +4112,11 @@ var resolveGitignoreTargets = async ({
|
|
|
4106
4112
|
}
|
|
4107
4113
|
const config = await ConfigResolver.resolve({});
|
|
4108
4114
|
if (config.getGitignoreTargetsOnly()) {
|
|
4109
|
-
|
|
4115
|
+
const targets = config.getTargets();
|
|
4116
|
+
if (targets.includes("agentsmd")) {
|
|
4117
|
+
return targets;
|
|
4118
|
+
}
|
|
4119
|
+
return [...targets, "agentsmd"];
|
|
4110
4120
|
}
|
|
4111
4121
|
return void 0;
|
|
4112
4122
|
};
|
|
@@ -4513,7 +4523,7 @@ function wrapCommand({
|
|
|
4513
4523
|
}
|
|
4514
4524
|
|
|
4515
4525
|
// src/cli/index.ts
|
|
4516
|
-
var getVersion = () => "8.
|
|
4526
|
+
var getVersion = () => "8.2.0";
|
|
4517
4527
|
function wrapCommand2(name, errorCode, handler) {
|
|
4518
4528
|
return wrapCommand({ name, errorCode, handler, getVersion });
|
|
4519
4529
|
}
|
package/dist/index.cjs
CHANGED
|
@@ -262,12 +262,13 @@ var FeaturesSchema = import_mini.z.array(FeatureSchema);
|
|
|
262
262
|
var FeatureOptionsSchema = import_mini.z.record(import_mini.z.string(), import_mini.z.unknown());
|
|
263
263
|
var FeatureValueSchema = import_mini.z.union([import_mini.z.boolean(), FeatureOptionsSchema]);
|
|
264
264
|
var PerFeatureConfigSchema = import_mini.z.record(import_mini.z.string(), FeatureValueSchema);
|
|
265
|
+
var PerTargetFeaturesValueSchema = import_mini.z.union([
|
|
266
|
+
import_mini.z.array(import_mini.z.enum(ALL_FEATURES_WITH_WILDCARD)),
|
|
267
|
+
PerFeatureConfigSchema
|
|
268
|
+
]);
|
|
265
269
|
var RulesyncFeaturesSchema = import_mini.z.union([
|
|
266
270
|
import_mini.z.array(import_mini.z.enum(ALL_FEATURES_WITH_WILDCARD)),
|
|
267
|
-
import_mini.z.record(
|
|
268
|
-
import_mini.z.string(),
|
|
269
|
-
import_mini.z.union([import_mini.z.array(import_mini.z.enum(ALL_FEATURES_WITH_WILDCARD)), PerFeatureConfigSchema])
|
|
270
|
-
)
|
|
271
|
+
import_mini.z.record(import_mini.z.string(), PerTargetFeaturesValueSchema)
|
|
271
272
|
]);
|
|
272
273
|
var isFeatureValueEnabled = (value) => {
|
|
273
274
|
if (value === true) return true;
|
|
@@ -310,6 +311,14 @@ var ALL_TOOL_TARGETS_WITH_WILDCARD = [...ALL_TOOL_TARGETS, "*"];
|
|
|
310
311
|
var ToolTargetSchema = import_mini2.z.enum(ALL_TOOL_TARGETS);
|
|
311
312
|
var ToolTargetsSchema = import_mini2.z.array(ToolTargetSchema);
|
|
312
313
|
var RulesyncTargetsSchema = import_mini2.z.array(import_mini2.z.enum(ALL_TOOL_TARGETS_WITH_WILDCARD));
|
|
314
|
+
var RulesyncConfigTargetsObjectSchema = import_mini2.z.record(import_mini2.z.string(), PerTargetFeaturesValueSchema);
|
|
315
|
+
var RulesyncConfigTargetsSchema = import_mini2.z.union([
|
|
316
|
+
RulesyncTargetsSchema,
|
|
317
|
+
RulesyncConfigTargetsObjectSchema
|
|
318
|
+
]);
|
|
319
|
+
var isRulesyncConfigTargetsObject = (value) => {
|
|
320
|
+
return !Array.isArray(value);
|
|
321
|
+
};
|
|
313
322
|
|
|
314
323
|
// src/utils/validation.ts
|
|
315
324
|
function findControlCharacter(value) {
|
|
@@ -346,7 +355,7 @@ var SourceEntrySchema = import_mini3.z.object({
|
|
|
346
355
|
});
|
|
347
356
|
var ConfigParamsSchema = import_mini3.z.object({
|
|
348
357
|
baseDirs: import_mini3.z.array(import_mini3.z.string()),
|
|
349
|
-
targets:
|
|
358
|
+
targets: RulesyncConfigTargetsSchema,
|
|
350
359
|
features: RulesyncFeaturesSchema,
|
|
351
360
|
verbose: import_mini3.z.boolean(),
|
|
352
361
|
delete: import_mini3.z.boolean(),
|
|
@@ -373,10 +382,42 @@ var CONFLICTING_TARGET_PAIRS = [
|
|
|
373
382
|
["claudecode", "claudecode-legacy"]
|
|
374
383
|
];
|
|
375
384
|
var LEGACY_TARGETS = ["augmentcode-legacy", "claudecode-legacy"];
|
|
385
|
+
var assertTargetsFeaturesExclusive = ({
|
|
386
|
+
targets,
|
|
387
|
+
features
|
|
388
|
+
}) => {
|
|
389
|
+
const targetsIsObject = targets !== void 0 && !Array.isArray(targets);
|
|
390
|
+
const featuresIsObject = features !== void 0 && !Array.isArray(features);
|
|
391
|
+
if (targetsIsObject && features !== void 0) {
|
|
392
|
+
throw new Error(
|
|
393
|
+
"Invalid config: when 'targets' is in object form, 'features' must be omitted. Declare per-target features inside the 'targets' object instead."
|
|
394
|
+
);
|
|
395
|
+
}
|
|
396
|
+
if (featuresIsObject && targets !== void 0) {
|
|
397
|
+
throw new Error(
|
|
398
|
+
"Invalid config: when 'features' is in object form, 'targets' must be omitted. Migrate to the 'targets' object form, e.g. `targets: { claudecode: [...] }`."
|
|
399
|
+
);
|
|
400
|
+
}
|
|
401
|
+
};
|
|
402
|
+
var assertTargetsOrFeaturesProvided = ({
|
|
403
|
+
targets,
|
|
404
|
+
features
|
|
405
|
+
}) => {
|
|
406
|
+
if (targets === void 0 && features === void 0) {
|
|
407
|
+
throw new Error("Invalid config: at least one of 'targets' or 'features' must be provided.");
|
|
408
|
+
}
|
|
409
|
+
};
|
|
376
410
|
var Config = class _Config {
|
|
377
411
|
baseDirs;
|
|
378
412
|
targets;
|
|
379
413
|
features;
|
|
414
|
+
/**
|
|
415
|
+
* Cached list of validated `ToolTarget` keys for the object form of
|
|
416
|
+
* `targets`. Populated in the constructor after `validateObjectFormTargetKeys`
|
|
417
|
+
* so `getTargets()` does not rebuild the `ALL_TOOL_TARGETS` set on every call.
|
|
418
|
+
* Undefined when `this.targets` is in array form.
|
|
419
|
+
*/
|
|
420
|
+
objectFormTargetKeys;
|
|
380
421
|
verbose;
|
|
381
422
|
delete;
|
|
382
423
|
global;
|
|
@@ -404,13 +445,19 @@ var Config = class _Config {
|
|
|
404
445
|
check,
|
|
405
446
|
sources
|
|
406
447
|
}) {
|
|
407
|
-
|
|
448
|
+
assertTargetsFeaturesExclusive({ targets, features });
|
|
449
|
+
assertTargetsOrFeaturesProvided({ targets, features });
|
|
450
|
+
const resolvedTargets = targets ?? [];
|
|
451
|
+
const resolvedFeatures = features ?? [];
|
|
452
|
+
this.validateObjectFormTargetKeys(resolvedTargets);
|
|
453
|
+
this.validateConflictingTargets(resolvedTargets);
|
|
408
454
|
if (dryRun && check) {
|
|
409
455
|
throw new Error("--dry-run and --check cannot be used together");
|
|
410
456
|
}
|
|
411
457
|
this.baseDirs = baseDirs;
|
|
412
|
-
this.targets =
|
|
413
|
-
this.features =
|
|
458
|
+
this.targets = resolvedTargets;
|
|
459
|
+
this.features = resolvedFeatures;
|
|
460
|
+
this.objectFormTargetKeys = isRulesyncConfigTargetsObject(resolvedTargets) ? _Config.filterValidToolTargets(Object.keys(resolvedTargets)) : void 0;
|
|
414
461
|
this.verbose = verbose;
|
|
415
462
|
this.delete = isDelete;
|
|
416
463
|
this.global = global ?? false;
|
|
@@ -423,11 +470,37 @@ var Config = class _Config {
|
|
|
423
470
|
this.check = check ?? false;
|
|
424
471
|
this.sources = sources ?? [];
|
|
425
472
|
}
|
|
473
|
+
/**
|
|
474
|
+
* Rejects unknown keys (and the special `*` key) in the object form of
|
|
475
|
+
* `targets`. For the array form this is already enforced at the Zod schema
|
|
476
|
+
* level via `z.enum(ALL_TOOL_TARGETS_WITH_WILDCARD)`; for the object form
|
|
477
|
+
* `z.record(z.string(), ...)` intentionally accepts any string key (to work
|
|
478
|
+
* around zod's `z.record(z.enum(...))` requiring ALL enum members), so
|
|
479
|
+
* runtime validation lives here instead.
|
|
480
|
+
*/
|
|
481
|
+
validateObjectFormTargetKeys(targets) {
|
|
482
|
+
if (Array.isArray(targets)) return;
|
|
483
|
+
const validTargets = new Set(ALL_TOOL_TARGETS);
|
|
484
|
+
for (const key of Object.keys(targets)) {
|
|
485
|
+
if (key === "*") {
|
|
486
|
+
throw new Error(
|
|
487
|
+
"Invalid target '*' in object form: wildcard is only supported in the array form `targets: ['*']`. Per-target options cannot be attached to a wildcard."
|
|
488
|
+
);
|
|
489
|
+
}
|
|
490
|
+
if (!validTargets.has(key)) {
|
|
491
|
+
throw new Error(`Unknown target '${key}'. Valid targets: ${ALL_TOOL_TARGETS.join(", ")}.`);
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
}
|
|
426
495
|
validateConflictingTargets(targets) {
|
|
496
|
+
const has = (target) => {
|
|
497
|
+
if (Array.isArray(targets)) {
|
|
498
|
+
return targets.includes(target);
|
|
499
|
+
}
|
|
500
|
+
return Object.prototype.hasOwnProperty.call(targets, target);
|
|
501
|
+
};
|
|
427
502
|
for (const [target1, target2] of CONFLICTING_TARGET_PAIRS) {
|
|
428
|
-
|
|
429
|
-
const hasTarget2 = targets.includes(target2);
|
|
430
|
-
if (hasTarget1 && hasTarget2) {
|
|
503
|
+
if (has(target1) && has(target2)) {
|
|
431
504
|
throw new Error(
|
|
432
505
|
`Conflicting targets: '${target1}' and '${target2}' cannot be used together. Please choose one.`
|
|
433
506
|
);
|
|
@@ -437,16 +510,45 @@ var Config = class _Config {
|
|
|
437
510
|
getBaseDirs() {
|
|
438
511
|
return this.baseDirs;
|
|
439
512
|
}
|
|
513
|
+
/**
|
|
514
|
+
* Filter an arbitrary string-key list down to the known `ToolTarget` set,
|
|
515
|
+
* skipping `*` (which is only meaningful as an array element, not a key).
|
|
516
|
+
*/
|
|
517
|
+
static filterValidToolTargets(keys) {
|
|
518
|
+
const validTargets = new Set(ALL_TOOL_TARGETS);
|
|
519
|
+
const result = [];
|
|
520
|
+
for (const key of keys) {
|
|
521
|
+
if (key === "*") continue;
|
|
522
|
+
if (!validTargets.has(key)) continue;
|
|
523
|
+
result.push(key);
|
|
524
|
+
}
|
|
525
|
+
return result;
|
|
526
|
+
}
|
|
440
527
|
getTargets() {
|
|
441
|
-
if (this.
|
|
528
|
+
if (this.objectFormTargetKeys !== void 0) {
|
|
529
|
+
return this.objectFormTargetKeys;
|
|
530
|
+
}
|
|
531
|
+
const arrayTargets = Array.isArray(this.targets) ? this.targets : [];
|
|
532
|
+
if (!Array.isArray(this.features)) {
|
|
533
|
+
return _Config.filterValidToolTargets(Object.keys(this.features));
|
|
534
|
+
}
|
|
535
|
+
if (arrayTargets.includes("*")) {
|
|
442
536
|
return ALL_TOOL_TARGETS.filter(
|
|
443
537
|
// eslint-disable-next-line no-type-assertion/no-type-assertion
|
|
444
538
|
(target) => !LEGACY_TARGETS.includes(target)
|
|
445
539
|
);
|
|
446
540
|
}
|
|
447
|
-
return
|
|
541
|
+
return arrayTargets.filter((target) => target !== "*");
|
|
448
542
|
}
|
|
449
543
|
getFeatures(target) {
|
|
544
|
+
if (isRulesyncConfigTargetsObject(this.targets)) {
|
|
545
|
+
if (target) {
|
|
546
|
+
const value = this.targets[target];
|
|
547
|
+
if (!value) return [];
|
|
548
|
+
return _Config.normalizeTargetFeatures(value);
|
|
549
|
+
}
|
|
550
|
+
return _Config.collectAllFeatures(Object.values(this.targets));
|
|
551
|
+
}
|
|
450
552
|
if (!Array.isArray(this.features)) {
|
|
451
553
|
const perTargetFeatures = this.features;
|
|
452
554
|
if (target) {
|
|
@@ -456,20 +558,7 @@ var Config = class _Config {
|
|
|
456
558
|
}
|
|
457
559
|
return _Config.normalizeTargetFeatures(targetFeatures);
|
|
458
560
|
}
|
|
459
|
-
|
|
460
|
-
for (const features of Object.values(perTargetFeatures)) {
|
|
461
|
-
if (!features) continue;
|
|
462
|
-
const normalized = _Config.normalizeTargetFeatures(features);
|
|
463
|
-
for (const feature of normalized) {
|
|
464
|
-
if (!allFeatures.includes(feature)) {
|
|
465
|
-
allFeatures.push(feature);
|
|
466
|
-
}
|
|
467
|
-
}
|
|
468
|
-
if (allFeatures.length === ALL_FEATURES.length) {
|
|
469
|
-
return allFeatures;
|
|
470
|
-
}
|
|
471
|
-
}
|
|
472
|
-
return allFeatures;
|
|
561
|
+
return _Config.collectAllFeatures(Object.values(perTargetFeatures));
|
|
473
562
|
}
|
|
474
563
|
if (this.features.includes("*")) {
|
|
475
564
|
return [...ALL_FEATURES];
|
|
@@ -497,23 +586,40 @@ var Config = class _Config {
|
|
|
497
586
|
}
|
|
498
587
|
return enabled;
|
|
499
588
|
}
|
|
589
|
+
/**
|
|
590
|
+
* Collect the union of features across all per-target values.
|
|
591
|
+
* Used when `getFeatures()` is called without a target in object mode.
|
|
592
|
+
*/
|
|
593
|
+
static collectAllFeatures(values) {
|
|
594
|
+
const allFeatures = [];
|
|
595
|
+
for (const value of values) {
|
|
596
|
+
if (!value) continue;
|
|
597
|
+
const normalized = _Config.normalizeTargetFeatures(value);
|
|
598
|
+
for (const feature of normalized) {
|
|
599
|
+
if (!allFeatures.includes(feature)) {
|
|
600
|
+
allFeatures.push(feature);
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
if (allFeatures.length === ALL_FEATURES.length) {
|
|
604
|
+
return allFeatures;
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
return allFeatures;
|
|
608
|
+
}
|
|
500
609
|
/**
|
|
501
610
|
* Returns the per-feature options object for a given target/feature, if any.
|
|
502
611
|
* Returns `undefined` when no per-feature options were provided or when the
|
|
503
612
|
* feature is not enabled for the given target.
|
|
504
613
|
*/
|
|
505
614
|
getFeatureOptions(target, feature) {
|
|
506
|
-
|
|
615
|
+
const value = isRulesyncConfigTargetsObject(this.targets) ? this.targets[target] : !Array.isArray(this.features) ? this.features[target] : void 0;
|
|
616
|
+
if (!value || Array.isArray(value)) {
|
|
507
617
|
return void 0;
|
|
508
618
|
}
|
|
509
|
-
const
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
const perFeature = targetFeatures;
|
|
514
|
-
const value = perFeature[feature];
|
|
515
|
-
if (value && typeof value === "object" && isFeatureValueEnabled(value)) {
|
|
516
|
-
return value;
|
|
619
|
+
const perFeature = value;
|
|
620
|
+
const featureValue = perFeature[feature];
|
|
621
|
+
if (featureValue && typeof featureValue === "object" && isFeatureValueEnabled(featureValue)) {
|
|
622
|
+
return featureValue;
|
|
517
623
|
}
|
|
518
624
|
return void 0;
|
|
519
625
|
}
|
|
@@ -521,6 +627,13 @@ var Config = class _Config {
|
|
|
521
627
|
* Check if per-target features configuration is being used.
|
|
522
628
|
*/
|
|
523
629
|
hasPerTargetFeatures() {
|
|
630
|
+
return isRulesyncConfigTargetsObject(this.targets) || !Array.isArray(this.features);
|
|
631
|
+
}
|
|
632
|
+
/**
|
|
633
|
+
* Returns true if the deprecated object form under `features` is in use.
|
|
634
|
+
* Callers can use this to emit a migration warning.
|
|
635
|
+
*/
|
|
636
|
+
hasDeprecatedFeaturesObjectForm() {
|
|
524
637
|
return !Array.isArray(this.features);
|
|
525
638
|
}
|
|
526
639
|
getVerbose() {
|
|
@@ -565,6 +678,17 @@ var Config = class _Config {
|
|
|
565
678
|
}
|
|
566
679
|
};
|
|
567
680
|
|
|
681
|
+
// src/config/deprecation-warnings.ts
|
|
682
|
+
var deprecationWarningEmitted = false;
|
|
683
|
+
var emitFeaturesObjectFormDeprecationWarning = () => {
|
|
684
|
+
if (deprecationWarningEmitted) return;
|
|
685
|
+
if (process.env.RULESYNC_SILENT_DEPRECATION) return;
|
|
686
|
+
deprecationWarningEmitted = true;
|
|
687
|
+
console.warn(
|
|
688
|
+
"[rulesync] DEPRECATED: 'features' object form is deprecated. Use the new 'targets' object form instead: `targets: { claudecode: { rules: true, ignore: { fileMode: 'local' } } }`. See https://github.com/dyoshikawa/rulesync/blob/main/docs/guide/configuration.md for the migration guide."
|
|
689
|
+
);
|
|
690
|
+
};
|
|
691
|
+
|
|
568
692
|
// src/config/config-resolver.ts
|
|
569
693
|
var getDefaults = () => ({
|
|
570
694
|
targets: ["agentsmd"],
|
|
@@ -591,6 +715,10 @@ var loadConfigFromFile = async (filePath) => {
|
|
|
591
715
|
const jsonData = (0, import_jsonc_parser.parse)(fileContent);
|
|
592
716
|
const parsed = ConfigFileSchema.parse(jsonData);
|
|
593
717
|
const { $schema: _schema, ...configParams } = parsed;
|
|
718
|
+
assertTargetsFeaturesExclusive({
|
|
719
|
+
targets: configParams.targets,
|
|
720
|
+
features: configParams.features
|
|
721
|
+
});
|
|
594
722
|
return configParams;
|
|
595
723
|
};
|
|
596
724
|
var mergeConfigs = (baseConfig, localConfig) => {
|
|
@@ -634,14 +762,35 @@ var ConfigResolver = class {
|
|
|
634
762
|
const localConfigPath = (0, import_node_path4.join)(configDir, RULESYNC_LOCAL_CONFIG_RELATIVE_FILE_PATH);
|
|
635
763
|
const localConfig = await loadConfigFromFile(localConfigPath);
|
|
636
764
|
const configByFile = mergeConfigs(baseConfig, localConfig);
|
|
765
|
+
try {
|
|
766
|
+
assertTargetsFeaturesExclusive({
|
|
767
|
+
targets: configByFile.targets,
|
|
768
|
+
features: configByFile.features
|
|
769
|
+
});
|
|
770
|
+
} catch (error) {
|
|
771
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
772
|
+
throw new Error(
|
|
773
|
+
`${detail} (detected after merging '${validatedConfigPath}' with '${localConfigPath}' \u2014 the two files combined produce the invalid combination; remove the conflicting field from one of them).`,
|
|
774
|
+
{ cause: error }
|
|
775
|
+
);
|
|
776
|
+
}
|
|
637
777
|
const resolvedGlobal = global ?? configByFile.global ?? getDefaults().global;
|
|
638
778
|
const resolvedSimulateCommands = simulateCommands ?? configByFile.simulateCommands ?? getDefaults().simulateCommands;
|
|
639
779
|
const resolvedSimulateSubagents = simulateSubagents ?? configByFile.simulateSubagents ?? getDefaults().simulateSubagents;
|
|
640
780
|
const resolvedSimulateSkills = simulateSkills ?? configByFile.simulateSkills ?? getDefaults().simulateSkills;
|
|
641
781
|
const resolvedGitignoreTargetsOnly = gitignoreTargetsOnly ?? configByFile.gitignoreTargetsOnly ?? getDefaults().gitignoreTargetsOnly;
|
|
782
|
+
const userProvidedFeatures = features ?? configByFile.features;
|
|
783
|
+
const userProvidedTargets = targets ?? configByFile.targets;
|
|
784
|
+
const targetsIsObject = userProvidedTargets !== void 0 && !Array.isArray(userProvidedTargets);
|
|
785
|
+
const featuresIsObject = userProvidedFeatures !== void 0 && !Array.isArray(userProvidedFeatures);
|
|
786
|
+
if (featuresIsObject) {
|
|
787
|
+
emitFeaturesObjectFormDeprecationWarning();
|
|
788
|
+
}
|
|
789
|
+
const resolvedFeatures = userProvidedFeatures ?? (targetsIsObject ? void 0 : getDefaults().features);
|
|
790
|
+
const resolvedTargets = userProvidedTargets ?? (featuresIsObject ? void 0 : getDefaults().targets);
|
|
642
791
|
const configParams = {
|
|
643
|
-
targets:
|
|
644
|
-
features:
|
|
792
|
+
targets: resolvedTargets,
|
|
793
|
+
features: resolvedFeatures,
|
|
645
794
|
verbose: verbose ?? configByFile.verbose ?? getDefaults().verbose,
|
|
646
795
|
delete: isDelete ?? configByFile.delete ?? getDefaults().delete,
|
|
647
796
|
baseDirs: getBaseDirsInLightOfGlobal({
|
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rulesync",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.2.0",
|
|
4
4
|
"description": "Unified AI rules management CLI tool that generates configuration files for various AI development tools",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai",
|
|
@@ -93,6 +93,7 @@
|
|
|
93
93
|
"simple-git-hooks": "2.13.1",
|
|
94
94
|
"sort-package-json": "3.6.1",
|
|
95
95
|
"tsup": "8.5.1",
|
|
96
|
+
"tsx": "4.21.0",
|
|
96
97
|
"typescript": "5.9.3",
|
|
97
98
|
"typescript-eslint": "8.57.1",
|
|
98
99
|
"vite": "7.3.1",
|
|
@@ -113,7 +114,7 @@
|
|
|
113
114
|
"cicheck:code": "pnpm run check && pnpm run test",
|
|
114
115
|
"cicheck:content": "pnpm run cspell && pnpm run secretlint",
|
|
115
116
|
"cspell": "cspell --no-progress --gitignore .",
|
|
116
|
-
"dev": "
|
|
117
|
+
"dev": "tsx src/cli/index.ts",
|
|
117
118
|
"docs:build": "vitepress build docs",
|
|
118
119
|
"docs:dev": "vitepress dev docs",
|
|
119
120
|
"docs:preview": "vitepress preview docs",
|
|
@@ -123,13 +124,13 @@
|
|
|
123
124
|
"fmt": "oxfmt .",
|
|
124
125
|
"fmt:check": "oxfmt --check .",
|
|
125
126
|
"generate": "pnpm run dev generate",
|
|
126
|
-
"generate:schema": "
|
|
127
|
+
"generate:schema": "tsx scripts/generate-json-schema.ts",
|
|
127
128
|
"knip": "knip",
|
|
128
129
|
"oxlint": "oxlint . --max-warnings 0",
|
|
129
130
|
"oxlint:fix": "oxlint . --fix --max-warnings 0",
|
|
130
131
|
"secretlint": "secretlint --secretlintignore .gitignore \"**/*\"",
|
|
131
132
|
"sort": "sort-package-json",
|
|
132
|
-
"task": "
|
|
133
|
+
"task": "tsx scripts/run-tasks.ts",
|
|
133
134
|
"test": "vitest run --silent=true",
|
|
134
135
|
"test:coverage": "vitest run --coverage --silent=true",
|
|
135
136
|
"test:e2e": "vitest run --config vitest.e2e.config.ts --silent=false",
|