@robinmordasiewicz/f5xc-api-mcp 1.0.82-2512312028 → 1.0.82-2601010145

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 (52) hide show
  1. package/dist/auth/credential-manager.d.ts +40 -29
  2. package/dist/auth/credential-manager.d.ts.map +1 -1
  3. package/dist/auth/credential-manager.js +132 -100
  4. package/dist/auth/credential-manager.js.map +1 -1
  5. package/dist/auth/http-client.d.ts.map +1 -1
  6. package/dist/auth/http-client.js +21 -10
  7. package/dist/auth/http-client.js.map +1 -1
  8. package/dist/auth/index.d.ts +5 -0
  9. package/dist/auth/index.d.ts.map +1 -1
  10. package/dist/auth/index.js +5 -0
  11. package/dist/auth/index.js.map +1 -1
  12. package/dist/config/paths.d.ts +34 -0
  13. package/dist/config/paths.d.ts.map +1 -0
  14. package/dist/config/paths.js +67 -0
  15. package/dist/config/paths.js.map +1 -0
  16. package/dist/index.d.ts +12 -6
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/index.js +22 -11
  19. package/dist/index.js.map +1 -1
  20. package/dist/profile/index.d.ts +9 -0
  21. package/dist/profile/index.d.ts.map +1 -0
  22. package/dist/profile/index.js +8 -0
  23. package/dist/profile/index.js.map +1 -0
  24. package/dist/profile/manager.d.ts +75 -0
  25. package/dist/profile/manager.d.ts.map +1 -0
  26. package/dist/profile/manager.js +327 -0
  27. package/dist/profile/manager.js.map +1 -0
  28. package/dist/profile/types.d.ts +51 -0
  29. package/dist/profile/types.d.ts.map +1 -0
  30. package/dist/profile/types.js +8 -0
  31. package/dist/profile/types.js.map +1 -0
  32. package/dist/server.d.ts +6 -1
  33. package/dist/server.d.ts.map +1 -1
  34. package/dist/server.js +8 -2
  35. package/dist/server.js.map +1 -1
  36. package/package.json +1 -1
  37. package/dist/config/config-manager.d.ts +0 -72
  38. package/dist/config/config-manager.d.ts.map +0 -1
  39. package/dist/config/config-manager.js +0 -247
  40. package/dist/config/config-manager.js.map +0 -1
  41. package/dist/config/index.d.ts +0 -7
  42. package/dist/config/index.d.ts.map +0 -1
  43. package/dist/config/index.js +0 -7
  44. package/dist/config/index.js.map +0 -1
  45. package/dist/config/schema.d.ts +0 -74
  46. package/dist/config/schema.d.ts.map +0 -1
  47. package/dist/config/schema.js +0 -75
  48. package/dist/config/schema.js.map +0 -1
  49. package/dist/config/types.d.ts +0 -77
  50. package/dist/config/types.d.ts.map +0 -1
  51. package/dist/config/types.js +0 -31
  52. package/dist/config/types.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EACL,QAAQ,EACR,aAAa,EACb,iBAAiB,EACjB,eAAe,EACf,oBAAoB,GACrB,MAAM,yBAAyB,CAAC;AAEjC,YAAY,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAE3D,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEhE,YAAY,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EACL,QAAQ,EACR,aAAa,EACb,iBAAiB,EACjB,eAAe,EACf,oBAAoB,GACrB,MAAM,yBAAyB,CAAC;AAEjC,YAAY,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAE3D,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEhE,YAAY,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAGtE,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAExE,YAAY,EACV,OAAO,EACP,aAAa,EACb,aAAa,EACb,sBAAsB,GACvB,MAAM,qBAAqB,CAAC"}
@@ -1,6 +1,11 @@
1
1
  /**
2
2
  * Auth Module - Export all authentication utilities
3
+ *
4
+ * Cross-compatible with f5xc-xcsh CLI.
5
+ * Profiles are stored in ~/.config/xcsh/ (shared with xcsh CLI).
3
6
  */
4
7
  export { AuthMode, AUTH_ENV_VARS, CredentialManager, normalizeApiUrl, extractTenantFromUrl, } from "./credential-manager.js";
5
8
  export { HttpClient, createHttpClient } from "./http-client.js";
