create-whop-kit 1.0.6 → 1.0.7

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.
@@ -17,32 +17,32 @@ function isVercelInstalled() {
17
17
  return hasCommand("vercel");
18
18
  }
19
19
  async function installOrUpdateVercel() {
20
- const s2 = p.spinner();
20
+ const s = p.spinner();
21
21
  if (isVercelInstalled()) {
22
22
  const versionResult = exec("vercel --version");
23
23
  const currentVersion = versionResult.stdout.replace(/[^0-9.]/g, "");
24
- s2.start("Checking for Vercel CLI updates...");
24
+ s.start("Checking for Vercel CLI updates...");
25
25
  const updateResult = exec("npm install -g vercel@latest", void 0, 6e4);
26
26
  if (updateResult.success) {
27
27
  const newVersion = exec("vercel --version");
28
28
  const newVer = newVersion.stdout.replace(/[^0-9.]/g, "");
29
29
  if (newVer !== currentVersion) {
30
- s2.stop(`Vercel CLI updated: ${currentVersion} \u2192 ${newVer}`);
30
+ s.stop(`Vercel CLI updated: ${currentVersion} \u2192 ${newVer}`);
31
31
  } else {
32
- s2.stop(`Vercel CLI up to date (v${currentVersion})`);
32
+ s.stop(`Vercel CLI up to date (v${currentVersion})`);
33
33
  }
34
34
  } else {
35
- s2.stop(`Vercel CLI v${currentVersion} (update check failed, continuing)`);
35
+ s.stop(`Vercel CLI v${currentVersion} (update check failed, continuing)`);
36
36
  }
37
37
  return true;
38
38
  }
39
- s2.start("Installing Vercel CLI...");
39
+ s.start("Installing Vercel CLI...");
40
40
  const result = exec("npm install -g vercel@latest");
41
41
  if (result.success) {
42
- s2.stop("Vercel CLI installed");
42
+ s.stop("Vercel CLI installed");
43
43
  return true;
44
44
  }
45
- s2.stop("Failed to install Vercel CLI");
45
+ s.stop("Failed to install Vercel CLI");
46
46
  p.log.error(`Install manually: ${pc.bold("npm install -g vercel@latest")}`);
47
47
  return false;
48
48
  }
@@ -121,14 +121,14 @@ function isGhAuthenticated() {
121
121
  return result.success;
122
122
  }
