@untangle-code/file-graph 0.0.0-stage → 0.1.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 (130) hide show
  1. package/LICENSE +661 -0
  2. package/NOTICE +90 -0
  3. package/README.md +284 -2
  4. package/THIRD_PARTY_LICENSES.md +29 -0
  5. package/dist/assignment.d.ts +15 -0
  6. package/dist/assignment.d.ts.map +1 -0
  7. package/dist/assignment.js +75 -0
  8. package/dist/assignment.js.map +1 -0
  9. package/dist/boundaries/endpoints.d.ts +11 -0
  10. package/dist/boundaries/endpoints.d.ts.map +1 -0
  11. package/dist/boundaries/endpoints.js +195 -0
  12. package/dist/boundaries/endpoints.js.map +1 -0
  13. package/dist/boundaries/index.d.ts +9 -0
  14. package/dist/boundaries/index.d.ts.map +1 -0
  15. package/dist/boundaries/index.js +93 -0
  16. package/dist/boundaries/index.js.map +1 -0
  17. package/dist/boundaries/requests.d.ts +12 -0
  18. package/dist/boundaries/requests.d.ts.map +1 -0
  19. package/dist/boundaries/requests.js +311 -0
  20. package/dist/boundaries/requests.js.map +1 -0
  21. package/dist/edges.d.ts +49 -0
  22. package/dist/edges.d.ts.map +1 -0
  23. package/dist/edges.js +223 -0
  24. package/dist/edges.js.map +1 -0
  25. package/dist/file-index.d.ts +37 -0
  26. package/dist/file-index.d.ts.map +1 -0
  27. package/dist/file-index.js +103 -0
  28. package/dist/file-index.js.map +1 -0
  29. package/dist/graph.d.ts +160 -0
  30. package/dist/graph.d.ts.map +1 -0
  31. package/dist/graph.js +448 -0
  32. package/dist/graph.js.map +1 -0
  33. package/dist/index.d.ts +35 -0
  34. package/dist/index.d.ts.map +1 -0
  35. package/dist/index.js +48 -0
  36. package/dist/index.js.map +1 -0
  37. package/dist/metrics.d.ts +67 -0
  38. package/dist/metrics.d.ts.map +1 -0
  39. package/dist/metrics.js +272 -0
  40. package/dist/metrics.js.map +1 -0
  41. package/dist/package-catalog.d.ts +43 -0
  42. package/dist/package-catalog.d.ts.map +1 -0
  43. package/dist/package-catalog.js +136 -0
  44. package/dist/package-catalog.js.map +1 -0
  45. package/dist/paths.d.ts +56 -0
  46. package/dist/paths.d.ts.map +1 -0
  47. package/dist/paths.js +129 -0
  48. package/dist/paths.js.map +1 -0
  49. package/dist/persistence.d.ts +83 -0
  50. package/dist/persistence.d.ts.map +1 -0
  51. package/dist/persistence.js +538 -0
  52. package/dist/persistence.js.map +1 -0
  53. package/dist/resolve/candidates.d.ts +52 -0
  54. package/dist/resolve/candidates.d.ts.map +1 -0
  55. package/dist/resolve/candidates.js +202 -0
  56. package/dist/resolve/candidates.js.map +1 -0
  57. package/dist/resolve/package-exports.d.ts +31 -0
  58. package/dist/resolve/package-exports.d.ts.map +1 -0
  59. package/dist/resolve/package-exports.js +229 -0
  60. package/dist/resolve/package-exports.js.map +1 -0
  61. package/dist/resolve/pipeline.d.ts +11 -0
  62. package/dist/resolve/pipeline.d.ts.map +1 -0
  63. package/dist/resolve/pipeline.js +109 -0
  64. package/dist/resolve/pipeline.js.map +1 -0
  65. package/dist/resolve/resolvers.d.ts +25 -0
  66. package/dist/resolve/resolvers.d.ts.map +1 -0
  67. package/dist/resolve/resolvers.js +367 -0
  68. package/dist/resolve/resolvers.js.map +1 -0
  69. package/dist/restore.d.ts +75 -0
  70. package/dist/restore.d.ts.map +1 -0
  71. package/dist/restore.js +136 -0
  72. package/dist/restore.js.map +1 -0
  73. package/dist/topology/compose.d.ts +27 -0
  74. package/dist/topology/compose.d.ts.map +1 -0
  75. package/dist/topology/compose.js +208 -0
  76. package/dist/topology/compose.js.map +1 -0
  77. package/dist/topology/jsonc.d.ts +38 -0
  78. package/dist/topology/jsonc.d.ts.map +1 -0
  79. package/dist/topology/jsonc.js +137 -0
  80. package/dist/topology/jsonc.js.map +1 -0
  81. package/dist/topology/load.d.ts +61 -0
  82. package/dist/topology/load.d.ts.map +1 -0
  83. package/dist/topology/load.js +436 -0
  84. package/dist/topology/load.js.map +1 -0
  85. package/dist/topology/manifest.d.ts +48 -0
  86. package/dist/topology/manifest.d.ts.map +1 -0
  87. package/dist/topology/manifest.js +109 -0
  88. package/dist/topology/manifest.js.map +1 -0
  89. package/dist/topology/project-config.d.ts +39 -0
  90. package/dist/topology/project-config.d.ts.map +1 -0
  91. package/dist/topology/project-config.js +150 -0
  92. package/dist/topology/project-config.js.map +1 -0
  93. package/dist/topology/workspace-definition.d.ts +26 -0
  94. package/dist/topology/workspace-definition.d.ts.map +1 -0
  95. package/dist/topology/workspace-definition.js +104 -0
  96. package/dist/topology/workspace-definition.js.map +1 -0
  97. package/dist/traverse.d.ts +49 -0
  98. package/dist/traverse.d.ts.map +1 -0
  99. package/dist/traverse.js +167 -0
  100. package/dist/traverse.js.map +1 -0
  101. package/dist/types.d.ts +332 -0
  102. package/dist/types.d.ts.map +1 -0
  103. package/dist/types.js +2 -0
  104. package/dist/types.js.map +1 -0
  105. package/package.json +63 -3
  106. package/src/assignment.ts +83 -0
  107. package/src/boundaries/endpoints.ts +273 -0
  108. package/src/boundaries/index.ts +118 -0
  109. package/src/boundaries/requests.ts +411 -0
  110. package/src/edges.ts +334 -0
  111. package/src/file-index.ts +127 -0
  112. package/src/graph.ts +591 -0
  113. package/src/index.ts +58 -0
  114. package/src/metrics.ts +350 -0
  115. package/src/package-catalog.ts +145 -0
  116. package/src/paths.ts +138 -0
  117. package/src/persistence.ts +746 -0
  118. package/src/resolve/candidates.ts +230 -0
  119. package/src/resolve/package-exports.ts +268 -0
  120. package/src/resolve/pipeline.ts +140 -0
  121. package/src/resolve/resolvers.ts +468 -0
  122. package/src/restore.ts +201 -0
  123. package/src/topology/compose.ts +268 -0
  124. package/src/topology/jsonc.ts +147 -0
  125. package/src/topology/load.ts +644 -0
  126. package/src/topology/manifest.ts +132 -0
  127. package/src/topology/project-config.ts +183 -0
  128. package/src/topology/workspace-definition.ts +115 -0
  129. package/src/traverse.ts +232 -0
  130. package/src/types.ts +372 -0
