@component-compass/cli 0.0.0-pr-3-8916f3c-20260507145532

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 (124) hide show
  1. package/README.md +5 -0
  2. package/dist/cli.d.ts +2 -0
  3. package/dist/cli.js +110 -0
  4. package/dist/cli.js.map +1 -0
  5. package/dist/commands/init.d.ts +6 -0
  6. package/dist/commands/init.js +61 -0
  7. package/dist/commands/init.js.map +1 -0
  8. package/dist/commands/scan.d.ts +12 -0
  9. package/dist/commands/scan.js +147 -0
  10. package/dist/commands/scan.js.map +1 -0
  11. package/dist/config/loader.d.ts +6 -0
  12. package/dist/config/loader.js +62 -0
  13. package/dist/config/loader.js.map +1 -0
  14. package/dist/config/schema.d.ts +32 -0
  15. package/dist/config/schema.js +15 -0
  16. package/dist/config/schema.js.map +1 -0
  17. package/dist/config/tag-rules.d.ts +2 -0
  18. package/dist/config/tag-rules.js +34 -0
  19. package/dist/config/tag-rules.js.map +1 -0
  20. package/dist/dispatcher.d.ts +8 -0
  21. package/dist/dispatcher.js +22 -0
  22. package/dist/dispatcher.js.map +1 -0
  23. package/dist/envelope/git.d.ts +13 -0
  24. package/dist/envelope/git.js +69 -0
  25. package/dist/envelope/git.js.map +1 -0
  26. package/dist/envelope/index.d.ts +10 -0
  27. package/dist/envelope/index.js +57 -0
  28. package/dist/envelope/index.js.map +1 -0
  29. package/dist/envelope/repo-id.d.ts +16 -0
  30. package/dist/envelope/repo-id.js +40 -0
  31. package/dist/envelope/repo-id.js.map +1 -0
  32. package/dist/identity.d.ts +46 -0
  33. package/dist/identity.js +92 -0
  34. package/dist/identity.js.map +1 -0
  35. package/dist/index.d.ts +1 -0
  36. package/dist/index.js +2 -0
  37. package/dist/index.js.map +1 -0
  38. package/dist/local-index/detect-react.d.ts +2 -0
  39. package/dist/local-index/detect-react.js +128 -0
  40. package/dist/local-index/detect-react.js.map +1 -0
  41. package/dist/local-index/detect-vue.d.ts +2 -0
  42. package/dist/local-index/detect-vue.js +164 -0
  43. package/dist/local-index/detect-vue.js.map +1 -0
  44. package/dist/local-index/detect-wc.d.ts +2 -0
  45. package/dist/local-index/detect-wc.js +74 -0
  46. package/dist/local-index/detect-wc.js.map +1 -0
  47. package/dist/local-index/index.d.ts +6 -0
  48. package/dist/local-index/index.js +31 -0
  49. package/dist/local-index/index.js.map +1 -0
  50. package/dist/local-index/types.d.ts +2 -0
  51. package/dist/local-index/types.js +2 -0
  52. package/dist/local-index/types.js.map +1 -0
  53. package/dist/local-index/walker.d.ts +11 -0
  54. package/dist/local-index/walker.js +47 -0
  55. package/dist/local-index/walker.js.map +1 -0
  56. package/dist/manifest/barrel-parser.d.ts +22 -0
  57. package/dist/manifest/barrel-parser.js +62 -0
  58. package/dist/manifest/barrel-parser.js.map +1 -0
  59. package/dist/manifest/discovery.d.ts +24 -0
  60. package/dist/manifest/discovery.js +194 -0
  61. package/dist/manifest/discovery.js.map +1 -0
  62. package/dist/manifest/index.d.ts +6 -0
  63. package/dist/manifest/index.js +98 -0
  64. package/dist/manifest/index.js.map +1 -0
  65. package/dist/manifest/resolver.d.ts +30 -0
  66. package/dist/manifest/resolver.js +136 -0
  67. package/dist/manifest/resolver.js.map +1 -0
  68. package/dist/manifest/run-discovery.d.ts +12 -0
  69. package/dist/manifest/run-discovery.js +46 -0
  70. package/dist/manifest/run-discovery.js.map +1 -0
  71. package/dist/manifest/types.d.ts +3 -0
  72. package/dist/manifest/types.js +2 -0
  73. package/dist/manifest/types.js.map +1 -0
  74. package/dist/occurrences.d.ts +12 -0
  75. package/dist/occurrences.js +42 -0
  76. package/dist/occurrences.js.map +1 -0
  77. package/dist/reporter/index.d.ts +25 -0
  78. package/dist/reporter/index.js +50 -0
  79. package/dist/reporter/index.js.map +1 -0
  80. package/dist/reporter/json.d.ts +6 -0
  81. package/dist/reporter/json.js +11 -0
  82. package/dist/reporter/json.js.map +1 -0
  83. package/dist/reporter/stdout.d.ts +2 -0
  84. package/dist/reporter/stdout.js +40 -0
  85. package/dist/reporter/stdout.js.map +1 -0
  86. package/dist/rollup.d.ts +21 -0
  87. package/dist/rollup.js +78 -0
  88. package/dist/rollup.js.map +1 -0
  89. package/dist/seeds.d.ts +28 -0
  90. package/dist/seeds.js +109 -0
  91. package/dist/seeds.js.map +1 -0
  92. package/dist/types/brand.d.ts +11 -0
  93. package/dist/types/brand.js +5 -0
  94. package/dist/types/brand.js.map +1 -0
  95. package/dist/types/component-id.d.ts +2 -0
  96. package/dist/types/component-id.js +2 -0
  97. package/dist/types/component-id.js.map +1 -0
  98. package/dist/types.d.ts +17 -0
  99. package/dist/types.js +2 -0
  100. package/dist/types.js.map +1 -0
  101. package/dist/util/git.d.ts +1 -0
  102. package/dist/util/git.js +13 -0
  103. package/dist/util/git.js.map +1 -0
  104. package/dist/util/log.d.ts +7 -0
  105. package/dist/util/log.js +17 -0
  106. package/dist/util/log.js.map +1 -0
  107. package/dist/util/pkg.d.ts +1 -0
  108. package/dist/util/pkg.js +13 -0
  109. package/dist/util/pkg.js.map +1 -0
  110. package/dist/util/pnp-check.d.ts +1 -0
  111. package/dist/util/pnp-check.js +6 -0
  112. package/dist/util/pnp-check.js.map +1 -0
  113. package/dist/util/posix.d.ts +2 -0
  114. package/dist/util/posix.js +18 -0
  115. package/dist/util/posix.js.map +1 -0
  116. package/dist/walker/files.d.ts +6 -0
  117. package/dist/walker/files.js +12 -0
  118. package/dist/walker/files.js.map +1 -0
  119. package/dist/walker/resolve-import.d.ts +9 -0
  120. package/dist/walker/resolve-import.js +119 -0
  121. package/dist/walker/resolve-import.js.map +1 -0
  122. package/examples/github-actions-workflow.yml +20 -0
  123. package/package.json +63 -0
  124. package/schema/config.schema.json +61 -0
