@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.
- package/README.md +106 -30
- package/dist/{automatify.js → automatify.cjs} +1553 -54
- package/package.json +8 -4
|
@@ -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
|
-
|
|
18
|
-
|
|
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
|
-
|
|
59
|
-
|
|
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"] ?
|
|
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 ?
|
|
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
|
-
|
|
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(
|
|
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
|
-
|
|
678
|
-
|
|
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 (!
|
|
1662
|
+
if (!(0, import_node_fs2.existsSync)(featureAbsolutePath)) {
|
|
689
1663
|
return { names: [], issueKeys: [] };
|
|
690
1664
|
}
|
|
691
|
-
const raw =
|
|
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 =
|
|
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
|
-
|
|
799
|
-
|
|
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(
|
|
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 =
|
|
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 =
|
|
877
|
-
const relativeEntryPath = normalizeRelativePath(
|
|
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
|
|
1958
|
+
return import_node_path5.default.resolve(cwd, rootFlag);
|
|
985
1959
|
}
|
|
986
1960
|
function countScenariosInFeatureFile(featurePath) {
|
|
987
|
-
const lines =
|
|
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 =
|
|
1000
|
-
if (!
|
|
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
|
|
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 =
|
|
1057
|
-
if (!
|
|
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(
|
|
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 =
|
|
1158
|
-
if (!
|
|
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 =
|
|
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 (!
|
|
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([
|
|
1776
|
-
|
|
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
|
|
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
|
|
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 (
|
|
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 (
|
|
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
|
-
|
|
2677
|
-
|
|
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) =>
|
|
2764
|
-
const readStdin = deps.readStdin ?? (() =>
|
|
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"] ?
|
|
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
|
-
|
|
2904
|
-
|
|
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) =>
|
|
3046
|
-
const readStdin = deps.readStdin ?? (() =>
|
|
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"] ?
|
|
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
|
{
|