@leancodepl/folder-structure-cruiser 9.5.2

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.
@@ -0,0 +1,30 @@
1
+ {
2
+ "forbidden": [
3
+ {
4
+ "name": "no-orphans",
5
+ "from": {
6
+ "orphan": true
7
+ },
8
+ "to": {}
9
+ }
10
+ ],
11
+ "options": {
12
+ "doNotFollow": {
13
+ "path": [
14
+ "node_modules",
15
+ "(^|/)[.][^/]+[.](?:js|cjs|mjs|ts|cts|mts|json)$",
16
+ "[.]d[.]ts$",
17
+ "(^|/)tsconfig[.]json$"
18
+ ],
19
+ "dependencyTypes": ["npm-no-pkg", "npm-unknown"]
20
+ },
21
+ "exclude": {
22
+ "path": ["node_modules", "(^|/)[.][^/]+[.](?:js|cjs|mjs|ts|cts|mts|json)$", "[.]d[.]ts$", "(^|/)tsconfig[.]json$"]
23
+ },
24
+ "tsPreCompilationDeps": true,
25
+ "enhancedResolveOptions": {
26
+ "exportsFields": ["exports"],
27
+ "conditionNames": ["import", "require", "node", "default"]
28
+ }
29
+ }
30
+ }
package/CHANGELOG.md ADDED
@@ -0,0 +1,41 @@
1
+ # Change Log
2
+
3
+ All notable changes to this project will be documented in this file. See
4
+ [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
+
6
+ ## [9.5.2](https://github.com/leancodepl/js_corelibrary/compare/v9.5.1...v9.5.2) (2025-08-13)
7
+
8
+ ### Bug Fixes
9
+
10
+ - add missing new line
11
+ ([e8ce9e1](https://github.com/leancodepl/js_corelibrary/commit/e8ce9e1836981fe68ddd8095e7c7f874ca93b750))
12
+ - adjust linting file
13
+ ([b05100c](https://github.com/leancodepl/js_corelibrary/commit/b05100cb6264c4bd6f33eb7434cd34610a191d6b))
14
+ - adjust readme
15
+ ([51cab7f](https://github.com/leancodepl/js_corelibrary/commit/51cab7fdf3d937a62bb39c5b637b01fa8bb71954))
16
+ - adjust readme
17
+ ([7be4027](https://github.com/leancodepl/js_corelibrary/commit/7be4027d466889a0474b183f091b2e8431c50b2a))
18
+ - bring back output encoding
19
+ ([2e45613](https://github.com/leancodepl/js_corelibrary/commit/2e456135762ca3c52e5a277328b39f34704868ae))
20
+ - consoleSpy types
21
+ ([82ec3dd](https://github.com/leancodepl/js_corelibrary/commit/82ec3ddc1442bc9ea977cf0faec6ff20d003109c))
22
+ - enhance regex
23
+ ([e18fe68](https://github.com/leancodepl/js_corelibrary/commit/e18fe6822a36792b74c98250b916139ee841cb13))
24
+ - extensions ([98606c9](https://github.com/leancodepl/js_corelibrary/commit/98606c98403c6151b97c22c1e8a1b262a073474e))
25
+ - make tests compatible with es modules
26
+ ([7df498a](https://github.com/leancodepl/js_corelibrary/commit/7df498abef57ee133ed666ca4c29dd9ec953ae65))
27
+ - no-orphans tests
28
+ ([901d3a4](https://github.com/leancodepl/js_corelibrary/commit/901d3a4150bead4899993d8d6994facb4e103f91))
29
+ - remove type module
30
+ ([cfc0baa](https://github.com/leancodepl/js_corelibrary/commit/cfc0baa1ee3f7da29628b8d29cf6a32b11ffb78c))
31
+ - test project.json target
32
+ ([75ee897](https://github.com/leancodepl/js_corelibrary/commit/75ee897ea1930a4b4e9283141c7c8aaa4f1c4240))
33
+
34
+ ### Features
35
+
36
+ - create cross feature imports check
37
+ ([53d0bb1](https://github.com/leancodepl/js_corelibrary/commit/53d0bb19067fc5bc1212ae1ba9fe536e2d664a4c))
38
+ - create folder structure dependency cruiser rules
39
+ ([6c8b90c](https://github.com/leancodepl/js_corelibrary/commit/6c8b90c15fec9099478d189bf2261c9f0e6b3189))
40
+ - create folder structure dependency cruiser rules
41
+ ([673bc11](https://github.com/leancodepl/js_corelibrary/commit/673bc1107d73b522c3c77d81b53f35ce92008532))
package/README.md ADDED
@@ -0,0 +1,139 @@
1
+ # @leancodepl/folder-structure-cruiser
2
+
3
+ Validates folder structure rules and enforces cross-feature import restrictions in TypeScript/JavaScript projects.
4
+
5
+ ## Installation
6
+
7
+ ```sh
8
+ npm install -D dependency-cruiser @leancodepl/folder-structure-cruiser
9
+ ```
10
+
11
+ ## API
12
+
13
+ ### `validateCrossFeatureImports(cruiseParams)`
14
+
15
+ Validates cross-feature nested imports according to folder structure rules.
16
+
17
+ **Parameters:**
18
+
19
+ - `cruiseParams: CruiseParams` - Configuration parameters for the dependency analysis
20
+ - `directory: string` - Directory to analyze. Defaults to `".*"` if not provided
21
+ - `configPath: string` - Path to the dependency-cruiser configuration file (e.g., `.dependency-cruiser.js`)
22
+ - `tsConfigPath: string` - Optional path to TypeScript configuration file for enhanced type resolution
23
+ - `webpackConfigPath?: string` - Optional path to webpack configuration file for webpack alias resolution
24
+
25
+ **Returns:** `Promise<void>` - The function doesn't return a value but outputs results to console
26
+
27
+ **Throws:** `Error` - Throws an error if the dependency analysis fails or configuration is invalid
28
+
29
+ ### `validateSharedComponent(cruiseParams)`
30
+
31
+ Validates if shared components are located at the first shared level.
32
+
33
+ **Parameters:**
34
+
35
+ - `cruiseParams: CruiseParams` - Configuration parameters for the dependency analysis
36
+ - `directory: string` - Directory to analyze. Defaults to `".*"` if not provided
37
+ - `configPath: string` - Path to the dependency-cruiser configuration file (e.g., `.dependency-cruiser.js`)
38
+ - `tsConfigPath: string` - Optional path to TypeScript configuration file for enhanced type resolution
39
+ - `webpackConfigPath?: string` - Optional path to webpack configuration file for webpack alias resolution
40
+
41
+ **Returns:** `Promise<void>` - The function doesn't return a value but outputs results to console
42
+
43
+ **Throws:** `Error` - Throws an error if the dependency analysis fails or configuration is invalid
44
+
45
+ ## Usage Examples
46
+
47
+ ### Cross-Feature Import Validation
48
+
49
+ ```sh
50
+ # Basic validation
51
+ npx @leancodepl/folder-structure-cruiser validate-cross-feature-imports --directory "packages/admin" --config "./.dependency-cruiser.json"
52
+
53
+ # With both TypeScript and webpack config
54
+ npx @leancodepl/folder-structure-cruiser validate-cross-feature-imports --directory "packages/admin" --config "./.dependency-cruiser.json" --tsConfig "./tsconfig.base.json" --webpackConfig "./webpack.config.js"
55
+ ```
56
+
57
+ ### Shared Component Validation
58
+
59
+ ```sh
60
+ # Basic validation
61
+ npx @leancodepl/folder-structure-cruiser validate-shared-components --directory "packages/admin" --config "./.dependency-cruiser.json"
62
+
63
+ # With both TypeScript and webpack config
64
+ npx @leancodepl/folder-structure-cruiser validate-shared-components --directory "packages/admin" --config "./.dependency-cruiser.json" --tsConfig "./tsconfig.base.json" --webpackConfig "./webpack.config.js"
65
+ ```
66
+
67
+ ### No-Orphan Rule Validation
68
+
69
+ ```sh
70
+ # Use dependency-cruiser directly for no-orphan rule
71
+ npx depcruise --config ./.dependency-cruiser.json ./packages/admin/.*
72
+
73
+ # With TypeScript config
74
+ npx depcruise --ts-config ./tsconfig.base.json --config ./.dependency-cruiser.json ./packages/admin/.*
75
+
76
+ # With both TypeScript and webpack config
77
+ npx depcruise --ts-config ./tsconfig.base.json --webpack-config ./webpack.config.js --config ./.dependency-cruiser.json ./packages/admin/.*
78
+ ```
79
+
80
+ **Configuration:**
81
+
82
+ ```json
83
+ {
84
+ "extends": ["@leancodepl/folder-structure-cruiser/.dependency-cruiser.json"]
85
+ }
86
+ ```
87
+
88
+ ## Features
89
+
90
+ ### Cross-Feature Import Rules
91
+
92
+ Imports are allowed only if they meet one of these conditions:
93
+
94
+ 1. **Inside module directory**: Import is within the same module
95
+ - ✅ `src/feature1/subfeature1/ComponentA` → `src/feature1/subfeature1/ComponentB`
96
+
97
+ 2. **Sibling's immediate child**: Import is from an immediate sibling's or ancestors siblings' child
98
+ - ✅ `src/feature1/subfeature1/ComponentA` → `src/feature1/subfeature2/ComponentB`
99
+
100
+ ### Shared Component Detection
101
+
102
+ Identifies components that should be moved to shared levels when:
103
+
104
+ - Multiple dependents use the same component
105
+ - The component is not positioned at the first shared level among its dependents
106
+
107
+ ## Configuration
108
+
109
+ Create a `.dependency-cruiser.json` file in your project root:
110
+
111
+ ```json
112
+ {
113
+ "extends": ["@leancodepl/folder-structure-cruiser/.dependency-cruiser.json"]
114
+ }
115
+ ```
116
+
117
+ This configuration serves as a base config that can be extended with your own rules.
118
+
119
+ ## Nx Configuration
120
+
121
+ Configure folder-structure-cruiser commands as Nx target in your `project.json`. Example configuration:
122
+
123
+ ```json
124
+ "folder-structure": {
125
+ "executor": "nx:run-commands",
126
+ "defaultConfiguration": "validate-cross-feature-imports",
127
+ "configurations": {
128
+ "validate-cross-feature-imports": {
129
+ "command": "npx @leancodepl/folder-structure-cruiser validate-cross-feature-imports --config ./.dependency-cruiser.json --ts-config ./tsconfig.base.json --directory '{projectRoot}'"
130
+ },
131
+ "validate-shared-components": {
132
+ "command": "npx @leancodepl/folder-structure-cruiser validate-shared-components --config ./.dependency-cruiser.json --ts-config ./tsconfig.base.json --directory '{projectRoot}'"
133
+ },
134
+ "validate-no-orphans": {
135
+ "command": "npx depcruise --ts-config ./tsconfig.base.json --config ./.dependency-cruiser.json '{projectRoot}/.*'"
136
+ }
137
+ }
138
+ }
139
+ ```
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "@leancodepl/folder-structure-cruiser",
3
+ "version": "9.5.2",
4
+ "license": "Apache-2.0",
5
+ "type": "module",
6
+ "bin": {
7
+ "folder-structure-cruiser": "src/bin.js"
8
+ },
9
+ "dependencies": {
10
+ "commander": "^14.0.0",
11
+ "picocolors": "^1.1.1"
12
+ },
13
+ "peerDependencies": {
14
+ "dependency-cruiser": "^17.0.0"
15
+ },
16
+ "devDependencies": {
17
+ "@jest/globals": "^30.0.5",
18
+ "jest": "^29.0.0"
19
+ },
20
+ "publishConfig": {
21
+ "access": "public",
22
+ "registry": "https://registry.npmjs.org/"
23
+ },
24
+ "engines": {
25
+ "node": ">=18.0.0"
26
+ },
27
+ "repository": {
28
+ "type": "git",
29
+ "url": "git+https://github.com/leancodepl/js_corelibrary.git",
30
+ "directory": "packages/linters/folder-structure-cruiser"
31
+ },
32
+ "homepage": "https://github.com/leancodepl/js_corelibrary",
33
+ "bugs": {
34
+ "url": "https://github.com/leancodepl/js_corelibrary/issues"
35
+ },
36
+ "description": "Dependency-cruiser configuration for enforcing folder structure rules. Requires dependency-cruiser to be installed in your project.",
37
+ "keywords": [
38
+ "dependency-cruiser",
39
+ "folder-structure",
40
+ "import-rules",
41
+ "linting",
42
+ "javascript",
43
+ "typescript",
44
+ "leancode"
45
+ ],
46
+ "author": {
47
+ "name": "LeanCode",
48
+ "url": "https://leancode.co"
49
+ },
50
+ "sideEffects": false,
51
+ "types": "./src/index.d.ts",
52
+ "module": "./src/index.js",
53
+ "main": "./src/index.js"
54
+ }
package/src/bin.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/src/bin.js ADDED
@@ -0,0 +1,35 @@
1
+ #!/usr/bin/env node
2
+ import { program } from "commander";
3
+ import { validateCrossFeatureImports } from "./commands/validateCrossFeatureImports.js";
4
+ import { validateSharedComponent } from "./commands/validateSharedComponent.js";
5
+ program.name("folder-structure-cruiser").description("CLI tool for validating folder structure rules");
6
+ program
7
+ .command("validate-shared-components")
8
+ .description("Validate if shared components are located at the first shared level")
9
+ .option("-d, --directory <dir>", "Directory to analyze", ".")
10
+ .option("-c, --config <path_to_config>", "Path to config file")
11
+ .option("-t, --tsConfig <path_to_ts_config>", "Path to ts config file")
12
+ .option("-w, --webpackConfig <path_to_webpack_config>", "Path to webpack config file")
13
+ .action(async (options) => {
14
+ const directories = options.directory ? [options.directory] : [".*"];
15
+ const configPath = options.config ?? "";
16
+ const tsConfigPath = options.tsConfig;
17
+ const webpackConfigPath = options.webpackConfig;
18
+ await validateSharedComponent({ directories, configPath, tsConfigPath, webpackConfigPath });
19
+ });
20
+ program
21
+ .command("validate-cross-feature-imports")
22
+ .description("Validate if cross-feature nested imports are allowed")
23
+ .option("-d, --directory <dir>", "Directory to analyze", ".")
24
+ .option("-c, --config <path_to_config>", "Path to config file")
25
+ .option("-t, --tsConfig <path_to_ts_config>", "Path to ts config file")
26
+ .option("-w, --webpackConfig <path_to_webpack_config>", "Path to webpack config file")
27
+ .action(async (options) => {
28
+ const directories = options.directory ? [options.directory] : [".*"];
29
+ const configPath = options.config ?? "";
30
+ const tsConfigPath = options.tsConfig;
31
+ const webpackConfigPath = options.webpackConfig;
32
+ await validateCrossFeatureImports({ directories, configPath, tsConfigPath, webpackConfigPath });
33
+ });
34
+ program.parse();
35
+ //# sourceMappingURL=bin.js.map
package/src/bin.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bin.js","sourceRoot":"","sources":["../../../../packages/folder-structure-cruiser/src/bin.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,EAAE,2BAA2B,EAAE,MAAM,2CAA2C,CAAA;AACvF,OAAO,EAAE,uBAAuB,EAAE,MAAM,uCAAuC,CAAA;AAE/E,OAAO,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC,WAAW,CAAC,gDAAgD,CAAC,CAAA;AAEtG,OAAO;KACJ,OAAO,CAAC,4BAA4B,CAAC;KACrC,WAAW,CAAC,qEAAqE,CAAC;KAClF,MAAM,CAAC,uBAAuB,EAAE,sBAAsB,EAAE,GAAG,CAAC;KAC5D,MAAM,CAAC,+BAA+B,EAAE,qBAAqB,CAAC;KAC9D,MAAM,CAAC,oCAAoC,EAAE,wBAAwB,CAAC;KACtE,MAAM,CAAC,8CAA8C,EAAE,6BAA6B,CAAC;KAErF,MAAM,CAAC,KAAK,EAAC,OAAO,EAAC,EAAE;IACtB,MAAM,WAAW,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAA;IACpE,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,IAAI,EAAE,CAAA;IACvC,MAAM,YAAY,GAAG,OAAO,CAAC,QAAQ,CAAA;IACrC,MAAM,iBAAiB,GAAG,OAAO,CAAC,aAAa,CAAA;IAE/C,MAAM,uBAAuB,CAAC,EAAE,WAAW,EAAE,UAAU,EAAE,YAAY,EAAE,iBAAiB,EAAE,CAAC,CAAA;AAC7F,CAAC,CAAC,CAAA;AAEJ,OAAO;KACJ,OAAO,CAAC,gCAAgC,CAAC;KACzC,WAAW,CAAC,sDAAsD,CAAC;KACnE,MAAM,CAAC,uBAAuB,EAAE,sBAAsB,EAAE,GAAG,CAAC;KAC5D,MAAM,CAAC,+BAA+B,EAAE,qBAAqB,CAAC;KAC9D,MAAM,CAAC,oCAAoC,EAAE,wBAAwB,CAAC;KACtE,MAAM,CAAC,8CAA8C,EAAE,6BAA6B,CAAC;KACrF,MAAM,CAAC,KAAK,EAAC,OAAO,EAAC,EAAE;IACtB,MAAM,WAAW,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAA;IACpE,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,IAAI,EAAE,CAAA;IACvC,MAAM,YAAY,GAAG,OAAO,CAAC,QAAQ,CAAA;IACrC,MAAM,iBAAiB,GAAG,OAAO,CAAC,aAAa,CAAA;IAE/C,MAAM,2BAA2B,CAAC,EAAE,WAAW,EAAE,UAAU,EAAE,YAAY,EAAE,iBAAiB,EAAE,CAAC,CAAA;AACjG,CAAC,CAAC,CAAA;AAEJ,OAAO,CAAC,KAAK,EAAE,CAAA"}
@@ -0,0 +1,59 @@
1
+ import { CruiseParams } from "../lib/getCruiseResult.js";
2
+ /**
3
+ * Validates cross-feature nested imports according to folder structure rules.
4
+ *
5
+ * This function analyzes the codebase using dependency-cruiser to identify violations
6
+ * of cross-feature import restrictions. It checks if modules with multiple dependents
7
+ * are properly structured to avoid cross-feature nested imports that violate the
8
+ * established folder structure rules.
9
+ *
10
+ * The function will output violations to the console, showing which modules have
11
+ * cross-feature import issues that need to be resolved.
12
+ *
13
+ * @param cruiseParams - Configuration parameters for the dependency analysis
14
+ * @param cruiseParams.directories - Array of directory paths to analyze. Defaults to [".*"] if not provided
15
+ * @param cruiseParams.configPath - Path to the dependency-cruiser configuration file (e.g., .dependency-cruiser.js)
16
+ * @param cruiseParams.tsConfigPath - Optional path to TypeScript configuration file for enhanced type resolution
17
+ * @param cruiseParams.webpackConfigPath - Optional path to webpack configuration file for webpack alias resolution
18
+ *
19
+ * @returns Promise<void> - The function doesn't return a value but outputs results to console
20
+ *
21
+ * @throws {Error} - Throws an error if the dependency analysis fails or configuration is invalid
22
+ *
23
+ * @example
24
+ * ```typescript
25
+ * // Basic usage with default settings
26
+ * await validateCrossFeatureImports({
27
+ * directories: ["src"],
28
+ * configPath: ".dependency-cruiser.js",
29
+ * tsConfigPath: "./tsconfig.base.json"
30
+ * });
31
+ *
32
+ * // Advanced usage with webpack support
33
+ * await validateCrossFeatureImports({
34
+ * directories: ["src", "packages"],
35
+ * configPath: ".dependency-cruiser.js",
36
+ * tsConfigPath: "./tsconfig.base.json",
37
+ * webpackConfigPath: "./webpack.config.js"
38
+ * });
39
+ * ```
40
+ *
41
+ * @example
42
+ * ```typescript
43
+ * // Using in a build script
44
+ * import { validateCrossFeatureImports } from "@leancodepl/folder-structure-cruiser";
45
+ *
46
+ * try {
47
+ * await validateCrossFeatureImports({
48
+ * directories: ["src"],
49
+ * configPath: ".dependency-cruiser.js",
50
+ * tsConfigPath: "./tsconfig.base.json"
51
+ * });
52
+ * console.log("✅ Cross-feature import validation passed");
53
+ * } catch (error) {
54
+ * console.error("❌ Cross-feature import validation failed:", error);
55
+ * process.exit(1);
56
+ * }
57
+ * ```
58
+ */
59
+ export declare function validateCrossFeatureImports(cruiseParams: CruiseParams): Promise<void>;
@@ -0,0 +1,80 @@
1
+ import pc from "picocolors";
2
+ import { checkCrossFeatureImports } from "../lib/checkCrossFeatureImports.js";
3
+ import { formatMessages } from "../lib/formatMessages.js";
4
+ import { getCruiseResult } from "../lib/getCruiseResult.js";
5
+ const { red } = pc;
6
+ /**
7
+ * Validates cross-feature nested imports according to folder structure rules.
8
+ *
9
+ * This function analyzes the codebase using dependency-cruiser to identify violations
10
+ * of cross-feature import restrictions. It checks if modules with multiple dependents
11
+ * are properly structured to avoid cross-feature nested imports that violate the
12
+ * established folder structure rules.
13
+ *
14
+ * The function will output violations to the console, showing which modules have
15
+ * cross-feature import issues that need to be resolved.
16
+ *
17
+ * @param cruiseParams - Configuration parameters for the dependency analysis
18
+ * @param cruiseParams.directories - Array of directory paths to analyze. Defaults to [".*"] if not provided
19
+ * @param cruiseParams.configPath - Path to the dependency-cruiser configuration file (e.g., .dependency-cruiser.js)
20
+ * @param cruiseParams.tsConfigPath - Optional path to TypeScript configuration file for enhanced type resolution
21
+ * @param cruiseParams.webpackConfigPath - Optional path to webpack configuration file for webpack alias resolution
22
+ *
23
+ * @returns Promise<void> - The function doesn't return a value but outputs results to console
24
+ *
25
+ * @throws {Error} - Throws an error if the dependency analysis fails or configuration is invalid
26
+ *
27
+ * @example
28
+ * ```typescript
29
+ * // Basic usage with default settings
30
+ * await validateCrossFeatureImports({
31
+ * directories: ["src"],
32
+ * configPath: ".dependency-cruiser.js",
33
+ * tsConfigPath: "./tsconfig.base.json"
34
+ * });
35
+ *
36
+ * // Advanced usage with webpack support
37
+ * await validateCrossFeatureImports({
38
+ * directories: ["src", "packages"],
39
+ * configPath: ".dependency-cruiser.js",
40
+ * tsConfigPath: "./tsconfig.base.json",
41
+ * webpackConfigPath: "./webpack.config.js"
42
+ * });
43
+ * ```
44
+ *
45
+ * @example
46
+ * ```typescript
47
+ * // Using in a build script
48
+ * import { validateCrossFeatureImports } from "@leancodepl/folder-structure-cruiser";
49
+ *
50
+ * try {
51
+ * await validateCrossFeatureImports({
52
+ * directories: ["src"],
53
+ * configPath: ".dependency-cruiser.js",
54
+ * tsConfigPath: "./tsconfig.base.json"
55
+ * });
56
+ * console.log("✅ Cross-feature import validation passed");
57
+ * } catch (error) {
58
+ * console.error("❌ Cross-feature import validation failed:", error);
59
+ * process.exit(1);
60
+ * }
61
+ * ```
62
+ */
63
+ export async function validateCrossFeatureImports(cruiseParams) {
64
+ try {
65
+ const cruiseResult = await getCruiseResult(cruiseParams);
66
+ const { messages: errorMessages, totalCruised } = checkCrossFeatureImports(cruiseResult);
67
+ if (errorMessages.length === 0) {
68
+ console.info("\n✅ No issues found!");
69
+ }
70
+ if (errorMessages.length > 0) {
71
+ const messages = formatMessages(errorMessages);
72
+ console.error(messages.join("\n"));
73
+ console.error(`\n${red(`x Found ${errorMessages.length} violations(s). ${totalCruised} modules cruised.`)}`);
74
+ }
75
+ }
76
+ catch (pError) {
77
+ console.error(pError);
78
+ }
79
+ }
80
+ //# sourceMappingURL=validateCrossFeatureImports.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validateCrossFeatureImports.js","sourceRoot":"","sources":["../../../../../packages/folder-structure-cruiser/src/commands/validateCrossFeatureImports.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAA;AAC3B,OAAO,EAAE,wBAAwB,EAAE,MAAM,oCAAoC,CAAA;AAC7E,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAA;AACzD,OAAO,EAAgB,eAAe,EAAE,MAAM,2BAA2B,CAAA;AAEzE,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,CAAA;AAElB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwDG;AACH,MAAM,CAAC,KAAK,UAAU,2BAA2B,CAAC,YAA0B;IAC1E,IAAI,CAAC;QACH,MAAM,YAAY,GAAG,MAAM,eAAe,CAAC,YAAY,CAAC,CAAA;QAExD,MAAM,EAAE,QAAQ,EAAE,aAAa,EAAE,YAAY,EAAE,GAAG,wBAAwB,CAAC,YAAY,CAAC,CAAA;QAExF,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC/B,OAAO,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAA;QACtC,CAAC;QAED,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC7B,MAAM,QAAQ,GAAG,cAAc,CAAC,aAAa,CAAC,CAAA;YAC9C,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAA;YAClC,OAAO,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,WAAW,aAAa,CAAC,MAAM,mBAAmB,YAAY,mBAAmB,CAAC,EAAE,CAAC,CAAA;QAC9G,CAAC;IACH,CAAC;IAAC,OAAO,MAAM,EAAE,CAAC;QAChB,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;IACvB,CAAC;AACH,CAAC"}
@@ -0,0 +1,59 @@
1
+ import { CruiseParams } from "../lib/getCruiseResult.js";
2
+ /**
3
+ * Validates if shared components are located at the first shared level.
4
+ *
5
+ * This function analyzes the codebase using dependency-cruiser to identify components
6
+ * that should be moved to shared levels. It checks if components that are used across
7
+ * multiple features are properly placed at the appropriate shared level in the folder
8
+ * structure, following the established architectural patterns.
9
+ *
10
+ * The function will output recommendations to the console, showing which components
11
+ * should be moved to shared levels for better code organization and reusability.
12
+ *
13
+ * @param cruiseParams - Configuration parameters for the dependency analysis
14
+ * @param cruiseParams.directories - Array of directory paths to analyze. Defaults to [".*"] if not provided
15
+ * @param cruiseParams.configPath - Path to the dependency-cruiser configuration file (e.g., .dependency-cruiser.js)
16
+ * @param cruiseParams.tsConfigPath - Optional path to TypeScript configuration file for enhanced type resolution
17
+ * @param cruiseParams.webpackConfigPath - Optional path to webpack configuration file for webpack alias resolution
18
+ *
19
+ * @returns Promise<void> - The function doesn't return a value but outputs results to console
20
+ *
21
+ * @throws {Error} - Throws an error if the dependency analysis fails or configuration is invalid
22
+ *
23
+ * @example
24
+ * ```typescript
25
+ * // Basic usage with default settings
26
+ * await validateSharedComponent({
27
+ * directories: ["src"],
28
+ * configPath: ".dependency-cruiser.js",
29
+ * tsConfigPath: "./tsconfig.base.json"
30
+ * });
31
+ *
32
+ * // Advanced usage with webpack support
33
+ * await validateSharedComponent({
34
+ * directories: ["src", "packages"],
35
+ * configPath: ".dependency-cruiser.js",
36
+ * tsConfigPath: "./tsconfig.base.json",
37
+ * webpackConfigPath: "./webpack.config.js"
38
+ * });
39
+ * ```
40
+ *
41
+ * @example
42
+ * ```typescript
43
+ * // Using in a build script
44
+ * import { validateSharedComponent } from "@leancodepl/folder-structure-cruiser";
45
+ *
46
+ * try {
47
+ * await validateSharedComponent({
48
+ * directories: ["src"],
49
+ * configPath: ".dependency-cruiser.js",
50
+ * tsConfigPath: "./tsconfig.base.json"
51
+ * });
52
+ * console.log("✅ Shared component validation passed");
53
+ * } catch (error) {
54
+ * console.error("❌ Shared component validation failed:", error);
55
+ * process.exit(1);
56
+ * }
57
+ * ```
58
+ */
59
+ export declare function validateSharedComponent(cruiseParams: CruiseParams): Promise<void>;
@@ -0,0 +1,78 @@
1
+ import { checkSharedComponents } from "../lib/checkSharedComponents.js";
2
+ import { formatMessages } from "../lib/formatMessages.js";
3
+ import { getCruiseResult } from "../lib/getCruiseResult.js";
4
+ /**
5
+ * Validates if shared components are located at the first shared level.
6
+ *
7
+ * This function analyzes the codebase using dependency-cruiser to identify components
8
+ * that should be moved to shared levels. It checks if components that are used across
9
+ * multiple features are properly placed at the appropriate shared level in the folder
10
+ * structure, following the established architectural patterns.
11
+ *
12
+ * The function will output recommendations to the console, showing which components
13
+ * should be moved to shared levels for better code organization and reusability.
14
+ *
15
+ * @param cruiseParams - Configuration parameters for the dependency analysis
16
+ * @param cruiseParams.directories - Array of directory paths to analyze. Defaults to [".*"] if not provided
17
+ * @param cruiseParams.configPath - Path to the dependency-cruiser configuration file (e.g., .dependency-cruiser.js)
18
+ * @param cruiseParams.tsConfigPath - Optional path to TypeScript configuration file for enhanced type resolution
19
+ * @param cruiseParams.webpackConfigPath - Optional path to webpack configuration file for webpack alias resolution
20
+ *
21
+ * @returns Promise<void> - The function doesn't return a value but outputs results to console
22
+ *
23
+ * @throws {Error} - Throws an error if the dependency analysis fails or configuration is invalid
24
+ *
25
+ * @example
26
+ * ```typescript
27
+ * // Basic usage with default settings
28
+ * await validateSharedComponent({
29
+ * directories: ["src"],
30
+ * configPath: ".dependency-cruiser.js",
31
+ * tsConfigPath: "./tsconfig.base.json"
32
+ * });
33
+ *
34
+ * // Advanced usage with webpack support
35
+ * await validateSharedComponent({
36
+ * directories: ["src", "packages"],
37
+ * configPath: ".dependency-cruiser.js",
38
+ * tsConfigPath: "./tsconfig.base.json",
39
+ * webpackConfigPath: "./webpack.config.js"
40
+ * });
41
+ * ```
42
+ *
43
+ * @example
44
+ * ```typescript
45
+ * // Using in a build script
46
+ * import { validateSharedComponent } from "@leancodepl/folder-structure-cruiser";
47
+ *
48
+ * try {
49
+ * await validateSharedComponent({
50
+ * directories: ["src"],
51
+ * configPath: ".dependency-cruiser.js",
52
+ * tsConfigPath: "./tsconfig.base.json"
53
+ * });
54
+ * console.log("✅ Shared component validation passed");
55
+ * } catch (error) {
56
+ * console.error("❌ Shared component validation failed:", error);
57
+ * process.exit(1);
58
+ * }
59
+ * ```
60
+ */
61
+ export async function validateSharedComponent(cruiseParams) {
62
+ try {
63
+ const cruiseResult = await getCruiseResult(cruiseParams);
64
+ const { messages: infoMessages, totalCruised } = checkSharedComponents(cruiseResult);
65
+ if (infoMessages.length === 0) {
66
+ console.info("\n✅ No issues found!");
67
+ }
68
+ if (infoMessages.length > 0) {
69
+ const messages = formatMessages(infoMessages);
70
+ console.info(messages.join("\n"));
71
+ console.info(`\nx Found ${infoMessages.length} violations(s). ${totalCruised} modules cruised.`);
72
+ }
73
+ }
74
+ catch (pError) {
75
+ console.error(pError);
76
+ }
77
+ }
78
+ //# sourceMappingURL=validateSharedComponent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validateSharedComponent.js","sourceRoot":"","sources":["../../../../../packages/folder-structure-cruiser/src/commands/validateSharedComponent.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAA;AACvE,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAA;AACzD,OAAO,EAAgB,eAAe,EAAE,MAAM,2BAA2B,CAAA;AAEzE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwDG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAAC,YAA0B;IACtE,IAAI,CAAC;QACH,MAAM,YAAY,GAAG,MAAM,eAAe,CAAC,YAAY,CAAC,CAAA;QAExD,MAAM,EAAE,QAAQ,EAAE,YAAY,EAAE,YAAY,EAAE,GAAG,qBAAqB,CAAC,YAAY,CAAC,CAAA;QAEpF,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC9B,OAAO,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAA;QACtC,CAAC;QAED,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC5B,MAAM,QAAQ,GAAG,cAAc,CAAC,YAAY,CAAC,CAAA;YAC7C,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAA;YACjC,OAAO,CAAC,IAAI,CAAC,aAAa,YAAY,CAAC,MAAM,mBAAmB,YAAY,mBAAmB,CAAC,CAAA;QAClG,CAAC;IACH,CAAC;IAAC,OAAO,MAAM,EAAE,CAAC;QAChB,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;IACvB,CAAC;AACH,CAAC"}
package/src/index.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ export * from "./commands/validateCrossFeatureImports.js";
2
+ export * from "./commands/validateSharedComponent.js";
package/src/index.js ADDED
@@ -0,0 +1,3 @@
1
+ export * from "./commands/validateCrossFeatureImports.js";
2
+ export * from "./commands/validateSharedComponent.js";
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../packages/folder-structure-cruiser/src/index.ts"],"names":[],"mappings":"AAAA,cAAc,2CAA2C,CAAA;AACzD,cAAc,uCAAuC,CAAA"}
@@ -0,0 +1,8 @@
1
+ import { IReporterOutput } from "dependency-cruiser";
2
+ import { Message } from "./formatMessages.js";
3
+ type CheckResult = {
4
+ messages: Message[];
5
+ totalCruised: number;
6
+ };
7
+ export declare function checkCrossFeatureImports(result: IReporterOutput): CheckResult;
8
+ export {};
@@ -0,0 +1,31 @@
1
+ import { findCommonPathsPrefixLength } from "./findCommonPathsPrefix.js";
2
+ export function checkCrossFeatureImports(result) {
3
+ const output = typeof result.output === "object" ? result.output : undefined;
4
+ const modules = output?.modules ?? [];
5
+ const errorMessages = [];
6
+ for (const module of modules) {
7
+ if (module.coreModule) {
8
+ continue;
9
+ }
10
+ const dependencies = module.dependencies || [];
11
+ const modulePath = module.source.split("/");
12
+ dependencies.forEach(dependency => {
13
+ const dependencyPath = dependency.resolved.split("/");
14
+ const commonPrefixPathLength = findCommonPathsPrefixLength([modulePath, dependencyPath]);
15
+ if (!commonPrefixPathLength ||
16
+ (commonPrefixPathLength < modulePath.length && dependencyPath.length > commonPrefixPathLength + 2)) {
17
+ errorMessages.push({
18
+ source: module.source,
19
+ target: dependency.resolved,
20
+ rule: "cross-feature-nested-imports",
21
+ severity: "error",
22
+ });
23
+ }
24
+ });
25
+ }
26
+ return {
27
+ messages: errorMessages,
28
+ totalCruised: output?.summary.totalCruised ?? 0,
29
+ };
30
+ }
31
+ //# sourceMappingURL=checkCrossFeatureImports.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checkCrossFeatureImports.js","sourceRoot":"","sources":["../../../../../packages/folder-structure-cruiser/src/lib/checkCrossFeatureImports.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,2BAA2B,EAAE,MAAM,4BAA4B,CAAA;AAKxE,MAAM,UAAU,wBAAwB,CAAC,MAAuB;IAC9D,MAAM,MAAM,GAAG,OAAO,MAAM,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAA;IAC5E,MAAM,OAAO,GAAG,MAAM,EAAE,OAAO,IAAI,EAAE,CAAA;IAErC,MAAM,aAAa,GAAc,EAAE,CAAA;IAEnC,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;YACtB,SAAQ;QACV,CAAC;QAED,MAAM,YAAY,GAAG,MAAM,CAAC,YAAY,IAAI,EAAE,CAAA;QAE9C,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;QAE3C,YAAY,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE;YAChC,MAAM,cAAc,GAAG,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;YACrD,MAAM,sBAAsB,GAAG,2BAA2B,CAAC,CAAC,UAAU,EAAE,cAAc,CAAC,CAAC,CAAA;YAExF,IACE,CAAC,sBAAsB;gBACvB,CAAC,sBAAsB,GAAG,UAAU,CAAC,MAAM,IAAI,cAAc,CAAC,MAAM,GAAG,sBAAsB,GAAG,CAAC,CAAC,EAClG,CAAC;gBACD,aAAa,CAAC,IAAI,CAAC;oBACjB,MAAM,EAAE,MAAM,CAAC,MAAM;oBACrB,MAAM,EAAE,UAAU,CAAC,QAAQ;oBAC3B,IAAI,EAAE,8BAA8B;oBACpC,QAAQ,EAAE,OAAO;iBAClB,CAAC,CAAA;YACJ,CAAC;QACH,CAAC,CAAC,CAAA;IACJ,CAAC;IAED,OAAO;QACL,QAAQ,EAAE,aAAa;QACvB,YAAY,EAAE,MAAM,EAAE,OAAO,CAAC,YAAY,IAAI,CAAC;KAChD,CAAA;AACH,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { IReporterOutput } from "dependency-cruiser";
2
+ import { Message } from "./formatMessages.js";
3
+ type CheckResult = {
4
+ messages: Message[];
5
+ totalCruised: number;
6
+ };
7
+ export declare function checkSharedComponents(result: IReporterOutput): CheckResult;
8
+ export {};
@@ -0,0 +1,48 @@
1
+ import { findCommonPathsPrefix, findCommonPathsPrefixLength } from "./findCommonPathsPrefix.js";
2
+ function isIndexFileProperlyPositioned(pathParts, commonDependentPrefix, commonPrefixLength) {
3
+ const fileName = pathParts.at(-1) ?? "";
4
+ if (!/index\.(tsx?|jsx?|ts|js)$/.test(fileName)) {
5
+ return false;
6
+ }
7
+ const parentFolder = pathParts.at(-3) ?? "";
8
+ const expectedParentFolder = commonDependentPrefix.at(-1);
9
+ return parentFolder === expectedParentFolder && commonPrefixLength === pathParts.length - 2;
10
+ }
11
+ export function checkSharedComponents(result) {
12
+ const output = typeof result.output === "object" ? result.output : undefined;
13
+ const modules = output?.modules ?? [];
14
+ const infoMessages = [];
15
+ for (const module of modules) {
16
+ if (module.coreModule) {
17
+ continue;
18
+ }
19
+ const dependents = module.dependents || [];
20
+ if (dependents.length <= 1) {
21
+ continue;
22
+ }
23
+ const pathParts = module.source.split("/");
24
+ const pathPartsLength = pathParts.length;
25
+ if (pathPartsLength <= 2) {
26
+ continue;
27
+ }
28
+ const dependentPathParts = dependents.map(dep => dep.split("/"));
29
+ const commonDependentPrefix = findCommonPathsPrefix(dependentPathParts);
30
+ const commonPrefixLength = findCommonPathsPrefixLength([pathParts, commonDependentPrefix]);
31
+ if (isIndexFileProperlyPositioned(pathParts, commonDependentPrefix, commonPrefixLength)) {
32
+ continue;
33
+ }
34
+ if (commonPrefixLength < pathPartsLength - 1) {
35
+ infoMessages.push({
36
+ source: module.source,
37
+ target: commonDependentPrefix.join("/"),
38
+ rule: "not-shared-level",
39
+ severity: "info",
40
+ });
41
+ }
42
+ }
43
+ return {
44
+ messages: infoMessages,
45
+ totalCruised: output?.summary.totalCruised ?? 0,
46
+ };
47
+ }
48
+ //# sourceMappingURL=checkSharedComponents.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checkSharedComponents.js","sourceRoot":"","sources":["../../../../../packages/folder-structure-cruiser/src/lib/checkSharedComponents.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,qBAAqB,EAAE,2BAA2B,EAAE,MAAM,4BAA4B,CAAA;AAK/F,SAAS,6BAA6B,CACpC,SAAmB,EACnB,qBAA+B,EAC/B,kBAA0B;IAE1B,MAAM,QAAQ,GAAG,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAA;IAEvC,IAAI,CAAC,2BAA2B,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;QAChD,OAAO,KAAK,CAAA;IACd,CAAC;IAED,MAAM,YAAY,GAAG,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAA;IAC3C,MAAM,oBAAoB,GAAG,qBAAqB,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAA;IAEzD,OAAO,YAAY,KAAK,oBAAoB,IAAI,kBAAkB,KAAK,SAAS,CAAC,MAAM,GAAG,CAAC,CAAA;AAC7F,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,MAAuB;IAC3D,MAAM,MAAM,GAAG,OAAO,MAAM,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAA;IAC5E,MAAM,OAAO,GAAG,MAAM,EAAE,OAAO,IAAI,EAAE,CAAA;IACrC,MAAM,YAAY,GAAc,EAAE,CAAA;IAElC,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;YACtB,SAAQ;QACV,CAAC;QAED,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,IAAI,EAAE,CAAA;QAE1C,IAAI,UAAU,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;YAC3B,SAAQ;QACV,CAAC;QAED,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;QAC1C,MAAM,eAAe,GAAG,SAAS,CAAC,MAAM,CAAA;QAExC,IAAI,eAAe,IAAI,CAAC,EAAE,CAAC;YACzB,SAAQ;QACV,CAAC;QAED,MAAM,kBAAkB,GAAG,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAA;QAChE,MAAM,qBAAqB,GAAG,qBAAqB,CAAC,kBAAkB,CAAC,CAAA;QAEvE,MAAM,kBAAkB,GAAG,2BAA2B,CAAC,CAAC,SAAS,EAAE,qBAAqB,CAAC,CAAC,CAAA;QAE1F,IAAI,6BAA6B,CAAC,SAAS,EAAE,qBAAqB,EAAE,kBAAkB,CAAC,EAAE,CAAC;YACxF,SAAQ;QACV,CAAC;QAED,IAAI,kBAAkB,GAAG,eAAe,GAAG,CAAC,EAAE,CAAC;YAC7C,YAAY,CAAC,IAAI,CAAC;gBAChB,MAAM,EAAE,MAAM,CAAC,MAAM;gBACrB,MAAM,EAAE,qBAAqB,CAAC,IAAI,CAAC,GAAG,CAAC;gBACvC,IAAI,EAAE,kBAAkB;gBACxB,QAAQ,EAAE,MAAM;aACjB,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;IAED,OAAO;QACL,QAAQ,EAAE,YAAY;QACtB,YAAY,EAAE,MAAM,EAAE,OAAO,CAAC,YAAY,IAAI,CAAC;KAChD,CAAA;AACH,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function findCommonPathsPrefix(paths: string[][]): string[];
2
+ export declare function findCommonPathsPrefixLength(paths: string[][]): number;
@@ -0,0 +1,22 @@
1
+ export function findCommonPathsPrefix(paths) {
2
+ if (paths.length === 0)
3
+ return [];
4
+ if (paths.length === 1)
5
+ return paths[0];
6
+ const commonPrefix = [];
7
+ const minLength = Math.min(...paths.map(path => path.length));
8
+ for (let i = 0; i < minLength; i++) {
9
+ const segment = paths[0][i];
10
+ if (paths.every(path => path[i] === segment)) {
11
+ commonPrefix.push(segment);
12
+ }
13
+ else {
14
+ break;
15
+ }
16
+ }
17
+ return commonPrefix;
18
+ }
19
+ export function findCommonPathsPrefixLength(paths) {
20
+ return findCommonPathsPrefix(paths).length;
21
+ }
22
+ //# sourceMappingURL=findCommonPathsPrefix.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"findCommonPathsPrefix.js","sourceRoot":"","sources":["../../../../../packages/folder-structure-cruiser/src/lib/findCommonPathsPrefix.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,qBAAqB,CAAC,KAAiB;IACrD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAA;IACjC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC,CAAC,CAAC,CAAA;IAEvC,MAAM,YAAY,GAAa,EAAE,CAAA;IACjC,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAA;IAE7D,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,EAAE,CAAC,EAAE,EAAE,CAAC;QACnC,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;QAC3B,IAAI,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,EAAE,CAAC;YAC7C,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;QAC5B,CAAC;aAAM,CAAC;YACN,MAAK;QACP,CAAC;IACH,CAAC;IAED,OAAO,YAAY,CAAA;AACrB,CAAC;AAED,MAAM,UAAU,2BAA2B,CAAC,KAAiB;IAC3D,OAAO,qBAAqB,CAAC,KAAK,CAAC,CAAC,MAAM,CAAA;AAC5C,CAAC"}
@@ -0,0 +1,9 @@
1
+ type Severity = "error" | "info";
2
+ export interface Message {
3
+ source: string;
4
+ target: string;
5
+ rule: string;
6
+ severity: Severity;
7
+ }
8
+ export declare function formatMessages(messages: Message[]): string[];
9
+ export {};
@@ -0,0 +1,9 @@
1
+ import pc from "picocolors";
2
+ const { blue, bold, red } = pc;
3
+ const colorSeverity = (type) => (type === "info" ? blue(type) : red(type));
4
+ export function formatMessages(messages) {
5
+ return messages.map(message => {
6
+ return ` ${colorSeverity(message.severity)} ${message.rule}: ${bold(message.source)} → ${bold(message.target)}`;
7
+ });
8
+ }
9
+ //# sourceMappingURL=formatMessages.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formatMessages.js","sourceRoot":"","sources":["../../../../../packages/folder-structure-cruiser/src/lib/formatMessages.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAA;AAE3B,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,CAAA;AAI9B,MAAM,aAAa,GAAG,CAAC,IAAc,EAAE,EAAE,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAA;AASpF,MAAM,UAAU,cAAc,CAAC,QAAmB;IAChD,OAAO,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE;QAC5B,OAAO,KAAK,aAAa,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,OAAO,CAAC,IAAI,KAAK,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAA;IAClH,CAAC,CAAC,CAAA;AACJ,CAAC"}
@@ -0,0 +1,7 @@
1
+ export type CruiseParams = {
2
+ directories: string[];
3
+ configPath: string;
4
+ tsConfigPath?: string;
5
+ webpackConfigPath?: string;
6
+ };
7
+ export declare function getCruiseResult({ directories, configPath, tsConfigPath, webpackConfigPath, }: CruiseParams): Promise<import("dependency-cruiser").IReporterOutput>;
@@ -0,0 +1,14 @@
1
+ import { cruise } from "dependency-cruiser";
2
+ import extractDepcruiseOptions from "dependency-cruiser/config-utl/extract-depcruise-options";
3
+ import extractTSConfig from "dependency-cruiser/config-utl/extract-ts-config";
4
+ import extractWebpackResolveConfig from "dependency-cruiser/config-utl/extract-webpack-resolve-config";
5
+ export async function getCruiseResult({ directories = [".*"], configPath, tsConfigPath, webpackConfigPath, }) {
6
+ const depcruiseOptions = await extractDepcruiseOptions(configPath);
7
+ const webpackConfig = webpackConfigPath ? await extractWebpackResolveConfig(webpackConfigPath) : undefined;
8
+ const tsConfig = tsConfigPath ? extractTSConfig(tsConfigPath) : undefined;
9
+ const cruiseResult = await cruise(directories, { ...depcruiseOptions }, webpackConfig, {
10
+ tsConfig,
11
+ });
12
+ return cruiseResult;
13
+ }
14
+ //# sourceMappingURL=getCruiseResult.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getCruiseResult.js","sourceRoot":"","sources":["../../../../../packages/folder-structure-cruiser/src/lib/getCruiseResult.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAmC,MAAM,oBAAoB,CAAA;AAC5E,OAAO,uBAAuB,MAAM,yDAAyD,CAAA;AAC7F,OAAO,eAAe,MAAM,iDAAiD,CAAA;AAC7E,OAAO,2BAA2B,MAAM,8DAA8D,CAAA;AAStG,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,EACpC,WAAW,GAAG,CAAC,IAAI,CAAC,EACpB,UAAU,EACV,YAAY,EACZ,iBAAiB,GACJ;IACb,MAAM,gBAAgB,GAAmB,MAAM,uBAAuB,CAAC,UAAU,CAAC,CAAA;IAClF,MAAM,aAAa,GAAG,iBAAiB,CAAC,CAAC,CAAC,MAAM,2BAA2B,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;IAC1G,MAAM,QAAQ,GAAG,YAAY,CAAC,CAAC,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;IAEzE,MAAM,YAAY,GAAG,MAAM,MAAM,CAAC,WAAW,EAAE,EAAE,GAAG,gBAAgB,EAAE,EAAE,aAAgC,EAAE;QACxG,QAAQ;KACT,CAAC,CAAA;IAEF,OAAO,YAAY,CAAA;AACrB,CAAC"}