@mf-toolkit/shared-inspector 0.3.2 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/README.md +320 -156
  2. package/dist/cli/args.d.ts +5 -0
  3. package/dist/cli/args.d.ts.map +1 -0
  4. package/dist/cli/args.js +98 -0
  5. package/dist/cli/args.js.map +1 -0
  6. package/dist/cli/colorize-report.d.ts +6 -0
  7. package/dist/cli/colorize-report.d.ts.map +1 -0
  8. package/dist/cli/colorize-report.js +71 -0
  9. package/dist/cli/colorize-report.js.map +1 -0
  10. package/dist/cli/colors.d.ts +14 -0
  11. package/dist/cli/colors.d.ts.map +1 -0
  12. package/dist/cli/colors.js +26 -0
  13. package/dist/cli/colors.js.map +1 -0
  14. package/dist/cli/help.d.ts +2 -0
  15. package/dist/cli/help.d.ts.map +1 -0
  16. package/dist/cli/help.js +30 -0
  17. package/dist/cli/help.js.map +1 -0
  18. package/dist/cli/index.d.ts +8 -0
  19. package/dist/cli/index.d.ts.map +1 -0
  20. package/dist/cli/index.js +62 -0
  21. package/dist/cli/index.js.map +1 -0
  22. package/dist/cli/interactive.d.ts +8 -0
  23. package/dist/cli/interactive.d.ts.map +1 -0
  24. package/dist/cli/interactive.js +41 -0
  25. package/dist/cli/interactive.js.map +1 -0
  26. package/dist/cli/run-federation.d.ts +3 -0
  27. package/dist/cli/run-federation.d.ts.map +1 -0
  28. package/dist/cli/run-federation.js +41 -0
  29. package/dist/cli/run-federation.js.map +1 -0
  30. package/dist/cli/run-project.d.ts +5 -0
  31. package/dist/cli/run-project.d.ts.map +1 -0
  32. package/dist/cli/run-project.js +57 -0
  33. package/dist/cli/run-project.js.map +1 -0
  34. package/dist/cli/spinner.d.ts +10 -0
  35. package/dist/cli/spinner.d.ts.map +1 -0
  36. package/dist/cli/spinner.js +45 -0
  37. package/dist/cli/spinner.js.map +1 -0
  38. package/dist/cli/types.d.ts +17 -0
  39. package/dist/cli/types.d.ts.map +1 -0
  40. package/dist/cli/types.js +2 -0
  41. package/dist/cli/types.js.map +1 -0
  42. package/dist/cli.d.ts +3 -0
  43. package/dist/cli.d.ts.map +1 -0
  44. package/dist/cli.js +13 -0
  45. package/dist/cli.js.map +1 -0
  46. package/dist/index.d.ts +1 -0
  47. package/dist/index.d.ts.map +1 -1
  48. package/dist/index.js +1 -0
  49. package/dist/index.js.map +1 -1
  50. package/dist/reporter/diagnostics.d.ts +23 -0
  51. package/dist/reporter/diagnostics.d.ts.map +1 -0
  52. package/dist/reporter/diagnostics.js +138 -0
  53. package/dist/reporter/diagnostics.js.map +1 -0
  54. package/dist/reporter/format-federation-report.d.ts +11 -5
  55. package/dist/reporter/format-federation-report.d.ts.map +1 -1
  56. package/dist/reporter/format-federation-report.js +78 -37
  57. package/dist/reporter/format-federation-report.js.map +1 -1
  58. package/dist/reporter/format-report.d.ts +14 -7
  59. package/dist/reporter/format-report.d.ts.map +1 -1
  60. package/dist/reporter/format-report.js +67 -38
  61. package/dist/reporter/format-report.js.map +1 -1
  62. package/dist/reporter/scoring.d.ts +28 -0
  63. package/dist/reporter/scoring.d.ts.map +1 -0
  64. package/dist/reporter/scoring.js +74 -0
  65. package/dist/reporter/scoring.js.map +1 -0
  66. package/package.json +8 -3
