kaven-cli 0.4.1-alpha.0 → 0.6.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.
- package/README.md +154 -215
- package/dist/EnvManager-NMS3NMIE.js +15 -0
- package/dist/MarketplaceClient-YCFH2VU4.js +1 -0
- package/dist/chunk-JHLQ46NG.js +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +224 -301
- package/dist/tier-table-DQMPQSI2.js +6 -0
- package/package.json +26 -11
- package/dist/EnvManager-GQMEZ6NV.js +0 -158
- package/dist/MarketplaceClient-IJGRQRC4.js +0 -7
- package/dist/chunk-3RG5ZIWI.js +0 -10
- package/dist/chunk-GHZX5OAA.js +0 -455
- package/dist/commands/aiox/index.js +0 -20
- package/dist/commands/auth/login.js +0 -122
- package/dist/commands/auth/logout.js +0 -23
- package/dist/commands/auth/whoami.js +0 -36
- package/dist/commands/cache/index.js +0 -43
- package/dist/commands/config/features.js +0 -161
- package/dist/commands/config/index.js +0 -95
- package/dist/commands/index.js +0 -2
- package/dist/commands/init/aiox-bootstrap.js +0 -83
- package/dist/commands/init/index.js +0 -210
- package/dist/commands/init-ci/index.js +0 -153
- package/dist/commands/license/index.js +0 -10
- package/dist/commands/license/status.js +0 -44
- package/dist/commands/license/tier-table.js +0 -46
- package/dist/commands/marketplace/browse.js +0 -186
- package/dist/commands/marketplace/install.js +0 -263
- package/dist/commands/marketplace/list.js +0 -122
- package/dist/commands/module/activate.js +0 -245
- package/dist/commands/module/add.js +0 -69
- package/dist/commands/module/doctor.js +0 -175
- package/dist/commands/module/list.js +0 -51
- package/dist/commands/module/publish.js +0 -258
- package/dist/commands/module/remove.js +0 -58
- package/dist/commands/telemetry/view.js +0 -27
- package/dist/commands/upgrade/check.js +0 -162
- package/dist/commands/upgrade/index.js +0 -185
- package/dist/core/AuthService.js +0 -222
- package/dist/core/CacheManager.js +0 -154
- package/dist/core/ConfigManager.js +0 -166
- package/dist/core/EnvManager.js +0 -196
- package/dist/core/ErrorRecovery.js +0 -192
- package/dist/core/LicenseService.js +0 -83
- package/dist/core/ManifestParser.js +0 -52
- package/dist/core/MarkerService.js +0 -62
- package/dist/core/ModuleDoctor.js +0 -451
- package/dist/core/ModuleInstaller.js +0 -169
- package/dist/core/ProjectInitializer.js +0 -183
- package/dist/core/RegistryResolver.js +0 -95
- package/dist/core/SchemaActivator.js +0 -278
- package/dist/core/ScriptRunner.js +0 -73
- package/dist/core/SignatureVerifier.js +0 -75
- package/dist/core/index.js +0 -2
- package/dist/infrastructure/Container.js +0 -37
- package/dist/infrastructure/MarketplaceClient.js +0 -425
- package/dist/infrastructure/TelemetryBuffer.js +0 -73
- package/dist/infrastructure/TransactionalFileSystem.js +0 -77
- package/dist/infrastructure/errors.js +0 -63
- package/dist/infrastructure/index.js +0 -2
- package/dist/lib/capabilities-catalog.js +0 -73
- package/dist/lib/module-registry.js +0 -47
- package/dist/lib/schema-modifier.js +0 -40
- package/dist/tier-table-LAL6PAVW.js +0 -52
- package/dist/types/auth.js +0 -2
- package/dist/types/manifest.js +0 -45
- package/dist/types/markers.js +0 -10
- package/dist/types/marketplace.js +0 -2
package/dist/chunk-GHZX5OAA.js
DELETED
|
@@ -1,455 +0,0 @@
|
|
|
1
|
-
// src/infrastructure/MarketplaceClient.ts
|
|
2
|
-
import fs from "fs-extra";
|
|
3
|
-
import path from "path";
|
|
4
|
-
import os from "os";
|
|
5
|
-
|
|
6
|
-
// src/infrastructure/errors.ts
|
|
7
|
-
var MarketplaceError = class extends Error {
|
|
8
|
-
constructor(message) {
|
|
9
|
-
super(message);
|
|
10
|
-
this.name = "MarketplaceError";
|
|
11
|
-
}
|
|
12
|
-
};
|
|
13
|
-
var AuthenticationError = class extends MarketplaceError {
|
|
14
|
-
constructor(message) {
|
|
15
|
-
super(message);
|
|
16
|
-
this.name = "AuthenticationError";
|
|
17
|
-
}
|
|
18
|
-
};
|
|
19
|
-
var LicenseRequiredError = class extends MarketplaceError {
|
|
20
|
-
constructor(requiredTier, message) {
|
|
21
|
-
super(message);
|
|
22
|
-
this.requiredTier = requiredTier;
|
|
23
|
-
this.name = "LicenseRequiredError";
|
|
24
|
-
}
|
|
25
|
-
};
|
|
26
|
-
var NotFoundError = class extends MarketplaceError {
|
|
27
|
-
constructor(message) {
|
|
28
|
-
super(message);
|
|
29
|
-
this.name = "NotFoundError";
|
|
30
|
-
}
|
|
31
|
-
};
|
|
32
|
-
var RateLimitError = class extends MarketplaceError {
|
|
33
|
-
constructor(retryAfter) {
|
|
34
|
-
super(`Rate limited. Try again in ${retryAfter}s`);
|
|
35
|
-
this.retryAfter = retryAfter;
|
|
36
|
-
this.name = "RateLimitError";
|
|
37
|
-
}
|
|
38
|
-
};
|
|
39
|
-
var ServerError = class extends MarketplaceError {
|
|
40
|
-
constructor(message) {
|
|
41
|
-
super(message);
|
|
42
|
-
this.name = "ServerError";
|
|
43
|
-
}
|
|
44
|
-
};
|
|
45
|
-
var NetworkError = class extends MarketplaceError {
|
|
46
|
-
constructor(message) {
|
|
47
|
-
super(message);
|
|
48
|
-
this.name = "NetworkError";
|
|
49
|
-
}
|
|
50
|
-
};
|
|
51
|
-
var SignatureVerificationError = class extends MarketplaceError {
|
|
52
|
-
constructor(message) {
|
|
53
|
-
super(message);
|
|
54
|
-
this.name = "SignatureVerificationError";
|
|
55
|
-
}
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
// src/infrastructure/MarketplaceClient.ts
|
|
59
|
-
var DEFAULT_BASE_URL = "https://api.kaven.sh";
|
|
60
|
-
var REQUEST_TIMEOUT_MS = 3e4;
|
|
61
|
-
var MAX_RETRIES = 3;
|
|
62
|
-
var INITIAL_RETRY_DELAY_MS = 1e3;
|
|
63
|
-
function debug(message) {
|
|
64
|
-
if (process.env.KAVEN_DEBUG === "1") {
|
|
65
|
-
console.debug(`[kaven:debug] ${message}`);
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
async function loadConfigApiUrl() {
|
|
69
|
-
try {
|
|
70
|
-
const configPath = path.join(os.homedir(), ".kaven", "config.json");
|
|
71
|
-
if (await fs.pathExists(configPath)) {
|
|
72
|
-
const config = await fs.readJson(configPath);
|
|
73
|
-
if (typeof config.apiUrl === "string" && config.apiUrl) {
|
|
74
|
-
return config.apiUrl;
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
} catch {
|
|
78
|
-
}
|
|
79
|
-
return null;
|
|
80
|
-
}
|
|
81
|
-
async function resolveBaseUrl() {
|
|
82
|
-
if (process.env.KAVEN_API_URL) {
|
|
83
|
-
return process.env.KAVEN_API_URL.replace(/\/$/, "");
|
|
84
|
-
}
|
|
85
|
-
const configUrl = await loadConfigApiUrl();
|
|
86
|
-
if (configUrl) {
|
|
87
|
-
return configUrl.replace(/\/$/, "");
|
|
88
|
-
}
|
|
89
|
-
return DEFAULT_BASE_URL;
|
|
90
|
-
}
|
|
91
|
-
function sleep(ms) {
|
|
92
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
93
|
-
}
|
|
94
|
-
function isRetryable(status) {
|
|
95
|
-
return status >= 500;
|
|
96
|
-
}
|
|
97
|
-
var MarketplaceClient = class {
|
|
98
|
-
baseURLPromise;
|
|
99
|
-
authService;
|
|
100
|
-
constructor(authService) {
|
|
101
|
-
this.authService = authService ?? null;
|
|
102
|
-
this.baseURLPromise = resolveBaseUrl();
|
|
103
|
-
}
|
|
104
|
-
/** Resolve a relative API path to an absolute URL. */
|
|
105
|
-
async resolveUrl(path2) {
|
|
106
|
-
const baseURL = await this.baseURLPromise;
|
|
107
|
-
return `${baseURL}${path2}`;
|
|
108
|
-
}
|
|
109
|
-
// ──────────────────────────────────────────────────────────
|
|
110
|
-
// Core HTTP helpers
|
|
111
|
-
// ──────────────────────────────────────────────────────────
|
|
112
|
-
/**
|
|
113
|
-
* Make an HTTP request with retry logic and typed error mapping.
|
|
114
|
-
* `authenticated` controls whether Authorization header is attached.
|
|
115
|
-
*/
|
|
116
|
-
async request(method, endpoint, options = {}) {
|
|
117
|
-
const baseURL = await this.baseURLPromise;
|
|
118
|
-
const url = `${baseURL}${endpoint}`;
|
|
119
|
-
const { body, authenticated = false } = options;
|
|
120
|
-
let lastError = null;
|
|
121
|
-
for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
|
|
122
|
-
if (attempt > 0) {
|
|
123
|
-
const delay = INITIAL_RETRY_DELAY_MS * Math.pow(2, attempt - 1);
|
|
124
|
-
debug(`Retry attempt ${attempt} for ${method} ${endpoint} (delay ${delay}ms)`);
|
|
125
|
-
await sleep(delay);
|
|
126
|
-
}
|
|
127
|
-
try {
|
|
128
|
-
const headers = {
|
|
129
|
-
"Content-Type": "application/json",
|
|
130
|
-
Accept: "application/json"
|
|
131
|
-
};
|
|
132
|
-
if (authenticated && this.authService) {
|
|
133
|
-
const token = await this.authService.getValidToken();
|
|
134
|
-
headers["Authorization"] = `Bearer ${token}`;
|
|
135
|
-
}
|
|
136
|
-
debug(`${method} ${url}`);
|
|
137
|
-
const controller = new AbortController();
|
|
138
|
-
const timeoutId = setTimeout(
|
|
139
|
-
() => controller.abort(),
|
|
140
|
-
REQUEST_TIMEOUT_MS
|
|
141
|
-
);
|
|
142
|
-
let response;
|
|
143
|
-
try {
|
|
144
|
-
response = await fetch(url, {
|
|
145
|
-
method,
|
|
146
|
-
headers,
|
|
147
|
-
body: body !== void 0 ? JSON.stringify(body) : void 0,
|
|
148
|
-
signal: controller.signal
|
|
149
|
-
});
|
|
150
|
-
} finally {
|
|
151
|
-
clearTimeout(timeoutId);
|
|
152
|
-
}
|
|
153
|
-
debug(`Response: ${response.status} ${response.statusText}`);
|
|
154
|
-
if (!response.ok) {
|
|
155
|
-
const errorText = await response.text().catch(() => "");
|
|
156
|
-
let errorMessage = errorText;
|
|
157
|
-
try {
|
|
158
|
-
const errorJson = JSON.parse(errorText);
|
|
159
|
-
errorMessage = errorJson.message || errorJson.error || errorText;
|
|
160
|
-
} catch {
|
|
161
|
-
}
|
|
162
|
-
switch (response.status) {
|
|
163
|
-
case 401:
|
|
164
|
-
throw new AuthenticationError(
|
|
165
|
-
errorMessage || "Authentication required"
|
|
166
|
-
);
|
|
167
|
-
case 403: {
|
|
168
|
-
let requiredTier = "pro";
|
|
169
|
-
try {
|
|
170
|
-
const parsed = JSON.parse(errorText);
|
|
171
|
-
requiredTier = parsed.requiredTier || requiredTier;
|
|
172
|
-
} catch {
|
|
173
|
-
}
|
|
174
|
-
throw new LicenseRequiredError(
|
|
175
|
-
requiredTier,
|
|
176
|
-
errorMessage || "License required"
|
|
177
|
-
);
|
|
178
|
-
}
|
|
179
|
-
case 404:
|
|
180
|
-
throw new NotFoundError(errorMessage || "Resource not found");
|
|
181
|
-
case 429: {
|
|
182
|
-
const retryAfter = parseInt(
|
|
183
|
-
response.headers.get("retry-after") ?? "60",
|
|
184
|
-
10
|
|
185
|
-
);
|
|
186
|
-
throw new RateLimitError(isNaN(retryAfter) ? 60 : retryAfter);
|
|
187
|
-
}
|
|
188
|
-
default:
|
|
189
|
-
if (isRetryable(response.status)) {
|
|
190
|
-
lastError = new ServerError(
|
|
191
|
-
errorMessage || `Server error: ${response.status}`
|
|
192
|
-
);
|
|
193
|
-
continue;
|
|
194
|
-
}
|
|
195
|
-
throw new ServerError(
|
|
196
|
-
errorMessage || `Server error: ${response.status}`
|
|
197
|
-
);
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
const contentType = response.headers.get("content-type") ?? "";
|
|
201
|
-
if (contentType.includes("application/json")) {
|
|
202
|
-
return await response.json();
|
|
203
|
-
}
|
|
204
|
-
return {};
|
|
205
|
-
} catch (error) {
|
|
206
|
-
if (error instanceof AuthenticationError || error instanceof LicenseRequiredError || error instanceof NotFoundError || error instanceof RateLimitError) {
|
|
207
|
-
throw error;
|
|
208
|
-
}
|
|
209
|
-
if (error instanceof TypeError || error instanceof Error && error.name === "AbortError") {
|
|
210
|
-
const networkError = new NetworkError(
|
|
211
|
-
error.name === "AbortError" ? "Request timed out after 30s" : `Network error: ${error.message}`
|
|
212
|
-
);
|
|
213
|
-
lastError = networkError;
|
|
214
|
-
if (attempt < MAX_RETRIES) continue;
|
|
215
|
-
throw networkError;
|
|
216
|
-
}
|
|
217
|
-
if (error instanceof ServerError) {
|
|
218
|
-
lastError = error;
|
|
219
|
-
if (attempt < MAX_RETRIES) continue;
|
|
220
|
-
throw error;
|
|
221
|
-
}
|
|
222
|
-
throw error;
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
throw lastError ?? new NetworkError("Request failed after retries");
|
|
226
|
-
}
|
|
227
|
-
// ──────────────────────────────────────────────────────────
|
|
228
|
-
// Auth endpoints (unauthenticated)
|
|
229
|
-
// ──────────────────────────────────────────────────────────
|
|
230
|
-
/**
|
|
231
|
-
* Step 1 of Device Code Flow: Request device code from marketplace.
|
|
232
|
-
*/
|
|
233
|
-
async requestDeviceCode() {
|
|
234
|
-
return this.request("POST", "/auth/device-code", {
|
|
235
|
-
body: { client_id: "kaven-cli" },
|
|
236
|
-
authenticated: false
|
|
237
|
-
});
|
|
238
|
-
}
|
|
239
|
-
/**
|
|
240
|
-
* Step 2 of Device Code Flow: Poll for access token.
|
|
241
|
-
*/
|
|
242
|
-
async pollDeviceToken(deviceCode) {
|
|
243
|
-
try {
|
|
244
|
-
const baseURL = await this.baseURLPromise;
|
|
245
|
-
const url = `${baseURL}/auth/token`;
|
|
246
|
-
const controller = new AbortController();
|
|
247
|
-
const timeoutId = setTimeout(
|
|
248
|
-
() => controller.abort(),
|
|
249
|
-
REQUEST_TIMEOUT_MS
|
|
250
|
-
);
|
|
251
|
-
let response;
|
|
252
|
-
try {
|
|
253
|
-
response = await fetch(url, {
|
|
254
|
-
method: "POST",
|
|
255
|
-
headers: { "Content-Type": "application/json" },
|
|
256
|
-
body: JSON.stringify({
|
|
257
|
-
device_code: deviceCode,
|
|
258
|
-
grant_type: "urn:ietf:params:oauth:grant-type:device_code"
|
|
259
|
-
}),
|
|
260
|
-
signal: controller.signal
|
|
261
|
-
});
|
|
262
|
-
} finally {
|
|
263
|
-
clearTimeout(timeoutId);
|
|
264
|
-
}
|
|
265
|
-
if (response.ok) {
|
|
266
|
-
const tokens = await response.json();
|
|
267
|
-
return { status: "success", tokens };
|
|
268
|
-
}
|
|
269
|
-
const errorData = await response.json().catch(() => ({}));
|
|
270
|
-
const errorCode = errorData.error ?? "unknown_error";
|
|
271
|
-
switch (errorCode) {
|
|
272
|
-
case "authorization_pending":
|
|
273
|
-
return { status: "authorization_pending" };
|
|
274
|
-
case "slow_down":
|
|
275
|
-
return { status: "slow_down" };
|
|
276
|
-
case "access_denied":
|
|
277
|
-
return { status: "access_denied" };
|
|
278
|
-
case "expired_token":
|
|
279
|
-
return { status: "expired_token" };
|
|
280
|
-
default:
|
|
281
|
-
throw new Error(`Unexpected error: ${errorCode}`);
|
|
282
|
-
}
|
|
283
|
-
} catch (error) {
|
|
284
|
-
const nodeError = error;
|
|
285
|
-
if (nodeError.code === "ECONNREFUSED" || nodeError.code === "ENOTFOUND") {
|
|
286
|
-
throw new NetworkError(
|
|
287
|
-
"Network error. Check your connection and try again."
|
|
288
|
-
);
|
|
289
|
-
}
|
|
290
|
-
throw error;
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
/**
|
|
294
|
-
* Refresh access token using refresh token.
|
|
295
|
-
*/
|
|
296
|
-
async refreshToken(refreshToken) {
|
|
297
|
-
return this.request("POST", "/auth/refresh", {
|
|
298
|
-
body: { refresh_token: refreshToken },
|
|
299
|
-
authenticated: false
|
|
300
|
-
});
|
|
301
|
-
}
|
|
302
|
-
// ──────────────────────────────────────────────────────────
|
|
303
|
-
// Module endpoints (authenticated)
|
|
304
|
-
// ──────────────────────────────────────────────────────────
|
|
305
|
-
/**
|
|
306
|
-
* List available modules with optional filters.
|
|
307
|
-
*/
|
|
308
|
-
async listModules(filters) {
|
|
309
|
-
const params = new URLSearchParams();
|
|
310
|
-
if (filters?.category) params.set("category", filters.category);
|
|
311
|
-
if (filters?.tier) params.set("tier", filters.tier);
|
|
312
|
-
if (filters?.q) params.set("q", filters.q);
|
|
313
|
-
if (filters?.page) params.set("page", String(filters.page));
|
|
314
|
-
if (filters?.pageSize) params.set("pageSize", String(filters.pageSize));
|
|
315
|
-
const query = params.toString();
|
|
316
|
-
const endpoint = `/modules${query ? `?${query}` : ""}`;
|
|
317
|
-
return this.request("GET", endpoint);
|
|
318
|
-
}
|
|
319
|
-
/**
|
|
320
|
-
* Get a single module by slug.
|
|
321
|
-
*/
|
|
322
|
-
async getModule(slug) {
|
|
323
|
-
return this.request("GET", `/modules/${slug}`);
|
|
324
|
-
}
|
|
325
|
-
/**
|
|
326
|
-
* Get a module's manifest for a specific version.
|
|
327
|
-
*/
|
|
328
|
-
async getManifest(slug, version) {
|
|
329
|
-
return this.request(
|
|
330
|
-
"GET",
|
|
331
|
-
`/modules/${slug}/versions/${version}/manifest`
|
|
332
|
-
);
|
|
333
|
-
}
|
|
334
|
-
/**
|
|
335
|
-
* Create a download token for a module release.
|
|
336
|
-
*/
|
|
337
|
-
async createDownloadToken(moduleSlug, version) {
|
|
338
|
-
return this.request("POST", "/download-tokens", {
|
|
339
|
-
body: { moduleSlug, version },
|
|
340
|
-
authenticated: true
|
|
341
|
-
});
|
|
342
|
-
}
|
|
343
|
-
// ──────────────────────────────────────────────────────────
|
|
344
|
-
// License endpoints
|
|
345
|
-
// ──────────────────────────────────────────────────────────
|
|
346
|
-
/**
|
|
347
|
-
* Validate a license key against the required tier.
|
|
348
|
-
*/
|
|
349
|
-
async validateLicense(licenseKey, requiredTier) {
|
|
350
|
-
const response = await this.request(
|
|
351
|
-
"POST",
|
|
352
|
-
"/licenses/validate",
|
|
353
|
-
{
|
|
354
|
-
body: { licenseKey, requiredTier }
|
|
355
|
-
}
|
|
356
|
-
);
|
|
357
|
-
return response;
|
|
358
|
-
}
|
|
359
|
-
/**
|
|
360
|
-
* Get full license status including expiry information.
|
|
361
|
-
*/
|
|
362
|
-
async getLicenseStatus(licenseKey) {
|
|
363
|
-
return this.request("GET", `/licenses/status?key=${encodeURIComponent(licenseKey)}`);
|
|
364
|
-
}
|
|
365
|
-
// ──────────────────────────────────────────────────────────
|
|
366
|
-
// Legacy / backward-compat methods
|
|
367
|
-
// ──────────────────────────────────────────────────────────
|
|
368
|
-
/**
|
|
369
|
-
* @deprecated Use getManifest(slug, version) instead.
|
|
370
|
-
*/
|
|
371
|
-
async getModuleManifest(moduleId) {
|
|
372
|
-
try {
|
|
373
|
-
return await this.getManifest(moduleId, "latest");
|
|
374
|
-
} catch (error) {
|
|
375
|
-
if (error instanceof NotFoundError) return null;
|
|
376
|
-
throw error;
|
|
377
|
-
}
|
|
378
|
-
}
|
|
379
|
-
/**
|
|
380
|
-
* Get release details for a specific module version.
|
|
381
|
-
* Returns checksum, signature, and publicKey for verification.
|
|
382
|
-
*/
|
|
383
|
-
async getReleaseInfo(slug, version) {
|
|
384
|
-
return this.request(
|
|
385
|
-
"GET",
|
|
386
|
-
`/modules/${slug}/versions/${version}`
|
|
387
|
-
);
|
|
388
|
-
}
|
|
389
|
-
// ──────────────────────────────────────────────────────────
|
|
390
|
-
// Publish endpoints (authenticated)
|
|
391
|
-
// ──────────────────────────────────────────────────────────
|
|
392
|
-
/**
|
|
393
|
-
* Get a presigned S3 upload URL for a new module release.
|
|
394
|
-
*/
|
|
395
|
-
async getUploadUrl(moduleSlug, version, size) {
|
|
396
|
-
return this.request("POST", "/releases/upload-url", {
|
|
397
|
-
body: { moduleSlug, version, size },
|
|
398
|
-
authenticated: true
|
|
399
|
-
});
|
|
400
|
-
}
|
|
401
|
-
/**
|
|
402
|
-
* Create a release record after uploading the artifact.
|
|
403
|
-
*/
|
|
404
|
-
async createRelease(data) {
|
|
405
|
-
return this.request("POST", "/releases", {
|
|
406
|
-
body: data,
|
|
407
|
-
authenticated: true
|
|
408
|
-
});
|
|
409
|
-
}
|
|
410
|
-
// ──────────────────────────────────────────────────────────
|
|
411
|
-
// Checkout / upgrade endpoints (authenticated)
|
|
412
|
-
// ──────────────────────────────────────────────────────────
|
|
413
|
-
/**
|
|
414
|
-
* Create a Paddle checkout session for tier upgrade.
|
|
415
|
-
*/
|
|
416
|
-
async createCheckoutSession(tier, licenseKey) {
|
|
417
|
-
return this.request("POST", "/checkout/session", {
|
|
418
|
-
body: { tier, licenseKey },
|
|
419
|
-
authenticated: true
|
|
420
|
-
});
|
|
421
|
-
}
|
|
422
|
-
/**
|
|
423
|
-
* Poll the status of an ongoing Paddle checkout session.
|
|
424
|
-
*/
|
|
425
|
-
async getCheckoutStatus(sessionId) {
|
|
426
|
-
return this.request(
|
|
427
|
-
"GET",
|
|
428
|
-
`/checkout/session/${sessionId}/status`,
|
|
429
|
-
{ authenticated: true }
|
|
430
|
-
);
|
|
431
|
-
}
|
|
432
|
-
// ──────────────────────────────────────────────────────────
|
|
433
|
-
// Categories endpoint (authenticated)
|
|
434
|
-
// ──────────────────────────────────────────────────────────
|
|
435
|
-
/**
|
|
436
|
-
* Get all available module categories.
|
|
437
|
-
*/
|
|
438
|
-
async getCategories() {
|
|
439
|
-
const result = await this.request(
|
|
440
|
-
"GET",
|
|
441
|
-
"/modules/categories",
|
|
442
|
-
{ authenticated: true }
|
|
443
|
-
);
|
|
444
|
-
return result.categories;
|
|
445
|
-
}
|
|
446
|
-
};
|
|
447
|
-
|
|
448
|
-
export {
|
|
449
|
-
AuthenticationError,
|
|
450
|
-
LicenseRequiredError,
|
|
451
|
-
NotFoundError,
|
|
452
|
-
NetworkError,
|
|
453
|
-
SignatureVerificationError,
|
|
454
|
-
MarketplaceClient
|
|
455
|
-
};
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.registerAioxCommand = registerAioxCommand;
|
|
4
|
-
const aiox_bootstrap_1 = require("../init/aiox-bootstrap");
|
|
5
|
-
/**
|
|
6
|
-
* Registers the AIOX integration commands
|
|
7
|
-
*/
|
|
8
|
-
function registerAioxCommand(program) {
|
|
9
|
-
const aiox = program
|
|
10
|
-
.command("aiox")
|
|
11
|
-
.description("AIOX integration utilities");
|
|
12
|
-
aiox
|
|
13
|
-
.command("bootstrap")
|
|
14
|
-
.description("Run AIOX environment bootstrap in current project")
|
|
15
|
-
.option("--skip-aiox", "Skip AIOX logic (for testing)")
|
|
16
|
-
.action(async (options) => {
|
|
17
|
-
const projectDir = process.cwd();
|
|
18
|
-
await (0, aiox_bootstrap_1.runEnvironmentBootstrap)(projectDir, options);
|
|
19
|
-
});
|
|
20
|
-
}
|
|
@@ -1,122 +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.authLogin = authLogin;
|
|
7
|
-
const chalk_1 = __importDefault(require("chalk"));
|
|
8
|
-
const ora_1 = __importDefault(require("ora"));
|
|
9
|
-
const open_1 = __importDefault(require("open"));
|
|
10
|
-
const AuthService_1 = require("../../core/AuthService");
|
|
11
|
-
const MarketplaceClient_1 = require("../../infrastructure/MarketplaceClient");
|
|
12
|
-
const TelemetryBuffer_1 = require("../../infrastructure/TelemetryBuffer");
|
|
13
|
-
/**
|
|
14
|
-
* Sleep helper for polling delays
|
|
15
|
-
*/
|
|
16
|
-
function sleep(ms) {
|
|
17
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
18
|
-
}
|
|
19
|
-
/**
|
|
20
|
-
* Poll for access token with exponential backoff
|
|
21
|
-
*/
|
|
22
|
-
async function pollForToken(client, deviceCode, expiresIn, initialInterval, spinner) {
|
|
23
|
-
const deadline = Date.now() + expiresIn * 1000;
|
|
24
|
-
const backoffIntervals = [5, 10, 15, 20]; // seconds - exponential backoff
|
|
25
|
-
let backoffIndex = 0;
|
|
26
|
-
let interval = initialInterval;
|
|
27
|
-
while (Date.now() < deadline) {
|
|
28
|
-
// Update countdown spinner
|
|
29
|
-
const remaining = Math.ceil((deadline - Date.now()) / 1000);
|
|
30
|
-
const mm = Math.floor(remaining / 60);
|
|
31
|
-
const ss = String(remaining % 60).padStart(2, '0');
|
|
32
|
-
spinner.text = `Waiting for authorization... (expires in ${mm}:${ss})`;
|
|
33
|
-
// Wait for next poll
|
|
34
|
-
await sleep(interval * 1000);
|
|
35
|
-
try {
|
|
36
|
-
const result = await client.pollDeviceToken(deviceCode);
|
|
37
|
-
// Success - return tokens
|
|
38
|
-
if (result.status === 'success' && result.tokens) {
|
|
39
|
-
return result.tokens;
|
|
40
|
-
}
|
|
41
|
-
// Handle different status codes
|
|
42
|
-
switch (result.status) {
|
|
43
|
-
case 'slow_down':
|
|
44
|
-
// Increase interval by 5s as requested by server
|
|
45
|
-
interval += 5;
|
|
46
|
-
break;
|
|
47
|
-
case 'access_denied':
|
|
48
|
-
throw new Error('Authorization denied by user. Try again with \'kaven auth login\'.');
|
|
49
|
-
case 'expired_token':
|
|
50
|
-
throw new Error('Device code expired. Run \'kaven auth login\' again.');
|
|
51
|
-
case 'authorization_pending':
|
|
52
|
-
// Continue polling - apply exponential backoff
|
|
53
|
-
if (backoffIndex < backoffIntervals.length - 1) {
|
|
54
|
-
backoffIndex++;
|
|
55
|
-
interval = backoffIntervals[backoffIndex];
|
|
56
|
-
}
|
|
57
|
-
break;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
catch (error) {
|
|
61
|
-
// Re-throw our custom errors
|
|
62
|
-
if (error.message.includes('denied') ||
|
|
63
|
-
error.message.includes('expired')) {
|
|
64
|
-
throw error;
|
|
65
|
-
}
|
|
66
|
-
// Network errors
|
|
67
|
-
const nodeError = error;
|
|
68
|
-
if (nodeError.code === 'ECONNREFUSED' || nodeError.code === 'ENOTFOUND') {
|
|
69
|
-
throw new Error('Network error. Check your connection and try again.');
|
|
70
|
-
}
|
|
71
|
-
// Unknown error
|
|
72
|
-
throw error;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
// Timeout - device code expired
|
|
76
|
-
throw new Error('Device code expired. Run \'kaven auth login\' again.');
|
|
77
|
-
}
|
|
78
|
-
/**
|
|
79
|
-
* Main login command - OAuth 2.0 Device Authorization Grant (RFC 8628)
|
|
80
|
-
*/
|
|
81
|
-
async function authLogin() {
|
|
82
|
-
const telemetry = TelemetryBuffer_1.TelemetryBuffer.getInstance();
|
|
83
|
-
const startTime = Date.now();
|
|
84
|
-
telemetry.capture("cli.auth.login.start");
|
|
85
|
-
const client = new MarketplaceClient_1.MarketplaceClient();
|
|
86
|
-
const authService = new AuthService_1.AuthService();
|
|
87
|
-
console.log(chalk_1.default.blue("🔐 Starting authentication flow...\n"));
|
|
88
|
-
const spinner = (0, ora_1.default)("Requesting device code from marketplace...").start();
|
|
89
|
-
try {
|
|
90
|
-
// Step 1: Request device code
|
|
91
|
-
const { device_code, user_code, verification_uri, expires_in, interval } = await client.requestDeviceCode();
|
|
92
|
-
spinner.stop();
|
|
93
|
-
// Step 2: Display code and open browser
|
|
94
|
-
console.log(chalk_1.default.yellow("To complete login, follow these steps:\n"));
|
|
95
|
-
console.log(chalk_1.default.bold(` Your verification code: ${chalk_1.default.cyan(user_code)}\n`));
|
|
96
|
-
try {
|
|
97
|
-
await (0, open_1.default)(verification_uri);
|
|
98
|
-
console.log(chalk_1.default.dim(" ✓ Browser opened automatically"));
|
|
99
|
-
}
|
|
100
|
-
catch {
|
|
101
|
-
console.log(chalk_1.default.yellow(` Open this URL in your browser:`));
|
|
102
|
-
console.log(chalk_1.default.underline(` ${verification_uri}\n`));
|
|
103
|
-
}
|
|
104
|
-
// Step 3: Poll for token with exponential backoff
|
|
105
|
-
const pollSpinner = (0, ora_1.default)('Waiting for authorization...').start();
|
|
106
|
-
const tokens = await pollForToken(client, device_code, expires_in, interval, pollSpinner);
|
|
107
|
-
// Step 4: Store tokens securely
|
|
108
|
-
await authService.saveTokens(tokens);
|
|
109
|
-
pollSpinner.succeed(chalk_1.default.green(`Logged in as ${chalk_1.default.bold(tokens.user.email)}`));
|
|
110
|
-
console.log(chalk_1.default.dim(` Tier: ${tokens.user.tier}`));
|
|
111
|
-
console.log(chalk_1.default.gray("\n Your credentials were saved securely in ~/.kaven/auth.json\n"));
|
|
112
|
-
telemetry.capture("cli.auth.login.success", { tier: tokens.user.tier }, Date.now() - startTime);
|
|
113
|
-
await telemetry.flush();
|
|
114
|
-
}
|
|
115
|
-
catch (error) {
|
|
116
|
-
telemetry.capture("cli.auth.login.error", { error: error.message }, Date.now() - startTime);
|
|
117
|
-
await telemetry.flush();
|
|
118
|
-
spinner.fail(chalk_1.default.red("Authentication failed"));
|
|
119
|
-
console.error(chalk_1.default.red(`\n Error: ${error.message}\n`));
|
|
120
|
-
process.exit(1);
|
|
121
|
-
}
|
|
122
|
-
}
|
|
@@ -1,23 +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.authLogout = authLogout;
|
|
7
|
-
const chalk_1 = __importDefault(require("chalk"));
|
|
8
|
-
const AuthService_1 = require("../../core/AuthService");
|
|
9
|
-
async function authLogout() {
|
|
10
|
-
const authService = new AuthService_1.AuthService();
|
|
11
|
-
try {
|
|
12
|
-
if (!(await authService.isAuthenticated())) {
|
|
13
|
-
console.log(chalk_1.default.yellow("You are not authenticated."));
|
|
14
|
-
return;
|
|
15
|
-
}
|
|
16
|
-
await authService.logout();
|
|
17
|
-
console.log(chalk_1.default.green("Logged out successfully."));
|
|
18
|
-
}
|
|
19
|
-
catch {
|
|
20
|
-
console.error(chalk_1.default.red("Error during logout."));
|
|
21
|
-
process.exit(1);
|
|
22
|
-
}
|
|
23
|
-
}
|
|
@@ -1,36 +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.authWhoami = authWhoami;
|
|
7
|
-
const chalk_1 = __importDefault(require("chalk"));
|
|
8
|
-
const AuthService_1 = require("../../core/AuthService");
|
|
9
|
-
const TelemetryBuffer_1 = require("../../infrastructure/TelemetryBuffer");
|
|
10
|
-
async function authWhoami() {
|
|
11
|
-
const telemetry = TelemetryBuffer_1.TelemetryBuffer.getInstance();
|
|
12
|
-
telemetry.capture("cli.auth.whoami.start");
|
|
13
|
-
const authService = new AuthService_1.AuthService();
|
|
14
|
-
try {
|
|
15
|
-
const info = await authService.getWhoamiInfo();
|
|
16
|
-
if (!info) {
|
|
17
|
-
console.log(chalk_1.default.yellow("You are not authenticated."));
|
|
18
|
-
console.log(chalk_1.default.gray("Use 'kaven auth login' to sign in."));
|
|
19
|
-
telemetry.capture("cli.auth.whoami.not_authenticated");
|
|
20
|
-
await telemetry.flush();
|
|
21
|
-
return;
|
|
22
|
-
}
|
|
23
|
-
telemetry.capture("cli.auth.whoami.authenticated");
|
|
24
|
-
console.log();
|
|
25
|
-
console.log(` ${chalk_1.default.bold("Email:")} ${info.email}`);
|
|
26
|
-
console.log(` ${chalk_1.default.bold("GitHub:")} ${info.githubId}`);
|
|
27
|
-
console.log(` ${chalk_1.default.bold("Tier:")} ${info.tier}`);
|
|
28
|
-
console.log(` ${chalk_1.default.bold("Session:")} ${info.sessionExpiry}`);
|
|
29
|
-
console.log();
|
|
30
|
-
}
|
|
31
|
-
catch {
|
|
32
|
-
console.error(chalk_1.default.red("Error checking authentication status."));
|
|
33
|
-
process.exit(1);
|
|
34
|
-
}
|
|
35
|
-
await telemetry.flush();
|
|
36
|
-
}
|