@vocoder/cli 0.1.27 → 0.2.0

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 CHANGED
@@ -5,15 +5,15 @@ import {
5
5
  detectLocalEcosystem,
6
6
  getPackagesToInstall,
7
7
  getSetupSnippets
8
- } from "./chunk-OFQLREXF.mjs";
8
+ } from "./chunk-JTRTTGYF.mjs";
9
9
 
10
10
  // src/bin.ts
11
11
  import { Command } from "commander";
12
12
 
13
13
  // src/commands/init.ts
14
14
  import { execSync as execSync3, spawn as spawn2 } from "child_process";
15
- import { existsSync, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
16
- import { join as join2 } from "path";
15
+ import { existsSync as existsSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync3 } from "fs";
16
+ import { join as join3 } from "path";
17
17
  import * as p5 from "@clack/prompts";
18
18
  import chalk6 from "chalk";
19
19
  import { config as loadEnv } from "dotenv";
@@ -739,6 +739,37 @@ function clearAuthData() {
739
739
  }
740
740
  }
741
741
 
742
+ // src/utils/write-config.ts
743
+ import { existsSync, writeFileSync as writeFileSync2 } from "fs";
744
+ import { join as join2 } from "path";
745
+ function writeVocoderConfig(options) {
746
+ const { targetBranches = ["main"], cwd = process.cwd() } = options;
747
+ const configPath = join2(cwd, "vocoder.config.ts");
748
+ if (existsSync(configPath)) return false;
749
+ const branchesStr = targetBranches.map((b) => `'${b}'`).join(", ");
750
+ const content = `import { defineConfig } from '@vocoder/extractor'
751
+
752
+ export default defineConfig({
753
+ targetBranches: [${branchesStr}],
754
+ include: ['**/*.{tsx,jsx,ts,js}'],
755
+ exclude: [
756
+ '**/node_modules/**',
757
+ '**/.next/**',
758
+ '**/dist/**',
759
+ '**/build/**',
760
+ '**/*.test.*',
761
+ '**/*.spec.*',
762
+ ],
763
+ })
764
+ `;
765
+ try {
766
+ writeFileSync2(configPath, content, "utf-8");
767
+ return true;
768
+ } catch {
769
+ return false;
770
+ }
771
+ }
772
+
742
773
  // src/utils/git-identity.ts
743
774
  import { execSync } from "child_process";
744
775
  import { relative, resolve } from "path";
@@ -2029,6 +2060,14 @@ function runScaffold(params) {
2029
2060
  printCodeBlock(step.code);
2030
2061
  if (i < steps.length - 1) p5.log.message("");
2031
2062
  }
2063
+ const written = writeVocoderConfig({ targetBranches });
2064
+ if (written) {
2065
+ p5.log.success(`Created ${chalk6.cyan("vocoder.config.ts")}`);
2066
+ } else if (!existsSync2(join3(process.cwd(), "vocoder.config.ts"))) {
2067
+ p5.log.warn(
2068
+ "Could not write vocoder.config.ts \u2014 create it manually with your extraction patterns."
2069
+ );
2070
+ }
2032
2071
  p5.log.message("");
2033
2072
  const branchList = targetBranches.length > 0 ? targetBranches.map((b) => chalk6.cyan(b)).join(" or ") : chalk6.cyan("your target branch");
