@component-compass/cli 0.0.2 → 0.0.4

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 (112) hide show
  1. package/dist/cli.js +5 -1
  2. package/dist/cli.js.map +1 -1
  3. package/dist/commands/init.js +1 -3
  4. package/dist/commands/init.js.map +1 -1
  5. package/dist/commands/scan.d.ts +13 -1
  6. package/dist/commands/scan.js +192 -72
  7. package/dist/commands/scan.js.map +1 -1
  8. package/dist/composition-rollup.d.ts +16 -14
  9. package/dist/composition-rollup.js +33 -43
  10. package/dist/composition-rollup.js.map +1 -1
  11. package/dist/config/loader.js +5 -9
  12. package/dist/config/loader.js.map +1 -1
  13. package/dist/config/schema.d.ts +2 -15
  14. package/dist/config/schema.js.map +1 -1
  15. package/dist/envelope/index.d.ts +0 -9
  16. package/dist/envelope/index.js +1 -46
  17. package/dist/envelope/index.js.map +1 -1
  18. package/dist/identity.d.ts +19 -17
  19. package/dist/identity.js +42 -21
  20. package/dist/identity.js.map +1 -1
  21. package/dist/index.d.ts +2 -0
  22. package/dist/index.js +1 -0
  23. package/dist/index.js.map +1 -1
  24. package/dist/local-index/detect-react.d.ts +2 -1
  25. package/dist/local-index/detect-react.js +269 -72
  26. package/dist/local-index/detect-react.js.map +1 -1
  27. package/dist/local-index/detect-vue.d.ts +15 -1
  28. package/dist/local-index/detect-vue.js +130 -107
  29. package/dist/local-index/detect-vue.js.map +1 -1
  30. package/dist/local-index/detect-wc.d.ts +7 -1
  31. package/dist/local-index/detect-wc.js +56 -60
  32. package/dist/local-index/detect-wc.js.map +1 -1
  33. package/dist/local-index/index.d.ts +12 -4
  34. package/dist/local-index/index.js +40 -25
  35. package/dist/local-index/index.js.map +1 -1
  36. package/dist/manifest/barrel-parser.d.ts +10 -0
  37. package/dist/manifest/barrel-parser.js +11 -0
  38. package/dist/manifest/barrel-parser.js.map +1 -1
  39. package/dist/manifest/derived-manifest-stub.d.ts +16 -7
  40. package/dist/manifest/derived-manifest-stub.js +43 -7
  41. package/dist/manifest/derived-manifest-stub.js.map +1 -1
  42. package/dist/manifest/lazy-resolver.d.ts +52 -34
  43. package/dist/manifest/lazy-resolver.js +269 -69
  44. package/dist/manifest/lazy-resolver.js.map +1 -1
  45. package/dist/occurrences.d.ts +4 -4
  46. package/dist/occurrences.js +49 -9
  47. package/dist/occurrences.js.map +1 -1
  48. package/dist/parse-by-ext.d.ts +21 -0
  49. package/dist/parse-by-ext.js +53 -0
  50. package/dist/parse-by-ext.js.map +1 -0
  51. package/dist/reporter/index.d.ts +27 -28
  52. package/dist/reporter/index.js +99 -58
  53. package/dist/reporter/index.js.map +1 -1
  54. package/dist/reporter/stdout.js +4 -4
  55. package/dist/reporter/stdout.js.map +1 -1
  56. package/dist/rollup.d.ts +13 -6
  57. package/dist/rollup.js +9 -6
  58. package/dist/rollup.js.map +1 -1
  59. package/dist/scan/cem-index.d.ts +38 -0
  60. package/dist/scan/cem-index.js +139 -0
  61. package/dist/scan/cem-index.js.map +1 -0
  62. package/dist/scan/git-mtime.d.ts +2 -0
  63. package/dist/scan/git-mtime.js +22 -0
  64. package/dist/scan/git-mtime.js.map +1 -0
  65. package/dist/scan/meta.d.ts +5 -0
  66. package/dist/scan/meta.js +58 -0
  67. package/dist/scan/meta.js.map +1 -0
  68. package/dist/scan/stamp-deprecated.d.ts +16 -0
  69. package/dist/scan/stamp-deprecated.js +33 -0
  70. package/dist/scan/stamp-deprecated.js.map +1 -0
  71. package/dist/scan/stamp-version.d.ts +18 -0
  72. package/dist/scan/stamp-version.js +94 -0
  73. package/dist/scan/stamp-version.js.map +1 -0
  74. package/dist/seeds.d.ts +20 -19
  75. package/dist/seeds.js +136 -68
  76. package/dist/seeds.js.map +1 -1
  77. package/dist/types.d.ts +2 -5
  78. package/dist/util/git.d.ts +8 -0
  79. package/dist/util/git.js +73 -0
  80. package/dist/util/git.js.map +1 -1
  81. package/dist/util/progress.d.ts +21 -0
  82. package/dist/util/progress.js +54 -0
  83. package/dist/util/progress.js.map +1 -0
  84. package/dist/walker/files.d.ts +1 -0
  85. package/dist/walker/files.js +11 -5
  86. package/dist/walker/files.js.map +1 -1
  87. package/dist/workspace/build-graph.d.ts +2 -0
  88. package/dist/workspace/build-graph.js +117 -0
  89. package/dist/workspace/build-graph.js.map +1 -0
  90. package/dist/workspace/declared-deps.d.ts +5 -0
  91. package/dist/workspace/declared-deps.js +42 -0
  92. package/dist/workspace/declared-deps.js.map +1 -0
  93. package/dist/workspace/find-owning-package.d.ts +8 -0
  94. package/dist/workspace/find-owning-package.js +69 -0
  95. package/dist/workspace/find-owning-package.js.map +1 -0
  96. package/dist/workspace/index.d.ts +4 -0
  97. package/dist/workspace/index.js +4 -0
  98. package/dist/workspace/index.js.map +1 -0
  99. package/dist/workspace/types.d.ts +46 -0
  100. package/dist/workspace/types.js +13 -0
  101. package/dist/workspace/types.js.map +1 -0
  102. package/package.json +15 -7
  103. package/schema/config.schema.json +2 -24
  104. package/dist/config/tag-rules.d.ts +0 -2
  105. package/dist/config/tag-rules.js +0 -34
  106. package/dist/config/tag-rules.js.map +0 -1
  107. package/dist/local-index/walker.d.ts +0 -11
  108. package/dist/local-index/walker.js +0 -47
  109. package/dist/local-index/walker.js.map +0 -1
  110. package/dist/manifest/diagnostic-filter.d.ts +0 -12
  111. package/dist/manifest/diagnostic-filter.js +0 -23
  112. package/dist/manifest/diagnostic-filter.js.map +0 -1
