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.
Files changed (67) hide show
  1. package/bin/patram.js +25 -147
  2. package/lib/build-graph-identity.js +270 -0
  3. package/lib/build-graph.js +156 -77
  4. package/lib/check-graph.js +23 -7
  5. package/lib/claim-helpers.js +55 -0
  6. package/lib/cli-help-metadata.js +552 -0
  7. package/lib/command-output.js +83 -0
  8. package/lib/derived-summary.js +278 -0
  9. package/lib/format-derived-summary-row.js +9 -0
  10. package/lib/format-node-header.js +19 -0
  11. package/lib/format-output-item-block.js +22 -0
  12. package/lib/format-output-metadata.js +62 -0
  13. package/lib/layout-stored-queries.js +361 -0
  14. package/lib/list-queries.js +18 -0
  15. package/lib/list-source-files.js +50 -15
  16. package/lib/load-patram-config.js +505 -18
  17. package/lib/load-patram-config.types.ts +40 -0
  18. package/lib/load-project-graph.js +124 -0
  19. package/lib/output-view.types.ts +88 -0
  20. package/lib/parse-claims.js +38 -158
  21. package/lib/parse-claims.types.ts +7 -0
  22. package/lib/parse-cli-arguments-helpers.js +446 -0
  23. package/lib/parse-cli-arguments.js +266 -0
  24. package/lib/parse-cli-arguments.types.ts +69 -0
  25. package/lib/parse-cli-color-options.js +44 -0
  26. package/lib/parse-cli-query-pagination.js +49 -0
  27. package/lib/parse-jsdoc-blocks.js +184 -0
  28. package/lib/parse-jsdoc-claims.js +280 -0
  29. package/lib/parse-jsdoc-prose.js +111 -0
  30. package/lib/parse-markdown-claims.js +242 -0
  31. package/lib/parse-markdown-directives.js +136 -0
  32. package/lib/parse-where-clause.js +707 -0
  33. package/lib/parse-where-clause.types.ts +70 -0
  34. package/lib/patram-cli.js +464 -0
  35. package/lib/patram-config.js +3 -1
  36. package/lib/patram-config.types.ts +2 -1
  37. package/lib/patram.js +6 -0
  38. package/lib/query-graph.js +368 -0
  39. package/lib/query-inspection.js +523 -0
  40. package/lib/render-check-output.js +315 -0
  41. package/lib/render-cli-help.js +419 -0
  42. package/lib/render-json-output.js +161 -0
  43. package/lib/render-output-view.js +222 -0
  44. package/lib/render-plain-output.js +182 -0
  45. package/lib/render-rich-output.js +240 -0
  46. package/lib/render-rich-source.js +1333 -0
  47. package/lib/resolve-check-target.js +190 -0
  48. package/lib/resolve-output-mode.js +60 -0
  49. package/lib/resolve-patram-graph-config.js +88 -0
  50. package/lib/resolve-where-clause.js +66 -0
  51. package/lib/show-document.js +311 -0
  52. package/lib/source-file-defaults.js +28 -0
  53. package/lib/tagged-fenced-block-error.js +17 -0
  54. package/lib/tagged-fenced-block-markdown.js +111 -0
  55. package/lib/tagged-fenced-block-metadata.js +97 -0
  56. package/lib/tagged-fenced-block-parser.js +292 -0
  57. package/lib/tagged-fenced-blocks.js +100 -0
  58. package/lib/tagged-fenced-blocks.types.ts +38 -0
  59. package/lib/write-paged-output.js +87 -0
  60. package/package.json +28 -12
  61. package/bin/patram.test.js +0 -184
  62. package/lib/build-graph.test.js +0 -141
  63. package/lib/check-graph.test.js +0 -103
  64. package/lib/list-source-files.test.js +0 -101
  65. package/lib/load-patram-config.test.js +0 -211
  66. package/lib/parse-claims.test.js +0 -113
  67. package/lib/patram-config.test.js +0 -147
