patram 0.4.0 → 0.5.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 +6 -6
- package/lib/build-graph.js +1 -1
- package/lib/check-directive-metadata.js +16 -2
- package/lib/load-patram-config.js +171 -111
- package/lib/load-patram-config.types.ts +50 -152
- package/lib/parse-claims.js +2 -3
- package/lib/parse-jsdoc-claims.js +3 -3
- 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/package.json +1 -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) {
|
|
@@ -246,8 +246,8 @@ function getDocumentEntityMapKey(document_path, class_name) {
|
|
|
246
246
|
}
|
|
247
247
|
|
|
248
248
|
/**
|
|
249
|
-
* @param {
|
|
250
|
-
* @returns {document_node_reference is
|
|
249
|
+
* @param {DocumentNodeReference | undefined} document_node_reference
|
|
250
|
+
* @returns {document_node_reference is DocumentNodeReference}
|
|
251
251
|
*/
|
|
252
252
|
function documentNodeReferenceIsPromoted(document_node_reference) {
|
|
253
253
|
return (
|
package/lib/build-graph.js
CHANGED
|
@@ -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
|
/**
|
|
@@ -47,7 +47,7 @@ export function checkDirectiveMetadata(
|
|
|
47
47
|
if (
|
|
48
48
|
claims.length === 0 ||
|
|
49
49
|
(repo_config.fields === undefined &&
|
|
50
|
-
repo_config
|
|
50
|
+
!hasConfiguredClassSchemas(repo_config))
|
|
51
51
|
) {
|
|
52
52
|
return [];
|
|
53
53
|
}
|
|
@@ -143,7 +143,7 @@ function collectDocumentDiagnostics(
|
|
|
143
143
|
document_paths,
|
|
144
144
|
) {
|
|
145
145
|
const document_kind = resolveDocumentKind(graph, document_path);
|
|
146
|
-
const schema_definition = repo_config.
|
|
146
|
+
const schema_definition = repo_config.classes?.[document_kind]?.schema;
|
|
147
147
|
/** @type {Map<string, number>} */
|
|
148
148
|
const directive_counts = new Map();
|
|
149
149
|
|
|
@@ -240,6 +240,20 @@ function collectClaimDiagnostics(
|
|
|
240
240
|
];
|
|
241
241
|
}
|
|
242
242
|
|
|
243
|
+
/**
|
|
244
|
+
* @param {PatramRepoConfig} repo_config
|
|
245
|
+
* @returns {boolean}
|
|
246
|
+
*/
|
|
247
|
+
function hasConfiguredClassSchemas(repo_config) {
|
|
248
|
+
for (const class_definition of Object.values(repo_config.classes ?? {})) {
|
|
249
|
+
if (class_definition.schema) {
|
|
250
|
+
return true;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
return false;
|
|
255
|
+
}
|
|
256
|
+
|
|
243
257
|
/**
|
|
244
258
|
* @param {PatramRepoConfig} repo_config
|
|
245
259
|
* @param {string} document_path
|
|
@@ -1,12 +1,8 @@
|
|
|
1
|
+
/** @import * as $k$$l$patram$j$config$k$js from './patram-config.js'; */
|
|
1
2
|
/* eslint-disable max-lines */
|
|
3
|
+
|
|
2
4
|
/**
|
|
3
|
-
* @import {
|
|
4
|
-
* ClassSchemaConfig,
|
|
5
|
-
* LoadPatramConfigResult,
|
|
6
|
-
* MetadataFieldConfig,
|
|
7
|
-
* PatramDiagnostic,
|
|
8
|
-
* PatramRepoConfig,
|
|
9
|
-
* } from './load-patram-config.types.ts';
|
|
5
|
+
* @import { ClassDefinition } from './patram-config.js';
|
|
10
6
|
*/
|
|
11
7
|
|
|
12
8
|
import { readFile } from 'node:fs/promises';
|
|
@@ -15,7 +11,12 @@ import process from 'node:process';
|
|
|
15
11
|
|
|
16
12
|
import { z } from 'zod';
|
|
17
13
|
|
|
18
|
-
import {
|
|
14
|
+
import {
|
|
15
|
+
class_definition_schema,
|
|
16
|
+
mapping_definition_schema,
|
|
17
|
+
parsePatramConfig,
|
|
18
|
+
relation_definition_schema,
|
|
19
|
+
} from './patram-config.js';
|
|
19
20
|
import { parseWhereClause } from './parse-where-clause.js';
|
|
20
21
|
import { getQuerySemanticDiagnostics } from './query-inspection.js';
|
|
21
22
|
import { resolvePatramGraphConfig } from './resolve-patram-graph-config.js';
|
|
@@ -40,12 +41,28 @@ import { DEFAULT_INCLUDE_PATTERNS } from './source-file-defaults.js';
|
|
|
40
41
|
const CONFIG_FILE_NAME = '.patram.json';
|
|
41
42
|
const RESERVED_STRUCTURAL_FIELD_NAMES = new Set(['$class', '$id', '$path']);
|
|
42
43
|
|
|
44
|
+
/**
|
|
45
|
+
* @typedef {object} PatramDiagnostic
|
|
46
|
+
* @property {string} code
|
|
47
|
+
* @property {number} column
|
|
48
|
+
* @property {'error'} level
|
|
49
|
+
* @property {number} line
|
|
50
|
+
* @property {string} message
|
|
51
|
+
* @property {string} path
|
|
52
|
+
*/
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* @typedef {z.output<typeof stored_query_schema>} StoredQueryConfig
|
|
56
|
+
*/
|
|
43
57
|
const stored_query_schema = z
|
|
44
58
|
.object({
|
|
45
59
|
where: z.string().min(1, 'Stored query "where" must not be empty.'),
|
|
46
60
|
})
|
|
47
61
|
.strict();
|
|
48
62
|
|
|
63
|
+
/**
|
|
64
|
+
* @typedef {z.output<typeof derived_summary_scalar_schema>} DerivedSummaryScalar
|
|
65
|
+
*/
|
|
49
66
|
const derived_summary_scalar_schema = z.union([
|
|
50
67
|
z.boolean(),
|
|
51
68
|
z.number(),
|
|
@@ -53,6 +70,9 @@ const derived_summary_scalar_schema = z.union([
|
|
|
53
70
|
z.null(),
|
|
54
71
|
]);
|
|
55
72
|
|
|
73
|
+
/**
|
|
74
|
+
* @typedef {z.output<typeof derived_summary_count_schema>} DerivedSummaryCountConfig
|
|
75
|
+
*/
|
|
56
76
|
const derived_summary_count_schema = z
|
|
57
77
|
.object({
|
|
58
78
|
traversal: z
|
|
@@ -64,6 +84,9 @@ const derived_summary_count_schema = z
|
|
|
64
84
|
})
|
|
65
85
|
.strict();
|
|
66
86
|
|
|
87
|
+
/**
|
|
88
|
+
* @typedef {z.output<typeof derived_summary_select_case_schema>} DerivedSummarySelectCaseConfig
|
|
89
|
+
*/
|
|
67
90
|
const derived_summary_select_case_schema = z
|
|
68
91
|
.object({
|
|
69
92
|
value: derived_summary_scalar_schema,
|
|
@@ -71,21 +94,41 @@ const derived_summary_select_case_schema = z
|
|
|
71
94
|
})
|
|
72
95
|
.strict();
|
|
73
96
|
|
|
74
|
-
const
|
|
97
|
+
const derived_summary_field_name_schema = z
|
|
98
|
+
.string()
|
|
99
|
+
.regex(
|
|
100
|
+
/^[a-z][a-z0-9_]*$/du,
|
|
101
|
+
'Derived summary field names must use lower_snake_case.',
|
|
102
|
+
);
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* @typedef {z.output<typeof derived_summary_field_schema>} DerivedSummaryFieldConfig
|
|
106
|
+
*/
|
|
107
|
+
const derived_summary_count_field_schema = z
|
|
75
108
|
.object({
|
|
76
|
-
count: derived_summary_count_schema
|
|
77
|
-
|
|
78
|
-
name: z
|
|
79
|
-
.string()
|
|
80
|
-
.regex(
|
|
81
|
-
/^[a-z][a-z0-9_]*$/du,
|
|
82
|
-
'Derived summary field names must use lower_snake_case.',
|
|
83
|
-
),
|
|
84
|
-
select: z.array(derived_summary_select_case_schema).optional(),
|
|
109
|
+
count: derived_summary_count_schema,
|
|
110
|
+
name: derived_summary_field_name_schema,
|
|
85
111
|
})
|
|
86
|
-
.strict()
|
|
87
|
-
|
|
112
|
+
.strict();
|
|
113
|
+
|
|
114
|
+
const derived_summary_select_field_schema = z
|
|
115
|
+
.object({
|
|
116
|
+
default: derived_summary_scalar_schema,
|
|
117
|
+
name: derived_summary_field_name_schema,
|
|
118
|
+
select: z
|
|
119
|
+
.array(derived_summary_select_case_schema)
|
|
120
|
+
.min(1, 'Derived summary "select" must contain at least one case.'),
|
|
121
|
+
})
|
|
122
|
+
.strict();
|
|
123
|
+
|
|
124
|
+
const derived_summary_field_schema = z.union([
|
|
125
|
+
derived_summary_count_field_schema,
|
|
126
|
+
derived_summary_select_field_schema,
|
|
127
|
+
]);
|
|
88
128
|
|
|
129
|
+
/**
|
|
130
|
+
* @typedef {z.output<typeof derived_summary_schema>} DerivedSummaryConfig
|
|
131
|
+
*/
|
|
89
132
|
const derived_summary_schema = z
|
|
90
133
|
.object({
|
|
91
134
|
classes: z
|
|
@@ -98,6 +141,9 @@ const derived_summary_schema = z
|
|
|
98
141
|
.strict()
|
|
99
142
|
.superRefine(validateDerivedSummaryDefinition);
|
|
100
143
|
|
|
144
|
+
/**
|
|
145
|
+
* @typedef {z.output<typeof field_display_schema>} FieldDisplayConfig
|
|
146
|
+
*/
|
|
101
147
|
const field_display_schema = z
|
|
102
148
|
.object({
|
|
103
149
|
hidden: z.boolean().optional(),
|
|
@@ -105,6 +151,9 @@ const field_display_schema = z
|
|
|
105
151
|
})
|
|
106
152
|
.strict();
|
|
107
153
|
|
|
154
|
+
/**
|
|
155
|
+
* @typedef {z.output<typeof field_query_schema>} FieldQueryConfig
|
|
156
|
+
*/
|
|
108
157
|
const field_query_schema = z
|
|
109
158
|
.object({
|
|
110
159
|
contains: z.boolean().optional(),
|
|
@@ -118,6 +167,9 @@ const field_base_shape = {
|
|
|
118
167
|
path_class: z.string().min(1).optional(),
|
|
119
168
|
};
|
|
120
169
|
|
|
170
|
+
/**
|
|
171
|
+
* @typedef {z.output<typeof metadata_field_schema>} MetadataFieldConfig
|
|
172
|
+
*/
|
|
121
173
|
const metadata_field_schema = z.discriminatedUnion('type', [
|
|
122
174
|
z
|
|
123
175
|
.object({
|
|
@@ -167,12 +219,18 @@ const metadata_field_schema = z.discriminatedUnion('type', [
|
|
|
167
219
|
.strict(),
|
|
168
220
|
]);
|
|
169
221
|
|
|
222
|
+
/**
|
|
223
|
+
* @typedef {z.output<typeof class_field_rule_schema>} ClassFieldRuleConfig
|
|
224
|
+
*/
|
|
170
225
|
const class_field_rule_schema = z
|
|
171
226
|
.object({
|
|
172
227
|
presence: z.enum(['required', 'optional', 'forbidden']),
|
|
173
228
|
})
|
|
174
229
|
.strict();
|
|
175
230
|
|
|
231
|
+
/**
|
|
232
|
+
* @typedef {z.output<typeof class_schema_schema>} ClassSchemaConfig
|
|
233
|
+
*/
|
|
176
234
|
const class_schema_schema = z
|
|
177
235
|
.object({
|
|
178
236
|
document_path_class: z.string().min(1).optional(),
|
|
@@ -181,6 +239,16 @@ const class_schema_schema = z
|
|
|
181
239
|
})
|
|
182
240
|
.strict();
|
|
183
241
|
|
|
242
|
+
/**
|
|
243
|
+
* @typedef {z.output<typeof repo_class_definition_schema>} RepoClassConfig
|
|
244
|
+
*/
|
|
245
|
+
const repo_class_definition_schema = class_definition_schema.extend({
|
|
246
|
+
schema: class_schema_schema.optional(),
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* @typedef {z.output<typeof path_class_schema>} PathClassConfig
|
|
251
|
+
*/
|
|
184
252
|
const path_class_schema = z
|
|
185
253
|
.object({
|
|
186
254
|
prefixes: z
|
|
@@ -189,10 +257,14 @@ const path_class_schema = z
|
|
|
189
257
|
})
|
|
190
258
|
.strict();
|
|
191
259
|
|
|
260
|
+
/**
|
|
261
|
+
* @typedef {z.output<typeof patram_repo_config_schema>} PatramRepoConfig
|
|
262
|
+
*/
|
|
192
263
|
const patram_repo_config_schema = z
|
|
193
264
|
.object({
|
|
194
|
-
|
|
195
|
-
|
|
265
|
+
classes: z
|
|
266
|
+
.record(z.string().min(1), repo_class_definition_schema)
|
|
267
|
+
.optional(),
|
|
196
268
|
derived_summaries: z
|
|
197
269
|
.record(z.string().min(1), derived_summary_schema)
|
|
198
270
|
.optional(),
|
|
@@ -201,14 +273,23 @@ const patram_repo_config_schema = z
|
|
|
201
273
|
.array(z.string().min(1, 'Include globs must not be empty.'))
|
|
202
274
|
.min(1, 'Include must contain at least one glob.')
|
|
203
275
|
.default(DEFAULT_INCLUDE_PATTERNS),
|
|
204
|
-
mappings: z.
|
|
276
|
+
mappings: z.record(z.string().min(1), mapping_definition_schema).optional(),
|
|
205
277
|
path_classes: z.record(z.string().min(1), path_class_schema).optional(),
|
|
206
278
|
queries: z.record(z.string().min(1), stored_query_schema).default({}),
|
|
207
|
-
relations: z
|
|
279
|
+
relations: z
|
|
280
|
+
.record(z.string().min(1), relation_definition_schema)
|
|
281
|
+
.optional(),
|
|
208
282
|
})
|
|
209
283
|
.strict()
|
|
210
284
|
.superRefine(validateFieldDefinitionKeys);
|
|
211
285
|
|
|
286
|
+
/**
|
|
287
|
+
* @typedef {object} LoadPatramConfigResult
|
|
288
|
+
* @property {PatramRepoConfig | null} config
|
|
289
|
+
* @property {string} config_path
|
|
290
|
+
* @property {PatramDiagnostic[]} diagnostics
|
|
291
|
+
*/
|
|
292
|
+
|
|
212
293
|
/**
|
|
213
294
|
* Load and validate the repo Patram config.
|
|
214
295
|
*
|
|
@@ -229,6 +310,14 @@ export async function loadPatramConfig(project_directory = process.cwd()) {
|
|
|
229
310
|
return createLoadResult(null, [parse_result.diagnostic]);
|
|
230
311
|
}
|
|
231
312
|
|
|
313
|
+
const legacy_config_diagnostics = validateLegacyConfigShape(
|
|
314
|
+
parse_result.value,
|
|
315
|
+
);
|
|
316
|
+
|
|
317
|
+
if (legacy_config_diagnostics.length > 0) {
|
|
318
|
+
return createLoadResult(null, legacy_config_diagnostics);
|
|
319
|
+
}
|
|
320
|
+
|
|
232
321
|
const config_result = patram_repo_config_schema.safeParse(parse_result.value);
|
|
233
322
|
|
|
234
323
|
if (!config_result.success) {
|
|
@@ -382,61 +471,6 @@ function validateFieldDefinitionKeys(repo_config, refinement_context) {
|
|
|
382
471
|
}
|
|
383
472
|
}
|
|
384
473
|
|
|
385
|
-
/**
|
|
386
|
-
* @param {{ count?: unknown, default?: unknown, select?: unknown }} field_definition
|
|
387
|
-
* @param {import('zod').RefinementCtx} refinement_context
|
|
388
|
-
*/
|
|
389
|
-
function validateDerivedSummaryFieldDefinition(
|
|
390
|
-
field_definition,
|
|
391
|
-
refinement_context,
|
|
392
|
-
) {
|
|
393
|
-
const evaluator_count =
|
|
394
|
-
Number(field_definition.count !== undefined) +
|
|
395
|
-
Number(field_definition.select !== undefined);
|
|
396
|
-
|
|
397
|
-
if (evaluator_count !== 1) {
|
|
398
|
-
refinement_context.addIssue({
|
|
399
|
-
code: 'custom',
|
|
400
|
-
message:
|
|
401
|
-
'Derived summary fields must define exactly one of "count" or "select".',
|
|
402
|
-
});
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
if (
|
|
406
|
-
field_definition.count !== undefined &&
|
|
407
|
-
field_definition.default !== undefined
|
|
408
|
-
) {
|
|
409
|
-
refinement_context.addIssue({
|
|
410
|
-
code: 'custom',
|
|
411
|
-
message: 'Derived summary count fields must not define "default".',
|
|
412
|
-
path: ['default'],
|
|
413
|
-
});
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
if (field_definition.select === undefined) {
|
|
417
|
-
return;
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
if (
|
|
421
|
-
Array.isArray(field_definition.select) &&
|
|
422
|
-
field_definition.select.length === 0
|
|
423
|
-
) {
|
|
424
|
-
refinement_context.addIssue({
|
|
425
|
-
code: 'custom',
|
|
426
|
-
message: 'Derived summary "select" must contain at least one case.',
|
|
427
|
-
path: ['select'],
|
|
428
|
-
});
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
if (field_definition.default === undefined) {
|
|
432
|
-
refinement_context.addIssue({
|
|
433
|
-
code: 'custom',
|
|
434
|
-
message: 'Derived summary select fields must define "default".',
|
|
435
|
-
path: ['default'],
|
|
436
|
-
});
|
|
437
|
-
}
|
|
438
|
-
}
|
|
439
|
-
|
|
440
474
|
/**
|
|
441
475
|
* @param {{ fields: Array<{ name: string }> }} summary_definition
|
|
442
476
|
* @param {import('zod').RefinementCtx} refinement_context
|
|
@@ -465,7 +499,7 @@ function validateDerivedSummaryDefinition(
|
|
|
465
499
|
}
|
|
466
500
|
|
|
467
501
|
/**
|
|
468
|
-
* @param {
|
|
502
|
+
* @param {PatramRepoConfig} repo_config
|
|
469
503
|
* @returns {PatramDiagnostic[]}
|
|
470
504
|
*/
|
|
471
505
|
function validateGraphSchema(repo_config) {
|
|
@@ -479,7 +513,7 @@ function validateGraphSchema(repo_config) {
|
|
|
479
513
|
|
|
480
514
|
try {
|
|
481
515
|
parsePatramConfig({
|
|
482
|
-
classes: repo_config.classes
|
|
516
|
+
classes: collectGraphClassDefinitions(repo_config.classes),
|
|
483
517
|
mappings: repo_config.mappings ?? {},
|
|
484
518
|
relations: repo_config.relations ?? {},
|
|
485
519
|
});
|
|
@@ -509,9 +543,8 @@ function validateFieldSchemaConfig(repo_config) {
|
|
|
509
543
|
collectClassSchemaConfigDiagnostics(
|
|
510
544
|
diagnostics,
|
|
511
545
|
path_classes,
|
|
512
|
-
classes,
|
|
513
546
|
fields,
|
|
514
|
-
|
|
547
|
+
classes,
|
|
515
548
|
);
|
|
516
549
|
|
|
517
550
|
return diagnostics;
|
|
@@ -586,7 +619,7 @@ function createDefaultRepoConfig() {
|
|
|
586
619
|
}
|
|
587
620
|
|
|
588
621
|
/**
|
|
589
|
-
* @param {
|
|
622
|
+
* @param {PatramRepoConfig} repo_config
|
|
590
623
|
* @returns {PatramRepoConfig}
|
|
591
624
|
*/
|
|
592
625
|
function normalizeRepoConfig(repo_config) {
|
|
@@ -596,11 +629,6 @@ function normalizeRepoConfig(repo_config) {
|
|
|
596
629
|
queries: { ...repo_config.queries },
|
|
597
630
|
};
|
|
598
631
|
|
|
599
|
-
assignOptionalRepoConfigField(
|
|
600
|
-
normalized_config,
|
|
601
|
-
'class_schemas',
|
|
602
|
-
repo_config.class_schemas,
|
|
603
|
-
);
|
|
604
632
|
assignOptionalRepoConfigField(
|
|
605
633
|
normalized_config,
|
|
606
634
|
'classes',
|
|
@@ -635,6 +663,27 @@ function normalizeRepoConfig(repo_config) {
|
|
|
635
663
|
return normalized_config;
|
|
636
664
|
}
|
|
637
665
|
|
|
666
|
+
/**
|
|
667
|
+
* @param {unknown} config_value
|
|
668
|
+
* @returns {PatramDiagnostic[]}
|
|
669
|
+
*/
|
|
670
|
+
function validateLegacyConfigShape(config_value) {
|
|
671
|
+
if (
|
|
672
|
+
config_value === null ||
|
|
673
|
+
typeof config_value !== 'object' ||
|
|
674
|
+
!Object.hasOwn(config_value, 'class_schemas')
|
|
675
|
+
) {
|
|
676
|
+
return [];
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
return [
|
|
680
|
+
createConfigDiagnostic(
|
|
681
|
+
'class_schemas',
|
|
682
|
+
'Top-level "class_schemas" is not supported. Move entries into classes.<name>.schema.',
|
|
683
|
+
),
|
|
684
|
+
];
|
|
685
|
+
}
|
|
686
|
+
|
|
638
687
|
/**
|
|
639
688
|
* @param {PatramDiagnostic[]} diagnostics
|
|
640
689
|
* @param {Map<string, string>} class_coverage
|
|
@@ -669,7 +718,7 @@ function collectDuplicateClassDiagnostics(
|
|
|
669
718
|
* @param {Set<string>} known_relation_names
|
|
670
719
|
* @param {PatramRepoConfig} repo_config
|
|
671
720
|
* @param {string} summary_name
|
|
672
|
-
* @param {
|
|
721
|
+
* @param {DerivedSummaryFieldConfig[]} field_definitions
|
|
673
722
|
*/
|
|
674
723
|
function collectDerivedSummaryFieldDiagnostics(
|
|
675
724
|
diagnostics,
|
|
@@ -861,35 +910,22 @@ function collectFieldPathClassDiagnostic(
|
|
|
861
910
|
/**
|
|
862
911
|
* @param {PatramDiagnostic[]} diagnostics
|
|
863
912
|
* @param {Record<string, { prefixes: string[] }>} path_classes
|
|
864
|
-
* @param {Record<string, unknown>} classes
|
|
865
913
|
* @param {Record<string, MetadataFieldConfig>} fields
|
|
866
|
-
* @param {PatramRepoConfig['
|
|
914
|
+
* @param {NonNullable<PatramRepoConfig['classes']>} classes
|
|
867
915
|
*/
|
|
868
916
|
function collectClassSchemaConfigDiagnostics(
|
|
869
917
|
diagnostics,
|
|
870
918
|
path_classes,
|
|
871
|
-
classes,
|
|
872
919
|
fields,
|
|
873
|
-
|
|
920
|
+
classes,
|
|
874
921
|
) {
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
}
|
|
922
|
+
for (const [class_name, class_definition] of Object.entries(classes)) {
|
|
923
|
+
const schema_definition = class_definition.schema;
|
|
878
924
|
|
|
879
|
-
|
|
880
|
-
if (classes[class_name]) {
|
|
925
|
+
if (!schema_definition) {
|
|
881
926
|
continue;
|
|
882
927
|
}
|
|
883
928
|
|
|
884
|
-
diagnostics.push(
|
|
885
|
-
createConfigDiagnostic(
|
|
886
|
-
`class_schemas.${class_name}`,
|
|
887
|
-
`Unknown class "${class_name}".`,
|
|
888
|
-
),
|
|
889
|
-
);
|
|
890
|
-
}
|
|
891
|
-
|
|
892
|
-
for (const [class_name, schema_definition] of Object.entries(class_schemas)) {
|
|
893
929
|
for (const field_name of Object.keys(schema_definition.fields)) {
|
|
894
930
|
if (fields[field_name]) {
|
|
895
931
|
continue;
|
|
@@ -897,14 +933,20 @@ function collectClassSchemaConfigDiagnostics(
|
|
|
897
933
|
|
|
898
934
|
diagnostics.push(
|
|
899
935
|
createConfigDiagnostic(
|
|
900
|
-
`
|
|
936
|
+
`classes.${class_name}.schema.fields.${field_name}`,
|
|
901
937
|
`Unknown field "${field_name}".`,
|
|
902
938
|
),
|
|
903
939
|
);
|
|
904
940
|
}
|
|
905
941
|
}
|
|
906
942
|
|
|
907
|
-
for (const [class_name,
|
|
943
|
+
for (const [class_name, class_definition] of Object.entries(classes)) {
|
|
944
|
+
const schema_definition = class_definition.schema;
|
|
945
|
+
|
|
946
|
+
if (!schema_definition) {
|
|
947
|
+
continue;
|
|
948
|
+
}
|
|
949
|
+
|
|
908
950
|
if (
|
|
909
951
|
schema_definition.document_path_class === undefined ||
|
|
910
952
|
path_classes[schema_definition.document_path_class]
|
|
@@ -914,13 +956,31 @@ function collectClassSchemaConfigDiagnostics(
|
|
|
914
956
|
|
|
915
957
|
diagnostics.push(
|
|
916
958
|
createConfigDiagnostic(
|
|
917
|
-
`
|
|
959
|
+
`classes.${class_name}.schema.document_path_class`,
|
|
918
960
|
`Unknown path class "${schema_definition.document_path_class}".`,
|
|
919
961
|
),
|
|
920
962
|
);
|
|
921
963
|
}
|
|
922
964
|
}
|
|
923
965
|
|
|
966
|
+
/**
|
|
967
|
+
* @param {PatramRepoConfig['classes']} classes
|
|
968
|
+
* @returns {Record<string, ClassDefinition>}
|
|
969
|
+
*/
|
|
970
|
+
function collectGraphClassDefinitions(classes) {
|
|
971
|
+
/** @type {Record<string, ClassDefinition>} */
|
|
972
|
+
const graph_class_definitions = {};
|
|
973
|
+
|
|
974
|
+
for (const [class_name, class_definition] of Object.entries(classes ?? {})) {
|
|
975
|
+
graph_class_definitions[class_name] = {
|
|
976
|
+
builtin: class_definition.builtin,
|
|
977
|
+
label: class_definition.label,
|
|
978
|
+
};
|
|
979
|
+
}
|
|
980
|
+
|
|
981
|
+
return graph_class_definitions;
|
|
982
|
+
}
|
|
983
|
+
|
|
924
984
|
/**
|
|
925
985
|
* @template {Exclude<keyof PatramRepoConfig, 'include' | 'queries'>} TKey
|
|
926
986
|
* @param {PatramRepoConfig} normalized_config
|
|
@@ -1,158 +1,56 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
export interface StoredQueryConfig {
|
|
8
|
-
where: string;
|
|
9
|
-
}
|
|
10
|
-
|
|
1
|
+
export type StoredQueryConfig =
|
|
2
|
+
import('./load-patram-config.js').StoredQueryConfig;
|
|
3
|
+
export type FieldDisplayConfig =
|
|
4
|
+
import('./load-patram-config.js').FieldDisplayConfig;
|
|
5
|
+
export type FieldQueryConfig =
|
|
6
|
+
import('./load-patram-config.js').FieldQueryConfig;
|
|
11
7
|
export type FieldValueTypeName =
|
|
12
|
-
|
|
13
|
-
| 'integer'
|
|
14
|
-
| 'enum'
|
|
15
|
-
| 'path'
|
|
16
|
-
| 'glob'
|
|
17
|
-
| 'date'
|
|
18
|
-
| 'date_time';
|
|
19
|
-
|
|
20
|
-
export interface FieldDisplayConfig {
|
|
21
|
-
hidden?: boolean;
|
|
22
|
-
order?: number;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export interface FieldQueryConfig {
|
|
26
|
-
contains?: boolean;
|
|
27
|
-
prefix?: boolean;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export interface StringFieldConfig {
|
|
31
|
-
display?: FieldDisplayConfig;
|
|
32
|
-
multiple?: boolean;
|
|
33
|
-
query?: FieldQueryConfig;
|
|
34
|
-
type: 'string';
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export interface IntegerFieldConfig {
|
|
38
|
-
display?: FieldDisplayConfig;
|
|
39
|
-
multiple?: boolean;
|
|
40
|
-
type: 'integer';
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export interface EnumFieldConfig {
|
|
44
|
-
display?: FieldDisplayConfig;
|
|
45
|
-
multiple?: boolean;
|
|
46
|
-
type: 'enum';
|
|
47
|
-
values: string[];
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
export interface PathFieldConfig {
|
|
51
|
-
display?: FieldDisplayConfig;
|
|
52
|
-
multiple?: boolean;
|
|
53
|
-
path_class?: string;
|
|
54
|
-
type: 'path';
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
export interface GlobFieldConfig {
|
|
58
|
-
display?: FieldDisplayConfig;
|
|
59
|
-
multiple?: boolean;
|
|
60
|
-
type: 'glob';
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
export interface DateFieldConfig {
|
|
64
|
-
display?: FieldDisplayConfig;
|
|
65
|
-
multiple?: boolean;
|
|
66
|
-
type: 'date';
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
export interface DateTimeFieldConfig {
|
|
70
|
-
display?: FieldDisplayConfig;
|
|
71
|
-
multiple?: boolean;
|
|
72
|
-
type: 'date_time';
|
|
73
|
-
}
|
|
74
|
-
|
|
8
|
+
import('./load-patram-config.js').MetadataFieldConfig['type'];
|
|
75
9
|
export type MetadataFieldConfig =
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
}
|
|
87
|
-
|
|
10
|
+
import('./load-patram-config.js').MetadataFieldConfig;
|
|
11
|
+
export type StringFieldConfig = Extract<
|
|
12
|
+
MetadataFieldConfig,
|
|
13
|
+
{ type: 'string' }
|
|
14
|
+
>;
|
|
15
|
+
export type IntegerFieldConfig = Extract<
|
|
16
|
+
MetadataFieldConfig,
|
|
17
|
+
{ type: 'integer' }
|
|
18
|
+
>;
|
|
19
|
+
export type EnumFieldConfig = Extract<MetadataFieldConfig, { type: 'enum' }>;
|
|
20
|
+
export type PathFieldConfig = Extract<MetadataFieldConfig, { type: 'path' }>;
|
|
21
|
+
export type GlobFieldConfig = Extract<MetadataFieldConfig, { type: 'glob' }>;
|
|
22
|
+
export type DateFieldConfig = Extract<MetadataFieldConfig, { type: 'date' }>;
|
|
23
|
+
export type DateTimeFieldConfig = Extract<
|
|
24
|
+
MetadataFieldConfig,
|
|
25
|
+
{ type: 'date_time' }
|
|
26
|
+
>;
|
|
27
|
+
export type ClassFieldRuleConfig =
|
|
28
|
+
import('./load-patram-config.js').ClassFieldRuleConfig;
|
|
88
29
|
export type DirectiveTypeConfig = MetadataFieldConfig;
|
|
89
30
|
export type MetadataDirectiveRuleConfig = ClassFieldRuleConfig;
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
document_path_class?: string;
|
|
93
|
-
fields: Record<string, ClassFieldRuleConfig>;
|
|
94
|
-
unknown_fields?: 'ignore' | 'error';
|
|
95
|
-
}
|
|
96
|
-
|
|
31
|
+
export type ClassSchemaConfig =
|
|
32
|
+
import('./load-patram-config.js').ClassSchemaConfig;
|
|
97
33
|
export type MetadataSchemaConfig = ClassSchemaConfig;
|
|
98
|
-
|
|
99
|
-
export
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
export type DerivedSummaryScalar = boolean | number | string | null;
|
|
104
|
-
|
|
105
|
-
export interface DerivedSummaryCountFieldConfig {
|
|
106
|
-
count: {
|
|
107
|
-
traversal: string;
|
|
108
|
-
where: string;
|
|
109
|
-
};
|
|
110
|
-
name: string;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
export interface DerivedSummarySelectCaseConfig {
|
|
114
|
-
value: DerivedSummaryScalar;
|
|
115
|
-
when: string;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
export interface DerivedSummarySelectFieldConfig {
|
|
119
|
-
default: DerivedSummaryScalar;
|
|
120
|
-
name: string;
|
|
121
|
-
select: DerivedSummarySelectCaseConfig[];
|
|
122
|
-
}
|
|
123
|
-
|
|
34
|
+
export type PathClassConfig = import('./load-patram-config.js').PathClassConfig;
|
|
35
|
+
export type DerivedSummaryScalar =
|
|
36
|
+
import('./load-patram-config.js').DerivedSummaryScalar;
|
|
37
|
+
export type DerivedSummarySelectCaseConfig =
|
|
38
|
+
import('./load-patram-config.js').DerivedSummarySelectCaseConfig;
|
|
124
39
|
export type DerivedSummaryFieldConfig =
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
relations?: Record<string, RelationDefinition>;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
export interface PatramDiagnostic {
|
|
146
|
-
code: string;
|
|
147
|
-
column: number;
|
|
148
|
-
level: 'error';
|
|
149
|
-
line: number;
|
|
150
|
-
message: string;
|
|
151
|
-
path: string;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
export interface LoadPatramConfigResult {
|
|
155
|
-
config: PatramRepoConfig | null;
|
|
156
|
-
config_path: string;
|
|
157
|
-
diagnostics: PatramDiagnostic[];
|
|
158
|
-
}
|
|
40
|
+
import('./load-patram-config.js').DerivedSummaryFieldConfig;
|
|
41
|
+
export type DerivedSummaryCountFieldConfig = Extract<
|
|
42
|
+
DerivedSummaryFieldConfig,
|
|
43
|
+
{ count: unknown }
|
|
44
|
+
>;
|
|
45
|
+
export type DerivedSummarySelectFieldConfig = Extract<
|
|
46
|
+
DerivedSummaryFieldConfig,
|
|
47
|
+
{ select: unknown }
|
|
48
|
+
>;
|
|
49
|
+
export type DerivedSummaryConfig =
|
|
50
|
+
import('./load-patram-config.js').DerivedSummaryConfig;
|
|
51
|
+
export type PatramRepoConfig =
|
|
52
|
+
import('./load-patram-config.js').PatramRepoConfig;
|
|
53
|
+
export type PatramDiagnostic =
|
|
54
|
+
import('./load-patram-config.js').PatramDiagnostic;
|
|
55
|
+
export type LoadPatramConfigResult =
|
|
56
|
+
import('./load-patram-config.js').LoadPatramConfigResult;
|
package/lib/parse-claims.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
/** @import * as $k$$l$parse$j$claims$k$types$k$ts from './parse-claims.types.ts'; */
|
|
2
1
|
/**
|
|
3
|
-
* @import { ParseClaimsInput, ParseSourceFileResult } from './parse-claims.types.ts';
|
|
2
|
+
* @import { ParseClaimsInput, ParseSourceFileResult, PatramClaim } from './parse-claims.types.ts';
|
|
4
3
|
*/
|
|
5
4
|
|
|
6
5
|
import { getFileExtension } from './claim-helpers.js';
|
|
@@ -51,7 +50,7 @@ export function parseSourceFile(parse_input) {
|
|
|
51
50
|
* Parse a file into neutral Patram claims.
|
|
52
51
|
*
|
|
53
52
|
* @param {ParseClaimsInput} parse_input
|
|
54
|
-
* @returns {
|
|
53
|
+
* @returns {PatramClaim[]}
|
|
55
54
|
*/
|
|
56
55
|
export function parseClaims(parse_input) {
|
|
57
56
|
return parseSourceFile(parse_input).claims;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
/** @import * as $k$$l$load$j$patram$j$config$k$types$k$ts from './load-patram-config.types.ts'; */
|
|
2
1
|
/**
|
|
3
|
-
* @import {
|
|
2
|
+
* @import { PatramDiagnostic } from './load-patram-config.types.ts';
|
|
3
|
+
* @import { ParseClaimsInput, ParseSourceFileResult, PatramClaimFields } from './parse-claims.types.ts';
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import {
|
|
@@ -266,7 +266,7 @@ function compareClaimEntries(left_entry, right_entry) {
|
|
|
266
266
|
/**
|
|
267
267
|
* @param {string} file_path
|
|
268
268
|
* @param {{ activation_column: number | null, activation_line: number | null }} jsdoc_block
|
|
269
|
-
* @returns {
|
|
269
|
+
* @returns {PatramDiagnostic}
|
|
270
270
|
*/
|
|
271
271
|
function createMultiplePatramBlocksDiagnostic(file_path, jsdoc_block) {
|
|
272
272
|
return {
|
package/lib/patram-config.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @import { PatramConfig } from './patram-config.types.ts';
|
|
3
2
|
* @import { RefinementCtx } from 'zod';
|
|
4
3
|
*/
|
|
5
4
|
|
|
@@ -11,14 +10,20 @@ const CLAIM_TYPE_SCHEMA = z.string().min(1);
|
|
|
11
10
|
const KEY_SOURCE_SCHEMA = z.enum(['path', 'value']);
|
|
12
11
|
const TARGET_SCHEMA = z.enum(['path', 'value']);
|
|
13
12
|
|
|
14
|
-
|
|
13
|
+
/**
|
|
14
|
+
* @typedef {z.output<typeof class_definition_schema>} ClassDefinition
|
|
15
|
+
*/
|
|
16
|
+
export const class_definition_schema = z
|
|
15
17
|
.object({
|
|
16
18
|
builtin: z.boolean().optional(),
|
|
17
19
|
label: z.string().min(1).optional(),
|
|
18
20
|
})
|
|
19
21
|
.strict();
|
|
20
22
|
|
|
21
|
-
|
|
23
|
+
/**
|
|
24
|
+
* @typedef {z.output<typeof relation_definition_schema>} RelationDefinition
|
|
25
|
+
*/
|
|
26
|
+
export const relation_definition_schema = z
|
|
22
27
|
.object({
|
|
23
28
|
builtin: z.boolean().optional(),
|
|
24
29
|
from: z.array(CLASS_NAME_SCHEMA).min(1),
|
|
@@ -26,6 +31,9 @@ const relation_definition_schema = z
|
|
|
26
31
|
})
|
|
27
32
|
.strict();
|
|
28
33
|
|
|
34
|
+
/**
|
|
35
|
+
* @typedef {z.output<typeof mapping_node_schema>} MappingNodeDefinition
|
|
36
|
+
*/
|
|
29
37
|
const mapping_node_schema = z
|
|
30
38
|
.object({
|
|
31
39
|
class: CLASS_NAME_SCHEMA,
|
|
@@ -34,6 +42,9 @@ const mapping_node_schema = z
|
|
|
34
42
|
})
|
|
35
43
|
.strict();
|
|
36
44
|
|
|
45
|
+
/**
|
|
46
|
+
* @typedef {z.output<typeof mapping_emit_schema>} MappingEmitDefinition
|
|
47
|
+
*/
|
|
37
48
|
const mapping_emit_schema = z
|
|
38
49
|
.object({
|
|
39
50
|
relation: RELATION_NAME_SCHEMA,
|
|
@@ -42,7 +53,10 @@ const mapping_emit_schema = z
|
|
|
42
53
|
})
|
|
43
54
|
.strict();
|
|
44
55
|
|
|
45
|
-
|
|
56
|
+
/**
|
|
57
|
+
* @typedef {z.output<typeof mapping_definition_schema>} MappingDefinition
|
|
58
|
+
*/
|
|
59
|
+
export const mapping_definition_schema = z
|
|
46
60
|
.object({
|
|
47
61
|
emit: mapping_emit_schema.optional(),
|
|
48
62
|
node: mapping_node_schema.optional(),
|
|
@@ -50,6 +64,9 @@ const mapping_definition_schema = z
|
|
|
50
64
|
.strict()
|
|
51
65
|
.superRefine(validateMappingDefinition);
|
|
52
66
|
|
|
67
|
+
/**
|
|
68
|
+
* @typedef {z.output<typeof patramConfigSchema>} PatramGraphConfig
|
|
69
|
+
*/
|
|
53
70
|
export const patramConfigSchema = z
|
|
54
71
|
.object({
|
|
55
72
|
$schema: z.url().optional(),
|
|
@@ -64,7 +81,7 @@ export const patramConfigSchema = z
|
|
|
64
81
|
* Parse and validate Patram JSON configuration.
|
|
65
82
|
*
|
|
66
83
|
* @param {unknown} config_json
|
|
67
|
-
* @returns {
|
|
84
|
+
* @returns {PatramGraphConfig}
|
|
68
85
|
*/
|
|
69
86
|
export function parsePatramConfig(config_json) {
|
|
70
87
|
return patramConfigSchema.parse(config_json);
|
|
@@ -86,7 +103,7 @@ function validateMappingDefinition(mapping_definition, refinement_context) {
|
|
|
86
103
|
}
|
|
87
104
|
|
|
88
105
|
/**
|
|
89
|
-
* @param {
|
|
106
|
+
* @param {PatramGraphConfig} config_json
|
|
90
107
|
* @param {RefinementCtx} refinement_context
|
|
91
108
|
*/
|
|
92
109
|
function validatePatramConfigReferences(config_json, refinement_context) {
|
|
@@ -96,7 +113,7 @@ function validatePatramConfigReferences(config_json, refinement_context) {
|
|
|
96
113
|
}
|
|
97
114
|
|
|
98
115
|
/**
|
|
99
|
-
* @param {
|
|
116
|
+
* @param {PatramGraphConfig} config_json
|
|
100
117
|
* @param {RefinementCtx} refinement_context
|
|
101
118
|
*/
|
|
102
119
|
function validateRelationClasses(config_json, refinement_context) {
|
|
@@ -119,7 +136,7 @@ function validateRelationClasses(config_json, refinement_context) {
|
|
|
119
136
|
}
|
|
120
137
|
|
|
121
138
|
/**
|
|
122
|
-
* @param {
|
|
139
|
+
* @param {PatramGraphConfig} config_json
|
|
123
140
|
* @param {RefinementCtx} refinement_context
|
|
124
141
|
*/
|
|
125
142
|
function validateMappingClasses(config_json, refinement_context) {
|
|
@@ -147,7 +164,7 @@ function validateMappingClasses(config_json, refinement_context) {
|
|
|
147
164
|
}
|
|
148
165
|
|
|
149
166
|
/**
|
|
150
|
-
* @param {
|
|
167
|
+
* @param {PatramGraphConfig} config_json
|
|
151
168
|
* @param {RefinementCtx} refinement_context
|
|
152
169
|
*/
|
|
153
170
|
function validateMappingRelations(config_json, refinement_context) {
|
|
@@ -1,40 +1,22 @@
|
|
|
1
|
-
export interface ClassDefinition {
|
|
2
|
-
builtin?: boolean;
|
|
3
|
-
label?: string;
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
export interface RelationDefinition {
|
|
7
|
-
builtin?: boolean;
|
|
8
|
-
from: string[];
|
|
9
|
-
to: string[];
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export interface MappingNodeDefinition {
|
|
13
|
-
class: string;
|
|
14
|
-
field: string;
|
|
15
|
-
key?: 'path' | 'value';
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export interface MappingEmitDefinition {
|
|
19
|
-
relation: string;
|
|
20
|
-
target: 'path' | 'value';
|
|
21
|
-
target_class: string;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export interface MappingDefinition {
|
|
25
|
-
emit?: MappingEmitDefinition;
|
|
26
|
-
node?: MappingNodeDefinition;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export interface PatramConfig {
|
|
30
|
-
$schema?: string;
|
|
31
|
-
classes: Record<string, ClassDefinition>;
|
|
32
|
-
class_schemas?: Record<string, ClassSchemaConfig>;
|
|
33
|
-
fields?: Record<string, MetadataFieldConfig>;
|
|
34
|
-
mappings: Record<string, MappingDefinition>;
|
|
35
|
-
relations: Record<string, RelationDefinition>;
|
|
36
|
-
}
|
|
37
1
|
import type {
|
|
38
2
|
ClassSchemaConfig,
|
|
39
3
|
MetadataFieldConfig,
|
|
40
4
|
} from './load-patram-config.types.ts';
|
|
5
|
+
|
|
6
|
+
export type ClassDefinition = import('./patram-config.js').ClassDefinition;
|
|
7
|
+
export type RelationDefinition =
|
|
8
|
+
import('./patram-config.js').RelationDefinition;
|
|
9
|
+
export type MappingNodeDefinition =
|
|
10
|
+
import('./patram-config.js').MappingNodeDefinition;
|
|
11
|
+
export type MappingEmitDefinition =
|
|
12
|
+
import('./patram-config.js').MappingEmitDefinition;
|
|
13
|
+
export type MappingDefinition = import('./patram-config.js').MappingDefinition;
|
|
14
|
+
export type PatramGraphConfig = import('./patram-config.js').PatramGraphConfig;
|
|
15
|
+
export type PatramClassConfig = ClassDefinition & {
|
|
16
|
+
schema?: ClassSchemaConfig;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export type PatramConfig = Omit<PatramGraphConfig, 'classes'> & {
|
|
20
|
+
classes: Record<string, PatramClassConfig>;
|
|
21
|
+
fields?: Record<string, MetadataFieldConfig>;
|
|
22
|
+
};
|
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
/** @import * as $k$$l$output$j$view$k$types$k$ts from './output-view.types.ts'; */
|
|
2
|
-
/* eslint-disable max-lines */
|
|
3
1
|
/**
|
|
4
2
|
* @import { BuildGraphResult, GraphNode } from './build-graph.types.ts';
|
|
5
3
|
* @import { DerivedSummaryEvaluator } from './derived-summary.js';
|
|
6
4
|
* @import { PatramRepoConfig } from './load-patram-config.types.ts';
|
|
7
5
|
* @import { ParsedCliArguments } from './parse-cli-arguments.types.ts';
|
|
8
|
-
* @import { OutputMetadataField, OutputStoredQueryItem, OutputView, ResolvedOutputMode, ShowOutputView } from './output-view.types.ts';
|
|
6
|
+
* @import { OutputDerivedSummary, OutputMetadataField, OutputNodeItem, OutputResolvedLinkItem, OutputResolvedLinkTarget, OutputStoredQueryItem, OutputView, ResolvedOutputMode, ShowOutputView } from './output-view.types.ts';
|
|
9
7
|
*/
|
|
8
|
+
/* eslint-disable max-lines */
|
|
10
9
|
|
|
11
10
|
import { renderJsonOutput } from './render-json-output.js';
|
|
12
11
|
import { renderPlainOutput } from './render-plain-output.js';
|
|
@@ -171,9 +170,9 @@ function createStoredQueriesOutputView(stored_queries) {
|
|
|
171
170
|
|
|
172
171
|
/**
|
|
173
172
|
* @param {GraphNode} graph_node
|
|
174
|
-
* @param {
|
|
173
|
+
* @param {OutputDerivedSummary | null} derived_summary
|
|
175
174
|
* @param {NonNullable<PatramRepoConfig['fields']>} field_definitions
|
|
176
|
-
* @returns {
|
|
175
|
+
* @returns {OutputNodeItem}
|
|
177
176
|
*/
|
|
178
177
|
function createOutputNodeItem(graph_node, derived_summary, field_definitions) {
|
|
179
178
|
const title = getOutputNodeTitle(graph_node);
|
|
@@ -203,9 +202,9 @@ function createOutputNodeItem(graph_node, derived_summary, field_definitions) {
|
|
|
203
202
|
/**
|
|
204
203
|
* @param {{ kind?: string, path: string, status?: string, title: string }} target
|
|
205
204
|
* @param {NonNullable<PatramRepoConfig['fields']>} field_definitions
|
|
206
|
-
* @param {
|
|
205
|
+
* @param {OutputDerivedSummary | null} derived_summary
|
|
207
206
|
* @param {GraphNode | undefined} graph_node
|
|
208
|
-
* @returns {
|
|
207
|
+
* @returns {OutputResolvedLinkTarget}
|
|
209
208
|
*/
|
|
210
209
|
function createResolvedLinkTarget(
|
|
211
210
|
target,
|
|
@@ -220,7 +219,7 @@ function createResolvedLinkTarget(
|
|
|
220
219
|
fields.status = target.status;
|
|
221
220
|
}
|
|
222
221
|
|
|
223
|
-
/** @type {
|
|
222
|
+
/** @type {OutputResolvedLinkTarget} */
|
|
224
223
|
const resolved_target = {
|
|
225
224
|
derived_summary: derived_summary ?? undefined,
|
|
226
225
|
fields,
|
|
@@ -288,7 +287,7 @@ function getOutputNodeId(graph_node) {
|
|
|
288
287
|
/**
|
|
289
288
|
* @param {{ label: string, reference: number, target: { kind?: string, path: string, status?: string, title: string } }} resolved_link
|
|
290
289
|
* @param {{ derived_summary_evaluator?: DerivedSummaryEvaluator, document_node_ids?: BuildGraphResult['document_node_ids'], graph_nodes?: BuildGraphResult['nodes'], repo_config?: PatramRepoConfig }} command_options
|
|
291
|
-
* @returns {
|
|
290
|
+
* @returns {OutputResolvedLinkItem}
|
|
292
291
|
*/
|
|
293
292
|
function createResolvedLinkOutputItem(resolved_link, command_options) {
|
|
294
293
|
const target_graph_node = resolveDocumentGraphNode(
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
+
* @import { ClassDefinition } from './patram-config.js';
|
|
2
3
|
* @import { PatramRepoConfig } from './load-patram-config.types.ts';
|
|
3
4
|
* @import { PatramConfig } from './patram-config.types.ts';
|
|
4
5
|
*/
|
|
@@ -74,7 +75,7 @@ export function resolvePatramGraphConfig(repo_config) {
|
|
|
74
75
|
const graph_config = parsePatramConfig({
|
|
75
76
|
classes: {
|
|
76
77
|
...BUILT_IN_PATRAM_CONFIG.classes,
|
|
77
|
-
...repo_config.classes,
|
|
78
|
+
...collectGraphClassDefinitions(repo_config.classes),
|
|
78
79
|
},
|
|
79
80
|
mappings: {
|
|
80
81
|
...BUILT_IN_PATRAM_CONFIG.mappings,
|
|
@@ -88,7 +89,44 @@ export function resolvePatramGraphConfig(repo_config) {
|
|
|
88
89
|
|
|
89
90
|
return {
|
|
90
91
|
...graph_config,
|
|
91
|
-
|
|
92
|
+
classes: mergeResolvedClasses(graph_config.classes, repo_config.classes),
|
|
92
93
|
fields: repo_config.fields,
|
|
93
94
|
};
|
|
94
95
|
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* @param {PatramRepoConfig['classes']} classes
|
|
99
|
+
* @returns {Record<string, ClassDefinition>}
|
|
100
|
+
*/
|
|
101
|
+
function collectGraphClassDefinitions(classes) {
|
|
102
|
+
/** @type {Record<string, ClassDefinition>} */
|
|
103
|
+
const graph_class_definitions = {};
|
|
104
|
+
|
|
105
|
+
for (const [class_name, class_definition] of Object.entries(classes ?? {})) {
|
|
106
|
+
graph_class_definitions[class_name] = {
|
|
107
|
+
builtin: class_definition.builtin,
|
|
108
|
+
label: class_definition.label,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return graph_class_definitions;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* @param {Record<string, ClassDefinition>} graph_classes
|
|
117
|
+
* @param {PatramRepoConfig['classes']} repo_classes
|
|
118
|
+
* @returns {PatramConfig['classes']}
|
|
119
|
+
*/
|
|
120
|
+
function mergeResolvedClasses(graph_classes, repo_classes) {
|
|
121
|
+
/** @type {PatramConfig['classes']} */
|
|
122
|
+
const resolved_classes = {};
|
|
123
|
+
|
|
124
|
+
for (const [class_name, class_definition] of Object.entries(graph_classes)) {
|
|
125
|
+
resolved_classes[class_name] = {
|
|
126
|
+
...class_definition,
|
|
127
|
+
schema: repo_classes?.[class_name]?.schema,
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
return resolved_classes;
|
|
132
|
+
}
|