kaven-cli 0.4.1-alpha.0 → 0.5.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.
Files changed (68) hide show
  1. package/README.md +154 -215
  2. package/dist/EnvManager-NMS3NMIE.js +15 -0
  3. package/dist/MarketplaceClient-YCFH2VU4.js +1 -0
  4. package/dist/chunk-JHLQ46NG.js +1 -0
  5. package/dist/index.d.ts +4 -0
  6. package/dist/index.js +215 -301
  7. package/dist/tier-table-DQMPQSI2.js +6 -0
  8. package/package.json +26 -11
  9. package/dist/EnvManager-GQMEZ6NV.js +0 -158
  10. package/dist/MarketplaceClient-IJGRQRC4.js +0 -7
  11. package/dist/chunk-3RG5ZIWI.js +0 -10
  12. package/dist/chunk-GHZX5OAA.js +0 -455
  13. package/dist/commands/aiox/index.js +0 -20
  14. package/dist/commands/auth/login.js +0 -122
  15. package/dist/commands/auth/logout.js +0 -23
  16. package/dist/commands/auth/whoami.js +0 -36
  17. package/dist/commands/cache/index.js +0 -43
  18. package/dist/commands/config/features.js +0 -161
  19. package/dist/commands/config/index.js +0 -95
  20. package/dist/commands/index.js +0 -2
  21. package/dist/commands/init/aiox-bootstrap.js +0 -83
  22. package/dist/commands/init/index.js +0 -210
  23. package/dist/commands/init-ci/index.js +0 -153
  24. package/dist/commands/license/index.js +0 -10
  25. package/dist/commands/license/status.js +0 -44
  26. package/dist/commands/license/tier-table.js +0 -46
  27. package/dist/commands/marketplace/browse.js +0 -186
  28. package/dist/commands/marketplace/install.js +0 -263
  29. package/dist/commands/marketplace/list.js +0 -122
  30. package/dist/commands/module/activate.js +0 -245
  31. package/dist/commands/module/add.js +0 -69
  32. package/dist/commands/module/doctor.js +0 -175
  33. package/dist/commands/module/list.js +0 -51
  34. package/dist/commands/module/publish.js +0 -258
  35. package/dist/commands/module/remove.js +0 -58
  36. package/dist/commands/telemetry/view.js +0 -27
  37. package/dist/commands/upgrade/check.js +0 -162
  38. package/dist/commands/upgrade/index.js +0 -185
  39. package/dist/core/AuthService.js +0 -222
  40. package/dist/core/CacheManager.js +0 -154
  41. package/dist/core/ConfigManager.js +0 -166
  42. package/dist/core/EnvManager.js +0 -196
  43. package/dist/core/ErrorRecovery.js +0 -192
  44. package/dist/core/LicenseService.js +0 -83
  45. package/dist/core/ManifestParser.js +0 -52
  46. package/dist/core/MarkerService.js +0 -62
  47. package/dist/core/ModuleDoctor.js +0 -451
  48. package/dist/core/ModuleInstaller.js +0 -169
  49. package/dist/core/ProjectInitializer.js +0 -183
  50. package/dist/core/RegistryResolver.js +0 -95
  51. package/dist/core/SchemaActivator.js +0 -278
  52. package/dist/core/ScriptRunner.js +0 -73
  53. package/dist/core/SignatureVerifier.js +0 -75
  54. package/dist/core/index.js +0 -2
  55. package/dist/infrastructure/Container.js +0 -37
  56. package/dist/infrastructure/MarketplaceClient.js +0 -425
  57. package/dist/infrastructure/TelemetryBuffer.js +0 -73
  58. package/dist/infrastructure/TransactionalFileSystem.js +0 -77
  59. package/dist/infrastructure/errors.js +0 -63
  60. package/dist/infrastructure/index.js +0 -2
  61. package/dist/lib/capabilities-catalog.js +0 -73
  62. package/dist/lib/module-registry.js +0 -47
  63. package/dist/lib/schema-modifier.js +0 -40
  64. package/dist/tier-table-LAL6PAVW.js +0 -52
  65. package/dist/types/auth.js +0 -2
  66. package/dist/types/manifest.js +0 -45
  67. package/dist/types/markers.js +0 -10
  68. package/dist/types/marketplace.js +0 -2
