patram 0.1.1 → 0.2.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 +39 -7
- package/lib/build-graph.js +14 -1
- package/lib/cli-help-metadata.js +552 -0
- package/lib/derived-summary.js +278 -0
- package/lib/format-derived-summary-row.js +9 -0
- package/lib/format-node-header.js +19 -0
- package/lib/format-output-item-block.js +22 -0
- package/lib/format-output-metadata.js +62 -0
- package/lib/layout-stored-queries.js +150 -2
- package/lib/load-patram-config.js +401 -2
- package/lib/load-patram-config.types.ts +31 -0
- package/lib/output-view.types.ts +15 -0
- package/lib/parse-cli-arguments-helpers.js +263 -90
- package/lib/parse-cli-arguments.js +160 -8
- package/lib/parse-cli-arguments.types.ts +48 -3
- package/lib/parse-where-clause.js +604 -209
- package/lib/parse-where-clause.types.ts +70 -0
- package/lib/patram-cli.js +144 -17
- package/lib/patram.js +6 -0
- package/lib/query-graph.js +231 -119
- package/lib/query-inspection.js +523 -0
- package/lib/render-check-output.js +1 -1
- package/lib/render-cli-help.js +419 -0
- package/lib/render-json-output.js +57 -4
- package/lib/render-output-view.js +37 -8
- package/lib/render-plain-output.js +31 -86
- package/lib/render-rich-output.js +34 -87
- package/lib/resolve-where-clause.js +18 -3
- 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 +8 -3
|
@@ -10,6 +10,8 @@ import process from 'node:process';
|
|
|
10
10
|
import { z } from 'zod';
|
|
11
11
|
|
|
12
12
|
import { parsePatramConfig } from './patram-config.js';
|
|
13
|
+
import { parseWhereClause } from './parse-where-clause.js';
|
|
14
|
+
import { resolvePatramGraphConfig } from './resolve-patram-graph-config.js';
|
|
13
15
|
import { DEFAULT_INCLUDE_PATTERNS } from './source-file-defaults.js';
|
|
14
16
|
|
|
15
17
|
/**
|
|
@@ -36,8 +38,63 @@ const stored_query_schema = z
|
|
|
36
38
|
})
|
|
37
39
|
.strict();
|
|
38
40
|
|
|
41
|
+
const derived_summary_scalar_schema = z.union([
|
|
42
|
+
z.boolean(),
|
|
43
|
+
z.number(),
|
|
44
|
+
z.string(),
|
|
45
|
+
z.null(),
|
|
46
|
+
]);
|
|
47
|
+
|
|
48
|
+
const derived_summary_count_schema = z
|
|
49
|
+
.object({
|
|
50
|
+
traversal: z
|
|
51
|
+
.string()
|
|
52
|
+
.min(1, 'Derived summary count "traversal" must not be empty.'),
|
|
53
|
+
where: z
|
|
54
|
+
.string()
|
|
55
|
+
.min(1, 'Derived summary count "where" must not be empty.'),
|
|
56
|
+
})
|
|
57
|
+
.strict();
|
|
58
|
+
|
|
59
|
+
const derived_summary_select_case_schema = z
|
|
60
|
+
.object({
|
|
61
|
+
value: derived_summary_scalar_schema,
|
|
62
|
+
when: z.string().min(1, 'Derived summary select "when" must not be empty.'),
|
|
63
|
+
})
|
|
64
|
+
.strict();
|
|
65
|
+
|
|
66
|
+
const derived_summary_field_schema = z
|
|
67
|
+
.object({
|
|
68
|
+
count: derived_summary_count_schema.optional(),
|
|
69
|
+
default: derived_summary_scalar_schema.optional(),
|
|
70
|
+
name: z
|
|
71
|
+
.string()
|
|
72
|
+
.regex(
|
|
73
|
+
/^[a-z][a-z0-9_]*$/du,
|
|
74
|
+
'Derived summary field names must use lower_snake_case.',
|
|
75
|
+
),
|
|
76
|
+
select: z.array(derived_summary_select_case_schema).optional(),
|
|
77
|
+
})
|
|
78
|
+
.strict()
|
|
79
|
+
.superRefine(validateDerivedSummaryFieldDefinition);
|
|
80
|
+
|
|
81
|
+
const derived_summary_schema = z
|
|
82
|
+
.object({
|
|
83
|
+
fields: z
|
|
84
|
+
.array(derived_summary_field_schema)
|
|
85
|
+
.min(1, 'Derived summary "fields" must contain at least one field.'),
|
|
86
|
+
kinds: z
|
|
87
|
+
.array(z.string().min(1))
|
|
88
|
+
.min(1, 'Derived summary "kinds" must contain at least one kind.'),
|
|
89
|
+
})
|
|
90
|
+
.strict()
|
|
91
|
+
.superRefine(validateDerivedSummaryDefinition);
|
|
92
|
+
|
|
39
93
|
const patram_repo_config_schema = z
|
|
40
94
|
.object({
|
|
95
|
+
derived_summaries: z
|
|
96
|
+
.record(z.string().min(1), derived_summary_schema)
|
|
97
|
+
.optional(),
|
|
41
98
|
include: z
|
|
42
99
|
.array(z.string().min(1, 'Include globs must not be empty.'))
|
|
43
100
|
.min(1, 'Include must contain at least one glob.')
|
|
@@ -84,7 +141,15 @@ export async function loadPatramConfig(project_directory = process.cwd()) {
|
|
|
84
141
|
return createLoadResult(null, graph_schema_diagnostics);
|
|
85
142
|
}
|
|
86
143
|
|
|
87
|
-
|
|
144
|
+
const normalized_config = normalizeRepoConfig(config_result.data);
|
|
145
|
+
const derived_summary_diagnostics =
|
|
146
|
+
validateDerivedSummaries(normalized_config);
|
|
147
|
+
|
|
148
|
+
if (derived_summary_diagnostics.length > 0) {
|
|
149
|
+
return createLoadResult(null, derived_summary_diagnostics);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
return createLoadResult(normalized_config, []);
|
|
88
153
|
}
|
|
89
154
|
|
|
90
155
|
/**
|
|
@@ -184,6 +249,88 @@ function createValidationDiagnostic(issue) {
|
|
|
184
249
|
};
|
|
185
250
|
}
|
|
186
251
|
|
|
252
|
+
/**
|
|
253
|
+
* @param {{ count?: unknown, default?: unknown, select?: unknown }} field_definition
|
|
254
|
+
* @param {import('zod').RefinementCtx} refinement_context
|
|
255
|
+
*/
|
|
256
|
+
function validateDerivedSummaryFieldDefinition(
|
|
257
|
+
field_definition,
|
|
258
|
+
refinement_context,
|
|
259
|
+
) {
|
|
260
|
+
const evaluator_count =
|
|
261
|
+
Number(field_definition.count !== undefined) +
|
|
262
|
+
Number(field_definition.select !== undefined);
|
|
263
|
+
|
|
264
|
+
if (evaluator_count !== 1) {
|
|
265
|
+
refinement_context.addIssue({
|
|
266
|
+
code: 'custom',
|
|
267
|
+
message:
|
|
268
|
+
'Derived summary fields must define exactly one of "count" or "select".',
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
if (
|
|
273
|
+
field_definition.count !== undefined &&
|
|
274
|
+
field_definition.default !== undefined
|
|
275
|
+
) {
|
|
276
|
+
refinement_context.addIssue({
|
|
277
|
+
code: 'custom',
|
|
278
|
+
message: 'Derived summary count fields must not define "default".',
|
|
279
|
+
path: ['default'],
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
if (field_definition.select === undefined) {
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
if (
|
|
288
|
+
Array.isArray(field_definition.select) &&
|
|
289
|
+
field_definition.select.length === 0
|
|
290
|
+
) {
|
|
291
|
+
refinement_context.addIssue({
|
|
292
|
+
code: 'custom',
|
|
293
|
+
message: 'Derived summary "select" must contain at least one case.',
|
|
294
|
+
path: ['select'],
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
if (field_definition.default === undefined) {
|
|
299
|
+
refinement_context.addIssue({
|
|
300
|
+
code: 'custom',
|
|
301
|
+
message: 'Derived summary select fields must define "default".',
|
|
302
|
+
path: ['default'],
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* @param {{ fields: Array<{ name: string }> }} summary_definition
|
|
309
|
+
* @param {import('zod').RefinementCtx} refinement_context
|
|
310
|
+
*/
|
|
311
|
+
function validateDerivedSummaryDefinition(
|
|
312
|
+
summary_definition,
|
|
313
|
+
refinement_context,
|
|
314
|
+
) {
|
|
315
|
+
const seen_field_names = new Set();
|
|
316
|
+
|
|
317
|
+
for (const [
|
|
318
|
+
field_index,
|
|
319
|
+
field_definition,
|
|
320
|
+
] of summary_definition.fields.entries()) {
|
|
321
|
+
if (!seen_field_names.has(field_definition.name)) {
|
|
322
|
+
seen_field_names.add(field_definition.name);
|
|
323
|
+
continue;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
refinement_context.addIssue({
|
|
327
|
+
code: 'custom',
|
|
328
|
+
message: `Duplicate derived summary field "${field_definition.name}".`,
|
|
329
|
+
path: ['fields', field_index, 'name'],
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
|
|
187
334
|
/**
|
|
188
335
|
* @param {{ include: string[], queries: Record<string, { where: string }>, kinds?: unknown, mappings?: unknown, relations?: unknown }} repo_config
|
|
189
336
|
* @returns {PatramDiagnostic[]}
|
|
@@ -214,6 +361,41 @@ function validateGraphSchema(repo_config) {
|
|
|
214
361
|
return [];
|
|
215
362
|
}
|
|
216
363
|
|
|
364
|
+
/**
|
|
365
|
+
* @param {PatramRepoConfig} repo_config
|
|
366
|
+
* @returns {PatramDiagnostic[]}
|
|
367
|
+
*/
|
|
368
|
+
function validateDerivedSummaries(repo_config) {
|
|
369
|
+
if (!repo_config.derived_summaries) {
|
|
370
|
+
return [];
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
const graph_config = resolvePatramGraphConfig(repo_config);
|
|
374
|
+
const known_relation_names = new Set(Object.keys(graph_config.relations));
|
|
375
|
+
/** @type {PatramDiagnostic[]} */
|
|
376
|
+
const diagnostics = [];
|
|
377
|
+
const kind_coverage = new Map();
|
|
378
|
+
|
|
379
|
+
for (const [summary_name, summary_definition] of Object.entries(
|
|
380
|
+
repo_config.derived_summaries,
|
|
381
|
+
)) {
|
|
382
|
+
collectDuplicateKindDiagnostics(
|
|
383
|
+
diagnostics,
|
|
384
|
+
kind_coverage,
|
|
385
|
+
summary_definition.kinds,
|
|
386
|
+
summary_name,
|
|
387
|
+
);
|
|
388
|
+
collectDerivedSummaryFieldDiagnostics(
|
|
389
|
+
diagnostics,
|
|
390
|
+
known_relation_names,
|
|
391
|
+
summary_name,
|
|
392
|
+
summary_definition.fields,
|
|
393
|
+
);
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
return diagnostics;
|
|
397
|
+
}
|
|
398
|
+
|
|
217
399
|
/**
|
|
218
400
|
* @returns {PatramRepoConfig}
|
|
219
401
|
*/
|
|
@@ -225,7 +407,7 @@ function createDefaultRepoConfig() {
|
|
|
225
407
|
}
|
|
226
408
|
|
|
227
409
|
/**
|
|
228
|
-
* @param {{ include: string[], queries: Record<string, { where: string }>, kinds?: unknown, mappings?: unknown, relations?: unknown }} repo_config
|
|
410
|
+
* @param {{ derived_summaries?: unknown, include: string[], queries: Record<string, { where: string }>, kinds?: unknown, mappings?: unknown, relations?: unknown }} repo_config
|
|
229
411
|
* @returns {PatramRepoConfig}
|
|
230
412
|
*/
|
|
231
413
|
function normalizeRepoConfig(repo_config) {
|
|
@@ -235,6 +417,16 @@ function normalizeRepoConfig(repo_config) {
|
|
|
235
417
|
queries: { ...repo_config.queries },
|
|
236
418
|
};
|
|
237
419
|
|
|
420
|
+
if (
|
|
421
|
+
repo_config.derived_summaries !== undefined &&
|
|
422
|
+
repo_config.derived_summaries !== null
|
|
423
|
+
) {
|
|
424
|
+
normalized_config.derived_summaries =
|
|
425
|
+
/** @type {PatramRepoConfig['derived_summaries']} */ (
|
|
426
|
+
repo_config.derived_summaries
|
|
427
|
+
);
|
|
428
|
+
}
|
|
429
|
+
|
|
238
430
|
if (repo_config.kinds !== undefined && repo_config.kinds !== null) {
|
|
239
431
|
normalized_config.kinds = /** @type {PatramRepoConfig['kinds']} */ (
|
|
240
432
|
repo_config.kinds
|
|
@@ -256,6 +448,213 @@ function normalizeRepoConfig(repo_config) {
|
|
|
256
448
|
return normalized_config;
|
|
257
449
|
}
|
|
258
450
|
|
|
451
|
+
/**
|
|
452
|
+
* @param {PatramDiagnostic[]} diagnostics
|
|
453
|
+
* @param {Map<string, string>} kind_coverage
|
|
454
|
+
* @param {string[]} kind_names
|
|
455
|
+
* @param {string} summary_name
|
|
456
|
+
*/
|
|
457
|
+
function collectDuplicateKindDiagnostics(
|
|
458
|
+
diagnostics,
|
|
459
|
+
kind_coverage,
|
|
460
|
+
kind_names,
|
|
461
|
+
summary_name,
|
|
462
|
+
) {
|
|
463
|
+
for (const kind_name of kind_names) {
|
|
464
|
+
const existing_summary_name = kind_coverage.get(kind_name);
|
|
465
|
+
|
|
466
|
+
if (!existing_summary_name) {
|
|
467
|
+
kind_coverage.set(kind_name, summary_name);
|
|
468
|
+
continue;
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
diagnostics.push(
|
|
472
|
+
createConfigDiagnostic(
|
|
473
|
+
`derived_summaries.${summary_name}.kinds`,
|
|
474
|
+
`Kind "${kind_name}" is already covered by derived summary "${existing_summary_name}".`,
|
|
475
|
+
),
|
|
476
|
+
);
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
/**
|
|
481
|
+
* @param {PatramDiagnostic[]} diagnostics
|
|
482
|
+
* @param {Set<string>} known_relation_names
|
|
483
|
+
* @param {string} summary_name
|
|
484
|
+
* @param {import('./load-patram-config.types.ts').DerivedSummaryFieldConfig[]} field_definitions
|
|
485
|
+
*/
|
|
486
|
+
function collectDerivedSummaryFieldDiagnostics(
|
|
487
|
+
diagnostics,
|
|
488
|
+
known_relation_names,
|
|
489
|
+
summary_name,
|
|
490
|
+
field_definitions,
|
|
491
|
+
) {
|
|
492
|
+
for (const [field_index, field_definition] of field_definitions.entries()) {
|
|
493
|
+
if ('count' in field_definition) {
|
|
494
|
+
collectTraversalDiagnostic(
|
|
495
|
+
diagnostics,
|
|
496
|
+
field_definition.count.traversal,
|
|
497
|
+
known_relation_names,
|
|
498
|
+
`derived_summaries.${summary_name}.fields.${field_index}.count.traversal`,
|
|
499
|
+
);
|
|
500
|
+
collectWhereClauseDiagnostics(
|
|
501
|
+
diagnostics,
|
|
502
|
+
field_definition.count.where,
|
|
503
|
+
known_relation_names,
|
|
504
|
+
`derived_summaries.${summary_name}.fields.${field_index}.count.where`,
|
|
505
|
+
);
|
|
506
|
+
continue;
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
for (const [case_index, select_case] of field_definition.select.entries()) {
|
|
510
|
+
collectWhereClauseDiagnostics(
|
|
511
|
+
diagnostics,
|
|
512
|
+
select_case.when,
|
|
513
|
+
known_relation_names,
|
|
514
|
+
`derived_summaries.${summary_name}.fields.${field_index}.select.${case_index}.when`,
|
|
515
|
+
);
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
/**
|
|
521
|
+
* @param {PatramDiagnostic[]} diagnostics
|
|
522
|
+
* @param {string} traversal_text
|
|
523
|
+
* @param {Set<string>} known_relation_names
|
|
524
|
+
* @param {string} diagnostic_path
|
|
525
|
+
*/
|
|
526
|
+
function collectTraversalDiagnostic(
|
|
527
|
+
diagnostics,
|
|
528
|
+
traversal_text,
|
|
529
|
+
known_relation_names,
|
|
530
|
+
diagnostic_path,
|
|
531
|
+
) {
|
|
532
|
+
const traversal_match =
|
|
533
|
+
/^(?<direction>in|out):(?<relation_name>[a-zA-Z0-9_]+)$/du.exec(
|
|
534
|
+
traversal_text,
|
|
535
|
+
);
|
|
536
|
+
|
|
537
|
+
if (!traversal_match?.groups?.relation_name) {
|
|
538
|
+
diagnostics.push(
|
|
539
|
+
createConfigDiagnostic(
|
|
540
|
+
diagnostic_path,
|
|
541
|
+
'Derived summary traversal must use "in:<relation>" or "out:<relation>".',
|
|
542
|
+
),
|
|
543
|
+
);
|
|
544
|
+
|
|
545
|
+
return;
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
if (known_relation_names.has(traversal_match.groups.relation_name)) {
|
|
549
|
+
return;
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
diagnostics.push(
|
|
553
|
+
createConfigDiagnostic(
|
|
554
|
+
diagnostic_path,
|
|
555
|
+
`Unknown relation "${traversal_match.groups.relation_name}" in derived summary traversal.`,
|
|
556
|
+
),
|
|
557
|
+
);
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
/**
|
|
561
|
+
* @param {PatramDiagnostic[]} diagnostics
|
|
562
|
+
* @param {string} where_clause
|
|
563
|
+
* @param {Set<string>} known_relation_names
|
|
564
|
+
* @param {string} diagnostic_path
|
|
565
|
+
*/
|
|
566
|
+
function collectWhereClauseDiagnostics(
|
|
567
|
+
diagnostics,
|
|
568
|
+
where_clause,
|
|
569
|
+
known_relation_names,
|
|
570
|
+
diagnostic_path,
|
|
571
|
+
) {
|
|
572
|
+
const parse_result = parseWhereClause(where_clause);
|
|
573
|
+
|
|
574
|
+
if (!parse_result.success) {
|
|
575
|
+
diagnostics.push(
|
|
576
|
+
createConfigDiagnostic(diagnostic_path, parse_result.diagnostic.message),
|
|
577
|
+
);
|
|
578
|
+
|
|
579
|
+
return;
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
for (const clause of parse_result.clauses) {
|
|
583
|
+
collectClauseRelationDiagnostics(
|
|
584
|
+
diagnostics,
|
|
585
|
+
clause.term,
|
|
586
|
+
known_relation_names,
|
|
587
|
+
diagnostic_path,
|
|
588
|
+
);
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
/**
|
|
593
|
+
* @param {PatramDiagnostic[]} diagnostics
|
|
594
|
+
* @param {import('./parse-where-clause.types.ts').ParsedTerm} term
|
|
595
|
+
* @param {Set<string>} known_relation_names
|
|
596
|
+
* @param {string} diagnostic_path
|
|
597
|
+
*/
|
|
598
|
+
function collectClauseRelationDiagnostics(
|
|
599
|
+
diagnostics,
|
|
600
|
+
term,
|
|
601
|
+
known_relation_names,
|
|
602
|
+
diagnostic_path,
|
|
603
|
+
) {
|
|
604
|
+
if (term.kind === 'aggregate') {
|
|
605
|
+
if (!known_relation_names.has(term.traversal.relation_name)) {
|
|
606
|
+
diagnostics.push(
|
|
607
|
+
createConfigDiagnostic(
|
|
608
|
+
diagnostic_path,
|
|
609
|
+
`Unknown relation "${term.traversal.relation_name}" in traversal clause.`,
|
|
610
|
+
),
|
|
611
|
+
);
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
for (const nested_clause of term.clauses) {
|
|
615
|
+
collectClauseRelationDiagnostics(
|
|
616
|
+
diagnostics,
|
|
617
|
+
nested_clause.term,
|
|
618
|
+
known_relation_names,
|
|
619
|
+
diagnostic_path,
|
|
620
|
+
);
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
return;
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
if (term.kind !== 'relation' && term.kind !== 'relation_target') {
|
|
627
|
+
return;
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
if (known_relation_names.has(term.relation_name)) {
|
|
631
|
+
return;
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
diagnostics.push(
|
|
635
|
+
createConfigDiagnostic(
|
|
636
|
+
diagnostic_path,
|
|
637
|
+
`Unknown relation "${term.relation_name}" in relation clause.`,
|
|
638
|
+
),
|
|
639
|
+
);
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
/**
|
|
643
|
+
* @param {string} issue_path
|
|
644
|
+
* @param {string} message
|
|
645
|
+
* @returns {PatramDiagnostic}
|
|
646
|
+
*/
|
|
647
|
+
function createConfigDiagnostic(issue_path, message) {
|
|
648
|
+
return {
|
|
649
|
+
code: 'config.invalid',
|
|
650
|
+
column: 1,
|
|
651
|
+
level: 'error',
|
|
652
|
+
line: 1,
|
|
653
|
+
message: `Invalid config at "${issue_path}": ${message}`,
|
|
654
|
+
path: CONFIG_FILE_NAME,
|
|
655
|
+
};
|
|
656
|
+
}
|
|
657
|
+
|
|
259
658
|
/**
|
|
260
659
|
* @param {unknown} error
|
|
261
660
|
* @returns {error is NodeJS.ErrnoException}
|
|
@@ -8,7 +8,38 @@ export interface StoredQueryConfig {
|
|
|
8
8
|
where: string;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
+
export type DerivedSummaryScalar = boolean | number | string | null;
|
|
12
|
+
|
|
13
|
+
export interface DerivedSummaryCountFieldConfig {
|
|
14
|
+
count: {
|
|
15
|
+
traversal: string;
|
|
16
|
+
where: string;
|
|
17
|
+
};
|
|
18
|
+
name: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface DerivedSummarySelectCaseConfig {
|
|
22
|
+
value: DerivedSummaryScalar;
|
|
23
|
+
when: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface DerivedSummarySelectFieldConfig {
|
|
27
|
+
default: DerivedSummaryScalar;
|
|
28
|
+
name: string;
|
|
29
|
+
select: DerivedSummarySelectCaseConfig[];
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export type DerivedSummaryFieldConfig =
|
|
33
|
+
| DerivedSummaryCountFieldConfig
|
|
34
|
+
| DerivedSummarySelectFieldConfig;
|
|
35
|
+
|
|
36
|
+
export interface DerivedSummaryConfig {
|
|
37
|
+
fields: DerivedSummaryFieldConfig[];
|
|
38
|
+
kinds: string[];
|
|
39
|
+
}
|
|
40
|
+
|
|
11
41
|
export interface PatramRepoConfig {
|
|
42
|
+
derived_summaries?: Record<string, DerivedSummaryConfig>;
|
|
12
43
|
include: string[];
|
|
13
44
|
kinds?: Record<string, KindDefinition>;
|
|
14
45
|
mappings?: Record<string, MappingDefinition>;
|
package/lib/output-view.types.ts
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
import type { GraphNode } from './build-graph.types.ts';
|
|
2
2
|
|
|
3
|
+
export type OutputDerivedValue = boolean | number | string | null;
|
|
4
|
+
|
|
5
|
+
export interface OutputDerivedField {
|
|
6
|
+
name: string;
|
|
7
|
+
value: OutputDerivedValue;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface OutputDerivedSummary {
|
|
11
|
+
fields: OutputDerivedField[];
|
|
12
|
+
name: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
3
15
|
export interface OutputViewSummary {
|
|
4
16
|
count: number;
|
|
5
17
|
kind: 'resolved_link_list' | 'result_list' | 'stored_query_list';
|
|
@@ -13,6 +25,7 @@ export interface QueryOutputViewSummary extends OutputViewSummary {
|
|
|
13
25
|
}
|
|
14
26
|
|
|
15
27
|
export interface OutputNodeItem {
|
|
28
|
+
derived_summary?: OutputDerivedSummary;
|
|
16
29
|
id: string;
|
|
17
30
|
kind: 'node';
|
|
18
31
|
node_kind: GraphNode['kind'];
|
|
@@ -28,6 +41,7 @@ export interface OutputStoredQueryItem {
|
|
|
28
41
|
}
|
|
29
42
|
|
|
30
43
|
export interface OutputResolvedLinkTarget {
|
|
44
|
+
derived_summary?: OutputDerivedSummary;
|
|
31
45
|
kind?: string;
|
|
32
46
|
path: string;
|
|
33
47
|
status?: string;
|
|
@@ -57,6 +71,7 @@ export interface QueriesOutputView {
|
|
|
57
71
|
|
|
58
72
|
export interface ShowOutputView {
|
|
59
73
|
command: 'show';
|
|
74
|
+
document?: OutputNodeItem;
|
|
60
75
|
hints: string[];
|
|
61
76
|
items: OutputResolvedLinkItem[];
|
|
62
77
|
path: string;
|