@gpc-cli/config 0.1.1 → 0.1.3

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 ADDED
@@ -0,0 +1,97 @@
1
+ # @gpc-cli/config
2
+
3
+ Configuration loading and validation for GPC. Handles config files, environment variables, profiles, and XDG-compliant paths.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install @gpc-cli/config
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```typescript
14
+ import {
15
+ loadConfig,
16
+ findConfigFile,
17
+ loadEnvConfig,
18
+ getConfigDir,
19
+ initConfig,
20
+ } from "@gpc-cli/config";
21
+
22
+ // Load config (merges file + env vars)
23
+ const config = await loadConfig();
24
+
25
+ // Find .gpcrc.json in cwd or parents
26
+ const configPath = findConfigFile();
27
+
28
+ // Load from environment variables only
29
+ const envConfig = loadEnvConfig();
30
+
31
+ // Get XDG-compliant paths
32
+ const configDir = getConfigDir(); // ~/.config/gpc
33
+ ```
34
+
35
+ ## Config Sources
36
+
37
+ Configuration is merged in priority order:
38
+
39
+ 1. CLI flags (highest)
40
+ 2. Environment variables (`GPC_*`)
41
+ 3. Project config (`.gpcrc.json` in cwd or parents)
42
+ 4. User config (`~/.config/gpc/config.json`)
43
+ 5. Defaults (lowest)
44
+
45
+ ## Environment Variables
46
+
47
+ | Variable | Description |
48
+ | --------------------- | ---------------------------------------- |
49
+ | `GPC_SERVICE_ACCOUNT` | Service account JSON string or file path |
50
+ | `GPC_APP` | Default package name |
51
+ | `GPC_PROFILE` | Auth profile name |
52
+ | `GPC_OUTPUT` | Default output format |
53
+ | `GPC_NO_COLOR` | Disable color output |
54
+ | `GPC_NO_INTERACTIVE` | Disable prompts |
55
+
56
+ ## Profiles
57
+
58
+ ```typescript
59
+ import { setProfileConfig, listProfiles, deleteProfile } from "@gpc-cli/config";
60
+
61
+ // Create a profile
62
+ await setProfileConfig("production", {
63
+ serviceAccount: "./keys/prod.json",
64
+ });
65
+
66
+ // List profiles
67
+ const profiles = await listProfiles();
68
+
69
+ // Delete a profile
70
+ await deleteProfile("staging");
71
+ ```
72
+
73
+ ## API
74
+
75
+ | Function | Description |
76
+ | ------------------------ | ----------------------------------------------- |
77
+ | `loadConfig()` | Load merged config from all sources |
78
+ | `findConfigFile()` | Find `.gpcrc.json` in cwd or parent directories |
79
+ | `loadEnvConfig()` | Load config from `GPC_*` env vars |
80
+ | `initConfig()` | Create initial `.gpcrc.json` |
81
+ | `setConfigValue()` | Set a config key/value |
82
+ | `getConfigDir()` | XDG config directory (`~/.config/gpc`) |
83
+ | `getDataDir()` | XDG data directory (`~/.local/share/gpc`) |
84
+ | `getCacheDir()` | XDG cache directory (`~/.cache/gpc`) |
85
+ | `listProfiles()` | List saved auth profiles |
86
+ | `setProfileConfig()` | Create or update a profile |
87
+ | `deleteProfile()` | Delete a profile |
88
+ | `approvePlugin()` | Approve a third-party plugin |
89
+ | `revokePluginApproval()` | Revoke plugin approval |
90
+
91
+ ## Part of the GPC Monorepo
92
+
93
+ This is the config layer for [GPC](https://github.com/yasserstudio/gpc).
94
+
95
+ ## License
96
+
97
+ MIT
package/dist/index.d.ts CHANGED
@@ -29,7 +29,7 @@ interface ResolvedConfig extends Required<Pick<GpcConfig, "output">> {
29
29
  }
30
30
 
31
31
  declare function loadEnvConfig(): Partial<GpcConfig>;
32
- declare function findConfigFile(startDir?: string): string | undefined;
32
+ declare function findConfigFile(startDir?: string): Promise<string | undefined>;
33
33
  declare function loadConfig(overrides?: Partial<GpcConfig>): Promise<ResolvedConfig>;
34
34
 
35
35
  declare function getConfigDir(): string;
package/dist/index.js CHANGED
@@ -1,6 +1,5 @@
1
1
  // src/loader.ts
2
- import { statSync } from "fs";
3
- import { readFile } from "fs/promises";
2
+ import { readFile, stat } from "fs/promises";
4
3
  import { dirname, join as join2 } from "path";
5
4
 
6
5
  // src/defaults.ts
@@ -11,34 +10,30 @@ var DEFAULT_CONFIG = {
11
10
  // src/paths.ts
12
11
  import { homedir } from "os";
13
12
  import { join, isAbsolute } from "path";
13
+ var HOME = homedir();
14
14
  function resolveXdg(envVar, fallback) {
15
15
  const xdg = process.env[envVar];
16
16
  if (xdg && isAbsolute(xdg)) return xdg;
17
17
  return fallback;
18
18
  }
19
19
  function getConfigDir() {
20
- const base = resolveXdg("XDG_CONFIG_HOME", join(homedir(), ".config"));
20
+ const base = resolveXdg("XDG_CONFIG_HOME", join(HOME, ".config"));
21
21
  return join(base, "gpc");
22
22
  }
23
23
  function getUserConfigPath() {
24
24
  return join(getConfigDir(), "config.json");
25
25
  }
26
26
  function getDataDir() {
27
- const base = resolveXdg("XDG_DATA_HOME", join(homedir(), ".local", "share"));
27
+ const base = resolveXdg("XDG_DATA_HOME", join(HOME, ".local", "share"));
28
28
  return join(base, "gpc");
29
29
  }
30
30
  function getCacheDir() {
31
- const base = resolveXdg("XDG_CACHE_HOME", join(homedir(), ".cache"));
31
+ const base = resolveXdg("XDG_CACHE_HOME", join(HOME, ".cache"));
32
32
  return join(base, "gpc");
33
33
  }
34
34
 
35
35
  // src/loader.ts
36
- var VALID_OUTPUT_FORMATS = /* @__PURE__ */ new Set([
37
- "table",
38
- "json",
39
- "yaml",
40
- "markdown"
41
- ]);
36
+ var VALID_OUTPUT_FORMATS = /* @__PURE__ */ new Set(["table", "json", "yaml", "markdown"]);
42
37
  function isValidOutputFormat(value) {
43
38
  return VALID_OUTPUT_FORMATS.has(value);
44
39
  }
@@ -62,12 +57,12 @@ function loadEnvConfig() {
62
57
  if (developerId) config.developerId = developerId;
63
58
  return config;
64
59
  }
65
- function findConfigFile(startDir) {
60
+ async function findConfigFile(startDir) {
66
61
  let dir = startDir || process.cwd();
67
62
  while (true) {
68
63
  const candidate = join2(dir, ".gpcrc.json");
69
64
  try {
70
- statSync(candidate);
65
+ await stat(candidate);
71
66
  return candidate;
72
67
  } catch {
73
68
  }
@@ -98,7 +93,7 @@ function sanitizeObject(obj) {
98
93
  const record = obj;
99
94
  for (const key of Object.keys(record)) {
100
95
  if (DANGEROUS_KEYS.has(key)) {
101
- delete record[key];
96
+ record[key] = void 0;
102
97
  } else if (typeof record[key] === "object" && record[key] !== null) {
103
98
  sanitizeObject(record[key]);
104
99
  }
@@ -111,7 +106,7 @@ async function loadConfig(overrides) {
111
106
  Object.assign(result, stripUndefined(userConfig));
112
107
  } catch {
113
108
  }
114
- const projectConfigPath = findConfigFile();
109
+ const projectConfigPath = await findConfigFile();
115
110
  if (projectConfigPath) {
116
111
  try {
117
112
  const projectConfig = await readConfigFile(projectConfigPath);
@@ -127,9 +122,9 @@ async function loadConfig(overrides) {
127
122
  }
128
123
  if (result.profile && result.profiles?.[result.profile]) {
129
124
  const p = result.profiles[result.profile];
130
- if (p.auth) result.auth = p.auth;
131
- if (p.app) result.app = p.app;
132
- if (p.developerId) result.developerId = p.developerId;
125
+ if (p?.auth) result.auth = p.auth;
126
+ if (p?.app) result.app = p.app;
127
+ if (p?.developerId) result.developerId = p.developerId;
133
128
  } else if (result.profile && result.profiles && !(result.profile in result.profiles)) {
134
129
  const available = Object.keys(result.profiles).join(", ");
135
130
  throw new Error(
@@ -176,7 +171,8 @@ async function setConfigValue(key, value) {
176
171
  }
177
172
  target = target[k];
178
173
  }
179
- target[keys[keys.length - 1]] = value;
174
+ const lastKey = keys[keys.length - 1];
175
+ target[lastKey] = value;
180
176
  await mkdir(dirname2(configPath), { recursive: true, mode: 448 });
181
177
  await writeSecureFile(configPath, JSON.stringify(existing, null, 2) + "\n");
182
178
  }
@@ -197,7 +193,7 @@ async function setProfileConfig(profileName, config) {
197
193
  }
198
194
  async function deleteProfile(profileName) {
199
195
  const configPath = join3(getConfigDir(), "config.json");
200
- let existing = {};
196
+ let existing;
201
197
  try {
202
198
  const content = await readFile2(configPath, "utf-8");
203
199
  existing = JSON.parse(content);
@@ -206,7 +202,9 @@ async function deleteProfile(profileName) {
206
202
  }
207
203
  const profiles = existing["profiles"];
208
204
  if (!profiles || !(profileName in profiles)) return false;
209
- delete profiles[profileName];
205
+ existing["profiles"] = Object.fromEntries(
206
+ Object.entries(profiles).filter(([key]) => key !== profileName)
207
+ );
210
208
  await writeSecureFile(configPath, JSON.stringify(existing, null, 2) + "\n");
211
209
  return true;
212
210
  }
@@ -239,7 +237,7 @@ async function approvePlugin(pluginName) {
239
237
  }
240
238
  async function revokePluginApproval(pluginName) {
241
239
  const configPath = join3(getConfigDir(), "config.json");
242
- let existing = {};
240
+ let existing;
243
241
  try {
244
242
  const content = await readFile2(configPath, "utf-8");
245
243
  existing = JSON.parse(content);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/loader.ts","../src/defaults.ts","../src/paths.ts","../src/writer.ts"],"sourcesContent":["import { statSync } from \"node:fs\";\nimport { readFile } from \"node:fs/promises\";\nimport { dirname, join } from \"node:path\";\n\nimport { DEFAULT_CONFIG } from \"./defaults.js\";\nimport { getUserConfigPath } from \"./paths.js\";\nimport type { GpcConfig, OutputFormat, ResolvedConfig } from \"./types.js\";\n\nconst VALID_OUTPUT_FORMATS: ReadonlySet<string> = new Set([\n \"table\",\n \"json\",\n \"yaml\",\n \"markdown\",\n]);\n\nfunction isValidOutputFormat(value: string): value is OutputFormat {\n return VALID_OUTPUT_FORMATS.has(value);\n}\n\nexport function loadEnvConfig(): Partial<GpcConfig> {\n const config: Partial<GpcConfig> = {};\n\n const app = process.env[\"GPC_APP\"];\n if (app) config.app = app;\n\n const output = process.env[\"GPC_OUTPUT\"];\n if (output) {\n if (isValidOutputFormat(output)) {\n config.output = output;\n }\n }\n\n const profile = process.env[\"GPC_PROFILE\"];\n if (profile) config.profile = profile;\n\n const serviceAccount = process.env[\"GPC_SERVICE_ACCOUNT\"];\n if (serviceAccount) {\n config.auth = { serviceAccount };\n }\n\n const developerId = process.env[\"GPC_DEVELOPER_ID\"];\n if (developerId) config.developerId = developerId;\n\n return config;\n}\n\nexport function findConfigFile(startDir?: string): string | undefined {\n let dir = startDir || process.cwd();\n\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n while (true) {\n const candidate = join(dir, \".gpcrc.json\");\n try {\n statSync(candidate);\n return candidate;\n } catch {\n // file does not exist, keep walking up\n }\n\n const parent = dirname(dir);\n if (parent === dir) break; // reached root\n dir = parent;\n }\n\n return undefined;\n}\n\nexport async function readConfigFile(filePath: string): Promise<GpcConfig> {\n const content = await readFile(filePath, \"utf-8\");\n const parsed = JSON.parse(content) as GpcConfig;\n\n // Guard against prototype pollution\n sanitizeObject(parsed);\n\n // Validate output format if present\n if (parsed.output !== undefined && !isValidOutputFormat(parsed.output)) {\n throw new Error(\n `Invalid output format \"${String(parsed.output)}\" in ${filePath}. Must be one of: ${[...VALID_OUTPUT_FORMATS].join(\", \")}`,\n );\n }\n\n return parsed;\n}\n\nconst DANGEROUS_KEYS = new Set([\"__proto__\", \"constructor\", \"prototype\"]);\n\n/** Remove prototype pollution vectors from parsed JSON objects recursively. */\nfunction sanitizeObject(obj: unknown): void {\n if (!obj || typeof obj !== \"object\") return;\n if (Array.isArray(obj)) {\n for (const item of obj) sanitizeObject(item);\n return;\n }\n const record = obj as Record<string, unknown>;\n for (const key of Object.keys(record)) {\n if (DANGEROUS_KEYS.has(key)) {\n delete record[key];\n } else if (typeof record[key] === \"object\" && record[key] !== null) {\n sanitizeObject(record[key]);\n }\n }\n}\n\nexport async function loadConfig(\n overrides?: Partial<GpcConfig>,\n): Promise<ResolvedConfig> {\n // Layer 5: defaults\n const result: ResolvedConfig = { ...DEFAULT_CONFIG };\n\n // Layer 4: user config file (~/.config/gpc/config.json)\n try {\n const userConfig = await readConfigFile(getUserConfigPath());\n Object.assign(result, stripUndefined(userConfig));\n } catch {\n // User config doesn't exist or is invalid — skip\n }\n\n // Layer 3: project config file (.gpcrc.json walking up)\n const projectConfigPath = findConfigFile();\n if (projectConfigPath) {\n try {\n const projectConfig = await readConfigFile(projectConfigPath);\n Object.assign(result, stripUndefined(projectConfig));\n result.configPath = projectConfigPath;\n } catch {\n // Project config is invalid — skip\n }\n }\n\n // Layer 2: environment variables\n const envConfig = loadEnvConfig();\n Object.assign(result, stripUndefined(envConfig));\n\n // Layer 1: CLI flag overrides\n if (overrides) {\n Object.assign(result, stripUndefined(overrides));\n }\n\n // Resolve profile overrides\n if (result.profile && result.profiles?.[result.profile]) {\n const p = result.profiles[result.profile]!;\n if (p.auth) result.auth = p.auth;\n if (p.app) result.app = p.app;\n if (p.developerId) result.developerId = p.developerId;\n } else if (result.profile && result.profiles && !(result.profile in result.profiles)) {\n const available = Object.keys(result.profiles).join(\", \");\n throw new Error(\n `Profile \"${result.profile}\" not found. Available profiles: ${available || \"(none)\"}`,\n );\n }\n\n // Validate final output format\n if (!isValidOutputFormat(result.output)) {\n result.output = DEFAULT_CONFIG.output;\n }\n\n return result;\n}\n\nfunction stripUndefined<T extends object>(obj: T): Partial<T> {\n const cleaned: Partial<T> = {};\n for (const [key, value] of Object.entries(obj)) {\n if (value !== undefined) {\n (cleaned as Record<string, unknown>)[key] = value;\n }\n }\n return cleaned;\n}\n","import type { ResolvedConfig } from \"./types.js\";\n\nexport const DEFAULT_CONFIG: ResolvedConfig = {\n output: \"table\",\n};\n","import { homedir } from \"node:os\";\nimport { join, isAbsolute } from \"node:path\";\n\nfunction resolveXdg(envVar: string, fallback: string): string {\n const xdg = process.env[envVar];\n if (xdg && isAbsolute(xdg)) return xdg;\n return fallback;\n}\n\nexport function getConfigDir(): string {\n const base = resolveXdg(\"XDG_CONFIG_HOME\", join(homedir(), \".config\"));\n return join(base, \"gpc\");\n}\n\nexport function getUserConfigPath(): string {\n return join(getConfigDir(), \"config.json\");\n}\n\nexport function getDataDir(): string {\n const base = resolveXdg(\"XDG_DATA_HOME\", join(homedir(), \".local\", \"share\"));\n return join(base, \"gpc\");\n}\n\nexport function getCacheDir(): string {\n const base = resolveXdg(\"XDG_CACHE_HOME\", join(homedir(), \".cache\"));\n return join(base, \"gpc\");\n}\n","import { chmod, mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport { dirname, join } from \"node:path\";\n\nimport { getConfigDir } from \"./paths.js\";\nimport type { GpcConfig, ProfileConfig } from \"./types.js\";\n\nasync function writeSecureFile(filePath: string, content: string): Promise<void> {\n await writeFile(filePath, content, { encoding: \"utf-8\", mode: 0o600 });\n await chmod(filePath, 0o600).catch(() => {});\n}\n\nexport async function setConfigValue(\n key: string,\n value: string,\n): Promise<void> {\n const configPath = join(getConfigDir(), \"config.json\");\n\n let existing: Record<string, unknown> = {};\n try {\n const content = await readFile(configPath, \"utf-8\");\n existing = JSON.parse(content) as Record<string, unknown>;\n } catch {\n // File doesn't exist yet — start fresh\n }\n\n // Support dotted keys like \"auth.serviceAccount\"\n const keys = key.split(\".\");\n let target = existing;\n for (let i = 0; i < keys.length - 1; i++) {\n const k = keys[i]!;\n if (typeof target[k] !== \"object\" || target[k] === null) {\n target[k] = {};\n }\n target = target[k] as Record<string, unknown>;\n }\n target[keys[keys.length - 1]!] = value;\n\n await mkdir(dirname(configPath), { recursive: true, mode: 0o700 });\n await writeSecureFile(configPath, JSON.stringify(existing, null, 2) + \"\\n\");\n}\n\nexport async function setProfileConfig(\n profileName: string,\n config: ProfileConfig,\n): Promise<void> {\n const configPath = join(getConfigDir(), \"config.json\");\n\n let existing: Record<string, unknown> = {};\n try {\n const content = await readFile(configPath, \"utf-8\");\n existing = JSON.parse(content) as Record<string, unknown>;\n } catch {\n // start fresh\n }\n\n if (typeof existing[\"profiles\"] !== \"object\" || existing[\"profiles\"] === null) {\n existing[\"profiles\"] = {};\n }\n (existing[\"profiles\"] as Record<string, unknown>)[profileName] = config;\n\n await mkdir(dirname(configPath), { recursive: true, mode: 0o700 });\n await writeSecureFile(configPath, JSON.stringify(existing, null, 2) + \"\\n\");\n}\n\nexport async function deleteProfile(profileName: string): Promise<boolean> {\n const configPath = join(getConfigDir(), \"config.json\");\n\n let existing: Record<string, unknown> = {};\n try {\n const content = await readFile(configPath, \"utf-8\");\n existing = JSON.parse(content) as Record<string, unknown>;\n } catch {\n return false;\n }\n\n const profiles = existing[\"profiles\"] as Record<string, unknown> | undefined;\n if (!profiles || !(profileName in profiles)) return false;\n\n delete profiles[profileName];\n await writeSecureFile(configPath, JSON.stringify(existing, null, 2) + \"\\n\");\n return true;\n}\n\nexport async function listProfiles(): Promise<string[]> {\n const configPath = join(getConfigDir(), \"config.json\");\n\n try {\n const content = await readFile(configPath, \"utf-8\");\n const config = JSON.parse(content) as Record<string, unknown>;\n const profiles = config[\"profiles\"] as Record<string, unknown> | undefined;\n return profiles ? Object.keys(profiles) : [];\n } catch {\n return [];\n }\n}\n\nexport async function approvePlugin(pluginName: string): Promise<void> {\n const configPath = join(getConfigDir(), \"config.json\");\n\n let existing: Record<string, unknown> = {};\n try {\n const content = await readFile(configPath, \"utf-8\");\n existing = JSON.parse(content) as Record<string, unknown>;\n } catch {\n // start fresh\n }\n\n const approved = (existing[\"approvedPlugins\"] as string[] | undefined) ?? [];\n if (!approved.includes(pluginName)) {\n approved.push(pluginName);\n }\n existing[\"approvedPlugins\"] = approved;\n\n await mkdir(dirname(configPath), { recursive: true, mode: 0o700 });\n await writeSecureFile(configPath, JSON.stringify(existing, null, 2) + \"\\n\");\n}\n\nexport async function revokePluginApproval(pluginName: string): Promise<boolean> {\n const configPath = join(getConfigDir(), \"config.json\");\n\n let existing: Record<string, unknown> = {};\n try {\n const content = await readFile(configPath, \"utf-8\");\n existing = JSON.parse(content) as Record<string, unknown>;\n } catch {\n return false;\n }\n\n const approved = (existing[\"approvedPlugins\"] as string[] | undefined) ?? [];\n const index = approved.indexOf(pluginName);\n if (index === -1) return false;\n\n approved.splice(index, 1);\n existing[\"approvedPlugins\"] = approved;\n await writeSecureFile(configPath, JSON.stringify(existing, null, 2) + \"\\n\");\n return true;\n}\n\nexport async function initConfig(config: GpcConfig): Promise<string> {\n const configDir = getConfigDir();\n const configPath = join(configDir, \"config.json\");\n\n await mkdir(configDir, { recursive: true, mode: 0o700 });\n await writeSecureFile(configPath, JSON.stringify(config, null, 2) + \"\\n\");\n\n return configPath;\n}\n"],"mappings":"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","names":["join","join","readFile","dirname","join","join","readFile","dirname"]}
1
+ {"version":3,"sources":["../src/loader.ts","../src/defaults.ts","../src/paths.ts","../src/writer.ts"],"sourcesContent":["import { readFile, stat } from \"node:fs/promises\";\nimport { dirname, join } from \"node:path\";\n\nimport { DEFAULT_CONFIG } from \"./defaults.js\";\nimport { getUserConfigPath } from \"./paths.js\";\nimport type { GpcConfig, OutputFormat, ResolvedConfig } from \"./types.js\";\n\nconst VALID_OUTPUT_FORMATS: ReadonlySet<string> = new Set([\"table\", \"json\", \"yaml\", \"markdown\"]);\n\nfunction isValidOutputFormat(value: string): value is OutputFormat {\n return VALID_OUTPUT_FORMATS.has(value);\n}\n\nexport function loadEnvConfig(): Partial<GpcConfig> {\n const config: Partial<GpcConfig> = {};\n\n const app = process.env[\"GPC_APP\"];\n if (app) config.app = app;\n\n const output = process.env[\"GPC_OUTPUT\"];\n if (output) {\n if (isValidOutputFormat(output)) {\n config.output = output;\n }\n }\n\n const profile = process.env[\"GPC_PROFILE\"];\n if (profile) config.profile = profile;\n\n const serviceAccount = process.env[\"GPC_SERVICE_ACCOUNT\"];\n if (serviceAccount) {\n config.auth = { serviceAccount };\n }\n\n const developerId = process.env[\"GPC_DEVELOPER_ID\"];\n if (developerId) config.developerId = developerId;\n\n return config;\n}\n\nexport async function findConfigFile(startDir?: string): Promise<string | undefined> {\n let dir = startDir || process.cwd();\n\n while (true) {\n const candidate = join(dir, \".gpcrc.json\");\n try {\n await stat(candidate);\n return candidate;\n } catch {\n // file does not exist, keep walking up\n }\n\n const parent = dirname(dir);\n if (parent === dir) break; // reached root\n dir = parent;\n }\n\n return undefined;\n}\n\nexport async function readConfigFile(filePath: string): Promise<GpcConfig> {\n const content = await readFile(filePath, \"utf-8\");\n const parsed = JSON.parse(content) as GpcConfig;\n\n // Guard against prototype pollution\n sanitizeObject(parsed);\n\n // Validate output format if present\n if (parsed.output !== undefined && !isValidOutputFormat(parsed.output)) {\n throw new Error(\n `Invalid output format \"${String(parsed.output)}\" in ${filePath}. Must be one of: ${[...VALID_OUTPUT_FORMATS].join(\", \")}`,\n );\n }\n\n return parsed;\n}\n\nconst DANGEROUS_KEYS = new Set([\"__proto__\", \"constructor\", \"prototype\"]);\n\n/** Remove prototype pollution vectors from parsed JSON objects recursively. */\nfunction sanitizeObject(obj: unknown): void {\n if (!obj || typeof obj !== \"object\") return;\n if (Array.isArray(obj)) {\n for (const item of obj) sanitizeObject(item);\n return;\n }\n const record = obj as Record<string, unknown>;\n for (const key of Object.keys(record)) {\n if (DANGEROUS_KEYS.has(key)) {\n record[key] = undefined;\n } else if (typeof record[key] === \"object\" && record[key] !== null) {\n sanitizeObject(record[key]);\n }\n }\n}\n\nexport async function loadConfig(overrides?: Partial<GpcConfig>): Promise<ResolvedConfig> {\n // Layer 5: defaults\n const result: ResolvedConfig = { ...DEFAULT_CONFIG };\n\n // Layer 4: user config file (~/.config/gpc/config.json)\n try {\n const userConfig = await readConfigFile(getUserConfigPath());\n Object.assign(result, stripUndefined(userConfig));\n } catch {\n // User config doesn't exist or is invalid — skip\n }\n\n // Layer 3: project config file (.gpcrc.json walking up)\n const projectConfigPath = await findConfigFile();\n if (projectConfigPath) {\n try {\n const projectConfig = await readConfigFile(projectConfigPath);\n Object.assign(result, stripUndefined(projectConfig));\n result.configPath = projectConfigPath;\n } catch {\n // Project config is invalid — skip\n }\n }\n\n // Layer 2: environment variables\n const envConfig = loadEnvConfig();\n Object.assign(result, stripUndefined(envConfig));\n\n // Layer 1: CLI flag overrides\n if (overrides) {\n Object.assign(result, stripUndefined(overrides));\n }\n\n // Resolve profile overrides\n if (result.profile && result.profiles?.[result.profile]) {\n const p = result.profiles[result.profile];\n if (p?.auth) result.auth = p.auth;\n if (p?.app) result.app = p.app;\n if (p?.developerId) result.developerId = p.developerId;\n } else if (result.profile && result.profiles && !(result.profile in result.profiles)) {\n const available = Object.keys(result.profiles).join(\", \");\n throw new Error(\n `Profile \"${result.profile}\" not found. Available profiles: ${available || \"(none)\"}`,\n );\n }\n\n // Validate final output format\n if (!isValidOutputFormat(result.output)) {\n result.output = DEFAULT_CONFIG.output;\n }\n\n return result;\n}\n\nfunction stripUndefined<T extends object>(obj: T): Partial<T> {\n const cleaned: Partial<T> = {};\n for (const [key, value] of Object.entries(obj)) {\n if (value !== undefined) {\n (cleaned as Record<string, unknown>)[key] = value;\n }\n }\n return cleaned;\n}\n","import type { ResolvedConfig } from \"./types.js\";\n\nexport const DEFAULT_CONFIG: ResolvedConfig = {\n output: \"table\",\n};\n","import { homedir } from \"node:os\";\nimport { join, isAbsolute } from \"node:path\";\n\n// Cache homedir() — it calls an OS function, no need to repeat per call\nconst HOME = homedir();\n\nfunction resolveXdg(envVar: string, fallback: string): string {\n const xdg = process.env[envVar];\n if (xdg && isAbsolute(xdg)) return xdg;\n return fallback;\n}\n\nexport function getConfigDir(): string {\n const base = resolveXdg(\"XDG_CONFIG_HOME\", join(HOME, \".config\"));\n return join(base, \"gpc\");\n}\n\nexport function getUserConfigPath(): string {\n return join(getConfigDir(), \"config.json\");\n}\n\nexport function getDataDir(): string {\n const base = resolveXdg(\"XDG_DATA_HOME\", join(HOME, \".local\", \"share\"));\n return join(base, \"gpc\");\n}\n\nexport function getCacheDir(): string {\n const base = resolveXdg(\"XDG_CACHE_HOME\", join(HOME, \".cache\"));\n return join(base, \"gpc\");\n}\n","import { chmod, mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport { dirname, join } from \"node:path\";\n\nimport { getConfigDir } from \"./paths.js\";\nimport type { GpcConfig, ProfileConfig } from \"./types.js\";\n\nasync function writeSecureFile(filePath: string, content: string): Promise<void> {\n await writeFile(filePath, content, { encoding: \"utf-8\", mode: 0o600 });\n await chmod(filePath, 0o600).catch(() => {});\n}\n\nexport async function setConfigValue(key: string, value: string): Promise<void> {\n const configPath = join(getConfigDir(), \"config.json\");\n\n let existing: Record<string, unknown> = {};\n try {\n const content = await readFile(configPath, \"utf-8\");\n existing = JSON.parse(content) as Record<string, unknown>;\n } catch {\n // File doesn't exist yet — start fresh\n }\n\n // Support dotted keys like \"auth.serviceAccount\"\n const keys = key.split(\".\");\n let target = existing;\n for (let i = 0; i < keys.length - 1; i++) {\n const k = keys[i] as string;\n if (typeof target[k] !== \"object\" || target[k] === null) {\n target[k] = {};\n }\n target = target[k] as Record<string, unknown>;\n }\n const lastKey = keys[keys.length - 1] as string;\n target[lastKey] = value;\n\n await mkdir(dirname(configPath), { recursive: true, mode: 0o700 });\n await writeSecureFile(configPath, JSON.stringify(existing, null, 2) + \"\\n\");\n}\n\nexport async function setProfileConfig(profileName: string, config: ProfileConfig): Promise<void> {\n const configPath = join(getConfigDir(), \"config.json\");\n\n let existing: Record<string, unknown> = {};\n try {\n const content = await readFile(configPath, \"utf-8\");\n existing = JSON.parse(content) as Record<string, unknown>;\n } catch {\n // start fresh\n }\n\n if (typeof existing[\"profiles\"] !== \"object\" || existing[\"profiles\"] === null) {\n existing[\"profiles\"] = {};\n }\n (existing[\"profiles\"] as Record<string, unknown>)[profileName] = config;\n\n await mkdir(dirname(configPath), { recursive: true, mode: 0o700 });\n await writeSecureFile(configPath, JSON.stringify(existing, null, 2) + \"\\n\");\n}\n\nexport async function deleteProfile(profileName: string): Promise<boolean> {\n const configPath = join(getConfigDir(), \"config.json\");\n\n let existing: Record<string, unknown>;\n try {\n const content = await readFile(configPath, \"utf-8\");\n existing = JSON.parse(content) as Record<string, unknown>;\n } catch {\n return false;\n }\n\n const profiles = existing[\"profiles\"] as Record<string, unknown> | undefined;\n if (!profiles || !(profileName in profiles)) return false;\n\n existing[\"profiles\"] = Object.fromEntries(\n Object.entries(profiles).filter(([key]) => key !== profileName),\n );\n await writeSecureFile(configPath, JSON.stringify(existing, null, 2) + \"\\n\");\n return true;\n}\n\nexport async function listProfiles(): Promise<string[]> {\n const configPath = join(getConfigDir(), \"config.json\");\n\n try {\n const content = await readFile(configPath, \"utf-8\");\n const config = JSON.parse(content) as Record<string, unknown>;\n const profiles = config[\"profiles\"] as Record<string, unknown> | undefined;\n return profiles ? Object.keys(profiles) : [];\n } catch {\n return [];\n }\n}\n\nexport async function approvePlugin(pluginName: string): Promise<void> {\n const configPath = join(getConfigDir(), \"config.json\");\n\n let existing: Record<string, unknown> = {};\n try {\n const content = await readFile(configPath, \"utf-8\");\n existing = JSON.parse(content) as Record<string, unknown>;\n } catch {\n // start fresh\n }\n\n const approved = (existing[\"approvedPlugins\"] as string[] | undefined) ?? [];\n if (!approved.includes(pluginName)) {\n approved.push(pluginName);\n }\n existing[\"approvedPlugins\"] = approved;\n\n await mkdir(dirname(configPath), { recursive: true, mode: 0o700 });\n await writeSecureFile(configPath, JSON.stringify(existing, null, 2) + \"\\n\");\n}\n\nexport async function revokePluginApproval(pluginName: string): Promise<boolean> {\n const configPath = join(getConfigDir(), \"config.json\");\n\n let existing: Record<string, unknown>;\n try {\n const content = await readFile(configPath, \"utf-8\");\n existing = JSON.parse(content) as Record<string, unknown>;\n } catch {\n return false;\n }\n\n const approved = (existing[\"approvedPlugins\"] as string[] | undefined) ?? [];\n const index = approved.indexOf(pluginName);\n if (index === -1) return false;\n\n approved.splice(index, 1);\n existing[\"approvedPlugins\"] = approved;\n await writeSecureFile(configPath, JSON.stringify(existing, null, 2) + \"\\n\");\n return true;\n}\n\nexport async function initConfig(config: GpcConfig): Promise<string> {\n const configDir = getConfigDir();\n const configPath = join(configDir, \"config.json\");\n\n await mkdir(configDir, { recursive: true, mode: 0o700 });\n await writeSecureFile(configPath, JSON.stringify(config, null, 2) + \"\\n\");\n\n return configPath;\n}\n"],"mappings":"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","names":["join","join","readFile","dirname","join","join","readFile","dirname"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gpc-cli/config",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "Configuration loading and validation for GPC",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",