UNPKG

181 kBJavaScriptView Raw
1'use strict';
2
3function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
4
5var commander = _interopDefault(require('commander'));
6var chalk = _interopDefault(require('chalk'));
7var React = require('react');
8var React__default = _interopDefault(React);
9var ink = require('ink');
10var semver = require('semver');
11var semver__default = _interopDefault(semver);
12var execa = _interopDefault(require('execa'));
13var axios = _interopDefault(require('axios'));
14var path$1 = require('path');
15var path$1__default = _interopDefault(path$1);
16var lodash = require('lodash');
17var codeFrame = require('@babel/code-frame');
18var resolve = _interopDefault(require('resolve-from'));
19var Worker = _interopDefault(require('jest-worker'));
20var PQueue = _interopDefault(require('p-queue'));
21var fs = require('fs');
22var fs__default = _interopDefault(fs);
23require('core-js/modules/es.array.iterator');
24var jsYaml = require('js-yaml');
25var ora = _interopDefault(require('ora'));
26var slugify = _interopDefault(require('slugify'));
27var inquirer = require('inquirer');
28var util = require('util');
29var prettierConfig$1 = _interopDefault(require('@burst/prettier-config'));
30var stylelint = _interopDefault(require('stylelint'));
31var client = require('@slack/client');
32var xml2js = _interopDefault(require('xml2js'));
33var rimrafWithCallback = _interopDefault(require('rimraf'));
34var stagedFilesWithCallback = _interopDefault(require('staged-git-files'));
35
36var fails = function (exec) {
37 try {
38 return !!exec();
39 } catch (error) {
40 return true;
41 }
42};
43
44// Thank's IE8 for his funny defineProperty
45var descriptors = !fails(function () {
46 return Object.defineProperty({}, 'a', { get: function () { return 7; } }).a != 7;
47});
48
49var hasOwnProperty = {}.hasOwnProperty;
50
51var has = function (it, key) {
52 return hasOwnProperty.call(it, key);
53};
54
55var isObject = function (it) {
56 return typeof it === 'object' ? it !== null : typeof it === 'function';
57};
58
59// https://github.com/zloirock/core-js/issues/86#issuecomment-115759028
60var global = typeof window == 'object' && window && window.Math == Math ? window
61 : typeof self == 'object' && self && self.Math == Math ? self
62 // eslint-disable-next-line no-new-func
63 : Function('return this')();
64
65var document$1 = global.document;
66// typeof document.createElement is 'object' in old IE
67var exist = isObject(document$1) && isObject(document$1.createElement);
68
69var documentCreateElement = function (it) {
70 return exist ? document$1.createElement(it) : {};
71};
72
73// Thank's IE8 for his funny defineProperty
74var ie8DomDefine = !descriptors && !fails(function () {
75 return Object.defineProperty(documentCreateElement('div'), 'a', {
76 get: function () { return 7; }
77 }).a != 7;
78});
79
80var anObject = function (it) {
81 if (!isObject(it)) {
82 throw TypeError(String(it) + ' is not an object');
83 } return it;
84};
85
86// 7.1.1 ToPrimitive(input [, PreferredType])
87
88// instead of the ES6 spec version, we didn't implement @@toPrimitive case
89// and the second argument - flag - preferred type is a string
90var toPrimitive = function (it, S) {
91 if (!isObject(it)) return it;
92 var fn, val;
93 if (S && typeof (fn = it.toString) == 'function' && !isObject(val = fn.call(it))) return val;
94 if (typeof (fn = it.valueOf) == 'function' && !isObject(val = fn.call(it))) return val;
95 if (!S && typeof (fn = it.toString) == 'function' && !isObject(val = fn.call(it))) return val;
96 throw TypeError("Can't convert object to primitive value");
97};
98
99var nativeDefineProperty = Object.defineProperty;
100
101var f = descriptors ? nativeDefineProperty : function defineProperty(O, P, Attributes) {
102 anObject(O);
103 P = toPrimitive(P, true);
104 anObject(Attributes);
105 if (ie8DomDefine) try {
106 return nativeDefineProperty(O, P, Attributes);
107 } catch (error) { /* empty */ }
108 if ('get' in Attributes || 'set' in Attributes) throw TypeError('Accessors not supported');
109 if ('value' in Attributes) O[P] = Attributes.value;
110 return O;
111};
112
113var objectDefineProperty = {
114 f: f
115};
116
117var toString = {}.toString;
118
119var classofRaw = function (it) {
120 return toString.call(it).slice(8, -1);
121};
122
123// fallback for non-array-like ES3 and non-enumerable old V8 strings
124
125
126var split = ''.split;
127
128var indexedObject = fails(function () {
129 // throws an error in rhino, see https://github.com/mozilla/rhino/issues/346
130 // eslint-disable-next-line no-prototype-builtins
131 return !Object('z').propertyIsEnumerable(0);
132}) ? function (it) {
133 return classofRaw(it) == 'String' ? split.call(it, '') : Object(it);
134} : Object;
135
136// `RequireObjectCoercible` abstract operation
137// https://tc39.github.io/ecma262/#sec-requireobjectcoercible
138var requireObjectCoercible = function (it) {
139 if (it == undefined) throw TypeError("Can't call method on " + it);
140 return it;
141};
142
143// toObject with fallback for non-array-like ES3 strings
144
145
146
147var toIndexedObject = function (it) {
148 return indexedObject(requireObjectCoercible(it));
149};
150
151var ceil = Math.ceil;
152var floor = Math.floor;
153
154// `ToInteger` abstract operation
155// https://tc39.github.io/ecma262/#sec-tointeger
156var toInteger = function (argument) {
157 return isNaN(argument = +argument) ? 0 : (argument > 0 ? floor : ceil)(argument);
158};
159
160var min = Math.min;
161
162// `ToLength` abstract operation
163// https://tc39.github.io/ecma262/#sec-tolength
164var toLength = function (argument) {
165 return argument > 0 ? min(toInteger(argument), 0x1FFFFFFFFFFFFF) : 0; // 2 ** 53 - 1 == 9007199254740991
166};
167
168var max = Math.max;
169var min$1 = Math.min;
170
171// Helper for a popular repeating case of the spec:
172// Let integer be ? ToInteger(index).
173// If integer < 0, let result be max((length + integer), 0); else let result be min(length, length).
174var toAbsoluteIndex = function (index, length) {
175 var integer = toInteger(index);
176 return integer < 0 ? max(integer + length, 0) : min$1(integer, length);
177};
178
179// `Array.prototype.{ indexOf, includes }` methods implementation
180// false -> Array#indexOf
181// https://tc39.github.io/ecma262/#sec-array.prototype.indexof
182// true -> Array#includes
183// https://tc39.github.io/ecma262/#sec-array.prototype.includes
184var arrayIncludes = function (IS_INCLUDES) {
185 return function ($this, el, fromIndex) {
186 var O = toIndexedObject($this);
187 var length = toLength(O.length);
188 var index = toAbsoluteIndex(fromIndex, length);
189 var value;
190 // Array#includes uses SameValueZero equality algorithm
191 // eslint-disable-next-line no-self-compare
192 if (IS_INCLUDES && el != el) while (length > index) {
193 value = O[index++];
194 // eslint-disable-next-line no-self-compare
195 if (value != value) return true;
196 // Array#indexOf ignores holes, Array#includes - not
197 } else for (;length > index; index++) if (IS_INCLUDES || index in O) {
198 if (O[index] === el) return IS_INCLUDES || index || 0;
199 } return !IS_INCLUDES && -1;
200 };
201};
202
203var hiddenKeys = {};
204
205var arrayIndexOf = arrayIncludes(false);
206
207
208var objectKeysInternal = function (object, names) {
209 var O = toIndexedObject(object);
210 var i = 0;
211 var result = [];
212 var key;
213 for (key in O) !has(hiddenKeys, key) && has(O, key) && result.push(key);
214 // Don't enum bug & hidden keys
215 while (names.length > i) if (has(O, key = names[i++])) {
216 ~arrayIndexOf(result, key) || result.push(key);
217 }
218 return result;
219};
220
221// IE8- don't enum bug keys
222var enumBugKeys = [
223 'constructor',
224 'hasOwnProperty',
225 'isPrototypeOf',
226 'propertyIsEnumerable',
227 'toLocaleString',
228 'toString',
229 'valueOf'
230];
231
232// 19.1.2.7 / 15.2.3.4 Object.getOwnPropertyNames(O)
233
234var hiddenKeys$1 = enumBugKeys.concat('length', 'prototype');
235
236var f$1 = Object.getOwnPropertyNames || function getOwnPropertyNames(O) {
237 return objectKeysInternal(O, hiddenKeys$1);
238};
239
240var objectGetOwnPropertyNames = {
241 f: f$1
242};
243
244var f$2 = Object.getOwnPropertySymbols;
245
246var objectGetOwnPropertySymbols = {
247 f: f$2
248};
249
250var Reflect = global.Reflect;
251
252// all object keys, includes non-enumerable and symbols
253var ownKeys = Reflect && Reflect.ownKeys || function ownKeys(it) {
254 var keys = objectGetOwnPropertyNames.f(anObject(it));
255 var getOwnPropertySymbols = objectGetOwnPropertySymbols.f;
256 return getOwnPropertySymbols ? keys.concat(getOwnPropertySymbols(it)) : keys;
257};
258
259var nativePropertyIsEnumerable = {}.propertyIsEnumerable;
260var nativeGetOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
261
262// Nashorn ~ JDK8 bug
263var NASHORN_BUG = nativeGetOwnPropertyDescriptor && !nativePropertyIsEnumerable.call({ 1: 2 }, 1);
264
265var f$3 = NASHORN_BUG ? function propertyIsEnumerable(V) {
266 var descriptor = nativeGetOwnPropertyDescriptor(this, V);
267 return !!descriptor && descriptor.enumerable;
268} : nativePropertyIsEnumerable;
269
270var objectPropertyIsEnumerable = {
271 f: f$3
272};
273
274var createPropertyDescriptor = function (bitmap, value) {
275 return {
276 enumerable: !(bitmap & 1),
277 configurable: !(bitmap & 2),
278 writable: !(bitmap & 4),
279 value: value
280 };
281};
282
283var nativeGetOwnPropertyDescriptor$1 = Object.getOwnPropertyDescriptor;
284
285var f$4 = descriptors ? nativeGetOwnPropertyDescriptor$1 : function getOwnPropertyDescriptor(O, P) {
286 O = toIndexedObject(O);
287 P = toPrimitive(P, true);
288 if (ie8DomDefine) try {
289 return nativeGetOwnPropertyDescriptor$1(O, P);
290 } catch (error) { /* empty */ }
291 if (has(O, P)) return createPropertyDescriptor(!objectPropertyIsEnumerable.f.call(O, P), O[P]);
292};
293
294var objectGetOwnPropertyDescriptor = {
295 f: f$4
296};
297
298var copyConstructorProperties = function (target, source) {
299 var keys = ownKeys(source);
300 var defineProperty = objectDefineProperty.f;
301 var getOwnPropertyDescriptor = objectGetOwnPropertyDescriptor.f;
302 for (var i = 0; i < keys.length; i++) {
303 var key = keys[i];
304 if (!has(target, key)) defineProperty(target, key, getOwnPropertyDescriptor(source, key));
305 }
306};
307
308var hide = descriptors ? function (object, key, value) {
309 return objectDefineProperty.f(object, key, createPropertyDescriptor(1, value));
310} : function (object, key, value) {
311 object[key] = value;
312 return object;
313};
314
315function createCommonjsModule(fn, module) {
316 return module = { exports: {} }, fn(module, module.exports), module.exports;
317}
318
319var setGlobal = function (key, value) {
320 try {
321 hide(global, key, value);
322 } catch (error) {
323 global[key] = value;
324 } return value;
325};
326
327var isPure = false;
328
329var shared = createCommonjsModule(function (module) {
330var SHARED = '__core-js_shared__';
331var store = global[SHARED] || setGlobal(SHARED, {});
332
333(module.exports = function (key, value) {
334 return store[key] || (store[key] = value !== undefined ? value : {});
335})('versions', []).push({
336 version: '3.0.1',
337 mode: 'global',
338 copyright: '© 2019 Denis Pushkarev (zloirock.ru)'
339});
340});
341
342var functionToString = shared('native-function-to-string', Function.toString);
343
344var WeakMap = global.WeakMap;
345
346var nativeWeakMap = typeof WeakMap === 'function' && /native code/.test(functionToString.call(WeakMap));
347
348var id = 0;
349var postfix = Math.random();
350
351var uid = function (key) {
352 return 'Symbol('.concat(key === undefined ? '' : key, ')_', (++id + postfix).toString(36));
353};
354
355var shared$1 = shared('keys');
356
357
358var sharedKey = function (key) {
359 return shared$1[key] || (shared$1[key] = uid(key));
360};
361
362var WeakMap$1 = global.WeakMap;
363var set, get, has$1;
364
365var enforce = function (it) {
366 return has$1(it) ? get(it) : set(it, {});
367};
368
369var getterFor = function (TYPE) {
370 return function (it) {
371 var state;
372 if (!isObject(it) || (state = get(it)).type !== TYPE) {
373 throw TypeError('Incompatible receiver, ' + TYPE + ' required');
374 } return state;
375 };
376};
377
378if (nativeWeakMap) {
379 var store = new WeakMap$1();
380 var wmget = store.get;
381 var wmhas = store.has;
382 var wmset = store.set;
383 set = function (it, metadata) {
384 wmset.call(store, it, metadata);
385 return metadata;
386 };
387 get = function (it) {
388 return wmget.call(store, it) || {};
389 };
390 has$1 = function (it) {
391 return wmhas.call(store, it);
392 };
393} else {
394 var STATE = sharedKey('state');
395 hiddenKeys[STATE] = true;
396 set = function (it, metadata) {
397 hide(it, STATE, metadata);
398 return metadata;
399 };
400 get = function (it) {
401 return has(it, STATE) ? it[STATE] : {};
402 };
403 has$1 = function (it) {
404 return has(it, STATE);
405 };
406}
407
408var internalState = {
409 set: set,
410 get: get,
411 has: has$1,
412 enforce: enforce,
413 getterFor: getterFor
414};
415
416var redefine = createCommonjsModule(function (module) {
417var getInternalState = internalState.get;
418var enforceInternalState = internalState.enforce;
419var TEMPLATE = String(functionToString).split('toString');
420
421shared('inspectSource', function (it) {
422 return functionToString.call(it);
423});
424
425(module.exports = function (O, key, value, options) {
426 var unsafe = options ? !!options.unsafe : false;
427 var simple = options ? !!options.enumerable : false;
428 var noTargetGet = options ? !!options.noTargetGet : false;
429 if (typeof value == 'function') {
430 if (typeof key == 'string' && !has(value, 'name')) hide(value, 'name', key);
431 enforceInternalState(value).source = TEMPLATE.join(typeof key == 'string' ? key : '');
432 }
433 if (O === global) {
434 if (simple) O[key] = value;
435 else setGlobal(key, value);
436 return;
437 } else if (!unsafe) {
438 delete O[key];
439 } else if (!noTargetGet && O[key]) {
440 simple = true;
441 }
442 if (simple) O[key] = value;
443 else hide(O, key, value);
444// add fake Function#toString for correct work wrapped methods / constructors with methods like LoDash isNative
445})(Function.prototype, 'toString', function toString() {
446 return typeof this == 'function' && getInternalState(this).source || functionToString.call(this);
447});
448});
449
450var replacement = /#|\.prototype\./;
451
452var isForced = function (feature, detection) {
453 var value = data[normalize(feature)];
454 return value == POLYFILL ? true
455 : value == NATIVE ? false
456 : typeof detection == 'function' ? fails(detection)
457 : !!detection;
458};
459
460var normalize = isForced.normalize = function (string) {
461 return String(string).replace(replacement, '.').toLowerCase();
462};
463
464var data = isForced.data = {};
465var NATIVE = isForced.NATIVE = 'N';
466var POLYFILL = isForced.POLYFILL = 'P';
467
468var isForced_1 = isForced;
469
470var getOwnPropertyDescriptor = objectGetOwnPropertyDescriptor.f;
471
472
473
474
475
476
477/*
478 options.target - name of the target object
479 options.global - target is the global object
480 options.stat - export as static methods of target
481 options.proto - export as prototype methods of target
482 options.real - real prototype method for the `pure` version
483 options.forced - export even if the native feature is available
484 options.bind - bind methods to the target, required for the `pure` version
485 options.wrap - wrap constructors to preventing global pollution, required for the `pure` version
486 options.unsafe - use the simple assignment of property instead of delete + defineProperty
487 options.sham - add a flag to not completely full polyfills
488 options.enumerable - export as enumerable property
489 options.noTargetGet - prevent calling a getter on target
490*/
491var _export = function (options, source) {
492 var TARGET = options.target;
493 var GLOBAL = options.global;
494 var STATIC = options.stat;
495 var FORCED, target, key, targetProperty, sourceProperty, descriptor;
496 if (GLOBAL) {
497 target = global;
498 } else if (STATIC) {
499 target = global[TARGET] || setGlobal(TARGET, {});
500 } else {
501 target = (global[TARGET] || {}).prototype;
502 }
503 if (target) for (key in source) {
504 sourceProperty = source[key];
505 if (options.noTargetGet) {
506 descriptor = getOwnPropertyDescriptor(target, key);
507 targetProperty = descriptor && descriptor.value;
508 } else targetProperty = target[key];
509 FORCED = isForced_1(GLOBAL ? key : TARGET + (STATIC ? '.' : '#') + key, options.forced);
510 // contained in target
511 if (!FORCED && targetProperty !== undefined) {
512 if (typeof sourceProperty === typeof targetProperty) continue;
513 copyConstructorProperties(sourceProperty, targetProperty);
514 }
515 // add a flag to not completely full polyfills
516 if (options.sham || (targetProperty && targetProperty.sham)) {
517 hide(sourceProperty, 'sham', true);
518 }
519 // extend global
520 redefine(target, key, sourceProperty, options);
521 }
522};
523
524var defineProperty = objectDefineProperty.f;
525
526var NativeSymbol = global.Symbol;
527
528if (descriptors && typeof NativeSymbol == 'function' && (!('description' in NativeSymbol.prototype) ||
529 // Safari 12 bug
530 NativeSymbol().description !== undefined
531)) {
532 var EmptyStringDescriptionStore = {};
533 // wrap Symbol constructor for correct work with undefined description
534 var SymbolWrapper = function Symbol() {
535 var description = arguments.length < 1 || arguments[0] === undefined ? undefined : String(arguments[0]);
536 var result = this instanceof SymbolWrapper
537 ? new NativeSymbol(description)
538 // in Edge 13, String(Symbol(undefined)) === 'Symbol(undefined)'
539 : description === undefined ? NativeSymbol() : NativeSymbol(description);
540 if (description === '') EmptyStringDescriptionStore[result] = true;
541 return result;
542 };
543 copyConstructorProperties(SymbolWrapper, NativeSymbol);
544 var symbolPrototype = SymbolWrapper.prototype = NativeSymbol.prototype;
545 symbolPrototype.constructor = SymbolWrapper;
546
547 var symbolToString = symbolPrototype.toString;
548 var native = String(NativeSymbol('test')) == 'Symbol(test)';
549 var regexp = /^Symbol\((.*)\)[^)]+$/;
550 defineProperty(symbolPrototype, 'description', {
551 configurable: true,
552 get: function description() {
553 var symbol = isObject(this) ? this.valueOf() : this;
554 var string = symbolToString.call(symbol);
555 if (has(EmptyStringDescriptionStore, symbol)) return '';
556 var desc = native ? string.slice(7, -1) : string.replace(regexp, '$1');
557 return desc === '' ? undefined : desc;
558 }
559 });
560
561 _export({ global: true, forced: true }, { Symbol: SymbolWrapper });
562}
563
564// Chrome 38 Symbol has incorrect toString conversion
565var nativeSymbol = !fails(function () {
566 // eslint-disable-next-line no-undef
567 return !String(Symbol());
568});
569
570var store$1 = shared('wks');
571
572var Symbol$1 = global.Symbol;
573
574
575var wellKnownSymbol = function (name) {
576 return store$1[name] || (store$1[name] = nativeSymbol && Symbol$1[name]
577 || (nativeSymbol ? Symbol$1 : uid)('Symbol.' + name));
578};
579
580// 19.1.2.14 / 15.2.3.14 Object.keys(O)
581
582
583
584var objectKeys = Object.keys || function keys(O) {
585 return objectKeysInternal(O, enumBugKeys);
586};
587
588var objectDefineProperties = descriptors ? Object.defineProperties : function defineProperties(O, Properties) {
589 anObject(O);
590 var keys = objectKeys(Properties);
591 var length = keys.length;
592 var i = 0;
593 var key;
594 while (length > i) objectDefineProperty.f(O, key = keys[i++], Properties[key]);
595 return O;
596};
597
598var document$2 = global.document;
599
600var html = document$2 && document$2.documentElement;
601
602// 19.1.2.2 / 15.2.3.5 Object.create(O [, Properties])
603
604
605
606
607
608var IE_PROTO = sharedKey('IE_PROTO');
609var PROTOTYPE = 'prototype';
610var Empty = function () { /* empty */ };
611
612// Create object with fake `null` prototype: use iframe Object with cleared prototype
613var createDict = function () {
614 // Thrash, waste and sodomy: IE GC bug
615 var iframe = documentCreateElement('iframe');
616 var length = enumBugKeys.length;
617 var lt = '<';
618 var script = 'script';
619 var gt = '>';
620 var js = 'java' + script + ':';
621 var iframeDocument;
622 iframe.style.display = 'none';
623 html.appendChild(iframe);
624 iframe.src = String(js);
625 iframeDocument = iframe.contentWindow.document;
626 iframeDocument.open();
627 iframeDocument.write(lt + script + gt + 'document.F=Object' + lt + '/' + script + gt);
628 iframeDocument.close();
629 createDict = iframeDocument.F;
630 while (length--) delete createDict[PROTOTYPE][enumBugKeys[length]];
631 return createDict();
632};
633
634var objectCreate = Object.create || function create(O, Properties) {
635 var result;
636 if (O !== null) {
637 Empty[PROTOTYPE] = anObject(O);
638 result = new Empty();
639 Empty[PROTOTYPE] = null;
640 // add "__proto__" for Object.getPrototypeOf polyfill
641 result[IE_PROTO] = O;
642 } else result = createDict();
643 return Properties === undefined ? result : objectDefineProperties(result, Properties);
644};
645
646hiddenKeys[IE_PROTO] = true;
647
648var UNSCOPABLES = wellKnownSymbol('unscopables');
649
650
651var ArrayPrototype = Array.prototype;
652
653// Array.prototype[@@unscopables]
654// https://tc39.github.io/ecma262/#sec-array.prototype-@@unscopables
655if (ArrayPrototype[UNSCOPABLES] == undefined) {
656 hide(ArrayPrototype, UNSCOPABLES, objectCreate(null));
657}
658
659// add a key to Array.prototype[@@unscopables]
660var addToUnscopables = function (key) {
661 ArrayPrototype[UNSCOPABLES][key] = true;
662};
663
664var iterators = {};
665
666// `ToObject` abstract operation
667// https://tc39.github.io/ecma262/#sec-toobject
668var toObject = function (argument) {
669 return Object(requireObjectCoercible(argument));
670};
671
672var correctPrototypeGetter = !fails(function () {
673 function F() { /* empty */ }
674 F.prototype.constructor = null;
675 return Object.getPrototypeOf(new F()) !== F.prototype;
676});
677
678// 19.1.2.9 / 15.2.3.2 Object.getPrototypeOf(O)
679
680
681var IE_PROTO$1 = sharedKey('IE_PROTO');
682
683var ObjectPrototype = Object.prototype;
684
685var objectGetPrototypeOf = correctPrototypeGetter ? Object.getPrototypeOf : function (O) {
686 O = toObject(O);
687 if (has(O, IE_PROTO$1)) return O[IE_PROTO$1];
688 if (typeof O.constructor == 'function' && O instanceof O.constructor) {
689 return O.constructor.prototype;
690 } return O instanceof Object ? ObjectPrototype : null;
691};
692
693var ITERATOR = wellKnownSymbol('iterator');
694var BUGGY_SAFARI_ITERATORS = false;
695
696var returnThis = function () { return this; };
697
698// `%IteratorPrototype%` object
699// https://tc39.github.io/ecma262/#sec-%iteratorprototype%-object
700var IteratorPrototype, PrototypeOfArrayIteratorPrototype, arrayIterator;
701
702if ([].keys) {
703 arrayIterator = [].keys();
704 // Safari 8 has buggy iterators w/o `next`
705 if (!('next' in arrayIterator)) BUGGY_SAFARI_ITERATORS = true;
706 else {
707 PrototypeOfArrayIteratorPrototype = objectGetPrototypeOf(objectGetPrototypeOf(arrayIterator));
708 if (PrototypeOfArrayIteratorPrototype !== Object.prototype) IteratorPrototype = PrototypeOfArrayIteratorPrototype;
709 }
710}
711
712if (IteratorPrototype == undefined) IteratorPrototype = {};
713
714// 25.1.2.1.1 %IteratorPrototype%[@@iterator]()
715if (!has(IteratorPrototype, ITERATOR)) hide(IteratorPrototype, ITERATOR, returnThis);
716
717var iteratorsCore = {
718 IteratorPrototype: IteratorPrototype,
719 BUGGY_SAFARI_ITERATORS: BUGGY_SAFARI_ITERATORS
720};
721
722var defineProperty$1 = objectDefineProperty.f;
723
724var TO_STRING_TAG = wellKnownSymbol('toStringTag');
725
726var setToStringTag = function (it, TAG, STATIC) {
727 if (it && !has(it = STATIC ? it : it.prototype, TO_STRING_TAG)) {
728 defineProperty$1(it, TO_STRING_TAG, { configurable: true, value: TAG });
729 }
730};
731
732var IteratorPrototype$1 = iteratorsCore.IteratorPrototype;
733
734
735
736
737
738var returnThis$1 = function () { return this; };
739
740var createIteratorConstructor = function (IteratorConstructor, NAME, next) {
741 var TO_STRING_TAG = NAME + ' Iterator';
742 IteratorConstructor.prototype = objectCreate(IteratorPrototype$1, { next: createPropertyDescriptor(1, next) });
743 setToStringTag(IteratorConstructor, TO_STRING_TAG, false, true);
744 iterators[TO_STRING_TAG] = returnThis$1;
745 return IteratorConstructor;
746};
747
748var validateSetPrototypeOfArguments = function (O, proto) {
749 anObject(O);
750 if (!isObject(proto) && proto !== null) {
751 throw TypeError("Can't set " + String(proto) + ' as a prototype');
752 }
753};
754
755// Works with __proto__ only. Old v8 can't work with null proto objects.
756/* eslint-disable no-proto */
757
758
759var objectSetPrototypeOf = Object.setPrototypeOf || ('__proto__' in {} ? function () {
760 var correctSetter = false;
761 var test = {};
762 var setter;
763 try {
764 setter = Object.getOwnPropertyDescriptor(Object.prototype, '__proto__').set;
765 setter.call(test, []);
766 correctSetter = test instanceof Array;
767 } catch (error) { /* empty */ }
768 return function setPrototypeOf(O, proto) {
769 validateSetPrototypeOfArguments(O, proto);
770 if (correctSetter) setter.call(O, proto);
771 else O.__proto__ = proto;
772 return O;
773 };
774}() : undefined);
775
776var ITERATOR$1 = wellKnownSymbol('iterator');
777
778
779var IteratorPrototype$2 = iteratorsCore.IteratorPrototype;
780var BUGGY_SAFARI_ITERATORS$1 = iteratorsCore.BUGGY_SAFARI_ITERATORS;
781var KEYS = 'keys';
782var VALUES = 'values';
783var ENTRIES = 'entries';
784
785var returnThis$2 = function () { return this; };
786
787var defineIterator = function (Iterable, NAME, IteratorConstructor, next, DEFAULT, IS_SET, FORCED) {
788 createIteratorConstructor(IteratorConstructor, NAME, next);
789
790 var getIterationMethod = function (KIND) {
791 if (KIND === DEFAULT && defaultIterator) return defaultIterator;
792 if (!BUGGY_SAFARI_ITERATORS$1 && KIND in IterablePrototype) return IterablePrototype[KIND];
793 switch (KIND) {
794 case KEYS: return function keys() { return new IteratorConstructor(this, KIND); };
795 case VALUES: return function values() { return new IteratorConstructor(this, KIND); };
796 case ENTRIES: return function entries() { return new IteratorConstructor(this, KIND); };
797 } return function () { return new IteratorConstructor(this); };
798 };
799
800 var TO_STRING_TAG = NAME + ' Iterator';
801 var INCORRECT_VALUES_NAME = false;
802 var IterablePrototype = Iterable.prototype;
803 var nativeIterator = IterablePrototype[ITERATOR$1]
804 || IterablePrototype['@@iterator']
805 || DEFAULT && IterablePrototype[DEFAULT];
806 var defaultIterator = !BUGGY_SAFARI_ITERATORS$1 && nativeIterator || getIterationMethod(DEFAULT);
807 var anyNativeIterator = NAME == 'Array' ? IterablePrototype.entries || nativeIterator : nativeIterator;
808 var CurrentIteratorPrototype, methods, KEY;
809
810 // fix native
811 if (anyNativeIterator) {
812 CurrentIteratorPrototype = objectGetPrototypeOf(anyNativeIterator.call(new Iterable()));
813 if (IteratorPrototype$2 !== Object.prototype && CurrentIteratorPrototype.next) {
814 if (objectGetPrototypeOf(CurrentIteratorPrototype) !== IteratorPrototype$2) {
815 if (objectSetPrototypeOf) {
816 objectSetPrototypeOf(CurrentIteratorPrototype, IteratorPrototype$2);
817 } else if (typeof CurrentIteratorPrototype[ITERATOR$1] != 'function') {
818 hide(CurrentIteratorPrototype, ITERATOR$1, returnThis$2);
819 }
820 }
821 // Set @@toStringTag to native iterators
822 setToStringTag(CurrentIteratorPrototype, TO_STRING_TAG, true, true);
823 }
824 }
825
826 // fix Array#{values, @@iterator}.name in V8 / FF
827 if (DEFAULT == VALUES && nativeIterator && nativeIterator.name !== VALUES) {
828 INCORRECT_VALUES_NAME = true;
829 defaultIterator = function values() { return nativeIterator.call(this); };
830 }
831
832 // define iterator
833 if (IterablePrototype[ITERATOR$1] !== defaultIterator) {
834 hide(IterablePrototype, ITERATOR$1, defaultIterator);
835 }
836 iterators[NAME] = defaultIterator;
837
838 // export additional methods
839 if (DEFAULT) {
840 methods = {
841 values: getIterationMethod(VALUES),
842 keys: IS_SET ? defaultIterator : getIterationMethod(KEYS),
843 entries: getIterationMethod(ENTRIES)
844 };
845 if (FORCED) for (KEY in methods) {
846 if (BUGGY_SAFARI_ITERATORS$1 || INCORRECT_VALUES_NAME || !(KEY in IterablePrototype)) {
847 redefine(IterablePrototype, KEY, methods[KEY]);
848 }
849 } else _export({ target: NAME, proto: true, forced: BUGGY_SAFARI_ITERATORS$1 || INCORRECT_VALUES_NAME }, methods);
850 }
851
852 return methods;
853};
854
855var ARRAY_ITERATOR = 'Array Iterator';
856var setInternalState = internalState.set;
857var getInternalState = internalState.getterFor(ARRAY_ITERATOR);
858
859// `Array.prototype.entries` method
860// https://tc39.github.io/ecma262/#sec-array.prototype.entries
861// `Array.prototype.keys` method
862// https://tc39.github.io/ecma262/#sec-array.prototype.keys
863// `Array.prototype.values` method
864// https://tc39.github.io/ecma262/#sec-array.prototype.values
865// `Array.prototype[@@iterator]` method
866// https://tc39.github.io/ecma262/#sec-array.prototype-@@iterator
867// `CreateArrayIterator` internal method
868// https://tc39.github.io/ecma262/#sec-createarrayiterator
869var es_array_iterator = defineIterator(Array, 'Array', function (iterated, kind) {
870 setInternalState(this, {
871 type: ARRAY_ITERATOR,
872 target: toIndexedObject(iterated), // target
873 index: 0, // next index
874 kind: kind // kind
875 });
876// `%ArrayIteratorPrototype%.next` method
877// https://tc39.github.io/ecma262/#sec-%arrayiteratorprototype%.next
878}, function () {
879 var state = getInternalState(this);
880 var target = state.target;
881 var kind = state.kind;
882 var index = state.index++;
883 if (!target || index >= target.length) {
884 state.target = undefined;
885 return { value: undefined, done: true };
886 }
887 if (kind == 'keys') return { value: index, done: false };
888 if (kind == 'values') return { value: target[index], done: false };
889 return { value: [index, target[index]], done: false };
890}, 'values');
891
892// argumentsList[@@iterator] is %ArrayProto_values%
893// https://tc39.github.io/ecma262/#sec-createunmappedargumentsobject
894// https://tc39.github.io/ecma262/#sec-createmappedargumentsobject
895iterators.Arguments = iterators.Array;
896
897// https://tc39.github.io/ecma262/#sec-array.prototype-@@unscopables
898addToUnscopables('keys');
899addToUnscopables('values');
900addToUnscopables('entries');
901
902var aFunction = function (it) {
903 if (typeof it != 'function') {
904 throw TypeError(String(it) + ' is not a function');
905 } return it;
906};
907
908var anInstance = function (it, Constructor, name) {
909 if (!(it instanceof Constructor)) {
910 throw TypeError('Incorrect ' + (name ? name + ' ' : '') + 'invocation');
911 } return it;
912};
913
914// check on default Array iterator
915
916var ITERATOR$2 = wellKnownSymbol('iterator');
917var ArrayPrototype$1 = Array.prototype;
918
919var isArrayIteratorMethod = function (it) {
920 return it !== undefined && (iterators.Array === it || ArrayPrototype$1[ITERATOR$2] === it);
921};
922
923// optional / simple context binding
924var bindContext = function (fn, that, length) {
925 aFunction(fn);
926 if (that === undefined) return fn;
927 switch (length) {
928 case 0: return function () {
929 return fn.call(that);
930 };
931 case 1: return function (a) {
932 return fn.call(that, a);
933 };
934 case 2: return function (a, b) {
935 return fn.call(that, a, b);
936 };
937 case 3: return function (a, b, c) {
938 return fn.call(that, a, b, c);
939 };
940 }
941 return function (/* ...args */) {
942 return fn.apply(that, arguments);
943 };
944};
945
946var TO_STRING_TAG$1 = wellKnownSymbol('toStringTag');
947// ES3 wrong here
948var CORRECT_ARGUMENTS = classofRaw(function () { return arguments; }()) == 'Arguments';
949
950// fallback for IE11 Script Access Denied error
951var tryGet = function (it, key) {
952 try {
953 return it[key];
954 } catch (error) { /* empty */ }
955};
956
957// getting tag from ES6+ `Object.prototype.toString`
958var classof = function (it) {
959 var O, tag, result;
960 return it === undefined ? 'Undefined' : it === null ? 'Null'
961 // @@toStringTag case
962 : typeof (tag = tryGet(O = Object(it), TO_STRING_TAG$1)) == 'string' ? tag
963 // builtinTag case
964 : CORRECT_ARGUMENTS ? classofRaw(O)
965 // ES3 arguments fallback
966 : (result = classofRaw(O)) == 'Object' && typeof O.callee == 'function' ? 'Arguments' : result;
967};
968
969var ITERATOR$3 = wellKnownSymbol('iterator');
970
971
972var getIteratorMethod = function (it) {
973 if (it != undefined) return it[ITERATOR$3]
974 || it['@@iterator']
975 || iterators[classof(it)];
976};
977
978// call something on iterator step with safe closing on error
979var callWithSafeIterationClosing = function (iterator, fn, value, ENTRIES) {
980 try {
981 return ENTRIES ? fn(anObject(value)[0], value[1]) : fn(value);
982 // 7.4.6 IteratorClose(iterator, completion)
983 } catch (error) {
984 var returnMethod = iterator['return'];
985 if (returnMethod !== undefined) anObject(returnMethod.call(iterator));
986 throw error;
987 }
988};
989
990var iterate = createCommonjsModule(function (module) {
991var BREAK = {};
992
993var exports = module.exports = function (iterable, fn, that, ENTRIES, ITERATOR) {
994 var boundFunction = bindContext(fn, that, ENTRIES ? 2 : 1);
995 var iterator, iterFn, index, length, result, step;
996
997 if (ITERATOR) {
998 iterator = iterable;
999 } else {
1000 iterFn = getIteratorMethod(iterable);
1001 if (typeof iterFn != 'function') throw TypeError('Target is not iterable');
1002 // optimisation for array iterators
1003 if (isArrayIteratorMethod(iterFn)) {
1004 for (index = 0, length = toLength(iterable.length); length > index; index++) {
1005 result = ENTRIES ? boundFunction(anObject(step = iterable[index])[0], step[1]) : boundFunction(iterable[index]);
1006 if (result === BREAK) return BREAK;
1007 } return;
1008 }
1009 iterator = iterFn.call(iterable);
1010 }
1011
1012 while (!(step = iterator.next()).done) {
1013 if (callWithSafeIterationClosing(iterator, boundFunction, step.value, ENTRIES) === BREAK) return BREAK;
1014 }
1015};
1016
1017exports.BREAK = BREAK;
1018});
1019
1020var ITERATOR$4 = wellKnownSymbol('iterator');
1021var SAFE_CLOSING = false;
1022
1023try {
1024 var called = 0;
1025 var iteratorWithReturn = {
1026 next: function () {
1027 return { done: !!called++ };
1028 },
1029 'return': function () {
1030 SAFE_CLOSING = true;
1031 }
1032 };
1033 iteratorWithReturn[ITERATOR$4] = function () {
1034 return this;
1035 };
1036} catch (error) { /* empty */ }
1037
1038var checkCorrectnessOfIteration = function (exec, SKIP_CLOSING) {
1039 if (!SKIP_CLOSING && !SAFE_CLOSING) return false;
1040 var ITERATION_SUPPORT = false;
1041 try {
1042 var object = {};
1043 object[ITERATOR$4] = function () {
1044 return {
1045 next: function () {
1046 return { done: ITERATION_SUPPORT = true };
1047 }
1048 };
1049 };
1050 exec(object);
1051 } catch (error) { /* empty */ }
1052 return ITERATION_SUPPORT;
1053};
1054
1055var SPECIES = wellKnownSymbol('species');
1056
1057// `SpeciesConstructor` abstract operation
1058// https://tc39.github.io/ecma262/#sec-speciesconstructor
1059var speciesConstructor = function (O, defaultConstructor) {
1060 var C = anObject(O).constructor;
1061 var S;
1062 return C === undefined || (S = anObject(C)[SPECIES]) == undefined ? defaultConstructor : aFunction(S);
1063};
1064
1065var set$1 = global.setImmediate;
1066var clear = global.clearImmediate;
1067var process$1 = global.process;
1068var MessageChannel = global.MessageChannel;
1069var Dispatch = global.Dispatch;
1070var counter = 0;
1071var queue = {};
1072var ONREADYSTATECHANGE = 'onreadystatechange';
1073var defer, channel, port;
1074
1075var run = function () {
1076 var id = +this;
1077 // eslint-disable-next-line no-prototype-builtins
1078 if (queue.hasOwnProperty(id)) {
1079 var fn = queue[id];
1080 delete queue[id];
1081 fn();
1082 }
1083};
1084
1085var listener = function (event) {
1086 run.call(event.data);
1087};
1088
1089// Node.js 0.9+ & IE10+ has setImmediate, otherwise:
1090if (!set$1 || !clear) {
1091 set$1 = function setImmediate(fn) {
1092 var args = [];
1093 var i = 1;
1094 while (arguments.length > i) args.push(arguments[i++]);
1095 queue[++counter] = function () {
1096 // eslint-disable-next-line no-new-func
1097 (typeof fn == 'function' ? fn : Function(fn)).apply(undefined, args);
1098 };
1099 defer(counter);
1100 return counter;
1101 };
1102 clear = function clearImmediate(id) {
1103 delete queue[id];
1104 };
1105 // Node.js 0.8-
1106 if (classofRaw(process$1) == 'process') {
1107 defer = function (id) {
1108 process$1.nextTick(bindContext(run, id, 1));
1109 };
1110 // Sphere (JS game engine) Dispatch API
1111 } else if (Dispatch && Dispatch.now) {
1112 defer = function (id) {
1113 Dispatch.now(bindContext(run, id, 1));
1114 };
1115 // Browsers with MessageChannel, includes WebWorkers
1116 } else if (MessageChannel) {
1117 channel = new MessageChannel();
1118 port = channel.port2;
1119 channel.port1.onmessage = listener;
1120 defer = bindContext(port.postMessage, port, 1);
1121 // Browsers with postMessage, skip WebWorkers
1122 // IE8 has postMessage, but it's sync & typeof its postMessage is 'object'
1123 } else if (global.addEventListener && typeof postMessage == 'function' && !global.importScripts) {
1124 defer = function (id) {
1125 global.postMessage(id + '', '*');
1126 };
1127 global.addEventListener('message', listener, false);
1128 // IE8-
1129 } else if (ONREADYSTATECHANGE in documentCreateElement('script')) {
1130 defer = function (id) {
1131 html.appendChild(documentCreateElement('script'))[ONREADYSTATECHANGE] = function () {
1132 html.removeChild(this);
1133 run.call(id);
1134 };
1135 };
1136 // Rest old browsers
1137 } else {
1138 defer = function (id) {
1139 setTimeout(bindContext(run, id, 1), 0);
1140 };
1141 }
1142}
1143
1144var task = {
1145 set: set$1,
1146 clear: clear
1147};
1148
1149var navigator = global.navigator;
1150
1151var userAgent = navigator && navigator.userAgent || '';
1152
1153var getOwnPropertyDescriptor$1 = objectGetOwnPropertyDescriptor.f;
1154
1155var macrotask = task.set;
1156
1157var MutationObserver = global.MutationObserver || global.WebKitMutationObserver;
1158var process$2 = global.process;
1159var Promise$1 = global.Promise;
1160var IS_NODE = classofRaw(process$2) == 'process';
1161// Node.js 11 shows ExperimentalWarning on getting `queueMicrotask`
1162var queueMicrotaskDescriptor = getOwnPropertyDescriptor$1(global, 'queueMicrotask');
1163var queueMicrotask = queueMicrotaskDescriptor && queueMicrotaskDescriptor.value;
1164
1165var flush, head, last, notify, toggle, node, promise;
1166
1167// modern engines have queueMicrotask method
1168if (!queueMicrotask) {
1169 flush = function () {
1170 var parent, fn;
1171 if (IS_NODE && (parent = process$2.domain)) parent.exit();
1172 while (head) {
1173 fn = head.fn;
1174 head = head.next;
1175 try {
1176 fn();
1177 } catch (error) {
1178 if (head) notify();
1179 else last = undefined;
1180 throw error;
1181 }
1182 } last = undefined;
1183 if (parent) parent.enter();
1184 };
1185
1186 // Node.js
1187 if (IS_NODE) {
1188 notify = function () {
1189 process$2.nextTick(flush);
1190 };
1191 // browsers with MutationObserver, except iOS - https://github.com/zloirock/core-js/issues/339
1192 } else if (MutationObserver && !/(iPhone|iPod|iPad).*AppleWebKit/i.test(userAgent)) {
1193 toggle = true;
1194 node = document.createTextNode('');
1195 new MutationObserver(flush).observe(node, { characterData: true }); // eslint-disable-line no-new
1196 notify = function () {
1197 node.data = toggle = !toggle;
1198 };
1199 // environments with maybe non-completely correct, but existent Promise
1200 } else if (Promise$1 && Promise$1.resolve) {
1201 // Promise.resolve without an argument throws an error in LG WebOS 2
1202 promise = Promise$1.resolve(undefined);
1203 notify = function () {
1204 promise.then(flush);
1205 };
1206 // for other environments - macrotask based on:
1207 // - setImmediate
1208 // - MessageChannel
1209 // - window.postMessag
1210 // - onreadystatechange
1211 // - setTimeout
1212 } else {
1213 notify = function () {
1214 // strange IE + webpack dev server bug - use .call(global)
1215 macrotask.call(global, flush);
1216 };
1217 }
1218}
1219
1220var microtask = queueMicrotask || function (fn) {
1221 var task = { fn: fn, next: undefined };
1222 if (last) last.next = task;
1223 if (!head) {
1224 head = task;
1225 notify();
1226 } last = task;
1227};
1228
1229// 25.4.1.5 NewPromiseCapability(C)
1230
1231
1232var PromiseCapability = function (C) {
1233 var resolve, reject;
1234 this.promise = new C(function ($$resolve, $$reject) {
1235 if (resolve !== undefined || reject !== undefined) throw TypeError('Bad Promise constructor');
1236 resolve = $$resolve;
1237 reject = $$reject;
1238 });
1239 this.resolve = aFunction(resolve);
1240 this.reject = aFunction(reject);
1241};
1242
1243var f$5 = function (C) {
1244 return new PromiseCapability(C);
1245};
1246
1247var newPromiseCapability = {
1248 f: f$5
1249};
1250
1251var promiseResolve = function (C, x) {
1252 anObject(C);
1253 if (isObject(x) && x.constructor === C) return x;
1254 var promiseCapability = newPromiseCapability.f(C);
1255 var resolve = promiseCapability.resolve;
1256 resolve(x);
1257 return promiseCapability.promise;
1258};
1259
1260var hostReportErrors = function (a, b) {
1261 var console = global.console;
1262 if (console && console.error) {
1263 arguments.length === 1 ? console.error(a) : console.error(a, b);
1264 }
1265};
1266
1267var perform = function (exec) {
1268 try {
1269 return { error: false, value: exec() };
1270 } catch (error) {
1271 return { error: true, value: error };
1272 }
1273};
1274
1275var redefineAll = function (target, src, options) {
1276 for (var key in src) redefine(target, key, src[key], options);
1277 return target;
1278};
1279
1280var path = global;
1281
1282var aFunction$1 = function (variable) {
1283 return typeof variable == 'function' ? variable : undefined;
1284};
1285
1286var getBuiltIn = function (namespace, method) {
1287 return arguments.length < 2 ? aFunction$1(path[namespace]) || aFunction$1(global[namespace])
1288 : path[namespace] && path[namespace][method] || global[namespace] && global[namespace][method];
1289};
1290
1291var SPECIES$1 = wellKnownSymbol('species');
1292
1293var setSpecies = function (CONSTRUCTOR_NAME) {
1294 var C = getBuiltIn(CONSTRUCTOR_NAME);
1295 var defineProperty = objectDefineProperty.f;
1296 if (descriptors && C && !C[SPECIES$1]) defineProperty(C, SPECIES$1, {
1297 configurable: true,
1298 get: function () { return this; }
1299 });
1300};
1301
1302var PROMISE = 'Promise';
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313var task$1 = task.set;
1314
1315
1316
1317
1318
1319
1320var SPECIES$2 = wellKnownSymbol('species');
1321
1322
1323var getInternalState$1 = internalState.get;
1324var setInternalState$1 = internalState.set;
1325var getInternalPromiseState = internalState.getterFor(PROMISE);
1326var PromiseConstructor = global[PROMISE];
1327var TypeError$1 = global.TypeError;
1328var document$3 = global.document;
1329var process$3 = global.process;
1330var $fetch = global.fetch;
1331var versions = process$3 && process$3.versions;
1332var v8 = versions && versions.v8 || '';
1333var newPromiseCapability$1 = newPromiseCapability.f;
1334var newGenericPromiseCapability = newPromiseCapability$1;
1335var IS_NODE$1 = classofRaw(process$3) == 'process';
1336var DISPATCH_EVENT = !!(document$3 && document$3.createEvent && global.dispatchEvent);
1337var UNHANDLED_REJECTION = 'unhandledrejection';
1338var REJECTION_HANDLED = 'rejectionhandled';
1339var PENDING = 0;
1340var FULFILLED = 1;
1341var REJECTED = 2;
1342var HANDLED = 1;
1343var UNHANDLED = 2;
1344var Internal, OwnPromiseCapability, PromiseWrapper;
1345
1346var FORCED = isForced_1(PROMISE, function () {
1347 // correct subclassing with @@species support
1348 var promise = PromiseConstructor.resolve(1);
1349 var empty = function () { /* empty */ };
1350 var FakePromise = (promise.constructor = {})[SPECIES$2] = function (exec) {
1351 exec(empty, empty);
1352 };
1353 // unhandled rejections tracking support, NodeJS Promise without it fails @@species test
1354 return !((IS_NODE$1 || typeof PromiseRejectionEvent == 'function')
1355 && (!isPure || promise['finally'])
1356 && promise.then(empty) instanceof FakePromise
1357 // v8 6.6 (Node 10 and Chrome 66) have a bug with resolving custom thenables
1358 // https://bugs.chromium.org/p/chromium/issues/detail?id=830565
1359 // we can't detect it synchronously, so just check versions
1360 && v8.indexOf('6.6') !== 0
1361 && userAgent.indexOf('Chrome/66') === -1);
1362});
1363
1364var INCORRECT_ITERATION = FORCED || !checkCorrectnessOfIteration(function (iterable) {
1365 PromiseConstructor.all(iterable)['catch'](function () { /* empty */ });
1366});
1367
1368// helpers
1369var isThenable = function (it) {
1370 var then;
1371 return isObject(it) && typeof (then = it.then) == 'function' ? then : false;
1372};
1373
1374var notify$1 = function (promise, state, isReject) {
1375 if (state.notified) return;
1376 state.notified = true;
1377 var chain = state.reactions;
1378 microtask(function () {
1379 var value = state.value;
1380 var ok = state.state == FULFILLED;
1381 var i = 0;
1382 var run = function (reaction) {
1383 var handler = ok ? reaction.ok : reaction.fail;
1384 var resolve = reaction.resolve;
1385 var reject = reaction.reject;
1386 var domain = reaction.domain;
1387 var result, then, exited;
1388 try {
1389 if (handler) {
1390 if (!ok) {
1391 if (state.rejection === UNHANDLED) onHandleUnhandled(promise, state);
1392 state.rejection = HANDLED;
1393 }
1394 if (handler === true) result = value;
1395 else {
1396 if (domain) domain.enter();
1397 result = handler(value); // may throw
1398 if (domain) {
1399 domain.exit();
1400 exited = true;
1401 }
1402 }
1403 if (result === reaction.promise) {
1404 reject(TypeError$1('Promise-chain cycle'));
1405 } else if (then = isThenable(result)) {
1406 then.call(result, resolve, reject);
1407 } else resolve(result);
1408 } else reject(value);
1409 } catch (error) {
1410 if (domain && !exited) domain.exit();
1411 reject(error);
1412 }
1413 };
1414 while (chain.length > i) run(chain[i++]); // variable length - can't use forEach
1415 state.reactions = [];
1416 state.notified = false;
1417 if (isReject && !state.rejection) onUnhandled(promise, state);
1418 });
1419};
1420
1421var dispatchEvent = function (name, promise, reason) {
1422 var event, handler;
1423 if (DISPATCH_EVENT) {
1424 event = document$3.createEvent('Event');
1425 event.promise = promise;
1426 event.reason = reason;
1427 event.initEvent(name, false, true);
1428 global.dispatchEvent(event);
1429 } else event = { promise: promise, reason: reason };
1430 if (handler = global['on' + name]) handler(event);
1431 else if (name === UNHANDLED_REJECTION) hostReportErrors('Unhandled promise rejection', reason);
1432};
1433
1434var onUnhandled = function (promise, state) {
1435 task$1.call(global, function () {
1436 var value = state.value;
1437 var IS_UNHANDLED = isUnhandled(state);
1438 var result;
1439 if (IS_UNHANDLED) {
1440 result = perform(function () {
1441 if (IS_NODE$1) {
1442 process$3.emit('unhandledRejection', value, promise);
1443 } else dispatchEvent(UNHANDLED_REJECTION, promise, value);
1444 });
1445 // Browsers should not trigger `rejectionHandled` event if it was handled here, NodeJS - should
1446 state.rejection = IS_NODE$1 || isUnhandled(state) ? UNHANDLED : HANDLED;
1447 if (result.error) throw result.value;
1448 }
1449 });
1450};
1451
1452var isUnhandled = function (state) {
1453 return state.rejection !== HANDLED && !state.parent;
1454};
1455
1456var onHandleUnhandled = function (promise, state) {
1457 task$1.call(global, function () {
1458 if (IS_NODE$1) {
1459 process$3.emit('rejectionHandled', promise);
1460 } else dispatchEvent(REJECTION_HANDLED, promise, state.value);
1461 });
1462};
1463
1464var bind = function (fn, promise, state, unwrap) {
1465 return function (value) {
1466 fn(promise, state, value, unwrap);
1467 };
1468};
1469
1470var internalReject = function (promise, state, value, unwrap) {
1471 if (state.done) return;
1472 state.done = true;
1473 if (unwrap) state = unwrap;
1474 state.value = value;
1475 state.state = REJECTED;
1476 notify$1(promise, state, true);
1477};
1478
1479var internalResolve = function (promise, state, value, unwrap) {
1480 if (state.done) return;
1481 state.done = true;
1482 if (unwrap) state = unwrap;
1483 try {
1484 if (promise === value) throw TypeError$1("Promise can't be resolved itself");
1485 var then = isThenable(value);
1486 if (then) {
1487 microtask(function () {
1488 var wrapper = { done: false };
1489 try {
1490 then.call(value,
1491 bind(internalResolve, promise, wrapper, state),
1492 bind(internalReject, promise, wrapper, state)
1493 );
1494 } catch (error) {
1495 internalReject(promise, wrapper, error, state);
1496 }
1497 });
1498 } else {
1499 state.value = value;
1500 state.state = FULFILLED;
1501 notify$1(promise, state, false);
1502 }
1503 } catch (error) {
1504 internalReject(promise, { done: false }, error, state);
1505 }
1506};
1507
1508// constructor polyfill
1509if (FORCED) {
1510 // 25.4.3.1 Promise(executor)
1511 PromiseConstructor = function Promise(executor) {
1512 anInstance(this, PromiseConstructor, PROMISE);
1513 aFunction(executor);
1514 Internal.call(this);
1515 var state = getInternalState$1(this);
1516 try {
1517 executor(bind(internalResolve, this, state), bind(internalReject, this, state));
1518 } catch (error) {
1519 internalReject(this, state, error);
1520 }
1521 };
1522 // eslint-disable-next-line no-unused-vars
1523 Internal = function Promise(executor) {
1524 setInternalState$1(this, {
1525 type: PROMISE,
1526 done: false,
1527 notified: false,
1528 parent: false,
1529 reactions: [],
1530 rejection: false,
1531 state: PENDING,
1532 value: undefined
1533 });
1534 };
1535 Internal.prototype = redefineAll(PromiseConstructor.prototype, {
1536 // `Promise.prototype.then` method
1537 // https://tc39.github.io/ecma262/#sec-promise.prototype.then
1538 then: function then(onFulfilled, onRejected) {
1539 var state = getInternalPromiseState(this);
1540 var reaction = newPromiseCapability$1(speciesConstructor(this, PromiseConstructor));
1541 reaction.ok = typeof onFulfilled == 'function' ? onFulfilled : true;
1542 reaction.fail = typeof onRejected == 'function' && onRejected;
1543 reaction.domain = IS_NODE$1 ? process$3.domain : undefined;
1544 state.parent = true;
1545 state.reactions.push(reaction);
1546 if (state.state != PENDING) notify$1(this, state, false);
1547 return reaction.promise;
1548 },
1549 // `Promise.prototype.catch` method
1550 // https://tc39.github.io/ecma262/#sec-promise.prototype.catch
1551 'catch': function (onRejected) {
1552 return this.then(undefined, onRejected);
1553 }
1554 });
1555 OwnPromiseCapability = function () {
1556 var promise = new Internal();
1557 var state = getInternalState$1(promise);
1558 this.promise = promise;
1559 this.resolve = bind(internalResolve, promise, state);
1560 this.reject = bind(internalReject, promise, state);
1561 };
1562 newPromiseCapability.f = newPromiseCapability$1 = function (C) {
1563 return C === PromiseConstructor || C === PromiseWrapper
1564 ? new OwnPromiseCapability(C)
1565 : newGenericPromiseCapability(C);
1566 };
1567
1568 // wrap fetch result
1569 if (typeof $fetch == 'function') _export({ global: true, enumerable: true, forced: true }, {
1570 // eslint-disable-next-line no-unused-vars
1571 fetch: function fetch(input) {
1572 return promiseResolve(PromiseConstructor, $fetch.apply(global, arguments));
1573 }
1574 });
1575}
1576
1577_export({ global: true, wrap: true, forced: FORCED }, { Promise: PromiseConstructor });
1578
1579setToStringTag(PromiseConstructor, PROMISE, false, true);
1580setSpecies(PROMISE);
1581
1582PromiseWrapper = path[PROMISE];
1583
1584// statics
1585_export({ target: PROMISE, stat: true, forced: FORCED }, {
1586 // `Promise.reject` method
1587 // https://tc39.github.io/ecma262/#sec-promise.reject
1588 reject: function reject(r) {
1589 var capability = newPromiseCapability$1(this);
1590 capability.reject.call(undefined, r);
1591 return capability.promise;
1592 }
1593});
1594
1595_export({ target: PROMISE, stat: true, forced: FORCED }, {
1596 // `Promise.resolve` method
1597 // https://tc39.github.io/ecma262/#sec-promise.resolve
1598 resolve: function resolve(x) {
1599 return promiseResolve(this, x);
1600 }
1601});
1602
1603_export({ target: PROMISE, stat: true, forced: INCORRECT_ITERATION }, {
1604 // `Promise.all` method
1605 // https://tc39.github.io/ecma262/#sec-promise.all
1606 all: function all(iterable) {
1607 var C = this;
1608 var capability = newPromiseCapability$1(C);
1609 var resolve = capability.resolve;
1610 var reject = capability.reject;
1611 var result = perform(function () {
1612 var values = [];
1613 var counter = 0;
1614 var remaining = 1;
1615 iterate(iterable, function (promise) {
1616 var index = counter++;
1617 var alreadyCalled = false;
1618 values.push(undefined);
1619 remaining++;
1620 C.resolve(promise).then(function (value) {
1621 if (alreadyCalled) return;
1622 alreadyCalled = true;
1623 values[index] = value;
1624 --remaining || resolve(values);
1625 }, reject);
1626 });
1627 --remaining || resolve(values);
1628 });
1629 if (result.error) reject(result.value);
1630 return capability.promise;
1631 },
1632 // `Promise.race` method
1633 // https://tc39.github.io/ecma262/#sec-promise.race
1634 race: function race(iterable) {
1635 var C = this;
1636 var capability = newPromiseCapability$1(C);
1637 var reject = capability.reject;
1638 var result = perform(function () {
1639 iterate(iterable, function (promise) {
1640 C.resolve(promise).then(capability.resolve, reject);
1641 });
1642 });
1643 if (result.error) reject(result.value);
1644 return capability.promise;
1645 }
1646});
1647
1648function _defineProperty(obj, key, value) {
1649 if (key in obj) {
1650 Object.defineProperty(obj, key, {
1651 value: value,
1652 enumerable: true,
1653 configurable: true,
1654 writable: true
1655 });
1656 } else {
1657 obj[key] = value;
1658 }
1659
1660 return obj;
1661}
1662
1663function _objectSpread(target) {
1664 for (var i = 1; i < arguments.length; i++) {
1665 var source = arguments[i] != null ? arguments[i] : {};
1666 var ownKeys = Object.keys(source);
1667
1668 if (typeof Object.getOwnPropertySymbols === 'function') {
1669 ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) {
1670 return Object.getOwnPropertyDescriptor(source, sym).enumerable;
1671 }));
1672 }
1673
1674 ownKeys.forEach(function (key) {
1675 _defineProperty(target, key, source[key]);
1676 });
1677 }
1678
1679 return target;
1680}
1681
1682function _objectWithoutPropertiesLoose(source, excluded) {
1683 if (source == null) return {};
1684 var target = {};
1685 var sourceKeys = Object.keys(source);
1686 var key, i;
1687
1688 for (i = 0; i < sourceKeys.length; i++) {
1689 key = sourceKeys[i];
1690 if (excluded.indexOf(key) >= 0) continue;
1691 target[key] = source[key];
1692 }
1693
1694 return target;
1695}
1696
1697function _objectWithoutProperties(source, excluded) {
1698 if (source == null) return {};
1699
1700 var target = _objectWithoutPropertiesLoose(source, excluded);
1701
1702 var key, i;
1703
1704 if (Object.getOwnPropertySymbols) {
1705 var sourceSymbolKeys = Object.getOwnPropertySymbols(source);
1706
1707 for (i = 0; i < sourceSymbolKeys.length; i++) {
1708 key = sourceSymbolKeys[i];
1709 if (excluded.indexOf(key) >= 0) continue;
1710 if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
1711 target[key] = source[key];
1712 }
1713 }
1714
1715 return target;
1716}
1717
1718/**
1719 * This abstract class should be implemented by all commands.
1720 */
1721class Command {
1722 /**
1723 * Definitions of the command.
1724 */
1725 constructor() {
1726 _defineProperty(this, "command", void 0);
1727
1728 _defineProperty(this, "description", void 0);
1729
1730 _defineProperty(this, "options", []);
1731 }
1732 /**
1733 * What gets executed when this command runs.
1734 */
1735
1736
1737}
1738
1739// a string of all valid unicode whitespaces
1740// eslint-disable-next-line max-len
1741var whitespaces = '\u0009\u000A\u000B\u000C\u000D\u0020\u00A0\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028\u2029\uFEFF';
1742
1743var whitespace = '[' + whitespaces + ']';
1744var ltrim = RegExp('^' + whitespace + whitespace + '*');
1745var rtrim = RegExp(whitespace + whitespace + '*$');
1746
1747// 1 -> String#trimStart
1748// 2 -> String#trimEnd
1749// 3 -> String#trim
1750var stringTrim = function (string, TYPE) {
1751 string = String(requireObjectCoercible(string));
1752 if (TYPE & 1) string = string.replace(ltrim, '');
1753 if (TYPE & 2) string = string.replace(rtrim, '');
1754 return string;
1755};
1756
1757var non = '\u200B\u0085\u180E';
1758
1759// check that a method works with the correct list
1760// of whitespaces and has a correct name
1761var forcedStringTrimMethod = function (METHOD_NAME) {
1762 return fails(function () {
1763 return !!whitespaces[METHOD_NAME]() || non[METHOD_NAME]() != non || whitespaces[METHOD_NAME].name !== METHOD_NAME;
1764 });
1765};
1766
1767var FORCED$1 = forcedStringTrimMethod('trim');
1768
1769// `String.prototype.trim` method
1770// https://tc39.github.io/ecma262/#sec-string.prototype.trim
1771_export({ target: 'String', proto: true, forced: FORCED$1 }, {
1772 trim: function trim() {
1773 return stringTrim(this, 3);
1774 }
1775});
1776
1777const semverRegex = require('semver-regex');
1778
1779const getLatestVersion = require('latest-version');
1780
1781function parseVersion(v) {
1782 if (v === null) throw new Error('Version is null.');
1783
1784 if (typeof v === 'string') {
1785 const parsedV = semver__default.parse(semverRegex().exec(v)[0]);
1786
1787 if (parsedV === null) {
1788 throw new Error(`Version ${v.trim()} cannot be parsed.`);
1789 }
1790
1791 return parsedV;
1792 }
1793
1794 return v;
1795}
1796async function latestVersion(npmPackageName) {
1797 return parseVersion((await getLatestVersion(npmPackageName)));
1798}
1799
1800function useExeca(cmd) {
1801 const [execaResult, setExecaResult] = React__default.useState();
1802 React__default.useEffect(() => {
1803 const p = execa.command(cmd, {
1804 reject: false
1805 });
1806 p.then(r => {
1807 if (r.killed) return;
1808 setExecaResult(r);
1809 });
1810 return () => p.kill();
1811 }, [cmd]);
1812 return execaResult;
1813}
1814function useLatestNpmVersion(pkg) {
1815 const [latest, setLatest] = React__default.useState(null);
1816 const [error, setError] = React__default.useState();
1817 React__default.useEffect(() => {
1818 let mounted = true;
1819 latestVersion(pkg).then(v => {
1820 if (mounted) setLatest(v);
1821 }).catch(e => {
1822 if (mounted) setError(e);
1823 });
1824 return () => {
1825 mounted = false;
1826 };
1827 }, [pkg]);
1828 return {
1829 latest,
1830 error
1831 };
1832}
1833function latestVersionResult(version) {
1834 return {
1835 type: CheckStatusType.Ok,
1836 message: React__default.createElement(React__default.Fragment, null, "Version ", React__default.createElement(Version, {
1837 version: version
1838 }), " is the latest.")
1839 };
1840}
1841function outdatedVersionResult(current, latest, type = CheckStatusType.Warning) {
1842 return {
1843 type,
1844 message: React__default.createElement(React__default.Fragment, null, "You have version ", React__default.createElement(Version, {
1845 version: current
1846 }), " while the latest is", ' ', React__default.createElement(Version, {
1847 version: latest
1848 }), ".")
1849 };
1850}
1851function Version({
1852 version
1853}) {
1854 return React__default.createElement(ink.Color, {
1855 cyan: true
1856 }, typeof version === 'string' ? version : version.format());
1857}
1858
1859function usePHPCheck() {
1860 const phpV = useExeca('php -v');
1861 const version = phpV ? parseVersion(phpV.stdout) : undefined;
1862
1863 if (!phpV) {
1864 return {
1865 type: CheckStatusType.Loading,
1866 message: 'Checking your PHP version...'
1867 };
1868 }
1869
1870 if (!version) {
1871 return {
1872 type: CheckStatusType.Error,
1873 message: "Looks like you don't have PHP correctly installed."
1874 };
1875 }
1876
1877 if (version.major >= 7 && version.minor >= 1) {
1878 return {
1879 type: CheckStatusType.Ok,
1880 message: React__default.createElement(React__default.Fragment, null, "You have PHP ", React__default.createElement(Version, {
1881 version: version
1882 }), " installed.")
1883 };
1884 }
1885
1886 return {
1887 type: CheckStatusType.Ok,
1888 message: React__default.createElement(React__default.Fragment, null, "You have PHP ", React__default.createElement(Version, {
1889 version: version
1890 }), " installed, but you need at least ", React__default.createElement(Version, {
1891 version: "7.1"
1892 }), ".")
1893 };
1894}
1895
1896function useExit(shouldExit, error) {
1897 const {
1898 exit
1899 } = React__default.useContext(ink.AppContext);
1900 React__default.useEffect(() => {
1901 if (shouldExit) exit(error);
1902 }, [error, exit, shouldExit]);
1903}
1904
1905function useAxios(url, config) {
1906 const [res, setRes] = React__default.useState({
1907 loading: true
1908 });
1909 React__default.useEffect(() => {
1910 const source = axios.CancelToken.source();
1911 axios(_objectSpread({
1912 url,
1913 cancelToken: source.token
1914 }, config)).then(response => {
1915 setRes({
1916 response,
1917 loading: false
1918 });
1919 }).catch(error => {
1920 if (!axios.isCancel(error)) {
1921 setRes({
1922 error,
1923 loading: false
1924 });
1925 }
1926 });
1927 return () => {
1928 source.cancel();
1929 };
1930 }, [config, url]);
1931 return res;
1932}
1933
1934const axiosConfig = {
1935 timeout: 3000
1936};
1937function useNodeJsCheck() {
1938 const nodeVersions = useAxios('https://nodejs.org/dist/index.json', axiosConfig);
1939 const nodeVersion = parseVersion(process.version);
1940 const versionSupported = nodeVersion.major === 8 || nodeVersion.major === 10;
1941
1942 if (!versionSupported) {
1943 return {
1944 type: CheckStatusType.Error,
1945 message: 'You should use Node.js 8 or 10.'
1946 };
1947 }
1948
1949 if (nodeVersions.error) {
1950 return {
1951 type: CheckStatusType.LoadingError,
1952 message: `Error fetching latest version: ${nodeVersions.error.message}`
1953 };
1954 }
1955
1956 if (nodeVersions.loading) {
1957 return {
1958 type: CheckStatusType.Loading,
1959 message: 'Fetching latest version...'
1960 };
1961 }
1962
1963 const latestInMajor = nodeVersions.response.data.map(v => parseVersion(v.version)).find(s => !!s && s.major === nodeVersion.major);
1964
1965 if (!latestInMajor) {
1966 return {
1967 type: CheckStatusType.LoadingError,
1968 message: "Can't find latest Node.js version."
1969 };
1970 }
1971
1972 if (latestInMajor.compare(nodeVersion) === 0) {
1973 return latestVersionResult(nodeVersion);
1974 }
1975
1976 return outdatedVersionResult(nodeVersion, latestInMajor);
1977}
1978
1979function useNPMCheck() {
1980 const npmV = useExeca('npm -v');
1981 const version = npmV ? parseVersion(npmV.stdout) : undefined;
1982 const {
1983 latest,
1984 error
1985 } = useLatestNpmVersion('npm');
1986
1987 if (!npmV) {
1988 return {
1989 type: CheckStatusType.Loading,
1990 message: 'Getting your NPM version...'
1991 };
1992 }
1993
1994 if (!version) {
1995 return {
1996 type: CheckStatusType.Error,
1997 message: 'Something is wrong with your NPM installation.'
1998 };
1999 }
2000
2001 if (error) {
2002 return {
2003 type: CheckStatusType.LoadingError,
2004 message: `Error fetching latest version: ${error.message}`
2005 };
2006 }
2007
2008 if (!latest) {
2009 return {
2010 type: CheckStatusType.Loading,
2011 message: 'Getting latest version from NPM...'
2012 };
2013 }
2014
2015 if (latest.compare(version.version) === 0) {
2016 return latestVersionResult(version);
2017 }
2018
2019 return outdatedVersionResult(version, latest);
2020}
2021
2022var version = "0.0.124";
2023
2024/* eslint-disable no-console */
2025function UpdateBurstCli() {
2026 const updateCommand = useExeca('npm i -g @burst/cli');
2027 React__default.useEffect(() => {
2028 if (updateCommand) {
2029 console.log('Burst CLI updated, please re-run your command.');
2030 console.log();
2031 process.exit(1);
2032 }
2033 }, [updateCommand]);
2034
2035 if (!updateCommand) {
2036 return React__default.createElement(ink.Box, {
2037 marginTop: 1,
2038 marginBottom: 1
2039 }, "Updating the Burst CLI to the latest version...");
2040 }
2041
2042 return null;
2043}
2044function useBurstCliCheck() {
2045 const {
2046 latest,
2047 error
2048 } = useLatestNpmVersion('@burst/cli');
2049
2050 if (error) {
2051 return {
2052 type: CheckStatusType.LoadingError,
2053 message: `Error fetching latest version: ${error.message}`
2054 };
2055 }
2056
2057 if (latest) {
2058 if (latest.compare(version) !== 0) {
2059 return outdatedVersionResult(version, latest, CheckStatusType.Error);
2060 }
2061
2062 return latestVersionResult(latest);
2063 }
2064
2065 return {
2066 type: CheckStatusType.Loading,
2067 message: 'Getting latest version from NPM...'
2068 };
2069}
2070
2071const minVersion = '3.0.0-rc.12';
2072const maxVersion = '3.0.0-rc.15';
2073function useLandoCheck() {
2074 const lando = useExeca('lando version');
2075 const version = lando && lando.exitCode === 0 ? parseVersion(lando.stdout) : undefined;
2076
2077 if (!lando) {
2078 return {
2079 type: CheckStatusType.Loading,
2080 message: 'Checking your Lando version...'
2081 };
2082 }
2083
2084 if (!version) {
2085 return {
2086 type: CheckStatusType.Ok,
2087 message: "You don't have Lando installed, which is fine."
2088 };
2089 }
2090
2091 const downloadLink = React__default.createElement(React__default.Fragment, null, "Download the latest supported version here:", ' ', `https://github.com/lando/lando/releases/tag/v${maxVersion}`);
2092
2093 if (version.compare(minVersion) === -1) {
2094 return {
2095 type: CheckStatusType.Error,
2096 message: React__default.createElement(React__default.Fragment, null, "You have Lando ", React__default.createElement(Version, {
2097 version: version
2098 }), " installed, but you need at least ", React__default.createElement(Version, {
2099 version: minVersion
2100 }), ". Please update to", ' ', React__default.createElement(Version, {
2101 version: maxVersion
2102 }), " if possible. ", downloadLink)
2103 };
2104 }
2105
2106 if (version.compare(maxVersion) === 1) {
2107 return {
2108 type: CheckStatusType.Error,
2109 message: React__default.createElement(React__default.Fragment, null, "You have Lando ", React__default.createElement(Version, {
2110 version: version
2111 }), " installed, but the latest supported version is ", React__default.createElement(Version, {
2112 version: maxVersion
2113 }), ". Please downgrade to to that version. ", downloadLink)
2114 };
2115 }
2116
2117 if (version.compare(maxVersion) === -1) {
2118 return {
2119 type: CheckStatusType.Warning,
2120 message: React__default.createElement(React__default.Fragment, null, "You have Lando ", React__default.createElement(Version, {
2121 version: version
2122 }), " installed, but the latest supported version is ", React__default.createElement(Version, {
2123 version: maxVersion
2124 }), ". ", downloadLink)
2125 };
2126 }
2127
2128 return {
2129 type: CheckStatusType.Ok,
2130 message: React__default.createElement(React__default.Fragment, null, "You have Lando ", React__default.createElement(Version, {
2131 version: version
2132 }), " installed.")
2133 };
2134}
2135
2136const isCI = require('is-ci');
2137
2138class CheckCommand extends Command {
2139 constructor(...args) {
2140 super(...args);
2141
2142 _defineProperty(this, "command", 'check');
2143
2144 _defineProperty(this, "description", 'Check your local environment.');
2145 }
2146
2147 async action() {
2148 const a = ink.render(React__default.createElement(Check, null));
2149 await a.waitUntilExit();
2150 }
2151
2152}
2153function checkFirst(funcToWrap) {
2154 return async (...args) => {
2155 // We don't want to check first on the CI.
2156 if (!isCI) {
2157 const a = ink.render(React__default.createElement(Check, {
2158 onlyDisplayErrors: true
2159 }));
2160 await a.waitUntilExit(); // @ts-ignore
2161
2162 a.cleanup();
2163 }
2164
2165 return funcToWrap(...args);
2166 };
2167}
2168let CheckStatusType;
2169
2170(function (CheckStatusType) {
2171 CheckStatusType[CheckStatusType["Loading"] = 0] = "Loading";
2172 CheckStatusType[CheckStatusType["Warning"] = 1] = "Warning";
2173 CheckStatusType[CheckStatusType["Error"] = 2] = "Error";
2174 CheckStatusType[CheckStatusType["LoadingError"] = 3] = "LoadingError";
2175 CheckStatusType[CheckStatusType["Ok"] = 4] = "Ok";
2176})(CheckStatusType || (CheckStatusType = {}));
2177
2178function Check({
2179 onlyDisplayErrors = false
2180}) {
2181 const checks = [['Burst CLI', useBurstCliCheck()], ['Node.js', useNodeJsCheck()], ['PHP', usePHPCheck()], ['NPM', useNPMCheck()], ['Lando', useLandoCheck()]];
2182 const burstCliNeedsUpdate = checks[0][1].type === CheckStatusType.Error;
2183 const checksLoaded = checks.every(([, c]) => c.type !== CheckStatusType.Loading);
2184 useExit(checksLoaded && !burstCliNeedsUpdate);
2185 return React__default.createElement(ink.Box, {
2186 marginBottom: 1,
2187 flexDirection: "column"
2188 }, (onlyDisplayErrors ? checks.filter(([, c]) => c.type !== CheckStatusType.Loading && c.type !== CheckStatusType.Ok) : checks).map(([n, c]) => React__default.createElement(ink.Box, {
2189 key: n
2190 }, React__default.createElement(ink.Box, {
2191 width: 4
2192 }, c.type === CheckStatusType.Loading ? '⌚' : c.type === CheckStatusType.Warning ? '🚧' : c.type === CheckStatusType.Error ? '❌' : c.type === CheckStatusType.LoadingError ? '❌' : '👍'), React__default.createElement(ink.Box, {
2193 width: 12
2194 }, n), React__default.createElement(ink.Box, {
2195 textWrap: "wrap",
2196 flexGrow: 1
2197 }, c.message))), !checksLoaded && React__default.createElement(ink.Box, {
2198 marginTop: 1,
2199 marginBottom: 1
2200 }, "Checking your local development environment..."), burstCliNeedsUpdate && React__default.createElement(UpdateBurstCli, null));
2201}
2202
2203const isCI$1 = require('is-ci');
2204
2205class PrepareCICommand extends Command {
2206 constructor(...args) {
2207 super(...args);
2208
2209 _defineProperty(this, "command", 'prepare-ci');
2210
2211 _defineProperty(this, "description", 'This adds various environment varibles.');
2212
2213 _defineProperty(this, "action", async () => {
2214 if (!isCI$1) {
2215 console.log('You can only run this command in the CI.');
2216 process.exit(1);
2217 }
2218
2219 console.log((await prepareCI()));
2220 });
2221 }
2222
2223}
2224async function prepareCI() {
2225 if (!isCI$1) return [];
2226 const toEval = []; // Start ssh agent
2227
2228 if (!process.env.SSH_AUTH_SOCK || !process.env.SSH_AGENT_PID) {
2229 const {
2230 stdout: agent
2231 } = await execa('ssh-agent');
2232 toEval.push(agent);
2233 const [, authSock] = /SSH_AUTH_SOCK=(.*); export/.exec(agent) || ['', ''];
2234 const [, agentPid] = /SSH_AGENT_PID=(.*); export/.exec(agent) || ['', ''];
2235 process.env.SSH_AUTH_SOCK = authSock;
2236 process.env.SSH_AGENT_PID = agentPid;
2237 } // Add ssh key
2238
2239
2240 if (process.env.PLATFORMSH_SSH_KEY) {
2241 await execa.command(`echo "$PLATFORMSH_SSH_KEY" | tr -d '\\r' | ssh-add - > /dev/null`, {
2242 shell: true
2243 });
2244 }
2245
2246 return toEval.join('\n');
2247}
2248
2249const isCI$2 = require('is-ci');
2250
2251const repoRootGitCmd = execa.sync('git', ['rev-parse', '--show-toplevel'], {
2252 reject: false
2253});
2254
2255if (repoRootGitCmd.failed) {
2256 throw new Error('Please use the Burst CLI in a git repository.');
2257}
2258
2259const repoRoot = repoRootGitCmd.stdout;
2260/** @deprecated */
2261
2262function getRepoRoot() {
2263 return repoRoot;
2264}
2265async function push(url, branch, {
2266 dir,
2267 showProgress
2268} = {}) {
2269 // Remove any possible old remote we could still have.
2270 // We catch everything, because it fails if there isn't one.
2271 // That's no problem.
2272 await execa('git', ['remote', 'remove', '_burst_tmp_']).catch(() => undefined); // Add a new remote with the push url.
2273
2274 await execa('git', ['remote', 'add', '_burst_tmp_', url]); // Push current head to the new remote on the branch provided.
2275
2276 try {
2277 let src = 'HEAD';
2278
2279 if (dir) {
2280 console.log(`Creating git subtree of the ${chalk.cyan(dir)} directory.`);
2281 ({
2282 stdout: src
2283 } = await execa('git', ['subtree', 'split', '--prefix', dir], {
2284 stderr: showProgress && !isCI$2 ? 'inherit' : undefined,
2285 // We always need to run the subtree command from the root of the
2286 // project, see #44.
2287 cwd: repoRoot
2288 }));
2289 console.log('Done with creating subtree.');
2290 } // Make sure we can push with SSH if on the Gitlab CI
2291
2292
2293 await prepareCI(); // We push the src (which is HEAD or a commit id) to the remote repository. We prefix
2294 // the remote repository with refs/heads/ so the branch is created if it doesn't
2295 // exist on the remote already.
2296
2297 await execa('git', ['push', '_burst_tmp_', `${src}:refs/heads/${branch}`, '--force'], showProgress ? {
2298 stdio: 'inherit'
2299 } : undefined);
2300 } finally {
2301 // Remove the remote (even if pushing failed).
2302 await execa('git', ['remote', 'remove', '_burst_tmp_']).catch(() => {// do nothing
2303 });
2304 }
2305}
2306async function getCurrentBranch() {
2307 // In Gitlab CI, we can use this environment variable.
2308 if (process.env.CI_COMMIT_REF_NAME) return process.env.CI_COMMIT_REF_NAME; // Otherwise, we use the Git CLI to get the current branch.
2309
2310 return (await execa('git', ['rev-parse', '--abbrev-ref', 'HEAD'])).stdout;
2311}
2312async function getListOfRepoFiles(search = [], fromRoot = false) {
2313 const cwd = fromRoot || !search.length ? repoRoot : undefined; // To get a complete list of all files that are on disk and not excluded by a
2314 // gitignore rule, we need to do multple 'git ls-files' calls.
2315 //
2316 // CACHED:
2317 // This are all the files that are currently staged.
2318 // If a file is deleted but that change isn't staged yet, it will still be
2319 // returned.
2320 //
2321 // DELETED:
2322 // This returns all files that are staged at this moment, but aren't
2323 // available on the disk anymore. If a deletion is staged, it isn't returned
2324 // anymore.
2325 //
2326 // UNTRACKED:
2327 // This are all the new files that exist on disk, but aren't tracked / staged
2328 // yet.
2329
2330 const [cached, deleted, untracked] = await Promise.all([gitLsFiles(search, cwd), gitLsFiles(['--deleted', ...search], cwd), gitLsFiles([...search, '--others', '--exclude-standard'], cwd)]);
2331 return [...untracked, ...cached.filter(file => !deleted.includes(file))];
2332}
2333
2334async function gitLsFiles(opts, cwd) {
2335 const {
2336 stdout: command
2337 } = await execa('git', ['ls-files', ...opts, '--full-name'], {
2338 cwd
2339 });
2340 return command.split('\n').filter(f => f.length);
2341}
2342
2343function useTsWorker() {
2344 return useWorker('./workers/ts', ['doTsCheck']);
2345}
2346function usePrettierWorker() {
2347 return useWorker('./workers/prettier', ['getFileInfo', 'format']);
2348}
2349function useEslintWorker() {
2350 return useWorker('./workers/eslint', ['lintFile', 'writeToDisk']);
2351}
2352
2353function useWorker(path, exposedMethods) {
2354 const exposedMethodsJson = JSON.stringify(exposedMethods);
2355 const worker = React.useMemo(() => new Worker(require.resolve(path), {
2356 exposedMethods: JSON.parse(exposedMethodsJson)
2357 }), [exposedMethodsJson, path]);
2358 React.useEffect(() => () => worker.end(), [worker]);
2359 return worker;
2360}
2361
2362function useTsChecker(allFiles) {
2363 const files = React.useMemo(() => allFiles.filter(f => f.path.endsWith('.ts') || f.path.endsWith('.tsx')), [allFiles]);
2364 const [filesWithTs, filesWithoutTs] = React.useMemo(() => {
2365 const resolved = lodash.groupBy(files, file => resolve.silent(file.absolutePath, 'typescript'));
2366
2367 const {
2368 undefined: withoutTs = []
2369 } = resolved,
2370 withTs = _objectWithoutProperties(resolved, ["undefined"]);
2371
2372 return [withTs, withoutTs];
2373 }, [files]);
2374 const worker = useTsWorker();
2375 const [workerResults, setWorkerResults] = React.useState([]);
2376 React.useEffect(() => {
2377 Object.entries(filesWithTs).forEach(async ([tsPath, tsFiles]) => {
2378 const workerResult = await worker.doTsCheck(tsPath, tsFiles.map(f => f.absolutePath));
2379 setWorkerResults(r => [...r, workerResult]);
2380 });
2381 }, [filesWithTs, worker]);
2382 const filesWithoutProject = lodash.flatten(workerResults.map(r => r.filesWithoutProject));
2383 const filesNotIncludedInProject = lodash.flatten(workerResults.map(r => r.filesNotIncludedInProject));
2384 const errors = [...filesWithoutTs.map(f => ({
2385 filename: f.absolutePath,
2386 message: 'No TypeScript module can be found for this file. \nAre you sure TypeScript is installed?'
2387 })), ...filesWithoutProject.map(f => ({
2388 filename: f,
2389 message: 'Found no tsconfig.json file. \nAre you sure there is a tsconfig.json file in the root of the app?'
2390 })), ...filesNotIncludedInProject.map(f => ({
2391 filename: f,
2392 message: 'There is a tsconfig.json file, but it looks like this file is excluded. \nPlease check the include / exclude part of the tsconfig.json file.'
2393 })), ...lodash.flatten(workerResults.map(r => r.errors))].map(f => _objectSpread({}, f, {
2394 linter: 'TypeScript',
2395 autoFixable: false
2396 }));
2397 return {
2398 files,
2399 done: workerResults.length === Object.keys(filesWithTs).length,
2400 errors
2401 };
2402}
2403
2404function useEslint(allFiles, fix) {
2405 const files = React.useMemo(() => allFiles.filter(f => f.path.endsWith('.js') || f.path.endsWith('.jsx') || f.path.endsWith('.ts') || f.path.endsWith('.tsx')), [allFiles]);
2406 const eslint = useEslintWorker();
2407 const [reports, setReports] = React.useState([]);
2408 const [execErrors, setExecErrors] = React.useState({});
2409 React.useEffect(() => {
2410 files.forEach(async file => {
2411 try {
2412 const report = await eslint.lintFile(file.absolutePath, fix);
2413
2414 if (fix) {
2415 await eslint.writeToDisk(report);
2416 }
2417
2418 setReports(r => [...r, ...report.results]);
2419 } catch (e) {
2420 setExecErrors(exe => _objectSpread({}, exe, {
2421 [file.absolutePath]: e.message || e.toString()
2422 }));
2423 }
2424 });
2425 }, [eslint, files, fix]);
2426 const filesAutoFixed = fix ? reports.reduce((c, r) => c + (r.output ? 1 : 0), 0) : 0;
2427 const errors = [];
2428 const prettierErrors = [];
2429 reports.forEach(r => {
2430 r.messages.forEach(m => {
2431 // We only want to show the Prettier error once per file.
2432 if (m.ruleId === 'prettier/prettier') {
2433 if (prettierErrors.includes(r.filePath)) return;
2434 errors.push({
2435 linter: 'ESLint',
2436 filename: r.filePath,
2437 autoFixable: true,
2438 message: 'Not according to Prettier styling.',
2439 rule: 'prettier/prettier'
2440 });
2441 prettierErrors.push(r.filePath);
2442 return;
2443 }
2444
2445 errors.push({
2446 linter: 'ESLint',
2447 filename: r.filePath,
2448 autoFixable: !!m.fix,
2449 message: m.message,
2450 rule: m.ruleId || undefined,
2451 sourceLocation: _objectSpread({
2452 start: {
2453 line: m.line,
2454 column: m.column
2455 }
2456 }, m.endLine ? {
2457 end: {
2458 line: m.endLine,
2459 column: m.endColumn
2460 }
2461 } : {})
2462 });
2463 });
2464 });
2465 Object.entries(execErrors).forEach(([filename, error]) => {
2466 errors.push({
2467 linter: 'ESLint',
2468 filename,
2469 autoFixable: false,
2470 message: error
2471 });
2472 });
2473 return {
2474 files,
2475 reports,
2476 filesAutoFixed,
2477 errors,
2478 done: reports.length + Object.keys(execErrors).length === files.length
2479 };
2480}
2481
2482var sloppyArrayMethod = function (METHOD_NAME, argument) {
2483 var method = [][METHOD_NAME];
2484 return !method || !fails(function () {
2485 // eslint-disable-next-line no-useless-call,no-throw-literal
2486 method.call(null, argument || function () { throw 1; }, 1);
2487 });
2488};
2489
2490var nativeSort = [].sort;
2491var test = [1, 2, 3];
2492
2493// IE8-
2494var FAILS_ON_UNDEFINED = fails(function () {
2495 test.sort(undefined);
2496});
2497// V8 bug
2498var FAILS_ON_NULL = fails(function () {
2499 test.sort(null);
2500});
2501// Old WebKit
2502var SLOPPY_METHOD = sloppyArrayMethod('sort');
2503
2504var FORCED$2 = FAILS_ON_UNDEFINED || !FAILS_ON_NULL || SLOPPY_METHOD;
2505
2506// `Array.prototype.sort` method
2507// https://tc39.github.io/ecma262/#sec-array.prototype.sort
2508_export({ target: 'Array', proto: true, forced: FORCED$2 }, {
2509 sort: function sort(comparefn) {
2510 return comparefn === undefined
2511 ? nativeSort.call(toObject(this))
2512 : nativeSort.call(toObject(this), aFunction(comparefn));
2513 }
2514});
2515
2516function isObject$1(something) {
2517 return typeof something === 'object' && something !== null;
2518}
2519
2520const appTypes = ['drupal', 'wordpress', 'magento', 'other'];
2521function getProjectConfiguration(burstYaml, gitlabYaml, getPathFromDir) {
2522 const burstConfig = jsYaml.safeLoad(burstYaml);
2523 const gitlabConfig = jsYaml.safeLoad(gitlabYaml);
2524
2525 if (!isObject$1(burstConfig)) {
2526 throw new Error('The burst.yaml is invalid. Please export an object.');
2527 }
2528
2529 if (!isObject$1(gitlabConfig)) {
2530 throw new Error('The .gitlab-ci.yml file is invalid. The contents should be an object.');
2531 }
2532
2533 const apps = isObject$1(burstConfig.apps) ? Object.entries(burstConfig.apps).map(([name, app]) => {
2534 if (!isObject$1(app)) {
2535 throw new Error(`App "${name}" should be an object.`);
2536 }
2537
2538 let type = 'other';
2539
2540 if (typeof app.type !== 'undefined') {
2541 if (!isAppType(app.type)) {
2542 throw new Error(`The type of "${name}" should be any of: ${appTypes.join(', ')}.`);
2543 }
2544
2545 ({
2546 type
2547 } = app);
2548 } else if (isAppType(name)) {
2549 type = name;
2550 }
2551
2552 let dir = name;
2553
2554 if (typeof app.dir === 'string') {
2555 ({
2556 dir
2557 } = app);
2558
2559 if (app.dir === '__legacy__project_root__') {
2560 dir = undefined;
2561 }
2562 }
2563
2564 const path = getPathFromDir(dir);
2565 return {
2566 name,
2567 type,
2568 dir,
2569 path,
2570 options: app,
2571 disableLinting: !!app.disableLinting
2572 };
2573 }) : [];
2574
2575 if (typeof burstConfig.apps !== 'undefined' && !apps.length) {
2576 throw new Error("The 'apps' property in the burst.yaml should be an object with one or more keys.");
2577 }
2578
2579 const usesProjectTemplate = Array.isArray(gitlabConfig.include) && gitlabConfig.include.some(i => isObject$1(i) && i.project === 'burstdigital/utils/burst-devtools' && i.file === '/ci-templates/project.yml');
2580 const vars = isObject$1(gitlabConfig.variables) ? gitlabConfig.variables : {};
2581 return {
2582 apps,
2583 deployEnabled: variableFlag(vars, 'BURST_DEPLOY', true),
2584 lintEnabled: variableFlag(vars, 'BURST_LINT', usesProjectTemplate),
2585 lintStylesEnabled: variableFlag(vars, 'BURST_LINT_STYLES', usesProjectTemplate),
2586 lintPhpEnabled: variableFlag(vars, 'BURST_LINT_PHP', usesProjectTemplate)
2587 };
2588}
2589
2590function variableFlag(variables, variableName, fallback) {
2591 const variable = variables[variableName];
2592
2593 if (typeof process.env[variableName] !== 'undefined' && process.env[variableName] !== variable) {
2594 throw new Error(`It looks like there exists an environment variable with the name of ${variableName}. You should not set this environment variable yourself. It should only be present in the 'variables' section in the .gitlab-ci.yml file. This way, the configuration is consistent for everyone. The .gitlab-ci.yml file is also read when using the Burst CLI locally.`);
2595 }
2596
2597 if (typeof variable === 'undefined') return fallback;
2598 if (variable === 'disable') return false;
2599 if (variable === 'enable') return true;
2600 throw new Error(`The variable ${variableName} defined in .gitlab-ci.yml should be 'enable' or 'disable'. ` + `If you remove the variable, it will default to '${fallback ? 'enable' : 'disable'}'.`);
2601}
2602
2603function isAppType(something) {
2604 return typeof something === 'string' && appTypes.includes(something);
2605}
2606
2607// CONVERT_TO_STRING: true -> String#at
2608// CONVERT_TO_STRING: false -> String#codePointAt
2609var stringAt = function (that, pos, CONVERT_TO_STRING) {
2610 var S = String(requireObjectCoercible(that));
2611 var position = toInteger(pos);
2612 var size = S.length;
2613 var first, second;
2614 if (position < 0 || position >= size) return CONVERT_TO_STRING ? '' : undefined;
2615 first = S.charCodeAt(position);
2616 return first < 0xD800 || first > 0xDBFF || position + 1 === size
2617 || (second = S.charCodeAt(position + 1)) < 0xDC00 || second > 0xDFFF
2618 ? CONVERT_TO_STRING ? S.charAt(position) : first
2619 : CONVERT_TO_STRING ? S.slice(position, position + 2) : (first - 0xD800 << 10) + (second - 0xDC00) + 0x10000;
2620};
2621
2622// `AdvanceStringIndex` abstract operation
2623// https://tc39.github.io/ecma262/#sec-advancestringindex
2624var advanceStringIndex = function (S, index, unicode) {
2625 return index + (unicode ? stringAt(S, index, true).length : 1);
2626};
2627
2628// `RegExp.prototype.flags` getter implementation
2629// https://tc39.github.io/ecma262/#sec-get-regexp.prototype.flags
2630var regexpFlags = function () {
2631 var that = anObject(this);
2632 var result = '';
2633 if (that.global) result += 'g';
2634 if (that.ignoreCase) result += 'i';
2635 if (that.multiline) result += 'm';
2636 if (that.unicode) result += 'u';
2637 if (that.sticky) result += 'y';
2638 return result;
2639};
2640
2641var nativeExec = RegExp.prototype.exec;
2642// This always refers to the native implementation, because the
2643// String#replace polyfill uses ./fix-regexp-well-known-symbol-logic.js,
2644// which loads this file before patching the method.
2645var nativeReplace = String.prototype.replace;
2646
2647var patchedExec = nativeExec;
2648
2649var UPDATES_LAST_INDEX_WRONG = (function () {
2650 var re1 = /a/;
2651 var re2 = /b*/g;
2652 nativeExec.call(re1, 'a');
2653 nativeExec.call(re2, 'a');
2654 return re1.lastIndex !== 0 || re2.lastIndex !== 0;
2655})();
2656
2657// nonparticipating capturing group, copied from es5-shim's String#split patch.
2658var NPCG_INCLUDED = /()??/.exec('')[1] !== undefined;
2659
2660var PATCH = UPDATES_LAST_INDEX_WRONG || NPCG_INCLUDED;
2661
2662if (PATCH) {
2663 patchedExec = function exec(str) {
2664 var re = this;
2665 var lastIndex, reCopy, match, i;
2666
2667 if (NPCG_INCLUDED) {
2668 reCopy = new RegExp('^' + re.source + '$(?!\\s)', regexpFlags.call(re));
2669 }
2670 if (UPDATES_LAST_INDEX_WRONG) lastIndex = re.lastIndex;
2671
2672 match = nativeExec.call(re, str);
2673
2674 if (UPDATES_LAST_INDEX_WRONG && match) {
2675 re.lastIndex = re.global ? match.index + match[0].length : lastIndex;
2676 }
2677 if (NPCG_INCLUDED && match && match.length > 1) {
2678 // Fix browsers whose `exec` methods don't consistently return `undefined`
2679 // for NPCG, like IE8. NOTE: This doesn' work for /(.?)?/
2680 nativeReplace.call(match[0], reCopy, function () {
2681 for (i = 1; i < arguments.length - 2; i++) {
2682 if (arguments[i] === undefined) match[i] = undefined;
2683 }
2684 });
2685 }
2686
2687 return match;
2688 };
2689}
2690
2691var regexpExec = patchedExec;
2692
2693// `RegExpExec` abstract operation
2694// https://tc39.github.io/ecma262/#sec-regexpexec
2695var regexpExecAbstract = function (R, S) {
2696 var exec = R.exec;
2697 if (typeof exec === 'function') {
2698 var result = exec.call(R, S);
2699 if (typeof result !== 'object') {
2700 throw TypeError('RegExp exec method returned something other than an Object or null');
2701 }
2702 return result;
2703 }
2704
2705 if (classofRaw(R) !== 'RegExp') {
2706 throw TypeError('RegExp#exec called on incompatible receiver');
2707 }
2708
2709 return regexpExec.call(R, S);
2710};
2711
2712var SPECIES$3 = wellKnownSymbol('species');
2713
2714var REPLACE_SUPPORTS_NAMED_GROUPS = !fails(function () {
2715 // #replace needs built-in support for named groups.
2716 // #match works fine because it just return the exec results, even if it has
2717 // a "grops" property.
2718 var re = /./;
2719 re.exec = function () {
2720 var result = [];
2721 result.groups = { a: '7' };
2722 return result;
2723 };
2724 return ''.replace(re, '$<a>') !== '7';
2725});
2726
2727// Chrome 51 has a buggy "split" implementation when RegExp#exec !== nativeExec
2728// Weex JS has frozen built-in prototypes, so use try / catch wrapper
2729var SPLIT_WORKS_WITH_OVERWRITTEN_EXEC = !fails(function () {
2730 var re = /(?:)/;
2731 var originalExec = re.exec;
2732 re.exec = function () { return originalExec.apply(this, arguments); };
2733 var result = 'ab'.split(re);
2734 return result.length !== 2 || result[0] !== 'a' || result[1] !== 'b';
2735});
2736
2737var fixRegexpWellKnownSymbolLogic = function (KEY, length, exec, sham) {
2738 var SYMBOL = wellKnownSymbol(KEY);
2739
2740 var DELEGATES_TO_SYMBOL = !fails(function () {
2741 // String methods call symbol-named RegEp methods
2742 var O = {};
2743 O[SYMBOL] = function () { return 7; };
2744 return ''[KEY](O) != 7;
2745 });
2746
2747 var DELEGATES_TO_EXEC = DELEGATES_TO_SYMBOL && !fails(function () {
2748 // Symbol-named RegExp methods call .exec
2749 var execCalled = false;
2750 var re = /a/;
2751 re.exec = function () { execCalled = true; return null; };
2752
2753 if (KEY === 'split') {
2754 // RegExp[@@split] doesn't call the regex's exec method, but first creates
2755 // a new one. We need to return the patched regex when creating the new one.
2756 re.constructor = {};
2757 re.constructor[SPECIES$3] = function () { return re; };
2758 }
2759
2760 re[SYMBOL]('');
2761 return !execCalled;
2762 });
2763
2764 if (
2765 !DELEGATES_TO_SYMBOL ||
2766 !DELEGATES_TO_EXEC ||
2767 (KEY === 'replace' && !REPLACE_SUPPORTS_NAMED_GROUPS) ||
2768 (KEY === 'split' && !SPLIT_WORKS_WITH_OVERWRITTEN_EXEC)
2769 ) {
2770 var nativeRegExpMethod = /./[SYMBOL];
2771 var methods = exec(SYMBOL, ''[KEY], function (nativeMethod, regexp, str, arg2, forceStringMethod) {
2772 if (regexp.exec === regexpExec) {
2773 if (DELEGATES_TO_SYMBOL && !forceStringMethod) {
2774 // The native String method already delegates to @@method (this
2775 // polyfilled function), leasing to infinite recursion.
2776 // We avoid it by directly calling the native @@method method.
2777 return { done: true, value: nativeRegExpMethod.call(regexp, str, arg2) };
2778 }
2779 return { done: true, value: nativeMethod.call(str, regexp, arg2) };
2780 }
2781 return { done: false };
2782 });
2783 var stringMethod = methods[0];
2784 var regexMethod = methods[1];
2785
2786 redefine(String.prototype, KEY, stringMethod);
2787 redefine(RegExp.prototype, SYMBOL, length == 2
2788 // 21.2.5.8 RegExp.prototype[@@replace](string, replaceValue)
2789 // 21.2.5.11 RegExp.prototype[@@split](string, limit)
2790 ? function (string, arg) { return regexMethod.call(string, this, arg); }
2791 // 21.2.5.6 RegExp.prototype[@@match](string)
2792 // 21.2.5.9 RegExp.prototype[@@search](string)
2793 : function (string) { return regexMethod.call(string, this); }
2794 );
2795 if (sham) hide(RegExp.prototype[SYMBOL], 'sham', true);
2796 }
2797};
2798
2799var max$1 = Math.max;
2800var min$2 = Math.min;
2801var floor$1 = Math.floor;
2802var SUBSTITUTION_SYMBOLS = /\$([$&`']|\d\d?|<[^>]*>)/g;
2803var SUBSTITUTION_SYMBOLS_NO_NAMED = /\$([$&`']|\d\d?)/g;
2804
2805var maybeToString = function (it) {
2806 return it === undefined ? it : String(it);
2807};
2808
2809// @@replace logic
2810fixRegexpWellKnownSymbolLogic(
2811 'replace',
2812 2,
2813 function (REPLACE, nativeReplace, maybeCallNative) {
2814 return [
2815 // `String.prototype.replace` method
2816 // https://tc39.github.io/ecma262/#sec-string.prototype.replace
2817 function replace(searchValue, replaceValue) {
2818 var O = requireObjectCoercible(this);
2819 var replacer = searchValue == undefined ? undefined : searchValue[REPLACE];
2820 return replacer !== undefined
2821 ? replacer.call(searchValue, O, replaceValue)
2822 : nativeReplace.call(String(O), searchValue, replaceValue);
2823 },
2824 // `RegExp.prototype[@@replace]` method
2825 // https://tc39.github.io/ecma262/#sec-regexp.prototype-@@replace
2826 function (regexp, replaceValue) {
2827 var res = maybeCallNative(nativeReplace, regexp, this, replaceValue);
2828 if (res.done) return res.value;
2829
2830 var rx = anObject(regexp);
2831 var S = String(this);
2832
2833 var functionalReplace = typeof replaceValue === 'function';
2834 if (!functionalReplace) replaceValue = String(replaceValue);
2835
2836 var global = rx.global;
2837 if (global) {
2838 var fullUnicode = rx.unicode;
2839 rx.lastIndex = 0;
2840 }
2841 var results = [];
2842 while (true) {
2843 var result = regexpExecAbstract(rx, S);
2844 if (result === null) break;
2845
2846 results.push(result);
2847 if (!global) break;
2848
2849 var matchStr = String(result[0]);
2850 if (matchStr === '') rx.lastIndex = advanceStringIndex(S, toLength(rx.lastIndex), fullUnicode);
2851 }
2852
2853 var accumulatedResult = '';
2854 var nextSourcePosition = 0;
2855 for (var i = 0; i < results.length; i++) {
2856 result = results[i];
2857
2858 var matched = String(result[0]);
2859 var position = max$1(min$2(toInteger(result.index), S.length), 0);
2860 var captures = [];
2861 // NOTE: This is equivalent to
2862 // captures = result.slice(1).map(maybeToString)
2863 // but for some reason `nativeSlice.call(result, 1, result.length)` (called in
2864 // the slice polyfill when slicing native arrays) "doesn't work" in safari 9 and
2865 // causes a crash (https://pastebin.com/N21QzeQA) when trying to debug it.
2866 for (var j = 1; j < result.length; j++) captures.push(maybeToString(result[j]));
2867 var namedCaptures = result.groups;
2868 if (functionalReplace) {
2869 var replacerArgs = [matched].concat(captures, position, S);
2870 if (namedCaptures !== undefined) replacerArgs.push(namedCaptures);
2871 var replacement = String(replaceValue.apply(undefined, replacerArgs));
2872 } else {
2873 replacement = getSubstitution(matched, S, position, captures, namedCaptures, replaceValue);
2874 }
2875 if (position >= nextSourcePosition) {
2876 accumulatedResult += S.slice(nextSourcePosition, position) + replacement;
2877 nextSourcePosition = position + matched.length;
2878 }
2879 }
2880 return accumulatedResult + S.slice(nextSourcePosition);
2881 }
2882 ];
2883
2884 // https://tc39.github.io/ecma262/#sec-getsubstitution
2885 function getSubstitution(matched, str, position, captures, namedCaptures, replacement) {
2886 var tailPos = position + matched.length;
2887 var m = captures.length;
2888 var symbols = SUBSTITUTION_SYMBOLS_NO_NAMED;
2889 if (namedCaptures !== undefined) {
2890 namedCaptures = toObject(namedCaptures);
2891 symbols = SUBSTITUTION_SYMBOLS;
2892 }
2893 return nativeReplace.call(replacement, symbols, function (match, ch) {
2894 var capture;
2895 switch (ch.charAt(0)) {
2896 case '$': return '$';
2897 case '&': return matched;
2898 case '`': return str.slice(0, position);
2899 case "'": return str.slice(tailPos);
2900 case '<':
2901 capture = namedCaptures[ch.slice(1, -1)];
2902 break;
2903 default: // \d\d?
2904 var n = +ch;
2905 if (n === 0) return match;
2906 if (n > m) {
2907 var f = floor$1(n / 10);
2908 if (f === 0) return match;
2909 if (f <= m) return captures[f - 1] === undefined ? ch.charAt(1) : captures[f - 1] + ch.charAt(1);
2910 return match;
2911 }
2912 capture = captures[n - 1];
2913 }
2914 return capture === undefined ? '' : capture;
2915 });
2916 }
2917 }
2918);
2919
2920class HostingProvider {
2921 constructor(config) {
2922 this.config = config;
2923 }
2924
2925 /**
2926 * The number of deploy target levels this hosting provider supports. For example,
2927 * Platform.sh supports 2 special ones: 'Production', 'Staging'.
2928 *
2929 * Heroku only has one environment per app, so there it's only 1.
2930 */
2931 static getAvailableDeployTargetLevels() {
2932 return 1;
2933 }
2934
2935}
2936class HostingProviderEnvironment {
2937 /**
2938 * The deploy target level for this application. Should be set using the
2939 * 'deployTargetLevels' option. This should never be the same or higher then the passed
2940 * option.
2941 *
2942 * The lower the number, the more important the deploy target is.
2943 */
2944 getDeployTarget() {
2945 return DeployTarget.Other;
2946 }
2947
2948 isSuggested() {
2949 return false;
2950 }
2951
2952 isActive() {
2953 return false;
2954 }
2955
2956}
2957
2958const PlatformClient = require('platformsh-client').default;
2959
2960class Platform extends HostingProvider {
2961 constructor(...args) {
2962 super(...args);
2963
2964 _defineProperty(this, "name", 'platform');
2965
2966 _defineProperty(this, "isEnterpriseProject", false);
2967
2968 _defineProperty(this, "platformProject", null);
2969 }
2970
2971 isSameAs(config) {
2972 return config.id === this.config.id;
2973 }
2974
2975 getDisplayName() {
2976 if (this.platformProject) return this.platformProject.title;
2977 return this.config.id;
2978 }
2979
2980 getLink() {
2981 return `https://console.platform.sh/burst/${encodeURIComponent(this.config.id)}`;
2982 }
2983
2984 static getAvailableDeployTargetLevels() {
2985 return 3;
2986 }
2987
2988 static async getClient() {
2989 if (this.client) return this.client;
2990
2991 if (process.env.PLATFORMSH_CLI_TOKEN) {
2992 this.client = new PlatformClient({
2993 api_token: process.env.PLATFORMSH_CLI_TOKEN
2994 });
2995 } else {
2996 this.client = new PlatformClient({
2997 access_token: await getPlatformToken()
2998 });
2999 }
3000
3001 return this.client;
3002 }
3003
3004 async getPlatformProject() {
3005 if (this.platformProject) return this.platformProject;
3006 const platformClient = await Platform.getClient();
3007 this.platformProject = await platformClient.getProject(this.config.id);
3008 return this.platformProject;
3009 }
3010
3011 async getPossibleEnvs(config) {
3012 const spinner = ora().start(`Getting platform environments for project ${this.config.id}.`);
3013 const platformProject = await this.getPlatformProject();
3014 const platformEnvs = await platformProject.getEnvironments();
3015 this.isEnterpriseProject = platformEnvs.some(e => e.id === 'production' && e.deployment_target === 'enterprise');
3016 spinner.stop();
3017 const instances = [];
3018 instances.push(...platformEnvs.map( // eslint-disable-next-line no-use-before-define
3019 e => new PlatformEnvironment(this, e, config, instances)));
3020
3021 if (!instances.find(i => i.isSuggested())) {
3022 instances.push( // eslint-disable-next-line no-use-before-define
3023 new PlatformEnvironment(this, {
3024 new: true
3025 }, config, instances));
3026 }
3027
3028 return instances;
3029 }
3030
3031 async getGitUrl() {
3032 return (await this.getPlatformProject()).getGitUrl();
3033 }
3034
3035}
3036
3037_defineProperty(Platform, "client", void 0);
3038
3039class PlatformEnvironment extends HostingProviderEnvironment {
3040 constructor(project, model, config, environments) {
3041 super();
3042 this.project = project;
3043 this.config = config;
3044 this.environments = environments;
3045
3046 _defineProperty(this, "model", void 0);
3047
3048 if (model.new) {
3049 const target = Object.entries(this.branchNamesWithTargets()).find(([, t]) => t === config.suggestedTarget);
3050 const id = target ? target[0] : config.suggestedName;
3051
3052 if (!id) {
3053 throw new Error(`Not a valid config was passed. Either pass a 'suggestedTarget' or ` + `'suggestedName'.\n Passed now: \n${JSON.stringify(config)}`);
3054 }
3055
3056 this.model = _objectSpread({}, model, {
3057 id
3058 });
3059 } else {
3060 this.model = model;
3061 }
3062 }
3063
3064 getDisplayName() {
3065 const {
3066 id
3067 } = this.model;
3068
3069 if (this.project.isEnterpriseProject) {
3070 if (id === 'production') return 'Production (enterprise)';
3071 if (id === 'staging') return 'Staging (enterprise)';
3072 if (id === 'master') return 'Mirror';
3073 }
3074
3075 if (id === 'master') return 'Production';
3076 if (id === 'staging') return 'Staging (will be deleted in the future)';
3077 if (id === 'mirror') return 'Mirror';
3078 if (this.hasOptedOutResync()) return `${id} [keep data]`;
3079 if (this.hasOptedOutDeactvation()) return `${id} [keep]`;
3080 return id;
3081 }
3082
3083 branchNamesWithTargets() {
3084 if (this.project.isEnterpriseProject) {
3085 return {
3086 production: DeployTarget.Production,
3087 staging: DeployTarget.Staging,
3088 master: DeployTarget.Staging
3089 };
3090 }
3091
3092 return {
3093 master: DeployTarget.Production,
3094 staging: DeployTarget.Staging,
3095 mirror: DeployTarget.Staging
3096 };
3097 }
3098
3099 getDeployTarget() {
3100 const {
3101 id
3102 } = this.model;
3103
3104 if (this.branchNamesWithTargets()[id]) {
3105 return this.branchNamesWithTargets()[id];
3106 }
3107
3108 return DeployTarget.Dynamic;
3109 }
3110
3111 isSuggested() {
3112 return this.config.suggestedTarget === this.getDeployTarget() || this.config.suggestedName === this.model.id || // We also check if there is a slugified version, because previously we
3113 // used the branch slug from the Gitlab CI env variables instead of the
3114 !!this.config.suggestedName && slugify(this.config.suggestedName).replace(/-+/g, '') === slugify(this.model.id).replace(/-+/g, '');
3115 }
3116
3117 isActive() {
3118 if (this.model.new) return false; // There is a bug in the Platform.sh client, that marks 'dirty' environments
3119 // as inactive. An environment is dirty when someting is happening on that
3120 // env (deploy, backup, activation, deactivation). Most of the time when an
3121 // env is dirty, it's active. Only if there is an #activate _link available,
3122 // it's not.
3123
3124 if (this.model.is_dirty) {
3125 return !this.model.hasLink('#activate');
3126 }
3127
3128 return this.model.isActive();
3129 }
3130
3131 hasOptedOutDeactvation() {
3132 return this.hasOptedOutResync() || !this.model.new && this.model.title.endsWith('[keep]');
3133 }
3134
3135 hasOptedOutResync() {
3136 return !this.model.new && this.model.title.endsWith('[keep data]');
3137 }
3138
3139 canBeResyncedOrDeactivated() {
3140 return !this.model.new && !['master', 'production', 'mirror'].includes(this.model.id) && !(this.project.isEnterpriseProject && this.model.id === 'staging') && this.isActive();
3141 }
3142
3143 async deploy({
3144 deployOnlySubdirectory
3145 }) {
3146 if (!this.project.platformProject) {
3147 throw Error('Not possible.');
3148 }
3149
3150 const envsMax = this.project.platformProject.data.subscription.environments + 1;
3151 const envsToBeUsed = this.environments.filter(e => e === this || e.isActive()).length;
3152 const mirrorPossible = envsToBeUsed <= envsMax || this.environments.some(e => e.model.id === 'mirror');
3153 let newParent = this.project.isEnterpriseProject || this.getDeployTarget() !== DeployTarget.Dynamic ? 'master' : !this.model.new && this.model.parent === 'staging' && this.environments.some(e => e.model.id === 'staging' && e.isActive()) && this.isActive() ? 'staging' : 'mirror';
3154
3155 if (newParent === 'staging' && mirrorPossible && !process.env.CI) {
3156 const {
3157 transfer
3158 } = await inquirer.prompt([{
3159 type: 'confirm',
3160 name: 'transfer',
3161 message: `Do you want to change the parent from 'staging' to 'mirror'? The staging environment is deprecated.`
3162 }]);
3163
3164 if (transfer) {
3165 newParent = 'mirror';
3166 }
3167 }
3168
3169 let resync = false;
3170
3171 if (this.canBeResyncedOrDeactivated() && !this.hasOptedOutResync() && !process.env.CI) {
3172 ({
3173 resync
3174 } = await inquirer.prompt([{
3175 type: 'confirm',
3176 name: 'resync',
3177 message: `💣 Do you want to use fresh data (and remove the database on this environment)?`
3178 }]));
3179 }
3180
3181 if (this.canBeResyncedOrDeactivated() && !this.hasOptedOutResync() && !resync) {
3182 console.log('\n\n💣');
3183 console.log('💣 WARNING');
3184 console.log('💣');
3185 console.log('💣 In the future, a deploy will automatically use fresh data.');
3186 console.log('💣 This means that the database will be removed.');
3187 console.log('💣');
3188 console.log(`💣 If you want to opt out, add ${chalk.cyan('[keep data]')} to the name of the environment.`);
3189 console.log('💣\n\n');
3190 }
3191
3192 console.log(`\n\n${chalk.bgYellow.black(' DEPLOY START ')} Deploying to Platform.sh project ${this.project.getDisplayName()} branch ${this.model.id}\n\n`);
3193
3194 try {
3195 // If we want to resync, we first deactivate the environment.
3196 if (resync && !this.model.new) {
3197 try {
3198 await this.model.backup();
3199 } catch (e) {
3200 ({
3201 resync
3202 } = await inquirer.prompt([{
3203 type: 'confirm',
3204 name: 'resync',
3205 message: `💣 Creating a backup isn't possible at the moment. Continue?`
3206 }]));
3207 }
3208 }
3209
3210 if (resync && !this.model.new) {
3211 await this.model.runLongOperation('deactivate', 'POST', undefined);
3212 await this.model.refresh();
3213 } // If the environment doesn't exist yet, we first need to push. This creates an inactive environment.
3214
3215
3216 let isPushed = false;
3217
3218 if (this.model.new) {
3219 await this.push(deployOnlySubdirectory);
3220 isPushed = true;
3221 this.model = await this.project.platformProject.getEnvironment(encodeURIComponent(this.model.id));
3222 } // We make sure the title and parent are as expected.
3223 // If they aren't currently, we set them before deploying.
3224
3225
3226 let needsSave = false;
3227 const {
3228 title
3229 } = this.model;
3230 const newTitle = this.getDisplayName();
3231
3232 if (title !== newTitle) {
3233 console.log(`The environment title is currently ${chalk.red(title)}. That will be changed to ${chalk.cyan(newTitle)}.`);
3234 this.model.title = newTitle;
3235 needsSave = true;
3236 }
3237
3238 if (this.getDeployTarget() === DeployTarget.Dynamic) {
3239 if (this.model.parent !== newParent) {
3240 console.log(`The parent of the environment was ${chalk.red(this.model.parent)}. That will be changed to ${chalk.cyan(newParent)}.`);
3241 this.model.parent = newParent;
3242 needsSave = true;
3243 } // Check if the needed parent actually exists. If not, we should create it.
3244 // We do this by branching from the master. If it does exist but it's
3245 // inactive, we activate it.
3246
3247
3248 const p = this.environments.find(e => e.model.id === newParent);
3249
3250 if (!p) {
3251 const m = this.environments.find(e => e.model.id === 'master');
3252 if (!m || m.model.new) throw new Error("The master envronment doesn't exist.");
3253 await this.catchTooManyEnvironments(() => {
3254 if (m.model.new) throw new Error('Not possible.');
3255 return m.model.branch('Mirror', newParent);
3256 });
3257 } else if (!p.isActive()) {
3258 await this.catchTooManyEnvironments(() => {
3259 if (p.model.new) throw new Error('Not possible.');
3260 return p.model.activate();
3261 });
3262 }
3263 }
3264
3265 if (needsSave) {
3266 await this.model.update(this.model.data);
3267 console.log('Updated environment information.');
3268 } // We push the code to Platform now. Except when we did that to create an inactive
3269 // environment.
3270
3271
3272 if (!isPushed) {
3273 await this.push(deployOnlySubdirectory);
3274 } // We use our own isActive instead of Platform.sh's one, because the
3275 // Platform.sh one is buggy.
3276
3277
3278 if (!this.isActive()) {
3279 await this.catchTooManyEnvironments(() => {
3280 if (this.model.new) throw new Error('Not possible');
3281 return this.model.activate();
3282 });
3283 console.log('\n\nThe environment is being activated.');
3284 console.log('Follow the progress here: ');
3285 console.log(`${this.project.getLink()}/${encodeURIComponent(this.model.id)}`);
3286 }
3287
3288 console.log(`\n\n${chalk.bgGreen.black(' DEPLOY DONE ')} Deploy successfully completed.\n\n`);
3289 } catch (e) {
3290 console.error(chalk.bgRed(' DEPLOY FAILED '));
3291 throw e;
3292 }
3293 }
3294
3295 async push(dir) {
3296 return push((await this.project.getGitUrl()), this.model.id, {
3297 dir,
3298 showProgress: true
3299 });
3300 }
3301
3302 getUrls() {
3303 if (this.model.new) return [];
3304 const urls = this.model.getRouteUrls();
3305 return urls.filter(u => !u.startsWith('http://'));
3306 }
3307
3308 async catchTooManyEnvironments(action) {
3309 try {
3310 return await action();
3311 } catch (error) {
3312 if (error.message !== 'This action would raise the count of environments over its limit.') {
3313 throw error;
3314 }
3315
3316 console.log(chalk.red('\n\nThere are not enough environments available.\n\n'));
3317 const envsThatCanBeDeleted = this.environments.filter(env => env.canBeResyncedOrDeactivated() && !env.hasOptedOutDeactvation());
3318
3319 if (!envsThatCanBeDeleted.length) {
3320 throw new Error('There are no environments that can be deactivated. Please upgrade the number of available environments.');
3321 }
3322
3323 if (process.env.CI) {
3324 throw new Error('Use the Burst CLI locally to choose an environment to remove.');
3325 }
3326
3327 const {
3328 envToDeactivate
3329 } = await inquirer.prompt([{
3330 type: 'list',
3331 name: 'envToDeactivate',
3332 message: '💣 What environment do you want to deactivate? (we will create a backup before deactivation, just to be sure)',
3333 choices: envsThatCanBeDeleted.map(env => ({
3334 name: env.getDisplayName(),
3335 value: env
3336 }))
3337 }]);
3338 if (envToDeactivate.model.new) throw new Error('Not possible');
3339 await envToDeactivate.model.backup();
3340 await envToDeactivate.model.deactivate();
3341 return action();
3342 }
3343 }
3344
3345}
3346
3347async function getPlatformToken() {
3348 const {
3349 stdout: res
3350 } = await execa('platform', ['auth:token'], {
3351 preferLocal: false
3352 });
3353
3354 if (res.length === 0) {
3355 throw new Error("The Platform access_token token can't be fetched from the Platform CLI.");
3356 }
3357
3358 return res;
3359}
3360
3361class Heroku extends HostingProvider {
3362 constructor(config) {
3363 super(config);
3364
3365 if (typeof config.id !== 'string') {
3366 throw new Error('Hosting config not okay.');
3367 }
3368 }
3369
3370 getDisplayName() {
3371 return this.config.id;
3372 }
3373
3374 getLink() {
3375 return '';
3376 }
3377
3378 isSameAs(config) {
3379 return config.id === this.config.id;
3380 }
3381
3382 async getPossibleEnvs() {
3383 // eslint-disable-next-line no-use-before-define
3384 return [new HerokuApp(this)];
3385 }
3386
3387}
3388class HerokuApp extends HostingProviderEnvironment {
3389 constructor(hostingProvider) {
3390 super();
3391 this.hostingProvider = hostingProvider;
3392 }
3393
3394 getDisplayName() {
3395 return this.hostingProvider.getDisplayName();
3396 }
3397
3398 async deploy() {
3399 throw new Error('Not possible to deploy a Heroku application yet.');
3400 }
3401
3402 getUrls() {
3403 return [];
3404 }
3405
3406}
3407
3408const hostingProviders = {
3409 platform: Platform,
3410 heroku: Heroku
3411};
3412
3413let DeployTarget;
3414
3415(function (DeployTarget) {
3416 DeployTarget["Production"] = "production";
3417 DeployTarget["Staging"] = "staging";
3418 DeployTarget["Dynamic"] = "dynamic";
3419 DeployTarget["Other"] = "other";
3420})(DeployTarget || (DeployTarget = {}));
3421
3422function isFile(path) {
3423 try {
3424 return fs.statSync(path).isFile();
3425 } catch (_unused) {
3426 return false;
3427 }
3428}
3429
3430const burstYamlPath = `${repoRoot}/burst.yaml`;
3431const gitlabYamlPath = `${repoRoot}/.gitlab-ci.yml`;
3432const projectConfig = getProjectConfiguration(isFile(burstYamlPath) ? fs.readFileSync(burstYamlPath, 'utf8') : '{}', isFile(gitlabYamlPath) ? fs.readFileSync(gitlabYamlPath, 'utf8') : '{}', dir => {
3433 const path = dir ? `${repoRoot}/${dir}` : repoRoot;
3434
3435 try {
3436 const isDir = fs.statSync(path).isDirectory();
3437
3438 if (!isDir) {
3439 throw new Error(`The location ${path} was found, but it's not a directory.`);
3440 }
3441
3442 return path;
3443 } catch (e) {
3444 console.log();
3445 console.log();
3446 console.log(chalk.red("Your burst.yaml file references a path that doesn't exist:"));
3447 console.log(chalk.yellow(path));
3448 console.log();
3449 console.log();
3450 console.log(chalk.red('Please fix the burst.yaml file in the root.'));
3451 console.log();
3452 console.log();
3453 throw e;
3454 }
3455});
3456
3457class ProjectInfo {
3458 /**
3459 * This gets all different hosting options there are.
3460 *
3461 * Every hosting option can deploy one or more apps.
3462 * Every hosting option can have multiple deploy targets (production for
3463 * example). These deploy targets can be different per app.
3464 */
3465 async getHostingProvidersWithApps() {
3466 const hostingProvidersWithApps = [];
3467 projectConfig.apps.forEach(app => {
3468 // If the app doesn't have any hosting places defined, continue to the next app.
3469 if (typeof app.options.hosting === 'undefined') return; // Get all hosting configs
3470
3471 const hostingConfigs = Array.isArray(app.options.hosting) ? app.options.hosting : [app.options.hosting];
3472 hostingConfigs.forEach(hc => {
3473 // Verify that what we got is actually an object.
3474 if (typeof hc !== 'object' || typeof hc.type !== 'string') {
3475 throw new Error('Please check your burst.yaml file.');
3476 }
3477
3478 const {
3479 type
3480 } = hc,
3481 hostingConfig = _objectWithoutProperties(hc, ["type"]); // Verify that there is a class for this hosting type.
3482
3483
3484 const ThisHostingProvider = hostingProviders[type];
3485
3486 if (!ThisHostingProvider) {
3487 throw new Error(`There is no hosting provider with the name '${type}' supported.`);
3488 } // Check if there is a hosting with the same type and id.
3489 // If there is, we just need to add the app.
3490
3491
3492 const existingHosting = hostingProvidersWithApps.find(h => h.hostingProvider instanceof ThisHostingProvider && h.hostingProvider.isSameAs(hostingConfig));
3493
3494 if (existingHosting) {
3495 existingHosting.apps.push(app);
3496 } else {
3497 hostingProvidersWithApps.push({
3498 hostingProvider: new ThisHostingProvider(hostingConfig),
3499 apps: [app]
3500 });
3501 }
3502 });
3503 });
3504 return hostingProvidersWithApps;
3505 }
3506 /**
3507 * This gets all hosting options, and groups them on the combination of apps.
3508 *
3509 * The apps will be the same for all hostings in a collection, but the deploy
3510 * type can be different per app.
3511 */
3512
3513
3514 async getHostingProvidersByAppCominations() {
3515 const hostings = await this.getHostingProvidersWithApps();
3516 const hostingsGrouped = lodash.groupBy(hostings, hosting => hosting.apps.map(a => a.name).sort().join('__'));
3517 return Object.values(hostingsGrouped).map(hostingsGroup => ({
3518 apps: hostingsGroup[0].apps,
3519 hostingProviders: hostingsGroup.map(hosting => hosting.hostingProvider)
3520 }));
3521 }
3522
3523}
3524
3525let projectInfo;
3526function getProjectInfo() {
3527 if (projectInfo) return projectInfo;
3528 projectInfo = new ProjectInfo();
3529 return projectInfo;
3530}
3531
3532const composerHelperDir = path$1__default.join(__dirname, '../composer-helper');
3533function usePHPCS(allFiles, fix) {
3534 const files = React.useMemo(() => allFiles.filter(f => f.path.endsWith('.php') || f.path.endsWith('.module') || f.path.endsWith('.theme') || f.path.endsWith('.inc') || f.path.endsWith('.install')), [allFiles]);
3535 const composerInstalled = useComposerHelper(files.length > 0 && projectConfig.lintPhpEnabled);
3536 const fileChunksPerStandard = React.useMemo(() => {
3537 const filesPerStandard = lodash.groupBy(files, file => {
3538 if (file.app) {
3539 if (file.app.type === 'drupal') {
3540 return `${composerHelperDir}/drupal_ruleset.xml`;
3541 }
3542
3543 if (file.app.type === 'magento') {
3544 return `${composerHelperDir}/magento_ruleset.xml`;
3545 }
3546
3547 if (file.app.type === 'wordpress') {
3548 return `${composerHelperDir}/wordpress_ruleset.xml`;
3549 }
3550 }
3551
3552 return `${composerHelperDir}/other_ruleset.xml`;
3553 });
3554 return lodash.flatten(Object.entries(filesPerStandard).map(([standard, fs]) => lodash.chunk(fs, 20).map(fc => ({
3555 chunkFiles: fc,
3556 standard
3557 }))));
3558 }, [files]);
3559 const [results, setResults] = React.useState({});
3560 const [filesFixed, setFilesFixed] = React.useState(0);
3561 const [filesWithoutFixes, setFilesWithoutFixes] = React.useState(0);
3562 React.useEffect(() => {
3563 if (!composerInstalled) return;
3564 const queue = new PQueue({
3565 concurrency: 20
3566 });
3567 queue.addAll(fileChunksPerStandard.map(({
3568 chunkFiles,
3569 standard
3570 }) => async () => {
3571 // The arguments we need to pass to the phpcs and phpcbf commands.
3572 const args = [...chunkFiles.map(f => f.absolutePath), '-q', `--standard=${standard}`]; // We first execute phpcs. This way we know how many errors there are.
3573
3574 const result = parsePhpcsResult((await execa(`${composerHelperDir}/vendor/bin/phpcs`, [...args, '--report=json'], {
3575 reject: false,
3576 preferLocal: false
3577 })).stdout); // Sometimes, files aren't linted. We should still add them to the
3578 // result, so we won't wait forever for these files to be linted.
3579
3580 chunkFiles.forEach(f => {
3581 if (!result.files[f.absolutePath]) result.files[f.absolutePath] = {
3582 errors: 0,
3583 warnings: 0,
3584 messages: []
3585 };
3586 });
3587 setResults(r => _objectSpread({}, r, result.files)); // If there are auto-fixable errors or warnings, we can fix them.
3588
3589 if (fix) {
3590 if (result.totals.fixable > 0) {
3591 await execa(`${composerHelperDir}/vendor/bin/phpcbf`, args, {
3592 reject: false,
3593 preferLocal: false
3594 });
3595 setFilesFixed(f => f + chunkFiles.length);
3596 } else {
3597 setFilesWithoutFixes(f => f + chunkFiles.length);
3598 }
3599 }
3600 }));
3601 return () => queue.clear();
3602 }, [composerInstalled, fileChunksPerStandard, fix]); // If there are, create nice error objects.
3603
3604 const errors = lodash.flatten(Object.entries(results).map(([filename, r]) => r.messages.filter(message => fix ? message.type === 'ERROR' && !message.fixable : message.type === 'ERROR' || message.fixable).map(message => ({
3605 linter: 'PHPCS',
3606 filename,
3607 autoFixable: message.fixable,
3608 message: message.message,
3609 rule: message.source,
3610 sourceLocation: {
3611 start: {
3612 line: message.line,
3613 column: message.column
3614 }
3615 }
3616 }))));
3617
3618 if (composerInstalled === false) {
3619 errors.push({
3620 linter: 'PHPCS',
3621 filename: 'Composer dependencies',
3622 autoFixable: false,
3623 message: "The composer dependencies couldn't be installed. PHP files can't be linted."
3624 });
3625 }
3626
3627 const filesLinted = Object.keys(results).length;
3628 const done = !projectConfig.lintPhpEnabled || composerInstalled === false || filesLinted === files.length && (!fix || files.length - filesFixed - filesWithoutFixes === 0);
3629 return {
3630 errors,
3631 files,
3632 filesLinted,
3633 filesFixed,
3634 filesWithFixes: fix ? files.length - filesWithoutFixes : 0,
3635 done
3636 };
3637}
3638
3639function parsePhpcsResult(result) {
3640 return JSON.parse(result);
3641}
3642
3643function useComposerHelper(install) {
3644 const [installCompleted, setInstallCompleted] = React.useState();
3645 React.useEffect(() => {
3646 if (!install) return;
3647 const composerInstall = execa('composer', ['install', '--no-interaction'], {
3648 cwd: composerHelperDir,
3649 reject: false,
3650 preferLocal: false
3651 });
3652 composerInstall.then(a => {
3653 if (a.killed) return;
3654 if (a.failed) setInstallCompleted(false);
3655 setInstallCompleted(true);
3656 });
3657 return () => composerInstall.kill();
3658 }, [install]);
3659 return installCompleted;
3660}
3661
3662const readFileAsync = util.promisify(fs.readFile);
3663const writeFileAsync = util.promisify(fs.writeFile);
3664function usePrettier(allFiles, fix) {
3665 const prettier = usePrettierWorker();
3666 const [filesInfo, setFilesInfo] = React.useState({});
3667 React.useEffect(() => {
3668 const queue = new PQueue({
3669 concurrency: 10
3670 });
3671 queue.addAll(allFiles.map(file => async () => {
3672 // We don't want to test Drupal configuration exports.
3673 if (/\/config\/[\w/]+\/[\w.-]+\.yml$/.test(file.absolutePath)) {
3674 setFilesInfo(i => _objectSpread({}, i, {
3675 [file.absolutePath]: {
3676 ignored: true,
3677 inferredParser: null
3678 }
3679 }));
3680 return;
3681 }
3682
3683 const fileInfo = await prettier.getFileInfo(file.absolutePath);
3684 setFilesInfo(i => _objectSpread({}, i, {
3685 [file.absolutePath]: fileInfo
3686 }));
3687 }));
3688 return () => queue.clear();
3689 }, [allFiles, prettier]);
3690 const filesChecked = Object.keys(filesInfo).length;
3691 const files = React.useMemo(() => Object.entries(filesInfo).filter(([, result]) => result.inferredParser).map(([filename, result]) => ({
3692 filename,
3693 inferredParser: result.inferredParser
3694 })), [filesInfo]);
3695 const [results, setResults] = React.useState({});
3696 const [errorResults, setErrorResults] = React.useState({});
3697 React.useEffect(() => {
3698 if (filesChecked < allFiles.length) return;
3699 const queue = new PQueue({
3700 concurrency: 10
3701 });
3702 queue.addAll(files.map(({
3703 filename,
3704 inferredParser
3705 }) => async () => {
3706 // Create the default prettier config.
3707 const filePrettierConfig = _objectSpread({}, prettierConfig$1, {
3708 parser: inferredParser
3709 }); // Some files have a special prettier config.
3710
3711
3712 if (filename.endsWith('composer.lock') || filename.endsWith('composer.json')) {
3713 filePrettierConfig.parser = 'json-stringify';
3714 filePrettierConfig.tabWidth = 4;
3715 }
3716
3717 try {
3718 // Get the contents of the file.
3719 const fileContents = await readFileAsync(filename, {
3720 encoding: 'utf8'
3721 }); // Format the files, so we can check if they are different.
3722
3723 const newFileContents = await prettier.format(fileContents, filePrettierConfig); // If the file contents didn't change, nothing was fixed.
3724
3725 const correct = fileContents === newFileContents; // If something was fixed, write the results back to disk.
3726
3727 if (fix && !correct) {
3728 await writeFileAsync(filename, newFileContents, {
3729 encoding: 'utf8'
3730 });
3731 }
3732
3733 setResults(r => _objectSpread({}, r, {
3734 [filename]: correct
3735 }));
3736 } catch (e) {
3737 setErrorResults(r => _objectSpread({}, r, {
3738 [filename]: e.message || e.toString()
3739 }));
3740 }
3741 }));
3742 return () => queue.clear();
3743 }, [allFiles.length, files, filesChecked, fix, prettier]);
3744 const filesToLint = Object.keys(files).length;
3745 const linted = Object.keys(results).length + Object.keys(errorResults).length;
3746 const filesNotCorrect = Object.entries(results).filter(([, correct]) => !correct).map(([file]) => file);
3747 const errors = [...(fix ? [] : filesNotCorrect.map(f => ({
3748 linter: 'Prettier',
3749 filename: f,
3750 autoFixable: true,
3751 message: 'Not according to Prettier styling.'
3752 }))), ...Object.entries(errorResults).map(([filename, error]) => ({
3753 linter: 'Prettier',
3754 filename,
3755 autoFixable: false,
3756 message: `Error while linting with Prettier: ${error}`
3757 }))];
3758 return {
3759 filesChecked,
3760 filesToLint,
3761 linted,
3762 done: allFiles.length === filesChecked && linted === filesToLint,
3763 errors,
3764 fixed: fix ? filesNotCorrect : [],
3765 filesNotCorrect
3766 };
3767}
3768
3769function useStylelint(allFiles, fix) {
3770 const [lintResults, setLintResults] = React.useState();
3771 const [fixResults, setFixResults] = React.useState();
3772 const filesLintable = React.useMemo(() => projectConfig.lintStylesEnabled ? allFiles.filter(({
3773 filename: f
3774 }) => !f.endsWith('.d.ts') && (f.endsWith('.js') || f.endsWith('.jsx') || f.endsWith('.ts') || f.endsWith('.tsx'))) : [], [allFiles]);
3775 const filesFixable = React.useMemo(() => projectConfig.lintStylesEnabled ? allFiles.filter(({
3776 filename: f
3777 }) => f.endsWith('.css') || f.endsWith('.sass') || f.endsWith('.scss') || f.endsWith('.less')) : [], [allFiles]);
3778 const filesForLintRun = React.useMemo(() => fix ? filesLintable : [...filesLintable, ...filesFixable], [filesFixable, filesLintable, fix]);
3779 const filesForFixRun = React.useMemo(() => fix ? filesFixable : [], [filesFixable, fix]);
3780 React.useEffect(() => {
3781 if (!filesForLintRun.length) return;
3782 stylelint.lint({
3783 configFile: require.resolve('@burst/stylelint-config'),
3784 files: filesForLintRun.map(f => f.absolutePath)
3785 }).then(r => setLintResults(r));
3786 }, [filesForLintRun]);
3787 React.useEffect(() => {
3788 if (!filesForFixRun.length) return;
3789 stylelint.lint({
3790 configFile: require.resolve('@burst/stylelint-config/pure'),
3791 files: filesForFixRun.map(f => f.absolutePath),
3792 fix: true
3793 }).then(() => // We need to lint a second time, because the autofixer disables
3794 // stylelint-disable comments. We only get the correct results if we
3795 // lint without fix: true.
3796 stylelint.lint({
3797 configFile: require.resolve('@burst/stylelint-config/pure'),
3798 files: filesForFixRun.map(f => f.absolutePath)
3799 })).then(r => setFixResults(r));
3800 }, [filesForFixRun]);
3801 const errors = [];
3802 [...(lintResults ? lintResults.results : []), ...(fixResults ? fixResults.results : [])].forEach(r => {
3803 errors.push(...[...r.parseErrors, ...r.warnings].map(e => ({
3804 linter: 'Stylelint',
3805 filename: r.source,
3806 autoFixable: false,
3807 message: e.text.replace(` (${e.line}:${e.column})`, '').replace(` (${e.rule})`, ''),
3808 rule: e.rule,
3809 sourceLocation: {
3810 start: {
3811 line: e.line,
3812 column: e.column
3813 }
3814 }
3815 })));
3816 });
3817 return {
3818 filesFixable,
3819 filesToLint: filesForFixRun.length + filesForLintRun.length,
3820 done: (!filesForLintRun.length || !!lintResults) && (!filesForFixRun.length || !!fixResults),
3821 errors
3822 };
3823}
3824
3825const lintingFailed = new Error('ERRORS');
3826class LintCommand extends Command {
3827 constructor(...args) {
3828 super(...args);
3829
3830 _defineProperty(this, "command", 'lint [files...]');
3831
3832 _defineProperty(this, "description", 'Lint files in the current git repository.');
3833
3834 _defineProperty(this, "options", [{
3835 flags: '-f, --fix',
3836 description: 'Fix linting errors automatically if possible.'
3837 }, {
3838 flags: '-v, --verbose',
3839 description: 'Show the source of every linting error.'
3840 }, {
3841 flags: '--summary',
3842 description: 'Show a list of errors and how many times they occur.'
3843 }, {
3844 flags: '--staged',
3845 description: 'Only lint staged files.'
3846 }]);
3847 }
3848
3849 async action(filesToSearch, {
3850 fix,
3851 verbose,
3852 summary,
3853 staged
3854 }) {
3855 if (!projectConfig.lintEnabled) {
3856 console.log(chalk.underline('\n\n\nThe Burst linter is not enabled for this project.\n'));
3857 console.log('Is this a new project, or are you trying to add the linter');
3858 console.log('to a project that is not yet lint-compatible? Then you can');
3859 console.log("use the Gitlab CI Template to enable the linter. If that's");
3860 console.log('not possible, you can add to the .gitlab-ci.yml:\n');
3861 console.log(chalk.grey('variables:'));
3862 console.log(chalk.grey(' BURST_LINT: enable\n'));
3863 console.log('But using the Gitlab CI Template is preferred.\n\n');
3864 console.log(chalk.bold.yellow(`If this is a project where linting was enabled before, you\nprobabily only have to ${chalk.underline('merge from master')}!`));
3865 console.log('\n\nIf you have any questions, please ask Bart.\n\n');
3866 process.exit(1);
3867 }
3868
3869 if (staged) {
3870 // eslint-disable-next-line global-require
3871 const lintStaged = require('lint-staged/src');
3872
3873 if (!filesToSearch.length) {
3874 process.chdir(repoRoot);
3875 }
3876
3877 lintStaged(console, `${__dirname}../../config/lint-staged.js`);
3878 return;
3879 }
3880
3881 const a = ink.render(React__default.createElement(Lint, {
3882 paths: filesToSearch,
3883 fix: !!fix,
3884 verbose: !!verbose,
3885 summary: !!summary,
3886 staged: !!staged
3887 }));
3888
3889 try {
3890 await a.waitUntilExit();
3891 } catch (e) {
3892 if (e.message !== 'ERRORS') throw e;
3893 process.exitCode = 1;
3894 } // @ts-ignore
3895
3896
3897 a.cleanup();
3898 }
3899
3900}
3901
3902function Lint(props) {
3903 const filePaths = useFilePaths(props.paths); // We want to exit with exit code 1 if there were no files found.
3904
3905 useExit(!!filePaths && filePaths.length === 0, lintingFailed);
3906
3907 if (!filePaths || !projectConfig.apps || !repoRoot) {
3908 return React__default.createElement(ink.Box, null, "Listing all files in this repository...");
3909 }
3910
3911 if (filePaths.length === 0) {
3912 return React__default.createElement(ink.Box, null, "We found no files.");
3913 }
3914
3915 const files = filePaths.map(path => ({
3916 path,
3917 absolutePath: `${repoRoot}/${path}`,
3918 filename: path$1.basename(path),
3919 app: projectConfig.apps.find(a => !!a.dir && path.startsWith(`${a.dir}/`)) || projectConfig.apps.find(a => !a.dir)
3920 })).filter(f => !f.app || !f.app.disableLinting);
3921 return React__default.createElement(Lint2, {
3922 files: files,
3923 verbose: props.verbose,
3924 fix: props.fix,
3925 repoRoot: repoRoot,
3926 summary: props.summary
3927 });
3928}
3929
3930function Lint2(props) {
3931 const startTime = React.useMemo(() => new Date(), []);
3932 const eslint = useEslint(props.files, props.fix);
3933 const phpcs = usePHPCS(props.files, props.fix);
3934 const stylelint = useStylelint(props.files, props.fix);
3935 const prettierFiles = React.useMemo(() => props.files.filter(f => !eslint.files.includes(f) && !phpcs.files.includes(f) && !stylelint.filesFixable.includes(f)), [eslint.files, phpcs.files, props.files, stylelint.filesFixable]);
3936 const prettier = usePrettier(prettierFiles, props.fix);
3937 const tsChecker = useTsChecker(props.files); // Build the complete array of found errors.
3938
3939 const allErrors = [...prettier.errors, ...eslint.errors, ...tsChecker.errors, ...phpcs.errors, ...stylelint.errors];
3940 const done = eslint.done && tsChecker.done && phpcs.done && prettier.done && stylelint.done;
3941 const numErrors = allErrors.length;
3942 const numAutofixed = prettier.fixed.length + eslint.filesAutoFixed + phpcs.filesFixed;
3943 const errorsAutofixable = allErrors.filter(e => e.autoFixable).length;
3944 useExit(done, allErrors.length ? lintingFailed : undefined);
3945 useTick();
3946 return React__default.createElement(React__default.Fragment, null, React__default.createElement(ink.Box, {
3947 marginTop: 1,
3948 flexDirection: "column"
3949 }, props.summary ? React__default.createElement(ErrorSummaryList, {
3950 allErrors: allErrors
3951 }) : React__default.createElement(FileErrorList, {
3952 allErrors: allErrors,
3953 repoRoot: props.repoRoot,
3954 verbose: props.verbose
3955 })), React__default.createElement(ink.Box, null, React__default.createElement(ink.Box, {
3956 width: 15
3957 }, "Git"), React__default.createElement(ink.Box, null, "Found ", React__default.createElement(ink.Color, {
3958 cyan: true
3959 }, props.files.length), " files.")), !!eslint.files.length && React__default.createElement(ink.Box, null, React__default.createElement(ink.Box, {
3960 width: 15
3961 }, "ESLint"), React__default.createElement(ink.Box, null, "Linted", ' ', React__default.createElement(NumberOfTotal, {
3962 number: eslint.reports.length,
3963 total: eslint.files.length
3964 }), ' ', "files, found ", React__default.createElement(ErrorCount, {
3965 errors: eslint.errors.length
3966 }), ".")), !!prettierFiles.length && React__default.createElement(ink.Box, null, React__default.createElement(ink.Box, {
3967 width: 15
3968 }, "Prettier"), React__default.createElement(ink.Box, null, "Linted", ' ', React__default.createElement(NumberOfTotal, {
3969 number: prettier.linted,
3970 total: prettier.filesToLint
3971 }), ' ', "files, found ", React__default.createElement(ErrorCount, {
3972 errors: prettier.filesNotCorrect.length
3973 }), ".")), !!tsChecker.files.length && React__default.createElement(ink.Box, null, React__default.createElement(ink.Box, {
3974 width: 15
3975 }, "Typescript"), tsChecker.done ? React__default.createElement(ink.Box, null, "Typechecked projects, found", ' ', React__default.createElement(ErrorCount, {
3976 errors: tsChecker.errors.length
3977 }), ".") : React__default.createElement(ink.Box, null, "Typechecking projects...", !!tsChecker.errors.length && React__default.createElement(React__default.Fragment, null, ' ', "found ", React__default.createElement(ErrorCount, {
3978 errors: tsChecker.errors.length
3979 }), " so far."))), !!phpcs.files.length && projectConfig.lintPhpEnabled && React__default.createElement(ink.Box, null, React__default.createElement(ink.Box, {
3980 width: 15
3981 }, "PHPCS"), React__default.createElement(ink.Box, null, "Linted", ' ', React__default.createElement(NumberOfTotal, {
3982 number: phpcs.filesLinted,
3983 total: phpcs.files.length
3984 }), ' ', "files", props.fix && React__default.createElement(React__default.Fragment, null, ", fixed", ' ', React__default.createElement(NumberOfTotal, {
3985 number: phpcs.filesFixed,
3986 total: phpcs.filesWithFixes
3987 }), ' ', "files"), ". Found ", React__default.createElement(ErrorCount, {
3988 errors: phpcs.errors.length
3989 }), ".")), projectConfig.lintPhpEnabled || React__default.createElement(ink.Box, null, React__default.createElement(ink.Box, {
3990 width: 15
3991 }, "PHPCS"), React__default.createElement(ink.Box, null, React__default.createElement(ink.Text, {
3992 italic: true
3993 }, "Disabled."))), !!stylelint.filesToLint && React__default.createElement(ink.Box, null, React__default.createElement(ink.Box, {
3994 width: 15
3995 }, "Stylelint"), React__default.createElement(ink.Box, null, stylelint.done ? 'Linted' : 'Linting', ' ', React__default.createElement(ink.Color, {
3996 cyan: true
3997 }, stylelint.filesToLint), " files", stylelint.done ? '.' : '...', " Found", ' ', React__default.createElement(ErrorCount, {
3998 errors: stylelint.errors.length
3999 }), ".")), projectConfig.lintStylesEnabled || React__default.createElement(ink.Box, null, React__default.createElement(ink.Box, {
4000 width: 15
4001 }, "Stylelint"), React__default.createElement(ink.Box, null, React__default.createElement(ink.Text, {
4002 italic: true
4003 }, "Disabled."))), React__default.createElement(ink.Box, null, React__default.createElement(ink.Box, {
4004 width: 15
4005 }, "Time"), React__default.createElement(ink.Box, null, Math.round((new Date().getTime() - startTime.getTime()) / 1000), "s")), React__default.createElement(ink.Box, {
4006 marginY: 1,
4007 flexDirection: "column"
4008 }, numErrors === 0 && numAutofixed === 0 && done ? React__default.createElement(ink.Text, {
4009 underline: true
4010 }, "No errors found. Perfect!") : numErrors === 0 && numAutofixed === 0 ? React__default.createElement(ink.Text, {
4011 underline: true
4012 }, "No errors found so far...") : numErrors === 0 && numAutofixed > 0 ? React__default.createElement(ink.Text, {
4013 underline: true
4014 }, "Autofixed ", numAutofixed, " file", numAutofixed === 1 ? '' : 's', done ? '' : ' so far', ", found no unfixable errors", done ? '.' : ' yet...') : numErrors > 0 && numAutofixed > 0 ? React__default.createElement(ink.Text, {
4015 underline: true
4016 }, "Autofixed ", numAutofixed, " file", numAutofixed === 1 ? '' : 's', done ? '' : ' so far', ", but also found ", allErrors.length, " error", allErrors.length === 1 ? ' ' : 's ', "that you need to fix manually.") : numErrors > 0 && numAutofixed === 0 ? React__default.createElement(ink.Text, {
4017 underline: true
4018 }, "Found ", allErrors.length, " error", allErrors.length === 1 ? '' : 's', done ? '.' : ' so far...') : null, !props.fix && errorsAutofixable > 0 && React__default.createElement(ink.Box, {
4019 marginTop: 1
4020 }, React__default.createElement(ink.Color, {
4021 grey: true
4022 }, "If you run ", React__default.createElement(ink.Color, {
4023 red: true
4024 }, "burst lint --fix"), " ", errorsAutofixable, ' ', "error", errorsAutofixable !== 1 && 's', " will be automatically fixed."))));
4025}
4026
4027function useTick() {
4028 const [, setS] = React.useState(0);
4029 React.useEffect(() => {
4030 const t = setTimeout(() => setS(se => se + 1), 1000);
4031 return () => clearTimeout(t);
4032 });
4033}
4034
4035function FileErrorList(props) {
4036 const errorsPerFile = lodash.groupBy(props.allErrors, 'filename');
4037 return React__default.createElement(React__default.Fragment, null, Object.entries(errorsPerFile).map(([file, errors], i1) => React__default.createElement(ink.Box, {
4038 marginBottom: 1,
4039 flexDirection: "column",
4040 key: file
4041 }, React__default.createElement(ink.Text, {
4042 italic: true
4043 }, file.startsWith(props.repoRoot) ? file.substr(props.repoRoot.length + 1) : file), errors.map((e, i2) => React__default.createElement(LintErrorMessage // eslint-disable-next-line react/no-array-index-key
4044 , {
4045 key: `${i1}_${i2}`,
4046 error: e,
4047 verbose: props.verbose
4048 })))));
4049}
4050
4051function ErrorSummaryList(props) {
4052 const errorsPerError = lodash.countBy(props.allErrors, e => e.rule ? `${e.linter} - ${e.rule}` : `${e.linter} - ${e.message}`);
4053 return React__default.createElement(ink.Box, {
4054 marginBottom: 2,
4055 flexDirection: "column"
4056 }, React__default.createElement(ink.Text, {
4057 italic: true
4058 }, "There are ", Object.keys(errorsPerError).length, " different types of errors."), lodash.sortBy(Object.entries(errorsPerError), ['1', '0']).map(([error, errors]) => React__default.createElement(ink.Box, {
4059 key: error
4060 }, React__default.createElement(ink.Box, {
4061 width: 6,
4062 alignItems: "flex-end"
4063 }, errors), React__default.createElement(ink.Box, {
4064 textWrap: "wrap"
4065 }, error))));
4066}
4067
4068function useFilePaths(paths) {
4069 const [filePaths, setFilePaths] = React.useState(null);
4070 React.useEffect(() => {
4071 getListOfRepoFiles(paths).then(f => setFilePaths(f));
4072 }, [paths]);
4073 return filePaths;
4074}
4075
4076function LintErrorMessage({
4077 error,
4078 verbose
4079}) {
4080 return React__default.createElement(React__default.Fragment, null, React__default.createElement(ink.Box, null, React__default.createElement(ink.Box, {
4081 width: 3
4082 }, error.autoFixable ? '✨' : ''), React__default.createElement(ink.Box, {
4083 width: 10
4084 }, error.linter), React__default.createElement(ink.Box, {
4085 width: 10
4086 }, error.sourceLocation ? React__default.createElement(ink.Color, {
4087 grey: true,
4088 blue: true
4089 }, error.sourceLocation.start.line, ":", error.sourceLocation.start.column) : null), React__default.createElement(ink.Box, {
4090 textWrap: "wrap"
4091 }, error.message, " ", !!error.rule && React__default.createElement(ink.Color, {
4092 grey: true
4093 }, error.rule))), verbose && error.rawlines && error.sourceLocation && codeFrame.codeFrameColumns(error.rawlines, error.sourceLocation));
4094}
4095
4096function ErrorCount(props) {
4097 return React__default.createElement(React__default.Fragment, null, React__default.createElement(ink.Color, {
4098 red: !!props.errors,
4099 cyan: !props.errors
4100 }, props.errors), ' ', "error", props.errors !== 1 ? 's' : '');
4101}
4102
4103function NumberOfTotal(props) {
4104 return React__default.createElement(React__default.Fragment, null, React__default.createElement(ink.Color, {
4105 cyan: true
4106 }, props.number), props.number !== props.total && React__default.createElement(React__default.Fragment, null, ' ', "/ ", React__default.createElement(ink.Color, {
4107 cyan: true
4108 }, props.total)));
4109}
4110
4111const {
4112 SLACK_TOKEN,
4113 GITLAB_USER_NAME
4114} = process.env;
4115const token = SLACK_TOKEN;
4116const web = new client.WebClient(token);
4117async function sendStartDeploymentMessage(project, environment) {
4118 if (!token) return;
4119 const attachment = {
4120 color: '#ffff00',
4121 fallback: `Deploy ${project.getDisplayName()}`,
4122 title: `Deploy ${project.getDisplayName()}`,
4123 title_link: project.getLink(),
4124 text: GITLAB_USER_NAME ? `The Gitlab user ${GITLAB_USER_NAME} triggered a deploy.\n` : 'A deploy was triggered.\n',
4125 fields: [{
4126 title: 'Deploy start',
4127 value: new Date().toTimeString(),
4128 short: true
4129 }, {
4130 title: 'Deploy done',
4131 value: 'Not yet...',
4132 short: true
4133 }, {
4134 title: 'URLs',
4135 value: environment.getUrls().join('\n'),
4136 short: false
4137 }]
4138 };
4139 const message = await web.chat.postMessage({
4140 channel: '#deploys',
4141 text: '',
4142 attachments: [attachment]
4143 });
4144 return async (successful, text) => {
4145 attachment.color = successful ? '#00ff00' : '#ff0000';
4146 attachment.fields[1].value = new Date().toTimeString();
4147 if (text) attachment.text += `${text}\n`;
4148 await web.chat.update({
4149 channel: message.channel,
4150 text: '',
4151 attachments: [attachment],
4152 ts: message.ts
4153 });
4154 };
4155}
4156
4157const isCI$3 = require('is-ci');
4158
4159class DeployCommand extends Command {
4160 constructor(...args) {
4161 super(...args);
4162
4163 _defineProperty(this, "command", 'deploy');
4164
4165 _defineProperty(this, "description", 'Deploy one or more applications.');
4166
4167 _defineProperty(this, "options", [{
4168 flags: '--all',
4169 description: "Deprecated. Doesn't do anything."
4170 }, {
4171 flags: '--production',
4172 description: 'Deploy to the production environment.'
4173 }, {
4174 flags: '--same-branch',
4175 description: "Deprecated. Doesn't do anything."
4176 }]);
4177 }
4178
4179 async action(command) {
4180 /**
4181 * First, we need to know which apps we need to deploy.
4182 */
4183 const allHostingProvidersPerAppCombination = await getProjectInfo().getHostingProvidersByAppCominations();
4184
4185 if (allHostingProvidersPerAppCombination.length === 0) {
4186 console.error('There are no apps configured for deployment.');
4187 return process.exit(1);
4188 }
4189
4190 let hostingProvidersPerAppCombination = allHostingProvidersPerAppCombination;
4191 /**
4192 * If there is more then one app, we need to ask the user which app they want to
4193 * deploy. If this is in the CI, we always want to deploy all the apps.
4194 */
4195
4196 if (!isCI$3 && allHostingProvidersPerAppCombination.length >= 2) {
4197 const answers = await inquirer.prompt([{
4198 type: 'list',
4199 name: 'h',
4200 message: 'What apps do you want to deploy?',
4201 choices: [...allHostingProvidersPerAppCombination.map(h => ({
4202 name: `Deploy ${h.apps.map(a => a.name).join(' + ')}`,
4203 value: [h]
4204 })), new inquirer.Separator(), {
4205 name: 'All of the above',
4206 value: hostingProvidersPerAppCombination
4207 }]
4208 }]);
4209 hostingProvidersPerAppCombination = answers.h;
4210 }
4211 /**
4212 * Now that we know which apps to deploy, we need to know what environments we
4213 * need to deploy to.
4214 */
4215
4216
4217 const environmentsToDeploy = [];
4218 const branch = await getCurrentBranch(); // If the --production arg was passed, we prefer to deploy to production.
4219 // If the branch is 'master', we prefer to deploy to staging.
4220
4221 const suggestedTarget = command.production ? DeployTarget.Production : branch === 'master' ? DeployTarget.Staging : undefined; // If neither --production or 'master', we prefer to deploy to an environment with
4222 // the same name as the current branch.
4223
4224 const suggestedName = suggestedTarget ? undefined : branch; // Now, we get the environments for all hosting providers.
4225
4226 for (const appCombi of hostingProvidersPerAppCombination) {
4227 const environments = lodash.flatten((await Promise.all(appCombi.hostingProviders.map(async provider => (await provider.getPossibleEnvs({
4228 suggestedTarget,
4229 suggestedName
4230 })).map(environment => ({
4231 provider,
4232 environment,
4233 apps: appCombi.apps
4234 })))))); // When running in the CI, we just always deploy to the suggested environments.
4235 // When interaction is possible, we ask the user what environments to deploy to.
4236
4237 if (isCI$3) {
4238 environmentsToDeploy.push(...environments.filter(e => e.environment.isSuggested()));
4239 } else {
4240 const {
4241 e
4242 } = await inquirer.prompt([{
4243 type: 'list',
4244 name: 'e',
4245 message: `Where do you want to deploy ${appCombi.apps.map(awdt => awdt.name).join(' + ')} to?`,
4246 choices: [// We first want to show suggested environments, then normal environments
4247 ...lodash.sortBy(environments, ewa => ewa.environment.isSuggested() ? 0 : ewa.environment.isActive() ? 1 : 2).map(ewa => ({
4248 // If it's a suggested environment, we show a rocket emoji.
4249 name: (ewa.environment.isSuggested() ? '🚀 ' : ' ') + getEnvironmentDisplayName(ewa),
4250 value: ewa
4251 }))],
4252 pageSize: 30
4253 }]);
4254 environmentsToDeploy.push(e);
4255 }
4256 } // If there are no suggestions, die.
4257
4258
4259 if (environmentsToDeploy.length === 0) {
4260 console.error('There are no environments to deploy to.');
4261 return process.exit(1);
4262 }
4263 /**
4264 * Ask for confirmation before deploying. Only ask for real confirmation when
4265 * interaction is possible. On the CI, we still show what we're about to do.
4266 */
4267
4268
4269 console.log("You're about to perform the following actions:");
4270 environmentsToDeploy.forEach(e => console.log(` - ${getEnvironmentDisplayName(e)}`));
4271
4272 if (!isCI$3) {
4273 const {
4274 sure
4275 } = await inquirer.prompt([{
4276 type: 'confirm',
4277 name: 'sure',
4278 message: `Are you sure?`
4279 }]);
4280 if (!sure) return process.exit(1);
4281 }
4282 /**
4283 * Now, deploy!
4284 */
4285
4286
4287 for (const env of environmentsToDeploy) {
4288 // If there are multiple, different hosting provider configurations of the same
4289 // hosting provider we need to only deploy a subfolder.
4290 const hostingProvidersOfSameType = allHostingProvidersPerAppCombination.filter(hppac => hppac.hostingProviders.find(hp => hp.constructor === env.provider.constructor));
4291
4292 if (hostingProvidersOfSameType.length > 1 && env.apps.length !== 1) {
4293 console.error('Impossible to have multiple apps deployed when more then 1 hosting provider config of that type available.');
4294 process.exit(1);
4295 }
4296
4297 const deployOnlySubdirectory = hostingProvidersOfSameType.length > 1 ? env.apps[0].dir : undefined; // Send a message to Slack when deploying to production.
4298
4299 const done = env.environment.getDeployTarget() === DeployTarget.Production ? await sendStartDeploymentMessage(env.provider, env.environment).catch(e => console.error('Slack fail!', e)) : null;
4300
4301 try {
4302 await env.environment.deploy({
4303 deployOnlySubdirectory
4304 });
4305 } catch (e) {
4306 // Notify Slack that the deployment failed.
4307 if (done) {
4308 await done(false, e.message).catch(console.error);
4309 }
4310
4311 throw e;
4312 } // Notify Slack that the deployment is completed.
4313
4314
4315 if (done) {
4316 await done(true).catch(e => console.error('Slack fail!', e));
4317 }
4318 }
4319 }
4320
4321}
4322
4323function getEnvironmentDisplayName(e) {
4324 const displayName = e.apps.map(a => `Deploy ${chalk.magenta(a.name)} to ${chalk.cyan(e.environment.getDisplayName())}`).join(' and ') + chalk.grey(` - ${e.provider.getDisplayName()}`);
4325 if (e.environment.isActive()) return displayName;
4326 return chalk.dim(displayName) + chalk.grey(' (inactive)');
4327}
4328
4329// `IsArray` abstract operation
4330// https://tc39.github.io/ecma262/#sec-isarray
4331var isArray = Array.isArray || function isArray(arg) {
4332 return classofRaw(arg) == 'Array';
4333};
4334
4335// `FlattenIntoArray` abstract operation
4336// https://tc39.github.io/proposal-flatMap/#sec-FlattenIntoArray
4337var flattenIntoArray = function (target, original, source, sourceLen, start, depth, mapper, thisArg) {
4338 var targetIndex = start;
4339 var sourceIndex = 0;
4340 var mapFn = mapper ? bindContext(mapper, thisArg, 3) : false;
4341 var element;
4342
4343 while (sourceIndex < sourceLen) {
4344 if (sourceIndex in source) {
4345 element = mapFn ? mapFn(source[sourceIndex], sourceIndex, original) : source[sourceIndex];
4346
4347 if (depth > 0 && isArray(element)) {
4348 targetIndex = flattenIntoArray(target, original, element, toLength(element.length), targetIndex, depth - 1) - 1;
4349 } else {
4350 if (targetIndex >= 0x1FFFFFFFFFFFFF) throw TypeError('Exceed the acceptable array length');
4351 target[targetIndex] = element;
4352 }
4353
4354 targetIndex++;
4355 }
4356 sourceIndex++;
4357 }
4358 return targetIndex;
4359};
4360
4361var flattenIntoArray_1 = flattenIntoArray;
4362
4363var SPECIES$4 = wellKnownSymbol('species');
4364
4365// `ArraySpeciesCreate` abstract operation
4366// https://tc39.github.io/ecma262/#sec-arrayspeciescreate
4367var arraySpeciesCreate = function (originalArray, length) {
4368 var C;
4369 if (isArray(originalArray)) {
4370 C = originalArray.constructor;
4371 // cross-realm fallback
4372 if (typeof C == 'function' && (C === Array || isArray(C.prototype))) C = undefined;
4373 else if (isObject(C)) {
4374 C = C[SPECIES$4];
4375 if (C === null) C = undefined;
4376 }
4377 } return new (C === undefined ? Array : C)(length === 0 ? 0 : length);
4378};
4379
4380// `Array.prototype.flat` method
4381// https://github.com/tc39/proposal-flatMap
4382_export({ target: 'Array', proto: true }, {
4383 flat: function flat(/* depthArg = 1 */) {
4384 var depthArg = arguments[0];
4385 var O = toObject(this);
4386 var sourceLen = toLength(O.length);
4387 var A = arraySpeciesCreate(O, 0);
4388 A.length = flattenIntoArray_1(A, O, O, sourceLen, 0, depthArg === undefined ? 1 : toInteger(depthArg));
4389 return A;
4390 }
4391});
4392
4393// this method was added to unscopables after implementation
4394// in popular engines, so it's moved to a separate module
4395addToUnscopables('flat');
4396
4397const prettierConfig = require('@burst/prettier-config');
4398
4399const write = util.promisify(fs__default.writeFile);
4400const read = util.promisify(fs__default.readFile);
4401const unlink = util.promisify(fs__default.unlink);
4402const mkdir = util.promisify(fs__default.mkdir);
4403const access = util.promisify(fs__default.access);
4404const parseXml = util.promisify(new xml2js.Parser().parseString);
4405const buildXml = new xml2js.Builder();
4406const {
4407 apps
4408} = projectConfig;
4409class ScaffoldCommand extends Command {
4410 constructor(...args) {
4411 super(...args);
4412
4413 _defineProperty(this, "command", 'scaffold');
4414
4415 _defineProperty(this, "description", 'Scaffolds various configuration files into the root of the git repository.');
4416
4417 _defineProperty(this, "action", async () => {
4418 // Delete all files that were created in previous versions of the scaffold
4419 // command. They can conflict with the other settings written to the file
4420 // system.
4421 const filesToDelete = ['.eslintrc.yaml', '.prettierrc.yaml', 'tslint.yaml'];
4422 await Promise.all(filesToDelete.map(async filename => {
4423 if (await this.exists(`${repoRoot}/${filename}`)) {
4424 await unlink(`${repoRoot}/${filename}`);
4425 console.log(`💣 Deleted ${filename} because it isn't used anymore.`);
4426 }
4427 }));
4428 const composerHelperDir = path$1__default.join(__dirname, '../composer-helper');
4429 const rootApp = apps.find(a => a.dir === undefined);
4430 const rootRuleset = rootApp ? rootApp.type : 'other';
4431 const paths = {};
4432 appTypes.filter(t => t !== rootRuleset).forEach(t => {
4433 paths[t] = apps.filter(a => a.type === t).map(a => [a.path, `phpcs_temp.tmp/${a.dir}`]).flat();
4434 });
4435 const allNotOtherPaths = Object.values(paths).flat();
4436 const phpcsRuleset = ['<?xml version="1.0"?>', '<ruleset name="Auto-generated ruleset for this project by the Burst CLI" namespace="Burst">', ` <rule ref="${composerHelperDir}/${rootRuleset}_ruleset.xml">`, ...allNotOtherPaths.map(p => ` <exclude-pattern>${p}</exclude-pattern>`), ` </rule>`, ...Object.entries(paths).map(([type, ps]) => ps.length ? ` <rule ref="${composerHelperDir}/${type}_ruleset.xml">\n${ps.map(p => ` <include-pattern>${p}</include-pattern>\n`).join('')} </rule>` : ` <!-- No ${type} apps -->`), '</ruleset>'];
4437 await write(`${repoRoot}/phpcs.xml`, phpcsRuleset.join('\n'));
4438 console.log('🔥 Written to phpcs.xml');
4439 const eslintModuleFolder = `${require.resolve('eslint').split('/node_modules/eslint/')[0]}/node_modules`;
4440 const eslintFolder = `${eslintModuleFolder}/eslint`;
4441
4442 if (!(await this.exists(`${repoRoot}/.idea`))) {
4443 console.log("⛔ The .idea folder doesn't exist, so IntelliJ won't be configured.");
4444 } else {
4445 // PHPStorm reads from a eslint.xml file. Because it only contains eslint
4446 if (!(await this.exists(`${repoRoot}/.idea/jsLinters`))) {
4447 await mkdir(`${repoRoot}/.idea/jsLinters`);
4448 console.log('🔥 Created .idea/jsLinters');
4449 }
4450
4451 await write(`${repoRoot}/.idea/jsLinters/eslint.xml`, `<?xml version="1.0" encoding="UTF-8"?>
4452 <project version="4">
4453 <component name="EslintConfiguration">
4454 <custom-configuration-file used="true" path="${require.resolve('@burst/eslint-config')}" />
4455 </component>
4456 </project>
4457 `);
4458 console.log('🔥 Written to .idea/jsLinters/eslint.xml');
4459 const phpXmlPath = `${repoRoot}/.idea/php.xml`;
4460
4461 if (!(await this.exists(phpXmlPath))) {
4462 await write(`${repoRoot}/.idea/php.xml`, `<?xml version="1.0" encoding="UTF-8"?>
4463 <project version="4">
4464 <component name="PhpCodeSniffer">
4465 <phpcs_settings>
4466 <PhpCSConfiguration standards="Drupal;DrupalPractice;MySource;PEAR;PHPCS;PSR1;PSR2;Squiz;Zend" tool_path="${composerHelperDir}/vendor/bin/phpcs" timeout="30000" />
4467 </phpcs_settings>
4468 </component>
4469 </project>
4470 `);
4471 console.log('🔥 Created .idea/php.xml');
4472 } else {
4473 try {
4474 const phpXml = await parseXml((await read(phpXmlPath)));
4475 phpXml.project.component = phpXml.project.component ? phpXml.project.component.filter(c => c.$.name !== 'PhpCodeSniffer') : [];
4476 phpXml.project.component.push({
4477 $: {
4478 name: 'PhpCodeSniffer'
4479 },
4480 phpcs_settings: [{
4481 PhpCSConfiguration: [{
4482 $: {
4483 standards: 'Drupal;DrupalPractice;MySource;PEAR;PHPCS;PSR1;PSR2;Squiz;Zend',
4484 tool_path: `${composerHelperDir}/vendor/bin/phpcs`,
4485 beautifier_path: `${composerHelperDir}/vendor/bin/phpcbf`,
4486 timeout: 30000
4487 }
4488 }]
4489 }]
4490 });
4491 await write(phpXmlPath, buildXml.buildObject(phpXml));
4492 console.log('🔥 Adjusted .idea/php.xml');
4493 } catch (e) {
4494 console.error(e);
4495 console.error();
4496 console.log('⛔ Writing to .idea/php.xml not possible. Please configure the following phpcs package:');
4497 console.error(` ${composerHelperDir}/vendor/bin/phpcs`);
4498 }
4499 }
4500
4501 try {
4502 const workspacePath = `${repoRoot}/.idea/workspace.xml`;
4503 const workspaceXml = await parseXml((await read(workspacePath)));
4504 const properties = workspaceXml.project.component.find(c => c.$.name === 'PropertiesComponent').property;
4505 Object.entries({
4506 'node.js.detected.package.eslint': 'true',
4507 'node.js.path.for.package.eslint': 'project',
4508 'node.js.selected.package.eslint': eslintFolder,
4509 'node.js.detected.package.standard': 'true',
4510 'node.js.path.for.package.standard': 'project',
4511 'node.js.selected.package.standard': eslintFolder
4512 }).forEach(([name, value]) => {
4513 const property = properties.find(p => p.$.name === name);
4514 if (property) property.$.value = value;else properties.push({
4515 $: {
4516 name,
4517 value
4518 }
4519 });
4520 });
4521 await write(workspacePath, buildXml.buildObject(workspaceXml));
4522 console.log('🔥 Written to .idea/workspace.xml');
4523 } catch (e) {
4524 console.error(e);
4525 console.error();
4526 console.log('⛔ Writing to .idea/workspace.xml not possible. Please configure the following eslint package:');
4527 console.log(` ${eslintFolder}`);
4528 }
4529
4530 try {
4531 const inspectionPath = `${repoRoot}/.idea/inspectionProfiles/Project_Default.xml`;
4532
4533 if (!(await this.exists(`${repoRoot}/.idea/inspectionProfiles`))) {
4534 await mkdir(`${repoRoot}/.idea/inspectionProfiles`);
4535 console.log('🔥 Created .idea/inspectionProfiles');
4536 }
4537
4538 if (!(await this.exists(inspectionPath))) {
4539 await write(inspectionPath, `<component name="InspectionProjectProfileManager">
4540 <profile version="1.0">
4541 <option name="myName" value="Project Default" />
4542 <inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
4543 </profile>
4544 </component>`);
4545 console.log('🔥 Created .idea/inspectionProfiles/Project_Default.xml');
4546 } else {
4547 const inspectionXml = await parseXml((await read(inspectionPath)));
4548 const profile = inspectionXml.component.profile[0];
4549
4550 if (!profile.inspection_tool) {
4551 profile.inspection_tool = [];
4552 }
4553
4554 profile.inspection_tool = profile.inspection_tool.filter(i => i.$.class !== 'Eslint' && i.$.class !== 'PhpCSValidationInspection');
4555 profile.inspection_tool.push({
4556 $: {
4557 class: 'Eslint',
4558 enabled: true,
4559 level: 'WARNING',
4560 enabled_by_default: 'true'
4561 }
4562 });
4563 profile.inspection_tool.push({
4564 $: {
4565 class: 'PhpCSValidationInspection',
4566 enabled: true,
4567 level: 'WARNING',
4568 enabled_by_default: 'true'
4569 },
4570 option: [{
4571 $: {
4572 name: 'CODING_STANDARD',
4573 value: 'Custom'
4574 }
4575 }, {
4576 $: {
4577 name: 'CUSTOM_RULESET_PATH',
4578 value: `${repoRoot}/phpcs.xml`
4579 }
4580 }, {
4581 $: {
4582 name: 'EXTENSIONS',
4583 value: 'php'
4584 }
4585 }]
4586 });
4587 await write(inspectionPath, buildXml.buildObject(inspectionXml));
4588 console.log('🔥 Adjusted .idea/inspectionProfiles/Project_Default.xml');
4589 }
4590 } catch (e) {
4591 console.error(e);
4592 console.error();
4593 console.log('⛔ Writing to .idea/inspectionProfiles/Project_Default.xml not possible. You need to enable eslint in the project settings yourself.');
4594 }
4595 } // VSCode reads its settings from .vscode/settings.json. We write to this
4596 // file to configure VSCode to automatically fix all linting errors.
4597
4598
4599 const vscode = this.json(_objectSpread({
4600 // Prettier uses 80 as the max line length, so we want to show that in the
4601 // editor too.
4602 'editor.rulers': [80],
4603 // This adds eslint configs to reflect the burst lint command.
4604 'eslint.autoFixOnSave': true,
4605 'eslint.validate': ['javascript', 'javascriptreact', {
4606 language: 'typescript',
4607 autoFix: true
4608 }, {
4609 language: 'typescriptreact',
4610 autoFix: true
4611 }],
4612 'eslint.nodePath': `${eslintModuleFolder}/`,
4613 'eslint.options': {
4614 configFile: require.resolve('@burst/eslint-config'),
4615 useEslintRc: false,
4616 reportUnusedDisaleDirectives: true
4617 }
4618 }, Object.entries(prettierConfig).reduce((c, [k, v]) => _objectSpread({}, c, {
4619 [`prettier.${k}`]: v
4620 }), {}), {
4621 // We want to run Prettier every time someone saves a file.
4622 'editor.formatOnSave': true,
4623 // Because ESLint already fixes all JS and TS files, we need to disable
4624 // prettier on these file types.
4625 '[javascript]': {
4626 'editor.formatOnSave': false
4627 },
4628 '[javascriptreact]': {
4629 'editor.formatOnSave': false
4630 },
4631 '[typescript]': {
4632 'editor.formatOnSave': false
4633 },
4634 '[typescriptreact]': {
4635 'editor.formatOnSave': false
4636 },
4637 'phpSniffer.executablesFolder': `${composerHelperDir}/vendor/bin/`,
4638 'phpSniffer.standard': `${repoRoot}/phpcs.xml`,
4639 'phpSniffer.run': 'onType',
4640 'phpcs.executablePath': `${composerHelperDir}/vendor/bin/phpcs`,
4641 'phpcs.standard': `${repoRoot}/phpcs.xml`,
4642 'css.validate': false,
4643 'stylelint.config': {
4644 extends: require.resolve('@burst/stylelint-config')
4645 }
4646 })).trim().split('\n').slice(1, -1); // Create .vscode/settings.json if it doesn't exist yet.
4647
4648 if (!(await this.exists(`${repoRoot}/.vscode`))) {
4649 await mkdir(`${repoRoot}/.vscode`);
4650 console.log('🔥 Created .vscode');
4651 }
4652
4653 if (!(await this.exists(`${repoRoot}/.vscode/settings.json`))) {
4654 await write(`${repoRoot}/.vscode/settings.json`, `{\n}`);
4655 console.log('🔥 Created .vscode/settings.json');
4656 }
4657
4658 const vscodeFile = (await read(`${repoRoot}/.vscode/settings.json`, {
4659 encoding: 'utf8'
4660 })).trim().split('\n');
4661 const startScaffoldL = ' // @start-burst-cli-scaffold';
4662 const endScaffoldL = ' // @end-burst-cli-scaffold';
4663 const startScaffoldI = vscodeFile.findIndex(l => l.trim() === startScaffoldL.trim());
4664 const endScaffoldI = vscodeFile.findIndex(l => l.trim() === endScaffoldL.trim());
4665 const newVscodeFile = startScaffoldI !== -1 && endScaffoldI !== -1 ? [// Only replace the parts between the start and end scaffold lines.
4666 ...vscodeFile.slice(0, startScaffoldI + 1), ...vscode, ...vscodeFile.slice(endScaffoldI), ''] : [// Always start with our own settings.
4667 '{', startScaffoldL, ...vscode, endScaffoldL, // Then output the original contents, but without the brackets.
4668 ...vscodeFile.slice(1, -1), '}', ''];
4669 await write(`${repoRoot}/.vscode/settings.json`, newVscodeFile.join('\n'));
4670 console.log('🔥 Written to .vscode/settings.json'); // Write to the .gitignore file.
4671
4672 const gitignoreLines = ['# @start-burst-cli-gitignore', '', `# DON'T ADD ANY RULES BEFORE THIS BLOCK.`, `# These rules are automatically generated by the 'burst scaffold' command.`, '# Add your own rules after this block, or they will be overwritten.', '', '.vscode', '.idea', 'phpcs.xml', '', '# YOU CAN ADD RULES AFTER THE NEXT LINE.', '# @end-burst-cli-gitignore'];
4673 const giS = gitignoreLines[0];
4674 const giE = gitignoreLines[gitignoreLines.length - 1];
4675 const gitignore = await read(`${repoRoot}/.gitignore`, {
4676 encoding: 'utf8'
4677 });
4678
4679 if (gitignore.startsWith(giS)) {
4680 await write(`${repoRoot}/.gitignore`, `${gitignoreLines.join('\n')}${gitignore.split(giE, 2)[1]}`);
4681 console.log('🔥 Adjusted .gitignore rules');
4682 } else {
4683 await write(`${repoRoot}/.gitignore`, `${gitignoreLines.join('\n')}\n\n${gitignore}`);
4684 console.log('🔥 Added new .gitignore rules');
4685 }
4686 });
4687 }
4688
4689 json(data) {
4690 return JSON.stringify(data, null, 2);
4691 }
4692
4693 async exists(somePath) {
4694 return access(somePath).then(() => true).catch(() => false);
4695 }
4696
4697}
4698
4699class InstallCommand extends Command {
4700 constructor(...args) {
4701 super(...args);
4702
4703 _defineProperty(this, "command", 'install');
4704
4705 _defineProperty(this, "description", 'Installs all dependencies of a repository.');
4706
4707 _defineProperty(this, "action", async () => {
4708 // With these parameters, the CI job can be parallized. This means that in
4709 // this script, we only have to execute a part of the installations.
4710 const index = parseInt(process.env.CI_NODE_INDEX || '0', 10) - 1;
4711 const total = parseInt(process.env.CI_NODE_TOTAL || '1', 10); // Get all package manager files.
4712
4713 const lockfiles = await getListOfRepoFiles(['package-lock.json', '*/package-lock.json', 'yarn.lock', '*/yarn.lock', 'composer.lock', '*/composer.lock'], true); // Take the lockfiles we're going to install this time.
4714 // Let's take this example:
4715 // - lockfiles.length = 8
4716 // - index = 2 (shows up as 3/5)
4717 // - total = 5
4718 // That means that we want to execute the install of the third and the
4719 // eighth lockfile. The following formula does that:
4720
4721 const lockfilesToInstall = lockfiles.filter(({}, i) => (i - index) % total === 0);
4722
4723 if (lockfilesToInstall.length === 0) {
4724 console.log("This job doesn't do anything.");
4725 console.log("That's completely fine, and you don't have to change anything about that.");
4726
4727 if (lockfiles.length > 0) {
4728 console.log(`Please look at the first ${lockfiles.length !== 1 ? `${lockfiles.length} jobs` : 'job'}.`);
4729 }
4730
4731 return;
4732 }
4733
4734 console.log('===================================');
4735 console.log('INSTALLING THE FOLLOWING LOCKFILES:\n');
4736 lockfilesToInstall.forEach(l => console.log(l));
4737 console.log('===================================\n\n');
4738 const root = await getRepoRoot(); // eslint-disable-next-line no-restricted-syntax
4739
4740 for (const lockfile of lockfilesToInstall) {
4741 const absolutePath = `${root}/${lockfile}`;
4742 console.log('===================================');
4743 console.log('Starting installation of:');
4744 console.log(absolutePath);
4745 console.log('===================================\n');
4746
4747 if (absolutePath.endsWith('/package-lock.json')) {
4748 await exec('npm install', absolutePath);
4749 } else if (absolutePath.endsWith('/yarn.lock')) {
4750 // Make sure that there is not a package-lock.json file in the same
4751 // directory.
4752 if (lockfiles.includes(lockfile.replace('yarn.lock', 'package-lock.json'))) {
4753 console.log('There is both a yarn.lock and package-lock.json in the same folder.');
4754 console.log('Please delete one of them.');
4755 process.exit(1);
4756 }
4757
4758 await exec('yarn', absolutePath);
4759 } else if (absolutePath.endsWith('/composer.lock')) {
4760 await exec('composer validate', absolutePath);
4761 await exec('composer install --no-interaction', absolutePath);
4762 } else {
4763 console.log('Unexpected file.');
4764 process.exit(1);
4765 }
4766 }
4767
4768 const {
4769 stdout: status
4770 } = await execa('git', ['status', '--porcelain']);
4771
4772 if (status) {
4773 console.log("\n\nAfter installations, some files were changed. That shouldn't happen.");
4774 console.log("It's about these files:");
4775 console.log(status);
4776 process.exit(1);
4777 }
4778 });
4779 }
4780
4781}
4782
4783function exec(cmd, path) {
4784 console.log(`\n\n$ ${cmd}\n\n`);
4785 const [bin, ...args] = cmd.split(' ');
4786 return execa(bin, args, {
4787 cwd: path$1.dirname(path),
4788 stdio: 'inherit',
4789 preferLocal: false,
4790 env: {
4791 NODE_ENV: 'development'
4792 }
4793 });
4794}
4795
4796const rimraf = util.promisify(rimrafWithCallback);
4797const stagedFiles = util.promisify(stagedFilesWithCallback);
4798const read$1 = util.promisify(fs.readFile);
4799const write$1 = util.promisify(fs.writeFile);
4800const append = util.promisify(fs.appendFile); // Always run Composer commands without memory limit.
4801
4802process.env.COMPOSER_MEMORY_LIMIT = '-1';
4803class UpdateDrupalCommand extends Command {
4804 constructor(...args) {
4805 super(...args);
4806
4807 _defineProperty(this, "command", 'update-drupal');
4808
4809 _defineProperty(this, "description", 'Updates a Drupal project to the latest versions of all modules');
4810
4811 _defineProperty(this, "unstageFiles", []);
4812
4813 _defineProperty(this, "options", [{
4814 flags: '--no-db',
4815 description: 'Do not download a fresh database and import it.'
4816 }]);
4817
4818 _defineProperty(this, "action", async ({
4819 db
4820 }) => {
4821 const apps = projectConfig.apps.filter(a => a.type === 'drupal');
4822
4823 if (!apps.length) {
4824 console.log('There were no Drupal apps found in the burst.yaml file.');
4825 }
4826
4827 for (const app of apps) {
4828 // We change the working directory to the directory of this app. This
4829 // way, all commands executed will be automatically executed in this
4830 // directory.
4831 process.chdir(app.path); // Get the Platform.sh project ID.
4832
4833 const platform = app.options && isObject$1(app.options.hosting) && app.options.hosting.type === 'platform' && typeof app.options.hosting.id === 'string' && app.options.hosting.id;
4834
4835 if (!platform) {
4836 console.log(`The Drupal app ${app.name} doesn't have a Platform hosting configured in the burst.yaml file.`);
4837 continue;
4838 } // Get the name of this Drupal app in Platform.
4839
4840
4841 const platformApp = jsYaml.safeLoad((await read$1(`${app.path}/.platform.app.yaml`, 'utf8'))).name;
4842
4843 if (typeof platformApp !== 'string') {
4844 throw new Error("Platform app yaml doesn't contain a valid name.");
4845 }
4846
4847 console.log(`
4848
4849 UPDATING DRUPAL
4850
4851 Path: ${app.path}
4852 Platform project: ${platform}
4853 Platform app name: ${platformApp}
4854
4855 `); // Unstage all changes, start with a clean slate. This is only for local stuff, in
4856 // Gitlab CI the slate should always be clean.
4857
4858 await execa.command('git reset');
4859 await this.cleanComposer(); // There are some best practices that we want to have in every composer.json file.
4860
4861 await this.applyComposerConfig();
4862 await this.commit('build(drupal): change composer config', 'composer.json composer.lock'); // Now, install the whole site with Composer!
4863
4864 await this.cleanComposer();
4865 await this.logPromise('composer install', this.composer('install'));
4866 await this.lint(); // At this phase, there should be nothing to commit. But if there is, it should be
4867 // in git. Probabily some scaffolded files that aren't committed.
4868
4869 await this.commit('build(drupal): add missing files');
4870 const devtool = process.env.MYSQL_DATABASE ? null : (await execa.command('ddev describe').catch(() => false)) ? 'ddev' : 'lando'; // We need to start the Lando containers, if we're not in the CI.
4871
4872 if (devtool) {
4873 await this.logPromise(`${devtool} start`, execa.command(`${devtool} start`));
4874 } else {
4875 // If we are in the CI, we need to add the database connection to the
4876 // settings.php file.
4877 const {
4878 all: statusString
4879 } = await this.drush(devtool, 'status --format=json');
4880 const status = JSON.parse(statusString);
4881 const settingsPath = `${status.root}/${status.site}/settings.php`;
4882 await append(settingsPath, `
4883 $databases['default']['default'] = [
4884 'database' => getenv('MYSQL_DATABASE'),
4885 'username' => 'root',
4886 'password' => getenv('MYSQL_ROOT_PASSWORD'),
4887 'host' => 'mariadb',
4888 'port' => getenv('MARIADB_PORT_3306_TCP_PORT'),
4889 'driver' => 'mysql',
4890 'prefix' => '',
4891 'collation' => 'utf8mb4_general_ci',
4892 ];
4893 `);
4894 this.unstageFiles.push(settingsPath);
4895 } // For debugging purposes, show the status.
4896
4897
4898 await this.logPromise('Logging result of "drush status"', this.drush(devtool, 'status', true));
4899
4900 if (db) {
4901 // We need a database! Get the latest datbase from Platform.
4902 await this.logPromise('database download', execa.command(`platform db:dump --project ${platform} --environment master --directory . --file drupal--dump.sql --app ${platformApp} --yes`)); // Import the database, and remove the datbase from the file system. This
4903 // way, it's not accidentely committed.
4904
4905 await this.importDatabase(devtool);
4906 await rimraf(`${process.cwd()}/drupal--dump.sql`);
4907 } // We re-export the config. This shouldn't present any changes, but if it does, we
4908 // need to commit that first.
4909
4910
4911 await this.clearCache(devtool);
4912
4913 try {
4914 await this.exportConfig(devtool); // Exported files shouldn't be linted by the burst linter, but let's just be safe here ;-)
4915
4916 await this.lint();
4917 await this.commit('fix(drupal): update config with latest production data');
4918 } catch (e) {
4919 console.log(e.all || e);
4920 console.log(`${chalk.bgRed('ERROR')} Re-exporting config failed. Let's just ignore this for now.`); // Reset the config folder to the latest git version.
4921
4922 await execa.command('git checkout -- config');
4923 }
4924
4925 await this.addBurstDrupalDistribution(); // Now, we're going to do the actual updating.
4926
4927 await this.logPromise('updating drupal modules with composer', this.composer('update burst/drupal-distribution drupal/* --with-all-dependencies'));
4928 await this.clearCache(devtool);
4929 await this.accountForSlowDocker(devtool, () => this.logPromise('update database', this.drush(devtool, 'updb')));
4930
4931 try {
4932 await this.exportConfig(devtool);
4933 } catch (_unused) {
4934 await this.clearCache(devtool);
4935 await this.exportConfig(devtool);
4936 }
4937
4938 await this.lint();
4939 await this.commit('fix(drupal): update all drupal-related packages');
4940
4941 if (devtool) {
4942 await this.logPromise(`${devtool} stop`, execa.command(`${devtool} stop`));
4943 }
4944 }
4945
4946 console.log('Done with all sites.');
4947 });
4948
4949 _defineProperty(this, "log", {
4950 start(label) {
4951 console.time(label);
4952 console.log(chalk.bgYellow('START'), label);
4953 return () => {
4954 process.stdout.write(`${chalk.bgGreen('DONE')} `);
4955 console.timeEnd(label);
4956 };
4957 }
4958
4959 });
4960 }
4961
4962 async applyComposerConfig() {
4963 const l = this.log.start('Applying composer best practices');
4964 await this.composer('config minimum-stability dev');
4965 await this.composer('config prefer-stable true');
4966 await this.composer('config discard-changes true');
4967 await this.composer('config sort-packages true');
4968 await this.composer('config extra.enable-patching true');
4969 await this.composer('config extra.composer-exit-on-patch-failure true');
4970 await this.composer('config extra.drupal-scaffold.locations web-root.web');
4971 const composerFile = `${process.cwd()}/composer.json`;
4972 await write$1(composerFile, (await read$1(composerFile, 'utf8')).replace(`"enable-patching": "true"`, `"enable-patching": true`).replace(`"composer-exit-on-patch-failure": "true"`, `"composer-exit-on-patch-failure": true`).replace(`"locations": "web-root.web"`, `"locations": {"web-root": "web"}`));
4973 await this.composer('update --lock');
4974 await this.lint();
4975 l();
4976 }
4977
4978 async importDatabase(devtool) {
4979 if (devtool) {
4980 await this.logPromise('database import', execa.command(devtool === 'lando' ? 'lando db-import drupal--dump.sql' : 'ddev import-db --src=drupal--dump.sql'));
4981 } else {
4982 const connectionCommand = await this.drush(devtool, 'sql-connect');
4983 this.log.start('database import');
4984 await this.logPromise('database import', execa.command(`${connectionCommand.all} < drupal--dump.sql`, {
4985 shell: true
4986 }));
4987 }
4988 }
4989
4990 async addBurstDrupalDistribution() {
4991 let composerJson = await this.readJsonFile(`${process.cwd()}/composer.json`);
4992 const composerLock = await this.readJsonFile(`${process.cwd()}/composer.lock`);
4993 const burstDistribution = composerLock.packages.find(p => p.name === 'burst/drupal-distribution');
4994 const hnDistribution = composerLock.packages.find(p => p.name === 'headless-ninja/drupal-distribution');
4995
4996 if (burstDistribution && !hnDistribution) {
4997 console.log('There was not a legacy version of the Burst distribution found that needs migration.');
4998 return;
4999 }
5000
5001 if (burstDistribution) {
5002 console.log('Found a legacy version of the Burst distribution that will be removed.');
5003 const requiredPackagesByDists = [...Object.entries(burstDistribution.require), ...Object.entries(hnDistribution.require)]; // This requires all packages to the root composer.json that are
5004 // already required by one of the distributions, but do not exist
5005 // in the root composer.json already.
5006
5007 await this.logPromise('Adding packages of legacy Burst distribution to the root composer.json', this.composer(`require ${requiredPackagesByDists.filter(([p]) => p !== 'headless-ninja/drupal-distribution' && !Object.keys(composerJson.require).includes(p)).map(([p, v]) => `"${p}:${v}"`).join(' ')} --no-update`, {
5008 shell: true
5009 })); // This removes the old distribution.
5010
5011 await this.logPromise('Removing legacy Burst distribution', this.composer('remove burst/drupal-distribution'));
5012 await this.applyComposerConfig();
5013 await this.commit('refactor(drupal): remove legacy Burst distribution');
5014 }
5015
5016 console.log('Installing latest version of the Burst distribution.');
5017 await this.upgradeDistributionSettingsCall();
5018
5019 if (composerLock.packages.some(p => p.name === 'drupal-composer/drupal-scaffold')) {
5020 const configChangesDone = this.log.start('Remove old drupal-scaffold scripts');
5021 composerJson = await this.readJsonFile(`${process.cwd()}/composer.json`);
5022
5023 if (typeof composerJson.scripts === 'object') {
5024 Object.entries(composerJson.scripts).forEach(([key, value]) => {
5025 const newValue = (Array.isArray(value) ? value : [value]).filter(s => !s.startsWith('DrupalProject\\') && !s.startsWith('DrupalComposer\\') && s !== '@drupal-scaffold'); // eslint-disable-next-line prefer-destructuring
5026
5027 if (newValue.length === 1) composerJson.scripts[key] = newValue[0];else if (newValue.length) composerJson.scripts[key] = newValue;else delete composerJson.scripts[key];
5028 });
5029 }
5030
5031 if (composerJson.autoload && Array.isArray(composerJson.autoload.classmap)) {
5032 composerJson.autoload.classmap = composerJson.autoload.classmap.filter(c => c !== 'scripts/composer/ScriptHandler.php');
5033 if (composerJson.autoload.classmap.length === 0) delete composerJson.autoload.classmap;
5034 if (Object.keys(composerJson.autoload).length === 0) delete composerJson.autoload;
5035 }
5036
5037 if (!composerJson.extra) composerJson.extra = {};
5038 composerJson.extra['drupal-scaffold'] = {
5039 locations: {
5040 'web-root': 'web'
5041 }
5042 };
5043 await write$1(`${process.cwd()}/composer.json`, JSON.stringify(composerJson, null, 4));
5044 configChangesDone();
5045 }
5046
5047 const packagesInLatest = [// In the last version of the Burst distribution
5048 'composer/installers', 'cweagans/composer-patches', 'drupal/admin_toolbar', 'drupal/config_ignore', 'drupal/core', 'drupal/core-composer-scaffold', 'drupal/devel', 'drupal/paragraphs', 'drupal/pathauto', 'drupal/simple_sitemap', 'drush/drush', // Not needed anymore
5049 'drupal-composer/drupal-scaffold', 'drupal/console'];
5050 await this.logPromise('Remove packages that are part of the latest Burst distribution', this.composer(`remove ${packagesInLatest.join(' ')}`));
5051 await this.logPromise('Add latest Burst distribution', this.composer('require burst/drupal-distribution --update-with-all-dependencies'));
5052 await this.lint();
5053 await this.commit('feat(drupal): add Burst distribution');
5054 }
5055
5056 async upgradeDistributionSettingsCall() {
5057 // Find all calls to burst_distribution_settings();
5058 const files = await execa.command('git grep -l burst_distribution_settings', {
5059 reject: false
5060 });
5061 await Promise.all(files.stdout.split('\n').filter(Boolean).map(relativeFile => `${process.cwd()}/${relativeFile}`).map(async absoluteFile => this.logPromise(`Rewriting burst_distribution_settings() call in file ${absoluteFile}`, write$1(absoluteFile, (await read$1(absoluteFile, 'utf8')).replace(/burst_distribution_settings\([^)]*\)/g, `require_once __DIR__ . '/${path$1.relative(path$1.dirname(absoluteFile), `${process.cwd()}/web/profiles/contrib/burst-drupal-distribution/includes/settings.php`)}'`))).catch(() => {// The error will be logged, and we will continue.
5062 })));
5063 }
5064
5065 async drush(devtool, drushCommand, echo = false) {
5066 const drush = devtool === 'ddev' ? 'ddev . drush' : devtool === 'lando' ? 'lando drush' : `drush --root=${process.cwd()}`;
5067 const cmd = `${drush} -y ${drushCommand}`;
5068
5069 if (echo) {
5070 await execa.command(cmd, {
5071 stdio: 'inherit'
5072 });
5073 return null;
5074 }
5075
5076 return execa.command(cmd);
5077 }
5078
5079 cleanComposer() {
5080 return Promise.all([rimraf(`${process.cwd()}/vendor`), rimraf(`${process.cwd()}/web/core`), rimraf(`${process.cwd()}/web/modules/contrib`), rimraf(`${process.cwd()}/web/themes/contrib`), rimraf(`${process.cwd()}/web/profiles/contrib`), rimraf(`${process.cwd()}/drush/contrib`)]);
5081 }
5082
5083 async composer(command, options = {}, retryCount = 0) {
5084 try {
5085 const res = await execa.command(`composer ${command} --ansi${command.startsWith('install') || command.startsWith('require') || command.startsWith('update') ? ' --no-progress --no-suggest' : ''}`, options);
5086
5087 if (retryCount > 0) {
5088 console.log('This time, the command succeeded.');
5089 }
5090
5091 return res;
5092 } catch (err) {
5093 const log = err && err.all;
5094 if (!log) throw err;
5095 const cannotApplyMatch = log.match(/Cannot apply patch [^(]* \(([^)]*)\)/);
5096
5097 if (cannotApplyMatch) {
5098 const composerFile = `${process.cwd()}/composer.json`;
5099 const contents = await read$1(composerFile, 'utf8');
5100 const newContents = contents.replace(new RegExp(`,?\\s*"[^"]*":\\s"${cannotApplyMatch[1]}"`), '');
5101
5102 if (contents !== newContents) {
5103 await write$1(composerFile, newContents);
5104 console.log(`Removed patch ${cannotApplyMatch[1]}`); // This makes sure that every package will be re-installed the next run.
5105
5106 await this.cleanComposer(); // Something changed, so reset the retryCount.
5107
5108 return this.composer(command, options);
5109 }
5110
5111 console.log(`Could not find patch ${cannotApplyMatch[1]}, so can't fix.`);
5112 } // Show the formatted output that Composer generated.
5113
5114
5115 console.log(log);
5116 console.log(`\n\n\nThe composer command failed: ${command}`);
5117
5118 if (retryCount < 3) {
5119 console.log('Deleting all composer folders...');
5120 await this.cleanComposer();
5121 console.log(`Re-running command (retry ${retryCount + 1})...`);
5122 return this.composer(command, options, retryCount + 1);
5123 }
5124
5125 throw err;
5126 }
5127 }
5128
5129 async accountForSlowDocker(devtool, promise) {
5130 try {
5131 return await promise();
5132 } catch (e) {
5133 if (!devtool) throw e;
5134 console.log('Retry in 40 seconds (could be slow Docker sync)');
5135 await new Promise(r => setTimeout(r, 40 * 1000));
5136 return promise();
5137 }
5138 }
5139
5140 async clearCache(devtool) {
5141 await this.accountForSlowDocker(devtool, () => this.logPromise('cache clear', this.drush(devtool, 'cache-rebuild')));
5142 }
5143
5144 async commit(msg, filesToAdd = '.') {
5145 await execa.command(`git add ${filesToAdd}`);
5146
5147 if (this.unstageFiles.length) {
5148 await execa.command(`git reset -- ${this.unstageFiles.join(' ')}`);
5149 }
5150
5151 if (!(await stagedFiles()).length) {
5152 console.log(`${chalk.bgBlue('EMPTY COMMIT SKIPPED')} ${msg}\n\n`);
5153 return;
5154 }
5155
5156 const {
5157 all
5158 } = await execa('git', ['commit', `-m ${msg}`, '--author="Bart Langelaan <bart@burst-digital.com>"', '--no-verify']);
5159 console.log(`\n\n${chalk.bgBlue('COMMIT')} ${all}\n\n`);
5160 }
5161
5162 async exportConfig(devtool) {
5163 await rimraf(`${process.cwd()}/config/**/*.yml`);
5164 await this.logPromise('config export', this.drush(devtool, 'config-export'));
5165 }
5166
5167 async readJsonFile(file) {
5168 return JSON.parse((await read$1(file, 'utf8')));
5169 }
5170
5171 lint() {
5172 return this.logPromise('Linting & fixing project', execa.command(`${process.argv0} ${process.argv[1]} lint --fix`, {
5173 reject: false
5174 }));
5175 }
5176
5177 async logPromise(label, promise) {
5178 const promiseDone = this.log.start(label);
5179
5180 try {
5181 const p = await promise;
5182 promiseDone();
5183 return p;
5184 } catch (e) {
5185 process.stdout.write(`${chalk.bgRed('ERROR')} `);
5186 console.timeEnd(label);
5187 throw e;
5188 }
5189 }
5190
5191}
5192
5193/**
5194 * All available commands are listed here.
5195 */
5196
5197const commands = [CheckCommand, LintCommand, DeployCommand, ScaffoldCommand, PrepareCICommand, InstallCommand, UpdateDrupalCommand];
5198/**
5199 * This registers all commands to commander.
5200 */
5201
5202function registerCommands(commander) {
5203 commands.forEach(CommandClass => {
5204 // Create an instance of the command class.
5205 const command = new CommandClass(); // Declare the command and it's description from the instance.
5206
5207 const commanderCommand = commander.command(command.command).description(command.description); // All commands should execute the 'checkFirst' function, except the 'check' command.
5208
5209 if (command.command === 'check') {
5210 commanderCommand.action(command.action);
5211 } else {
5212 commanderCommand.action(checkFirst(command.action));
5213 } // Add all options to the command.
5214
5215
5216 command.options.forEach(opt => commanderCommand.option(opt.flags, opt.description));
5217 });
5218}
5219
5220/* eslint-disable no-console */
5221// running `burst --version`.
5222
5223const pkg = require('../package.json');
5224
5225commander.version(pkg.version); // Add all available commands to the commander.
5226// You can see all available commands in ./commands/index.tsx.
5227
5228registerCommands(commander); // When the command isn't found, show an error.
5229
5230commander.on('command:*', checkFirst(() => {
5231 console.log(chalk`Command {magenta ${commander.args.join(' ')}} not found.`);
5232 process.exit(1);
5233})); // Parse the argumens passed to the process. This actually executes the
5234// registered commands.
5235
5236commander.parse(process.argv); // If there was no command entered (just 'burst'), show help.
5237
5238if (!process.argv.slice(2).length) {
5239 commander.help();
5240}