@@ -0,0 +1,70 @@
1
+ import type { PatramDiagnostic } from './load-patram-config.types.ts';
2
+
3
+ export type ParsedFieldName = 'id' | 'kind' | 'path' | 'status' | 'title';
4
+
5
+ export interface ParsedFieldTerm {
6
+ field_name: ParsedFieldName;
7
+ kind: 'field';
8
+ operator: '=' | '^=' | '~';
9
+ value: string;
10
+ }
11
+
12
+ export interface ParsedFieldSetTerm {
13
+ field_name: ParsedFieldName;
14
+ kind: 'field_set';
15
+ operator: 'in' | 'not in';
16
+ values: string[];
17
+ }
18
+
19
+ export interface ParsedTraversalTerm {
20
+ column: number;
21
+ direction: 'in' | 'out';
22
+ relation_name: string;
23
+ }
24
+
25
+ export interface ParsedRelationTerm {
26
+ column: number;
27
+ kind: 'relation';
28
+ relation_name: string;
29
+ }
30
+
31
+ export interface ParsedRelationTargetTerm {
32
+ column: number;
33
+ kind: 'relation_target';
34
+ relation_name: string;
35
+ target_id: string;
36
+ }
37
+
38
+ export type ParsedAggregateComparison = '!=' | '<' | '<=' | '=' | '>' | '>=';
39
+ export type ParsedAggregateName = 'any' | 'count' | 'none';
40
+
41
+ export interface ParsedAggregateTerm {
42
+ aggregate_name: ParsedAggregateName;
43
+ clauses: ParsedClause[];
44
+ comparison?: ParsedAggregateComparison;
45
+ kind: 'aggregate';
46
+ traversal: ParsedTraversalTerm;
47
+ value?: number;
48
+ }
49
+
50
+ export type ParsedTerm =
51
+ | ParsedAggregateTerm
52
+ | ParsedFieldSetTerm
53
+ | ParsedFieldTerm
54
+ | ParsedRelationTargetTerm
55
+ | ParsedRelationTerm;
56
+
57
+ export interface ParsedClause {
58
+ is_negated: boolean;
59
+ term: ParsedTerm;
60
+ }
61
+
62
+ export type ParseWhereClauseResult =
63
+ | {
64
+ clauses: ParsedClause[];
65
+ success: true;
66
+ }
67
+ | {
68
+ diagnostic: PatramDiagnostic;
69
+ success: false;
70
+ };
@@ -0,0 +1,464 @@
1
+ /* eslint-disable max-lines */
2
+ /**
3
+ * @import { ParsedCliCommandRequest } from './parse-cli-arguments.types.ts';
4
+ */
5
+
6
+ import process from 'node:process';
7
+
8
+ import { checkGraph } from './check-graph.js';
9
+ import {
10
+ shouldPageCommandOutput,
11
+ writeCommandOutput,
12
+ } from './command-output.js';
13
+ import { listRepoFiles } from './list-source-files.js';
14
+ import { listQueries } from './list-queries.js';
15
+ import { loadPatramConfig } from './load-patram-config.js';
16
+ import { loadProjectGraph } from './load-project-graph.js';
17
+ import { parseCliArguments } from './parse-cli-arguments.js';
18
+ import { DEFAULT_QUERY_LIMIT, queryGraph } from './query-graph.js';
19
+ import { inspectQuery, renderQueryInspection } from './query-inspection.js';
20
+ import { createDerivedSummaryEvaluator } from './derived-summary.js';
21
+ import {
22
+ renderCheckDiagnostics,
23
+ renderCheckSuccess,
24
+ } from './render-check-output.js';
25
+ import {
26
+ renderCliParseError,
27
+ renderHelpRequest,
28
+ renderInvalidWhereDiagnostic,
29
+ } from './render-cli-help.js';
30
+ import {
31
+ resolveCheckTarget,
32
+ selectCheckTargetDiagnostics,
33
+ selectCheckTargetSourceFiles,
34
+ } from './resolve-check-target.js';
35
+ import {
36
+ createOutputView,
37
+ createShowOutputView,
38
+ } from './render-output-view.js';
39
+ import { resolveWhereClause } from './resolve-where-clause.js';
40
+ import { resolveOutputMode } from './resolve-output-mode.js';
41
+ import { loadShowOutput } from './show-document.js';
42
+
43
+ /**
44
+ * Patram command execution flow.
45
+ *
46
+ * Loads repo state and routes `check`, `query`, `queries`, and `show` through
47
+ * the shared output pipeline.
48
+ *
49
+ * Kind: cli
50
+ * Status: active
51
+ * Implements Command: ../docs/reference/commands/check.md
52
+ * Implements Command: ../docs/reference/commands/query.md
53
+ * Implements Command: ../docs/reference/commands/queries.md
54
+ * Implements Command: ../docs/reference/commands/show.md
55
+ * Tracked in: ../docs/plans/v0/source-anchor-dogfooding.md
56
+ * Decided by: ../docs/decisions/cli-output-architecture.md
57
+ * Decided by: ../docs/decisions/cli-argument-parser.md
58
+ * @patram
59
+ * @see {@link ./parse-cli-arguments.js}
60
+ * @see {@link ./render-output-view.js}
61
+ */
62
+
63
+ /**
64
+ * Run the Patram CLI.
65
+ *
66
+ * @param {string[]} cli_arguments
67
+ * @param {{ stderr: { write(chunk: string): boolean }, stdout: { isTTY?: boolean, write(chunk: string): boolean }, write_paged_output?: (output_text: string) => Promise<void> }} io_context
68
+ * @returns {Promise<number>}
69
+ */
70
+ export async function main(cli_arguments, io_context) {
71
+ const parsed_arguments = parseCliArguments(cli_arguments);
72
+
73
+ if (!parsed_arguments.success) {
74
+ io_context.stderr.write(renderCliParseError(parsed_arguments.error));
75
+
76
+ return 1;
77
+ }
78
+
79
+ if (parsed_arguments.value.kind === 'help') {
80
+ io_context.stdout.write(renderHelpRequest(parsed_arguments.value));
81
+
82
+ return 0;
83
+ }
84
+
85
+ const parsed_command = /** @type {ParsedCliCommandRequest} */ (
86
+ parsed_arguments.value
87
+ );
88
+
89
+ if (parsed_command.command_name === 'check') {
90
+ return runCheckCommand(parsed_command, io_context);
91
+ }
92
+
93
+ if (parsed_command.command_name === 'query') {
94
+ return runQueryCommand(parsed_command, io_context);
95
+ }
96
+
97
+ if (parsed_command.command_name === 'queries') {
98
+ return runQueriesCommand(parsed_command, io_context);
99
+ }
100
+
101
+ if (parsed_command.command_name === 'show') {
102
+ return runShowCommand(parsed_command, io_context);
103
+ }
104
+
105
+ io_context.stderr.write('Unknown command.\n');
106
+
107
+ return 1;
108
+ }
109
+
110
+ /**
111
+ * @param {ParsedCliCommandRequest} parsed_command
112
+ * @param {{ stderr: { write(chunk: string): boolean }, stdout: { isTTY?: boolean, write(chunk: string): boolean }, write_paged_output?: (output_text: string) => Promise<void> }} io_context
113
+ * @returns {Promise<number>}
114
+ */
115
+ async function runCheckCommand(parsed_command, io_context) {
116
+ const output_mode = resolveOutputMode(parsed_command, {
117
+ is_tty: io_context.stdout.isTTY === true,
118
+ no_color: process.env.NO_COLOR !== undefined,
119
+ term: process.env.TERM,
120
+ });
121
+ const resolved_target = await resolveCheckTarget(
122
+ parsed_command.command_arguments[0],
123
+ );
124
+ const project_graph_result = await loadProjectGraph(
125
+ resolved_target.project_directory,
126
+ );
127
+ const repo_file_paths = await listRepoFiles(
128
+ resolved_target.project_directory,
129
+ );
130
+ const selected_source_file_paths = selectCheckTargetSourceFiles(
131
+ project_graph_result.source_file_paths,
132
+ resolved_target,
133
+ );
134
+
135
+ if (project_graph_result.diagnostics.length > 0) {
136
+ io_context.stderr.write(
137
+ renderCheckDiagnostics(project_graph_result.diagnostics, output_mode),
138
+ );
139
+
140
+ return 1;
141
+ }
142
+
143
+ const diagnostics = checkGraph(project_graph_result.graph, repo_file_paths);
144
+ const selected_diagnostics = selectCheckTargetDiagnostics(
145
+ diagnostics,
146
+ resolved_target,
147
+ );
148
+
149
+ if (selected_diagnostics.length > 0) {
150
+ io_context.stderr.write(
151
+ renderCheckDiagnostics(selected_diagnostics, output_mode),
152
+ );
153
+
154
+ return 1;
155
+ }
156
+
157
+ io_context.stdout.write(
158
+ renderCheckSuccess(selected_source_file_paths.length, output_mode),
159
+ );
160
+
161
+ return 0;
162
+ }
163
+
164
+ /**
165
+ * @param {ParsedCliCommandRequest} parsed_command
166
+ * @param {{ stderr: { write(chunk: string): boolean }, stdout: { isTTY?: boolean, write(chunk: string): boolean }, write_paged_output?: (output_text: string) => Promise<void> }} io_context
167
+ * @returns {Promise<number>}
168
+ */
169
+ async function runQueryCommand(parsed_command, io_context) {
170
+ const use_pager = shouldPageCommandOutput(parsed_command, io_context.stdout);
171
+ const output_mode = resolveOutputMode(parsed_command, {
172
+ is_tty: io_context.stdout.isTTY === true,
173
+ no_color: process.env.NO_COLOR !== undefined,
174
+ term: process.env.TERM,
175
+ });
176
+
177
+ if (parsed_command.query_inspection_mode) {
178
+ return runQueryInspectionCommand(
179
+ parsed_command,
180
+ io_context,
181
+ output_mode,
182
+ use_pager,
183
+ );
184
+ }
185
+
186
+ const project_graph_result = await loadProjectGraph(process.cwd());
187
+
188
+ if (project_graph_result.diagnostics.length > 0) {
189
+ writeDiagnostics(io_context.stderr, project_graph_result.diagnostics);
190
+
191
+ return 1;
192
+ }
193
+
194
+ const where_clause = resolveWhereClause(
195
+ project_graph_result.config,
196
+ parsed_command.command_arguments,
197
+ );
198
+
199
+ if (!where_clause.success) {
200
+ io_context.stderr.write(`${where_clause.message}\n`);
201
+
202
+ return 1;
203
+ }
204
+
205
+ const query_result = queryGraph(
206
+ project_graph_result.graph,
207
+ where_clause.value.where_clause,
208
+ createQueryPaginationOptions(parsed_command, use_pager),
209
+ );
210
+
211
+ if (query_result.diagnostics.length > 0) {
212
+ io_context.stderr.write(
213
+ renderInvalidWhereDiagnostic(query_result.diagnostics[0]),
214
+ );
215
+
216
+ return 1;
217
+ }
218
+
219
+ const derived_summary_evaluator = createDerivedSummaryEvaluator(
220
+ project_graph_result.config,
221
+ project_graph_result.graph,
222
+ );
223
+
224
+ await writeCommandOutput(
225
+ io_context,
226
+ parsed_command,
227
+ createOutputView('query', query_result.nodes, {
228
+ derived_summary_evaluator,
229
+ ...createQueryOutputOptions(parsed_command, query_result, use_pager),
230
+ }),
231
+ );
232
+
233
+ return 0;
234
+ }
235
+
236
+ /**
237
+ * @param {ParsedCliCommandRequest} parsed_command
238
+ * @param {{ stderr: { write(chunk: string): boolean }, stdout: { isTTY?: boolean, write(chunk: string): boolean } }} io_context
239
+ * @param {import('./output-view.types.ts').ResolvedOutputMode} output_mode
240
+ * @param {boolean} use_pager
241
+ * @returns {Promise<number>}
242
+ */
243
+ async function runQueryInspectionCommand(
244
+ parsed_command,
245
+ io_context,
246
+ output_mode,
247
+ use_pager,
248
+ ) {
249
+ const query_inspection_mode = parsed_command.query_inspection_mode;
250
+
251
+ if (!query_inspection_mode) {
252
+ throw new Error('Expected a query inspection mode.');
253
+ }
254
+
255
+ const load_result = await loadPatramConfig(process.cwd());
256
+
257
+ if (load_result.diagnostics.length > 0) {
258
+ io_context.stderr.write(
259
+ renderCheckDiagnostics(load_result.diagnostics, output_mode),
260
+ );
261
+
262
+ return 1;
263
+ }
264
+
265
+ const repo_config = load_result.config;
266
+
267
+ if (!repo_config) {
268
+ throw new Error('Expected a valid Patram repo config.');
269
+ }
270
+
271
+ const where_clause = resolveWhereClause(
272
+ repo_config,
273
+ parsed_command.command_arguments,
274
+ );
275
+
276
+ if (!where_clause.success) {
277
+ io_context.stderr.write(`${where_clause.message}\n`);
278
+
279
+ return 1;
280
+ }
281
+
282
+ const query_inspection = inspectQuery(repo_config, where_clause.value, {
283
+ inspection_mode: query_inspection_mode,
284
+ ...createQueryExecutionOptions(parsed_command, use_pager),
285
+ });
286
+
287
+ if (!query_inspection.success) {
288
+ io_context.stderr.write(
289
+ renderCheckDiagnostics(query_inspection.diagnostics, output_mode),
290
+ );
291
+
292
+ return 1;
293
+ }
294
+
295
+ io_context.stdout.write(
296
+ renderQueryInspection(query_inspection.value, output_mode),
297
+ );
298
+
299
+ return 0;
300
+ }
301
+
302
+ /**
303
+ * @param {ParsedCliCommandRequest} parsed_command
304
+ * @param {{ stderr: { write(chunk: string): boolean }, stdout: { isTTY?: boolean, write(chunk: string): boolean }, write_paged_output?: (output_text: string) => Promise<void> }} io_context
305
+ * @returns {Promise<number>}
306
+ */
307
+ async function runQueriesCommand(parsed_command, io_context) {
308
+ const load_result = await loadPatramConfig(process.cwd());
309
+
310
+ if (load_result.diagnostics.length > 0) {
311
+ writeDiagnostics(io_context.stderr, load_result.diagnostics);
312
+
313
+ return 1;
314
+ }
315
+
316
+ const repo_config = load_result.config;
317
+
318
+ if (!repo_config) {
319
+ throw new Error('Expected a valid Patram repo config.');
320
+ }
321
+
322
+ await writeCommandOutput(
323
+ io_context,
324
+ parsed_command,
325
+ createOutputView('queries', listQueries(repo_config.queries)),
326
+ );
327
+
328
+ return 0;
329
+ }
330
+
331
+ /**
332
+ * @param {ParsedCliCommandRequest} parsed_command
333
+ * @param {{ stderr: { write(chunk: string): boolean }, stdout: { isTTY?: boolean, write(chunk: string): boolean }, write_paged_output?: (output_text: string) => Promise<void> }} io_context
334
+ * @returns {Promise<number>}
335
+ */
336
+ async function runShowCommand(parsed_command, io_context) {
337
+ const project_graph_result = await loadProjectGraph(process.cwd());
338
+
339
+ if (project_graph_result.diagnostics.length > 0) {
340
+ writeDiagnostics(io_context.stderr, project_graph_result.diagnostics);
341
+
342
+ return 1;
343
+ }
344
+
345
+ const show_output = await loadShowOutput(
346
+ parsed_command.command_arguments[0],
347
+ process.cwd(),
348
+ project_graph_result.graph,
349
+ );
350
+
351
+ if (!show_output.success) {
352
+ writeDiagnostics(io_context.stderr, [show_output.diagnostic]);
353
+
354
+ return 1;
355
+ }
356
+
357
+ const derived_summary_evaluator = createDerivedSummaryEvaluator(
358
+ project_graph_result.config,
359
+ project_graph_result.graph,
360
+ );
361
+
362
+ await writeCommandOutput(
363
+ io_context,
364
+ parsed_command,
365
+ createShowOutputView(show_output.value, {
366
+ derived_summary_evaluator,
367
+ graph_nodes: project_graph_result.graph.nodes,
368
+ }),
369
+ );
370
+
371
+ return 0;
372
+ }
373
+
374
+ /**
375
+ * @param {{ write(chunk: string): boolean }} output_stream
376
+ * @param {import('./load-patram-config.types.ts').PatramDiagnostic[]} diagnostics
377
+ */
378
+ function writeDiagnostics(output_stream, diagnostics) {
379
+ for (const diagnostic of diagnostics) {
380
+ output_stream.write(formatDiagnostic(diagnostic));
381
+ }
382
+ }
383
+
384
+ /**
385
+ * @param {ParsedCliCommandRequest} parsed_command
386
+ * @param {{ total_count: number, nodes: import('./build-graph.types.ts').GraphNode[] }} query_result
387
+ * @param {boolean} use_pager
388
+ * @returns {{ hints: string[], limit: number, offset: number, total_count: number }}
389
+ */
390
+ function createQueryOutputOptions(parsed_command, query_result, use_pager) {
391
+ /** @type {string[]} */
392
+ const hints = [];
393
+ const limit =
394
+ parsed_command.query_limit ??
395
+ (use_pager ? query_result.nodes.length : DEFAULT_QUERY_LIMIT);
396
+ const offset = parsed_command.query_offset ?? 0;
397
+
398
+ if (query_result.total_count === 0) {
399
+ hints.push('Try: patram query --where "kind=task"');
400
+ }
401
+
402
+ if (
403
+ !use_pager &&
404
+ parsed_command.query_limit === undefined &&
405
+ parsed_command.query_offset === undefined &&
406
+ query_result.total_count > DEFAULT_QUERY_LIMIT
407
+ ) {
408
+ hints.push(
409
+ 'Hint: use --offset <n> or --limit <n> to page through more matches.',
410
+ );
411
+ }
412
+
413
+ return {
414
+ hints,
415
+ limit,
416
+ offset,
417
+ total_count: query_result.total_count,
418
+ };
419
+ }
420
+
421
+ /**
422
+ * @param {ParsedCliCommandRequest} parsed_command
423
+ * @param {boolean} use_pager
424
+ * @returns {{ limit?: number, offset: number }}
425
+ */
426
+ function createQueryPaginationOptions(parsed_command, use_pager) {
427
+ /** @type {{ limit?: number, offset: number }} */
428
+ const pagination_options = {
429
+ offset: parsed_command.query_offset ?? 0,
430
+ };
431
+
432
+ if (parsed_command.query_limit !== undefined) {
433
+ pagination_options.limit = parsed_command.query_limit;
434
+ } else if (!use_pager) {
435
+ pagination_options.limit = DEFAULT_QUERY_LIMIT;
436
+ }
437
+
438
+ return pagination_options;
439
+ }
440
+
441
+ /**
442
+ * @param {ParsedCliCommandRequest} parsed_command
443
+ * @param {boolean} use_pager
444
+ * @returns {{ limit: number | null, offset: number }}
445
+ */
446
+ function createQueryExecutionOptions(parsed_command, use_pager) {
447
+ const pagination_options = createQueryPaginationOptions(
448
+ parsed_command,
449
+ use_pager,
450
+ );
451
+
452
+ return {
453
+ limit: pagination_options.limit ?? null,
454
+ offset: pagination_options.offset,
455
+ };
456
+ }
457
+
458
+ /**
459
+ * @param {import('./load-patram-config.types.ts').PatramDiagnostic} diagnostic
460
+ * @returns {string}
461
+ */
462
+ function formatDiagnostic(diagnostic) {
463
+ return `${diagnostic.path}:${diagnostic.line}:${diagnostic.column} ${diagnostic.level} ${diagnostic.code} ${diagnostic.message}\n`;
464
+ }
@@ -8,7 +8,8 @@ import { z } from 'zod';
8
8
  const KIND_NAME_SCHEMA = z.string().min(1);
