@anytio/pspm 0.13.0 → 0.14.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.
@@ -0,0 +1,470 @@
1
+ import { dirname, join } from "node:path";
2
+ import { mkdir, readFile, stat, unlink, writeFile } from "node:fs/promises";
3
+ import { homedir } from "node:os";
4
+ import * as ini from "ini";
5
+ //#region ../../packages/shared/errors/src/extract.ts
6
+ const DEFAULT_STATUS_DESCRIPTIONS = {
7
+ 400: "Bad Request",
8
+ 401: "Unauthorized",
9
+ 403: "Forbidden",
10
+ 404: "Not Found",
11
+ 409: "Conflict",
12
+ 422: "Validation Error",
13
+ 429: "Too Many Requests",
14
+ 500: "Internal Server Error",
15
+ 502: "Bad Gateway",
16
+ 503: "Service Unavailable"
17
+ };
18
+ function getStatusDescription(status, overrides) {
19
+ return overrides?.[status] ?? DEFAULT_STATUS_DESCRIPTIONS[status] ?? `HTTP ${status}`;
20
+ }
21
+ function extractApiErrorMessage$1(response, fallbackMessage, options = {}) {
22
+ const errorData = response.data;
23
+ const overrides = options.statusDescriptions;
24
+ if (options.debug) {
25
+ const log = options.debugLogger ?? console.log;
26
+ log(`[debug] API response status: ${response.status}`);
27
+ log("[debug] API response data:", errorData);
28
+ }
29
+ if (typeof errorData === "string") {
30
+ if (response.status === 404) return `${fallbackMessage}: ${getStatusDescription(404, overrides)}`;
31
+ return `${fallbackMessage}: ${errorData} (HTTP ${response.status})`;
32
+ }
33
+ if (!errorData || typeof errorData !== "object") return `${fallbackMessage}: ${getStatusDescription(response.status, overrides)}`;
34
+ let errorMessage = errorData.message || fallbackMessage;
35
+ if (errorData.code === "VALIDATION_ERROR" && errorData.details) {
36
+ const issues = errorData.details.issues;
37
+ if (issues && Array.isArray(issues)) errorMessage = `Validation failed:\n${issues.map((issue) => {
38
+ return ` - ${issue.path?.join(".") || "input"}: ${issue.message || "invalid value"}`;
39
+ }).join("\n")}`;
40
+ }
41
+ if (errorData.code && !errorMessage.includes(errorData.code)) errorMessage = `[${errorData.code}] ${errorMessage}`;
42
+ if (response.status >= 400) errorMessage += ` (HTTP ${response.status})`;
43
+ if (errorData.requestId) errorMessage += `\n(Request ID: ${errorData.requestId})`;
44
+ return errorMessage;
45
+ }
46
+ //#endregion
47
+ //#region src/errors.ts
48
+ /**
49
+ * Base error class for PSPM configuration errors
50
+ */
51
+ var ConfigError = class extends Error {
52
+ constructor(message) {
53
+ super(message);
54
+ this.name = "ConfigError";
55
+ }
56
+ };
57
+ /**
58
+ * Error thrown when the user is not logged in
59
+ */
60
+ var NotLoggedInError = class extends ConfigError {
61
+ constructor() {
62
+ super("Not logged in. Run 'pspm login --api-key <key>' first, or set PSPM_API_KEY env var.");
63
+ this.name = "NotLoggedInError";
64
+ }
65
+ };
66
+ const CLI_STATUS_DESCRIPTIONS = {
67
+ 400: "Bad Request - The request was malformed",
68
+ 401: "Unauthorized - Please run 'pspm login' first",
69
+ 403: "Forbidden - You don't have permission for this action",
70
+ 404: "Not Found - The endpoint or resource doesn't exist",
71
+ 409: "Conflict - The resource already exists or there's a version conflict",
72
+ 422: "Validation Error - The request data is invalid",
73
+ 429: "Too Many Requests - Please slow down and try again",
74
+ 500: "Internal Server Error - Something went wrong on the server",
75
+ 502: "Bad Gateway - The server is temporarily unavailable",
76
+ 503: "Service Unavailable - The server is temporarily unavailable"
77
+ };
78
+ /**
79
+ * Extract a human-readable error message from an API response.
80
+ * Thin wrapper over `@anytio/errors/extract` with CLI-tuned status hints.
81
+ */
82
+ function extractApiErrorMessage(response, fallbackMessage) {
83
+ return extractApiErrorMessage$1(response, fallbackMessage, {
84
+ statusDescriptions: CLI_STATUS_DESCRIPTIONS,
85
+ debug: Boolean(process.env.PSPM_DEBUG),
86
+ debugLogger: (msg, data) => data === void 0 ? console.log(msg) : console.log(msg, JSON.stringify(data, null, 2))
87
+ });
88
+ }
89
+ //#endregion
90
+ //#region src/config-auth.ts
91
+ /**
92
+ * Get the auth token for a given registry URL.
93
+ * Falls back to the default API key if no registry-specific token is configured.
94
+ *
95
+ * @param config - The resolved configuration
96
+ * @param registryUrl - The registry URL
97
+ * @returns The auth token to use, or undefined if none available
98
+ */
99
+ function getTokenForRegistry(config, registryUrl) {
100
+ try {
101
+ const host = new URL(registryUrl).host;
102
+ if (config.registryTokens[host]) return config.registryTokens[host];
103
+ return config.apiKey;
104
+ } catch {
105
+ return config.apiKey;
106
+ }
107
+ }
108
+ /**
109
+ * Set credentials (authToken and optionally username/registry)
110
+ */
111
+ async function setCredentials(authToken, username, registry) {
112
+ const config = await readUserConfig();
113
+ config.authToken = authToken;
114
+ if (username) config.username = username;
115
+ if (registry && registry !== "https://registry.pspm.dev") config.registry = registry;
116
+ await writeUserConfig(config);
117
+ }
118
+ /**
119
+ * Clear credentials (authToken and username)
120
+ */
121
+ async function clearCredentials() {
122
+ const config = await readUserConfig();
123
+ config.authToken = void 0;
124
+ config.username = void 0;
125
+ await writeUserConfig(config);
126
+ }
127
+ /**
128
+ * Check if user is logged in
129
+ */
130
+ async function isLoggedIn() {
131
+ try {
132
+ return !!(await resolveConfig()).apiKey;
133
+ } catch {
134
+ return false;
135
+ }
136
+ }
137
+ /**
138
+ * Get the API key (throws if not logged in)
139
+ */
140
+ async function requireApiKey() {
141
+ const resolved = await resolveConfig();
142
+ if (!resolved.apiKey) {
143
+ if (process.env.PSPM_DEBUG) console.log("[config] requireApiKey: No API key found");
144
+ throw new NotLoggedInError();
145
+ }
146
+ if (process.env.PSPM_DEBUG) console.log(`[config] requireApiKey: Got API key (${resolved.apiKey.substring(0, 10)}...)`);
147
+ return resolved.apiKey;
148
+ }
149
+ /**
150
+ * Get the registry URL
151
+ */
152
+ async function getRegistryUrl() {
153
+ return (await resolveConfig()).registryUrl;
154
+ }
155
+ /**
156
+ * Get the encryption key for a given scope.
157
+ *
158
+ * Checks environment variable first (PSPM_ENCRYPTION_KEY_{SCOPE}),
159
+ * then falls back to ~/.pspmrc encryption-key:{scope}.
160
+ *
161
+ * @param scope - The scope (e.g., "@user/alice" or "@org/acme")
162
+ * @returns The encryption key, or undefined if not configured
163
+ */
164
+ async function getEncryptionKey(scope) {
165
+ const envSuffix = scope.replace(/^@/, "").replace(/\//g, "_").toUpperCase();
166
+ const envKey = process.env[`PSPM_ENCRYPTION_KEY_${envSuffix}`];
167
+ if (envKey) return envKey;
168
+ return (await readUserConfig()).encryptionKeys?.[scope];
169
+ }
170
+ /**
171
+ * Set the encryption key for a given scope in ~/.pspmrc.
172
+ *
173
+ * @param scope - The scope (e.g., "@user/alice" or "@org/acme")
174
+ * @param key - The encryption passphrase
175
+ */
176
+ async function setEncryptionKey(scope, key) {
177
+ const config = await readUserConfig();
178
+ if (!config.encryptionKeys) config.encryptionKeys = {};
179
+ config.encryptionKeys[scope] = key;
180
+ await writeUserConfig(config);
181
+ }
182
+ /**
183
+ * Remove the encryption key for a given scope from ~/.pspmrc.
184
+ *
185
+ * @param scope - The scope (e.g., "@user/alice" or "@org/acme")
186
+ */
187
+ async function removeEncryptionKey(scope) {
188
+ const config = await readUserConfig();
189
+ if (config.encryptionKeys) {
190
+ delete config.encryptionKeys[scope];
191
+ if (Object.keys(config.encryptionKeys).length === 0) config.encryptionKeys = void 0;
192
+ }
193
+ await writeUserConfig(config);
194
+ }
195
+ /**
196
+ * Derive the encryption scope from a package specifier.
197
+ *
198
+ * @user/alice/my-skill -> @user/alice
199
+ * @org/acme/tool -> @org/acme
200
+ */
201
+ function getEncryptionScope(namespace, owner) {
202
+ return `@${namespace}/${owner}`;
203
+ }
204
+ //#endregion
205
+ //#region src/config.ts
206
+ const DEFAULT_REGISTRY_URL = "https://registry.pspm.dev";
207
+ /**
208
+ * Get the user config file path (~/.pspmrc)
209
+ */
210
+ function getConfigPath() {
211
+ return join(homedir(), ".pspmrc");
212
+ }
213
+ /**
214
+ * Get the legacy config file path (~/.pspm/config.json) for migration
215
+ */
216
+ function getLegacyConfigPath() {
217
+ return join(homedir(), ".pspm", "config.json");
218
+ }
219
+ let _globalMode = false;
220
+ /**
221
+ * Set global mode. When enabled, all path functions return
222
+ * home-directory paths (~/.pspm/) instead of project-relative paths.
223
+ */
224
+ function setGlobalMode(global) {
225
+ _globalMode = global;
226
+ }
227
+ /**
228
+ * Check if global mode is enabled.
229
+ */
230
+ function isGlobalMode() {
231
+ return _globalMode;
232
+ }
233
+ /**
234
+ * Get the .pspm directory path
235
+ * Global: ~/.pspm/
236
+ * Project: ./.pspm/
237
+ */
238
+ function getPspmDir() {
239
+ if (_globalMode) return join(homedir(), ".pspm");
240
+ return join(process.cwd(), ".pspm");
241
+ }
242
+ /**
243
+ * Get the skills directory path
244
+ * Global: ~/.pspm/skills/
245
+ * Project: ./.pspm/skills/
246
+ */
247
+ function getSkillsDir() {
248
+ return join(getPspmDir(), "skills");
249
+ }
250
+ /**
251
+ * Get the cache directory path
252
+ * Global: ~/.pspm/cache/
253
+ * Project: ./.pspm/cache/
254
+ */
255
+ function getCacheDir() {
256
+ return join(getPspmDir(), "cache");
257
+ }
258
+ /**
259
+ * Get the lockfile path
260
+ * Global: ~/.pspm/pspm-lock.json
261
+ * Project: ./pspm-lock.json
262
+ */
263
+ function getLockfilePath() {
264
+ if (_globalMode) return join(homedir(), ".pspm", "pspm-lock.json");
265
+ return join(process.cwd(), "pspm-lock.json");
266
+ }
267
+ /**
268
+ * Get the legacy lockfile path (for migration)
269
+ */
270
+ function getLegacyLockfilePath() {
271
+ return join(process.cwd(), "skill-lock.json");
272
+ }
273
+ /**
274
+ * Get the legacy skills directory path (for migration)
275
+ */
276
+ function getLegacySkillsDir() {
277
+ return join(process.cwd(), ".skills");
278
+ }
279
+ /**
280
+ * Read the user config file (~/.pspmrc, INI format)
281
+ *
282
+ * Supports npm-style configuration:
283
+ * ```ini
284
+ * ; Default registry and auth
285
+ * registry = https://pspm.dev
286
+ * authToken = sk_default
287
+ *
288
+ * ; Scope mappings
289
+ * @myorg:registry = https://corp.pspm.io
290
+ *
291
+ * ; Per-registry tokens
292
+ * //pspm.dev:authToken = sk_public
293
+ * //corp.pspm.io:authToken = sk_corp
294
+ * ```
295
+ */
296
+ async function readUserConfig() {
297
+ const configPath = getConfigPath();
298
+ if (process.env.PSPM_DEBUG) console.log(`[config] Reading config from: ${configPath}`);
299
+ try {
300
+ const content = await readFile(configPath, "utf-8");
301
+ const parsed = ini.parse(content);
302
+ if (process.env.PSPM_DEBUG) console.log("[config] Parsed config:", JSON.stringify(parsed, null, 2));
303
+ const scopedRegistries = {};
304
+ for (const key of Object.keys(parsed)) {
305
+ const scopeMatch = key.match(/^(@[^:]+):registry$/);
306
+ if (scopeMatch) {
307
+ const scope = scopeMatch[1];
308
+ scopedRegistries[scope] = parsed[key];
309
+ }
310
+ }
311
+ const registryTokens = {};
312
+ for (const key of Object.keys(parsed)) {
313
+ const tokenMatch = key.match(/^\/\/([^:]+):authToken$/);
314
+ if (tokenMatch) {
315
+ const host = tokenMatch[1];
316
+ registryTokens[host] = parsed[key];
317
+ }
318
+ if (key.startsWith("//") && typeof parsed[key] === "object") {
319
+ const host = key.slice(2);
320
+ const section = parsed[key];
321
+ if (section.authToken) registryTokens[host] = section.authToken;
322
+ }
323
+ }
324
+ const encryptionKeys = {};
325
+ for (const key of Object.keys(parsed)) {
326
+ const encKeyMatch = key.match(/^encryption-key:(.+)$/);
327
+ if (encKeyMatch) {
328
+ const scope = encKeyMatch[1];
329
+ encryptionKeys[scope] = parsed[key];
330
+ }
331
+ }
332
+ return {
333
+ registry: parsed.registry,
334
+ authToken: parsed.authToken,
335
+ username: parsed.username,
336
+ scopedRegistries: Object.keys(scopedRegistries).length > 0 ? scopedRegistries : void 0,
337
+ registryTokens: Object.keys(registryTokens).length > 0 ? registryTokens : void 0,
338
+ encryptionKeys: Object.keys(encryptionKeys).length > 0 ? encryptionKeys : void 0
339
+ };
340
+ } catch (error) {
341
+ if (process.env.PSPM_DEBUG) console.log(`[config] Error reading config: ${error instanceof Error ? error.message : String(error)}`);
342
+ return {};
343
+ }
344
+ }
345
+ /**
346
+ * Write the user config file (~/.pspmrc, INI format)
347
+ */
348
+ async function writeUserConfig(config) {
349
+ const configPath = getConfigPath();
350
+ const lines = ["; PSPM Configuration", ""];
351
+ if (config.registry) lines.push(`registry = ${config.registry}`);
352
+ if (config.authToken) lines.push(`authToken = ${config.authToken}`);
353
+ if (config.username) lines.push(`username = ${config.username}`);
354
+ if (config.encryptionKeys && Object.keys(config.encryptionKeys).length > 0) {
355
+ lines.push("; Encryption keys (scope -> passphrase)");
356
+ for (const [scope, key] of Object.entries(config.encryptionKeys)) lines.push(`encryption-key:${scope} = ${key}`);
357
+ }
358
+ lines.push("");
359
+ await mkdir(dirname(configPath), { recursive: true });
360
+ await writeFile(configPath, lines.join("\n"));
361
+ if (process.env.PSPM_DEBUG) console.log(`[config] Wrote config to: ${configPath}`);
362
+ }
363
+ /**
364
+ * Find and read project config (.pspmrc) by searching up directory tree
365
+ */
366
+ async function findProjectConfig() {
367
+ let currentDir = process.cwd();
368
+ const root = dirname(currentDir);
369
+ while (currentDir !== root) {
370
+ const configPath = join(currentDir, ".pspmrc");
371
+ try {
372
+ if ((await stat(configPath)).isFile()) {
373
+ const content = await readFile(configPath, "utf-8");
374
+ try {
375
+ const parsed = ini.parse(content);
376
+ if (process.env.PSPM_DEBUG) console.log(`[config] Found project config at ${configPath}:`, JSON.stringify(parsed, null, 2));
377
+ return { registry: parsed.registry };
378
+ } catch {
379
+ try {
380
+ return { registry: JSON.parse(content).registryUrl };
381
+ } catch {}
382
+ }
383
+ }
384
+ } catch {}
385
+ currentDir = dirname(currentDir);
386
+ }
387
+ return null;
388
+ }
389
+ /**
390
+ * Migrate from legacy config format (~/.pspm/config.json) if it exists
391
+ */
392
+ async function migrateFromLegacyConfig() {
393
+ const legacyPath = getLegacyConfigPath();
394
+ try {
395
+ const content = await readFile(legacyPath, "utf-8");
396
+ const parsed = JSON.parse(content);
397
+ let config = {};
398
+ if (parsed.version === 2 && parsed.profiles) {
399
+ const v2Config = parsed;
400
+ const defaultProfileName = v2Config.defaultProfile || "default";
401
+ const profile = v2Config.profiles[defaultProfileName];
402
+ if (profile) config = {
403
+ registry: profile.registryUrl !== "https://registry.pspm.dev" ? profile.registryUrl : void 0,
404
+ authToken: profile.apiKey,
405
+ username: profile.username
406
+ };
407
+ console.log(`Migrating from legacy config (profile: ${defaultProfileName})...`);
408
+ } else {
409
+ const v1Config = parsed;
410
+ config = {
411
+ registry: v1Config.registryUrl !== "https://registry.pspm.dev" ? v1Config.registryUrl : void 0,
412
+ authToken: v1Config.apiKey,
413
+ username: v1Config.username
414
+ };
415
+ console.log("Migrating from legacy config...");
416
+ }
417
+ await writeUserConfig(config);
418
+ console.log(`Created new config at: ${getConfigPath()}`);
419
+ await unlink(legacyPath);
420
+ console.log(`Removed legacy config: ${legacyPath}`);
421
+ return config;
422
+ } catch {
423
+ return null;
424
+ }
425
+ }
426
+ /**
427
+ * Resolve the full configuration using cascade priority:
428
+ * 1. Environment variables (PSPM_REGISTRY_URL, PSPM_API_KEY)
429
+ * 2. Project config (.pspmrc in project directory)
430
+ * 3. User config (~/.pspmrc)
431
+ * 4. Defaults
432
+ */
433
+ async function resolveConfig() {
434
+ const newConfigPath = getConfigPath();
435
+ try {
436
+ await stat(newConfigPath);
437
+ } catch {
438
+ await migrateFromLegacyConfig();
439
+ }
440
+ const userConfig = await readUserConfig();
441
+ const projectConfig = await findProjectConfig();
442
+ let registryUrl = DEFAULT_REGISTRY_URL;
443
+ let apiKey = userConfig.authToken;
444
+ const username = userConfig.username;
445
+ const scopedRegistries = userConfig.scopedRegistries ?? {};
446
+ const registryTokens = userConfig.registryTokens ?? {};
447
+ if (userConfig.registry) registryUrl = userConfig.registry;
448
+ if (projectConfig?.registry) registryUrl = projectConfig.registry;
449
+ if (process.env.PSPM_REGISTRY_URL) registryUrl = process.env.PSPM_REGISTRY_URL;
450
+ if (process.env.PSPM_API_KEY) apiKey = process.env.PSPM_API_KEY;
451
+ if (process.env.PSPM_DEBUG) {
452
+ console.log("[config] Resolved config:");
453
+ console.log(`[config] registryUrl: ${registryUrl}`);
454
+ console.log(`[config] apiKey: ${apiKey ? "***" : "(not set)"}`);
455
+ console.log(`[config] username: ${username || "(not set)"}`);
456
+ console.log(`[config] scopedRegistries: ${JSON.stringify(scopedRegistries)}`);
457
+ console.log(`[config] registryTokens: ${Object.keys(registryTokens).length} configured`);
458
+ }
459
+ return {
460
+ registryUrl,
461
+ apiKey,
462
+ username,
463
+ scopedRegistries,
464
+ registryTokens
465
+ };
466
+ }
467
+ //#endregion
468
+ export { setCredentials as C, requireApiKey as S, extractApiErrorMessage as T, getEncryptionScope as _, getLegacyLockfilePath as a, isLoggedIn as b, getPspmDir as c, readUserConfig as d, resolveConfig as f, getEncryptionKey as g, clearCredentials as h, getConfigPath as i, getSkillsDir as l, writeUserConfig as m, findProjectConfig as n, getLegacySkillsDir as o, setGlobalMode as p, getCacheDir as r, getLockfilePath as s, DEFAULT_REGISTRY_URL as t, isGlobalMode as u, getRegistryUrl as v, setEncryptionKey as w, removeEncryptionKey as x, getTokenForRegistry as y };
469
+
470
+ //# sourceMappingURL=config-BQy_Rjip.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-BQy_Rjip.js","names":["extractApiErrorMessage","sharedExtract"],"sources":["../../../packages/shared/errors/src/extract.ts","../src/errors.ts","../src/config-auth.ts","../src/config.ts"],"sourcesContent":["/**\n * Shared API error extraction used by the web app and CLI.\n *\n * Handles three cases consistently:\n * 1. Zod validation errors ({ code: \"VALIDATION_ERROR\", details.issues })\n * 2. Generic API errors ({ code, message, requestId })\n * 3. Opaque/empty bodies (uses an HTTP status description)\n */\n\nexport interface ApiErrorResponse {\n code?: string;\n message?: string;\n details?:\n | {\n issues?: Array<{ path?: Array<string | number>; message?: string }>;\n }\n | Record<string, unknown>;\n requestId?: string;\n timestamp?: string;\n}\n\nexport interface ExtractOptions {\n statusDescriptions?: Record<number, string>;\n debug?: boolean;\n debugLogger?: (message: string, data?: unknown) => void;\n}\n\nconst DEFAULT_STATUS_DESCRIPTIONS: Record<number, string> = {\n 400: \"Bad Request\",\n 401: \"Unauthorized\",\n 403: \"Forbidden\",\n 404: \"Not Found\",\n 409: \"Conflict\",\n 422: \"Validation Error\",\n 429: \"Too Many Requests\",\n 500: \"Internal Server Error\",\n 502: \"Bad Gateway\",\n 503: \"Service Unavailable\",\n};\n\nfunction getStatusDescription(\n status: number,\n overrides?: Record<number, string>,\n): string {\n return (\n overrides?.[status] ??\n DEFAULT_STATUS_DESCRIPTIONS[status] ??\n `HTTP ${status}`\n );\n}\n\nexport function extractApiErrorMessage(\n response: { status: number; data: unknown },\n fallbackMessage: string,\n options: ExtractOptions = {},\n): string {\n const errorData = response.data as\n | ApiErrorResponse\n | string\n | null\n | undefined;\n const overrides = options.statusDescriptions;\n\n if (options.debug) {\n const log = options.debugLogger ?? console.log;\n log(`[debug] API response status: ${response.status}`);\n log(\"[debug] API response data:\", errorData);\n }\n\n if (typeof errorData === \"string\") {\n if (response.status === 404) {\n return `${fallbackMessage}: ${getStatusDescription(404, overrides)}`;\n }\n return `${fallbackMessage}: ${errorData} (HTTP ${response.status})`;\n }\n\n if (!errorData || typeof errorData !== \"object\") {\n return `${fallbackMessage}: ${getStatusDescription(response.status, overrides)}`;\n }\n\n let errorMessage = errorData.message || fallbackMessage;\n\n if (errorData.code === \"VALIDATION_ERROR\" && errorData.details) {\n const issues = (\n errorData.details as {\n issues?: Array<{ path?: Array<string | number>; message?: string }>;\n }\n ).issues;\n if (issues && Array.isArray(issues)) {\n const issueMessages = issues\n .map((issue) => {\n const path = issue.path?.join(\".\") || \"input\";\n const msg = issue.message || \"invalid value\";\n return ` - ${path}: ${msg}`;\n })\n .join(\"\\n\");\n errorMessage = `Validation failed:\\n${issueMessages}`;\n }\n }\n\n if (errorData.code && !errorMessage.includes(errorData.code)) {\n errorMessage = `[${errorData.code}] ${errorMessage}`;\n }\n\n if (response.status >= 400) {\n errorMessage += ` (HTTP ${response.status})`;\n }\n\n if (errorData.requestId) {\n errorMessage += `\\n(Request ID: ${errorData.requestId})`;\n }\n\n return errorMessage;\n}\n","import { extractApiErrorMessage as sharedExtract } from \"@anytio/errors/extract\";\n\n/**\n * Base error class for PSPM configuration errors\n */\nexport class ConfigError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"ConfigError\";\n }\n}\n\n/**\n * Error thrown when the user is not logged in\n */\nexport class NotLoggedInError extends ConfigError {\n constructor() {\n super(\n \"Not logged in. Run 'pspm login --api-key <key>' first, or set PSPM_API_KEY env var.\",\n );\n this.name = \"NotLoggedInError\";\n }\n}\n\nconst CLI_STATUS_DESCRIPTIONS: Record<number, string> = {\n 400: \"Bad Request - The request was malformed\",\n 401: \"Unauthorized - Please run 'pspm login' first\",\n 403: \"Forbidden - You don't have permission for this action\",\n 404: \"Not Found - The endpoint or resource doesn't exist\",\n 409: \"Conflict - The resource already exists or there's a version conflict\",\n 422: \"Validation Error - The request data is invalid\",\n 429: \"Too Many Requests - Please slow down and try again\",\n 500: \"Internal Server Error - Something went wrong on the server\",\n 502: \"Bad Gateway - The server is temporarily unavailable\",\n 503: \"Service Unavailable - The server is temporarily unavailable\",\n};\n\n/**\n * Extract a human-readable error message from an API response.\n * Thin wrapper over `@anytio/errors/extract` with CLI-tuned status hints.\n */\nexport function extractApiErrorMessage(\n response: { status: number; data: unknown },\n fallbackMessage: string,\n): string {\n return sharedExtract(response, fallbackMessage, {\n statusDescriptions: CLI_STATUS_DESCRIPTIONS,\n debug: Boolean(process.env.PSPM_DEBUG),\n debugLogger: (msg: string, data?: unknown) =>\n data === undefined\n ? console.log(msg)\n : console.log(msg, JSON.stringify(data, null, 2)),\n });\n}\n","import type { ResolvedConfig } from \"./config\";\nimport {\n DEFAULT_REGISTRY_URL,\n readUserConfig,\n resolveConfig,\n writeUserConfig,\n} from \"./config\";\nimport { NotLoggedInError } from \"./errors\";\n\n/**\n * Get the auth token for a given registry URL.\n * Falls back to the default API key if no registry-specific token is configured.\n *\n * @param config - The resolved configuration\n * @param registryUrl - The registry URL\n * @returns The auth token to use, or undefined if none available\n */\nexport function getTokenForRegistry(\n config: ResolvedConfig,\n registryUrl: string,\n): string | undefined {\n try {\n const url = new URL(registryUrl);\n const host = url.host;\n\n if (config.registryTokens[host]) {\n return config.registryTokens[host];\n }\n\n return config.apiKey;\n } catch {\n return config.apiKey;\n }\n}\n\n/**\n * Set credentials (authToken and optionally username/registry)\n */\nexport async function setCredentials(\n authToken: string,\n username?: string,\n registry?: string,\n): Promise<void> {\n const config = await readUserConfig();\n\n config.authToken = authToken;\n if (username) {\n config.username = username;\n }\n if (registry && registry !== DEFAULT_REGISTRY_URL) {\n config.registry = registry;\n }\n\n await writeUserConfig(config);\n}\n\n/**\n * Clear credentials (authToken and username)\n */\nexport async function clearCredentials(): Promise<void> {\n const config = await readUserConfig();\n\n config.authToken = undefined;\n config.username = undefined;\n\n await writeUserConfig(config);\n}\n\n/**\n * Check if user is logged in\n */\nexport async function isLoggedIn(): Promise<boolean> {\n try {\n const resolved = await resolveConfig();\n return !!resolved.apiKey;\n } catch {\n return false;\n }\n}\n\n/**\n * Get the API key (throws if not logged in)\n */\nexport async function requireApiKey(): Promise<string> {\n const resolved = await resolveConfig();\n\n if (!resolved.apiKey) {\n if (process.env.PSPM_DEBUG) {\n console.log(\"[config] requireApiKey: No API key found\");\n }\n throw new NotLoggedInError();\n }\n\n if (process.env.PSPM_DEBUG) {\n console.log(\n `[config] requireApiKey: Got API key (${resolved.apiKey.substring(0, 10)}...)`,\n );\n }\n\n return resolved.apiKey;\n}\n\n/**\n * Get the registry URL\n */\nexport async function getRegistryUrl(): Promise<string> {\n const resolved = await resolveConfig();\n return resolved.registryUrl;\n}\n\n/**\n * Get the encryption key for a given scope.\n *\n * Checks environment variable first (PSPM_ENCRYPTION_KEY_{SCOPE}),\n * then falls back to ~/.pspmrc encryption-key:{scope}.\n *\n * @param scope - The scope (e.g., \"@user/alice\" or \"@org/acme\")\n * @returns The encryption key, or undefined if not configured\n */\nexport async function getEncryptionKey(\n scope: string,\n): Promise<string | undefined> {\n const envSuffix = scope.replace(/^@/, \"\").replace(/\\//g, \"_\").toUpperCase();\n const envKey = process.env[`PSPM_ENCRYPTION_KEY_${envSuffix}`];\n if (envKey) {\n return envKey;\n }\n\n const config = await readUserConfig();\n return config.encryptionKeys?.[scope];\n}\n\n/**\n * Set the encryption key for a given scope in ~/.pspmrc.\n *\n * @param scope - The scope (e.g., \"@user/alice\" or \"@org/acme\")\n * @param key - The encryption passphrase\n */\nexport async function setEncryptionKey(\n scope: string,\n key: string,\n): Promise<void> {\n const config = await readUserConfig();\n if (!config.encryptionKeys) {\n config.encryptionKeys = {};\n }\n config.encryptionKeys[scope] = key;\n await writeUserConfig(config);\n}\n\n/**\n * Remove the encryption key for a given scope from ~/.pspmrc.\n *\n * @param scope - The scope (e.g., \"@user/alice\" or \"@org/acme\")\n */\nexport async function removeEncryptionKey(scope: string): Promise<void> {\n const config = await readUserConfig();\n if (config.encryptionKeys) {\n delete config.encryptionKeys[scope];\n if (Object.keys(config.encryptionKeys).length === 0) {\n config.encryptionKeys = undefined;\n }\n }\n await writeUserConfig(config);\n}\n\n/**\n * Derive the encryption scope from a package specifier.\n *\n * @user/alice/my-skill -> @user/alice\n * @org/acme/tool -> @org/acme\n */\nexport function getEncryptionScope(namespace: string, owner: string): string {\n return `@${namespace}/${owner}`;\n}\n","import { mkdir, readFile, stat, unlink, writeFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\nimport * as ini from \"ini\";\n\nexport {\n clearCredentials,\n getEncryptionKey,\n getEncryptionScope,\n getRegistryUrl,\n getTokenForRegistry,\n isLoggedIn,\n removeEncryptionKey,\n requireApiKey,\n setCredentials,\n setEncryptionKey,\n} from \"./config-auth\";\n\n// =============================================================================\n// Types\n// =============================================================================\n\n/**\n * User config stored in ~/.pspmrc (INI format)\n *\n * Supports npm-style configuration:\n * - registry = https://pspm.dev (default registry)\n * - authToken = sk_default (default auth token)\n * - @scope:registry = https://corp.pspm.io (scope to registry mapping)\n * - //host:authToken = sk_token (per-registry tokens)\n */\nexport interface UserConfig {\n registry?: string;\n authToken?: string;\n username?: string;\n /** Scope to registry URL mappings (e.g., @myorg -> https://corp.pspm.io) */\n scopedRegistries?: Record<string, string>;\n /** Host to auth token mappings (e.g., pspm.dev -> sk_xxx) */\n registryTokens?: Record<string, string>;\n /** Scope to encryption key mappings (e.g., @user/alice -> passphrase, @org/acme -> shared-key) */\n encryptionKeys?: Record<string, string>;\n}\n\n/**\n * Project config stored in .pspmrc (INI format)\n */\nexport interface ProjectConfig {\n registry?: string;\n}\n\n/**\n * Fully resolved configuration (after cascade)\n */\nexport interface ResolvedConfig {\n registryUrl: string;\n apiKey?: string;\n username?: string;\n /** Scope to registry URL mappings */\n scopedRegistries: Record<string, string>;\n /** Host to auth token mappings */\n registryTokens: Record<string, string>;\n}\n\n/**\n * Legacy V1 config schema (for migration)\n */\ninterface LegacyConfigV1 {\n registryUrl?: string;\n apiKey?: string;\n username?: string;\n}\n\n/**\n * Legacy V2 config schema (for migration)\n */\ninterface LegacyConfigV2 {\n version: 2;\n defaultProfile: string;\n profiles: Record<\n string,\n {\n registryUrl?: string;\n apiKey?: string;\n username?: string;\n }\n >;\n}\n\n// =============================================================================\n// Constants\n// =============================================================================\n\nexport const DEFAULT_REGISTRY_URL = \"https://registry.pspm.dev\";\n\n/**\n * Get the user config file path (~/.pspmrc)\n */\nexport function getConfigPath(): string {\n return join(homedir(), \".pspmrc\");\n}\n\n/**\n * Get the legacy config file path (~/.pspm/config.json) for migration\n */\nfunction getLegacyConfigPath(): string {\n return join(homedir(), \".pspm\", \"config.json\");\n}\n\n// =============================================================================\n// Global Mode\n// =============================================================================\n\nlet _globalMode = false;\n\n/**\n * Set global mode. When enabled, all path functions return\n * home-directory paths (~/.pspm/) instead of project-relative paths.\n */\nexport function setGlobalMode(global: boolean): void {\n _globalMode = global;\n}\n\n/**\n * Check if global mode is enabled.\n */\nexport function isGlobalMode(): boolean {\n return _globalMode;\n}\n\n/**\n * Get the .pspm directory path\n * Global: ~/.pspm/\n * Project: ./.pspm/\n */\nexport function getPspmDir(): string {\n if (_globalMode) return join(homedir(), \".pspm\");\n return join(process.cwd(), \".pspm\");\n}\n\n/**\n * Get the skills directory path\n * Global: ~/.pspm/skills/\n * Project: ./.pspm/skills/\n */\nexport function getSkillsDir(): string {\n return join(getPspmDir(), \"skills\");\n}\n\n/**\n * Get the cache directory path\n * Global: ~/.pspm/cache/\n * Project: ./.pspm/cache/\n */\nexport function getCacheDir(): string {\n return join(getPspmDir(), \"cache\");\n}\n\n/**\n * Get the lockfile path\n * Global: ~/.pspm/pspm-lock.json\n * Project: ./pspm-lock.json\n */\nexport function getLockfilePath(): string {\n if (_globalMode) return join(homedir(), \".pspm\", \"pspm-lock.json\");\n return join(process.cwd(), \"pspm-lock.json\");\n}\n\n/**\n * Get the legacy lockfile path (for migration)\n */\nexport function getLegacyLockfilePath(): string {\n return join(process.cwd(), \"skill-lock.json\");\n}\n\n/**\n * Get the legacy skills directory path (for migration)\n */\nexport function getLegacySkillsDir(): string {\n return join(process.cwd(), \".skills\");\n}\n\n// =============================================================================\n// INI Config Functions\n// =============================================================================\n\n/**\n * Read the user config file (~/.pspmrc, INI format)\n *\n * Supports npm-style configuration:\n * ```ini\n * ; Default registry and auth\n * registry = https://pspm.dev\n * authToken = sk_default\n *\n * ; Scope mappings\n * @myorg:registry = https://corp.pspm.io\n *\n * ; Per-registry tokens\n * //pspm.dev:authToken = sk_public\n * //corp.pspm.io:authToken = sk_corp\n * ```\n */\nexport async function readUserConfig(): Promise<UserConfig> {\n const configPath = getConfigPath();\n\n if (process.env.PSPM_DEBUG) {\n console.log(`[config] Reading config from: ${configPath}`);\n }\n\n try {\n const content = await readFile(configPath, \"utf-8\");\n const parsed = ini.parse(content);\n\n if (process.env.PSPM_DEBUG) {\n console.log(\"[config] Parsed config:\", JSON.stringify(parsed, null, 2));\n }\n\n // Extract scoped registries (@scope:registry = url)\n const scopedRegistries: Record<string, string> = {};\n for (const key of Object.keys(parsed)) {\n const scopeMatch = key.match(/^(@[^:]+):registry$/);\n if (scopeMatch) {\n const scope = scopeMatch[1];\n scopedRegistries[scope] = parsed[key] as string;\n }\n }\n\n // Extract per-registry tokens (//host:authToken = token)\n // INI parser may nest these under a key like \"//host\"\n const registryTokens: Record<string, string> = {};\n for (const key of Object.keys(parsed)) {\n // Check for //host:authToken format\n const tokenMatch = key.match(/^\\/\\/([^:]+):authToken$/);\n if (tokenMatch) {\n const host = tokenMatch[1];\n registryTokens[host] = parsed[key] as string;\n }\n // Also check for nested format (ini parser may parse //host as a section)\n if (key.startsWith(\"//\") && typeof parsed[key] === \"object\") {\n const host = key.slice(2);\n const section = parsed[key] as Record<string, string>;\n if (section.authToken) {\n registryTokens[host] = section.authToken;\n }\n }\n }\n\n // Extract encryption keys (encryption-key:@scope = passphrase)\n const encryptionKeys: Record<string, string> = {};\n for (const key of Object.keys(parsed)) {\n const encKeyMatch = key.match(/^encryption-key:(.+)$/);\n if (encKeyMatch) {\n const scope = encKeyMatch[1];\n encryptionKeys[scope] = parsed[key] as string;\n }\n }\n\n return {\n registry: parsed.registry as string | undefined,\n authToken: parsed.authToken as string | undefined,\n username: parsed.username as string | undefined,\n scopedRegistries:\n Object.keys(scopedRegistries).length > 0 ? scopedRegistries : undefined,\n registryTokens:\n Object.keys(registryTokens).length > 0 ? registryTokens : undefined,\n encryptionKeys:\n Object.keys(encryptionKeys).length > 0 ? encryptionKeys : undefined,\n };\n } catch (error) {\n if (process.env.PSPM_DEBUG) {\n console.log(\n `[config] Error reading config: ${\n error instanceof Error ? error.message : String(error)\n }`,\n );\n }\n return {};\n }\n}\n\n/**\n * Write the user config file (~/.pspmrc, INI format)\n */\nexport async function writeUserConfig(config: UserConfig): Promise<void> {\n const configPath = getConfigPath();\n\n // Build INI content with comments\n const lines: string[] = [\"; PSPM Configuration\", \"\"];\n\n if (config.registry) {\n lines.push(`registry = ${config.registry}`);\n }\n if (config.authToken) {\n lines.push(`authToken = ${config.authToken}`);\n }\n if (config.username) {\n lines.push(`username = ${config.username}`);\n }\n\n // Encryption keys\n if (config.encryptionKeys && Object.keys(config.encryptionKeys).length > 0) {\n lines.push(\"; Encryption keys (scope -> passphrase)\");\n for (const [scope, key] of Object.entries(config.encryptionKeys)) {\n lines.push(`encryption-key:${scope} = ${key}`);\n }\n }\n\n // Always end with a newline\n lines.push(\"\");\n\n await mkdir(dirname(configPath), { recursive: true });\n await writeFile(configPath, lines.join(\"\\n\"));\n\n if (process.env.PSPM_DEBUG) {\n console.log(`[config] Wrote config to: ${configPath}`);\n }\n}\n\n/**\n * Find and read project config (.pspmrc) by searching up directory tree\n */\nexport async function findProjectConfig(): Promise<ProjectConfig | null> {\n let currentDir = process.cwd();\n const root = dirname(currentDir);\n\n while (currentDir !== root) {\n const configPath = join(currentDir, \".pspmrc\");\n try {\n const stats = await stat(configPath);\n if (stats.isFile()) {\n const content = await readFile(configPath, \"utf-8\");\n // Try parsing as INI first\n try {\n const parsed = ini.parse(content);\n if (process.env.PSPM_DEBUG) {\n console.log(\n `[config] Found project config at ${configPath}:`,\n JSON.stringify(parsed, null, 2),\n );\n }\n return {\n registry: parsed.registry as string | undefined,\n };\n } catch {\n // Fall back to JSON for backward compatibility during migration\n try {\n const jsonConfig = JSON.parse(content);\n return {\n registry: jsonConfig.registryUrl,\n };\n } catch {\n // Unparseable, skip\n }\n }\n }\n } catch {\n // File doesn't exist, continue searching\n }\n currentDir = dirname(currentDir);\n }\n\n return null;\n}\n\n/**\n * Migrate from legacy config format (~/.pspm/config.json) if it exists\n */\nasync function migrateFromLegacyConfig(): Promise<UserConfig | null> {\n const legacyPath = getLegacyConfigPath();\n\n try {\n const content = await readFile(legacyPath, \"utf-8\");\n const parsed = JSON.parse(content);\n\n let config: UserConfig = {};\n\n // Check if V2 format (with profiles)\n if (parsed.version === 2 && parsed.profiles) {\n const v2Config = parsed as LegacyConfigV2;\n const defaultProfileName = v2Config.defaultProfile || \"default\";\n const profile = v2Config.profiles[defaultProfileName];\n\n if (profile) {\n config = {\n registry:\n profile.registryUrl !== DEFAULT_REGISTRY_URL\n ? profile.registryUrl\n : undefined,\n authToken: profile.apiKey,\n username: profile.username,\n };\n }\n\n console.log(\n `Migrating from legacy config (profile: ${defaultProfileName})...`,\n );\n } else {\n // V1 format (flat)\n const v1Config = parsed as LegacyConfigV1;\n config = {\n registry:\n v1Config.registryUrl !== DEFAULT_REGISTRY_URL\n ? v1Config.registryUrl\n : undefined,\n authToken: v1Config.apiKey,\n username: v1Config.username,\n };\n\n console.log(\"Migrating from legacy config...\");\n }\n\n // Write new format\n await writeUserConfig(config);\n console.log(`Created new config at: ${getConfigPath()}`);\n\n // Remove old config directory\n await unlink(legacyPath);\n console.log(`Removed legacy config: ${legacyPath}`);\n\n return config;\n } catch {\n // Legacy config doesn't exist or couldn't be read\n return null;\n }\n}\n\n/**\n * Resolve the full configuration using cascade priority:\n * 1. Environment variables (PSPM_REGISTRY_URL, PSPM_API_KEY)\n * 2. Project config (.pspmrc in project directory)\n * 3. User config (~/.pspmrc)\n * 4. Defaults\n */\nexport async function resolveConfig(): Promise<ResolvedConfig> {\n // Check for legacy config and migrate if needed\n const newConfigPath = getConfigPath();\n try {\n await stat(newConfigPath);\n } catch {\n // New config doesn't exist, try migrating from legacy\n await migrateFromLegacyConfig();\n }\n\n const userConfig = await readUserConfig();\n const projectConfig = await findProjectConfig();\n\n // Build resolved config with cascade priority\n let registryUrl = DEFAULT_REGISTRY_URL;\n let apiKey = userConfig.authToken;\n const username = userConfig.username;\n const scopedRegistries = userConfig.scopedRegistries ?? {};\n const registryTokens = userConfig.registryTokens ?? {};\n\n // User config\n if (userConfig.registry) {\n registryUrl = userConfig.registry;\n }\n\n // Project config can override registryUrl (but not apiKey for security)\n if (projectConfig?.registry) {\n registryUrl = projectConfig.registry;\n }\n\n // Environment variables always win\n if (process.env.PSPM_REGISTRY_URL) {\n registryUrl = process.env.PSPM_REGISTRY_URL;\n }\n if (process.env.PSPM_API_KEY) {\n apiKey = process.env.PSPM_API_KEY;\n }\n\n if (process.env.PSPM_DEBUG) {\n console.log(\"[config] Resolved config:\");\n console.log(`[config] registryUrl: ${registryUrl}`);\n console.log(`[config] apiKey: ${apiKey ? \"***\" : \"(not set)\"}`);\n console.log(`[config] username: ${username || \"(not set)\"}`);\n console.log(\n `[config] scopedRegistries: ${JSON.stringify(scopedRegistries)}`,\n );\n console.log(\n `[config] registryTokens: ${Object.keys(registryTokens).length} configured`,\n );\n }\n\n return {\n registryUrl,\n apiKey,\n username,\n scopedRegistries,\n registryTokens,\n };\n}\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import { f as resolveConfig, g as getEncryptionKey, p as setGlobalMode, w as setEncryptionKey, x as removeEncryptionKey } from "./config-BQy_Rjip.js";
2
+ export { getEncryptionKey, removeEncryptionKey, resolveConfig, setEncryptionKey, setGlobalMode };