project-structure-lint 1.0.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.
Files changed (62) hide show
  1. package/.validate-structurerc.example.json +45 -0
  2. package/CHANGELOG.md +42 -0
  3. package/CONTRIBUTING.md +142 -0
  4. package/LICENSE +21 -0
  5. package/PROJECT_SUMMARY.md +252 -0
  6. package/QUICK_START.md +164 -0
  7. package/README.md +330 -0
  8. package/dist/cli.d.ts +3 -0
  9. package/dist/cli.d.ts.map +1 -0
  10. package/dist/cli.js +121 -0
  11. package/dist/cli.js.map +1 -0
  12. package/dist/config/loader.d.ts +4 -0
  13. package/dist/config/loader.d.ts.map +1 -0
  14. package/dist/config/loader.js +71 -0
  15. package/dist/config/loader.js.map +1 -0
  16. package/dist/core/validator.d.ts +16 -0
  17. package/dist/core/validator.d.ts.map +1 -0
  18. package/dist/core/validator.js +231 -0
  19. package/dist/core/validator.js.map +1 -0
  20. package/dist/index.d.ts +6 -0
  21. package/dist/index.d.ts.map +1 -0
  22. package/dist/index.js +29 -0
  23. package/dist/index.js.map +1 -0
  24. package/dist/presets/index.d.ts +5 -0
  25. package/dist/presets/index.d.ts.map +1 -0
  26. package/dist/presets/index.js +17 -0
  27. package/dist/presets/index.js.map +1 -0
  28. package/dist/presets/react.d.ts +3 -0
  29. package/dist/presets/react.d.ts.map +1 -0
  30. package/dist/presets/react.js +94 -0
  31. package/dist/presets/react.js.map +1 -0
  32. package/dist/reporters/consoleReporter.d.ts +9 -0
  33. package/dist/reporters/consoleReporter.d.ts.map +1 -0
  34. package/dist/reporters/consoleReporter.js +98 -0
  35. package/dist/reporters/consoleReporter.js.map +1 -0
  36. package/dist/types/index.d.ts +59 -0
  37. package/dist/types/index.d.ts.map +1 -0
  38. package/dist/types/index.js +4 -0
  39. package/dist/types/index.js.map +1 -0
  40. package/dist/utils/fileScanner.d.ts +20 -0
  41. package/dist/utils/fileScanner.d.ts.map +1 -0
  42. package/dist/utils/fileScanner.js +166 -0
  43. package/dist/utils/fileScanner.js.map +1 -0
  44. package/dist/utils/naming.d.ts +4 -0
  45. package/dist/utils/naming.d.ts.map +1 -0
  46. package/dist/utils/naming.js +75 -0
  47. package/dist/utils/naming.js.map +1 -0
  48. package/jest.config.js +17 -0
  49. package/package.json +48 -0
  50. package/src/cli.ts +106 -0
  51. package/src/config/loader.ts +79 -0
  52. package/src/core/validator.ts +242 -0
  53. package/src/index.ts +6 -0
  54. package/src/presets/index.ts +16 -0
  55. package/src/presets/react.ts +93 -0
  56. package/src/reporters/consoleReporter.ts +116 -0
  57. package/src/types/index.ts +67 -0
  58. package/src/types/micromatch.d.ts +41 -0
  59. package/src/utils/__tests__/naming.test.ts +107 -0
  60. package/src/utils/fileScanner.ts +162 -0
  61. package/src/utils/naming.ts +99 -0
  62. package/tsconfig.json +20 -0
