@praeviso/code-env-switch 0.1.0 → 0.1.2

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.
Files changed (78) hide show
  1. package/.eslintrc.cjs +18 -0
  2. package/.github/workflows/npm-publish.yml +25 -0
  3. package/.vscode/settings.json +4 -0
  4. package/AGENTS.md +32 -0
  5. package/LICENSE +21 -0
  6. package/PLAN.md +33 -0
  7. package/README.md +208 -32
  8. package/README_zh.md +265 -0
  9. package/bin/cli/args.js +303 -0
  10. package/bin/cli/help.js +77 -0
  11. package/bin/cli/index.js +13 -0
  12. package/bin/commands/add.js +81 -0
  13. package/bin/commands/index.js +21 -0
  14. package/bin/commands/launch.js +330 -0
  15. package/bin/commands/list.js +57 -0
  16. package/bin/commands/show.js +10 -0
  17. package/bin/commands/statusline.js +12 -0
  18. package/bin/commands/unset.js +20 -0
  19. package/bin/commands/use.js +92 -0
  20. package/bin/config/defaults.js +85 -0
  21. package/bin/config/index.js +20 -0
  22. package/bin/config/io.js +72 -0
  23. package/bin/constants.js +27 -0
  24. package/bin/index.js +279 -0
  25. package/bin/profile/display.js +78 -0
  26. package/bin/profile/index.js +26 -0
  27. package/bin/profile/match.js +40 -0
  28. package/bin/profile/resolve.js +79 -0
  29. package/bin/profile/type.js +90 -0
  30. package/bin/shell/detect.js +40 -0
  31. package/bin/shell/index.js +18 -0
  32. package/bin/shell/snippet.js +92 -0
  33. package/bin/shell/utils.js +35 -0
  34. package/bin/statusline/claude.js +153 -0
  35. package/bin/statusline/codex.js +356 -0
  36. package/bin/statusline/index.js +469 -0
  37. package/bin/types.js +5 -0
  38. package/bin/ui/index.js +16 -0
  39. package/bin/ui/interactive.js +189 -0
  40. package/bin/ui/readline.js +76 -0
  41. package/bin/usage/index.js +709 -0
  42. package/code-env.example.json +36 -23
  43. package/package.json +14 -2
  44. package/src/cli/args.ts +318 -0
  45. package/src/cli/help.ts +75 -0
  46. package/src/cli/index.ts +5 -0
  47. package/src/commands/add.ts +91 -0
  48. package/src/commands/index.ts +10 -0
  49. package/src/commands/launch.ts +395 -0
  50. package/src/commands/list.ts +91 -0
  51. package/src/commands/show.ts +12 -0
  52. package/src/commands/statusline.ts +18 -0
  53. package/src/commands/unset.ts +19 -0
  54. package/src/commands/use.ts +121 -0
  55. package/src/config/defaults.ts +88 -0
  56. package/src/config/index.ts +19 -0
  57. package/src/config/io.ts +69 -0
  58. package/src/constants.ts +28 -0
  59. package/src/index.ts +359 -0
  60. package/src/profile/display.ts +77 -0
  61. package/src/profile/index.ts +12 -0
  62. package/src/profile/match.ts +41 -0
  63. package/src/profile/resolve.ts +84 -0
  64. package/src/profile/type.ts +83 -0
  65. package/src/shell/detect.ts +30 -0
  66. package/src/shell/index.ts +6 -0
  67. package/src/shell/snippet.ts +92 -0
  68. package/src/shell/utils.ts +30 -0
  69. package/src/statusline/claude.ts +172 -0
  70. package/src/statusline/codex.ts +393 -0
  71. package/src/statusline/index.ts +626 -0
  72. package/src/types.ts +95 -0
  73. package/src/ui/index.ts +5 -0
  74. package/src/ui/interactive.ts +220 -0
  75. package/src/ui/readline.ts +85 -0
  76. package/src/usage/index.ts +833 -0
  77. package/tsconfig.json +12 -0
  78. package/bin/codenv.js +0 -377
