intentpatch 0.1.1 → 0.3.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 (116) hide show
  1. package/README.ko.md +74 -22
  2. package/README.md +62 -17
  3. package/dist/application/ports/module-alias-resolver.d.ts +11 -0
  4. package/dist/application/ports/module-alias-resolver.d.ts.map +1 -0
  5. package/dist/application/ports/module-alias-resolver.js +2 -0
  6. package/dist/application/ports/module-alias-resolver.js.map +1 -0
  7. package/dist/application/ports/module-reference-extractor.d.ts +1 -0
  8. package/dist/application/ports/module-reference-extractor.d.ts.map +1 -1
  9. package/dist/application/ports/package-lock-parser.d.ts +20 -0
  10. package/dist/application/ports/package-lock-parser.d.ts.map +1 -0
  11. package/dist/application/ports/package-lock-parser.js +2 -0
  12. package/dist/application/ports/package-lock-parser.js.map +1 -0
  13. package/dist/application/ports/parse-failure.d.ts +7 -0
  14. package/dist/application/ports/parse-failure.d.ts.map +1 -0
  15. package/dist/application/ports/parse-failure.js +5 -0
  16. package/dist/application/ports/parse-failure.js.map +1 -0
  17. package/dist/application/ports/pnpm-lock-parser.d.ts +20 -0
  18. package/dist/application/ports/pnpm-lock-parser.d.ts.map +1 -0
  19. package/dist/application/ports/pnpm-lock-parser.js +2 -0
  20. package/dist/application/ports/pnpm-lock-parser.js.map +1 -0
  21. package/dist/application/ports/pnpm-workspace-parser.d.ts +14 -0
  22. package/dist/application/ports/pnpm-workspace-parser.d.ts.map +1 -0
  23. package/dist/application/ports/pnpm-workspace-parser.js +2 -0
  24. package/dist/application/ports/pnpm-workspace-parser.js.map +1 -0
  25. package/dist/application/rules/added-dependency-usage-rule.d.ts +16 -0
  26. package/dist/application/rules/added-dependency-usage-rule.d.ts.map +1 -0
  27. package/dist/application/rules/added-dependency-usage-rule.js +98 -0
  28. package/dist/application/rules/added-dependency-usage-rule.js.map +1 -0
  29. package/dist/application/rules/npm-lockfile-rule.d.ts +12 -0
  30. package/dist/application/rules/npm-lockfile-rule.d.ts.map +1 -0
  31. package/dist/application/rules/npm-lockfile-rule.js +109 -0
  32. package/dist/application/rules/npm-lockfile-rule.js.map +1 -0
  33. package/dist/application/rules/npm-workspace-dependency-rule.d.ts +10 -0
  34. package/dist/application/rules/npm-workspace-dependency-rule.d.ts.map +1 -0
  35. package/dist/application/rules/npm-workspace-dependency-rule.js +107 -0
  36. package/dist/application/rules/npm-workspace-dependency-rule.js.map +1 -0
  37. package/dist/application/rules/package-dependency-rule.d.ts +4 -3
  38. package/dist/application/rules/package-dependency-rule.d.ts.map +1 -1
  39. package/dist/application/rules/package-dependency-rule.js +34 -31
  40. package/dist/application/rules/package-dependency-rule.js.map +1 -1
  41. package/dist/application/rules/pnpm-lockfile-rule.d.ts +12 -0
  42. package/dist/application/rules/pnpm-lockfile-rule.d.ts.map +1 -0
  43. package/dist/application/rules/pnpm-lockfile-rule.js +119 -0
  44. package/dist/application/rules/pnpm-lockfile-rule.js.map +1 -0
  45. package/dist/application/rules/pnpm-workspace-dependency-rule.d.ts +12 -0
  46. package/dist/application/rules/pnpm-workspace-dependency-rule.d.ts.map +1 -0
  47. package/dist/application/rules/pnpm-workspace-dependency-rule.js +59 -0
  48. package/dist/application/rules/pnpm-workspace-dependency-rule.js.map +1 -0
  49. package/dist/application/services/analyze-import-impact.d.ts +3 -1
  50. package/dist/application/services/analyze-import-impact.d.ts.map +1 -1
  51. package/dist/application/services/analyze-import-impact.js +12 -7
  52. package/dist/application/services/analyze-import-impact.js.map +1 -1
  53. package/dist/application/services/workspace-manifest-analysis.d.ts +12 -0
  54. package/dist/application/services/workspace-manifest-analysis.d.ts.map +1 -0
  55. package/dist/application/services/workspace-manifest-analysis.js +60 -0
  56. package/dist/application/services/workspace-manifest-analysis.js.map +1 -0
  57. package/dist/domain/value-guards.d.ts +3 -0
  58. package/dist/domain/value-guards.d.ts.map +1 -0
  59. package/dist/domain/value-guards.js +5 -0
  60. package/dist/domain/value-guards.js.map +1 -0
  61. package/dist/infrastructure/config/json-change-contract-loader.d.ts.map +1 -1
  62. package/dist/infrastructure/config/json-change-contract-loader.js +1 -3
  63. package/dist/infrastructure/config/json-change-contract-loader.js.map +1 -1
  64. package/dist/infrastructure/config/text-intent-loader.d.ts +5 -0
  65. package/dist/infrastructure/config/text-intent-loader.d.ts.map +1 -0
  66. package/dist/infrastructure/config/text-intent-loader.js +30 -0
  67. package/dist/infrastructure/config/text-intent-loader.js.map +1 -0
  68. package/dist/infrastructure/git/git-file-snapshot-source.d.ts.map +1 -1
  69. package/dist/infrastructure/git/git-file-snapshot-source.js +6 -2
  70. package/dist/infrastructure/git/git-file-snapshot-source.js.map +1 -1
  71. package/dist/infrastructure/npm/npm-package-lock-parser.d.ts +6 -0
  72. package/dist/infrastructure/npm/npm-package-lock-parser.d.ts.map +1 -0
  73. package/dist/infrastructure/npm/npm-package-lock-parser.js +89 -0
  74. package/dist/infrastructure/npm/npm-package-lock-parser.js.map +1 -0
  75. package/dist/infrastructure/pnpm/pnpm-lock-parser.d.ts +6 -0
  76. package/dist/infrastructure/pnpm/pnpm-lock-parser.d.ts.map +1 -0
  77. package/dist/infrastructure/pnpm/pnpm-lock-parser.js +122 -0
  78. package/dist/infrastructure/pnpm/pnpm-lock-parser.js.map +1 -0
  79. package/dist/infrastructure/pnpm/pnpm-workspace-parser.d.ts +6 -0
  80. package/dist/infrastructure/pnpm/pnpm-workspace-parser.d.ts.map +1 -0
  81. package/dist/infrastructure/pnpm/pnpm-workspace-parser.js +62 -0
  82. package/dist/infrastructure/pnpm/pnpm-workspace-parser.js.map +1 -0
  83. package/dist/infrastructure/typescript/package-module-reference-extractor.d.ts +7 -0
  84. package/dist/infrastructure/typescript/package-module-reference-extractor.d.ts.map +1 -0
  85. package/dist/infrastructure/typescript/package-module-reference-extractor.js +68 -0
  86. package/dist/infrastructure/typescript/package-module-reference-extractor.js.map +1 -0
  87. package/dist/infrastructure/typescript/typescript-config-loader.d.ts +17 -0
  88. package/dist/infrastructure/typescript/typescript-config-loader.d.ts.map +1 -0
  89. package/dist/infrastructure/typescript/typescript-config-loader.js +97 -0
  90. package/dist/infrastructure/typescript/typescript-config-loader.js.map +1 -0
  91. package/dist/infrastructure/typescript/typescript-module-alias-resolver.d.ts +10 -0
  92. package/dist/infrastructure/typescript/typescript-module-alias-resolver.d.ts.map +1 -0
  93. package/dist/infrastructure/typescript/typescript-module-alias-resolver.js +78 -0
  94. package/dist/infrastructure/typescript/typescript-module-alias-resolver.js.map +1 -0
  95. package/dist/presentation/analyze-repository.d.ts +2 -0
  96. package/dist/presentation/analyze-repository.d.ts.map +1 -1
  97. package/dist/presentation/analyze-repository.js +28 -5
  98. package/dist/presentation/analyze-repository.js.map +1 -1
  99. package/dist/presentation/cli/arguments.d.ts +1 -0
  100. package/dist/presentation/cli/arguments.d.ts.map +1 -1
  101. package/dist/presentation/cli/arguments.js +7 -0
  102. package/dist/presentation/cli/arguments.js.map +1 -1
  103. package/dist/presentation/cli/main.js +5 -0
  104. package/dist/presentation/cli/main.js.map +1 -1
  105. package/dist/presentation/github/action-inputs.d.ts +2 -0
  106. package/dist/presentation/github/action-inputs.d.ts.map +1 -1
  107. package/dist/presentation/github/action-inputs.js +10 -0
  108. package/dist/presentation/github/action-inputs.js.map +1 -1
  109. package/dist/presentation/github/pr-body-intent.d.ts +3 -0
  110. package/dist/presentation/github/pr-body-intent.d.ts.map +1 -0
  111. package/dist/presentation/github/pr-body-intent.js +15 -0
  112. package/dist/presentation/github/pr-body-intent.js.map +1 -0
  113. package/dist/presentation/github/run-action.d.ts.map +1 -1
  114. package/dist/presentation/github/run-action.js +10 -0
  115. package/dist/presentation/github/run-action.js.map +1 -1
  116. package/package.json +3 -2
