oxlint-plugin-arch 0.2.3 → 0.2.4
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/CHANGELOG.md +4 -0
- package/README.md +3 -3
- package/dist/index.js +40 -6
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.2.4
|
|
4
|
+
|
|
5
|
+
- Add `trailingRoles` and `roleSeparators` so `export-file-prefix`, `declaration-name`, and `no-extra-exports` can treat `onchain-utils.ts` like `onchain.utils.ts`.
|
|
6
|
+
|
|
3
7
|
## 0.2.3
|
|
4
8
|
|
|
5
9
|
- Add `declaration-name` so selected declarations can follow a file prefix or pattern per glob.
|
package/README.md
CHANGED
|
@@ -47,13 +47,13 @@ Copy the shapes that match your repository; do not copy globs or naming policy b
|
|
|
47
47
|
|
|
48
48
|
## Rules
|
|
49
49
|
|
|
50
|
-
- `declaration-name` — require selected declarations to match a filename-derived prefix or a consumer pattern.
|
|
51
|
-
- `export-file-prefix` — require export names, or every function and type, to start with a filename-derived prefix, optionally singularized.
|
|
50
|
+
- `declaration-name` — require selected declarations to match a filename-derived prefix or a consumer pattern. Optional `trailingRoles` treat `onchain-utils.ts` like `onchain.utils.ts`.
|
|
51
|
+
- `export-file-prefix` — require export names, or every function and type, to start with a filename-derived prefix, optionally singularized. Optional `trailingRoles` drop a configured role suffix from that prefix.
|
|
52
52
|
- `export-name-pattern` — require export names, or every function and type, to match a configured regular expression.
|
|
53
53
|
- `filename-export-name` — derive expected function names from filename templates, optionally including locals.
|
|
54
54
|
- `filename-match` — require filenames to match a configured pattern.
|
|
55
55
|
- `folder-prefix` — require filenames to start with their parent folder name, or the folders after a configured root.
|
|
56
|
-
- `no-extra-exports` — restrict files to configured export templates.
|
|
56
|
+
- `no-extra-exports` — restrict files to configured export templates. Optional `trailingRoles` apply to `{Domain}` the same way as the prefix rules.
|
|
57
57
|
- `no-extra-factory-keys` — restrict direct factory return keys.
|
|
58
58
|
- `no-file-level-helpers` — keep unapproved helpers out of module scope.
|
|
59
59
|
- `no-imported-type-alias` — reject exported aliases that only rename imported types.
|
package/dist/index.js
CHANGED
|
@@ -422,9 +422,37 @@ function namingMatchTemplate(basename, template, placeholderPattern = "[a-z0-9-]
|
|
|
422
422
|
}
|
|
423
423
|
return new RegExp(`^${pattern}$`).exec(basename)?.groups ?? null;
|
|
424
424
|
}
|
|
425
|
+
var namingStemModes = ["before-first-dot", "full-basename"];
|
|
425
426
|
function namingNormalized(value, normalize) {
|
|
426
427
|
return normalize === "none" ? value : value.replaceAll(/[-_]/g, "").toLowerCase();
|
|
427
428
|
}
|
|
429
|
+
function namingFileStem(basename, mode = "before-first-dot", trailingRoles = [], roleSeparators = [".", "-"]) {
|
|
430
|
+
const stem = mode === "full-basename" ? basename : basename.split(".")[0] ?? "";
|
|
431
|
+
const roles = [...new Set(trailingRoles.filter(Boolean))].sort((left, right) => right.length - left.length);
|
|
432
|
+
const separators = [...new Set(roleSeparators.filter(Boolean))];
|
|
433
|
+
if (roles.length === 0 || separators.length === 0) {
|
|
434
|
+
return stem;
|
|
435
|
+
}
|
|
436
|
+
let remaining = stem;
|
|
437
|
+
let changed = true;
|
|
438
|
+
while (changed) {
|
|
439
|
+
changed = false;
|
|
440
|
+
for (const role of roles) {
|
|
441
|
+
for (const separator of separators) {
|
|
442
|
+
const suffix = `${separator}${role}`;
|
|
443
|
+
if (remaining.length > suffix.length && remaining.endsWith(suffix)) {
|
|
444
|
+
remaining = remaining.slice(0, -suffix.length);
|
|
445
|
+
changed = true;
|
|
446
|
+
break;
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
if (changed) {
|
|
450
|
+
break;
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
return remaining;
|
|
455
|
+
}
|
|
428
456
|
function namingFilePrefixes(stem, normalize = "remove-separators", singularize = "none") {
|
|
429
457
|
const prefixes = [namingNormalized(stem, normalize)];
|
|
430
458
|
const parts = stem.split(/[-_]+/).filter(Boolean);
|
|
@@ -699,7 +727,9 @@ var declarationName = defineRule({
|
|
|
699
727
|
},
|
|
700
728
|
pattern: { type: "string" },
|
|
701
729
|
flags: { type: "string" },
|
|
702
|
-
stem: { type: "string", enum: [
|
|
730
|
+
stem: { type: "string", enum: [...namingStemModes] },
|
|
731
|
+
trailingRoles: { type: "array", items: { type: "string" } },
|
|
732
|
+
roleSeparators: { type: "array", items: { type: "string" } },
|
|
703
733
|
normalize: { type: "string", enum: ["remove-separators", "none"] },
|
|
704
734
|
singularize: { type: "string", enum: ["none", "trailing-s"] },
|
|
705
735
|
allowPattern: { type: "string" }
|
|
@@ -720,7 +750,7 @@ var declarationName = defineRule({
|
|
|
720
750
|
const allowed = options2.allowPattern ? new RegExp(options2.allowPattern) : null;
|
|
721
751
|
const expected = options2.pattern ? new RegExp(options2.pattern, options2.flags) : null;
|
|
722
752
|
const basename = namingFileBasename(context.filename).replace(/\.(tsx?|jsx?)$/, "");
|
|
723
|
-
const stem = options2.stem
|
|
753
|
+
const stem = namingFileStem(basename, options2.stem, options2.trailingRoles, options2.roleSeparators);
|
|
724
754
|
const prefixes = namingFilePrefixes(stem, options2.normalize ?? "remove-separators", options2.singularize ?? "none");
|
|
725
755
|
const seen = new Set;
|
|
726
756
|
for (const item of declarationsCollectNamed(program, options2.kinds)) {
|
|
@@ -751,7 +781,9 @@ var exportFilePrefix = defineRule2({
|
|
|
751
781
|
type: "object",
|
|
752
782
|
additionalProperties: false,
|
|
753
783
|
properties: {
|
|
754
|
-
stem: { type: "string", enum: [
|
|
784
|
+
stem: { type: "string", enum: [...namingStemModes] },
|
|
785
|
+
trailingRoles: { type: "array", items: { type: "string" } },
|
|
786
|
+
roleSeparators: { type: "array", items: { type: "string" } },
|
|
755
787
|
normalize: { type: "string", enum: ["remove-separators", "none"] },
|
|
756
788
|
singularize: { type: "string", enum: ["none", "trailing-s"] },
|
|
757
789
|
allDeclarations: { type: "boolean" },
|
|
@@ -770,7 +802,7 @@ var exportFilePrefix = defineRule2({
|
|
|
770
802
|
normalize: "remove-separators"
|
|
771
803
|
});
|
|
772
804
|
const basename = namingFileBasename(context.filename).replace(/\.(tsx?|jsx?)$/, "");
|
|
773
|
-
const stem = options2.stem
|
|
805
|
+
const stem = namingFileStem(basename, options2.stem, options2.trailingRoles, options2.roleSeparators);
|
|
774
806
|
const prefixes = namingFilePrefixes(stem, options2.normalize ?? "remove-separators", options2.singularize ?? "none");
|
|
775
807
|
const allowed = options2.allowPattern ? new RegExp(options2.allowPattern) : null;
|
|
776
808
|
const names = options2.allDeclarations ? declarationsCollectNamed(program) : exportsCollect(program).map((binding) => ({
|
|
@@ -1003,7 +1035,9 @@ var noExtraExports = defineRule7({
|
|
|
1003
1035
|
additionalProperties: false,
|
|
1004
1036
|
properties: {
|
|
1005
1037
|
names: { type: "array", items: { type: "string" } },
|
|
1006
|
-
domainStem: { type: "string", enum: [
|
|
1038
|
+
domainStem: { type: "string", enum: [...namingStemModes] },
|
|
1039
|
+
trailingRoles: { type: "array", items: { type: "string" } },
|
|
1040
|
+
roleSeparators: { type: "array", items: { type: "string" } },
|
|
1007
1041
|
allowTypeExports: { type: "boolean" }
|
|
1008
1042
|
},
|
|
1009
1043
|
required: ["names"]
|
|
@@ -1017,7 +1051,7 @@ var noExtraExports = defineRule7({
|
|
|
1017
1051
|
Program(program) {
|
|
1018
1052
|
const options2 = optionsFirst(context);
|
|
1019
1053
|
const basename = namingFileBasename(context.filename).replace(/\.(tsx?|jsx?)$/, "");
|
|
1020
|
-
const domain = options2.domainStem
|
|
1054
|
+
const domain = namingFileStem(basename, options2.domainStem, options2.trailingRoles, options2.roleSeparators);
|
|
1021
1055
|
const allowed = options2.names.map((template) => template.replaceAll("{Domain}", namingPascalCase(domain)).replaceAll("{domain}", namingCamelCase(domain)));
|
|
1022
1056
|
for (const binding of exportsCollect(program)) {
|
|
1023
1057
|
if (options2.allowTypeExports && binding.typeOnly) {
|