@cavelang/cli 0.35.0 → 0.36.1
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/README.md +224 -12
- package/dist/internal/act/action.js +2 -1
- package/dist/internal/act/action.js.map +1 -1
- package/dist/internal/act/declare.d.ts.map +1 -1
- package/dist/internal/act/declare.js +82 -53
- package/dist/internal/act/declare.js.map +1 -1
- package/dist/internal/act/engine.d.ts +4 -3
- package/dist/internal/act/engine.d.ts.map +1 -1
- package/dist/internal/act/engine.js +121 -32
- package/dist/internal/act/engine.js.map +1 -1
- package/dist/internal/automate/cancellation.d.ts +3 -0
- package/dist/internal/automate/cancellation.d.ts.map +1 -0
- package/dist/internal/automate/cancellation.js +38 -0
- package/dist/internal/automate/cancellation.js.map +1 -0
- package/dist/internal/automate/declare.d.ts.map +1 -1
- package/dist/internal/automate/declare.js +49 -24
- package/dist/internal/automate/declare.js.map +1 -1
- package/dist/internal/automate/engine.d.ts +7 -3
- package/dist/internal/automate/engine.d.ts.map +1 -1
- package/dist/internal/automate/engine.js +196 -93
- package/dist/internal/automate/engine.js.map +1 -1
- package/dist/internal/automate/error-message.d.ts +3 -0
- package/dist/internal/automate/error-message.d.ts.map +1 -0
- package/dist/internal/automate/error-message.js +10 -0
- package/dist/internal/automate/error-message.js.map +1 -0
- package/dist/internal/automate/main.d.ts.map +1 -1
- package/dist/internal/automate/main.js +238 -35
- package/dist/internal/automate/main.js.map +1 -1
- package/dist/internal/automate/options.d.ts +4 -0
- package/dist/internal/automate/options.d.ts.map +1 -0
- package/dist/internal/automate/options.js +19 -0
- package/dist/internal/automate/options.js.map +1 -0
- package/dist/internal/connect/declared.d.ts +6 -27
- package/dist/internal/connect/declared.d.ts.map +1 -1
- package/dist/internal/connect/declared.js +165 -76
- package/dist/internal/connect/declared.js.map +1 -1
- package/dist/internal/connect/error-message.d.ts +3 -0
- package/dist/internal/connect/error-message.d.ts.map +1 -0
- package/dist/internal/connect/error-message.js +10 -0
- package/dist/internal/connect/error-message.js.map +1 -0
- package/dist/internal/connect/federation.d.ts +9 -0
- package/dist/internal/connect/federation.d.ts.map +1 -0
- package/dist/internal/connect/federation.js +19 -0
- package/dist/internal/connect/federation.js.map +1 -0
- package/dist/internal/connect/fetch-failure.d.ts +3 -0
- package/dist/internal/connect/fetch-failure.d.ts.map +1 -0
- package/dist/internal/connect/fetch-failure.js +36 -0
- package/dist/internal/connect/fetch-failure.js.map +1 -0
- package/dist/internal/connect/main.d.ts +1 -0
- package/dist/internal/connect/main.d.ts.map +1 -1
- package/dist/internal/connect/main.js +288 -114
- package/dist/internal/connect/main.js.map +1 -1
- package/dist/internal/connect/options.d.ts +3 -0
- package/dist/internal/connect/options.d.ts.map +1 -0
- package/dist/internal/connect/options.js +9 -0
- package/dist/internal/connect/options.js.map +1 -0
- package/dist/internal/connect/records.d.ts +3 -0
- package/dist/internal/connect/records.d.ts.map +1 -0
- package/dist/internal/connect/records.js +21 -0
- package/dist/internal/connect/records.js.map +1 -0
- package/dist/internal/connect/run.d.ts +1 -18
- package/dist/internal/connect/run.d.ts.map +1 -1
- package/dist/internal/connect/run.js +115 -55
- package/dist/internal/connect/run.js.map +1 -1
- package/dist/internal/connect/source.d.ts +3 -1
- package/dist/internal/connect/source.d.ts.map +1 -1
- package/dist/internal/connect/source.js +226 -47
- package/dist/internal/connect/source.js.map +1 -1
- package/dist/internal/connect/template.d.ts +2 -2
- package/dist/internal/connect/template.d.ts.map +1 -1
- package/dist/internal/connect/template.js +25 -9
- package/dist/internal/connect/template.js.map +1 -1
- package/dist/internal/connect/utf8.d.ts +3 -0
- package/dist/internal/connect/utf8.d.ts.map +1 -0
- package/dist/internal/connect/utf8.js +12 -0
- package/dist/internal/connect/utf8.js.map +1 -0
- package/dist/internal/eval/cleanup.d.ts +5 -0
- package/dist/internal/eval/cleanup.d.ts.map +1 -0
- package/dist/internal/eval/cleanup.js +50 -0
- package/dist/internal/eval/cleanup.js.map +1 -0
- package/dist/internal/eval/error-message.d.ts +3 -0
- package/dist/internal/eval/error-message.d.ts.map +1 -0
- package/dist/internal/eval/error-message.js +10 -0
- package/dist/internal/eval/error-message.js.map +1 -0
- package/dist/internal/eval/judge.d.ts.map +1 -1
- package/dist/internal/eval/judge.js +3 -31
- package/dist/internal/eval/judge.js.map +1 -1
- package/dist/internal/eval/loop.d.ts.map +1 -1
- package/dist/internal/eval/loop.js +18 -4
- package/dist/internal/eval/loop.js.map +1 -1
- package/dist/internal/eval/main.d.ts.map +1 -1
- package/dist/internal/eval/main.js +22 -10
- package/dist/internal/eval/main.js.map +1 -1
- package/dist/internal/eval/options.d.ts +6 -0
- package/dist/internal/eval/options.d.ts.map +1 -0
- package/dist/internal/eval/options.js +31 -0
- package/dist/internal/eval/options.js.map +1 -0
- package/dist/internal/eval/queries.d.ts.map +1 -1
- package/dist/internal/eval/queries.js +9 -6
- package/dist/internal/eval/queries.js.map +1 -1
- package/dist/internal/eval/run.d.ts.map +1 -1
- package/dist/internal/eval/run.js +112 -24
- package/dist/internal/eval/run.js.map +1 -1
- package/dist/internal/eval/score.d.ts.map +1 -1
- package/dist/internal/eval/score.js +9 -2
- package/dist/internal/eval/score.js.map +1 -1
- package/dist/internal/eval/suite.d.ts.map +1 -1
- package/dist/internal/eval/suite.js +14 -2
- package/dist/internal/eval/suite.js.map +1 -1
- package/dist/internal/ingest/cleanup.d.ts +5 -0
- package/dist/internal/ingest/cleanup.d.ts.map +1 -0
- package/dist/internal/ingest/cleanup.js +50 -0
- package/dist/internal/ingest/cleanup.js.map +1 -0
- package/dist/internal/ingest/content.d.ts +6 -0
- package/dist/internal/ingest/content.d.ts.map +1 -0
- package/dist/internal/ingest/content.js +25 -0
- package/dist/internal/ingest/content.js.map +1 -0
- package/dist/internal/ingest/context.d.ts.map +1 -1
- package/dist/internal/ingest/context.js +25 -7
- package/dist/internal/ingest/context.js.map +1 -1
- package/dist/internal/ingest/error-message.d.ts +3 -0
- package/dist/internal/ingest/error-message.d.ts.map +1 -0
- package/dist/internal/ingest/error-message.js +10 -0
- package/dist/internal/ingest/error-message.js.map +1 -0
- package/dist/internal/ingest/files.d.ts +4 -12
- package/dist/internal/ingest/files.d.ts.map +1 -1
- package/dist/internal/ingest/files.js +22 -10
- package/dist/internal/ingest/files.js.map +1 -1
- package/dist/internal/ingest/main.d.ts.map +1 -1
- package/dist/internal/ingest/main.js +46 -16
- package/dist/internal/ingest/main.js.map +1 -1
- package/dist/internal/ingest/options.d.ts +6 -0
- package/dist/internal/ingest/options.d.ts.map +1 -0
- package/dist/internal/ingest/options.js +27 -0
- package/dist/internal/ingest/options.js.map +1 -0
- package/dist/internal/ingest/prompt.d.ts.map +1 -1
- package/dist/internal/ingest/prompt.js +14 -10
- package/dist/internal/ingest/prompt.js.map +1 -1
- package/dist/internal/ingest/run.d.ts +9 -2
- package/dist/internal/ingest/run.d.ts.map +1 -1
- package/dist/internal/ingest/run.js +206 -62
- package/dist/internal/ingest/run.js.map +1 -1
- package/dist/internal/ingest/timeout.d.ts +3 -0
- package/dist/internal/ingest/timeout.d.ts.map +1 -0
- package/dist/internal/ingest/timeout.js +14 -0
- package/dist/internal/ingest/timeout.js.map +1 -0
- package/dist/internal/ingest/web.d.ts +2 -11
- package/dist/internal/ingest/web.d.ts.map +1 -1
- package/dist/internal/ingest/web.js +131 -25
- package/dist/internal/ingest/web.js.map +1 -1
- package/dist/internal/loop/budgets.d.ts +3 -0
- package/dist/internal/loop/budgets.d.ts.map +1 -0
- package/dist/internal/loop/budgets.js +10 -0
- package/dist/internal/loop/budgets.js.map +1 -0
- package/dist/internal/loop/index.d.ts +2 -0
- package/dist/internal/loop/index.d.ts.map +1 -1
- package/dist/internal/loop/index.js +2 -0
- package/dist/internal/loop/index.js.map +1 -1
- package/dist/internal/loop/json-answer.d.ts +7 -0
- package/dist/internal/loop/json-answer.d.ts.map +1 -0
- package/dist/internal/loop/json-answer.js +79 -0
- package/dist/internal/loop/json-answer.js.map +1 -0
- package/dist/internal/loop/json-spans.d.ts +3 -0
- package/dist/internal/loop/json-spans.d.ts.map +1 -0
- package/dist/internal/loop/json-spans.js +88 -0
- package/dist/internal/loop/json-spans.js.map +1 -0
- package/dist/internal/loop/llm.d.ts +3 -2
- package/dist/internal/loop/llm.d.ts.map +1 -1
- package/dist/internal/loop/llm.js +115 -32
- package/dist/internal/loop/llm.js.map +1 -1
- package/dist/internal/loop/process.d.ts +3 -1
- package/dist/internal/loop/process.d.ts.map +1 -1
- package/dist/internal/loop/process.js +159 -59
- package/dist/internal/loop/process.js.map +1 -1
- package/dist/internal/loop/read-snapshot.d.ts +4 -0
- package/dist/internal/loop/read-snapshot.d.ts.map +1 -0
- package/dist/internal/loop/read-snapshot.js +29 -0
- package/dist/internal/loop/read-snapshot.js.map +1 -0
- package/dist/internal/loop/reconstruct.d.ts +6 -5
- package/dist/internal/loop/reconstruct.d.ts.map +1 -1
- package/dist/internal/loop/reconstruct.js +19 -8
- package/dist/internal/loop/reconstruct.js.map +1 -1
- package/dist/internal/loop/score-settings.d.ts +5 -0
- package/dist/internal/loop/score-settings.d.ts.map +1 -0
- package/dist/internal/loop/score-settings.js +14 -0
- package/dist/internal/loop/score-settings.js.map +1 -0
- package/dist/internal/loop/sqlite.d.ts.map +1 -1
- package/dist/internal/loop/sqlite.js +15 -7
- package/dist/internal/loop/sqlite.js.map +1 -1
- package/dist/internal/loop/store.d.ts.map +1 -1
- package/dist/internal/loop/store.js +11 -7
- package/dist/internal/loop/store.js.map +1 -1
- package/dist/internal/loop/timeout.d.ts +3 -0
- package/dist/internal/loop/timeout.d.ts.map +1 -0
- package/dist/internal/loop/timeout.js +13 -0
- package/dist/internal/loop/timeout.js.map +1 -0
- package/dist/internal/mcp/error-message.d.ts +3 -0
- package/dist/internal/mcp/error-message.d.ts.map +1 -0
- package/dist/internal/mcp/error-message.js +10 -0
- package/dist/internal/mcp/error-message.js.map +1 -0
- package/dist/internal/mcp/main.d.ts.map +1 -1
- package/dist/internal/mcp/main.js +42 -27
- package/dist/internal/mcp/main.js.map +1 -1
- package/dist/internal/mcp/read-snapshot.d.ts +4 -0
- package/dist/internal/mcp/read-snapshot.d.ts.map +1 -0
- package/dist/internal/mcp/read-snapshot.js +22 -0
- package/dist/internal/mcp/read-snapshot.js.map +1 -0
- package/dist/internal/mcp/server.d.ts.map +1 -1
- package/dist/internal/mcp/server.js +181 -21
- package/dist/internal/mcp/server.js.map +1 -1
- package/dist/internal/mcp/source.d.ts +3 -0
- package/dist/internal/mcp/source.d.ts.map +1 -0
- package/dist/internal/mcp/source.js +13 -0
- package/dist/internal/mcp/source.js.map +1 -0
- package/dist/internal/mcp/tools.d.ts.map +1 -1
- package/dist/internal/mcp/tools.js +135 -72
- package/dist/internal/mcp/tools.js.map +1 -1
- package/dist/internal/rules/declarations.d.ts +6 -0
- package/dist/internal/rules/declarations.d.ts.map +1 -0
- package/dist/internal/rules/declarations.js +14 -0
- package/dist/internal/rules/declarations.js.map +1 -0
- package/dist/internal/rules/declare.d.ts.map +1 -1
- package/dist/internal/rules/declare.js +30 -16
- package/dist/internal/rules/declare.js.map +1 -1
- package/dist/internal/rules/engine.d.ts +8 -7
- package/dist/internal/rules/engine.d.ts.map +1 -1
- package/dist/internal/rules/engine.js +150 -44
- package/dist/internal/rules/engine.js.map +1 -1
- package/dist/internal/shape/alias-root.d.ts +3 -0
- package/dist/internal/shape/alias-root.d.ts.map +1 -0
- package/dist/internal/shape/alias-root.js +13 -0
- package/dist/internal/shape/alias-root.js.map +1 -0
- package/dist/internal/shape/check.d.ts +15 -3
- package/dist/internal/shape/check.d.ts.map +1 -1
- package/dist/internal/shape/check.js +230 -100
- package/dist/internal/shape/check.js.map +1 -1
- package/dist/internal/shape/client.d.ts.map +1 -1
- package/dist/internal/shape/client.js +42 -20
- package/dist/internal/shape/client.js.map +1 -1
- package/dist/internal/shape/constraints.d.ts +8 -0
- package/dist/internal/shape/constraints.d.ts.map +1 -0
- package/dist/internal/shape/constraints.js +17 -0
- package/dist/internal/shape/constraints.js.map +1 -0
- package/dist/internal/shape/edit-distance.d.ts +3 -0
- package/dist/internal/shape/edit-distance.d.ts.map +1 -0
- package/dist/internal/shape/edit-distance.js +33 -0
- package/dist/internal/shape/edit-distance.js.map +1 -0
- package/dist/internal/shape/gate.d.ts.map +1 -1
- package/dist/internal/shape/gate.js +0 -0
- package/dist/internal/shape/gate.js.map +1 -1
- package/dist/internal/shape/snapshot.d.ts +4 -0
- package/dist/internal/shape/snapshot.d.ts.map +1 -0
- package/dist/internal/shape/snapshot.js +20 -0
- package/dist/internal/shape/snapshot.js.map +1 -0
- package/dist/internal/shape/suggest.d.ts +8 -6
- package/dist/internal/shape/suggest.d.ts.map +1 -1
- package/dist/internal/shape/suggest.js +208 -92
- package/dist/internal/shape/suggest.js.map +1 -1
- package/dist/internal/sync/error-message.d.ts +3 -0
- package/dist/internal/sync/error-message.d.ts.map +1 -0
- package/dist/internal/sync/error-message.js +10 -0
- package/dist/internal/sync/error-message.js.map +1 -0
- package/dist/internal/sync/index.d.ts +3 -2
- package/dist/internal/sync/index.d.ts.map +1 -1
- package/dist/internal/sync/index.js +3 -2
- package/dist/internal/sync/index.js.map +1 -1
- package/dist/internal/sync/sync.d.ts +8 -5
- package/dist/internal/sync/sync.d.ts.map +1 -1
- package/dist/internal/sync/sync.js +322 -65
- package/dist/internal/sync/sync.js.map +1 -1
- package/dist/internal/view/api.d.ts +3 -1
- package/dist/internal/view/api.d.ts.map +1 -1
- package/dist/internal/view/api.js +154 -90
- package/dist/internal/view/api.js.map +1 -1
- package/dist/internal/view/error-message.d.ts +3 -0
- package/dist/internal/view/error-message.d.ts.map +1 -0
- package/dist/internal/view/error-message.js +10 -0
- package/dist/internal/view/error-message.js.map +1 -0
- package/dist/internal/view/main.d.ts.map +1 -1
- package/dist/internal/view/main.js +61 -8
- package/dist/internal/view/main.js.map +1 -1
- package/dist/internal/view/page.d.ts.map +1 -1
- package/dist/internal/view/page.js +119 -20
- package/dist/internal/view/page.js.map +1 -1
- package/dist/internal/view/report.d.ts.map +1 -1
- package/dist/internal/view/report.js +180 -145
- package/dist/internal/view/report.js.map +1 -1
- package/dist/internal/view/scope.d.ts +6 -2
- package/dist/internal/view/scope.d.ts.map +1 -1
- package/dist/internal/view/scope.js +107 -24
- package/dist/internal/view/scope.js.map +1 -1
- package/dist/internal/view/sensitivity.d.ts +4 -0
- package/dist/internal/view/sensitivity.d.ts.map +1 -0
- package/dist/internal/view/sensitivity.js +11 -0
- package/dist/internal/view/sensitivity.js.map +1 -0
- package/dist/internal/view/server.d.ts.map +1 -1
- package/dist/internal/view/server.js +57 -20
- package/dist/internal/view/server.js.map +1 -1
- package/dist/src/atomic-output.d.ts +3 -0
- package/dist/src/atomic-output.d.ts.map +1 -0
- package/dist/src/atomic-output.js +67 -0
- package/dist/src/atomic-output.js.map +1 -0
- package/dist/src/cli.d.ts +3 -2
- package/dist/src/cli.d.ts.map +1 -1
- package/dist/src/cli.js +188 -173
- package/dist/src/cli.js.map +1 -1
- package/dist/src/dispatch.d.ts.map +1 -1
- package/dist/src/dispatch.js +3 -2
- package/dist/src/dispatch.js.map +1 -1
- package/dist/src/doctor.d.ts.map +1 -1
- package/dist/src/doctor.js +178 -102
- package/dist/src/doctor.js.map +1 -1
- package/dist/src/error-message.d.ts +3 -0
- package/dist/src/error-message.d.ts.map +1 -0
- package/dist/src/error-message.js +20 -0
- package/dist/src/error-message.js.map +1 -0
- package/dist/src/hooks-config.d.ts +3 -0
- package/dist/src/hooks-config.d.ts.map +1 -0
- package/dist/src/hooks-config.js +23 -0
- package/dist/src/hooks-config.js.map +1 -0
- package/package.json +23 -20
- package/src/atomic-output.ts +47 -0
- package/src/cli.ts +170 -147
- package/src/dispatch.ts +3 -2
- package/src/doctor.ts +192 -111
- package/src/error-message.ts +13 -0
- package/src/hooks-config.ts +22 -0
|
@@ -2,7 +2,10 @@
|
|
|
2
2
|
* `cave connect` entry — argument parsing, pass orchestration (single,
|
|
3
3
|
* `--watch`, `--query`), and report rendering around `run.ts`.
|
|
4
4
|
*/
|
|
5
|
-
import {
|
|
5
|
+
import { rethrowFetchFailure } from "./fetch-failure.js";
|
|
6
|
+
import { errorMessage } from "./error-message.js";
|
|
7
|
+
import { existsSync, watch as watchFs } from 'node:fs';
|
|
8
|
+
import { readText } from "./utf8.js";
|
|
6
9
|
import { basename, dirname, resolve } from 'node:path';
|
|
7
10
|
import { parseArgs } from 'node:util';
|
|
8
11
|
import { Registry } from '@cavelang/canonical';
|
|
@@ -11,7 +14,8 @@ import { Record as QueryRecord, query as caveQuery } from '@cavelang/query';
|
|
|
11
14
|
import * as Declared from "./declared.js";
|
|
12
15
|
import * as Source from "./source.js";
|
|
13
16
|
import * as Template from "./template.js";
|
|
14
|
-
import { connect
|
|
17
|
+
import { connect } from "./run.js";
|
|
18
|
+
import { withFederatedSource } from "./federation.js";
|
|
15
19
|
const usage = `cave connect — deterministic structured ingestion through a mapping template (spec §23)
|
|
16
20
|
|
|
17
21
|
Usage:
|
|
@@ -21,7 +25,7 @@ Usage:
|
|
|
21
25
|
cave connect [--db <path>] --query '<pattern>'
|
|
22
26
|
|
|
23
27
|
The source is a .csv/.tsv/.json/.jsonl/.ndjson file, a SQLite database
|
|
24
|
-
(with --table or --sql), or an http(s) URL serving JSON or
|
|
28
|
+
(with --table or --sql), or an http(s) URL serving JSON, JSONL, CSV or TSV. The
|
|
25
29
|
mapping is an ordinary CAVE document whose ?field variables stand for
|
|
26
30
|
record fields; variable-free blocks append once per run, variable blocks
|
|
27
31
|
instantiate once per record — no LLM in the loop, same input, same claims.
|
|
@@ -83,7 +87,21 @@ Examples:
|
|
|
83
87
|
cave connect https://api.example.com/deps.json --records data.items --map deps.map.cave
|
|
84
88
|
cave connect events.jsonl --map events.map.cave --watch
|
|
85
89
|
cave connect people.csv --map people.map.cave --query '?who WORKS-AT acme'`;
|
|
86
|
-
|
|
90
|
+
/** Abort and fatal callbacks share one owned completion boundary. */
|
|
91
|
+
const watchEnd = (signal) => {
|
|
92
|
+
let failure;
|
|
93
|
+
let wake;
|
|
94
|
+
const done = new Promise(resolve => { wake = resolve; });
|
|
95
|
+
signal?.addEventListener('abort', wake, { once: true });
|
|
96
|
+
if (signal?.aborted)
|
|
97
|
+
wake();
|
|
98
|
+
return {
|
|
99
|
+
fail(error) { failure ??= { error }; wake(); },
|
|
100
|
+
async wait() { await done; if (failure !== undefined)
|
|
101
|
+
throw failure.error; },
|
|
102
|
+
close() { signal?.removeEventListener('abort', wake); }
|
|
103
|
+
};
|
|
104
|
+
};
|
|
87
105
|
const renderReport = (report) => {
|
|
88
106
|
const lines = [
|
|
89
107
|
`connect: ${report.records} record(s): ${report.mapped} mapped, ${report.skipped} skipped (unchanged)` +
|
|
@@ -98,28 +116,35 @@ const renderReport = (report) => {
|
|
|
98
116
|
}
|
|
99
117
|
for (const failure of report.failures) {
|
|
100
118
|
lines.push(` ${failure.record}: FAILED`);
|
|
101
|
-
|
|
119
|
+
for (const problem of failure.problems)
|
|
120
|
+
lines.push(` ${problem}`);
|
|
102
121
|
}
|
|
103
122
|
return lines.join('\n');
|
|
104
123
|
};
|
|
105
124
|
/** `--map` is a template file, or the template itself written inline (spec §23.1). */
|
|
106
125
|
const loadMapping = (spec) => Template.isInline(spec) && !existsSync(spec) ?
|
|
107
126
|
Template.parse(Template.inlineDocument(spec)) :
|
|
108
|
-
Template.parse(
|
|
127
|
+
Template.parse(readText(spec));
|
|
109
128
|
const sourceOptions = (values, context) => ({
|
|
110
129
|
...values.format === undefined ? {} : { format: values.format },
|
|
111
130
|
...values.delimiter === undefined ? {} : { delimiter: values.delimiter },
|
|
112
131
|
...values.table === undefined ? {} : { table: values.table },
|
|
113
132
|
...values.sql === undefined ? {} : { sql: values.sql },
|
|
114
133
|
...values.records === undefined ? {} : { records: values.records },
|
|
134
|
+
...context.signal === undefined ? {} : { signal: context.signal },
|
|
115
135
|
...context.fetchImpl === undefined ? {} : { fetchImpl: context.fetchImpl }
|
|
116
136
|
});
|
|
117
137
|
const loadSource = async (source, values, context) => {
|
|
118
138
|
try {
|
|
119
|
-
|
|
139
|
+
context.signal?.throwIfAborted();
|
|
140
|
+
const loaded = await Source.load(source, sourceOptions(values, context));
|
|
141
|
+
context.signal?.throwIfAborted();
|
|
142
|
+
return loaded;
|
|
120
143
|
}
|
|
121
144
|
catch (error) {
|
|
122
|
-
|
|
145
|
+
if (context.signal?.aborted)
|
|
146
|
+
rethrowFetchFailure(context.signal, error);
|
|
147
|
+
throw new Error(`load ${source}: ${errorMessage(error)}`, { cause: error });
|
|
123
148
|
}
|
|
124
149
|
};
|
|
125
150
|
const runPass = async (store, source, values, name, io, context) => {
|
|
@@ -167,6 +192,25 @@ const runDry = async (source, values, io, context) => {
|
|
|
167
192
|
io.stdout.write(`${sections.join('\n\n')}\n`);
|
|
168
193
|
return failures > 0 ? 1 : 0;
|
|
169
194
|
};
|
|
195
|
+
/** Own the command store until its work settles, preserving cleanup failures. */
|
|
196
|
+
const withCommandStore = async (store, run) => {
|
|
197
|
+
let result;
|
|
198
|
+
try {
|
|
199
|
+
result = await run();
|
|
200
|
+
}
|
|
201
|
+
catch (error) {
|
|
202
|
+
try {
|
|
203
|
+
store.close();
|
|
204
|
+
}
|
|
205
|
+
catch (closeError) {
|
|
206
|
+
const messages = [error, closeError].map(errorMessage);
|
|
207
|
+
throw new AggregateError([error, closeError], `command failed: ${messages[0]}; store close also failed: ${messages[1]}`, { cause: error });
|
|
208
|
+
}
|
|
209
|
+
throw error;
|
|
210
|
+
}
|
|
211
|
+
store.close();
|
|
212
|
+
return result;
|
|
213
|
+
};
|
|
170
214
|
const runQuery = async (source, values, name, io, context) => {
|
|
171
215
|
const { mapping, problems } = loadMapping(values.map);
|
|
172
216
|
if (mapping === undefined) {
|
|
@@ -178,13 +222,16 @@ const runQuery = async (source, values, name, io, context) => {
|
|
|
178
222
|
const registry = values['no-prelude'] === true ? { registry: Registry.empty } : {};
|
|
179
223
|
// Federation over a store that does not exist yet queries the source alone.
|
|
180
224
|
const store = kindOf(db) === 'missing' ? open(':memory:', registry) : openAt(db, { intent: 'scratch', assemble: Declared.assemble, ...registry });
|
|
181
|
-
|
|
182
|
-
const { matches, report } =
|
|
225
|
+
return await withCommandStore(store, () => {
|
|
226
|
+
const { result: { matches, records }, report } = withFederatedSource(store, mapping, loaded.records, {
|
|
183
227
|
name,
|
|
184
228
|
source,
|
|
185
229
|
...loaded.spans === undefined ? {} : { spans: loaded.spans },
|
|
186
230
|
...values.key === undefined ? {} : { key: values.key }
|
|
187
|
-
},
|
|
231
|
+
}, () => {
|
|
232
|
+
const matches = caveQuery(store, values.query, { all: values.all === true, aliases: values.aliases === true });
|
|
233
|
+
return { matches, records: values.json === true ? matches.map(match => QueryRecord.of(store, match)) : undefined };
|
|
234
|
+
});
|
|
188
235
|
// A failed record means the union was incomplete — matches still print
|
|
189
236
|
// as partial results, but the exit code must not read as success.
|
|
190
237
|
const code = report.failures.length > 0 ? 1 : 0;
|
|
@@ -192,7 +239,7 @@ const runQuery = async (source, values, name, io, context) => {
|
|
|
192
239
|
io.stderr.write(`${renderReport(report)}\n`);
|
|
193
240
|
}
|
|
194
241
|
if (values.json === true) {
|
|
195
|
-
io.stdout.write(`${JSON.stringify(
|
|
242
|
+
io.stdout.write(`${JSON.stringify(records, undefined, 2)}\n`);
|
|
196
243
|
return code;
|
|
197
244
|
}
|
|
198
245
|
if (matches.length === 0) {
|
|
@@ -207,18 +254,55 @@ const runQuery = async (source, values, name, io, context) => {
|
|
|
207
254
|
});
|
|
208
255
|
io.stdout.write(`${lines.join('\n')}\n`);
|
|
209
256
|
return code;
|
|
257
|
+
});
|
|
258
|
+
};
|
|
259
|
+
/** Finish every owned watch resource before returning or propagating failures. */
|
|
260
|
+
const watchSession = async (run, stop, watchers, active) => {
|
|
261
|
+
const errors = [];
|
|
262
|
+
let result;
|
|
263
|
+
try {
|
|
264
|
+
result = await run();
|
|
265
|
+
}
|
|
266
|
+
catch (error) {
|
|
267
|
+
errors.push(error);
|
|
268
|
+
}
|
|
269
|
+
try {
|
|
270
|
+
stop();
|
|
271
|
+
}
|
|
272
|
+
catch (error) {
|
|
273
|
+
errors.push(error);
|
|
274
|
+
}
|
|
275
|
+
for (const watcher of watchers()) {
|
|
276
|
+
try {
|
|
277
|
+
watcher.close();
|
|
278
|
+
}
|
|
279
|
+
catch (error) {
|
|
280
|
+
errors.push(error);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
try {
|
|
284
|
+
await active();
|
|
210
285
|
}
|
|
211
|
-
|
|
212
|
-
|
|
286
|
+
catch (error) {
|
|
287
|
+
errors.push(error);
|
|
213
288
|
}
|
|
289
|
+
if (errors.length === 1)
|
|
290
|
+
throw errors[0];
|
|
291
|
+
if (errors.length > 1) {
|
|
292
|
+
throw new AggregateError(errors, `watch session failed: ${errors.map(errorMessage).join('; ')}`, { cause: errors[0] });
|
|
293
|
+
}
|
|
294
|
+
return result;
|
|
214
295
|
};
|
|
215
296
|
const runWatch = async (store, source, values, name, io, context) => {
|
|
297
|
+
let stopped = false;
|
|
298
|
+
const end = watchEnd(io.signal);
|
|
299
|
+
const fail = (error) => { stopped = true; end.fail(error); };
|
|
216
300
|
const passOnce = async () => {
|
|
217
301
|
try {
|
|
218
302
|
await runPass(store, source, values, name, io, context);
|
|
219
303
|
}
|
|
220
304
|
catch (error) {
|
|
221
|
-
io.stderr.write(`cave connect watch pass: ${
|
|
305
|
+
io.stderr.write(`cave connect watch pass: ${errorMessage(error)}\n`);
|
|
222
306
|
}
|
|
223
307
|
};
|
|
224
308
|
let running = false;
|
|
@@ -231,60 +315,84 @@ const runWatch = async (store, source, values, name, io, context) => {
|
|
|
231
315
|
return;
|
|
232
316
|
}
|
|
233
317
|
running = true;
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
318
|
+
try {
|
|
319
|
+
do {
|
|
320
|
+
queued = false;
|
|
321
|
+
await passOnce();
|
|
322
|
+
} while (queued && !stopped && !io.signal?.aborted);
|
|
323
|
+
}
|
|
324
|
+
finally {
|
|
325
|
+
running = false;
|
|
326
|
+
}
|
|
239
327
|
};
|
|
240
328
|
const schedule = context.schedule ?? ((callback, delayMs) => setTimeout(() => { void callback(); }, delayMs));
|
|
241
329
|
const cancelScheduled = context.cancelScheduled ?? (handle => clearTimeout(handle));
|
|
242
330
|
const trigger = () => {
|
|
331
|
+
if (stopped || io.signal?.aborted)
|
|
332
|
+
return;
|
|
243
333
|
if (running) {
|
|
244
334
|
queued = true;
|
|
245
335
|
return;
|
|
246
336
|
}
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
timer =
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
active =
|
|
256
|
-
|
|
337
|
+
try {
|
|
338
|
+
if (timer !== undefined)
|
|
339
|
+
cancelScheduled(timer);
|
|
340
|
+
timer = schedule(async () => {
|
|
341
|
+
timer = undefined;
|
|
342
|
+
if (stopped)
|
|
343
|
+
return;
|
|
344
|
+
const pass = fire();
|
|
345
|
+
active = pass;
|
|
346
|
+
try {
|
|
347
|
+
await pass;
|
|
348
|
+
}
|
|
349
|
+
catch (error) {
|
|
350
|
+
fail(error);
|
|
351
|
+
}
|
|
352
|
+
if (active === pass)
|
|
353
|
+
active = undefined;
|
|
354
|
+
}, 200);
|
|
355
|
+
}
|
|
356
|
+
catch (error) {
|
|
357
|
+
fail(error);
|
|
358
|
+
}
|
|
257
359
|
};
|
|
258
360
|
// Watch the parent directories — editors replace files on save, and a
|
|
259
361
|
// watcher on the file itself dies with the old inode.
|
|
260
362
|
const targets = [...new Set([resolve(source), ...Template.isInline(values.map) && !existsSync(values.map) ? [] : [resolve(values.map)]])];
|
|
261
363
|
const watch = context.watch ?? ((path, listener) => watchFs(path, listener));
|
|
262
|
-
const watchers =
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
364
|
+
const watchers = [];
|
|
365
|
+
return watchSession(async () => {
|
|
366
|
+
for (const target of targets) {
|
|
367
|
+
const subscription = watch(dirname(target), (_event, filename) => {
|
|
368
|
+
// Filename-less events rescan; editors may replace the watched file.
|
|
369
|
+
if (filename === null || filename.toString() === basename(target))
|
|
370
|
+
trigger();
|
|
371
|
+
});
|
|
372
|
+
watchers.push(subscription);
|
|
373
|
+
subscription.on?.('error', error => { if (!stopped)
|
|
374
|
+
fail(error); });
|
|
375
|
+
}
|
|
271
376
|
// Install watchers before the initial pass. A save during startup is
|
|
272
377
|
// therefore either read by this pass or queued for the next one.
|
|
273
|
-
await
|
|
378
|
+
await fire();
|
|
379
|
+
if (stopped || io.signal?.aborted) {
|
|
380
|
+
await end.wait();
|
|
381
|
+
return 0;
|
|
382
|
+
}
|
|
274
383
|
io.stdout.write('watching (ctrl-c to stop)\n');
|
|
275
|
-
await
|
|
384
|
+
await end.wait();
|
|
276
385
|
return 0;
|
|
277
|
-
}
|
|
278
|
-
|
|
386
|
+
}, () => {
|
|
387
|
+
stopped = true;
|
|
388
|
+
end.close();
|
|
279
389
|
if (timer !== undefined)
|
|
280
390
|
cancelScheduled(timer);
|
|
281
|
-
|
|
282
|
-
await active;
|
|
283
|
-
}
|
|
391
|
+
}, () => watchers, () => active);
|
|
284
392
|
};
|
|
285
|
-
const printMatches = (
|
|
286
|
-
if (
|
|
287
|
-
io.stdout.write(`${JSON.stringify(
|
|
393
|
+
const printMatches = (matches, pattern, io, records) => {
|
|
394
|
+
if (records !== undefined) {
|
|
395
|
+
io.stdout.write(`${JSON.stringify(records, undefined, 2)}\n`);
|
|
288
396
|
return;
|
|
289
397
|
}
|
|
290
398
|
if (matches.length === 0) {
|
|
@@ -327,6 +435,7 @@ const declaredPass = async (store, root, values, io, context) => {
|
|
|
327
435
|
new Set(Declared.closure(store, selectDeclared(store, values).map(declared => declared.name)).map(declared => declared.name));
|
|
328
436
|
const version = Declared.versionCounter();
|
|
329
437
|
for (;;) {
|
|
438
|
+
io.signal?.throwIfAborted();
|
|
330
439
|
const next = Declared.declaredSources(store)
|
|
331
440
|
.find(declared => (allowed === undefined || allowed.has(declared.name)) && done.get(declared.name) !== Declared.signature(declared));
|
|
332
441
|
if (next === undefined) {
|
|
@@ -335,7 +444,8 @@ const declaredPass = async (store, root, values, io, context) => {
|
|
|
335
444
|
version(next.name);
|
|
336
445
|
done.set(next.name, Declared.signature(next));
|
|
337
446
|
try {
|
|
338
|
-
const ready = await Declared.prepare(next, dir, context.fetchImpl);
|
|
447
|
+
const ready = await Declared.prepare(next, dir, context.fetchImpl, io.signal);
|
|
448
|
+
io.signal?.throwIfAborted();
|
|
339
449
|
const before = Declared.signatures(Declared.declaredSources(store));
|
|
340
450
|
const report = Declared.run(store, ready, { force: values.force === true, prune: values.prune === true });
|
|
341
451
|
if (allowed !== undefined) {
|
|
@@ -352,7 +462,8 @@ const declaredPass = async (store, root, values, io, context) => {
|
|
|
352
462
|
failed += 1;
|
|
353
463
|
}
|
|
354
464
|
catch (error) {
|
|
355
|
-
io.
|
|
465
|
+
io.signal?.throwIfAborted();
|
|
466
|
+
io.stderr.write(`source/${next.name} (${next.path}): ${errorMessage(error)}\n`);
|
|
356
467
|
failed += 1;
|
|
357
468
|
}
|
|
358
469
|
}
|
|
@@ -360,6 +471,7 @@ const declaredPass = async (store, root, values, io, context) => {
|
|
|
360
471
|
const discoverOptions = (values, context, force = values.force === true) => ({
|
|
361
472
|
...values.name === undefined ? {} : { only: values.name },
|
|
362
473
|
...context.fetchImpl === undefined ? {} : { fetchImpl: context.fetchImpl },
|
|
474
|
+
...context.signal === undefined ? {} : { signal: context.signal },
|
|
363
475
|
force,
|
|
364
476
|
prune: values.prune === true
|
|
365
477
|
});
|
|
@@ -367,7 +479,9 @@ const discoverOptions = (values, context, force = values.force === true) => ({
|
|
|
367
479
|
const declaredDry = async (store, root, values, io, context) => {
|
|
368
480
|
const sections = [];
|
|
369
481
|
let failures = 0;
|
|
370
|
-
|
|
482
|
+
const sequence = await Declared.discover(store, root, discoverOptions(values, context));
|
|
483
|
+
io.signal?.throwIfAborted();
|
|
484
|
+
for (const ready of sequence) {
|
|
371
485
|
sections.push(`; === source/${ready.declared.name} (${ready.declared.path})`);
|
|
372
486
|
if (ready.mapping.prelude !== '') {
|
|
373
487
|
sections.push(`; --- prelude\n\n${ready.mapping.prelude.trimEnd()}`);
|
|
@@ -398,7 +512,9 @@ const declaredQuery = async (store, root, values, io, context) => {
|
|
|
398
512
|
// the declarations since, so the replay checks and rediscovers if so.
|
|
399
513
|
for (let attempt = 0; attempt < Declared.overlayAttempts; attempt += 1) {
|
|
400
514
|
const { sequence, baseline } = await Declared.discovery(store, root, discoverOptions(values, context, true));
|
|
515
|
+
io.signal?.throwIfAborted();
|
|
401
516
|
let matches;
|
|
517
|
+
let records;
|
|
402
518
|
let failed = 0;
|
|
403
519
|
try {
|
|
404
520
|
store.transaction(() => {
|
|
@@ -413,6 +529,8 @@ const declaredQuery = async (store, root, values, io, context) => {
|
|
|
413
529
|
}
|
|
414
530
|
}
|
|
415
531
|
matches = caveQuery(store, values.query, { all: values.all === true, aliases: values.aliases === true });
|
|
532
|
+
if (values.json === true)
|
|
533
|
+
records = matches.map(match => QueryRecord.of(store, match));
|
|
416
534
|
throw rollback;
|
|
417
535
|
});
|
|
418
536
|
}
|
|
@@ -424,21 +542,31 @@ const declaredQuery = async (store, root, values, io, context) => {
|
|
|
424
542
|
throw error;
|
|
425
543
|
}
|
|
426
544
|
}
|
|
427
|
-
printMatches(
|
|
545
|
+
printMatches(matches, values.query, io, records);
|
|
428
546
|
return failed > 0 ? 1 : 0;
|
|
429
547
|
}
|
|
430
548
|
throw Declared.staleOverlay();
|
|
431
549
|
};
|
|
432
550
|
const declaredWatch = async (store, root, values, io, context) => {
|
|
551
|
+
let stopped = false;
|
|
552
|
+
const end = watchEnd(io.signal);
|
|
553
|
+
const fail = (error) => { stopped = true; end.fail(error); };
|
|
433
554
|
const dir = Declared.directoryOf(root);
|
|
434
555
|
const passOnce = async () => {
|
|
435
556
|
try {
|
|
436
557
|
await declaredPass(store, root, values, io, context);
|
|
437
558
|
}
|
|
438
559
|
catch (error) {
|
|
439
|
-
io.stderr.write(`cave connect watch pass: ${
|
|
560
|
+
io.stderr.write(`cave connect watch pass: ${errorMessage(error)}\n`);
|
|
561
|
+
}
|
|
562
|
+
try {
|
|
563
|
+
if (!stopped && !io.signal?.aborted)
|
|
564
|
+
refreshWatchers();
|
|
565
|
+
}
|
|
566
|
+
catch (error) {
|
|
567
|
+
// Keep current subscriptions available to retry on the next save.
|
|
568
|
+
io.stderr.write(`cave connect watch subscriptions: ${errorMessage(error)}\n`);
|
|
440
569
|
}
|
|
441
|
-
refreshWatchers();
|
|
442
570
|
};
|
|
443
571
|
let running = false;
|
|
444
572
|
let queued = false;
|
|
@@ -450,31 +578,49 @@ const declaredWatch = async (store, root, values, io, context) => {
|
|
|
450
578
|
return;
|
|
451
579
|
}
|
|
452
580
|
running = true;
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
581
|
+
try {
|
|
582
|
+
do {
|
|
583
|
+
queued = false;
|
|
584
|
+
await passOnce();
|
|
585
|
+
} while (queued && !stopped && !io.signal?.aborted);
|
|
586
|
+
}
|
|
587
|
+
finally {
|
|
588
|
+
running = false;
|
|
589
|
+
}
|
|
458
590
|
};
|
|
459
591
|
const schedule = context.schedule ?? ((callback, delayMs) => setTimeout(() => { void callback(); }, delayMs));
|
|
460
592
|
const cancelScheduled = context.cancelScheduled ?? (handle => clearTimeout(handle));
|
|
461
593
|
const trigger = () => {
|
|
594
|
+
if (stopped || io.signal?.aborted)
|
|
595
|
+
return;
|
|
462
596
|
if (running) {
|
|
463
597
|
queued = true;
|
|
464
598
|
return;
|
|
465
599
|
}
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
timer =
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
active =
|
|
477
|
-
|
|
600
|
+
try {
|
|
601
|
+
if (timer !== undefined)
|
|
602
|
+
cancelScheduled(timer);
|
|
603
|
+
timer = schedule(async () => {
|
|
604
|
+
timer = undefined;
|
|
605
|
+
if (stopped)
|
|
606
|
+
return;
|
|
607
|
+
// Retained so shutdown waits for a pass in flight (a URL fetch, say)
|
|
608
|
+
// instead of closing the store under it.
|
|
609
|
+
const pass = fire();
|
|
610
|
+
active = pass;
|
|
611
|
+
try {
|
|
612
|
+
await pass;
|
|
613
|
+
}
|
|
614
|
+
catch (error) {
|
|
615
|
+
fail(error);
|
|
616
|
+
}
|
|
617
|
+
if (active === pass)
|
|
618
|
+
active = undefined;
|
|
619
|
+
}, 200);
|
|
620
|
+
}
|
|
621
|
+
catch (error) {
|
|
622
|
+
fail(error);
|
|
623
|
+
}
|
|
478
624
|
};
|
|
479
625
|
// Every local declared file and mapping; URL sources only run on file
|
|
480
626
|
// changes. A followed .cave source may declare more, so the set is
|
|
@@ -492,42 +638,68 @@ const declaredWatch = async (store, root, values, io, context) => {
|
|
|
492
638
|
catch {
|
|
493
639
|
return;
|
|
494
640
|
}
|
|
495
|
-
|
|
641
|
+
const targets = new Set(declared.flatMap(source => [
|
|
496
642
|
...Source.isUrl(source.path) ? [] : [Declared.resolvePath(source.path, dir)],
|
|
497
643
|
// A map is a file when it resolves to one, as the loader decides; only
|
|
498
644
|
// otherwise is it inline and nothing to watch.
|
|
499
645
|
...source.map === undefined || (Template.isInline(source.map) && !existsSync(Declared.resolvePath(source.map, dir))) ?
|
|
500
646
|
[] : [Declared.resolvePath(source.map, dir)]
|
|
501
|
-
]))
|
|
647
|
+
]));
|
|
648
|
+
for (const target of targets) {
|
|
502
649
|
if (watched.has(target))
|
|
503
650
|
continue;
|
|
504
|
-
|
|
651
|
+
let active = true;
|
|
652
|
+
const subscription = watch(dirname(target), (_event, filename) => {
|
|
653
|
+
if (!active)
|
|
654
|
+
return;
|
|
505
655
|
if (filename === null || filename.toString() === basename(target)) {
|
|
506
656
|
trigger();
|
|
507
657
|
}
|
|
508
|
-
})
|
|
658
|
+
});
|
|
659
|
+
watched.set(target, { close: () => { active = false; subscription.close(); } });
|
|
660
|
+
subscription.on?.('error', error => { if (active && !stopped)
|
|
661
|
+
fail(error); });
|
|
662
|
+
}
|
|
663
|
+
const errors = [];
|
|
664
|
+
for (const [target, subscription] of watched) {
|
|
665
|
+
if (targets.has(target))
|
|
666
|
+
continue;
|
|
667
|
+
// Retire ownership before closing: a failed close must not suppress a
|
|
668
|
+
// fresh subscription if this path is declared again on a later pass.
|
|
669
|
+
watched.delete(target);
|
|
670
|
+
try {
|
|
671
|
+
subscription.close();
|
|
672
|
+
}
|
|
673
|
+
catch (error) {
|
|
674
|
+
errors.push(error);
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
if (errors.length === 1)
|
|
678
|
+
throw errors[0];
|
|
679
|
+
if (errors.length > 1) {
|
|
680
|
+
throw new AggregateError(errors, `retiring watch subscriptions failed: ${errors.map(errorMessage).join('; ')}`, { cause: errors[0] });
|
|
509
681
|
}
|
|
510
682
|
};
|
|
511
|
-
|
|
512
|
-
if (watched.size === 0) {
|
|
513
|
-
io.stderr.write('cave connect: nothing to watch — no declared local source\n');
|
|
514
|
-
return 1;
|
|
515
|
-
}
|
|
516
|
-
try {
|
|
517
|
-
await passOnce();
|
|
683
|
+
return watchSession(async () => {
|
|
518
684
|
refreshWatchers();
|
|
685
|
+
if (watched.size === 0) {
|
|
686
|
+
io.stderr.write('cave connect: nothing to watch — no declared local source\n');
|
|
687
|
+
return 1;
|
|
688
|
+
}
|
|
689
|
+
await fire();
|
|
690
|
+
if (stopped || io.signal?.aborted) {
|
|
691
|
+
await end.wait();
|
|
692
|
+
return 0;
|
|
693
|
+
}
|
|
519
694
|
io.stdout.write('watching (ctrl-c to stop)\n');
|
|
520
|
-
await
|
|
695
|
+
await end.wait();
|
|
521
696
|
return 0;
|
|
522
|
-
}
|
|
523
|
-
|
|
697
|
+
}, () => {
|
|
698
|
+
stopped = true;
|
|
699
|
+
end.close();
|
|
524
700
|
if (timer !== undefined)
|
|
525
701
|
cancelScheduled(timer);
|
|
526
|
-
|
|
527
|
-
watcher.close();
|
|
528
|
-
if (active !== undefined)
|
|
529
|
-
await active;
|
|
530
|
-
}
|
|
702
|
+
}, () => watched.values(), () => active);
|
|
531
703
|
};
|
|
532
704
|
/**
|
|
533
705
|
* `cave connect` without a source (spec §23.4): the store's declared
|
|
@@ -547,49 +719,54 @@ const runDeclared = async (values, io, context) => {
|
|
|
547
719
|
try {
|
|
548
720
|
if (values.list === true) {
|
|
549
721
|
const store = openAt(db, { intent: 'read', assemble: Declared.assemble, ...registryOf(values) });
|
|
550
|
-
|
|
722
|
+
return await withCommandStore(store, () => {
|
|
551
723
|
const declared = selectDeclared(store, values);
|
|
552
724
|
io.stdout.write(declared.length === 0 ? 'no declared sources\n' : `${declared.map(Declared.describe).join('\n')}\n`);
|
|
553
725
|
return 0;
|
|
554
|
-
}
|
|
555
|
-
finally {
|
|
556
|
-
store.close();
|
|
557
|
-
}
|
|
726
|
+
});
|
|
558
727
|
}
|
|
559
728
|
if (values['dry-run'] === true || values.query !== undefined) {
|
|
560
729
|
// Discovery works on a private snapshot, so the dry run only reads;
|
|
561
730
|
// the overlay appends into the store's own rolled-back transaction.
|
|
562
731
|
const store = openAt(db, { intent: values.query === undefined ? 'read' : 'scratch', assemble: Declared.assemble, ...registryOf(values) });
|
|
563
|
-
|
|
732
|
+
return await withCommandStore(store, async () => {
|
|
564
733
|
return values.query === undefined ?
|
|
565
734
|
await declaredDry(store, db, values, io, context) :
|
|
566
735
|
await declaredQuery(store, db, values, io, context);
|
|
567
|
-
}
|
|
568
|
-
finally {
|
|
569
|
-
store.close();
|
|
570
|
-
}
|
|
736
|
+
});
|
|
571
737
|
}
|
|
572
738
|
const store = openAt(db, { intent: 'write', ...registryOf(values) });
|
|
573
|
-
|
|
739
|
+
return await withCommandStore(store, async () => {
|
|
574
740
|
return values.watch === true ?
|
|
575
741
|
await declaredWatch(store, db, values, io, context) :
|
|
576
742
|
await declaredPass(store, db, values, io, context);
|
|
577
|
-
}
|
|
578
|
-
finally {
|
|
579
|
-
store.close();
|
|
580
|
-
}
|
|
743
|
+
});
|
|
581
744
|
}
|
|
582
745
|
catch (error) {
|
|
583
|
-
io.stderr.write(`cave connect: ${
|
|
746
|
+
io.stderr.write(`cave connect: ${errorMessage(error)}\n`);
|
|
584
747
|
return error instanceof LocateError ? 1 : 1;
|
|
585
748
|
}
|
|
586
749
|
};
|
|
587
750
|
export const runConnect = async (argv, context = {}) => {
|
|
751
|
+
const signal = context.signal;
|
|
752
|
+
if (signal?.aborted === true)
|
|
753
|
+
return 0;
|
|
754
|
+
context = {
|
|
755
|
+
signal,
|
|
756
|
+
stdout: context.stdout,
|
|
757
|
+
stderr: context.stderr,
|
|
758
|
+
fetchImpl: context.fetchImpl,
|
|
759
|
+
watch: context.watch,
|
|
760
|
+
schedule: context.schedule,
|
|
761
|
+
cancelScheduled: context.cancelScheduled
|
|
762
|
+
};
|
|
588
763
|
const io = {
|
|
589
764
|
stdout: context.stdout ?? process.stdout,
|
|
590
765
|
stderr: context.stderr ?? process.stderr,
|
|
591
|
-
...
|
|
766
|
+
...signal === undefined ? {} : { signal }
|
|
592
767
|
};
|
|
768
|
+
if (Boolean(io.signal?.aborted))
|
|
769
|
+
return 0;
|
|
593
770
|
const { values, positionals } = parseArgs({
|
|
594
771
|
args: [...argv],
|
|
595
772
|
options: {
|
|
@@ -660,18 +837,15 @@ export const runConnect = async (argv, context = {}) => {
|
|
|
660
837
|
intent: 'write',
|
|
661
838
|
...values['no-prelude'] === true ? { registry: Registry.empty } : {}
|
|
662
839
|
});
|
|
663
|
-
|
|
840
|
+
return await withCommandStore(store, async () => {
|
|
664
841
|
if (values.watch === true) {
|
|
665
842
|
return await runWatch(store, source, values, name, io, context);
|
|
666
843
|
}
|
|
667
844
|
return await runPass(store, source, values, name, io, context);
|
|
668
|
-
}
|
|
669
|
-
finally {
|
|
670
|
-
store.close();
|
|
671
|
-
}
|
|
845
|
+
});
|
|
672
846
|
}
|
|
673
847
|
catch (error) {
|
|
674
|
-
io.stderr.write(`cave connect: ${
|
|
848
|
+
io.stderr.write(`cave connect: ${errorMessage(error)}\n`);
|
|
675
849
|
return 1;
|
|
676
850
|
}
|
|
677
851
|
};
|