@@ -0,0 +1,98 @@
1
+ import { NpmWorkspaceDependencyRule } from "./npm-workspace-dependency-rule.js";
2
+ import { PackageDependencyRule } from "./package-dependency-rule.js";
3
+ import { PnpmWorkspaceDependencyRule } from "./pnpm-workspace-dependency-rule.js";
4
+ const rootManifest = "package.json";
5
+ const generatedDirectories = new Set([
6
+ "node_modules",
7
+ "dist",
8
+ "build",
9
+ "coverage",
10
+ "action-dist",
11
+ ".next",
12
+ ".turbo",
13
+ ]);
14
+ /** 새 직접 dependency의 정적 소스 참조가 없을 때만 검토 후보를 제시한다. */
15
+ export class AddedDependencyUsageRule {
16
+ snapshots;
17
+ files;
18
+ extractor;
19
+ pnpmWorkspaceParser;
20
+ constructor(snapshots, files, extractor, pnpmWorkspaceParser) {
21
+ this.snapshots = snapshots;
22
+ this.files = files;
23
+ this.extractor = extractor;
24
+ this.pnpmWorkspaceParser = pnpmWorkspaceParser;
25
+ }
26
+ async analyze(context) {
27
+ const manifestFindings = (await Promise.all([
28
+ new PackageDependencyRule(this.snapshots, rootManifest).analyze(context),
29
+ new NpmWorkspaceDependencyRule(this.snapshots).analyze(context),
30
+ new PnpmWorkspaceDependencyRule(this.snapshots, this.pnpmWorkspaceParser).analyze(context),
31
+ ])).flat();
32
+ const added = manifestFindings.filter((finding) => finding.ruleId === "dependency/new-production" ||
33
+ finding.ruleId === "dependency/new-development");
34
+ if (added.length === 0)
35
+ return [];
36
+ const paths = (await this.files.listPaths(context.target)).filter((path) => this.extractor.supports(path) &&
37
+ !path.split("/").some((part) => generatedDirectories.has(part)));
38
+ const referenced = new Set();
39
+ if (paths.length === 0 || paths.length > 5_000)
40
+ return [];
41
+ let complete = true;
42
+ // 읽기·파싱 실패나 계산할 수 없는 동적 import가 있으면 미사용 후보를 단정하지 않는다.
43
+ for (const path of paths) {
44
+ const file = await this.files.read(context.target, path);
45
+ if (file.kind !== "success") {
46
+ complete = false;
47
+ break;
48
+ }
49
+ const references = this.extractor.extract(path, file.content);
50
+ if (references.kind !== "success" || references.hasDynamicSpecifier === true) {
51
+ complete = false;
52
+ break;
53
+ }
54
+ for (const specifier of references.specifiers) {
55
+ const packageName = packageNameFromSpecifier(specifier);
56
+ if (packageName !== undefined)
57
+ referenced.add(packageName);
58
+ }
59
+ }
60
+ if (!complete)
61
+ return [];
62
+ return added.flatMap((finding) => {
63
+ const name = finding.evidence.package;
64
+ if (typeof name !== "string" || referenced.has(name))
65
+ return [];
66
+ return [
67
+ {
68
+ ruleId: "dependency/no-static-reference",
69
+ severity: "low",
70
+ title: "New dependency has no static source reference",
71
+ description: `${name} was added to ${finding.file}, but no static JS/TS import was found. Check CLI, configuration, and generated-code usage before removing it.`,
72
+ file: finding.file,
73
+ evidence: {
74
+ package: name,
75
+ section: String(finding.evidence.section),
76
+ scannedFiles: paths.length,
77
+ ...(finding.evidence.workspace === undefined
78
+ ? {}
79
+ : { workspace: finding.evidence.workspace }),
80
+ ...(finding.evidence.packageManager === undefined
81
+ ? {}
82
+ : { packageManager: finding.evidence.packageManager }),
83
+ },
84
+ },
85
+ ];
86
+ });
87
+ }
88
+ }
89
+ function packageNameFromSpecifier(specifier) {
90
+ if (specifier.startsWith(".") ||
91
+ specifier.startsWith("/") ||
92
+ specifier.startsWith("#") ||
93
+ specifier.startsWith("node:"))
94
+ return undefined;
95
+ const parts = specifier.split("/");
96
+ return specifier.startsWith("@") && parts.length >= 2 ? `${parts[0]}/${parts[1]}` : parts[0];
97
+ }
98
+ //# sourceMappingURL=added-dependency-usage-rule.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"added-dependency-usage-rule.js","sourceRoot":"","sources":["../../../src/application/rules/added-dependency-usage-rule.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import type { Finding } from "../../domain/finding.js";
2
+ import type { AnalysisContext, AnalysisRule } from "../ports/analysis-rule.js";
3
+ import type { FileSnapshotSource } from "../ports/file-snapshot-source.js";
4
+ import type { PackageLockParser } from "../ports/package-lock-parser.js";
5
+ /** 선언 버전이 아닌, npm이 실제로 고정한 패키지 버전과 설치 위치의 변화를 분석한다. */
6
+ export declare class NpmLockfileRule implements AnalysisRule {
7
+ private readonly snapshots;
8
+ private readonly parser;
9
+ constructor(snapshots: FileSnapshotSource, parser: PackageLockParser);
10
+ analyze(context: AnalysisContext): Promise<readonly Finding[]>;
11
+ }
12
+ //# sourceMappingURL=npm-lockfile-rule.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"npm-lockfile-rule.d.ts","sourceRoot":"","sources":["../../../src/application/rules/npm-lockfile-rule.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAC/E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AAC3E,OAAO,KAAK,EAAiB,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AAIxF,uDAAuD;AACvD,qBAAa,eAAgB,YAAW,YAAY;IAEhD,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,MAAM;gBADN,SAAS,EAAE,kBAAkB,EAC7B,MAAM,EAAE,iBAAiB;IAG/B,OAAO,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,SAAS,OAAO,EAAE,CAAC;CAiC5E"}
@@ -0,0 +1,109 @@
1
+ const lockfilePath = "package-lock.json";
2
+ /** 선언 버전이 아닌, npm이 실제로 고정한 패키지 버전과 설치 위치의 변화를 분석한다. */
3
+ export class NpmLockfileRule {
4
+ snapshots;
5
+ parser;
6
+ constructor(snapshots, parser) {
7
+ this.snapshots = snapshots;
8
+ this.parser = parser;
9
+ }
10
+ async analyze(context) {
11
+ if (!context.changes.files.some((change) => change.path === lockfilePath || change.previousPath === lockfilePath)) {
12
+ return [];
13
+ }
14
+ const snapshot = await this.snapshots.read(context.target, lockfilePath);
15
+ const before = snapshot.before === undefined ? undefined : this.parser.parse(snapshot.before);
16
+ const after = snapshot.after === undefined ? undefined : this.parser.parse(snapshot.after);
17
+ const errors = [
18
+ ...(before !== undefined && !before.ok ? [parseFinding("base", before)] : []),
19
+ ...(after !== undefined && !after.ok ? [parseFinding("current", after)] : []),
20
+ ];
21
+ if (errors.length > 0) {
22
+ return errors;
23
+ }
24
+ if (before === undefined && after === undefined) {
25
+ return [];
26
+ }
27
+ if (before === undefined && after?.ok) {
28
+ return [lockfilePresenceFinding("added", after.packages.size)];
29
+ }
30
+ if (after === undefined && before?.ok) {
31
+ return [lockfilePresenceFinding("removed", before.packages.size)];
32
+ }
33
+ if (before?.ok && after?.ok) {
34
+ return comparePackages(before.packages, after.packages);
35
+ }
36
+ return [];
37
+ }
38
+ }
39
+ function comparePackages(before, after) {
40
+ const paths = [...new Set([...before.keys(), ...after.keys()])].sort();
41
+ const findings = [];
42
+ for (const path of paths) {
43
+ const previous = before.get(path);
44
+ const current = after.get(path);
45
+ if (previous === undefined && current !== undefined) {
46
+ findings.push({
47
+ ruleId: "dependency/locked-package-added",
48
+ severity: "low",
49
+ title: "Resolved package added",
50
+ description: `${current.name}@${current.version} was added at ${path}.`,
51
+ file: lockfilePath,
52
+ evidence: packageEvidence(current),
53
+ });
54
+ }
55
+ else if (previous !== undefined && current === undefined) {
56
+ findings.push({
57
+ ruleId: "dependency/locked-package-removed",
58
+ severity: "low",
59
+ title: "Resolved package removed",
60
+ description: `${previous.name}@${previous.version} was removed from ${path}.`,
61
+ file: lockfilePath,
62
+ evidence: packageEvidence(previous),
63
+ });
64
+ }
65
+ else if (previous !== undefined &&
66
+ current !== undefined &&
67
+ previous.version !== current.version) {
68
+ findings.push({
69
+ ruleId: "dependency/locked-version-changed",
70
+ severity: "low",
71
+ title: "Resolved package version changed",
72
+ description: `${current.name} at ${path} changed from ${previous.version} to ${current.version}.`,
73
+ file: lockfilePath,
74
+ evidence: { ...packageEvidence(current), from: previous.version, to: current.version },
75
+ });
76
+ }
77
+ }
78
+ return findings;
79
+ }
80
+ function packageEvidence(item) {
81
+ return {
82
+ package: item.name,
83
+ version: item.version,
84
+ installPath: item.path,
85
+ rootDirect: item.rootDirect,
86
+ };
87
+ }
88
+ function parseFinding(side, result) {
89
+ const unsupported = result.kind === "unsupported";
90
+ return {
91
+ ruleId: unsupported ? "dependency/unsupported-lockfile" : "dependency/invalid-lockfile",
92
+ severity: unsupported ? "low" : "high",
93
+ title: unsupported ? "Unsupported npm lockfile" : "Invalid npm lockfile",
94
+ description: `Could not analyze the ${side} package-lock.json: ${result.reason}`,
95
+ file: lockfilePath,
96
+ evidence: { side, reason: result.reason },
97
+ };
98
+ }
99
+ function lockfilePresenceFinding(kind, packageCount) {
100
+ return {
101
+ ruleId: `dependency/lockfile-${kind}`,
102
+ severity: "low",
103
+ title: kind === "added" ? "npm lockfile added" : "npm lockfile removed",
104
+ description: `package-lock.json was ${kind} with ${packageCount} resolved packages.`,
105
+ file: lockfilePath,
106
+ evidence: { packageCount },
107
+ };
108
+ }
109
+ //# sourceMappingURL=npm-lockfile-rule.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"npm-lockfile-rule.js","sourceRoot":"","sources":["../../../src/application/rules/npm-lockfile-rule.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import type { Finding } from "../../domain/finding.js";
2
+ import type { AnalysisContext, AnalysisRule } from "../ports/analysis-rule.js";
3
+ import type { FileSnapshotSource } from "../ports/file-snapshot-source.js";
4
+ /** npm workspaces에 속한 변경 manifest를 찾아 기존 직접 dependency 규칙으로 분석한다. */
5
+ export declare class NpmWorkspaceDependencyRule implements AnalysisRule {
6
+ private readonly snapshots;
7
+ constructor(snapshots: FileSnapshotSource);
8
+ analyze(context: AnalysisContext): Promise<readonly Finding[]>;
9
+ }
10
+ //# sourceMappingURL=npm-workspace-dependency-rule.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"npm-workspace-dependency-rule.d.ts","sourceRoot":"","sources":["../../../src/application/rules/npm-workspace-dependency-rule.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAEvD,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAC/E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AAY3E,qEAAqE;AACrE,qBAAa,0BAA2B,YAAW,YAAY;IAC1C,OAAO,CAAC,QAAQ,CAAC,SAAS;gBAAT,SAAS,EAAE,kBAAkB;IAEpD,OAAO,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,SAAS,OAAO,EAAE,CAAC;CAsD5E"}
@@ -0,0 +1,107 @@
1
+ import { isRecord } from "../../domain/value-guards.js";
2
+ import { analyzeWorkspaceManifests, isNestedManifestChange, } from "../services/workspace-manifest-analysis.js";
3
+ const rootManifestPath = "package.json";
4
+ /** npm workspaces에 속한 변경 manifest를 찾아 기존 직접 dependency 규칙으로 분석한다. */
5
+ export class NpmWorkspaceDependencyRule {
6
+ snapshots;
7
+ constructor(snapshots) {
8
+ this.snapshots = snapshots;
9
+ }
10
+ async analyze(context) {
11
+ const manifestChanges = context.changes.files.filter(isNestedManifestChange);
12
+ const rootChanged = context.changes.files.some((change) => change.path === rootManifestPath || change.previousPath === rootManifestPath);
13
+ if (manifestChanges.length === 0 && !rootChanged) {
14
+ return [];
15
+ }
16
+ // pnpm-workspace.yaml이 있으면 pnpm 설정이 우선한다. 동일 manifest의 finding 중복을 피한다.
17
+ const pnpmConfig = await this.snapshots.read(context.target, "pnpm-workspace.yaml");
18
+ if (pnpmConfig.before !== undefined || pnpmConfig.after !== undefined)
19
+ return [];
20
+ const snapshot = await this.snapshots.read(context.target, rootManifestPath);
21
+ const before = parseWorkspaceConfig(snapshot.before);
22
+ const after = parseWorkspaceConfig(snapshot.after);
23
+ const errors = [
24
+ ...(!before.ok ? [configFinding("base", before)] : []),
25
+ ...(!after.ok ? [configFinding("current", after)] : []),
26
+ ];
27
+ if (errors.length > 0) {
28
+ return errors;
29
+ }
30
+ if (!before.ok || !after.ok) {
31
+ return [];
32
+ }
33
+ const findings = [];
34
+ if (rootChanged && JSON.stringify(before.patterns) !== JSON.stringify(after.patterns)) {
35
+ findings.push({
36
+ ruleId: "dependency/workspace-config-changed",
37
+ severity: "low",
38
+ title: "npm workspace configuration changed",
39
+ description: "The root package.json workspace patterns changed.",
40
+ file: rootManifestPath,
41
+ evidence: {
42
+ from: JSON.stringify(before.patterns),
43
+ to: JSON.stringify(after.patterns),
44
+ },
45
+ });
46
+ }
47
+ return [
48
+ ...findings,
49
+ ...(await analyzeWorkspaceManifests(context, this.snapshots, manifestChanges, { includes: before.patterns, excludes: [] }, { includes: after.patterns, excludes: [] }, "npm")),
50
+ ];
51
+ }
52
+ }
53
+ function parseWorkspaceConfig(content) {
54
+ if (content === undefined) {
55
+ return { ok: true, patterns: [] };
56
+ }
57
+ let manifest;
58
+ try {
59
+ manifest = JSON.parse(content);
60
+ }
61
+ catch {
62
+ return { ok: false, kind: "invalid", reason: "The root package.json is not valid JSON." };
63
+ }
64
+ if (!isRecord(manifest)) {
65
+ return { ok: false, kind: "invalid", reason: "The root package.json must be an object." };
66
+ }
67
+ if (manifest.workspaces === undefined) {
68
+ return { ok: true, patterns: [] };
69
+ }
70
+ if (!Array.isArray(manifest.workspaces)) {
71
+ return { ok: false, kind: "invalid", reason: "workspaces must be an array of paths." };
72
+ }
73
+ const patterns = [];
74
+ for (const rawPattern of manifest.workspaces) {
75
+ if (typeof rawPattern !== "string" || rawPattern.trim().length === 0) {
76
+ return { ok: false, kind: "invalid", reason: "Each workspace path must be a string." };
77
+ }
78
+ const pattern = rawPattern.replace(/^(\.\/)+/, "").replace(/\/+$/, "");
79
+ if (pattern.length === 0 || pattern.startsWith("/") || pattern.split("/").includes("..")) {
80
+ return { ok: false, kind: "invalid", reason: `Invalid workspace path: ${rawPattern}.` };
81
+ }
82
+ if (["!", "{", "}", "[", "]", "\\"].some((character) => pattern.includes(character))) {
83
+ return {
84
+ ok: false,
85
+ kind: "unsupported",
86
+ reason: `Unsupported workspace pattern: ${rawPattern}. Only *, **, and ? globs are supported.`,
87
+ };
88
+ }
89
+ patterns.push(pattern);
90
+ }
91
+ return { ok: true, patterns };
92
+ }
93
+ function configFinding(side, result) {
94
+ return {
95
+ ruleId: result.kind === "invalid"
96
+ ? "dependency/invalid-workspace-config"
97
+ : "dependency/unsupported-workspace-pattern",
98
+ severity: result.kind === "invalid" ? "high" : "low",
99
+ title: result.kind === "invalid"
100
+ ? "Invalid npm workspace configuration"
101
+ : "Unsupported npm workspace pattern",
102
+ description: `Could not analyze the ${side} npm workspaces: ${result.reason}`,
103
+ file: rootManifestPath,
104
+ evidence: { side, reason: result.reason },
105
+ };
106
+ }
107
+ //# sourceMappingURL=npm-workspace-dependency-rule.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"npm-workspace-dependency-rule.js","sourceRoot":"","sources":["../../../src/application/rules/npm-workspace-dependency-rule.ts"],"names":[],"mappings":"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"}
@@ -2,12 +2,13 @@ import type { Finding } from "../../domain/finding.js";
2
2
  import type { AnalysisContext, AnalysisRule } from "../ports/analysis-rule.js";
