@vocoder/cli 0.12.0 → 0.12.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/README.md +3 -3
- package/dist/bin.mjs +35 -64
- package/dist/bin.mjs.map +1 -1
- package/dist/{chunk-XUCVAFBG.mjs → chunk-SR6SDGUI.mjs} +4 -4
- package/dist/{chunk-XUCVAFBG.mjs.map → chunk-SR6SDGUI.mjs.map} +1 -1
- package/dist/lib.d.mts +7 -6
- package/dist/lib.mjs +1 -1
- package/dist/lib.mjs.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -100,13 +100,13 @@ When running `vocoder init` from a subdirectory of a git repository, the CLI aut
|
|
|
100
100
|
|
|
101
101
|
**Stored credentials:**
|
|
102
102
|
|
|
103
|
-
After first sign-in, the CLI stores credentials at `~/.
|
|
103
|
+
After first sign-in, the CLI stores credentials at `~/.vocoder/auth.json` (mode `0600`). Tokens do not expire. Use `vocoder logout` to revoke.
|
|
104
104
|
|
|
105
105
|
**Token resolution:**
|
|
106
106
|
|
|
107
107
|
| Command | Source |
|
|
108
108
|
|---|---|
|
|
109
|
-
| `vocoder init` | `VOCODER_AUTH_TOKEN` env var → `~/.
|
|
109
|
+
| `vocoder init` | `VOCODER_AUTH_TOKEN` env var → `~/.vocoder/auth.json` |
|
|
110
110
|
| `vocoder sync` | `VOCODER_API_KEY` env var → `.env` file |
|
|
111
111
|
| MCP tools | `VOCODER_API_KEY` env var |
|
|
112
112
|
|
|
@@ -274,7 +274,7 @@ Git repository is auto-detected from the current directory's git remote. Use `--
|
|
|
274
274
|
|
|
275
275
|
### `vocoder logout`
|
|
276
276
|
|
|
277
|
-
Revoke the stored credentials and clear `~/.
|
|
277
|
+
Revoke the stored credentials and clear `~/.vocoder/auth.json`.
|
|
278
278
|
|
|
279
279
|
```bash
|
|
280
280
|
vocoder logout
|
package/dist/bin.mjs
CHANGED
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
readAuthData,
|
|
14
14
|
verifyStoredAuth,
|
|
15
15
|
writeAuthData
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-SR6SDGUI.mjs";
|
|
17
17
|
|
|
18
18
|
// src/bin.ts
|
|
19
19
|
import { Command } from "commander";
|
|
@@ -41,17 +41,21 @@ function writeVocoderConfig(options) {
|
|
|
41
41
|
const {
|
|
42
42
|
targetBranches = ["main"],
|
|
43
43
|
useTypeScript = true,
|
|
44
|
-
cwd = process.cwd()
|
|
44
|
+
cwd = process.cwd(),
|
|
45
|
+
appDir
|
|
45
46
|
} = options;
|
|
46
47
|
if (findExistingConfig(cwd)) return null;
|
|
47
48
|
const ext = useTypeScript ? "ts" : "js";
|
|
48
49
|
const configPath = join(cwd, `vocoder.config.${ext}`);
|
|
49
50
|
const branchesStr = targetBranches.map((b) => `'${b}'`).join(", ");
|
|
51
|
+
const defaultIncludes = ["**/*.{tsx,jsx,ts,js}"];
|
|
52
|
+
const includes = appDir ? defaultIncludes.map((p14) => `${appDir}/${p14}`) : defaultIncludes;
|
|
53
|
+
const includesStr = includes.map((p14) => `'${p14}'`).join(", ");
|
|
50
54
|
const content = `import { defineConfig } from '@vocoder/config'
|
|
51
55
|
|
|
52
56
|
export default defineConfig({
|
|
53
57
|
targetBranches: [${branchesStr}],
|
|
54
|
-
include: [
|
|
58
|
+
include: [${includesStr}],
|
|
55
59
|
exclude: [
|
|
56
60
|
'**/node_modules/**',
|
|
57
61
|
'**/.next/**',
|
|
@@ -878,25 +882,9 @@ async function runProjectCreate(params) {
|
|
|
878
882
|
return null;
|
|
879
883
|
}
|
|
880
884
|
const languageOptions = buildLanguageOptions(sourceLocales);
|
|
881
|
-
|
|
882
|
-
if (
|
|
883
|
-
appDir = params.defaultAppDir;
|
|
885
|
+
const appDir = params.defaultAppDir ?? "";
|
|
886
|
+
if (appDir) {
|
|
884
887
|
p3.log.success(`App directory: ${chalk4.bold(appDir)}`);
|
|
885
|
-
} else {
|
|
886
|
-
const rawScope = await p3.text({
|
|
887
|
-
message: "App directory (leave blank for the entire repo)",
|
|
888
|
-
placeholder: "e.g. apps/web, packages/frontend",
|
|
889
|
-
initialValue: "",
|
|
890
|
-
validate(value) {
|
|
891
|
-
const v = value.trim();
|
|
892
|
-
if (!v) return;
|
|
893
|
-
if (v.startsWith("/"))
|
|
894
|
-
return "Use a relative path, not an absolute path";
|
|
895
|
-
if (v.includes("..")) return 'Path must not contain ".."';
|
|
896
|
-
}
|
|
897
|
-
});
|
|
898
|
-
if (p3.isCancel(rawScope)) return null;
|
|
899
|
-
appDir = (rawScope ?? "").trim();
|
|
900
888
|
}
|
|
901
889
|
const sourceLocale = await searchSelectLocale(
|
|
902
890
|
languageOptions,
|
|
@@ -969,7 +957,7 @@ async function runProjectCreate(params) {
|
|
|
969
957
|
return null;
|
|
970
958
|
}
|
|
971
959
|
}
|
|
972
|
-
async function
|
|
960
|
+
async function runAppCreate(params) {
|
|
973
961
|
const { api, userToken, projectId, projectName, repoCanonical } = params;
|
|
974
962
|
const existingScopes = new Set(params.existingApps.map((a) => a.appDir));
|
|
975
963
|
let sourceLocales;
|
|
@@ -982,35 +970,13 @@ async function runProjectAppCreate(params) {
|
|
|
982
970
|
return null;
|
|
983
971
|
}
|
|
984
972
|
const languageOptions = buildLanguageOptions(sourceLocales);
|
|
985
|
-
|
|
986
|
-
if (
|
|
987
|
-
appDir
|
|
973
|
+
const appDir = params.defaultAppDir ?? "";
|
|
974
|
+
if (existingScopes.has(appDir)) {
|
|
975
|
+
p3.log.error(`App directory "${appDir}" is already configured for this project.`);
|
|
976
|
+
return null;
|
|
977
|
+
}
|
|
978
|
+
if (appDir) {
|
|
988
979
|
p3.log.success(`App directory: ${chalk4.bold(appDir)}`);
|
|
989
|
-
} else {
|
|
990
|
-
if (params.existingApps.length > 0) {
|
|
991
|
-
const configuredList = params.existingApps.map((a) => chalk4.dim(a.appDir || "(entire repo)")).join(", ");
|
|
992
|
-
p3.log.info(`Already configured: ${configuredList}`);
|
|
993
|
-
}
|
|
994
|
-
const hasWholeRepoApp = existingScopes.has("");
|
|
995
|
-
const rawScope = await p3.text({
|
|
996
|
-
message: "App directory for this new app",
|
|
997
|
-
placeholder: "e.g. apps/backend",
|
|
998
|
-
initialValue: params.defaultAppDir ?? "",
|
|
999
|
-
validate(value) {
|
|
1000
|
-
const v = value.trim();
|
|
1001
|
-
if (!v && hasWholeRepoApp)
|
|
1002
|
-
return "This project already covers the entire repo.";
|
|
1003
|
-
if (!v)
|
|
1004
|
-
return "App directory is required when other apps already exist.";
|
|
1005
|
-
if (v.startsWith("/"))
|
|
1006
|
-
return "Use a relative path, not an absolute path.";
|
|
1007
|
-
if (v.includes("..")) return 'Path must not contain "..".';
|
|
1008
|
-
if (existingScopes.has(v))
|
|
1009
|
-
return `"${v}" is already configured. Choose a different directory.`;
|
|
1010
|
-
}
|
|
1011
|
-
});
|
|
1012
|
-
if (p3.isCancel(rawScope)) return null;
|
|
1013
|
-
appDir = (rawScope ?? "").trim();
|
|
1014
980
|
}
|
|
1015
981
|
const sourceLocale = await searchSelectLocale(
|
|
1016
982
|
languageOptions,
|
|
@@ -1062,7 +1028,7 @@ async function runProjectAppCreate(params) {
|
|
|
1062
1028
|
}
|
|
1063
1029
|
const targetBranches = appPushBranches;
|
|
1064
1030
|
try {
|
|
1065
|
-
const result = await api.
|
|
1031
|
+
const result = await api.createApp(userToken, {
|
|
1066
1032
|
projectId,
|
|
1067
1033
|
appDir,
|
|
1068
1034
|
sourceLocale,
|
|
@@ -1302,7 +1268,7 @@ function printPlanLimitMessage(apiUrl, message) {
|
|
|
1302
1268
|
p5.log.info(`Manage subscription: ${getSubscriptionSettingsUrl(apiUrl)}`);
|
|
1303
1269
|
}
|
|
1304
1270
|
function runScaffold(params) {
|
|
1305
|
-
const { sourceLocale, targetBranches } = params;
|
|
1271
|
+
const { sourceLocale, targetBranches, appDir } = params;
|
|
1306
1272
|
const detection = detectLocalEcosystem();
|
|
1307
1273
|
const useTypeScript = detection.isTypeScript;
|
|
1308
1274
|
if (detection.ecosystem) {
|
|
@@ -1345,7 +1311,8 @@ function runScaffold(params) {
|
|
|
1345
1311
|
framework: detection.framework,
|
|
1346
1312
|
ecosystem: detection.ecosystem,
|
|
1347
1313
|
sourceLocale,
|
|
1348
|
-
targetBranches
|
|
1314
|
+
targetBranches,
|
|
1315
|
+
appDir
|
|
1349
1316
|
});
|
|
1350
1317
|
const steps = [];
|
|
1351
1318
|
if (snippets.pluginStep) {
|
|
@@ -1378,7 +1345,7 @@ function runScaffold(params) {
|
|
|
1378
1345
|
printCodeBlock(step.code);
|
|
1379
1346
|
if (i < steps.length - 1) p5.log.message("");
|
|
1380
1347
|
}
|
|
1381
|
-
const written = writeVocoderConfig({ targetBranches, useTypeScript });
|
|
1348
|
+
const written = writeVocoderConfig({ targetBranches, useTypeScript, appDir });
|
|
1382
1349
|
if (written) {
|
|
1383
1350
|
p5.log.success(`Created ${chalk6.cyan(written)}`);
|
|
1384
1351
|
} else if (!findExistingConfig(process.cwd())) {
|
|
@@ -1476,8 +1443,9 @@ async function runAuthFlow(api, options, reauth = false, repoCanonical) {
|
|
|
1476
1443
|
return null;
|
|
1477
1444
|
}
|
|
1478
1445
|
if (!shouldOpen) {
|
|
1479
|
-
|
|
1480
|
-
p5.
|
|
1446
|
+
server?.close();
|
|
1447
|
+
p5.cancel("Setup cancelled.");
|
|
1448
|
+
return null;
|
|
1481
1449
|
} else {
|
|
1482
1450
|
const opened = await tryOpenBrowser2(browserUrl);
|
|
1483
1451
|
if (!opened) {
|
|
@@ -1966,7 +1934,7 @@ async function init(options = {}) {
|
|
|
1966
1934
|
`${chalk6.bold(repoProjectName)} is already set up for this repo.
|
|
1967
1935
|
Configured apps: ${existingAppsForRepo.map((a) => chalk6.cyan(a.appDir || "(entire repo)")).join(", ")}`
|
|
1968
1936
|
);
|
|
1969
|
-
const appResult = await
|
|
1937
|
+
const appResult = await runAppCreate({
|
|
1970
1938
|
api,
|
|
1971
1939
|
userToken,
|
|
1972
1940
|
projectId: repoProjectId,
|
|
@@ -1982,7 +1950,8 @@ async function init(options = {}) {
|
|
|
1982
1950
|
}
|
|
1983
1951
|
runScaffold({
|
|
1984
1952
|
sourceLocale: appResult.sourceLocale,
|
|
1985
|
-
targetBranches: appResult.targetBranches
|
|
1953
|
+
targetBranches: appResult.targetBranches,
|
|
1954
|
+
appDir: identity?.repoAppDir
|
|
1986
1955
|
});
|
|
1987
1956
|
p5.outro("You're all set.");
|
|
1988
1957
|
return 0;
|
|
@@ -2039,7 +2008,7 @@ async function init(options = {}) {
|
|
|
2039
2008
|
return 1;
|
|
2040
2009
|
}
|
|
2041
2010
|
const chosen = existingProjects.find((proj) => proj.id === chosenId);
|
|
2042
|
-
const appResult = await
|
|
2011
|
+
const appResult = await runAppCreate({
|
|
2043
2012
|
api,
|
|
2044
2013
|
userToken,
|
|
2045
2014
|
projectId: chosen.id,
|
|
@@ -2055,7 +2024,8 @@ async function init(options = {}) {
|
|
|
2055
2024
|
}
|
|
2056
2025
|
runScaffold({
|
|
2057
2026
|
sourceLocale: appResult.sourceLocale,
|
|
2058
|
-
targetBranches: appResult.targetBranches
|
|
2027
|
+
targetBranches: appResult.targetBranches,
|
|
2028
|
+
appDir: identity?.repoAppDir
|
|
2059
2029
|
});
|
|
2060
2030
|
p5.outro("You're all set.");
|
|
2061
2031
|
return 0;
|
|
@@ -2090,7 +2060,8 @@ Translations won't run automatically until you grant access.
|
|
|
2090
2060
|
}
|
|
2091
2061
|
runScaffold({
|
|
2092
2062
|
sourceLocale: projectResult.sourceLocale,
|
|
2093
|
-
targetBranches: projectResult.targetBranches
|
|
2063
|
+
targetBranches: projectResult.targetBranches,
|
|
2064
|
+
appDir: identity?.repoAppDir
|
|
2094
2065
|
});
|
|
2095
2066
|
printApiKey(projectResult.apiKey);
|
|
2096
2067
|
p5.outro("You're all set.");
|
|
@@ -2405,8 +2376,8 @@ function buildTranslationData(params) {
|
|
|
2405
2376
|
const hashKeyed = {};
|
|
2406
2377
|
for (const [locale, localeMap] of Object.entries(params.translations)) {
|
|
2407
2378
|
hashKeyed[locale] = {};
|
|
2408
|
-
for (const [
|
|
2409
|
-
const hash = textToHash.get(
|
|
2379
|
+
for (const [text, translation] of Object.entries(localeMap)) {
|
|
2380
|
+
const hash = textToHash.get(text);
|
|
2410
2381
|
if (hash) hashKeyed[locale][hash] = translation;
|
|
2411
2382
|
}
|
|
2412
2383
|
}
|
|
@@ -2733,7 +2704,7 @@ async function sync(options = {}) {
|
|
|
2733
2704
|
requestedMaxWaitMs: waitTimeoutMs,
|
|
2734
2705
|
clientRunId: randomUUID(),
|
|
2735
2706
|
force: options.force,
|
|
2736
|
-
// Sync appIndustry from vocoder.config.ts to
|
|
2707
|
+
// Sync appIndustry from vocoder.config.ts to App on every push
|
|
2737
2708
|
...config.appIndustry ? { appIndustry: config.appIndustry } : {}
|
|
2738
2709
|
},
|
|
2739
2710
|
repoIdentity ? { ...repoIdentity, commitSha } : { commitSha }
|