zcf 1.1.4 → 1.1.5

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/cli.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import cac from 'cac';
3
3
  import ansis from 'ansis';
4
- import { t as displayBanner, u as selectScriptLanguage, v as readZcfConfig, I as I18N, S as SETTINGS_FILE, b as SUPPORTED_LANGS, L as LANG_LABELS, x as resolveAiOutputLanguage, y as updatePromptOnly, z as updateZcfConfig, B as version, i as init } from './shared/zcf.DK7kfRoM.mjs';
4
+ import { t as displayBanner, u as selectScriptLanguage, v as readZcfConfig, I as I18N, S as SETTINGS_FILE, b as SUPPORTED_LANGS, L as LANG_LABELS, x as resolveAiOutputLanguage, y as updatePromptOnly, z as updateZcfConfig, B as version, i as init } from './shared/zcf.CeJug3gT.mjs';
5
5
  import prompts from '@posva/prompts';
6
6
  import { existsSync } from 'node:fs';
7
7
  import 'node:os';
package/dist/index.d.mts CHANGED
@@ -100,6 +100,13 @@ declare const I18N: {
100
100
  yes: string;
101
101
  no: string;
102
102
  cancelled: string;
103
+ apiKeyValidation: {
104
+ empty: string;
105
+ invalid: string;
106
+ tooShort: string;
107
+ tooLong: string;
108
+ example: string;
109
+ };
103
110
  noExistingConfig: string;
104
111
  updatingPrompts: string;
105
112
  updateConfigLangPrompt: string;
@@ -154,6 +161,13 @@ declare const I18N: {
154
161
  yes: string;
155
162
  no: string;
156
163
  cancelled: string;
164
+ apiKeyValidation: {
165
+ empty: string;
166
+ invalid: string;
167
+ tooShort: string;
168
+ tooLong: string;
169
+ example: string;
170
+ };
157
171
  noExistingConfig: string;
158
172
  updatingPrompts: string;
159
173
  updateConfigLangPrompt: string;
@@ -187,7 +201,7 @@ interface ApiConfig {
187
201
  key: string;
188
202
  authType?: 'auth_token' | 'api_key';
189
203
  }
190
- declare function configureApi(apiConfig: ApiConfig | null): void;
204
+ declare function configureApi(apiConfig: ApiConfig | null): ApiConfig | null;
191
205
  declare function mergeConfigs(sourceFile: string, targetFile: string): void;
192
206
  declare function applyAiLanguageDirective(aiOutputLang: AiOutputLanguage | string): void;
193
207
 
package/dist/index.d.ts CHANGED
@@ -100,6 +100,13 @@ declare const I18N: {
100
100
  yes: string;
101
101
  no: string;
102
102
  cancelled: string;
103
+ apiKeyValidation: {
104
+ empty: string;
105
+ invalid: string;
106
+ tooShort: string;
107
+ tooLong: string;
108
+ example: string;
109
+ };
103
110
  noExistingConfig: string;
104
111
  updatingPrompts: string;
105
112
  updateConfigLangPrompt: string;
@@ -154,6 +161,13 @@ declare const I18N: {
154
161
  yes: string;
155
162
  no: string;
156
163
  cancelled: string;
164
+ apiKeyValidation: {
165
+ empty: string;
166
+ invalid: string;
167
+ tooShort: string;
168
+ tooLong: string;
169
+ example: string;
170
+ };
157
171
  noExistingConfig: string;
158
172
  updatingPrompts: string;
159
173
  updateConfigLangPrompt: string;
@@ -187,7 +201,7 @@ interface ApiConfig {
187
201
  key: string;
188
202
  authType?: 'auth_token' | 'api_key';
189
203
  }
190
- declare function configureApi(apiConfig: ApiConfig | null): void;
204
+ declare function configureApi(apiConfig: ApiConfig | null): ApiConfig | null;
191
205
  declare function mergeConfigs(sourceFile: string, targetFile: string): void;
192
206
  declare function applyAiLanguageDirective(aiOutputLang: AiOutputLanguage | string): void;
193
207
 
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- export { A as AI_OUTPUT_LANGUAGES, C as CLAUDE_DIR, a as CLAUDE_MD_FILE, I as I18N, L as LANG_LABELS, M as MCP_CONFIG_FILE, d as MCP_SERVICES, S as SETTINGS_FILE, b as SUPPORTED_LANGS, Z as ZCF_CONFIG_FILE, n as applyAiLanguageDirective, j as backupExistingConfig, p as backupMcpConfig, s as buildMcpServerConfig, c as commandExists, l as configureApi, k as copyConfigFiles, h as ensureClaudeDir, o as getMcpConfigPath, g as getPlatform, i as init, f as installClaudeCode, e as isClaudeCodeInstalled, m as mergeConfigs, q as mergeMcpServers, r as readMcpConfig, w as writeMcpConfig } from './shared/zcf.DK7kfRoM.mjs';
1
+ export { A as AI_OUTPUT_LANGUAGES, C as CLAUDE_DIR, a as CLAUDE_MD_FILE, I as I18N, L as LANG_LABELS, M as MCP_CONFIG_FILE, d as MCP_SERVICES, S as SETTINGS_FILE, b as SUPPORTED_LANGS, Z as ZCF_CONFIG_FILE, n as applyAiLanguageDirective, j as backupExistingConfig, p as backupMcpConfig, s as buildMcpServerConfig, c as commandExists, l as configureApi, k as copyConfigFiles, h as ensureClaudeDir, o as getMcpConfigPath, g as getPlatform, i as init, f as installClaudeCode, e as isClaudeCodeInstalled, m as mergeConfigs, q as mergeMcpServers, r as readMcpConfig, w as writeMcpConfig } from './shared/zcf.CeJug3gT.mjs';
2
2
  import '@posva/prompts';
3
3
  import 'ansis';
4
4
  import 'node:fs';
@@ -6,7 +6,7 @@ import { join, dirname } from 'pathe';
6
6
  import dayjs from 'dayjs';
7
7
  import { exec } from 'tinyexec';
8
8
 
9
- const version = "1.1.4";
9
+ const version = "1.1.5";
10
10
 
11
11
  const CLAUDE_DIR = join(homedir(), ".claude");
12
12
  const SETTINGS_FILE = join(CLAUDE_DIR, "settings.json");
@@ -70,6 +70,13 @@ const I18N = {
70
70
  yes: "\u662F",
71
71
  no: "\u5426",
72
72
  cancelled: "\u64CD\u4F5C\u5DF2\u53D6\u6D88",
73
+ apiKeyValidation: {
74
+ empty: "API Key \u4E0D\u80FD\u4E3A\u7A7A",
75
+ invalid: "API Key \u683C\u5F0F\u65E0\u6548\u3002\u53EA\u80FD\u5305\u542B\u5B57\u6BCD\u3001\u6570\u5B57\u3001\u4E0B\u5212\u7EBF\uFF08_\uFF09\u548C\u8FDE\u5B57\u7B26\uFF08-\uFF09",
76
+ tooShort: "API Key \u957F\u5EA6\u592A\u77ED\uFF08\u81F3\u5C11\u9700\u8981 1 \u4E2A\u5B57\u7B26\uFF09",
77
+ tooLong: "API Key \u957F\u5EA6\u592A\u957F\uFF08\u6700\u591A 256 \u4E2A\u5B57\u7B26\uFF09",
78
+ example: "\u793A\u4F8B\u683C\u5F0F: sk-abcdef123456_789xyz"
79
+ },
73
80
  noExistingConfig: "\u672A\u627E\u5230\u73B0\u6709\u914D\u7F6E\u3002\u8BF7\u5148\u8FD0\u884C `zcf`\u3002",
74
81
  updatingPrompts: "\u6B63\u5728\u66F4\u65B0 Claude Code Prompt \u6587\u6863...",
75
82
  updateConfigLangPrompt: "\u9009\u62E9\u914D\u7F6E\u8BED\u8A00",
@@ -124,6 +131,13 @@ const I18N = {
124
131
  yes: "Yes",
125
132
  no: "No",
126
133
  cancelled: "Operation cancelled",
134
+ apiKeyValidation: {
135
+ empty: "API Key cannot be empty",
136
+ invalid: "Invalid API Key format. Only letters, numbers, underscores (_) and hyphens (-) are allowed",
137
+ tooShort: "API Key is too short (minimum 1 characters required)",
138
+ tooLong: "API Key is too long (maximum 256 characters allowed)",
139
+ example: "Example format: sk-abcdef123456_789xyz"
140
+ },
127
141
  noExistingConfig: "No existing configuration found. Please run `zcf` first.",
128
142
  updatingPrompts: "Updating Claude Code prompt documents...",
129
143
  updateConfigLangPrompt: "Select configuration language",
@@ -307,41 +321,30 @@ function copyDirectory(src, dest) {
307
321
  }
308
322
  }
309
323
  }
324
+ function getDefaultSettings() {
325
+ try {
326
+ const currentFileUrl = new URL(import.meta.url);
327
+ const currentFilePath = currentFileUrl.pathname;
328
+ const distDir = dirname(dirname(currentFilePath));
329
+ const rootDir = dirname(distDir);
330
+ const templateSettingsPath = join(rootDir, "templates", "settings.json");
331
+ if (existsSync(templateSettingsPath)) {
332
+ const content = readFileSync(templateSettingsPath, "utf-8");
333
+ return JSON.parse(content);
334
+ }
335
+ } catch (error) {
336
+ console.error("Failed to read template settings.json:", error);
337
+ return {};
338
+ }
339
+ }
310
340
  function configureApi(apiConfig) {
311
- if (!apiConfig) return;
312
- let settings = {
313
- $schema: "https://json.schemastore.org/claude-code-settings.json",
314
- env: {},
315
- includeCoAuthoredBy: false,
316
- permissions: {
317
- allow: [
318
- "Bash(*)",
319
- "LS(*)",
320
- "Read(*)",
321
- "Write(*)",
322
- "Edit(*)",
323
- "MultiEdit(*)",
324
- "Glob(*)",
325
- "Grep(*)",
326
- "WebFetch(*)",
327
- "WebSearch(*)",
328
- "TodoWrite(*)",
329
- "NotebookRead(*)",
330
- "NotebookEdit(*)"
331
- ],
332
- deny: []
333
- },
334
- hooks: {},
335
- model: "opus"
336
- };
341
+ if (!apiConfig) return null;
342
+ let settings = getDefaultSettings();
337
343
  if (existsSync(SETTINGS_FILE)) {
338
344
  const content = readFileSync(SETTINGS_FILE, "utf-8");
339
345
  try {
340
346
  const existingSettings = JSON.parse(content);
341
- settings = { ...settings, ...existingSettings };
342
- if (existingSettings.env) {
343
- settings.env = { ...settings.env, ...existingSettings.env };
344
- }
347
+ settings = deepMerge(settings, existingSettings);
345
348
  } catch (error) {
346
349
  console.error("Failed to parse existing settings.json, using defaults:", error);
347
350
  }
@@ -353,6 +356,7 @@ function configureApi(apiConfig) {
353
356
  }
354
357
  settings.env.ANTHROPIC_BASE_URL = apiConfig.url;
355
358
  writeFileSync(SETTINGS_FILE, JSON.stringify(settings, null, 2));
359
+ return apiConfig;
356
360
  }
357
361
  function mergeConfigs(sourceFile, targetFile) {
358
362
  if (!existsSync(sourceFile)) return;
@@ -609,6 +613,42 @@ async function resolveAiOutputLanguage(scriptLang, commandLineOption, savedConfi
609
613
  return await selectAiOutputLanguage(scriptLang, scriptLang);
610
614
  }
611
615
 
616
+ function validateApiKey(apiKey, lang = "zh-CN") {
617
+ const i18n = I18N[lang];
618
+ if (!apiKey || apiKey.trim() === "") {
619
+ return {
620
+ isValid: false,
621
+ error: i18n.apiKeyValidation.empty
622
+ };
623
+ }
624
+ const apiKeyPattern = /^[A-Za-z0-9_-]+$/;
625
+ if (!apiKeyPattern.test(apiKey)) {
626
+ return {
627
+ isValid: false,
628
+ error: i18n.apiKeyValidation.invalid
629
+ };
630
+ }
631
+ if (apiKey.length < 1) {
632
+ return {
633
+ isValid: false,
634
+ error: i18n.apiKeyValidation.tooShort
635
+ };
636
+ }
637
+ if (apiKey.length > 256) {
638
+ return {
639
+ isValid: false,
640
+ error: i18n.apiKeyValidation.tooLong
641
+ };
642
+ }
643
+ return { isValid: true };
644
+ }
645
+ function formatApiKeyDisplay(apiKey) {
646
+ if (!apiKey || apiKey.length < 12) {
647
+ return apiKey;
648
+ }
649
+ return `${apiKey.substring(0, 8)}...${apiKey.substring(apiKey.length - 4)}`;
650
+ }
651
+
612
652
  async function updatePromptOnly(configLang, scriptLang, aiOutputLang) {
613
653
  const i18n = I18N[scriptLang];
614
654
  const backupDir = backupExistingConfig();
@@ -750,13 +790,23 @@ async function init(options = {}) {
750
790
  type: "text",
751
791
  name: "key",
752
792
  message: keyMessage,
753
- validate: (value) => !!value || `${apiChoice === "auth_token" ? "Auth Token" : "API Key"} is required`
793
+ validate: (value) => {
794
+ if (!value) {
795
+ return `${apiChoice === "auth_token" ? "Auth Token" : "API Key"} is required`;
796
+ }
797
+ const validation = validateApiKey(value, scriptLang);
798
+ if (!validation.isValid) {
799
+ return validation.error || "Invalid API Key format";
800
+ }
801
+ return true;
802
+ }
754
803
  });
755
804
  if (keyResponse.key === void 0) {
756
805
  console.log(ansis.yellow(i18n.cancelled));
757
806
  process.exit(0);
758
807
  }
759
808
  const key = keyResponse.key;
809
+ console.log(ansis.gray(` API Key: ${formatApiKeyDisplay(key)}`));
760
810
  apiConfig = { url, key, authType: apiChoice };
761
811
  }
762
812
  }
@@ -783,8 +833,12 @@ async function init(options = {}) {
783
833
  }
784
834
  applyAiLanguageDirective(aiOutputLang);
785
835
  if (apiConfig && !onlyUpdateDocs) {
786
- configureApi(apiConfig);
787
- console.log(ansis.green(`\u2714 ${i18n.apiConfigSuccess}`));
836
+ const configuredApi = configureApi(apiConfig);
837
+ if (configuredApi) {
838
+ console.log(ansis.green(`\u2714 ${i18n.apiConfigSuccess}`));
839
+ console.log(ansis.gray(` URL: ${configuredApi.url}`));
840
+ console.log(ansis.gray(` Key: ${formatApiKeyDisplay(configuredApi.key)}`));
841
+ }
788
842
  }
789
843
  if (!onlyUpdateDocs) {
790
844
  const mcpResponse = await prompts({
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "zcf",
3
3
  "type": "module",
4
- "version": "1.1.4",
4
+ "version": "1.1.5",
5
5
  "description": "Zero-Config Claude-Code Flow - One-click configuration tool for Claude Code",
6
6
  "license": "MIT",
7
7
  "homepage": "https://github.com/UfoMiao/zcf#readme",
@@ -24,6 +24,5 @@
24
24
  ],
25
25
  "deny": []
26
26
  },
27
- "hooks": {},
28
- "model": "opus"
29
- }
27
+ "hooks": {}
28
+ }