2034
2073
  p5.log.success(
@@ -2037,8 +2076,8 @@ function runScaffold(params) {
2037
2076
  p5.log.message(chalk6.gray(" Docs: https://vocoder.app/docs/getting-started"));
2038
2077
  }
2039
2078
  function writeApiKeyToEnv(apiKey) {
2040
- const envPath = join2(process.cwd(), ".env");
2041
- if (!existsSync(envPath)) return false;
2079
+ const envPath = join3(process.cwd(), ".env");
2080
+ if (!existsSync2(envPath)) return false;
2042
2081
  try {
2043
2082
  const content = readFileSync2(envPath, "utf-8");
2044
2083
  const keyLine = `VOCODER_API_KEY=${apiKey}`;
@@ -2050,7 +2089,7 @@ function writeApiKeyToEnv(apiKey) {
2050
2089
  updated = `${content}${sep}${keyLine}
2051
2090
  `;
2052
2091
  }
2053
- writeFileSync2(envPath, updated);
2092
+ writeFileSync3(envPath, updated);
2054
2093
  return true;
2055
2094
  } catch {
2056
2095
  return false;
@@ -2298,6 +2337,8 @@ async function init(options = {}) {
2298
2337
  return 1;
2299
2338
  }
2300
2339
  }
2340
+ const written = writeVocoderConfig({ targetBranches: exactMatch.targetBranches ?? ["main"] });
2341
+ if (written) p5.log.success(`Created ${chalk6.cyan("vocoder.config.ts")}`);
2301
2342
  p5.outro("Vocoder is already set up for this repository.");
2302
2343
  return 0;
2303
2344
  }
@@ -2305,6 +2346,8 @@ async function init(options = {}) {
2305
2346
  const wholeRepo = lookup.existingApps.find((a) => a.appDir === "");
2306
2347
  if (wholeRepo) {
2307
2348
  p5.log.success(`Project: ${chalk6.bold(wholeRepo.projectName)}`);
2349
+ const written = writeVocoderConfig({ targetBranches: ["main"] });
2350
+ if (written) p5.log.success(`Created ${chalk6.cyan("vocoder.config.ts")}`);
2308
2351
  p5.outro("Vocoder is already set up for this repository.");
2309
2352
  return 0;
2310
2353
  }
@@ -2774,7 +2817,6 @@ Translations won't run automatically until you grant access.
2774
2817
  return 1;
2775
2818
  }
2776
2819
  p5.log.error(`Error: ${error.message}`);
2777
- p5.log.info(error.stack ?? "");
2778
2820
  } else {
2779
2821
  p5.log.error("Unknown setup error");
2780
2822
  }
