deepspace 0.2.3 → 0.2.5

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/dist/cli.js CHANGED
@@ -1,8 +1,11 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/cli/cli.ts
4
- import { defineCommand as defineCommand10, runMain } from "citty";
5
- import { execSync as execSync4 } from "child_process";
4
+ import { defineCommand as defineCommand13, runMain } from "citty";
5
+ import { execSync as execSync5 } from "child_process";
6
+ import { readFileSync as readFileSync9, existsSync as existsSync11 } from "fs";
7
+ import { dirname as dirname2, join as join12 } from "path";
8
+ import { fileURLToPath } from "url";
6
9
 
7
10
  // src/cli/commands/login.ts
8
11
  import { defineCommand } from "citty";
@@ -201,7 +204,7 @@ function openBrowser(url) {
201
204
  });
202
205
  }
203
206
  function sleep(ms) {
204
- return new Promise((resolve5) => setTimeout(resolve5, ms));
207
+ return new Promise((resolve6) => setTimeout(resolve6, ms));
205
208
  }
206
209
  async function doEmailLogin(email, password) {
207
210
  const res = await fetch(`${AUTH_URL}/api/auth/sign-in/email`, {
@@ -365,7 +368,7 @@ var dev_default = defineCommand3({
365
368
  console.log("Starting dev server...\n");
366
369
  const vite = spawn(
367
370
  "npx",
368
- ["vite", "--port", String(port), "--strictPort"],
371
+ ["vite", "--port", String(port), "--strictPort", "--host"],
369
372
  {
370
373
  cwd: appDir,
371
374
  stdio: "inherit",
@@ -497,11 +500,14 @@ function ensurePlaywright(appDir) {
497
500
  console.log("Installing Playwright...");
498
501
  execSync("npm install -D @playwright/test", { cwd: appDir, stdio: "pipe" });
499
502
  }
500
- try {
501
- execSync("npx playwright install --dry-run chromium", { cwd: appDir, stdio: "pipe" });
502
- } catch {
503
- console.log("Installing Chromium for Playwright...");
504
- execSync("npx playwright install chromium", { cwd: appDir, stdio: "inherit" });
503
+ const isLinux = process.platform === "linux";
504
+ const isRoot = isLinux && typeof process.getuid === "function" && process.getuid() === 0;
505
+ const args = isRoot ? ["install", "--with-deps", "chromium"] : ["install", "chromium"];
506
+ const result = spawnSync("npx", ["playwright", ...args], { cwd: appDir, stdio: "inherit" });
507
+ if (result.status !== 0) {
508
+ console.error("\nPlaywright install failed. On Linux, system libs may be missing \u2014 try:");
509
+ console.error(" sudo npx playwright install --with-deps chromium");
510
+ process.exit(1);
505
511
  }
506
512
  }
507
513
  function resolvePort2(arg) {
@@ -1112,8 +1118,715 @@ var add_default = defineCommand9({
1112
1118
  }
1113
1119
  });
1114
1120
 
1121
+ // src/cli/commands/domain.ts
1122
+ import { defineCommand as defineCommand10 } from "citty";
1123
+ import { execSync as execSync4 } from "child_process";
1124
+
1125
+ // src/cli/lib/app-context.ts
1126
+ import { existsSync as existsSync10, readFileSync as readFileSync7 } from "fs";
1127
+ import { join as join11, resolve as resolve5 } from "path";
1128
+ import { parse as parseToml4 } from "smol-toml";
1129
+ function detectAppName(cwd = process.cwd()) {
1130
+ const wranglerPath = join11(resolve5(cwd), "wrangler.toml");
1131
+ if (!existsSync10(wranglerPath)) return null;
1132
+ try {
1133
+ const cfg = parseToml4(readFileSync7(wranglerPath, "utf-8"));
1134
+ return typeof cfg.name === "string" && cfg.name.length > 0 ? cfg.name : null;
1135
+ } catch {
1136
+ return null;
1137
+ }
1138
+ }
1139
+ function requireAppName(explicit, cwd) {
1140
+ if (explicit) return explicit;
1141
+ const detected = detectAppName(cwd);
1142
+ if (detected) return detected;
1143
+ throw new Error(
1144
+ "No app specified. Pass --app <name>, or run from an app directory with a wrangler.toml."
1145
+ );
1146
+ }
1147
+
1148
+ // src/cli/commands/domain.ts
1149
+ var API_URL = process.env.DEEPSPACE_API_URL ?? ENVS.prod.api;
1150
+ async function api(token, path, init) {
1151
+ const res = await fetch(`${API_URL}${path}`, {
1152
+ ...init,
1153
+ headers: {
1154
+ Authorization: `Bearer ${token}`,
1155
+ "Content-Type": "application/json",
1156
+ ...init?.headers ?? {}
1157
+ }
1158
+ });
1159
+ const text = await res.text();
1160
+ if (!res.ok) {
1161
+ let msg = text;
1162
+ try {
1163
+ msg = JSON.parse(text).error ?? text;
1164
+ } catch {
1165
+ }
1166
+ throw new Error(`API ${path} (${res.status}): ${msg}`);
1167
+ }
1168
+ return JSON.parse(text);
1169
+ }
1170
+ function fmtCents(cents) {
1171
+ if (cents === null || cents === void 0) return "\u2014";
1172
+ return `$${(cents / 100).toFixed(2)}`;
1173
+ }
1174
+ function fmtDate(iso) {
1175
+ if (!iso) return "\u2014";
1176
+ return iso.slice(0, 10);
1177
+ }
1178
+ async function confirm2(message) {
1179
+ if (!process.stdin.isTTY) {
1180
+ throw new Error(`${message} \u2014 pass --yes to confirm non-interactively`);
1181
+ }
1182
+ process.stdout.write(`${message} [y/N] `);
1183
+ return new Promise((resolve6) => {
1184
+ process.stdin.setEncoding("utf-8");
1185
+ process.stdin.once("data", (data) => {
1186
+ const answer = data.toString().trim().toLowerCase();
1187
+ resolve6(answer === "y" || answer === "yes");
1188
+ });
1189
+ });
1190
+ }
1191
+ var search = defineCommand10({
1192
+ meta: { name: "search", description: "Search for available domains" },
1193
+ args: {
1194
+ query: { type: "positional", description: "Domain or keyword", required: true },
1195
+ limit: { type: "string", description: "Max results (default 10)", default: "10" },
1196
+ json: { type: "boolean", description: "Emit JSON instead of a table" }
1197
+ },
1198
+ async run({ args }) {
1199
+ const token = await ensureToken();
1200
+ const limit = parseInt(args.limit ?? "10", 10) || 10;
1201
+ const result = await api(
1202
+ token,
1203
+ `/api/domains/search?q=${encodeURIComponent(args.query)}&limit=${limit}`
1204
+ );
1205
+ if (args.json) {
1206
+ process.stdout.write(JSON.stringify(result, null, 2) + "\n");
1207
+ return;
1208
+ }
1209
+ if (result.domains.length === 0) {
1210
+ console.log("No matches.");
1211
+ return;
1212
+ }
1213
+ for (const d of result.domains) {
1214
+ const tag = d.registrable ? "\u2713" : "\u2717";
1215
+ const price = d.registrable ? `${fmtCents(d.chargedCents)}/yr` : d.reason ?? "\u2014";
1216
+ const slowFlag = d.registrar && d.registrar !== "cloudflare" ? " (15-60 min provisioning)" : "";
1217
+ console.log(`${tag} ${d.name.padEnd(40)} ${price}${slowFlag}`);
1218
+ }
1219
+ }
1220
+ });
1221
+ var buy = defineCommand10({
1222
+ meta: { name: "buy", description: "Buy a domain and attach it to an app" },
1223
+ args: {
1224
+ domain: { type: "positional", description: "Domain to buy", required: true },
1225
+ app: { type: "string", description: "App to attach (defaults to ./wrangler.toml)" },
1226
+ yes: { type: "boolean", description: "Skip the confirmation prompt", default: false },
1227
+ "no-open": { type: "boolean", description: "Do not open browser; print Stripe URL", default: false },
1228
+ "no-wait": { type: "boolean", description: "Exit after creating session; do not poll until active", default: false },
1229
+ json: { type: "boolean", description: "Emit JSON to stdout", default: false }
1230
+ },
1231
+ async run({ args }) {
1232
+ const token = await ensureToken();
1233
+ const appName = requireAppName(args.app);
1234
+ const priceCheck = await api(token, "/api/domains/check", {
1235
+ method: "POST",
1236
+ body: JSON.stringify({ domains: [args.domain] })
1237
+ });
1238
+ const result = priceCheck.domains[0];
1239
+ if (!result || !result.registrable) {
1240
+ console.error(`Not available: ${result?.reason ?? "unknown"}`);
1241
+ process.exit(1);
1242
+ }
1243
+ const price = fmtCents(result.chargedCents);
1244
+ const expectedTime = result.registrar === "cloudflare" ? "~60-90 seconds" : "15-60 minutes (registry NS propagation)";
1245
+ if (!args.yes) {
1246
+ const ok = await confirm2(
1247
+ `Buy ${args.domain} for ${price}/yr (auto-renews; non-refundable), attach to ${appName}? Provisioning takes ${expectedTime}.`
1248
+ );
1249
+ if (!ok) {
1250
+ console.log("Cancelled.");
1251
+ return;
1252
+ }
1253
+ }
1254
+ const checkout = await api(
1255
+ token,
1256
+ "/api/domains/checkout",
1257
+ {
1258
+ method: "POST",
1259
+ body: JSON.stringify({ domain: args.domain, appName })
1260
+ }
1261
+ );
1262
+ if (args.json) {
1263
+ process.stdout.write(JSON.stringify({ ...checkout, expectedTime, registrar: result.registrar }, null, 2) + "\n");
1264
+ } else {
1265
+ console.log(`Stripe Checkout: ${checkout.url}`);
1266
+ }
1267
+ if (!args["no-open"] && process.stdin.isTTY) {
1268
+ openBrowser2(checkout.url);
1269
+ }
1270
+ if (args["no-wait"]) return;
1271
+ const timeoutMs = result.registrar === "cloudflare" ? 5 * 60 * 1e3 : 60 * 60 * 1e3;
1272
+ if (!args.json) {
1273
+ console.log(`Waiting for payment & provisioning (up to ${expectedTime}). Press Ctrl-C anytime \u2014`);
1274
+ console.log(`provisioning continues server-side; check later with \`deepspace domain status ${args.domain}\`.`);
1275
+ }
1276
+ const deadline = Date.now() + timeoutMs;
1277
+ let lastStatus = "";
1278
+ while (Date.now() < deadline) {
1279
+ await new Promise((r) => setTimeout(r, 5e3));
1280
+ try {
1281
+ const detail = await api(
1282
+ token,
1283
+ `/api/domains/${checkout.purchaseId}`
1284
+ );
1285
+ if (detail.domain.status !== lastStatus) {
1286
+ lastStatus = detail.domain.status;
1287
+ if (!args.json) console.log(` \u2192 ${lastStatus}`);
1288
+ }
1289
+ if (detail.domain.status === "active") {
1290
+ if (args.json) {
1291
+ process.stdout.write(JSON.stringify({ ...checkout, status: "active", domain: args.domain }, null, 2) + "\n");
1292
+ } else {
1293
+ console.log(`\u2713 ${args.domain} is live and pointing at ${appName}`);
1294
+ }
1295
+ return;
1296
+ }
1297
+ if (detail.domain.status.startsWith("failed:")) {
1298
+ console.error(`Provisioning failed: ${detail.domain.statusError ?? detail.domain.status}`);
1299
+ process.exit(1);
1300
+ }
1301
+ } catch (err) {
1302
+ if (!args.json) console.error(`(poll error: ${err instanceof Error ? err.message : String(err)})`);
1303
+ }
1304
+ }
1305
+ console.error(`Polling timed out. Provisioning may still be in progress; check with:`);
1306
+ console.error(` deepspace domain status ${args.domain}`);
1307
+ process.exit(1);
1308
+ }
1309
+ });
1310
+ var list2 = defineCommand10({
1311
+ meta: { name: "list", description: "List your domains" },
1312
+ args: {
1313
+ json: { type: "boolean", description: "Emit JSON" }
1314
+ },
1315
+ async run({ args }) {
1316
+ const token = await ensureToken();
1317
+ const result = await api(token, "/api/domains");
1318
+ if (args.json) {
1319
+ process.stdout.write(JSON.stringify(result, null, 2) + "\n");
1320
+ return;
1321
+ }
1322
+ if (result.domains.length === 0) {
1323
+ console.log("No domains. Try `deepspace domain search <name>`.");
1324
+ return;
1325
+ }
1326
+ console.log(`DOMAIN APP STATUS EXPIRES AUTO-RENEW`);
1327
+ for (const d of result.domains) {
1328
+ console.log(
1329
+ `${d.domain.padEnd(35)} ${d.appName.padEnd(20)} ${d.status.padEnd(20)} ${fmtDate(d.expiresAt).padEnd(12)} ${d.autoRenew ? "on" : "off"}`
1330
+ );
1331
+ }
1332
+ }
1333
+ });
1334
+ var status = defineCommand10({
1335
+ meta: { name: "status", description: "Show details for one domain" },
1336
+ args: {
1337
+ domain: { type: "positional", description: "Domain", required: true },
1338
+ json: { type: "boolean" }
1339
+ },
1340
+ async run({ args }) {
1341
+ const token = await ensureToken();
1342
+ const all = await api(token, "/api/domains");
1343
+ const found = all.domains.find((d) => d.domain === args.domain);
1344
+ if (!found) {
1345
+ console.error(`No domain ${args.domain} in your account`);
1346
+ process.exit(1);
1347
+ }
1348
+ if (args.json) {
1349
+ process.stdout.write(JSON.stringify(found, null, 2) + "\n");
1350
+ return;
1351
+ }
1352
+ console.log(`Domain: ${found.domain}`);
1353
+ console.log(`Status: ${found.status}${found.statusError ? ` (${found.statusError})` : ""}`);
1354
+ console.log(`Attached app: ${found.appName}`);
1355
+ console.log(`Registrar: ${found.registrar}`);
1356
+ console.log(`Registered: ${fmtDate(found.registeredAt)}`);
1357
+ console.log(`Expires: ${fmtDate(found.expiresAt)}`);
1358
+ console.log(`Auto-renew: ${found.autoRenew ? "on" : "off"}`);
1359
+ console.log(`Charged: ${fmtCents(found.chargedCents)}/yr`);
1360
+ }
1361
+ });
1362
+ var attach = defineCommand10({
1363
+ meta: { name: "attach", description: "Re-point a domain at a different app" },
1364
+ args: {
1365
+ domain: { type: "positional", description: "Domain to re-point", required: true },
1366
+ app: { type: "string", description: "Target app (defaults to ./wrangler.toml)" },
1367
+ json: { type: "boolean" }
1368
+ },
1369
+ async run({ args }) {
1370
+ const token = await ensureToken();
1371
+ const targetApp = requireAppName(args.app);
1372
+ const all = await api(token, "/api/domains");
1373
+ const found = all.domains.find((d) => d.domain === args.domain);
1374
+ if (!found) {
1375
+ console.error(`No domain ${args.domain} in your account`);
1376
+ process.exit(1);
1377
+ }
1378
+ const result = await api(
1379
+ token,
1380
+ `/api/domains/${found.id}/reattach`,
1381
+ {
1382
+ method: "POST",
1383
+ body: JSON.stringify({ appName: targetApp })
1384
+ }
1385
+ );
1386
+ if (args.json) {
1387
+ process.stdout.write(JSON.stringify(result, null, 2) + "\n");
1388
+ return;
1389
+ }
1390
+ console.log(`\u2713 ${args.domain} now points at ${targetApp}`);
1391
+ }
1392
+ });
1393
+ var detach = defineCommand10({
1394
+ meta: {
1395
+ name: "detach",
1396
+ description: "Stop routing the domain (keeps the registration; auto-renew unchanged)"
1397
+ },
1398
+ args: {
1399
+ domain: { type: "positional", description: "Domain to detach", required: true },
1400
+ yes: { type: "boolean", description: "Skip the confirmation prompt" }
1401
+ },
1402
+ async run({ args }) {
1403
+ const token = await ensureToken();
1404
+ const all = await api(token, "/api/domains");
1405
+ const found = all.domains.find((d) => d.domain === args.domain);
1406
+ if (!found) {
1407
+ console.error(`No domain ${args.domain} in your account`);
1408
+ process.exit(1);
1409
+ }
1410
+ if (!args.yes) {
1411
+ const ok = await confirm2(
1412
+ `Detach ${args.domain}? Routing will stop; the domain stays registered (auto-renew is unchanged).`
1413
+ );
1414
+ if (!ok) {
1415
+ console.log("Cancelled.");
1416
+ return;
1417
+ }
1418
+ }
1419
+ await api(token, `/api/domains/${found.id}`, { method: "DELETE" });
1420
+ console.log(`\u2713 ${args.domain} detached. Use \`deepspace domain attach\` to re-route, or \`renew --auto off\` to stop auto-renewal.`);
1421
+ }
1422
+ });
1423
+ var renew = defineCommand10({
1424
+ meta: { name: "renew", description: "Toggle auto-renewal at the registrar" },
1425
+ args: {
1426
+ domain: { type: "positional", description: "Domain", required: true },
1427
+ auto: { type: "string", description: '"on" or "off"', required: true }
1428
+ },
1429
+ async run({ args }) {
1430
+ if (args.auto !== "on" && args.auto !== "off") {
1431
+ console.error('--auto must be "on" or "off"');
1432
+ process.exit(1);
1433
+ }
1434
+ const token = await ensureToken();
1435
+ const all = await api(token, "/api/domains");
1436
+ const found = all.domains.find((d) => d.domain === args.domain);
1437
+ if (!found) {
1438
+ console.error(`No domain ${args.domain} in your account`);
1439
+ process.exit(1);
1440
+ }
1441
+ const enabled = args.auto === "on";
1442
+ await api(token, `/api/domains/${found.id}/auto-renew`, {
1443
+ method: "POST",
1444
+ body: JSON.stringify({ autoRenew: enabled })
1445
+ });
1446
+ console.log(`\u2713 ${args.domain} auto-renew ${enabled ? "enabled" : "disabled"}`);
1447
+ }
1448
+ });
1449
+ function openBrowser2(url) {
1450
+ try {
1451
+ if (process.platform === "darwin") execSync4(`open ${JSON.stringify(url)}`);
1452
+ else if (process.platform === "win32") execSync4(`start "" ${JSON.stringify(url)}`);
1453
+ else execSync4(`xdg-open ${JSON.stringify(url)} 2>/dev/null || true`);
1454
+ } catch {
1455
+ }
1456
+ }
1457
+ var domain_default = defineCommand10({
1458
+ meta: { name: "domain", description: "Buy and manage custom domains" },
1459
+ subCommands: { search, buy, list: list2, status, attach, detach, renew }
1460
+ });
1461
+
1462
+ // src/cli/commands/integrations.ts
1463
+ import { defineCommand as defineCommand11 } from "citty";
1464
+
1465
+ // src/cli/commands/_invoke-impl.ts
1466
+ import { readFileSync as readFileSync8 } from "fs";
1467
+ var API_URL2 = process.env.DEEPSPACE_API_URL ?? ENVS.prod.api;
1468
+ var DEFAULT_TIMEOUT_MS = 12e4;
1469
+ function parseTarget(target) {
1470
+ if (!target || typeof target !== "string") {
1471
+ throw new Error("Missing target. Expected '<integration>/<endpoint>' (e.g. 'openai/chat-completion').");
1472
+ }
1473
+ const parts = target.split("/");
1474
+ if (parts.length !== 2 || !parts[0] || !parts[1]) {
1475
+ throw new Error(`Bad target '${target}'. Expected '<integration>/<endpoint>' (e.g. 'openai/chat-completion').`);
1476
+ }
1477
+ return { integration: parts[0], endpoint: parts[1] };
1478
+ }
1479
+ function resolveBody(opts) {
1480
+ if (opts.body != null && opts.bodyFile != null) {
1481
+ throw new Error("Pass either --body or --body-file, not both.");
1482
+ }
1483
+ let raw;
1484
+ if (opts.body != null) {
1485
+ raw = opts.body;
1486
+ } else if (opts.bodyFile != null) {
1487
+ raw = opts.bodyFile === "-" ? readFileSync8(0, "utf-8") : readFileSync8(opts.bodyFile, "utf-8");
1488
+ } else {
1489
+ return "{}";
1490
+ }
1491
+ try {
1492
+ JSON.parse(raw);
1493
+ } catch (err) {
1494
+ const msg = err instanceof Error ? err.message : "invalid JSON";
1495
+ throw new Error(`Body is not valid JSON: ${msg}`);
1496
+ }
1497
+ return raw;
1498
+ }
1499
+ function flushAndExit(code) {
1500
+ return new Promise(() => {
1501
+ process.stdout.write("", () => process.exit(code));
1502
+ });
1503
+ }
1504
+ async function fetchCatalog() {
1505
+ const res = await fetch(`${API_URL2}/api/integrations`);
1506
+ if (!res.ok) {
1507
+ throw new Error(`Failed to fetch integration catalog (${res.status})`);
1508
+ }
1509
+ return await res.json();
1510
+ }
1511
+ function findEndpoint(catalog, integration, endpoint) {
1512
+ const endpoints = catalog.integrations[integration];
1513
+ if (!endpoints) return null;
1514
+ return endpoints.find((e) => e.endpoint === endpoint) ?? null;
1515
+ }
1516
+ function formatCurrency(value, currency) {
1517
+ if (currency === "USD") return `$${value}`;
1518
+ return `${value} ${currency}`;
1519
+ }
1520
+ async function runList(args) {
1521
+ const catalog = await fetchCatalog();
1522
+ if (args.json) {
1523
+ process.stdout.write(JSON.stringify(catalog) + "\n");
1524
+ await flushAndExit(0);
1525
+ }
1526
+ const names = Object.keys(catalog.integrations).sort();
1527
+ if (names.length === 0) {
1528
+ console.log("No integrations available.");
1529
+ return;
1530
+ }
1531
+ for (const name of names) {
1532
+ console.log(name);
1533
+ const endpoints = [...catalog.integrations[name]].sort((a, b) => a.endpoint.localeCompare(b.endpoint));
1534
+ const widest = Math.max(...endpoints.map((e) => e.endpoint.length));
1535
+ for (const ep of endpoints) {
1536
+ const pad = ep.endpoint.padEnd(widest);
1537
+ const cost = formatCurrency(ep.billing.baseCost, ep.billing.currency);
1538
+ console.log(` ${pad} ${ep.billing.model.padEnd(12)} ${cost}`);
1539
+ }
1540
+ console.log();
1541
+ }
1542
+ console.log("Run 'deepspace integrations info <integration>/<endpoint>' for the request schema.");
1543
+ }
1544
+ async function runInfo(args) {
1545
+ const { integration, endpoint } = parseTarget(args.target);
1546
+ const catalog = await fetchCatalog();
1547
+ const info2 = findEndpoint(catalog, integration, endpoint);
1548
+ if (!info2) {
1549
+ const available = catalog.integrations[integration];
1550
+ if (!available) {
1551
+ const names = Object.keys(catalog.integrations).sort().join(", ");
1552
+ throw new Error(`Unknown integration '${integration}'. Available: ${names}`);
1553
+ }
1554
+ const endpoints = available.map((e) => e.endpoint).join(", ");
1555
+ throw new Error(`Unknown endpoint '${endpoint}' for '${integration}'. Available: ${endpoints}`);
1556
+ }
1557
+ if (args.json) {
1558
+ process.stdout.write(JSON.stringify(info2) + "\n");
1559
+ await flushAndExit(0);
1560
+ }
1561
+ console.log(`${integration}/${endpoint}`);
1562
+ console.log(` billing: ${info2.billing.model}, ${formatCurrency(info2.billing.baseCost, info2.billing.currency)} per call`);
1563
+ console.log();
1564
+ console.log("Input schema:");
1565
+ console.log(info2.inputSchema ? JSON.stringify(info2.inputSchema, null, 2) : " (no schema registered)");
1566
+ console.log();
1567
+ console.log("Example body:");
1568
+ console.log(info2.example ? JSON.stringify(info2.example, null, 2) : " (no example available)");
1569
+ }
1570
+ async function runInvoke(args) {
1571
+ const { integration, endpoint } = parseTarget(args.target);
1572
+ const body = resolveBody({ body: args.body, bodyFile: args.bodyFile });
1573
+ const timeoutMs = args.timeout ?? DEFAULT_TIMEOUT_MS;
1574
+ let jwt;
1575
+ try {
1576
+ jwt = await ensureToken();
1577
+ } catch (err) {
1578
+ const msg = err instanceof Error ? err.message : String(err);
1579
+ throw new Error(msg);
1580
+ }
1581
+ const controller = new AbortController();
1582
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
1583
+ const startedAt = Date.now();
1584
+ let res;
1585
+ try {
1586
+ res = await fetch(`${API_URL2}/api/integrations/${integration}/${endpoint}`, {
1587
+ method: "POST",
1588
+ headers: {
1589
+ "Content-Type": "application/json",
1590
+ Authorization: `Bearer ${jwt}`
1591
+ },
1592
+ body,
1593
+ signal: controller.signal
1594
+ });
1595
+ } catch (err) {
1596
+ if (err instanceof Error && err.name === "AbortError") {
1597
+ throw new Error(`Request timed out after ${timeoutMs}ms`);
1598
+ }
1599
+ throw new Error(err instanceof Error ? err.message : "Request failed");
1600
+ } finally {
1601
+ clearTimeout(timer);
1602
+ }
1603
+ const elapsed = Date.now() - startedAt;
1604
+ let payload;
1605
+ try {
1606
+ payload = await res.json();
1607
+ } catch {
1608
+ throw new Error(`Request failed (${res.status}) with non-JSON response`);
1609
+ }
1610
+ if (args.json) {
1611
+ process.stdout.write(JSON.stringify(payload) + "\n");
1612
+ await flushAndExit(payload?.success === false || !res.ok ? 1 : 0);
1613
+ }
1614
+ const ok = payload?.success !== false && res.ok;
1615
+ if (ok) {
1616
+ const data = "data" in payload ? payload.data : payload;
1617
+ console.log(JSON.stringify(data, null, 2));
1618
+ console.error(`
1619
+ \u2713 ${integration}/${endpoint} (${elapsed}ms)`);
1620
+ return;
1621
+ }
1622
+ const errMsg = payload.error ?? `Request failed (${res.status})`;
1623
+ console.error(`\u2717 ${integration}/${endpoint} (${res.status}, ${elapsed}ms): ${errMsg}`);
1624
+ if (Array.isArray(payload.issues)) {
1625
+ for (const issue of payload.issues) {
1626
+ const path = issue.path?.length ? issue.path.join(".") : "(root)";
1627
+ console.error(` - ${path}: ${issue.message}`);
1628
+ }
1629
+ }
1630
+ if (res.status === 401) {
1631
+ console.error("\nHint: run 'deepspace login' to authenticate.");
1632
+ }
1633
+ process.exit(1);
1634
+ }
1635
+
1636
+ // src/cli/commands/integrations.ts
1637
+ var list3 = defineCommand11({
1638
+ meta: {
1639
+ name: "list",
1640
+ description: "List all available integrations"
1641
+ },
1642
+ args: {
1643
+ json: {
1644
+ type: "boolean",
1645
+ description: "Print raw JSON (machine-readable)",
1646
+ default: false
1647
+ }
1648
+ },
1649
+ async run({ args }) {
1650
+ try {
1651
+ await runList({ json: args.json });
1652
+ } catch (err) {
1653
+ console.error(err instanceof Error ? err.message : String(err));
1654
+ process.exit(1);
1655
+ }
1656
+ }
1657
+ });
1658
+ var info = defineCommand11({
1659
+ meta: {
1660
+ name: "info",
1661
+ description: "Print schema + example body for an integration endpoint"
1662
+ },
1663
+ args: {
1664
+ target: {
1665
+ type: "positional",
1666
+ description: "<integration>/<endpoint> (e.g. 'openai/chat-completion')",
1667
+ required: true
1668
+ },
1669
+ json: {
1670
+ type: "boolean",
1671
+ description: "Print raw JSON (machine-readable)",
1672
+ default: false
1673
+ }
1674
+ },
1675
+ async run({ args }) {
1676
+ try {
1677
+ await runInfo({ target: args.target, json: args.json });
1678
+ } catch (err) {
1679
+ console.error(err instanceof Error ? err.message : String(err));
1680
+ process.exit(1);
1681
+ }
1682
+ }
1683
+ });
1684
+ var invoke = defineCommand11({
1685
+ meta: {
1686
+ name: "invoke",
1687
+ description: "Invoke a platform integration as the logged-in user"
1688
+ },
1689
+ args: {
1690
+ target: {
1691
+ type: "positional",
1692
+ description: "<integration>/<endpoint> (e.g. 'openai/chat-completion')",
1693
+ required: true
1694
+ },
1695
+ body: {
1696
+ type: "string",
1697
+ alias: "d",
1698
+ description: "Inline JSON body",
1699
+ required: false
1700
+ },
1701
+ "body-file": {
1702
+ type: "string",
1703
+ alias: "f",
1704
+ description: "Read JSON body from file (use - for stdin)",
1705
+ required: false
1706
+ },
1707
+ json: {
1708
+ type: "boolean",
1709
+ description: "Print only the response JSON (machine-readable)",
1710
+ default: false
1711
+ },
1712
+ timeout: {
1713
+ type: "string",
1714
+ description: "Request timeout in milliseconds (default: 120000)",
1715
+ required: false
1716
+ }
1717
+ },
1718
+ async run({ args }) {
1719
+ try {
1720
+ const timeout = args.timeout != null ? Number(args.timeout) : void 0;
1721
+ if (timeout != null && (!Number.isFinite(timeout) || timeout <= 0)) {
1722
+ throw new Error(`Invalid --timeout '${args.timeout}'. Must be a positive number of milliseconds.`);
1723
+ }
1724
+ await runInvoke({
1725
+ target: args.target,
1726
+ body: args.body,
1727
+ bodyFile: args["body-file"],
1728
+ json: args.json,
1729
+ timeout
1730
+ });
1731
+ } catch (err) {
1732
+ console.error(err instanceof Error ? err.message : String(err));
1733
+ process.exit(1);
1734
+ }
1735
+ }
1736
+ });
1737
+ var integrations_default = defineCommand11({
1738
+ meta: {
1739
+ name: "integrations",
1740
+ description: "List, inspect, and invoke platform integrations"
1741
+ },
1742
+ subCommands: {
1743
+ list: list3,
1744
+ info,
1745
+ invoke
1746
+ }
1747
+ });
1748
+
1749
+ // src/cli/commands/invoke.ts
1750
+ import { defineCommand as defineCommand12 } from "citty";
1751
+ var invoke_default = defineCommand12({
1752
+ meta: {
1753
+ name: "invoke",
1754
+ description: "Invoke a platform integration as the logged-in user"
1755
+ },
1756
+ args: {
1757
+ target: {
1758
+ type: "positional",
1759
+ description: "<integration>/<endpoint> (e.g. 'openai/chat-completion')",
1760
+ required: false
1761
+ },
1762
+ body: {
1763
+ type: "string",
1764
+ alias: "d",
1765
+ description: "Inline JSON body",
1766
+ required: false
1767
+ },
1768
+ "body-file": {
1769
+ type: "string",
1770
+ alias: "f",
1771
+ description: "Read JSON body from file (use - for stdin)",
1772
+ required: false
1773
+ },
1774
+ json: {
1775
+ type: "boolean",
1776
+ description: "Print only the response JSON (machine-readable)",
1777
+ default: false
1778
+ },
1779
+ info: {
1780
+ type: "boolean",
1781
+ description: "Print schema + example body for the endpoint, then exit",
1782
+ default: false
1783
+ },
1784
+ list: {
1785
+ type: "boolean",
1786
+ description: "Print all available integrations, then exit",
1787
+ default: false
1788
+ },
1789
+ timeout: {
1790
+ type: "string",
1791
+ description: "Request timeout in milliseconds (default: 120000)",
1792
+ required: false
1793
+ }
1794
+ },
1795
+ async run({ args }) {
1796
+ try {
1797
+ if (args.list) {
1798
+ await runList({ json: args.json });
1799
+ return;
1800
+ }
1801
+ if (args.info) {
1802
+ await runInfo({ target: args.target, json: args.json });
1803
+ return;
1804
+ }
1805
+ const timeout = args.timeout != null ? Number(args.timeout) : void 0;
1806
+ if (timeout != null && (!Number.isFinite(timeout) || timeout <= 0)) {
1807
+ throw new Error(`Invalid --timeout '${args.timeout}'. Must be a positive number of milliseconds.`);
1808
+ }
1809
+ await runInvoke({
1810
+ target: args.target,
1811
+ body: args.body,
1812
+ bodyFile: args["body-file"],
1813
+ json: args.json,
1814
+ timeout
1815
+ });
1816
+ } catch (err) {
1817
+ console.error(err instanceof Error ? err.message : String(err));
1818
+ process.exit(1);
1819
+ }
1820
+ }
1821
+ });
1822
+
1115
1823
  // src/cli/cli.ts
1116
- var create2 = defineCommand10({
1824
+ var __dirname = dirname2(fileURLToPath(import.meta.url));
1825
+ var pkg = JSON.parse(readFileSync9(join12(__dirname, "..", "package.json"), "utf-8"));
1826
+ if (process.platform === "linux" && !process.env.SSL_CERT_FILE && existsSync11("/etc/ssl/certs/ca-certificates.crt")) {
1827
+ process.env.SSL_CERT_FILE = "/etc/ssl/certs/ca-certificates.crt";
1828
+ }
1829
+ var create2 = defineCommand13({
1117
1830
  meta: {
1118
1831
  name: "create",
1119
1832
  description: "Create a new DeepSpace app"
@@ -1129,13 +1842,13 @@ var create2 = defineCommand10({
1129
1842
  const name = args.name ? ` ${args.name}` : "";
1130
1843
  console.log(`Running: npm create deepspace${name}
1131
1844
  `);
1132
- execSync4(`npm create deepspace@latest${name}`, { stdio: "inherit" });
1845
+ execSync5(`npm create deepspace@latest${name}`, { stdio: "inherit" });
1133
1846
  }
1134
1847
  });
1135
- var main = defineCommand10({
1848
+ var main = defineCommand13({
1136
1849
  meta: {
1137
1850
  name: "deepspace",
1138
- version: "0.2.3",
1851
+ version: pkg.version,
1139
1852
  description: "DeepSpace SDK CLI"
1140
1853
  },
1141
1854
  subCommands: {
@@ -1147,12 +1860,16 @@ var main = defineCommand10({
1147
1860
  test: test_default,
1148
1861
  "test-accounts": test_accounts_default,
1149
1862
  add: add_default,
1863
+ integrations: integrations_default,
1864
+ invoke: invoke_default,
1150
1865
  deploy: deploy_default,
1151
- undeploy: undeploy_default
1152
- },
1153
- run() {
1154
- console.log("deepspace CLI \u2014 run `npx deepspace --help` for usage");
1866
+ undeploy: undeploy_default,
1867
+ domain: domain_default
1155
1868
  }
1869
+ // No `run()` here — citty cascades parent run() AFTER subcommand finishes,
1870
+ // which corrupts agent-friendly output (`--json`) and prints noise on every
1871
+ // command. Citty's default behavior when no subcommand matches is to print
1872
+ // help, which is what we want for `deepspace` with no args.
1156
1873
  });
1157
1874
  runMain(main);
1158
1875
  //# sourceMappingURL=cli.js.map