tdepend 0.2.0 → 0.3.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 (115) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +212 -116
  3. package/dist/api/analyze.d.ts +8 -68
  4. package/dist/api/analyze.js +33 -108
  5. package/dist/api/analyze.js.map +1 -1
  6. package/dist/api/explain.d.ts +22 -0
  7. package/dist/api/explain.js +38 -0
  8. package/dist/api/explain.js.map +1 -0
  9. package/dist/api/export.d.ts +4 -47
  10. package/dist/api/export.js +6 -45
  11. package/dist/api/export.js.map +1 -1
  12. package/dist/api/serialization.d.ts +6 -26
  13. package/dist/api/serialization.js +68 -58
  14. package/dist/api/serialization.js.map +1 -1
  15. package/dist/cli/index.js +11 -129
  16. package/dist/cli/index.js.map +1 -1
  17. package/dist/cli/run.d.ts +12 -0
  18. package/dist/cli/run.js +112 -0
  19. package/dist/cli/run.js.map +1 -0
  20. package/dist/config/loadConfig.d.ts +10 -10
  21. package/dist/config/loadConfig.js +73 -36
  22. package/dist/config/loadConfig.js.map +1 -1
  23. package/dist/config/schema.d.ts +59 -29
  24. package/dist/config/schema.js +45 -51
  25. package/dist/config/schema.js.map +1 -1
  26. package/dist/errors.d.ts +9 -0
  27. package/dist/errors.js +21 -0
  28. package/dist/errors.js.map +1 -0
  29. package/dist/files/collectFiles.d.ts +21 -0
  30. package/dist/files/collectFiles.js +189 -0
  31. package/dist/files/collectFiles.js.map +1 -0
  32. package/dist/fs.d.ts +16 -0
  33. package/dist/fs.js +50 -0
  34. package/dist/fs.js.map +1 -0
  35. package/dist/graph/buildFileGraph.d.ts +33 -0
  36. package/dist/graph/buildFileGraph.js +163 -0
  37. package/dist/graph/buildFileGraph.js.map +1 -0
  38. package/dist/graph/fileGraph.d.ts +20 -0
  39. package/dist/graph/fileGraph.js +75 -0
  40. package/dist/graph/fileGraph.js.map +1 -0
  41. package/dist/index.d.ts +10 -21
  42. package/dist/index.js +6 -29
  43. package/dist/index.js.map +1 -1
  44. package/dist/output/analyzeText.d.ts +7 -0
  45. package/dist/output/analyzeText.js +91 -0
  46. package/dist/output/analyzeText.js.map +1 -0
  47. package/dist/parser/extractSites.d.ts +3 -0
  48. package/dist/parser/extractSites.js +704 -0
  49. package/dist/parser/extractSites.js.map +1 -0
  50. package/dist/parser/loadsTarget.d.ts +10 -0
  51. package/dist/parser/loadsTarget.js +304 -0
  52. package/dist/parser/loadsTarget.js.map +1 -0
  53. package/dist/parser/types.d.ts +30 -0
  54. package/dist/{types/graph.js → parser/types.js} +1 -1
  55. package/dist/parser/types.js.map +1 -0
  56. package/dist/project/discoverProject.d.ts +2 -0
  57. package/dist/project/discoverProject.js +477 -0
  58. package/dist/project/discoverProject.js.map +1 -0
  59. package/dist/project/gitignore.d.ts +13 -0
  60. package/dist/project/gitignore.js +138 -0
  61. package/dist/project/gitignore.js.map +1 -0
  62. package/dist/project/types.d.ts +44 -0
  63. package/dist/{types/parser.js → project/types.js} +1 -1
  64. package/dist/project/types.js.map +1 -0
  65. package/dist/resolver/createResolver.d.ts +4 -0
  66. package/dist/resolver/createResolver.js +276 -0
  67. package/dist/resolver/createResolver.js.map +1 -0
  68. package/dist/resolver/types.d.ts +28 -0
  69. package/dist/resolver/types.js +3 -0
  70. package/dist/resolver/types.js.map +1 -0
  71. package/dist/resolver/workspaceHost.d.ts +12 -0
  72. package/dist/resolver/workspaceHost.js +253 -0
  73. package/dist/resolver/workspaceHost.js.map +1 -0
  74. package/dist/types/api.d.ts +71 -64
  75. package/package.json +24 -25
  76. package/dist/analysis/reporter.d.ts +0 -22
  77. package/dist/analysis/reporter.js +0 -116
  78. package/dist/analysis/reporter.js.map +0 -1
  79. package/dist/graph/cycleDetector.d.ts +0 -2
  80. package/dist/graph/cycleDetector.js +0 -56
  81. package/dist/graph/cycleDetector.js.map +0 -1
  82. package/dist/graph/dependencyGraph.d.ts +0 -10
  83. package/dist/graph/dependencyGraph.js +0 -41
  84. package/dist/graph/dependencyGraph.js.map +0 -1
  85. package/dist/metrics/abstractness.d.ts +0 -2
  86. package/dist/metrics/abstractness.js +0 -10
  87. package/dist/metrics/abstractness.js.map +0 -1
  88. package/dist/metrics/distance.d.ts +0 -1
  89. package/dist/metrics/distance.js +0 -7
  90. package/dist/metrics/distance.js.map +0 -1
  91. package/dist/metrics/index.d.ts +0 -4
  92. package/dist/metrics/index.js +0 -30
  93. package/dist/metrics/index.js.map +0 -1
  94. package/dist/metrics/instability.d.ts +0 -1
  95. package/dist/metrics/instability.js +0 -8
  96. package/dist/metrics/instability.js.map +0 -1
  97. package/dist/parser/fileScanner.d.ts +0 -8
  98. package/dist/parser/fileScanner.js +0 -22
  99. package/dist/parser/fileScanner.js.map +0 -1
  100. package/dist/parser/tsParser.d.ts +0 -18
  101. package/dist/parser/tsParser.js +0 -158
  102. package/dist/parser/tsParser.js.map +0 -1
  103. package/dist/types/graph.d.ts +0 -14
  104. package/dist/types/graph.js.map +0 -1
  105. package/dist/types/parser.d.ts +0 -26
  106. package/dist/types/parser.js.map +0 -1
  107. package/dist/utils/deepMerge.d.ts +0 -1
  108. package/dist/utils/deepMerge.js +0 -23
  109. package/dist/utils/deepMerge.js.map +0 -1
  110. package/dist/utils/log.d.ts +0 -2
  111. package/dist/utils/log.js +0 -9
  112. package/dist/utils/log.js.map +0 -1
  113. package/dist/utils/pathUtils.d.ts +0 -12
  114. package/dist/utils/pathUtils.js +0 -27
  115. package/dist/utils/pathUtils.js.map +0 -1
