patram 0.0.2 → 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/bin/patram.js +25 -147
- package/lib/build-graph-identity.js +270 -0
- package/lib/build-graph.js +156 -77
- package/lib/check-graph.js +23 -7
- package/lib/claim-helpers.js +55 -0
- package/lib/cli-help-metadata.js +552 -0
- package/lib/command-output.js +83 -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 +361 -0
- package/lib/list-queries.js +18 -0
- package/lib/list-source-files.js +50 -15
- package/lib/load-patram-config.js +505 -18
- package/lib/load-patram-config.types.ts +40 -0
- package/lib/load-project-graph.js +124 -0
- package/lib/output-view.types.ts +88 -0
- package/lib/parse-claims.js +38 -158
- package/lib/parse-claims.types.ts +7 -0
- package/lib/parse-cli-arguments-helpers.js +446 -0
- package/lib/parse-cli-arguments.js +266 -0
- package/lib/parse-cli-arguments.types.ts +69 -0
- package/lib/parse-cli-color-options.js +44 -0
- package/lib/parse-cli-query-pagination.js +49 -0
- package/lib/parse-jsdoc-blocks.js +184 -0
- package/lib/parse-jsdoc-claims.js +280 -0
- package/lib/parse-jsdoc-prose.js +111 -0
- package/lib/parse-markdown-claims.js +242 -0
- package/lib/parse-markdown-directives.js +136 -0
- package/lib/parse-where-clause.js +707 -0
- package/lib/parse-where-clause.types.ts +70 -0
- package/lib/patram-cli.js +464 -0
- package/lib/patram-config.js +3 -1
- package/lib/patram-config.types.ts +2 -1
- package/lib/patram.js +6 -0
- package/lib/query-graph.js +368 -0
- package/lib/query-inspection.js +523 -0
- package/lib/render-check-output.js +315 -0
- package/lib/render-cli-help.js +419 -0
- package/lib/render-json-output.js +161 -0
- package/lib/render-output-view.js +222 -0
- package/lib/render-plain-output.js +182 -0
- package/lib/render-rich-output.js +240 -0
- package/lib/render-rich-source.js +1333 -0
- package/lib/resolve-check-target.js +190 -0
- package/lib/resolve-output-mode.js +60 -0
- package/lib/resolve-patram-graph-config.js +88 -0
- package/lib/resolve-where-clause.js +66 -0
- package/lib/show-document.js +311 -0
- package/lib/source-file-defaults.js +28 -0
- 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/lib/write-paged-output.js +87 -0
- package/package.json +28 -12
- package/bin/patram.test.js +0 -184
- package/lib/build-graph.test.js +0 -141
- package/lib/check-graph.test.js +0 -103
- package/lib/list-source-files.test.js +0 -101
- package/lib/load-patram-config.test.js +0 -211
- package/lib/parse-claims.test.js +0 -113
- package/lib/patram-config.test.js +0 -147
package/bin/patram.js
CHANGED
|
@@ -1,169 +1,47 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
* @import { PatramClaim } from '../lib/parse-claims.types.ts';
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { readFile } from 'node:fs/promises';
|
|
8
|
-
import { resolve } from 'node:path';
|
|
3
|
+
import { realpath } from 'node:fs/promises';
|
|
9
4
|
import process from 'node:process';
|
|
10
|
-
import {
|
|
5
|
+
import { fileURLToPath } from 'node:url';
|
|
11
6
|
|
|
12
|
-
import {
|
|
13
|
-
import { checkGraph } from '../lib/check-graph.js';
|
|
14
|
-
import { listSourceFiles } from '../lib/list-source-files.js';
|
|
15
|
-
import { loadPatramConfig } from '../lib/load-patram-config.js';
|
|
16
|
-
import { parseClaims } from '../lib/parse-claims.js';
|
|
17
|
-
import { parsePatramConfig } from '../lib/patram-config.js';
|
|
7
|
+
import { main } from '../lib/patram-cli.js';
|
|
18
8
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
'markdown.link': {
|
|
34
|
-
emit: {
|
|
35
|
-
relation: 'links_to',
|
|
36
|
-
target: 'path',
|
|
37
|
-
target_kind: 'document',
|
|
38
|
-
},
|
|
39
|
-
},
|
|
40
|
-
},
|
|
41
|
-
relations: {
|
|
42
|
-
links_to: {
|
|
43
|
-
builtin: true,
|
|
44
|
-
from: ['document'],
|
|
45
|
-
to: ['document'],
|
|
46
|
-
},
|
|
47
|
-
},
|
|
48
|
-
});
|
|
9
|
+
/**
|
|
10
|
+
* Patram CLI entrypoint.
|
|
11
|
+
*
|
|
12
|
+
* Detects direct process execution and forwards command handling to the shared
|
|
13
|
+
* CLI runtime.
|
|
14
|
+
*
|
|
15
|
+
* Kind: entrypoint
|
|
16
|
+
* Status: active
|
|
17
|
+
* Tracked in: ../docs/plans/v0/source-anchor-dogfooding.md
|
|
18
|
+
* Decided by: ../docs/decisions/cli-entrypoint-symlink.md
|
|
19
|
+
* @patram
|
|
20
|
+
* @see {@link ../lib/patram-cli.js}
|
|
21
|
+
* @see {@link ../docs/patram.md}
|
|
22
|
+
*/
|
|
49
23
|
|
|
50
|
-
if (isEntrypoint(import.meta.url, process.argv[1])) {
|
|
24
|
+
if (await isEntrypoint(import.meta.url, process.argv[1])) {
|
|
51
25
|
process.exitCode = await main(process.argv.slice(2), {
|
|
52
26
|
stderr: process.stderr,
|
|
53
27
|
stdout: process.stdout,
|
|
54
28
|
});
|
|
55
29
|
}
|
|
56
30
|
|
|
57
|
-
|
|
58
|
-
* Run the Patram CLI.
|
|
59
|
-
*
|
|
60
|
-
* @param {string[]} cli_arguments
|
|
61
|
-
* @param {{ stderr: { write(chunk: string): boolean }, stdout: { write(chunk: string): boolean } }} io_context
|
|
62
|
-
* @returns {Promise<number>}
|
|
63
|
-
*/
|
|
64
|
-
export async function main(cli_arguments, io_context) {
|
|
65
|
-
const command_name = cli_arguments[0];
|
|
66
|
-
|
|
67
|
-
if (command_name === 'check') {
|
|
68
|
-
return runCheckCommand(cli_arguments.slice(1), io_context);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
io_context.stderr.write('Unknown command.\n');
|
|
72
|
-
|
|
73
|
-
return 1;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* @param {string[]} command_arguments
|
|
78
|
-
* @param {{ stderr: { write(chunk: string): boolean }, stdout: { write(chunk: string): boolean } }} io_context
|
|
79
|
-
* @returns {Promise<number>}
|
|
80
|
-
*/
|
|
81
|
-
async function runCheckCommand(command_arguments, io_context) {
|
|
82
|
-
const project_directory = command_arguments[0] ?? process.cwd();
|
|
83
|
-
const load_result = await loadPatramConfig(project_directory);
|
|
84
|
-
|
|
85
|
-
if (load_result.diagnostics.length > 0) {
|
|
86
|
-
writeDiagnostics(io_context.stderr, load_result.diagnostics);
|
|
87
|
-
|
|
88
|
-
return 1;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
const repo_config = load_result.config;
|
|
92
|
-
|
|
93
|
-
if (!repo_config) {
|
|
94
|
-
throw new Error('Expected a valid Patram repo config.');
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
const source_file_paths = await listSourceFiles(
|
|
98
|
-
repo_config.include,
|
|
99
|
-
project_directory,
|
|
100
|
-
);
|
|
101
|
-
const claims = await collectClaims(source_file_paths, project_directory);
|
|
102
|
-
const graph = buildGraph(CHECK_GRAPH_CONFIG, claims);
|
|
103
|
-
const diagnostics = checkGraph(graph, source_file_paths);
|
|
104
|
-
|
|
105
|
-
if (diagnostics.length > 0) {
|
|
106
|
-
writeDiagnostics(io_context.stderr, diagnostics);
|
|
107
|
-
|
|
108
|
-
return 1;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
return 0;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
/**
|
|
115
|
-
* @param {string[]} source_file_paths
|
|
116
|
-
* @param {string} project_directory
|
|
117
|
-
* @returns {Promise<PatramClaim[]>}
|
|
118
|
-
*/
|
|
119
|
-
async function collectClaims(source_file_paths, project_directory) {
|
|
120
|
-
/** @type {PatramClaim[]} */
|
|
121
|
-
const claims = [];
|
|
122
|
-
|
|
123
|
-
for (const source_file_path of source_file_paths) {
|
|
124
|
-
const source_text = await readFile(
|
|
125
|
-
resolve(project_directory, source_file_path),
|
|
126
|
-
'utf8',
|
|
127
|
-
);
|
|
128
|
-
|
|
129
|
-
claims.push(
|
|
130
|
-
...parseClaims({
|
|
131
|
-
path: source_file_path,
|
|
132
|
-
source: source_text,
|
|
133
|
-
}),
|
|
134
|
-
);
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
return claims;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
/**
|
|
141
|
-
* @param {{ write(chunk: string): boolean }} output_stream
|
|
142
|
-
* @param {import('../lib/load-patram-config.types.ts').PatramDiagnostic[]} diagnostics
|
|
143
|
-
*/
|
|
144
|
-
function writeDiagnostics(output_stream, diagnostics) {
|
|
145
|
-
for (const diagnostic of diagnostics) {
|
|
146
|
-
output_stream.write(formatDiagnostic(diagnostic));
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
/**
|
|
151
|
-
* @param {import('../lib/load-patram-config.types.ts').PatramDiagnostic} diagnostic
|
|
152
|
-
* @returns {string}
|
|
153
|
-
*/
|
|
154
|
-
function formatDiagnostic(diagnostic) {
|
|
155
|
-
return `${diagnostic.path}:${diagnostic.line}:${diagnostic.column} ${diagnostic.level} ${diagnostic.code} ${diagnostic.message}\n`;
|
|
156
|
-
}
|
|
31
|
+
export { main };
|
|
157
32
|
|
|
158
33
|
/**
|
|
159
34
|
* @param {string} module_url
|
|
160
35
|
* @param {string | undefined} process_entry_path
|
|
161
|
-
* @returns {boolean}
|
|
36
|
+
* @returns {Promise<boolean>}
|
|
162
37
|
*/
|
|
163
|
-
function isEntrypoint(module_url, process_entry_path) {
|
|
38
|
+
async function isEntrypoint(module_url, process_entry_path) {
|
|
164
39
|
if (!process_entry_path) {
|
|
165
40
|
return false;
|
|
166
41
|
}
|
|
167
42
|
|
|
168
|
-
|
|
43
|
+
const module_path = await realpath(fileURLToPath(module_url));
|
|
44
|
+
const entry_path = await realpath(process_entry_path);
|
|
45
|
+
|
|
46
|
+
return module_path === entry_path;
|
|
169
47
|
}
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @import { GraphNode } from './build-graph.types.ts';
|
|
3
|
+
* @import { PatramClaim } from './parse-claims.types.ts';
|
|
4
|
+
* @import { MappingDefinition } from './patram-config.types.ts';
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { posix } from 'node:path';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Collect semantic entity keys defined by canonical documents.
|
|
11
|
+
*
|
|
12
|
+
* @param {Record<string, MappingDefinition>} mappings
|
|
13
|
+
* @param {PatramClaim[]} claims
|
|
14
|
+
* @returns {Map<string, string>}
|
|
15
|
+
*/
|
|
16
|
+
export function collectDocumentEntityKeys(mappings, claims) {
|
|
17
|
+
/** @type {Map<string, string>} */
|
|
18
|
+
const document_entity_keys = new Map();
|
|
19
|
+
|
|
20
|
+
for (const claim of claims) {
|
|
21
|
+
const mapping_definition = resolveMappingDefinition(mappings, claim);
|
|
22
|
+
|
|
23
|
+
if (mapping_definition?.node?.key !== 'value') {
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const source_path = normalizeRepoRelativePath(claim.origin.path);
|
|
28
|
+
const entity_map_key = getDocumentEntityMapKey(
|
|
29
|
+
source_path,
|
|
30
|
+
mapping_definition.node.kind,
|
|
31
|
+
);
|
|
32
|
+
const entity_key = getStringClaimValue(claim);
|
|
33
|
+
const existing_entity_key = document_entity_keys.get(entity_map_key);
|
|
34
|
+
|
|
35
|
+
if (existing_entity_key && existing_entity_key !== entity_key) {
|
|
36
|
+
throw new Error(
|
|
37
|
+
`Document "${source_path}" defines multiple ${mapping_definition.node.kind} ids.`,
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
document_entity_keys.set(entity_map_key, entity_key);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return document_entity_keys;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Resolve the node key for one mapped claim.
|
|
49
|
+
*
|
|
50
|
+
* @param {{ field: string, key?: 'path' | 'value', kind: string }} node_mapping
|
|
51
|
+
* @param {PatramClaim} claim
|
|
52
|
+
* @param {Map<string, string>} document_entity_keys
|
|
53
|
+
* @returns {string}
|
|
54
|
+
*/
|
|
55
|
+
export function resolveNodeKey(node_mapping, claim, document_entity_keys) {
|
|
56
|
+
const source_key = normalizeRepoRelativePath(claim.origin.path);
|
|
57
|
+
|
|
58
|
+
if (node_mapping.kind === 'document') {
|
|
59
|
+
return source_key;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (node_mapping.key === 'value') {
|
|
63
|
+
return getStringClaimValue(claim);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return (
|
|
67
|
+
document_entity_keys.get(
|
|
68
|
+
getDocumentEntityMapKey(source_key, node_mapping.kind),
|
|
69
|
+
) ?? source_key
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Resolve one edge target key and canonical path.
|
|
75
|
+
*
|
|
76
|
+
* @param {string} target_kind
|
|
77
|
+
* @param {'path' | 'value'} target_type
|
|
78
|
+
* @param {PatramClaim} claim
|
|
79
|
+
* @param {Map<string, string>} document_entity_keys
|
|
80
|
+
* @param {Set<string>} document_paths
|
|
81
|
+
* @returns {{ key: string, path?: string }}
|
|
82
|
+
*/
|
|
83
|
+
export function resolveTargetReference(
|
|
84
|
+
target_kind,
|
|
85
|
+
target_type,
|
|
86
|
+
claim,
|
|
87
|
+
document_entity_keys,
|
|
88
|
+
document_paths,
|
|
89
|
+
) {
|
|
90
|
+
if (target_type === 'value') {
|
|
91
|
+
return resolveValueTargetReference(target_kind, claim);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return resolvePathTargetReference(
|
|
95
|
+
target_kind,
|
|
96
|
+
claim,
|
|
97
|
+
document_entity_keys,
|
|
98
|
+
document_paths,
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Attach one canonical path to a non-document graph node.
|
|
104
|
+
*
|
|
105
|
+
* @param {GraphNode} graph_node
|
|
106
|
+
* @param {string | undefined} source_path
|
|
107
|
+
*/
|
|
108
|
+
export function setNonDocumentPath(graph_node, source_path) {
|
|
109
|
+
if (!source_path || graph_node.kind === 'document') {
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (!graph_node.path) {
|
|
114
|
+
graph_node.path = source_path;
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
if (graph_node.path !== source_path) {
|
|
119
|
+
throw new Error(
|
|
120
|
+
`Node "${graph_node.id}" maps to multiple canonical paths.`,
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Normalize one repo-relative source path.
|
|
127
|
+
*
|
|
128
|
+
* @param {string} source_path
|
|
129
|
+
* @returns {string}
|
|
130
|
+
*/
|
|
131
|
+
export function normalizeRepoRelativePath(source_path) {
|
|
132
|
+
return posix.normalize(source_path.replaceAll('\\', '/'));
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* @param {Record<string, MappingDefinition>} mappings
|
|
137
|
+
* @param {PatramClaim} claim
|
|
138
|
+
* @returns {MappingDefinition | null}
|
|
139
|
+
*/
|
|
140
|
+
function resolveMappingDefinition(mappings, claim) {
|
|
141
|
+
if (claim.type === 'directive') {
|
|
142
|
+
return resolveDirectiveMapping(mappings, claim);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
return mappings[claim.type] ?? null;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* @param {Record<string, MappingDefinition>} mappings
|
|
150
|
+
* @param {PatramClaim} claim
|
|
151
|
+
* @returns {MappingDefinition | null}
|
|
152
|
+
*/
|
|
153
|
+
function resolveDirectiveMapping(mappings, claim) {
|
|
154
|
+
if (!claim.parser || !claim.name) {
|
|
155
|
+
return null;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
return mappings[`${claim.parser}.directive.${claim.name}`] ?? null;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* @param {string} target_kind
|
|
163
|
+
* @param {PatramClaim} claim
|
|
164
|
+
* @returns {{ key: string, path?: string }}
|
|
165
|
+
*/
|
|
166
|
+
function resolveValueTargetReference(target_kind, claim) {
|
|
167
|
+
const target_key = getStringClaimValue(claim);
|
|
168
|
+
|
|
169
|
+
if (target_kind === 'document') {
|
|
170
|
+
return {
|
|
171
|
+
key: target_key,
|
|
172
|
+
path: target_key,
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
return {
|
|
177
|
+
key: target_key,
|
|
178
|
+
path: normalizeRepoRelativePath(claim.origin.path),
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* @param {string} target_kind
|
|
184
|
+
* @param {PatramClaim} claim
|
|
185
|
+
* @param {Map<string, string>} document_entity_keys
|
|
186
|
+
* @param {Set<string>} document_paths
|
|
187
|
+
* @returns {{ key: string, path?: string }}
|
|
188
|
+
*/
|
|
189
|
+
function resolvePathTargetReference(
|
|
190
|
+
target_kind,
|
|
191
|
+
claim,
|
|
192
|
+
document_entity_keys,
|
|
193
|
+
document_paths,
|
|
194
|
+
) {
|
|
195
|
+
const raw_target = getPathTargetValue(claim);
|
|
196
|
+
const target_path = resolveDirectiveAwareTargetPath(
|
|
197
|
+
claim,
|
|
198
|
+
raw_target,
|
|
199
|
+
document_paths,
|
|
200
|
+
);
|
|
201
|
+
|
|
202
|
+
if (target_kind === 'document') {
|
|
203
|
+
return {
|
|
204
|
+
key: target_path,
|
|
205
|
+
path: target_path,
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
const semantic_target_key = document_entity_keys.get(
|
|
210
|
+
getDocumentEntityMapKey(target_path, target_kind),
|
|
211
|
+
);
|
|
212
|
+
|
|
213
|
+
return {
|
|
214
|
+
key: semantic_target_key ?? target_path,
|
|
215
|
+
path: target_path,
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* @param {PatramClaim} claim
|
|
221
|
+
* @param {string} raw_target
|
|
222
|
+
* @param {Set<string>} document_paths
|
|
223
|
+
* @returns {string}
|
|
224
|
+
*/
|
|
225
|
+
function resolveDirectiveAwareTargetPath(claim, raw_target, document_paths) {
|
|
226
|
+
const normalized_raw_target = normalizeRepoRelativePath(raw_target);
|
|
227
|
+
|
|
228
|
+
if (claim.type === 'directive' && document_paths.has(normalized_raw_target)) {
|
|
229
|
+
return normalized_raw_target;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
const source_directory = posix.dirname(
|
|
233
|
+
normalizeRepoRelativePath(claim.origin.path),
|
|
234
|
+
);
|
|
235
|
+
|
|
236
|
+
return normalizeRepoRelativePath(posix.join(source_directory, raw_target));
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* @param {PatramClaim} claim
|
|
241
|
+
* @returns {string}
|
|
242
|
+
*/
|
|
243
|
+
function getPathTargetValue(claim) {
|
|
244
|
+
if (typeof claim.value === 'string') {
|
|
245
|
+
return claim.value;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
return claim.value.target;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* @param {PatramClaim} claim
|
|
253
|
+
* @returns {string}
|
|
254
|
+
*/
|
|
255
|
+
function getStringClaimValue(claim) {
|
|
256
|
+
if (typeof claim.value === 'string') {
|
|
257
|
+
return claim.value;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
throw new Error(`Claim "${claim.id}" does not carry a string value.`);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* @param {string} document_path
|
|
265
|
+
* @param {string} kind_name
|
|
266
|
+
* @returns {string}
|
|
267
|
+
*/
|
|
268
|
+
function getDocumentEntityMapKey(document_path, kind_name) {
|
|
269
|
+
return `${kind_name}:${document_path}`;
|
|
270
|
+
}
|