@@ -0,0 +1,85 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getDefaultProfiles = getDefaultProfiles;
4
+ exports.deleteDefaultProfileEntry = deleteDefaultProfileEntry;
5
+ exports.resolveDefaultProfileForType = resolveDefaultProfileForType;
6
+ exports.getResolvedDefaultProfileKeys = getResolvedDefaultProfileKeys;
7
+ exports.getTypeDefaultUnsetKeys = getTypeDefaultUnsetKeys;
8
+ exports.getFilteredUnsetKeys = getFilteredUnsetKeys;
9
+ const constants_1 = require("../constants");
10
+ const type_1 = require("../profile/type");
11
+ const resolve_1 = require("../profile/resolve");
12
+ function getDefaultProfiles(config) {
13
+ const defaults = {};
14
+ if (!config || typeof config !== "object")
15
+ return defaults;
16
+ if (!config.defaultProfiles || typeof config.defaultProfiles !== "object") {
17
+ return defaults;
18
+ }
19
+ for (const [rawType, rawValue] of Object.entries(config.defaultProfiles)) {
20
+ const type = (0, type_1.normalizeType)(rawType);
21
+ if (!type)
22
+ continue;
23
+ const trimmed = String(rawValue !== null && rawValue !== void 0 ? rawValue : "").trim();
24
+ if (trimmed)
25
+ defaults[type] = trimmed;
26
+ }
27
+ return defaults;
28
+ }
29
+ function deleteDefaultProfileEntry(config, type) {
30
+ if (!config.defaultProfiles || typeof config.defaultProfiles !== "object") {
31
+ return false;
32
+ }
33
+ let changed = false;
34
+ for (const key of Object.keys(config.defaultProfiles)) {
35
+ if ((0, type_1.normalizeType)(key) === type) {
36
+ delete config.defaultProfiles[key];
37
+ changed = true;
38
+ }
39
+ }
40
+ return changed;
41
+ }
42
+ function resolveDefaultProfileForType(config, type, value) {
43
+ const trimmed = String(value !== null && value !== void 0 ? value : "").trim();
44
+ if (!trimmed)
45
+ return null;
46
+ const params = trimmed.split(/\s+/).filter(Boolean);
47
+ if (params.length === 0)
48
+ return null;
49
+ const explicitType = (0, type_1.normalizeType)(params[0]);
50
+ if (explicitType) {
51
+ if (explicitType !== type) {
52
+ throw new Error(`Default profile for "${type}" must match type "${type}".`);
53
+ }
54
+ return (0, resolve_1.resolveProfileName)(config, params);
55
+ }
56
+ return (0, resolve_1.resolveProfileName)(config, [type, ...params]);
57
+ }
58
+ function getResolvedDefaultProfileKeys(config) {
59
+ const defaults = getDefaultProfiles(config);
60
+ const resolved = {};
61
+ for (const type of constants_1.DEFAULT_PROFILE_TYPES) {
62
+ const value = defaults[type];
63
+ if (!value)
64
+ continue;
65
+ try {
66
+ const profileName = resolveDefaultProfileForType(config, type, value);
67
+ if (profileName)
68
+ resolved[type] = profileName;
69
+ }
70
+ catch (err) {
71
+ // ignore invalid defaults for list output
72
+ }
73
+ }
74
+ return resolved;
75
+ }
76
+ function getTypeDefaultUnsetKeys(type) {
77
+ return constants_1.DEFAULT_UNSET_KEYS[type] || [];
78
+ }
79
+ function getFilteredUnsetKeys(config, activeType) {
80
+ const keys = Array.isArray(config.unset) ? config.unset : [];
81
+ if (!activeType)
82
+ return [...keys];
83
+ const otherDefaults = new Set(constants_1.DEFAULT_PROFILE_TYPES.filter((type) => type !== activeType).flatMap((type) => constants_1.DEFAULT_UNSET_KEYS[type]));
84
+ return keys.filter((key) => !otherDefaults.has(key));
85
+ }
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getFilteredUnsetKeys = exports.getTypeDefaultUnsetKeys = exports.getResolvedDefaultProfileKeys = exports.resolveDefaultProfileForType = exports.deleteDefaultProfileEntry = exports.getDefaultProfiles = exports.writeConfig = exports.readConfigIfExists = exports.readConfig = exports.findConfigPathForWrite = exports.findConfigPath = exports.getDefaultConfigPath = void 0;
4
+ /**
5
+ * Config module exports
6
+ */
7
+ var io_1 = require("./io");
8
+ Object.defineProperty(exports, "getDefaultConfigPath", { enumerable: true, get: function () { return io_1.getDefaultConfigPath; } });
9
+ Object.defineProperty(exports, "findConfigPath", { enumerable: true, get: function () { return io_1.findConfigPath; } });
10
+ Object.defineProperty(exports, "findConfigPathForWrite", { enumerable: true, get: function () { return io_1.findConfigPathForWrite; } });
11
+ Object.defineProperty(exports, "readConfig", { enumerable: true, get: function () { return io_1.readConfig; } });
12
+ Object.defineProperty(exports, "readConfigIfExists", { enumerable: true, get: function () { return io_1.readConfigIfExists; } });
13
+ Object.defineProperty(exports, "writeConfig", { enumerable: true, get: function () { return io_1.writeConfig; } });
14
+ var defaults_1 = require("./defaults");
15
+ Object.defineProperty(exports, "getDefaultProfiles", { enumerable: true, get: function () { return defaults_1.getDefaultProfiles; } });
16
+ Object.defineProperty(exports, "deleteDefaultProfileEntry", { enumerable: true, get: function () { return defaults_1.deleteDefaultProfileEntry; } });
17
+ Object.defineProperty(exports, "resolveDefaultProfileForType", { enumerable: true, get: function () { return defaults_1.resolveDefaultProfileForType; } });
18
+ Object.defineProperty(exports, "getResolvedDefaultProfileKeys", { enumerable: true, get: function () { return defaults_1.getResolvedDefaultProfileKeys; } });
19
+ Object.defineProperty(exports, "getTypeDefaultUnsetKeys", { enumerable: true, get: function () { return defaults_1.getTypeDefaultUnsetKeys; } });
20
+ Object.defineProperty(exports, "getFilteredUnsetKeys", { enumerable: true, get: function () { return defaults_1.getFilteredUnsetKeys; } });
@@ -0,0 +1,72 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getDefaultConfigPath = getDefaultConfigPath;
4
+ exports.findConfigPath = findConfigPath;
5
+ exports.findConfigPathForWrite = findConfigPathForWrite;
6
+ exports.readConfig = readConfig;
7
+ exports.readConfigIfExists = readConfigIfExists;
8
+ exports.writeConfig = writeConfig;
9
+ /**
10
+ * Config I/O utilities
11
+ */
12
+ const fs = require("fs");
13
+ const path = require("path");
14
+ const os = require("os");
15
+ const utils_1 = require("../shell/utils");
16
+ function getDefaultConfigPath() {
17
+ return path.join(os.homedir(), ".config", "code-env", "config.json");
18
+ }
19
+ function findConfigPath(explicitPath) {
20
+ if (explicitPath) {
21
+ const resolved = (0, utils_1.resolvePath)(explicitPath);
22
+ if (fs.existsSync(resolved))
23
+ return resolved;
24
+ return resolved; // let readConfig raise a helpful error
25
+ }
26
+ if (process.env.CODE_ENV_CONFIG) {
27
+ const fromEnv = (0, utils_1.resolvePath)(process.env.CODE_ENV_CONFIG);
28
+ if (fs.existsSync(fromEnv))
29
+ return fromEnv;
30
+ return fromEnv;
31
+ }
32
+ return getDefaultConfigPath();
33
+ }
34
+ function findConfigPathForWrite(explicitPath) {
35
+ if (explicitPath)
36
+ return (0, utils_1.resolvePath)(explicitPath);
37
+ if (process.env.CODE_ENV_CONFIG)
38
+ return (0, utils_1.resolvePath)(process.env.CODE_ENV_CONFIG);
39
+ return getDefaultConfigPath();
40
+ }
41
+ function readConfig(configPath) {
42
+ if (!configPath) {
43
+ throw new Error("No config file found. Use --config or set CODE_ENV_CONFIG.");
44
+ }
45
+ if (!fs.existsSync(configPath)) {
46
+ throw new Error(`Config file not found: ${configPath}`);
47
+ }
48
+ const raw = fs.readFileSync(configPath, "utf8");
49
+ try {
50
+ return JSON.parse(raw);
51
+ }
52
+ catch (err) {
53
+ throw new Error(`Invalid JSON in config: ${configPath}`);
54
+ }
55
+ }
56
+ function readConfigIfExists(configPath) {
57
+ if (!configPath || !fs.existsSync(configPath)) {
58
+ return { unset: [], profiles: {} };
59
+ }
60
+ return readConfig(configPath);
61
+ }
62
+ function writeConfig(configPath, config) {
63
+ if (!configPath) {
64
+ throw new Error("Missing config path for write.");
65
+ }
66
+ const dir = path.dirname(configPath);
67
+ if (!fs.existsSync(dir)) {
68
+ fs.mkdirSync(dir, { recursive: true });
69
+ }
70
+ const data = JSON.stringify(config, null, 2);
71
+ fs.writeFileSync(configPath, `${data}\n`, "utf8");
72
+ }
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DEFAULT_UNSET_KEYS = exports.DEFAULT_PROFILE_TYPES = exports.CODEX_AUTH_PATH = void 0;
4
+ /**
5
+ * Constants for codenv
6
+ */
7
+ const path = require("path");
8
+ const os = require("os");
9
+ exports.CODEX_AUTH_PATH = path.join(os.homedir(), ".codex", "auth.json");
10
+ exports.DEFAULT_PROFILE_TYPES = ["codex", "claude"];
11
+ exports.DEFAULT_UNSET_KEYS = {
12
+ codex: [
13
+ "OPENAI_BASE_URL",
14
+ "OPENAI_API_KEY",
15
+ "CODE_ENV_PROFILE_KEY_CODEX",
16
+ "CODE_ENV_PROFILE_NAME_CODEX",
17
+ "CODE_ENV_CONFIG_PATH",
18
+ ],
19
+ claude: [
20
+ "ANTHROPIC_BASE_URL",
21
+ "ANTHROPIC_API_KEY",
22
+ "ANTHROPIC_AUTH_TOKEN",
23
+ "CODE_ENV_PROFILE_KEY_CLAUDE",
24
+ "CODE_ENV_PROFILE_NAME_CLAUDE",
25
+ "CODE_ENV_CONFIG_PATH",
26
+ ],
27
+ };
package/bin/index.js ADDED
@@ -0,0 +1,279 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ /**
5
+ * codenv - switch Claude/Codex env vars
6
+ * Main entry point
7
+ */
8
+ const fs = require("fs");
9
+ const constants_1 = require("./constants");
10
+ const cli_1 = require("./cli");
11
+ const shell_1 = require("./shell");
12
+ const config_1 = require("./config");
13
+ const profile_1 = require("./profile");
14
+ const commands_1 = require("./commands");
15
+ const usage_1 = require("./usage");
16
+ const ui_1 = require("./ui");
17
+ function getErrorMessage(err) {
18
+ return err instanceof Error ? err.message : String(err);
19
+ }
20
+ async function main() {
21
+ const parsed = (0, cli_1.parseArgs)(process.argv.slice(2));
22
+ if (parsed.help) {
23
+ (0, cli_1.printHelp)();
24
+ return;
25
+ }
26
+ const args = parsed.args || [];
27
+ if (args.length === 0) {
28
+ (0, cli_1.printHelp)();
29
+ return;
30
+ }
31
+ const cmd = args[0];
32
+ try {
33
+ if (cmd === "init") {
34
+ const initArgs = (0, cli_1.parseInitArgs)(args.slice(1));
35
+ const shellName = (0, shell_1.detectShell)(initArgs.shell);
36
+ if (!shellName) {
37
+ throw new Error("Unknown shell. Use --shell <bash|zsh|fish> to specify.");
38
+ }
39
+ const snippet = (0, shell_1.getShellSnippet)(shellName);
40
+ if (initArgs.apply) {
41
+ const rcPath = (0, shell_1.getShellRcPath)(shellName);
42
+ (0, shell_1.upsertShellSnippet)(rcPath, snippet);
43
+ console.log(`Updated shell config: ${rcPath}`);
44
+ }
45
+ else {
46
+ console.log(snippet);
47
+ }
48
+ return;
49
+ }
50
+ if (cmd === "add") {
51
+ const writePath = (0, config_1.findConfigPathForWrite)(parsed.configPath);
52
+ const addArgsRaw = args.slice(1);
53
+ const hasInteractive = addArgsRaw.length === 0;
54
+ if (hasInteractive) {
55
+ await (0, ui_1.runInteractiveAdd)(writePath);
56
+ return;
57
+ }
58
+ const addArgsResult = (0, cli_1.parseAddArgs)(addArgsRaw);
59
+ const config = (0, config_1.readConfigIfExists)(writePath);
60
+ const updated = (0, commands_1.addConfig)(config, addArgsResult);
61
+ (0, config_1.writeConfig)(writePath, updated);
62
+ console.log(`Updated config: ${writePath}`);
63
+ return;
64
+ }
65
+ if (cmd === "auto") {
66
+ const configPath = (0, config_1.findConfigPath)(parsed.configPath);
67
+ if (!configPath || !fs.existsSync(configPath))
68
+ return;
69
+ const config = (0, config_1.readConfig)(configPath);
70
+ const defaults = (0, config_1.getDefaultProfiles)(config);
71
+ const hasDefaults = constants_1.DEFAULT_PROFILE_TYPES.some((type) => defaults[type]);
72
+ if (!hasDefaults)
73
+ return;
74
+ let includeGlobalUnset = true;
75
+ for (const type of constants_1.DEFAULT_PROFILE_TYPES) {
76
+ const value = defaults[type];
77
+ if (!value)
78
+ continue;
79
+ try {
80
+ const profileName = (0, config_1.resolveDefaultProfileForType)(config, type, value);
81
+ if (!profileName)
82
+ continue;
83
+ (0, usage_1.logProfileUse)(config, configPath, profileName, type, process.env.CODE_ENV_TERMINAL_TAG || null, process.cwd());
84
+ (0, commands_1.printUse)(config, profileName, type, includeGlobalUnset, configPath);
85
+ includeGlobalUnset = false;
86
+ }
87
+ catch (err) {
88
+ console.error(`codenv: ${getErrorMessage(err)}`);
89
+ }
90
+ }
91
+ return;
92
+ }
93
+ if (cmd === "launch") {
94
+ const params = args.slice(1);
95
+ if (params.length === 0) {
96
+ throw new Error("Missing launch target.");
97
+ }
98
+ const target = params[0];
99
+ const passArgs = params.slice(1);
100
+ if (passArgs[0] === "--")
101
+ passArgs.shift();
102
+ const configPath = process.env.CODE_ENV_CONFIG_PATH || (0, config_1.findConfigPath)(parsed.configPath);
103
+ const config = (0, config_1.readConfigIfExists)(configPath);
104
+ const exitCode = await (0, commands_1.runLaunch)(config, configPath, target, passArgs);
105
+ process.exit(exitCode);
106
+ }
107
+ if (cmd === "statusline") {
108
+ const statuslineArgs = (0, cli_1.parseStatuslineArgs)(args.slice(1));
109
+ const configPath = process.env.CODE_ENV_CONFIG_PATH || (0, config_1.findConfigPath)(parsed.configPath);
110
+ const config = (0, config_1.readConfigIfExists)(configPath);
111
+ (0, commands_1.printStatusline)(config, configPath, statuslineArgs);
112
+ return;
113
+ }
114
+ const configPath = (0, config_1.findConfigPath)(parsed.configPath);
115
+ const config = (0, config_1.readConfig)(configPath);
116
+ if (cmd === "default") {
117
+ const params = args.slice(1);
118
+ if (params.length === 0) {
119
+ throw new Error("Missing profile name.");
120
+ }
121
+ const clear = params.length === 1 &&
122
+ (params[0] === "--clear" || params[0] === "--unset");
123
+ if (clear) {
124
+ const rl = (0, ui_1.createReadline)();
125
+ try {
126
+ const confirmed = await (0, ui_1.askConfirm)(rl, "Clear all default profiles? (y/N): ");
127
+ if (!confirmed)
128
+ return;
129
+ }
130
+ finally {
131
+ rl.close();
132
+ }
133
+ let changed = false;
134
+ if (Object.prototype.hasOwnProperty.call(config, "defaultProfiles")) {
135
+ delete config.defaultProfiles;
136
+ changed = true;
137
+ }
138
+ if (changed) {
139
+ (0, config_1.writeConfig)(configPath, config);
140
+ console.log(`Updated config: ${configPath}`);
141
+ }
142
+ return;
143
+ }
144
+ const requestedType = params.length >= 2 ? (0, profile_1.normalizeType)(params[0]) : null;
145
+ const profileName = (0, profile_1.resolveProfileName)(config, params);
146
+ let targetType = requestedType;
147
+ if (!targetType) {
148
+ const profile = config.profiles && config.profiles[profileName];
149
+ targetType = (0, profile_1.inferProfileType)(profileName, profile, null);
150
+ }
151
+ if (!targetType) {
152
+ throw new Error("Unable to infer profile type. Use: codenv default <type> <name>.");
153
+ }
154
+ if (!config.defaultProfiles || typeof config.defaultProfiles !== "object") {
155
+ config.defaultProfiles = {};
156
+ }
157
+ config.defaultProfiles[targetType] = profileName;
158
+ (0, config_1.writeConfig)(configPath, config);
159
+ console.log(`Updated config: ${configPath}`);
160
+ return;
161
+ }
162
+ if (cmd === "remove") {
163
+ const params = args.slice(1);
164
+ if (params.length === 0) {
165
+ throw new Error("Missing profile name.");
166
+ }
167
+ const isAll = params.length === 1 && params[0] === "--all";
168
+ if (isAll) {
169
+ if (!config.profiles || typeof config.profiles !== "object") {
170
+ config.profiles = {};
171
+ }
172
+ else {
173
+ config.profiles = {};
174
+ }
175
+ if (Object.prototype.hasOwnProperty.call(config, "defaultProfiles")) {
176
+ delete config.defaultProfiles;
177
+ }
178
+ (0, config_1.writeConfig)(configPath, config);
179
+ console.log(`Updated config: ${configPath}`);
180
+ return;
181
+ }
182
+ const targets = [];
183
+ const allPairs = params.length >= 2 &&
184
+ params.length % 2 === 0 &&
185
+ params.every((value, idx) => idx % 2 === 0 ? (0, profile_1.normalizeType)(value) : true);
186
+ if (allPairs) {
187
+ for (let i = 0; i < params.length; i += 2) {
188
+ targets.push((0, profile_1.resolveProfileName)(config, params.slice(i, i + 2)));
189
+ }
190
+ }
191
+ else {
192
+ for (const param of params) {
193
+ targets.push((0, profile_1.resolveProfileName)(config, [param]));
194
+ }
195
+ }
196
+ const uniqueTargets = Array.from(new Set(targets));
197
+ const missing = uniqueTargets.filter((name) => !config.profiles || !config.profiles[name]);
198
+ if (missing.length > 0) {
199
+ throw new Error(`Unknown profile(s): ${missing.join(", ")}`);
200
+ }
201
+ for (const name of uniqueTargets) {
202
+ delete config.profiles[name];
203
+ }
204
+ const defaults = (0, config_1.getDefaultProfiles)(config);
205
+ let changedDefaults = false;
206
+ for (const type of constants_1.DEFAULT_PROFILE_TYPES) {
207
+ const value = defaults[type];
208
+ if (!value)
209
+ continue;
210
+ try {
211
+ const resolved = (0, config_1.resolveDefaultProfileForType)(config, type, value);
212
+ if (resolved && uniqueTargets.includes(resolved)) {
213
+ if ((0, config_1.deleteDefaultProfileEntry)(config, type)) {
214
+ changedDefaults = true;
215
+ }
216
+ }
217
+ }
218
+ catch (err) {
219
+ // keep defaults that cannot be resolved
220
+ }
221
+ }
222
+ if (changedDefaults &&
223
+ config.defaultProfiles &&
224
+ Object.keys(config.defaultProfiles).length === 0) {
225
+ delete config.defaultProfiles;
226
+ }
227
+ (0, config_1.writeConfig)(configPath, config);
228
+ console.log(`Updated config: ${configPath}`);
229
+ return;
230
+ }
231
+ if (cmd === "config") {
232
+ const cfgPath = (0, config_1.findConfigPath)(parsed.configPath);
233
+ if (!cfgPath) {
234
+ console.log("(no config found)");
235
+ return;
236
+ }
237
+ console.log(cfgPath);
238
+ return;
239
+ }
240
+ if (cmd === "list" || cmd === "ls") {
241
+ (0, commands_1.printList)(config, configPath);
242
+ return;
243
+ }
244
+ if (cmd === "use") {
245
+ const params = args.slice(1);
246
+ if (params.length === 0) {
247
+ const printUseWithLog = (cfg, profileName, requestedType) => {
248
+ (0, usage_1.logProfileUse)(cfg, configPath, profileName, requestedType, process.env.CODE_ENV_TERMINAL_TAG || null, process.cwd());
249
+ (0, commands_1.printUse)(cfg, profileName, requestedType, true, configPath);
250
+ };
251
+ await (0, ui_1.runInteractiveUse)(config, printUseWithLog);
252
+ return;
253
+ }
254
+ const requestedType = params.length >= 2 ? (0, profile_1.normalizeType)(params[0]) : null;
255
+ const profileName = (0, profile_1.resolveProfileName)(config, params);
256
+ (0, usage_1.logProfileUse)(config, configPath, profileName, requestedType, process.env.CODE_ENV_TERMINAL_TAG || null, process.cwd());
257
+ (0, commands_1.printUse)(config, profileName, requestedType, true, configPath);
258
+ return;
259
+ }
260
+ if (cmd === "show") {
261
+ const profileName = (0, profile_1.resolveProfileName)(config, args.slice(1));
262
+ (0, commands_1.printShow)(config, profileName);
263
+ return;
264
+ }
265
+ if (cmd === "unset") {
266
+ (0, commands_1.printUnset)(config);
267
+ return;
268
+ }
269
+ throw new Error(`Unknown command: ${cmd}`);
270
+ }
271
+ catch (err) {
272
+ console.error(`codenv: ${getErrorMessage(err)}`);
273
+ process.exit(1);
274
+ }
275
+ }
276
+ main().catch((err) => {
277
+ console.error(`codenv: ${getErrorMessage(err)}`);
278
+ process.exit(1);
279
+ });
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isEnvValueUnset = isEnvValueUnset;
4
+ exports.buildEffectiveEnv = buildEffectiveEnv;
5
+ exports.envMatchesProfile = envMatchesProfile;
6
+ exports.buildListRows = buildListRows;
7
+ const constants_1 = require("../constants");
8
+ const type_1 = require("./type");
9
+ function isEnvValueUnset(value) {
10
+ return value === null || value === undefined || value === "";
11
+ }
12
+ function buildEffectiveEnv(profile, activeType) {
13
+ const env = profile && profile.env ? profile.env : {};
14
+ if (!activeType)
15
+ return env;
16
+ if (activeType !== "claude")
17
+ return env;
18
+ const apiKey = env.ANTHROPIC_API_KEY;
19
+ const authToken = env.ANTHROPIC_AUTH_TOKEN;
20
+ if (isEnvValueUnset(apiKey) || !isEnvValueUnset(authToken))
21
+ return env;
22
+ return { ...env, ANTHROPIC_AUTH_TOKEN: apiKey };
23
+ }
24
+ function envMatchesProfile(profile) {
25
+ if (!profile || !profile.env)
26
+ return false;
27
+ for (const key of Object.keys(profile.env)) {
28
+ const expected = profile.env[key];
29
+ const actual = process.env[key];
30
+ if (isEnvValueUnset(expected)) {
31
+ if (actual !== undefined && actual !== "")
32
+ return false;
33
+ continue;
34
+ }
35
+ if (actual !== String(expected))
36
+ return false;
37
+ }
38
+ return Object.keys(profile.env).length > 0;
39
+ }
40
+ // Forward declaration to avoid circular dependency
41
+ // getResolvedDefaultProfileKeys will be imported from config/defaults
42
+ function buildListRows(config, getResolvedDefaultProfileKeys) {
43
+ const profiles = config && config.profiles ? config.profiles : {};
44
+ const entries = Object.entries(profiles);
45
+ if (entries.length === 0)
46
+ return [];
47
+ const defaults = getResolvedDefaultProfileKeys(config);
48
+ const rows = entries.map(([key, profile]) => {
49
+ const safeProfile = profile || {};
50
+ const rawType = safeProfile.type ? String(safeProfile.type) : "";
51
+ const normalizedType = (0, type_1.normalizeType)(rawType);
52
+ const type = normalizedType || rawType || "-";
53
+ const inferredType = (0, type_1.inferProfileType)(key, safeProfile, null);
54
+ const usageType = inferredType || normalizedType || null;
55
+ const displayName = (0, type_1.getProfileDisplayName)(key, safeProfile);
56
+ const note = safeProfile.note ? String(safeProfile.note) : "";
57
+ const defaultTypes = constants_1.DEFAULT_PROFILE_TYPES.filter((profileType) => defaults[profileType] === key);
58
+ const defaultLabel = defaultTypes.length > 0 ? "default" : "";
59
+ const noteParts = [];
60
+ if (defaultLabel)
61
+ noteParts.push(defaultLabel);
62
+ if (note)
63
+ noteParts.push(note);
64
+ const noteText = noteParts.join(" | ");
65
+ const active = envMatchesProfile(safeProfile);
66
+ return { key, name: displayName, type, note: noteText, active, usageType };
67
+ });
68
+ rows.sort((a, b) => {
69
+ const nameCmp = a.name.localeCompare(b.name);
70
+ if (nameCmp !== 0)
71
+ return nameCmp;
72
+ const typeCmp = a.type.localeCompare(b.type);
73
+ if (typeCmp !== 0)
74
+ return typeCmp;
75
+ return a.key.localeCompare(b.key);
76
+ });
77
+ return rows;
78
+ }
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildListRows = exports.envMatchesProfile = exports.buildEffectiveEnv = exports.isEnvValueUnset = exports.resolveProfileByType = exports.resolveProfileName = exports.generateProfileKey = exports.shouldRemoveCodexAuth = exports.findProfileKeysByName = exports.profileMatchesType = exports.getProfileDisplayName = exports.stripTypePrefixFromName = exports.inferProfileType = exports.hasEnvKeyPrefix = exports.hasTypePrefix = exports.normalizeType = void 0;
4
+ /**
5
+ * Profile module exports
6
+ */
7
+ var type_1 = require("./type");
8
+ Object.defineProperty(exports, "normalizeType", { enumerable: true, get: function () { return type_1.normalizeType; } });
9
+ Object.defineProperty(exports, "hasTypePrefix", { enumerable: true, get: function () { return type_1.hasTypePrefix; } });
10
+ Object.defineProperty(exports, "hasEnvKeyPrefix", { enumerable: true, get: function () { return type_1.hasEnvKeyPrefix; } });
11
+ Object.defineProperty(exports, "inferProfileType", { enumerable: true, get: function () { return type_1.inferProfileType; } });
12
+ Object.defineProperty(exports, "stripTypePrefixFromName", { enumerable: true, get: function () { return type_1.stripTypePrefixFromName; } });
13
+ Object.defineProperty(exports, "getProfileDisplayName", { enumerable: true, get: function () { return type_1.getProfileDisplayName; } });
14
+ var match_1 = require("./match");
15
+ Object.defineProperty(exports, "profileMatchesType", { enumerable: true, get: function () { return match_1.profileMatchesType; } });
16
+ Object.defineProperty(exports, "findProfileKeysByName", { enumerable: true, get: function () { return match_1.findProfileKeysByName; } });
17
+ Object.defineProperty(exports, "shouldRemoveCodexAuth", { enumerable: true, get: function () { return match_1.shouldRemoveCodexAuth; } });
18
+ var resolve_1 = require("./resolve");
19
+ Object.defineProperty(exports, "generateProfileKey", { enumerable: true, get: function () { return resolve_1.generateProfileKey; } });
20
+ Object.defineProperty(exports, "resolveProfileName", { enumerable: true, get: function () { return resolve_1.resolveProfileName; } });
21
+ Object.defineProperty(exports, "resolveProfileByType", { enumerable: true, get: function () { return resolve_1.resolveProfileByType; } });
22
+ var display_1 = require("./display");
23
+ Object.defineProperty(exports, "isEnvValueUnset", { enumerable: true, get: function () { return display_1.isEnvValueUnset; } });
24
+ Object.defineProperty(exports, "buildEffectiveEnv", { enumerable: true, get: function () { return display_1.buildEffectiveEnv; } });
25
+ Object.defineProperty(exports, "envMatchesProfile", { enumerable: true, get: function () { return display_1.envMatchesProfile; } });
26
+ Object.defineProperty(exports, "buildListRows", { enumerable: true, get: function () { return display_1.buildListRows; } });
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.profileMatchesType = profileMatchesType;
4
+ exports.findProfileKeysByName = findProfileKeysByName;
5
+ exports.shouldRemoveCodexAuth = shouldRemoveCodexAuth;
6
+ const type_1 = require("./type");
7
+ function profileMatchesType(profile, type) {
8
+ if (!profile)
9
+ return false;
10
+ if (!profile.type)
11
+ return true;
12
+ const t = (0, type_1.normalizeType)(profile.type);
13
+ if (!t)
14
+ return false;
15
+ return t === type;
16
+ }
17
+ function findProfileKeysByName(config, name, type) {
18
+ const profiles = config && config.profiles ? config.profiles : {};
19
+ const matches = [];
20
+ for (const [key, profile] of Object.entries(profiles)) {
21
+ const safeProfile = profile || {};
22
+ if (type && !profileMatchesType(safeProfile, type))
23
+ continue;
24
+ const displayName = (0, type_1.getProfileDisplayName)(key, safeProfile, type || null);
25
+ if (displayName === name)
26
+ matches.push(key);
27
+ }
28
+ return matches;
29
+ }
30
+ function shouldRemoveCodexAuth(profileName, profile, requestedType) {
31
+ if (requestedType === "codex")
32
+ return true;
33
+ if (!profile)
34
+ return false;
35
+ if ((0, type_1.normalizeType)(profile.type) === "codex")
36
+ return true;
37
+ if ((0, type_1.hasEnvKeyPrefix)(profile, "OPENAI_"))
38
+ return true;
39
+ return (0, type_1.hasTypePrefix)(profileName, "codex");
40
+ }