@@ -0,0 +1,272 @@
1
+ import { FILE_GRAPH_VERSION, compareCodepoints } from "@untangle-code/domain";
2
+ /** Benannte Formel hinter `FileGraphCentralityEntryV1.centrality`. */
3
+ export const CENTRALITY_FORMULA = "degree-centrality-v1: (inDegree + outDegree) / (2 * max(1, nodeCount - 1)), clamped to [0, 1]";
4
+ export const DEFAULT_GRAPH_LIMITS = {
5
+ maxCycles: 1_000,
6
+ topCentralCount: 25,
7
+ maxCycleSearchNodes: 200_000,
8
+ };
9
+ /**
10
+ * Baut die Nachbarschaft aus den Kanten.
11
+ *
12
+ * Nur `resolved`-Kanten mit einem Ziel INNERHALB der Knotenmenge zaehlen —
13
+ * eine externe Abhaengigkeit hat keinen Knoten, und eine unaufgeloeste erst
14
+ * recht nicht. Beide bleiben als Kante erhalten und in der
15
+ * Import-Resolution-Rate sichtbar, sie sind nur keine Graphverbindung.
16
+ */
17
+ export function buildAdjacency(nodeIds, edges) {
18
+ const known = new Set(nodeIds);
19
+ const forwardSets = new Map();
20
+ const reverseSets = new Map();
21
+ for (const id of nodeIds) {
22
+ forwardSets.set(id, new Set());
23
+ reverseSets.set(id, new Set());
24
+ }
25
+ for (const edge of edges) {
26
+ if (edge.resolution.status !== "resolved")
27
+ continue;
28
+ const target = edge.resolution.targetFileId;
29
+ if (!known.has(edge.fromFileId) || !known.has(target))
30
+ continue;
31
+ forwardSets.get(edge.fromFileId)?.add(target);
32
+ reverseSets.get(target)?.add(edge.fromFileId);
33
+ }
34
+ const forward = new Map();
35
+ const reverse = new Map();
36
+ for (const id of nodeIds) {
37
+ forward.set(id, [...(forwardSets.get(id) ?? [])].sort(compareCodepoints));
38
+ reverse.set(id, [...(reverseSets.get(id) ?? [])].sort(compareCodepoints));
39
+ }
40
+ return { forward, reverse };
41
+ }
42
+ /**
43
+ * Stark zusammenhaengende Komponenten nach Tarjan, iterativ.
44
+ *
45
+ * Ergebnis enthaelt NUR Komponenten mit mehr als einem Knoten — eine
46
+ * einelementige Komponente ohne Selbstschleife ist kein Befund. Selbstbezuege
47
+ * kommen ueber `findCycles` als einelementige Zyklen zurueck.
48
+ */
49
+ export function stronglyConnectedComponents(nodeIds, forward) {
50
+ const index = new Map();
51
+ const lowlink = new Map();
52
+ const onStack = new Set();
53
+ const stack = [];
54
+ const components = [];
55
+ let counter = 0;
56
+ for (const root of nodeIds) {
57
+ if (index.has(root))
58
+ continue;
59
+ const work = [{ node: root, childIndex: 0 }];
60
+ index.set(root, counter);
61
+ lowlink.set(root, counter);
62
+ counter += 1;
63
+ stack.push(root);
64
+ onStack.add(root);
65
+ while (work.length > 0) {
66
+ const frame = work[work.length - 1];
67
+ const children = forward.get(frame.node) ?? [];
68
+ if (frame.childIndex < children.length) {
69
+ const child = children[frame.childIndex];
70
+ frame.childIndex += 1;
71
+ if (!index.has(child)) {
72
+ index.set(child, counter);
73
+ lowlink.set(child, counter);
74
+ counter += 1;
75
+ stack.push(child);
76
+ onStack.add(child);
77
+ work.push({ node: child, childIndex: 0 });
78
+ }
79
+ else if (onStack.has(child)) {
80
+ lowlink.set(frame.node, Math.min(lowlink.get(frame.node), index.get(child)));
81
+ }
82
+ continue;
83
+ }
84
+ work.pop();
85
+ const parent = work[work.length - 1];
86
+ if (parent !== undefined) {
87
+ lowlink.set(parent.node, Math.min(lowlink.get(parent.node), lowlink.get(frame.node)));
88
+ }
89
+ if (lowlink.get(frame.node) === index.get(frame.node)) {
90
+ const component = [];
91
+ for (;;) {
92
+ const popped = stack.pop();
93
+ onStack.delete(popped);
94
+ component.push(popped);
95
+ if (popped === frame.node)
96
+ break;
97
+ }
98
+ if (component.length > 1) {
99
+ components.push(component.sort(compareCodepoints));
100
+ }
101
+ }
102
+ }
103
+ }
104
+ components.sort((left, right) => compareCodepoints(left[0], right[0]));
105
+ return components;
106
+ }
107
+ /**
108
+ * Zaehlt elementare Zyklen auf, komponentenweise und gegen ein Budget.
109
+ *
110
+ * Vorgehen: je stark zusammenhaengender Komponente wird von jedem Knoten aus
111
+ * gesucht, aber nur ueber Knoten, die in der komponenteninternen Ordnung NICHT
112
+ * VOR dem Startknoten liegen. Damit wird jeder Zyklus genau einmal gefunden
113
+ * (an seinem kleinsten Knoten) statt einmal je Rotation.
114
+ */
115
+ export function findCycles(nodeIds, forward, components, limits) {
116
+ const cycles = [];
117
+ let steps = 0;
118
+ let truncationReason;
119
+ // Selbstbezuege: eine Datei, die sich selbst importiert. Auch sie zaehlen
120
+ // gegen das Budget — sonst koennte eine Liste voller Selbstbezuege das
121
+ // Limit ueberschreiten, ohne dass es jemand erfaehrt.
122
+ for (const node of nodeIds) {
123
+ if (!(forward.get(node) ?? []).includes(node))
124
+ continue;
125
+ if (cycles.length >= limits.maxCycles) {
126
+ truncationReason = `cycle enumeration stopped at maxCycles=${String(limits.maxCycles)}; more elementary cycles exist`;
127
+ break;
128
+ }
129
+ cycles.push([node]);
130
+ }
131
+ for (const component of components) {
132
+ if (truncationReason !== undefined)
133
+ break;
134
+ const members = [...component].sort(compareCodepoints);
135
+ const rank = new Map(members.map((id, position) => [id, position]));
136
+ for (const start of members) {
137
+ if (truncationReason !== undefined)
138
+ break;
139
+ const startRank = rank.get(start);
140
+ const path = [start];
141
+ const onPath = new Set([start]);
142
+ const work = [{ node: start, childIndex: 0 }];
143
+ while (work.length > 0) {
144
+ if (cycles.length >= limits.maxCycles) {
145
+ truncationReason = `cycle enumeration stopped at maxCycles=${String(limits.maxCycles)}; more elementary cycles exist`;
146
+ break;
147
+ }
148
+ if (steps >= limits.maxCycleSearchNodes) {
149
+ truncationReason = `cycle enumeration stopped at maxCycleSearchNodes=${String(limits.maxCycleSearchNodes)}; the cycle list is incomplete`;
150
+ break;
151
+ }
152
+ steps += 1;
153
+ const frame = work[work.length - 1];
154
+ const children = forward.get(frame.node) ?? [];
155
+ if (frame.childIndex >= children.length) {
156
+ work.pop();
157
+ const removed = path.pop();
158
+ if (removed !== undefined)
159
+ onPath.delete(removed);
160
+ continue;
161
+ }
162
+ const child = children[frame.childIndex];
163
+ frame.childIndex += 1;
164
+ const childRank = rank.get(child);
165
+ if (childRank === undefined || childRank < startRank)
166
+ continue;
167
+ if (child === start) {
168
+ if (path.length > 1) {
169
+ cycles.push([...path]);
170
+ }
171
+ continue;
172
+ }
173
+ if (onPath.has(child))
174
+ continue;
175
+ path.push(child);
176
+ onPath.add(child);
177
+ work.push({ node: child, childIndex: 0 });
178
+ }
179
+ }
180
+ }
181
+ cycles.sort((left, right) => left.length - right.length || compareCodepoints(left.join("/"), right.join("/")));
182
+ return truncationReason === undefined ? { cycles } : { cycles, truncationReason };
183
+ }
184
+ /** Berechnet die vollstaendige Metrikaufstellung. */
185
+ export function computeFileGraphMetrics(input) {
186
+ const nodeIds = input.nodes.map((node) => node.fileId).sort(compareCodepoints);
187
+ const components = stronglyConnectedComponents(nodeIds, input.adjacency.forward);
188
+ const cycleSearch = findCycles(nodeIds, input.adjacency.forward, components, input.limits);
189
+ const orphanFileIds = [];
190
+ const centrality = [];
191
+ const denominator = 2 * Math.max(1, nodeIds.length - 1);
192
+ const pathById = new Map(input.nodes.map((node) => [node.fileId, node.filePath]));
193
+ for (const id of nodeIds) {
194
+ const outDegree = (input.adjacency.forward.get(id) ?? []).length;
195
+ const inDegree = (input.adjacency.reverse.get(id) ?? []).length;
196
+ if (outDegree === 0 && inDegree === 0) {
197
+ orphanFileIds.push(id);
198
+ }
199
+ centrality.push({
200
+ fileId: id,
201
+ filePath: pathById.get(id) ?? "",
202
+ inDegree,
203
+ outDegree,
204
+ centrality: Math.min(1, (inDegree + outDegree) / denominator),
205
+ });
206
+ }
207
+ const topCentralFiles = [...centrality]
208
+ .sort((left, right) => right.centrality - left.centrality ||
209
+ right.inDegree - left.inDegree ||
210
+ compareCodepoints(left.fileId, right.fileId))
211
+ .slice(0, Math.max(0, input.limits.topCentralCount));
212
+ let resolvedCount = 0;
213
+ let externalCount = 0;
214
+ let unresolvedCount = 0;
215
+ for (const edge of input.edges) {
216
+ switch (edge.resolution.status) {
217
+ case "resolved":
218
+ resolvedCount += 1;
219
+ break;
220
+ case "external":
221
+ externalCount += 1;
222
+ break;
223
+ case "unresolved":
224
+ unresolvedCount += 1;
225
+ break;
226
+ }
227
+ }
228
+ const total = resolvedCount + externalCount + unresolvedCount;
229
+ const repositoryDistribution = {};
230
+ const languageDistribution = {};
231
+ for (const node of [...input.nodes].sort((left, right) => compareCodepoints(left.fileId, right.fileId))) {
232
+ repositoryDistribution[node.repoId] = (repositoryDistribution[node.repoId] ?? 0) + 1;
233
+ languageDistribution[node.language] = (languageDistribution[node.language] ?? 0) + 1;
234
+ }
235
+ return {
236
+ schemaVersion: 1,
237
+ workspaceId: input.workspaceId,
238
+ graphGeneration: input.graphGeneration,
239
+ graphVersion: FILE_GRAPH_VERSION,
240
+ nodeCount: input.nodes.length,
241
+ edgeCount: input.edges.length,
242
+ orphanFileIds,
243
+ stronglyConnectedComponents: components,
244
+ cycles: cycleSearch.cycles,
245
+ importResolution: {
246
+ resolvedCount,
247
+ externalCount,
248
+ unresolvedCount,
249
+ rate: total === 0 ? 0 : resolvedCount / total,
250
+ },
251
+ repositoryDistribution: sortRecord(repositoryDistribution),
252
+ languageDistribution: sortRecord(languageDistribution),
253
+ topCentralFiles,
254
+ centralityFormula: CENTRALITY_FORMULA,
255
+ ...(cycleSearch.truncationReason === undefined
256
+ ? {}
257
+ : { truncationReason: cycleSearch.truncationReason }),
258
+ };
259
+ }
260
+ /**
261
+ * Kanonische Schluesselreihenfolge eines Zaehlerobjekts. Ohne sie haengt die
262
+ * Reihenfolge von der Einfuegereihenfolge ab — und damit das kanonische JSON
263
+ * und jeder daraus abgeleitete Hash.
264
+ */
265
+ function sortRecord(record) {
266
+ const sorted = {};
267
+ for (const key of Object.keys(record).sort(compareCodepoints)) {
268
+ sorted[key] = record[key];
269
+ }
270
+ return sorted;
271
+ }
272
+ //# sourceMappingURL=metrics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metrics.js","sourceRoot":"","sources":["../src/metrics.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,43 @@
1
+ import type { PackageLookupV1, WorkspacePackageCatalogV1, WorkspacePackageV1 } from "./types.js";
2
+ /** Stabile Ordnung des Katalogs: Name, Repository, Verzeichnis. */
3
+ export declare function comparePackages(left: WorkspacePackageV1, right: WorkspacePackageV1): number;
4
+ export declare class WorkspacePackageCatalog implements WorkspacePackageCatalogV1 {
5
+ private readonly entries;
6
+ private readonly byName;
7
+ private readonly byRepoAndName;
8
+ constructor(packages: readonly WorkspacePackageV1[]);
9
+ all(): readonly WorkspacePackageV1[];
10
+ byPackageName(name: string): readonly WorkspacePackageV1[];
11
+ /**
12
+ * Das Paket dieses Namens in diesem Repository — nur wenn es GENAU EINES
13
+ * gibt. Bei mehreren gleichnamigen Manifesten desselben Repositories ist
14
+ * `null` die einzige ehrliche Antwort; welches gemeint ist, steht nirgends,
15
+ * und `lookup` meldet den Fall als `ambiguous`.
16
+ */
17
+ inRepo(repoId: string, name: string): WorkspacePackageV1 | null;
18
+ /** Alle Pakete dieses Namens in diesem Repository, kanonisch geordnet. */
19
+ inRepoAll(repoId: string, name: string): readonly WorkspacePackageV1[];
20
+ has(name: string): boolean;
21
+ /**
22
+ * Sucht `name` aus der Sicht von `fromRepoId`.
23
+ *
24
+ * REIHENFOLGE UND IHR GRUND: Das eigene Repository zuerst — ein Manifest, das
25
+ * `shared-lib` deklariert, meint zuerst das `shared-lib`, das neben ihm
26
+ * liegt. Gibt es dort keines und genau EIN fremdes, ist der Cross-Repo-Bezug
27
+ * die einzige moegliche Lesart und damit ein Treffer. Gibt es mehrere
28
+ * fremde, ist der Bezug ohne weitere Angabe nicht entscheidbar — und dann
29
+ * wird geraten oder gemeldet. Geraten wird nicht.
30
+ */
31
+ lookup(fromRepoId: string, name: string): PackageLookupV1;
32
+ /**
33
+ * Namen, die von MEHR ALS EINEM Manifest deklariert werden,
34
+ * codepoint-sortiert.
35
+ *
36
+ * Frueher wurde hier `repos.size > 1` gefragt — damit blieb die Doppelung
37
+ * INNERHALB eines Repositories unsichtbar, obwohl genau sie einen Import
38
+ * unentscheidbar macht. Massstab ist die Zahl der Manifeste, nicht die der
39
+ * Repositories.
40
+ */
41
+ ambiguousNames(): readonly string[];
42
+ }
43
+ //# sourceMappingURL=package-catalog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"package-catalog.d.ts","sourceRoot":"","sources":["../src/package-catalog.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAE,eAAe,EAAE,yBAAyB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAEjG,mEAAmE;AACnE,wBAAgB,eAAe,CAAC,IAAI,EAAE,kBAAkB,EAAE,KAAK,EAAE,kBAAkB,GAAG,MAAM,CAO3F;AAED,qBAAa,uBAAwB,YAAW,yBAAyB;IACvE,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAuB;IAC/C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA2C;IAClE,OAAO,CAAC,QAAQ,CAAC,aAAa,CAA2C;gBAE7D,QAAQ,EAAE,SAAS,kBAAkB,EAAE;IA2BnD,GAAG,IAAI,SAAS,kBAAkB,EAAE;IAIpC,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,kBAAkB,EAAE;IAI1D;;;;;OAKG;IACH,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,kBAAkB,GAAG,IAAI;IAK/D,0EAA0E;IAC1E,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,kBAAkB,EAAE;IAItE,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAI1B;;;;;;;;;OASG;IACH,MAAM,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,eAAe;IAiBzD;;;;;;;;OAQG;IACH,cAAc,IAAI,SAAS,MAAM,EAAE;CAOpC"}
@@ -0,0 +1,136 @@
1
+ /**
2
+ * Der Paketkatalog des Workspace — nach Repository UND Name geschluesselt.
3
+ *
4
+ * WARUM NICHT NACH NAMEN ALLEIN: Ein Workspace darf aus mehreren Repositories
5
+ * bestehen (genau das ist der Cross-Repo-Fall, den dieses Paket koennen soll).
6
+ * Paketnamen sind dann NICHT eindeutig: zwei Repositories duerfen beide ein
7
+ * `shared-lib` enthalten, und in einem realen Bestand tun sie es auch — ein
8
+ * abgespaltener Fork, eine geteilte Bibliothek in zwei Staenden, ein
9
+ * gleichnamiges internes Hilfspaket. Ein `Map<name, package>` verliert in
10
+ * diesem Moment das frueher eingefuegte Paket ERSATZLOS: seine
11
+ * Abhaengigkeiten werden aus dem fremden Manifest gefuellt, seine Dateien
12
+ * werden nie mehr ueber den Katalog gefunden, und ein Import auf den Namen
13
+ * loest ins falsche Repository auf — gezaehlt als Erfolg.
14
+ *
15
+ * Der Katalog haelt deshalb ALLE gleichnamigen Pakete und beantwortet jede
16
+ * Frage aus der Sicht eines fragenden Repositories. Mehrdeutigkeit wird
17
+ * gemeldet, nicht aufgeloest (E4).
18
+ */
19
+ import { compareCodepoints } from "@untangle-code/domain";
20
+ /** Stabile Ordnung des Katalogs: Name, Repository, Verzeichnis. */
21
+ export function comparePackages(left, right) {
22
+ return (compareCodepoints(left.name, right.name) ||
23
+ compareCodepoints(left.repoId, right.repoId) ||
24
+ compareCodepoints(left.packageDir, right.packageDir) ||
25
+ compareCodepoints(left.manifestPath, right.manifestPath));
26
+ }
27
+ export class WorkspacePackageCatalog {
28
+ entries;
29
+ byName = new Map();
30
+ byRepoAndName = new Map();
31
+ constructor(packages) {
32
+ this.entries = [...packages].sort(comparePackages);
33
+ for (const entry of this.entries) {
34
+ const bucket = this.byName.get(entry.name);
35
+ if (bucket === undefined) {
36
+ this.byName.set(entry.name, [entry]);
37
+ }
38
+ else {
39
+ bucket.push(entry);
40
+ }
41
+ // Auch innerhalb EINES Repositories ist der Name nicht garantiert
42
+ // eindeutig: zwei Verzeichnisse duerfen dasselbe `name`-Feld tragen
43
+ // (ein kopiertes Paket, ein halb vollzogener Umzug). Das ist ein Fehler
44
+ // des Bestandes — aber ihn zu glaetten, indem der erste in kanonischer
45
+ // Ordnung gewinnt, ist GERATEN: der Bereich im Manifest des
46
+ // Importierenden kann sehr wohl auf das zweite zeigen. Der Katalog
47
+ // haelt deshalb auch hier ALLE Eintraege und laesst `lookup` melden
48
+ // statt entscheiden (E4).
49
+ const key = keyOf(entry.repoId, entry.name);
50
+ const owned = this.byRepoAndName.get(key);
51
+ if (owned === undefined) {
52
+ this.byRepoAndName.set(key, [entry]);
53
+ }
54
+ else {
55
+ owned.push(entry);
56
+ }
57
+ }
58
+ }
59
+ all() {
60
+ return this.entries;
61
+ }
62
+ byPackageName(name) {
63
+ return this.byName.get(name) ?? [];
64
+ }
65
+ /**
66
+ * Das Paket dieses Namens in diesem Repository — nur wenn es GENAU EINES
67
+ * gibt. Bei mehreren gleichnamigen Manifesten desselben Repositories ist
68
+ * `null` die einzige ehrliche Antwort; welches gemeint ist, steht nirgends,
69
+ * und `lookup` meldet den Fall als `ambiguous`.
70
+ */
71
+ inRepo(repoId, name) {
72
+ const owned = this.byRepoAndName.get(keyOf(repoId, name)) ?? [];
73
+ return owned.length === 1 ? owned[0] : null;
74
+ }
75
+ /** Alle Pakete dieses Namens in diesem Repository, kanonisch geordnet. */
76
+ inRepoAll(repoId, name) {
77
+ return this.byRepoAndName.get(keyOf(repoId, name)) ?? [];
78
+ }
79
+ has(name) {
80
+ return this.byName.has(name);
81
+ }
82
+ /**
83
+ * Sucht `name` aus der Sicht von `fromRepoId`.
84
+ *
85
+ * REIHENFOLGE UND IHR GRUND: Das eigene Repository zuerst — ein Manifest, das
86
+ * `shared-lib` deklariert, meint zuerst das `shared-lib`, das neben ihm
87
+ * liegt. Gibt es dort keines und genau EIN fremdes, ist der Cross-Repo-Bezug
88
+ * die einzige moegliche Lesart und damit ein Treffer. Gibt es mehrere
89
+ * fremde, ist der Bezug ohne weitere Angabe nicht entscheidbar — und dann
90
+ * wird geraten oder gemeldet. Geraten wird nicht.
91
+ */
92
+ lookup(fromRepoId, name) {
93
+ const own = this.inRepoAll(fromRepoId, name);
94
+ if (own.length === 1) {
95
+ return { status: "found", entry: own[0], crossRepo: false };
96
+ }
97
+ // Mehrere gleichnamige Pakete im EIGENEN Repository: nicht auf das erste
98
+ // ausweichen und erst recht nicht ins fremde Repository weitersuchen —
99
+ // beides waere geraten. Die Kandidaten sind die des eigenen Repositories.
100
+ if (own.length > 1)
101
+ return { status: "ambiguous", candidates: own };
102
+ const candidates = this.byPackageName(name);
103
+ if (candidates.length === 0)
104
+ return { status: "absent" };
105
+ if (candidates.length === 1) {
106
+ return { status: "found", entry: candidates[0], crossRepo: true };
107
+ }
108
+ return { status: "ambiguous", candidates };
109
+ }
110
+ /**
111
+ * Namen, die von MEHR ALS EINEM Manifest deklariert werden,
112
+ * codepoint-sortiert.
113
+ *
114
+ * Frueher wurde hier `repos.size > 1` gefragt — damit blieb die Doppelung
115
+ * INNERHALB eines Repositories unsichtbar, obwohl genau sie einen Import
116
+ * unentscheidbar macht. Massstab ist die Zahl der Manifeste, nicht die der
117
+ * Repositories.
118
+ */
119
+ ambiguousNames() {
120
+ const names = [];
121
+ for (const [name, bucket] of this.byName) {
122
+ if (bucket.length > 1)
123
+ names.push(name);
124
+ }
125
+ return names.sort(compareCodepoints);
126
+ }
127
+ }
128
+ /**
129
+ * U+001F als Trenner: derselbe Trenner wie in `file-index.ts`. Er kommt weder
130
+ * in einer Repository-ID noch in einem Paketnamen vor, also kann der
131
+ * Schluessel von ("ab", "c") nie mit dem von ("a", "bc") kollidieren.
132
+ */
133
+ function keyOf(repoId, name) {
134
+ return `${repoId}\u001f${name}`;
135
+ }
136
+ //# sourceMappingURL=package-catalog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"package-catalog.js","sourceRoot":"","sources":["../src/package-catalog.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Pfadhilfen des Dateigraphen — ausschliesslich POSIX, ausschliesslich
3
+ * repo-relativ.
4
+ *
5
+ * Warum eigene Helfer statt `node:path`: der Dateigraph rechnet nie auf
6
+ * Betriebssystempfaden. Er kennt nur `"/"`-normalisierte, repo-relative
7
+ * Pfade (spec.md §5.4), und `node:path` auf Windows wuerde aus `a/b`
8
+ * beim Zusammensetzen `a\b` machen — damit haette dieselbe Codebasis auf
9
+ * zwei Maschinen zwei verschiedene `file_id`s. `node:path/posix` deckt
10
+ * einen Teil ab, liefert aber `".."`-Ergebnisse ausserhalb der Wurzel
11
+ * still zurueck; hier wird das zu `null` und damit zu einem benannten
12
+ * Fehlschlag (E4).
13
+ */
14
+ /** Normalisiert Trennzeichen und entfernt fuehrende `"./"` sowie Mehrfachslashes. */
15
+ export declare function normalizePath(path: string): string;
16
+ /** Verzeichnisanteil eines repo-relativen Pfades; `""` fuer Dateien in der Wurzel. */
17
+ export declare function dirnameOf(path: string): string;
18
+ /** Dateiname ohne Verzeichnisanteil. */
19
+ export declare function basenameOf(path: string): string;
20
+ /** Erweiterung inklusive Punkt, kleingeschrieben; `""` bei Dotfiles und ohne Punkt. */
21
+ export declare function extensionOf(path: string): string;
22
+ /**
23
+ * Setzt einen Basispfad und ein Segment zusammen und loest `.`/`..` auf.
24
+ *
25
+ * Gibt `null` zurueck, wenn die Aufloesung ueber die Repositorywurzel
26
+ * hinauslaeuft. Ein Import wie `"../../../../etc/passwd"` aus `src/a.ts`
27
+ * ist damit ein benannter Fehlschlag und kein still auf `etc/passwd`
28
+ * gekuerzter Treffer.
29
+ */
30
+ export declare function joinRelative(baseDir: string, segment: string): string | null;
31
+ /** True, wenn `path` unterhalb von `directory` liegt (oder gleich ist). */
32
+ export declare function isWithin(directory: string, path: string): boolean;
33
+ /**
34
+ * Pfad von `path` relativ zu `directory`; `null`, wenn `path` nicht darunter
35
+ * liegt. Bewusst kein `..`-Ergebnis: der Aufrufer will hier wissen, ob etwas
36
+ * INNERHALB eines Verzeichnisses liegt, nicht wie man hinaufkommt.
37
+ */
38
+ export declare function relativeWithin(directory: string, path: string): string | null;
39
+ /** True fuer `"./x"`, `"../x"` und `"."`/`".."` selbst. */
40
+ export declare function isRelativeSpecifier(specifier: string): boolean;
41
+ /**
42
+ * Normalisiert nur die Trennzeichen und laesst einen fuehrenden `"/"` stehen.
43
+ *
44
+ * `normalizePath` ist fuer REPO-RELATIVE Pfade gedacht und entfernt deshalb
45
+ * einen fuehrenden Schraegstrich. Auf einen absoluten Wurzelpfad angewandt
46
+ * wuerde daraus ein relativer — und jeder Lesezugriff ginge ins Leere. Fuer
47
+ * absolute Pfade (Repositorywurzeln, Eintraege des Dateisystemports) gilt
48
+ * diese Funktion.
49
+ */
50
+ export declare function normalizeSeparators(path: string): string;
51
+ /**
52
+ * Pfad von `path` relativ zur absoluten Wurzel `root`; `null`, wenn `path`
53
+ * nicht darunter liegt. Beide Angaben sind absolut.
54
+ */
55
+ export declare function relativeToRoot(root: string, path: string): string | null;
56
+ //# sourceMappingURL=paths.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,qFAAqF;AACrF,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAUlD;AAED,sFAAsF;AACtF,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAI9C;AAED,wCAAwC;AACxC,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAI/C;AAED,uFAAuF;AACvF,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAOhD;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAkB5E;AAED,2EAA2E;AAC3E,wBAAgB,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAOjE;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAU7E;AAED,2DAA2D;AAC3D,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAE9D;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAGxD;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAQxE"}