3
3
  import type { FileSnapshotSource } from "../ports/file-snapshot-source.js";
4
4
  /**
5
- * 루트 package.json의 직접 dependency 변경만 판단한다.
6
- * lockfile의 전이 dependency와 workspace package 지원은 별도 규칙으로 확장한다.
5
+ * 한 package.json의 직접 dependency 선언 변경을 판단한다.
6
+ * 루트와 workspace 규칙이 같은 판단 기준을 사용하도록 경로를 주입받는다.
7
7
  */
8
8
  export declare class PackageDependencyRule implements AnalysisRule {
9
9
  private readonly snapshots;
10
- constructor(snapshots: FileSnapshotSource);
10
+ private readonly manifestPath;
11
+ constructor(snapshots: FileSnapshotSource, manifestPath?: string);
11
12
  analyze(context: AnalysisContext): Promise<readonly Finding[]>;
12
13
  }
13
14
  //# sourceMappingURL=package-dependency-rule.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"package-dependency-rule.d.ts","sourceRoot":"","sources":["../../../src/application/rules/package-dependency-rule.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAY,MAAM,yBAAyB,CAAC;AACjE,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAC/E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AAgB3E;;;GAGG;AACH,qBAAa,qBAAsB,YAAW,YAAY;IACrC,OAAO,CAAC,QAAQ,CAAC,SAAS;gBAAT,SAAS,EAAE,kBAAkB;IAEpD,OAAO,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,SAAS,OAAO,EAAE,CAAC;CAoB5E"}