123
123
  async function installGh() {
124
- const s2 = p2.spinner();
125
- s2.start("Installing GitHub CLI...");
124
+ const s = p2.spinner();
125
+ s.start("Installing GitHub CLI...");
126
126
  const result = exec("npm install -g gh", void 0, 6e4);
127
127
  if (result.success && hasCommand("gh")) {
128
- s2.stop("GitHub CLI installed");
128
+ s.stop("GitHub CLI installed");
129
129
  return true;
130
130
  }
131
- s2.stop("Could not auto-install GitHub CLI");
131
+ s.stop("Could not auto-install GitHub CLI");
132
132
  p2.log.info("Install manually:");
133
133
  p2.log.info(pc2.bold(" https://cli.github.com"));
134
134
  return false;
@@ -141,8 +141,8 @@ async function ghLogin() {
141
141
  return ok;
142
142
  }
143
143
  async function createGitHubRepo(projectDir, projectName) {
144
- let s2 = p2.spinner();
145
- s2.start("Creating private GitHub repository...");
144
+ let s = p2.spinner();
145
+ s.start("Creating private GitHub repository...");
146
146
  const createResult = exec(
147
147
  `gh repo create ${projectName} --private --source=.`,
148
148
  projectDir,
@@ -151,35 +151,35 @@ async function createGitHubRepo(projectDir, projectName) {
151
151
  if (!createResult.success) {
152
152
  const stderr = createResult.stderr || createResult.stdout;
153
153
  if (stderr.includes("already exists")) {
154
- s2.stop(`Repository "${projectName}" already exists`);
154
+ s.stop(`Repository "${projectName}" already exists`);
155
155
  exec(`git remote add origin https://github.com/$(gh api user --jq .login)/${projectName}.git`, projectDir);
156
156
  } else {
157
- s2.stop("Could not create GitHub repo");
157
+ s.stop("Could not create GitHub repo");
158
158
  if (stderr) p2.log.error(pc2.dim(stderr.substring(0, 200)));
159
159
  return null;
160
160
  }
161
161
  } else {
162
- s2.stop("GitHub repo created");
162
+ s.stop("GitHub repo created");
163
163
  }
164
- s2 = p2.spinner();
165
- s2.start("Pushing code to GitHub...");
164
+ s = p2.spinner();
165
+ s.start("Pushing code to GitHub...");
166
166
  const branchResult = exec("git branch --show-current", projectDir);
167
167
  const branch = branchResult.success ? branchResult.stdout.trim() : "main";
168
168
  let pushOk = false;
169
169
  for (const delay of [0, 3e3, 7e3]) {
170
170
  if (delay > 0) {
171
- s2.stop(`Waiting for GitHub to propagate...`);
171
+ s.stop(`Waiting for GitHub to propagate...`);
172
172
  await new Promise((r) => setTimeout(r, delay));
173
- s2 = p2.spinner();
174
- s2.start("Pushing code to GitHub...");
173
+ s = p2.spinner();
174
+ s.start("Pushing code to GitHub...");
175
175
  }
176
176
  pushOk = exec(`git push -u origin ${branch}`, projectDir, 3e4).success;
177
177
  if (pushOk) break;
178
178
  }
179
179
  if (!pushOk) {
180
- s2.stop(`Could not push (try manually: git push -u origin ${branch})`);
180
+ s.stop(`Could not push (try manually: git push -u origin ${branch})`);
181
181
  } else {
182
- s2.stop("Code pushed to GitHub");
182
+ s.stop("Code pushed to GitHub");
183
183
  }
184
184
  const repoUrl = exec("gh repo view --json url --jq .url", projectDir);
185
185
  if (repoUrl.success && repoUrl.stdout.trim()) {
@@ -201,72 +201,55 @@ function headers(apiKey) {
201
201
  "Content-Type": "application/json"
202
202
  };
203
203
  }
204
- async function getCompanyId(apiKey) {
204
+ async function validateApiKey(apiKey) {
205
205
  try {
206
- const res = await fetch(`${WHOP_API}/companies`, {
206
+ const res = await fetch(`${WHOP_API}/apps?per_page=1`, {
207
207
  headers: headers(apiKey)
208
208
  });
209
- if (!res.ok) return null;
210
- const data = await res.json();
211
- const companies = data.data || data;
212
- if (Array.isArray(companies) && companies.length > 0) {
213
- return companies[0].id;
214
- }
215
- return null;
209
+ return res.ok;
216
210
  } catch {
217
- return null;
211
+ return false;
218
212
  }
219
213
  }
220
- async function validateApiKey(apiKey) {
221
- return getCompanyId(apiKey);
222
- }
223
- async function createWhopApp(apiKey, name, redirectUris, companyId) {
214
+ async function createWhopApp(apiKey, name, redirectUris) {
224
215
  try {
225
216
  const res = await fetch(`${WHOP_API}/apps`, {
226
217
  method: "POST",
227
218
  headers: headers(apiKey),
228
219
  body: JSON.stringify({
229
220
  name,
230
- company_id: companyId,
231
221
  redirect_uris: redirectUris
232
222
  })
233
223
  });
234
- if (!res.ok) {
235
- const err = await res.text().catch(() => "");
236
- console.error(`[Whop API] Create app failed (${res.status}): ${err}`);
237
- return null;
224
+ if (res.ok) {
225
+ const data = await res.json();
226
+ return { id: data.id, client_secret: data.client_secret };
238
227
  }
239
- const data = await res.json();
240
- return {
241
- id: data.id,
242
- client_secret: data.client_secret
243
- };
228
+ const err = await res.text().catch(() => "");
229
+ console.error(`[Whop API] Create app failed (${res.status}): ${err}`);
230
+ return null;
244
231
  } catch (err) {
245
232
  console.error("[Whop API] Create app error:", err);
246
233
  return null;
247
234
  }
248
235
  }
249
- async function createWhopWebhook(apiKey, url, events, companyId) {
236
+ async function createWhopWebhook(apiKey, url, events) {
250
237
  try {
251
238
  const res = await fetch(`${WHOP_API}/webhooks`, {
252
239
  method: "POST",
253
240
  headers: headers(apiKey),
254
- body: JSON.stringify({
255
- url,
256
- events,
257
- company_id: companyId
258
- })
241
+ body: JSON.stringify({ url, events })
259
242
  });
260
- if (!res.ok) {
261
- const err = await res.text().catch(() => "");
262
- console.error(`[Whop API] Create webhook failed (${res.status}): ${err}`);
263
- return null;
243
+ if (res.ok) {
244
+ const data = await res.json();
245
+ return {
246
+ id: data.id,
247
+ secret: data.secret || data.signing_secret || data.webhook_secret || ""
248
+ };
264
249
  }
265
- const data = await res.json();
266
- return {
267
- id: data.id,
268
- secret: data.secret || data.signing_secret || data.webhook_secret || ""
269
- };
250
+ const err = await res.text().catch(() => "");
251
+ console.error(`[Whop API] Create webhook failed (${res.status}): ${err}`);
252
+ return null;
270
253
  } catch (err) {
271
254
  console.error("[Whop API] Create webhook error:", err);
272
255
  return null;
@@ -372,28 +355,28 @@ async function runDeployPipeline(options) {
372
355
  p3.log.success(`Signed in${vercelUser ? ` as ${pc3.bold(vercelUser)}` : ""}`);
373
356
  await vercelLink(projectDir);
374
357
  if (githubRepoUrl) {
375
- const s2 = p3.spinner();
376
- s2.start("Connecting GitHub to Vercel (auto-deploy on push)...");
358
+ const s = p3.spinner();
359
+ s.start("Connecting GitHub to Vercel (auto-deploy on push)...");
377
360
  const connectResult = exec(`vercel git connect ${githubRepoUrl}`, projectDir, 3e4);
378
361
  if (connectResult.success) {
379
- s2.stop("Connected \u2014 every git push will auto-deploy");
362
+ s.stop("Connected \u2014 every git push will auto-deploy");
380
363
  } else {
381
- s2.stop("Auto-connect failed (connect manually in Vercel dashboard \u2192 Git)");
364
+ s.stop("Auto-connect failed (connect manually in Vercel dashboard \u2192 Git)");
382
365
  }
383
366
  }
384
367
  if (databaseUrl) {
385
- let s2 = p3.spinner();
386
- s2.start("Setting DATABASE_URL \u2192 production...");
368
+ let s = p3.spinner();
369
+ s.start("Setting DATABASE_URL \u2192 production...");
387
370
  vercelEnvSet("DATABASE_URL", databaseUrl, "production", projectDir);
388
- s2.stop("DATABASE_URL \u2192 production \u2713");
389
- s2 = p3.spinner();
390
- s2.start("Setting DATABASE_URL \u2192 preview...");
371
+ s.stop("DATABASE_URL \u2192 production \u2713");
372
+ s = p3.spinner();
373
+ s.start("Setting DATABASE_URL \u2192 preview...");
391
374
  vercelEnvSet("DATABASE_URL", databaseUrl, "preview", projectDir);
392
- s2.stop("DATABASE_URL \u2192 preview \u2713");
393
- s2 = p3.spinner();
394
- s2.start("Setting DATABASE_URL \u2192 development...");
375
+ s.stop("DATABASE_URL \u2192 preview \u2713");
376
+ s = p3.spinner();
377
+ s.start("Setting DATABASE_URL \u2192 development...");
395
378
  vercelEnvSet("DATABASE_URL", databaseUrl, "development", projectDir);
396
- s2.stop("DATABASE_URL \u2192 development \u2713");
379
+ s.stop("DATABASE_URL \u2192 development \u2713");
397
380
  }
398
381
  productionUrl = await vercelDeploy(projectDir);
399
382
  if (!productionUrl) {
@@ -414,18 +397,18 @@ async function runDeployPipeline(options) {
414
397
  `${pc3.bold("1.")} Go to ${pc3.cyan("https://whop.com/dashboard/developer")}`,
415
398
  `${pc3.bold("2.")} Click ${pc3.bold('"Create"')} under "Company API Keys"`,
416
399
  `${pc3.bold("3.")} Give it a name (e.g. "${projectName}")`,
417
- `${pc3.bold("4.")} Set role to ${pc3.bold('"Owner"')} ${pc3.dim("(ensures all permissions)")}`,
418
- `${pc3.bold("5.")} Click Create, copy the key, and paste it below`
400
+ `${pc3.bold("4.")} Click Create and copy the key`,
401
+ `${pc3.bold("5.")} Paste it below`
419
402
  ].join("\n"),
420
403
  "Whop Company API Key"
421
404
  );
422
405
  openUrl("https://whop.com/dashboard/developer");
423
406
  let apiKey = options.whopCompanyKey ?? "";
424
- let companyId = null;
407
+ let keyValid = false;
425
408
  for (let attempt = 0; attempt < 3; attempt++) {
426
409
  if (!apiKey) {
427
410
  const result = await p3.text({
428
- message: attempt === 0 ? "Paste your Company API key" : "Paste a new Company API key (make sure role is set to Owner)",
411
+ message: attempt === 0 ? "Paste your Company API key" : "Paste a new Company API key",
429
412
  placeholder: "paste the key here...",
430
413
  validate: (v) => !v ? "API key is required" : void 0
431
414
  });
@@ -436,14 +419,13 @@ async function runDeployPipeline(options) {
436
419
  }
437
420
  const s2 = p3.spinner();
438
421
  s2.start("Validating API key...");
439
- companyId = await validateApiKey(apiKey);
440
- if (companyId) {
441
- s2.stop(`API key valid (company: ${pc3.dim(companyId)})`);
422
+ keyValid = await validateApiKey(apiKey);
423
+ if (keyValid) {
424
+ s2.stop("API key valid");
442
425
  break;
443
426
  }
444
- s2.stop("API key invalid or missing permissions");
427
+ s2.stop("API key invalid");
445
428
  if (attempt < 2) {
446
- p3.log.warning(`Make sure the key's role is set to "Owner" (not Admin).`);
447
429
  const retry = await p3.confirm({
448
430
  message: "Try a different key?",
449
431
  initialValue: true
@@ -453,19 +435,20 @@ async function runDeployPipeline(options) {
453
435
  }
454
436
  apiKey = "";
455
437
  } else {
456
- p3.log.error("Could not validate after 3 attempts. Configure Whop manually via the setup wizard.");
438
+ p3.log.error("Could not validate. Configure Whop manually via the setup wizard.");
457
439
  return { productionUrl, githubUrl: githubRepoUrl ?? void 0 };
458
440
  }
459
441
  }
460
- if (!companyId) {
442
+ if (!keyValid) {
461
443
  return { productionUrl, githubUrl: githubRepoUrl ?? void 0 };
462
444
  }
463
445
  const redirectUris = [
464
446
  "http://localhost:3000/api/auth/callback",
465
447
  `${productionUrl}/api/auth/callback`
466
448
  ];
449
+ const s = p3.spinner();
467
450
  s.start("Creating Whop OAuth app...");
468
- const app = await createWhopApp(apiKey, projectName, redirectUris, companyId);
451
+ const app = await createWhopApp(apiKey, projectName, redirectUris);
469
452
  if (!app) {
470
453
  s.stop("Failed to create app");
471
454
  p3.log.error("Create manually: " + pc3.cyan("https://whop.com/dashboard/developer"));
@@ -473,7 +456,7 @@ async function runDeployPipeline(options) {
473
456
  }
474
457
  s.stop(`OAuth app created: ${pc3.bold(app.id)}`);
475
458
  s.start("Creating webhook...");
476
- const webhook = await createWhopWebhook(apiKey, `${productionUrl}/api/webhooks/whop`, WEBHOOK_EVENTS, companyId);
459
+ const webhook = await createWhopWebhook(apiKey, `${productionUrl}/api/webhooks/whop`, WEBHOOK_EVENTS);
477
460
  if (!webhook) {
478
461
  s.stop("Failed (create manually in Whop dashboard)");
479
462
  } else {
@@ -684,7 +684,7 @@ var init_default = defineCommand({
684
684
  });
685
685
  if (!isCancelled(deployChoice) && deployChoice === "deploy") {
686
686
  deployAttempted = true;
687
- const { runDeployPipeline } = await import("./deploy-P3HDSFDE.js");
687
+ const { runDeployPipeline } = await import("./deploy-AMH7INFV.js");
688
688
  deployResult = await runDeployPipeline({
689
689
  projectDir,
690
690
  projectName,
package/dist/cli-kit.js CHANGED
@@ -9,7 +9,7 @@ import {
9
9
  } from "./chunk-HOQ5QQ2M.js";
10
10
  import {
11
11
  runDeployPipeline
12
- } from "./chunk-XTFE7H37.js";
12
+ } from "./chunk-E2IWGU3U.js";
13
13
  import {
14
14
  detectPackageManager,
15
15
  exec
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  runDeployPipeline
4
- } from "./chunk-XTFE7H37.js";
4
+ } from "./chunk-E2IWGU3U.js";
5
5
  import "./chunk-42L7PRMT.js";
6
6
  export {
7
7
  runDeployPipeline
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-whop-kit",
3
- "version": "1.0.6",
3
+ "version": "1.0.7",
4
4
  "description": "Scaffold and manage Whop-powered apps with whop-kit",
5
5
  "type": "module",
6
6
  "license": "MIT",