@vocoder/cli 0.1.14 → 0.1.16
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/dist/bin.mjs +158 -50
- package/dist/bin.mjs.map +1 -1
- package/package.json +1 -1
package/dist/bin.mjs
CHANGED
|
@@ -1249,7 +1249,7 @@ function filterItems(items, query) {
|
|
|
1249
1249
|
const lower = query.toLowerCase();
|
|
1250
1250
|
return items.filter((i) => i.value.toLowerCase().includes(lower));
|
|
1251
1251
|
}
|
|
1252
|
-
function buildList2(filtered, cursor, scrollOffset, selected, filter, customPatterns, addCursor) {
|
|
1252
|
+
function buildList2(filtered, cursor, scrollOffset, selected, filter, customPatterns, addCursor, optional = false) {
|
|
1253
1253
|
const lines = [];
|
|
1254
1254
|
const end = Math.min(filtered.length, scrollOffset + MAX_VISIBLE2);
|
|
1255
1255
|
for (let i = scrollOffset; i < end; i++) {
|
|
@@ -1274,11 +1274,16 @@ function buildList2(filtered, cursor, scrollOffset, selected, filter, customPatt
|
|
|
1274
1274
|
}
|
|
1275
1275
|
const hidden = filtered.length - (end - scrollOffset);
|
|
1276
1276
|
if (hidden > 0) lines.push(dim2(`${S_BAR2} ${hidden} more`));
|
|
1277
|
-
if (selected.size > 0)
|
|
1277
|
+
if (selected.size > 0) {
|
|
1278
|
+
lines.push(dim2(`${S_BAR2} ${selected.size} selected \u2014 Enter to confirm`));
|
|
1279
|
+
} else if (optional) {
|
|
1280
|
+
lines.push(dim2(`${S_BAR2} Enter to skip`));
|
|
1281
|
+
}
|
|
1278
1282
|
return lines.join("\n");
|
|
1279
1283
|
}
|
|
1280
1284
|
async function filterableBranchSelect(params) {
|
|
1281
1285
|
const { message, branches, defaultBranch } = params;
|
|
1286
|
+
const optional = params.optional ?? false;
|
|
1282
1287
|
let filter = "";
|
|
1283
1288
|
let cursor = 0;
|
|
1284
1289
|
let scrollOffset = 0;
|
|
@@ -1305,7 +1310,7 @@ async function filterableBranchSelect(params) {
|
|
|
1305
1310
|
const prompt = new Prompt2(
|
|
1306
1311
|
{
|
|
1307
1312
|
validate() {
|
|
1308
|
-
if (selected.size === 0) return "At least one branch is required.";
|
|
1313
|
+
if (!optional && selected.size === 0) return "At least one branch is required.";
|
|
1309
1314
|
return void 0;
|
|
1310
1315
|
},
|
|
1311
1316
|
render() {
|
|
@@ -1326,7 +1331,7 @@ ${symbol2(this.state)} ${message}
|
|
|
1326
1331
|
return [
|
|
1327
1332
|
hdr.trimEnd(),
|
|
1328
1333
|
`${ylw2(S_BAR2)} ${dim2("/")} ${hint}`,
|
|
1329
|
-
buildList2(filtered, cursor, scrollOffset, selected, filter, customPatterns, addCursor),
|
|
1334
|
+
buildList2(filtered, cursor, scrollOffset, selected, filter, customPatterns, addCursor, optional),
|
|
1330
1335
|
`${ylw2(S_BAR_END2)} ${ylw2(this.error)}`,
|
|
1331
1336
|
""
|
|
1332
1337
|
].join("\n");
|
|
@@ -1334,7 +1339,7 @@ ${symbol2(this.state)} ${message}
|
|
|
1334
1339
|
return [
|
|
1335
1340
|
hdr.trimEnd(),
|
|
1336
1341
|
`${cyan2(S_BAR2)} ${dim2("/")} ${hint}`,
|
|
1337
|
-
buildList2(filtered, cursor, scrollOffset, selected, filter, customPatterns, addCursor),
|
|
1342
|
+
buildList2(filtered, cursor, scrollOffset, selected, filter, customPatterns, addCursor, optional),
|
|
1338
1343
|
`${cyan2(S_BAR_END2)}`,
|
|
1339
1344
|
""
|
|
1340
1345
|
].join("\n");
|
|
@@ -1472,12 +1477,12 @@ async function runProjectCreate(params) {
|
|
|
1472
1477
|
}
|
|
1473
1478
|
const detected = detectGitBranches();
|
|
1474
1479
|
const initialBranches = params.defaultBranches?.length ? params.defaultBranches : [detected.defaultBranch];
|
|
1475
|
-
let
|
|
1480
|
+
let pushBranches = [];
|
|
1476
1481
|
{
|
|
1477
1482
|
let initial = initialBranches;
|
|
1478
|
-
while (
|
|
1483
|
+
while (pushBranches.length === 0) {
|
|
1479
1484
|
const result = await filterableBranchSelect({
|
|
1480
|
-
message: "
|
|
1485
|
+
message: "Translate on push \u2014 which branches?",
|
|
1481
1486
|
branches: detected.branches,
|
|
1482
1487
|
defaultBranch: detected.defaultBranch,
|
|
1483
1488
|
initialValues: initial
|
|
@@ -1487,24 +1492,54 @@ async function runProjectCreate(params) {
|
|
|
1487
1492
|
p3.log.warn("At least one branch is required. Please select at least one.");
|
|
1488
1493
|
initial = [detected.defaultBranch];
|
|
1489
1494
|
} else {
|
|
1490
|
-
|
|
1495
|
+
pushBranches = result;
|
|
1491
1496
|
}
|
|
1492
1497
|
}
|
|
1493
1498
|
}
|
|
1494
|
-
const
|
|
1495
|
-
message: "
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1499
|
+
const prResult = await filterableBranchSelect({
|
|
1500
|
+
message: "Translate on pull requests \u2014 which branches? (optional)",
|
|
1501
|
+
branches: detected.branches,
|
|
1502
|
+
defaultBranch: detected.defaultBranch,
|
|
1503
|
+
initialValues: [],
|
|
1504
|
+
optional: true
|
|
1505
|
+
});
|
|
1506
|
+
if (prResult === null) return null;
|
|
1507
|
+
const prBranches = prResult;
|
|
1508
|
+
const autoSet = /* @__PURE__ */ new Set([...pushBranches, ...prBranches]);
|
|
1509
|
+
const manualResult = await filterableBranchSelect({
|
|
1510
|
+
message: `Manual-only branches \u2014 translate via \`vocoder sync\` only (optional)`,
|
|
1511
|
+
branches: detected.branches.filter((b) => !autoSet.has(b)),
|
|
1512
|
+
defaultBranch: detected.defaultBranch,
|
|
1513
|
+
initialValues: [],
|
|
1514
|
+
optional: true
|
|
1515
|
+
});
|
|
1516
|
+
if (manualResult === null) return null;
|
|
1517
|
+
const manualBranches = manualResult.filter((b) => {
|
|
1518
|
+
if (autoSet.has(b)) {
|
|
1519
|
+
p3.log.warn(`"${b}" is already configured for automatic translation \u2014 skipping from manual.`);
|
|
1520
|
+
return false;
|
|
1521
|
+
}
|
|
1522
|
+
return true;
|
|
1502
1523
|
});
|
|
1503
|
-
if (
|
|
1504
|
-
|
|
1505
|
-
|
|
1524
|
+
if (pushBranches.length === 0 && prBranches.length === 0 && manualBranches.length === 0) {
|
|
1525
|
+
p3.log.error("At least one branch must be configured.");
|
|
1526
|
+
return null;
|
|
1527
|
+
}
|
|
1528
|
+
const triggerMap = /* @__PURE__ */ new Map();
|
|
1529
|
+
for (const b of pushBranches) {
|
|
1530
|
+
if (!triggerMap.has(b)) triggerMap.set(b, /* @__PURE__ */ new Set());
|
|
1531
|
+
triggerMap.get(b).add("push");
|
|
1532
|
+
}
|
|
1533
|
+
for (const b of prBranches) {
|
|
1534
|
+
if (!triggerMap.has(b)) triggerMap.set(b, /* @__PURE__ */ new Set());
|
|
1535
|
+
triggerMap.get(b).add("pull_request");
|
|
1536
|
+
}
|
|
1537
|
+
for (const b of manualBranches) {
|
|
1538
|
+
triggerMap.set(b, /* @__PURE__ */ new Set(["manual"]));
|
|
1539
|
+
}
|
|
1540
|
+
const branchTriggers = Array.from(triggerMap.entries()).map(([pattern, triggers]) => ({
|
|
1506
1541
|
pattern,
|
|
1507
|
-
triggers:
|
|
1542
|
+
triggers: Array.from(triggers)
|
|
1508
1543
|
}));
|
|
1509
1544
|
try {
|
|
1510
1545
|
const result = await api.createProject(userToken, {
|
|
@@ -1577,40 +1612,65 @@ async function runProjectAppCreate(params) {
|
|
|
1577
1612
|
if (targetLocales.length === 0) {
|
|
1578
1613
|
p3.log.warn("No target languages selected \u2014 you can add them later from the dashboard.");
|
|
1579
1614
|
}
|
|
1580
|
-
const
|
|
1581
|
-
|
|
1582
|
-
options: [
|
|
1583
|
-
{ value: "push", label: "On push to target branches" },
|
|
1584
|
-
{ value: "pull_request", label: "On pull requests" },
|
|
1585
|
-
{ value: "push_and_pr", label: "On push and pull requests" },
|
|
1586
|
-
{ value: "manual", label: "Manual only", hint: "use vocoder sync or trigger from dashboard" }
|
|
1587
|
-
]
|
|
1588
|
-
});
|
|
1589
|
-
if (p3.isCancel(triggerChoice)) return null;
|
|
1590
|
-
const triggersForBranch = triggerChoice === "push_and_pr" ? ["push", "pull_request"] : [triggerChoice];
|
|
1591
|
-
const detected = detectGitBranches();
|
|
1592
|
-
let selectedBranches = [];
|
|
1615
|
+
const detectedApp = detectGitBranches();
|
|
1616
|
+
let appPushBranches = [];
|
|
1593
1617
|
{
|
|
1594
|
-
let initial = [
|
|
1595
|
-
while (
|
|
1618
|
+
let initial = [detectedApp.defaultBranch];
|
|
1619
|
+
while (appPushBranches.length === 0) {
|
|
1596
1620
|
const result = await filterableBranchSelect({
|
|
1597
|
-
message: "
|
|
1598
|
-
branches:
|
|
1599
|
-
defaultBranch:
|
|
1621
|
+
message: "Translate on push \u2014 which branches?",
|
|
1622
|
+
branches: detectedApp.branches,
|
|
1623
|
+
defaultBranch: detectedApp.defaultBranch,
|
|
1600
1624
|
initialValues: initial
|
|
1601
1625
|
});
|
|
1602
1626
|
if (result === null) return null;
|
|
1603
1627
|
if (result.length === 0) {
|
|
1604
1628
|
p3.log.warn("At least one branch is required.");
|
|
1605
|
-
initial = [
|
|
1629
|
+
initial = [detectedApp.defaultBranch];
|
|
1606
1630
|
} else {
|
|
1607
|
-
|
|
1631
|
+
appPushBranches = result;
|
|
1608
1632
|
}
|
|
1609
1633
|
}
|
|
1610
1634
|
}
|
|
1611
|
-
const
|
|
1635
|
+
const appPrResult = await filterableBranchSelect({
|
|
1636
|
+
message: "Translate on pull requests \u2014 which branches? (optional)",
|
|
1637
|
+
branches: detectedApp.branches,
|
|
1638
|
+
defaultBranch: detectedApp.defaultBranch,
|
|
1639
|
+
initialValues: [],
|
|
1640
|
+
optional: true
|
|
1641
|
+
});
|
|
1642
|
+
if (appPrResult === null) return null;
|
|
1643
|
+
const appAutoSet = /* @__PURE__ */ new Set([...appPushBranches, ...appPrResult]);
|
|
1644
|
+
const appManualResult = await filterableBranchSelect({
|
|
1645
|
+
message: "Manual-only branches (optional)",
|
|
1646
|
+
branches: detectedApp.branches.filter((b) => !appAutoSet.has(b)),
|
|
1647
|
+
defaultBranch: detectedApp.defaultBranch,
|
|
1648
|
+
initialValues: [],
|
|
1649
|
+
optional: true
|
|
1650
|
+
});
|
|
1651
|
+
if (appManualResult === null) return null;
|
|
1652
|
+
const appManualBranches = appManualResult.filter((b) => {
|
|
1653
|
+
if (appAutoSet.has(b)) {
|
|
1654
|
+
p3.log.warn(`"${b}" is already configured for automatic translation \u2014 skipping from manual.`);
|
|
1655
|
+
return false;
|
|
1656
|
+
}
|
|
1657
|
+
return true;
|
|
1658
|
+
});
|
|
1659
|
+
const appTriggerMap = /* @__PURE__ */ new Map();
|
|
1660
|
+
for (const b of appPushBranches) {
|
|
1661
|
+
if (!appTriggerMap.has(b)) appTriggerMap.set(b, /* @__PURE__ */ new Set());
|
|
1662
|
+
appTriggerMap.get(b).add("push");
|
|
1663
|
+
}
|
|
1664
|
+
for (const b of appPrResult) {
|
|
1665
|
+
if (!appTriggerMap.has(b)) appTriggerMap.set(b, /* @__PURE__ */ new Set());
|
|
1666
|
+
appTriggerMap.get(b).add("pull_request");
|
|
1667
|
+
}
|
|
1668
|
+
for (const b of appManualBranches) {
|
|
1669
|
+
appTriggerMap.set(b, /* @__PURE__ */ new Set(["manual"]));
|
|
1670
|
+
}
|
|
1671
|
+
const branchTriggers = Array.from(appTriggerMap.entries()).map(([pattern, triggers]) => ({
|
|
1612
1672
|
pattern,
|
|
1613
|
-
triggers:
|
|
1673
|
+
triggers: Array.from(triggers)
|
|
1614
1674
|
}));
|
|
1615
1675
|
try {
|
|
1616
1676
|
const result = await api.createProjectApp(userToken, {
|
|
@@ -2332,20 +2392,68 @@ async function init(options = {}) {
|
|
|
2332
2392
|
p5.log.warn(
|
|
2333
2393
|
`Project limit reached \u2014 ${ws.projectCount}/${ws.maxProjects} on your ${chalk6.bold(ws.planId)} plan.`
|
|
2334
2394
|
);
|
|
2395
|
+
const hasRepoContext = !!identity?.repoCanonical;
|
|
2396
|
+
const options2 = [];
|
|
2397
|
+
if (hasRepoContext) {
|
|
2398
|
+
options2.push({
|
|
2399
|
+
value: "connect",
|
|
2400
|
+
label: "Connect this repo to an existing project"
|
|
2401
|
+
});
|
|
2402
|
+
}
|
|
2403
|
+
options2.push({ value: "upgrade", label: "Upgrade plan" });
|
|
2404
|
+
options2.push({ value: "cancel", label: "Cancel" });
|
|
2335
2405
|
const limitAction = await p5.select({
|
|
2336
2406
|
message: "What would you like to do?",
|
|
2337
|
-
options:
|
|
2338
|
-
{ value: "upgrade", label: "Upgrade plan" },
|
|
2339
|
-
{ value: "cancel", label: "Cancel" }
|
|
2340
|
-
]
|
|
2407
|
+
options: options2
|
|
2341
2408
|
});
|
|
2342
2409
|
if (p5.isCancel(limitAction) || limitAction === "cancel") {
|
|
2343
2410
|
p5.cancel("Setup cancelled.");
|
|
2344
2411
|
return 1;
|
|
2345
2412
|
}
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2413
|
+
if (limitAction === "upgrade") {
|
|
2414
|
+
await tryOpenBrowser2(`${apiUrl}${SUBSCRIPTION_SETTINGS_PATH}`);
|
|
2415
|
+
p5.cancel("Upgrade your plan in the browser, then re-run `vocoder init`.");
|
|
2416
|
+
return 1;
|
|
2417
|
+
}
|
|
2418
|
+
const existingProjects = await api.listProjects(userToken, selectedWorkspaceId);
|
|
2419
|
+
if (existingProjects.length === 0) {
|
|
2420
|
+
p5.log.error("No projects found in this workspace.");
|
|
2421
|
+
return 1;
|
|
2422
|
+
}
|
|
2423
|
+
const chosenId = await p5.select({
|
|
2424
|
+
message: "Which project should this repo be connected to?",
|
|
2425
|
+
options: existingProjects.map((proj) => ({
|
|
2426
|
+
value: proj.id,
|
|
2427
|
+
label: proj.name
|
|
2428
|
+
}))
|
|
2429
|
+
});
|
|
2430
|
+
if (p5.isCancel(chosenId)) {
|
|
2431
|
+
p5.cancel("Setup cancelled.");
|
|
2432
|
+
return 1;
|
|
2433
|
+
}
|
|
2434
|
+
const chosen = existingProjects.find((proj) => proj.id === chosenId);
|
|
2435
|
+
const appResult = await runProjectAppCreate({
|
|
2436
|
+
api,
|
|
2437
|
+
userToken,
|
|
2438
|
+
projectId: chosen.id,
|
|
2439
|
+
projectName: chosen.name,
|
|
2440
|
+
organizationName: selectedWorkspaceName,
|
|
2441
|
+
repoCanonical: identity?.repoCanonical,
|
|
2442
|
+
defaultScopePath: identity?.repoScopePath,
|
|
2443
|
+
existingApps: []
|
|
2444
|
+
});
|
|
2445
|
+
if (!appResult) {
|
|
2446
|
+
p5.log.error("Setup failed. Run `vocoder init` again.");
|
|
2447
|
+
return 1;
|
|
2448
|
+
}
|
|
2449
|
+
runScaffold({
|
|
2450
|
+
projectName: appResult.projectName,
|
|
2451
|
+
organizationName: selectedWorkspaceName,
|
|
2452
|
+
sourceLocale: appResult.sourceLocale,
|
|
2453
|
+
branchTriggers: appResult.branchTriggers
|
|
2454
|
+
});
|
|
2455
|
+
p5.outro("You're all set.");
|
|
2456
|
+
return 0;
|
|
2349
2457
|
}
|
|
2350
2458
|
} catch {
|
|
2351
2459
|
}
|