patram 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/build-graph-identity.js +70 -84
- package/lib/build-graph.js +170 -18
- package/lib/build-graph.types.ts +1 -0
- package/lib/check-directive-metadata.js +20 -2
- package/lib/check-directive-value.js +9 -0
- package/lib/check-graph.js +1 -2
- package/lib/cli-help-metadata.js +12 -0
- package/lib/command-output.js +16 -1
- package/lib/discover-fields.js +9 -1
- package/lib/document-node-identity.js +317 -0
- package/lib/layout-stored-queries.js +122 -29
- package/lib/load-patram-config.js +1 -1
- package/lib/parse-where-clause.js +237 -66
- package/lib/parse-where-clause.types.ts +21 -6
- package/lib/patram-cli.js +34 -2
- package/lib/query-graph.js +29 -19
- package/lib/query-inspection.js +173 -68
- package/lib/render-field-discovery.js +44 -8
- package/lib/render-output-view.js +65 -19
- package/lib/render-rich-source.js +245 -14
- package/lib/show-document.js +15 -2
- package/package.json +1 -1
|
@@ -1,48 +1,19 @@
|
|
|
1
|
+
/** @import * as $k$$l$document$j$node$j$identity$k$js from './document-node-identity.js'; */
|
|
1
2
|
/**
|
|
2
3
|
* @import { GraphNode } from './build-graph.types.ts';
|
|
3
4
|
* @import { PatramClaim } from './parse-claims.types.ts';
|
|
4
|
-
* @import { MappingDefinition } from './patram-config.types.ts';
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import { posix } from 'node:path';
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
* Collect semantic entity keys defined by canonical documents.
|
|
11
|
-
*
|
|
12
|
-
* @param {Record<string, MappingDefinition>} mappings
|
|
13
|
-
* @param {PatramClaim[]} claims
|
|
14
|
-
* @returns {Map<string, string>}
|
|
15
|
-
*/
|
|
16
|
-
export function collectDocumentEntityKeys(mappings, claims) {
|
|
17
|
-
/** @type {Map<string, string>} */
|
|
18
|
-
const document_entity_keys = new Map();
|
|
19
|
-
|
|
20
|
-
for (const claim of claims) {
|
|
21
|
-
const mapping_definition = resolveMappingDefinition(mappings, claim);
|
|
22
|
-
|
|
23
|
-
if (mapping_definition?.node?.key !== 'value') {
|
|
24
|
-
continue;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
const source_path = normalizeRepoRelativePath(claim.origin.path);
|
|
28
|
-
const entity_map_key = getDocumentEntityMapKey(
|
|
29
|
-
source_path,
|
|
30
|
-
mapping_definition.node.class,
|
|
31
|
-
);
|
|
32
|
-
const entity_key = getStringClaimValue(claim);
|
|
33
|
-
const existing_entity_key = document_entity_keys.get(entity_map_key);
|
|
9
|
+
import { normalizeRepoRelativePath } from './document-node-identity.js';
|
|
34
10
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
document_entity_keys.set(entity_map_key, entity_key);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
return document_entity_keys;
|
|
45
|
-
}
|
|
11
|
+
export {
|
|
12
|
+
collectDocumentEntityKeys,
|
|
13
|
+
collectDocumentNodeReferences,
|
|
14
|
+
normalizeRepoRelativePath,
|
|
15
|
+
resolveDocumentNodeId,
|
|
16
|
+
} from './document-node-identity.js';
|
|
46
17
|
|
|
47
18
|
/**
|
|
48
19
|
* Resolve the node key for one mapped claim.
|
|
@@ -77,14 +48,16 @@ export function resolveNodeKey(node_mapping, claim, document_entity_keys) {
|
|
|
77
48
|
* @param {'path' | 'value'} target_type
|
|
78
49
|
* @param {PatramClaim} claim
|
|
79
50
|
* @param {Map<string, string>} document_entity_keys
|
|
51
|
+
* @param {Map<string, import('./document-node-identity.js').DocumentNodeReference>} document_node_references
|
|
80
52
|
* @param {Set<string>} document_paths
|
|
81
|
-
* @returns {{ key: string, path?: string }}
|
|
53
|
+
* @returns {{ class_name: string, key: string, path?: string }}
|
|
82
54
|
*/
|
|
83
55
|
export function resolveTargetReference(
|
|
84
56
|
target_class,
|
|
85
57
|
target_type,
|
|
86
58
|
claim,
|
|
87
59
|
document_entity_keys,
|
|
60
|
+
document_node_references,
|
|
88
61
|
document_paths,
|
|
89
62
|
) {
|
|
90
63
|
if (target_type === 'value') {
|
|
@@ -95,18 +68,19 @@ export function resolveTargetReference(
|
|
|
95
68
|
target_class,
|
|
96
69
|
claim,
|
|
97
70
|
document_entity_keys,
|
|
71
|
+
document_node_references,
|
|
98
72
|
document_paths,
|
|
99
73
|
);
|
|
100
74
|
}
|
|
101
75
|
|
|
102
76
|
/**
|
|
103
|
-
* Attach one canonical path to a
|
|
77
|
+
* Attach one canonical path to a graph node.
|
|
104
78
|
*
|
|
105
79
|
* @param {GraphNode} graph_node
|
|
106
80
|
* @param {string | undefined} source_path
|
|
107
81
|
*/
|
|
108
|
-
export function
|
|
109
|
-
if (!source_path
|
|
82
|
+
export function setCanonicalPath(graph_node, source_path) {
|
|
83
|
+
if (!source_path) {
|
|
110
84
|
return;
|
|
111
85
|
}
|
|
112
86
|
|
|
@@ -123,58 +97,24 @@ export function setNonDocumentPath(graph_node, source_path) {
|
|
|
123
97
|
}
|
|
124
98
|
}
|
|
125
99
|
|
|
126
|
-
/**
|
|
127
|
-
* Normalize one repo-relative source path.
|
|
128
|
-
*
|
|
129
|
-
* @param {string} source_path
|
|
130
|
-
* @returns {string}
|
|
131
|
-
*/
|
|
132
|
-
export function normalizeRepoRelativePath(source_path) {
|
|
133
|
-
return posix.normalize(source_path.replaceAll('\\', '/'));
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
/**
|
|
137
|
-
* @param {Record<string, MappingDefinition>} mappings
|
|
138
|
-
* @param {PatramClaim} claim
|
|
139
|
-
* @returns {MappingDefinition | null}
|
|
140
|
-
*/
|
|
141
|
-
function resolveMappingDefinition(mappings, claim) {
|
|
142
|
-
if (claim.type === 'directive') {
|
|
143
|
-
return resolveDirectiveMapping(mappings, claim);
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
return mappings[claim.type] ?? null;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
/**
|
|
150
|
-
* @param {Record<string, MappingDefinition>} mappings
|
|
151
|
-
* @param {PatramClaim} claim
|
|
152
|
-
* @returns {MappingDefinition | null}
|
|
153
|
-
*/
|
|
154
|
-
function resolveDirectiveMapping(mappings, claim) {
|
|
155
|
-
if (!claim.parser || !claim.name) {
|
|
156
|
-
return null;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
return mappings[`${claim.parser}.directive.${claim.name}`] ?? null;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
100
|
/**
|
|
163
101
|
* @param {string} target_kind
|
|
164
102
|
* @param {PatramClaim} claim
|
|
165
|
-
* @returns {{ key: string, path?: string }}
|
|
103
|
+
* @returns {{ class_name: string, key: string, path?: string }}
|
|
166
104
|
*/
|
|
167
105
|
function resolveValueTargetReference(target_kind, claim) {
|
|
168
106
|
const target_key = getStringClaimValue(claim);
|
|
169
107
|
|
|
170
108
|
if (target_kind === 'document') {
|
|
171
109
|
return {
|
|
110
|
+
class_name: 'document',
|
|
172
111
|
key: target_key,
|
|
173
112
|
path: target_key,
|
|
174
113
|
};
|
|
175
114
|
}
|
|
176
115
|
|
|
177
116
|
return {
|
|
117
|
+
class_name: target_kind,
|
|
178
118
|
key: target_key,
|
|
179
119
|
path: normalizeRepoRelativePath(claim.origin.path),
|
|
180
120
|
};
|
|
@@ -184,13 +124,15 @@ function resolveValueTargetReference(target_kind, claim) {
|
|
|
184
124
|
* @param {string} target_class
|
|
185
125
|
* @param {PatramClaim} claim
|
|
186
126
|
* @param {Map<string, string>} document_entity_keys
|
|
127
|
+
* @param {Map<string, import('./document-node-identity.js').DocumentNodeReference>} document_node_references
|
|
187
128
|
* @param {Set<string>} document_paths
|
|
188
|
-
* @returns {{ key: string, path?: string }}
|
|
129
|
+
* @returns {{ class_name: string, key: string, path?: string }}
|
|
189
130
|
*/
|
|
190
131
|
function resolvePathTargetReference(
|
|
191
132
|
target_class,
|
|
192
133
|
claim,
|
|
193
134
|
document_entity_keys,
|
|
135
|
+
document_node_references,
|
|
194
136
|
document_paths,
|
|
195
137
|
) {
|
|
196
138
|
const raw_target = getPathTargetValue(claim);
|
|
@@ -201,18 +143,51 @@ function resolvePathTargetReference(
|
|
|
201
143
|
);
|
|
202
144
|
|
|
203
145
|
if (target_class === 'document') {
|
|
146
|
+
return resolveDocumentTargetReference(
|
|
147
|
+
target_path,
|
|
148
|
+
document_node_references,
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const document_node_reference = document_node_references.get(target_path);
|
|
153
|
+
|
|
154
|
+
if (documentNodeReferenceIsPromoted(document_node_reference)) {
|
|
204
155
|
return {
|
|
205
|
-
|
|
156
|
+
class_name: document_node_reference.class_name,
|
|
157
|
+
key: document_node_reference.key,
|
|
206
158
|
path: target_path,
|
|
207
159
|
};
|
|
208
160
|
}
|
|
209
161
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
162
|
+
return {
|
|
163
|
+
class_name: target_class,
|
|
164
|
+
key:
|
|
165
|
+
document_entity_keys.get(
|
|
166
|
+
getDocumentEntityMapKey(target_path, target_class),
|
|
167
|
+
) ?? target_path,
|
|
168
|
+
path: target_path,
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* @param {string} target_path
|
|
174
|
+
* @param {Map<string, import('./document-node-identity.js').DocumentNodeReference>} document_node_references
|
|
175
|
+
* @returns {{ class_name: string, key: string, path?: string }}
|
|
176
|
+
*/
|
|
177
|
+
function resolveDocumentTargetReference(target_path, document_node_references) {
|
|
178
|
+
const document_node_reference = document_node_references.get(target_path);
|
|
179
|
+
|
|
180
|
+
if (!document_node_reference) {
|
|
181
|
+
return {
|
|
182
|
+
class_name: 'document',
|
|
183
|
+
key: target_path,
|
|
184
|
+
path: target_path,
|
|
185
|
+
};
|
|
186
|
+
}
|
|
213
187
|
|
|
214
188
|
return {
|
|
215
|
-
|
|
189
|
+
class_name: document_node_reference.class_name,
|
|
190
|
+
key: document_node_reference.key,
|
|
216
191
|
path: target_path,
|
|
217
192
|
};
|
|
218
193
|
}
|
|
@@ -269,3 +244,14 @@ function getStringClaimValue(claim) {
|
|
|
269
244
|
function getDocumentEntityMapKey(document_path, class_name) {
|
|
270
245
|
return `${class_name}:${document_path}`;
|
|
271
246
|
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* @param {import('./document-node-identity.js').DocumentNodeReference | undefined} document_node_reference
|
|
250
|
+
* @returns {document_node_reference is $k$$l$document$j$node$j$identity$k$js.DocumentNodeReference}
|
|
251
|
+
*/
|
|
252
|
+
function documentNodeReferenceIsPromoted(document_node_reference) {
|
|
253
|
+
return (
|
|
254
|
+
document_node_reference !== undefined &&
|
|
255
|
+
document_node_reference.class_name !== 'document'
|
|
256
|
+
);
|
|
257
|
+
}
|
package/lib/build-graph.js
CHANGED
|
@@ -10,10 +10,11 @@ import { posix } from 'node:path';
|
|
|
10
10
|
|
|
11
11
|
import {
|
|
12
12
|
collectDocumentEntityKeys,
|
|
13
|
+
collectDocumentNodeReferences,
|
|
13
14
|
normalizeRepoRelativePath,
|
|
14
15
|
resolveNodeKey,
|
|
15
16
|
resolveTargetReference,
|
|
16
|
-
|
|
17
|
+
setCanonicalPath,
|
|
17
18
|
} from './build-graph-identity.js';
|
|
18
19
|
|
|
19
20
|
/**
|
|
@@ -52,6 +53,10 @@ const EXPLICIT_TITLE_PRIORITY = 2;
|
|
|
52
53
|
export function buildGraph(patram_config, claims) {
|
|
53
54
|
/** @type {Map<string, GraphNode>} */
|
|
54
55
|
const graph_nodes = new Map();
|
|
56
|
+
const document_node_references = collectDocumentNodeReferences(
|
|
57
|
+
patram_config.mappings,
|
|
58
|
+
claims,
|
|
59
|
+
);
|
|
55
60
|
const document_entity_keys = collectDocumentEntityKeys(
|
|
56
61
|
patram_config.mappings,
|
|
57
62
|
claims,
|
|
@@ -63,12 +68,13 @@ export function buildGraph(patram_config, claims) {
|
|
|
63
68
|
/** @type {Map<string, number>} */
|
|
64
69
|
const title_priorities = new Map();
|
|
65
70
|
|
|
66
|
-
createDocumentNodes(graph_nodes,
|
|
71
|
+
createDocumentNodes(graph_nodes, document_node_references);
|
|
67
72
|
applyNodeMappings(
|
|
68
73
|
graph_nodes,
|
|
69
74
|
patram_config,
|
|
70
75
|
claims,
|
|
71
76
|
document_entity_keys,
|
|
77
|
+
document_node_references,
|
|
72
78
|
title_priorities,
|
|
73
79
|
);
|
|
74
80
|
const graph_edges = createGraphEdges(
|
|
@@ -76,16 +82,26 @@ export function buildGraph(patram_config, claims) {
|
|
|
76
82
|
patram_config.mappings,
|
|
77
83
|
claims,
|
|
78
84
|
document_entity_keys,
|
|
85
|
+
document_node_references,
|
|
79
86
|
document_paths,
|
|
80
87
|
);
|
|
81
88
|
applyFallbackTitles(graph_nodes, title_priorities);
|
|
82
89
|
|
|
83
|
-
|
|
90
|
+
const graph_result = {
|
|
84
91
|
edges: graph_edges,
|
|
85
92
|
nodes: Object.fromEntries(
|
|
86
93
|
[...graph_nodes.entries()].sort(compareNodeEntries),
|
|
87
94
|
),
|
|
88
95
|
};
|
|
96
|
+
|
|
97
|
+
attachDocumentNodeAliases(graph_result.nodes, document_node_references);
|
|
98
|
+
Object.defineProperty(
|
|
99
|
+
graph_result,
|
|
100
|
+
'document_node_ids',
|
|
101
|
+
createDocumentNodeIdsProperty(document_node_references),
|
|
102
|
+
);
|
|
103
|
+
|
|
104
|
+
return graph_result;
|
|
89
105
|
}
|
|
90
106
|
|
|
91
107
|
/**
|
|
@@ -116,15 +132,17 @@ function resolveDirectiveMapping(mappings, claim) {
|
|
|
116
132
|
|
|
117
133
|
/**
|
|
118
134
|
* @param {Map<string, GraphNode>} graph_nodes
|
|
119
|
-
* @param {
|
|
135
|
+
* @param {Map<string, import('./document-node-identity.js').DocumentNodeReference>} document_node_references
|
|
120
136
|
*/
|
|
121
|
-
function createDocumentNodes(graph_nodes,
|
|
122
|
-
for (const
|
|
123
|
-
upsertNode(
|
|
137
|
+
function createDocumentNodes(graph_nodes, document_node_references) {
|
|
138
|
+
for (const document_node_reference of document_node_references.values()) {
|
|
139
|
+
const graph_node = upsertNode(
|
|
124
140
|
graph_nodes,
|
|
125
|
-
|
|
126
|
-
|
|
141
|
+
document_node_reference.class_name,
|
|
142
|
+
document_node_reference.key,
|
|
127
143
|
);
|
|
144
|
+
|
|
145
|
+
setCanonicalPath(graph_node, document_node_reference.path);
|
|
128
146
|
}
|
|
129
147
|
}
|
|
130
148
|
|
|
@@ -133,6 +151,7 @@ function createDocumentNodes(graph_nodes, claims) {
|
|
|
133
151
|
* @param {PatramConfig} patram_config
|
|
134
152
|
* @param {PatramClaim[]} claims
|
|
135
153
|
* @param {Map<string, string>} document_entity_keys
|
|
154
|
+
* @param {Map<string, import('./document-node-identity.js').DocumentNodeReference>} document_node_references
|
|
136
155
|
* @param {Map<string, number>} title_priorities
|
|
137
156
|
*/
|
|
138
157
|
function applyNodeMappings(
|
|
@@ -140,6 +159,7 @@ function applyNodeMappings(
|
|
|
140
159
|
patram_config,
|
|
141
160
|
claims,
|
|
142
161
|
document_entity_keys,
|
|
162
|
+
document_node_references,
|
|
143
163
|
title_priorities,
|
|
144
164
|
) {
|
|
145
165
|
for (const claim of claims) {
|
|
@@ -158,6 +178,7 @@ function applyNodeMappings(
|
|
|
158
178
|
mapping_definition.node,
|
|
159
179
|
claim,
|
|
160
180
|
document_entity_keys,
|
|
181
|
+
document_node_references,
|
|
161
182
|
title_priorities,
|
|
162
183
|
);
|
|
163
184
|
}
|
|
@@ -168,6 +189,7 @@ function applyNodeMappings(
|
|
|
168
189
|
* @param {Record<string, MappingDefinition>} mappings
|
|
169
190
|
* @param {PatramClaim[]} claims
|
|
170
191
|
* @param {Map<string, string>} document_entity_keys
|
|
192
|
+
* @param {Map<string, import('./document-node-identity.js').DocumentNodeReference>} document_node_references
|
|
171
193
|
* @param {Set<string>} document_paths
|
|
172
194
|
* @returns {GraphEdge[]}
|
|
173
195
|
*/
|
|
@@ -176,6 +198,7 @@ function createGraphEdges(
|
|
|
176
198
|
mappings,
|
|
177
199
|
claims,
|
|
178
200
|
document_entity_keys,
|
|
201
|
+
document_node_references,
|
|
179
202
|
document_paths,
|
|
180
203
|
) {
|
|
181
204
|
/** @type {GraphEdge[]} */
|
|
@@ -189,25 +212,26 @@ function createGraphEdges(
|
|
|
189
212
|
continue;
|
|
190
213
|
}
|
|
191
214
|
|
|
192
|
-
const source_document_node =
|
|
215
|
+
const source_document_node = getDocumentGraphNode(
|
|
193
216
|
graph_nodes,
|
|
194
|
-
|
|
195
|
-
|
|
217
|
+
document_node_references,
|
|
218
|
+
claim,
|
|
196
219
|
);
|
|
197
220
|
const target_reference = resolveTargetReference(
|
|
198
221
|
mapping_definition.emit.target_class,
|
|
199
222
|
mapping_definition.emit.target,
|
|
200
223
|
claim,
|
|
201
224
|
document_entity_keys,
|
|
225
|
+
document_node_references,
|
|
202
226
|
document_paths,
|
|
203
227
|
);
|
|
204
228
|
const target_node = upsertNode(
|
|
205
229
|
graph_nodes,
|
|
206
|
-
|
|
230
|
+
target_reference.class_name,
|
|
207
231
|
target_reference.key,
|
|
208
232
|
);
|
|
209
233
|
|
|
210
|
-
|
|
234
|
+
setCanonicalPath(target_node, target_reference.path);
|
|
211
235
|
|
|
212
236
|
edge_number += 1;
|
|
213
237
|
graph_edges.push({
|
|
@@ -228,6 +252,7 @@ function createGraphEdges(
|
|
|
228
252
|
* @param {{ field: string, key?: 'path' | 'value', class: string }} node_mapping
|
|
229
253
|
* @param {PatramClaim} claim
|
|
230
254
|
* @param {Map<string, string>} document_entity_keys
|
|
255
|
+
* @param {Map<string, import('./document-node-identity.js').DocumentNodeReference>} document_node_references
|
|
231
256
|
* @param {Map<string, number>} title_priorities
|
|
232
257
|
*/
|
|
233
258
|
function applyNodeMapping(
|
|
@@ -236,14 +261,25 @@ function applyNodeMapping(
|
|
|
236
261
|
node_mapping,
|
|
237
262
|
claim,
|
|
238
263
|
document_entity_keys,
|
|
264
|
+
document_node_references,
|
|
239
265
|
title_priorities,
|
|
240
266
|
) {
|
|
241
267
|
const source_key = normalizeRepoRelativePath(claim.origin.path);
|
|
242
|
-
const
|
|
243
|
-
|
|
244
|
-
|
|
268
|
+
const graph_node = resolveGraphNode(
|
|
269
|
+
graph_nodes,
|
|
270
|
+
node_mapping,
|
|
271
|
+
claim,
|
|
272
|
+
document_entity_keys,
|
|
273
|
+
document_node_references,
|
|
274
|
+
);
|
|
275
|
+
const field_value = resolveNodeFieldValue(
|
|
276
|
+
graph_node,
|
|
277
|
+
node_mapping,
|
|
278
|
+
claim,
|
|
279
|
+
source_key,
|
|
280
|
+
);
|
|
245
281
|
|
|
246
|
-
|
|
282
|
+
setCanonicalPath(graph_node, source_key);
|
|
247
283
|
validateNodeFieldMapping(
|
|
248
284
|
patram_config,
|
|
249
285
|
node_mapping.class,
|
|
@@ -408,6 +444,122 @@ function getNodeFieldValue(claim) {
|
|
|
408
444
|
throw new Error(`Claim "${claim.id}" does not carry a string value.`);
|
|
409
445
|
}
|
|
410
446
|
|
|
447
|
+
/**
|
|
448
|
+
* @param {Map<string, import('./document-node-identity.js').DocumentNodeReference>} document_node_references
|
|
449
|
+
* @returns {{ configurable: false, enumerable: false, value: Record<string, string>, writable: false }}
|
|
450
|
+
*/
|
|
451
|
+
function createDocumentNodeIdsProperty(document_node_references) {
|
|
452
|
+
return {
|
|
453
|
+
configurable: false,
|
|
454
|
+
enumerable: false,
|
|
455
|
+
value: Object.fromEntries(
|
|
456
|
+
[...document_node_references.entries()].map(
|
|
457
|
+
([document_path, document_node_reference]) => [
|
|
458
|
+
document_path,
|
|
459
|
+
document_node_reference.id,
|
|
460
|
+
],
|
|
461
|
+
),
|
|
462
|
+
),
|
|
463
|
+
writable: false,
|
|
464
|
+
};
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
/**
|
|
468
|
+
* @param {Map<string, GraphNode>} graph_nodes
|
|
469
|
+
* @param {Map<string, import('./document-node-identity.js').DocumentNodeReference>} document_node_references
|
|
470
|
+
* @param {PatramClaim} claim
|
|
471
|
+
* @returns {GraphNode}
|
|
472
|
+
*/
|
|
473
|
+
function getDocumentGraphNode(graph_nodes, document_node_references, claim) {
|
|
474
|
+
const document_path = normalizeRepoRelativePath(claim.origin.path);
|
|
475
|
+
const document_node_reference = document_node_references.get(document_path);
|
|
476
|
+
|
|
477
|
+
if (!document_node_reference) {
|
|
478
|
+
throw new Error(`Missing document node reference for "${document_path}".`);
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
const graph_node = upsertNode(
|
|
482
|
+
graph_nodes,
|
|
483
|
+
document_node_reference.class_name,
|
|
484
|
+
document_node_reference.key,
|
|
485
|
+
);
|
|
486
|
+
|
|
487
|
+
setCanonicalPath(graph_node, document_node_reference.path);
|
|
488
|
+
|
|
489
|
+
return graph_node;
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
/**
|
|
493
|
+
* @param {Map<string, GraphNode>} graph_nodes
|
|
494
|
+
* @param {{ field: string, key?: 'path' | 'value', class: string }} node_mapping
|
|
495
|
+
* @param {PatramClaim} claim
|
|
496
|
+
* @param {Map<string, string>} document_entity_keys
|
|
497
|
+
* @param {Map<string, import('./document-node-identity.js').DocumentNodeReference>} document_node_references
|
|
498
|
+
* @returns {GraphNode}
|
|
499
|
+
*/
|
|
500
|
+
function resolveGraphNode(
|
|
501
|
+
graph_nodes,
|
|
502
|
+
node_mapping,
|
|
503
|
+
claim,
|
|
504
|
+
document_entity_keys,
|
|
505
|
+
document_node_references,
|
|
506
|
+
) {
|
|
507
|
+
if (node_mapping.class === 'document') {
|
|
508
|
+
return getDocumentGraphNode(graph_nodes, document_node_references, claim);
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
const node_key = resolveNodeKey(node_mapping, claim, document_entity_keys);
|
|
512
|
+
|
|
513
|
+
return upsertNode(graph_nodes, node_mapping.class, node_key);
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
/**
|
|
517
|
+
* @param {GraphNode} graph_node
|
|
518
|
+
* @param {{ field: string, key?: 'path' | 'value', class: string }} node_mapping
|
|
519
|
+
* @param {PatramClaim} claim
|
|
520
|
+
* @param {string} source_path
|
|
521
|
+
* @returns {string}
|
|
522
|
+
*/
|
|
523
|
+
function resolveNodeFieldValue(graph_node, node_mapping, claim, source_path) {
|
|
524
|
+
if (node_mapping.field === '$id') {
|
|
525
|
+
return graph_node.id;
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
if (node_mapping.field === '$class') {
|
|
529
|
+
return graph_node.$class ?? graph_node.kind ?? node_mapping.class;
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
if (node_mapping.field === '$path') {
|
|
533
|
+
return source_path;
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
return getNodeFieldValue(claim);
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
/**
|
|
540
|
+
* @param {Record<string, GraphNode>} graph_nodes
|
|
541
|
+
* @param {Map<string, import('./document-node-identity.js').DocumentNodeReference>} document_node_references
|
|
542
|
+
*/
|
|
543
|
+
function attachDocumentNodeAliases(graph_nodes, document_node_references) {
|
|
544
|
+
for (const [
|
|
545
|
+
document_path,
|
|
546
|
+
document_node_reference,
|
|
547
|
+
] of document_node_references) {
|
|
548
|
+
const document_node_id = `doc:${document_path}`;
|
|
549
|
+
|
|
550
|
+
if (document_node_id === document_node_reference.id) {
|
|
551
|
+
continue;
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
Object.defineProperty(graph_nodes, document_node_id, {
|
|
555
|
+
configurable: false,
|
|
556
|
+
enumerable: false,
|
|
557
|
+
value: graph_nodes[document_node_reference.id],
|
|
558
|
+
writable: false,
|
|
559
|
+
});
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
|
|
411
563
|
/**
|
|
412
564
|
* @param {Map<string, GraphNode>} graph_nodes
|
|
413
565
|
* @param {Map<string, number>} title_priorities
|
package/lib/build-graph.types.ts
CHANGED
|
@@ -8,7 +8,9 @@
|
|
|
8
8
|
|
|
9
9
|
import {
|
|
10
10
|
collectDocumentEntityKeys,
|
|
11
|
+
collectDocumentNodeReferences,
|
|
11
12
|
normalizeRepoRelativePath,
|
|
13
|
+
resolveDocumentNodeId,
|
|
12
14
|
} from './build-graph-identity.js';
|
|
13
15
|
import { checkDirectiveValue } from './check-directive-value.js';
|
|
14
16
|
import {
|
|
@@ -55,6 +57,10 @@ export function checkDirectiveMetadata(
|
|
|
55
57
|
graph_config.mappings,
|
|
56
58
|
claims,
|
|
57
59
|
);
|
|
60
|
+
const document_node_references = collectDocumentNodeReferences(
|
|
61
|
+
graph_config.mappings,
|
|
62
|
+
claims,
|
|
63
|
+
);
|
|
58
64
|
const document_paths = new Set(
|
|
59
65
|
existing_file_paths.map((file_path) =>
|
|
60
66
|
normalizeRepoRelativePath(file_path),
|
|
@@ -79,6 +85,7 @@ export function checkDirectiveMetadata(
|
|
|
79
85
|
document_path,
|
|
80
86
|
document_claims,
|
|
81
87
|
document_entity_keys,
|
|
88
|
+
document_node_references,
|
|
82
89
|
document_paths,
|
|
83
90
|
);
|
|
84
91
|
}
|
|
@@ -121,6 +128,7 @@ function groupDirectiveClaimsByDocument(claims) {
|
|
|
121
128
|
* @param {string} document_path
|
|
122
129
|
* @param {PatramClaim[]} document_claims
|
|
123
130
|
* @param {Map<string, string>} document_entity_keys
|
|
131
|
+
* @param {Map<string, import('./document-node-identity.js').DocumentNodeReference>} document_node_references
|
|
124
132
|
* @param {Set<string>} document_paths
|
|
125
133
|
*/
|
|
126
134
|
function collectDocumentDiagnostics(
|
|
@@ -131,6 +139,7 @@ function collectDocumentDiagnostics(
|
|
|
131
139
|
document_path,
|
|
132
140
|
document_claims,
|
|
133
141
|
document_entity_keys,
|
|
142
|
+
document_node_references,
|
|
134
143
|
document_paths,
|
|
135
144
|
) {
|
|
136
145
|
const document_kind = resolveDocumentKind(graph, document_path);
|
|
@@ -152,6 +161,7 @@ function collectDocumentDiagnostics(
|
|
|
152
161
|
schema_definition,
|
|
153
162
|
directive_counts,
|
|
154
163
|
document_entity_keys,
|
|
164
|
+
document_node_references,
|
|
155
165
|
document_paths,
|
|
156
166
|
),
|
|
157
167
|
);
|
|
@@ -176,6 +186,7 @@ function collectDocumentDiagnostics(
|
|
|
176
186
|
* @param {MetadataSchemaConfig | undefined} schema_definition
|
|
177
187
|
* @param {Map<string, number>} directive_counts
|
|
178
188
|
* @param {Map<string, string>} document_entity_keys
|
|
189
|
+
* @param {Map<string, import('./document-node-identity.js').DocumentNodeReference>} document_node_references
|
|
179
190
|
* @param {Set<string>} document_paths
|
|
180
191
|
* @returns {PatramDiagnostic[]}
|
|
181
192
|
*/
|
|
@@ -187,6 +198,7 @@ function collectClaimDiagnostics(
|
|
|
187
198
|
schema_definition,
|
|
188
199
|
directive_counts,
|
|
189
200
|
document_entity_keys,
|
|
201
|
+
document_node_references,
|
|
190
202
|
document_paths,
|
|
191
203
|
) {
|
|
192
204
|
if (!claim.name) {
|
|
@@ -222,6 +234,7 @@ function collectClaimDiagnostics(
|
|
|
222
234
|
repo_config,
|
|
223
235
|
schema_definition?.fields[claim.name],
|
|
224
236
|
document_entity_keys,
|
|
237
|
+
document_node_references,
|
|
225
238
|
document_paths,
|
|
226
239
|
),
|
|
227
240
|
];
|
|
@@ -392,9 +405,14 @@ function getDirectiveFieldDefinition(repo_config, validation_field_name) {
|
|
|
392
405
|
* @returns {string}
|
|
393
406
|
*/
|
|
394
407
|
function resolveDocumentKind(graph, document_path) {
|
|
408
|
+
const document_node_id = resolveDocumentNodeId(
|
|
409
|
+
graph.document_node_ids,
|
|
410
|
+
document_path,
|
|
411
|
+
);
|
|
412
|
+
|
|
395
413
|
return (
|
|
396
|
-
graph.nodes[
|
|
397
|
-
graph.nodes[
|
|
414
|
+
graph.nodes[document_node_id]?.$class ??
|
|
415
|
+
graph.nodes[document_node_id]?.kind ??
|
|
398
416
|
'document'
|
|
399
417
|
);
|
|
400
418
|
}
|