@@ -0,0 +1,38 @@
1
+ /**
2
+ * A single entry in `CemIndex.byTag`.
3
+ *
4
+ * `manifest` is the **per-declaration** payload — one component's data, not
5
+ * the full package manifest. For CCM this is one entry from `components[]`;
6
+ * for CEM this is one declaration from `modules[].declarations[]`.
7
+ * Use `CemIndex.byPackageName` to retrieve the full-package manifest.
8
+ */
9
+ export type CemIndexEntry = {
10
+ packageName: string;
11
+ manifest: unknown;
12
+ };
13
+ export type CemIndex = {
14
+ byTag: Map<string, CemIndexEntry>;
15
+ byPackageName: Map<string, {
16
+ manifest: unknown;
17
+ }>;
18
+ };
19
+ /**
20
+ * Build a global CEM index from all packages reachable from `<root>/node_modules`.
21
+ *
22
+ * Yarn workspace packages are symlinked into `node_modules/<name>`, so they
23
+ * are indexed automatically alongside published dependencies. There's no
24
+ * separate workspace-enumeration pass — `node_modules` covers both.
25
+ *
26
+ * For each package found:
27
+ * - If it ships a `component-compass-manifest.json` (CCM), index its
28
+ * declarations. CCM takes precedence over CEM.
29
+ * - Otherwise, if it ships a CEM (`pkg.customElements` field or
30
+ * `custom-elements.json` at the package root), index its declarations.
31
+ *
32
+ * Each declaration with a `tagName` is added to `byTag`. Each package
33
+ * with any indexed manifest is added to `byPackageName`.
34
+ *
35
+ * @param root Absolute or relative path to the repository root containing
36
+ * a `node_modules` directory.
37
+ */
38
+ export declare function buildCemIndex(root: string): Promise<CemIndex>;
@@ -0,0 +1,139 @@
1
+ /**
2
+ * Global CEM index — built once at scan startup.
3
+ *
4
+ * Enumerates every package.json under <root>/node_modules, finds any
5
+ * CEM (`custom-elements.json`) or CCM (`component-compass-manifest.json`)
6
+ * files, and builds two lookup tables:
7
+ * - `byTag` tagName → { packageName, manifest }
8
+ * - `byPackageName` packageName → { manifest }
9
+ *
10
+ * CCM takes precedence over CEM when both exist.
11
+ *
12
+ * Parsers use `byTag` to resolve hyphenated tags (<pie-link>, <sl-button>)
13
+ * unconditionally — no consumer-side config required.
14
+ *
15
+ * Shape contract:
16
+ * - `byTag` entry.manifest is the **per-declaration** manifest payload —
17
+ * a single component's data, not the full package manifest. For CCM this
18
+ * is one entry from `components[]`; for CEM this is one declaration from
19
+ * `modules[].declarations[]`. Use `byPackageName` for the full-package view.
20
+ * - `byPackageName` entry.manifest is the full top-level manifest document
21
+ * (the CCM root object or the CEM root object).
22
+ */
23
+ import { readFile } from "node:fs/promises";
24
+ import { existsSync } from "node:fs";
25
+ import { join, dirname } from "node:path";
26
+ import { globby } from "globby";
27
+ /**
28
+ * Walk a CEM document and collect all custom-element declarations that carry a
29
+ * `tagName`. Returns each declaration object paired with its tag name so the
30
+ * caller can store the per-declaration entry in `byTag`.
31
+ */
32
+ function walkCemForTagDeclarations(cem) {
33
+ const results = [];
34
+ for (const mod of cem.modules ?? []) {
35
+ for (const decl of mod.declarations ?? []) {
36
+ if (decl.customElement === true && typeof decl.tagName === "string") {
37
+ results.push({ tagName: decl.tagName, decl });
38
+ }
39
+ }
40
+ }
41
+ return results;
42
+ }
43
+ /**
44
+ * Build a global CEM index from all packages reachable from `<root>/node_modules`.
45
+ *
46
+ * Yarn workspace packages are symlinked into `node_modules/<name>`, so they
47
+ * are indexed automatically alongside published dependencies. There's no
48
+ * separate workspace-enumeration pass — `node_modules` covers both.
49
+ *
50
+ * For each package found:
51
+ * - If it ships a `component-compass-manifest.json` (CCM), index its
52
+ * declarations. CCM takes precedence over CEM.
53
+ * - Otherwise, if it ships a CEM (`pkg.customElements` field or
54
+ * `custom-elements.json` at the package root), index its declarations.
55
+ *
56
+ * Each declaration with a `tagName` is added to `byTag`. Each package
57
+ * with any indexed manifest is added to `byPackageName`.
58
+ *
59
+ * @param root Absolute or relative path to the repository root containing
60
+ * a `node_modules` directory.
61
+ */
62
+ export async function buildCemIndex(root) {
63
+ const index = {
64
+ byTag: new Map(),
65
+ byPackageName: new Map(),
66
+ };
67
+ // Enumerate: unscoped node_modules/*/package.json and scoped node_modules/@*/*/package.json
68
+ const pkgJsonPaths = await globby([
69
+ "node_modules/*/package.json",
70
+ "node_modules/@*/*/package.json",
71
+ ], {
72
+ cwd: root,
73
+ absolute: true,
74
+ onlyFiles: true,
75
+ suppressErrors: true,
76
+ // Don't traverse into nested node_modules — only the top-level
77
+ // dependency tree is relevant for CEM discovery.
78
+ ignore: ["node_modules/*/node_modules/**", "node_modules/@*/*/node_modules/**"],
79
+ });
80
+ await Promise.all(pkgJsonPaths.map(async (pkgJsonPath) => {
81
+ const pkgDir = dirname(pkgJsonPath);
82
+ let pkg = null;
83
+ try {
84
+ pkg = JSON.parse(await readFile(pkgJsonPath, "utf8"));
85
+ }
86
+ catch {
87
+ return;
88
+ }
89
+ if (!pkg || typeof pkg.name !== "string")
90
+ return;
91
+ const packageName = pkg.name;
92
+ // CCM takes precedence: if both exist, CCM wins.
93
+ const ccmPath = join(pkgDir, "component-compass-manifest.json");
94
+ if (existsSync(ccmPath)) {
95
+ try {
96
+ const ccmJson = JSON.parse(await readFile(ccmPath, "utf8"));
97
+ // CCM format has `components[]` — custom-element entries carry tagName
98
+ if (ccmJson && Array.isArray(ccmJson.components)) {
99
+ for (const c of ccmJson.components) {
100
+ if (c.kind === "custom-element" && typeof c.tagName === "string") {
101
+ index.byTag.set(c.tagName, { packageName, manifest: c });
102
+ }
103
+ }
104
+ }
105
+ index.byPackageName.set(packageName, { manifest: ccmJson });
106
+ }
107
+ catch {
108
+ // Malformed CCM — skip.
109
+ }
110
+ return; // CCM found; don't also load CEM for this package.
111
+ }
112
+ // CEM: check `pkg.customElements` field first (authoritative path),
113
+ // then fall back to the conventional `custom-elements.json`.
114
+ const cemRelPath = typeof pkg.customElements === "string"
115
+ ? pkg.customElements
116
+ : "custom-elements.json";
117
+ const cemPath = join(pkgDir, cemRelPath);
118
+ if (!existsSync(cemPath))
119
+ return;
120
+ try {
121
+ const cemJson = JSON.parse(await readFile(cemPath, "utf8"));
122
+ const tagDecls = walkCemForTagDeclarations(cemJson);
123
+ // byPackageName is always populated for any CEM-shipping package,
124
+ // regardless of whether it declares any custom elements (e.g. mixin-only
125
+ // packages have no tagName entries but are still valid CEM consumers).
126
+ index.byPackageName.set(packageName, { manifest: cemJson });
127
+ for (const { tagName, decl } of tagDecls) {
128
+ // Store the per-declaration entry so byTag consumers get the specific
129
+ // component's data, not a haystack to search. Mirrors CCM behaviour.
130
+ index.byTag.set(tagName, { packageName, manifest: decl });
131
+ }
132
+ }
133
+ catch {
134
+ // Malformed CEM — skip.
135
+ }
136
+ }));
137
+ return index;
138
+ }
139
+ //# sourceMappingURL=cem-index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cem-index.js","sourceRoot":"","sources":["../../src/scan/cem-index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import type { OutputComponent } from "@component-compass/plugin-core";
2
+ export declare function stampGitMTime(root: string, components: OutputComponent[]): Promise<void>;
@@ -0,0 +1,22 @@
1
+ import { readFileMTimes } from "../util/git.js";
2
+ export async function stampGitMTime(root, components) {
3
+ const localPaths = new Set();
4
+ for (const c of components) {
5
+ if (c.identity.scope === "local" && c.identity.filePath) {
6
+ localPaths.add(c.identity.filePath);
7
+ }
8
+ }
9
+ const map = await readFileMTimes(root, [...localPaths]);
10
+ for (const c of components) {
11
+ if (c.identity.scope === "local" && c.identity.filePath) {
12
+ const range = map.get(c.identity.filePath);
13
+ c.createdAt = range?.firstCommitAt ?? null;
14
+ c.updatedAt = range?.lastCommitAt ?? null;
15
+ }
16
+ else {
17
+ c.createdAt = null;
18
+ c.updatedAt = null;
19
+ }
20
+ }
21
+ }
22
+ //# sourceMappingURL=git-mtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git-mtime.js","sourceRoot":"","sources":["../../src/scan/git-mtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAGhD,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,IAAY,EACZ,UAA6B;IAE7B,MAAM,UAAU,GAAG,IAAI,GAAG,EAAU,CAAC;IACrC,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;QAC3B,IAAI,CAAC,CAAC,QAAQ,CAAC,KAAK,KAAK,OAAO,IAAI,CAAC,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC;YACxD,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACtC,CAAC;IACH,CAAC;IACD,MAAM,GAAG,GAAG,MAAM,cAAc,CAAC,IAAI,EAAE,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC;IACxD,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;QAC3B,IAAI,CAAC,CAAC,QAAQ,CAAC,KAAK,KAAK,OAAO,IAAI,CAAC,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC;YACxD,MAAM,KAAK,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;YAC3C,CAAC,CAAC,SAAS,GAAG,KAAK,EAAE,aAAa,IAAI,IAAI,CAAC;YAC3C,CAAC,CAAC,SAAS,GAAG,KAAK,EAAE,YAAY,IAAI,IAAI,CAAC;QAC5C,CAAC;aAAM,CAAC;YACN,CAAC,CAAC,SAAS,GAAG,IAAI,CAAC;YACnB,CAAC,CAAC,SAAS,GAAG,IAAI,CAAC;QACrB,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1,5 @@
1
+ import type { ScanMeta } from "@component-compass/plugin-core";
2
+ export declare function stampMeta(opts: {
3
+ cwd: string;
4
+ repoIdOverride?: string;
5
+ }): Promise<ScanMeta>;
@@ -0,0 +1,58 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { basename, dirname, join, resolve } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ import { ulid } from "ulid";
5
+ import { readGitCommit, readGitRemote, readGitBranch, readInitialCommit } from "../util/git.js";
6
+ import { readToolVersion } from "../envelope/index.js";
7
+ export async function stampMeta(opts) {
8
+ const commit = await readGitCommit(opts.cwd);
9
+ if (!commit)
10
+ throw new Error(`not a git repository: ${opts.cwd}`);
11
+ const rawInitialCommit = await readInitialCommit(opts.cwd);
12
+ const initialCommit = rawInitialCommit ?? null;
13
+ if (!initialCommit) {
14
+ process.stderr.write("warn: initial commit unavailable (shallow clone?) — set fetch-depth: 0 in CI for stable repo identity\n");
15
+ }
16
+ const gitRemote = await readGitRemote(opts.cwd);
17
+ const branch = await readGitBranch(opts.cwd);
18
+ const id = opts.repoIdOverride ?? deriveId(gitRemote, opts.cwd);
19
+ return {
20
+ ccVersion: readToolVersion(findCliPackageRoot()),
21
+ scanId: ulid(),
22
+ scannedAt: new Date().toISOString(),
23
+ repo: { id, gitRemote, commit, initialCommit, branch },
24
+ };
25
+ }
26
+ function deriveId(remote, cwd) {
27
+ if (remote) {
28
+ const match = remote.match(/[/:]([^/]+?)(\.git)?$/);
29
+ if (match?.[1])
30
+ return match[1];
31
+ }
32
+ return basename(cwd);
33
+ }
34
+ /**
35
+ * Walk up from this module's directory until we find the @component-compass/cli
36
+ * package.json. Robust to running from dist/ or src/ (vitest) without
37
+ * hardcoding a relative depth. Mirrors the pattern in envelope/index.ts.
38
+ */
39
+ function findCliPackageRoot() {
40
+ let dir = dirname(fileURLToPath(import.meta.url));
41
+ for (let i = 0; i < 6; i++) {
42
+ const candidate = join(dir, "package.json");
43
+ try {
44
+ const parsed = JSON.parse(readFileSync(candidate, "utf8"));
45
+ if (parsed.name === "@component-compass/cli")
46
+ return dir;
47
+ }
48
+ catch {
49
+ // continue walking
50
+ }
51
+ const parent = resolve(dir, "..");
52
+ if (parent === dir)
53
+ break;
54
+ dir = parent;
55
+ }
56
+ return dirname(fileURLToPath(import.meta.url));
57
+ }
58
+ //# sourceMappingURL=meta.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"meta.js","sourceRoot":"","sources":["../../src/scan/meta.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import type { OutputComponent } from "@component-compass/plugin-core";
2
+ import type { CemIndex } from "./cem-index.js";
3
+ /**
4
+ * Stamp `deprecated: true` onto each custom-element component whose CEM
5
+ * declaration carries `deprecated: true` (or a reason string). All other
6
+ * components keep the default `deprecated: false` set during rollup.
7
+ *
8
+ * Sources checked, in priority order:
9
+ * 1. Global CEM index (built from node_modules at scan startup) — covers
10
+ * custom-elements resolved via the HTML/Lit/Vue tag-name path.
11
+ * 2. component.manifest?.data?.lifecycle?.status — covers components whose
12
+ * manifest was loaded via the lazy-resolver path.
13
+ *
14
+ * A component is deprecated when EITHER source says so.
15
+ */
16
+ export declare function stampDeprecated(components: OutputComponent[], cemIndex: CemIndex): void;
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Stamp `deprecated: true` onto each custom-element component whose CEM
3
+ * declaration carries `deprecated: true` (or a reason string). All other
4
+ * components keep the default `deprecated: false` set during rollup.
5
+ *
6
+ * Sources checked, in priority order:
7
+ * 1. Global CEM index (built from node_modules at scan startup) — covers
8
+ * custom-elements resolved via the HTML/Lit/Vue tag-name path.
9
+ * 2. component.manifest?.data?.lifecycle?.status — covers components whose
10
+ * manifest was loaded via the lazy-resolver path.
11
+ *
12
+ * A component is deprecated when EITHER source says so.
13
+ */
14
+ export function stampDeprecated(components, cemIndex) {
15
+ for (const c of components) {
16
+ // Manifest-lifecycle path: already captured via lazy-resolver enrichment.
17
+ if (c.manifest?.data?.lifecycle?.status === "deprecated") {
18
+ c.deprecated = true;
19
+ continue;
20
+ }
21
+ // CEM-index path: look up the tag name in the global CEM index.
22
+ if (c.identity.kind === "custom-element" && c.identity.tagName) {
23
+ const entry = cemIndex.byTag.get(c.identity.tagName);
24
+ if (entry) {
25
+ const rawDecl = entry.manifest;
26
+ if (rawDecl && rawDecl.deprecated !== undefined && rawDecl.deprecated !== false) {
27
+ c.deprecated = true;
28
+ }
29
+ }
30
+ }
31
+ }
32
+ }
33
+ //# sourceMappingURL=stamp-deprecated.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stamp-deprecated.js","sourceRoot":"","sources":["../../src/scan/stamp-deprecated.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,eAAe,CAC7B,UAA6B,EAC7B,QAAkB;IAElB,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;QAC3B,0EAA0E;QAC1E,IAAI,CAAC,CAAC,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,KAAK,YAAY,EAAE,CAAC;YACzD,CAAC,CAAC,UAAU,GAAG,IAAI,CAAC;YACpB,SAAS;QACX,CAAC;QAED,gEAAgE;QAChE,IAAI,CAAC,CAAC,QAAQ,CAAC,IAAI,KAAK,gBAAgB,IAAI,CAAC,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;YAC/D,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;YACrD,IAAI,KAAK,EAAE,CAAC;gBACV,MAAM,OAAO,GAAG,KAAK,CAAC,QAAoD,CAAC;gBAC3E,IAAI,OAAO,IAAI,OAAO,CAAC,UAAU,KAAK,SAAS,IAAI,OAAO,CAAC,UAAU,KAAK,KAAK,EAAE,CAAC;oBAChF,CAAC,CAAC,UAAU,GAAG,IAAI,CAAC;gBACtB,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1,18 @@
1
+ import type { OutputComponent, OutputOccurrence } from "@component-compass/plugin-core";
2
+ /**
3
+ * Reads each external/workspace package's `version` from its installed
4
+ * `package.json` and stamps it onto every component from that package.
5
+ * Local components keep `version: null`.
6
+ *
7
+ * Uses Node-style module resolution: walks upward from a representative
8
+ * occurrence's file directory through ancestor `node_modules` directories
9
+ * until the package is found. Starting from inside the sub-app that uses
10
+ * the package handles multi-app monorepos where deps are installed per-app
11
+ * (e.g. `pie-aperture/nextjs-app-v14/node_modules/`) rather than hoisted
12
+ * to the workspace root. Falls back to `startDir` for packages with no
13
+ * occurrences.
14
+ *
15
+ * Batches IO: one package.json read per unique external package name, not
16
+ * per component.
17
+ */
18
+ export declare function stampVersion(startDir: string, components: OutputComponent[], occurrences?: OutputOccurrence[]): Promise<void>;
@@ -0,0 +1,94 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import { join, dirname, resolve } from "node:path";
3
+ /**
4
+ * Reads each external/workspace package's `version` from its installed
5
+ * `package.json` and stamps it onto every component from that package.
6
+ * Local components keep `version: null`.
7
+ *
8
+ * Uses Node-style module resolution: walks upward from a representative
9
+ * occurrence's file directory through ancestor `node_modules` directories
10
+ * until the package is found. Starting from inside the sub-app that uses
11
+ * the package handles multi-app monorepos where deps are installed per-app
12
+ * (e.g. `pie-aperture/nextjs-app-v14/node_modules/`) rather than hoisted
13
+ * to the workspace root. Falls back to `startDir` for packages with no
14
+ * occurrences.
15
+ *
16
+ * Batches IO: one package.json read per unique external package name, not
17
+ * per component.
18
+ */
19
+ export async function stampVersion(startDir, components, occurrences = []) {
20
+ // Collect unique external package names.
21
+ const packageNames = new Set();
22
+ for (const c of components) {
23
+ if (c.identity.scope !== "local" && c.identity.packageName) {
24
+ packageNames.add(c.identity.packageName);
25
+ }
26
+ }
27
+ // componentId → packageName for fast occurrence → package lookup.
28
+ const pkgByComponentId = new Map();
29
+ for (const c of components) {
30
+ if (c.identity.scope !== "local" && c.identity.packageName) {
31
+ pkgByComponentId.set(c.id, c.identity.packageName);
32
+ }
33
+ }
34
+ // packageName → directory to start the walk-up from. Use the parent dir of
35
+ // any occurrence's file path (resolved relative to startDir). Multi-app
36
+ // monorepos install deps per-app, so walking up from inside the sub-app
37
+ // hits the per-app node_modules. Falls back to startDir for packages with
38
+ // no occurrences.
39
+ const starterDirByPackage = new Map();
40
+ for (const o of occurrences) {
41
+ const pkg = pkgByComponentId.get(o.componentId);
42
+ if (pkg && !starterDirByPackage.has(pkg)) {
43
+ starterDirByPackage.set(pkg, dirname(resolve(startDir, o.filePath)));
44
+ }
45
+ }
46
+ // Read each package.json once. Store null when not found / no version field.
47
+ const versionByPackage = new Map();
48
+ await Promise.all([...packageNames].map(async (name) => {
49
+ const searchFrom = starterDirByPackage.get(name) ?? startDir;
50
+ const version = await resolvePackageVersion(searchFrom, name);
51
+ versionByPackage.set(name, version);
52
+ }));
53
+ // Stamp each component.
54
+ for (const c of components) {
55
+ if (c.identity.scope !== "local" && c.identity.packageName) {
56
+ c.version = versionByPackage.get(c.identity.packageName) ?? null;
57
+ }
58
+ else {
59
+ c.version = null;
60
+ }
61
+ }
62
+ }
63
+ /**
64
+ * Walk up the directory tree from `startDir`, trying
65
+ * `<dir>/node_modules/<packageName>/package.json` at each level.
66
+ * Returns the `version` string, or null when not found anywhere.
67
+ */
68
+ async function resolvePackageVersion(startDir, packageName) {
69
+ let dir = startDir;
70
+ while (true) {
71
+ const pkgPath = join(dir, "node_modules", packageName, "package.json");
72
+ try {
73
+ const raw = await readFile(pkgPath, "utf8");
74
+ try {
75
+ const pkg = JSON.parse(raw);
76
+ return pkg.version ?? null;
77
+ }
78
+ catch {
79
+ // Malformed JSON — file exists, version unreadable.
80
+ return null;
81
+ }
82
+ }
83
+ catch {
84
+ // File not found or unreadable — try parent.
85
+ }
86
+ const parent = dirname(dir);
87
+ if (parent === dir) {
88
+ // Reached filesystem root.
89
+ return null;
90
+ }
91
+ dir = parent;
92
+ }
93
+ }
94
+ //# sourceMappingURL=stamp-version.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stamp-version.js","sourceRoot":"","sources":["../../src/scan/stamp-version.ts"],"names":[],"mappings":"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"}
package/dist/seeds.d.ts CHANGED
@@ -1,15 +1,14 @@
1
1
  /**
2
- * Builds per-component seeds from a resolver-emitted snapshot,
3
- * parser-emitted occurrences, and the workspace tag rules. Seeds are the
4
- * per-component input to `rollupOccurrencesToComponents`: they carry
5
- * identity, derivedTags, and manifest enrichment but no occurrence data
6
- * (that is merged separately during rollup).
2
+ * Builds per-component seeds from a resolver-emitted snapshot and
3
+ * parser-emitted occurrences. Seeds are the per-component input to
4
+ * `rollupOccurrencesToComponents`: they carry identity and manifest enrichment
5
+ * but no occurrence data (that is merged separately during rollup).
7
6
  *
8
7
  * Pure function; no I/O.
9
8
  */
