@poe-platform/safe-bash 0.1.508 → 0.1.509

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 (45) hide show
  1. package/dist/safe-bash/chunks/chunk-4OKU6JXB.js +5279 -0
  2. package/dist/safe-bash/chunks/chunk-4OKU6JXB.js.map +7 -0
  3. package/dist/safe-bash/chunks/chunk-5HT35GTV.js +520 -0
  4. package/dist/safe-bash/chunks/chunk-5HT35GTV.js.map +7 -0
  5. package/dist/safe-bash/chunks/{chunk-3ISDVRIM.js → chunk-B637PJBS.js} +19 -523
  6. package/dist/safe-bash/chunks/chunk-B637PJBS.js.map +7 -0
  7. package/dist/safe-bash/commands/structured/query-core.d.ts +35 -0
  8. package/dist/safe-bash/commands/structured/query-core.d.ts.map +1 -0
  9. package/dist/safe-bash/commands/structured/query-core.js +588 -0
  10. package/dist/safe-bash/commands/structured/query-core.js.map +1 -0
  11. package/dist/safe-bash/commands/xml/index.browser.js +2 -1
  12. package/dist/safe-bash/commands/yq/accounting.d.ts +64 -0
  13. package/dist/safe-bash/commands/yq/accounting.d.ts.map +1 -0
  14. package/dist/safe-bash/commands/yq/accounting.js +257 -0
  15. package/dist/safe-bash/commands/yq/accounting.js.map +1 -0
  16. package/dist/safe-bash/commands/yq/encoder.d.ts +6 -0
  17. package/dist/safe-bash/commands/yq/encoder.d.ts.map +1 -0
  18. package/dist/safe-bash/commands/yq/encoder.js +240 -0
  19. package/dist/safe-bash/commands/yq/encoder.js.map +1 -0
  20. package/dist/safe-bash/commands/yq/errors.d.ts +15 -0
  21. package/dist/safe-bash/commands/yq/errors.d.ts.map +1 -0
  22. package/dist/safe-bash/commands/yq/errors.js +37 -0
  23. package/dist/safe-bash/commands/yq/errors.js.map +1 -0
  24. package/dist/safe-bash/commands/yq/index.browser.js +12 -0
  25. package/dist/safe-bash/commands/yq/index.browser.js.map +7 -0
  26. package/dist/safe-bash/commands/yq/index.d.ts +9 -0
  27. package/dist/safe-bash/commands/yq/index.d.ts.map +1 -0
  28. package/dist/safe-bash/commands/yq/index.js +719 -0
  29. package/dist/safe-bash/commands/yq/index.js.map +1 -0
  30. package/dist/safe-bash/commands/yq/parser.d.ts +5 -0
  31. package/dist/safe-bash/commands/yq/parser.d.ts.map +1 -0
  32. package/dist/safe-bash/commands/yq/parser.js +1326 -0
  33. package/dist/safe-bash/commands/yq/parser.js.map +1 -0
  34. package/dist/safe-bash/commands/yq/toml.d.ts +5 -0
  35. package/dist/safe-bash/commands/yq/toml.d.ts.map +1 -0
  36. package/dist/safe-bash/commands/yq/toml.js +690 -0
  37. package/dist/safe-bash/commands/yq/toml.js.map +1 -0
  38. package/dist/safe-bash/core.browser.js +221 -2171
  39. package/dist/safe-bash/core.browser.js.map +4 -4
  40. package/dist/safe-bash/core.d.ts +1 -0
  41. package/dist/safe-bash/core.d.ts.map +1 -1
  42. package/dist/safe-bash/core.js +1 -0
  43. package/dist/safe-bash/core.js.map +1 -1
  44. package/package.json +8 -2
  45. package/dist/safe-bash/chunks/chunk-3ISDVRIM.js.map +0 -7
