@mf-toolkit/shared-inspector 0.1.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 (70) hide show
  1. package/README.md +254 -0
  2. package/dist/analyzer/analyze-project.d.ts +9 -0
  3. package/dist/analyzer/analyze-project.d.ts.map +1 -0
  4. package/dist/analyzer/analyze-project.js +38 -0
  5. package/dist/analyzer/analyze-project.js.map +1 -0
  6. package/dist/analyzer/detect-issues.d.ts +33 -0
  7. package/dist/analyzer/detect-issues.d.ts.map +1 -0
  8. package/dist/analyzer/detect-issues.js +69 -0
  9. package/dist/analyzer/detect-issues.js.map +1 -0
  10. package/dist/analyzer/policy.d.ts +27 -0
  11. package/dist/analyzer/policy.d.ts.map +1 -0
  12. package/dist/analyzer/policy.js +84 -0
  13. package/dist/analyzer/policy.js.map +1 -0
  14. package/dist/collector/build-project-manifest.d.ts +10 -0
  15. package/dist/collector/build-project-manifest.d.ts.map +1 -0
  16. package/dist/collector/build-project-manifest.js +82 -0
  17. package/dist/collector/build-project-manifest.js.map +1 -0
  18. package/dist/collector/collect-imports.d.ts +17 -0
  19. package/dist/collector/collect-imports.d.ts.map +1 -0
  20. package/dist/collector/collect-imports.js +87 -0
  21. package/dist/collector/collect-imports.js.map +1 -0
  22. package/dist/collector/parse-declarations.d.ts +26 -0
  23. package/dist/collector/parse-declarations.d.ts.map +1 -0
  24. package/dist/collector/parse-declarations.js +134 -0
  25. package/dist/collector/parse-declarations.js.map +1 -0
  26. package/dist/collector/parse-shared-config.d.ts +12 -0
  27. package/dist/collector/parse-shared-config.d.ts.map +1 -0
  28. package/dist/collector/parse-shared-config.js +56 -0
  29. package/dist/collector/parse-shared-config.js.map +1 -0
  30. package/dist/collector/resolve-tsconfig-paths.d.ts +39 -0
  31. package/dist/collector/resolve-tsconfig-paths.d.ts.map +1 -0
  32. package/dist/collector/resolve-tsconfig-paths.js +89 -0
  33. package/dist/collector/resolve-tsconfig-paths.js.map +1 -0
  34. package/dist/collector/resolve-versions.d.ts +15 -0
  35. package/dist/collector/resolve-versions.d.ts.map +1 -0
  36. package/dist/collector/resolve-versions.js +49 -0
  37. package/dist/collector/resolve-versions.js.map +1 -0
  38. package/dist/collector/traverse-local-modules.d.ts +27 -0
  39. package/dist/collector/traverse-local-modules.d.ts.map +1 -0
  40. package/dist/collector/traverse-local-modules.js +119 -0
  41. package/dist/collector/traverse-local-modules.js.map +1 -0
  42. package/dist/index.d.ts +7 -0
  43. package/dist/index.d.ts.map +1 -0
  44. package/dist/index.js +9 -0
  45. package/dist/index.js.map +1 -0
  46. package/dist/inspect.d.ts +12 -0
  47. package/dist/inspect.d.ts.map +1 -0
  48. package/dist/inspect.js +15 -0
  49. package/dist/inspect.js.map +1 -0
  50. package/dist/plugins/webpack.d.ts +40 -0
  51. package/dist/plugins/webpack.d.ts.map +1 -0
  52. package/dist/plugins/webpack.js +95 -0
  53. package/dist/plugins/webpack.js.map +1 -0
  54. package/dist/reporter/format-report.d.ts +18 -0
  55. package/dist/reporter/format-report.d.ts.map +1 -0
  56. package/dist/reporter/format-report.js +87 -0
  57. package/dist/reporter/format-report.js.map +1 -0
  58. package/dist/reporter/write-report.d.ts +12 -0
  59. package/dist/reporter/write-report.d.ts.map +1 -0
  60. package/dist/reporter/write-report.js +19 -0
  61. package/dist/reporter/write-report.js.map +1 -0
  62. package/dist/types.d.ts +179 -0
  63. package/dist/types.d.ts.map +1 -0
  64. package/dist/types.js +3 -0
  65. package/dist/types.js.map +1 -0
  66. package/dist/webpack.d.ts +3 -0
  67. package/dist/webpack.d.ts.map +1 -0
  68. package/dist/webpack.js +2 -0
  69. package/dist/webpack.js.map +1 -0
  70. package/package.json +55 -0