@@ -0,0 +1,45 @@
1
+ // ─── Terminal spinner ─────────────────────────────────────────────────────────
2
+ //
3
+ // Uses braille frames for TTY, plain text for non-TTY / CI environments.
4
+ // Does NOT use the injectable `write` — writes directly to process.stdout
5
+ // so it can overwrite lines in place without interfering with the report output.
6
+ import { isTTY, green, gray } from './colors.js';
7
+ const FRAMES = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
8
+ const INTERVAL_MS = 80;
9
+ export function createSpinner() {
10
+ if (!isTTY) {
11
+ // Non-TTY (CI, piped): emit plain text lines via stdout
12
+ return {
13
+ start(text) { process.stdout.write(` ${text}...\n`); },
14
+ succeed(text) { process.stdout.write(` ✓ ${text}\n`); },
15
+ stop() { },
16
+ };
17
+ }
18
+ let frame = 0;
19
+ let timer;
20
+ function clearLine() {
21
+ process.stdout.write('\r\x1b[K'); // carriage return + erase to end of line
22
+ }
23
+ return {
24
+ start(text) {
25
+ process.stdout.write('\x1b[?25l'); // hide cursor
26
+ timer = setInterval(() => {
27
+ clearLine();
28
+ process.stdout.write(gray(`${FRAMES[frame % FRAMES.length]} ${text}`));
29
+ frame++;
30
+ }, INTERVAL_MS);
31
+ },
32
+ succeed(text) {
33
+ clearInterval(timer);
34
+ clearLine();
35
+ process.stdout.write(`${green('✓')} ${text}\n`);
36
+ process.stdout.write('\x1b[?25h'); // show cursor
37
+ },
38
+ stop() {
39
+ clearInterval(timer);
40
+ clearLine();
41
+ process.stdout.write('\x1b[?25h');
42
+ },
43
+ };
44
+ }
45
+ //# sourceMappingURL=spinner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spinner.js","sourceRoot":"","sources":["../../src/cli/spinner.ts"],"names":[],"mappings":"AAAA,iFAAiF;AACjF,EAAE;AACF,yEAAyE;AACzE,0EAA0E;AAC1E,iFAAiF;AAEjF,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAEjD,MAAM,MAAM,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;AAClE,MAAM,WAAW,GAAG,EAAE,CAAC;AAWvB,MAAM,UAAU,aAAa;IAC3B,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,wDAAwD;QACxD,OAAO;YACL,KAAK,CAAC,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC;YACvD,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC;YACxD,IAAI,KAAI,CAAC;SACV,CAAC;IACJ,CAAC;IAED,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,KAAiD,CAAC;IAEtD,SAAS,SAAS;QAChB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,yCAAyC;IAC7E,CAAC;IAED,OAAO;QACL,KAAK,CAAC,IAAI;YACR,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,cAAc;YACjD,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE;gBACvB,SAAS,EAAE,CAAC;gBACZ,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC;gBACxE,KAAK,EAAE,CAAC;YACV,CAAC,EAAE,WAAW,CAAC,CAAC;QAClB,CAAC;QACD,OAAO,CAAC,IAAI;YACV,aAAa,CAAC,KAAK,CAAC,CAAC;YACrB,SAAS,EAAE,CAAC;YACZ,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC;YACjD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,cAAc;QACnD,CAAC;QACD,IAAI;YACF,aAAa,CAAC,KAAK,CAAC,CAAC;YACrB,SAAS,EAAE,CAAC;YACZ,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;QACpC,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,17 @@
1
+ import type { SharedDepConfig } from '../types.js';
2
+ export interface CliArgs {
3
+ command: 'project' | 'federation' | 'help' | 'version';
4
+ interactive: boolean;
5
+ sourceDirs: string[];
6
+ depth: 'direct' | 'local-graph';
7
+ sharedConfig?: Record<string, SharedDepConfig>;
8
+ tsconfigPath?: string;
9
+ workspacePackages: string[];
10
+ failOn?: 'mismatch' | 'unused' | 'any';
11
+ writeManifest: boolean;
12
+ outputDir: string;
13
+ name?: string;
14
+ manifestFiles: string[];
15
+ }
16
+ export type PromptFn = (question: string) => Promise<string>;
17
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/cli/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD,MAAM,WAAW,OAAO;IACtB,OAAO,EAAE,SAAS,GAAG,YAAY,GAAG,MAAM,GAAG,SAAS,CAAC;IACvD,WAAW,EAAE,OAAO,CAAC;IAErB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,KAAK,EAAE,QAAQ,GAAG,aAAa,CAAC;IAChC,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IAC/C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,MAAM,CAAC,EAAE,UAAU,GAAG,QAAQ,GAAG,KAAK,CAAC;IACvC,aAAa,EAAE,OAAO,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd,aAAa,EAAE,MAAM,EAAE,CAAC;CACzB;AAED,MAAM,MAAM,QAAQ,GAAG,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/cli/types.ts"],"names":[],"mappings":""}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export * from './cli/index.js';
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,cAAc,gBAAgB,CAAC"}
package/dist/cli.js ADDED
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env node
2
+ export * from './cli/index.js';
3
+ import { main } from './cli/index.js';
4
+ const moduleUrl = new URL(import.meta.url);
5
+ const scriptUrl = process.argv[1] ? new URL(process.argv[1], 'file://') : null;
6
+ if (scriptUrl && moduleUrl.href === scriptUrl.href) {
7
+ main(process.argv.slice(2)).then((code) => { if (code !== 0)
8
+ process.exit(code); }, (err) => {
9
+ process.stderr.write(`Error: ${err.message}\n`);
10
+ process.exit(1);
11
+ });
12
+ }
13
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,cAAc,gBAAgB,CAAC;AAC/B,OAAO,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAEtC,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC3C,MAAM,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AAE/E,IAAI,SAAS,IAAI,SAAS,CAAC,IAAI,KAAK,SAAS,CAAC,IAAI,EAAE,CAAC;IACnD,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAC9B,CAAC,IAAI,EAAE,EAAE,GAAG,IAAI,IAAI,KAAK,CAAC;QAAE,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EACjD,CAAC,GAAU,EAAE,EAAE;QACb,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,GAAG,CAAC,OAAO,IAAI,CAAC,CAAC;QAChD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CACF,CAAC;AACJ,CAAC"}
package/dist/index.d.ts CHANGED
@@ -5,5 +5,6 @@ export { inspect } from './inspect.js';
5
5
  export { formatReport, type FormatReportContext } from './reporter/format-report.js';
