@insforge/cli 0.1.19 → 0.1.21

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 CHANGED
@@ -137,6 +137,49 @@ insforge metadata
137
137
  insforge metadata --json
138
138
  ```
139
139
 
140
+ #### `insforge logs`
141
+
142
+ Fetch backend container logs.
143
+
144
+ ```bash
145
+ insforge logs <source> [options]
146
+ ```
147
+
148
+ **Sources:** `insforge.logs`, `postgREST.logs`, `postgres.logs`, `function.logs`
149
+
150
+ **Options:**
151
+ - `--limit <n>`: Number of log entries to return (default: 20)
152
+
153
+ **Examples:**
154
+ ```bash
155
+ insforge logs insforge.logs
156
+ insforge logs postgres.logs --limit 50
157
+ insforge logs function.logs --json
158
+ ```
159
+
160
+ #### `insforge docs`
161
+
162
+ Browse InsForge SDK documentation.
163
+
164
+ ```bash
165
+ insforge docs [feature] [language]
166
+ ```
167
+
168
+ **Features:** `db`, `storage`, `functions`, `auth`, `ai`, `realtime`, `instructions`
169
+ **Languages:** `typescript`, `swift`, `kotlin`, `rest-api`
170
+
171
+ **Examples:**
172
+ ```bash
173
+ # List all available docs
174
+ insforge docs
175
+
176
+ # Specific feature/language docs
177
+ insforge docs instructions # Show backend setup instructions
178
+ insforge docs db typescript # Show TypeScript database SDK docs
179
+ insforge docs auth swift # Show Swift auth SDK docs
180
+ insforge docs storage rest-api # Show REST API storage docs
181
+ ```
182
+
140
183
  ---
141
184
 
142
185
  ### Database — `insforge db`
@@ -258,6 +301,15 @@ insforge functions invoke my-function --method GET
258
301
  insforge functions invoke my-function --data '{"key": "value"}' --json
259
302
  ```
260
303
 
304
+ #### `insforge functions delete <slug>`
305
+
306
+ Delete an edge function.
307
+
308
+ ```bash
309
+ insforge functions delete my-function
310
+ insforge functions delete my-function -y # skip confirmation
311
+ ```
312
+
261
313
  ---
262
314
 
263
315
  ### Storage — `insforge storage`
@@ -409,6 +461,64 @@ insforge secrets delete STRIPE_API_KEY
409
461
  insforge secrets delete STRIPE_API_KEY -y # skip confirmation
