patram 0.10.0 → 0.11.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/cli/arguments.types.d.ts +1 -0
- package/lib/cli/commands/check.js +27 -15
- package/lib/cli/commands/queries.js +189 -1
- package/lib/cli/help-metadata.js +43 -13
- package/lib/cli/parse-arguments-helpers.js +278 -34
- package/lib/cli/render-help.js +8 -2
- package/lib/config/load-patram-config.d.ts +11 -0
- package/lib/config/load-patram-config.js +9 -88
- package/lib/config/manage-stored-queries-helpers.d.ts +69 -0
- package/lib/config/manage-stored-queries-helpers.js +262 -0
- package/lib/config/manage-stored-queries-jsonc.d.ts +31 -0
- package/lib/config/manage-stored-queries-jsonc.js +95 -0
- package/lib/config/manage-stored-queries.d.ts +77 -0
- package/lib/config/manage-stored-queries.js +294 -0
- package/lib/config/validate-patram-config-value.d.ts +13 -0
- package/lib/config/validate-patram-config-value.js +119 -0
- package/lib/graph/query/resolve.d.ts +6 -0
- package/lib/graph/query/resolve.js +4 -1
- package/lib/output/resolve-check-target.js +120 -11
- package/lib/patram.d.ts +8 -0
- package/package.json +2 -1
|
@@ -9,13 +9,15 @@ import {
|
|
|
9
9
|
renderCheckSuccess,
|
|
10
10
|
} from '../../output/render-check-output.js';
|
|
11
11
|
import {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
resolveCheckTargetProjectDirectory,
|
|
13
|
+
resolveCheckTargets,
|
|
14
|
+
selectCheckTargetsDiagnostics,
|
|
15
|
+
selectCheckTargetsSourceFiles,
|
|
15
16
|
} from '../../output/resolve-check-target.js';
|
|
16
17
|
import { listRepoFiles } from '../../scan/list-repo-files.js';
|
|
17
18
|
|
|
18
19
|
import { resolveCommandOutputMode } from '../command-helpers.js';
|
|
20
|
+
import { renderCliParseError } from '../render-help.js';
|
|
19
21
|
|
|
20
22
|
/**
|
|
21
23
|
* @param {ParsedCliCommandRequest} parsed_command
|
|
@@ -24,18 +26,28 @@ import { resolveCommandOutputMode } from '../command-helpers.js';
|
|
|
24
26
|
*/
|
|
25
27
|
export async function runCheckCommand(parsed_command, io_context) {
|
|
26
28
|
const output_mode = resolveCommandOutputMode(parsed_command, io_context);
|
|
27
|
-
const
|
|
28
|
-
parsed_command.command_arguments
|
|
29
|
+
const resolved_targets = await resolveCheckTargets(
|
|
30
|
+
parsed_command.command_arguments,
|
|
29
31
|
);
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
32
|
+
const project_directory =
|
|
33
|
+
resolveCheckTargetProjectDirectory(resolved_targets);
|
|
34
|
+
|
|
35
|
+
if (!project_directory) {
|
|
36
|
+
io_context.stderr.write(
|
|
37
|
+
renderCliParseError({
|
|
38
|
+
code: 'message',
|
|
39
|
+
message: 'Check paths must resolve to the same project root.',
|
|
40
|
+
}),
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
return 1;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const project_graph_result = await loadProjectGraph(project_directory);
|
|
47
|
+
const repo_file_paths = await listRepoFiles(project_directory);
|
|
48
|
+
const selected_source_file_paths = selectCheckTargetsSourceFiles(
|
|
37
49
|
project_graph_result.source_file_paths,
|
|
38
|
-
|
|
50
|
+
resolved_targets,
|
|
39
51
|
);
|
|
40
52
|
|
|
41
53
|
if (project_graph_result.diagnostics.length > 0) {
|
|
@@ -52,9 +64,9 @@ export async function runCheckCommand(parsed_command, io_context) {
|
|
|
52
64
|
project_graph_result.config,
|
|
53
65
|
project_graph_result.claims,
|
|
54
66
|
);
|
|
55
|
-
const selected_diagnostics =
|
|
67
|
+
const selected_diagnostics = selectCheckTargetsDiagnostics(
|
|
56
68
|
diagnostics,
|
|
57
|
-
|
|
69
|
+
resolved_targets,
|
|
58
70
|
);
|
|
59
71
|
|
|
60
72
|
if (selected_diagnostics.length > 0) {
|
|
@@ -4,12 +4,18 @@
|
|
|
4
4
|
|
|
5
5
|
import process from 'node:process';
|
|
6
6
|
|
|
7
|
+
import { manageStoredQueries } from '../../config/manage-stored-queries.js';
|
|
7
8
|
import { loadPatramConfig } from '../../config/load-patram-config.js';
|
|
9
|
+
import { renderCheckDiagnostics } from '../../output/render-check-output.js';
|
|
8
10
|
import { writeCommandOutput } from '../../output/command-output.js';
|
|
9
11
|
import { listQueries } from '../../output/list-queries.js';
|
|
10
12
|
import { createOutputView } from '../../output/render-output-view.js';
|
|
13
|
+
import { renderCliParseError } from '../render-help.js';
|
|
11
14
|
|
|
12
|
-
import {
|
|
15
|
+
import {
|
|
16
|
+
resolveCommandOutputMode,
|
|
17
|
+
writeDiagnostics,
|
|
18
|
+
} from '../command-helpers.js';
|
|
13
19
|
|
|
14
20
|
/**
|
|
15
21
|
* @param {ParsedCliCommandRequest} parsed_command
|
|
@@ -17,6 +23,10 @@ import { writeDiagnostics } from '../command-helpers.js';
|
|
|
17
23
|
* @returns {Promise<number>}
|
|
18
24
|
*/
|
|
19
25
|
export async function runQueriesCommand(parsed_command, io_context) {
|
|
26
|
+
if (parsed_command.command_arguments.length > 0) {
|
|
27
|
+
return runQueriesMutationCommand(parsed_command, io_context);
|
|
28
|
+
}
|
|
29
|
+
|
|
20
30
|
const load_result = await loadPatramConfig(process.cwd());
|
|
21
31
|
|
|
22
32
|
if (load_result.diagnostics.length > 0) {
|
|
@@ -39,3 +49,181 @@ export async function runQueriesCommand(parsed_command, io_context) {
|
|
|
39
49
|
|
|
40
50
|
return 0;
|
|
41
51
|
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* @param {ParsedCliCommandRequest} parsed_command
|
|
55
|
+
* @param {{ stderr: { write(chunk: string): boolean }, stdout: { isTTY?: boolean, write(chunk: string): boolean } }} io_context
|
|
56
|
+
* @returns {Promise<number>}
|
|
57
|
+
*/
|
|
58
|
+
async function runQueriesMutationCommand(parsed_command, io_context) {
|
|
59
|
+
const mutation_request = parseStoredQueryMutation(
|
|
60
|
+
parsed_command.command_arguments,
|
|
61
|
+
);
|
|
62
|
+
const output_mode = resolveCommandOutputMode(parsed_command, io_context);
|
|
63
|
+
|
|
64
|
+
if (!mutation_request.success) {
|
|
65
|
+
io_context.stderr.write(renderCliParseError(mutation_request.error));
|
|
66
|
+
|
|
67
|
+
return 1;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const mutation_result = await manageStoredQueries(
|
|
71
|
+
process.cwd(),
|
|
72
|
+
mutation_request.value,
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
if (!mutation_result.success) {
|
|
76
|
+
if ('error' in mutation_result) {
|
|
77
|
+
io_context.stderr.write(renderCliParseError(mutation_result.error));
|
|
78
|
+
|
|
79
|
+
return 1;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
io_context.stderr.write(
|
|
83
|
+
renderCheckDiagnostics(mutation_result.diagnostics, output_mode),
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
return 1;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
io_context.stdout.write(
|
|
90
|
+
renderStoredQueryMutationResult(
|
|
91
|
+
mutation_result.value,
|
|
92
|
+
parsed_command.output_mode,
|
|
93
|
+
),
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
return 0;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* @param {string[]} command_arguments
|
|
101
|
+
* @returns {{
|
|
102
|
+
* success: true,
|
|
103
|
+
* value:
|
|
104
|
+
* | { action: 'add', description?: string, name: string, where: string }
|
|
105
|
+
* | { action: 'remove', name: string }
|
|
106
|
+
* | {
|
|
107
|
+
* action: 'update',
|
|
108
|
+
* description?: string,
|
|
109
|
+
* name: string,
|
|
110
|
+
* next_name?: string,
|
|
111
|
+
* where?: string,
|
|
112
|
+
* },
|
|
113
|
+
* } | { error: import('../arguments.types.ts').CliParseError, success: false }}
|
|
114
|
+
*/
|
|
115
|
+
function parseStoredQueryMutation(command_arguments) {
|
|
116
|
+
const subcommand_name = command_arguments[0];
|
|
117
|
+
|
|
118
|
+
if (subcommand_name === 'add') {
|
|
119
|
+
return {
|
|
120
|
+
success: true,
|
|
121
|
+
value: {
|
|
122
|
+
action: 'add',
|
|
123
|
+
description: readOptionValue(command_arguments, '--desc'),
|
|
124
|
+
name: command_arguments[1],
|
|
125
|
+
where: readRequiredOptionValue(command_arguments, '--query'),
|
|
126
|
+
},
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
if (subcommand_name === 'remove') {
|
|
131
|
+
return {
|
|
132
|
+
success: true,
|
|
133
|
+
value: {
|
|
134
|
+
action: 'remove',
|
|
135
|
+
name: command_arguments[1],
|
|
136
|
+
},
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if (subcommand_name === 'update') {
|
|
141
|
+
return {
|
|
142
|
+
success: true,
|
|
143
|
+
value: {
|
|
144
|
+
action: 'update',
|
|
145
|
+
description: readOptionValue(command_arguments, '--desc'),
|
|
146
|
+
name: command_arguments[1],
|
|
147
|
+
next_name: readOptionValue(command_arguments, '--name'),
|
|
148
|
+
where: readOptionValue(command_arguments, '--query'),
|
|
149
|
+
},
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
return {
|
|
154
|
+
error: {
|
|
155
|
+
code: 'unexpected_argument',
|
|
156
|
+
command_name: 'queries',
|
|
157
|
+
token: subcommand_name ?? '',
|
|
158
|
+
},
|
|
159
|
+
success: false,
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* @param {{
|
|
165
|
+
* action: 'added',
|
|
166
|
+
* name: string,
|
|
167
|
+
* } | {
|
|
168
|
+
* action: 'removed',
|
|
169
|
+
* name: string,
|
|
170
|
+
* } | {
|
|
171
|
+
* action: 'updated',
|
|
172
|
+
* name: string,
|
|
173
|
+
* previous_name?: string,
|
|
174
|
+
* }} mutation_result
|
|
175
|
+
* @param {ParsedCliCommandRequest['output_mode']} output_mode
|
|
176
|
+
* @returns {string}
|
|
177
|
+
*/
|
|
178
|
+
function renderStoredQueryMutationResult(mutation_result, output_mode) {
|
|
179
|
+
if (output_mode === 'json') {
|
|
180
|
+
return `${JSON.stringify(mutation_result, null, 2)}\n`;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
if (
|
|
184
|
+
mutation_result.action === 'updated' &&
|
|
185
|
+
mutation_result.previous_name !== undefined
|
|
186
|
+
) {
|
|
187
|
+
return `Updated stored query: ${mutation_result.previous_name} -> ${mutation_result.name}\n`;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
if (mutation_result.action === 'updated') {
|
|
191
|
+
return `Updated stored query: ${mutation_result.name}\n`;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
if (mutation_result.action === 'added') {
|
|
195
|
+
return `Added stored query: ${mutation_result.name}\n`;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
return `Removed stored query: ${mutation_result.name}\n`;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* @param {string[]} command_arguments
|
|
203
|
+
* @param {'--desc' | '--name' | '--query'} option_name
|
|
204
|
+
* @returns {string}
|
|
205
|
+
*/
|
|
206
|
+
function readRequiredOptionValue(command_arguments, option_name) {
|
|
207
|
+
const option_value = readOptionValue(command_arguments, option_name);
|
|
208
|
+
|
|
209
|
+
if (option_value === undefined) {
|
|
210
|
+
throw new Error(`Expected ${option_name} to be present.`);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
return option_value;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* @param {string[]} command_arguments
|
|
218
|
+
* @param {'--desc' | '--name' | '--query'} option_name
|
|
219
|
+
* @returns {string | undefined}
|
|
220
|
+
*/
|
|
221
|
+
function readOptionValue(command_arguments, option_name) {
|
|
222
|
+
const option_index = command_arguments.indexOf(option_name);
|
|
223
|
+
|
|
224
|
+
if (option_index < 0) {
|
|
225
|
+
return undefined;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
return command_arguments[option_index + 1];
|
|
229
|
+
}
|
package/lib/cli/help-metadata.js
CHANGED
|
@@ -87,14 +87,15 @@ const COMMAND_DEFINITIONS = {
|
|
|
87
87
|
'patram check',
|
|
88
88
|
'patram check docs',
|
|
89
89
|
'patram check docs/patram.md',
|
|
90
|
+
'patram check docs docs/patram.md',
|
|
90
91
|
],
|
|
91
|
-
extra_positionals_message: 'Check accepts
|
|
92
|
+
extra_positionals_message: 'Check accepts zero or more paths.',
|
|
92
93
|
help_topics: [],
|
|
93
|
-
max_positionals:
|
|
94
|
+
max_positionals: Number.POSITIVE_INFINITY,
|
|
94
95
|
min_positionals: 0,
|
|
95
96
|
missing_argument_examples: [],
|
|
96
97
|
missing_argument_label: null,
|
|
97
|
-
missing_usage_lines: ['patram check [path]'],
|
|
98
|
+
missing_usage_lines: ['patram check [path ...]'],
|
|
98
99
|
option_column_width: 10,
|
|
99
100
|
options: [
|
|
100
101
|
{
|
|
@@ -110,7 +111,7 @@ const COMMAND_DEFINITIONS = {
|
|
|
110
111
|
root_summary: 'Validate a project, directory, or file',
|
|
111
112
|
summary:
|
|
112
113
|
'Validate a project, directory, or file and report graph diagnostics.',
|
|
113
|
-
usage_lines: ['patram check [path] [options]'],
|
|
114
|
+
usage_lines: ['patram check [path ...] [options]'],
|
|
114
115
|
},
|
|
115
116
|
fields: {
|
|
116
117
|
allowed_option_names: new Set(),
|
|
@@ -221,17 +222,40 @@ const COMMAND_DEFINITIONS = {
|
|
|
221
222
|
],
|
|
222
223
|
},
|
|
223
224
|
queries: {
|
|
224
|
-
allowed_option_names: new Set(),
|
|
225
|
-
examples: [
|
|
226
|
-
|
|
225
|
+
allowed_option_names: new Set(['desc', 'name', 'query']),
|
|
226
|
+
examples: [
|
|
227
|
+
'patram queries',
|
|
228
|
+
"patram queries add ready-tasks --query '$class=task and status=ready'",
|
|
229
|
+
"patram queries update ready-tasks --desc 'Show tasks that are ready.'",
|
|
230
|
+
'patram queries remove ready-tasks',
|
|
231
|
+
],
|
|
232
|
+
extra_positionals_message:
|
|
233
|
+
'Queries accepts no positionals unless using add, update, or remove.',
|
|
227
234
|
help_topics: [],
|
|
228
|
-
max_positionals:
|
|
235
|
+
max_positionals: 2,
|
|
229
236
|
min_positionals: 0,
|
|
230
237
|
missing_argument_examples: [],
|
|
231
238
|
missing_argument_label: null,
|
|
232
|
-
missing_usage_lines: [
|
|
233
|
-
|
|
239
|
+
missing_usage_lines: [
|
|
240
|
+
'patram queries',
|
|
241
|
+
'patram queries add <name> --query <clause>',
|
|
242
|
+
'patram queries update <name> [--name <new_name>] [--query <clause>] [--desc <text>]',
|
|
243
|
+
'patram queries remove <name>',
|
|
244
|
+
],
|
|
245
|
+
option_column_width: 19,
|
|
234
246
|
options: [
|
|
247
|
+
{
|
|
248
|
+
description: 'Persist a new stored query',
|
|
249
|
+
label: '--query <clause>',
|
|
250
|
+
},
|
|
251
|
+
{
|
|
252
|
+
description: 'Set or rename the stored query name for update',
|
|
253
|
+
label: '--name <new_name>',
|
|
254
|
+
},
|
|
255
|
+
{
|
|
256
|
+
description: 'Set or clear the stored query description',
|
|
257
|
+
label: '--desc <text>',
|
|
258
|
+
},
|
|
235
259
|
{
|
|
236
260
|
description: 'Print plain text output',
|
|
237
261
|
label: '--plain',
|
|
@@ -242,9 +266,15 @@ const COMMAND_DEFINITIONS = {
|
|
|
242
266
|
},
|
|
243
267
|
],
|
|
244
268
|
related: ['query'],
|
|
245
|
-
root_summary: 'List stored queries',
|
|
246
|
-
summary:
|
|
247
|
-
|
|
269
|
+
root_summary: 'List and manage stored queries',
|
|
270
|
+
summary:
|
|
271
|
+
'List stored queries or mutate them through add, update, and remove.',
|
|
272
|
+
usage_lines: [
|
|
273
|
+
'patram queries [options]',
|
|
274
|
+
'patram queries add <name> --query <clause> [--desc <text>] [options]',
|
|
275
|
+
'patram queries update <name> [--name <new_name>] [--query <clause>] [--desc <text>] [options]',
|
|
276
|
+
'patram queries remove <name> [options]',
|
|
277
|
+
],
|
|
248
278
|
},
|
|
249
279
|
refs: {
|
|
250
280
|
allowed_option_names: new Set(['where']),
|