@@ -1,162 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.upgradeCheck = upgradeCheck;
7
- exports.upgradeInstall = upgradeInstall;
8
- const chalk_1 = __importDefault(require("chalk"));
9
- const ora_1 = __importDefault(require("ora"));
10
- const path_1 = __importDefault(require("path"));
11
- const child_process_1 = require("child_process");
12
- const fs_1 = __importDefault(require("fs"));
13
- const packageJsonPath = path_1.default.join(__dirname, "../../..", "package.json");
14
- const PACKAGE_JSON = JSON.parse(fs_1.default.readFileSync(packageJsonPath, "utf8"));
15
- const CURRENT_VERSION = PACKAGE_JSON.version;
16
- const CLI_NAME = "kaven-cli";
17
- /**
18
- * C2.3: Check for CLI updates
19
- */
20
- async function upgradeCheck() {
21
- const spinner = (0, ora_1.default)("Checking for updates...").start();
22
- try {
23
- // Fetch latest version from npm registry
24
- const response = await fetch(`https://registry.npmjs.org/${CLI_NAME}`);
25
- if (!response.ok) {
26
- spinner.fail("Could not check for updates");
27
- return;
28
- }
29
- const data = (await response.json());
30
- const distTags = data["dist-tags"];
31
- const latestVersion = distTags?.latest || CURRENT_VERSION;
32
- spinner.stop();
33
- console.log();
34
- console.log(chalk_1.default.bold("Version Check:"));
35
- console.log(` Current: ${chalk_1.default.cyan(CURRENT_VERSION)}`);
36
- console.log(` Latest: ${chalk_1.default.cyan(latestVersion)}`);
37
- console.log();
38
- if (latestVersion === CURRENT_VERSION) {
39
- console.log(chalk_1.default.green("✅ You're on the latest version!"));
40
- return;
41
- }
42
- // Check if update available
43
- const current = parseVersion(CURRENT_VERSION);
44
- const latest = parseVersion(latestVersion);
45
- if (latest.major > current.major ||
46
- (latest.major === current.major && latest.minor > current.minor) ||
47
- (latest.major === current.major &&
48
- latest.minor === current.minor &&
49
- latest.patch > current.patch)) {
50
- console.log(chalk_1.default.yellow(`⚠ Update available: ${latestVersion}`));
51
- console.log();
52
- console.log(chalk_1.default.bold("To upgrade, run:"));
53
- console.log(chalk_1.default.cyan(` npm install -g ${CLI_NAME}@latest`));
54
- console.log(chalk_1.default.cyan(` or`));
55
- console.log(chalk_1.default.cyan(` pnpm add -g ${CLI_NAME}@latest`));
56
- console.log();
57
- console.log(chalk_1.default.gray("Release notes: https://github.com/kaven-co/kaven-cli/releases"));
58
- }
59
- else {
60
- console.log(chalk_1.default.green("✅ You're on the latest version!"));
61
- }
62
- }
63
- catch (error) {
64
- spinner.fail(`Check failed: ${error instanceof Error ? error.message : String(error)}`);
65
- console.log(chalk_1.default.gray("You can manually check at: https://www.npmjs.com/package/kaven-cli"));
66
- }
67
- }
68
- /**
69
- * C2.3: Install latest CLI version
70
- */
71
- async function upgradeInstall() {
72
- console.log();
73
- const spinner = (0, ora_1.default)("Fetching latest version...").start();
74
- try {
75
- // Get latest version
76
- const response = await fetch(`https://registry.npmjs.org/${CLI_NAME}`);
77
- if (!response.ok) {
78
- throw new Error("Failed to fetch package info");
79
- }
80
- const data = (await response.json());
81
- const distTags = data["dist-tags"];
82
- const latestVersion = distTags?.latest || CURRENT_VERSION;
83
- if (latestVersion === CURRENT_VERSION) {
84
- spinner.succeed("Already on latest version");
85
- return;
86
- }
87
- spinner.text = `Installing ${CLI_NAME}@${latestVersion}...`;
88
- // Determine package manager
89
- const packageManager = process.env.npm_config_user_agent?.includes("pnpm")
90
- ? "pnpm"
91
- : "npm";
92
- // Install with appropriate package manager
93
- const exitCode = await runCommand(packageManager, [
94
- "install",
95
- "-g",
96
- `${CLI_NAME}@${latestVersion}`,
97
- ]);
98
- if (exitCode !== 0) {
99
- spinner.fail(`Installation failed with exit code ${exitCode}`);
100
- console.error(chalk_1.default.gray(`Try: ${packageManager} install -g ${CLI_NAME}@latest`));
101
- process.exit(1);
102
- return;
103
- }
104
- spinner.succeed(`Updated to ${latestVersion}`);
105
- // Health check after install
106
- const healthSpinner = (0, ora_1.default)("Running health check...").start();
107
- const health = await verifyInstallation();
108
- if (health.ok) {
109
- healthSpinner.succeed("Installation verified");
110
- console.log();
111
- console.log(chalk_1.default.green("✅ CLI upgraded successfully!"));
112
- console.log(chalk_1.default.gray("Try: kaven --version"));
113
- }
114
- else {
115
- healthSpinner.warn("Installation verification failed");
116
- console.log(chalk_1.default.yellow(health.errors.join("\n")));
117
- }
118
- }
119
- catch (error) {
120
- spinner.fail(`Installation failed: ${error instanceof Error ? error.message : String(error)}`);
121
- process.exit(1);
122
- }
123
- }
124
- /**
125
- * Verify CLI installation is working
126
- */
127
- async function verifyInstallation() {
128
- const errors = [];
129
- try {
130
- // Check if kaven command is available
131
- const code = await runCommand("kaven", ["--version"], { stdio: "pipe" });
132
- if (code !== 0) {
133
- errors.push("kaven command not available in PATH");
134
- }
135
- }
136
- catch {
137
- errors.push("Could not execute kaven command");
138
- }
139
- return { ok: errors.length === 0, errors };
140
- }
141
- /**
142
- * Run shell command
143
- */
144
- function runCommand(cmd, args, options) {
145
- return new Promise((resolve, reject) => {
146
- const proc = (0, child_process_1.spawn)(cmd, args, options || { stdio: "inherit" });
147
- proc.on("error", reject);
148
- proc.on("close", (code) => resolve(code ?? 0));
149
- });
150
- }
151
- /**
152
- * Parse semver version
153
- */
154
- function parseVersion(version) {
155
- const cleaned = version.replace(/^v/, "").split("-")[0];
156
- const [major, minor, patch] = cleaned.split(".").map(Number);
157
- return {
158
- major: major || 0,
159
- minor: minor || 0,
160
- patch: patch || 0,
161
- };
162
- }
@@ -1,185 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.upgradeInstall = exports.upgradeCheck = void 0;
7
- exports.upgradeCommand = upgradeCommand;
8
- const chalk_1 = __importDefault(require("chalk"));
9
- const ora_1 = __importDefault(require("ora"));
10
- const open_1 = __importDefault(require("open"));
11
- const path_1 = __importDefault(require("path"));
12
- const fs_extra_1 = __importDefault(require("fs-extra"));
13
- const os_1 = __importDefault(require("os"));
14
- const AuthService_1 = require("../../core/AuthService");
15
- const MarketplaceClient_1 = require("../../infrastructure/MarketplaceClient");
16
- const check_1 = require("./check");
17
- Object.defineProperty(exports, "upgradeCheck", { enumerable: true, get: function () { return check_1.upgradeCheck; } });
18
- Object.defineProperty(exports, "upgradeInstall", { enumerable: true, get: function () { return check_1.upgradeInstall; } });
19
- const LICENSE_PATH = path_1.default.join(os_1.default.homedir(), ".kaven", "license.json");
20
- const TIERS = ["starter", "complete", "pro", "enterprise"];
21
- const TIER_LABELS = {
22
- starter: "Starter",
23
- complete: "Complete",
24
- pro: "Pro",
25
- enterprise: "Enterprise",
26
- };
27
- const POLL_INTERVAL_MS = 5_000;
28
- const MAX_POLLS = 120; // 10 minutes
29
- async function loadLicenseKey() {
30
- if (!(await fs_extra_1.default.pathExists(LICENSE_PATH)))
31
- return null;
32
- try {
33
- const data = await fs_extra_1.default.readJson(LICENSE_PATH);
34
- return data.key || null;
35
- }
36
- catch {
37
- return null;
38
- }
39
- }
40
- async function saveLicenseTier(tier) {
41
- let existing = {};
42
- if (await fs_extra_1.default.pathExists(LICENSE_PATH)) {
43
- try {
44
- existing = await fs_extra_1.default.readJson(LICENSE_PATH);
45
- }
46
- catch {
47
- // ignore
48
- }
49
- }
50
- await fs_extra_1.default.ensureDir(path_1.default.dirname(LICENSE_PATH));
51
- await fs_extra_1.default.writeJson(LICENSE_PATH, { ...existing, tier }, { spaces: 2 });
52
- }
53
- function sleep(ms) {
54
- return new Promise((resolve) => setTimeout(resolve, ms));
55
- }
56
- async function upgradeCommand(options) {
57
- // 1. Require auth
58
- const authService = new AuthService_1.AuthService();
59
- try {
60
- await authService.getValidToken();
61
- }
62
- catch {
63
- console.error(chalk_1.default.red("Error: Not authenticated. Run 'kaven auth login' first."));
64
- process.exit(1);
65
- return;
66
- }
67
- // 2. Load current license key
68
- const licenseKey = await loadLicenseKey();
69
- if (!licenseKey) {
70
- console.error(chalk_1.default.red("Error: No license found. Add your license key first with 'kaven license status'."));
71
- process.exit(1);
72
- return;
73
- }
74
- // 3. Get current tier
75
- const client = new MarketplaceClient_1.MarketplaceClient(authService);
76
- const tierSpinner = (0, ora_1.default)("Loading your current license...").start();
77
- let currentTier;
78
- try {
79
- const licenseStatus = await client.getLicenseStatus(licenseKey);
80
- currentTier = licenseStatus.tier.toLowerCase();
81
- tierSpinner.succeed(`Current tier: ${chalk_1.default.bold(TIER_LABELS[currentTier] || currentTier)}`);
82
- }
83
- catch {
84
- tierSpinner.fail("Could not load license status");
85
- console.error(chalk_1.default.gray("Try: kaven license status"));
86
- process.exit(1);
87
- return;
88
- }
89
- // 4. Show tier comparison table (imported from license command)
90
- const { printTierComparisonTable } = await import("../license/tier-table.js");
91
- printTierComparisonTable(currentTier, "pro");
92
- console.log();
93
- // 5. Prompt target tier (exclude current tier)
94
- const { select } = await import("@inquirer/prompts");
95
- const availableTiers = TIERS.filter((t) => t !== currentTier && t !== "enterprise");
96
- if (availableTiers.length === 0) {
97
- console.log(chalk_1.default.yellow(`You're already on the highest available tier (${TIER_LABELS[currentTier] || currentTier}).`));
98
- console.log(chalk_1.default.gray("For Enterprise plans, contact: enterprise@kaven.site"));
99
- return;
100
- }
101
- const targetTier = await select({
102
- message: "Select target tier:",
103
- choices: availableTiers.map((t) => ({
104
- name: TIER_LABELS[t],
105
- value: t,
106
- })),
107
- });
108
- // 6. Guard: same tier
109
- if (targetTier === currentTier) {
110
- console.log(chalk_1.default.yellow(`Already on ${TIER_LABELS[currentTier] || currentTier}.`));
111
- return;
112
- }
113
- // 7. Create checkout session
114
- const checkoutSpinner = (0, ora_1.default)("Creating checkout session...").start();
115
- let sessionUrl;
116
- let sessionId;
117
- try {
118
- const session = await client.createCheckoutSession(targetTier, licenseKey);
119
- sessionUrl = session.sessionUrl;
120
- sessionId = session.sessionId;
121
- checkoutSpinner.succeed("Checkout session created");
122
- }
123
- catch (error) {
124
- checkoutSpinner.fail("Failed to create checkout session");
125
- console.error(chalk_1.default.red(error instanceof Error ? error.message : String(error)));
126
- process.exit(1);
127
- return;
128
- }
129
- // 8. Open browser
130
- if (options.browser !== false) {
131
- console.log(chalk_1.default.cyan(`Opening checkout in your browser...`));
132
- console.log(chalk_1.default.gray(`URL: ${sessionUrl}`));
133
- try {
134
- await (0, open_1.default)(sessionUrl);
135
- }
136
- catch {
137
- console.log(chalk_1.default.yellow("Could not open browser automatically. Open this URL manually:"));
138
- console.log(chalk_1.default.cyan(sessionUrl));
139
- }
140
- }
141
- else {
142
- console.log(chalk_1.default.cyan("Open this URL to complete checkout:"));
143
- console.log(chalk_1.default.bold(sessionUrl));
144
- }
145
- console.log();
146
- // 9. Poll for checkout status
147
- const pollSpinner = (0, ora_1.default)(`Waiting for payment confirmation (checking every 5s, max 10 min)...`).start();
148
- for (let i = 0; i < MAX_POLLS; i++) {
149
- await sleep(POLL_INTERVAL_MS);
150
- const remaining = MAX_POLLS - i - 1;
151
- pollSpinner.text = `Waiting for payment confirmation... (${remaining * 5}s remaining)`;
152
- try {
153
- const status = await client.getCheckoutStatus(sessionId);
154
- if (status.status === "confirmed") {
155
- pollSpinner.succeed("Payment confirmed!");
156
- const newTier = status.tier || targetTier;
157
- await saveLicenseTier(newTier);
158
- console.log();
159
- console.log(chalk_1.default.green(`✅ Successfully upgraded to ${TIER_LABELS[newTier] || newTier}!`));
160
- console.log(chalk_1.default.gray("Your new features are now unlocked."));
161
- return;
162
- }
163
- if (status.status === "cancelled") {
164
- pollSpinner.fail("Checkout was cancelled.");
165
- console.log(chalk_1.default.gray("No changes were made to your subscription."));
166
- return;
167
- }
168
- if (status.status === "failed") {
169
- pollSpinner.fail("Payment failed.");
170
- console.log(chalk_1.default.gray("Please try again or contact support@kaven.site"));
171
- process.exit(1);
172
- return;
173
- }
174
- // status === "pending" — continue polling
175
- }
176
- catch {
177
- // Network hiccup — keep polling
178
- }
179
- }
180
- // Timeout
181
- pollSpinner.warn("Timed out waiting for payment confirmation.");
182
- console.log();
183
- console.log(chalk_1.default.yellow("If you completed payment, your upgrade may take a few minutes to activate."));
184
- console.log(chalk_1.default.gray("Check your upgrade status at: https://dashboard.kaven.site/billing"));
185
- }
@@ -1,222 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.AuthService = void 0;
7
- const fs_extra_1 = __importDefault(require("fs-extra"));
8
- const path_1 = __importDefault(require("path"));
9
- const os_1 = __importDefault(require("os"));
10
- /** Decode a JWT payload without verifying the signature (server's responsibility). */
11
- function decodeJwtPayload(token) {
12
- try {
13
- const parts = token.split(".");
14
- if (parts.length !== 3)
15
- return null;
16
- // Base64url → Base64 → JSON
17
- const base64 = parts[1].replace(/-/g, "+").replace(/_/g, "/");
18
- const padded = base64 + "=".repeat((4 - (base64.length % 4)) % 4);
19
- const json = Buffer.from(padded, "base64").toString("utf8");
20
- return JSON.parse(json);
21
- }
22
- catch {
23
- return null;
24
- }
25
- }
26
- /** Format a future timestamp into a human-readable "expires in X" string. */
27
- function formatExpiryRelative(expiresAt) {
28
- const now = Date.now();
29
- const expMs = new Date(expiresAt).getTime();
30
- const diffSeconds = Math.max(0, Math.floor((expMs - now) / 1000));
31
- if (diffSeconds === 0)
32
- return "expired";
33
- const hours = Math.floor(diffSeconds / 3600);
34
- const minutes = Math.floor((diffSeconds % 3600) / 60);
35
- if (hours > 0) {
36
- return `expires in ${hours}h ${minutes}m`;
37
- }
38
- return `expires in ${minutes}m`;
39
- }
40
- class AuthService {
41
- configPath;
42
- constructor() {
43
- this.configPath = path_1.default.join(os_1.default.homedir(), ".kaven", "auth.json");
44
- }
45
- /**
46
- * Store complete auth tokens (new format for C1.1+)
47
- */
48
- async saveTokens(tokens) {
49
- const configDir = path_1.default.dirname(this.configPath);
50
- await fs_extra_1.default.ensureDir(configDir);
51
- await fs_extra_1.default.writeJson(this.configPath, tokens, { spaces: 2 });
52
- // Set restrictive permissions (0600 - owner read/write only) on Unix-like systems
53
- if (process.platform !== "win32") {
54
- await fs_extra_1.default.chmod(this.configPath, 0o600);
55
- }
56
- }
57
- /**
58
- * Legacy method - kept for backwards compatibility
59
- * @deprecated Use saveTokens() instead
60
- */
61
- async storeToken(token) {
62
- const configDir = path_1.default.dirname(this.configPath);
63
- await fs_extra_1.default.ensureDir(configDir);
64
- await fs_extra_1.default.writeJson(this.configPath, { token }, { spaces: 2 });
65
- if (process.platform !== "win32") {
66
- await fs_extra_1.default.chmod(this.configPath, 0o600);
67
- }
68
- }
69
- /**
70
- * Get stored authentication data (new format)
71
- */
72
- async getAuth() {
73
- if (!(await fs_extra_1.default.pathExists(this.configPath))) {
74
- return null;
75
- }
76
- try {
77
- const data = await fs_extra_1.default.readJson(this.configPath);
78
- if (data.access_token) {
79
- return data;
80
- }
81
- return null;
82
- }
83
- catch {
84
- return null;
85
- }
86
- }
87
- /**
88
- * Legacy method - kept for backwards compatibility
89
- * @deprecated Use getAuth() instead
90
- */
91
- async getToken() {
92
- if (!(await fs_extra_1.default.pathExists(this.configPath))) {
93
- return null;
94
- }
95
- try {
96
- const data = await fs_extra_1.default.readJson(this.configPath);
97
- if (data.access_token) {
98
- return data.access_token;
99
- }
100
- return data.token || null;
101
- }
102
- catch {
103
- return null;
104
- }
105
- }
106
- /**
107
- * Return a valid access token, auto-refreshing if it expires in <5 minutes.
108
- * Throws if the session is expired and refresh fails.
109
- */
110
- async getValidToken() {
111
- const auth = await this.getAuth();
112
- if (!auth) {
113
- throw new Error("Not authenticated. Run 'kaven auth login' to authenticate.");
114
- }
115
- const expiresAt = new Date(auth.expires_at).getTime();
116
- const now = Date.now();
117
- const fiveMinutesMs = 5 * 60 * 1000;
118
- const isExpiringSoon = expiresAt - now < fiveMinutesMs;
119
- const isExpired = now >= expiresAt;
120
- if (!isExpiringSoon) {
121
- // Token is still valid and not expiring soon — return as-is
122
- return auth.access_token;
123
- }
124
- // Attempt refresh
125
- try {
126
- // Lazy import to avoid circular dependency at module level
127
- const { MarketplaceClient } = await import("../infrastructure/MarketplaceClient.js");
128
- const client = new MarketplaceClient(this);
129
- const refreshed = await client.refreshToken(auth.refresh_token);
130
- // Update stored auth with new tokens
131
- const newAuth = {
132
- access_token: refreshed.access_token,
133
- refresh_token: refreshed.refresh_token,
134
- expires_at: refreshed.expires_at,
135
- user: auth.user,
136
- };
137
- await this.saveTokens(newAuth);
138
- return refreshed.access_token;
139
- }
140
- catch {
141
- // Refresh failed — use existing token if still valid, else throw
142
- if (!isExpired) {
143
- console.warn("[kaven] Warning: Failed to refresh token. Using existing token.");
144
- return auth.access_token;
145
- }
146
- throw new Error("Session expired. Run 'kaven auth login' to re-authenticate.");
147
- }
148
- }
149
- /**
150
- * Check if the user is authenticated. Never throws.
151
- */
152
- async isAuthenticated() {
153
- try {
154
- const token = await this.getToken();
155
- return !!token;
156
- }
157
- catch {
158
- return false;
159
- }
160
- }
161
- /**
162
- * Remove auth.json (logout)
163
- */
164
- async logout() {
165
- if (await fs_extra_1.default.pathExists(this.configPath)) {
166
- await fs_extra_1.default.remove(this.configPath);
167
- }
168
- }
169
- /**
170
- * Legacy alias for logout()
171
- * @deprecated Use logout() instead
172
- */
173
- async clearToken() {
174
- return this.logout();
175
- }
176
- /**
177
- * Decode JWT and return user info from the access token payload.
178
- */
179
- async getUserInfo() {
180
- const auth = await this.getAuth();
181
- if (!auth)
182
- return null;
183
- const payload = decodeJwtPayload(auth.access_token);
184
- if (payload) {
185
- return {
186
- id: payload.sub,
187
- email: payload.email,
188
- name: payload.githubId,
189
- };
190
- }
191
- // Fallback to stored user data if JWT decode fails
192
- return {
193
- id: auth.user.githubId,
194
- email: auth.user.email,
195
- name: undefined,
196
- };
197
- }
198
- /**
199
- * Get decoded JWT payload from stored access token.
200
- */
201
- async getDecodedToken() {
202
- const auth = await this.getAuth();
203
- if (!auth)
204
- return null;
205
- return decodeJwtPayload(auth.access_token);
206
- }
207
- /**
208
- * Get the stored auth data along with human-readable expiry string.
209
- */
210
- async getWhoamiInfo() {
211
- const auth = await this.getAuth();
212
- if (!auth)
213
- return null;
214
- return {
215
- email: auth.user.email,
216
- githubId: auth.user.githubId,
217
- tier: auth.user.tier.charAt(0).toUpperCase() + auth.user.tier.slice(1),
218
- sessionExpiry: formatExpiryRelative(auth.expires_at),
219
- };
220
- }
221
- }
222
- exports.AuthService = AuthService;