@shivaedev/quality 0.39.0 → 0.39.1

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 CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.39.1 - 2026-10-25
4
+
5
+ ### Fixed
6
+
7
+ - Recognise Xcode bundles and asset catalogs, Swift Package Manager source targets and Android source sets and resources in file and folder naming checks, so Capacitor-generated native shells pass without consumer configuration while authored names remain checked.
8
+
3
9
  ## 0.39.0 - 2026-10-25
4
10
 
5
11
  ### Changed
package/README.md CHANGED
@@ -86,6 +86,14 @@ Module folders under `src/modules/<name>` use the same `client/` and `server/` i
86
86
 
87
87
  Naming rules treat numbered migration files such as `src/server/migrations/0001_create_notes.ts` as tool-owned, including in nested apps and in module folders such as `src/modules/notes/server/migrations`. The file must sit directly in its migration folder and match `NNNN_snake_case.ts`: four digits, an underscore and a lowercase name starting with a letter. Files elsewhere, files with other names and subfolders remain checked. The Biome preset lets `.ts` files directly in that folder whose names start with four digits and an underscore default-export their migration Effect, because Effect's migration loader imports the default export; Biome globs cannot spell the rest of the pattern, so the naming rules still report a malformed name.
88
88
 
89
+ Naming rules recognise Xcode's `*.xcodeproj` and `*.xcworkspace` bundles and their `Contents.json`, project containers and matching app folders, localised `*.lproj` folders, and `*.xcassets` catalogs with their asset sets, metadata and images.
90
+
91
+ Swift Package Manager packages containing `Package.swift` retain their package folder name and `Sources/<Target>` layout.
92
+
93
+ Android source sets with a sibling or own `AndroidManifest.xml` retain their native source set names and `res/` resource directories, including qualifiers such as `mipmap-hdpi` and `values-night`, with lower_snake_case resource files.
94
+
95
+ These contexts work at any repository path without configuration; TypeScript and JavaScript, deeper app source folders and ordinary assets outside native resource contexts remain checked, including within `ios/` and `android/`.
96
+
89
97
  `defineConfig` checks the config's types. The CLI also validates it: a broken config, unknown rule id or invalid options fails before checks run. An explicit `--config` path must exist.
90
98
 
91
99
  ### 2. When architecture needs it: describe an import boundary
