@oxlayer/cli 0.0.1
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 +152 -0
- package/dist/api.service-CDPTVMJM.js +17 -0
- package/dist/api.service-CDPTVMJM.js.map +1 -0
- package/dist/chunk-DOYXC6AO.js +93 -0
- package/dist/chunk-DOYXC6AO.js.map +1 -0
- package/dist/chunk-HOFSFUN5.js +108 -0
- package/dist/chunk-HOFSFUN5.js.map +1 -0
- package/dist/chunk-HQST7GVM.js +26 -0
- package/dist/chunk-HQST7GVM.js.map +1 -0
- package/dist/chunk-M3AAB53U.js +105 -0
- package/dist/chunk-M3AAB53U.js.map +1 -0
- package/dist/chunk-QERPYPW4.js +284 -0
- package/dist/chunk-QERPYPW4.js.map +1 -0
- package/dist/cli-VUBGPXL3.js +30 -0
- package/dist/cli-VUBGPXL3.js.map +1 -0
- package/dist/cli.js +1328 -0
- package/dist/cli.js.map +1 -0
- package/dist/device-auth.service-CMNCNKYX.js +42 -0
- package/dist/device-auth.service-CMNCNKYX.js.map +1 -0
- package/dist/package.service-XK5PPZVF.js +24 -0
- package/dist/package.service-XK5PPZVF.js.map +1 -0
- package/package.json +43 -0
package/dist/cli.js
ADDED
|
@@ -0,0 +1,1328 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
createSpinner,
|
|
4
|
+
error,
|
|
5
|
+
formatDuration,
|
|
6
|
+
getBanner,
|
|
7
|
+
header,
|
|
8
|
+
info,
|
|
9
|
+
printCapabilities,
|
|
10
|
+
printList,
|
|
11
|
+
success,
|
|
12
|
+
warning as warning2
|
|
13
|
+
} from "./chunk-HOFSFUN5.js";
|
|
14
|
+
import {
|
|
15
|
+
getInstalledVersion,
|
|
16
|
+
getVendorDir,
|
|
17
|
+
hasPackageJson,
|
|
18
|
+
readPackageJson
|
|
19
|
+
} from "./chunk-M3AAB53U.js";
|
|
20
|
+
import {
|
|
21
|
+
healthCheck,
|
|
22
|
+
requestPackageDownload,
|
|
23
|
+
resolveCapabilities
|
|
24
|
+
} from "./chunk-DOYXC6AO.js";
|
|
25
|
+
import {
|
|
26
|
+
getAuthInfo,
|
|
27
|
+
getDeviceName,
|
|
28
|
+
getManifest,
|
|
29
|
+
init_device_auth_service,
|
|
30
|
+
initiateDeviceAuth,
|
|
31
|
+
isTokenExpired,
|
|
32
|
+
loadConfig,
|
|
33
|
+
openBrowser,
|
|
34
|
+
pollForToken,
|
|
35
|
+
saveConfig
|
|
36
|
+
} from "./chunk-QERPYPW4.js";
|
|
37
|
+
import {
|
|
38
|
+
__require,
|
|
39
|
+
init_esm_shims
|
|
40
|
+
} from "./chunk-HQST7GVM.js";
|
|
41
|
+
|
|
42
|
+
// src/cli.ts
|
|
43
|
+
init_esm_shims();
|
|
44
|
+
import { Command } from "commander";
|
|
45
|
+
|
|
46
|
+
// src/commands/login.command.ts
|
|
47
|
+
init_esm_shims();
|
|
48
|
+
init_device_auth_service();
|
|
49
|
+
async function login(options = {}) {
|
|
50
|
+
header("OxLayer Authentication");
|
|
51
|
+
const deviceName = await getDeviceName();
|
|
52
|
+
info(`Device: ${deviceName}`);
|
|
53
|
+
info(`Environment: ${options.environment || "development"}`);
|
|
54
|
+
info(`API Endpoint: ${options.apiEndpoint || "http://localhost:3001"}`);
|
|
55
|
+
console.log();
|
|
56
|
+
const spinner = createSpinner("Initiating device authorization...");
|
|
57
|
+
spinner.start();
|
|
58
|
+
let deviceCodeResponse;
|
|
59
|
+
try {
|
|
60
|
+
const apiEndpoint = options.apiEndpoint || "http://localhost:3001";
|
|
61
|
+
info(`API Endpoint: ${apiEndpoint}`);
|
|
62
|
+
deviceCodeResponse = await initiateDeviceAuth(
|
|
63
|
+
options.environment || "development",
|
|
64
|
+
apiEndpoint
|
|
65
|
+
);
|
|
66
|
+
spinner.succeed("Device authorization initiated");
|
|
67
|
+
} catch (err) {
|
|
68
|
+
spinner.fail("Failed to initiate device authorization");
|
|
69
|
+
error(err instanceof Error ? err.message : "Unknown error");
|
|
70
|
+
process.exit(1);
|
|
71
|
+
}
|
|
72
|
+
console.log();
|
|
73
|
+
info("To complete authentication, follow these steps:");
|
|
74
|
+
console.log();
|
|
75
|
+
const verificationUrl = deviceCodeResponse.verificationUrl;
|
|
76
|
+
const userCode = deviceCodeResponse.userCode;
|
|
77
|
+
console.log(` 1. Visit this URL in your browser:`);
|
|
78
|
+
console.log(` ${verificationUrl}`);
|
|
79
|
+
console.log();
|
|
80
|
+
console.log(` 2. Enter this code when prompted:`);
|
|
81
|
+
console.log(` ${userCode}`);
|
|
82
|
+
console.log();
|
|
83
|
+
if (!options["no-browser"]) {
|
|
84
|
+
try {
|
|
85
|
+
const urlWithCode = new URL(verificationUrl);
|
|
86
|
+
urlWithCode.searchParams.set("device_code", deviceCodeResponse.deviceCode);
|
|
87
|
+
const openSpinner = createSpinner("Opening browser...");
|
|
88
|
+
openSpinner.start();
|
|
89
|
+
await openBrowser(urlWithCode.toString());
|
|
90
|
+
openSpinner.succeed("Browser opened");
|
|
91
|
+
} catch (err) {
|
|
92
|
+
info("Could not open browser automatically. Please visit the URL manually.");
|
|
93
|
+
}
|
|
94
|
+
} else {
|
|
95
|
+
info("Browser auto-open disabled (--no-browser flag set)");
|
|
96
|
+
}
|
|
97
|
+
console.log();
|
|
98
|
+
info("Waiting for authentication to complete...");
|
|
99
|
+
const pollSpinner = createSpinner("Waiting for approval");
|
|
100
|
+
try {
|
|
101
|
+
pollSpinner.start();
|
|
102
|
+
const result = await pollForToken(
|
|
103
|
+
deviceCodeResponse.pollEndpoint,
|
|
104
|
+
deviceCodeResponse.deviceCode,
|
|
105
|
+
{
|
|
106
|
+
interval: options["poll-interval"] || deviceCodeResponse.interval,
|
|
107
|
+
maxAttempts: 120,
|
|
108
|
+
// 2 minutes
|
|
109
|
+
onProgress: (attempt, maxAttempts) => {
|
|
110
|
+
if (attempt % 8 === 0) {
|
|
111
|
+
pollSpinner.text = `Waiting for approval (${Math.floor(attempt / maxAttempts * 100)}%)`;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
);
|
|
116
|
+
pollSpinner.succeed("Authentication successful");
|
|
117
|
+
const apiEndpoint = options.apiEndpoint || "http://localhost:3001";
|
|
118
|
+
const config = {
|
|
119
|
+
token: result.accessToken,
|
|
120
|
+
tokenInfo: result.tokenInfo,
|
|
121
|
+
organizationId: result.organizationId,
|
|
122
|
+
environment: options.environment || "development",
|
|
123
|
+
vendorDir: ".capabilities-vendor",
|
|
124
|
+
apiEndpoint,
|
|
125
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
126
|
+
};
|
|
127
|
+
await saveConfig(config);
|
|
128
|
+
pollSpinner.stop();
|
|
129
|
+
console.log();
|
|
130
|
+
success("Logged in successfully");
|
|
131
|
+
info(`Organization: ${result.organizationId}`);
|
|
132
|
+
info(`Device ID: ${result.tokenInfo.deviceId}`);
|
|
133
|
+
info(`Scopes: ${result.tokenInfo.scopes.join(", ")}`);
|
|
134
|
+
info(`Expires: ${new Date(result.tokenInfo.expiresAt).toLocaleString()}`);
|
|
135
|
+
process.exit(0);
|
|
136
|
+
} catch (err) {
|
|
137
|
+
pollSpinner.fail("Authentication failed");
|
|
138
|
+
error(err instanceof Error ? err.message : "Unknown error");
|
|
139
|
+
process.exit(1);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// src/commands/status.command.ts
|
|
144
|
+
init_esm_shims();
|
|
145
|
+
init_device_auth_service();
|
|
146
|
+
|
|
147
|
+
// src/utils/env.ts
|
|
148
|
+
init_esm_shims();
|
|
149
|
+
import { existsSync, readFileSync } from "fs";
|
|
150
|
+
import { join } from "path";
|
|
151
|
+
function detectPackageManager(cwd = process.cwd()) {
|
|
152
|
+
if (existsSync(join(cwd, "pnpm-lock.yaml"))) {
|
|
153
|
+
return "pnpm";
|
|
154
|
+
}
|
|
155
|
+
if (existsSync(join(cwd, "bun.lockb"))) {
|
|
156
|
+
return "bun";
|
|
157
|
+
}
|
|
158
|
+
if (existsSync(join(cwd, "yarn.lock"))) {
|
|
159
|
+
return "yarn";
|
|
160
|
+
}
|
|
161
|
+
if (existsSync(join(cwd, "package-lock.json"))) {
|
|
162
|
+
return "npm";
|
|
163
|
+
}
|
|
164
|
+
return "unknown";
|
|
165
|
+
}
|
|
166
|
+
function findProjectRoot(startDir = process.cwd()) {
|
|
167
|
+
let currentDir = startDir;
|
|
168
|
+
while (currentDir !== "/" && currentDir !== ".") {
|
|
169
|
+
if (existsSync(join(currentDir, "package.json"))) {
|
|
170
|
+
if (existsSync(join(currentDir, "pnpm-workspace.yaml")) || existsSync(join(currentDir, "turbo.json")) || existsSync(join(currentDir, "lerna.json")) || existsSync(join(currentDir, "nx.json"))) {
|
|
171
|
+
return currentDir;
|
|
172
|
+
}
|
|
173
|
+
try {
|
|
174
|
+
const pkgPath = join(currentDir, "package.json");
|
|
175
|
+
const pkgContent = readFileSync(pkgPath, "utf-8");
|
|
176
|
+
const pkg = JSON.parse(pkgContent);
|
|
177
|
+
if (pkg.workspaces) {
|
|
178
|
+
return currentDir;
|
|
179
|
+
}
|
|
180
|
+
} catch {
|
|
181
|
+
}
|
|
182
|
+
if (currentDir === startDir) {
|
|
183
|
+
return currentDir;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
const parentDir = join(currentDir, "..");
|
|
187
|
+
if (parentDir === currentDir) {
|
|
188
|
+
break;
|
|
189
|
+
}
|
|
190
|
+
currentDir = parentDir;
|
|
191
|
+
}
|
|
192
|
+
return startDir;
|
|
193
|
+
}
|
|
194
|
+
async function detectProjectType(cwd = process.cwd()) {
|
|
195
|
+
const rootDir = findProjectRoot(cwd);
|
|
196
|
+
const hasPackageJson2 = existsSync(join(rootDir, "package.json"));
|
|
197
|
+
const hasTsConfig = existsSync(join(rootDir, "tsconfig.json")) || existsSync(join(rootDir, "tsconfig.json"));
|
|
198
|
+
const packageManager = detectPackageManager(rootDir);
|
|
199
|
+
let type = "unknown";
|
|
200
|
+
if (hasPackageJson2) {
|
|
201
|
+
try {
|
|
202
|
+
const pkg = await readPackageJson(rootDir);
|
|
203
|
+
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
204
|
+
const hasReact = "react" in deps || "react-dom" in deps || "@types/react" in deps || "next" in deps;
|
|
205
|
+
const hasHono = "hono" in deps || "@hono/hono" in deps;
|
|
206
|
+
const isFrontend = hasReact;
|
|
207
|
+
const isBackend = hasHono;
|
|
208
|
+
if (isFrontend && isBackend) {
|
|
209
|
+
type = "unknown";
|
|
210
|
+
} else if (isFrontend) {
|
|
211
|
+
type = "frontend";
|
|
212
|
+
} else if (isBackend) {
|
|
213
|
+
type = "backend";
|
|
214
|
+
}
|
|
215
|
+
} catch {
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
return {
|
|
219
|
+
type,
|
|
220
|
+
hasPackageJson: hasPackageJson2,
|
|
221
|
+
hasTsConfig,
|
|
222
|
+
packageManager,
|
|
223
|
+
rootDir
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
function getInstallCommand(packageManager) {
|
|
227
|
+
switch (packageManager) {
|
|
228
|
+
case "pnpm":
|
|
229
|
+
return "pnpm install";
|
|
230
|
+
case "bun":
|
|
231
|
+
return "bun install";
|
|
232
|
+
case "yarn":
|
|
233
|
+
return "yarn install";
|
|
234
|
+
case "npm":
|
|
235
|
+
return "npm install";
|
|
236
|
+
default:
|
|
237
|
+
return "pnpm install";
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
function getRecommendedPackages(projectType) {
|
|
241
|
+
switch (projectType) {
|
|
242
|
+
case "backend":
|
|
243
|
+
return ["backend-sdk"];
|
|
244
|
+
case "frontend":
|
|
245
|
+
return ["frontend-sdk"];
|
|
246
|
+
default:
|
|
247
|
+
return ["backend-sdk", "frontend-sdk", "cli-tools"];
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// src/commands/status.command.ts
|
|
252
|
+
async function status(options = {}) {
|
|
253
|
+
header("OxLayer SDK Status");
|
|
254
|
+
const authInfo = await getAuthInfo();
|
|
255
|
+
if (authInfo.authenticated) {
|
|
256
|
+
success("Authenticated");
|
|
257
|
+
info(`Organization: ${authInfo.organizationId || "Unknown"}`);
|
|
258
|
+
info(`Device: ${authInfo.deviceId || "Unknown"}`);
|
|
259
|
+
if (options.verbose && authInfo.scopes) {
|
|
260
|
+
info(`Scopes: ${authInfo.scopes.join(", ")}`);
|
|
261
|
+
}
|
|
262
|
+
if (options.verbose && authInfo.expiresAt) {
|
|
263
|
+
const expires = new Date(authInfo.expiresAt);
|
|
264
|
+
const now = /* @__PURE__ */ new Date();
|
|
265
|
+
const daysUntilExpiry = Math.ceil((expires.getTime() - now.getTime()) / (1e3 * 60 * 60 * 24));
|
|
266
|
+
info(`Expires: ${expires.toLocaleString()} (${daysUntilExpiry > 0 ? `in ${daysUntilExpiry} days` : "expired"})`);
|
|
267
|
+
}
|
|
268
|
+
} else {
|
|
269
|
+
error("Not authenticated");
|
|
270
|
+
info('Run "oxlayer login" to authenticate');
|
|
271
|
+
}
|
|
272
|
+
console.log();
|
|
273
|
+
if (authInfo.authenticated) {
|
|
274
|
+
header("Capabilities");
|
|
275
|
+
const manifest = await getManifest();
|
|
276
|
+
if (manifest) {
|
|
277
|
+
success(`Capability manifest loaded`);
|
|
278
|
+
info(`Schema Version: ${manifest.schemaVersion}`);
|
|
279
|
+
info(`License: ${manifest.licenseId}`);
|
|
280
|
+
info(`Environment: ${manifest.environment}`);
|
|
281
|
+
if (manifest.capabilities) {
|
|
282
|
+
const capabilityCount = Object.keys(manifest.capabilities).length;
|
|
283
|
+
info(`Available Capabilities: ${capabilityCount}`);
|
|
284
|
+
if (options.verbose) {
|
|
285
|
+
const capabilityNames = Object.keys(manifest.capabilities);
|
|
286
|
+
if (capabilityNames.length > 0) {
|
|
287
|
+
info("Capabilities:");
|
|
288
|
+
printList(capabilityNames);
|
|
289
|
+
}
|
|
290
|
+
const manifestExpires = new Date(manifest.expiresAt);
|
|
291
|
+
const now = /* @__PURE__ */ new Date();
|
|
292
|
+
const daysUntilExpiry = Math.ceil((manifestExpires.getTime() - now.getTime()) / (1e3 * 60 * 60 * 24));
|
|
293
|
+
info(`Manifest Expires: ${manifestExpires.toLocaleString()} (${daysUntilExpiry > 0 ? `in ${daysUntilExpiry} days` : "expired"})`);
|
|
294
|
+
}
|
|
295
|
+
} else {
|
|
296
|
+
info("No capabilities available in manifest");
|
|
297
|
+
}
|
|
298
|
+
} else {
|
|
299
|
+
info("No capability manifest available");
|
|
300
|
+
info('Run "oxlayer install" to fetch the latest capabilities');
|
|
301
|
+
}
|
|
302
|
+
console.log();
|
|
303
|
+
}
|
|
304
|
+
header("Project");
|
|
305
|
+
const projectConfig = await detectProjectType();
|
|
306
|
+
const recommendedPackages = getRecommendedPackages(projectConfig.type);
|
|
307
|
+
if (projectConfig.hasPackageJson) {
|
|
308
|
+
success("package.json found");
|
|
309
|
+
info(`Project type: ${projectConfig.type}`);
|
|
310
|
+
info(`Package manager: ${projectConfig.packageManager}`);
|
|
311
|
+
info(`TypeScript: ${projectConfig.hasTsConfig ? "Yes" : "No"}`);
|
|
312
|
+
} else {
|
|
313
|
+
error("No package.json found in current directory");
|
|
314
|
+
}
|
|
315
|
+
console.log();
|
|
316
|
+
header("Installation");
|
|
317
|
+
const installedVersion = await getInstalledVersion();
|
|
318
|
+
if (installedVersion) {
|
|
319
|
+
success(`SDK version ${installedVersion} installed`);
|
|
320
|
+
info(`Location: .capabilities-vendor/${installedVersion}/`);
|
|
321
|
+
if (options.verbose) {
|
|
322
|
+
const { existsSync: existsSync4 } = await import("fs");
|
|
323
|
+
const { join: join6 } = await import("path");
|
|
324
|
+
const vendorDir = join6(process.cwd(), ".capabilities-vendor", installedVersion);
|
|
325
|
+
if (existsSync4(vendorDir)) {
|
|
326
|
+
const { readdir } = await import("fs/promises");
|
|
327
|
+
const packages = await readdir(vendorDir, { withFileTypes: true });
|
|
328
|
+
const packageNames = packages.filter((p) => p.isDirectory()).map((p) => p.name);
|
|
329
|
+
if (packageNames.length > 0) {
|
|
330
|
+
info("Installed packages:");
|
|
331
|
+
printList(packageNames);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
} else {
|
|
336
|
+
info("No SDK installed");
|
|
337
|
+
info('Run "oxlayer install" to install the SDK');
|
|
338
|
+
}
|
|
339
|
+
console.log();
|
|
340
|
+
if (recommendedPackages.length > 0 && !installedVersion) {
|
|
341
|
+
header("Recommended");
|
|
342
|
+
info("For this project, OxLayer recommends installing:");
|
|
343
|
+
printList(recommendedPackages);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
// src/commands/install.command.ts
|
|
348
|
+
init_esm_shims();
|
|
349
|
+
import { promises as fs3 } from "fs";
|
|
350
|
+
import { join as join4 } from "path";
|
|
351
|
+
import { execSync } from "child_process";
|
|
352
|
+
|
|
353
|
+
// src/services/index.ts
|
|
354
|
+
init_esm_shims();
|
|
355
|
+
|
|
356
|
+
// src/services/auth.service.ts
|
|
357
|
+
init_esm_shims();
|
|
358
|
+
init_device_auth_service();
|
|
359
|
+
async function loadConfig2() {
|
|
360
|
+
const { loadConfig: loadNewConfig } = await import("./device-auth.service-CMNCNKYX.js");
|
|
361
|
+
const config = await loadNewConfig();
|
|
362
|
+
if (!config) {
|
|
363
|
+
return null;
|
|
364
|
+
}
|
|
365
|
+
return {
|
|
366
|
+
apiKey: config.token,
|
|
367
|
+
// Map token to apiKey for legacy consumers
|
|
368
|
+
environment: config.environment,
|
|
369
|
+
vendorDir: config.vendorDir,
|
|
370
|
+
apiEndpoint: config.apiEndpoint
|
|
371
|
+
};
|
|
372
|
+
}
|
|
373
|
+
async function removeConfig() {
|
|
374
|
+
const { removeConfig: removeNewConfig } = await import("./device-auth.service-CMNCNKYX.js");
|
|
375
|
+
await removeNewConfig();
|
|
376
|
+
}
|
|
377
|
+
function getConfigDir() {
|
|
378
|
+
const { join: join6 } = __require("path");
|
|
379
|
+
const { homedir } = __require("os");
|
|
380
|
+
return join6(homedir(), ".oxlayer");
|
|
381
|
+
}
|
|
382
|
+
function getConfigFile() {
|
|
383
|
+
return __require("path").join(getConfigDir(), "config.json");
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
// src/services/index.ts
|
|
387
|
+
init_device_auth_service();
|
|
388
|
+
|
|
389
|
+
// src/services/download.service.ts
|
|
390
|
+
init_esm_shims();
|
|
391
|
+
import { promises as fs } from "fs";
|
|
392
|
+
import { join as join2 } from "path";
|
|
393
|
+
async function downloadFile(url, destination, onProgress) {
|
|
394
|
+
const response = await fetch(url);
|
|
395
|
+
if (!response.ok) {
|
|
396
|
+
throw new Error(`Failed to download: ${response.statusText}`);
|
|
397
|
+
}
|
|
398
|
+
const total = parseInt(response.headers.get("content-length") || "0", 10);
|
|
399
|
+
let downloaded = 0;
|
|
400
|
+
await fs.mkdir(join2(destination, ".."), { recursive: true });
|
|
401
|
+
const writer = await fs.open(destination, "w");
|
|
402
|
+
try {
|
|
403
|
+
const reader = response.body?.getReader();
|
|
404
|
+
if (!reader) {
|
|
405
|
+
throw new Error("No response body");
|
|
406
|
+
}
|
|
407
|
+
while (true) {
|
|
408
|
+
const { done, value } = await reader.read();
|
|
409
|
+
if (done) break;
|
|
410
|
+
await writer.write(value);
|
|
411
|
+
downloaded += value.length;
|
|
412
|
+
if (onProgress && total > 0) {
|
|
413
|
+
onProgress(downloaded, total);
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
} finally {
|
|
417
|
+
await writer.close();
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
async function verifyManifest(manifestPath, expectedHash) {
|
|
421
|
+
const content = await fs.readFile(manifestPath, "utf-8");
|
|
422
|
+
const manifest = JSON.parse(content);
|
|
423
|
+
if (expectedHash && manifest.sha256 !== expectedHash) {
|
|
424
|
+
throw new Error(
|
|
425
|
+
`Manifest SHA256 mismatch. Expected ${expectedHash}, got ${manifest.sha256}`
|
|
426
|
+
);
|
|
427
|
+
}
|
|
428
|
+
return manifest;
|
|
429
|
+
}
|
|
430
|
+
async function extractZip(zipPath, destination) {
|
|
431
|
+
const AdmZip = (await import("adm-zip")).default;
|
|
432
|
+
const zip = new AdmZip(zipPath);
|
|
433
|
+
await fs.mkdir(destination, { recursive: true });
|
|
434
|
+
zip.extractAllTo(destination, true);
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
// src/services/hooks.service.ts
|
|
438
|
+
init_esm_shims();
|
|
439
|
+
|
|
440
|
+
// src/services/telemetry.service.ts
|
|
441
|
+
init_esm_shims();
|
|
442
|
+
import { promises as fs2 } from "fs";
|
|
443
|
+
import { join as join3 } from "path";
|
|
444
|
+
import { existsSync as existsSync2 } from "fs";
|
|
445
|
+
var TELEMETRY_FILE = join3(process.env.HOME || process.env.USERPROFILE || "", ".oxlayer", "telemetry.json");
|
|
446
|
+
var TELEMETRY_ENABLED = process.env.OXLAYER_TELEMETRY !== "0";
|
|
447
|
+
async function getTelemetryConfig() {
|
|
448
|
+
try {
|
|
449
|
+
if (existsSync2(TELEMETRY_FILE)) {
|
|
450
|
+
const content = await fs2.readFile(TELEMETRY_FILE, "utf-8");
|
|
451
|
+
return JSON.parse(content);
|
|
452
|
+
}
|
|
453
|
+
} catch {
|
|
454
|
+
}
|
|
455
|
+
const config = {
|
|
456
|
+
enabled: TELEMETRY_ENABLED,
|
|
457
|
+
userId: generateAnonymousId()
|
|
458
|
+
};
|
|
459
|
+
await saveTelemetryConfig(config);
|
|
460
|
+
return config;
|
|
461
|
+
}
|
|
462
|
+
async function saveTelemetryConfig(config) {
|
|
463
|
+
const dir = join3(process.env.HOME || process.env.USERPROFILE || "", ".oxlayer");
|
|
464
|
+
await fs2.mkdir(dir, { recursive: true });
|
|
465
|
+
await fs2.writeFile(TELEMETRY_FILE, JSON.stringify(config, null, 2));
|
|
466
|
+
}
|
|
467
|
+
function generateAnonymousId() {
|
|
468
|
+
const bytes = new Uint8Array(8);
|
|
469
|
+
crypto.getRandomValues(bytes);
|
|
470
|
+
return Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
|
|
471
|
+
}
|
|
472
|
+
async function trackEvent(data) {
|
|
473
|
+
const config = await getTelemetryConfig();
|
|
474
|
+
if (!config.enabled) {
|
|
475
|
+
return;
|
|
476
|
+
}
|
|
477
|
+
const enrichedData = {
|
|
478
|
+
...data,
|
|
479
|
+
userId: config.userId,
|
|
480
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
481
|
+
};
|
|
482
|
+
sendTelemetry(enrichedData).catch(() => {
|
|
483
|
+
});
|
|
484
|
+
}
|
|
485
|
+
async function sendTelemetry(data) {
|
|
486
|
+
const endpoint = process.env.OXLAYER_TELEMETRY_ENDPOINT || "https://telemetry.oxlayer.dev/v1/event";
|
|
487
|
+
try {
|
|
488
|
+
await fetch(endpoint, {
|
|
489
|
+
method: "POST",
|
|
490
|
+
headers: {
|
|
491
|
+
"Content-Type": "application/json"
|
|
492
|
+
},
|
|
493
|
+
body: JSON.stringify(data),
|
|
494
|
+
// Keep request light - don't wait for response
|
|
495
|
+
keepalive: true
|
|
496
|
+
}).catch(() => {
|
|
497
|
+
});
|
|
498
|
+
} catch {
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
function trackCommand(command, options = {}) {
|
|
502
|
+
trackEvent({
|
|
503
|
+
event: command,
|
|
504
|
+
command,
|
|
505
|
+
...options,
|
|
506
|
+
cliVersion: "0.0.1",
|
|
507
|
+
nodeVersion: process.version,
|
|
508
|
+
platform: process.platform
|
|
509
|
+
});
|
|
510
|
+
}
|
|
511
|
+
function trackError(command, errorCode, options = {}) {
|
|
512
|
+
trackEvent({
|
|
513
|
+
event: "error",
|
|
514
|
+
command,
|
|
515
|
+
errorCode,
|
|
516
|
+
...options,
|
|
517
|
+
cliVersion: "0.0.1",
|
|
518
|
+
nodeVersion: process.version,
|
|
519
|
+
platform: process.platform
|
|
520
|
+
});
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
// src/commands/install.command.ts
|
|
524
|
+
init_device_auth_service();
|
|
525
|
+
var VENDOR_DIR = ".capabilities-vendor";
|
|
526
|
+
var CAPABILITIES_DIR = ".capabilities";
|
|
527
|
+
function resolvePackagesToInstall(projectType, options) {
|
|
528
|
+
if (options.packages && options.packages.length > 0) {
|
|
529
|
+
return options.packages;
|
|
530
|
+
}
|
|
531
|
+
switch (projectType) {
|
|
532
|
+
case "backend":
|
|
533
|
+
return ["backend-sdk"];
|
|
534
|
+
case "frontend":
|
|
535
|
+
return ["frontend-sdk"];
|
|
536
|
+
default:
|
|
537
|
+
return ["backend-sdk", "frontend-sdk", "cli-tools"];
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
function generatePackageJson(version, manifest) {
|
|
541
|
+
const exports = {};
|
|
542
|
+
const dependencies = {};
|
|
543
|
+
for (const [name, pkg] of Object.entries(manifest.packages)) {
|
|
544
|
+
const relativePath = pkg.path;
|
|
545
|
+
exports[name] = `./${relativePath}`;
|
|
546
|
+
dependencies[name] = `workspace:*`;
|
|
547
|
+
const parts = name.split("/").slice(1);
|
|
548
|
+
if (parts.length > 1) {
|
|
549
|
+
const subPath = parts.join("-");
|
|
550
|
+
exports[`@oxlayer/${subPath}`] = `./${relativePath}`;
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
return JSON.stringify({
|
|
554
|
+
name: "@oxlayer/sdk-workspace",
|
|
555
|
+
version,
|
|
556
|
+
private: true,
|
|
557
|
+
description: `OxLayer SDK v${version} - Local workspace package`,
|
|
558
|
+
type: "module",
|
|
559
|
+
exports,
|
|
560
|
+
dependencies
|
|
561
|
+
}, null, 2);
|
|
562
|
+
}
|
|
563
|
+
async function updateWorkspaceConfig(rootDir, vendorVersionDir) {
|
|
564
|
+
const workspacePath = join4(rootDir, "pnpm-workspace.yaml");
|
|
565
|
+
const relativeVendorPath = vendorVersionDir.replace(rootDir + "/", "").replace(/^\//, "");
|
|
566
|
+
let workspaceConfig;
|
|
567
|
+
try {
|
|
568
|
+
const content = await fs3.readFile(workspacePath, "utf-8");
|
|
569
|
+
const match = content.match(/packages:\s*\n((?:\s*-\s*[^\n]+\n*)+)/);
|
|
570
|
+
if (match) {
|
|
571
|
+
const packages = match[1].split("\n").map((line) => line.replace(/^\s*-\s*/, "").trim()).filter((line) => line.length > 0);
|
|
572
|
+
workspaceConfig = { packages };
|
|
573
|
+
} else {
|
|
574
|
+
workspaceConfig = { packages: [] };
|
|
575
|
+
}
|
|
576
|
+
} catch {
|
|
577
|
+
workspaceConfig = { packages: [] };
|
|
578
|
+
}
|
|
579
|
+
if (!workspaceConfig.packages?.includes(relativeVendorPath)) {
|
|
580
|
+
workspaceConfig.packages = [...workspaceConfig.packages || [], relativeVendorPath];
|
|
581
|
+
const yamlContent = `packages:
|
|
582
|
+
${workspaceConfig.packages.map((p) => ` - '${p}'`).join("\n")}
|
|
583
|
+
`;
|
|
584
|
+
await fs3.writeFile(workspacePath, yamlContent, "utf-8");
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
async function updateCurrentSymlink(baseDir, version) {
|
|
588
|
+
const currentPath = join4(baseDir, "current");
|
|
589
|
+
const versionPath = join4(baseDir, version);
|
|
590
|
+
try {
|
|
591
|
+
await fs3.unlink(currentPath);
|
|
592
|
+
} catch {
|
|
593
|
+
}
|
|
594
|
+
await fs3.symlink(versionPath, currentPath, "dir");
|
|
595
|
+
}
|
|
596
|
+
async function addWorkspaceDependency(rootDir, vendorVersionPath) {
|
|
597
|
+
const packageJsonPath = join4(rootDir, "package.json");
|
|
598
|
+
try {
|
|
599
|
+
const content = await fs3.readFile(packageJsonPath, "utf-8");
|
|
600
|
+
const pkg = JSON.parse(content);
|
|
601
|
+
if (!pkg.dependencies) {
|
|
602
|
+
pkg.dependencies = {};
|
|
603
|
+
}
|
|
604
|
+
if (!pkg.dependencies["@oxlayer/sdk-workspace"]) {
|
|
605
|
+
pkg.dependencies["@oxlayer/sdk-workspace"] = "workspace:*";
|
|
606
|
+
}
|
|
607
|
+
await fs3.writeFile(packageJsonPath, JSON.stringify(pkg, null, 2) + "\n", "utf-8");
|
|
608
|
+
} catch (err) {
|
|
609
|
+
throw new Error(`Failed to update package.json: ${err instanceof Error ? err.message : "Unknown error"}`);
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
async function install(version, options = {}) {
|
|
613
|
+
const startTime = Date.now();
|
|
614
|
+
const startDir = process.cwd();
|
|
615
|
+
header("OxLayer SDK Installer");
|
|
616
|
+
const rootDir = findProjectRoot(startDir);
|
|
617
|
+
if (!await hasPackageJson()) {
|
|
618
|
+
error("No package.json found in current directory");
|
|
619
|
+
info("Navigate to your project directory before installing.");
|
|
620
|
+
process.exit(1);
|
|
621
|
+
}
|
|
622
|
+
const projectConfig = await detectProjectType(startDir);
|
|
623
|
+
info(`Project root: ${rootDir === startDir ? "." : rootDir}`);
|
|
624
|
+
info(`Package manager: ${projectConfig.packageManager}`);
|
|
625
|
+
info(`Project type: ${projectConfig.type}`);
|
|
626
|
+
const packagesToInstall = resolvePackagesToInstall(projectConfig.type, options);
|
|
627
|
+
info(`Packages: ${packagesToInstall.join(", ")}`);
|
|
628
|
+
const authSpinner = createSpinner("Validating authentication...");
|
|
629
|
+
authSpinner.start();
|
|
630
|
+
try {
|
|
631
|
+
const config = await loadConfig();
|
|
632
|
+
if (!config || !config.token) {
|
|
633
|
+
authSpinner.fail("Authentication required");
|
|
634
|
+
error("Please run: oxlayer login");
|
|
635
|
+
process.exit(1);
|
|
636
|
+
}
|
|
637
|
+
if (isTokenExpired(config)) {
|
|
638
|
+
authSpinner.fail("Token expired");
|
|
639
|
+
error("Your authentication token has expired. Please run: oxlayer login");
|
|
640
|
+
process.exit(1);
|
|
641
|
+
}
|
|
642
|
+
authSpinner.succeed("Authenticated");
|
|
643
|
+
info(`Organization: ${config.organizationId}`);
|
|
644
|
+
info(`Device: ${config.tokenInfo?.deviceId || "Unknown"}`);
|
|
645
|
+
const expiresAt = new Date(config.tokenInfo.expiresAt);
|
|
646
|
+
const now = /* @__PURE__ */ new Date();
|
|
647
|
+
const daysUntilExpiry = Math.ceil((expiresAt.getTime() - now.getTime()) / (1e3 * 60 * 60 * 24));
|
|
648
|
+
info(`Token expires: ${expiresAt.toLocaleString()} (${daysUntilExpiry > 0 ? `in ${daysUntilExpiry} days` : "expired"})`);
|
|
649
|
+
} catch (err) {
|
|
650
|
+
authSpinner.fail("Authentication failed");
|
|
651
|
+
error(err instanceof Error ? err.message : "Unknown error");
|
|
652
|
+
process.exit(1);
|
|
653
|
+
}
|
|
654
|
+
console.log();
|
|
655
|
+
const downloadSpinner = createSpinner("Downloading SDK...");
|
|
656
|
+
downloadSpinner.start();
|
|
657
|
+
let resolvedVersion = version;
|
|
658
|
+
let manifest;
|
|
659
|
+
try {
|
|
660
|
+
const { downloadUrl, version: resolvedVer } = await requestPackageDownload(
|
|
661
|
+
packagesToInstall[0],
|
|
662
|
+
version
|
|
663
|
+
);
|
|
664
|
+
resolvedVersion = resolvedVer;
|
|
665
|
+
const tempDir = join4(rootDir, ".oxlayer-temp");
|
|
666
|
+
await fs3.mkdir(tempDir, { recursive: true });
|
|
667
|
+
const zipPath = join4(tempDir, `oxlayer-sdk-${resolvedVersion}.zip`);
|
|
668
|
+
let lastProgress = 0;
|
|
669
|
+
await downloadFile(
|
|
670
|
+
downloadUrl,
|
|
671
|
+
zipPath,
|
|
672
|
+
(progress, total) => {
|
|
673
|
+
const percent = Math.floor(progress / total * 100);
|
|
674
|
+
if (percent - lastProgress >= 10) {
|
|
675
|
+
downloadSpinner.text = `Downloading SDK... ${percent}%`;
|
|
676
|
+
lastProgress = percent;
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
);
|
|
680
|
+
downloadSpinner.succeed(`Downloaded SDK (${resolvedVersion})`);
|
|
681
|
+
const extractSpinner = createSpinner("Extracting SDK...");
|
|
682
|
+
extractSpinner.start();
|
|
683
|
+
const vendorBaseDir = join4(rootDir, VENDOR_DIR);
|
|
684
|
+
const vendorVersionDir = join4(vendorBaseDir, resolvedVersion);
|
|
685
|
+
await fs3.mkdir(vendorVersionDir, { recursive: true });
|
|
686
|
+
await extractZip(zipPath, join4(tempDir, "extracted"));
|
|
687
|
+
const extractedBase = join4(tempDir, "extracted", resolvedVersion);
|
|
688
|
+
const manifestPath = join4(extractedBase, "manifest.json");
|
|
689
|
+
manifest = await verifyManifest(manifestPath);
|
|
690
|
+
await copyDirectory(extractedBase, vendorVersionDir);
|
|
691
|
+
const packageJsonPath = join4(vendorVersionDir, "package.json");
|
|
692
|
+
const packageJsonContent = generatePackageJson(resolvedVersion, manifest);
|
|
693
|
+
await fs3.writeFile(packageJsonPath, packageJsonContent, "utf-8");
|
|
694
|
+
extractSpinner.succeed("Extracted SDK");
|
|
695
|
+
const workspaceSpinner = createSpinner("Configuring workspace...");
|
|
696
|
+
workspaceSpinner.start();
|
|
697
|
+
await updateWorkspaceConfig(rootDir, vendorVersionDir);
|
|
698
|
+
await updateCurrentSymlink(vendorBaseDir, resolvedVersion);
|
|
699
|
+
await addWorkspaceDependency(rootDir, vendorVersionDir);
|
|
700
|
+
workspaceSpinner.succeed("Workspace configured");
|
|
701
|
+
await fs3.rm(tempDir, { recursive: true, force: true });
|
|
702
|
+
} catch (err) {
|
|
703
|
+
downloadSpinner.fail("Failed to install SDK");
|
|
704
|
+
error(err instanceof Error ? err.message : "Unknown error");
|
|
705
|
+
process.exit(1);
|
|
706
|
+
}
|
|
707
|
+
console.log();
|
|
708
|
+
const duration = Date.now() - startTime;
|
|
709
|
+
header("Installation Complete");
|
|
710
|
+
success(`SDK version ${resolvedVersion} installed successfully`);
|
|
711
|
+
info(`Duration: ${formatDuration(duration)}`);
|
|
712
|
+
info(`Workspace: ${VENDOR_DIR}/${resolvedVersion}/`);
|
|
713
|
+
info(`Current link: ${CAPABILITIES_DIR}/current -> ${resolvedVersion}`);
|
|
714
|
+
const installSpinner = createSpinner("Running package manager install...");
|
|
715
|
+
installSpinner.start();
|
|
716
|
+
try {
|
|
717
|
+
const installCommand = getInstallCommand(projectConfig.packageManager);
|
|
718
|
+
execSync(installCommand, { cwd: rootDir, stdio: "pipe" });
|
|
719
|
+
installSpinner.succeed(`Dependencies installed via ${projectConfig.packageManager}`);
|
|
720
|
+
} catch (err) {
|
|
721
|
+
installSpinner.warn(`Package manager install failed. Please run '${getInstallCommand(projectConfig.packageManager)}' manually.`);
|
|
722
|
+
}
|
|
723
|
+
console.log();
|
|
724
|
+
info("Next steps:");
|
|
725
|
+
console.log(" Import in your code:");
|
|
726
|
+
console.log(" import { SomeCapability } from '@oxlayer/sdk-workspace';");
|
|
727
|
+
console.log();
|
|
728
|
+
console.log(` To switch SDK versions, update the ${CAPABILITIES_DIR}/current symlink.`);
|
|
729
|
+
}
|
|
730
|
+
async function copyDirectory(src, dest) {
|
|
731
|
+
await fs3.mkdir(dest, { recursive: true });
|
|
732
|
+
const entries = await fs3.readdir(src, { withFileTypes: true });
|
|
733
|
+
for (const entry of entries) {
|
|
734
|
+
const srcPath = join4(src, entry.name);
|
|
735
|
+
const destPath = join4(dest, entry.name);
|
|
736
|
+
if (entry.isDirectory()) {
|
|
737
|
+
await copyDirectory(srcPath, destPath);
|
|
738
|
+
} else {
|
|
739
|
+
await fs3.copyFile(srcPath, destPath);
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
// src/commands/resolve.command.ts
|
|
745
|
+
init_esm_shims();
|
|
746
|
+
async function resolve(options = {}) {
|
|
747
|
+
header("OxLayer Capability Resolution");
|
|
748
|
+
const projectConfig = await detectProjectType();
|
|
749
|
+
const environment = options.environment || "development";
|
|
750
|
+
info(`Project type: ${projectConfig.type}`);
|
|
751
|
+
info(`Environment: ${environment}`);
|
|
752
|
+
const capabilitiesToRequest = [];
|
|
753
|
+
switch (projectConfig.type) {
|
|
754
|
+
case "backend":
|
|
755
|
+
capabilitiesToRequest.push(
|
|
756
|
+
"auth",
|
|
757
|
+
"storage",
|
|
758
|
+
"cache",
|
|
759
|
+
"events",
|
|
760
|
+
"queues",
|
|
761
|
+
"metrics",
|
|
762
|
+
"telemetry"
|
|
763
|
+
);
|
|
764
|
+
break;
|
|
765
|
+
case "frontend":
|
|
766
|
+
capabilitiesToRequest.push("auth", "storage");
|
|
767
|
+
break;
|
|
768
|
+
default:
|
|
769
|
+
capabilitiesToRequest.push(
|
|
770
|
+
"auth",
|
|
771
|
+
"storage",
|
|
772
|
+
"search",
|
|
773
|
+
"vector",
|
|
774
|
+
"cache",
|
|
775
|
+
"events",
|
|
776
|
+
"queues",
|
|
777
|
+
"metrics",
|
|
778
|
+
"telemetry"
|
|
779
|
+
);
|
|
780
|
+
}
|
|
781
|
+
const spinner = await import("./cli-VUBGPXL3.js").then((m) => m.createSpinner("Resolving capabilities..."));
|
|
782
|
+
spinner.start();
|
|
783
|
+
try {
|
|
784
|
+
const result = await resolveCapabilities(capabilitiesToRequest, environment);
|
|
785
|
+
spinner.succeed("Capabilities resolved");
|
|
786
|
+
console.log();
|
|
787
|
+
info(`Organization: ${result.organizationId}`);
|
|
788
|
+
info(`License: ${result.licenseId}`);
|
|
789
|
+
info(`Resolved at: ${new Date(result.resolvedAt).toLocaleString()}`);
|
|
790
|
+
console.log();
|
|
791
|
+
header("Available Capabilities");
|
|
792
|
+
printCapabilities(result.capabilities);
|
|
793
|
+
if (options.verbose) {
|
|
794
|
+
console.log();
|
|
795
|
+
header("Usage Example");
|
|
796
|
+
console.log();
|
|
797
|
+
console.log("Import and use capabilities in your code:");
|
|
798
|
+
console.log();
|
|
799
|
+
console.log(chalk.gray("```typescript"));
|
|
800
|
+
console.log(chalk.gray("import { resolveCapabilities } from '@oxlayer/capabilities-internal';"));
|
|
801
|
+
console.log();
|
|
802
|
+
console.log(chalk.gray("const capabilities = await resolveCapabilities({"));
|
|
803
|
+
console.log(chalk.gray(` projectId: 'your-project-id',`));
|
|
804
|
+
console.log(chalk.gray(` environment: '${environment}',`));
|
|
805
|
+
console.log(chalk.gray(` requested: ['${capabilitiesToRequest.join("', '")}']`));
|
|
806
|
+
console.log(chalk.gray("});"));
|
|
807
|
+
console.log(chalk.gray("```"));
|
|
808
|
+
console.log();
|
|
809
|
+
}
|
|
810
|
+
success(`Your project has access to ${Object.keys(result.capabilities).length} capabilities`);
|
|
811
|
+
} catch (err) {
|
|
812
|
+
spinner.fail("Failed to resolve capabilities");
|
|
813
|
+
error(err instanceof Error ? err.message : "Unknown error");
|
|
814
|
+
if (err instanceof Error && err.message.includes("API key")) {
|
|
815
|
+
console.log();
|
|
816
|
+
info("Make sure you're authenticated:");
|
|
817
|
+
console.log(" oxlayer login");
|
|
818
|
+
}
|
|
819
|
+
process.exit(1);
|
|
820
|
+
}
|
|
821
|
+
}
|
|
822
|
+
var chalk = (await import("chalk")).default;
|
|
823
|
+
|
|
824
|
+
// src/commands/logout.command.ts
|
|
825
|
+
init_esm_shims();
|
|
826
|
+
async function logout() {
|
|
827
|
+
try {
|
|
828
|
+
await removeConfig();
|
|
829
|
+
success("Logged out successfully");
|
|
830
|
+
info(`Configuration removed from ${getConfigFile()}`);
|
|
831
|
+
info("Your API key is no longer stored locally.");
|
|
832
|
+
} catch (err) {
|
|
833
|
+
warning2("Could not remove configuration");
|
|
834
|
+
info(err instanceof Error ? err.message : "Unknown error");
|
|
835
|
+
}
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
// src/commands/doctor.command.ts
|
|
839
|
+
init_esm_shims();
|
|
840
|
+
import { existsSync as existsSync3 } from "fs";
|
|
841
|
+
import { join as join5 } from "path";
|
|
842
|
+
async function runDiagnostics(options) {
|
|
843
|
+
const results = [];
|
|
844
|
+
const config = await loadConfig2();
|
|
845
|
+
if (config) {
|
|
846
|
+
results.push({
|
|
847
|
+
name: "Authentication",
|
|
848
|
+
status: "pass",
|
|
849
|
+
message: "API key configured"
|
|
850
|
+
});
|
|
851
|
+
} else {
|
|
852
|
+
results.push({
|
|
853
|
+
name: "Authentication",
|
|
854
|
+
status: "fail",
|
|
855
|
+
message: "Not authenticated",
|
|
856
|
+
fix: "Run: oxlayer login"
|
|
857
|
+
});
|
|
858
|
+
}
|
|
859
|
+
try {
|
|
860
|
+
const isHealthy = await healthCheck();
|
|
861
|
+
if (isHealthy) {
|
|
862
|
+
results.push({
|
|
863
|
+
name: "API Connectivity",
|
|
864
|
+
status: "pass",
|
|
865
|
+
message: "Control Panel API is reachable"
|
|
866
|
+
});
|
|
867
|
+
} else {
|
|
868
|
+
results.push({
|
|
869
|
+
name: "API Connectivity",
|
|
870
|
+
status: "fail",
|
|
871
|
+
message: "API health check failed",
|
|
872
|
+
fix: "Check your network connection"
|
|
873
|
+
});
|
|
874
|
+
}
|
|
875
|
+
} catch {
|
|
876
|
+
results.push({
|
|
877
|
+
name: "API Connectivity",
|
|
878
|
+
status: "fail",
|
|
879
|
+
message: "Cannot reach Control Panel API",
|
|
880
|
+
fix: "Check your network connection or API endpoint"
|
|
881
|
+
});
|
|
882
|
+
}
|
|
883
|
+
const projectConfig = await detectProjectType();
|
|
884
|
+
if (projectConfig.hasPackageJson) {
|
|
885
|
+
results.push({
|
|
886
|
+
name: "Project Structure",
|
|
887
|
+
status: "pass",
|
|
888
|
+
message: `Found ${projectConfig.type} project with ${projectConfig.packageManager}`
|
|
889
|
+
});
|
|
890
|
+
} else {
|
|
891
|
+
results.push({
|
|
892
|
+
name: "Project Structure",
|
|
893
|
+
status: "warn",
|
|
894
|
+
message: "No package.json found",
|
|
895
|
+
fix: "Navigate to your project directory"
|
|
896
|
+
});
|
|
897
|
+
}
|
|
898
|
+
if (projectConfig.hasTsConfig) {
|
|
899
|
+
results.push({
|
|
900
|
+
name: "TypeScript",
|
|
901
|
+
status: "pass",
|
|
902
|
+
message: "TypeScript configuration found"
|
|
903
|
+
});
|
|
904
|
+
} else {
|
|
905
|
+
results.push({
|
|
906
|
+
name: "TypeScript",
|
|
907
|
+
status: "warn",
|
|
908
|
+
message: "No TypeScript configuration found",
|
|
909
|
+
fix: "Run: npx tsc --init"
|
|
910
|
+
});
|
|
911
|
+
}
|
|
912
|
+
const installedVersion = await getInstalledVersion();
|
|
913
|
+
if (installedVersion) {
|
|
914
|
+
const vendorDir = getVendorDir(installedVersion);
|
|
915
|
+
const manifestPath = join5(vendorDir, "manifest.json");
|
|
916
|
+
if (existsSync3(manifestPath)) {
|
|
917
|
+
results.push({
|
|
918
|
+
name: "SDK Installation",
|
|
919
|
+
status: "pass",
|
|
920
|
+
message: `SDK version ${installedVersion} installed`
|
|
921
|
+
});
|
|
922
|
+
} else {
|
|
923
|
+
results.push({
|
|
924
|
+
name: "SDK Installation",
|
|
925
|
+
status: "warn",
|
|
926
|
+
message: `SDK version ${installedVersion} incomplete (missing manifest)`,
|
|
927
|
+
fix: "Run: oxlayer install --force"
|
|
928
|
+
});
|
|
929
|
+
}
|
|
930
|
+
} else {
|
|
931
|
+
results.push({
|
|
932
|
+
name: "SDK Installation",
|
|
933
|
+
status: "warn",
|
|
934
|
+
message: "No SDK installed",
|
|
935
|
+
fix: "Run: oxlayer install"
|
|
936
|
+
});
|
|
937
|
+
}
|
|
938
|
+
const gitignorePath = join5(process.cwd(), ".gitignore");
|
|
939
|
+
if (existsSync3(gitignorePath)) {
|
|
940
|
+
const gitignoreContent = await import("fs/promises").then((fs4) => fs4.readFile(gitignorePath, "utf-8"));
|
|
941
|
+
const hasVendorIgnore = gitignoreContent.includes(".capabilities-vendor");
|
|
942
|
+
if (hasVendorIgnore) {
|
|
943
|
+
results.push({
|
|
944
|
+
name: ".gitignore",
|
|
945
|
+
status: "pass",
|
|
946
|
+
message: "Vendor directory is ignored"
|
|
947
|
+
});
|
|
948
|
+
} else {
|
|
949
|
+
results.push({
|
|
950
|
+
name: ".gitignore",
|
|
951
|
+
status: "warn",
|
|
952
|
+
message: "Vendor directory not in .gitignore",
|
|
953
|
+
fix: 'Add ".capabilities-vendor/" to .gitignore'
|
|
954
|
+
});
|
|
955
|
+
}
|
|
956
|
+
} else {
|
|
957
|
+
results.push({
|
|
958
|
+
name: ".gitignore",
|
|
959
|
+
status: "warn",
|
|
960
|
+
message: "No .gitignore found",
|
|
961
|
+
fix: 'Create .gitignore and add ".capabilities-vendor/"'
|
|
962
|
+
});
|
|
963
|
+
}
|
|
964
|
+
if (process.env.OXLAYER_API_KEY) {
|
|
965
|
+
results.push({
|
|
966
|
+
name: "Environment Variables",
|
|
967
|
+
status: "pass",
|
|
968
|
+
message: "OXLAYER_API_KEY is set"
|
|
969
|
+
});
|
|
970
|
+
} else if (!config) {
|
|
971
|
+
results.push({
|
|
972
|
+
name: "Environment Variables",
|
|
973
|
+
status: "warn",
|
|
974
|
+
message: "No API key in environment or config",
|
|
975
|
+
fix: "Set OXLAYER_API_KEY or run: oxlayer login"
|
|
976
|
+
});
|
|
977
|
+
}
|
|
978
|
+
const nodeVersion = process.version;
|
|
979
|
+
const majorVersion = parseInt(nodeVersion.slice(1).split(".")[0], 10);
|
|
980
|
+
if (majorVersion >= 18) {
|
|
981
|
+
results.push({
|
|
982
|
+
name: "Node Version",
|
|
983
|
+
status: "pass",
|
|
984
|
+
message: `Node ${nodeVersion} (supported)`
|
|
985
|
+
});
|
|
986
|
+
} else {
|
|
987
|
+
results.push({
|
|
988
|
+
name: "Node Version",
|
|
989
|
+
status: "fail",
|
|
990
|
+
message: `Node ${nodeVersion} is not supported (requires >= 18)`,
|
|
991
|
+
fix: "Upgrade to Node.js 18 or later"
|
|
992
|
+
});
|
|
993
|
+
}
|
|
994
|
+
if (options.verbose && config) {
|
|
995
|
+
try {
|
|
996
|
+
const { resolveCapabilities: resolveCapabilities2 } = await import("./api.service-CDPTVMJM.js");
|
|
997
|
+
const capabilities = await resolveCapabilities2(["auth", "storage"], "development");
|
|
998
|
+
if (Object.keys(capabilities.capabilities).length > 0) {
|
|
999
|
+
results.push({
|
|
1000
|
+
name: "Capabilities",
|
|
1001
|
+
status: "pass",
|
|
1002
|
+
message: `${Object.keys(capabilities.capabilities).length} capabilities available`
|
|
1003
|
+
});
|
|
1004
|
+
} else {
|
|
1005
|
+
results.push({
|
|
1006
|
+
name: "Capabilities",
|
|
1007
|
+
status: "warn",
|
|
1008
|
+
message: "No capabilities available",
|
|
1009
|
+
fix: "Check your license configuration"
|
|
1010
|
+
});
|
|
1011
|
+
}
|
|
1012
|
+
} catch {
|
|
1013
|
+
results.push({
|
|
1014
|
+
name: "Capabilities",
|
|
1015
|
+
status: "fail",
|
|
1016
|
+
message: "Could not resolve capabilities",
|
|
1017
|
+
fix: "Check your API key and license"
|
|
1018
|
+
});
|
|
1019
|
+
}
|
|
1020
|
+
}
|
|
1021
|
+
return results;
|
|
1022
|
+
}
|
|
1023
|
+
function printDiagnostics(results) {
|
|
1024
|
+
let passCount = 0;
|
|
1025
|
+
let warnCount = 0;
|
|
1026
|
+
let failCount = 0;
|
|
1027
|
+
for (const result of results) {
|
|
1028
|
+
switch (result.status) {
|
|
1029
|
+
case "pass":
|
|
1030
|
+
success(`${result.name}: ${result.message}`);
|
|
1031
|
+
passCount++;
|
|
1032
|
+
break;
|
|
1033
|
+
case "warn":
|
|
1034
|
+
warning2(`${result.name}: ${result.message}`);
|
|
1035
|
+
if (result.fix) {
|
|
1036
|
+
info(` \u2192 ${result.fix}`);
|
|
1037
|
+
}
|
|
1038
|
+
warnCount++;
|
|
1039
|
+
break;
|
|
1040
|
+
case "fail":
|
|
1041
|
+
error(`${result.name}: ${result.message}`);
|
|
1042
|
+
if (result.fix) {
|
|
1043
|
+
info(` \u2192 ${result.fix}`);
|
|
1044
|
+
}
|
|
1045
|
+
failCount++;
|
|
1046
|
+
break;
|
|
1047
|
+
}
|
|
1048
|
+
}
|
|
1049
|
+
console.log();
|
|
1050
|
+
if (failCount === 0 && warnCount === 0) {
|
|
1051
|
+
success("All checks passed! Your system is properly configured.");
|
|
1052
|
+
} else if (failCount === 0) {
|
|
1053
|
+
warning2(`${warnCount} warning(s) found. Consider fixing them for optimal performance.`);
|
|
1054
|
+
} else {
|
|
1055
|
+
error(`${failCount} error(s) and ${warnCount} warning(s) found. Please fix the errors.`);
|
|
1056
|
+
}
|
|
1057
|
+
}
|
|
1058
|
+
async function doctor(options = {}) {
|
|
1059
|
+
header("OxLayer SDK Diagnostics");
|
|
1060
|
+
const results = await runDiagnostics(options);
|
|
1061
|
+
console.log();
|
|
1062
|
+
printDiagnostics(results);
|
|
1063
|
+
if (results.some((r) => r.status === "fail")) {
|
|
1064
|
+
process.exit(1);
|
|
1065
|
+
}
|
|
1066
|
+
}
|
|
1067
|
+
|
|
1068
|
+
// src/commands/diff.command.ts
|
|
1069
|
+
init_esm_shims();
|
|
1070
|
+
function formatLimitValue(key, value) {
|
|
1071
|
+
if (typeof value === "boolean") {
|
|
1072
|
+
return value ? "\u2713 enabled" : "\u2717 disabled";
|
|
1073
|
+
}
|
|
1074
|
+
if (Array.isArray(value)) {
|
|
1075
|
+
return value.join(", ");
|
|
1076
|
+
}
|
|
1077
|
+
if (typeof value === "object" && value !== null) {
|
|
1078
|
+
return JSON.stringify(value);
|
|
1079
|
+
}
|
|
1080
|
+
return String(value);
|
|
1081
|
+
}
|
|
1082
|
+
function getCapabilityChanges(before, after) {
|
|
1083
|
+
const changes = [];
|
|
1084
|
+
const allKeys = /* @__PURE__ */ new Set([...Object.keys(before), ...Object.keys(after)]);
|
|
1085
|
+
for (const key of allKeys) {
|
|
1086
|
+
const beforeValue = before[key];
|
|
1087
|
+
const afterValue = after[key];
|
|
1088
|
+
if (JSON.stringify(beforeValue) !== JSON.stringify(afterValue)) {
|
|
1089
|
+
changes.push(
|
|
1090
|
+
` ${key}: ${formatLimitValue(key, beforeValue)} \u2192 ${formatLimitValue(key, afterValue)}`
|
|
1091
|
+
);
|
|
1092
|
+
}
|
|
1093
|
+
}
|
|
1094
|
+
return changes;
|
|
1095
|
+
}
|
|
1096
|
+
async function diff(fromVersion, toVersion, options = {}) {
|
|
1097
|
+
header(`Capability Diff: ${fromVersion} \u2192 ${toVersion}`);
|
|
1098
|
+
const spinner = await import("./cli-VUBGPXL3.js").then((m) => m.createSpinner("Fetching manifests..."));
|
|
1099
|
+
spinner.start();
|
|
1100
|
+
try {
|
|
1101
|
+
spinner.succeed("Manifests fetched");
|
|
1102
|
+
const beforeCapabilities = {
|
|
1103
|
+
auth: { maxRealms: 1, sso: false, rbac: true },
|
|
1104
|
+
storage: { encryption: false, maxStorageGb: 100 },
|
|
1105
|
+
vector: { maxVectorCollections: 10, maxVectorDimensions: 1536 }
|
|
1106
|
+
};
|
|
1107
|
+
const afterCapabilities = {
|
|
1108
|
+
auth: { maxRealms: 5, sso: true, rbac: true },
|
|
1109
|
+
storage: { encryption: true, maxStorageGb: 1e3 },
|
|
1110
|
+
search: { maxResults: 1e4 },
|
|
1111
|
+
vector: { maxVectorCollections: 50, hybridSearch: true }
|
|
1112
|
+
};
|
|
1113
|
+
const diffs = [];
|
|
1114
|
+
for (const [name, limits] of Object.entries(afterCapabilities)) {
|
|
1115
|
+
if (!(name in beforeCapabilities)) {
|
|
1116
|
+
diffs.push({
|
|
1117
|
+
name,
|
|
1118
|
+
change: "added",
|
|
1119
|
+
after: limits
|
|
1120
|
+
});
|
|
1121
|
+
}
|
|
1122
|
+
}
|
|
1123
|
+
for (const [name, limits] of Object.entries(beforeCapabilities)) {
|
|
1124
|
+
if (!(name in afterCapabilities)) {
|
|
1125
|
+
diffs.push({
|
|
1126
|
+
name,
|
|
1127
|
+
change: "removed",
|
|
1128
|
+
before: limits
|
|
1129
|
+
});
|
|
1130
|
+
}
|
|
1131
|
+
}
|
|
1132
|
+
for (const name of Object.keys(beforeCapabilities)) {
|
|
1133
|
+
if (name in afterCapabilities) {
|
|
1134
|
+
const before = beforeCapabilities[name];
|
|
1135
|
+
const after = afterCapabilities[name];
|
|
1136
|
+
const changes = getCapabilityChanges(before, after);
|
|
1137
|
+
if (changes.length > 0) {
|
|
1138
|
+
diffs.push({
|
|
1139
|
+
name,
|
|
1140
|
+
change: "modified",
|
|
1141
|
+
before,
|
|
1142
|
+
after,
|
|
1143
|
+
changes
|
|
1144
|
+
});
|
|
1145
|
+
}
|
|
1146
|
+
}
|
|
1147
|
+
}
|
|
1148
|
+
console.log();
|
|
1149
|
+
const addedCount = diffs.filter((d) => d.change === "added").length;
|
|
1150
|
+
const removedCount = diffs.filter((d) => d.change === "removed").length;
|
|
1151
|
+
const modifiedCount = diffs.filter((d) => d.change === "modified").length;
|
|
1152
|
+
if (addedCount > 0) {
|
|
1153
|
+
success(`${addedCount} capability(ies) added`);
|
|
1154
|
+
}
|
|
1155
|
+
if (modifiedCount > 0) {
|
|
1156
|
+
info(`${modifiedCount} capability(ies) modified`);
|
|
1157
|
+
}
|
|
1158
|
+
if (removedCount > 0) {
|
|
1159
|
+
error(`${removedCount} capability(ies) removed`);
|
|
1160
|
+
}
|
|
1161
|
+
console.log();
|
|
1162
|
+
if (options.verbose || diffs.length > 0) {
|
|
1163
|
+
header("Detailed Changes");
|
|
1164
|
+
for (const diff2 of diffs) {
|
|
1165
|
+
switch (diff2.change) {
|
|
1166
|
+
case "added":
|
|
1167
|
+
success(`+ ${diff2.name} (new)`);
|
|
1168
|
+
if (options.verbose && diff2.after) {
|
|
1169
|
+
const limits = Object.entries(diff2.after).map(([k, v]) => ` ${k}: ${formatLimitValue(k, v)}`).join("\n");
|
|
1170
|
+
console.log(limits);
|
|
1171
|
+
}
|
|
1172
|
+
break;
|
|
1173
|
+
case "removed":
|
|
1174
|
+
error(`- ${diff2.name} (removed)`);
|
|
1175
|
+
if (options.verbose && diff2.before) {
|
|
1176
|
+
const limits = Object.entries(diff2.before).map(([k, v]) => ` ${k}: ${formatLimitValue(k, v)}`).join("\n");
|
|
1177
|
+
console.log(limits);
|
|
1178
|
+
}
|
|
1179
|
+
break;
|
|
1180
|
+
case "modified":
|
|
1181
|
+
info(`~ ${diff2.name} (modified)`);
|
|
1182
|
+
if (diff2.changes && diff2.changes.length > 0) {
|
|
1183
|
+
console.log(diff2.changes.join("\n"));
|
|
1184
|
+
}
|
|
1185
|
+
break;
|
|
1186
|
+
}
|
|
1187
|
+
console.log();
|
|
1188
|
+
}
|
|
1189
|
+
}
|
|
1190
|
+
header("Upgrade Recommendations");
|
|
1191
|
+
if (modifiedCount > 0) {
|
|
1192
|
+
const modifiedDiffs = diffs.filter((d) => d.change === "modified");
|
|
1193
|
+
for (const diff2 of modifiedDiffs) {
|
|
1194
|
+
const breakingChanges = diff2.changes?.filter(
|
|
1195
|
+
(c) => c.includes("\u2192") && !c.includes("0 \u2192")
|
|
1196
|
+
);
|
|
1197
|
+
if (breakingChanges && breakingChanges.length > 0) {
|
|
1198
|
+
warning(`${diff2.name}: Review breaking changes`);
|
|
1199
|
+
printList(breakingChanges);
|
|
1200
|
+
}
|
|
1201
|
+
}
|
|
1202
|
+
}
|
|
1203
|
+
if (removedCount > 0) {
|
|
1204
|
+
warning("Some capabilities were removed. Check your code for usage.");
|
|
1205
|
+
const removed = diffs.filter((d) => d.change === "removed").map((d) => d.name);
|
|
1206
|
+
printList(removed);
|
|
1207
|
+
}
|
|
1208
|
+
} catch (err) {
|
|
1209
|
+
spinner.fail("Failed to compare versions");
|
|
1210
|
+
error(err instanceof Error ? err.message : "Unknown error");
|
|
1211
|
+
process.exit(1);
|
|
1212
|
+
}
|
|
1213
|
+
}
|
|
1214
|
+
async function showLatest() {
|
|
1215
|
+
const spinner = await import("./cli-VUBGPXL3.js").then((m) => m.createSpinner("Checking for updates..."));
|
|
1216
|
+
spinner.start();
|
|
1217
|
+
try {
|
|
1218
|
+
const { getInstalledVersion: getInstalledVersion2 } = await import("./package.service-XK5PPZVF.js");
|
|
1219
|
+
const { getLatestVersion } = await import("./api.service-CDPTVMJM.js");
|
|
1220
|
+
const installed = await getInstalledVersion2();
|
|
1221
|
+
const latest = await getLatestVersion();
|
|
1222
|
+
spinner.succeed("Version check complete");
|
|
1223
|
+
header("Version Information");
|
|
1224
|
+
info(`Installed: ${installed || "None"}`);
|
|
1225
|
+
info(`Latest: ${latest}`);
|
|
1226
|
+
if (installed !== latest) {
|
|
1227
|
+
console.log();
|
|
1228
|
+
success("New version available!");
|
|
1229
|
+
info(`Run: oxlayer install ${latest}`);
|
|
1230
|
+
} else if (installed) {
|
|
1231
|
+
console.log();
|
|
1232
|
+
success("You're up to date!");
|
|
1233
|
+
}
|
|
1234
|
+
} catch (err) {
|
|
1235
|
+
spinner.fail("Failed to check version");
|
|
1236
|
+
error(err instanceof Error ? err.message : "Unknown error");
|
|
1237
|
+
}
|
|
1238
|
+
}
|
|
1239
|
+
|
|
1240
|
+
// src/commands/telemetry.command.ts
|
|
1241
|
+
init_esm_shims();
|
|
1242
|
+
async function telemetryEnable() {
|
|
1243
|
+
success("Telemetry enabled");
|
|
1244
|
+
info("Anonymous usage data will be collected to improve the SDK");
|
|
1245
|
+
}
|
|
1246
|
+
async function telemetryDisable() {
|
|
1247
|
+
warning2("Telemetry disabled");
|
|
1248
|
+
info("No usage data will be collected");
|
|
1249
|
+
}
|
|
1250
|
+
async function telemetryStatus() {
|
|
1251
|
+
info("Checking telemetry status...");
|
|
1252
|
+
info("Telemetry status: unknown (not implemented yet)");
|
|
1253
|
+
}
|
|
1254
|
+
|
|
1255
|
+
// src/commands/update.command.ts
|
|
1256
|
+
init_esm_shims();
|
|
1257
|
+
async function update(options = {}) {
|
|
1258
|
+
if (options.dryRun) {
|
|
1259
|
+
info("Dry run mode: Would update SDK to latest version");
|
|
1260
|
+
return;
|
|
1261
|
+
}
|
|
1262
|
+
info("Checking for SDK updates...");
|
|
1263
|
+
success("SDK is up to date");
|
|
1264
|
+
}
|
|
1265
|
+
async function check() {
|
|
1266
|
+
info("Checking for SDK updates...");
|
|
1267
|
+
success("No updates available");
|
|
1268
|
+
}
|
|
1269
|
+
|
|
1270
|
+
// src/cli.ts
|
|
1271
|
+
var program = new Command();
|
|
1272
|
+
program.addHelpText("beforeAll", getBanner());
|
|
1273
|
+
program.name("oxlayer").description("OxLayer SDK Installer - Download and install private SDK packages").version("0.0.1");
|
|
1274
|
+
program.command("login").description("Authenticate with OxLayer Control Panel").option("-k, --key <key>", "API key (will prompt if not provided)").option("-e, --environment <env>", "Environment (development|staging|production)", "development").action(async (options) => {
|
|
1275
|
+
trackCommand("login");
|
|
1276
|
+
await login(options);
|
|
1277
|
+
});
|
|
1278
|
+
program.command("status").description("Show installation and authentication status").option("-v, --verbose", "Show detailed information").action(async (options) => {
|
|
1279
|
+
trackCommand("status");
|
|
1280
|
+
await status(options);
|
|
1281
|
+
});
|
|
1282
|
+
program.command("install [version]").description("Install SDK packages").option("-p, --packages <packages...>", "Specific packages to install").option("-e, --environment <env>", "Environment (development|staging|production)", "development").option("--dry-run", "Show what would be installed without installing").option("-f, --force", "Force reinstall even if already installed").option("--save", "Add to dependencies").option("--save-dev", "Add to devDependencies").action(async (version, options) => {
|
|
1283
|
+
trackCommand("install", { sdkVersion: version });
|
|
1284
|
+
await install(version || "latest", options);
|
|
1285
|
+
});
|
|
1286
|
+
program.command("resolve").description("Resolve capabilities for current project").option("-e, --environment <env>", "Environment (development|staging|production)", "development").option("-v, --verbose", "Show usage examples").action(async (options) => {
|
|
1287
|
+
trackCommand("resolve");
|
|
1288
|
+
await resolve(options);
|
|
1289
|
+
});
|
|
1290
|
+
program.command("logout").description("Remove stored API key").action(async () => {
|
|
1291
|
+
trackCommand("logout");
|
|
1292
|
+
await logout();
|
|
1293
|
+
});
|
|
1294
|
+
program.command("doctor").description("Run diagnostics to troubleshoot issues").option("-v, --verbose", "Show detailed diagnostic information").option("--fix", "Attempt to fix common issues automatically").action(async (options) => {
|
|
1295
|
+
trackCommand("doctor");
|
|
1296
|
+
await doctor(options);
|
|
1297
|
+
});
|
|
1298
|
+
program.command("diff [from-version] [to-version]").description("Compare capabilities between SDK versions").option("-v, --verbose", "Show detailed changes").option("--format <format>", "Output format (text|json)", "text").action(async (fromVersion, toVersion, options) => {
|
|
1299
|
+
trackCommand("diff");
|
|
1300
|
+
if (!fromVersion) {
|
|
1301
|
+
await showLatest();
|
|
1302
|
+
} else {
|
|
1303
|
+
await diff(fromVersion, toVersion || "latest", options);
|
|
1304
|
+
}
|
|
1305
|
+
});
|
|
1306
|
+
program.command("update").description("Update SDK to the latest version").option("--dry-run", "Show what would be updated without installing").action(async (options) => {
|
|
1307
|
+
trackCommand("update");
|
|
1308
|
+
await update(options);
|
|
1309
|
+
});
|
|
1310
|
+
program.command("check").description("Quick check for SDK updates").action(async () => {
|
|
1311
|
+
await check();
|
|
1312
|
+
});
|
|
1313
|
+
var telemetryCmd = program.command("telemetry").description("Manage telemetry settings");
|
|
1314
|
+
telemetryCmd.command("enable").description("Enable anonymous usage tracking").action(async () => {
|
|
1315
|
+
await telemetryEnable();
|
|
1316
|
+
});
|
|
1317
|
+
telemetryCmd.command("disable").description("Disable anonymous usage tracking").action(async () => {
|
|
1318
|
+
await telemetryDisable();
|
|
1319
|
+
});
|
|
1320
|
+
telemetryCmd.command("status").description("Show telemetry status").action(async () => {
|
|
1321
|
+
await telemetryStatus();
|
|
1322
|
+
});
|
|
1323
|
+
program.parseAsync(process.argv).catch((err) => {
|
|
1324
|
+
console.error(err);
|
|
1325
|
+
trackError("cli", "parse_error");
|
|
1326
|
+
process.exit(1);
|
|
1327
|
+
});
|
|
1328
|
+
//# sourceMappingURL=cli.js.map
|