6
6
  export { formatFederationReport } from './reporter/format-federation-report.js';
7
7
  export { writeReport, writeManifest } from './reporter/write-report.js';
8
+ export { scoreProjectReport, scoreFederationReport, type RiskScore } from './reporter/scoring.js';
8
9
  export type { ProjectManifest, ProjectReport, CollectorOptions, AnalysisOptions, SharedDepConfig, PackageOccurrence, UnusedEntry, CandidateEntry, MismatchedEntry, SingletonRiskEntry, EagerRiskEntry, FederationAnalysisOptions, FederationReport, GhostShareEntry, HostGapEntry, VersionConflictEntry, SingletonMismatchEntry, } from './types.js';
9
10
  //# sourceMappingURL=index.d.ts.map
@@ -1 +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;AAC/D,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AAGrE,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAGvC,OAAO,EAAE,YAAY,EAAE,KAAK,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AACrF,OAAO,EAAE,sBAAsB,EAAE,MAAM,wCAAwC,CAAC;AAChF,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,EAClB,cAAc,EACd,yBAAyB,EACzB,gBAAgB,EAChB,eAAe,EACf,YAAY,EACZ,oBAAoB,EACpB,sBAAsB,GACvB,MAAM,YAAY,CAAC"}
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;AAC/D,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AAGrE,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAGvC,OAAO,EAAE,YAAY,EAAE,KAAK,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AACrF,OAAO,EAAE,sBAAsB,EAAE,MAAM,wCAAwC,CAAC;AAChF,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AACxE,OAAO,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,KAAK,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAGlG,YAAY,EACV,eAAe,EACf,aAAa,EACb,gBAAgB,EAChB,eAAe,EACf,eAAe,EACf,iBAAiB,EACjB,WAAW,EACX,cAAc,EACd,eAAe,EACf,kBAAkB,EAClB,cAAc,EACd,yBAAyB,EACzB,gBAAgB,EAChB,eAAe,EACf,YAAY,EACZ,oBAAoB,EACpB,sBAAsB,GACvB,MAAM,YAAY,CAAC"}
package/dist/index.js CHANGED
@@ -8,4 +8,5 @@ export { inspect } from './inspect.js';
8
8
  export { formatReport } from './reporter/format-report.js';
9
9
  export { formatFederationReport } from './reporter/format-federation-report.js';
10
10
  export { writeReport, writeManifest } from './reporter/write-report.js';