9
+ // Re-export profile module for cross-compatibility with f5xc-xcsh
10
+ export { ProfileManager, getProfileManager } from "../profile/index.js";
6
11
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EACL,QAAQ,EACR,aAAa,EACb,iBAAiB,EACjB,eAAe,EACf,oBAAoB,GACrB,MAAM,yBAAyB,CAAC;AAIjC,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EACL,QAAQ,EACR,aAAa,EACb,iBAAiB,EACjB,eAAe,EACf,oBAAoB,GACrB,MAAM,yBAAyB,CAAC;AAIjC,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAIhE,kEAAkE;AAClE,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * XDG Base Directory compliant paths for F5 XC configuration
3
+ * See: https://specifications.freedesktop.org/basedir/latest/
4
+ *
5
+ * This is the single source of truth for all application paths.
6
+ * All modules should import from here instead of constructing paths directly.
7
+ *
8
+ * Cross-compatible with f5xc-xcsh CLI - both tools share the same config directory.
9
+ */
10
+ /**
11
+ * Get XDG-compliant config directory
12
+ * Config files: settings, profiles, preferences
13
+ * Default: ~/.config/xcsh
14
+ */
15
+ export declare function getConfigDir(): string;
16
+ /**
17
+ * Get XDG-compliant state directory
18
+ * State files: history, logs, undo history, session state
19
+ * Default: ~/.local/state/xcsh
20
+ */
21
+ export declare function getStateDir(): string;
22
+ /**
23
+ * Centralized path definitions
24
+ * Use these getters for all file path access throughout the application
25
+ */
26
+ export declare const paths: {
27
+ readonly configDir: string;
28
+ readonly profilesDir: string;
29
+ readonly activeProfile: string;
30
+ readonly settings: string;
31
+ readonly stateDir: string;
32
+ readonly history: string;
33
+ };
34
+ //# sourceMappingURL=paths.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/config/paths.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAWH;;;;GAIG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAMrC;AAED;;;;GAIG;AACH,wBAAgB,WAAW,IAAI,MAAM,CAMpC;AAED;;;GAGG;AACH,eAAO,MAAM,KAAK;;;;;;;CAsBjB,CAAC"}
@@ -0,0 +1,67 @@
1
+ /**
2
+ * XDG Base Directory compliant paths for F5 XC configuration
3
+ * See: https://specifications.freedesktop.org/basedir/latest/
4
+ *
5
+ * This is the single source of truth for all application paths.
6
+ * All modules should import from here instead of constructing paths directly.
7
+ *
8
+ * Cross-compatible with f5xc-xcsh CLI - both tools share the same config directory.
9
+ */
10
+ import { homedir } from "os";
11
+ import { join } from "path";
12
+ /**
13
+ * Shared application name with f5xc-xcsh CLI for cross-compatibility
14
+ * Both tools will read/write profiles from the same directory
15
+ */
16
+ const APP_NAME = "xcsh";
17
+ /**
18
+ * Get XDG-compliant config directory
19
+ * Config files: settings, profiles, preferences
20
+ * Default: ~/.config/xcsh
21
+ */
22
+ export function getConfigDir() {
23
+ const xdgConfig = process.env.XDG_CONFIG_HOME;
24
+ if (xdgConfig) {
25
+ return join(xdgConfig, APP_NAME);
26
+ }
27
+ return join(homedir(), ".config", APP_NAME);
28
+ }
29
+ /**
30
+ * Get XDG-compliant state directory
31
+ * State files: history, logs, undo history, session state
32
+ * Default: ~/.local/state/xcsh
33
+ */
34
+ export function getStateDir() {
35
+ const xdgState = process.env.XDG_STATE_HOME;
36
+ if (xdgState) {
37
+ return join(xdgState, APP_NAME);
38
+ }
39
+ return join(homedir(), ".local", "state", APP_NAME);
40
+ }
41
+ /**
42
+ * Centralized path definitions
43
+ * Use these getters for all file path access throughout the application
44
+ */
45
+ export const paths = {
46
+ // Config files (XDG_CONFIG_HOME)
47
+ get configDir() {
48
+ return getConfigDir();
49
+ },
50
+ get profilesDir() {
51
+ return join(getConfigDir(), "profiles");
52
+ },
53
+ get activeProfile() {
54
+ return join(getConfigDir(), "active_profile");
55
+ },
56
+ get settings() {
57
+ return join(getConfigDir(), "config.yaml");
58
+ },
59
+ // State files (XDG_STATE_HOME)
60
+ get stateDir() {
61
+ return getStateDir();
62
+ },
63
+ get history() {
64
+ return join(getStateDir(), "history");
65
+ },
66
+ };
67
+ //# sourceMappingURL=paths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/config/paths.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AAC7B,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B;;;GAGG;AACH,MAAM,QAAQ,GAAG,MAAM,CAAC;AAExB;;;;GAIG;AACH,MAAM,UAAU,YAAY;IAC1B,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC;IAC9C,IAAI,SAAS,EAAE,CAAC;QACd,OAAO,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IACnC,CAAC;IACD,OAAO,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;AAC9C,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,WAAW;IACzB,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;IAC5C,IAAI,QAAQ,EAAE,CAAC;QACb,OAAO,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAClC,CAAC;IACD,OAAO,IAAI,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC;AACtD,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG;IACnB,iCAAiC;IACjC,IAAI,SAAS;QACX,OAAO,YAAY,EAAE,CAAC;IACxB,CAAC;IACD,IAAI,WAAW;QACb,OAAO,IAAI,CAAC,YAAY,EAAE,EAAE,UAAU,CAAC,CAAC;IAC1C,CAAC;IACD,IAAI,aAAa;QACf,OAAO,IAAI,CAAC,YAAY,EAAE,EAAE,gBAAgB,CAAC,CAAC;IAChD,CAAC;IACD,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,YAAY,EAAE,EAAE,aAAa,CAAC,CAAC;IAC7C,CAAC;IAED,+BAA+B;IAC/B,IAAI,QAAQ;QACV,OAAO,WAAW,EAAE,CAAC;IACvB,CAAC;IACD,IAAI,OAAO;QACT,OAAO,IAAI,CAAC,WAAW,EAAE,EAAE,SAAS,CAAC,CAAC;IACxC,CAAC;CACF,CAAC"}
package/dist/index.d.ts CHANGED
@@ -10,12 +10,18 @@
10
10
  * and Terraform examples