package/README.md ADDED
@@ -0,0 +1,330 @@
1
+ # project-structure-lint
2
+
3
+ A powerful CLI tool to validate project folder structure and file naming conventions with configurable presets. Perfect for maintaining consistency across React, Vue, Angular, and other JavaScript/TypeScript projects.
4
+
5
+ ## Features
6
+
7
+ ✅ **Component Co-location Validation** - Ensures all related files (tests, stories, styles) are in the same folder
8
+ ✅ **File Naming Convention Enforcement** - Supports PascalCase, camelCase, kebab-case, snake_case, and UPPER_CASE
9
+ ✅ **Folder Structure Validation** - Enforces project directory organization
10
+ ✅ **Configurable Presets** - Built-in React preset with easy customization
11
+ ✅ **Detailed Error Reporting** - Clear messages with suggestions for fixes
12
+ ✅ **CI/CD Integration** - Exit codes for automated workflows
13
+
14
+ ## Installation
15
+
16
+ ```bash
17
+ npm install --save-dev project-structure-lint
18
+ ```
19
+
20
+ Or use globally:
21
+
22
+ ```bash
23
+ npm install -g project-structure-lint
24
+ ```
25
+
26
+ ## Quick Start
27
+
28
+ ### 1. Initialize Configuration
29
+
30
+ ```bash
31
+ npx validate-structure init
32
+ ```
33
+
34
+ This creates a `.validate-structurerc.json` file with the React preset.
35
+
36
+ ### 2. Run Validation
37
+
38
+ ```bash
39
+ npx validate-structure check
40
+ ```
41
+
42
+ ## Usage
43
+
44
+ ### Commands
45
+
46
+ #### `check`
47
+ Validate your project structure:
48
+
49
+ ```bash
50
+ validate-structure check [options]
51
+
52
+ Options:
53
+ -c, --config <path> Path to configuration file
54
+ -r, --root <path> Root directory to validate (default: current directory)
55
+ ```
56
+
57
+ #### `init`
58
+ Initialize a configuration file:
59
+
60
+ ```bash
61
+ validate-structure init [options]
62
+
63
+ Options:
64
+ -p, --preset <name> Preset to use (default: react)
65
+ ```
66
+
67
+ #### `presets`
68
+ List available presets:
69
+
70
+ ```bash
71
+ validate-structure presets
72
+ ```
73
+
74
+ ## Configuration
75
+
76
+ ### Using Presets
77
+
78
+ The easiest way to get started is using a preset:
79
+
80
+ ```json
81
+ {
82
+ "preset": "react"
83
+ }
84
+ ```
85
+
86
+ ### Custom Configuration
87
+
88
+ Create a `.validate-structurerc.json` file:
89
+
90
+ ```json
91
+ {
92
+ "preset": "react",
93
+ "rootDir": "src",
94
+ "rules": {
95
+ "componentColocation": {
96
+ "enabled": true,
97
+ "componentDirs": ["components", "pages", "features"],
98
+ "requiredFiles": [
99
+ {
100
+ "pattern": "*.test.{ts,tsx}",
101
+ "required": true,
102
+ "description": "Test file"
103
+ },
104
+ {
105
+ "pattern": "*.stories.{ts,tsx}",
106
+ "required": true,
107
+ "description": "Storybook story"
108
+ }
109
+ ],
110
+ "namingConvention": "PascalCase"
111
+ },
112
+ "fileNaming": {
113
+ "components/**/*.{tsx,jsx}": {
114
+ "convention": "PascalCase",
115
+ "severity": "error"
116
+ },
117
+ "hooks/**/*.{ts,tsx}": {
118
+ "convention": "camelCase",
119
+ "severity": "error"
120
+ },
121
+ "utils/**/*.{ts,js}": {
122
+ "convention": "camelCase",
123
+ "severity": "error"
124
+ }
125
+ },
126
+ "folderStructure": [
127
+ {
128
+ "name": "components",
129
+ "path": "src/components",
130
+ "namingConvention": "PascalCase",
131
+ "allowedExtensions": [".tsx", ".ts", ".css", ".scss"]
132
+ }
133
+ ]
134
+ },
135
+ "ignore": [
136
+ "**/node_modules/**",
137
+ "**/dist/**",
138
+ "**/build/**"
139
+ ],
140
+ "severity": "error"
141
+ }
142
+ ```
143
+
144
+ ## Configuration Options
145
+
146
+ ### `preset`
147
+ - Type: `string`
148
+ - Available: `"react"`
149
+ - Use a predefined configuration preset
150
+
151
+ ### `rootDir`
152
+ - Type: `string`
153
+ - Default: `"src"`
154
+ - Root directory for validation
155
+
156
+ ### `rules.componentColocation`
157
+
158
+ Validates that component files are co-located with their tests, stories, etc.
159
+
160
+ ```json
161
+ {
162
+ "enabled": true,
163
+ "componentDirs": ["components", "pages"],
164
+ "requiredFiles": [
165
+ {
166
+ "pattern": "*.test.tsx",
167
+ "required": true,
168
+ "description": "Test file"
169
+ }
170
+ ],
171
+ "namingConvention": "PascalCase"
172
+ }
173
+ ```
174
+
175
+ ### `rules.fileNaming`
176
+
177
+ Enforces naming conventions for files matching patterns:
178
+
179
+ ```json
180
+ {
181
+ "components/**/*.tsx": {
182
+ "convention": "PascalCase",
183
+ "severity": "error"
184
+ }
185
+ }
186
+ ```
187
+
188
+ **Supported conventions:**
189
+ - `PascalCase` - `MyComponent.tsx`
190
+ - `camelCase` - `useAuth.ts`
191
+ - `kebab-case` - `my-component.tsx`
192
+ - `snake_case` - `my_component.tsx`
193
+ - `UPPER_CASE` - `API_CONSTANTS.ts`
194
+
195
+ ### `rules.folderStructure`
196
+
197
+ Validates directory structure and contents:
198
+
199
+ ```json
200
+ {
201
+ "name": "components",
202
+ "path": "src/components",
203
+ "namingConvention": "PascalCase",
204
+ "allowedExtensions": [".tsx", ".ts", ".css"]
205
+ }
206
+ ```
207
+
208
+ ### `ignore`
209
+
210
+ Patterns to ignore (uses glob syntax):
211
+
212
+ ```json
213
+ {
214
+ "ignore": [
215
+ "**/node_modules/**",
216
+ "**/dist/**",
217
+ "**/*.test.ts"
218
+ ]
219
+ }
220
+ ```
221
+
222
+ ### `severity`
223
+
224
+ Default severity level:
225
+ - `"error"` - Fails validation
226
+ - `"warning"` - Shows warning but passes
227
+
228
+ ## Examples
229
+
230
+ ### React Component Structure
231
+
232
+ For a component named `Button`, the tool validates:
233
+
234
+ ```
235
+ components/
236
+ └── Button/
237
+ ├── Button.tsx ✓ Main component
238
+ ├── Button.test.tsx ✓ Test file
239
+ ├── Button.stories.tsx ✓ Storybook story
240
+ ├── Button.module.css ✓ Styles
241
+ └── index.ts ✓ Re-export
242
+ ```
243
+
244
+ ### Naming Convention Validation
245
+
246
+ ```typescript
247
+ // ✓ Valid
248
+ components/Button/Button.tsx
249
+ hooks/useAuth.ts
250
+ utils/formatDate.ts
251
+
252
+ // ✗ Invalid
253
+ components/button/button.tsx // Should be PascalCase
254
+ hooks/UseAuth.ts // Should be camelCase
255
+ utils/format_date.ts // Should be camelCase
256
+ ```
257
+
258
+ ## CI/CD Integration
259
+
260
+ Add to your CI pipeline:
261
+
262
+ ```yaml
263
+ # GitHub Actions
264
+ - name: Validate Project Structure
265
+ run: npx validate-structure check
266
+ ```
267
+
268
+ ```json
269
+ // package.json
270
+ {
271
+ "scripts": {
272
+ "validate": "validate-structure check",
273
+ "precommit": "validate-structure check"
274
+ }
275
+ }
276
+ ```
277
+
278
+ ## Programmatic Usage
279
+
280
+ ```typescript
281
+ import { ProjectValidator, loadConfig } from 'project-structure-lint';
282
+
283
+ async function validate() {
284
+ const config = await loadConfig();
285
+ const validator = new ProjectValidator(config, process.cwd());
286
+ const result = await validator.validate();
287
+
288
+ console.log(`Valid: ${result.valid}`);
289
+ console.log(`Errors: ${result.errors.length}`);
290
+ console.log(`Warnings: ${result.warnings.length}`);
291
+ }
292
+ ```
293
+
294
+ ## Output Example
295
+
296
+ ```
297
+ Project Structure Validation Results
298
+ ──────────────────────────────────────────────────
299
+ Files scanned: 45
300
+ Directories scanned: 12
301
+
302
+ ✗ 2 Errors
303
+
304
+ 1. Missing required file: Test file for component
305
+ Directory: components/Button
306
+ Expected: Button.test.tsx
307
+ 💡 Create Button.test.tsx in components/Button/
308
+
309
+ 2. File name doesn't follow PascalCase convention
310
+ File: components/myComponent/myComponent.tsx
311
+ Actual: myComponent.tsx
312
+ Expected: MyComponent.tsx
313
+ 💡 Rename to MyComponent.tsx
314
+
315
+ ──────────────────────────────────────────────────
316
+
317
+ ✗ Validation failed with 2 errors
318
+ ```
319
+
320
+ ## Contributing
321
+
322
+ Contributions are welcome! Please feel free to submit a Pull Request.
323
+
324
+ ## License
325
+
326
+ MIT
327
+
328
+ ## Author
329
+
330
+ Created with ❤️ for better project organization
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
package/dist/cli.js ADDED
@@ -0,0 +1,121 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4
+ if (k2 === undefined) k2 = k;
5
+ var desc = Object.getOwnPropertyDescriptor(m, k);
6
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
7
+ desc = { enumerable: true, get: function() { return m[k]; } };
8
+ }
9
+ Object.defineProperty(o, k2, desc);
10
+ }) : (function(o, m, k, k2) {
11
+ if (k2 === undefined) k2 = k;
12
+ o[k2] = m[k];
13
+ }));
14
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
15
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
16
+ }) : function(o, v) {
17
+ o["default"] = v;
18
+ });
19
+ var __importStar = (this && this.__importStar) || (function () {
20
+ var ownKeys = function(o) {
21
+ ownKeys = Object.getOwnPropertyNames || function (o) {
22
+ var ar = [];
23
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
24
+ return ar;
25
+ };
26
+ return ownKeys(o);
27
+ };
28
+ return function (mod) {
29
+ if (mod && mod.__esModule) return mod;
30
+ var result = {};
31
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
32
+ __setModuleDefault(result, mod);
33
+ return result;
34
+ };
35
+ })();
36
+ Object.defineProperty(exports, "__esModule", { value: true });
37
+ const commander_1 = require("commander");
38
+ const loader_1 = require("./config/loader");
39
+ const validator_1 = require("./core/validator");
40
+ const consoleReporter_1 = require("./reporters/consoleReporter");
41
+ const presets_1 = require("./presets");
42
+ const program = new commander_1.Command();
43
+ program
44
+ .name('validate-structure')
45
+ .description('Validate project folder structure and file naming conventions')
46
+ .version('1.0.0');
47
+ program
48
+ .command('check')
49
+ .description('Validate the project structure')
50
+ .option('-c, --config <path>', 'Path to configuration file')
51
+ .option('-r, --root <path>', 'Root directory to validate (default: current directory)')
52
+ .action(async (options) => {
53
+ const reporter = new consoleReporter_1.ConsoleReporter();
54
+ try {
55
+ // Load configuration
56
+ const config = await (0, loader_1.loadConfig)(options.config);
57
+ // Validate configuration
58
+ const configErrors = (0, loader_1.validateConfig)(config);
59
+ if (configErrors.length > 0) {
60
+ reporter.reportConfigErrors(configErrors);
61
+ process.exit(1);
62
+ }
63
+ // Run validation
64
+ const rootDir = options.root || process.cwd();
65
+ const validator = new validator_1.ProjectValidator(config, rootDir);
66
+ const result = await validator.validate();
67
+ // Report results
68
+ reporter.report(result);
69
+ // Exit with appropriate code
70
+ process.exit(result.valid ? 0 : 1);
71
+ }
72
+ catch (error) {
73
+ reporter.reportConfigError(error instanceof Error ? error.message : 'Unknown error occurred');
74
+ process.exit(1);
75
+ }
76
+ });
77
+ program
78
+ .command('init')
79
+ .description('Initialize a configuration file')
80
+ .option('-p, --preset <name>', 'Preset to use (default: react)', 'react')
81
+ .action(async (options) => {
82
+ const fs = await Promise.resolve().then(() => __importStar(require('fs')));
83
+ const path = await Promise.resolve().then(() => __importStar(require('path')));
84
+ const configPath = path.join(process.cwd(), '.validate-structurerc.json');
85
+ if (fs.existsSync(configPath)) {
86
+ console.log('Configuration file already exists at:', configPath);
87
+ process.exit(1);
88
+ }
89
+ const presetName = options.preset;
90
+ const availablePresets = (0, presets_1.listPresets)();
91
+ if (!availablePresets.includes(presetName)) {
92
+ console.log(`Preset "${presetName}" not found.`);
93
+ console.log('Available presets:', availablePresets.join(', '));
94
+ process.exit(1);
95
+ }
96
+ const config = {
97
+ preset: presetName,
98
+ // Users can customize these
99
+ rules: {
100
+ componentColocation: {
101
+ enabled: true
102
+ }
103
+ }
104
+ };
105
+ fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
106
+ console.log(`Configuration file created at: ${configPath}`);
107
+ console.log(`Using preset: ${presetName}`);
108
+ });
109
+ program
110
+ .command('presets')
111
+ .description('List available presets')
112
+ .action(() => {
113
+ const presets = (0, presets_1.listPresets)();
114
+ console.log('\nAvailable presets:');
115
+ presets.forEach(preset => {
116
+ console.log(` • ${preset}`);
117
+ });
118
+ console.log('');
119
+ });
120
+ program.parse();
121
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import { ProjectConfig } from '../types';
2
+ export declare function loadConfig(configPath?: string): Promise<ProjectConfig>;
3
+ export declare function validateConfig(config: ProjectConfig): string[];
4
+ //# sourceMappingURL=loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/config/loader.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAKzC,wBAAsB,UAAU,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAgC5E;AAyBD,wBAAgB,cAAc,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,EAAE,CAa9D"}
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.loadConfig = loadConfig;
4
+ exports.validateConfig = validateConfig;
5
+ const cosmiconfig_1 = require("cosmiconfig");
6
+ const presets_1 = require("../presets");
7
+ const explorer = (0, cosmiconfig_1.cosmiconfig)('validate-structure');
8
+ async function loadConfig(configPath) {
9
+ let result;
10
+ if (configPath) {
11
+ result = await explorer.load(configPath);
12
+ }
13
+ else {
14
+ result = await explorer.search();
15
+ }
16
+ if (!result || !result.config) {
17
+ // Return default React preset if no config found
18
+ const reactPreset = (0, presets_1.getPreset)('react');
19
+ if (!reactPreset) {
20
+ throw new Error('Default React preset not found');
21
+ }
22
+ return reactPreset.config;
23
+ }
24
+ const config = result.config;
25
+ // If preset is specified, merge with preset config
26
+ if (config.preset) {
27
+ const preset = (0, presets_1.getPreset)(config.preset);
28
+ if (!preset) {
29
+ throw new Error(`Preset "${config.preset}" not found`);
30
+ }
31
+ // Merge preset config with user config (user config takes precedence)
32
+ return mergeConfigs(preset.config, config);
33
+ }
34
+ return config;
35
+ }
36
+ function mergeConfigs(preset, user) {
37
+ return {
38
+ ...preset,
39
+ ...user,
40
+ rules: {
41
+ ...preset.rules,
42
+ ...user.rules,
43
+ componentColocation: user.rules?.componentColocation
44
+ ? {
45
+ ...preset.rules?.componentColocation,
46
+ ...user.rules.componentColocation
47
+ }
48
+ : preset.rules?.componentColocation,
49
+ fileNaming: {
50
+ ...preset.rules?.fileNaming,
51
+ ...user.rules?.fileNaming
52
+ },
53
+ folderStructure: user.rules?.folderStructure || preset.rules?.folderStructure
54
+ },
55
+ ignore: [...(preset.ignore || []), ...(user.ignore || [])]
56
+ };
57
+ }
58
+ function validateConfig(config) {
59
+ const errors = [];
60
+ if (config.rules?.componentColocation?.enabled) {
61
+ if (!config.rules.componentColocation.componentDirs?.length) {
62
+ errors.push('componentColocation.componentDirs must be specified when enabled');
63
+ }
64
+ if (!config.rules.componentColocation.requiredFiles?.length) {
65
+ errors.push('componentColocation.requiredFiles must be specified when enabled');
66
+ }
67
+ }
68
+ return errors;
69
+ }
70
+ // Made with
71
+ //# sourceMappingURL=loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/config/loader.ts"],"names":[],"mappings":";;AAMA,gCAgCC;AAyBD,wCAaC;AA5ED,6CAA0C;AAE1C,wCAAuC;AAEvC,MAAM,QAAQ,GAAG,IAAA,yBAAW,EAAC,oBAAoB,CAAC,CAAC;AAE5C,KAAK,UAAU,UAAU,CAAC,UAAmB;IAClD,IAAI,MAAM,CAAC;IAEX,IAAI,UAAU,EAAE,CAAC;QACf,MAAM,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC3C,CAAC;SAAM,CAAC;QACN,MAAM,GAAG,MAAM,QAAQ,CAAC,MAAM,EAAE,CAAC;IACnC,CAAC;IAED,IAAI,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;QAC9B,iDAAiD;QACjD,MAAM,WAAW,GAAG,IAAA,mBAAS,EAAC,OAAO,CAAC,CAAC;QACvC,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;QACpD,CAAC;QACD,OAAO,WAAW,CAAC,MAAM,CAAC;IAC5B,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,CAAC,MAAuB,CAAC;IAE9C,mDAAmD;IACnD,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;QAClB,MAAM,MAAM,GAAG,IAAA,mBAAS,EAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACxC,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,WAAW,MAAM,CAAC,MAAM,aAAa,CAAC,CAAC;QACzD,CAAC;QAED,sEAAsE;QACtE,OAAO,YAAY,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7C,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,YAAY,CAAC,MAAqB,EAAE,IAAmB;IAC9D,OAAO;QACL,GAAG,MAAM;QACT,GAAG,IAAI;QACP,KAAK,EAAE;YACL,GAAG,MAAM,CAAC,KAAK;YACf,GAAG,IAAI,CAAC,KAAK;YACb,mBAAmB,EAAE,IAAI,CAAC,KAAK,EAAE,mBAAmB;gBAClD,CAAC,CAAC;oBACE,GAAG,MAAM,CAAC,KAAK,EAAE,mBAAmB;oBACpC,GAAG,IAAI,CAAC,KAAK,CAAC,mBAAmB;iBAClC;gBACH,CAAC,CAAC,MAAM,CAAC,KAAK,EAAE,mBAAmB;YACrC,UAAU,EAAE;gBACV,GAAG,MAAM,CAAC,KAAK,EAAE,UAAU;gBAC3B,GAAG,IAAI,CAAC,KAAK,EAAE,UAAU;aAC1B;YACD,eAAe,EAAE,IAAI,CAAC,KAAK,EAAE,eAAe,IAAI,MAAM,CAAC,KAAK,EAAE,eAAe;SAC9E;QACD,MAAM,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC;KAC3D,CAAC;AACJ,CAAC;AAED,SAAgB,cAAc,CAAC,MAAqB;IAClD,MAAM,MAAM,GAAa,EAAE,CAAC;IAE5B,IAAI,MAAM,CAAC,KAAK,EAAE,mBAAmB,EAAE,OAAO,EAAE,CAAC;QAC/C,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,mBAAmB,CAAC,aAAa,EAAE,MAAM,EAAE,CAAC;YAC5D,MAAM,CAAC,IAAI,CAAC,kEAAkE,CAAC,CAAC;QAClF,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,mBAAmB,CAAC,aAAa,EAAE,MAAM,EAAE,CAAC;YAC5D,MAAM,CAAC,IAAI,CAAC,kEAAkE,CAAC,CAAC;QAClF,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,aAAa"}
@@ -0,0 +1,16 @@
1
+ import { ProjectConfig, ValidationResult } from '../types';
2
+ export declare class ProjectValidator {
3
+ private config;
4
+ private scanner;
5
+ private errors;
6
+ private warnings;
7
+ constructor(config: ProjectConfig, rootDir?: string);
8
+ validate(): Promise<ValidationResult>;
9
+ private validateComponentColocation;
10
+ private validateFileNaming;
11
+ private validateFolderStructure;
12
+ private isComponentFile;
13
+ private expandPattern;
14
+ private addError;
15
+ }
16
+ //# sourceMappingURL=validator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../../src/core/validator.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAmB,gBAAgB,EAAe,MAAM,UAAU,CAAC;AAIzF,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,OAAO,CAAc;IAC7B,OAAO,CAAC,MAAM,CAAyB;IACvC,OAAO,CAAC,QAAQ,CAAyB;gBAE7B,MAAM,EAAE,aAAa,EAAE,OAAO,GAAE,MAAsB;IAM5D,QAAQ,IAAI,OAAO,CAAC,gBAAgB,CAAC;YAgC7B,2BAA2B;YA0E3B,kBAAkB;YAgClB,uBAAuB;IAkErC,OAAO,CAAC,eAAe;IAMvB,OAAO,CAAC,aAAa;IAIrB,OAAO,CAAC,QAAQ;CAOjB"}