patram 0.8.0 → 0.9.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/bin/patram.js +2 -2
- package/lib/{parse-cli-color-options.js → cli/color-options.js} +2 -2
- package/lib/cli/command-helpers.js +35 -0
- package/lib/cli/commands/check.js +73 -0
- package/lib/cli/commands/fields.js +57 -0
- package/lib/cli/commands/queries.js +41 -0
- package/lib/cli/commands/query.js +239 -0
- package/lib/cli/commands/refs.js +72 -0
- package/lib/cli/commands/show.js +58 -0
- package/lib/{cli-help-metadata.js → cli/help-metadata.js} +6 -6
- package/lib/cli/main.js +76 -0
- package/lib/{parse-cli-arguments-helpers.js → cli/parse-arguments-helpers.js} +7 -7
- package/lib/{parse-cli-arguments.js → cli/parse-arguments.js} +12 -12
- package/lib/{parse-cli-query-pagination.js → cli/query-pagination.js} +2 -2
- package/lib/{render-cli-help.js → cli/render-help.js} +3 -3
- package/lib/{resolve-output-mode.js → cli/resolve-output-mode.js} +2 -2
- package/lib/cli/test-helpers.js +30 -0
- package/lib/config/defaults.d.ts +10 -0
- package/lib/config/defaults.js +80 -0
- package/lib/config/load-patram-config.d.ts +76 -0
- package/lib/config/load-patram-config.js +315 -0
- package/lib/config/load-patram-config.types.d.ts +45 -0
- package/lib/{patram-config.d.ts → config/patram-config.d.ts} +31 -31
- package/lib/{patram-config.js → config/patram-config.js} +3 -3
- package/lib/{patram-config.types.d.ts → config/patram-config.types.d.ts} +1 -1
- package/lib/{resolve-patram-graph-config.d.ts → config/resolve-patram-graph-config.d.ts} +2 -2
- package/lib/{resolve-patram-graph-config.js → config/resolve-patram-graph-config.js} +3 -3
- package/lib/{load-patram-config.d.ts → config/schema.d.ts} +147 -191
- package/lib/config/schema.js +324 -0
- package/lib/{source-file-defaults.d.ts → config/source-file-defaults.d.ts} +0 -1
- package/lib/{source-file-defaults.js → config/source-file-defaults.js} +1 -1
- package/lib/config/validation.d.ts +27 -0
- package/lib/config/validation.js +615 -0
- package/lib/directive-validation-test-helpers.js +1 -1
- package/lib/{build-graph-identity.d.ts → graph/build-graph-identity.d.ts} +2 -2
- package/lib/{build-graph-identity.js → graph/build-graph-identity.js} +1 -1
- package/lib/{build-graph.d.ts → graph/build-graph.d.ts} +3 -3
- package/lib/{build-graph.js → graph/build-graph.js} +17 -13
- package/lib/{build-graph.types.d.ts → graph/build-graph.types.d.ts} +1 -1
- package/lib/graph/check-directive-metadata.d.ts +23 -0
- package/lib/{check-directive-metadata.js → graph/check-directive-metadata.js} +7 -7
- package/lib/graph/check-directive-path-target.d.ts +32 -0
- package/lib/{check-directive-path-target.js → graph/check-directive-path-target.js} +4 -4
- package/lib/graph/check-directive-value.d.ts +19 -0
- package/lib/{check-directive-value.js → graph/check-directive-value.js} +3 -3
- package/lib/graph/check-graph.d.ts +29 -0
- package/lib/{check-graph.js → graph/check-graph.js} +6 -6
- package/lib/graph/directive-diagnostics.d.ts +20 -0
- package/lib/{directive-diagnostics.js → graph/directive-diagnostics.js} +2 -2
- package/lib/graph/directive-type-rules.d.ts +18 -0
- package/lib/{directive-type-rules.js → graph/directive-type-rules.js} +3 -3
- package/lib/{document-node-identity.d.ts → graph/document-node-identity.d.ts} +2 -2
- package/lib/{document-node-identity.js → graph/document-node-identity.js} +2 -2
- package/lib/graph/inspect-reverse-references.d.ts +22 -0
- package/lib/{inspect-reverse-references.js → graph/inspect-reverse-references.js} +2 -2
- package/lib/{load-project-graph.d.ts → graph/load-project-graph.d.ts} +10 -10
- package/lib/{load-project-graph.js → graph/load-project-graph.js} +12 -12
- package/lib/{parse-where-clause.types.d.ts → graph/parse-where-clause.types.d.ts} +1 -1
- package/lib/{query-graph.d.ts → graph/query/execute.d.ts} +11 -11
- package/lib/{query-graph.js → graph/query/execute.js} +12 -12
- package/lib/{query-inspection.d.ts → graph/query/inspect.d.ts} +10 -8
- package/lib/{query-inspection.js → graph/query/inspect.js} +16 -17
- package/lib/{parse-where-clause.d.ts → graph/query/parse.d.ts} +6 -6
- package/lib/{parse-where-clause.js → graph/query/parse.js} +2 -2
- package/lib/graph/query/resolve.d.ts +30 -0
- package/lib/{resolve-where-clause.js → graph/query/resolve.js} +1 -1
- package/lib/graph/reverse-reference-test-helpers.d.ts +55 -0
- package/lib/{command-output.js → output/command-output.js} +5 -5
- package/lib/{derived-summary.js → output/derived-summary.js} +7 -7
- package/lib/{layout-incoming-references.js → output/layout-incoming-references.js} +4 -4
- package/lib/{layout-incoming-summary-lines.js → output/layout-incoming-summary-lines.js} +0 -5
- package/lib/{layout-stored-queries.js → output/layout-stored-queries.js} +9 -9
- package/lib/{list-queries.js → output/list-queries.js} +1 -1
- package/lib/{render-check-output.js → output/render-check-output.js} +1 -1
- package/lib/{render-field-discovery.js → output/render-field-discovery.js} +3 -3
- package/lib/output/render-output-view.js +56 -0
- package/lib/{render-json-output.js → output/renderers/json.js} +1 -1
- package/lib/{render-plain-output.js → output/renderers/plain.js} +19 -7
- package/lib/{render-rich-output.js → output/renderers/rich.js} +29 -13
- package/lib/{resolve-check-target.js → output/resolve-check-target.js} +1 -1
- package/lib/{render-rich-source.js → output/rich-source/render.js} +6 -6
- package/lib/{show-document.js → output/show-document.js} +12 -12
- package/lib/{render-output-view.js → output/view-model/index.js} +6 -52
- package/lib/{write-paged-output.js → output/write-paged-output.js} +9 -5
- package/lib/{claim-helpers.d.ts → parse/claim-helpers.d.ts} +2 -2
- package/lib/{parse-jsdoc-claims.d.ts → parse/jsdoc/parse-jsdoc-claims.d.ts} +2 -2
- package/lib/{parse-jsdoc-claims.js → parse/jsdoc/parse-jsdoc-claims.js} +9 -9
- package/lib/{parse-jsdoc-prose.d.ts → parse/jsdoc/parse-jsdoc-prose.d.ts} +1 -1
- package/lib/{parse-jsdoc-prose.js → parse/jsdoc/parse-jsdoc-prose.js} +1 -1
- package/lib/{parse-markdown-claims.d.ts → parse/markdown/parse-markdown-claims.d.ts} +3 -3
- package/lib/{parse-markdown-claims.js → parse/markdown/parse-markdown-claims.js} +8 -8
- package/lib/{parse-markdown-directives.d.ts → parse/markdown/parse-markdown-directives.d.ts} +2 -2
- package/lib/{parse-markdown-directives.js → parse/markdown/parse-markdown-directives.js} +3 -3
- package/lib/{parse-claims.d.ts → parse/parse-claims.d.ts} +4 -13
- package/lib/{parse-claims.js → parse/parse-claims.js} +18 -26
- package/lib/{parse-claims.types.d.ts → parse/parse-claims.types.d.ts} +1 -1
- package/lib/{tagged-fenced-block-error.d.ts → parse/tagged-fenced/tagged-fenced-block-error.d.ts} +2 -2
- package/lib/{tagged-fenced-block-parser.d.ts → parse/tagged-fenced/tagged-fenced-block-parser.d.ts} +3 -3
- package/lib/{tagged-fenced-blocks.d.ts → parse/tagged-fenced/tagged-fenced-blocks.d.ts} +7 -7
- package/lib/{tagged-fenced-blocks.js → parse/tagged-fenced/tagged-fenced-blocks.js} +3 -3
- package/lib/{parse-yaml-claims.d.ts → parse/yaml/parse-yaml-claims.d.ts} +4 -4
- package/lib/{parse-yaml-claims.js → parse/yaml/parse-yaml-claims.js} +22 -13
- package/lib/patram.d.ts +29 -28
- package/lib/patram.js +5 -6
- package/lib/{discover-fields.js → scan/discover-fields.js} +9 -8
- package/lib/scan/list-repo-files.d.ts +16 -0
- package/lib/{list-source-files.js → scan/list-repo-files.js} +2 -35
- package/lib/{list-source-files.d.ts → scan/list-source-files.d.ts} +4 -11
- package/lib/scan/list-source-files.js +45 -0
- package/package.json +8 -7
- package/lib/build-graph.types.ts +0 -27
- package/lib/discover-fields.types.ts +0 -52
- package/lib/load-patram-config.js +0 -1215
- package/lib/load-patram-config.types.d.ts +0 -45
- package/lib/load-patram-config.types.ts +0 -56
- package/lib/output-view.types.d.ts +0 -88
- package/lib/output-view.types.ts +0 -113
- package/lib/overlay-graph.d.ts +0 -43
- package/lib/overlay-graph.js +0 -191
- package/lib/parse-claims.types.ts +0 -41
- package/lib/parse-cli-arguments.types.ts +0 -75
- package/lib/parse-where-clause.types.ts +0 -87
- package/lib/patram-cli.js +0 -593
- package/lib/patram-config.types.ts +0 -22
- package/lib/tagged-fenced-blocks.types.ts +0 -38
- /package/lib/{reverse-reference-test-helpers.js → graph/reverse-reference-test-helpers.js} +0 -0
- /package/lib/{format-derived-summary-row.js → output/format-derived-summary-row.js} +0 -0
- /package/lib/{format-node-header.js → output/format-node-header.js} +0 -0
- /package/lib/{format-output-item-block.js → output/format-output-item-block.js} +0 -0
- /package/lib/{format-output-metadata.js → output/format-output-metadata.js} +0 -0
- /package/lib/{claim-helpers.js → parse/claim-helpers.js} +0 -0
- /package/lib/{parse-jsdoc-blocks.d.ts → parse/jsdoc/parse-jsdoc-blocks.d.ts} +0 -0
- /package/lib/{parse-jsdoc-blocks.js → parse/jsdoc/parse-jsdoc-blocks.js} +0 -0
- /package/lib/{tagged-fenced-block-error.js → parse/tagged-fenced/tagged-fenced-block-error.js} +0 -0
- /package/lib/{tagged-fenced-block-markdown.d.ts → parse/tagged-fenced/tagged-fenced-block-markdown.d.ts} +0 -0
- /package/lib/{tagged-fenced-block-markdown.js → parse/tagged-fenced/tagged-fenced-block-markdown.js} +0 -0
- /package/lib/{tagged-fenced-block-metadata.d.ts → parse/tagged-fenced/tagged-fenced-block-metadata.d.ts} +0 -0
- /package/lib/{tagged-fenced-block-metadata.js → parse/tagged-fenced/tagged-fenced-block-metadata.js} +0 -0
- /package/lib/{tagged-fenced-block-parser.js → parse/tagged-fenced/tagged-fenced-block-parser.js} +0 -0
- /package/lib/{tagged-fenced-blocks.types.d.ts → parse/tagged-fenced/tagged-fenced-blocks.types.d.ts} +0 -0
package/bin/patram.js
CHANGED
|
@@ -4,7 +4,7 @@ import { realpath } from 'node:fs/promises';
|
|
|
4
4
|
import process from 'node:process';
|
|
5
5
|
import { fileURLToPath } from 'node:url';
|
|
6
6
|
|
|
7
|
-
import { main } from '../lib/
|
|
7
|
+
import { main } from '../lib/cli/main.js';
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* Patram CLI entrypoint.
|
|
@@ -17,7 +17,7 @@ import { main } from '../lib/patram-cli.js';
|
|
|
17
17
|
* Tracked in: ../docs/plans/v0/source-anchor-dogfooding.md
|
|
18
18
|
* Decided by: ../docs/decisions/cli-entrypoint-symlink.md
|
|
19
19
|
* @patram
|
|
20
|
-
* @see {@link ../lib/
|
|
20
|
+
* @see {@link ../lib/cli/main.js}
|
|
21
21
|
* @see {@link ../docs/patram.md}
|
|
22
22
|
*/
|
|
23
23
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @typedef {import('./parse-
|
|
3
|
-
* @typedef {import('./
|
|
2
|
+
* @typedef {import('./parse-arguments-helpers.js').CliOptionToken} CliOptionToken
|
|
3
|
+
* @typedef {import('./arguments.types.ts').CliColorMode} CliColorMode
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
const VALID_COLOR_MODES = new Set(['auto', 'always', 'never']);
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/** @import * as $k$$k$$l$output$l$output$j$view$k$types$k$ts from '../output/output-view.types.ts'; */
|
|
2
|
+
import process from 'node:process';
|
|
3
|
+
|
|
4
|
+
import { resolveOutputMode } from './resolve-output-mode.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @param {import('./arguments.types.ts').ParsedCliCommandRequest} parsed_command
|
|
8
|
+
* @param {{ stdout: { isTTY?: boolean } }} io_context
|
|
9
|
+
* @returns {$k$$k$$l$output$l$output$j$view$k$types$k$ts.ResolvedOutputMode}
|
|
10
|
+
*/
|
|
11
|
+
export function resolveCommandOutputMode(parsed_command, io_context) {
|
|
12
|
+
return resolveOutputMode(parsed_command, {
|
|
13
|
+
is_tty: io_context.stdout.isTTY === true,
|
|
14
|
+
no_color: process.env.NO_COLOR !== undefined,
|
|
15
|
+
term: process.env.TERM,
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @param {{ write(chunk: string): boolean }} output_stream
|
|
21
|
+
* @param {import('../config/load-patram-config.types.ts').PatramDiagnostic[]} diagnostics
|
|
22
|
+
*/
|
|
23
|
+
export function writeDiagnostics(output_stream, diagnostics) {
|
|
24
|
+
for (const diagnostic of diagnostics) {
|
|
25
|
+
output_stream.write(formatDiagnostic(diagnostic));
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @param {import('../config/load-patram-config.types.ts').PatramDiagnostic} diagnostic
|
|
31
|
+
* @returns {string}
|
|
32
|
+
*/
|
|
33
|
+
function formatDiagnostic(diagnostic) {
|
|
34
|
+
return `${diagnostic.path}:${diagnostic.line}:${diagnostic.column} ${diagnostic.level} ${diagnostic.code} ${diagnostic.message}\n`;
|
|
35
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @import { ParsedCliCommandRequest } from '../arguments.types.ts';
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { checkGraph } from '../../graph/check-graph.js';
|
|
6
|
+
import { loadProjectGraph } from '../../graph/load-project-graph.js';
|
|
7
|
+
import {
|
|
8
|
+
renderCheckDiagnostics,
|
|
9
|
+
renderCheckSuccess,
|
|
10
|
+
} from '../../output/render-check-output.js';
|
|
11
|
+
import {
|
|
12
|
+
resolveCheckTarget,
|
|
13
|
+
selectCheckTargetDiagnostics,
|
|
14
|
+
selectCheckTargetSourceFiles,
|
|
15
|
+
} from '../../output/resolve-check-target.js';
|
|
16
|
+
import { listRepoFiles } from '../../scan/list-repo-files.js';
|
|
17
|
+
|
|
18
|
+
import { resolveCommandOutputMode } from '../command-helpers.js';
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* @param {ParsedCliCommandRequest} parsed_command
|
|
22
|
+
* @param {{ stderr: { write(chunk: string): boolean }, stdout: { isTTY?: boolean, write(chunk: string): boolean }, write_paged_output?: (output_text: string) => Promise<void> }} io_context
|
|
23
|
+
* @returns {Promise<number>}
|
|
24
|
+
*/
|
|
25
|
+
export async function runCheckCommand(parsed_command, io_context) {
|
|
26
|
+
const output_mode = resolveCommandOutputMode(parsed_command, io_context);
|
|
27
|
+
const resolved_target = await resolveCheckTarget(
|
|
28
|
+
parsed_command.command_arguments[0],
|
|
29
|
+
);
|
|
30
|
+
const project_graph_result = await loadProjectGraph(
|
|
31
|
+
resolved_target.project_directory,
|
|
32
|
+
);
|
|
33
|
+
const repo_file_paths = await listRepoFiles(
|
|
34
|
+
resolved_target.project_directory,
|
|
35
|
+
);
|
|
36
|
+
const selected_source_file_paths = selectCheckTargetSourceFiles(
|
|
37
|
+
project_graph_result.source_file_paths,
|
|
38
|
+
resolved_target,
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
if (project_graph_result.diagnostics.length > 0) {
|
|
42
|
+
io_context.stderr.write(
|
|
43
|
+
renderCheckDiagnostics(project_graph_result.diagnostics, output_mode),
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
return 1;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const diagnostics = checkGraph(
|
|
50
|
+
project_graph_result.graph,
|
|
51
|
+
repo_file_paths,
|
|
52
|
+
project_graph_result.config,
|
|
53
|
+
project_graph_result.claims,
|
|
54
|
+
);
|
|
55
|
+
const selected_diagnostics = selectCheckTargetDiagnostics(
|
|
56
|
+
diagnostics,
|
|
57
|
+
resolved_target,
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
if (selected_diagnostics.length > 0) {
|
|
61
|
+
io_context.stderr.write(
|
|
62
|
+
renderCheckDiagnostics(selected_diagnostics, output_mode),
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
return 1;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
io_context.stdout.write(
|
|
69
|
+
renderCheckSuccess(selected_source_file_paths.length, output_mode),
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
return 0;
|
|
73
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @import { ParsedCliCommandRequest } from '../arguments.types.ts';
|
|
3
|
+
* @import { PatramRepoConfig } from '../../config/load-patram-config.types.ts';
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import process from 'node:process';
|
|
7
|
+
|
|
8
|
+
import { loadPatramConfig } from '../../config/load-patram-config.js';
|
|
9
|
+
import { writeRenderedCommandOutput } from '../../output/command-output.js';
|
|
10
|
+
import { renderFieldDiscovery } from '../../output/render-field-discovery.js';
|
|
11
|
+
import { discoverFields } from '../../scan/discover-fields.js';
|
|
12
|
+
|
|
13
|
+
import { resolveCommandOutputMode } from '../command-helpers.js';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @param {ParsedCliCommandRequest} parsed_command
|
|
17
|
+
* @param {{ stderr: { write(chunk: string): boolean }, stdout: { isTTY?: boolean, write(chunk: string): boolean } }} io_context
|
|
18
|
+
* @returns {Promise<number>}
|
|
19
|
+
*/
|
|
20
|
+
export async function runFieldsCommand(parsed_command, io_context) {
|
|
21
|
+
const output_mode = resolveCommandOutputMode(parsed_command, io_context);
|
|
22
|
+
const load_result = await loadPatramConfig(process.cwd());
|
|
23
|
+
const defined_field_names =
|
|
24
|
+
load_result.diagnostics.length === 0
|
|
25
|
+
? collectDefinedDiscoveryNames(load_result.config)
|
|
26
|
+
: new Set();
|
|
27
|
+
const discovery_result = await discoverFields(process.cwd(), {
|
|
28
|
+
defined_field_names,
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
await writeRenderedCommandOutput(
|
|
32
|
+
io_context,
|
|
33
|
+
parsed_command,
|
|
34
|
+
renderFieldDiscovery(discovery_result, output_mode),
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
return 0;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* @param {PatramRepoConfig | null} repo_config
|
|
42
|
+
* @returns {Set<string>}
|
|
43
|
+
*/
|
|
44
|
+
function collectDefinedDiscoveryNames(repo_config) {
|
|
45
|
+
/** @type {Set<string>} */
|
|
46
|
+
const defined_field_names = new Set();
|
|
47
|
+
|
|
48
|
+
for (const field_name of Object.keys(repo_config?.fields ?? {})) {
|
|
49
|
+
defined_field_names.add(field_name);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
for (const relation_name of Object.keys(repo_config?.relations ?? {})) {
|
|
53
|
+
defined_field_names.add(relation_name);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return defined_field_names;
|
|
57
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @import { ParsedCliCommandRequest } from '../arguments.types.ts';
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import process from 'node:process';
|
|
6
|
+
|
|
7
|
+
import { loadPatramConfig } from '../../config/load-patram-config.js';
|
|
8
|
+
import { writeCommandOutput } from '../../output/command-output.js';
|
|
9
|
+
import { listQueries } from '../../output/list-queries.js';
|
|
10
|
+
import { createOutputView } from '../../output/render-output-view.js';
|
|
11
|
+
|
|
12
|
+
import { writeDiagnostics } from '../command-helpers.js';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @param {ParsedCliCommandRequest} parsed_command
|
|
16
|
+
* @param {{ stderr: { write(chunk: string): boolean }, stdout: { isTTY?: boolean, write(chunk: string): boolean }, write_paged_output?: (output_text: string) => Promise<void> }} io_context
|
|
17
|
+
* @returns {Promise<number>}
|
|
18
|
+
*/
|
|
19
|
+
export async function runQueriesCommand(parsed_command, io_context) {
|
|
20
|
+
const load_result = await loadPatramConfig(process.cwd());
|
|
21
|
+
|
|
22
|
+
if (load_result.diagnostics.length > 0) {
|
|
23
|
+
writeDiagnostics(io_context.stderr, load_result.diagnostics);
|
|
24
|
+
|
|
25
|
+
return 1;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const repo_config = load_result.config;
|
|
29
|
+
|
|
30
|
+
if (!repo_config) {
|
|
31
|
+
throw new Error('Expected a valid Patram repo config.');
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
await writeCommandOutput(
|
|
35
|
+
io_context,
|
|
36
|
+
parsed_command,
|
|
37
|
+
createOutputView('queries', listQueries(repo_config.queries)),
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
return 0;
|
|
41
|
+
}
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @import { ParsedCliCommandRequest } from '../arguments.types.ts';
|
|
3
|
+
* @import { GraphNode } from '../../graph/build-graph.types.ts';
|
|
4
|
+
* @import { ResolvedOutputMode } from '../../output/output-view.types.ts';
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import process from 'node:process';
|
|
8
|
+
|
|
9
|
+
import {
|
|
10
|
+
shouldPageCommandOutput,
|
|
11
|
+
writeCommandOutput,
|
|
12
|
+
} from '../../output/command-output.js';
|
|
13
|
+
import { createDerivedSummaryEvaluator } from '../../output/derived-summary.js';
|
|
14
|
+
import { renderCheckDiagnostics } from '../../output/render-check-output.js';
|
|
15
|
+
import { renderInvalidWhereDiagnostic } from '../render-help.js';
|
|
16
|
+
import { createOutputView } from '../../output/render-output-view.js';
|
|
17
|
+
import { loadPatramConfig } from '../../config/load-patram-config.js';
|
|
18
|
+
import { loadProjectGraph } from '../../graph/load-project-graph.js';
|
|
19
|
+
import { DEFAULT_QUERY_LIMIT, queryGraph } from '../../graph/query/execute.js';
|
|
20
|
+
import {
|
|
21
|
+
inspectQuery,
|
|
22
|
+
renderQueryInspection,
|
|
23
|
+
} from '../../graph/query/inspect.js';
|
|
24
|
+
import { resolveWhereClause } from '../../graph/query/resolve.js';
|
|
25
|
+
|
|
26
|
+
import {
|
|
27
|
+
resolveCommandOutputMode,
|
|
28
|
+
writeDiagnostics,
|
|
29
|
+
} from '../command-helpers.js';
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* @param {ParsedCliCommandRequest} parsed_command
|
|
33
|
+
* @param {{ stderr: { write(chunk: string): boolean }, stdout: { isTTY?: boolean, write(chunk: string): boolean }, write_paged_output?: (output_text: string) => Promise<void> }} io_context
|
|
34
|
+
* @returns {Promise<number>}
|
|
35
|
+
*/
|
|
36
|
+
export async function runQueryCommand(parsed_command, io_context) {
|
|
37
|
+
const use_pager = shouldPageCommandOutput(parsed_command, io_context.stdout);
|
|
38
|
+
const output_mode = resolveCommandOutputMode(parsed_command, io_context);
|
|
39
|
+
|
|
40
|
+
if (parsed_command.query_inspection_mode) {
|
|
41
|
+
return runQueryInspectionCommand(
|
|
42
|
+
parsed_command,
|
|
43
|
+
io_context,
|
|
44
|
+
output_mode,
|
|
45
|
+
use_pager,
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const project_graph_result = await loadProjectGraph(process.cwd());
|
|
50
|
+
|
|
51
|
+
if (project_graph_result.diagnostics.length > 0) {
|
|
52
|
+
writeDiagnostics(io_context.stderr, project_graph_result.diagnostics);
|
|
53
|
+
|
|
54
|
+
return 1;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const where_clause = resolveWhereClause(
|
|
58
|
+
project_graph_result.config,
|
|
59
|
+
parsed_command.command_arguments,
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
if (!where_clause.success) {
|
|
63
|
+
io_context.stderr.write(`${where_clause.message}\n`);
|
|
64
|
+
|
|
65
|
+
return 1;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const query_result = queryGraph(
|
|
69
|
+
project_graph_result.graph,
|
|
70
|
+
where_clause.value.where_clause,
|
|
71
|
+
project_graph_result.config,
|
|
72
|
+
createQueryPaginationOptions(parsed_command, use_pager),
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
if (query_result.diagnostics.length > 0) {
|
|
76
|
+
io_context.stderr.write(
|
|
77
|
+
renderInvalidWhereDiagnostic(query_result.diagnostics[0]),
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
return 1;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const derived_summary_evaluator = createDerivedSummaryEvaluator(
|
|
84
|
+
project_graph_result.config,
|
|
85
|
+
project_graph_result.graph,
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
await writeCommandOutput(
|
|
89
|
+
io_context,
|
|
90
|
+
parsed_command,
|
|
91
|
+
createOutputView('query', query_result.nodes, {
|
|
92
|
+
derived_summary_evaluator,
|
|
93
|
+
...createQueryOutputOptions(parsed_command, query_result, use_pager),
|
|
94
|
+
repo_config: project_graph_result.config,
|
|
95
|
+
}),
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
return 0;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* @param {ParsedCliCommandRequest} parsed_command
|
|
103
|
+
* @param {{ stderr: { write(chunk: string): boolean }, stdout: { isTTY?: boolean, write(chunk: string): boolean } }} io_context
|
|
104
|
+
* @param {ResolvedOutputMode} output_mode
|
|
105
|
+
* @param {boolean} use_pager
|
|
106
|
+
* @returns {Promise<number>}
|
|
107
|
+
*/
|
|
108
|
+
async function runQueryInspectionCommand(
|
|
109
|
+
parsed_command,
|
|
110
|
+
io_context,
|
|
111
|
+
output_mode,
|
|
112
|
+
use_pager,
|
|
113
|
+
) {
|
|
114
|
+
const query_inspection_mode = parsed_command.query_inspection_mode;
|
|
115
|
+
|
|
116
|
+
if (!query_inspection_mode) {
|
|
117
|
+
throw new Error('Expected a query inspection mode.');
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const load_result = await loadPatramConfig(process.cwd());
|
|
121
|
+
|
|
122
|
+
if (load_result.diagnostics.length > 0) {
|
|
123
|
+
io_context.stderr.write(
|
|
124
|
+
renderCheckDiagnostics(load_result.diagnostics, output_mode),
|
|
125
|
+
);
|
|
126
|
+
|
|
127
|
+
return 1;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const repo_config = load_result.config;
|
|
131
|
+
|
|
132
|
+
if (!repo_config) {
|
|
133
|
+
throw new Error('Expected a valid Patram repo config.');
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const where_clause = resolveWhereClause(
|
|
137
|
+
repo_config,
|
|
138
|
+
parsed_command.command_arguments,
|
|
139
|
+
);
|
|
140
|
+
|
|
141
|
+
if (!where_clause.success) {
|
|
142
|
+
io_context.stderr.write(`${where_clause.message}\n`);
|
|
143
|
+
|
|
144
|
+
return 1;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const query_inspection = inspectQuery(repo_config, where_clause.value, {
|
|
148
|
+
inspection_mode: query_inspection_mode,
|
|
149
|
+
...createQueryExecutionOptions(parsed_command, use_pager),
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
if (!query_inspection.success) {
|
|
153
|
+
io_context.stderr.write(
|
|
154
|
+
renderCheckDiagnostics(query_inspection.diagnostics, output_mode),
|
|
155
|
+
);
|
|
156
|
+
|
|
157
|
+
return 1;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
io_context.stdout.write(
|
|
161
|
+
renderQueryInspection(query_inspection.value, output_mode),
|
|
162
|
+
);
|
|
163
|
+
|
|
164
|
+
return 0;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* @param {ParsedCliCommandRequest} parsed_command
|
|
169
|
+
* @param {{ total_count: number, nodes: GraphNode[] }} query_result
|
|
170
|
+
* @param {boolean} use_pager
|
|
171
|
+
* @returns {{ hints: string[], limit: number, offset: number, total_count: number }}
|
|
172
|
+
*/
|
|
173
|
+
function createQueryOutputOptions(parsed_command, query_result, use_pager) {
|
|
174
|
+
/** @type {string[]} */
|
|
175
|
+
const hints = [];
|
|
176
|
+
const limit =
|
|
177
|
+
parsed_command.query_limit ??
|
|
178
|
+
(use_pager ? query_result.nodes.length : DEFAULT_QUERY_LIMIT);
|
|
179
|
+
const offset = parsed_command.query_offset ?? 0;
|
|
180
|
+
|
|
181
|
+
if (query_result.total_count === 0) {
|
|
182
|
+
hints.push("Try: patram query --where '$class=task'");
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
if (
|
|
186
|
+
!use_pager &&
|
|
187
|
+
parsed_command.query_limit === undefined &&
|
|
188
|
+
parsed_command.query_offset === undefined &&
|
|
189
|
+
query_result.total_count > DEFAULT_QUERY_LIMIT
|
|
190
|
+
) {
|
|
191
|
+
hints.push(
|
|
192
|
+
'Hint: use --offset <n> or --limit <n> to page through more matches.',
|
|
193
|
+
);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
return {
|
|
197
|
+
hints,
|
|
198
|
+
limit,
|
|
199
|
+
offset,
|
|
200
|
+
total_count: query_result.total_count,
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* @param {ParsedCliCommandRequest} parsed_command
|
|
206
|
+
* @param {boolean} use_pager
|
|
207
|
+
* @returns {{ limit?: number, offset: number }}
|
|
208
|
+
*/
|
|
209
|
+
function createQueryPaginationOptions(parsed_command, use_pager) {
|
|
210
|
+
/** @type {{ limit?: number, offset: number }} */
|
|
211
|
+
const pagination_options = {
|
|
212
|
+
offset: parsed_command.query_offset ?? 0,
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
if (parsed_command.query_limit !== undefined) {
|
|
216
|
+
pagination_options.limit = parsed_command.query_limit;
|
|
217
|
+
} else if (!use_pager) {
|
|
218
|
+
pagination_options.limit = DEFAULT_QUERY_LIMIT;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
return pagination_options;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* @param {ParsedCliCommandRequest} parsed_command
|
|
226
|
+
* @param {boolean} use_pager
|
|
227
|
+
* @returns {{ limit: number | null, offset: number }}
|
|
228
|
+
*/
|
|
229
|
+
function createQueryExecutionOptions(parsed_command, use_pager) {
|
|
230
|
+
const pagination_options = createQueryPaginationOptions(
|
|
231
|
+
parsed_command,
|
|
232
|
+
use_pager,
|
|
233
|
+
);
|
|
234
|
+
|
|
235
|
+
return {
|
|
236
|
+
limit: pagination_options.limit ?? null,
|
|
237
|
+
offset: pagination_options.offset,
|
|
238
|
+
};
|
|
239
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @import { ParsedCliCommandRequest } from '../arguments.types.ts';
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import process from 'node:process';
|
|
6
|
+
|
|
7
|
+
import { loadProjectGraph } from '../../graph/load-project-graph.js';
|
|
8
|
+
import { inspectReverseReferences } from '../../graph/inspect-reverse-references.js';
|
|
9
|
+
import { writeCommandOutput } from '../../output/command-output.js';
|
|
10
|
+
import { createDerivedSummaryEvaluator } from '../../output/derived-summary.js';
|
|
11
|
+
import { createRefsOutputView } from '../../output/render-output-view.js';
|
|
12
|
+
|
|
13
|
+
import { renderInvalidWhereDiagnostic } from '../render-help.js';
|
|
14
|
+
import { writeDiagnostics } from '../command-helpers.js';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @param {ParsedCliCommandRequest} parsed_command
|
|
18
|
+
* @param {{ stderr: { write(chunk: string): boolean }, stdout: { isTTY?: boolean, write(chunk: string): boolean }, write_paged_output?: (output_text: string) => Promise<void> }} io_context
|
|
19
|
+
* @returns {Promise<number>}
|
|
20
|
+
*/
|
|
21
|
+
export async function runRefsCommand(parsed_command, io_context) {
|
|
22
|
+
const project_graph_result = await loadProjectGraph(process.cwd());
|
|
23
|
+
|
|
24
|
+
if (project_graph_result.diagnostics.length > 0) {
|
|
25
|
+
writeDiagnostics(io_context.stderr, project_graph_result.diagnostics);
|
|
26
|
+
|
|
27
|
+
return 1;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const refs_output = inspectReverseReferences(
|
|
31
|
+
project_graph_result.graph,
|
|
32
|
+
parsed_command.command_arguments[0],
|
|
33
|
+
project_graph_result.config,
|
|
34
|
+
resolveRefsWhereClause(parsed_command.command_arguments),
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
if (refs_output.diagnostics.length > 0) {
|
|
38
|
+
io_context.stderr.write(
|
|
39
|
+
renderInvalidWhereDiagnostic(refs_output.diagnostics[0]),
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
return 1;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const derived_summary_evaluator = createDerivedSummaryEvaluator(
|
|
46
|
+
project_graph_result.config,
|
|
47
|
+
project_graph_result.graph,
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
await writeCommandOutput(
|
|
51
|
+
io_context,
|
|
52
|
+
parsed_command,
|
|
53
|
+
createRefsOutputView(refs_output, {
|
|
54
|
+
derived_summary_evaluator,
|
|
55
|
+
repo_config: project_graph_result.config,
|
|
56
|
+
}),
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
return 0;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* @param {string[]} command_arguments
|
|
64
|
+
* @returns {string | undefined}
|
|
65
|
+
*/
|
|
66
|
+
function resolveRefsWhereClause(command_arguments) {
|
|
67
|
+
if (command_arguments[1] !== '--where') {
|
|
68
|
+
return undefined;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return command_arguments.slice(2).join(' ').trim();
|
|
72
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @import { ParsedCliCommandRequest } from '../arguments.types.ts';
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import process from 'node:process';
|
|
6
|
+
|
|
7
|
+
import { loadProjectGraph } from '../../graph/load-project-graph.js';
|
|
8
|
+
import { writeCommandOutput } from '../../output/command-output.js';
|
|
9
|
+
import { createDerivedSummaryEvaluator } from '../../output/derived-summary.js';
|
|
10
|
+
import { createShowOutputView } from '../../output/render-output-view.js';
|
|
11
|
+
import { loadShowOutput } from '../../output/show-document.js';
|
|
12
|
+
|
|
13
|
+
import { writeDiagnostics } from '../command-helpers.js';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @param {ParsedCliCommandRequest} parsed_command
|
|
17
|
+
* @param {{ stderr: { write(chunk: string): boolean }, stdout: { isTTY?: boolean, write(chunk: string): boolean }, write_paged_output?: (output_text: string) => Promise<void> }} io_context
|
|
18
|
+
* @returns {Promise<number>}
|
|
19
|
+
*/
|
|
20
|
+
export async function runShowCommand(parsed_command, io_context) {
|
|
21
|
+
const project_graph_result = await loadProjectGraph(process.cwd());
|
|
22
|
+
|
|
23
|
+
if (project_graph_result.diagnostics.length > 0) {
|
|
24
|
+
writeDiagnostics(io_context.stderr, project_graph_result.diagnostics);
|
|
25
|
+
|
|
26
|
+
return 1;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const show_output = await loadShowOutput(
|
|
30
|
+
parsed_command.command_arguments[0],
|
|
31
|
+
process.cwd(),
|
|
32
|
+
project_graph_result.graph,
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
if (!show_output.success) {
|
|
36
|
+
writeDiagnostics(io_context.stderr, [show_output.diagnostic]);
|
|
37
|
+
|
|
38
|
+
return 1;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const derived_summary_evaluator = createDerivedSummaryEvaluator(
|
|
42
|
+
project_graph_result.config,
|
|
43
|
+
project_graph_result.graph,
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
await writeCommandOutput(
|
|
47
|
+
io_context,
|
|
48
|
+
parsed_command,
|
|
49
|
+
createShowOutputView(show_output.value, {
|
|
50
|
+
derived_summary_evaluator,
|
|
51
|
+
document_node_ids: project_graph_result.graph.document_node_ids,
|
|
52
|
+
graph_nodes: project_graph_result.graph.nodes,
|
|
53
|
+
repo_config: project_graph_result.config,
|
|
54
|
+
}),
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
return 0;
|
|
58
|
+
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* @import {
|
|
4
4
|
* CliCommandName,
|
|
5
5
|
* CliHelpTopicName,
|
|
6
|
-
* } from './
|
|
6
|
+
* } from './arguments.types.ts';
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
/**
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
* }} CliHelpTopicDefinition
|
|
46
46
|
*/
|
|
47
47
|
|
|
48
|
-
|
|
48
|
+
const COMMAND_NAMES = /** @type {const} */ ([
|
|
49
49
|
'check',
|
|
50
50
|
'fields',
|
|
51
51
|
'query',
|
|
@@ -54,7 +54,7 @@ export const COMMAND_NAMES = /** @type {const} */ ([
|
|
|
54
54
|
'show',
|
|
55
55
|
]);
|
|
56
56
|
|
|
57
|
-
|
|
57
|
+
const HELP_TOPIC_NAMES = /** @type {const} */ (['query-language']);
|
|
58
58
|
|
|
59
59
|
export const GLOBAL_OPTION_NAMES = new Set([
|
|
60
60
|
'help',
|
|
@@ -284,14 +284,14 @@ const COMMAND_DEFINITIONS = {
|
|
|
284
284
|
},
|
|
285
285
|
show: {
|
|
286
286
|
allowed_option_names: new Set(),
|
|
287
|
-
examples: ['patram show docs/patram.md', 'patram show lib/
|
|
287
|
+
examples: ['patram show docs/patram.md', 'patram show lib/cli/main.js'],
|
|
288
288
|
extra_positionals_message: 'Show accepts exactly one file path.',
|
|
289
289
|
help_topics: [],
|
|
290
290
|
max_positionals: 1,
|
|
291
291
|
min_positionals: 1,
|
|
292
292
|
missing_argument_examples: [
|
|
293
293
|
'patram show docs/patram.md',
|
|
294
|
-
'patram show lib/
|
|
294
|
+
'patram show lib/cli/main.js',
|
|
295
295
|
],
|
|
296
296
|
missing_argument_label: '<file>',
|
|
297
297
|
missing_usage_lines: ['patram show <file>'],
|
|
@@ -583,7 +583,7 @@ function scoreCandidate(input_text, candidate) {
|
|
|
583
583
|
function calculateDamerauLevenshteinDistance(left_text, right_text) {
|
|
584
584
|
/** @type {number[][]} */
|
|
585
585
|
const matrix = Array.from({ length: left_text.length + 1 }, () =>
|
|
586
|
-
Array(right_text.length + 1)
|
|
586
|
+
Array.from({ length: right_text.length + 1 }, () => 0),
|
|
587
587
|
);
|
|
588
588
|
|
|
589
589
|
for (let left_index = 0; left_index <= left_text.length; left_index += 1) {
|