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.
- package/README.ko.md +74 -22
- package/README.md +62 -17
- package/dist/application/ports/module-alias-resolver.d.ts +11 -0
- package/dist/application/ports/module-alias-resolver.d.ts.map +1 -0
- package/dist/application/ports/module-alias-resolver.js +2 -0
- package/dist/application/ports/module-alias-resolver.js.map +1 -0
- package/dist/application/ports/module-reference-extractor.d.ts +1 -0
- package/dist/application/ports/module-reference-extractor.d.ts.map +1 -1
- package/dist/application/ports/package-lock-parser.d.ts +20 -0
- package/dist/application/ports/package-lock-parser.d.ts.map +1 -0
- package/dist/application/ports/package-lock-parser.js +2 -0
- package/dist/application/ports/package-lock-parser.js.map +1 -0
- package/dist/application/ports/parse-failure.d.ts +7 -0
- package/dist/application/ports/parse-failure.d.ts.map +1 -0
- package/dist/application/ports/parse-failure.js +5 -0
- package/dist/application/ports/parse-failure.js.map +1 -0
- package/dist/application/ports/pnpm-lock-parser.d.ts +20 -0
- package/dist/application/ports/pnpm-lock-parser.d.ts.map +1 -0
- package/dist/application/ports/pnpm-lock-parser.js +2 -0
- package/dist/application/ports/pnpm-lock-parser.js.map +1 -0
- package/dist/application/ports/pnpm-workspace-parser.d.ts +14 -0
- package/dist/application/ports/pnpm-workspace-parser.d.ts.map +1 -0
- package/dist/application/ports/pnpm-workspace-parser.js +2 -0
- package/dist/application/ports/pnpm-workspace-parser.js.map +1 -0
- package/dist/application/rules/added-dependency-usage-rule.d.ts +16 -0
- package/dist/application/rules/added-dependency-usage-rule.d.ts.map +1 -0
- package/dist/application/rules/added-dependency-usage-rule.js +98 -0
- package/dist/application/rules/added-dependency-usage-rule.js.map +1 -0
- package/dist/application/rules/npm-lockfile-rule.d.ts +12 -0
- package/dist/application/rules/npm-lockfile-rule.d.ts.map +1 -0
- package/dist/application/rules/npm-lockfile-rule.js +109 -0
- package/dist/application/rules/npm-lockfile-rule.js.map +1 -0
- package/dist/application/rules/npm-workspace-dependency-rule.d.ts +10 -0
- package/dist/application/rules/npm-workspace-dependency-rule.d.ts.map +1 -0
- package/dist/application/rules/npm-workspace-dependency-rule.js +107 -0
- package/dist/application/rules/npm-workspace-dependency-rule.js.map +1 -0
- package/dist/application/rules/package-dependency-rule.d.ts +4 -3
- package/dist/application/rules/package-dependency-rule.d.ts.map +1 -1
- package/dist/application/rules/package-dependency-rule.js +34 -31
- package/dist/application/rules/package-dependency-rule.js.map +1 -1
- package/dist/application/rules/pnpm-lockfile-rule.d.ts +12 -0
- package/dist/application/rules/pnpm-lockfile-rule.d.ts.map +1 -0
- package/dist/application/rules/pnpm-lockfile-rule.js +119 -0
- package/dist/application/rules/pnpm-lockfile-rule.js.map +1 -0
- package/dist/application/rules/pnpm-workspace-dependency-rule.d.ts +12 -0
- package/dist/application/rules/pnpm-workspace-dependency-rule.d.ts.map +1 -0
- package/dist/application/rules/pnpm-workspace-dependency-rule.js +59 -0
- package/dist/application/rules/pnpm-workspace-dependency-rule.js.map +1 -0
- package/dist/application/services/analyze-import-impact.d.ts +3 -1
- package/dist/application/services/analyze-import-impact.d.ts.map +1 -1
- package/dist/application/services/analyze-import-impact.js +12 -7
- package/dist/application/services/analyze-import-impact.js.map +1 -1
- package/dist/application/services/workspace-manifest-analysis.d.ts +12 -0
- package/dist/application/services/workspace-manifest-analysis.d.ts.map +1 -0
- package/dist/application/services/workspace-manifest-analysis.js +60 -0
- package/dist/application/services/workspace-manifest-analysis.js.map +1 -0
- package/dist/domain/value-guards.d.ts +3 -0
- package/dist/domain/value-guards.d.ts.map +1 -0
- package/dist/domain/value-guards.js +5 -0
- package/dist/domain/value-guards.js.map +1 -0
- package/dist/infrastructure/config/json-change-contract-loader.d.ts.map +1 -1
- package/dist/infrastructure/config/json-change-contract-loader.js +1 -3
- package/dist/infrastructure/config/json-change-contract-loader.js.map +1 -1
- package/dist/infrastructure/config/text-intent-loader.d.ts +5 -0
- package/dist/infrastructure/config/text-intent-loader.d.ts.map +1 -0
- package/dist/infrastructure/config/text-intent-loader.js +30 -0
- package/dist/infrastructure/config/text-intent-loader.js.map +1 -0
- package/dist/infrastructure/git/git-file-snapshot-source.d.ts.map +1 -1
- package/dist/infrastructure/git/git-file-snapshot-source.js +6 -2
- package/dist/infrastructure/git/git-file-snapshot-source.js.map +1 -1
- package/dist/infrastructure/npm/npm-package-lock-parser.d.ts +6 -0
- package/dist/infrastructure/npm/npm-package-lock-parser.d.ts.map +1 -0
- package/dist/infrastructure/npm/npm-package-lock-parser.js +89 -0
- package/dist/infrastructure/npm/npm-package-lock-parser.js.map +1 -0
- package/dist/infrastructure/pnpm/pnpm-lock-parser.d.ts +6 -0
- package/dist/infrastructure/pnpm/pnpm-lock-parser.d.ts.map +1 -0
- package/dist/infrastructure/pnpm/pnpm-lock-parser.js +122 -0
- package/dist/infrastructure/pnpm/pnpm-lock-parser.js.map +1 -0
- package/dist/infrastructure/pnpm/pnpm-workspace-parser.d.ts +6 -0
- package/dist/infrastructure/pnpm/pnpm-workspace-parser.d.ts.map +1 -0
- package/dist/infrastructure/pnpm/pnpm-workspace-parser.js +62 -0
- package/dist/infrastructure/pnpm/pnpm-workspace-parser.js.map +1 -0
- package/dist/infrastructure/typescript/package-module-reference-extractor.d.ts +7 -0
- package/dist/infrastructure/typescript/package-module-reference-extractor.d.ts.map +1 -0
- package/dist/infrastructure/typescript/package-module-reference-extractor.js +68 -0
- package/dist/infrastructure/typescript/package-module-reference-extractor.js.map +1 -0
- package/dist/infrastructure/typescript/typescript-config-loader.d.ts +17 -0
- package/dist/infrastructure/typescript/typescript-config-loader.d.ts.map +1 -0
- package/dist/infrastructure/typescript/typescript-config-loader.js +97 -0
- package/dist/infrastructure/typescript/typescript-config-loader.js.map +1 -0
- package/dist/infrastructure/typescript/typescript-module-alias-resolver.d.ts +10 -0
- package/dist/infrastructure/typescript/typescript-module-alias-resolver.d.ts.map +1 -0
- package/dist/infrastructure/typescript/typescript-module-alias-resolver.js +78 -0
- package/dist/infrastructure/typescript/typescript-module-alias-resolver.js.map +1 -0
- package/dist/presentation/analyze-repository.d.ts +2 -0
- package/dist/presentation/analyze-repository.d.ts.map +1 -1
- package/dist/presentation/analyze-repository.js +28 -5
- package/dist/presentation/analyze-repository.js.map +1 -1
- package/dist/presentation/cli/arguments.d.ts +1 -0
- package/dist/presentation/cli/arguments.d.ts.map +1 -1
- package/dist/presentation/cli/arguments.js +7 -0
- package/dist/presentation/cli/arguments.js.map +1 -1
- package/dist/presentation/cli/main.js +5 -0
- package/dist/presentation/cli/main.js.map +1 -1
- package/dist/presentation/github/action-inputs.d.ts +2 -0
- package/dist/presentation/github/action-inputs.d.ts.map +1 -1
- package/dist/presentation/github/action-inputs.js +10 -0
- package/dist/presentation/github/action-inputs.js.map +1 -1
- package/dist/presentation/github/pr-body-intent.d.ts +3 -0
- package/dist/presentation/github/pr-body-intent.d.ts.map +1 -0
- package/dist/presentation/github/pr-body-intent.js +15 -0
- package/dist/presentation/github/pr-body-intent.js.map +1 -0
- package/dist/presentation/github/run-action.d.ts.map +1 -1
- package/dist/presentation/github/run-action.js +10 -0
- package/dist/presentation/github/run-action.js.map +1 -1
- 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
|
-
*
|
|
6
|
-
*
|
|
5
|
+
* 한 package.json의 직접 dependency 선언 변경을 판단한다.
|
|
6
|
+
* 루트와 workspace 규칙이 같은 판단 기준을 사용하도록 경로를 주입받는다.
|
|
7
7
|
*/
|
|
8
8
|
export declare class PackageDependencyRule implements AnalysisRule {
|
|
9
9
|
private readonly snapshots;
|
|
10
|
-
|
|
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;
|
|
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
|
-
|
|
1
|
+
import { isRecord } from "../../domain/value-guards.js";
|
|
2
|
+
const rootManifestPath = "package.json";
|
|
2
3
|
const dependencySections = ["dependencies", "devDependencies"];
|
|
3
4
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
5
|
+
* 한 package.json의 직접 dependency 선언 변경을 판단한다.
|
|
6
|
+
* 루트와 workspace 규칙이 같은 판단 기준을 사용하도록 경로를 주입받는다.
|
|
6
7
|
*/
|
|
7
8
|
export class PackageDependencyRule {
|
|
8
9
|
snapshots;
|
|
9
|
-
|
|
10
|
+
manifestPath;
|
|
11
|
+
constructor(snapshots, manifestPath = rootManifestPath) {
|
|
10
12
|
this.snapshots = snapshots;
|
|
13
|
+
this.manifestPath = manifestPath;
|
|
11
14
|
}
|
|
12
15
|
async analyze(context) {
|
|
13
|
-
|
|
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
|
-
|
|
18
|
-
|
|
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
|
|
32
|
-
return
|
|
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}
|
|
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":"
|
|
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"}
|