@whop/cli 0.0.6 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -8,9 +8,12 @@ import {
8
8
  Profile,
9
9
  PromptCancelledError,
10
10
  apiBaseUrl,
11
+ buildTarget,
11
12
  chooseAuthMethod,
13
+ configDir,
12
14
  createWhopFetch,
13
15
  deriveProfileName,
16
+ detectChannel,
14
17
  filterSpecByTag,
15
18
  getActiveProfile,
16
19
  getSecret,
@@ -28,11 +31,10 @@ import {
28
31
  switchProfile,
29
32
  upsertProfile,
30
33
  validateApiKey
31
- } from "./chunk-Z7WDX64Z.js";
34
+ } from "./chunk-ET6QSHSA.js";
32
35
  import {
33
36
  external_exports
34
- } from "./chunk-CXNQ6UGC.js";
35
- import "./chunk-MELVTXNG.js";
37
+ } from "./chunk-KFCNNWPI.js";
36
38
 
37
39
  // src/api/groups.json
38
40
  var groups_default = [
@@ -92,6 +94,14 @@ var groups_default = [
92
94
  "referrals",
93
95
  "Referrals"
94
96
  ],
97
+ [
98
+ "people",
99
+ "People"
100
+ ],
101
+ [
102
+ "events",
103
+ "Events"
104
+ ],
95
105
  [
96
106
  "ads",
97
107
  "Ads"
@@ -300,9 +310,9 @@ async function loginAdapter(c2) {
300
310
  const companyId = getActiveProfile()?.companyId ?? "";
301
311
  if (companyId) {
302
312
  try {
303
- const { createWhopFetch: createWhopFetch2 } = await import("./api-XJ22R3CT.js");
304
- const fetch2 = createWhopFetch2();
305
- const res = await fetch2(
313
+ const { createWhopFetch: createWhopFetch2 } = await import("./api-3MQ6MQGV.js");
314
+ const fetch3 = createWhopFetch2();
315
+ const res = await fetch3(
306
316
  new Request(
307
317
  `https://api.whop.com/products?company_id=${companyId}&first=1`
308
318
  )
@@ -585,10 +595,10 @@ import { text, isCancel } from "@clack/prompts";
585
595
  // src/commerce/client.ts
586
596
  var PLACEHOLDER = "https://api.whop.com";
587
597
  var whopFetch = createWhopFetch();
588
- async function makeWhopRequest(method, path, body) {
598
+ async function makeWhopRequest(method, path3, body) {
589
599
  const init = { method };
590
600
  if (body !== void 0) init.body = JSON.stringify(body);
591
- const res = await whopFetch(new Request(`${PLACEHOLDER}${path}`, init));
601
+ const res = await whopFetch(new Request(`${PLACEHOLDER}${path3}`, init));
592
602
  if (!res.ok) {
593
603
  const payload = await res.json().catch(() => null);
594
604
  throw new Error(payload?.message ?? res.statusText);
@@ -630,13 +640,13 @@ function registerListCommand(group, config) {
630
640
  });
631
641
  }
632
642
  function registerItemCommands(group, config) {
633
- const { path, noun, idLabel, schema, updateOptions, transformBody } = config;
643
+ const { path: path3, noun, idLabel, schema, updateOptions, transformBody } = config;
634
644
  const idArg = external_exports.object({ id: external_exports.string().describe(idLabel) });
635
645
  group.command("get", {
636
646
  description: `Get a ${noun} by ID`,
637
647
  args: idArg,
638
648
  output: schema,
639
- run: (c2) => makeWhopRequest(`GET`, `${path}/${c2.args.id}`)
649
+ run: (c2) => makeWhopRequest(`GET`, `${path3}/${c2.args.id}`)
640
650
  });
641
651
  if (updateOptions) {
642
652
  group.command("update", {
@@ -646,14 +656,14 @@ function registerItemCommands(group, config) {
646
656
  output: schema,
647
657
  run: (c2) => {
648
658
  const body = buildBody(c2.options);
649
- return makeWhopRequest("PATCH", `${path}/${c2.args.id}`, transformBody ? transformBody(body) : body);
659
+ return makeWhopRequest("PATCH", `${path3}/${c2.args.id}`, transformBody ? transformBody(body) : body);
650
660
  }
651
661
  });
652
662
  }
653
663
  group.command("delete", {
654
664
  description: `Delete a ${noun}`,
655
665
  args: idArg,
656
- run: (c2) => makeWhopRequest("DELETE", `${path}/${c2.args.id}`)
666
+ run: (c2) => makeWhopRequest("DELETE", `${path3}/${c2.args.id}`)
657
667
  });
658
668
  }
659
669
 
@@ -1535,6 +1545,479 @@ ${c.success("\u2713 Your store is fully set up.")}`);
1535
1545
  console.log("");
1536
1546
  }
1537
1547
 
1548
+ // package.json
1549
+ var package_default = {
1550
+ name: "@whop/cli",
1551
+ version: "0.1.0",
1552
+ description: "The Whop CLI \u2014 build and manage Whop apps from your terminal. Human and agent friendly.",
1553
+ keywords: [
1554
+ "agent",
1555
+ "apps",
1556
+ "cli",
1557
+ "developer",
1558
+ "whop"
1559
+ ],
1560
+ homepage: "https://whop.com/developers/",
1561
+ bugs: "https://github.com/whopio/whop-public-cli/issues",
1562
+ license: "MIT",
1563
+ repository: {
1564
+ type: "git",
1565
+ url: "git+https://github.com/whopio/whop-public-cli.git"
1566
+ },
1567
+ bin: {
1568
+ whop: "dist/index.js",
1569
+ "whop-cli": "dist/index.js"
1570
+ },
1571
+ files: [
1572
+ "dist"
1573
+ ],
1574
+ type: "module",
1575
+ publishConfig: {
1576
+ access: "public"
1577
+ },
1578
+ scripts: {
1579
+ build: "tsx scripts/sync-spec.ts && pnpm run clean && tsup",
1580
+ "build:binary": "tsx scripts/build-binary.ts",
1581
+ clean: "rm -rf dist",
1582
+ dev: "tsx scripts/sync-spec.ts && tsx src/index.ts",
1583
+ start: "node dist/index.js",
1584
+ "check-types": "tsx scripts/sync-spec.ts && tsc --noEmit",
1585
+ lint: "oxlint .",
1586
+ "lint:fix": "oxlint --fix --fix-suggestions && oxfmt",
1587
+ "ci:lint": "oxlint -f github .",
1588
+ format: "oxfmt",
1589
+ "sync-spec": "tsx scripts/sync-spec.ts",
1590
+ test: "tsx --test scripts/*.test.ts"
1591
+ },
1592
+ dependencies: {
1593
+ "@clack/prompts": "^1.5.1",
1594
+ "@napi-rs/keyring": "^1.3.0",
1595
+ "@whop/sdk": "^0.0.40",
1596
+ chalk: "5.4.1",
1597
+ yaml: "2.8.0"
1598
+ },
1599
+ devDependencies: {
1600
+ "@types/node": "25.3.5",
1601
+ incur: "github:whopio/incur#5ca60d5",
1602
+ tsup: "8.5.0",
1603
+ tsx: "4.19.4",
1604
+ typescript: "5.9.3"
1605
+ },
1606
+ engines: {
1607
+ node: ">=22"
1608
+ },
1609
+ packageManager: "pnpm@10.23.0"
1610
+ };
1611
+
1612
+ // src/lib/update/check.ts
1613
+ import fs from "fs";
1614
+ import path from "path";
1615
+ import { spawn } from "child_process";
1616
+
1617
+ // src/lib/colorize-output.ts
1618
+ var SECTION_HEADERS = /* @__PURE__ */ new Set([
1619
+ "Usage",
1620
+ "Arguments",
1621
+ "Options",
1622
+ "Examples",
1623
+ "Environment Variables",
1624
+ "Global Options",
1625
+ "Integrations",
1626
+ "Commands",
1627
+ "Aliases"
1628
+ ]);
1629
+ var FORMAT_FLAGS = ["--json", "--format", "--full-output", "--schema", "--llms", "--llms-full", "--mcp", "--token-count", "--token-limit", "--token-offset"];
1630
+ function hasStructuredOutputFlag(argv2) {
1631
+ return argv2.some((a) => FORMAT_FLAGS.includes(a) || a.startsWith("--format="));
1632
+ }
1633
+ function shouldColorize(argv2) {
1634
+ if (!process.stdout.isTTY) return false;
1635
+ return !hasStructuredOutputFlag(argv2);
1636
+ }
1637
+ function paintFlag(flag) {
1638
+ return flag.replace(/(<[^>]+>)/g, (m) => c.muted(m)).replace(/(--[\w-]+|-[\w])/g, (m) => c.flag(m));
1639
+ }
1640
+ var COMMAND_ROW = /^(\s+)(whop\s+\S.*?)(\s{2,}#\s.*)?$/;
1641
+ function highlightUrls(text3) {
1642
+ return text3.replace(/https?:\/\/[^\s)]+/g, (m) => c.link(m));
1643
+ }
1644
+ function colorizeLine(line, section, nextLine) {
1645
+ const errMatch = line.match(/^(Error(?: \([^)]+\))?:)(.*)$/);
1646
+ if (errMatch) return { line: c.error(errMatch[1]) + highlightUrls(errMatch[2]), section };
1647
+ if (line.startsWith("Run `")) return { line: c.heading(line), section };
1648
+ const header = line.match(/^([A-Z][A-Za-z ]+):(.*)$/);
1649
+ if (header && SECTION_HEADERS.has(header[1])) {
1650
+ const rest = header[2].replace(/(whop[\w\s-]*)/g, (m) => c.command(m));
1651
+ return { line: c.heading(`${header[1]}:`) + rest, section: header[1] };
1652
+ }
1653
+ const cmd = line.match(COMMAND_ROW);
1654
+ if (cmd) {
1655
+ return { line: `${cmd[1]}${c.command(cmd[2])}${cmd[3] ? c.description(cmd[3]) : ""}`, section };
1656
+ }
1657
+ if (line.trim().endsWith(":") && nextLine !== void 0 && COMMAND_ROW.test(nextLine)) {
1658
+ return { line: c.heading(line), section };
1659
+ }
1660
+ if (line.trim() === "") return { line, section: null };
1661
+ if (section === "Options" || section === "Global Options" || section === "Environment Variables") {
1662
+ const m = line.match(/^(\s+)(\S.*?)(\s{2,})(.*)$/);
1663
+ if (m) return { line: `${m[1]}${paintFlag(m[2])}${m[3]}${c.description(m[4])}`, section };
1664
+ }
1665
+ if (section === "Commands" || section === "Integrations" || section === "Aliases") {
1666
+ const m = line.match(/^(\s+)(\S+)(\s{2,})(.*)$/);
1667
+ if (m) return { line: `${m[1]}${c.command(m[2])}${m[3]}${c.description(m[4])}`, section };
1668
+ }
1669
+ if (section === "Arguments") {
1670
+ const m = line.match(/^(\s+)(\S+)(\s{2,})(.*)$/);
1671
+ if (m) return { line: `${m[1]}${c.id(m[2])}${m[3]}${c.description(m[4])}`, section };
1672
+ }
1673
+ return { line: highlightUrls(line), section };
1674
+ }
1675
+ function colorizeOutput(text3) {
1676
+ let section = null;
1677
+ const lines = text3.split("\n");
1678
+ return lines.map((line, i) => {
1679
+ const result = colorizeLine(line, section, lines[i + 1]);
1680
+ section = result.section;
1681
+ return result.line;
1682
+ }).join("\n");
1683
+ }
1684
+
1685
+ // src/lib/update/check.ts
1686
+ var DEFAULT_MANIFEST_URL = "https://github.com/whopio/whop-public-cli/releases/latest/download/manifest.json";
1687
+ function manifestUrl(env = process.env) {
1688
+ return env.WHOP_CLI_MANIFEST_URL?.trim() || DEFAULT_MANIFEST_URL;
1689
+ }
1690
+ var CHECK_INTERVAL_MS = 24 * 60 * 60 * 1e3;
1691
+ function cachePath(env) {
1692
+ return path.join(configDir(env), "update-check.json");
1693
+ }
1694
+ function readUpdateCache(env = process.env) {
1695
+ try {
1696
+ const parsed = JSON.parse(
1697
+ fs.readFileSync(cachePath(env), "utf8")
1698
+ );
1699
+ if (parsed != null && typeof parsed === "object" && !Array.isArray(parsed)) {
1700
+ return parsed;
1701
+ }
1702
+ } catch {
1703
+ }
1704
+ return {};
1705
+ }
1706
+ function writeUpdateCache(cache, env = process.env) {
1707
+ try {
1708
+ fs.mkdirSync(configDir(env), { recursive: true, mode: 448 });
1709
+ fs.writeFileSync(cachePath(env), `${JSON.stringify(cache, null, 2)}
1710
+ `, {
1711
+ mode: 384
1712
+ });
1713
+ } catch {
1714
+ }
1715
+ }
1716
+ function isNewerVersion(candidate, current) {
1717
+ const parse = (v) => v.replace(/^v/, "").split("-")[0].split(".").map((part) => Number.parseInt(part, 10) || 0);
1718
+ const a = parse(candidate);
1719
+ const b = parse(current);
1720
+ for (let i = 0; i < Math.max(a.length, b.length); i++) {
1721
+ if ((a[i] ?? 0) > (b[i] ?? 0)) return true;
1722
+ if ((a[i] ?? 0) < (b[i] ?? 0)) return false;
1723
+ }
1724
+ return false;
1725
+ }
1726
+ function upgradeCommandFor(channel) {
1727
+ switch (channel) {
1728
+ case "npm":
1729
+ return "npm install -g @whop/cli";
1730
+ case "brew":
1731
+ return "brew upgrade whop";
1732
+ default:
1733
+ return "whop upgrade";
1734
+ }
1735
+ }
1736
+ function updateCheckSuppressed(argv2, env = process.env, stderrIsTty = process.stderr.isTTY ?? false) {
1737
+ if (env.WHOP_CLI_NO_UPDATE_CHECK) return true;
1738
+ if (env.CI) return true;
1739
+ if (!stderrIsTty) return true;
1740
+ if (hasStructuredOutputFlag(argv2)) return true;
1741
+ const first = argv2[0];
1742
+ if (first === "upgrade" || first === "mcp" || first === "completions" || first?.startsWith("--")) {
1743
+ return true;
1744
+ }
1745
+ return false;
1746
+ }
1747
+ function spawnBackgroundCheck() {
1748
+ const args = detectChannel() === "standalone" || detectChannel() === "brew" ? ["upgrade", "--background"] : [process.argv[1], "upgrade", "--background"];
1749
+ try {
1750
+ spawn(process.execPath, args, {
1751
+ detached: true,
1752
+ stdio: "ignore"
1753
+ }).unref();
1754
+ } catch {
1755
+ }
1756
+ }
1757
+ function scheduleUpdateNotice(argv2, currentVersion, env = process.env) {
1758
+ const channel = detectChannel(env);
1759
+ if (channel === "dev") return;
1760
+ if (updateCheckSuppressed(argv2, env)) return;
1761
+ const cache = readUpdateCache(env);
1762
+ if (cache.updatedTo && cache.updatedTo === currentVersion) {
1763
+ writeUpdateCache({ ...cache, updatedTo: void 0 }, env);
1764
+ process.on("exit", () => {
1765
+ process.stderr.write(
1766
+ `
1767
+ whop was updated to v${currentVersion} automatically.
1768
+ `
1769
+ );
1770
+ });
1771
+ return;
1772
+ }
1773
+ if (cache.latestVersion && isNewerVersion(cache.latestVersion, currentVersion)) {
1774
+ const latest = cache.latestVersion;
1775
+ process.on("exit", () => {
1776
+ process.stderr.write(
1777
+ `
1778
+ A new version of whop is available: v${currentVersion} \u2192 v${latest}
1779
+ Run \`${upgradeCommandFor(channel)}\` to update.
1780
+ `
1781
+ );
1782
+ });
1783
+ }
1784
+ const lastChecked = cache.lastCheckedAt ? new Date(cache.lastCheckedAt).getTime() : 0;
1785
+ if (Date.now() - lastChecked > CHECK_INTERVAL_MS) {
1786
+ writeUpdateCache({ ...cache, lastCheckedAt: (/* @__PURE__ */ new Date()).toISOString() }, env);
1787
+ spawnBackgroundCheck();
1788
+ }
1789
+ }
1790
+
1791
+ // src/lib/update/self-update.ts
1792
+ import crypto from "crypto";
1793
+ import fs2 from "fs";
1794
+ import path2 from "path";
1795
+ var SelfUpdateError = class extends Error {
1796
+ constructor(code, message) {
1797
+ super(message);
1798
+ this.code = code;
1799
+ }
1800
+ };
1801
+ async function fetchManifest(env = process.env) {
1802
+ const url = manifestUrl(env);
1803
+ let response;
1804
+ try {
1805
+ response = await fetch(url, {
1806
+ signal: AbortSignal.timeout(1e4),
1807
+ redirect: "follow"
1808
+ });
1809
+ } catch {
1810
+ throw new SelfUpdateError(
1811
+ "MANIFEST_UNREACHABLE",
1812
+ `Could not reach the update manifest at ${url}.`
1813
+ );
1814
+ }
1815
+ if (!response.ok) {
1816
+ throw new SelfUpdateError(
1817
+ "MANIFEST_UNAVAILABLE",
1818
+ `Update manifest request failed with HTTP ${response.status}.`
1819
+ );
1820
+ }
1821
+ let parsed;
1822
+ try {
1823
+ parsed = await response.json();
1824
+ } catch {
1825
+ throw new SelfUpdateError(
1826
+ "MANIFEST_INVALID",
1827
+ "Update manifest is not valid JSON."
1828
+ );
1829
+ }
1830
+ const manifest = parsed;
1831
+ if (typeof manifest?.version !== "string" || manifest.assets == null || typeof manifest.assets !== "object") {
1832
+ throw new SelfUpdateError(
1833
+ "MANIFEST_INVALID",
1834
+ "Update manifest is missing version or assets."
1835
+ );
1836
+ }
1837
+ return manifest;
1838
+ }
1839
+ function assetForThisBinary(manifest) {
1840
+ if (!buildTarget) {
1841
+ throw new SelfUpdateError(
1842
+ "NOT_A_STANDALONE_BUILD",
1843
+ "This build has no compile target \u2014 self-update only applies to standalone binaries."
1844
+ );
1845
+ }
1846
+ const asset = manifest.assets[buildTarget];
1847
+ if (!asset?.url || !asset.sha256) {
1848
+ throw new SelfUpdateError(
1849
+ "NO_ASSET_FOR_TARGET",
1850
+ `The latest release has no binary for ${buildTarget}.`
1851
+ );
1852
+ }
1853
+ return { ...asset, target: buildTarget };
1854
+ }
1855
+ async function downloadAndSwap(asset, execPath = process.execPath) {
1856
+ let response;
1857
+ try {
1858
+ response = await fetch(asset.url, {
1859
+ signal: AbortSignal.timeout(12e4),
1860
+ redirect: "follow"
1861
+ });
1862
+ } catch {
1863
+ throw new SelfUpdateError(
1864
+ "DOWNLOAD_FAILED",
1865
+ `Could not download ${asset.url}.`
1866
+ );
1867
+ }
1868
+ if (!response.ok) {
1869
+ throw new SelfUpdateError(
1870
+ "DOWNLOAD_FAILED",
1871
+ `Binary download failed with HTTP ${response.status}.`
1872
+ );
1873
+ }
1874
+ const bytes = Buffer.from(await response.arrayBuffer());
1875
+ const digest = crypto.createHash("sha256").update(bytes).digest("hex");
1876
+ if (digest !== asset.sha256.toLowerCase()) {
1877
+ throw new SelfUpdateError(
1878
+ "CHECKSUM_MISMATCH",
1879
+ `Downloaded binary checksum ${digest} does not match the manifest \u2014 aborting.`
1880
+ );
1881
+ }
1882
+ const dir = path2.dirname(execPath);
1883
+ const tmp = path2.join(dir, `.${path2.basename(execPath)}.${process.pid}.new`);
1884
+ try {
1885
+ fs2.writeFileSync(tmp, bytes, { mode: 493 });
1886
+ fs2.renameSync(tmp, execPath);
1887
+ } catch (err) {
1888
+ try {
1889
+ fs2.rmSync(tmp, { force: true });
1890
+ } catch {
1891
+ }
1892
+ const code = err.code;
1893
+ if (code === "EACCES" || code === "EPERM" || code === "EROFS") {
1894
+ throw new SelfUpdateError(
1895
+ "PERMISSION_DENIED",
1896
+ `No write access to ${dir}. Re-run with elevated permissions (e.g. \`sudo whop upgrade\`) or reinstall.`
1897
+ );
1898
+ }
1899
+ throw err;
1900
+ }
1901
+ }
1902
+
1903
+ // src/lib/update/command.ts
1904
+ var upgradeOptions = external_exports.object({
1905
+ check: external_exports.boolean().optional().describe("Only check for a newer version, don't install it"),
1906
+ background: external_exports.boolean().optional().describe(
1907
+ "Internal: refresh the update cache silently (spawned by the automatic check)"
1908
+ )
1909
+ });
1910
+ var upgradeOutput = external_exports.object({
1911
+ status: external_exports.enum(["up-to-date", "update-available", "updated"]).describe("Result of the upgrade check"),
1912
+ current: external_exports.string().describe("The version currently running"),
1913
+ latest: external_exports.string().describe("The latest released version"),
1914
+ channel: external_exports.enum(["npm", "brew", "standalone", "dev"]).describe("How this CLI was installed"),
1915
+ upgradeCommand: external_exports.string().optional().describe("Run this shell command to install the available update")
1916
+ });
1917
+ async function runBackground(env) {
1918
+ const manifest = await fetchManifest(env);
1919
+ const cache = readUpdateCache(env);
1920
+ writeUpdateCache(
1921
+ {
1922
+ ...cache,
1923
+ lastCheckedAt: (/* @__PURE__ */ new Date()).toISOString(),
1924
+ latestVersion: manifest.version
1925
+ },
1926
+ env
1927
+ );
1928
+ if (detectChannel(env) === "standalone" && env.WHOP_CLI_AUTO_UPDATE !== "0" && isNewerVersion(manifest.version, package_default.version)) {
1929
+ await downloadAndSwap(assetForThisBinary(manifest));
1930
+ writeUpdateCache(
1931
+ {
1932
+ lastCheckedAt: (/* @__PURE__ */ new Date()).toISOString(),
1933
+ latestVersion: manifest.version,
1934
+ updatedTo: manifest.version
1935
+ },
1936
+ env
1937
+ );
1938
+ }
1939
+ }
1940
+ async function runUpgrade(c2, env = process.env) {
1941
+ if (c2.options.background) {
1942
+ try {
1943
+ await runBackground(env);
1944
+ } catch {
1945
+ }
1946
+ return c2.ok({
1947
+ status: "up-to-date",
1948
+ current: package_default.version,
1949
+ latest: package_default.version,
1950
+ channel: detectChannel(env)
1951
+ });
1952
+ }
1953
+ const channel = detectChannel(env);
1954
+ let manifest;
1955
+ try {
1956
+ manifest = await fetchManifest(env);
1957
+ } catch (err) {
1958
+ if (err instanceof SelfUpdateError) {
1959
+ return c2.error({ code: err.code, message: err.message, retryable: true });
1960
+ }
1961
+ throw err;
1962
+ }
1963
+ writeUpdateCache(
1964
+ {
1965
+ ...readUpdateCache(env),
1966
+ lastCheckedAt: (/* @__PURE__ */ new Date()).toISOString(),
1967
+ latestVersion: manifest.version
1968
+ },
1969
+ env
1970
+ );
1971
+ const base = { current: package_default.version, latest: manifest.version, channel };
1972
+ if (!isNewerVersion(manifest.version, package_default.version)) {
1973
+ return c2.ok({ status: "up-to-date", ...base });
1974
+ }
1975
+ if (channel === "npm" || channel === "brew") {
1976
+ return c2.ok({
1977
+ status: "update-available",
1978
+ ...base,
1979
+ upgradeCommand: upgradeCommandFor(channel)
1980
+ });
1981
+ }
1982
+ if (channel === "dev") {
1983
+ return c2.error({
1984
+ code: "DEV_BUILD",
1985
+ message: "Running from source \u2014 pull the latest instead of upgrading.",
1986
+ retryable: false
1987
+ });
1988
+ }
1989
+ if (c2.options.check) {
1990
+ return c2.ok(
1991
+ {
1992
+ status: "update-available",
1993
+ ...base,
1994
+ upgradeCommand: upgradeCommandFor(channel)
1995
+ },
1996
+ {
1997
+ cta: {
1998
+ description: `v${manifest.version} is available (you have v${package_default.version}). To update:`,
1999
+ commands: [
2000
+ { command: "upgrade", description: "Install the latest version" }
2001
+ ]
2002
+ }
2003
+ }
2004
+ );
2005
+ }
2006
+ try {
2007
+ await downloadAndSwap(assetForThisBinary(manifest));
2008
+ } catch (err) {
2009
+ if (err instanceof SelfUpdateError) {
2010
+ return c2.error({
2011
+ code: err.code,
2012
+ message: err.message,
2013
+ retryable: err.code !== "PERMISSION_DENIED"
2014
+ });
2015
+ }
2016
+ throw err;
2017
+ }
2018
+ return c2.ok({ status: "updated", ...base });
2019
+ }
2020
+
1538
2021
  // src/commands.ts
1539
2022
  var HANDWRITTEN_GROUPS = [
1540
2023
  {
@@ -1579,6 +2062,24 @@ var HANDWRITTEN_GROUPS = [
1579
2062
  section: "commerce",
1580
2063
  register: (cli2) => cli2.command(buildCheckoutGroup())
1581
2064
  },
2065
+ {
2066
+ name: "upgrade",
2067
+ description: "Update the CLI to the latest version",
2068
+ section: "get-started",
2069
+ register: (cli2) => cli2.command("upgrade", {
2070
+ description: "Update the whop CLI to the latest version",
2071
+ options: upgradeOptions,
2072
+ output: upgradeOutput,
2073
+ examples: [
2074
+ { description: "Update to the latest version" },
2075
+ {
2076
+ options: { check: true },
2077
+ description: "Check for a newer version without installing"
2078
+ }
2079
+ ],
2080
+ run: (c2) => runUpgrade(c2)
2081
+ })
2082
+ },
1582
2083
  {
1583
2084
  name: "auth",
1584
2085
  description: "Manage authentication",
@@ -1635,69 +2136,6 @@ async function setupAgents(cli2) {
1635
2136
  }
1636
2137
  }
1637
2138
 
1638
- // package.json
1639
- var package_default = {
1640
- name: "@whop/cli",
1641
- version: "0.0.6",
1642
- description: "The Whop CLI \u2014 build and manage Whop apps from your terminal. Human and agent friendly.",
1643
- keywords: [
1644
- "agent",
1645
- "apps",
1646
- "cli",
1647
- "developer",
1648
- "whop"
1649
- ],
1650
- homepage: "https://whop.com/developers/",
1651
- bugs: "https://github.com/whopio/whop-sdk-ts/issues",
1652
- license: "MIT",
1653
- repository: {
1654
- type: "git",
1655
- url: "git+https://github.com/whopio/whop-sdk-ts.git",
1656
- directory: "packages/cli"
1657
- },
1658
- bin: {
1659
- whop: "dist/index.js",
1660
- "whop-cli": "dist/index.js"
1661
- },
1662
- files: [
1663
- "dist"
1664
- ],
1665
- type: "module",
1666
- publishConfig: {
1667
- access: "public"
1668
- },
1669
- scripts: {
1670
- build: "tsx scripts/sync-spec.ts && pnpm run clean && tsup",
1671
- clean: "rm -rf dist",
1672
- dev: "tsx scripts/sync-spec.ts && tsx src/index.ts",
1673
- start: "node dist/index.js",
1674
- "check-types": "tsx scripts/sync-spec.ts && tsc --noEmit",
1675
- lint: "oxlint .",
1676
- "lint:fix": "oxlint --fix --fix-suggestions && oxfmt",
1677
- "ci:lint": "oxlint -f github .",
1678
- format: "oxfmt",
1679
- "sync-spec": "tsx scripts/sync-spec.ts",
1680
- test: "tsx --test scripts/*.test.ts"
1681
- },
1682
- dependencies: {
1683
- "@clack/prompts": "^1.5.1",
1684
- "@napi-rs/keyring": "^1.3.0",
1685
- "@whop/sdk": "^0.0.40",
1686
- chalk: "5.4.1"
1687
- },
1688
- devDependencies: {
1689
- "@types/node": "25.3.5",
1690
- incur: "github:whopio/incur#5ca60d5",
1691
- tsup: "8.5.0",
1692
- tsx: "4.19.4",
1693
- typescript: "5.9.3"
1694
- },
1695
- engines: {
1696
- node: ">=22"
1697
- },
1698
- packageManager: "pnpm@10.23.0"
1699
- };
1700
-
1701
2139
  // src/lib/renderer.ts
1702
2140
  var MAX_CELL_WIDTH = 40;
1703
2141
  function isPlainObject(value) {
@@ -1782,8 +2220,8 @@ var cli = Cli_exports.create("whop", {
1782
2220
  }
1783
2221
  });
1784
2222
  var spec = (tag) => filterSpecByTag(native_spec_default, tag);
1785
- var fetch = createWhopFetch();
1786
- var isAuthExempt = (cmd) => !cmd || cmd === "login" || cmd === "logout" || cmd === "completions" || cmd.startsWith("auth") || cmd.startsWith("mcp");
2223
+ var fetch2 = createWhopFetch();
2224
+ var isAuthExempt = (cmd) => !cmd || cmd === "login" || cmd === "logout" || cmd === "completions" || cmd === "upgrade" || cmd.startsWith("auth") || cmd.startsWith("mcp");
1787
2225
  cli.use(async (c2, next) => {
1788
2226
  if (isAuthExempt(c2.command)) return next();
1789
2227
  if (getActiveProfile()) return next();
@@ -1823,7 +2261,7 @@ cli.use(async (c2, next) => {
1823
2261
  });
1824
2262
  registerHandwrittenGroups(cli);
1825
2263
  for (const { name, tag } of API_GROUPS) {
1826
- cli.command(name, { fetch, openapi: spec(tag) });
2264
+ cli.command(name, { fetch: fetch2, openapi: spec(tag) });
1827
2265
  }
1828
2266
  var cli_default = cli;
1829
2267
 
@@ -1860,6 +2298,13 @@ var api_structure_default = [
1860
2298
  "Referrals"
1861
2299
  ]
1862
2300
  },
2301
+ {
2302
+ group: "Tracking",
2303
+ tags: [
2304
+ "People",
2305
+ "Events"
2306
+ ]
2307
+ },
1863
2308
  {
1864
2309
  group: "Ads",
1865
2310
  tags: [
@@ -1997,73 +2442,9 @@ function buildGroupedHelp(version, description) {
1997
2442
  return lines.join("\n");
1998
2443
  }
1999
2444
 
2000
- // src/lib/colorize-output.ts
2001
- var SECTION_HEADERS = /* @__PURE__ */ new Set([
2002
- "Usage",
2003
- "Arguments",
2004
- "Options",
2005
- "Examples",
2006
- "Environment Variables",
2007
- "Global Options",
2008
- "Integrations",
2009
- "Commands",
2010
- "Aliases"
2011
- ]);
2012
- var FORMAT_FLAGS = ["--json", "--format", "--full-output", "--schema", "--llms", "--llms-full", "--mcp", "--token-count", "--token-limit", "--token-offset"];
2013
- function shouldColorize(argv2) {
2014
- if (!process.stdout.isTTY) return false;
2015
- return !argv2.some((a) => FORMAT_FLAGS.includes(a) || a.startsWith("--format="));
2016
- }
2017
- function paintFlag(flag) {
2018
- return flag.replace(/(<[^>]+>)/g, (m) => c.muted(m)).replace(/(--[\w-]+|-[\w])/g, (m) => c.flag(m));
2019
- }
2020
- var COMMAND_ROW = /^(\s+)(whop\s+\S.*?)(\s{2,}#\s.*)?$/;
2021
- function highlightUrls(text3) {
2022
- return text3.replace(/https?:\/\/[^\s)]+/g, (m) => c.link(m));
2023
- }
2024
- function colorizeLine(line, section, nextLine) {
2025
- const errMatch = line.match(/^(Error(?: \([^)]+\))?:)(.*)$/);
2026
- if (errMatch) return { line: c.error(errMatch[1]) + highlightUrls(errMatch[2]), section };
2027
- if (line.startsWith("Run `")) return { line: c.heading(line), section };
2028
- const header = line.match(/^([A-Z][A-Za-z ]+):(.*)$/);
2029
- if (header && SECTION_HEADERS.has(header[1])) {
2030
- const rest = header[2].replace(/(whop[\w\s-]*)/g, (m) => c.command(m));
2031
- return { line: c.heading(`${header[1]}:`) + rest, section: header[1] };
2032
- }
2033
- const cmd = line.match(COMMAND_ROW);
2034
- if (cmd) {
2035
- return { line: `${cmd[1]}${c.command(cmd[2])}${cmd[3] ? c.description(cmd[3]) : ""}`, section };
2036
- }
2037
- if (line.trim().endsWith(":") && nextLine !== void 0 && COMMAND_ROW.test(nextLine)) {
2038
- return { line: c.heading(line), section };
2039
- }
2040
- if (line.trim() === "") return { line, section: null };
2041
- if (section === "Options" || section === "Global Options" || section === "Environment Variables") {
2042
- const m = line.match(/^(\s+)(\S.*?)(\s{2,})(.*)$/);
2043
- if (m) return { line: `${m[1]}${paintFlag(m[2])}${m[3]}${c.description(m[4])}`, section };
2044
- }
2045
- if (section === "Commands" || section === "Integrations" || section === "Aliases") {
2046
- const m = line.match(/^(\s+)(\S+)(\s{2,})(.*)$/);
2047
- if (m) return { line: `${m[1]}${c.command(m[2])}${m[3]}${c.description(m[4])}`, section };
2048
- }
2049
- if (section === "Arguments") {
2050
- const m = line.match(/^(\s+)(\S+)(\s{2,})(.*)$/);
2051
- if (m) return { line: `${m[1]}${c.id(m[2])}${m[3]}${c.description(m[4])}`, section };
2052
- }
2053
- return { line: highlightUrls(line), section };
2054
- }
2055
- function colorizeOutput(text3) {
2056
- let section = null;
2057
- const lines = text3.split("\n");
2058
- return lines.map((line, i) => {
2059
- const result = colorizeLine(line, section, lines[i + 1]);
2060
- section = result.section;
2061
- return result.line;
2062
- }).join("\n");
2063
- }
2064
-
2065
2445
  // src/index.ts
2066
2446
  var argv = process.argv.slice(2);
2447
+ scheduleUpdateNotice(argv, package_default.version);
2067
2448
  async function serve(argv2) {
2068
2449
  if (shouldColorize(argv2)) {
2069
2450
  await cli_default.serve(argv2, {
@@ -2086,8 +2467,4 @@ if (argv.length === 0 && !getActiveProfile() && !process.env.WHOP_API_KEY) {
2086
2467
  } else {
2087
2468
  await serve(argv);
2088
2469
  }
2089
- var index_default = cli_default;
2090
- export {
2091
- index_default as default
2092
- };
2093
2470
  //# sourceMappingURL=index.js.map