avo 3.2.14 → 3.3.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/cli.js +748 -592
- package/package.json +13 -6
package/cli.js
CHANGED
|
@@ -783,6 +783,15 @@ function writeAvoJson(json) {
|
|
|
783
783
|
indent: 2,
|
|
784
784
|
}).then(() => json);
|
|
785
785
|
}
|
|
786
|
+
// Helper function to map targets to sources and filter out nulls
|
|
787
|
+
function mapTargetsToSources(targets, sources) {
|
|
788
|
+
return targets
|
|
789
|
+
.map((target) => {
|
|
790
|
+
const source = sources.find(({ id }) => id === target.id);
|
|
791
|
+
return source ? { target, source } : null;
|
|
792
|
+
})
|
|
793
|
+
.filter((item) => item !== null);
|
|
794
|
+
}
|
|
786
795
|
function codegen(json, { schema, sources: targets, warnings, success, errors }) {
|
|
787
796
|
const newJson = { ...JSON.parse(JSON.stringify(json)), schema };
|
|
788
797
|
newJson.sources = newJson.sources.map((source) => {
|
|
@@ -801,9 +810,75 @@ function codegen(json, { schema, sources: targets, warnings, success, errors })
|
|
|
801
810
|
}
|
|
802
811
|
return source;
|
|
803
812
|
});
|
|
813
|
+
// Before writing files: detect file-per-event mode and store old event lists
|
|
814
|
+
const oldEventMaps = new Map();
|
|
815
|
+
mapTargetsToSources(targets, json.sources).forEach(({ source }) => {
|
|
816
|
+
try {
|
|
817
|
+
// Read existing main file to check for file-per-event mode
|
|
818
|
+
if (fs.existsSync(source.path)) {
|
|
819
|
+
const existingContent = fs.readFileSync(source.path, 'utf8');
|
|
820
|
+
// eslint-disable-next-line no-use-before-define
|
|
821
|
+
const moduleMap = getModuleMap(existingContent, false);
|
|
822
|
+
if (moduleMap) {
|
|
823
|
+
// getModuleMap returns a string (the module name), not an array
|
|
824
|
+
// The type annotation is incorrect, but the actual value is a string
|
|
825
|
+
// Handle both string and array types for safety
|
|
826
|
+
let moduleName = null;
|
|
827
|
+
if (typeof moduleMap === 'string') {
|
|
828
|
+
moduleName = moduleMap;
|
|
829
|
+
}
|
|
830
|
+
else if (Array.isArray(moduleMap) && moduleMap.length > 0) {
|
|
831
|
+
[moduleName] = moduleMap;
|
|
832
|
+
}
|
|
833
|
+
// eslint-disable-next-line no-use-before-define
|
|
834
|
+
if (moduleName && isFilePerEventMode(source.path, moduleName)) {
|
|
835
|
+
// eslint-disable-next-line no-use-before-define
|
|
836
|
+
const oldEvents = getEventMap(existingContent, false);
|
|
837
|
+
if (oldEvents) {
|
|
838
|
+
oldEventMaps.set(source.id, {
|
|
839
|
+
moduleName,
|
|
840
|
+
events: oldEvents,
|
|
841
|
+
});
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
catch (err) {
|
|
848
|
+
// If we can't read the file, skip cleanup for this source
|
|
849
|
+
if (err instanceof Error && 'code' in err && err.code !== 'ENOENT') {
|
|
850
|
+
// Only log non-ENOENT errors
|
|
851
|
+
report.warn(`Failed to read existing file for cleanup check: ${err.message}`);
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
});
|
|
804
855
|
const sourceTasks = targets.map((target) => Promise.all(target.code.map((code) => writeFile(code.path, code.content))));
|
|
805
856
|
const avoJsonTask = writeAvoJson(newJson);
|
|
806
|
-
Promise.all([avoJsonTask].concat(sourceTasks)).then(() => {
|
|
857
|
+
return Promise.all([avoJsonTask].concat(sourceTasks)).then(() => {
|
|
858
|
+
// After writing files: cleanup obsolete event files
|
|
859
|
+
mapTargetsToSources(targets, newJson.sources)
|
|
860
|
+
.map(({ target, source }) => {
|
|
861
|
+
const oldEventMap = oldEventMaps.get(source.id);
|
|
862
|
+
return oldEventMap ? { target, source, oldEventMap } : null;
|
|
863
|
+
})
|
|
864
|
+
.filter((item) => item !== null)
|
|
865
|
+
.forEach(({ target, source, oldEventMap }) => {
|
|
866
|
+
// Find the main file in target.code that matches source.path
|
|
867
|
+
const mainFile = target.code.find((code) => code.path === source.path);
|
|
868
|
+
if (mainFile) {
|
|
869
|
+
// Parse AVOEVENTMAP from the newly written main file
|
|
870
|
+
// eslint-disable-next-line no-use-before-define
|
|
871
|
+
const newEvents = getEventMap(mainFile.content, false);
|
|
872
|
+
if (newEvents) {
|
|
873
|
+
// eslint-disable-next-line no-use-before-define
|
|
874
|
+
const eventsDir = getEventsDirectoryPath(source.path, oldEventMap.moduleName);
|
|
875
|
+
// Extract file extension from source path (e.g., .ts, .kt, .swift)
|
|
876
|
+
const sourceExtension = path.extname(source.path);
|
|
877
|
+
// eslint-disable-next-line no-use-before-define
|
|
878
|
+
cleanupObsoleteEventFiles(eventsDir, oldEventMap.events, newEvents, sourceExtension);
|
|
879
|
+
}
|
|
880
|
+
}
|
|
881
|
+
});
|
|
807
882
|
if (errors !== undefined && errors !== null && errors !== '') {
|
|
808
883
|
report.warn(`${errors}\n`);
|
|
809
884
|
}
|
|
@@ -1068,6 +1143,51 @@ function getModuleMap(data, verbose) {
|
|
|
1068
1143
|
}
|
|
1069
1144
|
return null;
|
|
1070
1145
|
}
|
|
1146
|
+
// Get events directory path from source path and module name
|
|
1147
|
+
// e.g., source.path="./Avo.ts", moduleName="Avo" -> "./AvoEvents"
|
|
1148
|
+
export function getEventsDirectoryPath(sourcePath, moduleName) {
|
|
1149
|
+
const parsed = path.parse(sourcePath);
|
|
1150
|
+
return path.join(parsed.dir, `${moduleName}Events`);
|
|
1151
|
+
}
|
|
1152
|
+
// Check if file-per-event mode is active by checking for events directory
|
|
1153
|
+
export function isFilePerEventMode(sourcePath, moduleName) {
|
|
1154
|
+
const eventsDir = getEventsDirectoryPath(sourcePath, moduleName);
|
|
1155
|
+
try {
|
|
1156
|
+
if (!fs.existsSync(eventsDir)) {
|
|
1157
|
+
return false;
|
|
1158
|
+
}
|
|
1159
|
+
return fs.statSync(eventsDir).isDirectory();
|
|
1160
|
+
}
|
|
1161
|
+
catch (error) {
|
|
1162
|
+
// Treat any error (permission, transient FS errors, etc.) as "not a directory"
|
|
1163
|
+
// Log the error for debugging purposes
|
|
1164
|
+
if (error instanceof Error) {
|
|
1165
|
+
report.warn(`Error checking file-per-event mode for ${eventsDir}: ${error.message}`);
|
|
1166
|
+
}
|
|
1167
|
+
return false;
|
|
1168
|
+
}
|
|
1169
|
+
}
|
|
1170
|
+
// Convert event name to file name (camelCase convention from codegen)
|
|
1171
|
+
export function eventNameToFileName(eventName, extension) {
|
|
1172
|
+
const camelCase = eventName.charAt(0).toLowerCase() + eventName.slice(1);
|
|
1173
|
+
return `${camelCase}${extension}`;
|
|
1174
|
+
}
|
|
1175
|
+
// Cleanup obsolete event files
|
|
1176
|
+
export function cleanupObsoleteEventFiles(eventsDir, oldEvents, newEvents, extension) {
|
|
1177
|
+
const removedEvents = oldEvents.filter((e) => !newEvents.includes(e));
|
|
1178
|
+
removedEvents.forEach((eventName) => {
|
|
1179
|
+
const filePath = path.join(eventsDir, eventNameToFileName(eventName, extension));
|
|
1180
|
+
if (fs.existsSync(filePath)) {
|
|
1181
|
+
try {
|
|
1182
|
+
fs.unlinkSync(filePath);
|
|
1183
|
+
report.info(`Removed obsolete event file: ${filePath}`);
|
|
1184
|
+
}
|
|
1185
|
+
catch (error) {
|
|
1186
|
+
report.error(`Failed to remove obsolete event file: ${filePath} - ${error instanceof Error ? error.message : String(error)}`);
|
|
1187
|
+
}
|
|
1188
|
+
}
|
|
1189
|
+
});
|
|
1190
|
+
}
|
|
1071
1191
|
function getSource(argv, json) {
|
|
1072
1192
|
if (!json.sources || !json.sources.length) {
|
|
1073
1193
|
report.info('No sources configured.');
|
|
@@ -1357,190 +1477,380 @@ function logout(refreshToken) {
|
|
|
1357
1477
|
function parseForceFeaturesParam(forceFeatures) {
|
|
1358
1478
|
return forceFeatures?.split(',').map((it) => it.trim());
|
|
1359
1479
|
}
|
|
1360
|
-
yargs(
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
.
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1480
|
+
// Only execute yargs CLI if this file is run directly (not imported for testing)
|
|
1481
|
+
// Skip execution if we're in a test environment
|
|
1482
|
+
// Check multiple indicators that we're running under Jest
|
|
1483
|
+
const isMainModule = !process.env.AVO_TEST_MODE &&
|
|
1484
|
+
!process.env.JEST_WORKER_ID &&
|
|
1485
|
+
typeof jest === 'undefined' &&
|
|
1486
|
+
!process.argv.some((arg) => arg.includes('jest')) &&
|
|
1487
|
+
!process.argv.some((arg) => arg.includes('jest.js')) &&
|
|
1488
|
+
process.argv[1]?.endsWith('cli.js');
|
|
1489
|
+
if (isMainModule) {
|
|
1490
|
+
try {
|
|
1491
|
+
yargs(hideBin(process.argv)) // eslint-disable-line no-unused-expressions
|
|
1492
|
+
.usage('$0 command')
|
|
1493
|
+
.scriptName('avo')
|
|
1494
|
+
.version(pkg.version)
|
|
1495
|
+
.option('v', {
|
|
1496
|
+
alias: 'verbose',
|
|
1497
|
+
default: false,
|
|
1498
|
+
describe: 'make output more verbose',
|
|
1499
|
+
type: 'boolean',
|
|
1500
|
+
})
|
|
1501
|
+
.command({
|
|
1502
|
+
command: 'track-install',
|
|
1503
|
+
describe: false,
|
|
1504
|
+
handler: async (argv) => {
|
|
1505
|
+
try {
|
|
1506
|
+
Avo.cliInstalled({
|
|
1507
|
+
userId_: installIdOrUserId(),
|
|
1508
|
+
cliInvokedByCi: invokedByCi(),
|
|
1509
|
+
}).catch((error) => {
|
|
1510
|
+
if (argv.verbose) {
|
|
1511
|
+
console.error('Request to track cli installed failed', error);
|
|
1512
|
+
}
|
|
1513
|
+
});
|
|
1381
1514
|
}
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
}
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1515
|
+
catch (error) {
|
|
1516
|
+
console.error('Unexpected error failed to track cli installed', error);
|
|
1517
|
+
}
|
|
1518
|
+
},
|
|
1519
|
+
})
|
|
1520
|
+
.command({
|
|
1521
|
+
command: 'init',
|
|
1522
|
+
describe: 'Initialize an Avo workspace in the current folder',
|
|
1523
|
+
handler: (argv) => {
|
|
1524
|
+
loadAvoJsonOrInit({ argv, skipPullMaster: false, skipInit: true })
|
|
1525
|
+
.then((json) => {
|
|
1526
|
+
if (json) {
|
|
1527
|
+
Avo.cliInvoked({
|
|
1528
|
+
schemaId: json.schema.id,
|
|
1529
|
+
schemaName: json.schema.name,
|
|
1530
|
+
branchId: json.branch.id,
|
|
1531
|
+
branchName: json.branch.name,
|
|
1532
|
+
userId_: installIdOrUserId(),
|
|
1533
|
+
cliAction: Avo.CliAction.INIT,
|
|
1534
|
+
cliInvokedByCi: invokedByCi(),
|
|
1535
|
+
force: undefined,
|
|
1536
|
+
forceFeatures: undefined,
|
|
1537
|
+
});
|
|
1538
|
+
report.info(`Avo is already initialized for workspace ${cyan(json.schema.name)} (${file('avo.json')} exists)`);
|
|
1539
|
+
return Promise.resolve();
|
|
1540
|
+
}
|
|
1541
|
+
Avo.cliInvoked({
|
|
1542
|
+
schemaId: 'N/A',
|
|
1543
|
+
schemaName: 'N/A',
|
|
1544
|
+
branchId: 'N/A',
|
|
1545
|
+
branchName: 'N/A',
|
|
1546
|
+
userId_: installIdOrUserId(),
|
|
1547
|
+
cliAction: Avo.CliAction.INIT,
|
|
1548
|
+
cliInvokedByCi: invokedByCi(),
|
|
1549
|
+
force: undefined,
|
|
1550
|
+
forceFeatures: undefined,
|
|
1551
|
+
});
|
|
1552
|
+
return requireAuth(argv, () => init()
|
|
1553
|
+
.then(writeAvoJson)
|
|
1554
|
+
.then(() => {
|
|
1555
|
+
report.info("Run 'avo pull' to pull analytics wrappers from Avo");
|
|
1556
|
+
}));
|
|
1557
|
+
})
|
|
1558
|
+
.catch(() => {
|
|
1559
|
+
Avo.cliInvoked({
|
|
1560
|
+
schemaId: 'N/A',
|
|
1561
|
+
schemaName: 'N/A',
|
|
1562
|
+
branchId: 'N/A',
|
|
1563
|
+
branchName: 'N/A',
|
|
1564
|
+
userId_: installIdOrUserId(),
|
|
1565
|
+
cliAction: Avo.CliAction.INIT,
|
|
1566
|
+
cliInvokedByCi: invokedByCi(),
|
|
1567
|
+
force: undefined,
|
|
1568
|
+
forceFeatures: undefined,
|
|
1569
|
+
});
|
|
1570
|
+
});
|
|
1571
|
+
},
|
|
1572
|
+
})
|
|
1573
|
+
.command({
|
|
1574
|
+
command: 'pull [source]',
|
|
1575
|
+
describe: 'Pull analytics wrappers from Avo workspace',
|
|
1576
|
+
builder: (yargs) => yargs
|
|
1577
|
+
.option('branch', {
|
|
1578
|
+
describe: 'Name of Avo branch to pull from',
|
|
1579
|
+
type: 'string',
|
|
1580
|
+
})
|
|
1581
|
+
.option('f', {
|
|
1582
|
+
alias: 'force',
|
|
1583
|
+
describe: 'Proceed ignoring the unsupported features for given source',
|
|
1584
|
+
default: false,
|
|
1585
|
+
type: 'boolean',
|
|
1586
|
+
})
|
|
1587
|
+
.option('forceFeatures', {
|
|
1588
|
+
describe: 'Optional comma separated list of features to force enable, pass unsupported name to get the list of available features',
|
|
1589
|
+
default: undefined,
|
|
1590
|
+
type: 'string',
|
|
1591
|
+
}),
|
|
1592
|
+
handler: (argv) => {
|
|
1593
|
+
loadAvoJsonOrInit({ argv, skipInit: false, skipPullMaster: false })
|
|
1594
|
+
.then((json) => {
|
|
1595
|
+
Avo.cliInvoked({
|
|
1596
|
+
schemaId: json.schema.id,
|
|
1597
|
+
schemaName: json.schema.name,
|
|
1598
|
+
branchId: json.branch.id,
|
|
1599
|
+
branchName: json.branch.name,
|
|
1600
|
+
userId_: installIdOrUserId(),
|
|
1601
|
+
cliAction: Avo.CliAction.PULL,
|
|
1602
|
+
cliInvokedByCi: invokedByCi(),
|
|
1603
|
+
force: argv.f === true,
|
|
1604
|
+
forceFeatures: parseForceFeaturesParam(argv.forceFeatures),
|
|
1605
|
+
});
|
|
1606
|
+
requireAuth(argv, () => {
|
|
1607
|
+
if (argv.branch && json.branch.name !== argv.branch) {
|
|
1608
|
+
return checkout(argv.branch, json)
|
|
1609
|
+
.then((data) => getSource(argv, data))
|
|
1610
|
+
.then(([source, data]) => pull(source, data));
|
|
1611
|
+
}
|
|
1612
|
+
report.info(`Pulling from branch '${json.branch.name}'`);
|
|
1613
|
+
return getSource(argv, json).then(([source, data]) => pull(source, data));
|
|
1614
|
+
});
|
|
1615
|
+
})
|
|
1616
|
+
.catch((error) => {
|
|
1617
|
+
Avo.cliInvoked({
|
|
1618
|
+
schemaId: 'N/A',
|
|
1619
|
+
schemaName: 'N/A',
|
|
1620
|
+
branchId: 'N/A',
|
|
1621
|
+
branchName: 'N/A',
|
|
1622
|
+
userId_: installIdOrUserId(),
|
|
1623
|
+
cliAction: Avo.CliAction.PULL,
|
|
1624
|
+
cliInvokedByCi: invokedByCi(),
|
|
1625
|
+
force: undefined,
|
|
1626
|
+
forceFeatures: undefined,
|
|
1627
|
+
});
|
|
1628
|
+
throw error;
|
|
1629
|
+
});
|
|
1630
|
+
},
|
|
1631
|
+
})
|
|
1632
|
+
.command({
|
|
1633
|
+
command: 'checkout [branch]',
|
|
1634
|
+
aliases: ['branch'],
|
|
1635
|
+
describe: 'Switch branches',
|
|
1636
|
+
handler: (argv) => loadAvoJsonOrInit({ argv, skipInit: false, skipPullMaster: false })
|
|
1637
|
+
.then((json) => {
|
|
1396
1638
|
Avo.cliInvoked({
|
|
1397
1639
|
schemaId: json.schema.id,
|
|
1398
1640
|
schemaName: json.schema.name,
|
|
1399
1641
|
branchId: json.branch.id,
|
|
1400
1642
|
branchName: json.branch.name,
|
|
1401
1643
|
userId_: installIdOrUserId(),
|
|
1402
|
-
cliAction: Avo.CliAction.
|
|
1644
|
+
cliAction: Avo.CliAction.CHECKOUT,
|
|
1403
1645
|
cliInvokedByCi: invokedByCi(),
|
|
1404
1646
|
force: undefined,
|
|
1405
1647
|
forceFeatures: undefined,
|
|
1406
1648
|
});
|
|
1407
|
-
report.info(`
|
|
1408
|
-
|
|
1409
|
-
}
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
report.info("Run 'avo pull' to pull analytics wrappers from Avo");
|
|
1425
|
-
}));
|
|
1649
|
+
report.info(`Currently on branch '${json.branch.name}'`);
|
|
1650
|
+
requireAuth(argv, () => checkout(argv.branch, json).then(writeAvoJson));
|
|
1651
|
+
})
|
|
1652
|
+
.catch((error) => {
|
|
1653
|
+
Avo.cliInvoked({
|
|
1654
|
+
schemaId: 'N/A',
|
|
1655
|
+
schemaName: 'N/A',
|
|
1656
|
+
branchId: 'N/A',
|
|
1657
|
+
branchName: 'N/A',
|
|
1658
|
+
userId_: installIdOrUserId(),
|
|
1659
|
+
cliAction: Avo.CliAction.CHECKOUT,
|
|
1660
|
+
cliInvokedByCi: invokedByCi(),
|
|
1661
|
+
force: undefined,
|
|
1662
|
+
forceFeatures: undefined,
|
|
1663
|
+
});
|
|
1664
|
+
throw error;
|
|
1665
|
+
}),
|
|
1426
1666
|
})
|
|
1427
|
-
.
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1667
|
+
.command({
|
|
1668
|
+
command: 'source <command>',
|
|
1669
|
+
describe: 'Manage sources for the current project',
|
|
1670
|
+
builder: (yargs) => yargs
|
|
1671
|
+
.command({
|
|
1672
|
+
command: '$0',
|
|
1673
|
+
describe: 'List sources in this project',
|
|
1674
|
+
handler: (argv) => {
|
|
1675
|
+
loadAvoJsonOrInit({
|
|
1676
|
+
argv,
|
|
1677
|
+
skipInit: false,
|
|
1678
|
+
skipPullMaster: false,
|
|
1679
|
+
})
|
|
1680
|
+
.then((json) => {
|
|
1681
|
+
Avo.cliInvoked({
|
|
1682
|
+
schemaId: json.schema.id,
|
|
1683
|
+
schemaName: json.schema.name,
|
|
1684
|
+
branchId: json.branch.id,
|
|
1685
|
+
branchName: json.branch.name,
|
|
1686
|
+
userId_: installIdOrUserId(),
|
|
1687
|
+
cliAction: Avo.CliAction.SOURCE,
|
|
1688
|
+
cliInvokedByCi: invokedByCi(),
|
|
1689
|
+
force: undefined,
|
|
1690
|
+
forceFeatures: undefined,
|
|
1691
|
+
});
|
|
1692
|
+
if (!json.sources || !json.sources.length) {
|
|
1693
|
+
report.info(`No sources defined in ${file('avo.json')}. Run ${cmd('avo source add')} to add sources`);
|
|
1694
|
+
return;
|
|
1695
|
+
}
|
|
1696
|
+
report.info('Sources in this project:');
|
|
1697
|
+
report.tree('sources', json.sources.map((source) => ({
|
|
1698
|
+
name: source.name,
|
|
1699
|
+
children: [{ name: source.path }],
|
|
1700
|
+
})));
|
|
1701
|
+
})
|
|
1702
|
+
.catch((error) => {
|
|
1703
|
+
Avo.cliInvoked({
|
|
1704
|
+
schemaId: 'N/A',
|
|
1705
|
+
schemaName: 'N/A',
|
|
1706
|
+
branchId: 'N/A',
|
|
1707
|
+
branchName: 'N/A',
|
|
1708
|
+
userId_: installIdOrUserId(),
|
|
1709
|
+
cliAction: Avo.CliAction.SOURCE,
|
|
1710
|
+
cliInvokedByCi: invokedByCi(),
|
|
1711
|
+
force: undefined,
|
|
1712
|
+
forceFeatures: undefined,
|
|
1713
|
+
});
|
|
1714
|
+
throw error;
|
|
1715
|
+
});
|
|
1716
|
+
},
|
|
1717
|
+
})
|
|
1718
|
+
.command({
|
|
1719
|
+
command: 'add [source]',
|
|
1720
|
+
describe: 'Add a source to this project',
|
|
1721
|
+
handler: (argv) => {
|
|
1722
|
+
loadAvoJsonOrInit({
|
|
1723
|
+
argv,
|
|
1724
|
+
skipInit: false,
|
|
1725
|
+
skipPullMaster: false,
|
|
1726
|
+
})
|
|
1727
|
+
.then((json) => {
|
|
1728
|
+
Avo.cliInvoked({
|
|
1729
|
+
schemaId: json.schema.id,
|
|
1730
|
+
schemaName: json.schema.name,
|
|
1731
|
+
branchId: json.branch.id,
|
|
1732
|
+
branchName: json.branch.name,
|
|
1733
|
+
userId_: installIdOrUserId(),
|
|
1734
|
+
cliAction: Avo.CliAction.SOURCE_ADD,
|
|
1735
|
+
cliInvokedByCi: invokedByCi(),
|
|
1736
|
+
force: undefined,
|
|
1737
|
+
forceFeatures: undefined,
|
|
1738
|
+
});
|
|
1739
|
+
requireAuth(argv, () => {
|
|
1740
|
+
selectSource(argv.source, json).then(writeAvoJson);
|
|
1741
|
+
});
|
|
1742
|
+
})
|
|
1743
|
+
.catch((error) => {
|
|
1744
|
+
Avo.cliInvoked({
|
|
1745
|
+
schemaId: 'N/A',
|
|
1746
|
+
schemaName: 'N/A',
|
|
1747
|
+
branchId: 'N/A',
|
|
1748
|
+
branchName: 'N/A',
|
|
1749
|
+
userId_: installIdOrUserId(),
|
|
1750
|
+
cliAction: Avo.CliAction.SOURCE_ADD,
|
|
1751
|
+
cliInvokedByCi: invokedByCi(),
|
|
1752
|
+
force: undefined,
|
|
1753
|
+
forceFeatures: undefined,
|
|
1754
|
+
});
|
|
1755
|
+
throw error;
|
|
1756
|
+
});
|
|
1757
|
+
},
|
|
1758
|
+
})
|
|
1759
|
+
.command({
|
|
1760
|
+
command: 'remove [source]',
|
|
1761
|
+
aliases: ['rm'],
|
|
1762
|
+
describe: 'Remove a source from this project',
|
|
1763
|
+
handler: (argv) => {
|
|
1764
|
+
loadAvoJsonOrInit({
|
|
1765
|
+
argv,
|
|
1766
|
+
skipInit: false,
|
|
1767
|
+
skipPullMaster: false,
|
|
1768
|
+
})
|
|
1769
|
+
.then((json) => {
|
|
1770
|
+
Avo.cliInvoked({
|
|
1771
|
+
schemaId: json.schema.id,
|
|
1772
|
+
schemaName: json.schema.name,
|
|
1773
|
+
branchId: json.branch.id,
|
|
1774
|
+
branchName: json.branch.name,
|
|
1775
|
+
userId_: installIdOrUserId(),
|
|
1776
|
+
cliAction: Avo.CliAction.SOURCE_REMOVE,
|
|
1777
|
+
cliInvokedByCi: invokedByCi(),
|
|
1778
|
+
force: undefined,
|
|
1779
|
+
forceFeatures: undefined,
|
|
1780
|
+
});
|
|
1781
|
+
if (!json.sources || !json.sources.length) {
|
|
1782
|
+
report.warn(`No sources defined in ${file('avo.json')}. Run ${cmd('avo source add')} to add sources`);
|
|
1783
|
+
return;
|
|
1784
|
+
}
|
|
1785
|
+
const getSourceToRemove = (argv, json) => {
|
|
1786
|
+
if (argv.source) {
|
|
1787
|
+
return Promise.resolve(json.sources.find((source) => matchesSource(source, argv.source)));
|
|
1788
|
+
}
|
|
1789
|
+
const choices = json.sources.map((source) => ({
|
|
1790
|
+
value: source,
|
|
1791
|
+
name: source.name,
|
|
1792
|
+
}));
|
|
1793
|
+
return inquirer
|
|
1794
|
+
.prompt({
|
|
1795
|
+
type: 'list',
|
|
1796
|
+
name: 'source',
|
|
1797
|
+
message: 'Select a source to remove',
|
|
1798
|
+
choices,
|
|
1799
|
+
pageSize: 15,
|
|
1800
|
+
})
|
|
1801
|
+
.then((answer) => answer.source);
|
|
1802
|
+
};
|
|
1803
|
+
getSourceToRemove(argv, json).then((targetSource) => {
|
|
1804
|
+
if (!targetSource) {
|
|
1805
|
+
report.error(`Source ${argv.source} not found in project.`);
|
|
1806
|
+
return Promise.resolve();
|
|
1807
|
+
}
|
|
1808
|
+
return inquirer
|
|
1809
|
+
.prompt([
|
|
1810
|
+
{
|
|
1811
|
+
type: 'confirm',
|
|
1812
|
+
name: 'remove',
|
|
1813
|
+
default: true,
|
|
1814
|
+
message: `Are you sure you want to remove source ${targetSource.name} from project`,
|
|
1815
|
+
},
|
|
1816
|
+
])
|
|
1817
|
+
.then((answer) => {
|
|
1818
|
+
if (answer.remove) {
|
|
1819
|
+
const sources = (json.sources ?? []).filter((source) => source.id !== targetSource.id);
|
|
1820
|
+
const newJson = { ...json, sources };
|
|
1821
|
+
return writeAvoJson(newJson).then(() => {
|
|
1822
|
+
// XXX ask to remove file as well?
|
|
1823
|
+
report.info(`Removed source ${targetSource.name} from project`);
|
|
1824
|
+
});
|
|
1825
|
+
}
|
|
1826
|
+
report.info(`Did not remove source ${targetSource.name} from project`);
|
|
1827
|
+
return Promise.resolve();
|
|
1828
|
+
});
|
|
1829
|
+
});
|
|
1830
|
+
})
|
|
1831
|
+
.catch((error) => {
|
|
1832
|
+
Avo.cliInvoked({
|
|
1833
|
+
schemaId: 'N/A',
|
|
1834
|
+
schemaName: 'N/A',
|
|
1835
|
+
branchId: 'N/A',
|
|
1836
|
+
branchName: 'N/A',
|
|
1837
|
+
userId_: installIdOrUserId(),
|
|
1838
|
+
cliAction: Avo.CliAction.SOURCE_REMOVE,
|
|
1839
|
+
cliInvokedByCi: invokedByCi(),
|
|
1840
|
+
force: undefined,
|
|
1841
|
+
forceFeatures: undefined,
|
|
1842
|
+
});
|
|
1843
|
+
throw error;
|
|
1844
|
+
});
|
|
1845
|
+
},
|
|
1846
|
+
}),
|
|
1847
|
+
handler: () => {
|
|
1848
|
+
// Parent command - subcommands handle the actual logic
|
|
1849
|
+
},
|
|
1484
1850
|
})
|
|
1485
|
-
.catch((error) => {
|
|
1486
|
-
Avo.cliInvoked({
|
|
1487
|
-
schemaId: 'N/A',
|
|
1488
|
-
schemaName: 'N/A',
|
|
1489
|
-
branchId: 'N/A',
|
|
1490
|
-
branchName: 'N/A',
|
|
1491
|
-
userId_: installIdOrUserId(),
|
|
1492
|
-
cliAction: Avo.CliAction.PULL,
|
|
1493
|
-
cliInvokedByCi: invokedByCi(),
|
|
1494
|
-
force: undefined,
|
|
1495
|
-
forceFeatures: undefined,
|
|
1496
|
-
});
|
|
1497
|
-
throw error;
|
|
1498
|
-
});
|
|
1499
|
-
},
|
|
1500
|
-
})
|
|
1501
|
-
.command({
|
|
1502
|
-
command: 'checkout [branch]',
|
|
1503
|
-
aliases: ['branch'],
|
|
1504
|
-
desc: 'Switch branches',
|
|
1505
|
-
handler: (argv) => loadAvoJsonOrInit({ argv, skipInit: false, skipPullMaster: false })
|
|
1506
|
-
.then((json) => {
|
|
1507
|
-
Avo.cliInvoked({
|
|
1508
|
-
schemaId: json.schema.id,
|
|
1509
|
-
schemaName: json.schema.name,
|
|
1510
|
-
branchId: json.branch.id,
|
|
1511
|
-
branchName: json.branch.name,
|
|
1512
|
-
userId_: installIdOrUserId(),
|
|
1513
|
-
cliAction: Avo.CliAction.CHECKOUT,
|
|
1514
|
-
cliInvokedByCi: invokedByCi(),
|
|
1515
|
-
force: undefined,
|
|
1516
|
-
forceFeatures: undefined,
|
|
1517
|
-
});
|
|
1518
|
-
report.info(`Currently on branch '${json.branch.name}'`);
|
|
1519
|
-
requireAuth(argv, () => checkout(argv.branch, json).then(writeAvoJson));
|
|
1520
|
-
})
|
|
1521
|
-
.catch((error) => {
|
|
1522
|
-
Avo.cliInvoked({
|
|
1523
|
-
schemaId: 'N/A',
|
|
1524
|
-
schemaName: 'N/A',
|
|
1525
|
-
branchId: 'N/A',
|
|
1526
|
-
branchName: 'N/A',
|
|
1527
|
-
userId_: installIdOrUserId(),
|
|
1528
|
-
cliAction: Avo.CliAction.CHECKOUT,
|
|
1529
|
-
cliInvokedByCi: invokedByCi(),
|
|
1530
|
-
force: undefined,
|
|
1531
|
-
forceFeatures: undefined,
|
|
1532
|
-
});
|
|
1533
|
-
throw error;
|
|
1534
|
-
}),
|
|
1535
|
-
})
|
|
1536
|
-
.command({
|
|
1537
|
-
command: 'source <command>',
|
|
1538
|
-
desc: 'Manage sources for the current project',
|
|
1539
|
-
builder: (yargs) => {
|
|
1540
|
-
yargs
|
|
1541
1851
|
.command({
|
|
1542
|
-
command: '
|
|
1543
|
-
|
|
1852
|
+
command: 'status [source]',
|
|
1853
|
+
describe: 'Show the status of the Avo implementation',
|
|
1544
1854
|
handler: (argv) => {
|
|
1545
1855
|
loadAvoJsonOrInit({ argv, skipInit: false, skipPullMaster: false })
|
|
1546
1856
|
.then((json) => {
|
|
@@ -1550,21 +1860,15 @@ yargs(hideBin(process.argv)) // eslint-disable-line no-unused-expressions
|
|
|
1550
1860
|
branchId: json.branch.id,
|
|
1551
1861
|
branchName: json.branch.name,
|
|
1552
1862
|
userId_: installIdOrUserId(),
|
|
1553
|
-
cliAction: Avo.CliAction.
|
|
1863
|
+
cliAction: Avo.CliAction.STATUS,
|
|
1554
1864
|
cliInvokedByCi: invokedByCi(),
|
|
1555
1865
|
force: undefined,
|
|
1556
1866
|
forceFeatures: undefined,
|
|
1557
1867
|
});
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
return;
|
|
1561
|
-
}
|
|
1562
|
-
report.info('Sources in this project:');
|
|
1563
|
-
report.tree('sources', json.sources.map((source) => ({
|
|
1564
|
-
name: source.name,
|
|
1565
|
-
children: [{ name: source.path }],
|
|
1566
|
-
})));
|
|
1868
|
+
report.info(`Currently on branch '${json.branch.name}'`);
|
|
1869
|
+
return getSource(argv, json);
|
|
1567
1870
|
})
|
|
1871
|
+
.then(([source, json]) => status(source, json, argv))
|
|
1568
1872
|
.catch((error) => {
|
|
1569
1873
|
Avo.cliInvoked({
|
|
1570
1874
|
schemaId: 'N/A',
|
|
@@ -1572,7 +1876,7 @@ yargs(hideBin(process.argv)) // eslint-disable-line no-unused-expressions
|
|
|
1572
1876
|
branchId: 'N/A',
|
|
1573
1877
|
branchName: 'N/A',
|
|
1574
1878
|
userId_: installIdOrUserId(),
|
|
1575
|
-
cliAction: Avo.CliAction.
|
|
1879
|
+
cliAction: Avo.CliAction.STATUS,
|
|
1576
1880
|
cliInvokedByCi: invokedByCi(),
|
|
1577
1881
|
force: undefined,
|
|
1578
1882
|
forceFeatures: undefined,
|
|
@@ -1582,10 +1886,17 @@ yargs(hideBin(process.argv)) // eslint-disable-line no-unused-expressions
|
|
|
1582
1886
|
},
|
|
1583
1887
|
})
|
|
1584
1888
|
.command({
|
|
1585
|
-
command: '
|
|
1586
|
-
|
|
1889
|
+
command: 'merge main',
|
|
1890
|
+
aliases: ['merge master'],
|
|
1891
|
+
describe: 'Pull the Avo main branch into your current branch',
|
|
1892
|
+
builder: (yargs) => yargs.option('f', {
|
|
1893
|
+
alias: 'force',
|
|
1894
|
+
describe: 'Proceed with merge when incoming branch is open',
|
|
1895
|
+
default: false,
|
|
1896
|
+
type: 'boolean',
|
|
1897
|
+
}),
|
|
1587
1898
|
handler: (argv) => {
|
|
1588
|
-
loadAvoJsonOrInit({ argv,
|
|
1899
|
+
loadAvoJsonOrInit({ argv, skipPullMaster: true, skipInit: false })
|
|
1589
1900
|
.then((json) => {
|
|
1590
1901
|
Avo.cliInvoked({
|
|
1591
1902
|
schemaId: json.schema.id,
|
|
@@ -1593,14 +1904,12 @@ yargs(hideBin(process.argv)) // eslint-disable-line no-unused-expressions
|
|
|
1593
1904
|
branchId: json.branch.id,
|
|
1594
1905
|
branchName: json.branch.name,
|
|
1595
1906
|
userId_: installIdOrUserId(),
|
|
1596
|
-
cliAction: Avo.CliAction.
|
|
1907
|
+
cliAction: Avo.CliAction.MERGE,
|
|
1597
1908
|
cliInvokedByCi: invokedByCi(),
|
|
1598
|
-
force:
|
|
1909
|
+
force: json.force,
|
|
1599
1910
|
forceFeatures: undefined,
|
|
1600
1911
|
});
|
|
1601
|
-
requireAuth(argv, () =>
|
|
1602
|
-
selectSource(argv.source, json).then(writeAvoJson);
|
|
1603
|
-
});
|
|
1912
|
+
return requireAuth(argv, () => pullMaster(json).then(writeAvoJson));
|
|
1604
1913
|
})
|
|
1605
1914
|
.catch((error) => {
|
|
1606
1915
|
Avo.cliInvoked({
|
|
@@ -1609,7 +1918,7 @@ yargs(hideBin(process.argv)) // eslint-disable-line no-unused-expressions
|
|
|
1609
1918
|
branchId: 'N/A',
|
|
1610
1919
|
branchName: 'N/A',
|
|
1611
1920
|
userId_: installIdOrUserId(),
|
|
1612
|
-
cliAction: Avo.CliAction.
|
|
1921
|
+
cliAction: Avo.CliAction.MERGE,
|
|
1613
1922
|
cliInvokedByCi: invokedByCi(),
|
|
1614
1923
|
force: undefined,
|
|
1615
1924
|
forceFeatures: undefined,
|
|
@@ -1619,9 +1928,63 @@ yargs(hideBin(process.argv)) // eslint-disable-line no-unused-expressions
|
|
|
1619
1928
|
},
|
|
1620
1929
|
})
|
|
1621
1930
|
.command({
|
|
1622
|
-
command: '
|
|
1623
|
-
aliases: ['
|
|
1624
|
-
|
|
1931
|
+
command: 'conflict',
|
|
1932
|
+
aliases: ['resolve', 'conflicts'],
|
|
1933
|
+
describe: 'Resolve git conflicts in Avo files',
|
|
1934
|
+
handler: (argv) => pify(fs.readFile)('avo.json', 'utf8')
|
|
1935
|
+
.then((avoFile) => {
|
|
1936
|
+
if (hasMergeConflicts(avoFile)) {
|
|
1937
|
+
return requireAuth(argv, () => resolveAvoJsonConflicts(avoFile, {
|
|
1938
|
+
argv,
|
|
1939
|
+
skipPullMaster: false,
|
|
1940
|
+
}).then((json) => {
|
|
1941
|
+
Avo.cliInvoked({
|
|
1942
|
+
schemaId: json.schema.id,
|
|
1943
|
+
schemaName: json.schema.name,
|
|
1944
|
+
branchId: json.branch.id,
|
|
1945
|
+
branchName: json.branch.name,
|
|
1946
|
+
userId_: installIdOrUserId(),
|
|
1947
|
+
cliAction: Avo.CliAction.CONFLICT,
|
|
1948
|
+
cliInvokedByCi: invokedByCi(),
|
|
1949
|
+
force: undefined,
|
|
1950
|
+
forceFeatures: undefined,
|
|
1951
|
+
});
|
|
1952
|
+
pull(null, json);
|
|
1953
|
+
}));
|
|
1954
|
+
}
|
|
1955
|
+
report.info("No git conflicts found in avo.json. Run 'avo pull' to resolve git conflicts in other Avo files.");
|
|
1956
|
+
const json = JSON.parse(avoFile);
|
|
1957
|
+
Avo.cliInvoked({
|
|
1958
|
+
schemaId: json.schema.id,
|
|
1959
|
+
schemaName: json.schema.name,
|
|
1960
|
+
branchId: json.branch.id,
|
|
1961
|
+
branchName: json.branch.name,
|
|
1962
|
+
userId_: installIdOrUserId(),
|
|
1963
|
+
cliAction: Avo.CliAction.CONFLICT,
|
|
1964
|
+
cliInvokedByCi: invokedByCi(),
|
|
1965
|
+
force: undefined,
|
|
1966
|
+
forceFeatures: undefined,
|
|
1967
|
+
});
|
|
1968
|
+
return Promise.resolve(json);
|
|
1969
|
+
})
|
|
1970
|
+
.catch((error) => {
|
|
1971
|
+
Avo.cliInvoked({
|
|
1972
|
+
schemaId: 'N/A',
|
|
1973
|
+
schemaName: 'N/A',
|
|
1974
|
+
branchId: 'N/A',
|
|
1975
|
+
branchName: 'N/A',
|
|
1976
|
+
userId_: installIdOrUserId(),
|
|
1977
|
+
cliAction: Avo.CliAction.CONFLICT,
|
|
1978
|
+
cliInvokedByCi: invokedByCi(),
|
|
1979
|
+
force: undefined,
|
|
1980
|
+
forceFeatures: undefined,
|
|
1981
|
+
});
|
|
1982
|
+
throw error;
|
|
1983
|
+
}),
|
|
1984
|
+
})
|
|
1985
|
+
.command({
|
|
1986
|
+
command: 'edit',
|
|
1987
|
+
describe: 'Open the Avo workspace in your browser',
|
|
1625
1988
|
handler: (argv) => {
|
|
1626
1989
|
loadAvoJsonOrInit({ argv, skipInit: false, skipPullMaster: false })
|
|
1627
1990
|
.then((json) => {
|
|
@@ -1631,432 +1994,225 @@ yargs(hideBin(process.argv)) // eslint-disable-line no-unused-expressions
|
|
|
1631
1994
|
branchId: json.branch.id,
|
|
1632
1995
|
branchName: json.branch.name,
|
|
1633
1996
|
userId_: installIdOrUserId(),
|
|
1634
|
-
cliAction: Avo.CliAction.
|
|
1997
|
+
cliAction: Avo.CliAction.EDIT,
|
|
1998
|
+
cliInvokedByCi: invokedByCi(),
|
|
1999
|
+
force: undefined,
|
|
2000
|
+
forceFeatures: undefined,
|
|
2001
|
+
});
|
|
2002
|
+
const { schema } = json;
|
|
2003
|
+
const schemaUrl = `https://www.avo.app/schemas/${schema.id}`;
|
|
2004
|
+
report.info(`Opening ${cyan(schema.name)} workspace in Avo: ${link(schemaUrl)}`);
|
|
2005
|
+
open(schemaUrl);
|
|
2006
|
+
})
|
|
2007
|
+
.catch((error) => {
|
|
2008
|
+
Avo.cliInvoked({
|
|
2009
|
+
schemaId: 'N/A',
|
|
2010
|
+
schemaName: 'N/A',
|
|
2011
|
+
branchId: 'N/A',
|
|
2012
|
+
branchName: 'N/A',
|
|
2013
|
+
userId_: installIdOrUserId(),
|
|
2014
|
+
cliAction: Avo.CliAction.EDIT,
|
|
1635
2015
|
cliInvokedByCi: invokedByCi(),
|
|
1636
2016
|
force: undefined,
|
|
1637
2017
|
forceFeatures: undefined,
|
|
1638
2018
|
});
|
|
1639
|
-
|
|
1640
|
-
|
|
2019
|
+
throw error;
|
|
2020
|
+
});
|
|
2021
|
+
},
|
|
2022
|
+
})
|
|
2023
|
+
.command({
|
|
2024
|
+
command: 'login',
|
|
2025
|
+
describe: 'Log into the Avo platform',
|
|
2026
|
+
handler: () => {
|
|
2027
|
+
const command = () => {
|
|
2028
|
+
const user = conf.get('user');
|
|
2029
|
+
if (user) {
|
|
2030
|
+
report.info(`Already logged in as ${email(user.email)}`);
|
|
1641
2031
|
return;
|
|
1642
2032
|
}
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
.then((answer) => answer.source);
|
|
1660
|
-
};
|
|
1661
|
-
getSourceToRemove(argv, json).then((targetSource) => {
|
|
1662
|
-
if (!targetSource) {
|
|
1663
|
-
report.error(`Source ${argv.source} not found in project.`);
|
|
1664
|
-
return Promise.resolve();
|
|
1665
|
-
}
|
|
1666
|
-
return inquirer
|
|
1667
|
-
.prompt([
|
|
1668
|
-
{
|
|
1669
|
-
type: 'confirm',
|
|
1670
|
-
name: 'remove',
|
|
1671
|
-
default: true,
|
|
1672
|
-
message: `Are you sure you want to remove source ${targetSource.name} from project`,
|
|
1673
|
-
},
|
|
1674
|
-
])
|
|
1675
|
-
.then((answer) => {
|
|
1676
|
-
if (answer.remove) {
|
|
1677
|
-
const sources = (json.sources ?? []).filter((source) => source.id !== targetSource.id);
|
|
1678
|
-
const newJson = { ...json, sources };
|
|
1679
|
-
return writeAvoJson(newJson).then(() => {
|
|
1680
|
-
// XXX ask to remove file as well?
|
|
1681
|
-
report.info(`Removed source ${targetSource.name} from project`);
|
|
1682
|
-
});
|
|
1683
|
-
}
|
|
1684
|
-
report.info(`Did not remove source ${targetSource.name} from project`);
|
|
1685
|
-
return Promise.resolve();
|
|
2033
|
+
login()
|
|
2034
|
+
.then((result) => {
|
|
2035
|
+
conf.set('user', result.user);
|
|
2036
|
+
conf.set('tokens', result.tokens);
|
|
2037
|
+
Avo.signedIn({
|
|
2038
|
+
userId_: result.user.user_id,
|
|
2039
|
+
email: result.user.email,
|
|
2040
|
+
authenticationMethod: Avo.AuthenticationMethod.CLI,
|
|
2041
|
+
});
|
|
2042
|
+
report.success(`Logged in as ${email(result.user.email)}`);
|
|
2043
|
+
})
|
|
2044
|
+
.catch(() => {
|
|
2045
|
+
Avo.signInFailed({
|
|
2046
|
+
userId_: conf.get('avo_install_id'),
|
|
2047
|
+
emailInput: '', // XXX this is not passed back here
|
|
2048
|
+
signInError: Avo.SignInError.UNKNOWN,
|
|
1686
2049
|
});
|
|
1687
2050
|
});
|
|
2051
|
+
};
|
|
2052
|
+
loadAvoJson()
|
|
2053
|
+
.then((json) => {
|
|
2054
|
+
Avo.cliInvoked({
|
|
2055
|
+
schemaId: json.schema.id,
|
|
2056
|
+
schemaName: json.schema.name,
|
|
2057
|
+
branchId: json.branch.id,
|
|
2058
|
+
branchName: json.branch.name,
|
|
2059
|
+
userId_: installIdOrUserId(),
|
|
2060
|
+
cliAction: Avo.CliAction.LOGIN,
|
|
2061
|
+
cliInvokedByCi: invokedByCi(),
|
|
2062
|
+
force: undefined,
|
|
2063
|
+
forceFeatures: undefined,
|
|
2064
|
+
});
|
|
2065
|
+
command();
|
|
1688
2066
|
})
|
|
1689
|
-
.catch((
|
|
2067
|
+
.catch(() => {
|
|
1690
2068
|
Avo.cliInvoked({
|
|
1691
2069
|
schemaId: 'N/A',
|
|
1692
2070
|
schemaName: 'N/A',
|
|
1693
2071
|
branchId: 'N/A',
|
|
1694
2072
|
branchName: 'N/A',
|
|
1695
2073
|
userId_: installIdOrUserId(),
|
|
1696
|
-
cliAction: Avo.CliAction.
|
|
2074
|
+
cliAction: Avo.CliAction.LOGIN,
|
|
1697
2075
|
cliInvokedByCi: invokedByCi(),
|
|
1698
2076
|
force: undefined,
|
|
1699
2077
|
forceFeatures: undefined,
|
|
1700
2078
|
});
|
|
1701
|
-
|
|
2079
|
+
command();
|
|
1702
2080
|
});
|
|
1703
2081
|
},
|
|
1704
|
-
});
|
|
1705
|
-
},
|
|
1706
|
-
})
|
|
1707
|
-
.command({
|
|
1708
|
-
command: 'status [source]',
|
|
1709
|
-
desc: 'Show the status of the Avo implementation',
|
|
1710
|
-
handler: (argv) => {
|
|
1711
|
-
loadAvoJsonOrInit({ argv, skipInit: false, skipPullMaster: false })
|
|
1712
|
-
.then((json) => {
|
|
1713
|
-
Avo.cliInvoked({
|
|
1714
|
-
schemaId: json.schema.id,
|
|
1715
|
-
schemaName: json.schema.name,
|
|
1716
|
-
branchId: json.branch.id,
|
|
1717
|
-
branchName: json.branch.name,
|
|
1718
|
-
userId_: installIdOrUserId(),
|
|
1719
|
-
cliAction: Avo.CliAction.STATUS,
|
|
1720
|
-
cliInvokedByCi: invokedByCi(),
|
|
1721
|
-
force: undefined,
|
|
1722
|
-
forceFeatures: undefined,
|
|
1723
|
-
});
|
|
1724
|
-
report.info(`Currently on branch '${json.branch.name}'`);
|
|
1725
|
-
return getSource(argv, json);
|
|
1726
2082
|
})
|
|
1727
|
-
.
|
|
1728
|
-
|
|
1729
|
-
Avo
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
},
|
|
1785
|
-
})
|
|
1786
|
-
.command({
|
|
1787
|
-
command: 'conflict',
|
|
1788
|
-
aliases: ['resolve', 'conflicts'],
|
|
1789
|
-
desc: 'Resolve git conflicts in Avo files',
|
|
1790
|
-
handler: (argv) => pify(fs.readFile)('avo.json', 'utf8')
|
|
1791
|
-
.then((avoFile) => {
|
|
1792
|
-
if (hasMergeConflicts(avoFile)) {
|
|
1793
|
-
return requireAuth(argv, () => resolveAvoJsonConflicts(avoFile, {
|
|
1794
|
-
argv,
|
|
1795
|
-
skipPullMaster: false,
|
|
1796
|
-
}).then((json) => {
|
|
1797
|
-
Avo.cliInvoked({
|
|
1798
|
-
schemaId: json.schema.id,
|
|
1799
|
-
schemaName: json.schema.name,
|
|
1800
|
-
branchId: json.branch.id,
|
|
1801
|
-
branchName: json.branch.name,
|
|
1802
|
-
userId_: installIdOrUserId(),
|
|
1803
|
-
cliAction: Avo.CliAction.CONFLICT,
|
|
1804
|
-
cliInvokedByCi: invokedByCi(),
|
|
1805
|
-
force: undefined,
|
|
1806
|
-
forceFeatures: undefined,
|
|
2083
|
+
.command({
|
|
2084
|
+
command: 'logout',
|
|
2085
|
+
describe: 'Log out from the Avo platform',
|
|
2086
|
+
handler: () => {
|
|
2087
|
+
const command = () => {
|
|
2088
|
+
const user = conf.get('user');
|
|
2089
|
+
const tokens = conf.get('tokens');
|
|
2090
|
+
const currentToken = tokens.refreshToken;
|
|
2091
|
+
const token = currentToken;
|
|
2092
|
+
api.setRefreshToken(token);
|
|
2093
|
+
if (token) {
|
|
2094
|
+
logout(token);
|
|
2095
|
+
}
|
|
2096
|
+
if (token || user || tokens) {
|
|
2097
|
+
let msg = 'Logged out';
|
|
2098
|
+
if (token === currentToken) {
|
|
2099
|
+
if (user) {
|
|
2100
|
+
msg += ` from ${bold(user.email)}`;
|
|
2101
|
+
}
|
|
2102
|
+
}
|
|
2103
|
+
else {
|
|
2104
|
+
msg += ` token "${bold(token)}"`;
|
|
2105
|
+
}
|
|
2106
|
+
report.log(msg);
|
|
2107
|
+
}
|
|
2108
|
+
else {
|
|
2109
|
+
report.log("No need to logout, you're not logged in");
|
|
2110
|
+
}
|
|
2111
|
+
};
|
|
2112
|
+
loadAvoJson()
|
|
2113
|
+
.then((json) => {
|
|
2114
|
+
Avo.cliInvoked({
|
|
2115
|
+
schemaId: json.schema.id,
|
|
2116
|
+
schemaName: json.schema.name,
|
|
2117
|
+
branchId: json.branch.id,
|
|
2118
|
+
branchName: json.branch.name,
|
|
2119
|
+
userId_: installIdOrUserId(),
|
|
2120
|
+
cliAction: Avo.CliAction.LOGOUT,
|
|
2121
|
+
cliInvokedByCi: invokedByCi(),
|
|
2122
|
+
force: undefined,
|
|
2123
|
+
forceFeatures: undefined,
|
|
2124
|
+
});
|
|
2125
|
+
command();
|
|
2126
|
+
})
|
|
2127
|
+
.catch(() => {
|
|
2128
|
+
Avo.cliInvoked({
|
|
2129
|
+
schemaId: 'N/A',
|
|
2130
|
+
schemaName: 'N/A',
|
|
2131
|
+
branchId: 'N/A',
|
|
2132
|
+
branchName: 'N/A',
|
|
2133
|
+
userId_: installIdOrUserId(),
|
|
2134
|
+
cliAction: Avo.CliAction.LOGOUT,
|
|
2135
|
+
cliInvokedByCi: invokedByCi(),
|
|
2136
|
+
force: undefined,
|
|
2137
|
+
forceFeatures: undefined,
|
|
2138
|
+
});
|
|
2139
|
+
command();
|
|
1807
2140
|
});
|
|
1808
|
-
|
|
1809
|
-
}));
|
|
1810
|
-
}
|
|
1811
|
-
report.info("No git conflicts found in avo.json. Run 'avo pull' to resolve git conflicts in other Avo files.");
|
|
1812
|
-
const json = JSON.parse(avoFile);
|
|
1813
|
-
Avo.cliInvoked({
|
|
1814
|
-
schemaId: json.schema.id,
|
|
1815
|
-
schemaName: json.schema.name,
|
|
1816
|
-
branchId: json.branch.id,
|
|
1817
|
-
branchName: json.branch.name,
|
|
1818
|
-
userId_: installIdOrUserId(),
|
|
1819
|
-
cliAction: Avo.CliAction.CONFLICT,
|
|
1820
|
-
cliInvokedByCi: invokedByCi(),
|
|
1821
|
-
force: undefined,
|
|
1822
|
-
forceFeatures: undefined,
|
|
1823
|
-
});
|
|
1824
|
-
return Promise.resolve(json);
|
|
1825
|
-
})
|
|
1826
|
-
.catch((error) => {
|
|
1827
|
-
Avo.cliInvoked({
|
|
1828
|
-
schemaId: 'N/A',
|
|
1829
|
-
schemaName: 'N/A',
|
|
1830
|
-
branchId: 'N/A',
|
|
1831
|
-
branchName: 'N/A',
|
|
1832
|
-
userId_: installIdOrUserId(),
|
|
1833
|
-
cliAction: Avo.CliAction.CONFLICT,
|
|
1834
|
-
cliInvokedByCi: invokedByCi(),
|
|
1835
|
-
force: undefined,
|
|
1836
|
-
forceFeatures: undefined,
|
|
1837
|
-
});
|
|
1838
|
-
throw error;
|
|
1839
|
-
}),
|
|
1840
|
-
})
|
|
1841
|
-
.command({
|
|
1842
|
-
command: 'edit',
|
|
1843
|
-
desc: 'Open the Avo workspace in your browser',
|
|
1844
|
-
handler: (argv) => {
|
|
1845
|
-
loadAvoJsonOrInit({ argv, skipInit: false, skipPullMaster: false })
|
|
1846
|
-
.then((json) => {
|
|
1847
|
-
Avo.cliInvoked({
|
|
1848
|
-
schemaId: json.schema.id,
|
|
1849
|
-
schemaName: json.schema.name,
|
|
1850
|
-
branchId: json.branch.id,
|
|
1851
|
-
branchName: json.branch.name,
|
|
1852
|
-
userId_: installIdOrUserId(),
|
|
1853
|
-
cliAction: Avo.CliAction.EDIT,
|
|
1854
|
-
cliInvokedByCi: invokedByCi(),
|
|
1855
|
-
force: undefined,
|
|
1856
|
-
forceFeatures: undefined,
|
|
1857
|
-
});
|
|
1858
|
-
const { schema } = json;
|
|
1859
|
-
const schemaUrl = `https://www.avo.app/schemas/${schema.id}`;
|
|
1860
|
-
report.info(`Opening ${cyan(schema.name)} workspace in Avo: ${link(schemaUrl)}`);
|
|
1861
|
-
open(schemaUrl);
|
|
2141
|
+
},
|
|
1862
2142
|
})
|
|
1863
|
-
.
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
2143
|
+
.command({
|
|
2144
|
+
command: 'whoami',
|
|
2145
|
+
describe: 'Shows the currently logged in username',
|
|
2146
|
+
handler: (argv) => {
|
|
2147
|
+
const command = () => {
|
|
2148
|
+
requireAuth(argv, () => {
|
|
2149
|
+
if (conf.has('user')) {
|
|
2150
|
+
const user = conf.get('user');
|
|
2151
|
+
report.info(`Logged in as ${email(user.email)}`);
|
|
2152
|
+
}
|
|
2153
|
+
else {
|
|
2154
|
+
report.warn('Not logged in');
|
|
2155
|
+
}
|
|
2156
|
+
});
|
|
2157
|
+
};
|
|
2158
|
+
loadAvoJson()
|
|
2159
|
+
.then((json) => {
|
|
2160
|
+
Avo.cliInvoked({
|
|
2161
|
+
schemaId: json.schema.id,
|
|
2162
|
+
schemaName: json.schema.name,
|
|
2163
|
+
branchId: json.branch.id,
|
|
2164
|
+
branchName: json.branch.name,
|
|
2165
|
+
userId_: installIdOrUserId(),
|
|
2166
|
+
cliAction: Avo.CliAction.WHOAMI,
|
|
2167
|
+
cliInvokedByCi: invokedByCi(),
|
|
2168
|
+
force: undefined,
|
|
2169
|
+
forceFeatures: undefined,
|
|
2170
|
+
});
|
|
2171
|
+
command();
|
|
2172
|
+
})
|
|
2173
|
+
.catch(() => {
|
|
2174
|
+
Avo.cliInvoked({
|
|
2175
|
+
schemaId: 'N/A',
|
|
2176
|
+
schemaName: 'N/A',
|
|
2177
|
+
branchId: 'N/A',
|
|
2178
|
+
branchName: 'N/A',
|
|
2179
|
+
userId_: installIdOrUserId(),
|
|
2180
|
+
cliAction: Avo.CliAction.WHOAMI,
|
|
2181
|
+
cliInvokedByCi: invokedByCi(),
|
|
2182
|
+
force: undefined,
|
|
2183
|
+
forceFeatures: undefined,
|
|
2184
|
+
});
|
|
2185
|
+
command();
|
|
1905
2186
|
});
|
|
1906
|
-
}
|
|
1907
|
-
};
|
|
1908
|
-
loadAvoJson()
|
|
1909
|
-
.then((json) => {
|
|
1910
|
-
Avo.cliInvoked({
|
|
1911
|
-
schemaId: json.schema.id,
|
|
1912
|
-
schemaName: json.schema.name,
|
|
1913
|
-
branchId: json.branch.id,
|
|
1914
|
-
branchName: json.branch.name,
|
|
1915
|
-
userId_: installIdOrUserId(),
|
|
1916
|
-
cliAction: Avo.CliAction.LOGIN,
|
|
1917
|
-
cliInvokedByCi: invokedByCi(),
|
|
1918
|
-
force: undefined,
|
|
1919
|
-
forceFeatures: undefined,
|
|
1920
|
-
});
|
|
1921
|
-
command();
|
|
2187
|
+
},
|
|
1922
2188
|
})
|
|
1923
|
-
.
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
handler: () => {
|
|
1943
|
-
const command = () => {
|
|
1944
|
-
const user = conf.get('user');
|
|
1945
|
-
const tokens = conf.get('tokens');
|
|
1946
|
-
const currentToken = tokens.refreshToken;
|
|
1947
|
-
const token = currentToken;
|
|
1948
|
-
api.setRefreshToken(token);
|
|
1949
|
-
if (token) {
|
|
1950
|
-
logout(token);
|
|
1951
|
-
}
|
|
1952
|
-
if (token || user || tokens) {
|
|
1953
|
-
let msg = 'Logged out';
|
|
1954
|
-
if (token === currentToken) {
|
|
1955
|
-
if (user) {
|
|
1956
|
-
msg += ` from ${bold(user.email)}`;
|
|
1957
|
-
}
|
|
1958
|
-
}
|
|
1959
|
-
else {
|
|
1960
|
-
msg += ` token "${bold(token)}"`;
|
|
1961
|
-
}
|
|
1962
|
-
report.log(msg);
|
|
2189
|
+
.demandCommand(1, 'must provide a valid command')
|
|
2190
|
+
.recommendCommands()
|
|
2191
|
+
.help().argv;
|
|
2192
|
+
}
|
|
2193
|
+
catch (err) {
|
|
2194
|
+
// Always log yargs errors for visibility (e.g., in tests)
|
|
2195
|
+
report.error(`yargs error: ${err instanceof Error ? err.message : String(err)}`);
|
|
2196
|
+
// Only exit if we're actually running as the main module
|
|
2197
|
+
if (isMainModule) {
|
|
2198
|
+
throw err;
|
|
2199
|
+
}
|
|
2200
|
+
}
|
|
2201
|
+
/// ///////////////// ////////
|
|
2202
|
+
// catch unhandled promises
|
|
2203
|
+
if (isMainModule) {
|
|
2204
|
+
process.on('unhandledRejection', (err) => {
|
|
2205
|
+
cancelWait();
|
|
2206
|
+
if (!(err instanceof Error) && !(err instanceof AvoError)) {
|
|
2207
|
+
report.error(new AvoError(`Promise rejected with value: ${util.inspect(err)}`));
|
|
1963
2208
|
}
|
|
1964
2209
|
else {
|
|
1965
|
-
|
|
2210
|
+
// @ts-ignore
|
|
2211
|
+
report.error(err.message);
|
|
1966
2212
|
}
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
.
|
|
1970
|
-
Avo.cliInvoked({
|
|
1971
|
-
schemaId: json.schema.id,
|
|
1972
|
-
schemaName: json.schema.name,
|
|
1973
|
-
branchId: json.branch.id,
|
|
1974
|
-
branchName: json.branch.name,
|
|
1975
|
-
userId_: installIdOrUserId(),
|
|
1976
|
-
cliAction: Avo.CliAction.LOGOUT,
|
|
1977
|
-
cliInvokedByCi: invokedByCi(),
|
|
1978
|
-
force: undefined,
|
|
1979
|
-
forceFeatures: undefined,
|
|
1980
|
-
});
|
|
1981
|
-
command();
|
|
1982
|
-
})
|
|
1983
|
-
.catch(() => {
|
|
1984
|
-
Avo.cliInvoked({
|
|
1985
|
-
schemaId: 'N/A',
|
|
1986
|
-
schemaName: 'N/A',
|
|
1987
|
-
branchId: 'N/A',
|
|
1988
|
-
branchName: 'N/A',
|
|
1989
|
-
userId_: installIdOrUserId(),
|
|
1990
|
-
cliAction: Avo.CliAction.LOGOUT,
|
|
1991
|
-
cliInvokedByCi: invokedByCi(),
|
|
1992
|
-
force: undefined,
|
|
1993
|
-
forceFeatures: undefined,
|
|
1994
|
-
});
|
|
1995
|
-
command();
|
|
2213
|
+
// @ts-ignore
|
|
2214
|
+
// console.error(err.stack);
|
|
2215
|
+
process.exit(1);
|
|
1996
2216
|
});
|
|
1997
|
-
},
|
|
1998
|
-
})
|
|
1999
|
-
.command({
|
|
2000
|
-
command: 'whoami',
|
|
2001
|
-
desc: 'Shows the currently logged in username',
|
|
2002
|
-
handler: (argv) => {
|
|
2003
|
-
const command = () => {
|
|
2004
|
-
requireAuth(argv, () => {
|
|
2005
|
-
if (conf.has('user')) {
|
|
2006
|
-
const user = conf.get('user');
|
|
2007
|
-
report.info(`Logged in as ${email(user.email)}`);
|
|
2008
|
-
}
|
|
2009
|
-
else {
|
|
2010
|
-
report.warn('Not logged in');
|
|
2011
|
-
}
|
|
2012
|
-
});
|
|
2013
|
-
};
|
|
2014
|
-
loadAvoJson()
|
|
2015
|
-
.then((json) => {
|
|
2016
|
-
Avo.cliInvoked({
|
|
2017
|
-
schemaId: json.schema.id,
|
|
2018
|
-
schemaName: json.schema.name,
|
|
2019
|
-
branchId: json.branch.id,
|
|
2020
|
-
branchName: json.branch.name,
|
|
2021
|
-
userId_: installIdOrUserId(),
|
|
2022
|
-
cliAction: Avo.CliAction.WHOAMI,
|
|
2023
|
-
cliInvokedByCi: invokedByCi(),
|
|
2024
|
-
force: undefined,
|
|
2025
|
-
forceFeatures: undefined,
|
|
2026
|
-
});
|
|
2027
|
-
command();
|
|
2028
|
-
})
|
|
2029
|
-
.catch(() => {
|
|
2030
|
-
Avo.cliInvoked({
|
|
2031
|
-
schemaId: 'N/A',
|
|
2032
|
-
schemaName: 'N/A',
|
|
2033
|
-
branchId: 'N/A',
|
|
2034
|
-
branchName: 'N/A',
|
|
2035
|
-
userId_: installIdOrUserId(),
|
|
2036
|
-
cliAction: Avo.CliAction.WHOAMI,
|
|
2037
|
-
cliInvokedByCi: invokedByCi(),
|
|
2038
|
-
force: undefined,
|
|
2039
|
-
forceFeatures: undefined,
|
|
2040
|
-
});
|
|
2041
|
-
command();
|
|
2042
|
-
});
|
|
2043
|
-
},
|
|
2044
|
-
})
|
|
2045
|
-
.demandCommand(1, 'must provide a valid command')
|
|
2046
|
-
.recommendCommands()
|
|
2047
|
-
.help().argv;
|
|
2048
|
-
/// ///////////////// ////////
|
|
2049
|
-
// catch unhandled promises
|
|
2050
|
-
process.on('unhandledRejection', (err) => {
|
|
2051
|
-
cancelWait();
|
|
2052
|
-
if (!(err instanceof Error) && !(err instanceof AvoError)) {
|
|
2053
|
-
report.error(new AvoError(`Promise rejected with value: ${util.inspect(err)}`));
|
|
2054
|
-
}
|
|
2055
|
-
else {
|
|
2056
|
-
// @ts-ignore
|
|
2057
|
-
report.error(err.message);
|
|
2058
2217
|
}
|
|
2059
|
-
|
|
2060
|
-
// console.error(err.stack);
|
|
2061
|
-
process.exit(1);
|
|
2062
|
-
});
|
|
2218
|
+
}
|