1
+ {"version":3,"file":"package-dependency-rule.d.ts","sourceRoot":"","sources":["../../../src/application/rules/package-dependency-rule.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAY,MAAM,yBAAyB,CAAC;AAEjE,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAC/E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AAgB3E;;;GAGG;AACH,qBAAa,qBAAsB,YAAW,YAAY;IAEtD,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,YAAY;gBADZ,SAAS,EAAE,kBAAkB,EAC7B,YAAY,SAAmB;IAGrC,OAAO,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,SAAS,OAAO,EAAE,CAAC;CA6B5E"}
@@ -1,21 +1,27 @@
1
- const manifestPath = "package.json";
1
+ import { isRecord } from "../../domain/value-guards.js";
2
+ const rootManifestPath = "package.json";
2
3
  const dependencySections = ["dependencies", "devDependencies"];
3
4
  /**
4
- * 루트 package.json의 직접 dependency 변경만 판단한다.
5
- * lockfile의 전이 dependency와 workspace package 지원은 별도 규칙으로 확장한다.
5
+ * 한 package.json의 직접 dependency 선언 변경을 판단한다.
6
+ * 루트와 workspace 규칙이 같은 판단 기준을 사용하도록 경로를 주입받는다.
6
7
  */
7
8
  export class PackageDependencyRule {
8
9
  snapshots;
9
- constructor(snapshots) {
10
+ manifestPath;
11
+ constructor(snapshots, manifestPath = rootManifestPath) {
10
12
  this.snapshots = snapshots;
13
+ this.manifestPath = manifestPath;
11
14
  }
12
15
  async analyze(context) {
13
- if (!context.changes.files.some(isManifestChange)) {
16
+ const change = context.changes.files.find((item) => item.path === this.manifestPath || item.previousPath === this.manifestPath);
17
+ if (change === undefined) {
14
18
  return [];
15
19
  }
16
- const snapshot = await this.snapshots.read(context.target, manifestPath);
17
- const before = parseManifest(snapshot.before, "base");
18
- const after = parseManifest(snapshot.after, "current");
20
+ const snapshot = await this.snapshots.read(context.target, this.manifestPath, change.kind === "renamed" && isPackageManifestPath(change.previousPath)
21
+ ? change.previousPath
22
+ : undefined);
23
+ const before = parseManifest(snapshot.before, "base", this.manifestPath);
24
+ const after = parseManifest(snapshot.after, "current", this.manifestPath);
19
25
  if (!before.ok && !after.ok) {
20
26
  return [before.finding, after.finding];
21
27
  }
@@ -25,13 +31,13 @@ export class PackageDependencyRule {
25
31
  if (!after.ok) {
26
32
  return [after.finding];
27
33
  }
28
- return compareDependencies(before.dependencies, after.dependencies);
34
+ return compareDependencies(before.dependencies, after.dependencies, this.manifestPath);
29
35
  }
30
36
  }
31
- function isManifestChange(change) {
32
- return change.path === manifestPath || change.previousPath === manifestPath;
37
+ function isPackageManifestPath(path) {
38
+ return path === rootManifestPath || path?.endsWith("/package.json") === true;
33
39
  }
34
- function parseManifest(content, side) {
40
+ function parseManifest(content, side, manifestPath) {
35
41
  if (content === undefined) {
36
42
  return { ok: true, dependencies: new Map() };
37
43
  }
@@ -40,10 +46,10 @@ function parseManifest(content, side) {
40
46
  value = JSON.parse(content);
41
47
  }
42
48
  catch {
43
- return invalidManifest(side, "The file is not valid JSON.");
49
+ return invalidManifest(side, "The file is not valid JSON.", manifestPath);
44
50
  }
45
51
  if (!isRecord(value)) {
46
- return invalidManifest(side, "The root value must be a JSON object.");
52
+ return invalidManifest(side, "The root value must be a JSON object.", manifestPath);
47
53
  }
48
54
  const dependencies = new Map();
49
55
  for (const section of dependencySections) {
@@ -52,48 +58,48 @@ function parseManifest(content, side) {
52
58
  continue;
53
59
  }
54
60
  if (!isRecord(entries)) {
55
- return invalidManifest(side, `${section} must be a JSON object.`);
61
+ return invalidManifest(side, `${section} must be a JSON object.`, manifestPath);
56
62
  }
57
63
  for (const [name, version] of Object.entries(entries)) {
58
64
  if (typeof version !== "string") {
59
- return invalidManifest(side, `${section}.${name} must have a string version.`);
65
+ return invalidManifest(side, `${section}.${name} must have a string version.`, manifestPath);
60
66
  }
61
67
  if (dependencies.has(name)) {
62
- return invalidManifest(side, `${name} is declared in more than one dependency section.`);
68
+ return invalidManifest(side, `${name} is declared in more than one dependency section.`, manifestPath);
63
69
  }
64
70
  dependencies.set(name, { section, version });
65
71
  }
66
72
  }
67
73
  return { ok: true, dependencies };
68
74
  }
69
- function compareDependencies(before, after) {
75
+ function compareDependencies(before, after, manifestPath) {
70
76
  const names = [...new Set([...before.keys(), ...after.keys()])].sort((left, right) => left.localeCompare(right));
71
77
  const findings = [];
72
78
  for (const name of names) {
73
79
  const previous = before.get(name);
74
80
  const current = after.get(name);
75
81
  if (previous === undefined && current !== undefined) {
76
- findings.push(addedDependency(name, current));
82
+ findings.push(addedDependency(name, current, manifestPath));
77
83
  continue;
78
84
  }
79
85
  if (previous !== undefined && current === undefined) {
80
- findings.push(removedDependency(name, previous));
86
+ findings.push(removedDependency(name, previous, manifestPath));
81
87
  continue;
82
88
  }
83
89
  if (previous === undefined || current === undefined) {
84
90
  continue;
85
91
  }
86
92
  if (previous.section !== current.section) {
87
- findings.push(movedDependency(name, previous, current));
93
+ findings.push(movedDependency(name, previous, current, manifestPath));
88
94
  continue;
89
95
  }
90
96
  if (previous.version !== current.version) {
91
- findings.push(changedDependency(name, previous, current));
97
+ findings.push(changedDependency(name, previous, current, manifestPath));
92
98
  }
93
99
  }
94
100
  return findings;
95
101
  }
96
- function addedDependency(name, declaration) {
102
+ function addedDependency(name, declaration, manifestPath) {
97
103
  const production = declaration.section === "dependencies";
98
104
  return {
99
105
  ruleId: production ? "dependency/new-production" : "dependency/new-development",
@@ -108,7 +114,7 @@ function addedDependency(name, declaration) {
108
114
  },
109
115
  };
110
116
  }
111
- function removedDependency(name, declaration) {
117
+ function removedDependency(name, declaration, manifestPath) {
112
118
  return {
113
119
  ruleId: "dependency/removed",
114
120
  severity: "low",
@@ -122,7 +128,7 @@ function removedDependency(name, declaration) {
122
128
  },
123
129
  };
124
130
  }
125
- function movedDependency(name, previous, current) {
131
+ function movedDependency(name, previous, current, manifestPath) {
126
132
  return {
127
133
  ruleId: "dependency/section-changed",
128
134
  severity: current.section === "dependencies" ? "medium" : "low",
@@ -137,7 +143,7 @@ function movedDependency(name, previous, current) {
137
143
  },
138
144
  };
139
145
  }
140
- function changedDependency(name, previous, current) {
146
+ function changedDependency(name, previous, current, manifestPath) {
141
147
  return {
142
148
  ruleId: "dependency/version-changed",
143
149
  severity: severityFor(current.section),
@@ -152,14 +158,14 @@ function changedDependency(name, previous, current) {
152
158
  },
153
159
  };
154
160
  }
155
- function invalidManifest(side, reason) {
161
+ function invalidManifest(side, reason, manifestPath) {
156
162
  return {
157
163
  ok: false,
158
164
  finding: {
159
165
  ruleId: "dependency/invalid-manifest",
160
166
  severity: "high",
161
167
  title: "Invalid package manifest",
162
- description: `Could not analyze the ${side} package.json: ${reason}`,
168
+ description: `Could not analyze the ${side} ${manifestPath}: ${reason}`,
163
169
  file: manifestPath,
164
170
  evidence: { side, reason },
165
171
  },
@@ -168,7 +174,4 @@ function invalidManifest(side, reason) {
168
174
  function severityFor(section) {
169
175
  return section === "dependencies" ? "medium" : "low";
170
176
  }
171
- function isRecord(value) {
172
- return typeof value === "object" && value !== null && !Array.isArray(value);
173
- }
174
177
  //# sourceMappingURL=package-dependency-rule.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"package-dependency-rule.js","sourceRoot":"","sources":["../../../src/application/rules/package-dependency-rule.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"package-dependency-rule.js","sourceRoot":"","sources":["../../../src/application/rules/package-dependency-rule.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import type { Finding } from "../../domain/finding.js";
2
+ import type { AnalysisContext, AnalysisRule } from "../ports/analysis-rule.js";
3
+ import type { FileSnapshotSource } from "../ports/file-snapshot-source.js";
4
+ import type { PnpmLockParser } from "../ports/pnpm-lock-parser.js";
5
+ /** pnpm의 프로젝트 lockfile에서 고정된 레지스트리 패키지 버전 변화를 보고한다. */
6
+ export declare class PnpmLockfileRule implements AnalysisRule {
7
+ private readonly snapshots;
8
+ private readonly parser;
9
+ constructor(snapshots: FileSnapshotSource, parser: PnpmLockParser);
10
+ analyze(context: AnalysisContext): Promise<readonly Finding[]>;
11
+ }
12
+ //# sourceMappingURL=pnpm-lockfile-rule.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pnpm-lockfile-rule.d.ts","sourceRoot":"","sources":["../../../src/application/rules/pnpm-lockfile-rule.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAC/E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AAC3E,OAAO,KAAK,EAAqB,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAItF,uDAAuD;AACvD,qBAAa,gBAAiB,YAAW,YAAY;IAEjD,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,MAAM;gBADN,SAAS,EAAE,kBAAkB,EAC7B,MAAM,EAAE,cAAc;IAG5B,OAAO,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,SAAS,OAAO,EAAE,CAAC;CA8B5E"}