@whop/cli 0.4.0 → 0.5.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/{api-7L74UEG4.js → api-E6Y2WAEG.js} +2 -2
- package/dist/{chunk-2K4WBZA5.js → chunk-X34EUMEM.js} +595 -136
- package/dist/chunk-X34EUMEM.js.map +1 -0
- package/dist/index.js +134 -6
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-2K4WBZA5.js.map +0 -1
- /package/dist/{api-7L74UEG4.js.map → api-E6Y2WAEG.js.map} +0 -0
package/dist/index.js
CHANGED
|
@@ -35,7 +35,7 @@ import {
|
|
|
35
35
|
switchProfile,
|
|
36
36
|
upsertProfile,
|
|
37
37
|
validateApiKey
|
|
38
|
-
} from "./chunk-
|
|
38
|
+
} from "./chunk-X34EUMEM.js";
|
|
39
39
|
import {
|
|
40
40
|
external_exports
|
|
41
41
|
} from "./chunk-KFCNNWPI.js";
|
|
@@ -122,6 +122,10 @@ var groups_default = [
|
|
|
122
122
|
"audiences",
|
|
123
123
|
"Audiences"
|
|
124
124
|
],
|
|
125
|
+
[
|
|
126
|
+
"media",
|
|
127
|
+
"Media"
|
|
128
|
+
],
|
|
125
129
|
[
|
|
126
130
|
"social-accounts",
|
|
127
131
|
"Social Accounts"
|
|
@@ -314,7 +318,7 @@ async function loginAdapter(c2) {
|
|
|
314
318
|
const accountId = getActiveProfile()?.accountId ?? "";
|
|
315
319
|
if (accountId) {
|
|
316
320
|
try {
|
|
317
|
-
const { createWhopFetch: createWhopFetch2 } = await import("./api-
|
|
321
|
+
const { createWhopFetch: createWhopFetch2 } = await import("./api-E6Y2WAEG.js");
|
|
318
322
|
const fetch3 = createWhopFetch2();
|
|
319
323
|
const res = await fetch3(
|
|
320
324
|
new Request(
|
|
@@ -644,6 +648,9 @@ async function getApp(appId) {
|
|
|
644
648
|
async function updateAppRoute(appId, route) {
|
|
645
649
|
return makeWhopRequest("PATCH", `/apps/${appId}`, { route });
|
|
646
650
|
}
|
|
651
|
+
async function updateAppSecrets(appId, secrets) {
|
|
652
|
+
return makeWhopRequest("PATCH", `/apps/${appId}`, { secrets });
|
|
653
|
+
}
|
|
647
654
|
async function createAppBuild(input) {
|
|
648
655
|
return makeWhopRequest("POST", "/app_builds", {
|
|
649
656
|
app_id: input.app_id,
|
|
@@ -984,6 +991,17 @@ function replaceTopLevelName(content, route) {
|
|
|
984
991
|
|
|
985
992
|
// src/apps/commands.ts
|
|
986
993
|
var BUILD_ARCHIVE = "dist/whop-build.zip";
|
|
994
|
+
var UNSAFE_DEV_ENV_KEYS = /* @__PURE__ */ new Set([
|
|
995
|
+
"PATH",
|
|
996
|
+
"NODE_OPTIONS",
|
|
997
|
+
"NODE_EXTRA_CA_CERTS",
|
|
998
|
+
"NODE_REPL_EXTERNAL_MODULE"
|
|
999
|
+
]);
|
|
1000
|
+
var UNSAFE_DEV_ENV_PREFIXES = ["NPM_", "PNPM_", "YARN_", "BUN_", "LD_", "DYLD_"];
|
|
1001
|
+
function isUnsafeDevEnvKey(key) {
|
|
1002
|
+
const upper = key.toUpperCase();
|
|
1003
|
+
return UNSAFE_DEV_ENV_KEYS.has(upper) || UNSAFE_DEV_ENV_PREFIXES.some((prefix) => upper.startsWith(prefix));
|
|
1004
|
+
}
|
|
987
1005
|
var BuildSchema = external_exports.object({
|
|
988
1006
|
id: external_exports.string(),
|
|
989
1007
|
status: external_exports.string(),
|
|
@@ -1359,6 +1377,77 @@ async function withRoute(c2, app) {
|
|
|
1359
1377
|
});
|
|
1360
1378
|
}
|
|
1361
1379
|
}
|
|
1380
|
+
function resolveSecretsAppId(appOption) {
|
|
1381
|
+
if (appOption) return appOption;
|
|
1382
|
+
const projectDir = findProjectDir();
|
|
1383
|
+
const config = projectDir ? readAppConfig(projectDir) : null;
|
|
1384
|
+
if (config) return config.app_id;
|
|
1385
|
+
throw new Error(
|
|
1386
|
+
`No app specified. Pass --app app_xxx or run inside a project with ${APP_CONFIG_FILENAME}.`
|
|
1387
|
+
);
|
|
1388
|
+
}
|
|
1389
|
+
function buildSecretsGroup() {
|
|
1390
|
+
const secrets = Cli_exports.create("secrets", {
|
|
1391
|
+
description: "Manage app secrets \u2014 encrypted at rest, injected as env bindings into the hosted runtime and `whop apps dev`"
|
|
1392
|
+
});
|
|
1393
|
+
secrets.command("list", {
|
|
1394
|
+
description: "Show the app's secrets",
|
|
1395
|
+
options: external_exports.object({
|
|
1396
|
+
app: external_exports.string().optional().describe("App id (defaults to the project's linked app)")
|
|
1397
|
+
}),
|
|
1398
|
+
run: async (c2) => {
|
|
1399
|
+
const remote = await getApp(resolveSecretsAppId(c2.options.app));
|
|
1400
|
+
return c2.ok({ app_id: remote.id, secrets: remote.secrets ?? {} });
|
|
1401
|
+
}
|
|
1402
|
+
});
|
|
1403
|
+
secrets.command("set", {
|
|
1404
|
+
description: "Add or overwrite secrets",
|
|
1405
|
+
options: external_exports.object({
|
|
1406
|
+
secret: external_exports.array(external_exports.string()).min(1).describe("KEY=VALUE pair (repeatable)"),
|
|
1407
|
+
app: external_exports.string().optional().describe("App id (defaults to the project's linked app)")
|
|
1408
|
+
}),
|
|
1409
|
+
examples: [
|
|
1410
|
+
{ options: { secret: ["MAIL_API_KEY=mail-key-123"] } },
|
|
1411
|
+
{ options: { secret: ["A=1", "B=2"], app: "app_xxxxxxxx" } }
|
|
1412
|
+
],
|
|
1413
|
+
run: async (c2) => {
|
|
1414
|
+
const updates = {};
|
|
1415
|
+
for (const pair of c2.options.secret) {
|
|
1416
|
+
const eq = pair.indexOf("=");
|
|
1417
|
+
if (eq <= 0) {
|
|
1418
|
+
return c2.error({
|
|
1419
|
+
code: "INVALID_SECRET",
|
|
1420
|
+
message: `"${pair}" is not KEY=VALUE. Use --secret NAME=value (an empty value deletes the secret).`
|
|
1421
|
+
});
|
|
1422
|
+
}
|
|
1423
|
+
updates[pair.slice(0, eq)] = pair.slice(eq + 1);
|
|
1424
|
+
}
|
|
1425
|
+
const remote = await updateAppSecrets(
|
|
1426
|
+
resolveSecretsAppId(c2.options.app),
|
|
1427
|
+
updates
|
|
1428
|
+
);
|
|
1429
|
+
return c2.ok({ app_id: remote.id, secrets: remote.secrets ?? {} });
|
|
1430
|
+
}
|
|
1431
|
+
});
|
|
1432
|
+
secrets.command("unset", {
|
|
1433
|
+
description: "Delete secrets by name",
|
|
1434
|
+
options: external_exports.object({
|
|
1435
|
+
key: external_exports.array(external_exports.string()).min(1).describe("Secret name (repeatable)"),
|
|
1436
|
+
app: external_exports.string().optional().describe("App id (defaults to the project's linked app)")
|
|
1437
|
+
}),
|
|
1438
|
+
examples: [{ options: { key: ["MAIL_API_KEY"] } }],
|
|
1439
|
+
run: async (c2) => {
|
|
1440
|
+
const updates = {};
|
|
1441
|
+
for (const key of c2.options.key) updates[key] = null;
|
|
1442
|
+
const remote = await updateAppSecrets(
|
|
1443
|
+
resolveSecretsAppId(c2.options.app),
|
|
1444
|
+
updates
|
|
1445
|
+
);
|
|
1446
|
+
return c2.ok({ app_id: remote.id, secrets: remote.secrets ?? {} });
|
|
1447
|
+
}
|
|
1448
|
+
});
|
|
1449
|
+
return secrets;
|
|
1450
|
+
}
|
|
1362
1451
|
async function buildAppGroup() {
|
|
1363
1452
|
const app = Cli_exports.create("apps", {
|
|
1364
1453
|
description: "Build and deploy fully-hosted web apps on Whop (*.whop.app)"
|
|
@@ -1369,6 +1458,7 @@ async function buildAppGroup() {
|
|
|
1369
1458
|
});
|
|
1370
1459
|
await registerSpecCommands(builds, "App builds");
|
|
1371
1460
|
app.command(builds);
|
|
1461
|
+
app.command(buildSecretsGroup());
|
|
1372
1462
|
app.command("dev", {
|
|
1373
1463
|
description: "Run the local dev server for this app",
|
|
1374
1464
|
hint: "Starts the project's dev script with WHOP_APP_ID set and a short-lived access token injected as WHOP_API_KEY (minted from your CLI credential), so server-side SDK calls work locally without env setup. An explicitly exported WHOP_API_KEY is used as-is.",
|
|
@@ -1423,6 +1513,40 @@ async function buildAppGroup() {
|
|
|
1423
1513
|
);
|
|
1424
1514
|
}
|
|
1425
1515
|
}
|
|
1516
|
+
try {
|
|
1517
|
+
const remote = await getApp(config.app_id);
|
|
1518
|
+
const secretEntries = Object.entries(remote.secrets ?? {}).filter(
|
|
1519
|
+
([key]) => !(key in process.env) && !(key in injected)
|
|
1520
|
+
);
|
|
1521
|
+
const unsafe = secretEntries.filter(([key]) => isUnsafeDevEnvKey(key));
|
|
1522
|
+
for (const [key, value] of secretEntries) {
|
|
1523
|
+
if (!isUnsafeDevEnvKey(key)) injected[key] = value;
|
|
1524
|
+
}
|
|
1525
|
+
if (unsafe.length > 0) {
|
|
1526
|
+
log(
|
|
1527
|
+
c2,
|
|
1528
|
+
chalk.yellow(
|
|
1529
|
+
`Skipped app secret${unsafe.length === 1 ? "" : "s"} ${unsafe.map(([key]) => key).join(", ")} \u2014 these names control the local runtime and are never injected by \`whop apps dev\`.`
|
|
1530
|
+
)
|
|
1531
|
+
);
|
|
1532
|
+
}
|
|
1533
|
+
const injectedCount = secretEntries.length - unsafe.length;
|
|
1534
|
+
if (injectedCount > 0) {
|
|
1535
|
+
log(
|
|
1536
|
+
c2,
|
|
1537
|
+
chalk.dim(
|
|
1538
|
+
`Injected ${injectedCount} app secret${injectedCount === 1 ? "" : "s"} into the environment (${secretEntries.filter(([key]) => !isUnsafeDevEnvKey(key)).map(([key]) => key).join(", ")}).`
|
|
1539
|
+
)
|
|
1540
|
+
);
|
|
1541
|
+
}
|
|
1542
|
+
} catch (err) {
|
|
1543
|
+
log(
|
|
1544
|
+
c2,
|
|
1545
|
+
chalk.yellow(
|
|
1546
|
+
`Couldn't fetch app secrets (${err instanceof Error ? err.message : "unknown error"}) \u2014 continuing without them.`
|
|
1547
|
+
)
|
|
1548
|
+
);
|
|
1549
|
+
}
|
|
1426
1550
|
log(c2, chalk.dim(`Starting dev server for ${config.name}...`));
|
|
1427
1551
|
try {
|
|
1428
1552
|
runScript(projectDir, "dev", injected);
|
|
@@ -1443,9 +1567,7 @@ async function buildAppGroup() {
|
|
|
1443
1567
|
app: external_exports.string().optional().describe(
|
|
1444
1568
|
"Link this project to an app (app_xxx) before deploying \u2014 writes whop.app.json, replacing any existing link"
|
|
1445
1569
|
),
|
|
1446
|
-
skip_promote: external_exports.boolean().optional().describe(
|
|
1447
|
-
"Upload the build without promoting it to production"
|
|
1448
|
-
),
|
|
1570
|
+
skip_promote: external_exports.boolean().optional().describe("Upload the build without promoting it to production"),
|
|
1449
1571
|
skip_typecheck: external_exports.boolean().optional().describe("Skip the typecheck step"),
|
|
1450
1572
|
skip_build: external_exports.boolean().optional().describe("Skip the build step and upload the existing dist/ output")
|
|
1451
1573
|
}),
|
|
@@ -2218,7 +2340,7 @@ ${c.success("\u2713 Your store is fully set up.")}`);
|
|
|
2218
2340
|
// package.json
|
|
2219
2341
|
var package_default = {
|
|
2220
2342
|
name: "@whop/cli",
|
|
2221
|
-
version: "0.
|
|
2343
|
+
version: "0.5.0",
|
|
2222
2344
|
description: "The Whop CLI \u2014 build and manage Whop apps from your terminal. Human and agent friendly.",
|
|
2223
2345
|
keywords: [
|
|
2224
2346
|
"agent",
|
|
@@ -2990,6 +3112,12 @@ var api_structure_default = [
|
|
|
2990
3112
|
"Audiences"
|
|
2991
3113
|
]
|
|
2992
3114
|
},
|
|
3115
|
+
{
|
|
3116
|
+
group: "Media",
|
|
3117
|
+
tags: [
|
|
3118
|
+
"Media"
|
|
3119
|
+
]
|
|
3120
|
+
},
|
|
2993
3121
|
{
|
|
2994
3122
|
group: "Identity",
|
|
2995
3123
|
tags: [
|