@@ -0,0 +1,112 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.runCli = runCli;
4
+ const node_fs_1 = require("node:fs");
5
+ const node_path_1 = require("node:path");
6
+ const commander_1 = require("commander");
7
+ const analyze_1 = require("../api/analyze");
8
+ const export_1 = require("../api/export");
9
+ const explain_1 = require("../api/explain");
10
+ const serialization_1 = require("../api/serialization");
11
+ const errors_1 = require("../errors");
12
+ const analyzeText_1 = require("../output/analyzeText");
13
+ /**
14
+ * Runs the CLI and resolves to its exit code. Only the commands that exist at
15
+ * this milestone are registered: `analyze` and `explain`.
16
+ */
17
+ async function runCli(argv, io) {
18
+ let exitCode = 0;
19
+ const program = buildProgram(io, (code) => {
20
+ exitCode = code;
21
+ });
22
+ try {
23
+ await program.parseAsync(argv, { from: 'user' });
24
+ return exitCode;
25
+ }
26
+ catch (error) {
27
+ return handleError(error, io);
28
+ }
29
+ }
30
+ function handleError(error, io) {
31
+ if (error instanceof errors_1.ConfigError || error instanceof errors_1.ParseError) {
32
+ writeLine(io.stderr, error.message);
33
+ return 2;
34
+ }
35
+ if (error instanceof commander_1.CommanderError) {
36
+ return error.exitCode === 0 ? 0 : 2;
37
+ }
38
+ writeLine(io.stderr, error instanceof Error ? error.message : String(error));
39
+ return 2;
40
+ }
41
+ function packageVersion() {
42
+ const manifest = (0, node_fs_1.readFileSync)((0, node_path_1.join)(__dirname, '..', '..', 'package.json'), 'utf-8');
43
+ return JSON.parse(manifest).version;
44
+ }
45
+ function buildProgram(io, setExitCode) {
46
+ const program = new commander_1.Command();
47
+ program
48
+ .name('tdepend')
49
+ .description('Executable architecture contracts for TypeScript')
50
+ .version(packageVersion())
51
+ .exitOverride()
52
+ .showHelpAfterError()
53
+ .configureOutput({
54
+ writeOut: (s) => io.stdout(s),
55
+ writeErr: (s) => io.stderr(s),
56
+ });
57
+ const rootFor = (options) => options.root === undefined ? io.cwd : (0, node_path_1.resolve)(io.cwd, options.root);
58
+ const configFor = (options) => options.config === undefined ? undefined : (0, node_path_1.resolve)(io.cwd, options.config);
59
+ program
60
+ .command('analyze')
61
+ .description('Analyze a TypeScript project and report its import graph')
62
+ .option('-r, --root <dir>', 'analysis root, defaults to the working directory')
63
+ .option('-c, --config <path>', 'path to the tdepend config file')
64
+ .addOption(new commander_1.Option('-f, --format <format>', 'output format').choices(['text', 'json']).default('text'))
65
+ .option('-e, --export <path>', 'write the full result to a JSON file')
66
+ .option('--strict-resolution', 'exit 2 when any import is unresolved')
67
+ .action(async (options) => {
68
+ const result = await (0, analyze_1.analyze)({ root: rootFor(options), config: configFor(options) });
69
+ if (options.export !== undefined) {
70
+ await (0, export_1.exportToFile)(result, (0, node_path_1.resolve)(io.cwd, options.export));
71
+ }
72
+ if (options.format === 'json') {
73
+ io.stdout(`${JSON.stringify((0, serialization_1.toSerializable)(result), null, 2)}\n`);
74
+ }
75
+ else {
76
+ io.stdout((0, analyzeText_1.formatAnalyzeText)(result));
77
+ }
78
+ if (options.strictResolution === true && result.report.unresolved.length > 0) {
79
+ setExitCode(2);
80
+ }
81
+ });
82
+ program
83
+ .command('explain')
84
+ .description('Show every import in one file with its kind, load verdict and resolution')
85
+ .argument('<file>', 'file to explain, relative to the analysis root')
86
+ .option('-r, --root <dir>', 'analysis root, defaults to the working directory')
87
+ .option('-c, --config <path>', 'path to the tdepend config file')
88
+ .action(async (file, options) => {
89
+ const rows = await (0, explain_1.explainFile)({ root: rootFor(options), config: configFor(options), file });
90
+ io.stdout(formatExplain(rows));
91
+ });
92
+ return program;
93
+ }
94
+ function formatExplain(rows) {
95
+ if (rows.length === 0)
96
+ return '';
97
+ return `${rows.map(formatExplainRow).join('\n')}\n`;
98
+ }
99
+ function formatExplainRow(row) {
100
+ const verdict = `${row.loadsTarget ? 'loads' : 'erased'} (${row.loadsTargetBy ?? '-'}): ${row.loadReason}`;
101
+ const target = formatTarget(row.target);
102
+ return `${row.line}:${row.column} ${row.kind} ${row.class} '${row.specifier}' -> ${target} ${verdict}`;
103
+ }
104
+ function formatTarget(target) {
105
+ if (target === null)
106
+ return '-';
107
+ return 'file' in target ? target.file : target.module;
108
+ }
109
+ function writeLine(write, message) {
110
+ write(message.endsWith('\n') ? message : `${message}\n`);
111
+ }
112
+ //# sourceMappingURL=run.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/cli/run.ts"],"names":[],"mappings":"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"}
@@ -1,10 +1,10 @@
1
- import { type TDependConfig } from './schema';
2
- /**
3
- * Load and validate TDepend configuration
4
- *
5
- * @param configPath - Optional path to config file. If not provided, searches for
6
- * tdepend.config.json in current directory
7
- * @returns Validated and merged configuration
8
- * @throws Error if config file is not found, invalid JSON, or fails validation
9
- */
10
- export declare function loadConfig(configPath?: string): TDependConfig;
1
+ import { type UserConfig } from './schema';
2
+ export interface LoadConfigOptions {
3
+ cwd: string;
4
+ configPath?: string;
5
+ }
6
+ export interface LoadConfigResult {
7
+ config: UserConfig;
8
+ configFile: string | null;
9
+ }
10
+ export declare function loadConfig(opts: LoadConfigOptions): LoadConfigResult;
@@ -3,54 +3,91 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.loadConfig = loadConfig;
4
4
  const node_fs_1 = require("node:fs");