@@ -2803,8 +2845,8 @@ async function logout(options = {}) {
2803
2845
 
2804
2846
  // src/commands/sync.ts
2805
2847
  import { createHash, randomUUID } from "crypto";
2806
- import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "fs";
2807
- import { join as join3 } from "path";
2848
+ import { existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync3, writeFileSync as writeFileSync4 } from "fs";
2849
+ import { join as join4 } from "path";
2808
2850
  import * as p8 from "@clack/prompts";
2809
2851
  import chalk8 from "chalk";
2810
2852
 
@@ -2878,6 +2920,7 @@ function matchBranchPattern(branch, pattern) {
2878
2920
  import * as p7 from "@clack/prompts";
2879
2921
  import chalk7 from "chalk";
2880
2922
  import { config as loadEnv2 } from "dotenv";
2923
+ import { loadVocoderConfig } from "@vocoder/extractor";
2881
2924
  loadEnv2();
2882
2925
  function validateLocalConfig(config) {
2883
2926
  if (!config.apiKey || config.apiKey.length === 0) {
@@ -2932,6 +2975,12 @@ async function getMergedConfig(cliOptions, verbose = false, _startDir) {
2932
2975
  ],
2933
2976
  apiUrl: "https://vocoder.app"
2934
2977
  };
2978
+ const fileConfig = loadVocoderConfig(process.cwd());
2979
+ if (!fileConfig) {
2980
+ p7.log.warn(
2981
+ `No ${chalk7.cyan("vocoder.config.ts")} found \u2014 run ${chalk7.cyan("npx @vocoder/cli init")} to generate one.`
2982
+ );
2983
+ }
2935
2984
  const envExtractionPattern = process.env.VOCODER_INCLUDE_PATTERN;
2936
2985
  const envExcludePattern = process.env.VOCODER_EXCLUDE_PATTERN;
2937
2986
  const envApiUrl = process.env.VOCODER_API_URL;
@@ -2942,6 +2991,9 @@ async function getMergedConfig(cliOptions, verbose = false, _startDir) {
2942
2991
  if (cliOptions.include && cliOptions.include.length > 0) {
2943
2992
  includePattern = cliOptions.include;
2944
2993
  configSources.includePattern = "CLI flag";
2994
+ } else if (fileConfig?.include && fileConfig.include.length > 0) {
2995
+ includePattern = fileConfig.include;
2996
+ configSources.includePattern = "vocoder.config";
2945
2997
  } else if (envExtractionPattern) {
2946
2998
  includePattern = [envExtractionPattern];
2947
2999
  configSources.includePattern = "environment";
@@ -2952,6 +3004,9 @@ async function getMergedConfig(cliOptions, verbose = false, _startDir) {
2952
3004
  if (cliOptions.exclude && cliOptions.exclude.length > 0) {
2953
3005
  excludePattern = cliOptions.exclude;
2954
3006
  configSources.excludePattern = "CLI flag";
3007
+ } else if (fileConfig?.exclude && fileConfig.exclude.length > 0) {
3008
+ excludePattern = fileConfig.exclude;
3009
+ configSources.excludePattern = "vocoder.config";
2955
3010
  } else if (envExcludePattern) {
2956
3011
  excludePattern = envExcludePattern.split(",").map((p10) => p10.trim()).filter(Boolean);
2957
3012
  configSources.excludePattern = "environment";
@@ -3031,7 +3086,7 @@ function computeStringsHash(texts) {
3031
3086
  }
3032
3087
  function readCachedStringsHash(projectRoot, branch) {
3033
3088
  const filePath = getCacheFilePath(projectRoot, branch);
3034
- if (!existsSync2(filePath)) return null;
3089
+ if (!existsSync3(filePath)) return null;
3035
3090
  try {
3036
3091
  const raw = JSON.parse(readFileSync3(filePath, "utf-8"));
3037
3092
  if (isRecord(raw) && typeof raw.stringsHash === "string")
@@ -3085,7 +3140,7 @@ function parseTranslations(value) {
3085
3140
  }
3086
3141
  function getCacheFilePath(projectRoot, branch) {
3087
3142
  const branchHash = createHash("sha1").update(branch).digest("hex").slice(0, 12);
3088
- return join3(
3143
+ return join4(
3089
3144
  projectRoot,
3090
3145
  "node_modules",
3091
3146
  ".vocoder",
@@ -3098,7 +3153,7 @@ function readLocalSnapshotCache(params) {
3098
3153
  const candidateBranches = params.branch === "main" ? ["main"] : [params.branch, "main"];
3099
3154
  for (const candidateBranch of candidateBranches) {
3100
3155
  const cacheFilePath = getCacheFilePath(params.projectRoot, candidateBranch);
3101
- if (!existsSync2(cacheFilePath)) {
3156
+ if (!existsSync3(cacheFilePath)) {
3102
3157
  continue;
3103
3158
  }
3104
3159
  try {
@@ -3128,7 +3183,7 @@ function readLocalSnapshotCache(params) {
3128
3183
  function writeLocalSnapshotCache(params) {
3129
3184
  const cacheFilePath = getCacheFilePath(params.projectRoot, params.branch);
3130
3185
  mkdirSync2(
3131
- join3(params.projectRoot, "node_modules", ".vocoder", "cache", "sync"),
3186
+ join4(params.projectRoot, "node_modules", ".vocoder", "cache", "sync"),
3132
3187
  {
3133
3188
  recursive: true
3134
3189
  }
@@ -3145,7 +3200,7 @@ function writeLocalSnapshotCache(params) {
3145
3200
  ...params.localeMetadata ? { localeMetadata: params.localeMetadata } : {},
3146
3201
  translations: params.translations
3147
3202
  };
3148
- writeFileSync3(cacheFilePath, JSON.stringify(payload, null, 2), "utf-8");
3203
+ writeFileSync4(cacheFilePath, JSON.stringify(payload, null, 2), "utf-8");
3149
3204
  return cacheFilePath;
3150
3205
  }
3151
3206
  function resolveEffectiveModeFromPolicy(params) {