@@ -0,0 +1,719 @@
1
+ import { escapeText } from "../../escaping.js";
2
+ import { pathOf } from "../internal.js";
3
+ import { createOutputOperation, FsError, getCommandArguments, readBytes, } from "../../contracts/index.js";
4
+ import { shellValueByteLength } from "../../contracts/value.js";
5
+ import { createYqQuerySession, YqValueFailure } from "../structured/query-core.js";
6
+ import { interruptible, JqError, JqLimitError, wellFormed } from "../structured/limits.js";
7
+ import { YqLedger, yqCaps } from "./accounting.js";
8
+ import { encodeJson, encodeRaw, encodeYaml } from "./encoder.js";
9
+ import { fromJqLimit, YqError } from "./errors.js";
10
+ import { parseYamlDocuments } from "./parser.js";
11
+ import { parseTomlDocument } from "./toml.js";
12
+ const help = "virtual-bash restricted YAML/TOML profile\nusage: yq [eval|e] [OPTION ...] [--] [FILTER [FILE ...]]\n yq [eval|e] --help\n yq [eval|e] --version\noptions:\n -p, --input-format FORMAT FORMAT is yaml (default) or toml\n --input-format=FORMAT same as above\n -o, --output-format FORMAT FORMAT is yaml or json\n --output-format=FORMAT same as above\n -c, --compact-output compact JSON; requires -o json\n -r, --unwrapScalar raw strings; requires -o json\n -h, --help show this help (sole argument)\n --version show profile identity (sole argument)\n";
13
+ const version = "virtual-bash restricted YAML/TOML profile\n";
14
+ const diagnosticFallback = "yq: limit: DIAGNOSTIC_TRUNCATED\n";
15
+ class RawDocumentFramer {
16
+ #ranges = [];
17
+ #offset = 0;
18
+ #frameStart = 0;
19
+ #frameLine = 0;
20
+ #lineStart = 0;
21
+ #lineNumber = 0;
22
+ #line = "";
23
+ #pendingCr = false;
24
+ #frameBytes = 0;
25
+ #lineBytes = 0;
26
+ #lineCouldBeMarker = true;
27
+ #markerComment = false;
28
+ #hasContent = false;
29
+ admit(chunk) {
30
+ for (const byte of chunk) {
31
+ this.#offset++;
32
+ this.#lineBytes++;
33
+ if (this.#lineBytes > yqCaps.maxDocumentBytes)
34
+ throw new YqError("limit", "LIMIT_MAX_DOCUMENT_BYTES", 5);
35
+ if (this.#pendingCr) {
36
+ this.#pendingCr = false;
37
+ if (byte === 0x0a) {
38
+ this.#line += "\n";
39
+ this.#finishLine(this.#offset);
40
+ continue;
41
+ }
42
+ this.#finishLine(this.#offset - 1);
43
+ }
44
+ if (!this.#markerComment && (this.#line.length <= 8 || /^(?:---|\.\.\.)[ \t]+#/u.test(this.#line))) {
45
+ this.#line += String.fromCharCode(byte);
46
+ }
47
+ if (/^(?:---|\.\.\.)[ \t]+#/u.test(this.#line))
48
+ this.#markerComment = true;
49
+ const candidate = this.#line.replace(/[\r\n]+$/u, "");
50
+ this.#lineCouldBeMarker = /^(?:-{0,3}|\.{0,3})$/u.test(candidate)
51
+ || /^(?:---|\.\.\.)(?:[ \t]*|[ \t]+#.*)$/u.test(candidate);
52
+ if (!this.#lineCouldBeMarker && this.#lineBytes > yqCaps.maxDocumentBytes - this.#frameBytes) {
53
+ throw new YqError("limit", "LIMIT_MAX_DOCUMENT_BYTES", 5);
54
+ }
55
+ if (byte === 0x0d)
56
+ this.#pendingCr = true;
57
+ else if (byte === 0x0a)
58
+ this.#finishLine(this.#offset);
59
+ }
60
+ }
61
+ finish(bytes) {
62
+ if (this.#line !== "") {
63
+ this.#pendingCr = false;
64
+ this.#finishLine(this.#offset);
65
+ }
66
+ if (this.#frameStart < this.#offset)
67
+ this.#ranges.push({ start: this.#frameStart, end: this.#offset, lineOffset: this.#frameLine });
68
+ return this.#ranges.map(range => ({
69
+ bytes: bytes.subarray(range.start, range.end),
70
+ rawBytes: range.end - range.start,
71
+ lineOffset: range.lineOffset,
72
+ }));
73
+ }
74
+ #finishLine(end) {
75
+ const line = this.#line.replace(/[\r\n]+$/u, "");
76
+ const marker = /^---(?:[ \t]+#.*)?$/u.test(line);
77
+ const endMarker = /^\.\.\.(?:[ \t]+#.*)?$/u.test(line);
78
+ if (marker && this.#hasContent && this.#lineStart > this.#frameStart) {
79
+ this.#ranges.push({ start: this.#frameStart, end: this.#lineStart, lineOffset: this.#frameLine });
80
+ this.#frameStart = this.#lineStart;
81
+ this.#frameLine = this.#lineNumber;
82
+ this.#frameBytes = this.#lineBytes;
83
+ this.#hasContent = false;
84
+ }
85
+ else {
86
+ if (this.#lineBytes > yqCaps.maxDocumentBytes - this.#frameBytes)
87
+ throw new YqError("limit", "LIMIT_MAX_DOCUMENT_BYTES", 5);
88
+ this.#frameBytes += this.#lineBytes;
89
+ }
90
+ const visible = line.replace(/^\ufeff/u, "").trimStart();
91
+ if (visible !== "" && !visible.startsWith("#") && !visible.startsWith("%") && !marker && !endMarker)
92
+ this.#hasContent = true;
93
+ if (endMarker && this.#frameStart < end) {
94
+ this.#ranges.push({ start: this.#frameStart, end, lineOffset: this.#frameLine });
95
+ this.#frameStart = end;
96
+ this.#frameLine = this.#lineNumber + 1;
97
+ this.#frameBytes = 0;
98
+ this.#hasContent = false;
99
+ }
100
+ this.#line = "";
101
+ this.#lineBytes = 0;
102
+ this.#lineCouldBeMarker = true;
103
+ this.#markerComment = false;
104
+ this.#lineStart = end;
105
+ this.#lineNumber++;
106
+ }
107
+ }
108
+ class SinkFailure {
109
+ reason;
110
+ constructor(reason) {
111
+ this.reason = reason;
112
+ }
113
+ }
114
+ class InvocationOwner {
115
+ #accepting = true;
116
+ #callbacks = [];
117
+ #closePromise;
118
+ assertOpen(signal) {
119
+ if (signal.aborted)
120
+ throw signal.reason;
121
+ if (!this.#accepting)
122
+ throw new Error("yq invocation is closed");
123
+ }
124
+ register(cleanup) {
125
+ if (!this.#accepting)
126
+ throw new Error("yq invocation is closed");
127
+ if (typeof cleanup !== "function")
128
+ throw new TypeError("cleanup must be callable");
129
+ this.#callbacks.push(cleanup);
130
+ }
131
+ close() {
132
+ if (this.#closePromise)
133
+ return this.#closePromise;
134
+ this.#accepting = false;
135
+ this.#closePromise = (async () => {
136
+ const results = await Promise.allSettled(this.#callbacks.map(async (cleanup) => cleanup()));
137
+ const failures = results.filter((result) => result.status === "rejected").map(result => result.reason);
138
+ if (failures.length === 1)
139
+ throw failures[0];
140
+ if (failures.length > 1)
141
+ throw new AggregateError(failures, "yq invocation cleanup failed");
142
+ })();
143
+ void this.#closePromise.catch(() => { });
144
+ return this.#closePromise;
145
+ }
146
+ }
147
+ function cli(code) {
148
+ return new YqError("cli", code, 2);
149
+ }
150
+ function preflightArguments(context) {
151
+ const args = context.args;
152
+ if (args.length > yqCaps.maxArgvEntries)
153
+ throw cli("CLI_ARGV_ENTRIES_LIMIT");
154
+ let bytes = 0;
155
+ for (const argument of args) {
156
+ if (!wellFormed(argument))
157
+ throw cli("CLI_INVALID_UNICODE");
158
+ const incoming = Buffer.byteLength(argument);
159
+ if (incoming > yqCaps.maxArgvUtf8Bytes - bytes)
160
+ throw cli("CLI_ARGV_BYTES_LIMIT");
161
+ bytes += incoming;
162
+ }
163
+ const carrier = getCommandArguments(context);
164
+ bytes = 0;
165
+ const decoder = new TextDecoder("utf-8", { fatal: true, ignoreBOM: true });
166
+ for (let index = 0; index < args.length; index++) {
167
+ const incoming = shellValueByteLength(carrier.values[index]);
168
+ if (incoming > yqCaps.maxArgvUtf8Bytes - bytes)
169
+ throw cli("CLI_ARGV_BYTES_LIMIT");
170
+ bytes += incoming;
171
+ let decoded;
172
+ try {
173
+ decoded = decoder.decode(carrier.bytes(index));
174
+ }
175
+ catch {
176
+ throw cli("CLI_INVALID_UNICODE");
177
+ }
178
+ if (decoded !== args[index])
179
+ throw cli("CLI_INVALID_UNICODE");
180
+ }
181
+ }
182
+ function isInformationForm(args) {
183
+ const offset = args[0] === "eval" || args[0] === "e" ? 1 : 0;
184
+ if (args.length !== offset + 1)
185
+ return undefined;
186
+ const token = args[offset];
187
+ if (token === "-h" || token === "--help")
188
+ return "help";
189
+ if (token === "--version")
190
+ return "version";
191
+ return undefined;
192
+ }
193
+ function parseArguments(args, inputFormat) {
194
+ let index = args[0] === "eval" || args[0] === "e" ? 1 : 0;
195
+ if (args[0] === "eval-all" || args[0] === "ea")
196
+ throw cli("CLI_UNSUPPORTED_COMMAND");
197
+ let ended = false;
198
+ let inputFormatSeen = false;
199
+ let format = "yaml";
200
+ let explicitJson = false;
201
+ let formatSeen = false;
202
+ let compact = false;
203
+ let compactSeen = false;
204
+ let raw = false;
205
+ let rawSeen = false;
206
+ const operands = [];
207
+ const refused = /^(?:-s|-n|-p|-i|--slurp|--null-input|--input-format|--yaml-schema|--schema|--json-schema|--failsafe-schema|--inplace|--in-place|--allow-lossy-write|--write|--split-exp|--front-matter|--xml|--properties|--color-output)(?:=.*)?$/u;
208
+ for (; index < args.length; index++) {
209
+ const argument = args[index];
210
+ if (!ended && argument === "--") {
211
+ ended = true;
212
+ continue;
213
+ }
214
+ if (!ended && (argument === "-p" || argument === "--input-format" || argument.startsWith("--input-format="))) {
215
+ if (inputFormatSeen)
216
+ throw cli("CLI_DUPLICATE_OPTION");
217
+ const value = argument.startsWith("--input-format=") ? argument.slice("--input-format=".length) : args[++index];
218
+ if (value === undefined || value === "")
219
+ throw cli("CLI_MISSING_OPTION_VALUE");
220
+ if (value !== "yaml" && value !== "toml")
221
+ throw cli("CLI_INVALID_OPTION_VALUE");
222
+ inputFormatSeen = true;
223
+ inputFormat = value;
224
+ continue;
225
+ }
226
+ if (!ended && (argument === "-o" || argument === "--output-format")) {
227
+ if (formatSeen)
228
+ throw cli("CLI_DUPLICATE_OPTION");
229
+ const value = args[++index];
230
+ if (value === undefined)
231
+ throw cli("CLI_MISSING_OPTION_VALUE");
232
+ if (value !== "yaml" && value !== "json")
233
+ throw cli("CLI_INVALID_OPTION_VALUE");
234
+ formatSeen = true;
235
+ format = value;
236
+ explicitJson = value === "json";
237
+ continue;
238
+ }
239
+ if (!ended && argument.startsWith("--output-format=")) {
240
+ if (formatSeen)
241
+ throw cli("CLI_DUPLICATE_OPTION");
242
+ const value = argument.slice("--output-format=".length);
243
+ if (value === "")
244
+ throw cli("CLI_MISSING_OPTION_VALUE");
245
+ if (value !== "yaml" && value !== "json")
246
+ throw cli("CLI_INVALID_OPTION_VALUE");
247
+ formatSeen = true;
248
+ format = value;
249
+ explicitJson = value === "json";
250
+ continue;
251
+ }
252
+ if (!ended && (argument === "-c" || argument === "--compact-output")) {
253
+ if (compactSeen)
254
+ throw cli("CLI_DUPLICATE_OPTION");
255
+ compactSeen = true;
256
+ compact = true;
257
+ continue;
258
+ }
259
+ if (!ended && (argument === "-r" || argument === "--unwrapScalar")) {
260
+ if (rawSeen)
261
+ throw cli("CLI_DUPLICATE_OPTION");
262
+ rawSeen = true;
263
+ raw = true;
264
+ continue;
265
+ }
266
+ if (!ended && refused.test(argument))
267
+ throw cli("CLI_UNSUPPORTED_OPTION");
268
+ if (!ended && argument.startsWith("-") && argument !== "-")
269
+ throw cli("CLI_UNKNOWN_OPTION");
270
+ operands.push(argument);
271
+ }
272
+ if ((compact || raw) && !explicitJson)
273
+ throw cli("CLI_INCOMPATIBLE_OPTIONS");
274
+ const filter = operands[0] ?? ".";
275
+ const files = operands.slice(1);
276
+ let stdinSeen = false;
277
+ for (const file of files) {
278
+ if (file === "-") {
279
+ if (stdinSeen)
280
+ throw cli("CLI_DUPLICATE_STDIN");
281
+ stdinSeen = true;
282
+ }
283
+ else if (Buffer.byteLength(file) > yqCaps.maxVfsOperandPathBytes)
284
+ throw cli("CLI_VFS_OPERAND_LIMIT");
285
+ }
286
+ return { inputFormat, format, explicitJson, compact, raw, filter, files };
287
+ }
288
+ function displayedSource(source) {
289
+ if (source === "<stdin>")
290
+ return source;
291
+ const parts = ['"'];
292
+ let bytes = 2;
293
+ let truncated = false;
294
+ for (const character of source) {
295
+ const encoded = escapeText(JSON.stringify(character).slice(1, -1), "diagnostic");
296
+ const incoming = Buffer.byteLength(encoded);
297
+ if (incoming > yqCaps.maxDisplayedFilenameBytes - bytes) {
298
+ truncated = true;
299
+ break;
300
+ }
301
+ parts.push(encoded);
302
+ bytes += incoming;
303
+ }
304
+ if (truncated) {
305
+ while (parts.length > 1 && Buffer.byteLength(parts.join("")) + 4 > yqCaps.maxDisplayedFilenameBytes)
306
+ parts.pop();
307
+ parts.push("...");
308
+ }
309
+ parts.push('"');
310
+ return parts.join("");
311
+ }
312
+ function diagnostic(error) {
313
+ let location = "";
314
+ if (error.source !== undefined) {
315
+ location = ` at ${displayedSource(error.source)}`;
316
+ if (error.line !== undefined && error.column !== undefined)
317
+ location += `:${error.line}:${error.column}`;
318
+ }
319
+ return `yq: ${error.category}: ${error.code}${location}\n`;
320
+ }
321
+ function classifyValueFailure(error) {
322
+ const category = error.code.startsWith("ENCODE_") ? "encode" : "schema";
323
+ return new YqError(category, error.code, 5);
324
+ }
325
+ function withSource(error, source) {
326
+ if (error.source !== undefined)
327
+ return error;
328
+ return new YqError(error.category, error.code, error.status, source, error.line, error.column);
329
+ }
330
+ async function collectSource(context, owner, session, sourceName, source, vfs, inputFormat) {
331
+ let iterator;
332
+ let returned;
333
+ owner.register(async () => {
334
+ if (iterator?.return) {
335
+ returned ??= Promise.resolve().then(() => iterator.return());
336
+ await returned;
337
+ }
338
+ });
339
+ iterator = readBytes(source, context.signal)[Symbol.asyncIterator]();
340
+ const chunks = [];
341
+ const framer = inputFormat === "yaml" ? new RawDocumentFramer() : undefined;
342
+ let size = 0;
343
+ while (true) {
344
+ let next;
345
+ try {
346
+ next = await iterator.next();
347
+ }
348
+ catch (failure) {
349
+ if (context.signal.aborted)
350
+ throw context.signal.reason;
351
+ if (vfs && failure instanceof FsError)
352
+ throw new YqError("vfs", "VFS_INPUT_READ", 2, sourceName);
353
+ throw failure;
354
+ }
355
+ owner.assertOpen(context.signal);
356
+ if (next.done)
357
+ break;
358
+ const chunk = next.value;
359
+ if (inputFormat === "toml")
360
+ await session.ownedWork.charge();
361
+ session.ownedWork.admitInputBytes(chunk.byteLength);
362
+ if (chunk.byteLength > yqCaps.maxInputBytes - size)
363
+ throw fromJqLimit(new JqLimitError("maxInputBytes"));
364
+ if (inputFormat === "toml" && chunk.byteLength > yqCaps.maxDocumentBytes - size)
365
+ throw new YqError("limit", "LIMIT_MAX_DOCUMENT_BYTES", 5);
366
+ framer?.admit(chunk);
367
+ const owned = new Uint8Array(chunk);
368
+ owner.assertOpen(context.signal);
369
+ chunks.push(owned);
370
+ size += owned.byteLength;
371
+ }
372
+ owner.assertOpen(context.signal);
373
+ const bytes = new Uint8Array(size);
374
+ let offset = 0;
375
+ for (const chunk of chunks) {
376
+ bytes.set(chunk, offset);
377
+ offset += chunk.byteLength;
378
+ }
379
+ owner.assertOpen(context.signal);
380
+ return framer ? framer.finish(bytes) : [{ bytes, rawBytes: size, lineOffset: 0 }];
381
+ }
382
+ async function sourceFrames(context, owner, session, sourceName, inputFormat) {
383
+ if (sourceName === "-")
384
+ return collectSource(context, owner, session, "<stdin>", context.stdin, false, inputFormat);
385
+ const path = pathOf(context, sourceName);
386
+ await session.ownedWork.charge();
387
+ owner.assertOpen(context.signal);
388
+ let capabilities;
389
+ try {
390
+ capabilities = context.fs.capabilitiesFor
391
+ ? await interruptible(() => context.fs.capabilitiesFor(path, { signal: context.signal }), context.signal)
392
+ : context.fs.capabilities;
393
+ }
394
+ catch (failure) {
395
+ if (context.signal.aborted)
396
+ throw context.signal.reason;
397
+ if (failure instanceof FsError)
398
+ throw new YqError("vfs", "VFS_INPUT_OPEN", 2, sourceName);
399
+ throw failure;
400
+ }
401
+ owner.assertOpen(context.signal);
402
+ if (context.fs.readStream && capabilities.streamingRead !== false) {
403
+ let source;
404
+ try {
405
+ source = context.fs.readStream(path, { signal: context.signal });
406
+ }
407
+ catch (failure) {
408
+ if (context.signal.aborted)
409
+ throw context.signal.reason;
410
+ if (failure instanceof FsError)
411
+ throw new YqError("vfs", "VFS_INPUT_OPEN", 2, sourceName);
412
+ throw failure;
413
+ }
414
+ return collectSource(context, owner, session, sourceName, source, true, inputFormat);
415
+ }
416
+ let bytes;
417
+ try {
418
+ bytes = await context.fs.readFile(path, { signal: context.signal, maxBytes: inputFormat === "toml" ? yqCaps.maxDocumentBytes : yqCaps.maxInputBytes });
419
+ }
420
+ catch (failure) {
421
+ if (context.signal.aborted)
422
+ throw context.signal.reason;
423
+ if (inputFormat === "toml" && failure instanceof FsError && failure.code === "EFBIG")
424
+ throw new YqError("limit", "LIMIT_MAX_DOCUMENT_BYTES", 5);
425
+ if (failure instanceof FsError)
426
+ throw new YqError("vfs", "VFS_INPUT_READ", 2, sourceName);
427
+ throw failure;
428
+ }
429
+ owner.assertOpen(context.signal);
430
+ session.ownedWork.admitInputBytes(bytes.byteLength);
431
+ if (inputFormat === "toml") {
432
+ if (bytes.byteLength > yqCaps.maxDocumentBytes)
433
+ throw new YqError("limit", "LIMIT_MAX_DOCUMENT_BYTES", 5);
434
+ return [{ bytes: new Uint8Array(bytes), rawBytes: bytes.byteLength, lineOffset: 0 }];
435
+ }
436
+ const framer = new RawDocumentFramer();
437
+ framer.admit(bytes);
438
+ const owned = new Uint8Array(bytes);
439
+ owner.assertOpen(context.signal);
440
+ return framer.finish(owned);
441
+ }
442
+ function decodeDocument(bytes, inputFormat) {
443
+ try {
444
+ return new TextDecoder("utf-8", { fatal: true, ignoreBOM: inputFormat === "toml" }).decode(bytes);
445
+ }
446
+ catch {
447
+ throw new YqError("input", "INPUT_INVALID_UTF8", 5);
448
+ }
449
+ }
450
+ async function writeOperation(operation, bytes, owner, callerSignal) {
451
+ owner.assertOpen(callerSignal);
452
+ try {
453
+ await operation.output.write(bytes);
454
+ }
455
+ catch (failure) {
456
+ throw new SinkFailure(failure);
457
+ }
458
+ owner.assertOpen(callerSignal);
459
+ }
460
+ async function runCommand(context, owner, inputFormat) {
461
+ const ledger = new YqLedger();
462
+ let session;
463
+ let stdout;
464
+ let stderr;
465
+ const stdoutOperation = () => {
466
+ stdout ??= createOutputOperation({ signal: context.signal, registerCleanup: cleanup => owner.register(cleanup) }, context.stdout);
467
+ return stdout;
468
+ };
469
+ const stderrOperation = () => {
470
+ stderr ??= createOutputOperation({ signal: context.signal, registerCleanup: cleanup => owner.register(cleanup) }, context.stderr);
471
+ return stderr;
472
+ };
473
+ const emitDiagnostic = async (error) => {
474
+ const preferred = Buffer.from(diagnostic(error));
475
+ const fallback = Buffer.from(diagnosticFallback);
476
+ const selected = ledger.canAdmitDiagnostic(preferred.byteLength) ? preferred : ledger.canAdmitDiagnostic(fallback.byteLength) ? fallback : undefined;
477
+ if (!selected)
478
+ return;
479
+ ledger.admitDiagnostic(selected.byteLength);
480
+ session?.ownedWork.admitOutputBytes(selected.byteLength);
481
+ await writeOperation(stderrOperation(), selected, owner, context.signal);
482
+ };
483
+ try {
484
+ preflightArguments(context);
485
+ const info = isInformationForm(context.args);
486
+ if (context.args.some(argument => argument === "-h" || argument === "--help" || argument === "--version") && info === undefined) {
487
+ throw cli("CLI_INFO_COMBINATION");
488
+ }
489
+ if (info) {
490
+ const bytes = Buffer.from(info === "help" ? help : version);
491
+ ledger.admitStdout(bytes.byteLength);
492
+ await writeOperation(stdoutOperation(), bytes, owner, context.signal);
493
+ return { exitCode: 0 };
494
+ }
495
+ const options = parseArguments(context.args, inputFormat);
496
+ if (Buffer.byteLength(options.filter) > yqCaps.maxQuerySourceBytes)
497
+ throw new YqError("limit", "LIMIT_MAX_QUERY_SOURCE_BYTES", 5);
498
+ owner.register(async () => session?.close());
499
+ session = createYqQuerySession({ signal: context.signal });
500
+ try {
501
+ session.compileOnce(options.filter);
502
+ }
503
+ catch (failure) {
504
+ if (failure instanceof JqLimitError)
505
+ throw fromJqLimit(failure);
506
+ if (failure instanceof JqError)
507
+ throw new YqError("query", "QUERY_COMPILE_FAILED", 3);
508
+ throw failure;
509
+ }
510
+ const files = options.files.length > 0 ? options.files : ["-"];
511
+ let emitted = 0;
512
+ for (const file of files) {
513
+ const sourceName = file === "-" ? "<stdin>" : file;
514
+ let frames;
515
+ try {
516
+ frames = await sourceFrames(context, owner, session, file, options.inputFormat);
517
+ }
518
+ catch (failure) {
519
+ throw failure instanceof YqError ? withSource(failure, sourceName) : failure;
520
+ }
521
+ owner.assertOpen(context.signal);
522
+ for (const frame of frames) {
523
+ ledger.admitDocumentBytes(frame.rawBytes);
524
+ let input;
525
+ try {
526
+ input = decodeDocument(frame.bytes, options.inputFormat);
527
+ }
528
+ catch (failure) {
529
+ throw failure instanceof YqError ? withSource(failure, sourceName) : failure;
530
+ }
531
+ owner.assertOpen(context.signal);
532
+ try {
533
+ const documents = options.inputFormat === "toml"
534
+ ? [await parseTomlDocument(input, session.ownedWork, ledger, frame.rawBytes)]
535
+ : parseYamlDocuments(input, session.ownedWork, ledger, frame.rawBytes, frame.lineOffset);
536
+ for await (const document of documents) {
537
+ owner.assertOpen(context.signal);
538
+ try {
539
+ await session.ownedWork.measure(document);
540
+ }
541
+ catch (failure) {
542
+ if (failure instanceof JqLimitError)
543
+ throw fromJqLimit(failure);
544
+ if (failure instanceof YqValueFailure)
545
+ throw classifyValueFailure(failure);
546
+ throw failure;
547
+ }
548
+ owner.assertOpen(context.signal);
549
+ const iterator = session.run(document);
550
+ try {
551
+ while (true) {
552
+ let next;
553
+ try {
554
+ next = await iterator.next();
555
+ }
556
+ catch (failure) {
557
+ if (context.signal.aborted)
558
+ throw context.signal.reason;
559
+ if (failure instanceof JqLimitError)
560
+ throw fromJqLimit(failure);
561
+ if (failure instanceof JqError)
562
+ throw new YqError("query", "QUERY_RUNTIME_FAILED", 5, sourceName);
563
+ throw failure;
564
+ }
565
+ owner.assertOpen(context.signal);
566
+ if (next.done)
567
+ break;
568
+ try {
569
+ await session.ownedWork.measure(next.value);
570
+ }
571
+ catch (failure) {
572
+ if (failure instanceof JqLimitError)
573
+ throw fromJqLimit(failure);
574
+ if (failure instanceof YqValueFailure)
575
+ throw classifyValueFailure(failure);
576
+ throw failure;
577
+ }
578
+ owner.assertOpen(context.signal);
579
+ session.ownedWork.admitResult();
580
+ const separator = emitted === 0 || options.format === "json" ? "" : "---\n";
581
+ const suffixBytes = Buffer.byteLength(separator) + 1;
582
+ const remaining = yqCaps.stdoutCapBytes - ledger.stdoutBytes;
583
+ if (suffixBytes > remaining)
584
+ throw new YqError("limit", "LIMIT_MAX_OUTPUT_BYTES", 5, sourceName);
585
+ let encoded;
586
+ try {
587
+ encoded = options.format === "yaml"
588
+ ? await encodeYaml(next.value, session.ownedWork, remaining - suffixBytes)
589
+ : options.raw && typeof next.value === "string"
590
+ ? await encodeRaw(next.value, session.ownedWork, remaining - 1)
591
+ : await encodeJson(next.value, session.ownedWork, !options.compact, remaining - 1);
592
+ }
593
+ catch (failure) {
594
+ if (failure instanceof JqLimitError)
595
+ throw fromJqLimit(failure);
596
+ if (failure instanceof YqValueFailure)
597
+ throw classifyValueFailure(failure);
598
+ throw failure;
599
+ }
600
+ owner.assertOpen(context.signal);
601
+ const encodedBytes = Buffer.byteLength(encoded);
602
+ const outputBytes = encodedBytes + suffixBytes;
603
+ ledger.admitStdout(outputBytes);
604
+ session.ownedWork.admitOutputBytes(outputBytes);
605
+ owner.assertOpen(context.signal);
606
+ const output = Buffer.allocUnsafe(outputBytes);
607
+ let offset = 0;
608
+ if (separator !== "")
609
+ offset += output.write(separator, offset, "utf8");
610
+ offset += output.write(encoded, offset, "utf8");
611
+ output[offset] = 0x0a;
612
+ owner.assertOpen(context.signal);
613
+ await writeOperation(stdoutOperation(), output, owner, context.signal);
614
+ emitted++;
615
+ }
616
+ }
617
+ finally {
618
+ await iterator.return(undefined);
619
+ owner.assertOpen(context.signal);
620
+ }
621
+ }
622
+ }
623
+ catch (failure) {
624
+ throw failure instanceof YqError ? withSource(failure, sourceName) : failure;
625
+ }
626
+ }
627
+ }
628
+ return { exitCode: 0 };
629
+ }
630
+ catch (failure) {
631
+ if (context.signal.aborted)
632
+ throw context.signal.reason;
633
+ if (failure instanceof SinkFailure)
634
+ throw failure.reason;
635
+ let normal;
636
+ if (failure instanceof YqError)
637
+ normal = failure;
638
+ else if (failure instanceof JqLimitError)
639
+ normal = fromJqLimit(failure);
640
+ else if (failure instanceof YqValueFailure)
641
+ normal = classifyValueFailure(failure);
642
+ if (!normal)
643
+ throw failure;
644
+ await emitDiagnostic(normal);
645
+ return { exitCode: normal.status };
646
+ }
647
+ }
648
+ async function execute(context, inputFormat) {
649
+ const owner = new InvocationOwner();
650
+ context.registerCleanup?.(() => owner.close());
651
+ let result;
652
+ let primary;
653
+ let hasPrimary = false;
654
+ try {
655
+ result = await runCommand(context, owner, inputFormat);
656
+ }
657
+ catch (failure) {
658
+ primary = failure;
659
+ hasPrimary = true;
660
+ }
661
+ let cleanup;
662
+ let hasCleanup = false;
663
+ try {
664
+ await owner.close();
665
+ }
666
+ catch (failure) {
667
+ cleanup = failure;
668
+ hasCleanup = true;
669
+ }
670
+ if (context.signal.aborted)
671
+ throw context.signal.reason;
672
+ if (hasPrimary)
673
+ throw primary;
674
+ if (hasCleanup)
675
+ throw cleanup;
676
+ return result;
677
+ }
678
+ function admittedOptions(options) {
679
+ if (typeof options !== "object" || options === null)
680
+ throw new TypeError("options must be an object");
681
+ if (Object.keys(options).some(key => key !== "replace" && key !== "inputFormat"))
682
+ throw new TypeError("unsupported yq option");
683
+ const { replace = false, inputFormat = "yaml" } = options;
684
+ if (typeof replace !== "boolean")
685
+ throw new TypeError("replace must be a boolean");
686
+ if (inputFormat !== "yaml" && inputFormat !== "toml")
687
+ throw new TypeError("inputFormat must be yaml or toml");
688
+ return { replace, inputFormat };
689
+ }
690
+ export function createYqCommand(options = {}) {
691
+ const { inputFormat } = admittedOptions(options);
692
+ return Object.freeze({
693
+ name: "yq",
694
+ description: "Bounded restricted YAML/TOML query and formatter",
695
+ execute: (context) => execute(context, inputFormat),
696
+ });
697
+ }
698
+ export function createYqCommands(options = {}) {
699
+ return Object.freeze([createYqCommand(options)]);
700
+ }
701
+ export function yqCommands(options = {}) {
702
+ const captured = admittedOptions(options);
703
+ const { replace } = captured;
704
+ const definitions = createYqCommands(captured);
705
+ const plugin = {
706
+ name: "yq-commands",
707
+ setup(host) {
708
+ if (!replace)
709
+ for (const definition of definitions) {
710
+ if (host.commands.has(definition.name))
711
+ throw new Error(`Command already registered: ${definition.name}`);
712
+ }
713
+ for (const definition of definitions)
714
+ host.commands.register(definition, { replace: replace ?? false });
715
+ },
716
+ };
717
+ return Object.freeze(plugin);
718
+ }
719
+ //# sourceMappingURL=index.js.map