11
11
  * - Execution mode: When F5XC credentials are provided, enables direct API calls
12
12
  *
13
- * Environment Variables:
14
- * - F5XC_API_URL: Tenant URL (auto-normalized)
15
- * - F5XC_API_TOKEN: API token for authentication
16
- * - F5XC_P12_FILE: Path to P12 certificate file (alternative to token)
17
- * - F5XC_P12_PASSWORD: Password for P12 certificate
18
- * - F5XC_PROFILE: Profile name to use (default: F5XC_DEFAULT_PROFILE)
13
+ * Credential Sources (in priority order):
14
+ * 1. Environment Variables (highest priority):
15
+ * - F5XC_API_URL: Tenant URL (auto-normalized)
16
+ * - F5XC_API_TOKEN: API token for authentication
17
+ * - F5XC_P12_BUNDLE: Path to P12 certificate bundle
18
+ * - F5XC_CERT: Path to certificate file (for mTLS)
19
+ * - F5XC_KEY: Path to private key file (for mTLS)
20
+ * - F5XC_NAMESPACE: Default namespace
21
+ *
22
+ * 2. Profile from ~/.config/xcsh/ (cross-compatible with f5xc-xcsh CLI):
23
+ * - Uses active profile from ~/.config/xcsh/active_profile
24
+ * - Individual profiles stored in ~/.config/xcsh/profiles/
19
25
  */
20
26
  /** Server version - synchronized with package.json */
21
27
  export declare const VERSION = "0.1.0";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;;;;;;;;;;;;;;;;GAiBG;AAKH,sDAAsD;AACtD,eAAO,MAAM,OAAO,UAAU,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAKH,sDAAsD;AACtD,eAAO,MAAM,OAAO,UAAU,CAAC"}
package/dist/index.js CHANGED
@@ -10,12 +10,18 @@
10
10
  * and Terraform examples
11
11
  * - Execution mode: When F5XC credentials are provided, enables direct API calls
12
12
  *