5
5
  const node_path_1 = require("node:path");
6
+ const errors_1 = require("../errors");
6
7
  const schema_1 = require("./schema");
7
- const deepMerge_1 = require("../utils/deepMerge");
8
- function resolveConfigPath(configPath) {
9
- if (configPath) {
10
- const resolvedPath = (0, node_path_1.resolve)(configPath);
11
- if (!(0, node_fs_1.existsSync)(resolvedPath)) {
12
- throw new Error(`Config file not found: ${resolvedPath}`);
13
- }
14
- return resolvedPath;
8
+ const CONFIG_FILENAME = 'tdepend.config.json';
9
+ function loadConfig(opts) {
10
+ const configFile = findConfigFile(opts);
11
+ if (configFile === null) {
12
+ return { config: schema_1.configSchema.parse({}), configFile: null };
15
13
  }
16
- const defaultPath = (0, node_path_1.resolve)('tdepend.config.json');
17
- if ((0, node_fs_1.existsSync)(defaultPath)) {
18
- return defaultPath;
14
+ const raw = readRawConfig(configFile);
15
+ rejectLegacyConfig(raw);
16
+ rejectUnavailableKeys(raw);
17
+ const parsed = schema_1.configSchema.safeParse(raw);
18
+ if (!parsed.success) {
19
+ throw new errors_1.ConfigError(formatZodError(parsed.error));
19
20
  }
20
- return null;
21
+ return { config: parsed.data, configFile };
21
22
  }
22
- function readConfigFile(filePath) {
23
- try {
24
- const fileContent = (0, node_fs_1.readFileSync)(filePath, 'utf-8');
25
- return JSON.parse(fileContent);
23
+ const LEGACY_KEYS = ['rootDir', 'ci', 'analysis'];
24
+ const UNAVAILABLE_KEYS = ['rules', 'components', 'baseline'];
25
+ function rejectLegacyConfig(raw) {
26
+ if (!isRecord(raw))
27
+ return;
28
+ if (LEGACY_KEYS.some((key) => key in raw)) {
29
+ throw new errors_1.ConfigError("This looks like a tdepend 0.2 config. See 'Migrating from 0.2' in the README.");
26
30
  }
27
- catch (error) {
28
- if (error instanceof SyntaxError) {
29
- throw new Error(`Invalid JSON in config file: ${filePath}`);
31
+ }
32
+ function rejectUnavailableKeys(raw) {
33
+ if (!isRecord(raw))
34
+ return;
35
+ const present = UNAVAILABLE_KEYS.filter((key) => key in raw);
36
+ const metrics = raw.metrics;
37
+ if (isRecord(metrics) && 'thresholds' in metrics)
38
+ present.push('metrics.thresholds');
39
+ if (present.length > 0) {
40
+ throw new errors_1.ConfigError(`Config key(s) not available in this version: ${present.join(', ')}. Remove them until the release that adds them.`);
41
+ }
42
+ }
43
+ function isRecord(value) {
44
+ return value !== null && typeof value === 'object' && !Array.isArray(value);
45
+ }
46
+ function findConfigFile(opts) {
47
+ if (opts.configPath !== undefined) {
48
+ const path = (0, node_path_1.isAbsolute)(opts.configPath) ? opts.configPath : (0, node_path_1.resolve)(opts.cwd, opts.configPath);
49
+ if (!(0, node_fs_1.existsSync)(path)) {
50
+ throw new errors_1.ConfigError(`Config file not found: ${opts.configPath}`);
30
51
  }
31
- throw error;
52
+ return path;
32
53
  }
54
+ const path = (0, node_path_1.join)(opts.cwd, CONFIG_FILENAME);
55
+ return (0, node_fs_1.existsSync)(path) ? path : null;
33
56
  }
34
- function validateConfig(config) {
57
+ function readRawConfig(file) {
58
+ let text;
59
+ try {
60
+ text = (0, node_fs_1.readFileSync)(file, 'utf-8');
61
+ }
62
+ catch (error) {
63
+ throw new errors_1.ConfigError(`Cannot read config file ${file}: ${error instanceof Error ? error.message : String(error)}`);
64
+ }
35
65
  try {
36
- return schema_1.configSchema.parse(config);
66
+ return JSON.parse(text);
37
67
  }
38
68
  catch (error) {
39
- throw new Error(`Config validation failed: ${error}`);
69
+ throw new errors_1.ParseError(`Invalid JSON in ${file}: ${error instanceof Error ? error.message : String(error)}`, file);
40
70
  }
41
71
  }
42
- /**
43
- * Load and validate TDepend configuration
44
- *
45
- * @param configPath - Optional path to config file. If not provided, searches for
46
- * tdepend.config.json in current directory
47
- * @returns Validated and merged configuration
48
- * @throws Error if config file is not found, invalid JSON, or fails validation
49
- */
50
- function loadConfig(configPath) {
51
- const resolvedPath = resolveConfigPath(configPath);
52
- const loadedConfig = resolvedPath ? readConfigFile(resolvedPath) : {};
53
- const mergedConfig = (0, deepMerge_1.deepMerge)(schema_1.defaultConfig, loadedConfig);
54
- return validateConfig(mergedConfig);
72
+ function formatZodError(error) {
73
+ const unknownKeys = [];
74
+ const otherIssues = [];
75
+ for (const issue of error.issues) {
76
+ if (issue.code === 'unrecognized_keys') {
77
+ unknownKeys.push(...issue.keys);
78
+ }
79
+ else {
80
+ const at = issue.path.length > 0 ? issue.path.join('.') : '(root)';
81
+ otherIssues.push(`${at}: ${issue.message}`);
82
+ }
83
+ }
84
+ const parts = [];
85
+ if (unknownKeys.length > 0) {
86
+ parts.push(`Unknown config key(s): ${unknownKeys.join(', ')}`);
87
+ }
88
+ if (otherIssues.length > 0) {
89
+ parts.push(otherIssues.join('; '));
90
+ }
91
+ return `Invalid config. ${parts.join('. ')}`;
55
92
  }
56
93
  //# sourceMappingURL=loadConfig.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"loadConfig.js","sourceRoot":"","sources":["../../src/config/loadConfig.ts"],"names":[],"mappings":";;AAmDA,gCAKC;AAxDD,qCAAmD;AACnD,yCAAoC;AAEpC,qCAA2E;AAC3E,kDAA+C;AAE/C,SAAS,iBAAiB,CAAC,UAAmB;IAC5C,IAAI,UAAU,EAAE,CAAC;QACf,MAAM,YAAY,GAAG,IAAA,mBAAO,EAAC,UAAU,CAAC,CAAC;QACzC,IAAI,CAAC,IAAA,oBAAU,EAAC,YAAY,CAAC,EAAE,CAAC;YAC9B,MAAM,IAAI,KAAK,CAAC,0BAA0B,YAAY,EAAE,CAAC,CAAC;QAC5D,CAAC;QACD,OAAO,YAAY,CAAC;IACtB,CAAC;IAED,MAAM,WAAW,GAAG,IAAA,mBAAO,EAAC,qBAAqB,CAAC,CAAC;IACnD,IAAI,IAAA,oBAAU,EAAC,WAAW,CAAC,EAAE,CAAC;QAC5B,OAAO,WAAW,CAAC;IACrB,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,cAAc,CAAC,QAAgB;IACtC,IAAI,CAAC;QACH,MAAM,WAAW,GAAG,IAAA,sBAAY,EAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QACpD,OAAO,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;IACjC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,WAAW,EAAE,CAAC;YACjC,MAAM,IAAI,KAAK,CAAC,gCAAgC,QAAQ,EAAE,CAAC,CAAC;QAC9D,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAS,cAAc,CAAC,MAA8B;IACpD,IAAI,CAAC;QACH,OAAO,qBAAY,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACpC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,6BAA6B,KAAK,EAAE,CAAC,CAAC;IACxD,CAAC;AACH,CAAC;AAED;;;;;;;GAOG;AACH,SAAgB,UAAU,CAAC,UAAmB;IAC5C,MAAM,YAAY,GAAG,iBAAiB,CAAC,UAAU,CAAC,CAAC;IACnD,MAAM,YAAY,GAAG,YAAY,CAAC,CAAC,CAAC,cAAc,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACtE,MAAM,YAAY,GAAG,IAAA,qBAAS,EAAC,sBAAa,EAAE,YAAY,CAAC,CAAC;IAC5D,OAAO,cAAc,CAAC,YAAY,CAAC,CAAC;AACtC,CAAC"}
1
+ {"version":3,"file":"loadConfig.js","sourceRoot":"","sources":["../../src/config/loadConfig.ts"],"names":[],"mappings":"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"}
@@ -1,35 +1,65 @@
1
1
  import { z } from 'zod';
2
+ export declare const componentsSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
3
+ type: z.ZodLiteral<"directory">;
4
+ patterns: z.ZodArray<z.ZodString>;
5
+ coverage: z.ZodOptional<z.ZodObject<{
6
+ requireAll: z.ZodDefault<z.ZodBoolean>;
7
+ allowUnmatched: z.ZodDefault<z.ZodArray<z.ZodString>>;
8
+ }, z.core.$strict>>;
9
+ }, z.core.$strict>, z.ZodObject<{
10
+ type: z.ZodLiteral<"nest-module">;
11
+ coverage: z.ZodOptional<z.ZodObject<{
12
+ requireAll: z.ZodDefault<z.ZodBoolean>;
13
+ allowUnmatched: z.ZodDefault<z.ZodArray<z.ZodString>>;
14
+ }, z.core.$strict>>;
15
+ }, z.core.$strict>, z.ZodObject<{
16
+ type: z.ZodLiteral<"file">;
17
+ }, z.core.$strict>], "type">;
2
18
  export declare const configSchema: z.ZodObject<{
3
- rootDir: z.ZodDefault<z.ZodString>;
19
+ root: z.ZodDefault<z.ZodString>;
20
+ presets: z.ZodDefault<z.ZodArray<z.ZodString>>;
4
21
  include: z.ZodDefault<z.ZodArray<z.ZodString>>;
5
22
  exclude: z.ZodDefault<z.ZodArray<z.ZodString>>;
23
+ typeOnly: z.ZodDefault<z.ZodEnum<{
24
+ usage: "usage";
25
+ syntax: "syntax";
26
+ }>>;
27
+ compilers: z.ZodDefault<z.ZodArray<z.ZodEnum<{
28
+ tsc: "tsc";
29
+ esbuild: "esbuild";
30
+ swc: "swc";
31
+ }>>>;
32
+ resolve: z.ZodDefault<z.ZodObject<{
33
+ aliases: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodString>>;
34
+ virtual: z.ZodDefault<z.ZodArray<z.ZodString>>;
35
+ ignoreUnresolved: z.ZodDefault<z.ZodArray<z.ZodString>>;
36
+ }, z.core.$strict>>;
6
37
  metrics: z.ZodDefault<z.ZodObject<{
7
- enabled: z.ZodDefault<z.ZodArray<z.ZodEnum<{
8
- coupling: "coupling";
9
- abstractness: "abstractness";
10
- distance: "distance";
11
- cycles: "cycles";
12
- }>>>;
13
- thresholds: z.ZodDefault<z.ZodObject<{
14
- distance: z.ZodDefault<z.ZodNumber>;
15
- }, z.core.$strip>>;
16
- }, z.core.$strip>>;
17
- analysis: z.ZodDefault<z.ZodObject<{
18
- target: z.ZodDefault<z.ZodNullable<z.ZodEnum<{
19
- module: "module";
20
- class: "class";
21
- namespace: "namespace";
22
- }>>>;
23
- value: z.ZodDefault<z.ZodNullable<z.ZodString>>;
24
- }, z.core.$strip>>;
25
- ci: z.ZodDefault<z.ZodObject<{
26
- failOnThreshold: z.ZodDefault<z.ZodBoolean>;
27
- failOnCycle: z.ZodDefault<z.ZodBoolean>;
28
- outputFormat: z.ZodDefault<z.ZodEnum<{
29
- console: "console";
30
- json: "json";
38
+ abstractness: z.ZodDefault<z.ZodEnum<{
39
+ implemented: "implemented";
40
+ jdepend: "jdepend";
31
41
  }>>;
32
- }, z.core.$strip>>;
33
- }, z.core.$strip>;
34
- export type TDependConfig = z.infer<typeof configSchema>;
35
- export declare const defaultConfig: TDependConfig;
42
+ thresholds: z.ZodDefault<z.ZodObject<{
43
+ distance: z.ZodDefault<z.ZodNullable<z.ZodNumber>>;
44
+ }, z.core.$strict>>;
45
+ }, z.core.$strict>>;
46
+ rules: z.ZodDefault<z.ZodArray<z.ZodUnknown>>;
47
+ baseline: z.ZodDefault<z.ZodNullable<z.ZodString>>;
48
+ components: z.ZodOptional<z.ZodDiscriminatedUnion<[z.ZodObject<{
49
+ type: z.ZodLiteral<"directory">;
50
+ patterns: z.ZodArray<z.ZodString>;
51
+ coverage: z.ZodOptional<z.ZodObject<{
52
+ requireAll: z.ZodDefault<z.ZodBoolean>;
53
+ allowUnmatched: z.ZodDefault<z.ZodArray<z.ZodString>>;
54
+ }, z.core.$strict>>;
55
+ }, z.core.$strict>, z.ZodObject<{
56
+ type: z.ZodLiteral<"nest-module">;
57
+ coverage: z.ZodOptional<z.ZodObject<{
58
+ requireAll: z.ZodDefault<z.ZodBoolean>;
59
+ allowUnmatched: z.ZodDefault<z.ZodArray<z.ZodString>>;
60
+ }, z.core.$strict>>;
61
+ }, z.core.$strict>, z.ZodObject<{
62
+ type: z.ZodLiteral<"file">;
63
+ }, z.core.$strict>], "type">>;
64
+ }, z.core.$strict>;
65
+ export type UserConfig = z.infer<typeof configSchema>;
@@ -1,58 +1,52 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.defaultConfig = exports.configSchema = void 0;
3
+ exports.configSchema = exports.componentsSchema = void 0;
4
4
  const zod_1 = require("zod");
5
- exports.configSchema = zod_1.z.object({
6
- rootDir: zod_1.z.string().default('src'),
7
- include: zod_1.z.array(zod_1.z.string()).default(['src/**/*.ts', 'src/**/*.tsx']),
8
- exclude: zod_1.z.array(zod_1.z.string()).default(['**/*.test.ts', '**/*.spec.ts', 'dist']),
9
- metrics: zod_1.z
10
- .object({
11
- enabled: zod_1.z
12
- .array(zod_1.z.enum(['coupling', 'abstractness', 'distance', 'cycles']))
13
- .default(['coupling', 'abstractness', 'distance', 'cycles']),
14
- thresholds: zod_1.z
15
- .object({
16
- distance: zod_1.z.number().min(0).max(1).default(0.6),
17
- })
18
- .default({ distance: 0.6 }),
19
- })
20
- .default({
21
- enabled: ['coupling', 'abstractness', 'distance', 'cycles'],
22
- thresholds: { distance: 0.6 },
5
+ const coverageSchema = zod_1.z.strictObject({
6
+ requireAll: zod_1.z.boolean().default(false),
7
+ allowUnmatched: zod_1.z.array(zod_1.z.string()).default([]),
8
+ });
9
+ exports.componentsSchema = zod_1.z.discriminatedUnion('type', [
10
+ zod_1.z.strictObject({
11
+ type: zod_1.z.literal('directory'),
12
+ patterns: zod_1.z.array(zod_1.z.string()),
13
+ coverage: coverageSchema.optional(),
23
14
  }),
24
- analysis: zod_1.z
25
- .object({
26
- target: zod_1.z.enum(['module', 'class', 'namespace']).nullable().default(null),
27
- value: zod_1.z.string().nullable().default(null),
28
- })
29
- .default({ target: null, value: null }),
30
- ci: zod_1.z
31
- .object({
32
- failOnThreshold: zod_1.z.boolean().default(true),
33
- failOnCycle: zod_1.z.boolean().default(false),
34
- outputFormat: zod_1.z.enum(['console', 'json']).default('console'),
15
+ zod_1.z.strictObject({
16
+ type: zod_1.z.literal('nest-module'),
17
+ coverage: coverageSchema.optional(),
18
+ }),
19
+ zod_1.z.strictObject({
20
+ type: zod_1.z.literal('file'),
21
+ }),
22
+ ]);
23
+ const resolveSchema = zod_1.z.strictObject({
24
+ aliases: zod_1.z.record(zod_1.z.string(), zod_1.z.string()).default({}),
25
+ virtual: zod_1.z.array(zod_1.z.string()).default([]),
26
+ ignoreUnresolved: zod_1.z.array(zod_1.z.string()).default([]),
27
+ });
28
+ const metricsSchema = zod_1.z.strictObject({
29
+ abstractness: zod_1.z.enum(['implemented', 'jdepend']).default('implemented'),
30
+ thresholds: zod_1.z
31
+ .strictObject({
32
+ distance: zod_1.z.number().min(0).max(1).nullable().default(null),
35
33
  })
36
- .default({ failOnThreshold: true, failOnCycle: false, outputFormat: 'console' }),
34
+ .default({ distance: null }),
35
+ });
36
+ exports.configSchema = zod_1.z.strictObject({
37
+ root: zod_1.z.string().default('.'),
38
+ presets: zod_1.z.array(zod_1.z.string()).default(['auto']),
39
+ include: zod_1.z.array(zod_1.z.string()).default([]),
40
+ exclude: zod_1.z.array(zod_1.z.string()).default([]),
41
+ typeOnly: zod_1.z.enum(['usage', 'syntax']).default('usage'),
42
+ compilers: zod_1.z
43
+ .array(zod_1.z.enum(['tsc', 'esbuild', 'swc']))
44
+ .min(1)
45
+ .default(['tsc', 'esbuild', 'swc']),
46
+ resolve: resolveSchema.default({ aliases: {}, virtual: [], ignoreUnresolved: [] }),
47
+ metrics: metricsSchema.default({ abstractness: 'implemented', thresholds: { distance: null } }),
48
+ rules: zod_1.z.array(zod_1.z.unknown()).default([]),
49
+ baseline: zod_1.z.string().nullable().default(null),
50
+ components: exports.componentsSchema.optional(),
37
51
  });
38
- exports.defaultConfig = {
39
- rootDir: 'src',
40
- include: ['src/**/*.ts', 'src/**/*.tsx'],
41
- exclude: ['**/*.test.ts', '**/*.spec.ts', 'dist'],
42
- metrics: {
43
- enabled: ['coupling', 'abstractness', 'distance', 'cycles'],
44
- thresholds: {
45
- distance: 0.6,
46
- },
47
- },
48
- analysis: {
49
- target: null,
50
- value: null,
51
- },
52
- ci: {
53
- failOnThreshold: true,
54
- failOnCycle: false,
55
- outputFormat: 'console',
56
- },
57
- };
58
52
  //# sourceMappingURL=schema.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/config/schema.ts"],"names":[],"mappings":";;;AAAA,6BAAwB;AAEX,QAAA,YAAY,GAAG,OAAC,CAAC,MAAM,CAAC;IACnC,OAAO,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;IAClC,OAAO,EAAE,OAAC,CAAC,KAAK,CAAC,OAAC,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,aAAa,EAAE,cAAc,CAAC,CAAC;IACrE,OAAO,EAAE,OAAC,CAAC,KAAK,CAAC,OAAC,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,cAAc,EAAE,cAAc,EAAE,MAAM,CAAC,CAAC;IAC9E,OAAO,EAAE,OAAC;SACP,MAAM,CAAC;QACN,OAAO,EAAE,OAAC;aACP,KAAK,CAAC,OAAC,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,cAAc,EAAE,UAAU,EAAE,QAAQ,CAAC,CAAC,CAAC;aACjE,OAAO,CAAC,CAAC,UAAU,EAAE,cAAc,EAAE,UAAU,EAAE,QAAQ,CAAC,CAAC;QAC9D,UAAU,EAAE,OAAC;aACV,MAAM,CAAC;YACN,QAAQ,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC;SAChD,CAAC;aACD,OAAO,CAAC,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC;KAC9B,CAAC;SACD,OAAO,CAAC;QACP,OAAO,EAAE,CAAC,UAAU,EAAE,cAAc,EAAE,UAAU,EAAE,QAAQ,CAAC;QAC3D,UAAU,EAAE,EAAE,QAAQ,EAAE,GAAG,EAAE;KAC9B,CAAC;IACJ,QAAQ,EAAE,OAAC;SACR,MAAM,CAAC;QACN,MAAM,EAAE,OAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;QACzE,KAAK,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;KAC3C,CAAC;SACD,OAAO,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IACzC,EAAE,EAAE,OAAC;SACF,MAAM,CAAC;QACN,eAAe,EAAE,OAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;QAC1C,WAAW,EAAE,OAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;QACvC,YAAY,EAAE,OAAC,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC;KAC7D,CAAC;SACD,OAAO,CAAC,EAAE,eAAe,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,CAAC;CACnF,CAAC,CAAC;AAIU,QAAA,aAAa,GAAkB;IAC1C,OAAO,EAAE,KAAK;IACd,OAAO,EAAE,CAAC,aAAa,EAAE,cAAc,CAAC;IACxC,OAAO,EAAE,CAAC,cAAc,EAAE,cAAc,EAAE,MAAM,CAAC;IACjD,OAAO,EAAE;QACP,OAAO,EAAE,CAAC,UAAU,EAAE,cAAc,EAAE,UAAU,EAAE,QAAQ,CAAC;QAC3D,UAAU,EAAE;YACV,QAAQ,EAAE,GAAG;SACd;KACF;IACD,QAAQ,EAAE;QACR,MAAM,EAAE,IAAI;QACZ,KAAK,EAAE,IAAI;KACZ;IACD,EAAE,EAAE;QACF,eAAe,EAAE,IAAI;QACrB,WAAW,EAAE,KAAK;QAClB,YAAY,EAAE,SAAS;KACxB;CACF,CAAC"}
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/config/schema.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ export declare class ConfigError extends Error {
2
+ readonly exitCode: 2;
3
+ constructor(message: string);
4
+ }
5
+ export declare class ParseError extends Error {
6
+ readonly exitCode: 2;
7
+ readonly file: string;
8
+ constructor(message: string, file: string);
9
+ }
package/dist/errors.js ADDED
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ParseError = exports.ConfigError = void 0;
4
+ class ConfigError extends Error {
5
+ constructor(message) {
6
+ super(message);
7
+ this.exitCode = 2;
8
+ this.name = 'ConfigError';
9
+ }
10
+ }
11
+ exports.ConfigError = ConfigError;
12
+ class ParseError extends Error {
13
+ constructor(message, file) {
14
+ super(message);
15
+ this.exitCode = 2;
16
+ this.name = 'ParseError';
17
+ this.file = file;
18
+ }
19
+ }
20
+ exports.ParseError = ParseError;
21
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":";;;AAAA,MAAa,WAAY,SAAQ,KAAK;IAGpC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QAHR,aAAQ,GAAG,CAAU,CAAC;QAI7B,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC;IAC5B,CAAC;CACF;AAPD,kCAOC;AAED,MAAa,UAAW,SAAQ,KAAK;IAInC,YAAY,OAAe,EAAE,IAAY;QACvC,KAAK,CAAC,OAAO,CAAC,CAAC;QAJR,aAAQ,GAAG,CAAU,CAAC;QAK7B,IAAI,CAAC,IAAI,GAAG,YAAY,CAAC;QACzB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;CACF;AATD,gCASC"}
@@ -0,0 +1,21 @@
1
+ import { type FileSystemLike } from '../fs';
2
+ import type { ProjectContext } from '../project/types';
3
+ export declare const DEFAULT_SKIPS: string[];
4
+ export type SkipReason = 'excluded' | 'gitignored' | 'declaration' | 'outside-root';
5
+ export interface SkippedEntry {
6
+ file: string;
7
+ reason: SkipReason;
8
+ }
9
+ export interface CollectResult {
10
+ files: string[];
11
+ uncovered: string[];
12
+ skipped: SkippedEntry[];
13
+ }
14
+ export interface CollectOptions {
15
+ include: string[];
16
+ exclude: string[];
17
+ presetSkips: string[];
18
+ fs?: FileSystemLike;
19
+ }
20
+ export declare function collectFiles(ctx: ProjectContext, opts: CollectOptions): CollectResult;
21
+ export declare function createExcludeMatcher(presetSkips: string[], exclude: string[]): (rel: string) => boolean;