11
+ export { scoreProjectReport, scoreFederationReport } from './reporter/scoring.js';
11
12
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +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;AAC/D,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AAErE,iFAAiF;AACjF,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,iFAAiF;AACjF,OAAO,EAAE,YAAY,EAA4B,MAAM,6BAA6B,CAAC;AACrF,OAAO,EAAE,sBAAsB,EAAE,MAAM,wCAAwC,CAAC;AAChF,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC"}
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;AAC/D,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AAErE,iFAAiF;AACjF,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,iFAAiF;AACjF,OAAO,EAAE,YAAY,EAA4B,MAAM,6BAA6B,CAAC;AACrF,OAAO,EAAE,sBAAsB,EAAE,MAAM,wCAAwC,CAAC;AAChF,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AACxE,OAAO,EAAE,kBAAkB,EAAE,qBAAqB,EAAkB,MAAM,uBAAuB,CAAC"}
@@ -0,0 +1,23 @@
1
+ export interface DiagnosticInfo {
2
+ /** One-line risk description shown after "→ Risk:" */
3
+ risk: string;
4
+ }
5
+ export type IssueKind = 'mismatch' | 'unused' | 'candidate' | 'singleton-risk' | 'eager-risk';
6
+ export declare function getDiagnostic(pkg: string, kind: IssueKind): DiagnosticInfo;
7
+ export interface FixConfig {
8
+ singleton?: boolean;
9
+ requiredVersion?: string;
10
+ eager?: boolean;
11
+ }
12
+ /**
13
+ * Returns a ready-to-paste webpack/rspack shared config snippet.
14
+ *
15
+ * @example
16
+ * buildFixSnippet('react', { singleton: true, requiredVersion: '^18.2.0' })
17
+ * // →
18
+ * // shared: {
19
+ * // react: { singleton: true, requiredVersion: "^18.2.0" }
20
+ * // }
21
+ */
22
+ export declare function buildFixSnippet(pkg: string, cfg?: FixConfig): string;
23
+ //# sourceMappingURL=diagnostics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diagnostics.d.ts","sourceRoot":"","sources":["../../src/reporter/diagnostics.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,cAAc;IAC7B,sDAAsD;IACtD,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,MAAM,SAAS,GACjB,UAAU,GACV,QAAQ,GACR,WAAW,GACX,gBAAgB,GAChB,YAAY,CAAC;AAkHjB,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,GAAG,cAAc,CAG1E;AAID,MAAM,WAAW,SAAS;IACxB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,GAAE,SAAc,GAAG,MAAM,CAQxE"}
@@ -0,0 +1,138 @@
1
+ // ─── Diagnostics knowledge base ──────────────────────────────────────────────
2
+ //
3
+ // Maps (package, issue-kind) → { risk description, fix snippet hint }.
4
+ // Used by formatReport / formatFederationReport to produce actionable output.
5
+ // ─── Per-package knowledge ────────────────────────────────────────────────────
6
+ const PACKAGE_DIAGNOSTICS = {
7
+ react: {
8
+ mismatch: 'Invalid hook call, broken context across MFs',
9
+ candidate: 'Multiple React copies → invalid hook call',
10
+ 'singleton-risk': 'Multiple React instances → invalid hook call, broken context',
11
+ 'eager-risk': 'Duplicate React before negotiation completes → invalid hook call',
12
+ unused: 'React is consumed by JSX transform — removing may break JSX in remotes',
13
+ },
14
+ 'react-dom': {
15
+ mismatch: 'Rendering broken — host and remote use different ReactDOM',
16
+ candidate: 'Multiple ReactDOM copies → broken rendering',
17
+ 'singleton-risk': 'Multiple ReactDOM instances → broken rendering, portals fail',
18
+ unused: 'ReactDOM is consumed implicitly — removing may break renders in remotes',
19
+ },
20
+ 'react-router': {
21
+ mismatch: 'Router version mismatch → broken navigation, hooks (useParams, useNavigate) broken',
22
+ candidate: 'Each MF has its own router instance → history state conflicts',
23
+ 'singleton-risk': 'Multiple router instances → navigation conflicts between MFs',
24
+ unused: 'Route declarations in the remote may silently stop working',
25
+ },
26
+ 'react-router-dom': {
27
+ mismatch: 'Router version mismatch → broken navigation',
28
+ candidate: 'Each MF has its own router → useNavigate / useParams broken cross-MF',
29
+ 'singleton-risk': 'Multiple router instances → useNavigate / useParams broken',
30
+ unused: 'Link and Route components may stop working in other MFs',
31
+ },
32
+ mobx: {
33
+ mismatch: 'Observable state won\'t sync — MFs run different MobX versions',
34
+ candidate: 'Each MF gets its own MobX — observables and reactions won\'t sync between MFs',
35
+ 'singleton-risk': 'Multiple MobX instances → cross-MF reactions won\'t fire, state isolated',
36
+ unused: 'MobX stores in the remote will be untracked',
37
+ },
38
+ 'mobx-react': {
39
+ mismatch: 'observer() wraps components from different MobX instances',
40
+ candidate: 'Multiple mobx-react copies → observer() connects to wrong store instance',
41
+ 'singleton-risk': 'Multiple mobx-react instances → observer() binds to isolated store',
42
+ },
43
+ 'mobx-react-lite': {
44
+ mismatch: 'useObserver connects to wrong MobX instance',
45
+ candidate: 'Each MF gets its own observer binding',
46
+ 'singleton-risk': 'Multiple mobx-react-lite → useObserver connects to wrong store',
47
+ },
48
+ redux: {
49
+ mismatch: 'Redux version mismatch → dispatch / subscribe API incompatible',
50
+ candidate: 'Each MF creates its own store — actions won\'t propagate across MFs',
51
+ 'singleton-risk': 'Multiple Redux stores → dispatches won\'t propagate cross-MF',
52
+ },
53
+ '@reduxjs/toolkit': {
54
+ mismatch: 'RTK version mismatch → createSlice / createAsyncThunk API differences',
55
+ candidate: 'Each MF bundles its own RTK — separate store instances, no shared state',
56
+ 'singleton-risk': 'Multiple RTK instances → slices belong to different stores',
57
+ },
58
+ zustand: {
59
+ mismatch: 'Zustand API mismatch → store subscriptions may not work correctly',
60
+ candidate: 'Each MF gets its own Zustand store — state not shared across MFs',
61
+ 'singleton-risk': 'Multiple Zustand instances → store subscriptions not shared',
62
+ },
63
+ jotai: {
64
+ candidate: 'Each MF gets its own Jotai atom scope — atoms won\'t sync',
65
+ 'singleton-risk': 'Multiple Jotai instances → atoms not shared between MFs',
66
+ },
67
+ recoil: {
68
+ candidate: 'Each MF gets its own Recoil root — atoms isolated per MF',
69
+ 'singleton-risk': 'Multiple Recoil instances → RecoilRoot state not shared',
70
+ },
71
+ vue: {
72
+ mismatch: 'Vue runtime mismatch → app.use() and composables broken',
73
+ candidate: 'Each MF bundles Vue — composables won\'t share reactive state',
74
+ 'singleton-risk': 'Multiple Vue runtimes → provide/inject across MFs broken',
75
+ },
76
+ 'vue-router': {
77
+ mismatch: 'Router version mismatch → navigation guards and hooks broken',
78
+ candidate: 'Each MF has its own Vue Router instance → navigation conflicts',
79
+ 'singleton-risk': 'Multiple router instances → useRoute / useRouter broken cross-MF',
80
+ },
81
+ 'styled-components': {
82
+ mismatch: 'Style injection broken — className collisions between MFs',
83
+ candidate: 'Each MF bundles its own styled-components — class name conflicts in SSR',
84
+ 'singleton-risk': 'Multiple styled-components → theme context not shared, class collisions',
85
+ },
86
+ '@emotion/react': {
87
+ mismatch: 'Emotion cache mismatch → styles not injected correctly across MFs',
88
+ candidate: 'Each MF has its own Emotion cache — styles may conflict or duplicate',
89
+ 'singleton-risk': 'Multiple Emotion instances → theme context not shared, styles broken',
90
+ },
91
+ '@emotion/styled': {
92
+ mismatch: 'Emotion version mismatch → styled components lose theme context',
93
+ candidate: 'Each MF bundles @emotion/styled independently',
94
+ 'singleton-risk': 'Multiple Emotion instances → styled components lose theme context',
95
+ },
96
+ '@tanstack/react-query': {
97
+ candidate: 'Each MF has its own QueryClient → no shared cache, duplicate requests',
98
+ 'singleton-risk': 'Multiple QueryClient instances → cache not shared between MFs',
99
+ },
100
+ swr: {
101
+ candidate: 'Each MF has its own SWR cache → duplicate fetches, no deduplication',
102
+ 'singleton-risk': 'Multiple SWR instances → cache not shared between MFs',
103
+ },
104
+ };
105
+ // ─── Generic fallbacks ────────────────────────────────────────────────────────
106
+ const GENERIC_RISK = {
107
+ mismatch: 'Version mismatch may cause runtime errors or silent incompatibilities',
108
+ unused: 'Wastes bundle negotiation overhead with no import benefit',
109
+ candidate: 'Each MF bundles its own copy — larger bundles, possible state desync',
110
+ 'singleton-risk': 'Duplicate instances may cause unexpected runtime behavior',
111
+ 'eager-risk': 'Eager loading without singleton risks duplicate instances during negotiation',
112
+ };
113
+ export function getDiagnostic(pkg, kind) {
114
+ const risk = PACKAGE_DIAGNOSTICS[pkg]?.[kind] ?? GENERIC_RISK[kind];
115
+ return { risk };
116
+ }
117
+ /**
118
+ * Returns a ready-to-paste webpack/rspack shared config snippet.
119
+ *
120
+ * @example
121
+ * buildFixSnippet('react', { singleton: true, requiredVersion: '^18.2.0' })
122
+ * // →
123
+ * // shared: {
124
+ * // react: { singleton: true, requiredVersion: "^18.2.0" }
125
+ * // }
126
+ */
127
+ export function buildFixSnippet(pkg, cfg = {}) {
128
+ const entries = [];
129
+ if (cfg.singleton)
130
+ entries.push('singleton: true');
131
+ if (cfg.requiredVersion)
132
+ entries.push(`requiredVersion: "${cfg.requiredVersion}"`);
133
+ if (cfg.eager)
134
+ entries.push('eager: true');
135
+ const inner = entries.length > 0 ? ` { ${entries.join(', ')} }` : ' {}';
136
+ return `shared: {\n ${pkg}:${inner}\n}`;
137
+ }
138
+ //# sourceMappingURL=diagnostics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diagnostics.js","sourceRoot":"","sources":["../../src/reporter/diagnostics.ts"],"names":[],"mappings":"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"}
@@ -1,12 +1,18 @@
1
1
  import type { FederationReport } from '../types.js';