10
- import type { IndexedComponent, ParseResult } from "@component-compass/plugin-core";
11
- import type { TagRule } from "./config/schema.js";
9
+ import type { IndexedComponent, LocalDefinitionIndex, ParseResult } from "@component-compass/plugin-core";
12
10
  import type { ComponentSeed } from "./rollup.js";
11
+ import type { WorkspaceGraph } from "./workspace/types.js";
13
12
  /**
14
13
  * One entry in the resolver snapshot. Each entry pairs an `IndexedComponent`
15
14
  * (the manifest-shaped record) with an `enrichmentSource` label distinguishing
@@ -24,17 +23,19 @@ export type SnapshotEntry = {
24
23
  * ComponentSeeds.
25
24
  *
26
25
  * Two sources contribute:
27
- * 1. Snapshotted componentsfull enrichment via `manifestComponentToOutput`,
28
- * labelled with the snapshot entry's `enrichmentSource`.
29
- * 2. Components observed in parser walks but absent from the snapshot —
30
- * emitted with `manifest: null` so they surface in `components[]` per
31
- * the realignment principle ("manifest is enrichment, not gate").
26
+ * 1. Components observed in parser walks carry `modulePath` from the
27
+ * resolver and surface with `manifest: null` initially.
28
+ * 2. Snapshotted components full enrichment via `manifestComponentToOutput`,
29
+ * labelled with the snapshot entry's `enrichmentSource`. Snapshot entries
30
+ * have NO `modulePath` (manifests don't carry that info), so their stable
31
+ * id differs from the parser-emitted seed for the same logical component.
32
+ * To avoid emitting a ghost component, we attach the snapshot's manifest
33
+ * enrichment to a matching parser-emitted seed when the match is
34
+ * unambiguous (exactly one parser seed with `{kind, packageName,
35
+ * exportName-or-tagName}`). Ambiguous matches fall through to a
36
+ * snapshot-only seed.
32
37
  *
33
- * Dedupe by stable id; snapshotted seeds win.
34
- *
35
- * Scope derivation follows the three-lane model in identity.ts:
36
- * - local → source.type === "local"
37
- * - ds → external + derivedTags.length > 0
38
- * - external → external + no matching tag rules
38
+ * Scope derivation: "local" for source.type === "local"; "external" otherwise.
39
+ * DS-grouping is the web app's responsibility — CC emits two scopes only.
39
40
  */
40
- export declare function buildComponentSeeds(snapshot: SnapshotEntry[], parseResults: ParseResult[], tagRules: TagRule[] | undefined): ComponentSeed[];
41
+ export declare function buildComponentSeeds(snapshot: SnapshotEntry[], parseResults: ParseResult[], localIndex?: LocalDefinitionIndex, repoRoot?: string, workspaceGraph?: WorkspaceGraph): ComponentSeed[];