patram 0.2.0 → 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 +20 -19
- package/lib/build-graph.js +369 -16
- 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 +44 -16
- package/lib/derived-summary.js +10 -8
- 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-node-header.js +9 -7
- package/lib/format-output-metadata.js +15 -23
- package/lib/layout-stored-queries.js +6 -60
- package/lib/load-patram-config.js +433 -96
- package/lib/load-patram-config.types.ts +98 -3
- package/lib/load-project-graph.js +4 -1
- package/lib/output-view.types.ts +14 -6
- package/lib/parse-cli-arguments.types.ts +1 -1
- package/lib/parse-where-clause.js +117 -51
- package/lib/parse-where-clause.types.ts +4 -2
- package/lib/patram-cli.js +36 -4
- package/lib/patram-config.js +31 -31
- package/lib/patram-config.types.ts +10 -4
- package/lib/query-graph.js +241 -22
- package/lib/query-inspection.js +285 -10
- package/lib/render-field-discovery.js +148 -0
- package/lib/render-json-output.js +21 -22
- package/lib/render-output-view.js +240 -19
- package/lib/render-plain-output.js +1 -1
- package/lib/render-rich-output.js +1 -1
- package/lib/resolve-patram-graph-config.js +15 -9
- package/lib/show-document.js +51 -7
- package/package.json +5 -5
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type {
|
|
2
|
-
|
|
2
|
+
ClassDefinition,
|
|
3
3
|
MappingDefinition,
|
|
4
4
|
RelationDefinition,
|
|
5
5
|
} from './patram-config.types.ts';
|
|
@@ -8,6 +8,98 @@ export interface StoredQueryConfig {
|
|
|
8
8
|
where: string;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
+
export type FieldValueTypeName =
|
|
12
|
+
| 'string'
|
|
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
|
+
|
|
75
|
+
export type MetadataFieldConfig =
|
|
76
|
+
| DateFieldConfig
|
|
77
|
+
| DateTimeFieldConfig
|
|
78
|
+
| EnumFieldConfig
|
|
79
|
+
| GlobFieldConfig
|
|
80
|
+
| IntegerFieldConfig
|
|
81
|
+
| PathFieldConfig
|
|
82
|
+
| StringFieldConfig;
|
|
83
|
+
|
|
84
|
+
export interface ClassFieldRuleConfig {
|
|
85
|
+
presence: 'required' | 'optional' | 'forbidden';
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export type DirectiveTypeConfig = MetadataFieldConfig;
|
|
89
|
+
export type MetadataDirectiveRuleConfig = ClassFieldRuleConfig;
|
|
90
|
+
|
|
91
|
+
export interface ClassSchemaConfig {
|
|
92
|
+
document_path_class?: string;
|
|
93
|
+
fields: Record<string, ClassFieldRuleConfig>;
|
|
94
|
+
unknown_fields?: 'ignore' | 'error';
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export type MetadataSchemaConfig = ClassSchemaConfig;
|
|
98
|
+
|
|
99
|
+
export interface PathClassConfig {
|
|
100
|
+
prefixes: string[];
|
|
101
|
+
}
|
|
102
|
+
|
|
11
103
|
export type DerivedSummaryScalar = boolean | number | string | null;
|
|
12
104
|
|
|
13
105
|
export interface DerivedSummaryCountFieldConfig {
|
|
@@ -34,15 +126,18 @@ export type DerivedSummaryFieldConfig =
|
|
|
34
126
|
| DerivedSummarySelectFieldConfig;
|
|
35
127
|
|
|
36
128
|
export interface DerivedSummaryConfig {
|
|
129
|
+
classes: string[];
|
|
37
130
|
fields: DerivedSummaryFieldConfig[];
|
|
38
|
-
kinds: string[];
|
|
39
131
|
}
|
|
40
132
|
|
|
41
133
|
export interface PatramRepoConfig {
|
|
134
|
+
class_schemas?: Record<string, ClassSchemaConfig>;
|
|
135
|
+
classes?: Record<string, ClassDefinition>;
|
|
42
136
|
derived_summaries?: Record<string, DerivedSummaryConfig>;
|
|
137
|
+
fields?: Record<string, MetadataFieldConfig>;
|
|
43
138
|
include: string[];
|
|
44
|
-
kinds?: Record<string, KindDefinition>;
|
|
45
139
|
mappings?: Record<string, MappingDefinition>;
|
|
140
|
+
path_classes?: Record<string, PathClassConfig>;
|
|
46
141
|
queries: Record<string, StoredQueryConfig>;
|
|
47
142
|
relations?: Record<string, RelationDefinition>;
|
|
48
143
|
}
|
|
@@ -36,13 +36,14 @@ import { resolvePatramGraphConfig } from './resolve-patram-graph-config.js';
|
|
|
36
36
|
* project directory.
|
|
37
37
|
*
|
|
38
38
|
* @param {string} project_directory
|
|
39
|
-
* @returns {Promise<{ config: PatramRepoConfig, diagnostics: PatramDiagnostic[], graph: BuildGraphResult, source_file_paths: string[] }>}
|
|
39
|
+
* @returns {Promise<{ claims: PatramClaim[], config: PatramRepoConfig, diagnostics: PatramDiagnostic[], graph: BuildGraphResult, source_file_paths: string[] }>}
|
|
40
40
|
*/
|
|
41
41
|
export async function loadProjectGraph(project_directory) {
|
|
42
42
|
const load_result = await loadPatramConfig(project_directory);
|
|
43
43
|
|
|
44
44
|
if (load_result.diagnostics.length > 0) {
|
|
45
45
|
return {
|
|
46
|
+
claims: [],
|
|
46
47
|
config: {
|
|
47
48
|
include: [],
|
|
48
49
|
queries: {},
|
|
@@ -74,6 +75,7 @@ export async function loadProjectGraph(project_directory) {
|
|
|
74
75
|
|
|
75
76
|
if (collect_result.diagnostics.length > 0) {
|
|
76
77
|
return {
|
|
78
|
+
claims: collect_result.claims,
|
|
77
79
|
config: repo_config,
|
|
78
80
|
diagnostics: collect_result.diagnostics,
|
|
79
81
|
graph: {
|
|
@@ -85,6 +87,7 @@ export async function loadProjectGraph(project_directory) {
|
|
|
85
87
|
}
|
|
86
88
|
|
|
87
89
|
return {
|
|
90
|
+
claims: collect_result.claims,
|
|
88
91
|
config: repo_config,
|
|
89
92
|
diagnostics: [],
|
|
90
93
|
graph: buildGraph(graph_config, collect_result.claims),
|
package/lib/output-view.types.ts
CHANGED
|
@@ -12,6 +12,11 @@ export interface OutputDerivedSummary {
|
|
|
12
12
|
name: string;
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
+
export interface OutputMetadataField {
|
|
16
|
+
name: string;
|
|
17
|
+
value: string | string[];
|
|
18
|
+
}
|
|
19
|
+
|
|
15
20
|
export interface OutputViewSummary {
|
|
16
21
|
count: number;
|
|
17
22
|
kind: 'resolved_link_list' | 'result_list' | 'stored_query_list';
|
|
@@ -26,12 +31,13 @@ export interface QueryOutputViewSummary extends OutputViewSummary {
|
|
|
26
31
|
|
|
27
32
|
export interface OutputNodeItem {
|
|
28
33
|
derived_summary?: OutputDerivedSummary;
|
|
34
|
+
fields: Record<string, string | string[]>;
|
|
29
35
|
id: string;
|
|
30
36
|
kind: 'node';
|
|
31
|
-
node_kind:
|
|
32
|
-
path
|
|
33
|
-
status?: string;
|
|
37
|
+
node_kind: string;
|
|
38
|
+
path?: string;
|
|
34
39
|
title: string;
|
|
40
|
+
visible_fields: OutputMetadataField[];
|
|
35
41
|
}
|
|
36
42
|
|
|
37
43
|
export interface OutputStoredQueryItem {
|
|
@@ -42,10 +48,12 @@ export interface OutputStoredQueryItem {
|
|
|
42
48
|
|
|
43
49
|
export interface OutputResolvedLinkTarget {
|
|
44
50
|
derived_summary?: OutputDerivedSummary;
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
51
|
+
fields: Record<string, string | string[]>;
|
|
52
|
+
id: string;
|
|
53
|
+
kind: string;
|
|
54
|
+
path?: string;
|
|
48
55
|
title: string;
|
|
56
|
+
visible_fields: OutputMetadataField[];
|
|
49
57
|
}
|
|
50
58
|
|
|
51
59
|
export interface OutputResolvedLinkItem {
|
|
@@ -218,10 +218,7 @@ function parseAtomicTerm(parser_state) {
|
|
|
218
218
|
return failToken(parser_state);
|
|
219
219
|
}
|
|
220
220
|
|
|
221
|
-
return (
|
|
222
|
-
parseFieldSet(parser_state, field_or_relation_name) ??
|
|
223
|
-
parseOperatorTerm(parser_state, start_index, field_or_relation_name)
|
|
224
|
-
);
|
|
221
|
+
return parseOperatorTerm(parser_state, start_index, field_or_relation_name);
|
|
225
222
|
}
|
|
226
223
|
|
|
227
224
|
/**
|
|
@@ -259,16 +256,12 @@ function createAggregateTerm(parser_state, aggregate_name, traversal, clauses) {
|
|
|
259
256
|
|
|
260
257
|
/**
|
|
261
258
|
* @param {ParserState} parser_state
|
|
259
|
+
* @param {number} start_index
|
|
262
260
|
* @param {ParsedFieldName | string} field_name
|
|
263
261
|
* @returns {ParseTermResult | null}
|
|
264
262
|
*/
|
|
265
|
-
function parseFieldSet(parser_state, field_name) {
|
|
266
|
-
|
|
267
|
-
return null;
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
const start_index = parser_state.index;
|
|
271
|
-
|
|
263
|
+
function parseFieldSet(parser_state, start_index, field_name) {
|
|
264
|
+
const operator_start_index = parser_state.index;
|
|
272
265
|
if (!consumeRequiredWhitespace(parser_state)) {
|
|
273
266
|
return null;
|
|
274
267
|
}
|
|
@@ -276,7 +269,7 @@ function parseFieldSet(parser_state, field_name) {
|
|
|
276
269
|
const operator = parseSetOperator(parser_state);
|
|
277
270
|
|
|
278
271
|
if (!operator) {
|
|
279
|
-
parser_state.index =
|
|
272
|
+
parser_state.index = operator_start_index;
|
|
280
273
|
return null;
|
|
281
274
|
}
|
|
282
275
|
|
|
@@ -287,7 +280,13 @@ function parseFieldSet(parser_state, field_name) {
|
|
|
287
280
|
const values = parseList(parser_state);
|
|
288
281
|
|
|
289
282
|
return values
|
|
290
|
-
? success({
|
|
283
|
+
? success({
|
|
284
|
+
column: start_index + 1,
|
|
285
|
+
field_name,
|
|
286
|
+
kind: 'field_set',
|
|
287
|
+
operator,
|
|
288
|
+
values,
|
|
289
|
+
})
|
|
291
290
|
: failToken(parser_state);
|
|
292
291
|
}
|
|
293
292
|
|
|
@@ -298,18 +297,46 @@ function parseFieldSet(parser_state, field_name) {
|
|
|
298
297
|
* @returns {ParseTermResult}
|
|
299
298
|
*/
|
|
300
299
|
function parseOperatorTerm(parser_state, start_index, field_or_relation_name) {
|
|
301
|
-
const
|
|
300
|
+
const field_set = parseFieldSet(
|
|
301
|
+
parser_state,
|
|
302
|
+
start_index,
|
|
303
|
+
field_or_relation_name,
|
|
304
|
+
);
|
|
305
|
+
|
|
306
|
+
if (field_set) {
|
|
307
|
+
return field_set;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
const prefix_term = parsePrefixTerm(
|
|
311
|
+
parser_state,
|
|
312
|
+
start_index,
|
|
313
|
+
field_or_relation_name,
|
|
314
|
+
);
|
|
302
315
|
|
|
303
316
|
if (prefix_term) {
|
|
304
317
|
return prefix_term;
|
|
305
318
|
}
|
|
306
319
|
|
|
307
|
-
const contains_term = parseContainsTerm(
|
|
320
|
+
const contains_term = parseContainsTerm(
|
|
321
|
+
parser_state,
|
|
322
|
+
start_index,
|
|
323
|
+
field_or_relation_name,
|
|
324
|
+
);
|
|
308
325
|
|
|
309
326
|
if (contains_term) {
|
|
310
327
|
return contains_term;
|
|
311
328
|
}
|
|
312
329
|
|
|
330
|
+
const comparison_term = parseFieldComparisonTerm(
|
|
331
|
+
parser_state,
|
|
332
|
+
start_index,
|
|
333
|
+
field_or_relation_name,
|
|
334
|
+
);
|
|
335
|
+
|
|
336
|
+
if (comparison_term) {
|
|
337
|
+
return comparison_term;
|
|
338
|
+
}
|
|
339
|
+
|
|
313
340
|
const equality_term = parseEqualityTerm(
|
|
314
341
|
parser_state,
|
|
315
342
|
start_index,
|
|
@@ -395,39 +422,51 @@ function parseSetOperator(parser_state) {
|
|
|
395
422
|
|
|
396
423
|
/**
|
|
397
424
|
* @param {ParserState} parser_state
|
|
425
|
+
* @param {number} start_index
|
|
398
426
|
* @param {string} field_name
|
|
399
427
|
* @returns {ParseTermResult | null}
|
|
400
428
|
*/
|
|
401
|
-
function parsePrefixTerm(parser_state, field_name) {
|
|
402
|
-
if (field_name !== 'id' && field_name !== 'path') {
|
|
403
|
-
return null;
|
|
404
|
-
}
|
|
405
|
-
|
|
429
|
+
function parsePrefixTerm(parser_state, start_index, field_name) {
|
|
406
430
|
if (!consumeOperator(parser_state, '^=')) {
|
|
407
431
|
return null;
|
|
408
432
|
}
|
|
409
433
|
|
|
434
|
+
skipWhitespace(parser_state);
|
|
410
435
|
const value = parseBareValue(parser_state);
|
|
411
436
|
|
|
412
437
|
return value
|
|
413
|
-
? success({
|
|
438
|
+
? success({
|
|
439
|
+
column: start_index + 1,
|
|
440
|
+
field_name,
|
|
441
|
+
kind: 'field',
|
|
442
|
+
operator: '^=',
|
|
443
|
+
value,
|
|
444
|
+
})
|
|
414
445
|
: failToken(parser_state);
|
|
415
446
|
}
|
|
416
447
|
|
|
417
448
|
/**
|
|
418
449
|
* @param {ParserState} parser_state
|
|
450
|
+
* @param {number} start_index
|
|
419
451
|
* @param {string} field_name
|
|
420
452
|
* @returns {ParseTermResult | null}
|
|
421
453
|
*/
|
|
422
|
-
function parseContainsTerm(parser_state, field_name) {
|
|
423
|
-
if (
|
|
454
|
+
function parseContainsTerm(parser_state, start_index, field_name) {
|
|
455
|
+
if (!consumeOperator(parser_state, '~')) {
|
|
424
456
|
return null;
|
|
425
457
|
}
|
|
426
458
|
|
|
459
|
+
skipWhitespace(parser_state);
|
|
427
460
|
const value = parseBareValue(parser_state);
|
|
428
461
|
|
|
429
462
|
return value
|
|
430
|
-
? success({
|
|
463
|
+
? success({
|
|
464
|
+
column: start_index + 1,
|
|
465
|
+
field_name,
|
|
466
|
+
kind: 'field',
|
|
467
|
+
operator: '~',
|
|
468
|
+
value,
|
|
469
|
+
})
|
|
431
470
|
: failToken(parser_state);
|
|
432
471
|
}
|
|
433
472
|
|
|
@@ -442,14 +481,20 @@ function parseEqualityTerm(parser_state, start_index, field_or_relation_name) {
|
|
|
442
481
|
return null;
|
|
443
482
|
}
|
|
444
483
|
|
|
484
|
+
skipWhitespace(parser_state);
|
|
445
485
|
const value = parseBareValue(parser_state);
|
|
446
486
|
|
|
447
487
|
if (!value) {
|
|
448
488
|
return failToken(parser_state);
|
|
449
489
|
}
|
|
450
490
|
|
|
451
|
-
if (
|
|
491
|
+
if (
|
|
492
|
+
field_or_relation_name.startsWith('$') ||
|
|
493
|
+
field_or_relation_name === 'title' ||
|
|
494
|
+
!value.includes(':')
|
|
495
|
+
) {
|
|
452
496
|
return success({
|
|
497
|
+
column: start_index + 1,
|
|
453
498
|
field_name: field_or_relation_name,
|
|
454
499
|
kind: 'field',
|
|
455
500
|
operator: '=',
|
|
@@ -457,17 +502,54 @@ function parseEqualityTerm(parser_state, start_index, field_or_relation_name) {
|
|
|
457
502
|
});
|
|
458
503
|
}
|
|
459
504
|
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
505
|
+
return success({
|
|
506
|
+
column: start_index + 1,
|
|
507
|
+
kind: 'relation_target',
|
|
508
|
+
relation_name: field_or_relation_name,
|
|
509
|
+
target_id: value,
|
|
510
|
+
});
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
/**
|
|
514
|
+
* @param {ParserState} parser_state
|
|
515
|
+
* @param {number} start_index
|
|
516
|
+
* @param {string} field_name
|
|
517
|
+
* @returns {ParseTermResult | null}
|
|
518
|
+
*/
|
|
519
|
+
function parseFieldComparisonTerm(parser_state, start_index, field_name) {
|
|
520
|
+
const operator = parseFieldComparisonOperator(parser_state);
|
|
521
|
+
|
|
522
|
+
if (!operator) {
|
|
523
|
+
return null;
|
|
467
524
|
}
|
|
468
525
|
|
|
469
|
-
parser_state
|
|
470
|
-
|
|
526
|
+
skipWhitespace(parser_state);
|
|
527
|
+
const value = parseBareValue(parser_state);
|
|
528
|
+
|
|
529
|
+
if (!value) {
|
|
530
|
+
return failToken(parser_state);
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
return success({
|
|
534
|
+
column: start_index + 1,
|
|
535
|
+
field_name,
|
|
536
|
+
kind: 'field',
|
|
537
|
+
operator,
|
|
538
|
+
value,
|
|
539
|
+
});
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
/**
|
|
543
|
+
* @param {ParserState} parser_state
|
|
544
|
+
* @returns {'!=' | '<=' | '>=' | '<' | '>' | null}
|
|
545
|
+
*/
|
|
546
|
+
function parseFieldComparisonOperator(parser_state) {
|
|
547
|
+
/** @type {Array<'!=' | '<=' | '>=' | '<' | '>'>} */
|
|
548
|
+
const comparisons = ['!=', '<=', '>=', '<', '>'];
|
|
549
|
+
|
|
550
|
+
return (
|
|
551
|
+
comparisons.find((value) => consumeOperator(parser_state, value)) ?? null
|
|
552
|
+
);
|
|
471
553
|
}
|
|
472
554
|
|
|
473
555
|
/**
|
|
@@ -526,7 +608,7 @@ function parseComparison(parser_state) {
|
|
|
526
608
|
* @returns {string | null}
|
|
527
609
|
*/
|
|
528
610
|
function parseIdentifier(parser_state) {
|
|
529
|
-
return readMatch(parser_state,
|
|
611
|
+
return readMatch(parser_state, /^\$?[a-z_][a-z0-9_]*/u);
|
|
530
612
|
}
|
|
531
613
|
|
|
532
614
|
/**
|
|
@@ -643,22 +725,6 @@ function isAtEnd(parser_state) {
|
|
|
643
725
|
return parser_state.index >= parser_state.where_clause.length;
|
|
644
726
|
}
|
|
645
727
|
|
|
646
|
-
/**
|
|
647
|
-
* @param {string} field_name
|
|
648
|
-
* @returns {field_name is ParsedFieldName}
|
|
649
|
-
*/
|
|
650
|
-
function isSupportedFieldName(field_name) {
|
|
651
|
-
return ['id', 'kind', 'path', 'status', 'title'].includes(field_name);
|
|
652
|
-
}
|
|
653
|
-
|
|
654
|
-
/**
|
|
655
|
-
* @param {string} field_name
|
|
656
|
-
* @returns {field_name is 'id' | 'kind' | 'path' | 'status'}
|
|
657
|
-
*/
|
|
658
|
-
function isExactMatchField(field_name) {
|
|
659
|
-
return ['id', 'kind', 'path', 'status'].includes(field_name);
|
|
660
|
-
}
|
|
661
|
-
|
|
662
728
|
/**
|
|
663
729
|
* @param {ParsedTerm} term
|
|
664
730
|
* @returns {ParseTermResult}
|
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
import type { PatramDiagnostic } from './load-patram-config.types.ts';
|
|
2
2
|
|
|
3
|
-
export type ParsedFieldName =
|
|
3
|
+
export type ParsedFieldName = string;
|
|
4
4
|
|
|
5
5
|
export interface ParsedFieldTerm {
|
|
6
|
+
column: number;
|
|
6
7
|
field_name: ParsedFieldName;
|
|
7
8
|
kind: 'field';
|
|
8
|
-
operator: '=' | '^=' | '~';
|
|
9
|
+
operator: '!=' | '<' | '<=' | '=' | '>' | '>=' | '^=' | '~';
|
|
9
10
|
value: string;
|
|
10
11
|
}
|
|
11
12
|
|
|
12
13
|
export interface ParsedFieldSetTerm {
|
|
14
|
+
column: number;
|
|
13
15
|
field_name: ParsedFieldName;
|
|
14
16
|
kind: 'field_set';
|
|
15
17
|
operator: 'in' | 'not in';
|
package/lib/patram-cli.js
CHANGED
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
shouldPageCommandOutput,
|
|
11
11
|
writeCommandOutput,
|
|
12
12
|
} from './command-output.js';
|
|
13
|
+
import { discoverFields } from './discover-fields.js';
|
|
13
14
|
import { listRepoFiles } from './list-source-files.js';
|
|
14
15
|
import { listQueries } from './list-queries.js';
|
|
15
16
|
import { loadPatramConfig } from './load-patram-config.js';
|
|
@@ -36,6 +37,7 @@ import {
|
|
|
36
37
|
createOutputView,
|
|
37
38
|
createShowOutputView,
|
|
38
39
|
} from './render-output-view.js';
|
|
40
|
+
import { renderFieldDiscovery } from './render-field-discovery.js';
|
|
39
41
|
import { resolveWhereClause } from './resolve-where-clause.js';
|
|
40
42
|
import { resolveOutputMode } from './resolve-output-mode.js';
|
|
41
43
|
import { loadShowOutput } from './show-document.js';
|
|
@@ -43,8 +45,8 @@ import { loadShowOutput } from './show-document.js';
|
|
|
43
45
|
/**
|
|
44
46
|
* Patram command execution flow.
|
|
45
47
|
*
|
|
46
|
-
* Loads repo state and routes `check`, `query`, `queries`, and
|
|
47
|
-
* the shared output pipeline.
|
|
48
|
+
* Loads repo state and routes `check`, `fields`, `query`, `queries`, and
|
|
49
|
+
* `show` through the shared output pipeline.
|
|
48
50
|
*
|
|
49
51
|
* Kind: cli
|
|
50
52
|
* Status: active
|
|
@@ -94,6 +96,10 @@ export async function main(cli_arguments, io_context) {
|
|
|
94
96
|
return runQueryCommand(parsed_command, io_context);
|
|
95
97
|
}
|
|
96
98
|
|
|
99
|
+
if (parsed_command.command_name === 'fields') {
|
|
100
|
+
return runFieldsCommand(parsed_command, io_context);
|
|
101
|
+
}
|
|
102
|
+
|
|
97
103
|
if (parsed_command.command_name === 'queries') {
|
|
98
104
|
return runQueriesCommand(parsed_command, io_context);
|
|
99
105
|
}
|
|
@@ -140,7 +146,12 @@ async function runCheckCommand(parsed_command, io_context) {
|
|
|
140
146
|
return 1;
|
|
141
147
|
}
|
|
142
148
|
|
|
143
|
-
const diagnostics = checkGraph(
|
|
149
|
+
const diagnostics = checkGraph(
|
|
150
|
+
project_graph_result.graph,
|
|
151
|
+
repo_file_paths,
|
|
152
|
+
project_graph_result.config,
|
|
153
|
+
project_graph_result.claims,
|
|
154
|
+
);
|
|
144
155
|
const selected_diagnostics = selectCheckTargetDiagnostics(
|
|
145
156
|
diagnostics,
|
|
146
157
|
resolved_target,
|
|
@@ -205,6 +216,7 @@ async function runQueryCommand(parsed_command, io_context) {
|
|
|
205
216
|
const query_result = queryGraph(
|
|
206
217
|
project_graph_result.graph,
|
|
207
218
|
where_clause.value.where_clause,
|
|
219
|
+
project_graph_result.config,
|
|
208
220
|
createQueryPaginationOptions(parsed_command, use_pager),
|
|
209
221
|
);
|
|
210
222
|
|
|
@@ -227,12 +239,31 @@ async function runQueryCommand(parsed_command, io_context) {
|
|
|
227
239
|
createOutputView('query', query_result.nodes, {
|
|
228
240
|
derived_summary_evaluator,
|
|
229
241
|
...createQueryOutputOptions(parsed_command, query_result, use_pager),
|
|
242
|
+
repo_config: project_graph_result.config,
|
|
230
243
|
}),
|
|
231
244
|
);
|
|
232
245
|
|
|
233
246
|
return 0;
|
|
234
247
|
}
|
|
235
248
|
|
|
249
|
+
/**
|
|
250
|
+
* @param {ParsedCliCommandRequest} parsed_command
|
|
251
|
+
* @param {{ stderr: { write(chunk: string): boolean }, stdout: { isTTY?: boolean, write(chunk: string): boolean } }} io_context
|
|
252
|
+
* @returns {Promise<number>}
|
|
253
|
+
*/
|
|
254
|
+
async function runFieldsCommand(parsed_command, io_context) {
|
|
255
|
+
const output_mode = resolveOutputMode(parsed_command, {
|
|
256
|
+
is_tty: io_context.stdout.isTTY === true,
|
|
257
|
+
no_color: process.env.NO_COLOR !== undefined,
|
|
258
|
+
term: process.env.TERM,
|
|
259
|
+
});
|
|
260
|
+
const discovery_result = await discoverFields(process.cwd());
|
|
261
|
+
|
|
262
|
+
io_context.stdout.write(renderFieldDiscovery(discovery_result, output_mode));
|
|
263
|
+
|
|
264
|
+
return 0;
|
|
265
|
+
}
|
|
266
|
+
|
|
236
267
|
/**
|
|
237
268
|
* @param {ParsedCliCommandRequest} parsed_command
|
|
238
269
|
* @param {{ stderr: { write(chunk: string): boolean }, stdout: { isTTY?: boolean, write(chunk: string): boolean } }} io_context
|
|
@@ -365,6 +396,7 @@ async function runShowCommand(parsed_command, io_context) {
|
|
|
365
396
|
createShowOutputView(show_output.value, {
|
|
366
397
|
derived_summary_evaluator,
|
|
367
398
|
graph_nodes: project_graph_result.graph.nodes,
|
|
399
|
+
repo_config: project_graph_result.config,
|
|
368
400
|
}),
|
|
369
401
|
);
|
|
370
402
|
|
|
@@ -396,7 +428,7 @@ function createQueryOutputOptions(parsed_command, query_result, use_pager) {
|
|
|
396
428
|
const offset = parsed_command.query_offset ?? 0;
|
|
397
429
|
|
|
398
430
|
if (query_result.total_count === 0) {
|
|
399
|
-
hints.push('Try: patram query --where "
|
|
431
|
+
hints.push('Try: patram query --where "$class=task"');
|
|
400
432
|
}
|
|
401
433
|
|
|
402
434
|
if (
|