@tikoci/centrs 0.1.4 → 0.1.6
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/CHANGELOG.md +309 -0
- package/GLOSSARY.txt +40 -1
- package/README.md +8 -4
- package/commands/AGENTS.md +7 -4
- package/commands/api/AGENTS.md +13 -1
- package/commands/api/README.md +37 -8
- package/commands/api/examples.md +31 -1
- package/commands/execute/README.md +39 -10
- package/commands/execute/examples.md +79 -7
- package/commands/explain/README.md +1195 -155
- package/commands/explain/examples.md +99 -3
- package/commands/mcp/README.md +7 -4
- package/commands/mcp/examples.md +2 -2
- package/commands/terminal/examples.md +7 -1
- package/docs/CLI.md +2 -2
- package/docs/CONSTITUTION.md +72 -15
- package/docs/MATRIX.md +89 -52
- package/docs/errors/validation/syntax.md +29 -4
- package/package.json +13 -2
- package/src/api-fanout.ts +17 -4
- package/src/api.ts +254 -67
- package/src/cli/api.ts +1 -1
- package/src/cli/btest.ts +1 -1
- package/src/cli/explain.ts +1 -1
- package/src/cli/terminal.ts +1 -1
- package/src/core/envelope.ts +53 -0
- package/src/core/error-catalog.ts +2 -1
- package/src/core/execute-command.ts +148 -0
- package/src/core/inspect.ts +36 -4
- package/src/core/version.ts +4 -0
- package/src/core/yaml.ts +86 -0
- package/src/execute-fanout.ts +18 -4
- package/src/execute.ts +225 -244
- package/src/explain/arg-tokens.ts +62 -25
- package/src/explain/args.ts +398 -52
- package/src/explain/blocks.ts +54 -11
- package/src/explain/brace-tokens.ts +4 -3
- package/src/explain/catalog.ts +42 -44
- package/src/explain/coordinates.ts +159 -0
- package/src/explain/defects.ts +2 -1
- package/src/explain/escape-tokens.ts +77 -0
- package/src/explain/highlight-projection.ts +308 -0
- package/src/explain/menus.ts +9 -5
- package/src/explain/operator-tokens.ts +13 -7
- package/src/explain/operators.ts +27 -20
- package/src/explain/path-tokens.ts +1 -1
- package/src/explain/pathresolve.ts +358 -113
- package/src/explain/quoted-string.ts +110 -20
- package/src/explain/scope-brace.ts +175 -22
- package/src/explain/segment.ts +429 -21
- package/src/explain/separator.ts +187 -0
- package/src/explain/split-owner.ts +194 -0
- package/src/explain/string-tokens.ts +14 -4
- package/src/explain/symbol-values.ts +209 -173
- package/src/explain/symbols.ts +21 -1
- package/src/explain/transport.ts +17 -0
- package/src/explain/value-tokens.ts +15 -12
- package/src/explain/verbsplit.ts +165 -23
- package/src/explain/write.ts +47 -6
- package/src/explain.ts +522 -72
- package/src/index.ts +19 -2
- package/src/mcp/server.ts +2 -1
- package/src/offline-gate.ts +148 -0
- package/src/retrieve-fanout.ts +1 -1
- package/src/retrieve.ts +1 -59
- package/src/settings.ts +2 -1
- package/src/transfer-fanout.ts +1 -1
- package/src/transfer.ts +1 -1
package/src/index.ts
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
export const centrsVersion = "0.1.0";
|
|
2
|
-
|
|
3
1
|
export {
|
|
4
2
|
type ApiEnvelope,
|
|
5
3
|
type ApiErrorEnvelope,
|
|
@@ -81,6 +79,7 @@ export {
|
|
|
81
79
|
type EnvelopeMeta,
|
|
82
80
|
type EnvelopeTargetMeta,
|
|
83
81
|
type EnvelopeValidationMeta,
|
|
82
|
+
type EnvelopeValidationStage,
|
|
84
83
|
type FanoutData,
|
|
85
84
|
type FanoutSummary,
|
|
86
85
|
normalizeWarnings,
|
|
@@ -110,6 +109,7 @@ export {
|
|
|
110
109
|
type InspectChildItem,
|
|
111
110
|
type InspectCompletionItem,
|
|
112
111
|
type InspectRequestKind,
|
|
112
|
+
inspectArgumentNames,
|
|
113
113
|
inspectChildren,
|
|
114
114
|
inspectChildrenOrEmpty,
|
|
115
115
|
inspectCompletions,
|
|
@@ -136,6 +136,7 @@ export {
|
|
|
136
136
|
versionFactFromComment,
|
|
137
137
|
versionInRange,
|
|
138
138
|
} from "./core/preflight.ts";
|
|
139
|
+
export { centrsVersion } from "./core/version.ts";
|
|
139
140
|
export {
|
|
140
141
|
encodeMndpPacket,
|
|
141
142
|
MNDP_BROADCAST_ADDRESS,
|
|
@@ -305,13 +306,20 @@ export {
|
|
|
305
306
|
// relative to the statement it was handed; the `Token` is that rebased into
|
|
306
307
|
// document space by `explainCommand`. A consumer reading `explainCommand`'s
|
|
307
308
|
// result wants the latter.
|
|
309
|
+
//
|
|
310
|
+
// `lexExplainArgumentTokens` is the skip-tolerant reading (#316) and is
|
|
311
|
+
// exported for the same reason `lexExplainValueAnchors` is: a consumer building
|
|
312
|
+
// its own token-level rule needs the reading a rule wants, not the one a
|
|
313
|
+
// renderer wants. Its `undecided` tokens carry no `value` and never become one.
|
|
308
314
|
export {
|
|
309
315
|
type Argument as ExplainArgument,
|
|
310
316
|
type ArgumentKind as ExplainArgumentKind,
|
|
311
317
|
type ArgumentReading as ExplainArgumentReading,
|
|
312
318
|
type ArgumentsRead as ExplainArgumentsRead,
|
|
313
319
|
type ArgumentsUnread as ExplainArgumentsUnread,
|
|
320
|
+
type ArgumentTokenReading as ExplainArgumentTokenReading,
|
|
314
321
|
lexArguments as lexExplainArguments,
|
|
322
|
+
lexArgumentTokens as lexExplainArgumentTokens,
|
|
315
323
|
lexValueAnchors as lexExplainValueAnchors,
|
|
316
324
|
type ValueAnchor as ExplainValueAnchor,
|
|
317
325
|
type ValueAnchorKind as ExplainValueAnchorKind,
|
|
@@ -478,6 +486,14 @@ export {
|
|
|
478
486
|
explainOutputFormats,
|
|
479
487
|
renderExplainEnvelope,
|
|
480
488
|
} from "./explain.ts";
|
|
489
|
+
export {
|
|
490
|
+
assertOfflineSyntax,
|
|
491
|
+
isOfflineGateRejection,
|
|
492
|
+
OFFLINE_GATE_SOURCE,
|
|
493
|
+
type OfflineGateFinding,
|
|
494
|
+
type OfflineGateResult,
|
|
495
|
+
type ValidationStageName,
|
|
496
|
+
} from "./offline-gate.ts";
|
|
481
497
|
export {
|
|
482
498
|
type ApiVerb,
|
|
483
499
|
createProtocolAdapter,
|
|
@@ -672,6 +688,7 @@ export {
|
|
|
672
688
|
transferFanout,
|
|
673
689
|
} from "./transfer-fanout.ts";
|
|
674
690
|
|
|
691
|
+
import { centrsVersion } from "./core/version.ts";
|
|
675
692
|
import { plannedProtocols, type RouterOsProtocol } from "./protocols/index.ts";
|
|
676
693
|
|
|
677
694
|
export const plannedSurfaces = ["api", "cli", "tui", "mcp", "proxy"] as const;
|
package/src/mcp/server.ts
CHANGED
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
11
11
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
12
12
|
import type { Transport } from "@modelcontextprotocol/sdk/shared/transport.js";
|
|
13
|
+
import { centrsVersion } from "../core/version.ts";
|
|
13
14
|
import { type CentrsMcpConfig, resolveMcpConfig } from "./config.ts";
|
|
14
15
|
import {
|
|
15
16
|
buildDevicesResource,
|
|
@@ -79,7 +80,7 @@ export function createCentrsMcpServer(
|
|
|
79
80
|
config: CentrsMcpConfig = resolveMcpConfig(),
|
|
80
81
|
): McpServer {
|
|
81
82
|
const server = new McpServer(
|
|
82
|
-
{ name: "centrs-mcp", version:
|
|
83
|
+
{ name: "centrs-mcp", version: centrsVersion },
|
|
83
84
|
{ instructions: SERVER_INSTRUCTIONS },
|
|
84
85
|
);
|
|
85
86
|
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stage 1 of the validation gate: the offline analyzer in front of the device
|
|
3
|
+
* preflight (GH#354).
|
|
4
|
+
*
|
|
5
|
+
* centrs used to run two validators that did not know about each other — the
|
|
6
|
+
* device preflight (`:put [:parse …]` plus `/console/inspect request=child`)
|
|
7
|
+
* that `execute` / `api` / `validate` share, and offline `explain`, which is
|
|
8
|
+
* byte-accurate and corpus-gated but took no part in validation at all. This
|
|
9
|
+
* module is the seam that joins them: every CLI-shaped input is analyzed here
|
|
10
|
+
* first, with no connection, and only then handed to the device stage.
|
|
11
|
+
*
|
|
12
|
+
* Three things that buys, in the order they matter:
|
|
13
|
+
*
|
|
14
|
+
* 1. A syntax fault is rejected with a **byte span** and **no round trip** — the
|
|
15
|
+
* protocol adapter is never even constructed.
|
|
16
|
+
* 2. The device stage narrows to the semantic half it is actually needed for
|
|
17
|
+
* (`:parse` is name-level only; `/console/inspect` owns the attribute set).
|
|
18
|
+
* 3. Where the device probe is unsafe or unavailable — the 7.12.2 class of
|
|
19
|
+
* problem in GH#343 — the gate degrades to a real gate instead of to nothing.
|
|
20
|
+
*
|
|
21
|
+
* **A clean offline pass is necessary, never sufficient.** `explain` publishes
|
|
22
|
+
* `runtimeAcceptance: "not-proven"` for a reason: `/console/inspect` accepts
|
|
23
|
+
* forms the runtime rejects, and the analyzer has no per-menu schema (decision 3
|
|
24
|
+
* — no offline schema snapshot). The device stage is not optional and this
|
|
25
|
+
* module never reports success on its behalf. `verdict: "warn"` is an
|
|
26
|
+
* ABSTENTION, not a rejection, and passes through for the same reason.
|
|
27
|
+
*
|
|
28
|
+
* `--validate=false` disables BOTH stages — one flag, one meaning. That was
|
|
29
|
+
* settled with the `--raw` precedence layer on GH#154 and is why callers gate
|
|
30
|
+
* this on the same resolved `validate` setting as the device stage; the escape
|
|
31
|
+
* hatch has to cover a stage-1 defect too (GH#355 is a live example of the
|
|
32
|
+
* analyzer being wrong in the other direction).
|
|
33
|
+
*
|
|
34
|
+
* The offending byte range rides `context.span`, never {@link CentrsError}'s
|
|
35
|
+
* `position`. `RouterOsErrorPosition` is documented as RouterOS's own
|
|
36
|
+
* authoritative 1-based byte column, "carried verbatim; never re-derived"
|
|
37
|
+
* (`errors.ts`) — synthesizing one from offline analysis would make a
|
|
38
|
+
* centrs-derived offset indistinguishable from a device-reported one.
|
|
39
|
+
*/
|
|
40
|
+
|
|
41
|
+
import { CentrsError } from "./errors.ts";
|
|
42
|
+
import { type ExplainDiagnostic, explainCommand } from "./explain.ts";
|
|
43
|
+
|
|
44
|
+
/** Validator identity for `meta.validation` and error context. */
|
|
45
|
+
export const OFFLINE_GATE_SOURCE = "offline explain (canonicalizer)";
|
|
46
|
+
|
|
47
|
+
/** Which stage of the two-stage gate produced a verdict. */
|
|
48
|
+
export type ValidationStageName = "offline" | "device";
|
|
49
|
+
|
|
50
|
+
/** One rejected span, flattened out of {@link ExplainDiagnostic} for the error context. */
|
|
51
|
+
export interface OfflineGateFinding {
|
|
52
|
+
/** The `explain/<analyzer>/<slug>` diagnostic code. */
|
|
53
|
+
code: string;
|
|
54
|
+
message: string;
|
|
55
|
+
/** Byte offsets into the analyzed input, end-exclusive. */
|
|
56
|
+
start: number;
|
|
57
|
+
end: number;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/** Outcome of a stage-1 run that did not reject. */
|
|
61
|
+
export interface OfflineGateResult {
|
|
62
|
+
/**
|
|
63
|
+
* `pass` — the analyzer read the whole input. `warn` — it ABSTAINED on part
|
|
64
|
+
* of it (an unresolved menu, say). Both proceed to the device stage; only
|
|
65
|
+
* `fail` throws.
|
|
66
|
+
*/
|
|
67
|
+
verdict: "pass" | "warn";
|
|
68
|
+
/** Warning-severity diagnostics, kept so a caller can surface the abstention. */
|
|
69
|
+
warnings: readonly OfflineGateFinding[];
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function findingOf(diagnostic: ExplainDiagnostic): OfflineGateFinding {
|
|
73
|
+
return {
|
|
74
|
+
code: diagnostic.code,
|
|
75
|
+
message: diagnostic.message,
|
|
76
|
+
start: diagnostic.span.start,
|
|
77
|
+
end: diagnostic.span.end,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Run the offline stage over a RouterOS CLI string.
|
|
83
|
+
*
|
|
84
|
+
* Throws `validation/syntax` when the analyzer rejects the input; returns the
|
|
85
|
+
* verdict otherwise. Never opens a connection and never throws for any other
|
|
86
|
+
* reason — `explainCommand` itself is documented as total.
|
|
87
|
+
*
|
|
88
|
+
* `surface` names the caller in the error context (`execute`, `api /execute`) so
|
|
89
|
+
* a reader can tell which command's gate spoke; `via` is the resolved protocol
|
|
90
|
+
* when the caller has one, purely for context.
|
|
91
|
+
*/
|
|
92
|
+
export function assertOfflineSyntax(
|
|
93
|
+
command: string,
|
|
94
|
+
options: { surface: string; via?: string },
|
|
95
|
+
): OfflineGateResult {
|
|
96
|
+
const analysis = explainCommand(command);
|
|
97
|
+
const errors = analysis.diagnostics.filter(
|
|
98
|
+
(diagnostic) => diagnostic.severity === "error",
|
|
99
|
+
);
|
|
100
|
+
const warnings = analysis.diagnostics
|
|
101
|
+
.filter((diagnostic) => diagnostic.severity === "warning")
|
|
102
|
+
.map(findingOf);
|
|
103
|
+
|
|
104
|
+
if (analysis.verdict !== "fail") {
|
|
105
|
+
return { verdict: analysis.verdict === "warn" ? "warn" : "pass", warnings };
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// A `fail` verdict always carries at least one error diagnostic, but read it
|
|
109
|
+
// defensively: an empty list would otherwise produce an error that says
|
|
110
|
+
// nothing about what was wrong, which is worse than a generic summary.
|
|
111
|
+
const findings = errors.map(findingOf);
|
|
112
|
+
const first = findings[0];
|
|
113
|
+
throw new CentrsError({
|
|
114
|
+
code: "validation/syntax",
|
|
115
|
+
summary: first
|
|
116
|
+
? `RouterOS syntax rejected by offline analysis: ${first.message}`
|
|
117
|
+
: "RouterOS syntax rejected by offline analysis.",
|
|
118
|
+
remediation:
|
|
119
|
+
"Run `centrs explain '<command>'` to see the offending bytes in context, " +
|
|
120
|
+
"fix the syntax, then retry. `--validate=false` bypasses both validation " +
|
|
121
|
+
"stages if you are deliberately probing a RouterOS edge centrs reads wrong.",
|
|
122
|
+
context: {
|
|
123
|
+
command,
|
|
124
|
+
validationStage: "offline" satisfies ValidationStageName,
|
|
125
|
+
validationSource: OFFLINE_GATE_SOURCE,
|
|
126
|
+
surface: options.surface,
|
|
127
|
+
...(options.via ? { via: options.via } : {}),
|
|
128
|
+
...(first ? { span: { start: first.start, end: first.end } } : {}),
|
|
129
|
+
diagnostics: findings,
|
|
130
|
+
},
|
|
131
|
+
causeData: first?.code ?? "offline analysis rejected the input",
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* True when `error` is the rejection {@link assertOfflineSyntax} throws.
|
|
137
|
+
*
|
|
138
|
+
* Callers use this to build honest envelope metadata: on a stage-1 rejection the
|
|
139
|
+
* device stage did not run, and no connection was opened, so the meta must not
|
|
140
|
+
* claim `:parse` or `/console/inspect` failed.
|
|
141
|
+
*/
|
|
142
|
+
export function isOfflineGateRejection(error: unknown): boolean {
|
|
143
|
+
return (
|
|
144
|
+
error instanceof CentrsError &&
|
|
145
|
+
error.code === "validation/syntax" &&
|
|
146
|
+
(error.context?.["validationStage"] as string | undefined) === "offline"
|
|
147
|
+
);
|
|
148
|
+
}
|
package/src/retrieve-fanout.ts
CHANGED
|
@@ -46,6 +46,7 @@ import {
|
|
|
46
46
|
runFanout,
|
|
47
47
|
summarizeFanout,
|
|
48
48
|
} from "./core/fanout.ts";
|
|
49
|
+
import { toYaml } from "./core/yaml.ts";
|
|
49
50
|
import { CentrsError, serializeCentrsError } from "./errors.ts";
|
|
50
51
|
import { plannedProtocols, type RouterOsProtocol } from "./protocols/index.ts";
|
|
51
52
|
import {
|
|
@@ -71,7 +72,6 @@ import {
|
|
|
71
72
|
resolveRetrieveGlobalContext,
|
|
72
73
|
resolveRetrieveRequest,
|
|
73
74
|
runResolvedRetrieve,
|
|
74
|
-
toYaml,
|
|
75
75
|
validateRetrieveRequestShape,
|
|
76
76
|
} from "./retrieve.ts";
|
|
77
77
|
|
package/src/retrieve.ts
CHANGED
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
isCommandNode,
|
|
16
16
|
pathTokens,
|
|
17
17
|
} from "./core/inspect.ts";
|
|
18
|
+
import { toYaml } from "./core/yaml.ts";
|
|
18
19
|
import { CentrsError, serializeCentrsError } from "./errors.ts";
|
|
19
20
|
import {
|
|
20
21
|
createProtocolAdapter,
|
|
@@ -1192,62 +1193,3 @@ function exhaustiveOutputFormat(value: never): never {
|
|
|
1192
1193
|
function isPlainObject(value: unknown): value is Record<string, unknown> {
|
|
1193
1194
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1194
1195
|
}
|
|
1195
|
-
|
|
1196
|
-
export function toYaml(value: unknown, indent = 0): string {
|
|
1197
|
-
const prefix = " ".repeat(indent);
|
|
1198
|
-
if (value === null || value === undefined) {
|
|
1199
|
-
return "null";
|
|
1200
|
-
}
|
|
1201
|
-
if (typeof value === "string") {
|
|
1202
|
-
return yamlScalar(value);
|
|
1203
|
-
}
|
|
1204
|
-
if (typeof value === "number" || typeof value === "boolean") {
|
|
1205
|
-
return String(value);
|
|
1206
|
-
}
|
|
1207
|
-
if (Array.isArray(value)) {
|
|
1208
|
-
if (value.length === 0) {
|
|
1209
|
-
return `${prefix}[]`;
|
|
1210
|
-
}
|
|
1211
|
-
return value
|
|
1212
|
-
.map((item) => {
|
|
1213
|
-
if (isScalar(item)) {
|
|
1214
|
-
return `${prefix}- ${toYaml(item, indent + 2)}`;
|
|
1215
|
-
}
|
|
1216
|
-
return `${prefix}-\n${toYaml(item, indent + 2)}`;
|
|
1217
|
-
})
|
|
1218
|
-
.join("\n");
|
|
1219
|
-
}
|
|
1220
|
-
if (isPlainObject(value)) {
|
|
1221
|
-
const entries = Object.entries(value).filter(
|
|
1222
|
-
([, entryValue]) => entryValue !== undefined,
|
|
1223
|
-
);
|
|
1224
|
-
if (entries.length === 0) {
|
|
1225
|
-
return `${prefix}{}`;
|
|
1226
|
-
}
|
|
1227
|
-
return entries
|
|
1228
|
-
.map(([key, entryValue]) => {
|
|
1229
|
-
if (isScalar(entryValue)) {
|
|
1230
|
-
return `${prefix}${key}: ${toYaml(entryValue, indent + 2)}`;
|
|
1231
|
-
}
|
|
1232
|
-
return `${prefix}${key}:\n${toYaml(entryValue, indent + 2)}`;
|
|
1233
|
-
})
|
|
1234
|
-
.join("\n");
|
|
1235
|
-
}
|
|
1236
|
-
return yamlScalar(JSON.stringify(value));
|
|
1237
|
-
}
|
|
1238
|
-
|
|
1239
|
-
function isScalar(value: unknown): value is boolean | number | string | null {
|
|
1240
|
-
return (
|
|
1241
|
-
value === null ||
|
|
1242
|
-
typeof value === "string" ||
|
|
1243
|
-
typeof value === "number" ||
|
|
1244
|
-
typeof value === "boolean"
|
|
1245
|
-
);
|
|
1246
|
-
}
|
|
1247
|
-
|
|
1248
|
-
function yamlScalar(value: string): string {
|
|
1249
|
-
if (value.length === 0) {
|
|
1250
|
-
return '""';
|
|
1251
|
-
}
|
|
1252
|
-
return JSON.stringify(value);
|
|
1253
|
-
}
|
package/src/settings.ts
CHANGED
|
@@ -24,6 +24,7 @@ import type {
|
|
|
24
24
|
Warning,
|
|
25
25
|
} from "./core/envelope.ts";
|
|
26
26
|
import { buildTip } from "./core/envelope.ts";
|
|
27
|
+
import { toYaml } from "./core/yaml.ts";
|
|
27
28
|
import { loadCdb, resolveDevicesSettings } from "./devices.ts";
|
|
28
29
|
import { CentrsError, serializeCentrsError } from "./errors.ts";
|
|
29
30
|
import { plannedProtocols, type RouterOsProtocol } from "./protocols/index.ts";
|
|
@@ -37,7 +38,7 @@ import {
|
|
|
37
38
|
readSettingsFileRaw,
|
|
38
39
|
resolveOptionalIntegerSetting,
|
|
39
40
|
} from "./resolver/index.ts";
|
|
40
|
-
import { retrieveOutputFormats
|
|
41
|
+
import { retrieveOutputFormats } from "./retrieve.ts";
|
|
41
42
|
|
|
42
43
|
// ── Envelope shape ───────────────────────────────────────────────────────────
|
|
43
44
|
|
package/src/transfer-fanout.ts
CHANGED
|
@@ -38,6 +38,7 @@ import {
|
|
|
38
38
|
runFanout,
|
|
39
39
|
summarizeFanout,
|
|
40
40
|
} from "./core/fanout.ts";
|
|
41
|
+
import { toYaml } from "./core/yaml.ts";
|
|
41
42
|
import { CentrsError, serializeCentrsError } from "./errors.ts";
|
|
42
43
|
import { promptForWriteConfirmation } from "./execute.ts";
|
|
43
44
|
import { plannedProtocols, type RouterOsProtocol } from "./protocols/index.ts";
|
|
@@ -50,7 +51,6 @@ import {
|
|
|
50
51
|
type SelectionResolveInput,
|
|
51
52
|
type TargetSelection,
|
|
52
53
|
} from "./resolver/index.ts";
|
|
53
|
-
import { toYaml } from "./retrieve.ts";
|
|
54
54
|
import {
|
|
55
55
|
buildTransferErrorEnvelope,
|
|
56
56
|
isTransferWriteVerb,
|
package/src/transfer.ts
CHANGED
|
@@ -29,6 +29,7 @@ import type {
|
|
|
29
29
|
EnvelopeValidationMeta,
|
|
30
30
|
Warning,
|
|
31
31
|
} from "./core/envelope.ts";
|
|
32
|
+
import { toYaml } from "./core/yaml.ts";
|
|
32
33
|
import { CentrsError, serializeCentrsError } from "./errors.ts";
|
|
33
34
|
import {
|
|
34
35
|
createProtocolAdapter,
|
|
@@ -54,7 +55,6 @@ import {
|
|
|
54
55
|
resolveTarget,
|
|
55
56
|
toCoreSource,
|
|
56
57
|
} from "./resolver/index.ts";
|
|
57
|
-
import { toYaml } from "./retrieve.ts";
|
|
58
58
|
|
|
59
59
|
export const transferOutputFormats = ["text", "json", "yaml"] as const;
|
|
60
60
|
export type TransferOutputFormat = (typeof transferOutputFormats)[number];
|