patram 0.1.1 → 0.3.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 +57 -24
- package/lib/build-graph.js +383 -17
- package/lib/build-graph.types.ts +5 -2
- package/lib/check-directive-metadata.js +516 -0
- package/lib/check-directive-value.js +282 -0
- package/lib/check-graph.js +24 -5
- package/lib/cli-help-metadata.js +580 -0
- package/lib/derived-summary.js +280 -0
- package/lib/directive-diagnostics.js +38 -0
- package/lib/directive-type-rules.js +133 -0
- package/lib/discover-fields.js +427 -0
- package/lib/discover-fields.types.ts +52 -0
- package/lib/format-derived-summary-row.js +9 -0
- package/lib/format-node-header.js +21 -0
- package/lib/format-output-item-block.js +22 -0
- package/lib/format-output-metadata.js +54 -0
- package/lib/layout-stored-queries.js +96 -2
- package/lib/load-patram-config.js +754 -18
- package/lib/load-patram-config.types.ts +128 -2
- package/lib/load-project-graph.js +4 -1
- package/lib/output-view.types.ts +29 -6
- package/lib/parse-cli-arguments-helpers.js +263 -90
- package/lib/parse-cli-arguments.js +160 -8
- package/lib/parse-cli-arguments.types.ts +49 -4
- package/lib/parse-where-clause.js +670 -209
- package/lib/parse-where-clause.types.ts +72 -0
- package/lib/patram-cli.js +180 -21
- package/lib/patram-config.js +31 -31
- package/lib/patram-config.types.ts +10 -4
- package/lib/patram.js +6 -0
- package/lib/query-graph.js +444 -113
- package/lib/query-inspection.js +798 -0
- package/lib/render-check-output.js +1 -1
- package/lib/render-cli-help.js +419 -0
- package/lib/render-field-discovery.js +148 -0
- package/lib/render-json-output.js +66 -14
- package/lib/render-output-view.js +272 -22
- package/lib/render-plain-output.js +31 -86
- package/lib/render-rich-output.js +34 -87
- package/lib/resolve-patram-graph-config.js +15 -9
- package/lib/resolve-where-clause.js +18 -3
- package/lib/show-document.js +51 -7
- package/lib/tagged-fenced-block-error.js +17 -0
- package/lib/tagged-fenced-block-markdown.js +111 -0
- package/lib/tagged-fenced-block-metadata.js +97 -0
- package/lib/tagged-fenced-block-parser.js +292 -0
- package/lib/tagged-fenced-blocks.js +100 -0
- package/lib/tagged-fenced-blocks.types.ts +38 -0
- package/package.json +12 -7
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @import { DirectiveTypeConfig, MetadataDirectiveRuleConfig, PatramDiagnostic, PatramRepoConfig } from './load-patram-config.types.ts';
|
|
3
|
+
* @import { PatramClaim } from './parse-claims.types.ts';
|
|
4
|
+
* @import { MappingDefinition } from './patram-config.types.ts';
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { resolveTargetReference } from './build-graph-identity.js';
|
|
8
|
+
import { createOriginDiagnostic } from './directive-diagnostics.js';
|
|
9
|
+
import {
|
|
10
|
+
formatQuotedList,
|
|
11
|
+
getInvalidTypeMessage,
|
|
12
|
+
isDirectiveValueValid,
|
|
13
|
+
} from './directive-type-rules.js';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Check one directive claim value against typed validation rules.
|
|
17
|
+
*
|
|
18
|
+
* @param {PatramClaim} claim
|
|
19
|
+
* @param {string} directive_name
|
|
20
|
+
* @param {Record<string, MappingDefinition>} mappings
|
|
21
|
+
* @param {PatramRepoConfig} repo_config
|
|
22
|
+
* @param {MetadataDirectiveRuleConfig | undefined} _directive_rule
|
|
23
|
+
* @param {Map<string, string>} document_entity_keys
|
|
24
|
+
* @param {Set<string>} document_paths
|
|
25
|
+
* @returns {PatramDiagnostic[]}
|
|
26
|
+
*/
|
|
27
|
+
export function checkDirectiveValue(
|
|
28
|
+
claim,
|
|
29
|
+
directive_name,
|
|
30
|
+
mappings,
|
|
31
|
+
repo_config,
|
|
32
|
+
_directive_rule,
|
|
33
|
+
document_entity_keys,
|
|
34
|
+
document_paths,
|
|
35
|
+
) {
|
|
36
|
+
const mapping_definition = resolveDirectiveMapping(mappings, claim);
|
|
37
|
+
const validation_field_name = getDirectiveValidationFieldName(
|
|
38
|
+
directive_name,
|
|
39
|
+
mapping_definition,
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
if (!validation_field_name || typeof claim.value !== 'string') {
|
|
43
|
+
return [];
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (validation_field_name === '$class') {
|
|
47
|
+
return checkClassValue(claim, directive_name, repo_config);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (isStructuralDirectiveField(validation_field_name)) {
|
|
51
|
+
return [];
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const type_definition = repo_config.fields?.[validation_field_name];
|
|
55
|
+
|
|
56
|
+
if (!type_definition) {
|
|
57
|
+
return [];
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (type_definition.type === 'enum') {
|
|
61
|
+
return checkEnumValue(claim, directive_name, type_definition.values);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const type_diagnostic = createInvalidTypeDiagnostic(
|
|
65
|
+
claim,
|
|
66
|
+
directive_name,
|
|
67
|
+
type_definition,
|
|
68
|
+
claim.value,
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
if (type_diagnostic) {
|
|
72
|
+
return [type_diagnostic];
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return createPathClassDiagnostics(
|
|
76
|
+
claim,
|
|
77
|
+
directive_name,
|
|
78
|
+
mappings,
|
|
79
|
+
repo_config,
|
|
80
|
+
type_definition,
|
|
81
|
+
document_entity_keys,
|
|
82
|
+
document_paths,
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* @param {PatramClaim} claim
|
|
88
|
+
* @param {string} directive_name
|
|
89
|
+
* @param {PatramRepoConfig} repo_config
|
|
90
|
+
* @returns {PatramDiagnostic[]}
|
|
91
|
+
*/
|
|
92
|
+
function checkClassValue(claim, directive_name, repo_config) {
|
|
93
|
+
if (
|
|
94
|
+
typeof claim.value !== 'string' ||
|
|
95
|
+
repo_config.classes?.[claim.value] !== undefined
|
|
96
|
+
) {
|
|
97
|
+
return [];
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return [
|
|
101
|
+
createOriginDiagnostic(
|
|
102
|
+
claim,
|
|
103
|
+
'directive.invalid_enum',
|
|
104
|
+
`Directive "${directive_name}" must reference a configured class.`,
|
|
105
|
+
),
|
|
106
|
+
];
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* @param {PatramClaim} claim
|
|
111
|
+
* @param {string} directive_name
|
|
112
|
+
* @param {string[]} allowed_values
|
|
113
|
+
* @returns {PatramDiagnostic[]}
|
|
114
|
+
*/
|
|
115
|
+
function checkEnumValue(claim, directive_name, allowed_values) {
|
|
116
|
+
if (typeof claim.value !== 'string' || allowed_values.includes(claim.value)) {
|
|
117
|
+
return [];
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return [
|
|
121
|
+
createOriginDiagnostic(
|
|
122
|
+
claim,
|
|
123
|
+
'directive.invalid_enum',
|
|
124
|
+
`Directive "${directive_name}" must be one of ${formatQuotedList(allowed_values)}.`,
|
|
125
|
+
),
|
|
126
|
+
];
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* @param {PatramClaim} claim
|
|
131
|
+
* @param {string} directive_name
|
|
132
|
+
* @param {Exclude<DirectiveTypeConfig, { type: 'enum' }>} type_definition
|
|
133
|
+
* @param {string} directive_value
|
|
134
|
+
* @returns {PatramDiagnostic | null}
|
|
135
|
+
*/
|
|
136
|
+
function createInvalidTypeDiagnostic(
|
|
137
|
+
claim,
|
|
138
|
+
directive_name,
|
|
139
|
+
type_definition,
|
|
140
|
+
directive_value,
|
|
141
|
+
) {
|
|
142
|
+
if (isDirectiveValueValid(type_definition, directive_value)) {
|
|
143
|
+
return null;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return createOriginDiagnostic(
|
|
147
|
+
claim,
|
|
148
|
+
'directive.invalid_type',
|
|
149
|
+
getInvalidTypeMessage(directive_name, type_definition.type),
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* @param {PatramClaim} claim
|
|
155
|
+
* @param {string} directive_name
|
|
156
|
+
* @param {Record<string, MappingDefinition>} mappings
|
|
157
|
+
* @param {PatramRepoConfig} repo_config
|
|
158
|
+
* @param {Exclude<DirectiveTypeConfig, { type: 'enum' }>} type_definition
|
|
159
|
+
* @param {Map<string, string>} document_entity_keys
|
|
160
|
+
* @param {Set<string>} document_paths
|
|
161
|
+
* @returns {PatramDiagnostic[]}
|
|
162
|
+
*/
|
|
163
|
+
function createPathClassDiagnostics(
|
|
164
|
+
claim,
|
|
165
|
+
directive_name,
|
|
166
|
+
mappings,
|
|
167
|
+
repo_config,
|
|
168
|
+
type_definition,
|
|
169
|
+
document_entity_keys,
|
|
170
|
+
document_paths,
|
|
171
|
+
) {
|
|
172
|
+
if (
|
|
173
|
+
type_definition.type !== 'path' ||
|
|
174
|
+
type_definition.path_class === undefined ||
|
|
175
|
+
isDirectivePathInClass(
|
|
176
|
+
mappings,
|
|
177
|
+
claim,
|
|
178
|
+
type_definition.path_class,
|
|
179
|
+
document_entity_keys,
|
|
180
|
+
document_paths,
|
|
181
|
+
repo_config,
|
|
182
|
+
)
|
|
183
|
+
) {
|
|
184
|
+
return [];
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
return [
|
|
188
|
+
createOriginDiagnostic(
|
|
189
|
+
claim,
|
|
190
|
+
'directive.invalid_path_class',
|
|
191
|
+
`Directive "${directive_name}" must point to path class "${type_definition.path_class}".`,
|
|
192
|
+
),
|
|
193
|
+
];
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* @param {Record<string, MappingDefinition>} mappings
|
|
198
|
+
* @param {PatramClaim} claim
|
|
199
|
+
* @param {string} path_class_name
|
|
200
|
+
* @param {Map<string, string>} document_entity_keys
|
|
201
|
+
* @param {Set<string>} document_paths
|
|
202
|
+
* @param {PatramRepoConfig} repo_config
|
|
203
|
+
* @returns {boolean}
|
|
204
|
+
*/
|
|
205
|
+
function isDirectivePathInClass(
|
|
206
|
+
mappings,
|
|
207
|
+
claim,
|
|
208
|
+
path_class_name,
|
|
209
|
+
document_entity_keys,
|
|
210
|
+
document_paths,
|
|
211
|
+
repo_config,
|
|
212
|
+
) {
|
|
213
|
+
const path_class_definition = repo_config.path_classes?.[path_class_name];
|
|
214
|
+
|
|
215
|
+
if (!path_class_definition) {
|
|
216
|
+
return true;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
const mapping_definition = resolveDirectiveMapping(mappings, claim);
|
|
220
|
+
const target_kind = mapping_definition?.emit?.target_class ?? 'document';
|
|
221
|
+
const resolved_target = resolveTargetReference(
|
|
222
|
+
target_kind,
|
|
223
|
+
'path',
|
|
224
|
+
claim,
|
|
225
|
+
document_entity_keys,
|
|
226
|
+
document_paths,
|
|
227
|
+
);
|
|
228
|
+
|
|
229
|
+
if (!resolved_target.path) {
|
|
230
|
+
return false;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
return path_class_definition.prefixes.some((prefix) =>
|
|
234
|
+
resolved_target.path?.startsWith(prefix),
|
|
235
|
+
);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* @param {Record<string, MappingDefinition>} mappings
|
|
240
|
+
* @param {PatramClaim} claim
|
|
241
|
+
* @returns {MappingDefinition | null}
|
|
242
|
+
*/
|
|
243
|
+
function resolveDirectiveMapping(mappings, claim) {
|
|
244
|
+
if (!claim.name || !claim.parser) {
|
|
245
|
+
return null;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
return mappings[`${claim.parser}.directive.${claim.name}`] ?? null;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* @param {string} directive_name
|
|
253
|
+
* @param {MappingDefinition | null} mapping_definition
|
|
254
|
+
* @returns {string}
|
|
255
|
+
*/
|
|
256
|
+
function getDirectiveValidationFieldName(directive_name, mapping_definition) {
|
|
257
|
+
if (mapping_definition?.node?.field) {
|
|
258
|
+
return mapping_definition.node.field;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
return directive_name;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* @param {string} field_name
|
|
266
|
+
* @returns {boolean}
|
|
267
|
+
*/
|
|
268
|
+
function isStructuralDirectiveField(field_name) {
|
|
269
|
+
return (
|
|
270
|
+
field_name === '$class' ||
|
|
271
|
+
field_name === '$id' ||
|
|
272
|
+
field_name === '$path' ||
|
|
273
|
+
field_name === 'title'
|
|
274
|
+
);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* @param {PatramClaim} claim
|
|
279
|
+
* @param {string} code
|
|
280
|
+
* @param {string} message
|
|
281
|
+
* @returns {PatramDiagnostic}
|
|
282
|
+
*/
|
package/lib/check-graph.js
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @import { BuildGraphResult, GraphEdge, GraphNode } from './build-graph.types.ts';
|
|
3
|
-
* @import { PatramDiagnostic } from './load-patram-config.types.ts';
|
|
3
|
+
* @import { PatramDiagnostic, PatramRepoConfig } from './load-patram-config.types.ts';
|
|
4
|
+
* @import { PatramClaim } from './parse-claims.types.ts';
|
|
4
5
|
*/
|
|
5
6
|
|
|
7
|
+
import { checkDirectiveMetadata } from './check-directive-metadata.js';
|
|
8
|
+
|
|
6
9
|
/**
|
|
7
10
|
* Graph validation.
|
|
8
11
|
*
|
|
@@ -24,9 +27,11 @@
|
|
|
24
27
|
*
|
|
25
28
|
* @param {BuildGraphResult} graph
|
|
26
29
|
* @param {string[]} existing_file_paths
|
|
30
|
+
* @param {PatramRepoConfig} [repo_config]
|
|
31
|
+
* @param {PatramClaim[]} [claims]
|
|
27
32
|
* @returns {PatramDiagnostic[]}
|
|
28
33
|
*/
|
|
29
|
-
export function checkGraph(graph, existing_file_paths) {
|
|
34
|
+
export function checkGraph(graph, existing_file_paths, repo_config, claims) {
|
|
30
35
|
/** @type {PatramDiagnostic[]} */
|
|
31
36
|
const diagnostics = [];
|
|
32
37
|
const existing_file_path_set = new Set(existing_file_paths);
|
|
@@ -54,6 +59,17 @@ export function checkGraph(graph, existing_file_paths) {
|
|
|
54
59
|
);
|
|
55
60
|
}
|
|
56
61
|
|
|
62
|
+
if (repo_config && claims) {
|
|
63
|
+
diagnostics.push(
|
|
64
|
+
...checkDirectiveMetadata(
|
|
65
|
+
graph,
|
|
66
|
+
repo_config,
|
|
67
|
+
claims,
|
|
68
|
+
existing_file_paths,
|
|
69
|
+
),
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
|
|
57
73
|
return diagnostics;
|
|
58
74
|
}
|
|
59
75
|
|
|
@@ -102,15 +118,18 @@ function collectBrokenLinkDiagnostics(
|
|
|
102
118
|
target_node,
|
|
103
119
|
existing_file_path_set,
|
|
104
120
|
) {
|
|
121
|
+
const target_class = target_node.$class ?? target_node.kind;
|
|
122
|
+
const target_path = target_node.$path ?? target_node.path;
|
|
123
|
+
|
|
105
124
|
if (graph_edge.relation !== 'links_to') {
|
|
106
125
|
return;
|
|
107
126
|
}
|
|
108
127
|
|
|
109
|
-
if (
|
|
128
|
+
if (target_class !== 'document' || !target_path) {
|
|
110
129
|
return;
|
|
111
130
|
}
|
|
112
131
|
|
|
113
|
-
if (existing_file_path_set.has(
|
|
132
|
+
if (existing_file_path_set.has(target_path)) {
|
|
114
133
|
return;
|
|
115
134
|
}
|
|
116
135
|
|
|
@@ -118,7 +137,7 @@ function collectBrokenLinkDiagnostics(
|
|
|
118
137
|
createDiagnostic(
|
|
119
138
|
graph_edge,
|
|
120
139
|
'graph.link_broken',
|
|
121
|
-
`Document link target "${
|
|
140
|
+
`Document link target "${target_path}" was not found.`,
|
|
122
141
|
),
|
|
123
142
|
);
|
|
124
143
|
}
|