2
2
  /**
3
- * Formats a FederationReport as a human-readable terminal string.
3
+ * Formats a FederationReport as actionable diagnostic cards.
4
+ *
5
+ * Each finding shows:
6
+ * - Issue title + package name
7
+ * - Which MFs are involved
8
+ * - Risk description (what breaks at runtime)
9
+ * - Ready-to-paste fix snippet
4
10
  *
5
11
  * Section order (by severity):
6
- * 1. Version conflicts — deterministic, most dangerous (silent broken singleton)
7
- * 2. Singleton mismatches — deterministic, runtime risk
8
- * 3. Host gaps — heuristic, bundle duplication
9
- * 4. Ghost shares — heuristic, dead coupling
12
+ * 1. Version conflicts — most dangerous, singleton negotiation fails silently
13
+ * 2. Singleton mismatches — runtime risk, unpredictable instance selection
14
+ * 3. Host gaps — bundle duplication, no shared state
15
+ * 4. Ghost shares — dead coupling, safe to remove
10
16
  * 5. Summary line
11
17
  */
12
18
  export declare function formatFederationReport(report: FederationReport): string;
@@ -1 +1 @@
1
- {"version":3,"file":"format-federation-report.d.ts","sourceRoot":"","sources":["../../src/reporter/format-federation-report.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAEpD;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,gBAAgB,GAAG,MAAM,CAgFvE"}
1
+ {"version":3,"file":"format-federation-report.d.ts","sourceRoot":"","sources":["../../src/reporter/format-federation-report.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAwB,MAAM,aAAa,CAAC;AAM1E;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,gBAAgB,GAAG,MAAM,CAiGvE"}
@@ -1,72 +1,97 @@
1
+ import { getDiagnostic, buildFixSnippet } from './diagnostics.js';
2
+ import { scoreFederationReport, formatScoreBlock } from './scoring.js';
3
+ const HR = '─'.repeat(60);
1
4
  /**
2
- * Formats a FederationReport as a human-readable terminal string.
5
+ * Formats a FederationReport as actionable diagnostic cards.
6
+ *
7
+ * Each finding shows:
8
+ * - Issue title + package name
9
+ * - Which MFs are involved
10
+ * - Risk description (what breaks at runtime)
11
+ * - Ready-to-paste fix snippet
3
12
  *
4
13
  * Section order (by severity):
5
- * 1. Version conflicts — deterministic, most dangerous (silent broken singleton)
6
- * 2. Singleton mismatches — deterministic, runtime risk
7
- * 3. Host gaps — heuristic, bundle duplication
8
- * 4. Ghost shares — heuristic, dead coupling
14
+ * 1. Version conflicts — most dangerous, singleton negotiation fails silently
15
+ * 2. Singleton mismatches — runtime risk, unpredictable instance selection
16
+ * 3. Host gaps — bundle duplication, no shared state
17
+ * 4. Ghost shares — dead coupling, safe to remove
9
18
  * 5. Summary line
10
19
  */
11
20
  export function formatFederationReport(report) {
12
21
  const lines = [];
13
22
  const { ghostShares, hostGaps, versionConflicts, singletonMismatches, summary } = report;
14
- // ── Header ─────────────────────────────────────────────────────────────────
15
- lines.push('', `[MfSharedInspector] federation analysis (${summary.totalManifests} MFs)`, '');
23
+ lines.push('', `[MfSharedInspector] federation analysis (${summary.totalManifests} MFs)`, HR, '');
16
24
  const hasFindings = versionConflicts.length > 0 ||
17
25
  singletonMismatches.length > 0 ||
18
26
  hostGaps.length > 0 ||
19
27
  ghostShares.length > 0;
20
28
  if (!hasFindings) {
21
- lines.push(' No federation-level issues found.');
29
+ lines.push(' No federation-level issues found. Everything looks consistent.');
30
+ lines.push('');
31
+ lines.push(HR);
32
+ lines.push(formatScoreBlock(scoreFederationReport(report), 'version conflicts', 'singleton mismatches, host gaps', 'ghost shares'));
22
33
  lines.push('');
23
- lines.push(` Total: ${summary.totalManifests} MFs analysed, everything looks consistent.`);
34
+ lines.push(`Total: ${summary.totalManifests} MFs analysed, 0 issues.`);
24
35
  lines.push('');
25
36
  return lines.join('\n');
26
37
  }
27
38
  // ── 1. Version conflicts ───────────────────────────────────────────────────
28
- if (versionConflicts.length > 0) {
29
- lines.push(' Version conflicts (singleton negotiation will fail):');
30
- for (const c of versionConflicts) {
31
- const versions = Object.entries(c.versions)
32
- .map(([mf, v]) => `${mf}: ${v}`)
33
- .join(', ');
34
- lines.push(` ${c.package} ${versions}`);
39
+ for (const c of versionConflicts) {
40
+ const { risk } = getDiagnostic(c.package, 'mismatch');
41
+ lines.push(`⚠ Version Conflict ${c.package}`);
42
+ for (const [mf, v] of Object.entries(c.versions)) {
43
+ lines.push(` ${mf}: ${v}`);
44
+ }
45
+ lines.push(` Risk: MF singleton negotiation will silently load wrong version → ${risk}`);
46
+ lines.push(` 💡 Fix: Align requiredVersion across all MFs:`);
47
+ const best = pickHighestRequiredVersion(c);
48
+ for (const l of buildFixSnippet(c.package, { singleton: true, requiredVersion: best }).split('\n')) {
49
+ lines.push(` ${l}`);
35
50
  }
36
51
  lines.push('');
37
52
  }
38
53
  // ── 2. Singleton mismatches ────────────────────────────────────────────────
39
- if (singletonMismatches.length > 0) {
40
- lines.push(' Singleton mismatches (add singleton: true to all MFs):');
41
- for (const s of singletonMismatches) {
42
- lines.push(` ⚠ ${s.package} — singleton in [${s.singletonIn.join(', ')}], not singleton in [${s.nonSingletonIn.join(', ')}]`);
43
- }
54
+ for (const s of singletonMismatches) {
55
+ const { risk } = getDiagnostic(s.package, 'singleton-risk');
56
+ lines.push(`⚠ Singleton Mismatch ${s.package}`);
57
+ lines.push(` singleton in: [${s.singletonIn.join(', ')}]`);
58
+ lines.push(` not singleton in: [${s.nonSingletonIn.join(', ')}]`);
59
+ lines.push(` → Risk: ${risk}`);
60
+ lines.push(` 💡 Fix: Add singleton: true to all MFs that share ${s.package}`);
44
61
  lines.push('');
45
62
  }
46
63
  // ── 3. Host gaps ───────────────────────────────────────────────────────────
47
- if (hostGaps.length > 0) {
48
- lines.push(' Host gaps (add to shared each MF bundles its own copy):');
49
- for (const g of hostGaps) {
50
- lines.push(` → ${g.package} — used by [${g.missingIn.join(', ')}], not in shared`);
64
+ for (const g of hostGaps) {
65
+ const { risk } = getDiagnostic(g.package, 'candidate');
66
+ lines.push(`→ Host Gap ${g.package}`);
67
+ lines.push(` used by: [${g.missingIn.join(', ')}], not in shared config`);
68
+ lines.push(` → Risk: ${risk}`);
69
+ lines.push(` 💡 Fix:`);
70
+ for (const l of buildFixSnippet(g.package, { singleton: true }).split('\n')) {
71
+ lines.push(` ${l}`);
51
72
  }
52
73
  lines.push('');
53
74
  }
54
75
  // ── 4. Ghost shares ────────────────────────────────────────────────────────
55
- if (ghostShares.length > 0) {
56
- lines.push(' Ghost shares (remove from shared no other MF benefits):');
57
- for (const g of ghostShares) {
58
- if (g.usedUnsharedBy.length > 0) {
59
- lines.push(` ${g.package} — shared only by ${g.sharedBy}, ` +
60
- `used unshared by [${g.usedUnsharedBy.join(', ')}]`);
61
- }
62
- else {
63
- lines.push(` ✗ ${g.package} — shared only by ${g.sharedBy}, unused by all other MFs`);
64
- }
76
+ for (const g of ghostShares) {
77
+ lines.push(`✗ Ghost Share${g.package}`);
78
+ lines.push(` shared only by: ${g.sharedBy}`);
79
+ if (g.usedUnsharedBy.length > 0) {
80
+ lines.push(` used unshared by: [${g.usedUnsharedBy.join(', ')}]`);
65
81
  }
82
+ else {
83
+ lines.push(` unused by all other MFs`);
84
+ }
85
+ lines.push(` → One-sided coupling with no federation benefit`);
86
+ lines.push(` 💡 Fix: Remove "${g.package}" from ${g.sharedBy}'s shared config`);
66
87
  lines.push('');
67
88
  }
68
- // ── 5. Summary ─────────────────────────────────────────────────────────────
69
- lines.push(` Total: ${summary.totalManifests} MFs, ` +
89
+ // ── 5. Score + Summary ───────────────────────────────────────────────────
90
+ const score = scoreFederationReport(report);
91
+ lines.push(HR);
92
+ lines.push(formatScoreBlock(score, 'version conflicts', 'singleton mismatches, host gaps', 'ghost shares'));
93
+ lines.push('');
94
+ lines.push(`Total: ${summary.totalManifests} MFs, ` +
70
95
  `${summary.versionConflictsCount} version conflicts, ` +
71
96
  `${summary.singletonMismatchesCount} singleton mismatches, ` +
72
97
  `${summary.hostGapsCount} host gaps, ` +
@@ -74,4 +99,20 @@ export function formatFederationReport(report) {
74
99
  lines.push('');
75
100
  return lines.join('\n');
76
101
  }
102
+ // ─── Helpers ──────────────────────────────────────────────────────────────────
103
+ /** Pick the version string with the highest semver major (and minor) as the suggested fix. */
104
+ function pickHighestRequiredVersion(c) {
105
+ const versions = Object.values(c.versions);
106
+ const sorted = versions.slice().sort((a, b) => {
107
+ const clean = (v) => v.replace(/^[\^~>=<\s]+/, '').split('.').map(Number);
108
+ const [aMaj = 0, aMin = 0, aPatch = 0] = clean(a);
109
+ const [bMaj = 0, bMin = 0, bPatch = 0] = clean(b);
110
+ if (bMaj !== aMaj)
111
+ return bMaj - aMaj;
112
+ if (bMin !== aMin)
113
+ return bMin - aMin;
114
+ return bPatch - aPatch;
115
+ });
116
+ return sorted[0];
117
+ }
77
118
  //# sourceMappingURL=format-federation-report.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"format-federation-report.js","sourceRoot":"","sources":["../../src/reporter/format-federation-report.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"format-federation-report.js","sourceRoot":"","sources":["../../src/reporter/format-federation-report.ts"],"names":[],"mappings":"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"}
@@ -5,14 +5,21 @@ export interface FormatReportContext {
5
5
  filesScanned?: number;
6
6
  }
7
7
  /**
8
- * Formats a ProjectReport as a human-readable terminal string.
8
+ * Formats a ProjectReport as actionable diagnostic cards.
9
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
10
+ * Each finding is rendered as a card with:
11
+ * - Issue title + package name
12
+ * - Concrete detail (version numbers, import count, etc.)
13
+ * - Risk description (what breaks at runtime)
14
+ * - Ready-to-paste fix snippet
15
+ *
16
+ * Section order (by severity):
17
+ * 1. Version mismatch — most dangerous, sharing silently broken
18
+ * 2. Unused shared — easy wins, safe to remove
19
+ * 3. Candidates — not shared but should be
20
+ * 4. Singleton risks — missing singleton: true
21
+ * 5. Eager risks — eager without singleton
22
+ * 6. Summary line
16
23
  */
17
24
  export declare function formatReport(report: ProjectReport, ctx?: FormatReportContext): string;
18
25
  //# sourceMappingURL=format-report.d.ts.map
@@ -1 +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"}
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;AAIjD,MAAM,WAAW,mBAAmB;IAClC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,QAAQ,GAAG,aAAa,CAAC;IACjC,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAID;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,aAAa,EAAE,GAAG,CAAC,EAAE,mBAAmB,GAAG,MAAM,CAqGrF"}