stratifyjs 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +354 -0
  3. package/lib/adapters/config-file-loader.d.ts +8 -0
  4. package/lib/adapters/config-file-loader.js +55 -0
  5. package/lib/adapters/file-system-discovery.d.ts +22 -0
  6. package/lib/adapters/file-system-discovery.js +61 -0
  7. package/lib/api/api.d.ts +42 -0
  8. package/lib/api/api.js +75 -0
  9. package/lib/api/index.d.ts +15 -0
  10. package/lib/api/index.js +12 -0
  11. package/lib/cli/command-handler.d.ts +6 -0
  12. package/lib/cli/command-handler.js +50 -0
  13. package/lib/cli/index.d.ts +2 -0
  14. package/lib/cli/index.js +23 -0
  15. package/lib/cli/options.d.ts +18 -0
  16. package/lib/cli/options.js +21 -0
  17. package/lib/cli/output-helpers.d.ts +9 -0
  18. package/lib/cli/output-helpers.js +22 -0
  19. package/lib/core/config-defaults.d.ts +7 -0
  20. package/lib/core/config-defaults.js +22 -0
  21. package/lib/core/config-schema.d.ts +11 -0
  22. package/lib/core/config-schema.js +102 -0
  23. package/lib/core/errors.d.ts +44 -0
  24. package/lib/core/errors.js +25 -0
  25. package/lib/core/formatters/console-formatter.d.ts +3 -0
  26. package/lib/core/formatters/console-formatter.js +34 -0
  27. package/lib/core/formatters/json-formatter.d.ts +5 -0
  28. package/lib/core/formatters/json-formatter.js +11 -0
  29. package/lib/core/package-parser.d.ts +11 -0
  30. package/lib/core/package-parser.js +37 -0
  31. package/lib/core/report-builder.d.ts +18 -0
  32. package/lib/core/report-builder.js +17 -0
  33. package/lib/core/result.d.ts +33 -0
  34. package/lib/core/result.js +24 -0
  35. package/lib/core/rules.d.ts +14 -0
  36. package/lib/core/rules.js +19 -0
  37. package/lib/core/validation.d.ts +5 -0
  38. package/lib/core/validation.js +51 -0
  39. package/lib/types/types.d.ts +66 -0
  40. package/lib/types/types.js +1 -0
  41. package/package.json +67 -0