410
462
  ```
411
463
 
464
+ ### Schedules — `insforge schedules`
465
+
466
+ Manage scheduled tasks (cron jobs).
467
+
468
+ #### `insforge schedules list`
469
+
470
+ List all schedules in the current project.
471
+
472
+ ```bash
473
+ insforge schedules list
474
+ insforge schedules list --json
475
+ ```
476
+
477
+ #### `insforge schedules create`
478
+
479
+ Create a new scheduled task.
480
+
481
+ ```bash
482
+ insforge schedules create --name "daily-cleanup" --cron "0 0 * * *" --url "https://api.example.com/cleanup" --method POST
483
+ insforge schedules create --name "hourly-sync" --cron "0 * * * *" --url "https://api.example.com/sync" --method GET --headers '{"Authorization": "Bearer xxx"}'
484
+ ```
485
+
486
+ #### `insforge schedules get <id>`
487
+
488
+ Get details of a specific schedule.
489
+
490
+ ```bash
491
+ insforge schedules get <id>
492
+ insforge schedules get 123 --json
493
+ ```
494
+
495
+ #### `insforge schedules update <id>`
496
+
497
+ Update an existing schedule.
498
+
499
+ ```bash
500
+ insforge schedules update <id> --name "weekly-cleanup" --cron "0 0 * * 0"
501
+ insforge schedules update 123 --active false
502
+ ```
503
+
504
+ #### `insforge schedules delete <id>`
505
+
506
+ Delete a schedule.
507
+
508
+ ```bash
509
+ insforge schedules delete <id>
510
+ insforge schedules delete 123 -y
511
+ ```
512
+
513
+ #### `insforge schedules logs <id>`
514
+
515
+ Fetch execution logs for a specific schedule.
516
+
517
+ ```bash
518
+ insforge schedules logs <id>
519
+ insforge schedules logs 123 --limit 100
520
+ ```
521
+
412
522
  ---
413
523
 
414
524
  ## Project Configuration
package/dist/index.js CHANGED
@@ -5,7 +5,7 @@ import { readFileSync as readFileSync6 } from "fs";
5
5
  import { join as join6, dirname } from "path";
6
6
  import { fileURLToPath } from "url";
7
7
  import { Command } from "commander";
8
- import * as clack13 from "@clack/prompts";
8
+ import * as clack14 from "@clack/prompts";
9
9
 
10
10
  // src/lib/config.ts
11
11
  import { existsSync, mkdirSync, readFileSync, writeFileSync, unlinkSync } from "fs";
@@ -720,6 +720,16 @@ async function installSkills(json) {
720
720
  } catch {
721
721
  if (!json) clack5.log.warn("Failed to install agent skills. You can run manually: npx skills add insforge/agent-skills -s insforge -s insforge-cli");
722
722
  }
723
+ try {
724
+ if (!json) clack5.log.info("Installing find-skills...");
725
+ await execAsync("npx skills add https://github.com/vercel-labs/skills --skill find-skills -y", {
726
+ cwd: process.cwd(),
727
+ timeout: 6e4
728
+ });
729
+ if (!json) clack5.log.success("find-skills installed.");
730
+ } catch {
731
+ if (!json) clack5.log.warn("Failed to install find-skills. You can run manually: npx skills add https://github.com/vercel-labs/skills --skill find-skills");
732
+ }
723
733
  try {
724
734
  updateGitignore();
725
735
  } catch {
@@ -1399,22 +1409,41 @@ Specify --file <path> or create ${join3("insforge", "functions", slug, "index.ts
1399
1409
  } catch {
1400
1410
  exists = false;
1401
1411
  }
1412
+ let res;
1402
1413
  if (exists) {
1403
- await ossFetch(`/api/functions/${encodeURIComponent(slug)}`, {
1414
+ res = await ossFetch(`/api/functions/${encodeURIComponent(slug)}`, {
1404
1415
  method: "PUT",
1405
1416
  body: JSON.stringify({ name, description, code })
1406
1417
  });
1407
1418
  } else {
1408
- await ossFetch("/api/functions", {
1419
+ res = await ossFetch("/api/functions", {
1409
1420
  method: "POST",
1410
1421
  body: JSON.stringify({ slug, name, description, code })
1411
1422
  });
1412
1423
  }
1424
+ const result = await res.json();
1425
+ const deployFailed = result.deployment?.status === "failed";
1413
1426
  if (json) {
1414
- outputJson({ success: true, slug, action: exists ? "updated" : "created" });
1427
+ outputJson(result);
1415
1428
  } else {
1416
- outputSuccess(`Function "${slug}" ${exists ? "updated" : "created"} successfully.`);
1429
+ const action = exists ? "updation" : "creation";
1430
+ const resultStatus = result.success ? "success" : "failed";
1431
+ outputSuccess(`Function "${result.function.slug}" ${action} ${resultStatus}.`);
1432
+ if (result.deployment) {
1433
+ if (result.deployment.status === "success") {
1434
+ console.log(` Deployment: ${result.deployment.status}${result.deployment.url ? ` \u2192 ${result.deployment.url}` : ""}`);
1435
+ } else {
1436
+ console.log(` Deployment: ${result.deployment.status}`);
1437
+ if (result.deployment.buildLogs?.length) {
1438
+ console.log(" Build logs:");
1439
+ for (const line of result.deployment.buildLogs) {
1440
+ console.log(` ${line}`);
1441
+ }
1442
+ }
1443
+ }
1444
+ }
1417
1445
  }
1446
+ if (deployFailed) throw new CLIError("Function deployment failed");
1418
1447
  await reportCliUsage("cli.functions.deploy", true);
1419
1448
  } catch (err) {
1420
1449
  await reportCliUsage("cli.functions.deploy", false);
@@ -1451,20 +1480,14 @@ function registerFunctionsInvokeCommand(functionsCmd2) {
1451
1480
  if (json) {
1452
1481
  outputJson({ status, body: data });
1453
1482
  } else {
1454
- if (status >= 400) {
1455
- console.error(`HTTP ${status}`);
1456
- }
1457
1483
  console.log(JSON.stringify(data, null, 2));
1458
1484
  }
1459
1485
  } else {
1460
1486
  const text3 = await res.text();
1461
- if (!json && status >= 400) {
1462
- console.error(`HTTP ${status}`);
1463
- }
1464
1487
  console.log(text3);
1465
1488
  }
1466
1489
  if (status >= 400) {
1467
- process.exit(1);
1490
+ throw new CLIError(`HTTP ${status}`, 1, "HTTP_ERROR");
1468
1491
  }
1469
1492
  } catch (err) {
1470
1493
  handleError(err, json);
@@ -1496,6 +1519,43 @@ function registerFunctionsCodeCommand(functionsCmd2) {
1496
1519
  });
1497
1520
  }
1498
1521
 
1522
+ // src/commands/functions/delete.ts
1523
+ import * as clack7 from "@clack/prompts";
1524
+ function registerFunctionsDeleteCommand(functionsCmd2) {
1525
+ functionsCmd2.command("delete <slug>").description("Delete an edge function").action(async (slug, _opts, cmd) => {
1526
+ const { json, yes } = getRootOpts(cmd);
1527
+ try {
1528
+ await requireAuth();
1529
+ if (!yes && !json) {
1530
+ const confirmed = await clack7.confirm({
1531
+ message: `Delete function "${slug}"? This cannot be undone.`
1532
+ });
1533
+ if (clack7.isCancel(confirmed) || !confirmed) {
1534
+ clack7.log.info("Cancelled.");
1535
+ return;
1536
+ }
1537
+ }
1538
+ const res = await ossFetch(`/api/functions/${encodeURIComponent(slug)}`, {
1539
+ method: "DELETE"
1540
+ });
1541
+ const result = await res.json();
1542
+ if (json) {
1543
+ outputJson(result);
1544
+ } else {
1545
+ if (result.success) {
1546
+ outputSuccess(`Function "${slug}" deleted successfully.`);
1547
+ } else {
1548
+ outputSuccess(`Failed to delete function "${slug}".`);
1549
+ }
1550
+ }
1551
+ await reportCliUsage("cli.functions.delete", true);
1552
+ } catch (err) {
1553
+ await reportCliUsage("cli.functions.delete", false);
1554
+ handleError(err, json);
1555
+ }
1556
+ });
1557
+ }
1558
+
1499
1559
  // src/commands/storage/buckets.ts
1500
1560
  function registerStorageBucketsCommand(storageCmd2) {
1501
1561
  storageCmd2.command("buckets").description("List all storage buckets").action(async (_opts, cmd) => {
@@ -1629,17 +1689,17 @@ function registerStorageCreateBucketCommand(storageCmd2) {
1629
1689
  }
1630
1690
 
1631
1691
  // src/commands/storage/delete-bucket.ts
1632
- import * as clack7 from "@clack/prompts";
1692
+ import * as clack8 from "@clack/prompts";
1633
1693
  function registerStorageDeleteBucketCommand(storageCmd2) {
1634
1694
  storageCmd2.command("delete-bucket <name>").description("Delete a storage bucket and all its objects").action(async (name, _opts, cmd) => {
1635
1695
  const { json, yes } = getRootOpts(cmd);
1636
1696
  try {
1637
1697
  await requireAuth();
1638
1698
  if (!yes && !json) {
1639
- const confirm7 = await clack7.confirm({
1699
+ const confirm8 = await clack8.confirm({
1640
1700
  message: `Delete bucket "${name}" and all its objects? This cannot be undone.`
1641
1701
  });
1642
- if (!confirm7 || clack7.isCancel(confirm7)) {
1702
+ if (!confirm8 || clack8.isCancel(confirm8)) {
1643
1703
  process.exit(0);
1644
1704
  }
1645
1705
  }
@@ -1721,12 +1781,12 @@ import { tmpdir } from "os";
1721
1781
  import { promisify as promisify2 } from "util";
1722
1782
  import * as fs2 from "fs/promises";
1723
1783
  import * as path2 from "path";
1724
- import * as clack9 from "@clack/prompts";
1784
+ import * as clack10 from "@clack/prompts";
1725
1785
 
1726
1786
  // src/commands/deployments/deploy.ts
1727
1787
  import * as path from "path";
1728
1788
  import * as fs from "fs/promises";
1729
- import * as clack8 from "@clack/prompts";
1789
+ import * as clack9 from "@clack/prompts";
1730
1790
  import archiver from "archiver";
1731
1791
  var POLL_INTERVAL_MS = 5e3;
1732
1792
  var POLL_TIMEOUT_MS = 12e4;
@@ -1830,7 +1890,7 @@ function registerDeploymentsDeployCommand(deploymentsCmd2) {
1830
1890
  if (!stats?.isDirectory()) {
1831
1891
  throw new CLIError(`"${sourceDir}" is not a valid directory.`);
1832
1892
  }
1833
- const s = !json ? clack8.spinner() : null;
1893
+ const s = !json ? clack9.spinner() : null;
1834
1894
  const startBody = {};
1835
1895
  if (opts.env) {
1836
1896
  try {
@@ -1858,18 +1918,18 @@ function registerDeploymentsDeployCommand(deploymentsCmd2) {
1858
1918
  outputJson(result.deployment);
1859
1919
  } else {
1860
1920
  if (result.liveUrl) {
1861
- clack8.log.success(`Live at: ${result.liveUrl}`);
1921
+ clack9.log.success(`Live at: ${result.liveUrl}`);
1862
1922
  }
1863
- clack8.log.info(`Deployment ID: ${result.deploymentId}`);
1923
+ clack9.log.info(`Deployment ID: ${result.deploymentId}`);
1864
1924
  }
1865
1925
  } else {
1866
1926
  s?.stop("Deployment is still building");
1867
1927
  if (json) {
1868
1928
  outputJson({ id: result.deploymentId, status: result.deployment?.status ?? "building", timedOut: true });
1869
1929
  } else {
1870
- clack8.log.info(`Deployment ID: ${result.deploymentId}`);
1871
- clack8.log.warn("Deployment did not finish within 2 minutes.");
1872
- clack8.log.info(`Check status with: insforge deployments status ${result.deploymentId}`);
1930
+ clack9.log.info(`Deployment ID: ${result.deploymentId}`);
1931
+ clack9.log.warn("Deployment did not finish within 2 minutes.");
1932
+ clack9.log.info(`Check status with: insforge deployments status ${result.deploymentId}`);
1873
1933
  }
1874
1934
  }
1875
1935
  await reportCliUsage("cli.deployments.deploy", true);
@@ -1913,7 +1973,7 @@ function registerCreateCommand(program2) {
1913
1973
  try {
1914
1974
  await requireAuth(apiUrl);
1915
1975
  if (!json) {
1916
- clack9.intro("Create a new InsForge project");
1976
+ clack10.intro("Create a new InsForge project");
1917
1977
  }
1918
1978
  let orgId = opts.orgId;
1919
1979
  if (!orgId) {
@@ -1924,14 +1984,14 @@ function registerCreateCommand(program2) {
1924
1984
  if (json) {
1925
1985
  throw new CLIError("Specify --org-id in JSON mode.");
1926
1986
  }
1927
- const selected = await clack9.select({
1987
+ const selected = await clack10.select({
1928
1988
  message: "Select an organization:",
1929
1989
  options: orgs.map((o) => ({
1930
1990
  value: o.id,
1931
1991
  label: o.name
1932
1992
  }))
1933
1993
  });
1934
- if (clack9.isCancel(selected)) process.exit(0);
1994
+ if (clack10.isCancel(selected)) process.exit(0);
1935
1995
  orgId = selected;
1936
1996
  }
1937
1997
  const globalConfig = getGlobalConfig();
@@ -1940,11 +2000,11 @@ function registerCreateCommand(program2) {
1940
2000
  let projectName = opts.name;
1941
2001
  if (!projectName) {
1942
2002
  if (json) throw new CLIError("--name is required in JSON mode.");
1943
- const name = await clack9.text({
2003
+ const name = await clack10.text({
1944
2004
  message: "Project name:",
1945
2005
  validate: (v) => v.length >= 2 ? void 0 : "Name must be at least 2 characters"
1946
2006
  });
1947
- if (clack9.isCancel(name)) process.exit(0);
2007
+ if (clack10.isCancel(name)) process.exit(0);
1948
2008
  projectName = name;
1949
2009
  }
1950
2010
  let template = opts.template;
@@ -1952,7 +2012,7 @@ function registerCreateCommand(program2) {
1952
2012
  if (json) {
1953
2013
  template = "empty";
1954
2014
  } else {
1955
- const selected = await clack9.select({
2015
+ const selected = await clack10.select({
1956
2016
  message: "Choose a starter template:",
1957
2017
  options: [
1958
2018
  { value: "react", label: "Web app template with React" },
@@ -1960,11 +2020,11 @@ function registerCreateCommand(program2) {
1960
2020
  { value: "empty", label: "Empty project" }
1961
2021
  ]
1962
2022
  });
1963
- if (clack9.isCancel(selected)) process.exit(0);
2023
+ if (clack10.isCancel(selected)) process.exit(0);
1964
2024
  template = selected;
1965
2025
  }
1966
2026
  }
1967
- const s = !json ? clack9.spinner() : null;
2027
+ const s = !json ? clack10.spinner() : null;
1968
2028
  s?.start("Creating project...");
1969
2029
  const project = await createProject(orgId, projectName, opts.region, apiUrl);
1970
2030
  s?.message("Waiting for project to become active...");
@@ -1989,7 +2049,7 @@ function registerCreateCommand(program2) {
1989
2049
  await installSkills(json);
1990
2050
  await reportCliUsage("cli.create", true, 6);
1991
2051
  if (hasTemplate) {
1992
- const installSpinner = !json ? clack9.spinner() : null;
2052
+ const installSpinner = !json ? clack10.spinner() : null;
1993
2053
  installSpinner?.start("Installing dependencies...");
1994
2054
  try {
1995
2055
  await execAsync2("npm install", { cwd: process.cwd(), maxBuffer: 10 * 1024 * 1024 });
@@ -1997,19 +2057,19 @@ function registerCreateCommand(program2) {
1997
2057
  } catch (err) {
1998
2058
  installSpinner?.stop("Failed to install dependencies");
1999
2059
  if (!json) {
2000
- clack9.log.warn(`npm install failed: ${err.message}`);
2001
- clack9.log.info("Run `npm install` manually to install dependencies.");
2060
+ clack10.log.warn(`npm install failed: ${err.message}`);
2061
+ clack10.log.info("Run `npm install` manually to install dependencies.");
2002
2062
  }
2003
2063
  }
2004
2064
  }
2005
2065
  let liveUrl = null;
2006
2066
  if (hasTemplate && !json) {
2007
- const shouldDeploy = await clack9.confirm({
2067
+ const shouldDeploy = await clack10.confirm({
2008
2068
  message: "Would you like to deploy now?"
2009
2069
  });
2010
- if (!clack9.isCancel(shouldDeploy) && shouldDeploy) {
2070
+ if (!clack10.isCancel(shouldDeploy) && shouldDeploy) {
2011
2071
  try {
2012
- const deploySpinner = clack9.spinner();
2072
+ const deploySpinner = clack10.spinner();
2013
2073
  const result = await deployProject({
2014
2074
  sourceDir: process.cwd(),
2015
2075
  spinner: deploySpinner
@@ -2019,12 +2079,12 @@ function registerCreateCommand(program2) {
2019
2079
  liveUrl = result.liveUrl;
2020
2080
  } else {
2021
2081
  deploySpinner.stop("Deployment is still building");
2022
- clack9.log.info(`Deployment ID: ${result.deploymentId}`);
2023
- clack9.log.warn("Deployment did not finish within 2 minutes.");
2024
- clack9.log.info(`Check status with: insforge deployments status ${result.deploymentId}`);
2082
+ clack10.log.info(`Deployment ID: ${result.deploymentId}`);
2083
+ clack10.log.warn("Deployment did not finish within 2 minutes.");
2084
+ clack10.log.info(`Check status with: insforge deployments status ${result.deploymentId}`);
2025
2085
  }
2026
2086
  } catch (err) {
2027
- clack9.log.warn(`Deploy failed: ${err.message}`);
2087
+ clack10.log.warn(`Deploy failed: ${err.message}`);
2028
2088
  }
2029
2089
  }
2030
2090
  }
@@ -2040,11 +2100,11 @@ function registerCreateCommand(program2) {
2040
2100
  }
2041
2101
  });
2042
2102
  } else {
2043
- clack9.log.step(`Dashboard: ${dashboardUrl}`);
2103
+ clack10.log.step(`Dashboard: ${dashboardUrl}`);
2044
2104
  if (liveUrl) {
2045
- clack9.log.success(`Live site: ${liveUrl}`);
2105
+ clack10.log.success(`Live site: ${liveUrl}`);
2046
2106
  }
2047
- clack9.outro("Done!");
2107
+ clack10.outro("Done!");
2048
2108
  }
2049
2109
  } catch (err) {
2050
2110
  handleError(err, json);
@@ -2052,7 +2112,7 @@ function registerCreateCommand(program2) {
2052
2112
  });
2053
2113
  }
2054
2114
  async function downloadTemplate(framework, projectConfig, projectName, json, _apiUrl) {
2055
- const s = !json ? clack9.spinner() : null;
2115
+ const s = !json ? clack10.spinner() : null;
2056
2116
  s?.start("Downloading template...");
2057
2117
  try {
2058
2118
  const anonKey = await getAnonKey();
@@ -2083,8 +2143,8 @@ async function downloadTemplate(framework, projectConfig, projectName, json, _ap
2083
2143
  } catch (err) {
2084
2144
  s?.stop("Template download failed");
2085
2145
  if (!json) {
2086
- clack9.log.warn(`Failed to download template: ${err.message}`);
2087
- clack9.log.info("You can manually set up the template later.");
2146
+ clack10.log.warn(`Failed to download template: ${err.message}`);
2147
+ clack10.log.info("You can manually set up the template later.");
2088
2148
  }
2089
2149
  }
2090
2150
  }
@@ -2267,7 +2327,7 @@ function registerDeploymentsStatusCommand(deploymentsCmd2) {
2267
2327
  }
2268
2328
 
2269
2329
  // src/commands/deployments/cancel.ts
2270
- import * as clack10 from "@clack/prompts";
2330
+ import * as clack11 from "@clack/prompts";
2271
2331
  function registerDeploymentsCancelCommand(deploymentsCmd2) {
2272
2332
  deploymentsCmd2.command("cancel <id>").description("Cancel a deployment").action(async (id, _opts, cmd) => {
2273
2333
  const { json, yes } = getRootOpts(cmd);
@@ -2275,10 +2335,10 @@ function registerDeploymentsCancelCommand(deploymentsCmd2) {
2275
2335
  await requireAuth();
2276
2336
  if (!getProjectConfig()) throw new ProjectNotLinkedError();
2277
2337
  if (!yes && !json) {
2278
- const confirmed = await clack10.confirm({
2338
+ const confirmed = await clack11.confirm({
2279
2339
  message: `Cancel deployment ${id}?`
2280
2340
  });
2281
- if (clack10.isCancel(confirmed) || !confirmed) process.exit(0);
2341
+ if (clack11.isCancel(confirmed) || !confirmed) process.exit(0);
2282
2342
  }
2283
2343
  const res = await ossFetch(`/api/deployments/${id}/cancel`, { method: "POST" });
2284
2344
  const result = await res.json();
@@ -2481,17 +2541,17 @@ function registerSecretsUpdateCommand(secretsCmd2) {
2481
2541
  }
2482
2542
 
2483
2543
  // src/commands/secrets/delete.ts
2484
- import * as clack11 from "@clack/prompts";
2544
+ import * as clack12 from "@clack/prompts";
2485
2545
  function registerSecretsDeleteCommand(secretsCmd2) {
2486
2546
  secretsCmd2.command("delete <key>").description("Delete a secret").action(async (key, _opts, cmd) => {
2487
2547
  const { json, yes } = getRootOpts(cmd);
2488
2548
  try {
2489
2549
  await requireAuth();
2490
2550
  if (!yes && !json) {
2491
- const confirm7 = await clack11.confirm({
2551
+ const confirm8 = await clack12.confirm({
2492
2552
  message: `Delete secret "${key}"? This cannot be undone.`
2493
2553
  });
2494
- if (!confirm7 || clack11.isCancel(confirm7)) {
2554
+ if (!confirm8 || clack12.isCancel(confirm8)) {
2495
2555
  process.exit(0);
2496
2556
  }
2497
2557
  }
@@ -2667,17 +2727,17 @@ function registerSchedulesUpdateCommand(schedulesCmd2) {
2667
2727
  }
2668
2728
 
2669
2729
  // src/commands/schedules/delete.ts
2670
- import * as clack12 from "@clack/prompts";
2730
+ import * as clack13 from "@clack/prompts";
2671
2731
  function registerSchedulesDeleteCommand(schedulesCmd2) {
2672
2732
  schedulesCmd2.command("delete <id>").description("Delete a schedule").action(async (id, _opts, cmd) => {
2673
2733
  const { json, yes } = getRootOpts(cmd);
2674
2734
  try {
2675
2735
  await requireAuth();
2676
2736
  if (!yes && !json) {
2677
- const confirm7 = await clack12.confirm({
2737
+ const confirm8 = await clack13.confirm({
2678
2738
  message: `Delete schedule "${id}"? This cannot be undone.`
2679
2739
  });
2680
- if (!confirm7 || clack12.isCancel(confirm7)) {
2740
+ if (!confirm8 || clack13.isCancel(confirm8)) {
2681
2741
  process.exit(0);
2682
2742
  }
2683
2743
  }
@@ -2744,8 +2804,7 @@ function registerLogsCommand(program2) {
2744
2804
  await requireAuth();
2745
2805
  const resolved = SOURCE_LOOKUP.get(source.toLowerCase());
2746
2806
  if (!resolved) {
2747
- console.error(`Invalid log source "${source}". Valid sources: ${VALID_SOURCES.join(", ")}`);
2748
- process.exit(1);
2807
+ throw new CLIError(`Invalid log source "${source}". Valid sources: ${VALID_SOURCES.join(", ")}`);
2749
2808
  }
2750
2809
  const limit = parseInt(opts.limit, 10) || 20;
2751
2810
  const res = await ossFetch(`/api/logs/${encodeURIComponent(resolved)}?limit=${limit}`);
@@ -2906,6 +2965,7 @@ registerFunctionsCommands(functionsCmd);
2906
2965
  registerFunctionsCodeCommand(functionsCmd);
2907
2966
  registerFunctionsDeployCommand(functionsCmd);
2908
2967
  registerFunctionsInvokeCommand(functionsCmd);
2968
+ registerFunctionsDeleteCommand(functionsCmd);
2909
2969
  var storageCmd = program.command("storage").description("Manage storage");
2910
2970
  registerStorageBucketsCommand(storageCmd);
2911
2971
  registerStorageCreateBucketCommand(storageCmd);
@@ -2950,7 +3010,7 @@ async function showInteractiveMenu() {
2950
3010
  } catch {
2951
3011
  }
2952
3012
  console.log(INSFORGE_LOGO);
2953
- clack13.intro(`InsForge CLI v${pkg.version}`);
3013
+ clack14.intro(`InsForge CLI v${pkg.version}`);
2954
3014
  const options = [];
2955
3015
  if (!isLoggedIn) {
2956
3016
  options.push({ value: "login", label: "Log in to InsForge" });
@@ -2966,12 +3026,12 @@ async function showInteractiveMenu() {
2966
3026
  { value: "docs", label: "View documentation" },
2967
3027
  { value: "help", label: "Show all commands" }
2968
3028
  );
2969
- const action = await clack13.select({
3029
+ const action = await clack14.select({
2970
3030
  message: "What would you like to do?",
2971
3031
  options
2972
3032
  });
2973
- if (clack13.isCancel(action)) {
2974
- clack13.cancel("Bye!");
3033
+ if (clack14.isCancel(action)) {
3034
+ clack14.cancel("Bye!");
2975
3035
  process.exit(0);
2976
3036
  }
2977
3037
  switch (action) {