package/README.md ADDED
@@ -0,0 +1,5 @@
1
+ # component-compass
2
+
3
+ Open-source CLI for measuring design-system component usage across multi-framework consumer repos.
4
+
5
+ See the [usage docs](../../docs/usage.md) and the [v1 design spec](../../docs/superpowers/specs/2026-05-02-component-compass-design.md).
package/dist/cli.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/cli.js ADDED
@@ -0,0 +1,110 @@
1
+ #!/usr/bin/env node
2
+ import { runScan } from "./commands/scan.js";
3
+ import { runInit } from "./commands/init.js";
4
+ import { Logger } from "./util/log.js";
5
+ import { errorStack } from "@component-compass/ast-utils";
6
+ const VERSION = "0.1.0";
7
+ const HELP = `component-compass <command> [options]
8
+
9
+ Commands:
10
+ scan Scan repo and write component-compass.json
11
+ init Scaffold component-compass.config.json
12
+
13
+ Scan options:
14
+ --config <path> Override config path (default: ./component-compass.config.json)
15
+ --output <path> Override output path
16
+ --capture-values Force capture literal prop values
17
+ --quiet Suppress STDOUT summary
18
+ --json Print JSON to stdout (implies --quiet)
19
+ --fail-on <metric> CI gate (e.g. deprecated-usage)
20
+ --repo-id <value> Override scan envelope repoId (else env COMPONENT_COMPASS_REPO_ID, git remote, package.json name, or cwd hash)
21
+
22
+ Other:
23
+ --help, -h
24
+ --version, -v
25
+ `;
26
+ async function main(argv) {
27
+ const log = new Logger(false);
28
+ if (argv.includes("--version") || argv.includes("-v")) {
29
+ process.stdout.write(`${VERSION}\n`);
30
+ return 0;
31
+ }
32
+ if (argv.includes("--help") || argv.includes("-h")) {
33
+ process.stdout.write(HELP);
34
+ return 0;
35
+ }
36
+ const [cmd, ...rest] = argv;
37
+ if (!cmd) {
38
+ process.stdout.write(HELP);
39
+ return 0;
40
+ }
41
+ if (cmd === "scan") {
42
+ const flags = parseFlags(rest);
43
+ const scanOpts = {
44
+ configPath: flags.config ?? "./component-compass.config.json",
45
+ quiet: Boolean(flags.quiet || flags.json),
46
+ };
47
+ if (flags.output)
48
+ scanOpts.outputOverride = flags.output;
49
+ if (flags.captureValues)
50
+ scanOpts.captureValuesOverride = true;
51
+ if (flags.failOn)
52
+ scanOpts.failOn = flags.failOn;
53
+ if (flags.repoId)
54
+ scanOpts.repoId = flags.repoId;
55
+ const r = await runScan(scanOpts);
56
+ return r.exitCode;
57
+ }
58
+ if (cmd === "init") {
59
+ try {
60
+ await runInit({ cwd: process.cwd() });
61
+ return 0;
62
+ }
63
+ catch (err) {
64
+ process.stderr.write(`init failed: ${errorStack(err)}\n`);
65
+ return 1;
66
+ }
67
+ }
68
+ log.error(`Unknown command: ${cmd}\n${HELP}`);
69
+ return 2;
70
+ }
71
+ function parseFlags(args) {
72
+ const out = {};
73
+ for (let i = 0; i < args.length; i++) {
74
+ const a = args[i];
75
+ if (a === undefined)
76
+ continue;
77
+ if (a === "--config") {
78
+ const next = args[++i];
79
+ if (next)
80
+ out.config = next;
81
+ }
82
+ else if (a === "--output") {
83
+ const next = args[++i];
84
+ if (next)
85
+ out.output = next;
86
+ }
87
+ else if (a === "--capture-values")
88
+ out.captureValues = true;
89
+ else if (a === "--quiet")
90
+ out.quiet = true;
91
+ else if (a === "--json")
92
+ out.json = true;
93
+ else if (a === "--fail-on") {
94
+ const next = args[++i];
95
+ if (next)
96
+ out.failOn = next;
97
+ }
98
+ else if (a === "--repo-id") {
99
+ const next = args[++i];
100
+ if (next)
101
+ out.repoId = next;
102
+ }
103
+ }
104
+ return out;
105
+ }
106
+ main(process.argv.slice(2)).then((code) => process.exit(code), (err) => {
107
+ process.stderr.write(`Unhandled error: ${errorStack(err)}\n`);
108
+ process.exit(1);
109
+ });
110
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACvC,OAAO,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAG1D,MAAM,OAAO,GAAG,OAAO,CAAC;AAExB,MAAM,IAAI,GAAG;;;;;;;;;;;;;;;;;;CAkBZ,CAAC;AAEF,KAAK,UAAU,IAAI,CAAC,IAAc;IAChC,MAAM,GAAG,GAAG,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC;IAC9B,IAAI,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACtD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,OAAO,IAAI,CAAC,CAAC;QACrC,OAAO,CAAC,CAAC;IACX,CAAC;IACD,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACnD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC3B,OAAO,CAAC,CAAC;IACX,CAAC;IAED,MAAM,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;IAC5B,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC3B,OAAO,CAAC,CAAC;IACX,CAAC;IAED,IAAI,GAAG,KAAK,MAAM,EAAE,CAAC;QACnB,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;QAC/B,MAAM,QAAQ,GAAgB;YAC5B,UAAU,EAAE,KAAK,CAAC,MAAM,IAAI,iCAAiC;YAC7D,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,IAAI,CAAC;SAC1C,CAAC;QACF,IAAI,KAAK,CAAC,MAAM;YAAE,QAAQ,CAAC,cAAc,GAAG,KAAK,CAAC,MAAM,CAAC;QACzD,IAAI,KAAK,CAAC,aAAa;YAAE,QAAQ,CAAC,qBAAqB,GAAG,IAAI,CAAC;QAC/D,IAAI,KAAK,CAAC,MAAM;YAAE,QAAQ,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;QACjD,IAAI,KAAK,CAAC,MAAM;YAAE,QAAQ,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;QACjD,MAAM,CAAC,GAAG,MAAM,OAAO,CAAC,QAAQ,CAAC,CAAC;QAClC,OAAO,CAAC,CAAC,QAAQ,CAAC;IACpB,CAAC;IAED,IAAI,GAAG,KAAK,MAAM,EAAE,CAAC;QACnB,IAAI,CAAC;YACH,MAAM,OAAO,CAAC,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;YACtC,OAAO,CAAC,CAAC;QACX,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,gBAAgB,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAC1D,OAAO,CAAC,CAAC;QACX,CAAC;IACH,CAAC;IAED,GAAG,CAAC,KAAK,CAAC,oBAAoB,GAAG,KAAK,IAAI,EAAE,CAAC,CAAC;IAC9C,OAAO,CAAC,CAAC;AACX,CAAC;AAYD,SAAS,UAAU,CAAC,IAAc;IAChC,MAAM,GAAG,GAAU,EAAE,CAAC;IACtB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,IAAI,CAAC,KAAK,SAAS;YAAE,SAAS;QAC9B,IAAI,CAAC,KAAK,UAAU,EAAE,CAAC;YACrB,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;YACvB,IAAI,IAAI;gBAAE,GAAG,CAAC,MAAM,GAAG,IAAI,CAAC;QAC9B,CAAC;aAAM,IAAI,CAAC,KAAK,UAAU,EAAE,CAAC;YAC5B,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;YACvB,IAAI,IAAI;gBAAE,GAAG,CAAC,MAAM,GAAG,IAAI,CAAC;QAC9B,CAAC;aAAM,IAAI,CAAC,KAAK,kBAAkB;YAAE,GAAG,CAAC,aAAa,GAAG,IAAI,CAAC;aACzD,IAAI,CAAC,KAAK,SAAS;YAAE,GAAG,CAAC,KAAK,GAAG,IAAI,CAAC;aACtC,IAAI,CAAC,KAAK,QAAQ;YAAE,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC;aACpC,IAAI,CAAC,KAAK,WAAW,EAAE,CAAC;YAC3B,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;YACvB,IAAI,IAAI;gBAAE,GAAG,CAAC,MAAM,GAAG,IAAI,CAAC;QAC9B,CAAC;aAAM,IAAI,CAAC,KAAK,WAAW,EAAE,CAAC;YAC7B,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;YACvB,IAAI,IAAI;gBAAE,GAAG,CAAC,MAAM,GAAG,IAAI,CAAC;QAC9B,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAC9B,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAC5B,CAAC,GAAG,EAAE,EAAE;IACN,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,oBAAoB,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC9D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CACF,CAAC"}
@@ -0,0 +1,6 @@
1
+ export type InitOptions = {
2
+ cwd: string;
3
+ outputPath?: string;
4
+ };
5
+ export declare function runInit(opts: InitOptions): Promise<void>;
6
+ export declare function runInitCli(_argv: string[]): Promise<number>;
@@ -0,0 +1,61 @@
1
+ import { writeFile, stat, readFile } from "node:fs/promises";
2
+ import { basename, isAbsolute, resolve } from "node:path";
3
+ import { errorMessage } from "@component-compass/ast-utils";
4
+ const TEMPLATE = (repoId) => ({
5
+ $schema: "https://unpkg.com/@component-compass/cli/schema/config.schema.json",
6
+ repoId,
7
+ include: ["src/**/*.{ts,tsx,jsx,js,vue,html}"],
8
+ exclude: ["**/*.{test,spec,stories}.*", "**/node_modules/**"],
9
+ packageScopes: [],
10
+ captureValues: false,
11
+ output: "./component-compass.json",
12
+ tagRules: [],
13
+ });
14
+ export async function runInit(opts) {
15
+ const cwd = isAbsolute(opts.cwd) ? opts.cwd : resolve(opts.cwd);
16
+ const out = opts.outputPath ?? resolve(cwd, "component-compass.config.json");
17
+ // Don't clobber existing config.
18
+ try {
19
+ await stat(out);
20
+ throw new Error(`Config already exists at ${out}. Refusing to overwrite.`);
21
+ }
22
+ catch (err) {
23
+ const e = err;
24
+ if (e.code !== "ENOENT") {
25
+ // If the stat succeeded (no ENOENT), the throw above re-fires here. Detect
26
+ // by message and re-throw cleanly.
27
+ if (e.message?.startsWith("Config already exists"))
28
+ throw e;
29
+ throw err;
30
+ }
31
+ }
32
+ const repoId = await deriveRepoId(cwd);
33
+ const cfg = TEMPLATE(repoId);
34
+ await writeFile(out, `${JSON.stringify(cfg, null, 2)}\n`, "utf8");
35
+ // eslint-disable-next-line no-console
36
+ console.log(`Wrote ${out}.\nEdit packageScopes to declare which DS packages to track.`);
37
+ }
38
+ async function deriveRepoId(cwd) {
39
+ try {
40
+ const pkgRaw = await readFile(resolve(cwd, "package.json"), "utf8");
41
+ const pkg = JSON.parse(pkgRaw);
42
+ if (pkg.name)
43
+ return pkg.name;
44
+ }
45
+ catch {
46
+ // ignore
47
+ }
48
+ return basename(cwd) || "unknown";
49
+ }
50
+ export async function runInitCli(_argv) {
51
+ const cwd = process.cwd();
52
+ try {
53
+ await runInit({ cwd });
54
+ return 0;
55
+ }
56
+ catch (err) {
57
+ process.stderr.write(`init failed: ${errorMessage(err)}\n`);
58
+ return 1;
59
+ }
60
+ }
61
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ export type ScanOptions = {
2
+ configPath: string;
3
+ outputOverride?: string;
4
+ captureValuesOverride?: boolean;
5
+ quiet?: boolean;
6
+ failOn?: string;
7
+ repoId?: string;
8
+ };
9
+ export type ScanResult = {
10
+ exitCode: number;
11
+ };
12
+ export declare function runScan(opts: ScanOptions): Promise<ScanResult>;
@@ -0,0 +1,147 @@
1
+ import { performance } from "node:perf_hooks";
2
+ import { isAbsolute, resolve } from "node:path";
3
+ import { readFile } from "node:fs/promises";
4
+ import { loadConfig, ConfigError } from "../config/loader.js";
5
+ import { runDiscovery } from "../manifest/run-discovery.js";
6
+ import { buildComponentIndex } from "../manifest/index.js";
7
+ import { buildLocalIndex } from "../local-index/index.js";
8
+ import { walkFiles } from "../walker/files.js";
9
+ import { createImportResolver } from "../walker/resolve-import.js";
10
+ import { Dispatcher } from "../dispatcher.js";
11
+ import { reactPlugin } from "@component-compass/parser-react";
12
+ import { htmlPlugin } from "@component-compass/parser-html";
13
+ import { litTemplatePlugin } from "@component-compass/parser-lit";
14
+ import { vuePlugin } from "@component-compass/parser-vue";
15
+ import { writeJson } from "../reporter/json.js";
16
+ import { printSummary } from "../reporter/stdout.js";
17
+ import { buildScanEnvelope } from "../envelope/index.js";
18
+ import { isPnpProject } from "../util/pnp-check.js";
19
+ import { Logger } from "../util/log.js";
20
+ import { errorMessage } from "@component-compass/ast-utils";
21
+ import { buildComponentSeeds } from "../seeds.js";
22
+ import { parseResultsToOccurrences } from "../occurrences.js";
23
+ import { buildScanOutput } from "../reporter/index.js";
24
+ export async function runScan(opts) {
25
+ const log = new Logger(opts.quiet);
26
+ const t0 = performance.now();
27
+ let cfg;
28
+ try {
29
+ cfg = await loadConfig(opts.configPath);
30
+ }
31
+ catch (err) {
32
+ if (err instanceof ConfigError) {
33
+ log.error(err.message);
34
+ return { exitCode: 2 };
35
+ }
36
+ throw err;
37
+ }
38
+ if (isPnpProject(cfg.configDir)) {
39
+ log.error("yarn PnP detected; component-compass requires nodeLinker: node-modules. See docs/usage.md.");
40
+ return { exitCode: 2 };
41
+ }
42
+ if (opts.outputOverride)
43
+ cfg.output = opts.outputOverride;
44
+ if (opts.captureValuesOverride !== undefined)
45
+ cfg.captureValues = opts.captureValuesOverride;
46
+ const discovery = runDiscovery({
47
+ repoRoot: cfg.configDir,
48
+ packageScopes: cfg.packageScopes,
49
+ manifestSources: cfg.manifestSources ?? {},
50
+ });
51
+ const cems = discovery.manifests;
52
+ for (const d of discovery.diagnostics) {
53
+ if (d.code === "no-manifest-found") {
54
+ log.warn(`[component-compass] "${d.packageName}" matched packageScopes but no manifest could be resolved (root, re-export chain, manifestSources). Components from this package will surface with manifest: null.`);
55
+ }
56
+ else if (d.code === "untraceable-barrel") {
57
+ log.warn(`[component-compass] "${d.packageName}" resolved to ${d.resolvedFile} which has no statically-traceable re-exports (likely bundled). Add an entry under manifestSources to point at the source packages.`);
58
+ }
59
+ else if (d.code === "cycle-detected") {
60
+ log.warn(`[component-compass] cycle detected in re-export chain at ${d.file}. Truncating.`);
61
+ }
62
+ }
63
+ const { warnings: _compIndexWarnings, ...compIndexBase } = buildComponentIndex(cems);
64
+ const localIndex = await buildLocalIndex({ repoRoot: cfg.configDir });
65
+ const compIndex = { ...compIndexBase, local: localIndex };
66
+ const files = await walkFiles({
67
+ root: cfg.configDir,
68
+ include: cfg.include,
69
+ exclude: cfg.exclude,
70
+ });
71
+ if (files.length === 0) {
72
+ log.warn(`No files matched include globs: ${cfg.include.join(", ")}`);
73
+ }
74
+ const dispatcher = new Dispatcher([reactPlugin, htmlPlugin, litTemplatePlugin, vuePlugin]);
75
+ const resolveImportOpts = {
76
+ repoRoot: cfg.configDir,
77
+ };
78
+ if (cfg.aliases)
79
+ resolveImportOpts.aliases = cfg.aliases;
80
+ if (cfg.tsconfigPath) {
81
+ resolveImportOpts.tsconfigPath = isAbsolute(cfg.tsconfigPath)
82
+ ? cfg.tsconfigPath
83
+ : resolve(cfg.configDir, cfg.tsconfigPath);
84
+ }
85
+ const resolveImport = createImportResolver(resolveImportOpts);
86
+ const results = [];
87
+ for (const file of files) {
88
+ const source = await readFile(file, "utf8").catch(() => "");
89
+ if (!source)
90
+ continue;
91
+ for (const plugin of dispatcher.allPluginsFor(file)) {
92
+ try {
93
+ results.push(plugin.parse(file, source, {
94
+ index: compIndex,
95
+ config: cfg,
96
+ resolveImport,
97
+ repoRoot: cfg.configDir,
98
+ }));
99
+ }
100
+ catch (err) {
101
+ log.warn(`[component-compass] parse failure in ${file}: ${errorMessage(err)}`);
102
+ }
103
+ }
104
+ }
105
+ const t1 = performance.now();
106
+ const envelope = buildScanEnvelope({
107
+ cwd: cfg.configDir,
108
+ cliRepoIdFlag: opts.repoId,
109
+ });
110
+ const seeds = buildComponentSeeds(compIndex, results, cfg.tagRules);
111
+ const occurrences = parseResultsToOccurrences(results, cfg.captureValues);
112
+ const manifests = manifestsToRefs(cems);
113
+ const partialStats = {
114
+ filesScanned: files.length,
115
+ filesWithUsage: countFilesWithUsage(occurrences),
116
+ scanDurationMs: Math.round(t1 - t0),
117
+ };
118
+ const scanOutput = buildScanOutput(envelope, manifests, partialStats, seeds, occurrences);
119
+ const outputPath = isAbsolute(cfg.output) ? cfg.output : resolve(cfg.configDir, cfg.output);
120
+ await writeJson(scanOutput, outputPath);
121
+ if (!opts.quiet) {
122
+ printSummary(scanOutput, outputPath);
123
+ }
124
+ let exitCode = 0;
125
+ if (opts.failOn === "deprecated-usage") {
126
+ const hasDeprecated = scanOutput.components.some((c) => c.manifest?.lifecycle?.status === "deprecated" &&
127
+ c.stats.occurrenceCount > 0);
128
+ if (hasDeprecated)
129
+ exitCode = 1;
130
+ }
131
+ return { exitCode };
132
+ }
133
+ function countFilesWithUsage(occurrences) {
134
+ const files = new Set();
135
+ for (const o of occurrences)
136
+ files.add(o.filePath);
137
+ return files.size;
138
+ }
139
+ function manifestsToRefs(manifests) {
140
+ return manifests.map((m) => ({
141
+ source: m.kind === "cem" ? "cem" : m.manifest.source,
142
+ package: m.packageName,
143
+ path: m.path,
144
+ version: m.packageVersion ?? null,
145
+ }));
146
+ }
147
+ //# sourceMappingURL=scan.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scan.js","sourceRoot":"","sources":["../../src/commands/scan.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import type { ResolvedConfig } from "../types.js";
2
+ export declare class ConfigError extends Error {
3
+ code: "CONFIG_MISSING" | "CONFIG_INVALID";
4
+ constructor(code: "CONFIG_MISSING" | "CONFIG_INVALID", message: string);
5
+ }
6
+ export declare function loadConfig(configPath: string): Promise<ResolvedConfig>;
@@ -0,0 +1,62 @@
1
+ import { readFile, stat } from "node:fs/promises";
2
+ import { dirname, isAbsolute, resolve } from "node:path";
3
+ import { validateConfig } from "./schema.js";
4
+ import { errorMessage } from "@component-compass/ast-utils";
5
+ export class ConfigError extends Error {
6
+ code;
7
+ constructor(code, message) {
8
+ super(message);
9
+ this.code = code;
10
+ }
11
+ }
12
+ export async function loadConfig(configPath) {
13
+ const abs = isAbsolute(configPath) ? configPath : resolve(process.cwd(), configPath);
14
+ try {
15
+ await stat(abs);
16
+ }
17
+ catch {
18
+ throw new ConfigError("CONFIG_MISSING", `component-compass config not found at ${abs}. Run \`component-compass init\` to scaffold one.`);
19
+ }
20
+ const raw = await readFile(abs, "utf8");
21
+ let parsed;
22
+ try {
23
+ parsed = JSON.parse(raw);
24
+ }
25
+ catch (err) {
26
+ throw new ConfigError("CONFIG_INVALID", `${abs} is not valid JSON: ${errorMessage(err)}`);
27
+ }
28
+ // Pre-validation legacy field detection so we surface a migration message
29
+ // rather than a generic "additional property" AJV error.
30
+ if (parsed && typeof parsed === "object" && "manifests" in parsed) {
31
+ throw new ConfigError("CONFIG_INVALID", `${abs}: the \`manifests\` field was removed. Replace with \`packageScopes\` (array of glob patterns matching package names). See docs/usage.md.`);
32
+ }
33
+ if (!validateConfig(parsed)) {
34
+ const issues = (validateConfig.errors ?? [])
35
+ .map((e) => `${e.instancePath || "<root>"}: ${e.message}`)
36
+ .join("; ");
37
+ throw new ConfigError("CONFIG_INVALID", `Invalid config at ${abs}: ${issues}`);
38
+ }
39
+ // parsed is now narrowed to ConfigFile by the typed validator.
40
+ const resolved = {
41
+ configPath: abs,
42
+ configDir: dirname(abs),
43
+ repoId: parsed.repoId,
44
+ packageScopes: parsed.packageScopes,
45
+ include: parsed.include,
46
+ exclude: parsed.exclude ?? [],
47
+ captureValues: parsed.captureValues ?? false,
48
+ output: parsed.output ?? "./component-compass.json",
49
+ };
50
+ // Optional passthroughs — only assigned when present so we satisfy
51
+ // `exactOptionalPropertyTypes` (undefined ≠ absent).
52
+ if (parsed.manifestSources !== undefined)
53
+ resolved.manifestSources = parsed.manifestSources;
54
+ if (parsed.tsconfigPath !== undefined)
55
+ resolved.tsconfigPath = parsed.tsconfigPath;
56
+ if (parsed.aliases !== undefined)
57
+ resolved.aliases = parsed.aliases;
58
+ if (parsed.tagRules !== undefined)
59
+ resolved.tagRules = parsed.tagRules;
60
+ return resolved;
61
+ }
62
+ //# sourceMappingURL=loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/config/loader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzD,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAE5D,MAAM,OAAO,WAAY,SAAQ,KAAK;IACjB;IAAnB,YAAmB,IAAyC,EAAE,OAAe;QAC3E,KAAK,CAAC,OAAO,CAAC,CAAC;QADE,SAAI,GAAJ,IAAI,CAAqC;IAE5D,CAAC;CACF;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,UAAkB;IACjD,MAAM,GAAG,GAAG,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,UAAU,CAAC,CAAC;IAErF,IAAI,CAAC;QACH,MAAM,IAAI,CAAC,GAAG,CAAC,CAAC;IAClB,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,WAAW,CACnB,gBAAgB,EAChB,yCAAyC,GAAG,mDAAmD,CAChG,CAAC;IACJ,CAAC;IAED,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IACxC,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,WAAW,CAAC,gBAAgB,EAAE,GAAG,GAAG,uBAAuB,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC5F,CAAC;IAED,0EAA0E;IAC1E,yDAAyD;IACzD,IAAI,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,WAAW,IAAI,MAAM,EAAE,CAAC;QAClE,MAAM,IAAI,WAAW,CACnB,gBAAgB,EAChB,GAAG,GAAG,2IAA2I,CAClJ,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,EAAE,CAAC;QAC5B,MAAM,MAAM,GAAG,CAAC,cAAc,CAAC,MAAM,IAAI,EAAE,CAAC;aACzC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,YAAY,IAAI,QAAQ,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC;aACzD,IAAI,CAAC,IAAI,CAAC,CAAC;QACd,MAAM,IAAI,WAAW,CAAC,gBAAgB,EAAE,qBAAqB,GAAG,KAAK,MAAM,EAAE,CAAC,CAAC;IACjF,CAAC;IAED,+DAA+D;IAC/D,MAAM,QAAQ,GAAmB;QAC/B,UAAU,EAAE,GAAG;QACf,SAAS,EAAE,OAAO,CAAC,GAAG,CAAC;QACvB,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,aAAa,EAAE,MAAM,CAAC,aAAa;QACnC,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,OAAO,EAAE,MAAM,CAAC,OAAO,IAAI,EAAE;QAC7B,aAAa,EAAE,MAAM,CAAC,aAAa,IAAI,KAAK;QAC5C,MAAM,EAAE,MAAM,CAAC,MAAM,IAAI,0BAA0B;KACpD,CAAC;IACF,mEAAmE;IACnE,qDAAqD;IACrD,IAAI,MAAM,CAAC,eAAe,KAAK,SAAS;QAAE,QAAQ,CAAC,eAAe,GAAG,MAAM,CAAC,eAAe,CAAC;IAC5F,IAAI,MAAM,CAAC,YAAY,KAAK,SAAS;QAAE,QAAQ,CAAC,YAAY,GAAG,MAAM,CAAC,YAAY,CAAC;IACnF,IAAI,MAAM,CAAC,OAAO,KAAK,SAAS;QAAE,QAAQ,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC;IACpE,IAAI,MAAM,CAAC,QAAQ,KAAK,SAAS;QAAE,QAAQ,CAAC,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC;IACvE,OAAO,QAAQ,CAAC;AAClB,CAAC"}
@@ -0,0 +1,32 @@
1
+ import type { ValidateFunction } from "ajv";
2
+ /**
3
+ * A single tag rule maps imports from a matching package to an arbitrary tag
4
+ * string surfaced on Component identities. v1 only supports matching by
5
+ * `packageName` (exact); the schema's `additionalProperties: false` on `match`
6
+ * rejects other keys with a clear validation error.
7
+ */
8
+ export type TagRule = {
9
+ tag: string;
10
+ match: {
11
+ packageName: string;
12
+ };
13
+ };
14
+ /**
15
+ * Shape of a parsed component-compass.config.json after AJV validation.
16
+ * Mirrors schema/config.schema.json. loader.ts applies defaults for optional
17
+ * fields when producing ResolvedConfig.
18
+ */
19
+ export interface ConfigFile {
20
+ repoId: string;
21
+ packageScopes: string[];
22
+ manifestSources?: Record<string, string[]>;
23
+ include: string[];
24
+ exclude?: string[];
25
+ captureValues?: boolean;
26
+ output?: string;
27
+ $schema?: string;
28
+ tsconfigPath?: string;
29
+ aliases?: Record<string, string[]>;
30
+ tagRules?: TagRule[];
31
+ }
32
+ export declare const validateConfig: ValidateFunction<ConfigFile>;
@@ -0,0 +1,15 @@
1
+ import { createRequire } from "node:module";
2
+ import { readFileSync } from "node:fs";
3
+ import { fileURLToPath } from "node:url";
4
+ import { dirname, resolve } from "node:path";
5
+ // ajv is a CJS-only package. Same situation as @babel/traverse: under
6
+ // module: NodeNext, the bare default import is the namespace, not the class.
7
+ // createRequire is Node's official escape hatch for loading CJS from ESM.
8
+ const require = createRequire(import.meta.url);
9
+ const Ajv = require("ajv").default ?? require("ajv");
10
+ const __dirname = dirname(fileURLToPath(import.meta.url));
11
+ const schemaPath = resolve(__dirname, "../../schema/config.schema.json");
12
+ const schemaJson = JSON.parse(readFileSync(schemaPath, "utf8"));
13
+ const ajv = new Ajv({ allErrors: true, strict: false });
14
+ export const validateConfig = ajv.compile(schemaJson);
15
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/config/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAG5C,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAE7C,sEAAsE;AACtE,6EAA6E;AAC7E,0EAA0E;AAC1E,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC/C,MAAM,GAAG,GAA2B,OAAO,CAAC,KAAK,CAAC,CAAC,OAAO,IAAI,OAAO,CAAC,KAAK,CAAC,CAAC;AAE7E,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC1D,MAAM,UAAU,GAAG,OAAO,CAAC,SAAS,EAAE,iCAAiC,CAAC,CAAC;AACzE,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC;AA6BhE,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;AACxD,MAAM,CAAC,MAAM,cAAc,GACzB,GAAG,CAAC,OAAO,CAAa,UAAU,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { TagRule } from "./schema.js";
2
+ export declare function evaluateTagRules(packageName: string | null, rules: TagRule[] | undefined): string[];
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Pre-computes the list of tags that apply to a Component identity given its
3
+ * resolved `packageName` and the user's configured `tagRules`. Pure function;
4
+ * called once per Component during scan-time identity assembly.
5
+ *
6
+ * v1 rules match by `packageName` only, with `*` as the sole glob metacharacter
7
+ * (zero-or-more chars). All other regex metacharacters are escaped so patterns
8
+ * are interpreted literally. See spec §6.
9
+ *
10
+ * Local components (those without a resolved package) have `packageName === null`
11
+ * and never match any rule.
12
+ */
13
+ const REGEX_META = /[.+?^${}()|[\]\\]/g;
14
+ const cache = new Map();
15
+ function matcher(pattern) {
16
+ const cached = cache.get(pattern);
17
+ if (cached)
18
+ return cached;
19
+ const compiled = new RegExp(`^${pattern.replace(REGEX_META, "\\$&").replace(/\*/g, ".*")}$`);
20
+ cache.set(pattern, compiled);
21
+ return compiled;
22
+ }
23
+ export function evaluateTagRules(packageName, rules) {
24
+ if (packageName === null || !rules || rules.length === 0)
25
+ return [];
26
+ const tags = [];
27
+ for (const rule of rules) {
28
+ if (matcher(rule.match.packageName).test(packageName)) {
29
+ tags.push(rule.tag);
30
+ }
31
+ }
32
+ return tags;
33
+ }
34
+ //# sourceMappingURL=tag-rules.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tag-rules.js","sourceRoot":"","sources":["../../src/config/tag-rules.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;GAWG;AAEH,MAAM,UAAU,GAAG,oBAAoB,CAAC;AAExC,MAAM,KAAK,GAAG,IAAI,GAAG,EAAkB,CAAC;AAExC,SAAS,OAAO,CAAC,OAAe;IAC9B,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAClC,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC;IAC1B,MAAM,QAAQ,GAAG,IAAI,MAAM,CACzB,IAAI,OAAO,CAAC,OAAO,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,CAChE,CAAC;IACF,KAAK,CAAC,GAAG,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IAC7B,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,gBAAgB,CAC9B,WAA0B,EAC1B,KAA4B;IAE5B,IAAI,WAAW,KAAK,IAAI,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IACpE,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;YACtD,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACtB,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { ParserPlugin } from "@component-compass/plugin-core";
2
+ export declare class Dispatcher {
3
+ plugins: ParserPlugin[];
4
+ private byExt;
5
+ constructor(plugins: ParserPlugin[]);
6
+ pluginFor(file: string): ParserPlugin | undefined;
7
+ allPluginsFor(file: string): ParserPlugin[];
8
+ }
@@ -0,0 +1,22 @@
1
+ import { extname } from "node:path";
2
+ export class Dispatcher {
3
+ plugins;
4
+ byExt = new Map();
5
+ constructor(plugins) {
6
+ this.plugins = plugins;
7
+ for (const p of plugins) {
8
+ for (const ext of p.extensions) {
9
+ const list = this.byExt.get(ext) ?? [];
10
+ list.push(p);
11
+ this.byExt.set(ext, list);
12
+ }
13
+ }
14
+ }
15
+ pluginFor(file) {
16
+ return this.allPluginsFor(file)[0];
17
+ }
18
+ allPluginsFor(file) {
19
+ return this.byExt.get(extname(file)) ?? [];
20
+ }
21
+ }
22
+ //# sourceMappingURL=dispatcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dispatcher.js","sourceRoot":"","sources":["../src/dispatcher.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,MAAM,OAAO,UAAU;IAGF;IAFX,KAAK,GAAG,IAAI,GAAG,EAA0B,CAAC;IAElD,YAAmB,OAAuB;QAAvB,YAAO,GAAP,OAAO,CAAgB;QACxC,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;YACxB,KAAK,MAAM,GAAG,IAAI,CAAC,CAAC,UAAU,EAAE,CAAC;gBAC/B,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;gBACvC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;gBACb,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;YAC5B,CAAC;QACH,CAAC;IACH,CAAC;IAED,SAAS,CAAC,IAAY;QACpB,OAAO,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IACrC,CAAC;IAED,aAAa,CAAC,IAAY;QACxB,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;IAC7C,CAAC;CACF"}
@@ -0,0 +1,13 @@
1
+ export declare function resolveCommitSha(cwd: string): string | null;
2
+ export declare function resolveBranch(cwd: string): string | null;
3
+ export declare function resolveOriginRemote(cwd: string): string | null;
4
+ /**
5
+ * Normalise a git remote URL to `host/owner/repo` form (no `.git` suffix).
6
+ * Accepts:
7
+ * - https://github.com/owner/repo.git
8
+ * - https://github.com/owner/repo
9
+ * - git@github.com:owner/repo.git
10
+ * - ssh://git@github.com/owner/repo.git
11
+ * - ssh://git@github.com:22/owner/repo.git
12
+ */
13
+ export declare function parseRemoteUrl(url: string): string | null;