patram 0.4.0 → 0.6.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 +48 -7
- package/lib/build-graph.js +2 -2
- package/lib/check-directive-metadata.js +175 -6
- package/lib/check-directive-path-target.js +173 -0
- package/lib/check-directive-value.js +122 -125
- package/lib/directive-validation-test-helpers.js +87 -0
- package/lib/load-patram-config.js +263 -116
- package/lib/load-patram-config.types.ts +50 -152
- package/lib/load-project-graph.js +16 -6
- package/lib/parse-claims.js +97 -11
- package/lib/parse-claims.types.ts +7 -0
- package/lib/parse-jsdoc-claims.js +3 -3
- package/lib/parse-markdown-claims.js +9 -3
- package/lib/parse-markdown-directives.js +48 -25
- package/lib/parse-yaml-claims.js +472 -0
- package/lib/patram-config.js +26 -9
- package/lib/patram-config.types.ts +18 -36
- package/lib/render-output-view.js +8 -9
- package/lib/resolve-patram-graph-config.js +40 -2
- package/lib/source-file-defaults.js +3 -0
- package/package.json +2 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
/** @import * as $k$$l$document$j$node$j$identity$k$js from './document-node-identity.js'; */
|
|
2
1
|
/**
|
|
2
|
+
* @import { DocumentNodeReference } from './document-node-identity.js';
|
|
3
3
|
* @import { GraphNode } from './build-graph.types.ts';
|
|
4
4
|
* @import { PatramClaim } from './parse-claims.types.ts';
|
|
5
5
|
*/
|
|
@@ -48,7 +48,7 @@ export function resolveNodeKey(node_mapping, claim, document_entity_keys) {
|
|
|
48
48
|
* @param {'path' | 'value'} target_type
|
|
49
49
|
* @param {PatramClaim} claim
|
|
50
50
|
* @param {Map<string, string>} document_entity_keys
|
|
51
|
-
* @param {Map<string,
|
|
51
|
+
* @param {Map<string, DocumentNodeReference>} document_node_references
|
|
52
52
|
* @param {Set<string>} document_paths
|
|
53
53
|
* @returns {{ class_name: string, key: string, path?: string }}
|
|
54
54
|
*/
|
|
@@ -124,7 +124,7 @@ function resolveValueTargetReference(target_kind, claim) {
|
|
|
124
124
|
* @param {string} target_class
|
|
125
125
|
* @param {PatramClaim} claim
|
|
126
126
|
* @param {Map<string, string>} document_entity_keys
|
|
127
|
-
* @param {Map<string,
|
|
127
|
+
* @param {Map<string, DocumentNodeReference>} document_node_references
|
|
128
128
|
* @param {Set<string>} document_paths
|
|
129
129
|
* @returns {{ class_name: string, key: string, path?: string }}
|
|
130
130
|
*/
|
|
@@ -171,7 +171,7 @@ function resolvePathTargetReference(
|
|
|
171
171
|
|
|
172
172
|
/**
|
|
173
173
|
* @param {string} target_path
|
|
174
|
-
* @param {Map<string,
|
|
174
|
+
* @param {Map<string, DocumentNodeReference>} document_node_references
|
|
175
175
|
* @returns {{ class_name: string, key: string, path?: string }}
|
|
176
176
|
*/
|
|
177
177
|
function resolveDocumentTargetReference(target_path, document_node_references) {
|
|
@@ -201,7 +201,14 @@ function resolveDocumentTargetReference(target_path, document_node_references) {
|
|
|
201
201
|
function resolveDirectiveAwareTargetPath(claim, raw_target, document_paths) {
|
|
202
202
|
const normalized_raw_target = normalizeRepoRelativePath(raw_target);
|
|
203
203
|
|
|
204
|
-
if (
|
|
204
|
+
if (
|
|
205
|
+
claim.type === 'directive' &&
|
|
206
|
+
shouldKeepDirectiveTargetRepoRelative(
|
|
207
|
+
raw_target,
|
|
208
|
+
normalized_raw_target,
|
|
209
|
+
document_paths,
|
|
210
|
+
)
|
|
211
|
+
) {
|
|
205
212
|
return normalized_raw_target;
|
|
206
213
|
}
|
|
207
214
|
|
|
@@ -212,6 +219,40 @@ function resolveDirectiveAwareTargetPath(claim, raw_target, document_paths) {
|
|
|
212
219
|
return normalizeRepoRelativePath(posix.join(source_directory, raw_target));
|
|
213
220
|
}
|
|
214
221
|
|
|
222
|
+
/**
|
|
223
|
+
* @param {string} raw_target
|
|
224
|
+
* @param {string} normalized_raw_target
|
|
225
|
+
* @param {Set<string>} document_paths
|
|
226
|
+
* @returns {boolean}
|
|
227
|
+
*/
|
|
228
|
+
function shouldKeepDirectiveTargetRepoRelative(
|
|
229
|
+
raw_target,
|
|
230
|
+
normalized_raw_target,
|
|
231
|
+
document_paths,
|
|
232
|
+
) {
|
|
233
|
+
if (raw_target.startsWith('./') || raw_target.startsWith('../')) {
|
|
234
|
+
return false;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
if (document_paths.has(normalized_raw_target)) {
|
|
238
|
+
return true;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
const target_root_segment = normalized_raw_target.split('/')[0];
|
|
242
|
+
|
|
243
|
+
if (!target_root_segment) {
|
|
244
|
+
return false;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
for (const document_path of document_paths) {
|
|
248
|
+
if (document_path.split('/')[0] === target_root_segment) {
|
|
249
|
+
return true;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
return false;
|
|
254
|
+
}
|
|
255
|
+
|
|
215
256
|
/**
|
|
216
257
|
* @param {PatramClaim} claim
|
|
217
258
|
* @returns {string}
|
|
@@ -246,8 +287,8 @@ function getDocumentEntityMapKey(document_path, class_name) {
|
|
|
246
287
|
}
|
|
247
288
|
|
|
248
289
|
/**
|
|
249
|
-
* @param {
|
|
250
|
-
* @returns {document_node_reference is
|
|
290
|
+
* @param {DocumentNodeReference | undefined} document_node_reference
|
|
291
|
+
* @returns {document_node_reference is DocumentNodeReference}
|
|
251
292
|
*/
|
|
252
293
|
function documentNodeReferenceIsPromoted(document_node_reference) {
|
|
253
294
|
return (
|
package/lib/build-graph.js
CHANGED
|
@@ -30,7 +30,7 @@ import {
|
|
|
30
30
|
* Uses Term: ../docs/reference/terms/graph.md
|
|
31
31
|
* Uses Term: ../docs/reference/terms/mapping.md
|
|
32
32
|
* Uses Term: ../docs/reference/terms/relation.md
|
|
33
|
-
* Tracked in: ../docs/plans/v0/source-anchor-
|
|
33
|
+
* Tracked in: ../docs/plans/v0/source-anchor-dogfooding.md
|
|
34
34
|
* Decided by: ../docs/decisions/graph-materialization.md
|
|
35
35
|
* Implements: ../docs/tasks/v0/materialize-graph.md
|
|
36
36
|
* @patram
|
|
@@ -771,7 +771,7 @@ function getFieldDefinition(patram_config, field_name) {
|
|
|
771
771
|
* @returns {{ fields?: Record<string, { presence: 'required' | 'optional' | 'forbidden' }>, unknown_fields?: 'ignore' | 'error' } | undefined}
|
|
772
772
|
*/
|
|
773
773
|
function getClassSchema(patram_config, class_name) {
|
|
774
|
-
return patram_config.
|
|
774
|
+
return patram_config.classes[class_name]?.schema;
|
|
775
775
|
}
|
|
776
776
|
|
|
777
777
|
/**
|
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
createDocumentDiagnostic,
|
|
18
18
|
createOriginDiagnostic,
|
|
19
19
|
} from './directive-diagnostics.js';
|
|
20
|
+
import { formatQuotedList } from './directive-type-rules.js';
|
|
20
21
|
import { resolvePatramGraphConfig } from './resolve-patram-graph-config.js';
|
|
21
22
|
|
|
22
23
|
/**
|
|
@@ -44,11 +45,7 @@ export function checkDirectiveMetadata(
|
|
|
44
45
|
claims,
|
|
45
46
|
existing_file_paths,
|
|
46
47
|
) {
|
|
47
|
-
if (
|
|
48
|
-
claims.length === 0 ||
|
|
49
|
-
(repo_config.fields === undefined &&
|
|
50
|
-
repo_config.class_schemas === undefined)
|
|
51
|
-
) {
|
|
48
|
+
if (claims.length === 0 || !hasDirectiveValidationConfig(repo_config)) {
|
|
52
49
|
return [];
|
|
53
50
|
}
|
|
54
51
|
|
|
@@ -93,6 +90,19 @@ export function checkDirectiveMetadata(
|
|
|
93
90
|
return diagnostics;
|
|
94
91
|
}
|
|
95
92
|
|
|
93
|
+
/**
|
|
94
|
+
* @param {PatramRepoConfig} repo_config
|
|
95
|
+
* @returns {boolean}
|
|
96
|
+
*/
|
|
97
|
+
function hasDirectiveValidationConfig(repo_config) {
|
|
98
|
+
return (
|
|
99
|
+
repo_config.fields !== undefined ||
|
|
100
|
+
hasMarkdownStyleValidationConfig(repo_config) ||
|
|
101
|
+
hasConfiguredClassSchemas(repo_config) ||
|
|
102
|
+
hasPathTargetDirectiveMappings(repo_config)
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
|
|
96
106
|
/**
|
|
97
107
|
* @param {PatramClaim[]} claims
|
|
98
108
|
* @returns {Map<string, PatramClaim[]>}
|
|
@@ -143,9 +153,11 @@ function collectDocumentDiagnostics(
|
|
|
143
153
|
document_paths,
|
|
144
154
|
) {
|
|
145
155
|
const document_kind = resolveDocumentKind(graph, document_path);
|
|
146
|
-
const schema_definition = repo_config.
|
|
156
|
+
const schema_definition = repo_config.classes?.[document_kind]?.schema;
|
|
147
157
|
/** @type {Map<string, number>} */
|
|
148
158
|
const directive_counts = new Map();
|
|
159
|
+
/** @type {Set<string>} */
|
|
160
|
+
const seen_markdown_styles = new Set();
|
|
149
161
|
|
|
150
162
|
for (const claim of document_claims) {
|
|
151
163
|
if (!claim.name) {
|
|
@@ -160,6 +172,7 @@ function collectDocumentDiagnostics(
|
|
|
160
172
|
document_kind,
|
|
161
173
|
schema_definition,
|
|
162
174
|
directive_counts,
|
|
175
|
+
seen_markdown_styles,
|
|
163
176
|
document_entity_keys,
|
|
164
177
|
document_node_references,
|
|
165
178
|
document_paths,
|
|
@@ -185,6 +198,7 @@ function collectDocumentDiagnostics(
|
|
|
185
198
|
* @param {string} document_kind
|
|
186
199
|
* @param {MetadataSchemaConfig | undefined} schema_definition
|
|
187
200
|
* @param {Map<string, number>} directive_counts
|
|
201
|
+
* @param {Set<string>} seen_markdown_styles
|
|
188
202
|
* @param {Map<string, string>} document_entity_keys
|
|
189
203
|
* @param {Map<string, import('./document-node-identity.js').DocumentNodeReference>} document_node_references
|
|
190
204
|
* @param {Set<string>} document_paths
|
|
@@ -197,6 +211,7 @@ function collectClaimDiagnostics(
|
|
|
197
211
|
document_kind,
|
|
198
212
|
schema_definition,
|
|
199
213
|
directive_counts,
|
|
214
|
+
seen_markdown_styles,
|
|
200
215
|
document_entity_keys,
|
|
201
216
|
document_node_references,
|
|
202
217
|
document_paths,
|
|
@@ -227,6 +242,12 @@ function collectClaimDiagnostics(
|
|
|
227
242
|
schema_definition,
|
|
228
243
|
next_count,
|
|
229
244
|
),
|
|
245
|
+
...collectMarkdownStyleDiagnostics(
|
|
246
|
+
claim,
|
|
247
|
+
document_kind,
|
|
248
|
+
schema_definition,
|
|
249
|
+
seen_markdown_styles,
|
|
250
|
+
),
|
|
230
251
|
...checkDirectiveValue(
|
|
231
252
|
claim,
|
|
232
253
|
claim.name,
|
|
@@ -240,6 +261,68 @@ function collectClaimDiagnostics(
|
|
|
240
261
|
];
|
|
241
262
|
}
|
|
242
263
|
|
|
264
|
+
/**
|
|
265
|
+
* @param {PatramRepoConfig} repo_config
|
|
266
|
+
* @returns {boolean}
|
|
267
|
+
*/
|
|
268
|
+
function hasConfiguredClassSchemas(repo_config) {
|
|
269
|
+
for (const class_definition of Object.values(repo_config.classes ?? {})) {
|
|
270
|
+
if (class_definition.schema) {
|
|
271
|
+
return true;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
return false;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* @param {PatramRepoConfig} repo_config
|
|
280
|
+
* @returns {boolean}
|
|
281
|
+
*/
|
|
282
|
+
function hasMarkdownStyleValidationConfig(repo_config) {
|
|
283
|
+
for (const class_definition of Object.values(repo_config.classes ?? {})) {
|
|
284
|
+
const schema_definition = class_definition.schema;
|
|
285
|
+
|
|
286
|
+
if (!schema_definition) {
|
|
287
|
+
continue;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
if (
|
|
291
|
+
schema_definition.markdown_styles !== undefined ||
|
|
292
|
+
schema_definition.mixed_styles !== undefined
|
|
293
|
+
) {
|
|
294
|
+
return true;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
for (const field_rule of Object.values(schema_definition.fields)) {
|
|
298
|
+
if (field_rule.markdown_styles !== undefined) {
|
|
299
|
+
return true;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
return false;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* @param {PatramRepoConfig} repo_config
|
|
309
|
+
* @returns {boolean}
|
|
310
|
+
*/
|
|
311
|
+
function hasPathTargetDirectiveMappings(repo_config) {
|
|
312
|
+
for (const [mapping_name, mapping_definition] of Object.entries(
|
|
313
|
+
repo_config.mappings ?? {},
|
|
314
|
+
)) {
|
|
315
|
+
if (
|
|
316
|
+
mapping_name.includes('.directive.') &&
|
|
317
|
+
mapping_definition.emit?.target === 'path'
|
|
318
|
+
) {
|
|
319
|
+
return true;
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
return false;
|
|
324
|
+
}
|
|
325
|
+
|
|
243
326
|
/**
|
|
244
327
|
* @param {PatramRepoConfig} repo_config
|
|
245
328
|
* @param {string} document_path
|
|
@@ -532,3 +615,89 @@ function collectPlacementDiagnostics(
|
|
|
532
615
|
),
|
|
533
616
|
];
|
|
534
617
|
}
|
|
618
|
+
|
|
619
|
+
/**
|
|
620
|
+
* @param {PatramClaim} claim
|
|
621
|
+
* @param {string} document_kind
|
|
622
|
+
* @param {MetadataSchemaConfig | undefined} schema_definition
|
|
623
|
+
* @param {Set<string>} seen_markdown_styles
|
|
624
|
+
* @returns {PatramDiagnostic[]}
|
|
625
|
+
*/
|
|
626
|
+
function collectMarkdownStyleDiagnostics(
|
|
627
|
+
claim,
|
|
628
|
+
document_kind,
|
|
629
|
+
schema_definition,
|
|
630
|
+
seen_markdown_styles,
|
|
631
|
+
) {
|
|
632
|
+
const markdown_style = resolveClaimMarkdownStyle(claim);
|
|
633
|
+
|
|
634
|
+
if (!markdown_style || !claim.name) {
|
|
635
|
+
return [];
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
/** @type {PatramDiagnostic[]} */
|
|
639
|
+
const diagnostics = [];
|
|
640
|
+
const allowed_styles =
|
|
641
|
+
schema_definition?.fields[claim.name]?.markdown_styles ??
|
|
642
|
+
schema_definition?.markdown_styles;
|
|
643
|
+
|
|
644
|
+
if (allowed_styles && !allowed_styles.includes(markdown_style)) {
|
|
645
|
+
diagnostics.push(
|
|
646
|
+
createOriginDiagnostic(
|
|
647
|
+
claim,
|
|
648
|
+
'directive.invalid_style',
|
|
649
|
+
`Directive "${claim.name}" uses markdown style "${markdown_style}" but only ${formatQuotedList(allowed_styles)} are allowed.`,
|
|
650
|
+
),
|
|
651
|
+
);
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
if (
|
|
655
|
+
shouldReportMixedStyles(
|
|
656
|
+
schema_definition,
|
|
657
|
+
seen_markdown_styles,
|
|
658
|
+
markdown_style,
|
|
659
|
+
)
|
|
660
|
+
) {
|
|
661
|
+
diagnostics.push(
|
|
662
|
+
createOriginDiagnostic(
|
|
663
|
+
claim,
|
|
664
|
+
'document.mixed_styles',
|
|
665
|
+
`Document mixes markdown directive style "${markdown_style}" with ${formatQuotedList([...seen_markdown_styles])} while class "${document_kind}" sets mixed_styles="error".`,
|
|
666
|
+
),
|
|
667
|
+
);
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
seen_markdown_styles.add(markdown_style);
|
|
671
|
+
|
|
672
|
+
return diagnostics;
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
/**
|
|
676
|
+
* @param {PatramClaim} claim
|
|
677
|
+
* @returns {string | null}
|
|
678
|
+
*/
|
|
679
|
+
function resolveClaimMarkdownStyle(claim) {
|
|
680
|
+
if (claim.parser !== 'markdown' || claim.markdown_style === undefined) {
|
|
681
|
+
return null;
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
return claim.markdown_style;
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
/**
|
|
688
|
+
* @param {MetadataSchemaConfig | undefined} schema_definition
|
|
689
|
+
* @param {Set<string>} seen_markdown_styles
|
|
690
|
+
* @param {string} markdown_style
|
|
691
|
+
* @returns {boolean}
|
|
692
|
+
*/
|
|
693
|
+
function shouldReportMixedStyles(
|
|
694
|
+
schema_definition,
|
|
695
|
+
seen_markdown_styles,
|
|
696
|
+
markdown_style,
|
|
697
|
+
) {
|
|
698
|
+
return (
|
|
699
|
+
schema_definition?.mixed_styles === 'error' &&
|
|
700
|
+
seen_markdown_styles.size === 1 &&
|
|
701
|
+
!seen_markdown_styles.has(markdown_style)
|
|
702
|
+
);
|
|
703
|
+
}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @import { DirectiveTypeConfig, 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 { isPathLikeTarget } from './claim-helpers.js';
|
|
8
|
+
import { resolveTargetReference } from './build-graph-identity.js';
|
|
9
|
+
import { createOriginDiagnostic } from './directive-diagnostics.js';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @param {PatramClaim} claim
|
|
13
|
+
* @param {string} directive_name
|
|
14
|
+
* @param {MappingDefinition | null} mapping_definition
|
|
15
|
+
* @param {Exclude<DirectiveTypeConfig, { type: 'enum' }> | undefined} type_definition
|
|
16
|
+
* @param {Map<string, string>} document_entity_keys
|
|
17
|
+
* @param {Map<string, import('./document-node-identity.js').DocumentNodeReference>} document_node_references
|
|
18
|
+
* @param {Set<string>} document_paths
|
|
19
|
+
* @returns {PatramDiagnostic[]}
|
|
20
|
+
*/
|
|
21
|
+
export function createPathExistenceDiagnostics(
|
|
22
|
+
claim,
|
|
23
|
+
directive_name,
|
|
24
|
+
mapping_definition,
|
|
25
|
+
type_definition,
|
|
26
|
+
document_entity_keys,
|
|
27
|
+
document_node_references,
|
|
28
|
+
document_paths,
|
|
29
|
+
) {
|
|
30
|
+
if (
|
|
31
|
+
typeof claim.value !== 'string' ||
|
|
32
|
+
!isPathLikeTarget(claim.value) ||
|
|
33
|
+
!shouldCheckDirectivePathExistence(mapping_definition, type_definition)
|
|
34
|
+
) {
|
|
35
|
+
return [];
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const resolved_target = resolveDirectiveTargetPath(
|
|
39
|
+
claim,
|
|
40
|
+
mapping_definition,
|
|
41
|
+
document_entity_keys,
|
|
42
|
+
document_node_references,
|
|
43
|
+
document_paths,
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
if (!resolved_target || document_paths.has(resolved_target)) {
|
|
47
|
+
return [];
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return [
|
|
51
|
+
createOriginDiagnostic(
|
|
52
|
+
claim,
|
|
53
|
+
'directive.path_not_found',
|
|
54
|
+
`Directive "${directive_name}" points to missing file "${resolved_target}".`,
|
|
55
|
+
),
|
|
56
|
+
];
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* @param {PatramClaim} claim
|
|
61
|
+
* @param {string} directive_name
|
|
62
|
+
* @param {Record<string, MappingDefinition>} mappings
|
|
63
|
+
* @param {PatramRepoConfig} repo_config
|
|
64
|
+
* @param {Exclude<DirectiveTypeConfig, { type: 'enum' }>} type_definition
|
|
65
|
+
* @param {Map<string, string>} document_entity_keys
|
|
66
|
+
* @param {Map<string, import('./document-node-identity.js').DocumentNodeReference>} document_node_references
|
|
67
|
+
* @param {Set<string>} document_paths
|
|
68
|
+
* @returns {PatramDiagnostic[]}
|
|
69
|
+
*/
|
|
70
|
+
export function createPathClassDiagnostics(
|
|
71
|
+
claim,
|
|
72
|
+
directive_name,
|
|
73
|
+
mappings,
|
|
74
|
+
repo_config,
|
|
75
|
+
type_definition,
|
|
76
|
+
document_entity_keys,
|
|
77
|
+
document_node_references,
|
|
78
|
+
document_paths,
|
|
79
|
+
) {
|
|
80
|
+
if (type_definition.type !== 'path' || !type_definition.path_class) {
|
|
81
|
+
return [];
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const path_class_definition =
|
|
85
|
+
repo_config.path_classes?.[type_definition.path_class];
|
|
86
|
+
|
|
87
|
+
if (!path_class_definition) {
|
|
88
|
+
return [];
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const mapping_definition = resolveDirectiveMapping(mappings, claim);
|
|
92
|
+
const resolved_target = resolveDirectiveTargetPath(
|
|
93
|
+
claim,
|
|
94
|
+
mapping_definition,
|
|
95
|
+
document_entity_keys,
|
|
96
|
+
document_node_references,
|
|
97
|
+
document_paths,
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
if (
|
|
101
|
+
!resolved_target ||
|
|
102
|
+
path_class_definition.prefixes.some((prefix) =>
|
|
103
|
+
resolved_target.startsWith(prefix),
|
|
104
|
+
)
|
|
105
|
+
) {
|
|
106
|
+
return [];
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return [
|
|
110
|
+
createOriginDiagnostic(
|
|
111
|
+
claim,
|
|
112
|
+
'directive.invalid_path_class',
|
|
113
|
+
`Directive "${directive_name}" must point to path class "${type_definition.path_class}".`,
|
|
114
|
+
),
|
|
115
|
+
];
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* @param {PatramClaim} claim
|
|
120
|
+
* @param {MappingDefinition | null} mapping_definition
|
|
121
|
+
* @param {Map<string, string>} document_entity_keys
|
|
122
|
+
* @param {Map<string, import('./document-node-identity.js').DocumentNodeReference>} document_node_references
|
|
123
|
+
* @param {Set<string>} document_paths
|
|
124
|
+
* @returns {string | undefined}
|
|
125
|
+
*/
|
|
126
|
+
function resolveDirectiveTargetPath(
|
|
127
|
+
claim,
|
|
128
|
+
mapping_definition,
|
|
129
|
+
document_entity_keys,
|
|
130
|
+
document_node_references,
|
|
131
|
+
document_paths,
|
|
132
|
+
) {
|
|
133
|
+
const target_kind = mapping_definition?.emit?.target_class ?? 'document';
|
|
134
|
+
const resolved_target = resolveTargetReference(
|
|
135
|
+
target_kind,
|
|
136
|
+
'path',
|
|
137
|
+
claim,
|
|
138
|
+
document_entity_keys,
|
|
139
|
+
document_node_references,
|
|
140
|
+
document_paths,
|
|
141
|
+
);
|
|
142
|
+
|
|
143
|
+
return resolved_target.path;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* @param {Record<string, MappingDefinition>} mappings
|
|
148
|
+
* @param {PatramClaim} claim
|
|
149
|
+
* @returns {MappingDefinition | null}
|
|
150
|
+
*/
|
|
151
|
+
function resolveDirectiveMapping(mappings, claim) {
|
|
152
|
+
if (!claim.name || !claim.parser) {
|
|
153
|
+
return null;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
return mappings[`${claim.parser}.directive.${claim.name}`] ?? null;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* @param {MappingDefinition | null} mapping_definition
|
|
161
|
+
* @param {Exclude<DirectiveTypeConfig, { type: 'enum' }> | undefined} type_definition
|
|
162
|
+
* @returns {boolean}
|
|
163
|
+
*/
|
|
164
|
+
function shouldCheckDirectivePathExistence(
|
|
165
|
+
mapping_definition,
|
|
166
|
+
type_definition,
|
|
167
|
+
) {
|
|
168
|
+
if (type_definition?.type === 'path') {
|
|
169
|
+
return true;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
return mapping_definition?.emit?.target === 'path';
|
|
173
|
+
}
|