@@ -0,0 +1,6 @@
1
+ export declare function androidResources(files: readonly string[]): {
2
+ folders: Set<string>;
3
+ messageFor: (path: string) => string | undefined;
4
+ owns: (path: string) => boolean;
5
+ };
6
+ //# sourceMappingURL=androidResources.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"androidResources.d.ts","sourceRoot":"","sources":["../../src/naming/androidResources.ts"],"names":[],"mappings":"AAoBA,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE;;uBAuBpC,MAAM,KAAG,MAAM,GAAG,SAAS;iBAIjC,MAAM,KAAG,OAAO;EAE9B"}
@@ -0,0 +1,44 @@
1
+ import { posix } from "node:path";
2
+ const RESOURCE_FOLDER = /^(?:anim|animator|color|drawable|font|interpolator|layout|menu|mipmap|navigation|raw|transition|values|xml)(?:-(?:[a-z0-9]+|r[A-Z]{2}|b\+[a-zA-Z0-9+]+))*$/u;
3
+ const RESOURCE_FILE = /^[a-z][a-z0-9_]*(?:\.9)?\.[a-z0-9]+$/u;
4
+ const CODE = /\.[cm]?[jt]sx?$/u;
5
+ function sourceSetOf(file, inventory) {
6
+ const match = /^(?<module>.*\/)?src\/(?<sourceSet>[^/]+)\/(?<relative>.*)$/u.exec(file);
7
+ if (match?.groups === undefined) {
8
+ return undefined;
9
+ }
10
+ const { module = "", sourceSet = "", relative = "" } = match.groups;
11
+ return inventory.has(`${module}src/main/AndroidManifest.xml`) || inventory.has(`${module}src/${sourceSet}/AndroidManifest.xml`)
12
+ ? { folder: `${module}src/${sourceSet}`, name: sourceSet, relative }
13
+ : undefined;
14
+ }
15
+ export function androidResources(files) {
16
+ const inventory = new Set(files);
17
+ const folders = new Set();
18
+ const resources = new Set();
19
+ for (const file of files) {
20
+ const sourceSet = sourceSetOf(file, inventory);
21
+ if (sourceSet === undefined) {
22
+ continue;
23
+ }
24
+ if (/^[a-z][a-zA-Z0-9]*$/u.test(sourceSet.name) && /^(?:java\/|kotlin\/|res\/|AndroidManifest\.xml$)/u.test(sourceSet.relative)) {
25
+ folders.add(sourceSet.folder);
26
+ }
27
+ const [res, directory, name, ...nested] = sourceSet.relative.split("/");
28
+ if (res !== "res" || directory === undefined || !RESOURCE_FOLDER.test(directory)) {
29
+ continue;
30
+ }
31
+ folders.add(`${sourceSet.folder}/res/${directory}`);
32
+ if (name !== undefined && nested.length === 0 && !CODE.test(name)) {
33
+ resources.add(file);
34
+ }
35
+ }
36
+ return {
37
+ folders,
38
+ messageFor: (path) => resources.has(path) && !RESOURCE_FILE.test(posix.basename(path))
39
+ ? `"${posix.basename(path)}" is an Android resource, so it is named in lower_snake_case, such as ic_launcher.png.`
40
+ : undefined,
41
+ owns: (path) => resources.has(path),
42
+ };
43
+ }
44
+ //# sourceMappingURL=androidResources.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"androidResources.js","sourceRoot":"","sources":["../../src/naming/androidResources.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AAElC,MAAM,eAAe,GACpB,6JAA6J,CAAC;AAE/J,MAAM,aAAa,GAAG,uCAAuC,CAAC;AAE9D,MAAM,IAAI,GAAG,kBAAkB,CAAC;AAEhC,SAAS,WAAW,CAAC,IAAY,EAAE,SAA8B;IAChE,MAAM,KAAK,GAAG,8DAA8D,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACxF,IAAI,KAAK,EAAE,MAAM,KAAK,SAAS,EAAE,CAAC;QACjC,OAAO,SAAS,CAAC;IAClB,CAAC;IACD,MAAM,EAAE,MAAM,GAAG,EAAE,EAAE,SAAS,GAAG,EAAE,EAAE,QAAQ,GAAG,EAAE,EAAE,GAAG,KAAK,CAAC,MAAM,CAAC;IACpE,OAAO,SAAS,CAAC,GAAG,CAAC,GAAG,MAAM,8BAA8B,CAAC,IAAI,SAAS,CAAC,GAAG,CAAC,GAAG,MAAM,OAAO,SAAS,sBAAsB,CAAC;QAC9H,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM,OAAO,SAAS,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE;QACpE,CAAC,CAAC,SAAS,CAAC;AACd,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,KAAwB;IACxD,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC;IACjC,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;IAClC,MAAM,SAAS,GAAG,IAAI,GAAG,EAAU,CAAC;IACpC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QAC1B,MAAM,SAAS,GAAG,WAAW,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;QAC/C,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;YAC7B,SAAS;QACV,CAAC;QACD,IAAI,sBAAsB,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,mDAAmD,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC;YACjI,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;QAC/B,CAAC;QACD,MAAM,CAAC,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,MAAM,CAAC,GAAG,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACxE,IAAI,GAAG,KAAK,KAAK,IAAI,SAAS,KAAK,SAAS,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;YAClF,SAAS;QACV,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC,MAAM,QAAQ,SAAS,EAAE,CAAC,CAAC;QACpD,IAAI,IAAI,KAAK,SAAS,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YACnE,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACrB,CAAC;IACF,CAAC;IACD,OAAO;QACN,OAAO;QACP,UAAU,EAAE,CAAC,IAAY,EAAsB,EAAE,CAChD,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;YAC/D,CAAC,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,wFAAwF;YAClH,CAAC,CAAC,SAAS;QACb,IAAI,EAAE,CAAC,IAAY,EAAW,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC;KACpD,CAAC;AACH,CAAC"}
@@ -0,0 +1,6 @@
1
+ export declare function nativeNames(files: readonly string[]): {
2
+ folders: Set<string>;
3
+ messageFor: (path: string) => string | undefined;
4
+ owns: (path: string) => boolean;
5
+ };
6
+ //# sourceMappingURL=nativeNames.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nativeNames.d.ts","sourceRoot":"","sources":["../../src/naming/nativeNames.ts"],"names":[],"mappings":"AA2DA,wBAAgB,WAAW,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE;IAGlD,OAAO;IACP,UAAU;IACV,IAAI,SAAS,MAAM,KAAG,OAAO;EAM9B"}
@@ -0,0 +1,64 @@
1
+ import { posix } from "node:path";
2
+ import { androidResources } from "./androidResources.js";
3
+ const BUNDLE = /\.(?:xcodeproj|xcworkspace|xcassets)$/u;
4
+ const CATALOG = /(?:^|\/)[^/]+\.xcassets\//u;
5
+ const CODE = /\.[cm]?[jt]sx?$/u;
6
+ function localisationFolders(files, projects) {
7
+ const folders = new Set();
8
+ for (const file of files) {
9
+ for (let folder = posix.dirname(file); folder !== "."; folder = posix.dirname(folder)) {
10
+ if (folder.endsWith(".lproj") && [...projects].some((project) => folder.startsWith(`${project}/`))) {
11
+ folders.add(folder);
12
+ }
13
+ }
14
+ }
15
+ return [...folders];
16
+ }
17
+ function xcodeFolders(files) {
18
+ const folders = new Set();
19
+ const projects = new Set();
20
+ for (const file of files) {
21
+ for (let folder = posix.dirname(file); folder !== "."; folder = posix.dirname(folder)) {
22
+ if (BUNDLE.test(folder) || CATALOG.test(`${folder}/`)) {
23
+ folders.add(folder);
24
+ }
25
+ if (folder.endsWith(".xcodeproj")) {
26
+ const parent = posix.dirname(folder);
27
+ folders.add(parent);
28
+ const source = posix.join(parent, posix.basename(folder, ".xcodeproj"));
29
+ folders.add(source);
30
+ projects.add(source);
31
+ }
32
+ }
33
+ }
34
+ return new Set([...folders, ...localisationFolders(files, projects)]);
35
+ }
36
+ function swiftFolders(files) {
37
+ const packages = new Set(files.filter((file) => posix.basename(file) === "Package.swift").map((file) => posix.dirname(file)));
38
+ const folders = new Set(packages);
39
+ for (const file of files) {
40
+ for (const root of packages) {
41
+ const sources = posix.join(root, "Sources");
42
+ if (file.startsWith(`${sources}/`)) {
43
+ folders.add(sources);
44
+ const target = file.slice(sources.length + 1).split("/")[0];
45
+ if (target !== undefined && file.slice(sources.length + 1).includes("/")) {
46
+ folders.add(`${sources}/${target}`);
47
+ }
48
+ }
49
+ }
50
+ }
51
+ return folders;
52
+ }
53
+ export function nativeNames(files) {
54
+ const android = androidResources(files);
55
+ return {
56
+ folders: new Set([...xcodeFolders(files), ...swiftFolders(files), ...android.folders]),
57
+ messageFor: android.messageFor,
58
+ owns: (path) => !CODE.test(path)
59
+ && (android.owns(path)
60
+ || CATALOG.test(path)
61
+ || (posix.basename(path) === "Contents.json" && /(?:^|\/)[^/]+\.(?:xcodeproj|xcworkspace)\//u.test(path))),
62
+ };
63
+ }
64
+ //# sourceMappingURL=nativeNames.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nativeNames.js","sourceRoot":"","sources":["../../src/naming/nativeNames.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"folderNames.d.ts","sourceRoot":"","sources":["../../../src/rules/files/folderNames.ts"],"names":[],"mappings":"AAuEA,eAAO,MAAM,WAAW;;;EAkBtB,CAAC"}
1
+ {"version":3,"file":"folderNames.d.ts","sourceRoot":"","sources":["../../../src/rules/files/folderNames.ts"],"names":[],"mappings":"AAyEA,eAAO,MAAM,WAAW;;;EAmBtB,CAAC"}
@@ -1,6 +1,7 @@
1
1
  import { posix } from "node:path";
2
2
  import { Effect, Schema } from "effect";
3
3
  import ignore, {} from "ignore";
4
+ import { nativeNames } from "#naming/nativeNames.ts";
4
5
  import { packageLayout } from "#naming/packageLayout.ts";
5
6
  import { KEBAB, PASCAL } from "#naming/words.ts";
6
7
  import { defineRule } from "#rule.ts";
@@ -40,7 +41,7 @@ function groupMessage(name) {
40
41
  }
41
42
  function messageFor(folder, context) {
42
43
  const name = posix.basename(folder);
43
- if (context.toolOwned.ignores(`${folder}/`) || isModule(folder, context.stems)) {
44
+ if (context.native.has(folder) || context.toolOwned.ignores(`${folder}/`) || isModule(folder, context.stems)) {
44
45
  return undefined;
45
46
  }
46
47
  const packageName = context.names.get(folder);
@@ -58,6 +59,7 @@ export const folderNames = defineRule({
58
59
  const context = {
59
60
  content: ignore().add([...options.content]),
60
61
  names: layout.names,
62
+ native: nativeNames(files).folders,
61
63
  stems: stemsIn(files),
62
64
  toolOwned: ignore().add([...options.toolOwned]),
63
65
  };
@@ -1 +1 @@
1
- {"version":3,"file":"folderNames.js","sourceRoot":"","sources":["../../../src/rules/files/folderNames.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AACxC,OAAO,MAAM,EAAE,EAAe,MAAM,QAAQ,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAgB,MAAM,UAAU,CAAC;AAEpD,MAAM,KAAK,GAAG,6BAA6B,CAAC;AAE5C,MAAM,IAAI,GAAG,kBAAkB,CAAC;AAEhC,MAAM,kBAAkB,GAAG,MAAM,CAAC,MAAM,CAAC;IACxC,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,sBAAsB,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC;IAC5F,SAAS,EAAE,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,sBAAsB,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC;CAC9F,CAAC,CAAC;AAEH,SAAS,SAAS,CAAC,KAAwB;IAC1C,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;IAClC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QAC1B,KAAK,IAAI,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,MAAM,KAAK,GAAG,EAAE,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YACvF,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACrB,CAAC;IACF,CAAC;IACD,OAAO,CAAC,GAAG,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;AAC5B,CAAC;AAED,SAAS,OAAO,CAAC,KAAwB;IACxC,OAAO,IAAI,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;AAC3I,CAAC;AAED,SAAS,QAAQ,CAAC,MAAc,EAAE,KAA0B;IAC3D,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IACpC,OAAO,KAAK,CAAC,GAAG,CAAC,GAAG,MAAM,IAAI,IAAI,EAAE,CAAC,IAAI,KAAK,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;AACxF,CAAC;AAED,SAAS,cAAc,CAAC,IAAY,EAAE,WAAmB;IACxD,MAAM,QAAQ,GAAG,WAAW,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;IACvD,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,6BAA6B,WAAW,cAAc,QAAQ,0CAA0C,CAAC;AACjJ,CAAC;AAED,SAAS,YAAY,CAAC,IAAY;IACjC,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACvB,OAAO,IAAI,IAAI,gCAAgC,IAAI,UAAU,IAAI,mHAAmH,CAAC;IACtL,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QAC1C,CAAC,CAAC,SAAS;QACX,CAAC,CAAC,IAAI,IAAI,8JAA8J,CAAC;AAC3K,CAAC;AASD,SAAS,UAAU,CAAC,MAAc,EAAE,OAAgB;IACnD,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IACpC,IAAI,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC,GAAG,MAAM,GAAG,CAAC,IAAI,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QAChF,OAAO,SAAS,CAAC;IAClB,CAAC;IACD,MAAM,WAAW,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAC9C,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;QAC/B,OAAO,cAAc,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;IAC1C,CAAC;IACD,IAAI,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,MAAM,GAAG,CAAC,EAAE,CAAC;QAC3C,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,IAAI,sEAAsE,CAAC;IACtH,CAAC;IACD,OAAO,YAAY,CAAC,IAAI,CAAC,CAAC;AAC3B,CAAC;AAED,MAAM,CAAC,MAAM,WAAW,GAAG,UAAU,CAAC;IACrC,KAAK,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE;QAC7C,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;QACxD,MAAM,OAAO,GAAY;YACxB,OAAO,EAAE,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;YAC3C,KAAK,EAAE,MAAM,CAAC,KAAK;YACnB,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC;YACrB,SAAS,EAAE,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;SAC/C,CAAC;QACF,OAAO,SAAS,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,EAAsB,EAAE;YAC9D,MAAM,OAAO,GAAG,UAAU,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;YAC5C,OAAO,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;QACjE,CAAC,CAAC,CAAC;IACJ,CAAC;IACD,WAAW,EACV,wJAAwJ;IACzJ,EAAE,EAAE,oBAAoB;IACxB,OAAO,EAAE,MAAM,CAAC,kBAAkB,CAAC,kBAAkB,EAAE,EAAE,YAAY,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,gBAAgB,EAAE,OAAO,EAAE,EAAE,CAAC;CACtH,CAAC,CAAC"}
1
+ {"version":3,"file":"folderNames.js","sourceRoot":"","sources":["../../../src/rules/files/folderNames.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"otherNames.d.ts","sourceRoot":"","sources":["../../../src/rules/files/otherNames.ts"],"names":[],"mappings":"AAkFA,eAAO,MAAM,UAAU;;;EAgBrB,CAAC"}
1
+ {"version":3,"file":"otherNames.d.ts","sourceRoot":"","sources":["../../../src/rules/files/otherNames.ts"],"names":[],"mappings":"AAuFA,eAAO,MAAM,UAAU;;;EAiBrB,CAAC"}
@@ -1,6 +1,7 @@
1
1
  import { posix } from "node:path";
2
2
  import { Effect, Schema } from "effect";
3
3
  import ignore, {} from "ignore";
4
+ import { nativeNames } from "#naming/nativeNames.ts";
4
5
  import { CAMEL, KEBAB } from "#naming/words.ts";
5
6
  import { defineRule } from "#rule.ts";
6
7
  import { stylesheetImporters } from "./stylesheetImporters.js";
@@ -45,6 +46,9 @@ function messageFor(path, context) {
45
46
  const name = posix.basename(path);
46
47
  const kind = posix.extname(name).slice(1);
47
48
  const stem = name.slice(0, name.length - kind.length - 1);
49
+ if (context.native.owns(path)) {
50
+ return context.native.messageFor(path);
51
+ }
48
52
  if (kind === "" || context.toolOwned.ignores(path) || CONVENTIONAL.has(stem)) {
49
53
  return undefined;
50
54
  }
@@ -67,6 +71,7 @@ export const otherNames = defineRule({
67
71
  check: async ({ files, options, readText, sources }) => {
68
72
  const context = {
69
73
  content: ignore().add([...options.content]),
74
+ native: nativeNames(files),
70
75
  stylesheets: await stylesheetImporters({ files, readText, sources }),
71
76
  toolOwned: ignore().add([...DEFAULT_TOOL_OWNED, ...options.toolOwned]),
72
77
  };
@@ -1 +1 @@
1
- {"version":3,"file":"otherNames.js","sourceRoot":"","sources":["../../../src/rules/files/otherNames.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AACxC,OAAO,MAAM,EAAE,EAAe,MAAM,QAAQ,CAAC;AAC7C,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,UAAU,EAAgB,MAAM,UAAU,CAAC;AACpD,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAE/D,MAAM,kBAAkB,GAAsB,CAAC,IAAI,EAAE,cAAc,EAAE,gBAAgB,EAAE,YAAY,EAAE,aAAa,EAAE,YAAY,CAAC,CAAC;AAElI,MAAM,YAAY,GAAwB,IAAI,GAAG,CAAC,CAAC,QAAQ,EAAE,WAAW,EAAE,QAAQ,EAAE,cAAc,EAAE,SAAS,EAAE,QAAQ,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC;AAE/I,MAAM,WAAW,GAAwB,IAAI,GAAG,CAAC;IAChD,MAAM;IACN,KAAK;IACL,MAAM;IACN,KAAK;IACL,MAAM;IACN,KAAK;IACL,MAAM;IACN,OAAO;IACP,IAAI;IACJ,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,MAAM;IACN,MAAM;IACN,OAAO;CACP,CAAC,CAAC;AAEH,MAAM,WAAW,GAAwB,IAAI,GAAG,CAAC,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC;AAElE,MAAM,YAAY,GAAG,4DAA4D,CAAC;AAElF,MAAM,KAAK,GAAG,+BAA+B,CAAC;AAE9C,MAAM,IAAI,GAAG,kBAAkB,CAAC;AAEhC,MAAM,iBAAiB,GAAG,MAAM,CAAC,MAAM,CAAC;IACvC,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,sBAAsB,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC;IAC5F,SAAS,EAAE,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,sBAAsB,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC;CAC9F,CAAC,CAAC;AAEH,SAAS,iBAAiB,CAAC,IAAY,EAAE,IAAY,EAAE,UAA6B;IACnF,MAAM,CAAC,IAAI,CAAC,GAAG,UAAU,CAAC;IAC1B,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACtE,MAAM,KAAK,GAAG,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QACrD,OAAO,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,IAAI,oBAAoB,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,0BAA0B,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC;IAC9I,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,IAAI,oFAAoF,CAAC;AACpI,CAAC;AAQD,SAAS,UAAU,CAAC,IAAY,EAAE,OAAgB;IACjD,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAClC,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC1C,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAC1D,IAAI,IAAI,KAAK,EAAE,IAAI,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;QAC9E,OAAO,SAAS,CAAC;IAClB,CAAC;IACD,IAAI,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QACnC,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC;YACtB,CAAC,CAAC,SAAS;YACX,CAAC,CAAC,IAAI,IAAI,gKAAgK,CAAC;IAC7K,CAAC;IACD,IAAI,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;QAC3B,OAAO,iBAAiB,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;IAC3E,CAAC;IACD,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;QACvB,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,IAAI,2EAA2E,CAAC;IAC3H,CAAC;IACD,OAAO,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC;QACvD,CAAC,CAAC,IAAI,IAAI,gIAAgI;QAC1I,CAAC,CAAC,SAAS,CAAC;AACd,CAAC;AAED,MAAM,CAAC,MAAM,UAAU,GAAG,UAAU,CAAC;IACpC,KAAK,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,EAAE;QACtD,MAAM,OAAO,GAAY;YACxB,OAAO,EAAE,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;YAC3C,WAAW,EAAE,MAAM,mBAAmB,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;YACpE,SAAS,EAAE,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,GAAG,kBAAkB,EAAE,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;SACtE,CAAC;QACF,OAAO,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAsB,EAAE;YACjD,MAAM,OAAO,GAAG,UAAU,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;YAC1C,OAAO,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;QAC/D,CAAC,CAAC,CAAC;IACJ,CAAC;IACD,WAAW,EACV,6KAA6K;IAC9K,EAAE,EAAE,mBAAmB;IACvB,OAAO,EAAE,MAAM,CAAC,kBAAkB,CAAC,iBAAiB,EAAE,EAAE,YAAY,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,gBAAgB,EAAE,OAAO,EAAE,EAAE,CAAC;CACrH,CAAC,CAAC"}
1
+ {"version":3,"file":"otherNames.js","sourceRoot":"","sources":["../../../src/rules/files/otherNames.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shivaedev/quality",
3
- "version": "0.39.0",
3
+ "version": "0.39.1",
4
4
  "description": "Repository quality gate with typed rules, a baseline of existing debt and a registry of reasoned exceptions",
5
5
  "homepage": "https://github.com/ShivaeDev/platform/tree/main/packages/quality#readme",
6
6
  "bugs": {
@@ -0,0 +1,50 @@
1
+ import { posix } from "node:path";
2
+
3
+ const RESOURCE_FOLDER =
4
+ /^(?:anim|animator|color|drawable|font|interpolator|layout|menu|mipmap|navigation|raw|transition|values|xml)(?:-(?:[a-z0-9]+|r[A-Z]{2}|b\+[a-zA-Z0-9+]+))*$/u;
5
+
6
+ const RESOURCE_FILE = /^[a-z][a-z0-9_]*(?:\.9)?\.[a-z0-9]+$/u;
7
+
8
+ const CODE = /\.[cm]?[jt]sx?$/u;
9
+
10
+ function sourceSetOf(file: string, inventory: ReadonlySet<string>) {
11
+ const match = /^(?<module>.*\/)?src\/(?<sourceSet>[^/]+)\/(?<relative>.*)$/u.exec(file);
12
+ if (match?.groups === undefined) {
13
+ return undefined;
14
+ }
15
+ const { module = "", sourceSet = "", relative = "" } = match.groups;
16
+ return inventory.has(`${module}src/main/AndroidManifest.xml`) || inventory.has(`${module}src/${sourceSet}/AndroidManifest.xml`)
17
+ ? { folder: `${module}src/${sourceSet}`, name: sourceSet, relative }
18
+ : undefined;
19
+ }
20
+
21
+ export function androidResources(files: readonly string[]) {
22
+ const inventory = new Set(files);
23
+ const folders = new Set<string>();
24
+ const resources = new Set<string>();
25
+ for (const file of files) {
26
+ const sourceSet = sourceSetOf(file, inventory);
27
+ if (sourceSet === undefined) {
28
+ continue;
29
+ }
30
+ if (/^[a-z][a-zA-Z0-9]*$/u.test(sourceSet.name) && /^(?:java\/|kotlin\/|res\/|AndroidManifest\.xml$)/u.test(sourceSet.relative)) {
31
+ folders.add(sourceSet.folder);
32
+ }
33
+ const [res, directory, name, ...nested] = sourceSet.relative.split("/");
34
+ if (res !== "res" || directory === undefined || !RESOURCE_FOLDER.test(directory)) {
35
+ continue;
36
+ }
37
+ folders.add(`${sourceSet.folder}/res/${directory}`);
38
+ if (name !== undefined && nested.length === 0 && !CODE.test(name)) {
39
+ resources.add(file);
40
+ }
41
+ }
42
+ return {
43
+ folders,
44
+ messageFor: (path: string): string | undefined =>
45
+ resources.has(path) && !RESOURCE_FILE.test(posix.basename(path))
46
+ ? `"${posix.basename(path)}" is an Android resource, so it is named in lower_snake_case, such as ic_launcher.png.`
47
+ : undefined,
48
+ owns: (path: string): boolean => resources.has(path),
49
+ };
50
+ }
@@ -0,0 +1,71 @@
1
+ import { posix } from "node:path";
2
+ import { androidResources } from "./androidResources.ts";
3
+
4
+ const BUNDLE = /\.(?:xcodeproj|xcworkspace|xcassets)$/u;
5
+
6
+ const CATALOG = /(?:^|\/)[^/]+\.xcassets\//u;
7
+
8
+ const CODE = /\.[cm]?[jt]sx?$/u;
9
+
10
+ function localisationFolders(files: readonly string[], projects: ReadonlySet<string>): readonly string[] {
11
+ const folders = new Set<string>();
12
+ for (const file of files) {
13
+ for (let folder = posix.dirname(file); folder !== "."; folder = posix.dirname(folder)) {
14
+ if (folder.endsWith(".lproj") && [...projects].some((project) => folder.startsWith(`${project}/`))) {
15
+ folders.add(folder);
16
+ }
17
+ }
18
+ }
19
+ return [...folders];
20
+ }
21
+
22
+ function xcodeFolders(files: readonly string[]): ReadonlySet<string> {
23
+ const folders = new Set<string>();
24
+ const projects = new Set<string>();
25
+ for (const file of files) {
26
+ for (let folder = posix.dirname(file); folder !== "."; folder = posix.dirname(folder)) {
27
+ if (BUNDLE.test(folder) || CATALOG.test(`${folder}/`)) {
28
+ folders.add(folder);
29
+ }
30
+ if (folder.endsWith(".xcodeproj")) {
31
+ const parent = posix.dirname(folder);
32
+ folders.add(parent);
33
+ const source = posix.join(parent, posix.basename(folder, ".xcodeproj"));
34
+ folders.add(source);
35
+ projects.add(source);
36
+ }
37
+ }
38
+ }
39
+ return new Set([...folders, ...localisationFolders(files, projects)]);
40
+ }
41
+
42
+ function swiftFolders(files: readonly string[]): ReadonlySet<string> {
43
+ const packages = new Set(files.filter((file) => posix.basename(file) === "Package.swift").map((file) => posix.dirname(file)));
44
+ const folders = new Set<string>(packages);
45
+ for (const file of files) {
46
+ for (const root of packages) {
47
+ const sources = posix.join(root, "Sources");
48
+ if (file.startsWith(`${sources}/`)) {
49
+ folders.add(sources);
50
+ const target = file.slice(sources.length + 1).split("/")[0];
51
+ if (target !== undefined && file.slice(sources.length + 1).includes("/")) {
52
+ folders.add(`${sources}/${target}`);
53
+ }
54
+ }
55
+ }
56
+ }
57
+ return folders;
58
+ }
59
+
60
+ export function nativeNames(files: readonly string[]) {
61
+ const android = androidResources(files);
62
+ return {
63
+ folders: new Set([...xcodeFolders(files), ...swiftFolders(files), ...android.folders]),
64
+ messageFor: android.messageFor,
65
+ owns: (path: string): boolean =>
66
+ !CODE.test(path)
67
+ && (android.owns(path)
68
+ || CATALOG.test(path)
69
+ || (posix.basename(path) === "Contents.json" && /(?:^|\/)[^/]+\.(?:xcodeproj|xcworkspace)\//u.test(path))),
70
+ };
71
+ }
@@ -1,6 +1,7 @@
1
1
  import { posix } from "node:path";
2
2
  import { Effect, Schema } from "effect";
3
3
  import ignore, { type Ignore } from "ignore";
4
+ import { nativeNames } from "#naming/nativeNames.ts";
4
5
  import { packageLayout } from "#naming/packageLayout.ts";
5
6
  import { KEBAB, PASCAL } from "#naming/words.ts";
6
7
  import { defineRule, type Finding } from "#rule.ts";
@@ -50,13 +51,14 @@ function groupMessage(name: string): string | undefined {
50
51
  interface Context {
51
52
  readonly content: Ignore;
52
53
  readonly names: ReadonlyMap<string, string>;
54
+ readonly native: ReadonlySet<string>;
53
55
  readonly stems: ReadonlySet<string>;
54
56
  readonly toolOwned: Ignore;
55
57
  }
56
58
 
57
59
  function messageFor(folder: string, context: Context): string | undefined {
58
60
  const name = posix.basename(folder);
59
- if (context.toolOwned.ignores(`${folder}/`) || isModule(folder, context.stems)) {
61
+ if (context.native.has(folder) || context.toolOwned.ignores(`${folder}/`) || isModule(folder, context.stems)) {
60
62
  return undefined;
61
63
  }
62
64
  const packageName = context.names.get(folder);
@@ -75,6 +77,7 @@ export const folderNames = defineRule({
75
77
  const context: Context = {
76
78
  content: ignore().add([...options.content]),
77
79
  names: layout.names,
80
+ native: nativeNames(files).folders,
78
81
  stems: stemsIn(files),
79
82
  toolOwned: ignore().add([...options.toolOwned]),
80
83
  };
@@ -1,6 +1,7 @@
1
1
  import { posix } from "node:path";
2
2
  import { Effect, Schema } from "effect";
3
3
  import ignore, { type Ignore } from "ignore";
4
+ import { nativeNames } from "#naming/nativeNames.ts";
4
5
  import { CAMEL, KEBAB } from "#naming/words.ts";
5
6
  import { defineRule, type Finding } from "#rule.ts";
6
7
  import { stylesheetImporters } from "./stylesheetImporters.ts";
@@ -53,6 +54,7 @@ function stylesheetMessage(path: string, stem: string, importedBy: readonly stri
53
54
 
54
55
  interface Context {
55
56
  readonly content: Ignore;
57
+ readonly native: ReturnType<typeof nativeNames>;
56
58
  readonly stylesheets: ReadonlyMap<string, readonly string[]>;
57
59
  readonly toolOwned: Ignore;
58
60
  }
@@ -61,6 +63,9 @@ function messageFor(path: string, context: Context): string | undefined {
61
63
  const name = posix.basename(path);
62
64
  const kind = posix.extname(name).slice(1);
63
65
  const stem = name.slice(0, name.length - kind.length - 1);
66
+ if (context.native.owns(path)) {
67
+ return context.native.messageFor(path);
68
+ }
64
69
  if (kind === "" || context.toolOwned.ignores(path) || CONVENTIONAL.has(stem)) {
65
70
  return undefined;
66
71
  }
@@ -84,6 +89,7 @@ export const otherNames = defineRule({
84
89
  check: async ({ files, options, readText, sources }) => {
85
90
  const context: Context = {
86
91
  content: ignore().add([...options.content]),
92
+ native: nativeNames(files),
87
93
  stylesheets: await stylesheetImporters({ files, readText, sources }),
88
94
  toolOwned: ignore().add([...DEFAULT_TOOL_OWNED, ...options.toolOwned]),
89
95
  };