9
9
  const RELATION_NAME_SCHEMA = z.string().min(1);
10
10
  const CLAIM_TYPE_SCHEMA = z.string().min(1);
11
- const TARGET_SCHEMA = z.enum(['path']);
11
+ const KEY_SOURCE_SCHEMA = z.enum(['path', 'value']);
12
+ const TARGET_SCHEMA = z.enum(['path', 'value']);
12
13
 
13
14
  const kind_definition_schema = z
14
15
  .object({
@@ -28,6 +29,7 @@ const relation_definition_schema = z
28
29
  const mapping_node_schema = z
29
30
  .object({
30
31
  field: z.string().min(1),
32
+ key: KEY_SOURCE_SCHEMA.optional(),
31
33
  kind: KIND_NAME_SCHEMA,
32
34
  })
33
35
  .strict();
@@ -11,12 +11,13 @@ export interface RelationDefinition {
11
11
 
12
12
  export interface MappingNodeDefinition {
13
13
  field: string;
14
+ key?: 'path' | 'value';
14
15
  kind: string;
15
16
  }
16
17
 
17
18
  export interface MappingEmitDefinition {
18
19
  relation: string;
19
- target: 'path';
20
+ target: 'path' | 'value';
20
21
  target_kind: string;
21
22
  }
22
23
 
package/lib/patram.js ADDED
@@ -0,0 +1,6 @@
1
+ export {
2
+ extractTaggedFencedBlocks,
3
+ loadTaggedFencedBlocks,
4
+ selectTaggedBlock,
5
+ selectTaggedBlocks,
6
+ } from './tagged-fenced-blocks.js';