13
- * Environment Variables:
14
- * - F5XC_API_URL: Tenant URL (auto-normalized)
15
- * - F5XC_API_TOKEN: API token for authentication
16
- * - F5XC_P12_FILE: Path to P12 certificate file (alternative to token)
17
- * - F5XC_P12_PASSWORD: Password for P12 certificate
18
- * - F5XC_PROFILE: Profile name to use (default: F5XC_DEFAULT_PROFILE)
13
+ * Credential Sources (in priority order):
14
+ * 1. Environment Variables (highest priority):
15
+ * - F5XC_API_URL: Tenant URL (auto-normalized)
16
+ * - F5XC_API_TOKEN: API token for authentication
17
+ * - F5XC_P12_BUNDLE: Path to P12 certificate bundle
18
+ * - F5XC_CERT: Path to certificate file (for mTLS)
19
+ * - F5XC_KEY: Path to private key file (for mTLS)
20
+ * - F5XC_NAMESPACE: Default namespace
21
+ *
22
+ * 2. Profile from ~/.config/xcsh/ (cross-compatible with f5xc-xcsh CLI):
23
+ * - Uses active profile from ~/.config/xcsh/active_profile
24
+ * - Individual profiles stored in ~/.config/xcsh/profiles/
19
25
  */
20
26
  import { createServer } from "./server.js";
21
27
  import { logger } from "./utils/logging.js";
@@ -43,12 +49,17 @@ Options:
43
49
  -v, --version Show version number
44
50
  -h, --help Show help
45
51
 
46
- Environment Variables:
52
+ Environment Variables (override profile settings):
47
53
  F5XC_API_URL Tenant URL (e.g., https://tenant.console.ves.volterra.io)
48
54
  F5XC_API_TOKEN API token for authentication
49
- F5XC_P12_FILE Path to P12 certificate file (alternative to token)
50
- F5XC_P12_PASSWORD Password for P12 certificate
51
- F5XC_PROFILE Profile name to use
55
+ F5XC_P12_BUNDLE Path to P12 certificate bundle
56
+ F5XC_CERT Path to certificate file (for mTLS)
57
+ F5XC_KEY Path to private key file (for mTLS)
58
+ F5XC_NAMESPACE Default namespace
59
+
60
+ Profile Configuration (cross-compatible with f5xc-xcsh CLI):
61
+ Profiles are stored in ~/.config/xcsh/profiles/
62
+ Active profile is tracked in ~/.config/xcsh/active_profile
52
63
 
53
64
  The server runs in documentation mode when no credentials are provided,
54
65
  allowing exploration of the API without authentication.
@@ -56,7 +67,7 @@ allowing exploration of the API without authentication.
56
67
  process.exit(0);
57
68
  }
58
69
  // Start MCP server (default behavior)
59
- const server = createServer();
70
+ const server = await createServer();
60
71
  await server.start();
61
72
  // Handle graceful shutdown