@@ -0,0 +1,51 @@
1
+ import { hasRequiredLayer, isKnownLayer, isDependencyAllowed } from './rules.js';
2
+ /**
3
+ * Validate all packages against layer configuration.
4
+ */
5
+ export function validatePackages(packages, config) {
6
+ const violations = [];
7
+ const packageMap = new Map(packages.map(pkg => [pkg.name, pkg]));
8
+ for (const pkg of packages) {
9
+ // Rule 1: Check if package has a layer field
10
+ if (!hasRequiredLayer(pkg)) {
11
+ violations.push({
12
+ type: 'missing-layer',
13
+ package: pkg.name,
14
+ message: `Package "${pkg.name}" is missing the required "layer" field in package.json`,
15
+ });
16
+ continue; // Cannot validate further without layer
17
+ }
18
+ const layer = pkg.layer;
19
+ // Rule 2: Layer must be defined in config
20
+ if (!isKnownLayer(layer, config.layers)) {
21
+ violations.push({
22
+ type: 'unknown-layer',
23
+ package: pkg.name,
24
+ message: `Package "${pkg.name}" has unknown layer "${layer}". Valid layers: ${Object.keys(config.layers).join(', ')}`,
25
+ });
26
+ continue;
27
+ }
28
+ // Rule 3: Each dependency must target an allowed layer
29
+ const layerDef = config.layers[layer];
30
+ for (const depName of pkg.dependencies) {
31
+ const depPkg = packageMap.get(depName);
32
+ if (!depPkg || !depPkg.layer) {
33
+ continue; // Skip dependencies that are not discovered or have no layer
34
+ }
35
+ if (!isDependencyAllowed(layer, depPkg.layer, layerDef.allowedDependencies)) {
36
+ violations.push({
37
+ type: 'invalid-dependency',
38
+ package: pkg.name,
39
+ message: `Layer violation: "${pkg.name}" (${layer}) cannot depend on "${depPkg.name}" (${depPkg.layer})`,
40
+ details: {
41
+ fromLayer: layer,
42
+ toPackage: depPkg.name,
43
+ toLayer: depPkg.layer,
44
+ allowedLayers: layerDef.allowedDependencies,
45
+ },
46
+ });
47
+ }
48
+ }
49
+ }
50
+ return violations;
51
+ }
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Represents a discovered package in the monorepo
3
+ */
4
+ export interface Package {
5
+ name: string;
6
+ layer?: string;
7
+ dependencies: string[];
8
+ path: string;
9
+ }
10
+ /**
11
+ * Layer definition in the configuration
12
+ */
13
+ export interface LayerDefinition {
14
+ description?: string;
15
+ allowedDependencies: string[];
16
+ }
17
+ /**
18
+ * Map of layer names to their definitions
19
+ */
20
+ export type LayerMap = Record<string, LayerDefinition>;
21
+ /**
22
+ * Enforcement configuration
23
+ */
24
+ export interface EnforcementConfig {
25
+ mode: 'error' | 'warn' | 'off';
26
+ }
27
+ /**
28
+ * Workspace discovery configuration
29
+ */
30
+ export interface WorkspaceConfig {
31
+ patterns: string[];
32
+ }
33
+ /**
34
+ * Layer configuration file (as written by user)
35
+ */
36
+ export interface LayerConfig {
37
+ layers: LayerMap;
38
+ workspaces?: Partial<WorkspaceConfig>;
39
+ enforcement?: Partial<EnforcementConfig>;
40
+ }
41
+ /**
42
+ * Resolved config with all defaults applied
43
+ */
44
+ export interface ResolvedConfig {
45
+ layers: LayerMap;
46
+ workspaces: WorkspaceConfig;
47
+ enforcement: EnforcementConfig;
48
+ }
49
+ /**
50
+ * Violation types
51
+ */
52
+ export type ViolationType = 'missing-layer' | 'unknown-layer' | 'invalid-dependency';
53
+ /**
54
+ * A single validation violation
55
+ */
56
+ export interface Violation {
57
+ type: ViolationType;
58
+ package: string;
59
+ message: string;
60
+ details?: {
61
+ fromLayer?: string;
62
+ toPackage?: string;
63
+ toLayer?: string;
64
+ allowedLayers?: string[];
65
+ };
66
+ }
@@ -0,0 +1 @@
1
+ export {};
package/package.json ADDED
@@ -0,0 +1,67 @@
1
+ {
2
+ "name": "stratifyjs",
3
+ "version": "1.0.0",
4
+ "description": "Enforce architectural layer boundaries in monorepos",
5
+ "type": "module",
6
+ "bin": {
7
+ "stratify": "./lib/cli/index.js"
8
+ },
9
+ "main": "./lib/api/index.js",
10
+ "types": "./lib/api/index.d.ts",
11
+ "exports": {
12
+ ".": {
13
+ "source": "./src/api/index.ts",
14
+ "types": "./lib/api/index.d.ts",
15
+ "default": "./lib/api/index.js"
16
+ },
17
+ "./cli": {
18
+ "source": "./src/cli/index.ts",
19
+ "types": "./lib/cli/index.d.ts",
20
+ "default": "./lib/cli/index.js"
21
+ }
22
+ },
23
+ "scripts": {
24
+ "build": "tsc -p tsconfig.json",
25
+ "dev": "tsc -p tsconfig.json --watch",
26
+ "start": "node lib/cli/index.js",
27
+ "test": "node --experimental-vm-modules ./node_modules/jest/bin/jest.js",
28
+ "test:watch": "node --experimental-vm-modules ./node_modules/jest/bin/jest.js --watch",
29
+ "typecheck": "tsc --noEmit",
30
+ "prepublishOnly": "yarn build"
31
+ },
32
+ "repository": {
33
+ "type": "git",
34
+ "url": "https://github.com/smikula/stratifyjs.git"
35
+ },
36
+ "bugs": {
37
+ "url": "https://github.com/smikula/stratifyjs/issues"
38
+ },
39
+ "homepage": "https://github.com/smikula/stratifyjs#readme",
40
+ "keywords": [
41
+ "monorepo",
42
+ "architecture",
43
+ "layers",
44
+ "dependency",
45
+ "enforcement"
46
+ ],
47
+ "files": [
48
+ "lib/",
49
+ "bin/",
50
+ "README.md",
51
+ "LICENSE"
52
+ ],
53
+ "dependencies": {
54
+ "commander": "^14.0.3",
55
+ "glob": "^10.0.0",
56
+ "picocolors": "^1.1.0"
57
+ },
58
+ "devDependencies": {
59
+ "@types/jest": "^30.0.0",
60
+ "@types/node": "^25.2.3",
61
+ "jest": "^29.5.0",
62
+ "prettier": "^3.8.1",
63
+ "ts-jest": "^29.4.6",
64
+ "typescript": "^5.3.2"
65
+ },
66
+ "license": "MIT"
67
+ }