@automatify-au/cli 0.1.2 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +103 -27
- package/dist/automatify.js +1523 -19
- package/package.json +5 -1
package/dist/automatify.js
CHANGED
|
@@ -1,4 +1,983 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
9
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
10
|
+
}) : x)(function(x) {
|
|
11
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
12
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
13
|
+
});
|
|
14
|
+
var __commonJS = (cb, mod) => function __require2() {
|
|
15
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
16
|
+
};
|
|
17
|
+
var __copyProps = (to, from, except, desc) => {
|
|
18
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
19
|
+
for (let key of __getOwnPropNames(from))
|
|
20
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
21
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
22
|
+
}
|
|
23
|
+
return to;
|
|
24
|
+
};
|
|
25
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
26
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
27
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
28
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
29
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
30
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
31
|
+
mod
|
|
32
|
+
));
|
|
33
|
+
|
|
34
|
+
// ../../node_modules/.pnpm/buffer-crc32@1.0.0/node_modules/buffer-crc32/dist/index.cjs
|
|
35
|
+
var require_dist = __commonJS({
|
|
36
|
+
"../../node_modules/.pnpm/buffer-crc32@1.0.0/node_modules/buffer-crc32/dist/index.cjs"(exports, module) {
|
|
37
|
+
"use strict";
|
|
38
|
+
function getDefaultExportFromCjs(x) {
|
|
39
|
+
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x["default"] : x;
|
|
40
|
+
}
|
|
41
|
+
var CRC_TABLE = new Int32Array([
|
|
42
|
+
0,
|
|
43
|
+
1996959894,
|
|
44
|
+
3993919788,
|
|
45
|
+
2567524794,
|
|
46
|
+
124634137,
|
|
47
|
+
1886057615,
|
|
48
|
+
3915621685,
|
|
49
|
+
2657392035,
|
|
50
|
+
249268274,
|
|
51
|
+
2044508324,
|
|
52
|
+
3772115230,
|
|
53
|
+
2547177864,
|
|
54
|
+
162941995,
|
|
55
|
+
2125561021,
|
|
56
|
+
3887607047,
|
|
57
|
+
2428444049,
|
|
58
|
+
498536548,
|
|
59
|
+
1789927666,
|
|
60
|
+
4089016648,
|
|
61
|
+
2227061214,
|
|
62
|
+
450548861,
|
|
63
|
+
1843258603,
|
|
64
|
+
4107580753,
|
|
65
|
+
2211677639,
|
|
66
|
+
325883990,
|
|
67
|
+
1684777152,
|
|
68
|
+
4251122042,
|
|
69
|
+
2321926636,
|
|
70
|
+
335633487,
|
|
71
|
+
1661365465,
|
|
72
|
+
4195302755,
|
|
73
|
+
2366115317,
|
|
74
|
+
997073096,
|
|
75
|
+
1281953886,
|
|
76
|
+
3579855332,
|
|
77
|
+
2724688242,
|
|
78
|
+
1006888145,
|
|
79
|
+
1258607687,
|
|
80
|
+
3524101629,
|
|
81
|
+
2768942443,
|
|
82
|
+
901097722,
|
|
83
|
+
1119000684,
|
|
84
|
+
3686517206,
|
|
85
|
+
2898065728,
|
|
86
|
+
853044451,
|
|
87
|
+
1172266101,
|
|
88
|
+
3705015759,
|
|
89
|
+
2882616665,
|
|
90
|
+
651767980,
|
|
91
|
+
1373503546,
|
|
92
|
+
3369554304,
|
|
93
|
+
3218104598,
|
|
94
|
+
565507253,
|
|
95
|
+
1454621731,
|
|
96
|
+
3485111705,
|
|
97
|
+
3099436303,
|
|
98
|
+
671266974,
|
|
99
|
+
1594198024,
|
|
100
|
+
3322730930,
|
|
101
|
+
2970347812,
|
|
102
|
+
795835527,
|
|
103
|
+
1483230225,
|
|
104
|
+
3244367275,
|
|
105
|
+
3060149565,
|
|
106
|
+
1994146192,
|
|
107
|
+
31158534,
|
|
108
|
+
2563907772,
|
|
109
|
+
4023717930,
|
|
110
|
+
1907459465,
|
|
111
|
+
112637215,
|
|
112
|
+
2680153253,
|
|
113
|
+
3904427059,
|
|
114
|
+
2013776290,
|
|
115
|
+
251722036,
|
|
116
|
+
2517215374,
|
|
117
|
+
3775830040,
|
|
118
|
+
2137656763,
|
|
119
|
+
141376813,
|
|
120
|
+
2439277719,
|
|
121
|
+
3865271297,
|
|
122
|
+
1802195444,
|
|
123
|
+
476864866,
|
|
124
|
+
2238001368,
|
|
125
|
+
4066508878,
|
|
126
|
+
1812370925,
|
|
127
|
+
453092731,
|
|
128
|
+
2181625025,
|
|
129
|
+
4111451223,
|
|
130
|
+
1706088902,
|
|
131
|
+
314042704,
|
|
132
|
+
2344532202,
|
|
133
|
+
4240017532,
|
|
134
|
+
1658658271,
|
|
135
|
+
366619977,
|
|
136
|
+
2362670323,
|
|
137
|
+
4224994405,
|
|
138
|
+
1303535960,
|
|
139
|
+
984961486,
|
|
140
|
+
2747007092,
|
|
141
|
+
3569037538,
|
|
142
|
+
1256170817,
|
|
143
|
+
1037604311,
|
|
144
|
+
2765210733,
|
|
145
|
+
3554079995,
|
|
146
|
+
1131014506,
|
|
147
|
+
879679996,
|
|
148
|
+
2909243462,
|
|
149
|
+
3663771856,
|
|
150
|
+
1141124467,
|
|
151
|
+
855842277,
|
|
152
|
+
2852801631,
|
|
153
|
+
3708648649,
|
|
154
|
+
1342533948,
|
|
155
|
+
654459306,
|
|
156
|
+
3188396048,
|
|
157
|
+
3373015174,
|
|
158
|
+
1466479909,
|
|
159
|
+
544179635,
|
|
160
|
+
3110523913,
|
|
161
|
+
3462522015,
|
|
162
|
+
1591671054,
|
|
163
|
+
702138776,
|
|
164
|
+
2966460450,
|
|
165
|
+
3352799412,
|
|
166
|
+
1504918807,
|
|
167
|
+
783551873,
|
|
168
|
+
3082640443,
|
|
169
|
+
3233442989,
|
|
170
|
+
3988292384,
|
|
171
|
+
2596254646,
|
|
172
|
+
62317068,
|
|
173
|
+
1957810842,
|
|
174
|
+
3939845945,
|
|
175
|
+
2647816111,
|
|
176
|
+
81470997,
|
|
177
|
+
1943803523,
|
|
178
|
+
3814918930,
|
|
179
|
+
2489596804,
|
|
180
|
+
225274430,
|
|
181
|
+
2053790376,
|
|
182
|
+
3826175755,
|
|
183
|
+
2466906013,
|
|
184
|
+
167816743,
|
|
185
|
+
2097651377,
|
|
186
|
+
4027552580,
|
|
187
|
+
2265490386,
|
|
188
|
+
503444072,
|
|
189
|
+
1762050814,
|
|
190
|
+
4150417245,
|
|
191
|
+
2154129355,
|
|
192
|
+
426522225,
|
|
193
|
+
1852507879,
|
|
194
|
+
4275313526,
|
|
195
|
+
2312317920,
|
|
196
|
+
282753626,
|
|
197
|
+
1742555852,
|
|
198
|
+
4189708143,
|
|
199
|
+
2394877945,
|
|
200
|
+
397917763,
|
|
201
|
+
1622183637,
|
|
202
|
+
3604390888,
|
|
203
|
+
2714866558,
|
|
204
|
+
953729732,
|
|
205
|
+
1340076626,
|
|
206
|
+
3518719985,
|
|
207
|
+
2797360999,
|
|
208
|
+
1068828381,
|
|
209
|
+
1219638859,
|
|
210
|
+
3624741850,
|
|
211
|
+
2936675148,
|
|
212
|
+
906185462,
|
|
213
|
+
1090812512,
|
|
214
|
+
3747672003,
|
|
215
|
+
2825379669,
|
|
216
|
+
829329135,
|
|
217
|
+
1181335161,
|
|
218
|
+
3412177804,
|
|
219
|
+
3160834842,
|
|
220
|
+
628085408,
|
|
221
|
+
1382605366,
|
|
222
|
+
3423369109,
|
|
223
|
+
3138078467,
|
|
224
|
+
570562233,
|
|
225
|
+
1426400815,
|
|
226
|
+
3317316542,
|
|
227
|
+
2998733608,
|
|
228
|
+
733239954,
|
|
229
|
+
1555261956,
|
|
230
|
+
3268935591,
|
|
231
|
+
3050360625,
|
|
232
|
+
752459403,
|
|
233
|
+
1541320221,
|
|
234
|
+
2607071920,
|
|
235
|
+
3965973030,
|
|
236
|
+
1969922972,
|
|
237
|
+
40735498,
|
|
238
|
+
2617837225,
|
|
239
|
+
3943577151,
|
|
240
|
+
1913087877,
|
|
241
|
+
83908371,
|
|
242
|
+
2512341634,
|
|
243
|
+
3803740692,
|
|
244
|
+
2075208622,
|
|
245
|
+
213261112,
|
|
246
|
+
2463272603,
|
|
247
|
+
3855990285,
|
|
248
|
+
2094854071,
|
|
249
|
+
198958881,
|
|
250
|
+
2262029012,
|
|
251
|
+
4057260610,
|
|
252
|
+
1759359992,
|
|
253
|
+
534414190,
|
|
254
|
+
2176718541,
|
|
255
|
+
4139329115,
|
|
256
|
+
1873836001,
|
|
257
|
+
414664567,
|
|
258
|
+
2282248934,
|
|
259
|
+
4279200368,
|
|
260
|
+
1711684554,
|
|
261
|
+
285281116,
|
|
262
|
+
2405801727,
|
|
263
|
+
4167216745,
|
|
264
|
+
1634467795,
|
|
265
|
+
376229701,
|
|
266
|
+
2685067896,
|
|
267
|
+
3608007406,
|
|
268
|
+
1308918612,
|
|
269
|
+
956543938,
|
|
270
|
+
2808555105,
|
|
271
|
+
3495958263,
|
|
272
|
+
1231636301,
|
|
273
|
+
1047427035,
|
|
274
|
+
2932959818,
|
|
275
|
+
3654703836,
|
|
276
|
+
1088359270,
|
|
277
|
+
936918e3,
|
|
278
|
+
2847714899,
|
|
279
|
+
3736837829,
|
|
280
|
+
1202900863,
|
|
281
|
+
817233897,
|
|
282
|
+
3183342108,
|
|
283
|
+
3401237130,
|
|
284
|
+
1404277552,
|
|
285
|
+
615818150,
|
|
286
|
+
3134207493,
|
|
287
|
+
3453421203,
|
|
288
|
+
1423857449,
|
|
289
|
+
601450431,
|
|
290
|
+
3009837614,
|
|
291
|
+
3294710456,
|
|
292
|
+
1567103746,
|
|
293
|
+
711928724,
|
|
294
|
+
3020668471,
|
|
295
|
+
3272380065,
|
|
296
|
+
1510334235,
|
|
297
|
+
755167117
|
|
298
|
+
]);
|
|
299
|
+
function ensureBuffer(input) {
|
|
300
|
+
if (Buffer.isBuffer(input)) {
|
|
301
|
+
return input;
|
|
302
|
+
}
|
|
303
|
+
if (typeof input === "number") {
|
|
304
|
+
return Buffer.alloc(input);
|
|
305
|
+
} else if (typeof input === "string") {
|
|
306
|
+
return Buffer.from(input);
|
|
307
|
+
} else {
|
|
308
|
+
throw new Error("input must be buffer, number, or string, received " + typeof input);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
function bufferizeInt(num) {
|
|
312
|
+
const tmp = ensureBuffer(4);
|
|
313
|
+
tmp.writeInt32BE(num, 0);
|
|
314
|
+
return tmp;
|
|
315
|
+
}
|
|
316
|
+
function _crc32(buf, previous) {
|
|
317
|
+
buf = ensureBuffer(buf);
|
|
318
|
+
if (Buffer.isBuffer(previous)) {
|
|
319
|
+
previous = previous.readUInt32BE(0);
|
|
320
|
+
}
|
|
321
|
+
let crc = ~~previous ^ -1;
|
|
322
|
+
for (var n = 0; n < buf.length; n++) {
|
|
323
|
+
crc = CRC_TABLE[(crc ^ buf[n]) & 255] ^ crc >>> 8;
|
|
324
|
+
}
|
|
325
|
+
return crc ^ -1;
|
|
326
|
+
}
|
|
327
|
+
function crc32() {
|
|
328
|
+
return bufferizeInt(_crc32.apply(null, arguments));
|
|
329
|
+
}
|
|
330
|
+
crc32.signed = function() {
|
|
331
|
+
return _crc32.apply(null, arguments);
|
|
332
|
+
};
|
|
333
|
+
crc32.unsigned = function() {
|
|
334
|
+
return _crc32.apply(null, arguments) >>> 0;
|
|
335
|
+
};
|
|
336
|
+
var bufferCrc32 = crc32;
|
|
337
|
+
var index = /* @__PURE__ */ getDefaultExportFromCjs(bufferCrc32);
|
|
338
|
+
module.exports = index;
|
|
339
|
+
}
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
// ../../node_modules/.pnpm/yazl@3.3.1/node_modules/yazl/index.js
|
|
343
|
+
var require_yazl = __commonJS({
|
|
344
|
+
"../../node_modules/.pnpm/yazl@3.3.1/node_modules/yazl/index.js"(exports) {
|
|
345
|
+
var fs = __require("fs");
|
|
346
|
+
var Transform = __require("stream").Transform;
|
|
347
|
+
var PassThrough = __require("stream").PassThrough;
|
|
348
|
+
var zlib = __require("zlib");
|
|
349
|
+
var util = __require("util");
|
|
350
|
+
var EventEmitter = __require("events").EventEmitter;
|
|
351
|
+
var errorMonitor = __require("events").errorMonitor;
|
|
352
|
+
var crc32 = require_dist();
|
|
353
|
+
exports.ZipFile = ZipFile2;
|
|
354
|
+
exports.dateToDosDateTime = dateToDosDateTime;
|
|
355
|
+
util.inherits(ZipFile2, EventEmitter);
|
|
356
|
+
function ZipFile2() {
|
|
357
|
+
this.outputStream = new PassThrough();
|
|
358
|
+
this.entries = [];
|
|
359
|
+
this.outputStreamCursor = 0;
|
|
360
|
+
this.ended = false;
|
|
361
|
+
this.allDone = false;
|
|
362
|
+
this.forceZip64Eocd = false;
|
|
363
|
+
this.errored = false;
|
|
364
|
+
this.on(errorMonitor, function() {
|
|
365
|
+
this.errored = true;
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
ZipFile2.prototype.addFile = function(realPath, metadataPath, options) {
|
|
369
|
+
var self = this;
|
|
370
|
+
metadataPath = validateMetadataPath(metadataPath, false);
|
|
371
|
+
if (options == null) options = {};
|
|
372
|
+
if (shouldIgnoreAdding(self)) return;
|
|
373
|
+
var entry = new Entry(metadataPath, false, options);
|
|
374
|
+
self.entries.push(entry);
|
|
375
|
+
fs.stat(realPath, function(err, stats) {
|
|
376
|
+
if (err) return self.emit("error", err);
|
|
377
|
+
if (!stats.isFile()) return self.emit("error", new Error("not a file: " + realPath));
|
|
378
|
+
entry.uncompressedSize = stats.size;
|
|
379
|
+
if (options.mtime == null) entry.setLastModDate(stats.mtime);
|
|
380
|
+
if (options.mode == null) entry.setFileAttributesMode(stats.mode);
|
|
381
|
+
entry.setFileDataPumpFunction(function() {
|
|
382
|
+
var readStream = fs.createReadStream(realPath);
|
|
383
|
+
entry.state = Entry.FILE_DATA_IN_PROGRESS;
|
|
384
|
+
readStream.on("error", function(err2) {
|
|
385
|
+
self.emit("error", err2);
|
|
386
|
+
});
|
|
387
|
+
pumpFileDataReadStream(self, entry, readStream);
|
|
388
|
+
});
|
|
389
|
+
pumpEntries(self);
|
|
390
|
+
});
|
|
391
|
+
};
|
|
392
|
+
ZipFile2.prototype.addReadStream = function(readStream, metadataPath, options) {
|
|
393
|
+
this.addReadStreamLazy(metadataPath, options, function(cb) {
|
|
394
|
+
cb(null, readStream);
|
|
395
|
+
});
|
|
396
|
+
};
|
|
397
|
+
ZipFile2.prototype.addReadStreamLazy = function(metadataPath, options, getReadStreamFunction) {
|
|
398
|
+
var self = this;
|
|
399
|
+
if (typeof options === "function") {
|
|
400
|
+
getReadStreamFunction = options;
|
|
401
|
+
options = null;
|
|
402
|
+
}
|
|
403
|
+
if (options == null) options = {};
|
|
404
|
+
metadataPath = validateMetadataPath(metadataPath, false);
|
|
405
|
+
if (shouldIgnoreAdding(self)) return;
|
|
406
|
+
var entry = new Entry(metadataPath, false, options);
|
|
407
|
+
self.entries.push(entry);
|
|
408
|
+
entry.setFileDataPumpFunction(function() {
|
|
409
|
+
entry.state = Entry.FILE_DATA_IN_PROGRESS;
|
|
410
|
+
getReadStreamFunction(function(err, readStream) {
|
|
411
|
+
if (err) return self.emit("error", err);
|
|
412
|
+
pumpFileDataReadStream(self, entry, readStream);
|
|
413
|
+
});
|
|
414
|
+
});
|
|
415
|
+
pumpEntries(self);
|
|
416
|
+
};
|
|
417
|
+
ZipFile2.prototype.addBuffer = function(buffer, metadataPath, options) {
|
|
418
|
+
var self = this;
|
|
419
|
+
metadataPath = validateMetadataPath(metadataPath, false);
|
|
420
|
+
if (buffer.length > 1073741823) throw new Error("buffer too large: " + buffer.length + " > 1073741823");
|
|
421
|
+
if (options == null) options = {};
|
|
422
|
+
if (options.size != null) throw new Error("options.size not allowed");
|
|
423
|
+
if (shouldIgnoreAdding(self)) return;
|
|
424
|
+
var entry = new Entry(metadataPath, false, options);
|
|
425
|
+
entry.uncompressedSize = buffer.length;
|
|
426
|
+
entry.crc32 = crc32.unsigned(buffer);
|
|
427
|
+
entry.crcAndFileSizeKnown = true;
|
|
428
|
+
self.entries.push(entry);
|
|
429
|
+
if (entry.compressionLevel === 0) {
|
|
430
|
+
setCompressedBuffer(buffer);
|
|
431
|
+
} else {
|
|
432
|
+
zlib.deflateRaw(buffer, { level: entry.compressionLevel }, function(err, compressedBuffer) {
|
|
433
|
+
setCompressedBuffer(compressedBuffer);
|
|
434
|
+
});
|
|
435
|
+
}
|
|
436
|
+
function setCompressedBuffer(compressedBuffer) {
|
|
437
|
+
entry.compressedSize = compressedBuffer.length;
|
|
438
|
+
entry.setFileDataPumpFunction(function() {
|
|
439
|
+
writeToOutputStream(self, compressedBuffer);
|
|
440
|
+
writeToOutputStream(self, entry.getDataDescriptor());
|
|
441
|
+
entry.state = Entry.FILE_DATA_DONE;
|
|
442
|
+
setImmediate(function() {
|
|
443
|
+
pumpEntries(self);
|
|
444
|
+
});
|
|
445
|
+
});
|
|
446
|
+
pumpEntries(self);
|
|
447
|
+
}
|
|
448
|
+
};
|
|
449
|
+
ZipFile2.prototype.addEmptyDirectory = function(metadataPath, options) {
|
|
450
|
+
var self = this;
|
|
451
|
+
metadataPath = validateMetadataPath(metadataPath, true);
|
|
452
|
+
if (options == null) options = {};
|
|
453
|
+
if (options.size != null) throw new Error("options.size not allowed");
|
|
454
|
+
if (options.compress != null) throw new Error("options.compress not allowed");
|
|
455
|
+
if (options.compressionLevel != null) throw new Error("options.compressionLevel not allowed");
|
|
456
|
+
if (shouldIgnoreAdding(self)) return;
|
|
457
|
+
var entry = new Entry(metadataPath, true, options);
|
|
458
|
+
self.entries.push(entry);
|
|
459
|
+
entry.setFileDataPumpFunction(function() {
|
|
460
|
+
writeToOutputStream(self, entry.getDataDescriptor());
|
|
461
|
+
entry.state = Entry.FILE_DATA_DONE;
|
|
462
|
+
pumpEntries(self);
|
|
463
|
+
});
|
|
464
|
+
pumpEntries(self);
|
|
465
|
+
};
|
|
466
|
+
var eocdrSignatureBuffer = bufferFrom([80, 75, 5, 6]);
|
|
467
|
+
ZipFile2.prototype.end = function(options, calculatedTotalSizeCallback) {
|
|
468
|
+
if (typeof options === "function") {
|
|
469
|
+
calculatedTotalSizeCallback = options;
|
|
470
|
+
options = null;
|
|
471
|
+
}
|
|
472
|
+
if (options == null) options = {};
|
|
473
|
+
if (this.ended) return;
|
|
474
|
+
this.ended = true;
|
|
475
|
+
if (this.errored) return;
|
|
476
|
+
this.calculatedTotalSizeCallback = calculatedTotalSizeCallback;
|
|
477
|
+
this.forceZip64Eocd = !!options.forceZip64Format;
|
|
478
|
+
if (options.comment) {
|
|
479
|
+
if (typeof options.comment === "string") {
|
|
480
|
+
this.comment = encodeCp437(options.comment);
|
|
481
|
+
} else {
|
|
482
|
+
this.comment = options.comment;
|
|
483
|
+
}
|
|
484
|
+
if (this.comment.length > 65535) throw new Error("comment is too large");
|
|
485
|
+
if (bufferIncludes(this.comment, eocdrSignatureBuffer)) throw new Error("comment contains end of central directory record signature");
|
|
486
|
+
} else {
|
|
487
|
+
this.comment = EMPTY_BUFFER;
|
|
488
|
+
}
|
|
489
|
+
pumpEntries(this);
|
|
490
|
+
};
|
|
491
|
+
function writeToOutputStream(self, buffer) {
|
|
492
|
+
self.outputStream.write(buffer);
|
|
493
|
+
self.outputStreamCursor += buffer.length;
|
|
494
|
+
}
|
|
495
|
+
function pumpFileDataReadStream(self, entry, readStream) {
|
|
496
|
+
var crc32Watcher = new Crc32Watcher();
|
|
497
|
+
var uncompressedSizeCounter = new ByteCounter();
|
|
498
|
+
var compressor = entry.compressionLevel !== 0 ? new zlib.DeflateRaw({ level: entry.compressionLevel }) : new PassThrough();
|
|
499
|
+
var compressedSizeCounter = new ByteCounter();
|
|
500
|
+
readStream.pipe(crc32Watcher).pipe(uncompressedSizeCounter).pipe(compressor).pipe(compressedSizeCounter).pipe(self.outputStream, { end: false });
|
|
501
|
+
compressedSizeCounter.on("end", function() {
|
|
502
|
+
entry.crc32 = crc32Watcher.crc32;
|
|
503
|
+
if (entry.uncompressedSize == null) {
|
|
504
|
+
entry.uncompressedSize = uncompressedSizeCounter.byteCount;
|
|
505
|
+
} else {
|
|
506
|
+
if (entry.uncompressedSize !== uncompressedSizeCounter.byteCount) return self.emit("error", new Error("file data stream has unexpected number of bytes"));
|
|
507
|
+
}
|
|
508
|
+
entry.compressedSize = compressedSizeCounter.byteCount;
|
|
509
|
+
self.outputStreamCursor += entry.compressedSize;
|
|
510
|
+
writeToOutputStream(self, entry.getDataDescriptor());
|
|
511
|
+
entry.state = Entry.FILE_DATA_DONE;
|
|
512
|
+
pumpEntries(self);
|
|
513
|
+
});
|
|
514
|
+
}
|
|
515
|
+
function determineCompressionLevel(options) {
|
|
516
|
+
if (options.compress != null && options.compressionLevel != null) {
|
|
517
|
+
if (!!options.compress !== !!options.compressionLevel) throw new Error("conflicting settings for compress and compressionLevel");
|
|
518
|
+
}
|
|
519
|
+
if (options.compressionLevel != null) return options.compressionLevel;
|
|
520
|
+
if (options.compress === false) return 0;
|
|
521
|
+
return 6;
|
|
522
|
+
}
|
|
523
|
+
function pumpEntries(self) {
|
|
524
|
+
if (self.allDone || self.errored) return;
|
|
525
|
+
if (self.ended && self.calculatedTotalSizeCallback != null) {
|
|
526
|
+
var calculatedTotalSize = calculateTotalSize(self);
|
|
527
|
+
if (calculatedTotalSize != null) {
|
|
528
|
+
self.calculatedTotalSizeCallback(calculatedTotalSize);
|
|
529
|
+
self.calculatedTotalSizeCallback = null;
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
var entry = getFirstNotDoneEntry();
|
|
533
|
+
function getFirstNotDoneEntry() {
|
|
534
|
+
for (var i = 0; i < self.entries.length; i++) {
|
|
535
|
+
var entry2 = self.entries[i];
|
|
536
|
+
if (entry2.state < Entry.FILE_DATA_DONE) return entry2;
|
|
537
|
+
}
|
|
538
|
+
return null;
|
|
539
|
+
}
|
|
540
|
+
if (entry != null) {
|
|
541
|
+
if (entry.state < Entry.READY_TO_PUMP_FILE_DATA) return;
|
|
542
|
+
if (entry.state === Entry.FILE_DATA_IN_PROGRESS) return;
|
|
543
|
+
entry.relativeOffsetOfLocalHeader = self.outputStreamCursor;
|
|
544
|
+
var localFileHeader = entry.getLocalFileHeader();
|
|
545
|
+
writeToOutputStream(self, localFileHeader);
|
|
546
|
+
entry.doFileDataPump();
|
|
547
|
+
} else {
|
|
548
|
+
if (self.ended) {
|
|
549
|
+
self.offsetOfStartOfCentralDirectory = self.outputStreamCursor;
|
|
550
|
+
self.entries.forEach(function(entry2) {
|
|
551
|
+
var centralDirectoryRecord = entry2.getCentralDirectoryRecord();
|
|
552
|
+
writeToOutputStream(self, centralDirectoryRecord);
|
|
553
|
+
});
|
|
554
|
+
writeToOutputStream(self, getEndOfCentralDirectoryRecord(self));
|
|
555
|
+
self.outputStream.end();
|
|
556
|
+
self.allDone = true;
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
function calculateTotalSize(self) {
|
|
561
|
+
var pretendOutputCursor = 0;
|
|
562
|
+
var centralDirectorySize = 0;
|
|
563
|
+
for (var i = 0; i < self.entries.length; i++) {
|
|
564
|
+
var entry = self.entries[i];
|
|
565
|
+
if (entry.compressionLevel !== 0) return -1;
|
|
566
|
+
if (entry.state >= Entry.READY_TO_PUMP_FILE_DATA) {
|
|
567
|
+
if (entry.uncompressedSize == null) return -1;
|
|
568
|
+
} else {
|
|
569
|
+
if (entry.uncompressedSize == null) return null;
|
|
570
|
+
}
|
|
571
|
+
entry.relativeOffsetOfLocalHeader = pretendOutputCursor;
|
|
572
|
+
var useZip64Format = entry.useZip64Format();
|
|
573
|
+
pretendOutputCursor += LOCAL_FILE_HEADER_FIXED_SIZE + entry.utf8FileName.length;
|
|
574
|
+
pretendOutputCursor += entry.uncompressedSize;
|
|
575
|
+
if (!entry.crcAndFileSizeKnown) {
|
|
576
|
+
if (useZip64Format) {
|
|
577
|
+
pretendOutputCursor += ZIP64_DATA_DESCRIPTOR_SIZE;
|
|
578
|
+
} else {
|
|
579
|
+
pretendOutputCursor += DATA_DESCRIPTOR_SIZE;
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
centralDirectorySize += CENTRAL_DIRECTORY_RECORD_FIXED_SIZE + entry.utf8FileName.length + entry.fileComment.length;
|
|
583
|
+
if (!entry.forceDosTimestamp) {
|
|
584
|
+
centralDirectorySize += INFO_ZIP_UNIVERSAL_TIMESTAMP_EXTRA_FIELD_SIZE;
|
|
585
|
+
}
|
|
586
|
+
if (useZip64Format) {
|
|
587
|
+
centralDirectorySize += ZIP64_EXTENDED_INFORMATION_EXTRA_FIELD_SIZE;
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
var endOfCentralDirectorySize = 0;
|
|
591
|
+
if (self.forceZip64Eocd || self.entries.length >= 65535 || centralDirectorySize >= 65535 || pretendOutputCursor >= 4294967295) {
|
|
592
|
+
endOfCentralDirectorySize += ZIP64_END_OF_CENTRAL_DIRECTORY_RECORD_SIZE + ZIP64_END_OF_CENTRAL_DIRECTORY_LOCATOR_SIZE;
|
|
593
|
+
}
|
|
594
|
+
endOfCentralDirectorySize += END_OF_CENTRAL_DIRECTORY_RECORD_SIZE + self.comment.length;
|
|
595
|
+
return pretendOutputCursor + centralDirectorySize + endOfCentralDirectorySize;
|
|
596
|
+
}
|
|
597
|
+
function shouldIgnoreAdding(self) {
|
|
598
|
+
if (self.ended) throw new Error("cannot add entries after calling end()");
|
|
599
|
+
if (self.errored) return true;
|
|
600
|
+
return false;
|
|
601
|
+
}
|
|
602
|
+
var ZIP64_END_OF_CENTRAL_DIRECTORY_RECORD_SIZE = 56;
|
|
603
|
+
var ZIP64_END_OF_CENTRAL_DIRECTORY_LOCATOR_SIZE = 20;
|
|
604
|
+
var END_OF_CENTRAL_DIRECTORY_RECORD_SIZE = 22;
|
|
605
|
+
function getEndOfCentralDirectoryRecord(self, actuallyJustTellMeHowLongItWouldBe) {
|
|
606
|
+
var needZip64Format = false;
|
|
607
|
+
var normalEntriesLength = self.entries.length;
|
|
608
|
+
if (self.forceZip64Eocd || self.entries.length >= 65535) {
|
|
609
|
+
normalEntriesLength = 65535;
|
|
610
|
+
needZip64Format = true;
|
|
611
|
+
}
|
|
612
|
+
var sizeOfCentralDirectory = self.outputStreamCursor - self.offsetOfStartOfCentralDirectory;
|
|
613
|
+
var normalSizeOfCentralDirectory = sizeOfCentralDirectory;
|
|
614
|
+
if (self.forceZip64Eocd || sizeOfCentralDirectory >= 4294967295) {
|
|
615
|
+
normalSizeOfCentralDirectory = 4294967295;
|
|
616
|
+
needZip64Format = true;
|
|
617
|
+
}
|
|
618
|
+
var normalOffsetOfStartOfCentralDirectory = self.offsetOfStartOfCentralDirectory;
|
|
619
|
+
if (self.forceZip64Eocd || self.offsetOfStartOfCentralDirectory >= 4294967295) {
|
|
620
|
+
normalOffsetOfStartOfCentralDirectory = 4294967295;
|
|
621
|
+
needZip64Format = true;
|
|
622
|
+
}
|
|
623
|
+
if (actuallyJustTellMeHowLongItWouldBe) {
|
|
624
|
+
if (needZip64Format) {
|
|
625
|
+
return ZIP64_END_OF_CENTRAL_DIRECTORY_RECORD_SIZE + ZIP64_END_OF_CENTRAL_DIRECTORY_LOCATOR_SIZE + END_OF_CENTRAL_DIRECTORY_RECORD_SIZE;
|
|
626
|
+
} else {
|
|
627
|
+
return END_OF_CENTRAL_DIRECTORY_RECORD_SIZE;
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
var eocdrBuffer = bufferAlloc(END_OF_CENTRAL_DIRECTORY_RECORD_SIZE + self.comment.length);
|
|
631
|
+
eocdrBuffer.writeUInt32LE(101010256, 0);
|
|
632
|
+
eocdrBuffer.writeUInt16LE(0, 4);
|
|
633
|
+
eocdrBuffer.writeUInt16LE(0, 6);
|
|
634
|
+
eocdrBuffer.writeUInt16LE(normalEntriesLength, 8);
|
|
635
|
+
eocdrBuffer.writeUInt16LE(normalEntriesLength, 10);
|
|
636
|
+
eocdrBuffer.writeUInt32LE(normalSizeOfCentralDirectory, 12);
|
|
637
|
+
eocdrBuffer.writeUInt32LE(normalOffsetOfStartOfCentralDirectory, 16);
|
|
638
|
+
eocdrBuffer.writeUInt16LE(self.comment.length, 20);
|
|
639
|
+
self.comment.copy(eocdrBuffer, 22);
|
|
640
|
+
if (!needZip64Format) return eocdrBuffer;
|
|
641
|
+
var zip64EocdrBuffer = bufferAlloc(ZIP64_END_OF_CENTRAL_DIRECTORY_RECORD_SIZE);
|
|
642
|
+
zip64EocdrBuffer.writeUInt32LE(101075792, 0);
|
|
643
|
+
writeUInt64LE(zip64EocdrBuffer, ZIP64_END_OF_CENTRAL_DIRECTORY_RECORD_SIZE - 12, 4);
|
|
644
|
+
zip64EocdrBuffer.writeUInt16LE(VERSION_MADE_BY, 12);
|
|
645
|
+
zip64EocdrBuffer.writeUInt16LE(VERSION_NEEDED_TO_EXTRACT_ZIP64, 14);
|
|
646
|
+
zip64EocdrBuffer.writeUInt32LE(0, 16);
|
|
647
|
+
zip64EocdrBuffer.writeUInt32LE(0, 20);
|
|
648
|
+
writeUInt64LE(zip64EocdrBuffer, self.entries.length, 24);
|
|
649
|
+
writeUInt64LE(zip64EocdrBuffer, self.entries.length, 32);
|
|
650
|
+
writeUInt64LE(zip64EocdrBuffer, sizeOfCentralDirectory, 40);
|
|
651
|
+
writeUInt64LE(zip64EocdrBuffer, self.offsetOfStartOfCentralDirectory, 48);
|
|
652
|
+
var zip64EocdlBuffer = bufferAlloc(ZIP64_END_OF_CENTRAL_DIRECTORY_LOCATOR_SIZE);
|
|
653
|
+
zip64EocdlBuffer.writeUInt32LE(117853008, 0);
|
|
654
|
+
zip64EocdlBuffer.writeUInt32LE(0, 4);
|
|
655
|
+
writeUInt64LE(zip64EocdlBuffer, self.outputStreamCursor, 8);
|
|
656
|
+
zip64EocdlBuffer.writeUInt32LE(1, 16);
|
|
657
|
+
return Buffer.concat([
|
|
658
|
+
zip64EocdrBuffer,
|
|
659
|
+
zip64EocdlBuffer,
|
|
660
|
+
eocdrBuffer
|
|
661
|
+
]);
|
|
662
|
+
}
|
|
663
|
+
function validateMetadataPath(metadataPath, isDirectory) {
|
|
664
|
+
if (metadataPath === "") throw new Error("empty metadataPath");
|
|
665
|
+
metadataPath = metadataPath.replace(/\\/g, "/");
|
|
666
|
+
if (/^[a-zA-Z]:/.test(metadataPath) || /^\//.test(metadataPath)) throw new Error("absolute path: " + metadataPath);
|
|
667
|
+
if (metadataPath.split("/").indexOf("..") !== -1) throw new Error("invalid relative path: " + metadataPath);
|
|
668
|
+
var looksLikeDirectory = /\/$/.test(metadataPath);
|
|
669
|
+
if (isDirectory) {
|
|
670
|
+
if (!looksLikeDirectory) metadataPath += "/";
|
|
671
|
+
} else {
|
|
672
|
+
if (looksLikeDirectory) throw new Error("file path cannot end with '/': " + metadataPath);
|
|
673
|
+
}
|
|
674
|
+
return metadataPath;
|
|
675
|
+
}
|
|
676
|
+
var EMPTY_BUFFER = bufferAlloc(0);
|
|
677
|
+
function Entry(metadataPath, isDirectory, options) {
|
|
678
|
+
this.utf8FileName = bufferFrom(metadataPath);
|
|
679
|
+
if (this.utf8FileName.length > 65535) throw new Error("utf8 file name too long. " + utf8FileName.length + " > 65535");
|
|
680
|
+
this.isDirectory = isDirectory;
|
|
681
|
+
this.state = Entry.WAITING_FOR_METADATA;
|
|
682
|
+
this.setLastModDate(options.mtime != null ? options.mtime : /* @__PURE__ */ new Date());
|
|
683
|
+
this.forceDosTimestamp = !!options.forceDosTimestamp;
|
|
684
|
+
if (options.mode != null) {
|
|
685
|
+
this.setFileAttributesMode(options.mode);
|
|
686
|
+
} else {
|
|
687
|
+
this.setFileAttributesMode(isDirectory ? 16893 : 33204);
|
|
688
|
+
}
|
|
689
|
+
if (isDirectory) {
|
|
690
|
+
this.crcAndFileSizeKnown = true;
|
|
691
|
+
this.crc32 = 0;
|
|
692
|
+
this.uncompressedSize = 0;
|
|
693
|
+
this.compressedSize = 0;
|
|
694
|
+
} else {
|
|
695
|
+
this.crcAndFileSizeKnown = false;
|
|
696
|
+
this.crc32 = null;
|
|
697
|
+
this.uncompressedSize = null;
|
|
698
|
+
this.compressedSize = null;
|
|
699
|
+
if (options.size != null) this.uncompressedSize = options.size;
|
|
700
|
+
}
|
|
701
|
+
if (isDirectory) {
|
|
702
|
+
this.compressionLevel = 0;
|
|
703
|
+
} else {
|
|
704
|
+
this.compressionLevel = determineCompressionLevel(options);
|
|
705
|
+
}
|
|
706
|
+
this.forceZip64Format = !!options.forceZip64Format;
|
|
707
|
+
if (options.fileComment) {
|
|
708
|
+
if (typeof options.fileComment === "string") {
|
|
709
|
+
this.fileComment = bufferFrom(options.fileComment, "utf-8");
|
|
710
|
+
} else {
|
|
711
|
+
this.fileComment = options.fileComment;
|
|
712
|
+
}
|
|
713
|
+
if (this.fileComment.length > 65535) throw new Error("fileComment is too large");
|
|
714
|
+
} else {
|
|
715
|
+
this.fileComment = EMPTY_BUFFER;
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
Entry.WAITING_FOR_METADATA = 0;
|
|
719
|
+
Entry.READY_TO_PUMP_FILE_DATA = 1;
|
|
720
|
+
Entry.FILE_DATA_IN_PROGRESS = 2;
|
|
721
|
+
Entry.FILE_DATA_DONE = 3;
|
|
722
|
+
Entry.prototype.setLastModDate = function(date) {
|
|
723
|
+
this.mtime = date;
|
|
724
|
+
var dosDateTime = dateToDosDateTime(date);
|
|
725
|
+
this.lastModFileTime = dosDateTime.time;
|
|
726
|
+
this.lastModFileDate = dosDateTime.date;
|
|
727
|
+
};
|
|
728
|
+
Entry.prototype.setFileAttributesMode = function(mode) {
|
|
729
|
+
if ((mode & 65535) !== mode) throw new Error("invalid mode. expected: 0 <= " + mode + " <= 65535");
|
|
730
|
+
this.externalFileAttributes = mode << 16 >>> 0;
|
|
731
|
+
};
|
|
732
|
+
Entry.prototype.setFileDataPumpFunction = function(doFileDataPump) {
|
|
733
|
+
this.doFileDataPump = doFileDataPump;
|
|
734
|
+
this.state = Entry.READY_TO_PUMP_FILE_DATA;
|
|
735
|
+
};
|
|
736
|
+
Entry.prototype.useZip64Format = function() {
|
|
737
|
+
return this.forceZip64Format || this.uncompressedSize != null && this.uncompressedSize > 4294967294 || this.compressedSize != null && this.compressedSize > 4294967294 || this.relativeOffsetOfLocalHeader != null && this.relativeOffsetOfLocalHeader > 4294967294;
|
|
738
|
+
};
|
|
739
|
+
var LOCAL_FILE_HEADER_FIXED_SIZE = 30;
|
|
740
|
+
var VERSION_NEEDED_TO_EXTRACT_UTF8 = 20;
|
|
741
|
+
var VERSION_NEEDED_TO_EXTRACT_ZIP64 = 45;
|
|
742
|
+
var VERSION_MADE_BY = 3 << 8 | 63;
|
|
743
|
+
var FILE_NAME_IS_UTF8 = 1 << 11;
|
|
744
|
+
var UNKNOWN_CRC32_AND_FILE_SIZES = 1 << 3;
|
|
745
|
+
Entry.prototype.getLocalFileHeader = function() {
|
|
746
|
+
var crc322 = 0;
|
|
747
|
+
var compressedSize = 0;
|
|
748
|
+
var uncompressedSize = 0;
|
|
749
|
+
if (this.crcAndFileSizeKnown) {
|
|
750
|
+
crc322 = this.crc32;
|
|
751
|
+
compressedSize = this.compressedSize;
|
|
752
|
+
uncompressedSize = this.uncompressedSize;
|
|
753
|
+
}
|
|
754
|
+
var fixedSizeStuff = bufferAlloc(LOCAL_FILE_HEADER_FIXED_SIZE);
|
|
755
|
+
var generalPurposeBitFlag = FILE_NAME_IS_UTF8;
|
|
756
|
+
if (!this.crcAndFileSizeKnown) generalPurposeBitFlag |= UNKNOWN_CRC32_AND_FILE_SIZES;
|
|
757
|
+
fixedSizeStuff.writeUInt32LE(67324752, 0);
|
|
758
|
+
fixedSizeStuff.writeUInt16LE(VERSION_NEEDED_TO_EXTRACT_UTF8, 4);
|
|
759
|
+
fixedSizeStuff.writeUInt16LE(generalPurposeBitFlag, 6);
|
|
760
|
+
fixedSizeStuff.writeUInt16LE(this.getCompressionMethod(), 8);
|
|
761
|
+
fixedSizeStuff.writeUInt16LE(this.lastModFileTime, 10);
|
|
762
|
+
fixedSizeStuff.writeUInt16LE(this.lastModFileDate, 12);
|
|
763
|
+
fixedSizeStuff.writeUInt32LE(crc322, 14);
|
|
764
|
+
fixedSizeStuff.writeUInt32LE(compressedSize, 18);
|
|
765
|
+
fixedSizeStuff.writeUInt32LE(uncompressedSize, 22);
|
|
766
|
+
fixedSizeStuff.writeUInt16LE(this.utf8FileName.length, 26);
|
|
767
|
+
fixedSizeStuff.writeUInt16LE(0, 28);
|
|
768
|
+
return Buffer.concat([
|
|
769
|
+
fixedSizeStuff,
|
|
770
|
+
// file name (variable size)
|
|
771
|
+
this.utf8FileName
|
|
772
|
+
// extra field (variable size)
|
|
773
|
+
// no extra fields
|
|
774
|
+
]);
|
|
775
|
+
};
|
|
776
|
+
var DATA_DESCRIPTOR_SIZE = 16;
|
|
777
|
+
var ZIP64_DATA_DESCRIPTOR_SIZE = 24;
|
|
778
|
+
Entry.prototype.getDataDescriptor = function() {
|
|
779
|
+
if (this.crcAndFileSizeKnown) {
|
|
780
|
+
return EMPTY_BUFFER;
|
|
781
|
+
}
|
|
782
|
+
if (!this.useZip64Format()) {
|
|
783
|
+
var buffer = bufferAlloc(DATA_DESCRIPTOR_SIZE);
|
|
784
|
+
buffer.writeUInt32LE(134695760, 0);
|
|
785
|
+
buffer.writeUInt32LE(this.crc32, 4);
|
|
786
|
+
buffer.writeUInt32LE(this.compressedSize, 8);
|
|
787
|
+
buffer.writeUInt32LE(this.uncompressedSize, 12);
|
|
788
|
+
return buffer;
|
|
789
|
+
} else {
|
|
790
|
+
var buffer = bufferAlloc(ZIP64_DATA_DESCRIPTOR_SIZE);
|
|
791
|
+
buffer.writeUInt32LE(134695760, 0);
|
|
792
|
+
buffer.writeUInt32LE(this.crc32, 4);
|
|
793
|
+
writeUInt64LE(buffer, this.compressedSize, 8);
|
|
794
|
+
writeUInt64LE(buffer, this.uncompressedSize, 16);
|
|
795
|
+
return buffer;
|
|
796
|
+
}
|
|
797
|
+
};
|
|
798
|
+
var CENTRAL_DIRECTORY_RECORD_FIXED_SIZE = 46;
|
|
799
|
+
var INFO_ZIP_UNIVERSAL_TIMESTAMP_EXTRA_FIELD_SIZE = 9;
|
|
800
|
+
var ZIP64_EXTENDED_INFORMATION_EXTRA_FIELD_SIZE = 28;
|
|
801
|
+
Entry.prototype.getCentralDirectoryRecord = function() {
|
|
802
|
+
var fixedSizeStuff = bufferAlloc(CENTRAL_DIRECTORY_RECORD_FIXED_SIZE);
|
|
803
|
+
var generalPurposeBitFlag = FILE_NAME_IS_UTF8;
|
|
804
|
+
if (!this.crcAndFileSizeKnown) generalPurposeBitFlag |= UNKNOWN_CRC32_AND_FILE_SIZES;
|
|
805
|
+
var izutefBuffer = EMPTY_BUFFER;
|
|
806
|
+
if (!this.forceDosTimestamp) {
|
|
807
|
+
izutefBuffer = bufferAlloc(INFO_ZIP_UNIVERSAL_TIMESTAMP_EXTRA_FIELD_SIZE);
|
|
808
|
+
izutefBuffer.writeUInt16LE(21589, 0);
|
|
809
|
+
izutefBuffer.writeUInt16LE(INFO_ZIP_UNIVERSAL_TIMESTAMP_EXTRA_FIELD_SIZE - 4, 2);
|
|
810
|
+
var EB_UT_FL_MTIME = 1 << 0;
|
|
811
|
+
var EB_UT_FL_ATIME = 1 << 1;
|
|
812
|
+
izutefBuffer.writeUInt8(EB_UT_FL_MTIME | EB_UT_FL_ATIME, 4);
|
|
813
|
+
var timestamp = Math.floor(this.mtime.getTime() / 1e3);
|
|
814
|
+
if (timestamp < -2147483648) timestamp = -2147483648;
|
|
815
|
+
if (timestamp > 2147483647) timestamp = 2147483647;
|
|
816
|
+
izutefBuffer.writeUInt32LE(timestamp, 5);
|
|
817
|
+
}
|
|
818
|
+
var normalCompressedSize = this.compressedSize;
|
|
819
|
+
var normalUncompressedSize = this.uncompressedSize;
|
|
820
|
+
var normalRelativeOffsetOfLocalHeader = this.relativeOffsetOfLocalHeader;
|
|
821
|
+
var versionNeededToExtract = VERSION_NEEDED_TO_EXTRACT_UTF8;
|
|
822
|
+
var zeiefBuffer = EMPTY_BUFFER;
|
|
823
|
+
if (this.useZip64Format()) {
|
|
824
|
+
normalCompressedSize = 4294967295;
|
|
825
|
+
normalUncompressedSize = 4294967295;
|
|
826
|
+
normalRelativeOffsetOfLocalHeader = 4294967295;
|
|
827
|
+
versionNeededToExtract = VERSION_NEEDED_TO_EXTRACT_ZIP64;
|
|
828
|
+
zeiefBuffer = bufferAlloc(ZIP64_EXTENDED_INFORMATION_EXTRA_FIELD_SIZE);
|
|
829
|
+
zeiefBuffer.writeUInt16LE(1, 0);
|
|
830
|
+
zeiefBuffer.writeUInt16LE(ZIP64_EXTENDED_INFORMATION_EXTRA_FIELD_SIZE - 4, 2);
|
|
831
|
+
writeUInt64LE(zeiefBuffer, this.uncompressedSize, 4);
|
|
832
|
+
writeUInt64LE(zeiefBuffer, this.compressedSize, 12);
|
|
833
|
+
writeUInt64LE(zeiefBuffer, this.relativeOffsetOfLocalHeader, 20);
|
|
834
|
+
}
|
|
835
|
+
fixedSizeStuff.writeUInt32LE(33639248, 0);
|
|
836
|
+
fixedSizeStuff.writeUInt16LE(VERSION_MADE_BY, 4);
|
|
837
|
+
fixedSizeStuff.writeUInt16LE(versionNeededToExtract, 6);
|
|
838
|
+
fixedSizeStuff.writeUInt16LE(generalPurposeBitFlag, 8);
|
|
839
|
+
fixedSizeStuff.writeUInt16LE(this.getCompressionMethod(), 10);
|
|
840
|
+
fixedSizeStuff.writeUInt16LE(this.lastModFileTime, 12);
|
|
841
|
+
fixedSizeStuff.writeUInt16LE(this.lastModFileDate, 14);
|
|
842
|
+
fixedSizeStuff.writeUInt32LE(this.crc32, 16);
|
|
843
|
+
fixedSizeStuff.writeUInt32LE(normalCompressedSize, 20);
|
|
844
|
+
fixedSizeStuff.writeUInt32LE(normalUncompressedSize, 24);
|
|
845
|
+
fixedSizeStuff.writeUInt16LE(this.utf8FileName.length, 28);
|
|
846
|
+
fixedSizeStuff.writeUInt16LE(izutefBuffer.length + zeiefBuffer.length, 30);
|
|
847
|
+
fixedSizeStuff.writeUInt16LE(this.fileComment.length, 32);
|
|
848
|
+
fixedSizeStuff.writeUInt16LE(0, 34);
|
|
849
|
+
fixedSizeStuff.writeUInt16LE(0, 36);
|
|
850
|
+
fixedSizeStuff.writeUInt32LE(this.externalFileAttributes, 38);
|
|
851
|
+
fixedSizeStuff.writeUInt32LE(normalRelativeOffsetOfLocalHeader, 42);
|
|
852
|
+
return Buffer.concat([
|
|
853
|
+
fixedSizeStuff,
|
|
854
|
+
// file name (variable size)
|
|
855
|
+
this.utf8FileName,
|
|
856
|
+
// extra field (variable size)
|
|
857
|
+
izutefBuffer,
|
|
858
|
+
zeiefBuffer,
|
|
859
|
+
// file comment (variable size)
|
|
860
|
+
this.fileComment
|
|
861
|
+
]);
|
|
862
|
+
};
|
|
863
|
+
Entry.prototype.getCompressionMethod = function() {
|
|
864
|
+
var NO_COMPRESSION = 0;
|
|
865
|
+
var DEFLATE_COMPRESSION = 8;
|
|
866
|
+
return this.compressionLevel === 0 ? NO_COMPRESSION : DEFLATE_COMPRESSION;
|
|
867
|
+
};
|
|
868
|
+
var minDosDate = new Date(1980, 0, 1);
|
|
869
|
+
var maxDosDate = new Date(2107, 11, 31, 23, 59, 58);
|
|
870
|
+
function dateToDosDateTime(jsDate) {
|
|
871
|
+
if (jsDate < minDosDate) jsDate = minDosDate;
|
|
872
|
+
else if (jsDate > maxDosDate) jsDate = maxDosDate;
|
|
873
|
+
var date = 0;
|
|
874
|
+
date |= jsDate.getDate() & 31;
|
|
875
|
+
date |= (jsDate.getMonth() + 1 & 15) << 5;
|
|
876
|
+
date |= (jsDate.getFullYear() - 1980 & 127) << 9;
|
|
877
|
+
var time = 0;
|
|
878
|
+
time |= Math.floor(jsDate.getSeconds() / 2);
|
|
879
|
+
time |= (jsDate.getMinutes() & 63) << 5;
|
|
880
|
+
time |= (jsDate.getHours() & 31) << 11;
|
|
881
|
+
return { date, time };
|
|
882
|
+
}
|
|
883
|
+
function writeUInt64LE(buffer, n, offset) {
|
|
884
|
+
var high = Math.floor(n / 4294967296);
|
|
885
|
+
var low = n % 4294967296;
|
|
886
|
+
buffer.writeUInt32LE(low, offset);
|
|
887
|
+
buffer.writeUInt32LE(high, offset + 4);
|
|
888
|
+
}
|
|
889
|
+
util.inherits(ByteCounter, Transform);
|
|
890
|
+
function ByteCounter(options) {
|
|
891
|
+
Transform.call(this, options);
|
|
892
|
+
this.byteCount = 0;
|
|
893
|
+
}
|
|
894
|
+
ByteCounter.prototype._transform = function(chunk, encoding, cb) {
|
|
895
|
+
this.byteCount += chunk.length;
|
|
896
|
+
cb(null, chunk);
|
|
897
|
+
};
|
|
898
|
+
util.inherits(Crc32Watcher, Transform);
|
|
899
|
+
function Crc32Watcher(options) {
|
|
900
|
+
Transform.call(this, options);
|
|
901
|
+
this.crc32 = 0;
|
|
902
|
+
}
|
|
903
|
+
Crc32Watcher.prototype._transform = function(chunk, encoding, cb) {
|
|
904
|
+
this.crc32 = crc32.unsigned(chunk, this.crc32);
|
|
905
|
+
cb(null, chunk);
|
|
906
|
+
};
|
|
907
|
+
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";
|
|
908
|
+
if (cp437.length !== 256) throw new Error("assertion failure");
|
|
909
|
+
var reverseCp437 = null;
|
|
910
|
+
function encodeCp437(string) {
|
|
911
|
+
if (/^[\x20-\x7e]*$/.test(string)) {
|
|
912
|
+
return bufferFrom(string, "utf-8");
|
|
913
|
+
}
|
|
914
|
+
if (reverseCp437 == null) {
|
|
915
|
+
reverseCp437 = {};
|
|
916
|
+
for (var i = 0; i < cp437.length; i++) {
|
|
917
|
+
reverseCp437[cp437[i]] = i;
|
|
918
|
+
}
|
|
919
|
+
}
|
|
920
|
+
var result = bufferAlloc(string.length);
|
|
921
|
+
for (var i = 0; i < string.length; i++) {
|
|
922
|
+
var b = reverseCp437[string[i]];
|
|
923
|
+
if (b == null) throw new Error("character not encodable in CP437: " + JSON.stringify(string[i]));
|
|
924
|
+
result[i] = b;
|
|
925
|
+
}
|
|
926
|
+
return result;
|
|
927
|
+
}
|
|
928
|
+
function bufferAlloc(size) {
|
|
929
|
+
bufferAlloc = modern;
|
|
930
|
+
try {
|
|
931
|
+
return bufferAlloc(size);
|
|
932
|
+
} catch (e) {
|
|
933
|
+
bufferAlloc = legacy;
|
|
934
|
+
return bufferAlloc(size);
|
|
935
|
+
}
|
|
936
|
+
function modern(size2) {
|
|
937
|
+
return Buffer.allocUnsafe(size2);
|
|
938
|
+
}
|
|
939
|
+
function legacy(size2) {
|
|
940
|
+
return new Buffer(size2);
|
|
941
|
+
}
|
|
942
|
+
}
|
|
943
|
+
function bufferFrom(something, encoding) {
|
|
944
|
+
bufferFrom = modern;
|
|
945
|
+
try {
|
|
946
|
+
return bufferFrom(something, encoding);
|
|
947
|
+
} catch (e) {
|
|
948
|
+
bufferFrom = legacy;
|
|
949
|
+
return bufferFrom(something, encoding);
|
|
950
|
+
}
|
|
951
|
+
function modern(something2, encoding2) {
|
|
952
|
+
return Buffer.from(something2, encoding2);
|
|
953
|
+
}
|
|
954
|
+
function legacy(something2, encoding2) {
|
|
955
|
+
return new Buffer(something2, encoding2);
|
|
956
|
+
}
|
|
957
|
+
}
|
|
958
|
+
function bufferIncludes(buffer, content) {
|
|
959
|
+
bufferIncludes = modern;
|
|
960
|
+
try {
|
|
961
|
+
return bufferIncludes(buffer, content);
|
|
962
|
+
} catch (e) {
|
|
963
|
+
bufferIncludes = legacy;
|
|
964
|
+
return bufferIncludes(buffer, content);
|
|
965
|
+
}
|
|
966
|
+
function modern(buffer2, content2) {
|
|
967
|
+
return buffer2.includes(content2);
|
|
968
|
+
}
|
|
969
|
+
function legacy(buffer2, content2) {
|
|
970
|
+
for (var i = 0; i <= buffer2.length - content2.length; i++) {
|
|
971
|
+
for (var j = 0; ; j++) {
|
|
972
|
+
if (j === content2.length) return true;
|
|
973
|
+
if (buffer2[i + j] !== content2[j]) break;
|
|
974
|
+
}
|
|
975
|
+
}
|
|
976
|
+
return false;
|
|
977
|
+
}
|
|
978
|
+
}
|
|
979
|
+
}
|
|
980
|
+
});
|
|
2
981
|
|
|
3
982
|
// src/cliResult.ts
|
|
4
983
|
var ExitCode = {
|
|
@@ -1606,6 +2585,11 @@ function createAutoHandler(deps = {}) {
|
|
|
1606
2585
|
};
|
|
1607
2586
|
}
|
|
1608
2587
|
|
|
2588
|
+
// src/bdd.ts
|
|
2589
|
+
var import_yazl = __toESM(require_yazl(), 1);
|
|
2590
|
+
import { createWriteStream, mkdirSync, readFileSync as readFileSync4, readdirSync as readdirSync2, writeFileSync } from "node:fs";
|
|
2591
|
+
import path6 from "node:path";
|
|
2592
|
+
|
|
1609
2593
|
// src/forgeClient.ts
|
|
1610
2594
|
var ForgeClientError = class extends Error {
|
|
1611
2595
|
code;
|
|
@@ -1772,8 +2756,17 @@ function parseArgs2(args) {
|
|
|
1772
2756
|
const flags = {};
|
|
1773
2757
|
const boolFlags = /* @__PURE__ */ new Set();
|
|
1774
2758
|
const unknownFlags = [];
|
|
1775
|
-
const supportedValueFlags = /* @__PURE__ */ new Set([
|
|
1776
|
-
|
|
2759
|
+
const supportedValueFlags = /* @__PURE__ */ new Set([
|
|
2760
|
+
"--id",
|
|
2761
|
+
"--test-case-key",
|
|
2762
|
+
"--format",
|
|
2763
|
+
"--output-dir",
|
|
2764
|
+
"--input-dir",
|
|
2765
|
+
"--feature-id",
|
|
2766
|
+
"--file",
|
|
2767
|
+
...CONFIG_FLAGS2
|
|
2768
|
+
]);
|
|
2769
|
+
const supportedBoolFlags = /* @__PURE__ */ new Set(["--json", "--zip", "--all"]);
|
|
1777
2770
|
for (let index = 0; index < args.length; index += 1) {
|
|
1778
2771
|
const token = args[index];
|
|
1779
2772
|
if (!token.startsWith("--")) {
|
|
@@ -1831,6 +2824,94 @@ function toJsonScenario(scenario) {
|
|
|
1831
2824
|
updatedAt: scenario.updatedAt
|
|
1832
2825
|
};
|
|
1833
2826
|
}
|
|
2827
|
+
function scenarioToFeatureLines(scenario) {
|
|
2828
|
+
const lines = [];
|
|
2829
|
+
const tagSet = /* @__PURE__ */ new Set();
|
|
2830
|
+
tagSet.add(`@testops-scenario-${sanitizeFileToken(scenario.key ?? scenario.id)}`);
|
|
2831
|
+
for (const tag of scenario.tags) {
|
|
2832
|
+
tagSet.add(tag);
|
|
2833
|
+
}
|
|
2834
|
+
for (const issueKey of scenario.linkedIssueKeys) {
|
|
2835
|
+
tagSet.add(`@${issueKey}`);
|
|
2836
|
+
}
|
|
2837
|
+
if (tagSet.size > 0) {
|
|
2838
|
+
lines.push([...tagSet].join(" "));
|
|
2839
|
+
}
|
|
2840
|
+
lines.push(`Feature: ${scenario.featureName}`);
|
|
2841
|
+
lines.push("");
|
|
2842
|
+
lines.push(`Scenario: ${scenario.name}`);
|
|
2843
|
+
for (const step of scenario.steps) {
|
|
2844
|
+
lines.push(` ${step.keyword} ${step.text}`);
|
|
2845
|
+
}
|
|
2846
|
+
return lines;
|
|
2847
|
+
}
|
|
2848
|
+
function scenarioToExportFileName(scenario) {
|
|
2849
|
+
return `${sanitizeFileToken(scenario.key ?? scenario.id)}.feature`;
|
|
2850
|
+
}
|
|
2851
|
+
var ISSUE_KEY_PATTERN = /^[A-Z][A-Z0-9]+-\d+$/;
|
|
2852
|
+
var SCENARIO_METADATA_PATTERN = /^@testops-scenario-([A-Za-z0-9._-]+)$/i;
|
|
2853
|
+
function parseScenarioFeatureFile(raw, filePath) {
|
|
2854
|
+
let featureName = "";
|
|
2855
|
+
let scenarioName = "";
|
|
2856
|
+
let scenarioCount = 0;
|
|
2857
|
+
const tags = [];
|
|
2858
|
+
const steps = [];
|
|
2859
|
+
let inScenario = false;
|
|
2860
|
+
for (const rawLine of raw.split(/\r?\n/)) {
|
|
2861
|
+
const line = rawLine.trim();
|
|
2862
|
+
if (!line) {
|
|
2863
|
+
continue;
|
|
2864
|
+
}
|
|
2865
|
+
if (line.startsWith("@") && !inScenario && !scenarioName) {
|
|
2866
|
+
tags.push(...line.split(/\s+/).filter(Boolean));
|
|
2867
|
+
continue;
|
|
2868
|
+
}
|
|
2869
|
+
if (line.toLowerCase().startsWith("feature:")) {
|
|
2870
|
+
featureName = line.slice("feature:".length).trim();
|
|
2871
|
+
continue;
|
|
2872
|
+
}
|
|
2873
|
+
const scenarioMatch = line.match(/^Scenario(?: Outline)?:\s*(.+)$/i);
|
|
2874
|
+
if (scenarioMatch) {
|
|
2875
|
+
scenarioCount += 1;
|
|
2876
|
+
if (scenarioCount > 1) {
|
|
2877
|
+
return null;
|
|
2878
|
+
}
|
|
2879
|
+
scenarioName = scenarioMatch[1].trim();
|
|
2880
|
+
inScenario = true;
|
|
2881
|
+
continue;
|
|
2882
|
+
}
|
|
2883
|
+
const stepMatch = line.match(/^(Given|When|Then|And|But)\s+(.+)$/);
|
|
2884
|
+
if (stepMatch) {
|
|
2885
|
+
steps.push({
|
|
2886
|
+
keyword: stepMatch[1],
|
|
2887
|
+
text: stepMatch[2].trim()
|
|
2888
|
+
});
|
|
2889
|
+
continue;
|
|
2890
|
+
}
|
|
2891
|
+
}
|
|
2892
|
+
const scenarioTag = tags.map((tag) => tag.match(SCENARIO_METADATA_PATTERN)).find((match) => Boolean(match));
|
|
2893
|
+
const scenarioKeyFromTag = scenarioTag?.[1]?.trim().toUpperCase() ?? "";
|
|
2894
|
+
const fileKeyMatch = path6.basename(filePath ?? "").match(/^(SC-\d+)\.feature$/i);
|
|
2895
|
+
const scenarioKeyFromFile = fileKeyMatch?.[1]?.trim().toUpperCase() ?? "";
|
|
2896
|
+
const scenarioKey = scenarioKeyFromTag || scenarioKeyFromFile;
|
|
2897
|
+
if (scenarioKeyFromTag && scenarioKeyFromFile && scenarioKeyFromTag !== scenarioKeyFromFile) {
|
|
2898
|
+
return null;
|
|
2899
|
+
}
|
|
2900
|
+
if (!featureName || !scenarioName || !scenarioKey || steps.length === 0 || scenarioCount !== 1) {
|
|
2901
|
+
return null;
|
|
2902
|
+
}
|
|
2903
|
+
const linkedIssueKeys = [...new Set(
|
|
2904
|
+
tags.map((tag) => tag.replace(/^@/, "").trim().toUpperCase()).filter((tag) => ISSUE_KEY_PATTERN.test(tag))
|
|
2905
|
+
)];
|
|
2906
|
+
return {
|
|
2907
|
+
scenarioKey,
|
|
2908
|
+
featureName,
|
|
2909
|
+
scenarioName,
|
|
2910
|
+
tags,
|
|
2911
|
+
linkedIssueKeys,
|
|
2912
|
+
steps
|
|
2913
|
+
};
|
|
2914
|
+
}
|
|
1834
2915
|
function scenarioToLines(scenario) {
|
|
1835
2916
|
const lines = [
|
|
1836
2917
|
`BDD scenario: ${scenario.name}`,
|
|
@@ -1847,6 +2928,64 @@ function scenarioToLines(scenario) {
|
|
|
1847
2928
|
}
|
|
1848
2929
|
return lines;
|
|
1849
2930
|
}
|
|
2931
|
+
function featureToLines(feature) {
|
|
2932
|
+
return [
|
|
2933
|
+
`BDD feature: ${feature.payload.name}`,
|
|
2934
|
+
`Feature id: ${feature.id}`,
|
|
2935
|
+
`Project: ${feature.projectKey}`,
|
|
2936
|
+
`Linked issues: ${feature.linkedIssueKeys.join(", ") || "none"}`,
|
|
2937
|
+
`Created: ${feature.createdAt}`,
|
|
2938
|
+
`Scenarios: ${feature.parsedSummary.scenarios}`,
|
|
2939
|
+
`Steps: ${feature.parsedSummary.steps}`,
|
|
2940
|
+
`Lines: ${feature.parsedSummary.lines}`
|
|
2941
|
+
];
|
|
2942
|
+
}
|
|
2943
|
+
function slugifyFeatureName(value) {
|
|
2944
|
+
return value.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || "feature";
|
|
2945
|
+
}
|
|
2946
|
+
function sanitizeFileToken(value) {
|
|
2947
|
+
return value.trim().replace(/[^A-Za-z0-9._-]+/g, "-").replace(/^-+|-+$/g, "") || "feature";
|
|
2948
|
+
}
|
|
2949
|
+
function buildFeatureExportFileName(feature, index) {
|
|
2950
|
+
const slug = slugifyFeatureName(feature.payload.name);
|
|
2951
|
+
const ordinal = String(index + 1).padStart(3, "0");
|
|
2952
|
+
return `${ordinal}-${slug}.feature`;
|
|
2953
|
+
}
|
|
2954
|
+
function toExportManifestItems(features, fileNames) {
|
|
2955
|
+
return features.map((feature, index) => ({
|
|
2956
|
+
id: feature.id,
|
|
2957
|
+
name: feature.payload.name,
|
|
2958
|
+
fileName: fileNames[index],
|
|
2959
|
+
linkedIssueKeys: [...feature.linkedIssueKeys],
|
|
2960
|
+
scenarioCount: feature.parsedSummary.scenarios,
|
|
2961
|
+
stepCount: feature.parsedSummary.steps,
|
|
2962
|
+
createdAt: feature.createdAt
|
|
2963
|
+
}));
|
|
2964
|
+
}
|
|
2965
|
+
function toJsonExportManifestItems(items) {
|
|
2966
|
+
return items.map((item) => ({
|
|
2967
|
+
id: item.id,
|
|
2968
|
+
name: item.name,
|
|
2969
|
+
fileName: item.fileName,
|
|
2970
|
+
linkedIssueKeys: [...item.linkedIssueKeys],
|
|
2971
|
+
scenarioCount: item.scenarioCount,
|
|
2972
|
+
stepCount: item.stepCount,
|
|
2973
|
+
createdAt: item.createdAt
|
|
2974
|
+
}));
|
|
2975
|
+
}
|
|
2976
|
+
async function defaultCreateZipArchive(archivePath, entries) {
|
|
2977
|
+
await new Promise((resolve, reject) => {
|
|
2978
|
+
const zip = new import_yazl.ZipFile();
|
|
2979
|
+
const output = zip.outputStream.pipe(createWriteStream(archivePath));
|
|
2980
|
+
output.on("close", () => resolve());
|
|
2981
|
+
output.on("error", reject);
|
|
2982
|
+
zip.outputStream.on("error", reject);
|
|
2983
|
+
for (const entry of entries) {
|
|
2984
|
+
zip.addBuffer(Buffer.from(entry.content, "utf8"), entry.fileName);
|
|
2985
|
+
}
|
|
2986
|
+
zip.end();
|
|
2987
|
+
});
|
|
2988
|
+
}
|
|
1850
2989
|
function automationToLines(payload, scenarioKey) {
|
|
1851
2990
|
return [
|
|
1852
2991
|
`Triggered scenario automation for ${scenarioKey}`,
|
|
@@ -1867,10 +3006,16 @@ function missingProjectResponse() {
|
|
|
1867
3006
|
function createBddHandler(deps = {}) {
|
|
1868
3007
|
const cwd = deps.cwd ?? process.cwd();
|
|
1869
3008
|
const env = deps.env ?? process.env;
|
|
3009
|
+
const mkdir = deps.mkdir ?? ((targetPath, options) => mkdirSync(targetPath, options));
|
|
3010
|
+
const readFile = deps.readFile ?? ((filePath) => readFileSync4(filePath, "utf8"));
|
|
3011
|
+
const readDir = deps.readDir ?? ((dirPath) => readdirSync2(dirPath));
|
|
3012
|
+
const writeFile = deps.writeFile ?? ((filePath, content) => writeFileSync(filePath, content, "utf8"));
|
|
3013
|
+
const createZipArchive = deps.createZipArchive ?? defaultCreateZipArchive;
|
|
1870
3014
|
return async (request, context) => {
|
|
1871
3015
|
const [subcommand, ...restArgs] = request.args;
|
|
1872
3016
|
const parsed = parseArgs2(restArgs);
|
|
1873
|
-
const
|
|
3017
|
+
const requestedFormat = (parsed.flags["--format"] ?? "").trim().toLowerCase();
|
|
3018
|
+
const outputFormat = parsed.boolFlags.has("--json") ? "json" : requestedFormat || "text";
|
|
1874
3019
|
const config = resolveCliConfig(pickConfigArgs2(parsed), env, cwd);
|
|
1875
3020
|
const projectKey = config.values.projectKey;
|
|
1876
3021
|
const issueKey = config.values.issueKey;
|
|
@@ -1880,20 +3025,373 @@ function createBddHandler(deps = {}) {
|
|
|
1880
3025
|
stderr: [`ERROR: Unknown or invalid flags: ${parsed.unknownFlags.join(", ")}`]
|
|
1881
3026
|
};
|
|
1882
3027
|
}
|
|
3028
|
+
if (!["text", "json", "feature"].includes(outputFormat)) {
|
|
3029
|
+
return {
|
|
3030
|
+
exitCode: ExitCode.ValidationError,
|
|
3031
|
+
stderr: ["ERROR: Unsupported --format. Use one of: text, json, feature."]
|
|
3032
|
+
};
|
|
3033
|
+
}
|
|
1883
3034
|
if (!projectKey) {
|
|
1884
3035
|
return missingProjectResponse();
|
|
1885
3036
|
}
|
|
3037
|
+
if (subcommand === "features") {
|
|
3038
|
+
const nested = restArgs[0];
|
|
3039
|
+
if (nested !== "export") {
|
|
3040
|
+
return {
|
|
3041
|
+
exitCode: ExitCode.UsageError,
|
|
3042
|
+
stderr: [
|
|
3043
|
+
"ERROR: Unsupported bdd features subcommand. Use: testops bdd features export --output-dir <path> [--feature-id <FEATURE_ID>] [--json]"
|
|
3044
|
+
]
|
|
3045
|
+
};
|
|
3046
|
+
}
|
|
3047
|
+
const outputDirFlag = parsed.flags["--output-dir"]?.trim() ?? "";
|
|
3048
|
+
const featureId = parsed.flags["--feature-id"]?.trim() ?? "";
|
|
3049
|
+
const zipRequested = parsed.boolFlags.has("--zip");
|
|
3050
|
+
if (!outputDirFlag) {
|
|
3051
|
+
return {
|
|
3052
|
+
exitCode: ExitCode.ValidationError,
|
|
3053
|
+
stderr: ["ERROR: Missing required --output-dir for testops bdd features export."]
|
|
3054
|
+
};
|
|
3055
|
+
}
|
|
3056
|
+
const outputDir = path6.resolve(cwd, outputDirFlag);
|
|
3057
|
+
try {
|
|
3058
|
+
const result = await context.invokeForgeContract("listBddFeatures", {
|
|
3059
|
+
context: {
|
|
3060
|
+
projectKey,
|
|
3061
|
+
issueKey: issueKey || void 0
|
|
3062
|
+
}
|
|
3063
|
+
});
|
|
3064
|
+
if (!result.ok) {
|
|
3065
|
+
return {
|
|
3066
|
+
exitCode: ExitCode.RemoteError,
|
|
3067
|
+
stderr: [`ERROR: ${result.error.code}: ${result.error.message}`]
|
|
3068
|
+
};
|
|
3069
|
+
}
|
|
3070
|
+
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));
|
|
3071
|
+
if (featureId && features.length === 0) {
|
|
3072
|
+
return {
|
|
3073
|
+
exitCode: ExitCode.RemoteError,
|
|
3074
|
+
stderr: [`ERROR: NOT_FOUND: BDD feature ${featureId} was not found in this project.`]
|
|
3075
|
+
};
|
|
3076
|
+
}
|
|
3077
|
+
if (features.length === 0) {
|
|
3078
|
+
return {
|
|
3079
|
+
exitCode: ExitCode.RemoteError,
|
|
3080
|
+
stderr: ["ERROR: NOT_FOUND: No BDD features were found in this project context."]
|
|
3081
|
+
};
|
|
3082
|
+
}
|
|
3083
|
+
mkdir(outputDir, { recursive: true });
|
|
3084
|
+
const fileNames = features.map((feature, index) => buildFeatureExportFileName(feature, index));
|
|
3085
|
+
const manifestItems = toExportManifestItems(features, fileNames);
|
|
3086
|
+
const exportEntries = features.map((feature, index) => ({
|
|
3087
|
+
fileName: fileNames[index],
|
|
3088
|
+
content: `${feature.payload.gherkin.trimEnd()}
|
|
3089
|
+
`
|
|
3090
|
+
}));
|
|
3091
|
+
for (let index = 0; index < features.length; index += 1) {
|
|
3092
|
+
writeFile(path6.join(outputDir, fileNames[index]), exportEntries[index].content);
|
|
3093
|
+
}
|
|
3094
|
+
const manifest = {
|
|
3095
|
+
action: "bdd-features-export",
|
|
3096
|
+
projectKey,
|
|
3097
|
+
issueKey: issueKey || null,
|
|
3098
|
+
outputDir,
|
|
3099
|
+
exportedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3100
|
+
count: features.length,
|
|
3101
|
+
items: manifestItems
|
|
3102
|
+
};
|
|
3103
|
+
const manifestContent = `${JSON.stringify(manifest, null, 2)}
|
|
3104
|
+
`;
|
|
3105
|
+
writeFile(path6.join(outputDir, "manifest.json"), manifestContent);
|
|
3106
|
+
const archivePath = `${outputDir}.zip`;
|
|
3107
|
+
if (zipRequested) {
|
|
3108
|
+
await createZipArchive(archivePath, [
|
|
3109
|
+
...exportEntries,
|
|
3110
|
+
{ fileName: "manifest.json", content: manifestContent }
|
|
3111
|
+
]);
|
|
3112
|
+
}
|
|
3113
|
+
if (outputFormat === "json") {
|
|
3114
|
+
return {
|
|
3115
|
+
exitCode: ExitCode.Success,
|
|
3116
|
+
stdout: toJsonLine({
|
|
3117
|
+
action: manifest.action,
|
|
3118
|
+
projectKey: manifest.projectKey,
|
|
3119
|
+
issueKey: manifest.issueKey,
|
|
3120
|
+
outputDir: manifest.outputDir,
|
|
3121
|
+
exportedAt: manifest.exportedAt,
|
|
3122
|
+
count: manifest.count,
|
|
3123
|
+
items: toJsonExportManifestItems(manifestItems),
|
|
3124
|
+
archivePath: zipRequested ? archivePath : null
|
|
3125
|
+
})
|
|
3126
|
+
};
|
|
3127
|
+
}
|
|
3128
|
+
return {
|
|
3129
|
+
exitCode: ExitCode.Success,
|
|
3130
|
+
stdout: [
|
|
3131
|
+
`BDD features exported: ${features.length}`,
|
|
3132
|
+
`Output directory: ${outputDir}`,
|
|
3133
|
+
...zipRequested ? [`ZIP archive: ${archivePath}`] : [],
|
|
3134
|
+
"Files:",
|
|
3135
|
+
...manifestItems.flatMap((item) => [
|
|
3136
|
+
`- ${item.fileName}`,
|
|
3137
|
+
...featureToLines(features.find((feature) => feature.id === item.id))
|
|
3138
|
+
])
|
|
3139
|
+
]
|
|
3140
|
+
};
|
|
3141
|
+
} catch (error) {
|
|
3142
|
+
return {
|
|
3143
|
+
exitCode: ExitCode.TransportError,
|
|
3144
|
+
stderr: [`ERROR: ${normalizeError(error)}`]
|
|
3145
|
+
};
|
|
3146
|
+
}
|
|
3147
|
+
}
|
|
1886
3148
|
if (subcommand === "scenarios") {
|
|
1887
3149
|
const nested = restArgs[0];
|
|
1888
3150
|
if (nested !== "show") {
|
|
1889
|
-
if (nested !== "run") {
|
|
3151
|
+
if (nested !== "run" && nested !== "export" && nested !== "import") {
|
|
1890
3152
|
return {
|
|
1891
3153
|
exitCode: ExitCode.UsageError,
|
|
1892
3154
|
stderr: [
|
|
1893
|
-
"ERROR: Unsupported bdd scenarios subcommand. Use: testops bdd scenarios show
|
|
3155
|
+
"ERROR: Unsupported bdd scenarios subcommand. Use: testops bdd scenarios show|run|export|import ..."
|
|
1894
3156
|
]
|
|
1895
3157
|
};
|
|
1896
3158
|
}
|
|
3159
|
+
if (nested === "export") {
|
|
3160
|
+
const scenarioSelector = parsed.flags["--id"]?.trim() ?? "";
|
|
3161
|
+
const exportAll = parsed.boolFlags.has("--all");
|
|
3162
|
+
const outputDirFlag = parsed.flags["--output-dir"]?.trim() ?? "";
|
|
3163
|
+
if (!scenarioSelector && !exportAll) {
|
|
3164
|
+
return {
|
|
3165
|
+
exitCode: ExitCode.ValidationError,
|
|
3166
|
+
stderr: ["ERROR: Provide --id <SCENARIO_ID|SC-4> or --all for testops bdd scenarios export."]
|
|
3167
|
+
};
|
|
3168
|
+
}
|
|
3169
|
+
if (!outputDirFlag) {
|
|
3170
|
+
return {
|
|
3171
|
+
exitCode: ExitCode.ValidationError,
|
|
3172
|
+
stderr: ["ERROR: Missing required --output-dir for testops bdd scenarios export."]
|
|
3173
|
+
};
|
|
3174
|
+
}
|
|
3175
|
+
const outputDir = path6.resolve(cwd, outputDirFlag);
|
|
3176
|
+
const zipRequested = parsed.boolFlags.has("--zip");
|
|
3177
|
+
try {
|
|
3178
|
+
const scenariosResult = await context.invokeForgeContract("listBddScenarios", {
|
|
3179
|
+
context: {
|
|
3180
|
+
projectKey,
|
|
3181
|
+
issueKey: issueKey || void 0
|
|
3182
|
+
}
|
|
3183
|
+
});
|
|
3184
|
+
if (!scenariosResult.ok) {
|
|
3185
|
+
return {
|
|
3186
|
+
exitCode: ExitCode.RemoteError,
|
|
3187
|
+
stderr: [`ERROR: ${scenariosResult.error.code}: ${scenariosResult.error.message}`]
|
|
3188
|
+
};
|
|
3189
|
+
}
|
|
3190
|
+
const selectedScenarios = exportAll ? [...scenariosResult.data].sort((left, right) => (left.key ?? left.id).localeCompare(right.key ?? right.id)) : scenariosResult.data.filter(
|
|
3191
|
+
(item) => item.id === scenarioSelector || (item.key ?? "").toUpperCase() === scenarioSelector.toUpperCase()
|
|
3192
|
+
);
|
|
3193
|
+
if (!exportAll && selectedScenarios.length === 0) {
|
|
3194
|
+
return {
|
|
3195
|
+
exitCode: ExitCode.RemoteError,
|
|
3196
|
+
stderr: [`ERROR: NOT_FOUND: BDD scenario ${scenarioSelector} was not found in this project.`]
|
|
3197
|
+
};
|
|
3198
|
+
}
|
|
3199
|
+
if (selectedScenarios.length === 0) {
|
|
3200
|
+
return {
|
|
3201
|
+
exitCode: ExitCode.RemoteError,
|
|
3202
|
+
stderr: ["ERROR: NOT_FOUND: No BDD scenarios were found in this project context."]
|
|
3203
|
+
};
|
|
3204
|
+
}
|
|
3205
|
+
mkdir(outputDir, { recursive: true });
|
|
3206
|
+
const items = selectedScenarios.map((scenario) => {
|
|
3207
|
+
const fileName = scenarioToExportFileName(scenario);
|
|
3208
|
+
const fileContent = `${scenarioToFeatureLines(scenario).join("\n")}
|
|
3209
|
+
`;
|
|
3210
|
+
writeFile(path6.join(outputDir, fileName), fileContent);
|
|
3211
|
+
return {
|
|
3212
|
+
scenario,
|
|
3213
|
+
fileName,
|
|
3214
|
+
fileContent
|
|
3215
|
+
};
|
|
3216
|
+
});
|
|
3217
|
+
const manifest = {
|
|
3218
|
+
action: "bdd-scenarios-export",
|
|
3219
|
+
projectKey,
|
|
3220
|
+
issueKey: issueKey || null,
|
|
3221
|
+
outputDir,
|
|
3222
|
+
exportedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3223
|
+
count: items.length,
|
|
3224
|
+
items: items.map(({ scenario, fileName }) => ({
|
|
3225
|
+
id: scenario.id,
|
|
3226
|
+
key: scenario.key ?? null,
|
|
3227
|
+
featureName: scenario.featureName,
|
|
3228
|
+
scenarioName: scenario.name,
|
|
3229
|
+
fileName,
|
|
3230
|
+
linkedIssueKeys: [...scenario.linkedIssueKeys],
|
|
3231
|
+
tags: [...scenario.tags]
|
|
3232
|
+
}))
|
|
3233
|
+
};
|
|
3234
|
+
const manifestContent = `${JSON.stringify(manifest, null, 2)}
|
|
3235
|
+
`;
|
|
3236
|
+
writeFile(path6.join(outputDir, "manifest.json"), manifestContent);
|
|
3237
|
+
const archivePath = `${outputDir}.zip`;
|
|
3238
|
+
if (zipRequested) {
|
|
3239
|
+
await createZipArchive(archivePath, [
|
|
3240
|
+
...items.map(({ fileName, fileContent }) => ({ fileName, content: fileContent })),
|
|
3241
|
+
{ fileName: "manifest.json", content: manifestContent }
|
|
3242
|
+
]);
|
|
3243
|
+
}
|
|
3244
|
+
if (outputFormat === "json") {
|
|
3245
|
+
return {
|
|
3246
|
+
exitCode: ExitCode.Success,
|
|
3247
|
+
stdout: toJsonLine({
|
|
3248
|
+
action: manifest.action,
|
|
3249
|
+
projectKey,
|
|
3250
|
+
issueKey: issueKey || null,
|
|
3251
|
+
outputDir,
|
|
3252
|
+
exportedAt: manifest.exportedAt,
|
|
3253
|
+
count: items.length,
|
|
3254
|
+
archivePath: zipRequested ? archivePath : null,
|
|
3255
|
+
items: items.map(({ scenario, fileName }) => ({
|
|
3256
|
+
id: scenario.id,
|
|
3257
|
+
key: scenario.key ?? null,
|
|
3258
|
+
featureName: scenario.featureName,
|
|
3259
|
+
scenarioName: scenario.name,
|
|
3260
|
+
fileName,
|
|
3261
|
+
linkedIssueKeys: [...scenario.linkedIssueKeys],
|
|
3262
|
+
tags: [...scenario.tags]
|
|
3263
|
+
}))
|
|
3264
|
+
})
|
|
3265
|
+
};
|
|
3266
|
+
}
|
|
3267
|
+
return {
|
|
3268
|
+
exitCode: ExitCode.Success,
|
|
3269
|
+
stdout: [
|
|
3270
|
+
`BDD scenarios exported: ${items.length}`,
|
|
3271
|
+
`Output directory: ${outputDir}`,
|
|
3272
|
+
...zipRequested ? [`ZIP archive: ${archivePath}`] : [],
|
|
3273
|
+
...items.flatMap(({ scenario, fileName }) => [`File: ${fileName}`, ...scenarioToLines(scenario)])
|
|
3274
|
+
]
|
|
3275
|
+
};
|
|
3276
|
+
} catch (error) {
|
|
3277
|
+
return {
|
|
3278
|
+
exitCode: ExitCode.TransportError,
|
|
3279
|
+
stderr: [`ERROR: ${normalizeError(error)}`]
|
|
3280
|
+
};
|
|
3281
|
+
}
|
|
3282
|
+
}
|
|
3283
|
+
if (nested === "import") {
|
|
3284
|
+
const sourceFile = parsed.flags["--file"] ? path6.resolve(cwd, parsed.flags["--file"]) : "";
|
|
3285
|
+
const inputDir = parsed.flags["--input-dir"] ? path6.resolve(cwd, parsed.flags["--input-dir"]) : "";
|
|
3286
|
+
if (!sourceFile && !inputDir) {
|
|
3287
|
+
return {
|
|
3288
|
+
exitCode: ExitCode.ValidationError,
|
|
3289
|
+
stderr: ["ERROR: Provide --file <SC-4.feature> or --input-dir <dir> for testops bdd scenarios import."]
|
|
3290
|
+
};
|
|
3291
|
+
}
|
|
3292
|
+
try {
|
|
3293
|
+
const scenarioFiles = sourceFile ? [sourceFile] : readDir(inputDir).filter((entry) => entry.toLowerCase().endsWith(".feature")).map((entry) => path6.join(inputDir, entry)).sort((left, right) => left.localeCompare(right));
|
|
3294
|
+
if (scenarioFiles.length === 0) {
|
|
3295
|
+
return {
|
|
3296
|
+
exitCode: ExitCode.ValidationError,
|
|
3297
|
+
stderr: ["ERROR: No .feature files were found for scenario import."]
|
|
3298
|
+
};
|
|
3299
|
+
}
|
|
3300
|
+
const parsedScenarios = scenarioFiles.map((filePath) => ({
|
|
3301
|
+
filePath,
|
|
3302
|
+
parsed: parseScenarioFeatureFile(readFile(filePath), filePath)
|
|
3303
|
+
}));
|
|
3304
|
+
const invalidScenarioFile = parsedScenarios.find((item) => !item.parsed);
|
|
3305
|
+
if (invalidScenarioFile) {
|
|
3306
|
+
return {
|
|
3307
|
+
exitCode: ExitCode.ValidationError,
|
|
3308
|
+
stderr: [
|
|
3309
|
+
`ERROR: Scenario feature file ${invalidScenarioFile.filePath} must contain exactly one scenario, valid steps, and a matching SC-* key in tag or filename.`
|
|
3310
|
+
]
|
|
3311
|
+
};
|
|
3312
|
+
}
|
|
3313
|
+
const scenariosResult = await context.invokeForgeContract("listBddScenarios", {
|
|
3314
|
+
context: {
|
|
3315
|
+
projectKey,
|
|
3316
|
+
issueKey: issueKey || void 0
|
|
3317
|
+
}
|
|
3318
|
+
});
|
|
3319
|
+
if (!scenariosResult.ok) {
|
|
3320
|
+
return {
|
|
3321
|
+
exitCode: ExitCode.RemoteError,
|
|
3322
|
+
stderr: [`ERROR: ${scenariosResult.error.code}: ${scenariosResult.error.message}`]
|
|
3323
|
+
};
|
|
3324
|
+
}
|
|
3325
|
+
const updatedItems = [];
|
|
3326
|
+
for (const entry of parsedScenarios) {
|
|
3327
|
+
const parsedScenario = entry.parsed;
|
|
3328
|
+
const scenario = scenariosResult.data.find(
|
|
3329
|
+
(item) => (item.key ?? "").toUpperCase() === parsedScenario.scenarioKey.toUpperCase()
|
|
3330
|
+
);
|
|
3331
|
+
if (!scenario) {
|
|
3332
|
+
return {
|
|
3333
|
+
exitCode: ExitCode.RemoteError,
|
|
3334
|
+
stderr: [`ERROR: NOT_FOUND: BDD scenario ${parsedScenario.scenarioKey} was not found in this project.`]
|
|
3335
|
+
};
|
|
3336
|
+
}
|
|
3337
|
+
const nextTags = parsedScenario.tags.filter((tag) => !SCENARIO_METADATA_PATTERN.test(tag));
|
|
3338
|
+
const updateResult = await context.invokeForgeContract("updateScenario", {
|
|
3339
|
+
context: {
|
|
3340
|
+
projectKey,
|
|
3341
|
+
issueKey: issueKey || void 0
|
|
3342
|
+
},
|
|
3343
|
+
scenarioId: scenario.id,
|
|
3344
|
+
input: {
|
|
3345
|
+
featureName: parsedScenario.featureName,
|
|
3346
|
+
name: parsedScenario.scenarioName,
|
|
3347
|
+
steps: [...parsedScenario.steps],
|
|
3348
|
+
tags: nextTags,
|
|
3349
|
+
linkedIssueKeys: [...parsedScenario.linkedIssueKeys]
|
|
3350
|
+
}
|
|
3351
|
+
});
|
|
3352
|
+
if (!updateResult.ok) {
|
|
3353
|
+
return {
|
|
3354
|
+
exitCode: ExitCode.RemoteError,
|
|
3355
|
+
stderr: [`ERROR: ${updateResult.error.code}: ${updateResult.error.message}`]
|
|
3356
|
+
};
|
|
3357
|
+
}
|
|
3358
|
+
updatedItems.push({
|
|
3359
|
+
file: entry.filePath,
|
|
3360
|
+
item: updateResult.data
|
|
3361
|
+
});
|
|
3362
|
+
}
|
|
3363
|
+
if (outputFormat === "json") {
|
|
3364
|
+
return {
|
|
3365
|
+
exitCode: ExitCode.Success,
|
|
3366
|
+
stdout: toJsonLine({
|
|
3367
|
+
action: "bdd-scenarios-import",
|
|
3368
|
+
projectKey,
|
|
3369
|
+
issueKey: issueKey || null,
|
|
3370
|
+
count: updatedItems.length,
|
|
3371
|
+
file: sourceFile || null,
|
|
3372
|
+
inputDir: inputDir || null,
|
|
3373
|
+
items: updatedItems.map((entry) => ({
|
|
3374
|
+
file: entry.file,
|
|
3375
|
+
item: toJsonScenario(entry.item)
|
|
3376
|
+
}))
|
|
3377
|
+
})
|
|
3378
|
+
};
|
|
3379
|
+
}
|
|
3380
|
+
return {
|
|
3381
|
+
exitCode: ExitCode.Success,
|
|
3382
|
+
stdout: updatedItems.flatMap((entry) => [
|
|
3383
|
+
`BDD scenario imported: ${entry.item.key ?? entry.item.id}`,
|
|
3384
|
+
`Source: ${entry.file}`,
|
|
3385
|
+
...scenarioToLines(entry.item)
|
|
3386
|
+
])
|
|
3387
|
+
};
|
|
3388
|
+
} catch (error) {
|
|
3389
|
+
return {
|
|
3390
|
+
exitCode: ExitCode.TransportError,
|
|
3391
|
+
stderr: [`ERROR: ${normalizeError(error)}`]
|
|
3392
|
+
};
|
|
3393
|
+
}
|
|
3394
|
+
}
|
|
1897
3395
|
const scenarioId2 = parsed.flags["--id"]?.trim() ?? "";
|
|
1898
3396
|
const testCaseKey = parsed.flags["--test-case-key"]?.trim().toUpperCase() ?? "";
|
|
1899
3397
|
if (!scenarioId2 && !testCaseKey) {
|
|
@@ -1960,7 +3458,7 @@ function createBddHandler(deps = {}) {
|
|
|
1960
3458
|
}
|
|
1961
3459
|
runs.push(result.data);
|
|
1962
3460
|
}
|
|
1963
|
-
if (
|
|
3461
|
+
if (outputFormat === "json") {
|
|
1964
3462
|
return {
|
|
1965
3463
|
exitCode: ExitCode.Success,
|
|
1966
3464
|
stdout: toJsonLine({
|
|
@@ -2018,7 +3516,7 @@ function createBddHandler(deps = {}) {
|
|
|
2018
3516
|
stderr: [`ERROR: ${result.error.code}: ${result.error.message}`]
|
|
2019
3517
|
};
|
|
2020
3518
|
}
|
|
2021
|
-
if (
|
|
3519
|
+
if (outputFormat === "json") {
|
|
2022
3520
|
return {
|
|
2023
3521
|
exitCode: ExitCode.Success,
|
|
2024
3522
|
stdout: toJsonLine({
|
|
@@ -2029,6 +3527,12 @@ function createBddHandler(deps = {}) {
|
|
|
2029
3527
|
})
|
|
2030
3528
|
};
|
|
2031
3529
|
}
|
|
3530
|
+
if (outputFormat === "feature") {
|
|
3531
|
+
return {
|
|
3532
|
+
exitCode: ExitCode.Success,
|
|
3533
|
+
stdout: scenarioToFeatureLines(result.data)
|
|
3534
|
+
};
|
|
3535
|
+
}
|
|
2032
3536
|
return {
|
|
2033
3537
|
exitCode: ExitCode.Success,
|
|
2034
3538
|
stdout: scenarioToLines(result.data)
|
|
@@ -2673,8 +4177,8 @@ function createDoctorHandler(deps = {}) {
|
|
|
2673
4177
|
}
|
|
2674
4178
|
|
|
2675
4179
|
// src/ingestFeature.ts
|
|
2676
|
-
import { readFileSync as
|
|
2677
|
-
import
|
|
4180
|
+
import { readFileSync as readFileSync5 } from "node:fs";
|
|
4181
|
+
import path7 from "node:path";
|
|
2678
4182
|
var CONFIG_FLAGS5 = /* @__PURE__ */ new Set([
|
|
2679
4183
|
"--config",
|
|
2680
4184
|
"--base-url",
|
|
@@ -2760,8 +4264,8 @@ function normalizeError3(error) {
|
|
|
2760
4264
|
return "Unknown ingest error.";
|
|
2761
4265
|
}
|
|
2762
4266
|
function createIngestFeatureHandler(deps = {}) {
|
|
2763
|
-
const readFile = deps.readFile ?? ((filePath) =>
|
|
2764
|
-
const readStdin = deps.readStdin ?? (() =>
|
|
4267
|
+
const readFile = deps.readFile ?? ((filePath) => readFileSync5(filePath, "utf8"));
|
|
4268
|
+
const readStdin = deps.readStdin ?? (() => readFileSync5(0, "utf8"));
|
|
2765
4269
|
const cwd = deps.cwd ?? process.cwd();
|
|
2766
4270
|
const env = deps.env ?? process.env;
|
|
2767
4271
|
return async (request, context) => {
|
|
@@ -2771,7 +4275,7 @@ function createIngestFeatureHandler(deps = {}) {
|
|
|
2771
4275
|
const config = resolveCliConfig(configArgs, env, cwd);
|
|
2772
4276
|
const projectKey = config.values.projectKey;
|
|
2773
4277
|
const issueKey = config.values.issueKey;
|
|
2774
|
-
const sourceFile = parsed.flags["--file"] ?
|
|
4278
|
+
const sourceFile = parsed.flags["--file"] ? path7.resolve(cwd, parsed.flags["--file"]) : "";
|
|
2775
4279
|
const useStdin = parsed.boolFlags.has("--stdin");
|
|
2776
4280
|
const useJson = parsed.boolFlags.has("--json");
|
|
2777
4281
|
const sourceCount = Number(Boolean(sourceFile)) + Number(useStdin);
|
|
@@ -2900,8 +4404,8 @@ function createIngestFeatureHandler(deps = {}) {
|
|
|
2900
4404
|
}
|
|
2901
4405
|
|
|
2902
4406
|
// src/runUpload.ts
|
|
2903
|
-
import { readFileSync as
|
|
2904
|
-
import
|
|
4407
|
+
import { readFileSync as readFileSync6 } from "node:fs";
|
|
4408
|
+
import path8 from "node:path";
|
|
2905
4409
|
var STEP_RESULTS = [
|
|
2906
4410
|
StepResult.Passed,
|
|
2907
4411
|
StepResult.Failed,
|
|
@@ -3042,8 +4546,8 @@ function summarizeRunResult(result) {
|
|
|
3042
4546
|
return lines;
|
|
3043
4547
|
}
|
|
3044
4548
|
function createRunUploadHandler(deps = {}) {
|
|
3045
|
-
const readFile = deps.readFile ?? ((filePath) =>
|
|
3046
|
-
const readStdin = deps.readStdin ?? (() =>
|
|
4549
|
+
const readFile = deps.readFile ?? ((filePath) => readFileSync6(filePath, "utf8"));
|
|
4550
|
+
const readStdin = deps.readStdin ?? (() => readFileSync6(0, "utf8"));
|
|
3047
4551
|
const cwd = deps.cwd ?? process.cwd();
|
|
3048
4552
|
const env = deps.env ?? process.env;
|
|
3049
4553
|
return async (request, context) => {
|
|
@@ -3054,7 +4558,7 @@ function createRunUploadHandler(deps = {}) {
|
|
|
3054
4558
|
const projectKey = config.values.projectKey;
|
|
3055
4559
|
const issueKey = config.values.issueKey;
|
|
3056
4560
|
const testCaseKey = parsed.flags["--test-case-key"]?.trim().toUpperCase() ?? "";
|
|
3057
|
-
const sourceFile = parsed.flags["--file"] ?
|
|
4561
|
+
const sourceFile = parsed.flags["--file"] ? path8.resolve(cwd, parsed.flags["--file"]) : "";
|
|
3058
4562
|
const useStdin = parsed.boolFlags.has("--stdin");
|
|
3059
4563
|
const useJson = parsed.boolFlags.has("--json");
|
|
3060
4564
|
const sourceCount = Number(Boolean(sourceFile)) + Number(useStdin);
|
|
@@ -3900,8 +5404,8 @@ var COMMAND_REGISTRY = [
|
|
|
3900
5404
|
},
|
|
3901
5405
|
{
|
|
3902
5406
|
name: "bdd",
|
|
3903
|
-
description: "BDD scenario inspection commands",
|
|
3904
|
-
subcommands: ["scenarios"],
|
|
5407
|
+
description: "BDD scenario inspection and feature export commands",
|
|
5408
|
+
subcommands: ["features", "scenarios"],
|
|
3905
5409
|
handler: createBddHandler()
|
|
3906
5410
|
},
|
|
3907
5411
|
{
|