intentpatch 0.1.0 → 0.2.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 +488 -0
- package/README.md +215 -211
- 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/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/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 +155 -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 +33 -28
- package/dist/application/rules/package-dependency-rule.js.map +1 -1
- 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/infrastructure/git/git-file-snapshot-source.d.ts.map +1 -1
- package/dist/infrastructure/git/git-file-snapshot-source.js +4 -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 +93 -0
- package/dist/infrastructure/npm/npm-package-lock-parser.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 +99 -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.map +1 -1
- package/dist/presentation/analyze-repository.js +7 -3
- package/dist/presentation/analyze-repository.js.map +1 -1
- package/package.json +8 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"module-alias-resolver.d.ts","sourceRoot":"","sources":["../../../src/application/ports/module-alias-resolver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAE7D,oDAAoD;AACpD,MAAM,WAAW,mBAAmB;IAClC,OAAO,CACL,MAAM,EAAE,cAAc,EACtB,eAAe,EAAE,SAAS,MAAM,EAAE,EAClC,WAAW,EAAE,WAAW,CAAC,MAAM,CAAC,GAC/B,OAAO,CAAC,2BAA2B,CAAC,CAAC;CACzC;AAED,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,MAAM,EAAE,SAAS,mBAAmB,EAAE,CAAC;IAChD,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;CAClE"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"module-alias-resolver.js","sourceRoot":"","sources":["../../../src/application/ports/module-alias-resolver.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/** npm lockfile의 설치 위치를 기준으로 비교할 수 있는 패키지 정보다. */
|
|
2
|
+
export interface LockedPackage {
|
|
3
|
+
readonly path: string;
|
|
4
|
+
readonly name: string;
|
|
5
|
+
readonly version: string;
|
|
6
|
+
readonly rootDirect: boolean;
|
|
7
|
+
}
|
|
8
|
+
export type PackageLockParseResult = Readonly<{
|
|
9
|
+
ok: true;
|
|
10
|
+
packages: ReadonlyMap<string, LockedPackage>;
|
|
11
|
+
}> | Readonly<{
|
|
12
|
+
ok: false;
|
|
13
|
+
kind: "invalid" | "unsupported";
|
|
14
|
+
reason: string;
|
|
15
|
+
}>;
|
|
16
|
+
/** 패키지 매니저의 파일 형식을 분석 규칙에서 분리하는 입력 포트다. */
|
|
17
|
+
export interface PackageLockParser {
|
|
18
|
+
parse(content: string): PackageLockParseResult;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=package-lock-parser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"package-lock-parser.d.ts","sourceRoot":"","sources":["../../../src/application/ports/package-lock-parser.ts"],"names":[],"mappings":"AAAA,kDAAkD;AAClD,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;CAC9B;AAED,MAAM,MAAM,sBAAsB,GAC9B,QAAQ,CAAC;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,aAAa,CAAC,CAAA;CAAE,CAAC,GACpE,QAAQ,CAAC;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,SAAS,GAAG,aAAa,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAE7E,2CAA2C;AAC3C,MAAM,WAAW,iBAAiB;IAChC,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,sBAAsB,CAAC;CAChD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"package-lock-parser.js","sourceRoot":"","sources":["../../../src/application/ports/package-lock-parser.ts"],"names":[],"mappings":""}
|
|
@@ -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":"AACA,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;AAW3E,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;CAwF5E"}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import { matchesPathPattern } from "../services/path-pattern.js";
|
|
2
|
+
import { PackageDependencyRule } from "./package-dependency-rule.js";
|
|
3
|
+
const rootManifestPath = "package.json";
|
|
4
|
+
const manifestSuffix = "/package.json";
|
|
5
|
+
/** npm workspaces에 속한 변경 manifest를 찾아 기존 직접 dependency 규칙으로 분석한다. */
|
|
6
|
+
export class NpmWorkspaceDependencyRule {
|
|
7
|
+
snapshots;
|
|
8
|
+
constructor(snapshots) {
|
|
9
|
+
this.snapshots = snapshots;
|
|
10
|
+
}
|
|
11
|
+
async analyze(context) {
|
|
12
|
+
const manifestChanges = context.changes.files.filter(isNestedManifestChange);
|
|
13
|
+
const rootChanged = context.changes.files.some((change) => change.path === rootManifestPath || change.previousPath === rootManifestPath);
|
|
14
|
+
if (manifestChanges.length === 0 && !rootChanged) {
|
|
15
|
+
return [];
|
|
16
|
+
}
|
|
17
|
+
const snapshot = await this.snapshots.read(context.target, rootManifestPath);
|
|
18
|
+
const before = parseWorkspaceConfig(snapshot.before);
|
|
19
|
+
const after = parseWorkspaceConfig(snapshot.after);
|
|
20
|
+
const errors = [
|
|
21
|
+
...(!before.ok ? [configFinding("base", before)] : []),
|
|
22
|
+
...(!after.ok ? [configFinding("current", after)] : []),
|
|
23
|
+
];
|
|
24
|
+
if (errors.length > 0) {
|
|
25
|
+
return errors;
|
|
26
|
+
}
|
|
27
|
+
if (!before.ok || !after.ok) {
|
|
28
|
+
return [];
|
|
29
|
+
}
|
|
30
|
+
const findings = [];
|
|
31
|
+
if (rootChanged && JSON.stringify(before.patterns) !== JSON.stringify(after.patterns)) {
|
|
32
|
+
findings.push({
|
|
33
|
+
ruleId: "dependency/workspace-config-changed",
|
|
34
|
+
severity: "low",
|
|
35
|
+
title: "npm workspace configuration changed",
|
|
36
|
+
description: "The root package.json workspace patterns changed.",
|
|
37
|
+
file: rootManifestPath,
|
|
38
|
+
evidence: {
|
|
39
|
+
from: JSON.stringify(before.patterns),
|
|
40
|
+
to: JSON.stringify(after.patterns),
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
const results = await Promise.all(manifestChanges.map(async (change) => {
|
|
45
|
+
const previousPath = change.kind === "renamed" ? (change.previousPath ?? change.path) : change.path;
|
|
46
|
+
const currentPath = change.path;
|
|
47
|
+
const wasWorkspace = change.kind !== "added" &&
|
|
48
|
+
change.kind !== "copied" &&
|
|
49
|
+
isConfiguredWorkspace(previousPath, before.patterns);
|
|
50
|
+
const isWorkspace = change.kind !== "deleted" && isConfiguredWorkspace(currentPath, after.patterns);
|
|
51
|
+
if (!wasWorkspace && !isWorkspace) {
|
|
52
|
+
return [];
|
|
53
|
+
}
|
|
54
|
+
const manifestPath = isNestedManifestPath(currentPath) ? currentPath : previousPath;
|
|
55
|
+
const workspacePath = manifestPath.slice(0, -manifestSuffix.length);
|
|
56
|
+
const membershipFinding = change.kind === "renamed" && wasWorkspace !== isWorkspace
|
|
57
|
+
? [
|
|
58
|
+
{
|
|
59
|
+
ruleId: "dependency/workspace-membership-changed",
|
|
60
|
+
severity: "low",
|
|
61
|
+
title: "npm workspace membership changed",
|
|
62
|
+
description: `${previousPath} moved to ${currentPath}, changing workspace membership.`,
|
|
63
|
+
file: currentPath,
|
|
64
|
+
evidence: {
|
|
65
|
+
previousPath,
|
|
66
|
+
currentPath,
|
|
67
|
+
fromWorkspace: wasWorkspace,
|
|
68
|
+
toWorkspace: isWorkspace,
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
]
|
|
72
|
+
: [];
|
|
73
|
+
const dependencyFindings = await new PackageDependencyRule(this.snapshots, manifestPath).analyze(context);
|
|
74
|
+
return [
|
|
75
|
+
...membershipFinding,
|
|
76
|
+
...dependencyFindings.map((finding) => ({
|
|
77
|
+
...finding,
|
|
78
|
+
evidence: { ...finding.evidence, workspace: workspacePath },
|
|
79
|
+
})),
|
|
80
|
+
];
|
|
81
|
+
}));
|
|
82
|
+
return [...findings, ...results.flat()];
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
function isNestedManifestChange(change) {
|
|
86
|
+
return isNestedManifestPath(change.path) || isNestedManifestPath(change.previousPath);
|
|
87
|
+
}
|
|
88
|
+
function isNestedManifestPath(path) {
|
|
89
|
+
return path?.endsWith(manifestSuffix) === true;
|
|
90
|
+
}
|
|
91
|
+
function isConfiguredWorkspace(path, patterns) {
|
|
92
|
+
if (!isNestedManifestPath(path)) {
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
const directory = path.slice(0, -manifestSuffix.length);
|
|
96
|
+
return patterns.some((pattern) => matchesPathPattern(directory, pattern));
|
|
97
|
+
}
|
|
98
|
+
function parseWorkspaceConfig(content) {
|
|
99
|
+
if (content === undefined) {
|
|
100
|
+
return { ok: true, patterns: [] };
|
|
101
|
+
}
|
|
102
|
+
let manifest;
|
|
103
|
+
try {
|
|
104
|
+
manifest = JSON.parse(content);
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
return { ok: false, kind: "invalid", reason: "The root package.json is not valid JSON." };
|
|
108
|
+
}
|
|
109
|
+
if (!isRecord(manifest)) {
|
|
110
|
+
return { ok: false, kind: "invalid", reason: "The root package.json must be an object." };
|
|
111
|
+
}
|
|
112
|
+
if (manifest.workspaces === undefined) {
|
|
113
|
+
return { ok: true, patterns: [] };
|
|
114
|
+
}
|
|
115
|
+
if (!Array.isArray(manifest.workspaces)) {
|
|
116
|
+
return { ok: false, kind: "invalid", reason: "workspaces must be an array of paths." };
|
|
117
|
+
}
|
|
118
|
+
const patterns = [];
|
|
119
|
+
for (const rawPattern of manifest.workspaces) {
|
|
120
|
+
if (typeof rawPattern !== "string" || rawPattern.trim().length === 0) {
|
|
121
|
+
return { ok: false, kind: "invalid", reason: "Each workspace path must be a string." };
|
|
122
|
+
}
|
|
123
|
+
const pattern = rawPattern.replace(/^(\.\/)+/, "").replace(/\/+$/, "");
|
|
124
|
+
if (pattern.length === 0 || pattern.startsWith("/") || pattern.split("/").includes("..")) {
|
|
125
|
+
return { ok: false, kind: "invalid", reason: `Invalid workspace path: ${rawPattern}.` };
|
|
126
|
+
}
|
|
127
|
+
if (["!", "{", "}", "[", "]", "\\"].some((character) => pattern.includes(character))) {
|
|
128
|
+
return {
|
|
129
|
+
ok: false,
|
|
130
|
+
kind: "unsupported",
|
|
131
|
+
reason: `Unsupported workspace pattern: ${rawPattern}. Only *, **, and ? globs are supported.`,
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
patterns.push(pattern);
|
|
135
|
+
}
|
|
136
|
+
return { ok: true, patterns };
|
|
137
|
+
}
|
|
138
|
+
function configFinding(side, result) {
|
|
139
|
+
return {
|
|
140
|
+
ruleId: result.kind === "invalid"
|
|
141
|
+
? "dependency/invalid-workspace-config"
|
|
142
|
+
: "dependency/unsupported-workspace-pattern",
|
|
143
|
+
severity: result.kind === "invalid" ? "high" : "low",
|
|
144
|
+
title: result.kind === "invalid"
|
|
145
|
+
? "Invalid npm workspace configuration"
|
|
146
|
+
: "Unsupported npm workspace pattern",
|
|
147
|
+
description: `Could not analyze the ${side} npm workspaces: ${result.reason}`,
|
|
148
|
+
file: rootManifestPath,
|
|
149
|
+
evidence: { side, reason: result.reason },
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
function isRecord(value) {
|
|
153
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
154
|
+
}
|
|
155
|
+
//# 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;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;
|
|
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;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,26 @@
|
|
|
1
|
-
const
|
|
1
|
+
const rootManifestPath = "package.json";
|
|
2
2
|
const dependencySections = ["dependencies", "devDependencies"];
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* 한 package.json의 직접 dependency 선언 변경을 판단한다.
|
|
5
|
+
* 루트와 workspace 규칙이 같은 판단 기준을 사용하도록 경로를 주입받는다.
|
|
6
6
|
*/
|
|
7
7
|
export class PackageDependencyRule {
|
|
8
8
|
snapshots;
|
|
9
|
-
|
|
9
|
+
manifestPath;
|
|
10
|
+
constructor(snapshots, manifestPath = rootManifestPath) {
|
|
10
11
|
this.snapshots = snapshots;
|
|
12
|
+
this.manifestPath = manifestPath;
|
|
11
13
|
}
|
|
12
14
|
async analyze(context) {
|
|
13
|
-
|
|
15
|
+
const change = context.changes.files.find((item) => item.path === this.manifestPath || item.previousPath === this.manifestPath);
|
|
16
|
+
if (change === undefined) {
|
|
14
17
|
return [];
|
|
15
18
|
}
|
|
16
|
-
const snapshot = await this.snapshots.read(context.target, manifestPath)
|
|
17
|
-
|
|
18
|
-
|
|
19
|
+
const snapshot = await this.snapshots.read(context.target, this.manifestPath, change.kind === "renamed" && isPackageManifestPath(change.previousPath)
|
|
20
|
+
? change.previousPath
|
|
21
|
+
: undefined);
|
|
22
|
+
const before = parseManifest(snapshot.before, "base", this.manifestPath);
|
|
23
|
+
const after = parseManifest(snapshot.after, "current", this.manifestPath);
|
|
19
24
|
if (!before.ok && !after.ok) {
|
|
20
25
|
return [before.finding, after.finding];
|
|
21
26
|
}
|
|
@@ -25,13 +30,13 @@ export class PackageDependencyRule {
|
|
|
25
30
|
if (!after.ok) {
|
|
26
31
|
return [after.finding];
|
|
27
32
|
}
|
|
28
|
-
return compareDependencies(before.dependencies, after.dependencies);
|
|
33
|
+
return compareDependencies(before.dependencies, after.dependencies, this.manifestPath);
|
|
29
34
|
}
|
|
30
35
|
}
|
|
31
|
-
function
|
|
32
|
-
return
|
|
36
|
+
function isPackageManifestPath(path) {
|
|
37
|
+
return path === rootManifestPath || path?.endsWith("/package.json") === true;
|
|
33
38
|
}
|
|
34
|
-
function parseManifest(content, side) {
|
|
39
|
+
function parseManifest(content, side, manifestPath) {
|
|
35
40
|
if (content === undefined) {
|
|
36
41
|
return { ok: true, dependencies: new Map() };
|
|
37
42
|
}
|
|
@@ -40,10 +45,10 @@ function parseManifest(content, side) {
|
|
|
40
45
|
value = JSON.parse(content);
|
|
41
46
|
}
|
|
42
47
|
catch {
|
|
43
|
-
return invalidManifest(side, "The file is not valid JSON.");
|
|
48
|
+
return invalidManifest(side, "The file is not valid JSON.", manifestPath);
|
|
44
49
|
}
|
|
45
50
|
if (!isRecord(value)) {
|
|
46
|
-
return invalidManifest(side, "The root value must be a JSON object.");
|
|
51
|
+
return invalidManifest(side, "The root value must be a JSON object.", manifestPath);
|
|
47
52
|
}
|
|
48
53
|
const dependencies = new Map();
|
|
49
54
|
for (const section of dependencySections) {
|
|
@@ -52,48 +57,48 @@ function parseManifest(content, side) {
|
|
|
52
57
|
continue;
|
|
53
58
|
}
|
|
54
59
|
if (!isRecord(entries)) {
|
|
55
|
-
return invalidManifest(side, `${section} must be a JSON object
|
|
60
|
+
return invalidManifest(side, `${section} must be a JSON object.`, manifestPath);
|
|
56
61
|
}
|
|
57
62
|
for (const [name, version] of Object.entries(entries)) {
|
|
58
63
|
if (typeof version !== "string") {
|
|
59
|
-
return invalidManifest(side, `${section}.${name} must have a string version
|
|
64
|
+
return invalidManifest(side, `${section}.${name} must have a string version.`, manifestPath);
|
|
60
65
|
}
|
|
61
66
|
if (dependencies.has(name)) {
|
|
62
|
-
return invalidManifest(side, `${name} is declared in more than one dependency section
|
|
67
|
+
return invalidManifest(side, `${name} is declared in more than one dependency section.`, manifestPath);
|
|
63
68
|
}
|
|
64
69
|
dependencies.set(name, { section, version });
|
|
65
70
|
}
|
|
66
71
|
}
|
|
67
72
|
return { ok: true, dependencies };
|
|
68
73
|
}
|
|
69
|
-
function compareDependencies(before, after) {
|
|
74
|
+
function compareDependencies(before, after, manifestPath) {
|
|
70
75
|
const names = [...new Set([...before.keys(), ...after.keys()])].sort((left, right) => left.localeCompare(right));
|
|
71
76
|
const findings = [];
|
|
72
77
|
for (const name of names) {
|
|
73
78
|
const previous = before.get(name);
|
|
74
79
|
const current = after.get(name);
|
|
75
80
|
if (previous === undefined && current !== undefined) {
|
|
76
|
-
findings.push(addedDependency(name, current));
|
|
81
|
+
findings.push(addedDependency(name, current, manifestPath));
|
|
77
82
|
continue;
|
|
78
83
|
}
|
|
79
84
|
if (previous !== undefined && current === undefined) {
|
|
80
|
-
findings.push(removedDependency(name, previous));
|
|
85
|
+
findings.push(removedDependency(name, previous, manifestPath));
|
|
81
86
|
continue;
|
|
82
87
|
}
|
|
83
88
|
if (previous === undefined || current === undefined) {
|
|
84
89
|
continue;
|
|
85
90
|
}
|
|
86
91
|
if (previous.section !== current.section) {
|
|
87
|
-
findings.push(movedDependency(name, previous, current));
|
|
92
|
+
findings.push(movedDependency(name, previous, current, manifestPath));
|
|
88
93
|
continue;
|
|
89
94
|
}
|
|
90
95
|
if (previous.version !== current.version) {
|
|
91
|
-
findings.push(changedDependency(name, previous, current));
|
|
96
|
+
findings.push(changedDependency(name, previous, current, manifestPath));
|
|
92
97
|
}
|
|
93
98
|
}
|
|
94
99
|
return findings;
|
|
95
100
|
}
|
|
96
|
-
function addedDependency(name, declaration) {
|
|
101
|
+
function addedDependency(name, declaration, manifestPath) {
|
|
97
102
|
const production = declaration.section === "dependencies";
|
|
98
103
|
return {
|
|
99
104
|
ruleId: production ? "dependency/new-production" : "dependency/new-development",
|
|
@@ -108,7 +113,7 @@ function addedDependency(name, declaration) {
|
|
|
108
113
|
},
|
|
109
114
|
};
|
|
110
115
|
}
|
|
111
|
-
function removedDependency(name, declaration) {
|
|
116
|
+
function removedDependency(name, declaration, manifestPath) {
|
|
112
117
|
return {
|
|
113
118
|
ruleId: "dependency/removed",
|
|
114
119
|
severity: "low",
|
|
@@ -122,7 +127,7 @@ function removedDependency(name, declaration) {
|
|
|
122
127
|
},
|
|
123
128
|
};
|
|
124
129
|
}
|
|
125
|
-
function movedDependency(name, previous, current) {
|
|
130
|
+
function movedDependency(name, previous, current, manifestPath) {
|
|
126
131
|
return {
|
|
127
132
|
ruleId: "dependency/section-changed",
|
|
128
133
|
severity: current.section === "dependencies" ? "medium" : "low",
|
|
@@ -137,7 +142,7 @@ function movedDependency(name, previous, current) {
|
|
|
137
142
|
},
|
|
138
143
|
};
|
|
139
144
|
}
|
|
140
|
-
function changedDependency(name, previous, current) {
|
|
145
|
+
function changedDependency(name, previous, current, manifestPath) {
|
|
141
146
|
return {
|
|
142
147
|
ruleId: "dependency/version-changed",
|
|
143
148
|
severity: severityFor(current.section),
|
|
@@ -152,14 +157,14 @@ function changedDependency(name, previous, current) {
|
|
|
152
157
|
},
|
|
153
158
|
};
|
|
154
159
|
}
|
|
155
|
-
function invalidManifest(side, reason) {
|
|
160
|
+
function invalidManifest(side, reason, manifestPath) {
|
|
156
161
|
return {
|
|
157
162
|
ok: false,
|
|
158
163
|
finding: {
|
|
159
164
|
ruleId: "dependency/invalid-manifest",
|
|
160
165
|
severity: "high",
|
|
161
166
|
title: "Invalid package manifest",
|
|
162
|
-
description: `Could not analyze the ${side}
|
|
167
|
+
description: `Could not analyze the ${side} ${manifestPath}: ${reason}`,
|
|
163
168
|
file: manifestPath,
|
|
164
169
|
evidence: { side, reason },
|
|
165
170
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"package-dependency-rule.js","sourceRoot":"","sources":["../../../src/application/rules/package-dependency-rule.ts"],"names":[],"mappings":"AAIA,MAAM,
|
|
1
|
+
{"version":3,"file":"package-dependency-rule.js","sourceRoot":"","sources":["../../../src/application/rules/package-dependency-rule.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import { type ImpactAnalysis } from "../../domain/impact.js";
|
|
2
2
|
import type { AnalysisContext } from "../ports/analysis-rule.js";
|
|
3
3
|
import type { ChangeImpactAnalyzer } from "../ports/change-impact-analyzer.js";
|
|
4
|
+
import type { ModuleAliasResolver } from "../ports/module-alias-resolver.js";
|
|
4
5
|
import type { ModuleReferenceExtractor } from "../ports/module-reference-extractor.js";
|
|
5
6
|
import type { ProjectFileSource } from "../ports/project-file-source.js";
|
|
6
7
|
/** 현재 module graph를 역방향으로 탐색해 변경 파일의 직접·간접 의존자를 찾는다. */
|
|
7
8
|
export declare class AnalyzeImportImpact implements ChangeImpactAnalyzer {
|
|
8
9
|
private readonly files;
|
|
9
10
|
private readonly extractors;
|
|
10
|
-
|
|
11
|
+
private readonly aliases;
|
|
12
|
+
constructor(files: ProjectFileSource, extractors: readonly ModuleReferenceExtractor[], aliases: ModuleAliasResolver);
|
|
11
13
|
analyze(context: AnalysisContext): Promise<ImpactAnalysis>;
|
|
12
14
|
private extractorFor;
|
|
13
15
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analyze-import-impact.d.ts","sourceRoot":"","sources":["../../../src/application/services/analyze-import-impact.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,KAAK,cAAc,EAKpB,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AACjE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,oCAAoC,CAAC;AAC/E,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,wCAAwC,CAAC;AACvF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AAKzE,wDAAwD;AACxD,qBAAa,mBAAoB,YAAW,oBAAoB;IAE5D,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,UAAU;
|
|
1
|
+
{"version":3,"file":"analyze-import-impact.d.ts","sourceRoot":"","sources":["../../../src/application/services/analyze-import-impact.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,KAAK,cAAc,EAKpB,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AACjE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,oCAAoC,CAAC;AAC/E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AAC7E,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,wCAAwC,CAAC;AACvF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AAKzE,wDAAwD;AACxD,qBAAa,mBAAoB,YAAW,oBAAoB;IAE5D,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAFP,KAAK,EAAE,iBAAiB,EACxB,UAAU,EAAE,SAAS,wBAAwB,EAAE,EAC/C,OAAO,EAAE,mBAAmB;IAGlC,OAAO,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,cAAc,CAAC;IA4DvE,OAAO,CAAC,YAAY;CAGrB"}
|