62
73
  const shutdown = async (signal) => {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Profile Module - XDG-compliant profile management
3
+ *
4
+ * Cross-compatible with f5xc-xcsh CLI.
5
+ * Exports profile types and the ProfileManager singleton.
6
+ */
7
+ export type { Profile, ProfileConfig, ProfileResult, ProfileValidationError } from "./types.js";
8
+ export { ProfileManager, getProfileManager } from "./manager.js";
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/profile/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,YAAY,EAAE,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAEhG,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Profile Module - XDG-compliant profile management
3
+ *
4
+ * Cross-compatible with f5xc-xcsh CLI.
5
+ * Exports profile types and the ProfileManager singleton.
6
+ */
7
+ export { ProfileManager, getProfileManager } from "./manager.js";
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/profile/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC"}
@@ -0,0 +1,75 @@
1
+ /**
2
+ * ProfileManager - XDG-compliant profile storage and management
3
+ *
4
+ * Cross-compatible with f5xc-xcsh CLI.
5
+ * Profiles are stored in ~/.config/xcsh/profiles/ (XDG Base Directory compliant)
6
+ */
7
+ import type { Profile, ProfileResult } from "./types.js";
8
+ /**
9
+ * ProfileManager handles profile CRUD operations with secure file storage
10
+ */
11
+ export declare class ProfileManager {
12
+ private config;
13
+ constructor();
14
+ /**
15
+ * Ensure config directories exist
16
+ */
17
+ ensureDirectories(): Promise<void>;
18
+ /**
19
+ * Get path to profile JSON file
20
+ */
21
+ private getProfilePath;
22
+ /**
23
+ * Validate profile name (alphanumeric, dash, underscore only)
24
+ */
25
+ private isValidName;
26
+ /**
27
+ * Validate API URL format
28
+ */
29
+ private isValidUrl;
30
+ /**
31
+ * List all saved profiles
32
+ */
33
+ list(): Promise<Profile[]>;
34
+ /**
35
+ * Get a profile by name
36
+ */
37
+ get(name: string): Promise<Profile | null>;
38
+ /**
39
+ * Save a profile (create or update)
40
+ */
41
+ save(profile: Profile): Promise<ProfileResult>;
42
+ /**
43
+ * Delete a profile by name
44
+ */
45
+ delete(name: string): Promise<ProfileResult>;
46
+ /**
47
+ * Get the name of the active profile
48
+ */
49
+ getActive(): Promise<string | null>;
50
+ /**
51
+ * Clear the active profile (used for force delete)
52
+ */
53
+ clearActive(): Promise<void>;
54
+ /**
55
+ * Set the active profile
56
+ */
57
+ setActive(name: string): Promise<ProfileResult>;
58
+ /**
59
+ * Get the active profile (full profile data)
60
+ */
61
+ getActiveProfile(): Promise<Profile | null>;
62
+ /**
63
+ * Check if a profile exists
64
+ */
65
+ exists(name: string): Promise<boolean>;
66
+ /**
67
+ * Mask sensitive fields for display
68
+ */
69
+ maskProfile(profile: Profile): Record<string, string>;
70
+ }
71
+ /**
72
+ * Get the global ProfileManager instance
73
+ */
74
+ export declare function getProfileManager(): ProfileManager;
75
+ //# sourceMappingURL=manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/profile/manager.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,KAAK,EAAE,OAAO,EAAiB,aAAa,EAAE,MAAM,YAAY,CAAC;AAoBxE;;GAEG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAAgB;;IAU9B;;OAEG;IACG,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC;IAOxC;;OAEG;IACH,OAAO,CAAC,cAAc;IAItB;;OAEG;IACH,OAAO,CAAC,WAAW;IAInB;;OAEG;IACH,OAAO,CAAC,UAAU;IASlB;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;IAuChC;;OAEG;IACG,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;IA8BhD;;OAEG;IACG,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,aAAa,CAAC;IA+CpD;;OAEG;IACG,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IAqClD;;OAEG;IACG,SAAS,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IASzC;;OAEG;IACG,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC;IAQlC;;OAEG;IACG,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IA8BrD;;OAEG;IACG,gBAAgB,IAAI,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;IAQjD;;OAEG;IACG,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAK5C;;OAEG;IACH,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;CA8BtD;AAKD;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,cAAc,CAKlD"}
@@ -0,0 +1,327 @@
1
+ /**
2
+ * ProfileManager - XDG-compliant profile storage and management
3
+ *
4
+ * Cross-compatible with f5xc-xcsh CLI.
5
+ * Profiles are stored in ~/.config/xcsh/profiles/ (XDG Base Directory compliant)
6
+ */
7
+ import { promises as fs } from "fs";
8
+ import { join } from "path";
9
+ import YAML from "yaml";
10
+ import { paths } from "../config/paths.js";
11
+ /**
12
+ * Convert snake_case to camelCase
13
+ */
14
+ function snakeToCamel(str) {
15
+ return str.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());
16
+ }
17
+ /**
18
+ * Convert object keys from snake_case to camelCase
19
+ */
20
+ function convertKeysToCamelCase(obj) {
21
+ const result = {};
22
+ for (const [key, value] of Object.entries(obj)) {
23
+ result[snakeToCamel(key)] = value;
24
+ }
25
+ return result;
26
+ }
27
+ /**
28
+ * ProfileManager handles profile CRUD operations with secure file storage
29
+ */
30
+ export class ProfileManager {
31
+ config;
32
+ constructor() {
33
+ this.config = {
34
+ configDir: paths.configDir,
35
+ profilesDir: paths.profilesDir,
36
+ activeProfileFile: paths.activeProfile,
37
+ };
38
+ }
39
+ /**
40
+ * Ensure config directories exist
41
+ */
42
+ async ensureDirectories() {
43
+ await fs.mkdir(this.config.profilesDir, {
44
+ recursive: true,
45
+ mode: 0o700,
46
+ });
47
+ }
48
+ /**
49
+ * Get path to profile JSON file
50
+ */
51
+ getProfilePath(name) {
52
+ return join(this.config.profilesDir, `${name}.json`);
53
+ }
54
+ /**
55
+ * Validate profile name (alphanumeric, dash, underscore only)
56
+ */
57
+ isValidName(name) {
58
+ return /^[a-zA-Z0-9_-]+$/.test(name) && name.length > 0 && name.length <= 64;
59
+ }
60
+ /**
61
+ * Validate API URL format
62
+ */
63
+ isValidUrl(url) {
64
+ try {
65
+ const parsed = new URL(url);
66
+ return parsed.protocol === "https:" || parsed.protocol === "http:";
67
+ }
68
+ catch {
69
+ return false;
70
+ }
71
+ }
72
+ /**
73
+ * List all saved profiles
74
+ */
75
+ async list() {
76
+ await this.ensureDirectories();
77
+ try {
78
+ const files = await fs.readdir(this.config.profilesDir);
79
+ const profileNames = new Set();
80
+ // Collect unique profile names from filenames
81
+ for (const file of files) {
82
+ // Support both .json and .yaml/.yml extensions
83
+ let name = null;
84
+ if (file.endsWith(".json")) {
85
+ name = file.slice(0, -5);
86
+ }
87
+ else if (file.endsWith(".yaml")) {
88
+ name = file.slice(0, -5);
89
+ }
90
+ else if (file.endsWith(".yml")) {
91
+ name = file.slice(0, -4);
92
+ }
93
+ if (name) {
94
+ profileNames.add(name);
95
+ }
96
+ }
97
+ // Load profiles (get() handles file extension priority)
98
+ const profiles = [];
99
+ for (const name of profileNames) {
100
+ const profile = await this.get(name);
101
+ if (profile) {
102
+ profiles.push(profile);
103
+ }
104
+ }
105
+ return profiles.sort((a, b) => a.name.localeCompare(b.name));
106
+ }
107
+ catch {
108
+ return [];
109
+ }
110
+ }
111
+ /**
112
+ * Get a profile by name
113
+ */
114
+ async get(name) {
115
+ await this.ensureDirectories();
116
+ // Try different file extensions in order of preference
117
+ const extensions = [".json", ".yaml", ".yml"];
118
+ for (const ext of extensions) {
119
+ const path = join(this.config.profilesDir, `${name}${ext}`);
120
+ try {
121
+ const data = await fs.readFile(path, "utf-8");
122
+ let parsed;
123
+ if (ext === ".json") {
124
+ parsed = JSON.parse(data);
125
+ }
126
+ else {
127
+ // Parse YAML and convert snake_case to camelCase
128
+ parsed = YAML.parse(data);
129
+ parsed = convertKeysToCamelCase(parsed);
130
+ }
131
+ return parsed;
132
+ }
133
+ catch {
134
+ // Try next extension
135
+ continue;
136
+ }
137
+ }
138
+ return null;
139
+ }
140
+ /**
141
+ * Save a profile (create or update)
142
+ */
143
+ async save(profile) {
144
+ await this.ensureDirectories();
145
+ if (!this.isValidName(profile.name)) {
146
+ return {
147
+ success: false,
148
+ message: "Invalid profile name. Use alphanumeric characters, dashes, and underscores only (max 64 chars).",
149
+ };
150
+ }
151
+ if (!this.isValidUrl(profile.apiUrl)) {
152
+ return {
153
+ success: false,
154
+ message: "Invalid API URL. Must be a valid HTTP/HTTPS URL.",
155
+ };
156
+ }
157
+ // Require at least one form of authentication
158
+ if (!profile.apiToken && !profile.cert && !profile.p12Bundle) {
159
+ return {
160
+ success: false,
161
+ message: "Profile must have at least one authentication method (token, certificate, or P12 bundle).",
162
+ };
163
+ }
164
+ try {
165
+ const path = this.getProfilePath(profile.name);
166
+ const data = JSON.stringify(profile, null, 2);
167
+ // Write with secure permissions (owner read/write only)
168
+ await fs.writeFile(path, data, { mode: 0o600 });
169
+ return {
170
+ success: true,
171
+ message: `Profile '${profile.name}' saved successfully.`,
172
+ profile,
173
+ };
174
+ }
175
+ catch (error) {
176
+ return {
177
+ success: false,
178
+ message: `Failed to save profile: ${error instanceof Error ? error.message : "Unknown error"}`,
179
+ };
180
+ }
181
+ }
182
+ /**
183
+ * Delete a profile by name
184
+ */
185
+ async delete(name) {
186
+ await this.ensureDirectories();
187
+ // Check if profile exists
188
+ const existing = await this.get(name);
189
+ if (!existing) {
190
+ return {
191
+ success: false,
192
+ message: `Profile '${name}' not found.`,
193
+ };
194
+ }
195
+ // Check if it's the active profile
196
+ const active = await this.getActive();
197
+ if (active === name) {
198
+ return {
199
+ success: false,
200
+ message: `Cannot delete active profile '${name}'. Switch to another profile first.`,
201
+ };
202
+ }
203
+ try {
204
+ const path = this.getProfilePath(name);
205
+ await fs.unlink(path);
206
+ return {
207
+ success: true,
208
+ message: `Profile '${name}' deleted successfully.`,
209
+ };
210
+ }
211
+ catch (error) {
212
+ return {
213
+ success: false,
214
+ message: `Failed to delete profile: ${error instanceof Error ? error.message : "Unknown error"}`,
215
+ };
216
+ }
217
+ }
218
+ /**
219
+ * Get the name of the active profile
220
+ */
221
+ async getActive() {
222
+ try {
223
+ const name = await fs.readFile(this.config.activeProfileFile, "utf-8");
224
+ return name.trim() || null;
225
+ }
226
+ catch {
227
+ return null;
228
+ }
229
+ }
230
+ /**
231
+ * Clear the active profile (used for force delete)
232
+ */
233
+ async clearActive() {
234
+ try {
235
+ await fs.unlink(this.config.activeProfileFile);
236
+ }
237
+ catch {
238
+ // Ignore if file doesn't exist
239
+ }
240
+ }
241
+ /**
242
+ * Set the active profile
243
+ */
244
+ async setActive(name) {
245
+ await this.ensureDirectories();
246
+ // Verify profile exists
247
+ const profile = await this.get(name);
248
+ if (!profile) {
249
+ return {
250
+ success: false,
251
+ message: `Profile '${name}' not found.`,
252
+ };
253
+ }
254
+ try {
255
+ await fs.writeFile(this.config.activeProfileFile, name, {
256
+ mode: 0o600,
257
+ });
258
+ return {
259
+ success: true,
260
+ message: `Switched to profile '${name}'.`,
261
+ profile,
262
+ };
263
+ }
264
+ catch (error) {
265
+ return {
266
+ success: false,
267
+ message: `Failed to set active profile: ${error instanceof Error ? error.message : "Unknown error"}`,
268
+ };
269
+ }
270
+ }
271
+ /**
272
+ * Get the active profile (full profile data)
273
+ */
274
+ async getActiveProfile() {
275
+ const name = await this.getActive();
276
+ if (!name) {
277
+ return null;
278
+ }
279
+ return this.get(name);
280
+ }
281
+ /**
282
+ * Check if a profile exists
283
+ */
284
+ async exists(name) {
285
+ const profile = await this.get(name);
286
+ return profile !== null;
287
+ }
288
+ /**
289
+ * Mask sensitive fields for display
290
+ */
291
+ maskProfile(profile) {
292
+ const masked = {
293
+ name: profile.name,
294
+ apiUrl: profile.apiUrl,
295
+ };
296
+ if (profile.apiToken) {
297
+ // Show only last 4 characters
298
+ const len = profile.apiToken.length;
299
+ masked.apiToken = len > 4 ? `****${profile.apiToken.slice(-4)}` : "****";
300
+ }
301
+ if (profile.p12Bundle) {
302
+ masked.p12Bundle = "[configured]";
303
+ }
304
+ if (profile.cert) {
305
+ masked.cert = "[configured]";
306
+ }
307
+ if (profile.key) {
308
+ masked.key = "[configured]";
309
+ }
310
+ if (profile.defaultNamespace) {
311
+ masked.defaultNamespace = profile.defaultNamespace;
312
+ }
313
+ return masked;
314
+ }
315
+ }
316
+ // Singleton instance
317
+ let managerInstance = null;
318
+ /**
319
+ * Get the global ProfileManager instance
320
+ */
321
+ export function getProfileManager() {
322
+ if (!managerInstance) {
323
+ managerInstance = new ProfileManager();
324
+ }
325
+ return managerInstance;
326
+ }
327
+ //# sourceMappingURL=manager.js.map