@automatify-au/cli 0.1.2 → 0.1.4

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.
@@ -1,4 +1,978 @@
1
1
  #!/usr/bin/env node
2
+ "use strict";
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __commonJS = (cb, mod) => function __require() {
10
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+
29
+ // ../../node_modules/.pnpm/buffer-crc32@1.0.0/node_modules/buffer-crc32/dist/index.cjs
30
+ var require_dist = __commonJS({
31
+ "../../node_modules/.pnpm/buffer-crc32@1.0.0/node_modules/buffer-crc32/dist/index.cjs"(exports2, module2) {
32
+ "use strict";
33
+ function getDefaultExportFromCjs(x) {
34
+ return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x["default"] : x;
35
+ }
36
+ var CRC_TABLE = new Int32Array([
37
+ 0,
38
+ 1996959894,
39
+ 3993919788,
40
+ 2567524794,
41
+ 124634137,
42
+ 1886057615,
43
+ 3915621685,
44
+ 2657392035,
45
+ 249268274,
46
+ 2044508324,
47
+ 3772115230,
48
+ 2547177864,
49
+ 162941995,
50
+ 2125561021,
51
+ 3887607047,
52
+ 2428444049,
53
+ 498536548,
54
+ 1789927666,
55
+ 4089016648,
56
+ 2227061214,
57
+ 450548861,
58
+ 1843258603,
59
+ 4107580753,
60
+ 2211677639,
61
+ 325883990,
62
+ 1684777152,
63
+ 4251122042,
64
+ 2321926636,
65
+ 335633487,
66
+ 1661365465,
67
+ 4195302755,
68
+ 2366115317,
69
+ 997073096,
70
+ 1281953886,
71
+ 3579855332,
72
+ 2724688242,
73
+ 1006888145,
74
+ 1258607687,
75
+ 3524101629,
76
+ 2768942443,
77
+ 901097722,
78
+ 1119000684,
79
+ 3686517206,
80
+ 2898065728,
81
+ 853044451,
82
+ 1172266101,
83
+ 3705015759,
84
+ 2882616665,
85
+ 651767980,
86
+ 1373503546,
87
+ 3369554304,
88
+ 3218104598,
89
+ 565507253,
90
+ 1454621731,
91
+ 3485111705,
92
+ 3099436303,
93
+ 671266974,
94
+ 1594198024,
95
+ 3322730930,
96
+ 2970347812,
97
+ 795835527,
98
+ 1483230225,
99
+ 3244367275,
100
+ 3060149565,
101
+ 1994146192,
102
+ 31158534,
103
+ 2563907772,
104
+ 4023717930,
105
+ 1907459465,
106
+ 112637215,
107
+ 2680153253,
108
+ 3904427059,
109
+ 2013776290,
110
+ 251722036,
111
+ 2517215374,
112
+ 3775830040,
113
+ 2137656763,
114
+ 141376813,
115
+ 2439277719,
116
+ 3865271297,
117
+ 1802195444,
118
+ 476864866,
119
+ 2238001368,
120
+ 4066508878,
121
+ 1812370925,
122
+ 453092731,
123
+ 2181625025,
124
+ 4111451223,
125
+ 1706088902,
126
+ 314042704,
127
+ 2344532202,
128
+ 4240017532,
129
+ 1658658271,
130
+ 366619977,
131
+ 2362670323,
132
+ 4224994405,
133
+ 1303535960,
134
+ 984961486,
135
+ 2747007092,
136
+ 3569037538,
137
+ 1256170817,
138
+ 1037604311,
139
+ 2765210733,
140
+ 3554079995,
141
+ 1131014506,
142
+ 879679996,
143
+ 2909243462,
144
+ 3663771856,
145
+ 1141124467,
146
+ 855842277,
147
+ 2852801631,
148
+ 3708648649,
149
+ 1342533948,
150
+ 654459306,
151
+ 3188396048,
152
+ 3373015174,
153
+ 1466479909,
154
+ 544179635,
155
+ 3110523913,
156
+ 3462522015,
157
+ 1591671054,
158
+ 702138776,
159
+ 2966460450,
160
+ 3352799412,
161
+ 1504918807,
162
+ 783551873,
163
+ 3082640443,
164
+ 3233442989,
165
+ 3988292384,
166
+ 2596254646,
167
+ 62317068,
168
+ 1957810842,
169
+ 3939845945,
170
+ 2647816111,
171
+ 81470997,
172
+ 1943803523,
173
+ 3814918930,
174
+ 2489596804,
175
+ 225274430,
176
+ 2053790376,
177
+ 3826175755,
178
+ 2466906013,
179
+ 167816743,
180
+ 2097651377,
181
+ 4027552580,
182
+ 2265490386,
183
+ 503444072,
184
+ 1762050814,
185
+ 4150417245,
186
+ 2154129355,
187
+ 426522225,
188
+ 1852507879,
189
+ 4275313526,
190
+ 2312317920,
191
+ 282753626,
192
+ 1742555852,
193
+ 4189708143,
194
+ 2394877945,
195
+ 397917763,
196
+ 1622183637,
197
+ 3604390888,
198
+ 2714866558,
199
+ 953729732,
200
+ 1340076626,
201
+ 3518719985,
202
+ 2797360999,
203
+ 1068828381,
204
+ 1219638859,
205
+ 3624741850,
206
+ 2936675148,
207
+ 906185462,
208
+ 1090812512,
209
+ 3747672003,
210
+ 2825379669,
211
+ 829329135,
212
+ 1181335161,
213
+ 3412177804,
214
+ 3160834842,
215
+ 628085408,
216
+ 1382605366,
217
+ 3423369109,
218
+ 3138078467,
219
+ 570562233,
220
+ 1426400815,
221
+ 3317316542,
222
+ 2998733608,
223
+ 733239954,
224
+ 1555261956,
225
+ 3268935591,
226
+ 3050360625,
227
+ 752459403,
228
+ 1541320221,
229
+ 2607071920,
230
+ 3965973030,
231
+ 1969922972,
232
+ 40735498,
233
+ 2617837225,
234
+ 3943577151,
235
+ 1913087877,
236
+ 83908371,
237
+ 2512341634,
238
+ 3803740692,
239
+ 2075208622,
240
+ 213261112,
241
+ 2463272603,
242
+ 3855990285,
243
+ 2094854071,
244
+ 198958881,
245
+ 2262029012,
246
+ 4057260610,
247
+ 1759359992,
248
+ 534414190,
249
+ 2176718541,
250
+ 4139329115,
251
+ 1873836001,
252
+ 414664567,
253
+ 2282248934,
254
+ 4279200368,
255
+ 1711684554,
256
+ 285281116,
257
+ 2405801727,
258
+ 4167216745,
259
+ 1634467795,
260
+ 376229701,
261
+ 2685067896,
262
+ 3608007406,
263
+ 1308918612,
264
+ 956543938,
265
+ 2808555105,
266
+ 3495958263,
267
+ 1231636301,
268
+ 1047427035,
269
+ 2932959818,
270
+ 3654703836,
271
+ 1088359270,
272
+ 936918e3,
273
+ 2847714899,
274
+ 3736837829,
275
+ 1202900863,
276
+ 817233897,
277
+ 3183342108,
278
+ 3401237130,
279
+ 1404277552,
280
+ 615818150,
281
+ 3134207493,
282
+ 3453421203,
283
+ 1423857449,
284
+ 601450431,
285
+ 3009837614,
286
+ 3294710456,
287
+ 1567103746,
288
+ 711928724,
289
+ 3020668471,
290
+ 3272380065,
291
+ 1510334235,
292
+ 755167117
293
+ ]);
294
+ function ensureBuffer(input) {
295
+ if (Buffer.isBuffer(input)) {
296
+ return input;
297
+ }
298
+ if (typeof input === "number") {
299
+ return Buffer.alloc(input);
300
+ } else if (typeof input === "string") {
301
+ return Buffer.from(input);
302
+ } else {
303
+ throw new Error("input must be buffer, number, or string, received " + typeof input);
304
+ }
305
+ }
306
+ function bufferizeInt(num) {
307
+ const tmp = ensureBuffer(4);
308
+ tmp.writeInt32BE(num, 0);
309
+ return tmp;
310
+ }
311
+ function _crc32(buf, previous) {
312
+ buf = ensureBuffer(buf);
313
+ if (Buffer.isBuffer(previous)) {
314
+ previous = previous.readUInt32BE(0);
315
+ }
316
+ let crc = ~~previous ^ -1;
317
+ for (var n = 0; n < buf.length; n++) {
318
+ crc = CRC_TABLE[(crc ^ buf[n]) & 255] ^ crc >>> 8;
319
+ }
320
+ return crc ^ -1;
321
+ }
322
+ function crc32() {
323
+ return bufferizeInt(_crc32.apply(null, arguments));
324
+ }
325
+ crc32.signed = function() {
326
+ return _crc32.apply(null, arguments);
327
+ };
328
+ crc32.unsigned = function() {
329
+ return _crc32.apply(null, arguments) >>> 0;
330
+ };
331
+ var bufferCrc32 = crc32;
332
+ var index = /* @__PURE__ */ getDefaultExportFromCjs(bufferCrc32);
333
+ module2.exports = index;
334
+ }
335
+ });
336
+
337
+ // ../../node_modules/.pnpm/yazl@3.3.1/node_modules/yazl/index.js
338
+ var require_yazl = __commonJS({
339
+ "../../node_modules/.pnpm/yazl@3.3.1/node_modules/yazl/index.js"(exports2) {
340
+ var fs = require("fs");
341
+ var Transform = require("stream").Transform;
342
+ var PassThrough = require("stream").PassThrough;
343
+ var zlib = require("zlib");
344
+ var util = require("util");
345
+ var EventEmitter = require("events").EventEmitter;
346
+ var errorMonitor = require("events").errorMonitor;
347
+ var crc32 = require_dist();
348
+ exports2.ZipFile = ZipFile2;
349
+ exports2.dateToDosDateTime = dateToDosDateTime;
350
+ util.inherits(ZipFile2, EventEmitter);
351
+ function ZipFile2() {
352
+ this.outputStream = new PassThrough();
353
+ this.entries = [];
354
+ this.outputStreamCursor = 0;
355
+ this.ended = false;
356
+ this.allDone = false;
357
+ this.forceZip64Eocd = false;
358
+ this.errored = false;
359
+ this.on(errorMonitor, function() {
360
+ this.errored = true;
361
+ });
362
+ }
363
+ ZipFile2.prototype.addFile = function(realPath, metadataPath, options) {
364
+ var self = this;
365
+ metadataPath = validateMetadataPath(metadataPath, false);
366
+ if (options == null) options = {};
367
+ if (shouldIgnoreAdding(self)) return;
368
+ var entry = new Entry(metadataPath, false, options);
369
+ self.entries.push(entry);
370
+ fs.stat(realPath, function(err, stats) {
371
+ if (err) return self.emit("error", err);
372
+ if (!stats.isFile()) return self.emit("error", new Error("not a file: " + realPath));
373
+ entry.uncompressedSize = stats.size;
374
+ if (options.mtime == null) entry.setLastModDate(stats.mtime);
375
+ if (options.mode == null) entry.setFileAttributesMode(stats.mode);
376
+ entry.setFileDataPumpFunction(function() {
377
+ var readStream = fs.createReadStream(realPath);
378
+ entry.state = Entry.FILE_DATA_IN_PROGRESS;
379
+ readStream.on("error", function(err2) {
380
+ self.emit("error", err2);
381
+ });
382
+ pumpFileDataReadStream(self, entry, readStream);
383
+ });
384
+ pumpEntries(self);
385
+ });
386
+ };
387
+ ZipFile2.prototype.addReadStream = function(readStream, metadataPath, options) {
388
+ this.addReadStreamLazy(metadataPath, options, function(cb) {
389
+ cb(null, readStream);
390
+ });
391
+ };
392
+ ZipFile2.prototype.addReadStreamLazy = function(metadataPath, options, getReadStreamFunction) {
393
+ var self = this;
394
+ if (typeof options === "function") {
395
+ getReadStreamFunction = options;
396
+ options = null;
397
+ }
398
+ if (options == null) options = {};
399
+ metadataPath = validateMetadataPath(metadataPath, false);
400
+ if (shouldIgnoreAdding(self)) return;
401
+ var entry = new Entry(metadataPath, false, options);
402
+ self.entries.push(entry);
403
+ entry.setFileDataPumpFunction(function() {
404
+ entry.state = Entry.FILE_DATA_IN_PROGRESS;
405
+ getReadStreamFunction(function(err, readStream) {
406
+ if (err) return self.emit("error", err);
407
+ pumpFileDataReadStream(self, entry, readStream);
408
+ });
409
+ });
410
+ pumpEntries(self);
411
+ };
412
+ ZipFile2.prototype.addBuffer = function(buffer, metadataPath, options) {
413
+ var self = this;
414
+ metadataPath = validateMetadataPath(metadataPath, false);
415
+ if (buffer.length > 1073741823) throw new Error("buffer too large: " + buffer.length + " > 1073741823");
416
+ if (options == null) options = {};
417
+ if (options.size != null) throw new Error("options.size not allowed");
418
+ if (shouldIgnoreAdding(self)) return;
419
+ var entry = new Entry(metadataPath, false, options);
420
+ entry.uncompressedSize = buffer.length;
421
+ entry.crc32 = crc32.unsigned(buffer);
422
+ entry.crcAndFileSizeKnown = true;
423
+ self.entries.push(entry);
424
+ if (entry.compressionLevel === 0) {
425
+ setCompressedBuffer(buffer);
426
+ } else {
427
+ zlib.deflateRaw(buffer, { level: entry.compressionLevel }, function(err, compressedBuffer) {
428
+ setCompressedBuffer(compressedBuffer);
429
+ });
430
+ }
431
+ function setCompressedBuffer(compressedBuffer) {
432
+ entry.compressedSize = compressedBuffer.length;
433
+ entry.setFileDataPumpFunction(function() {
434
+ writeToOutputStream(self, compressedBuffer);
435
+ writeToOutputStream(self, entry.getDataDescriptor());
436
+ entry.state = Entry.FILE_DATA_DONE;
437
+ setImmediate(function() {
438
+ pumpEntries(self);
439
+ });
440
+ });
441
+ pumpEntries(self);
442
+ }
443
+ };
444
+ ZipFile2.prototype.addEmptyDirectory = function(metadataPath, options) {
445
+ var self = this;
446
+ metadataPath = validateMetadataPath(metadataPath, true);
447
+ if (options == null) options = {};
448
+ if (options.size != null) throw new Error("options.size not allowed");
449
+ if (options.compress != null) throw new Error("options.compress not allowed");
450
+ if (options.compressionLevel != null) throw new Error("options.compressionLevel not allowed");
451
+ if (shouldIgnoreAdding(self)) return;
452
+ var entry = new Entry(metadataPath, true, options);
453
+ self.entries.push(entry);
454
+ entry.setFileDataPumpFunction(function() {
455
+ writeToOutputStream(self, entry.getDataDescriptor());
456
+ entry.state = Entry.FILE_DATA_DONE;
457
+ pumpEntries(self);
458
+ });
459
+ pumpEntries(self);
460
+ };
461
+ var eocdrSignatureBuffer = bufferFrom([80, 75, 5, 6]);
462
+ ZipFile2.prototype.end = function(options, calculatedTotalSizeCallback) {
463
+ if (typeof options === "function") {
464
+ calculatedTotalSizeCallback = options;
465
+ options = null;
466
+ }
467
+ if (options == null) options = {};
468
+ if (this.ended) return;
469
+ this.ended = true;
470
+ if (this.errored) return;
471
+ this.calculatedTotalSizeCallback = calculatedTotalSizeCallback;
472
+ this.forceZip64Eocd = !!options.forceZip64Format;
473
+ if (options.comment) {
474
+ if (typeof options.comment === "string") {
475
+ this.comment = encodeCp437(options.comment);
476
+ } else {
477
+ this.comment = options.comment;
478
+ }
479
+ if (this.comment.length > 65535) throw new Error("comment is too large");
480
+ if (bufferIncludes(this.comment, eocdrSignatureBuffer)) throw new Error("comment contains end of central directory record signature");
481
+ } else {
482
+ this.comment = EMPTY_BUFFER;
483
+ }
484
+ pumpEntries(this);
485
+ };
486
+ function writeToOutputStream(self, buffer) {
487
+ self.outputStream.write(buffer);
488
+ self.outputStreamCursor += buffer.length;
489
+ }
490
+ function pumpFileDataReadStream(self, entry, readStream) {
491
+ var crc32Watcher = new Crc32Watcher();
492
+ var uncompressedSizeCounter = new ByteCounter();
493
+ var compressor = entry.compressionLevel !== 0 ? new zlib.DeflateRaw({ level: entry.compressionLevel }) : new PassThrough();
494
+ var compressedSizeCounter = new ByteCounter();
495
+ readStream.pipe(crc32Watcher).pipe(uncompressedSizeCounter).pipe(compressor).pipe(compressedSizeCounter).pipe(self.outputStream, { end: false });
496
+ compressedSizeCounter.on("end", function() {
497
+ entry.crc32 = crc32Watcher.crc32;
498
+ if (entry.uncompressedSize == null) {
499
+ entry.uncompressedSize = uncompressedSizeCounter.byteCount;
500
+ } else {
501
+ if (entry.uncompressedSize !== uncompressedSizeCounter.byteCount) return self.emit("error", new Error("file data stream has unexpected number of bytes"));
502
+ }
503
+ entry.compressedSize = compressedSizeCounter.byteCount;
504
+ self.outputStreamCursor += entry.compressedSize;
505
+ writeToOutputStream(self, entry.getDataDescriptor());
506
+ entry.state = Entry.FILE_DATA_DONE;
507
+ pumpEntries(self);
508
+ });
509
+ }
510
+ function determineCompressionLevel(options) {
511
+ if (options.compress != null && options.compressionLevel != null) {
512
+ if (!!options.compress !== !!options.compressionLevel) throw new Error("conflicting settings for compress and compressionLevel");
513
+ }
514
+ if (options.compressionLevel != null) return options.compressionLevel;
515
+ if (options.compress === false) return 0;
516
+ return 6;
517
+ }
518
+ function pumpEntries(self) {
519
+ if (self.allDone || self.errored) return;
520
+ if (self.ended && self.calculatedTotalSizeCallback != null) {
521
+ var calculatedTotalSize = calculateTotalSize(self);
522
+ if (calculatedTotalSize != null) {
523
+ self.calculatedTotalSizeCallback(calculatedTotalSize);
524
+ self.calculatedTotalSizeCallback = null;
525
+ }
526
+ }
527
+ var entry = getFirstNotDoneEntry();
528
+ function getFirstNotDoneEntry() {
529
+ for (var i = 0; i < self.entries.length; i++) {
530
+ var entry2 = self.entries[i];
531
+ if (entry2.state < Entry.FILE_DATA_DONE) return entry2;
532
+ }
533
+ return null;
534
+ }
535
+ if (entry != null) {
536
+ if (entry.state < Entry.READY_TO_PUMP_FILE_DATA) return;
537
+ if (entry.state === Entry.FILE_DATA_IN_PROGRESS) return;
538
+ entry.relativeOffsetOfLocalHeader = self.outputStreamCursor;
539
+ var localFileHeader = entry.getLocalFileHeader();
540
+ writeToOutputStream(self, localFileHeader);
541
+ entry.doFileDataPump();
542
+ } else {
543
+ if (self.ended) {
544
+ self.offsetOfStartOfCentralDirectory = self.outputStreamCursor;
545
+ self.entries.forEach(function(entry2) {
546
+ var centralDirectoryRecord = entry2.getCentralDirectoryRecord();
547
+ writeToOutputStream(self, centralDirectoryRecord);
548
+ });
549
+ writeToOutputStream(self, getEndOfCentralDirectoryRecord(self));
550
+ self.outputStream.end();
551
+ self.allDone = true;
552
+ }
553
+ }
554
+ }
555
+ function calculateTotalSize(self) {
556
+ var pretendOutputCursor = 0;
557
+ var centralDirectorySize = 0;
558
+ for (var i = 0; i < self.entries.length; i++) {
559
+ var entry = self.entries[i];
560
+ if (entry.compressionLevel !== 0) return -1;
561
+ if (entry.state >= Entry.READY_TO_PUMP_FILE_DATA) {
562
+ if (entry.uncompressedSize == null) return -1;
563
+ } else {
564
+ if (entry.uncompressedSize == null) return null;
565
+ }
566
+ entry.relativeOffsetOfLocalHeader = pretendOutputCursor;
567
+ var useZip64Format = entry.useZip64Format();
568
+ pretendOutputCursor += LOCAL_FILE_HEADER_FIXED_SIZE + entry.utf8FileName.length;
569
+ pretendOutputCursor += entry.uncompressedSize;
570
+ if (!entry.crcAndFileSizeKnown) {
571
+ if (useZip64Format) {
572
+ pretendOutputCursor += ZIP64_DATA_DESCRIPTOR_SIZE;
573
+ } else {
574
+ pretendOutputCursor += DATA_DESCRIPTOR_SIZE;
575
+ }
576
+ }
577
+ centralDirectorySize += CENTRAL_DIRECTORY_RECORD_FIXED_SIZE + entry.utf8FileName.length + entry.fileComment.length;
578
+ if (!entry.forceDosTimestamp) {
579
+ centralDirectorySize += INFO_ZIP_UNIVERSAL_TIMESTAMP_EXTRA_FIELD_SIZE;
580
+ }
581
+ if (useZip64Format) {
582
+ centralDirectorySize += ZIP64_EXTENDED_INFORMATION_EXTRA_FIELD_SIZE;
583
+ }
584
+ }
585
+ var endOfCentralDirectorySize = 0;
586
+ if (self.forceZip64Eocd || self.entries.length >= 65535 || centralDirectorySize >= 65535 || pretendOutputCursor >= 4294967295) {
587
+ endOfCentralDirectorySize += ZIP64_END_OF_CENTRAL_DIRECTORY_RECORD_SIZE + ZIP64_END_OF_CENTRAL_DIRECTORY_LOCATOR_SIZE;
588
+ }
589
+ endOfCentralDirectorySize += END_OF_CENTRAL_DIRECTORY_RECORD_SIZE + self.comment.length;
590
+ return pretendOutputCursor + centralDirectorySize + endOfCentralDirectorySize;
591
+ }
592
+ function shouldIgnoreAdding(self) {
593
+ if (self.ended) throw new Error("cannot add entries after calling end()");
594
+ if (self.errored) return true;
595
+ return false;
596
+ }
597
+ var ZIP64_END_OF_CENTRAL_DIRECTORY_RECORD_SIZE = 56;
598
+ var ZIP64_END_OF_CENTRAL_DIRECTORY_LOCATOR_SIZE = 20;
599
+ var END_OF_CENTRAL_DIRECTORY_RECORD_SIZE = 22;
600
+ function getEndOfCentralDirectoryRecord(self, actuallyJustTellMeHowLongItWouldBe) {
601
+ var needZip64Format = false;
602
+ var normalEntriesLength = self.entries.length;
603
+ if (self.forceZip64Eocd || self.entries.length >= 65535) {
604
+ normalEntriesLength = 65535;
605
+ needZip64Format = true;
606
+ }
607
+ var sizeOfCentralDirectory = self.outputStreamCursor - self.offsetOfStartOfCentralDirectory;
608
+ var normalSizeOfCentralDirectory = sizeOfCentralDirectory;
609
+ if (self.forceZip64Eocd || sizeOfCentralDirectory >= 4294967295) {
610
+ normalSizeOfCentralDirectory = 4294967295;
611
+ needZip64Format = true;
612
+ }
613
+ var normalOffsetOfStartOfCentralDirectory = self.offsetOfStartOfCentralDirectory;
614
+ if (self.forceZip64Eocd || self.offsetOfStartOfCentralDirectory >= 4294967295) {
615
+ normalOffsetOfStartOfCentralDirectory = 4294967295;
616
+ needZip64Format = true;
617
+ }
618
+ if (actuallyJustTellMeHowLongItWouldBe) {
619
+ if (needZip64Format) {
620
+ return ZIP64_END_OF_CENTRAL_DIRECTORY_RECORD_SIZE + ZIP64_END_OF_CENTRAL_DIRECTORY_LOCATOR_SIZE + END_OF_CENTRAL_DIRECTORY_RECORD_SIZE;
621
+ } else {
622
+ return END_OF_CENTRAL_DIRECTORY_RECORD_SIZE;
623
+ }
624
+ }
625
+ var eocdrBuffer = bufferAlloc(END_OF_CENTRAL_DIRECTORY_RECORD_SIZE + self.comment.length);
626
+ eocdrBuffer.writeUInt32LE(101010256, 0);
627
+ eocdrBuffer.writeUInt16LE(0, 4);
628
+ eocdrBuffer.writeUInt16LE(0, 6);
629
+ eocdrBuffer.writeUInt16LE(normalEntriesLength, 8);
630
+ eocdrBuffer.writeUInt16LE(normalEntriesLength, 10);
631
+ eocdrBuffer.writeUInt32LE(normalSizeOfCentralDirectory, 12);
632
+ eocdrBuffer.writeUInt32LE(normalOffsetOfStartOfCentralDirectory, 16);
633
+ eocdrBuffer.writeUInt16LE(self.comment.length, 20);
634
+ self.comment.copy(eocdrBuffer, 22);
635
+ if (!needZip64Format) return eocdrBuffer;
636
+ var zip64EocdrBuffer = bufferAlloc(ZIP64_END_OF_CENTRAL_DIRECTORY_RECORD_SIZE);
637
+ zip64EocdrBuffer.writeUInt32LE(101075792, 0);
638
+ writeUInt64LE(zip64EocdrBuffer, ZIP64_END_OF_CENTRAL_DIRECTORY_RECORD_SIZE - 12, 4);
639
+ zip64EocdrBuffer.writeUInt16LE(VERSION_MADE_BY, 12);
640
+ zip64EocdrBuffer.writeUInt16LE(VERSION_NEEDED_TO_EXTRACT_ZIP64, 14);
641
+ zip64EocdrBuffer.writeUInt32LE(0, 16);
642
+ zip64EocdrBuffer.writeUInt32LE(0, 20);
643
+ writeUInt64LE(zip64EocdrBuffer, self.entries.length, 24);
644
+ writeUInt64LE(zip64EocdrBuffer, self.entries.length, 32);
645
+ writeUInt64LE(zip64EocdrBuffer, sizeOfCentralDirectory, 40);
646
+ writeUInt64LE(zip64EocdrBuffer, self.offsetOfStartOfCentralDirectory, 48);
647
+ var zip64EocdlBuffer = bufferAlloc(ZIP64_END_OF_CENTRAL_DIRECTORY_LOCATOR_SIZE);
648
+ zip64EocdlBuffer.writeUInt32LE(117853008, 0);
649
+ zip64EocdlBuffer.writeUInt32LE(0, 4);
650
+ writeUInt64LE(zip64EocdlBuffer, self.outputStreamCursor, 8);
651
+ zip64EocdlBuffer.writeUInt32LE(1, 16);
652
+ return Buffer.concat([
653
+ zip64EocdrBuffer,
654
+ zip64EocdlBuffer,
655
+ eocdrBuffer
656
+ ]);
657
+ }
658
+ function validateMetadataPath(metadataPath, isDirectory) {
659
+ if (metadataPath === "") throw new Error("empty metadataPath");
660
+ metadataPath = metadataPath.replace(/\\/g, "/");
661
+ if (/^[a-zA-Z]:/.test(metadataPath) || /^\//.test(metadataPath)) throw new Error("absolute path: " + metadataPath);
662
+ if (metadataPath.split("/").indexOf("..") !== -1) throw new Error("invalid relative path: " + metadataPath);
663
+ var looksLikeDirectory = /\/$/.test(metadataPath);
664
+ if (isDirectory) {
665
+ if (!looksLikeDirectory) metadataPath += "/";
666
+ } else {
667
+ if (looksLikeDirectory) throw new Error("file path cannot end with '/': " + metadataPath);
668
+ }
669
+ return metadataPath;
670
+ }
671
+ var EMPTY_BUFFER = bufferAlloc(0);
672
+ function Entry(metadataPath, isDirectory, options) {
673
+ this.utf8FileName = bufferFrom(metadataPath);
674
+ if (this.utf8FileName.length > 65535) throw new Error("utf8 file name too long. " + utf8FileName.length + " > 65535");
675
+ this.isDirectory = isDirectory;
676
+ this.state = Entry.WAITING_FOR_METADATA;
677
+ this.setLastModDate(options.mtime != null ? options.mtime : /* @__PURE__ */ new Date());
678
+ this.forceDosTimestamp = !!options.forceDosTimestamp;
679
+ if (options.mode != null) {
680
+ this.setFileAttributesMode(options.mode);
681
+ } else {
682
+ this.setFileAttributesMode(isDirectory ? 16893 : 33204);
683
+ }
684
+ if (isDirectory) {
685
+ this.crcAndFileSizeKnown = true;
686
+ this.crc32 = 0;
687
+ this.uncompressedSize = 0;
688
+ this.compressedSize = 0;
689
+ } else {
690
+ this.crcAndFileSizeKnown = false;
691
+ this.crc32 = null;
692
+ this.uncompressedSize = null;
693
+ this.compressedSize = null;
694
+ if (options.size != null) this.uncompressedSize = options.size;
695
+ }
696
+ if (isDirectory) {
697
+ this.compressionLevel = 0;
698
+ } else {
699
+ this.compressionLevel = determineCompressionLevel(options);
700
+ }
701
+ this.forceZip64Format = !!options.forceZip64Format;
702
+ if (options.fileComment) {
703
+ if (typeof options.fileComment === "string") {
704
+ this.fileComment = bufferFrom(options.fileComment, "utf-8");
705
+ } else {
706
+ this.fileComment = options.fileComment;
707
+ }
708
+ if (this.fileComment.length > 65535) throw new Error("fileComment is too large");
709
+ } else {
710
+ this.fileComment = EMPTY_BUFFER;
711
+ }
712
+ }
713
+ Entry.WAITING_FOR_METADATA = 0;
714
+ Entry.READY_TO_PUMP_FILE_DATA = 1;
715
+ Entry.FILE_DATA_IN_PROGRESS = 2;
716
+ Entry.FILE_DATA_DONE = 3;
717
+ Entry.prototype.setLastModDate = function(date) {
718
+ this.mtime = date;
719
+ var dosDateTime = dateToDosDateTime(date);
720
+ this.lastModFileTime = dosDateTime.time;
721
+ this.lastModFileDate = dosDateTime.date;
722
+ };
723
+ Entry.prototype.setFileAttributesMode = function(mode) {
724
+ if ((mode & 65535) !== mode) throw new Error("invalid mode. expected: 0 <= " + mode + " <= 65535");
725
+ this.externalFileAttributes = mode << 16 >>> 0;
726
+ };
727
+ Entry.prototype.setFileDataPumpFunction = function(doFileDataPump) {
728
+ this.doFileDataPump = doFileDataPump;
729
+ this.state = Entry.READY_TO_PUMP_FILE_DATA;
730
+ };
731
+ Entry.prototype.useZip64Format = function() {
732
+ return this.forceZip64Format || this.uncompressedSize != null && this.uncompressedSize > 4294967294 || this.compressedSize != null && this.compressedSize > 4294967294 || this.relativeOffsetOfLocalHeader != null && this.relativeOffsetOfLocalHeader > 4294967294;
733
+ };
734
+ var LOCAL_FILE_HEADER_FIXED_SIZE = 30;
735
+ var VERSION_NEEDED_TO_EXTRACT_UTF8 = 20;
736
+ var VERSION_NEEDED_TO_EXTRACT_ZIP64 = 45;
737
+ var VERSION_MADE_BY = 3 << 8 | 63;
738
+ var FILE_NAME_IS_UTF8 = 1 << 11;
739
+ var UNKNOWN_CRC32_AND_FILE_SIZES = 1 << 3;
740
+ Entry.prototype.getLocalFileHeader = function() {
741
+ var crc322 = 0;
742
+ var compressedSize = 0;
743
+ var uncompressedSize = 0;
744
+ if (this.crcAndFileSizeKnown) {
745
+ crc322 = this.crc32;
746
+ compressedSize = this.compressedSize;
747
+ uncompressedSize = this.uncompressedSize;
748
+ }
749
+ var fixedSizeStuff = bufferAlloc(LOCAL_FILE_HEADER_FIXED_SIZE);
750
+ var generalPurposeBitFlag = FILE_NAME_IS_UTF8;
751
+ if (!this.crcAndFileSizeKnown) generalPurposeBitFlag |= UNKNOWN_CRC32_AND_FILE_SIZES;
752
+ fixedSizeStuff.writeUInt32LE(67324752, 0);
753
+ fixedSizeStuff.writeUInt16LE(VERSION_NEEDED_TO_EXTRACT_UTF8, 4);
754
+ fixedSizeStuff.writeUInt16LE(generalPurposeBitFlag, 6);
755
+ fixedSizeStuff.writeUInt16LE(this.getCompressionMethod(), 8);
756
+ fixedSizeStuff.writeUInt16LE(this.lastModFileTime, 10);
757
+ fixedSizeStuff.writeUInt16LE(this.lastModFileDate, 12);
758
+ fixedSizeStuff.writeUInt32LE(crc322, 14);
759
+ fixedSizeStuff.writeUInt32LE(compressedSize, 18);
760
+ fixedSizeStuff.writeUInt32LE(uncompressedSize, 22);
761
+ fixedSizeStuff.writeUInt16LE(this.utf8FileName.length, 26);
762
+ fixedSizeStuff.writeUInt16LE(0, 28);
763
+ return Buffer.concat([
764
+ fixedSizeStuff,
765
+ // file name (variable size)
766
+ this.utf8FileName
767
+ // extra field (variable size)
768
+ // no extra fields
769
+ ]);
770
+ };
771
+ var DATA_DESCRIPTOR_SIZE = 16;
772
+ var ZIP64_DATA_DESCRIPTOR_SIZE = 24;
773
+ Entry.prototype.getDataDescriptor = function() {
774
+ if (this.crcAndFileSizeKnown) {
775
+ return EMPTY_BUFFER;
776
+ }
777
+ if (!this.useZip64Format()) {
778
+ var buffer = bufferAlloc(DATA_DESCRIPTOR_SIZE);
779
+ buffer.writeUInt32LE(134695760, 0);
780
+ buffer.writeUInt32LE(this.crc32, 4);
781
+ buffer.writeUInt32LE(this.compressedSize, 8);
782
+ buffer.writeUInt32LE(this.uncompressedSize, 12);
783
+ return buffer;
784
+ } else {
785
+ var buffer = bufferAlloc(ZIP64_DATA_DESCRIPTOR_SIZE);
786
+ buffer.writeUInt32LE(134695760, 0);
787
+ buffer.writeUInt32LE(this.crc32, 4);
788
+ writeUInt64LE(buffer, this.compressedSize, 8);
789
+ writeUInt64LE(buffer, this.uncompressedSize, 16);
790
+ return buffer;
791
+ }
792
+ };
793
+ var CENTRAL_DIRECTORY_RECORD_FIXED_SIZE = 46;
794
+ var INFO_ZIP_UNIVERSAL_TIMESTAMP_EXTRA_FIELD_SIZE = 9;
795
+ var ZIP64_EXTENDED_INFORMATION_EXTRA_FIELD_SIZE = 28;
796
+ Entry.prototype.getCentralDirectoryRecord = function() {
797
+ var fixedSizeStuff = bufferAlloc(CENTRAL_DIRECTORY_RECORD_FIXED_SIZE);
798
+ var generalPurposeBitFlag = FILE_NAME_IS_UTF8;
799
+ if (!this.crcAndFileSizeKnown) generalPurposeBitFlag |= UNKNOWN_CRC32_AND_FILE_SIZES;
800
+ var izutefBuffer = EMPTY_BUFFER;
801
+ if (!this.forceDosTimestamp) {
802
+ izutefBuffer = bufferAlloc(INFO_ZIP_UNIVERSAL_TIMESTAMP_EXTRA_FIELD_SIZE);
803
+ izutefBuffer.writeUInt16LE(21589, 0);
804
+ izutefBuffer.writeUInt16LE(INFO_ZIP_UNIVERSAL_TIMESTAMP_EXTRA_FIELD_SIZE - 4, 2);
805
+ var EB_UT_FL_MTIME = 1 << 0;
806
+ var EB_UT_FL_ATIME = 1 << 1;
807
+ izutefBuffer.writeUInt8(EB_UT_FL_MTIME | EB_UT_FL_ATIME, 4);
808
+ var timestamp = Math.floor(this.mtime.getTime() / 1e3);
809
+ if (timestamp < -2147483648) timestamp = -2147483648;
810
+ if (timestamp > 2147483647) timestamp = 2147483647;
811
+ izutefBuffer.writeUInt32LE(timestamp, 5);
812
+ }
813
+ var normalCompressedSize = this.compressedSize;
814
+ var normalUncompressedSize = this.uncompressedSize;
815
+ var normalRelativeOffsetOfLocalHeader = this.relativeOffsetOfLocalHeader;
816
+ var versionNeededToExtract = VERSION_NEEDED_TO_EXTRACT_UTF8;
817
+ var zeiefBuffer = EMPTY_BUFFER;
818
+ if (this.useZip64Format()) {
819
+ normalCompressedSize = 4294967295;
820
+ normalUncompressedSize = 4294967295;
821
+ normalRelativeOffsetOfLocalHeader = 4294967295;
822
+ versionNeededToExtract = VERSION_NEEDED_TO_EXTRACT_ZIP64;
823
+ zeiefBuffer = bufferAlloc(ZIP64_EXTENDED_INFORMATION_EXTRA_FIELD_SIZE);
824
+ zeiefBuffer.writeUInt16LE(1, 0);
825
+ zeiefBuffer.writeUInt16LE(ZIP64_EXTENDED_INFORMATION_EXTRA_FIELD_SIZE - 4, 2);
826
+ writeUInt64LE(zeiefBuffer, this.uncompressedSize, 4);
827
+ writeUInt64LE(zeiefBuffer, this.compressedSize, 12);
828
+ writeUInt64LE(zeiefBuffer, this.relativeOffsetOfLocalHeader, 20);
829
+ }
830
+ fixedSizeStuff.writeUInt32LE(33639248, 0);
831
+ fixedSizeStuff.writeUInt16LE(VERSION_MADE_BY, 4);
832
+ fixedSizeStuff.writeUInt16LE(versionNeededToExtract, 6);
833
+ fixedSizeStuff.writeUInt16LE(generalPurposeBitFlag, 8);
834
+ fixedSizeStuff.writeUInt16LE(this.getCompressionMethod(), 10);
835
+ fixedSizeStuff.writeUInt16LE(this.lastModFileTime, 12);
836
+ fixedSizeStuff.writeUInt16LE(this.lastModFileDate, 14);
837
+ fixedSizeStuff.writeUInt32LE(this.crc32, 16);
838
+ fixedSizeStuff.writeUInt32LE(normalCompressedSize, 20);
839
+ fixedSizeStuff.writeUInt32LE(normalUncompressedSize, 24);
840
+ fixedSizeStuff.writeUInt16LE(this.utf8FileName.length, 28);
841
+ fixedSizeStuff.writeUInt16LE(izutefBuffer.length + zeiefBuffer.length, 30);
842
+ fixedSizeStuff.writeUInt16LE(this.fileComment.length, 32);
843
+ fixedSizeStuff.writeUInt16LE(0, 34);
844
+ fixedSizeStuff.writeUInt16LE(0, 36);
845
+ fixedSizeStuff.writeUInt32LE(this.externalFileAttributes, 38);
846
+ fixedSizeStuff.writeUInt32LE(normalRelativeOffsetOfLocalHeader, 42);
847
+ return Buffer.concat([
848
+ fixedSizeStuff,
849
+ // file name (variable size)
850
+ this.utf8FileName,
851
+ // extra field (variable size)
852
+ izutefBuffer,
853
+ zeiefBuffer,
854
+ // file comment (variable size)
855
+ this.fileComment
856
+ ]);
857
+ };
858
+ Entry.prototype.getCompressionMethod = function() {
859
+ var NO_COMPRESSION = 0;
860
+ var DEFLATE_COMPRESSION = 8;
861
+ return this.compressionLevel === 0 ? NO_COMPRESSION : DEFLATE_COMPRESSION;
862
+ };
863
+ var minDosDate = new Date(1980, 0, 1);
864
+ var maxDosDate = new Date(2107, 11, 31, 23, 59, 58);
865
+ function dateToDosDateTime(jsDate) {
866
+ if (jsDate < minDosDate) jsDate = minDosDate;
867
+ else if (jsDate > maxDosDate) jsDate = maxDosDate;
868
+ var date = 0;
869
+ date |= jsDate.getDate() & 31;
870
+ date |= (jsDate.getMonth() + 1 & 15) << 5;
871
+ date |= (jsDate.getFullYear() - 1980 & 127) << 9;
872
+ var time = 0;
873
+ time |= Math.floor(jsDate.getSeconds() / 2);
874
+ time |= (jsDate.getMinutes() & 63) << 5;
875
+ time |= (jsDate.getHours() & 31) << 11;
876
+ return { date, time };
877
+ }
878
+ function writeUInt64LE(buffer, n, offset) {
879
+ var high = Math.floor(n / 4294967296);
880
+ var low = n % 4294967296;
881
+ buffer.writeUInt32LE(low, offset);
882
+ buffer.writeUInt32LE(high, offset + 4);
883
+ }
884
+ util.inherits(ByteCounter, Transform);
885
+ function ByteCounter(options) {
886
+ Transform.call(this, options);
887
+ this.byteCount = 0;
888
+ }
889
+ ByteCounter.prototype._transform = function(chunk, encoding, cb) {
890
+ this.byteCount += chunk.length;
891
+ cb(null, chunk);
892
+ };
893
+ util.inherits(Crc32Watcher, Transform);
894
+ function Crc32Watcher(options) {
895
+ Transform.call(this, options);
896
+ this.crc32 = 0;
897
+ }
898
+ Crc32Watcher.prototype._transform = function(chunk, encoding, cb) {
899
+ this.crc32 = crc32.unsigned(chunk, this.crc32);
900
+ cb(null, chunk);
901
+ };
902
+ var cp437 = "\0\u263A\u263B\u2665\u2666\u2663\u2660\u2022\u25D8\u25CB\u25D9\u2642\u2640\u266A\u266B\u263C\u25BA\u25C4\u2195\u203C\xB6\xA7\u25AC\u21A8\u2191\u2193\u2192\u2190\u221F\u2194\u25B2\u25BC !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\u2302\xC7\xFC\xE9\xE2\xE4\xE0\xE5\xE7\xEA\xEB\xE8\xEF\xEE\xEC\xC4\xC5\xC9\xE6\xC6\xF4\xF6\xF2\xFB\xF9\xFF\xD6\xDC\xA2\xA3\xA5\u20A7\u0192\xE1\xED\xF3\xFA\xF1\xD1\xAA\xBA\xBF\u2310\xAC\xBD\xBC\xA1\xAB\xBB\u2591\u2592\u2593\u2502\u2524\u2561\u2562\u2556\u2555\u2563\u2551\u2557\u255D\u255C\u255B\u2510\u2514\u2534\u252C\u251C\u2500\u253C\u255E\u255F\u255A\u2554\u2569\u2566\u2560\u2550\u256C\u2567\u2568\u2564\u2565\u2559\u2558\u2552\u2553\u256B\u256A\u2518\u250C\u2588\u2584\u258C\u2590\u2580\u03B1\xDF\u0393\u03C0\u03A3\u03C3\xB5\u03C4\u03A6\u0398\u03A9\u03B4\u221E\u03C6\u03B5\u2229\u2261\xB1\u2265\u2264\u2320\u2321\xF7\u2248\xB0\u2219\xB7\u221A\u207F\xB2\u25A0\xA0";
903
+ if (cp437.length !== 256) throw new Error("assertion failure");
904
+ var reverseCp437 = null;
905
+ function encodeCp437(string) {
906
+ if (/^[\x20-\x7e]*$/.test(string)) {
907
+ return bufferFrom(string, "utf-8");
908
+ }
909
+ if (reverseCp437 == null) {
910
+ reverseCp437 = {};
911
+ for (var i = 0; i < cp437.length; i++) {
912
+ reverseCp437[cp437[i]] = i;
913
+ }
914
+ }
915
+ var result = bufferAlloc(string.length);
916
+ for (var i = 0; i < string.length; i++) {
917
+ var b = reverseCp437[string[i]];
918
+ if (b == null) throw new Error("character not encodable in CP437: " + JSON.stringify(string[i]));
919
+ result[i] = b;
920
+ }
921
+ return result;
922
+ }
923
+ function bufferAlloc(size) {
924
+ bufferAlloc = modern;
925
+ try {
926
+ return bufferAlloc(size);
927
+ } catch (e) {
928
+ bufferAlloc = legacy;
929
+ return bufferAlloc(size);
930
+ }
931
+ function modern(size2) {
932
+ return Buffer.allocUnsafe(size2);
933
+ }
934
+ function legacy(size2) {
935
+ return new Buffer(size2);
936
+ }
937
+ }
938
+ function bufferFrom(something, encoding) {
939
+ bufferFrom = modern;
940
+ try {
941
+ return bufferFrom(something, encoding);
942
+ } catch (e) {
943
+ bufferFrom = legacy;
944
+ return bufferFrom(something, encoding);
945
+ }
946
+ function modern(something2, encoding2) {
947
+ return Buffer.from(something2, encoding2);
948
+ }
949
+ function legacy(something2, encoding2) {
950
+ return new Buffer(something2, encoding2);
951
+ }
952
+ }
953
+ function bufferIncludes(buffer, content) {
954
+ bufferIncludes = modern;
955
+ try {
956
+ return bufferIncludes(buffer, content);
957
+ } catch (e) {
958
+ bufferIncludes = legacy;
959
+ return bufferIncludes(buffer, content);
960
+ }
961
+ function modern(buffer2, content2) {
962
+ return buffer2.includes(content2);
963
+ }
964
+ function legacy(buffer2, content2) {
965
+ for (var i = 0; i <= buffer2.length - content2.length; i++) {
966
+ for (var j = 0; ; j++) {
967
+ if (j === content2.length) return true;
968
+ if (buffer2[i + j] !== content2[j]) break;
969
+ }
970
+ }
971
+ return false;
972
+ }
973
+ }
974
+ }
975
+ });
2
976
 
3
977
  // src/cliResult.ts
4
978
  var ExitCode = {
@@ -14,8 +988,8 @@ function toJsonLine(data) {
14
988
  }
15
989
 
16
990
  // src/auto.ts
17
- import { existsSync as existsSync3, readFileSync as readFileSync3 } from "node:fs";
18
- import path5 from "node:path";
991
+ var import_node_fs4 = require("node:fs");
992
+ var import_node_path5 = __toESM(require("node:path"), 1);
19
993
 
20
994
  // ../../packages/shared-types/dist/index.js
21
995
  var TestCaseStatus;
@@ -55,8 +1029,8 @@ var Priority;
55
1029
  })(Priority || (Priority = {}));
56
1030
 
57
1031
  // src/config.ts
58
- import { existsSync, readFileSync } from "node:fs";
59
- import path from "node:path";
1032
+ var import_node_fs = require("node:fs");
1033
+ var import_node_path = __toESM(require("node:path"), 1);
60
1034
  var DEFAULT_CONFIG_FILENAME = ".testops-cli.json";
61
1035
  function parseFlags(args) {
62
1036
  const flags = {};
@@ -92,11 +1066,11 @@ function toStringValue(value) {
92
1066
  return typeof value === "string" ? value.trim() : "";
93
1067
  }
94
1068
  function readConfigFile(configPath) {
95
- if (!existsSync(configPath)) {
1069
+ if (!(0, import_node_fs.existsSync)(configPath)) {
96
1070
  return {};
97
1071
  }
98
1072
  try {
99
- const raw = readFileSync(configPath, "utf8");
1073
+ const raw = (0, import_node_fs.readFileSync)(configPath, "utf8");
100
1074
  const parsed = JSON.parse(raw);
101
1075
  return typeof parsed === "object" && parsed !== null ? parsed : {};
102
1076
  } catch {
@@ -129,9 +1103,9 @@ function valueFromPrecedence(key, flagValue, envValue, fileValue, fallback = "")
129
1103
  }
130
1104
  function resolveCliConfig(args, env = process.env, cwd = process.cwd()) {
131
1105
  const { flags, unknownFlags } = parseFlags(args);
132
- const configPathFlag = flags["--config"] ? path.resolve(cwd, flags["--config"]) : "";
1106
+ const configPathFlag = flags["--config"] ? import_node_path.default.resolve(cwd, flags["--config"]) : "";
133
1107
  const configPathEnv = toStringValue(env.TESTOPS_CONFIG_PATH);
134
- const configPath = configPathFlag || (configPathEnv ? path.resolve(cwd, configPathEnv) : path.resolve(cwd, DEFAULT_CONFIG_FILENAME));
1108
+ const configPath = configPathFlag || (configPathEnv ? import_node_path.default.resolve(cwd, configPathEnv) : import_node_path.default.resolve(cwd, DEFAULT_CONFIG_FILENAME));
135
1109
  const configPathSource = configPathFlag ? "flag" : configPathEnv ? "env" : "default";
136
1110
  const file = readConfigFile(configPath);
137
1111
  const baseUrlResolved = valueFromPrecedence(
@@ -193,7 +1167,7 @@ function resolveCliConfig(args, env = process.env, cwd = process.cwd()) {
193
1167
  if (unknownFlags.length > 0) {
194
1168
  warnings.push(`Ignored unknown config flags: ${unknownFlags.join(", ")}`);
195
1169
  }
196
- if (!existsSync(configPath) && sources.configPath !== "default") {
1170
+ if (!(0, import_node_fs.existsSync)(configPath) && sources.configPath !== "default") {
197
1171
  warnings.push(`Config file not found at ${configPath}; using env/flags/defaults.`);
198
1172
  }
199
1173
  return { values: config, sources, warnings };
@@ -570,7 +1544,7 @@ function diagExecutionNoWork() {
570
1544
  }
571
1545
 
572
1546
  // src/autoDiscover.ts
573
- import path2 from "node:path";
1547
+ var import_node_path2 = __toESM(require("node:path"), 1);
574
1548
  var RESULT_FOLDER_NAMES = /* @__PURE__ */ new Set([
575
1549
  "results",
576
1550
  "result",
@@ -582,7 +1556,7 @@ var RESULT_FOLDER_NAMES = /* @__PURE__ */ new Set([
582
1556
  "failsafe-reports"
583
1557
  ]);
584
1558
  function toPosix2(value) {
585
- return value.split(path2.sep).join("/");
1559
+ return value.split(import_node_path2.default.sep).join("/");
586
1560
  }
587
1561
  function isJUnitXmlArtifact(filePath) {
588
1562
  const normalized = toPosix2(filePath);
@@ -674,8 +1648,8 @@ function discoverFeatureFiles(scannedFiles) {
674
1648
  }
675
1649
 
676
1650
  // src/autoMapping.ts
677
- import { existsSync as existsSync2, readFileSync as readFileSync2 } from "node:fs";
678
- import path3 from "node:path";
1651
+ var import_node_fs2 = require("node:fs");
1652
+ var import_node_path3 = __toESM(require("node:path"), 1);
679
1653
  var ISSUE_KEY_REGEX = /\b[A-Z][A-Z0-9]+-\d+\b/g;
680
1654
  function normalizeName(value) {
681
1655
  return value.trim().toLowerCase();
@@ -685,10 +1659,10 @@ function extractIssueKeysFromText(text) {
685
1659
  return [...new Set(found)].sort((a, b) => a.localeCompare(b));
686
1660
  }
687
1661
  function parseFeatureFile(featureAbsolutePath) {
688
- if (!existsSync2(featureAbsolutePath)) {
1662
+ if (!(0, import_node_fs2.existsSync)(featureAbsolutePath)) {
689
1663
  return { names: [], issueKeys: [] };
690
1664
  }
691
- const raw = readFileSync2(featureAbsolutePath, "utf8");
1665
+ const raw = (0, import_node_fs2.readFileSync)(featureAbsolutePath, "utf8");
692
1666
  const lines = raw.split(/\r?\n/);
693
1667
  const names = /* @__PURE__ */ new Set();
694
1668
  const issueKeys = new Set(extractIssueKeysFromText(raw));
@@ -746,7 +1720,7 @@ function buildMappingPreview(input) {
746
1720
  const localNamesSet = /* @__PURE__ */ new Set();
747
1721
  const issueCandidatesSet = /* @__PURE__ */ new Set();
748
1722
  for (const featurePath of input.featurePaths) {
749
- const absolutePath = path3.join(input.rootPath, featurePath);
1723
+ const absolutePath = import_node_path3.default.join(input.rootPath, featurePath);
750
1724
  const parsed = parseFeatureFile(absolutePath);
751
1725
  for (const name of parsed.names) {
752
1726
  localNamesSet.add(name);
@@ -795,8 +1769,8 @@ function buildMappingPreview(input) {
795
1769
  }
796
1770
 
797
1771
  // src/autoScanner.ts
798
- import { readdirSync } from "node:fs";
799
- import path4 from "node:path";
1772
+ var import_node_fs3 = require("node:fs");
1773
+ var import_node_path4 = __toESM(require("node:path"), 1);
800
1774
  var DEFAULT_MAX_DEPTH = 5;
801
1775
  var DEFAULT_EXCLUDED_DIRECTORIES = /* @__PURE__ */ new Set([
802
1776
  ".cache",
@@ -811,7 +1785,7 @@ var DEFAULT_EXCLUDED_DIRECTORIES = /* @__PURE__ */ new Set([
811
1785
  "node_modules"
812
1786
  ]);
813
1787
  function normalizeRelativePath(value) {
814
- return value.split(path4.sep).join("/");
1788
+ return value.split(import_node_path4.default.sep).join("/");
815
1789
  }
816
1790
  function normalizePatterns(values) {
817
1791
  if (!values) {
@@ -865,16 +1839,16 @@ function scanProjectFiles(options) {
865
1839
  const includePatterns = normalizePatterns(options.includePatterns);
866
1840
  const excludePatterns = normalizePatterns(options.excludePatterns);
867
1841
  const maxDepth = safeMaxDepth(options.maxDepth);
868
- const rootPath = path4.resolve(options.rootPath);
1842
+ const rootPath = import_node_path4.default.resolve(options.rootPath);
869
1843
  const scannedFiles = [];
870
1844
  const visit = (absoluteDirectory, depth) => {
871
1845
  if (depth > maxDepth) {
872
1846
  return;
873
1847
  }
874
- const entries = readdirSync(absoluteDirectory, { withFileTypes: true }).slice().sort((a, b) => a.name.localeCompare(b.name));
1848
+ const entries = (0, import_node_fs3.readdirSync)(absoluteDirectory, { withFileTypes: true }).slice().sort((a, b) => a.name.localeCompare(b.name));
875
1849
  for (const entry of entries) {
876
- const absoluteEntryPath = path4.join(absoluteDirectory, entry.name);
877
- const relativeEntryPath = normalizeRelativePath(path4.relative(rootPath, absoluteEntryPath));
1850
+ const absoluteEntryPath = import_node_path4.default.join(absoluteDirectory, entry.name);
1851
+ const relativeEntryPath = normalizeRelativePath(import_node_path4.default.relative(rootPath, absoluteEntryPath));
878
1852
  if (!relativeEntryPath) {
879
1853
  continue;
880
1854
  }
@@ -981,10 +1955,10 @@ function resolveRoot(rootFlag, cwd) {
981
1955
  if (!rootFlag.trim()) {
982
1956
  return cwd;
983
1957
  }
984
- return path5.resolve(cwd, rootFlag);
1958
+ return import_node_path5.default.resolve(cwd, rootFlag);
985
1959
  }
986
1960
  function countScenariosInFeatureFile(featurePath) {
987
- const lines = readFileSync3(featurePath, "utf8").split(/\r?\n/).map((line) => line.trim().toLowerCase());
1961
+ const lines = (0, import_node_fs4.readFileSync)(featurePath, "utf8").split(/\r?\n/).map((line) => line.trim().toLowerCase());
988
1962
  let count = 0;
989
1963
  for (const line of lines) {
990
1964
  if (line.startsWith("scenario:") || line.startsWith("scenario outline:")) {
@@ -996,8 +1970,8 @@ function countScenariosInFeatureFile(featurePath) {
996
1970
  function buildScenarioStats(rootPath, featurePaths) {
997
1971
  let scenarios = 0;
998
1972
  for (const relativePath of featurePaths) {
999
- const absolutePath = path5.join(rootPath, relativePath);
1000
- if (!existsSync3(absolutePath)) {
1973
+ const absolutePath = import_node_path5.default.join(rootPath, relativePath);
1974
+ if (!(0, import_node_fs4.existsSync)(absolutePath)) {
1001
1975
  continue;
1002
1976
  }
1003
1977
  scenarios += countScenariosInFeatureFile(absolutePath);
@@ -1037,7 +2011,7 @@ function deriveFeatureNameFromGherkin(gherkin, fallbackPath) {
1037
2011
  return match[1].trim();
1038
2012
  }
1039
2013
  }
1040
- return path5.basename(fallbackPath, path5.extname(fallbackPath));
2014
+ return import_node_path5.default.basename(fallbackPath, import_node_path5.default.extname(fallbackPath));
1041
2015
  }
1042
2016
  function mapStepStatus(status) {
1043
2017
  const normalized = status.trim().toLowerCase();
@@ -1053,13 +2027,13 @@ function mapStepStatus(status) {
1053
2027
  return StepResult.Blocked;
1054
2028
  }
1055
2029
  function parseCucumberRunsFromArtifact(rootPath, artifactPath) {
1056
- const absolutePath = path5.join(rootPath, artifactPath);
1057
- if (!existsSync3(absolutePath)) {
2030
+ const absolutePath = import_node_path5.default.join(rootPath, artifactPath);
2031
+ if (!(0, import_node_fs4.existsSync)(absolutePath)) {
1058
2032
  return [];
1059
2033
  }
1060
2034
  let parsed;
1061
2035
  try {
1062
- parsed = JSON.parse(readFileSync3(absolutePath, "utf8"));
2036
+ parsed = JSON.parse((0, import_node_fs4.readFileSync)(absolutePath, "utf8"));
1063
2037
  } catch {
1064
2038
  return [];
1065
2039
  }
@@ -1154,15 +2128,15 @@ async function executeUploadFlow(input) {
1154
2128
  const diagnostics = [];
1155
2129
  const orderedFeatures = [...input.featurePaths].sort((a, b) => a.localeCompare(b));
1156
2130
  for (const featurePath of orderedFeatures) {
1157
- const absolutePath = path5.join(input.rootPath, featurePath);
1158
- if (!existsSync3(absolutePath)) {
2131
+ const absolutePath = import_node_path5.default.join(input.rootPath, featurePath);
2132
+ if (!(0, import_node_fs4.existsSync)(absolutePath)) {
1159
2133
  featureFailed += 1;
1160
2134
  const diagnostic = diagUploadFeatureFailure(featurePath, "missing feature file");
1161
2135
  errors.push(diagnostic.message);
1162
2136
  diagnostics.push(diagnostic);
1163
2137
  continue;
1164
2138
  }
1165
- const gherkin = readFileSync3(absolutePath, "utf8");
2139
+ const gherkin = (0, import_node_fs4.readFileSync)(absolutePath, "utf8");
1166
2140
  const name = deriveFeatureNameFromGherkin(gherkin, featurePath);
1167
2141
  const payload = {
1168
2142
  context: {
@@ -1501,7 +2475,7 @@ function createAutoHandler(deps = {}) {
1501
2475
  stderr: ["ERROR: --output must be either 'plain' or 'json'."]
1502
2476
  };
1503
2477
  }
1504
- if (!existsSync3(rootPath)) {
2478
+ if (!(0, import_node_fs4.existsSync)(rootPath)) {
1505
2479
  return {
1506
2480
  exitCode: ExitCode.ValidationError,
1507
2481
  stderr: [`ERROR: Root path does not exist: ${rootPath}`]
@@ -1606,6 +2580,11 @@ function createAutoHandler(deps = {}) {
1606
2580
  };
1607
2581
  }
1608
2582
 
2583
+ // src/bdd.ts
2584
+ var import_node_fs5 = require("node:fs");
2585
+ var import_node_path6 = __toESM(require("node:path"), 1);
2586
+ var import_yazl = __toESM(require_yazl(), 1);
2587
+
1609
2588
  // src/forgeClient.ts
1610
2589
  var ForgeClientError = class extends Error {
1611
2590
  code;
@@ -1772,8 +2751,17 @@ function parseArgs2(args) {
1772
2751
  const flags = {};
1773
2752
  const boolFlags = /* @__PURE__ */ new Set();
1774
2753
  const unknownFlags = [];
1775
- const supportedValueFlags = /* @__PURE__ */ new Set(["--id", "--test-case-key", ...CONFIG_FLAGS2]);
1776
- const supportedBoolFlags = /* @__PURE__ */ new Set(["--json"]);
2754
+ const supportedValueFlags = /* @__PURE__ */ new Set([
2755
+ "--id",
2756
+ "--test-case-key",
2757
+ "--format",
2758
+ "--output-dir",
2759
+ "--input-dir",
2760
+ "--feature-id",
2761
+ "--file",
2762
+ ...CONFIG_FLAGS2
2763
+ ]);
2764
+ const supportedBoolFlags = /* @__PURE__ */ new Set(["--json", "--zip", "--all"]);
1777
2765
  for (let index = 0; index < args.length; index += 1) {
1778
2766
  const token = args[index];
1779
2767
  if (!token.startsWith("--")) {
@@ -1831,6 +2819,94 @@ function toJsonScenario(scenario) {
1831
2819
  updatedAt: scenario.updatedAt
1832
2820
  };
1833
2821
  }
2822
+ function scenarioToFeatureLines(scenario) {
2823
+ const lines = [];
2824
+ const tagSet = /* @__PURE__ */ new Set();
2825
+ tagSet.add(`@testops-scenario-${sanitizeFileToken(scenario.key ?? scenario.id)}`);
2826
+ for (const tag of scenario.tags) {
2827
+ tagSet.add(tag);
2828
+ }
2829
+ for (const issueKey of scenario.linkedIssueKeys) {
2830
+ tagSet.add(`@${issueKey}`);
2831
+ }
2832
+ if (tagSet.size > 0) {
2833
+ lines.push([...tagSet].join(" "));
2834
+ }
2835
+ lines.push(`Feature: ${scenario.featureName}`);
2836
+ lines.push("");
2837
+ lines.push(`Scenario: ${scenario.name}`);
2838
+ for (const step of scenario.steps) {
2839
+ lines.push(` ${step.keyword} ${step.text}`);
2840
+ }
2841
+ return lines;
2842
+ }
2843
+ function scenarioToExportFileName(scenario) {
2844
+ return `${sanitizeFileToken(scenario.key ?? scenario.id)}.feature`;
2845
+ }
2846
+ var ISSUE_KEY_PATTERN = /^[A-Z][A-Z0-9]+-\d+$/;
2847
+ var SCENARIO_METADATA_PATTERN = /^@testops-scenario-([A-Za-z0-9._-]+)$/i;
2848
+ function parseScenarioFeatureFile(raw, filePath) {
2849
+ let featureName = "";
2850
+ let scenarioName = "";
2851
+ let scenarioCount = 0;
2852
+ const tags = [];
2853
+ const steps = [];
2854
+ let inScenario = false;
2855
+ for (const rawLine of raw.split(/\r?\n/)) {
2856
+ const line = rawLine.trim();
2857
+ if (!line) {
2858
+ continue;
2859
+ }
2860
+ if (line.startsWith("@") && !inScenario && !scenarioName) {
2861
+ tags.push(...line.split(/\s+/).filter(Boolean));
2862
+ continue;
2863
+ }
2864
+ if (line.toLowerCase().startsWith("feature:")) {
2865
+ featureName = line.slice("feature:".length).trim();
2866
+ continue;
2867
+ }
2868
+ const scenarioMatch = line.match(/^Scenario(?: Outline)?:\s*(.+)$/i);
2869
+ if (scenarioMatch) {
2870
+ scenarioCount += 1;
2871
+ if (scenarioCount > 1) {
2872
+ return null;
2873
+ }
2874
+ scenarioName = scenarioMatch[1].trim();
2875
+ inScenario = true;
2876
+ continue;
2877
+ }
2878
+ const stepMatch = line.match(/^(Given|When|Then|And|But)\s+(.+)$/);
2879
+ if (stepMatch) {
2880
+ steps.push({
2881
+ keyword: stepMatch[1],
2882
+ text: stepMatch[2].trim()
2883
+ });
2884
+ continue;
2885
+ }
2886
+ }
2887
+ const scenarioTag = tags.map((tag) => tag.match(SCENARIO_METADATA_PATTERN)).find((match) => Boolean(match));
2888
+ const scenarioKeyFromTag = scenarioTag?.[1]?.trim().toUpperCase() ?? "";
2889
+ const fileKeyMatch = import_node_path6.default.basename(filePath ?? "").match(/^(SC-\d+)\.feature$/i);
2890
+ const scenarioKeyFromFile = fileKeyMatch?.[1]?.trim().toUpperCase() ?? "";
2891
+ const scenarioKey = scenarioKeyFromTag || scenarioKeyFromFile;
2892
+ if (scenarioKeyFromTag && scenarioKeyFromFile && scenarioKeyFromTag !== scenarioKeyFromFile) {
2893
+ return null;
2894
+ }
2895
+ if (!featureName || !scenarioName || !scenarioKey || steps.length === 0 || scenarioCount !== 1) {
2896
+ return null;
2897
+ }
2898
+ const linkedIssueKeys = [...new Set(
2899
+ tags.map((tag) => tag.replace(/^@/, "").trim().toUpperCase()).filter((tag) => ISSUE_KEY_PATTERN.test(tag))
2900
+ )];
2901
+ return {
2902
+ scenarioKey,
2903
+ featureName,
2904
+ scenarioName,
2905
+ tags,
2906
+ linkedIssueKeys,
2907
+ steps
2908
+ };
2909
+ }
1834
2910
  function scenarioToLines(scenario) {
1835
2911
  const lines = [
1836
2912
  `BDD scenario: ${scenario.name}`,
@@ -1847,6 +2923,64 @@ function scenarioToLines(scenario) {
1847
2923
  }
1848
2924
  return lines;
1849
2925
  }
2926
+ function featureToLines(feature) {
2927
+ return [
2928
+ `BDD feature: ${feature.payload.name}`,
2929
+ `Feature id: ${feature.id}`,
2930
+ `Project: ${feature.projectKey}`,
2931
+ `Linked issues: ${feature.linkedIssueKeys.join(", ") || "none"}`,
2932
+ `Created: ${feature.createdAt}`,
2933
+ `Scenarios: ${feature.parsedSummary.scenarios}`,
2934
+ `Steps: ${feature.parsedSummary.steps}`,
2935
+ `Lines: ${feature.parsedSummary.lines}`
2936
+ ];
2937
+ }
2938
+ function slugifyFeatureName(value) {
2939
+ return value.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || "feature";
2940
+ }
2941
+ function sanitizeFileToken(value) {
2942
+ return value.trim().replace(/[^A-Za-z0-9._-]+/g, "-").replace(/^-+|-+$/g, "") || "feature";
2943
+ }
2944
+ function buildFeatureExportFileName(feature, index) {
2945
+ const slug = slugifyFeatureName(feature.payload.name);
2946
+ const ordinal = String(index + 1).padStart(3, "0");
2947
+ return `${ordinal}-${slug}.feature`;
2948
+ }
2949
+ function toExportManifestItems(features, fileNames) {
2950
+ return features.map((feature, index) => ({
2951
+ id: feature.id,
2952
+ name: feature.payload.name,
2953
+ fileName: fileNames[index],
2954
+ linkedIssueKeys: [...feature.linkedIssueKeys],
2955
+ scenarioCount: feature.parsedSummary.scenarios,
2956
+ stepCount: feature.parsedSummary.steps,
2957
+ createdAt: feature.createdAt
2958
+ }));
2959
+ }
2960
+ function toJsonExportManifestItems(items) {
2961
+ return items.map((item) => ({
2962
+ id: item.id,
2963
+ name: item.name,
2964
+ fileName: item.fileName,
2965
+ linkedIssueKeys: [...item.linkedIssueKeys],
2966
+ scenarioCount: item.scenarioCount,
2967
+ stepCount: item.stepCount,
2968
+ createdAt: item.createdAt
2969
+ }));
2970
+ }
2971
+ async function defaultCreateZipArchive(archivePath, entries) {
2972
+ await new Promise((resolve, reject) => {
2973
+ const zip = new import_yazl.ZipFile();
2974
+ const output = zip.outputStream.pipe((0, import_node_fs5.createWriteStream)(archivePath));
2975
+ output.on("close", () => resolve());
2976
+ output.on("error", reject);
2977
+ zip.outputStream.on("error", reject);
2978
+ for (const entry of entries) {
2979
+ zip.addBuffer(Buffer.from(entry.content, "utf8"), entry.fileName);
2980
+ }
2981
+ zip.end();
2982
+ });
2983
+ }
1850
2984
  function automationToLines(payload, scenarioKey) {
1851
2985
  return [
1852
2986
  `Triggered scenario automation for ${scenarioKey}`,
@@ -1867,10 +3001,16 @@ function missingProjectResponse() {
1867
3001
  function createBddHandler(deps = {}) {
1868
3002
  const cwd = deps.cwd ?? process.cwd();
1869
3003
  const env = deps.env ?? process.env;
3004
+ const mkdir = deps.mkdir ?? ((targetPath, options) => (0, import_node_fs5.mkdirSync)(targetPath, options));
3005
+ const readFile = deps.readFile ?? ((filePath) => (0, import_node_fs5.readFileSync)(filePath, "utf8"));
3006
+ const readDir = deps.readDir ?? ((dirPath) => (0, import_node_fs5.readdirSync)(dirPath));
3007
+ const writeFile = deps.writeFile ?? ((filePath, content) => (0, import_node_fs5.writeFileSync)(filePath, content, "utf8"));
3008
+ const createZipArchive = deps.createZipArchive ?? defaultCreateZipArchive;
1870
3009
  return async (request, context) => {
1871
3010
  const [subcommand, ...restArgs] = request.args;
1872
3011
  const parsed = parseArgs2(restArgs);
1873
- const useJson = parsed.boolFlags.has("--json");
3012
+ const requestedFormat = (parsed.flags["--format"] ?? "").trim().toLowerCase();
3013
+ const outputFormat = parsed.boolFlags.has("--json") ? "json" : requestedFormat || "text";
1874
3014
  const config = resolveCliConfig(pickConfigArgs2(parsed), env, cwd);
1875
3015
  const projectKey = config.values.projectKey;
1876
3016
  const issueKey = config.values.issueKey;
@@ -1880,20 +3020,373 @@ function createBddHandler(deps = {}) {
1880
3020
  stderr: [`ERROR: Unknown or invalid flags: ${parsed.unknownFlags.join(", ")}`]
1881
3021
  };
1882
3022
  }
3023
+ if (!["text", "json", "feature"].includes(outputFormat)) {
3024
+ return {
3025
+ exitCode: ExitCode.ValidationError,
3026
+ stderr: ["ERROR: Unsupported --format. Use one of: text, json, feature."]
3027
+ };
3028
+ }
1883
3029
  if (!projectKey) {
1884
3030
  return missingProjectResponse();
1885
3031
  }
3032
+ if (subcommand === "features") {
3033
+ const nested = restArgs[0];
3034
+ if (nested !== "export") {
3035
+ return {
3036
+ exitCode: ExitCode.UsageError,
3037
+ stderr: [
3038
+ "ERROR: Unsupported bdd features subcommand. Use: testops bdd features export --output-dir <path> [--feature-id <FEATURE_ID>] [--json]"
3039
+ ]
3040
+ };
3041
+ }
3042
+ const outputDirFlag = parsed.flags["--output-dir"]?.trim() ?? "";
3043
+ const featureId = parsed.flags["--feature-id"]?.trim() ?? "";
3044
+ const zipRequested = parsed.boolFlags.has("--zip");
3045
+ if (!outputDirFlag) {
3046
+ return {
3047
+ exitCode: ExitCode.ValidationError,
3048
+ stderr: ["ERROR: Missing required --output-dir for testops bdd features export."]
3049
+ };
3050
+ }
3051
+ const outputDir = import_node_path6.default.resolve(cwd, outputDirFlag);
3052
+ try {
3053
+ const result = await context.invokeForgeContract("listBddFeatures", {
3054
+ context: {
3055
+ projectKey,
3056
+ issueKey: issueKey || void 0
3057
+ }
3058
+ });
3059
+ if (!result.ok) {
3060
+ return {
3061
+ exitCode: ExitCode.RemoteError,
3062
+ stderr: [`ERROR: ${result.error.code}: ${result.error.message}`]
3063
+ };
3064
+ }
3065
+ const features = (featureId ? result.data.filter((feature) => feature.id === featureId) : result.data).sort((left, right) => left.payload.name.localeCompare(right.payload.name) || left.createdAt.localeCompare(right.createdAt));
3066
+ if (featureId && features.length === 0) {
3067
+ return {
3068
+ exitCode: ExitCode.RemoteError,
3069
+ stderr: [`ERROR: NOT_FOUND: BDD feature ${featureId} was not found in this project.`]
3070
+ };
3071
+ }
3072
+ if (features.length === 0) {
3073
+ return {
3074
+ exitCode: ExitCode.RemoteError,
3075
+ stderr: ["ERROR: NOT_FOUND: No BDD features were found in this project context."]
3076
+ };
3077
+ }
3078
+ mkdir(outputDir, { recursive: true });
3079
+ const fileNames = features.map((feature, index) => buildFeatureExportFileName(feature, index));
3080
+ const manifestItems = toExportManifestItems(features, fileNames);
3081
+ const exportEntries = features.map((feature, index) => ({
3082
+ fileName: fileNames[index],
3083
+ content: `${feature.payload.gherkin.trimEnd()}
3084
+ `
3085
+ }));
3086
+ for (let index = 0; index < features.length; index += 1) {
3087
+ writeFile(import_node_path6.default.join(outputDir, fileNames[index]), exportEntries[index].content);
3088
+ }
3089
+ const manifest = {
3090
+ action: "bdd-features-export",
3091
+ projectKey,
3092
+ issueKey: issueKey || null,
3093
+ outputDir,
3094
+ exportedAt: (/* @__PURE__ */ new Date()).toISOString(),
3095
+ count: features.length,
3096
+ items: manifestItems
3097
+ };
3098
+ const manifestContent = `${JSON.stringify(manifest, null, 2)}
3099
+ `;
3100
+ writeFile(import_node_path6.default.join(outputDir, "manifest.json"), manifestContent);
3101
+ const archivePath = `${outputDir}.zip`;
3102
+ if (zipRequested) {
3103
+ await createZipArchive(archivePath, [
3104
+ ...exportEntries,
3105
+ { fileName: "manifest.json", content: manifestContent }
3106
+ ]);
3107
+ }
3108
+ if (outputFormat === "json") {
3109
+ return {
3110
+ exitCode: ExitCode.Success,
3111
+ stdout: toJsonLine({
3112
+ action: manifest.action,
3113
+ projectKey: manifest.projectKey,
3114
+ issueKey: manifest.issueKey,
3115
+ outputDir: manifest.outputDir,
3116
+ exportedAt: manifest.exportedAt,
3117
+ count: manifest.count,
3118
+ items: toJsonExportManifestItems(manifestItems),
3119
+ archivePath: zipRequested ? archivePath : null
3120
+ })
3121
+ };
3122
+ }
3123
+ return {
3124
+ exitCode: ExitCode.Success,
3125
+ stdout: [
3126
+ `BDD features exported: ${features.length}`,
3127
+ `Output directory: ${outputDir}`,
3128
+ ...zipRequested ? [`ZIP archive: ${archivePath}`] : [],
3129
+ "Files:",
3130
+ ...manifestItems.flatMap((item) => [
3131
+ `- ${item.fileName}`,
3132
+ ...featureToLines(features.find((feature) => feature.id === item.id))
3133
+ ])
3134
+ ]
3135
+ };
3136
+ } catch (error) {
3137
+ return {
3138
+ exitCode: ExitCode.TransportError,
3139
+ stderr: [`ERROR: ${normalizeError(error)}`]
3140
+ };
3141
+ }
3142
+ }
1886
3143
  if (subcommand === "scenarios") {
1887
3144
  const nested = restArgs[0];
1888
3145
  if (nested !== "show") {
1889
- if (nested !== "run") {
3146
+ if (nested !== "run" && nested !== "export" && nested !== "import") {
1890
3147
  return {
1891
3148
  exitCode: ExitCode.UsageError,
1892
3149
  stderr: [
1893
- "ERROR: Unsupported bdd scenarios subcommand. Use: testops bdd scenarios show --id <SCENARIO_ID> or testops bdd scenarios run --id <SCENARIO_ID> --test-case-key <TC-197>"
3150
+ "ERROR: Unsupported bdd scenarios subcommand. Use: testops bdd scenarios show|run|export|import ..."
1894
3151
  ]
1895
3152
  };
1896
3153
  }
3154
+ if (nested === "export") {
3155
+ const scenarioSelector = parsed.flags["--id"]?.trim() ?? "";
3156
+ const exportAll = parsed.boolFlags.has("--all");
3157
+ const outputDirFlag = parsed.flags["--output-dir"]?.trim() ?? "";
3158
+ if (!scenarioSelector && !exportAll) {
3159
+ return {
3160
+ exitCode: ExitCode.ValidationError,
3161
+ stderr: ["ERROR: Provide --id <SCENARIO_ID|SC-4> or --all for testops bdd scenarios export."]
3162
+ };
3163
+ }
3164
+ if (!outputDirFlag) {
3165
+ return {
3166
+ exitCode: ExitCode.ValidationError,
3167
+ stderr: ["ERROR: Missing required --output-dir for testops bdd scenarios export."]
3168
+ };
3169
+ }
3170
+ const outputDir = import_node_path6.default.resolve(cwd, outputDirFlag);
3171
+ const zipRequested = parsed.boolFlags.has("--zip");
3172
+ try {
3173
+ const scenariosResult = await context.invokeForgeContract("listBddScenarios", {
3174
+ context: {
3175
+ projectKey,
3176
+ issueKey: issueKey || void 0
3177
+ }
3178
+ });
3179
+ if (!scenariosResult.ok) {
3180
+ return {
3181
+ exitCode: ExitCode.RemoteError,
3182
+ stderr: [`ERROR: ${scenariosResult.error.code}: ${scenariosResult.error.message}`]
3183
+ };
3184
+ }
3185
+ const selectedScenarios = exportAll ? [...scenariosResult.data].sort((left, right) => (left.key ?? left.id).localeCompare(right.key ?? right.id)) : scenariosResult.data.filter(
3186
+ (item) => item.id === scenarioSelector || (item.key ?? "").toUpperCase() === scenarioSelector.toUpperCase()
3187
+ );
3188
+ if (!exportAll && selectedScenarios.length === 0) {
3189
+ return {
3190
+ exitCode: ExitCode.RemoteError,
3191
+ stderr: [`ERROR: NOT_FOUND: BDD scenario ${scenarioSelector} was not found in this project.`]
3192
+ };
3193
+ }
3194
+ if (selectedScenarios.length === 0) {
3195
+ return {
3196
+ exitCode: ExitCode.RemoteError,
3197
+ stderr: ["ERROR: NOT_FOUND: No BDD scenarios were found in this project context."]
3198
+ };
3199
+ }
3200
+ mkdir(outputDir, { recursive: true });
3201
+ const items = selectedScenarios.map((scenario) => {
3202
+ const fileName = scenarioToExportFileName(scenario);
3203
+ const fileContent = `${scenarioToFeatureLines(scenario).join("\n")}
3204
+ `;
3205
+ writeFile(import_node_path6.default.join(outputDir, fileName), fileContent);
3206
+ return {
3207
+ scenario,
3208
+ fileName,
3209
+ fileContent
3210
+ };
3211
+ });
3212
+ const manifest = {
3213
+ action: "bdd-scenarios-export",
3214
+ projectKey,
3215
+ issueKey: issueKey || null,
3216
+ outputDir,
3217
+ exportedAt: (/* @__PURE__ */ new Date()).toISOString(),
3218
+ count: items.length,
3219
+ items: items.map(({ scenario, fileName }) => ({
3220
+ id: scenario.id,
3221
+ key: scenario.key ?? null,
3222
+ featureName: scenario.featureName,
3223
+ scenarioName: scenario.name,
3224
+ fileName,
3225
+ linkedIssueKeys: [...scenario.linkedIssueKeys],
3226
+ tags: [...scenario.tags]
3227
+ }))
3228
+ };
3229
+ const manifestContent = `${JSON.stringify(manifest, null, 2)}
3230
+ `;
3231
+ writeFile(import_node_path6.default.join(outputDir, "manifest.json"), manifestContent);
3232
+ const archivePath = `${outputDir}.zip`;
3233
+ if (zipRequested) {
3234
+ await createZipArchive(archivePath, [
3235
+ ...items.map(({ fileName, fileContent }) => ({ fileName, content: fileContent })),
3236
+ { fileName: "manifest.json", content: manifestContent }
3237
+ ]);
3238
+ }
3239
+ if (outputFormat === "json") {
3240
+ return {
3241
+ exitCode: ExitCode.Success,
3242
+ stdout: toJsonLine({
3243
+ action: manifest.action,
3244
+ projectKey,
3245
+ issueKey: issueKey || null,
3246
+ outputDir,
3247
+ exportedAt: manifest.exportedAt,
3248
+ count: items.length,
3249
+ archivePath: zipRequested ? archivePath : null,
3250
+ items: items.map(({ scenario, fileName }) => ({
3251
+ id: scenario.id,
3252
+ key: scenario.key ?? null,
3253
+ featureName: scenario.featureName,
3254
+ scenarioName: scenario.name,
3255
+ fileName,
3256
+ linkedIssueKeys: [...scenario.linkedIssueKeys],
3257
+ tags: [...scenario.tags]
3258
+ }))
3259
+ })
3260
+ };
3261
+ }
3262
+ return {
3263
+ exitCode: ExitCode.Success,
3264
+ stdout: [
3265
+ `BDD scenarios exported: ${items.length}`,
3266
+ `Output directory: ${outputDir}`,
3267
+ ...zipRequested ? [`ZIP archive: ${archivePath}`] : [],
3268
+ ...items.flatMap(({ scenario, fileName }) => [`File: ${fileName}`, ...scenarioToLines(scenario)])
3269
+ ]
3270
+ };
3271
+ } catch (error) {
3272
+ return {
3273
+ exitCode: ExitCode.TransportError,
3274
+ stderr: [`ERROR: ${normalizeError(error)}`]
3275
+ };
3276
+ }
3277
+ }
3278
+ if (nested === "import") {
3279
+ const sourceFile = parsed.flags["--file"] ? import_node_path6.default.resolve(cwd, parsed.flags["--file"]) : "";
3280
+ const inputDir = parsed.flags["--input-dir"] ? import_node_path6.default.resolve(cwd, parsed.flags["--input-dir"]) : "";
3281
+ if (!sourceFile && !inputDir) {
3282
+ return {
3283
+ exitCode: ExitCode.ValidationError,
3284
+ stderr: ["ERROR: Provide --file <SC-4.feature> or --input-dir <dir> for testops bdd scenarios import."]
3285
+ };
3286
+ }
3287
+ try {
3288
+ const scenarioFiles = sourceFile ? [sourceFile] : readDir(inputDir).filter((entry) => entry.toLowerCase().endsWith(".feature")).map((entry) => import_node_path6.default.join(inputDir, entry)).sort((left, right) => left.localeCompare(right));
3289
+ if (scenarioFiles.length === 0) {
3290
+ return {
3291
+ exitCode: ExitCode.ValidationError,
3292
+ stderr: ["ERROR: No .feature files were found for scenario import."]
3293
+ };
3294
+ }
3295
+ const parsedScenarios = scenarioFiles.map((filePath) => ({
3296
+ filePath,
3297
+ parsed: parseScenarioFeatureFile(readFile(filePath), filePath)
3298
+ }));
3299
+ const invalidScenarioFile = parsedScenarios.find((item) => !item.parsed);
3300
+ if (invalidScenarioFile) {
3301
+ return {
3302
+ exitCode: ExitCode.ValidationError,
3303
+ stderr: [
3304
+ `ERROR: Scenario feature file ${invalidScenarioFile.filePath} must contain exactly one scenario, valid steps, and a matching SC-* key in tag or filename.`
3305
+ ]
3306
+ };
3307
+ }
3308
+ const scenariosResult = await context.invokeForgeContract("listBddScenarios", {
3309
+ context: {
3310
+ projectKey,
3311
+ issueKey: issueKey || void 0
3312
+ }
3313
+ });
3314
+ if (!scenariosResult.ok) {
3315
+ return {
3316
+ exitCode: ExitCode.RemoteError,
3317
+ stderr: [`ERROR: ${scenariosResult.error.code}: ${scenariosResult.error.message}`]
3318
+ };
3319
+ }
3320
+ const updatedItems = [];
3321
+ for (const entry of parsedScenarios) {
3322
+ const parsedScenario = entry.parsed;
3323
+ const scenario = scenariosResult.data.find(
3324
+ (item) => (item.key ?? "").toUpperCase() === parsedScenario.scenarioKey.toUpperCase()
3325
+ );
3326
+ if (!scenario) {
3327
+ return {
3328
+ exitCode: ExitCode.RemoteError,
3329
+ stderr: [`ERROR: NOT_FOUND: BDD scenario ${parsedScenario.scenarioKey} was not found in this project.`]
3330
+ };
3331
+ }
3332
+ const nextTags = parsedScenario.tags.filter((tag) => !SCENARIO_METADATA_PATTERN.test(tag));
3333
+ const updateResult = await context.invokeForgeContract("updateScenario", {
3334
+ context: {
3335
+ projectKey,
3336
+ issueKey: issueKey || void 0
3337
+ },
3338
+ scenarioId: scenario.id,
3339
+ input: {
3340
+ featureName: parsedScenario.featureName,
3341
+ name: parsedScenario.scenarioName,
3342
+ steps: [...parsedScenario.steps],
3343
+ tags: nextTags,
3344
+ linkedIssueKeys: [...parsedScenario.linkedIssueKeys]
3345
+ }
3346
+ });
3347
+ if (!updateResult.ok) {
3348
+ return {
3349
+ exitCode: ExitCode.RemoteError,
3350
+ stderr: [`ERROR: ${updateResult.error.code}: ${updateResult.error.message}`]
3351
+ };
3352
+ }
3353
+ updatedItems.push({
3354
+ file: entry.filePath,
3355
+ item: updateResult.data
3356
+ });
3357
+ }
3358
+ if (outputFormat === "json") {
3359
+ return {
3360
+ exitCode: ExitCode.Success,
3361
+ stdout: toJsonLine({
3362
+ action: "bdd-scenarios-import",
3363
+ projectKey,
3364
+ issueKey: issueKey || null,
3365
+ count: updatedItems.length,
3366
+ file: sourceFile || null,
3367
+ inputDir: inputDir || null,
3368
+ items: updatedItems.map((entry) => ({
3369
+ file: entry.file,
3370
+ item: toJsonScenario(entry.item)
3371
+ }))
3372
+ })
3373
+ };
3374
+ }
3375
+ return {
3376
+ exitCode: ExitCode.Success,
3377
+ stdout: updatedItems.flatMap((entry) => [
3378
+ `BDD scenario imported: ${entry.item.key ?? entry.item.id}`,
3379
+ `Source: ${entry.file}`,
3380
+ ...scenarioToLines(entry.item)
3381
+ ])
3382
+ };
3383
+ } catch (error) {
3384
+ return {
3385
+ exitCode: ExitCode.TransportError,
3386
+ stderr: [`ERROR: ${normalizeError(error)}`]
3387
+ };
3388
+ }
3389
+ }
1897
3390
  const scenarioId2 = parsed.flags["--id"]?.trim() ?? "";
1898
3391
  const testCaseKey = parsed.flags["--test-case-key"]?.trim().toUpperCase() ?? "";
1899
3392
  if (!scenarioId2 && !testCaseKey) {
@@ -1960,7 +3453,7 @@ function createBddHandler(deps = {}) {
1960
3453
  }
1961
3454
  runs.push(result.data);
1962
3455
  }
1963
- if (useJson) {
3456
+ if (outputFormat === "json") {
1964
3457
  return {
1965
3458
  exitCode: ExitCode.Success,
1966
3459
  stdout: toJsonLine({
@@ -2018,7 +3511,7 @@ function createBddHandler(deps = {}) {
2018
3511
  stderr: [`ERROR: ${result.error.code}: ${result.error.message}`]
2019
3512
  };
2020
3513
  }
2021
- if (useJson) {
3514
+ if (outputFormat === "json") {
2022
3515
  return {
2023
3516
  exitCode: ExitCode.Success,
2024
3517
  stdout: toJsonLine({
@@ -2029,6 +3522,12 @@ function createBddHandler(deps = {}) {
2029
3522
  })
2030
3523
  };
2031
3524
  }
3525
+ if (outputFormat === "feature") {
3526
+ return {
3527
+ exitCode: ExitCode.Success,
3528
+ stdout: scenarioToFeatureLines(result.data)
3529
+ };
3530
+ }
2032
3531
  return {
2033
3532
  exitCode: ExitCode.Success,
2034
3533
  stdout: scenarioToLines(result.data)
@@ -2673,8 +4172,8 @@ function createDoctorHandler(deps = {}) {
2673
4172
  }
2674
4173
 
2675
4174
  // src/ingestFeature.ts
2676
- import { readFileSync as readFileSync4 } from "node:fs";
2677
- import path6 from "node:path";
4175
+ var import_node_fs6 = require("node:fs");
4176
+ var import_node_path7 = __toESM(require("node:path"), 1);
2678
4177
  var CONFIG_FLAGS5 = /* @__PURE__ */ new Set([
2679
4178
  "--config",
2680
4179
  "--base-url",
@@ -2760,8 +4259,8 @@ function normalizeError3(error) {
2760
4259
  return "Unknown ingest error.";
2761
4260
  }
2762
4261
  function createIngestFeatureHandler(deps = {}) {
2763
- const readFile = deps.readFile ?? ((filePath) => readFileSync4(filePath, "utf8"));
2764
- const readStdin = deps.readStdin ?? (() => readFileSync4(0, "utf8"));
4262
+ const readFile = deps.readFile ?? ((filePath) => (0, import_node_fs6.readFileSync)(filePath, "utf8"));
4263
+ const readStdin = deps.readStdin ?? (() => (0, import_node_fs6.readFileSync)(0, "utf8"));
2765
4264
  const cwd = deps.cwd ?? process.cwd();
2766
4265
  const env = deps.env ?? process.env;
2767
4266
  return async (request, context) => {
@@ -2771,7 +4270,7 @@ function createIngestFeatureHandler(deps = {}) {
2771
4270
  const config = resolveCliConfig(configArgs, env, cwd);
2772
4271
  const projectKey = config.values.projectKey;
2773
4272
  const issueKey = config.values.issueKey;
2774
- const sourceFile = parsed.flags["--file"] ? path6.resolve(cwd, parsed.flags["--file"]) : "";
4273
+ const sourceFile = parsed.flags["--file"] ? import_node_path7.default.resolve(cwd, parsed.flags["--file"]) : "";
2775
4274
  const useStdin = parsed.boolFlags.has("--stdin");
2776
4275
  const useJson = parsed.boolFlags.has("--json");
2777
4276
  const sourceCount = Number(Boolean(sourceFile)) + Number(useStdin);
@@ -2900,8 +4399,8 @@ function createIngestFeatureHandler(deps = {}) {
2900
4399
  }
2901
4400
 
2902
4401
  // src/runUpload.ts
2903
- import { readFileSync as readFileSync5 } from "node:fs";
2904
- import path7 from "node:path";
4402
+ var import_node_fs7 = require("node:fs");
4403
+ var import_node_path8 = __toESM(require("node:path"), 1);
2905
4404
  var STEP_RESULTS = [
2906
4405
  StepResult.Passed,
2907
4406
  StepResult.Failed,
@@ -3042,8 +4541,8 @@ function summarizeRunResult(result) {
3042
4541
  return lines;
3043
4542
  }
3044
4543
  function createRunUploadHandler(deps = {}) {
3045
- const readFile = deps.readFile ?? ((filePath) => readFileSync5(filePath, "utf8"));
3046
- const readStdin = deps.readStdin ?? (() => readFileSync5(0, "utf8"));
4544
+ const readFile = deps.readFile ?? ((filePath) => (0, import_node_fs7.readFileSync)(filePath, "utf8"));
4545
+ const readStdin = deps.readStdin ?? (() => (0, import_node_fs7.readFileSync)(0, "utf8"));
3047
4546
  const cwd = deps.cwd ?? process.cwd();
3048
4547
  const env = deps.env ?? process.env;
3049
4548
  return async (request, context) => {
@@ -3054,7 +4553,7 @@ function createRunUploadHandler(deps = {}) {
3054
4553
  const projectKey = config.values.projectKey;
3055
4554
  const issueKey = config.values.issueKey;
3056
4555
  const testCaseKey = parsed.flags["--test-case-key"]?.trim().toUpperCase() ?? "";
3057
- const sourceFile = parsed.flags["--file"] ? path7.resolve(cwd, parsed.flags["--file"]) : "";
4556
+ const sourceFile = parsed.flags["--file"] ? import_node_path8.default.resolve(cwd, parsed.flags["--file"]) : "";
3058
4557
  const useStdin = parsed.boolFlags.has("--stdin");
3059
4558
  const useJson = parsed.boolFlags.has("--json");
3060
4559
  const sourceCount = Number(Boolean(sourceFile)) + Number(useStdin);
@@ -3900,8 +5399,8 @@ var COMMAND_REGISTRY = [
3900
5399
  },
3901
5400
  {
3902
5401
  name: "bdd",
3903
- description: "BDD scenario inspection commands",
3904
- subcommands: ["scenarios"],
5402
+ description: "BDD scenario inspection and feature export commands",
5403
+ subcommands: ["features", "scenarios"],
3905
5404
  handler: createBddHandler()
3906
5405
  },
3907
5406
  {