@@ -0,0 +1,119 @@
1
+ import { readFile } from 'node:fs/promises';
2
+ import { resolve, dirname, join } from 'node:path';
3
+ import { scanFiles } from './collect-imports.js';
4
+ import { parseDeclarations, isRelativeSpecifier, isNodeBuiltin, normalizePackageName, } from './parse-declarations.js';
5
+ import { loadTsConfigPaths, resolveAliasedSpecifier, } from './resolve-tsconfig-paths.js';
6
+ const DEFAULT_EXTENSIONS = ['.ts', '.tsx', '.js', '.jsx'];
7
+ /**
8
+ * Local-graph mode collector.
9
+ *
10
+ * Scans all files in sourceDirs and follows relative import/export chains
11
+ * recursively within those directories. Finds external packages reachable
12
+ * through barrel re-exports and local module wrappers.
13
+ *
14
+ * When tsconfigPath is provided, TypeScript path aliases (e.g. '@app/*') are
15
+ * resolved to local files and followed in the same DFS — packages behind
16
+ * aliases become visible.
17
+ *
18
+ * Uses two-phase approach:
19
+ * Phase 1 — parallel async reads of all source files into contentMap
20
+ * Phase 2 — synchronous DFS over in-memory content (zero disk I/O)
21
+ */
22
+ export async function traverseLocalModules(options) {
23
+ const extensions = options.extensions ?? DEFAULT_EXTENSIONS;
24
+ const files = await scanFiles(options.sourceDirs, extensions);
25
+ // Phase 1: pre-read all files in parallel — turns F sequential disk reads
26
+ // into a single concurrent batch, giving 3-8× speedup on large projects.
27
+ const contentMap = new Map();
28
+ await Promise.all(files.map(async (filePath) => {
29
+ try {
30
+ contentMap.set(filePath, await readFile(filePath, 'utf-8'));
31
+ }
32
+ catch {
33
+ // Unreadable files are skipped silently during DFS
34
+ }
35
+ }));
36
+ // Load tsconfig path aliases once, before DFS
37
+ const tsConfigPaths = options.tsconfigPath
38
+ ? loadTsConfigPaths(options.tsconfigPath)
39
+ : null;
40
+ const visited = new Set();
41
+ /** package → { files observed in, via: direct | reexport } */
42
+ const pkgMap = new Map();
43
+ // Phase 2: DFS over in-memory content — no disk I/O during traversal.
44
+ function visit(filePath) {
45
+ if (visited.has(filePath))
46
+ return;
47
+ visited.add(filePath);
48
+ const content = contentMap.get(filePath);
49
+ if (content === undefined)
50
+ return;
51
+ for (const decl of parseDeclarations(content)) {
52
+ // ── Relative import → follow locally ──────────────────────────────────
53
+ if (isRelativeSpecifier(decl.specifier)) {
54
+ const resolved = resolveLocalFile(decl.specifier, filePath, contentMap);
55
+ if (resolved)
56
+ visit(resolved);
57
+ continue;
58
+ }
59
+ if (isNodeBuiltin(decl.specifier))
60
+ continue;
61
+ // ── TypeScript path alias → resolve and follow locally ────────────────
62
+ if (tsConfigPaths) {
63
+ const aliased = resolveAliasedSpecifier(decl.specifier, tsConfigPaths, contentMap);
64
+ if (aliased) {
65
+ visit(aliased);
66
+ continue;
67
+ }
68
+ }
69
+ // ── External package ──────────────────────────────────────────────────
70
+ const pkg = normalizePackageName(decl.specifier);
71
+ if (options.ignore?.some((p) => matchesIgnorePattern(pkg, p)))
72
+ continue;
73
+ if (options.workspacePackages?.some((p) => matchesIgnorePattern(pkg, p)))
74
+ continue;
75
+ const via = decl.kind === 'reexport' ? 'reexport' : 'direct';
76
+ const existing = pkgMap.get(pkg);
77
+ if (!existing) {
78
+ pkgMap.set(pkg, { files: new Set([filePath]), via });
79
+ }
80
+ else {
81
+ existing.files.add(filePath);
82
+ // Direct import takes precedence: once seen as direct, stays direct
83
+ if (via === 'direct')
84
+ existing.via = 'direct';
85
+ }
86
+ }
87
+ }
88
+ for (const file of files) {
89
+ visit(file);
90
+ }
91
+ // One PackageOccurrence per (package, file) pair — consistent with collectImports
92
+ return Array.from(pkgMap.entries()).flatMap(([pkg, { files: fileSet, via }]) => [...fileSet].map((file) => ({ package: pkg, file, via })));
93
+ }
94
+ // ─── Local file resolver ──────────────────────────────────────────────────────
95
+ /**
96
+ * Resolves a relative specifier to an absolute file path.
97
+ * Uses the pre-built contentMap (Map lookup) instead of existsSync —
98
+ * zero disk I/O during DFS traversal.
99
+ */
100
+ function resolveLocalFile(specifier, fromFile, contentMap) {
101
+ const base = resolve(dirname(fromFile), specifier);
102
+ for (const ext of ['.ts', '.tsx', '.js', '.jsx']) {
103
+ const candidate = base + ext;
104
+ if (contentMap.has(candidate))
105
+ return candidate;
106
+ }
107
+ for (const ext of ['.ts', '.tsx', '.js', '.jsx']) {
108
+ const candidate = join(base, 'index' + ext);
109
+ if (contentMap.has(candidate))
110
+ return candidate;
111
+ }
112
+ return null;
113
+ }
114
+ function matchesIgnorePattern(pkg, pattern) {
115
+ if (pattern.endsWith('/*'))
116
+ return pkg.startsWith(pattern.slice(0, -2) + '/');
117
+ return pkg === pattern;
118
+ }
119
+ //# sourceMappingURL=traverse-local-modules.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"traverse-local-modules.js","sourceRoot":"","sources":["../../src/collector/traverse-local-modules.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ export { buildProjectManifest } from './collector/build-project-manifest.js';
2
+ export { analyzeProject } from './analyzer/analyze-project.js';
3
+ export { inspect } from './inspect.js';
4
+ export { formatReport } from './reporter/format-report.js';
5
+ export { writeReport, writeManifest } from './reporter/write-report.js';
6
+ export type { ProjectManifest, ProjectReport, CollectorOptions, AnalysisOptions, SharedDepConfig, PackageOccurrence, UnusedEntry, CandidateEntry, MismatchedEntry, SingletonRiskEntry, } from './types.js';
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,uCAAuC,CAAC;AAC7E,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAG/D,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAGvC,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAGxE,YAAY,EACV,eAAe,EACf,aAAa,EACb,gBAAgB,EAChB,eAAe,EACf,eAAe,EACf,iBAAiB,EACjB,WAAW,EACX,cAAc,EACd,eAAe,EACf,kBAAkB,GACnB,MAAM,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,9 @@
1
+ // ─── Two-phase API ────────────────────────────────────────────────────────────
2
+ export { buildProjectManifest } from './collector/build-project-manifest.js';
3
+ export { analyzeProject } from './analyzer/analyze-project.js';
4
+ // ─── Shortcut API ─────────────────────────────────────────────────────────────
5
+ export { inspect } from './inspect.js';
6
+ // ─── Reporter ─────────────────────────────────────────────────────────────────
7
+ export { formatReport } from './reporter/format-report.js';
8
+ export { writeReport, writeManifest } from './reporter/write-report.js';
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,iFAAiF;AACjF,OAAO,EAAE,oBAAoB,EAAE,MAAM,uCAAuC,CAAC;AAC7E,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAE/D,iFAAiF;AACjF,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,iFAAiF;AACjF,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type { CollectorOptions, AnalysisOptions, ProjectReport } from './types.js';
2
+ /**
3
+ * Shortcut API — combines buildProjectManifest() + analyzeProject() in one call.
4
+ *
5
+ * Use this when you only need the report and don't need the intermediate manifest.
6
+ * For CI pipelines or multi-project federation analysis, use the two-phase API
7
+ * directly so you can persist and share the manifest.
8
+ */
9
+ export declare function inspect(options: CollectorOptions & {
10
+ analysis?: AnalysisOptions;
11
+ }): Promise<ProjectReport>;
12
+ //# sourceMappingURL=inspect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inspect.d.ts","sourceRoot":"","sources":["../src/inspect.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAInF;;;;;;GAMG;AACH,wBAAsB,OAAO,CAC3B,OAAO,EAAE,gBAAgB,GAAG;IAAE,QAAQ,CAAC,EAAE,eAAe,CAAA;CAAE,GACzD,OAAO,CAAC,aAAa,CAAC,CAIxB"}
@@ -0,0 +1,15 @@
1
+ import { buildProjectManifest } from './collector/build-project-manifest.js';
2
+ import { analyzeProject } from './analyzer/analyze-project.js';
3
+ /**
4
+ * Shortcut API — combines buildProjectManifest() + analyzeProject() in one call.
5
+ *
6
+ * Use this when you only need the report and don't need the intermediate manifest.
7
+ * For CI pipelines or multi-project federation analysis, use the two-phase API
8
+ * directly so you can persist and share the manifest.
9
+ */
10
+ export async function inspect(options) {
11
+ const { analysis, ...collectorOptions } = options;
12
+ const manifest = await buildProjectManifest(collectorOptions);
13
+ return analyzeProject(manifest, analysis);
14
+ }
15
+ //# sourceMappingURL=inspect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inspect.js","sourceRoot":"","sources":["../src/inspect.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,uCAAuC,CAAC;AAC7E,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAE/D;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO,CAC3B,OAA0D;IAE1D,MAAM,EAAE,QAAQ,EAAE,GAAG,gBAAgB,EAAE,GAAG,OAAO,CAAC;IAClD,MAAM,QAAQ,GAAG,MAAM,oBAAoB,CAAC,gBAAgB,CAAC,CAAC;IAC9D,OAAO,cAAc,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;AAC5C,CAAC"}
@@ -0,0 +1,40 @@
1
+ import type { WebpackPluginOptions } from '../types.js';
2
+ interface WebpackCompilation {
3
+ errors: Error[];
4
+ warnings: Error[];
5
+ }
6
+ interface WebpackCompiler {
7
+ context: string;
8
+ options: {
9
+ name?: string;
10
+ };
11
+ hooks: {
12
+ afterCompile: {
13
+ tapPromise(name: string, fn: (compilation: WebpackCompilation) => Promise<void>): void;
14
+ };
15
+ };
16
+ }
17
+ /**
18
+ * Webpack plugin that analyses Module Federation shared dependencies after
19
+ * each compilation and reports issues to the console and/or build output.
20
+ *
21
+ * In v0.1, `sharedConfig` must be provided explicitly. Auto-extraction from
22
+ * ModuleFederationPlugin is planned for v0.1.1.
23
+ *
24
+ * @example
25
+ * ```js
26
+ * new MfSharedInspectorPlugin({
27
+ * sourceDirs: ['./src'],
28
+ * sharedConfig: { react: { singleton: true }, mobx: { singleton: true } },
29
+ * warn: true,
30
+ * writeManifest: true,
31
+ * })
32
+ * ```
33
+ */
34
+ export declare class MfSharedInspectorPlugin {
35
+ private options;
36
+ constructor(options: WebpackPluginOptions);
37
+ apply(compiler: WebpackCompiler): void;
38
+ }
39
+ export {};
40
+ //# sourceMappingURL=webpack.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webpack.d.ts","sourceRoot":"","sources":["../../src/plugins/webpack.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AASxD,UAAU,kBAAkB;IAC1B,MAAM,EAAE,KAAK,EAAE,CAAC;IAChB,QAAQ,EAAE,KAAK,EAAE,CAAC;CACnB;AAED,UAAU,eAAe;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE;QACP,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,CAAC;IACF,KAAK,EAAE;QACL,YAAY,EAAE;YACZ,UAAU,CACR,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,CAAC,WAAW,EAAE,kBAAkB,KAAK,OAAO,CAAC,IAAI,CAAC,GACrD,IAAI,CAAC;SACT,CAAC;KACH,CAAC;CACH;AAMD;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,uBAAuB;IAClC,OAAO,CAAC,OAAO,CAAuB;gBAE1B,OAAO,EAAE,oBAAoB;IAIzC,KAAK,CAAC,QAAQ,EAAE,eAAe,GAAG,IAAI;CAyFvC"}
@@ -0,0 +1,95 @@
1
+ import { isAbsolute, join, basename } from 'node:path';
2
+ import { buildProjectManifest } from '../collector/build-project-manifest.js';
3
+ import { analyzeProject } from '../analyzer/analyze-project.js';
4
+ import { formatReport } from '../reporter/format-report.js';
5
+ import { writeManifest } from '../reporter/write-report.js';
6
+ // ─────────────────────────────────────────────────────────────────────────────
7
+ const PLUGIN_NAME = 'MfSharedInspectorPlugin';
8
+ /**
9
+ * Webpack plugin that analyses Module Federation shared dependencies after
10
+ * each compilation and reports issues to the console and/or build output.
11
+ *
12
+ * In v0.1, `sharedConfig` must be provided explicitly. Auto-extraction from
13
+ * ModuleFederationPlugin is planned for v0.1.1.
14
+ *
15
+ * @example
16
+ * ```js
17
+ * new MfSharedInspectorPlugin({
18
+ * sourceDirs: ['./src'],
19
+ * sharedConfig: { react: { singleton: true }, mobx: { singleton: true } },
20
+ * warn: true,
21
+ * writeManifest: true,
22
+ * })
23
+ * ```
24
+ */
25
+ export class MfSharedInspectorPlugin {
26
+ options;
27
+ constructor(options) {
28
+ this.options = options;
29
+ }
30
+ apply(compiler) {
31
+ compiler.hooks.afterCompile.tapPromise(PLUGIN_NAME, async (compilation) => {
32
+ const { sourceDirs, depth = 'local-graph', sharedConfig, kind, packageJsonPath, extensions, ignore, parser, analysis, warn = true, failOn, writeManifest: shouldWriteManifest = false, outputDir = '.', } = this.options;
33
+ // Resolve name from webpack compiler, fallback to context dir name
34
+ const name = compiler.options.name ?? basename(compiler.context);
35
+ // Resolve paths relative to compiler.context when not absolute
36
+ const resolvedPkgJson = packageJsonPath
37
+ ? (isAbsolute(packageJsonPath) ? packageJsonPath : join(compiler.context, packageJsonPath))
38
+ : join(compiler.context, 'package.json');
39
+ const resolvedSourceDirs = sourceDirs.map((dir) => isAbsolute(dir) ? dir : join(compiler.context, dir));
40
+ const resolvedOutputDir = isAbsolute(outputDir)
41
+ ? outputDir
42
+ : join(compiler.context, outputDir);
43
+ try {
44
+ const manifest = await buildProjectManifest({
45
+ name,
46
+ sourceDirs: resolvedSourceDirs,
47
+ depth,
48
+ sharedConfig,
49
+ kind,
50
+ packageJsonPath: resolvedPkgJson,
51
+ extensions,
52
+ ignore,
53
+ parser,
54
+ });
55
+ const report = analyzeProject(manifest, analysis);
56
+ const hasFindings = report.mismatched.length > 0 ||
57
+ report.unused.length > 0 ||
58
+ report.candidates.length > 0 ||
59
+ report.singletonRisks.length > 0;
60
+ if (warn && hasFindings) {
61
+ console.warn(formatReport(report, {
62
+ name: manifest.project.name,
63
+ depth: manifest.source.depth,
64
+ filesScanned: manifest.source.filesScanned,
65
+ }));
66
+ }
67
+ if (shouldWriteManifest) {
68
+ await writeManifest(manifest, join(resolvedOutputDir, 'project-manifest.json'));
69
+ }
70
+ if (failOn && shouldFailBuild(failOn, report)) {
71
+ const msg = `[${PLUGIN_NAME}] Build failed (failOn: "${failOn}"): ` +
72
+ `${report.mismatched.length} mismatch, ${report.unused.length} unused, ` +
73
+ `${report.candidates.length} candidates, ${report.singletonRisks.length} singleton risks.`;
74
+ compilation.errors.push(new Error(msg));
75
+ }
76
+ }
77
+ catch (err) {
78
+ // Analysis errors are non-fatal — warn but don't break the build
79
+ compilation.warnings.push(new Error(`[${PLUGIN_NAME}] Analysis failed: ${err instanceof Error ? err.message : String(err)}`));
80
+ }
81
+ });
82
+ }
83
+ }
84
+ // ─── Helpers ──────────────────────────────────────────────────────────────────
85
+ function shouldFailBuild(failOn, report) {
86
+ switch (failOn) {
87
+ case 'mismatch': return report.mismatched.length > 0;
88
+ case 'unused': return report.unused.length > 0;
89
+ case 'any': return (report.mismatched.length > 0 ||
90
+ report.unused.length > 0 ||
91
+ report.candidates.length > 0 ||
92
+ report.singletonRisks.length > 0);
93
+ }
94
+ }
95
+ //# sourceMappingURL=webpack.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webpack.js","sourceRoot":"","sources":["../../src/plugins/webpack.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import type { ProjectReport } from '../types.js';
2
+ export interface FormatReportContext {
3
+ name?: string;
4
+ depth?: 'direct' | 'local-graph';
5
+ filesScanned?: number;
6
+ }
7
+ /**
8
+ * Formats a ProjectReport as a human-readable terminal string.
9
+ *
10
+ * Section order (by severity / determinism):
11
+ * 1. Version mismatch — deterministic, most dangerous
12
+ * 2. Unused shared — deterministic, easy wins
13
+ * 3. Candidates — heuristic, actionable suggestions
14
+ * 4. Singleton risks — heuristic, potential runtime issues
15
+ * 5. Summary line
16
+ */
17
+ export declare function formatReport(report: ProjectReport, ctx?: FormatReportContext): string;
18
+ //# sourceMappingURL=format-report.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format-report.d.ts","sourceRoot":"","sources":["../../src/reporter/format-report.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD,MAAM,WAAW,mBAAmB;IAClC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,QAAQ,GAAG,aAAa,CAAC;IACjC,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,aAAa,EAAE,GAAG,CAAC,EAAE,mBAAmB,GAAG,MAAM,CA6ErF"}
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Formats a ProjectReport as a human-readable terminal string.
3
+ *
4
+ * Section order (by severity / determinism):
5
+ * 1. Version mismatch — deterministic, most dangerous
6
+ * 2. Unused shared — deterministic, easy wins
7
+ * 3. Candidates — heuristic, actionable suggestions
8
+ * 4. Singleton risks — heuristic, potential runtime issues
9
+ * 5. Summary line
10
+ */
11
+ export function formatReport(report, ctx) {
12
+ const lines = [];
13
+ const { unused, candidates, mismatched, singletonRisks, eagerRisks, summary } = report;
14
+ // Header
15
+ const header = buildHeader(ctx);
16
+ lines.push('', header, '');
17
+ const hasFindings = mismatched.length > 0 ||
18
+ unused.length > 0 ||
19
+ candidates.length > 0 ||
20
+ singletonRisks.length > 0 ||
21
+ eagerRisks.length > 0;
22
+ if (!hasFindings) {
23
+ lines.push(' No issues found. Shared config looks good.');
24
+ }
25
+ // ── 1. Version mismatch ────────────────────────────────────────────────────
26
+ if (mismatched.length > 0) {
27
+ lines.push(' Version mismatch (sharing silently broken):');
28
+ for (const m of mismatched) {
29
+ lines.push(` ⚠ ${m.package} — requires ${m.configured}, installed ${m.installed}`);
30
+ }
31
+ lines.push('');
32
+ }
33
+ // ── 2. Unused shared ──────────────────────────────────────────────────────
34
+ if (unused.length > 0) {
35
+ lines.push(' Unused shared (safe to remove):');
36
+ for (const u of unused) {
37
+ const note = u.singleton ? 'shared as singleton' : 'shared without singleton';
38
+ lines.push(` ✗ ${u.package} — 0 imports, ${note}`);
39
+ }
40
+ lines.push('');
41
+ }
42
+ // ── 3. Candidates ─────────────────────────────────────────────────────────
43
+ if (candidates.length > 0) {
44
+ lines.push(' Candidates (consider adding to shared):');
45
+ for (const c of candidates) {
46
+ const fileCount = c.files.length;
47
+ const filesLabel = fileCount === 1 ? '1 file' : `${fileCount} files`;
48
+ const viaLabel = c.via === 'reexport' ? `, via re-export in ${c.files[0]}` : '';
49
+ lines.push(` → ${c.package} (${c.importCount} imports in ${filesLabel}${viaLabel})`);
50
+ }
51
+ lines.push('');
52
+ }
53
+ // ── 4. Singleton risks ────────────────────────────────────────────────────
54
+ if (singletonRisks.length > 0) {
55
+ lines.push(' Singleton risks (add singleton: true):');
56
+ for (const r of singletonRisks) {
57
+ lines.push(` ⚠ ${r.package} — manages global state, singleton: true recommended`);
58
+ }
59
+ lines.push('');
60
+ }
61
+ // ── 5. Eager risks ────────────────────────────────────────────────────────
62
+ if (eagerRisks.length > 0) {
63
+ lines.push(' Eager risks (add singleton: true or remove eager: true):');
64
+ for (const r of eagerRisks) {
65
+ lines.push(` ⚠ ${r.package} — eager: true without singleton: true, risk of duplicate instances`);
66
+ }
67
+ lines.push('');
68
+ }
69
+ // ── 6. Summary ────────────────────────────────────────────────────────────
70
+ lines.push(` Total: ${summary.totalShared} shared, ${summary.usedShared} used, ` +
71
+ `${summary.unusedCount} unused, ${summary.candidatesCount} candidates, ` +
72
+ `${summary.mismatchedCount} mismatch, ${summary.eagerRisksCount} eager risks`);
73
+ lines.push('');
74
+ return lines.join('\n');
75
+ }
76
+ // ─── Helpers ──────────────────────────────────────────────────────────────────
77
+ function buildHeader(ctx) {
78
+ const parts = [];
79
+ if (ctx?.depth)
80
+ parts.push(`depth: ${ctx.depth}`);
81
+ if (ctx?.filesScanned !== undefined)
82
+ parts.push(`${ctx.filesScanned} files scanned`);
83
+ const meta = parts.length > 0 ? ` (${parts.join(', ')})` : '';
84
+ const name = ctx?.name ? ` ${ctx.name}` : '';
85
+ return `[MfSharedInspector]${name}${meta}`;
86
+ }
87
+ //# sourceMappingURL=format-report.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format-report.js","sourceRoot":"","sources":["../../src/reporter/format-report.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import type { ProjectReport, ProjectManifest } from '../types.js';
2
+ /**
3
+ * Serialises a ProjectReport to a JSON file.
4
+ * Creates parent directories if they don't exist.
5
+ */
6
+ export declare function writeReport(report: ProjectReport, outputPath: string): Promise<void>;
7
+ /**
8
+ * Serialises a ProjectManifest to a JSON file.
9
+ * Creates parent directories if they don't exist.
10
+ */
11
+ export declare function writeManifest(manifest: ProjectManifest, outputPath: string): Promise<void>;
12
+ //# sourceMappingURL=write-report.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"write-report.d.ts","sourceRoot":"","sources":["../../src/reporter/write-report.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAElE;;;GAGG;AACH,wBAAsB,WAAW,CAAC,MAAM,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAG1F;AAED;;;GAGG;AACH,wBAAsB,aAAa,CAAC,QAAQ,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAGhG"}
@@ -0,0 +1,19 @@
1
+ import { writeFile, mkdir } from 'node:fs/promises';
2
+ import { dirname } from 'node:path';
3
+ /**
4
+ * Serialises a ProjectReport to a JSON file.
5
+ * Creates parent directories if they don't exist.
6
+ */
7
+ export async function writeReport(report, outputPath) {
8
+ await mkdir(dirname(outputPath), { recursive: true });
9
+ await writeFile(outputPath, JSON.stringify(report, null, 2), 'utf-8');
10
+ }
11
+ /**
12
+ * Serialises a ProjectManifest to a JSON file.
13
+ * Creates parent directories if they don't exist.
14
+ */
15
+ export async function writeManifest(manifest, outputPath) {
16
+ await mkdir(dirname(outputPath), { recursive: true });
17
+ await writeFile(outputPath, JSON.stringify(manifest, null, 2), 'utf-8');
18
+ }
19
+ //# sourceMappingURL=write-report.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"write-report.js","sourceRoot":"","sources":["../../src/reporter/write-report.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,MAAqB,EAAE,UAAkB;IACzE,MAAM,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACtD,MAAM,SAAS,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;AACxE,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,QAAyB,EAAE,UAAkB;IAC/E,MAAM,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACtD,MAAM,SAAS,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;AAC1E,CAAC"}