create-whop-kit 1.0.5 → 1.0.6

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 s = p.spinner();
20
+ const s2 = p.spinner();
21
21
  if (isVercelInstalled()) {
22
22
  const versionResult = exec("vercel --version");
23
23
  const currentVersion = versionResult.stdout.replace(/[^0-9.]/g, "");
24
- s.start("Checking for Vercel CLI updates...");
24
+ s2.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
- s.stop(`Vercel CLI updated: ${currentVersion} \u2192 ${newVer}`);
30
+ s2.stop(`Vercel CLI updated: ${currentVersion} \u2192 ${newVer}`);
31
31
  } else {
32
- s.stop(`Vercel CLI up to date (v${currentVersion})`);
32
+ s2.stop(`Vercel CLI up to date (v${currentVersion})`);
33
33
  }
34
34
  } else {
35
- s.stop(`Vercel CLI v${currentVersion} (update check failed, continuing)`);
35
+ s2.stop(`Vercel CLI v${currentVersion} (update check failed, continuing)`);
36
36
  }
37
37
  return true;
38
38
  }
39
- s.start("Installing Vercel CLI...");
39
+ s2.start("Installing Vercel CLI...");
40
40
  const result = exec("npm install -g vercel@latest");
41
41
  if (result.success) {
42
- s.stop("Vercel CLI installed");
42
+ s2.stop("Vercel CLI installed");
43
43
  return true;
44
44
  }
45
- s.stop("Failed to install Vercel CLI");
45
+ s2.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 s = p2.spinner();
125
- s.start("Installing GitHub CLI...");
124
+ const s2 = p2.spinner();
125
+ s2.start("Installing GitHub CLI...");
126
126
  const result = exec("npm install -g gh", void 0, 6e4);
127
127
  if (result.success && hasCommand("gh")) {
128
- s.stop("GitHub CLI installed");
128
+ s2.stop("GitHub CLI installed");
129
129
  return true;
130
130
  }
131
- s.stop("Could not auto-install GitHub CLI");
131
+ s2.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 s = p2.spinner();
145
- s.start("Creating private GitHub repository...");
144
+ let s2 = p2.spinner();
145
+ s2.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
- s.stop(`Repository "${projectName}" already exists`);
154
+ s2.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
- s.stop("Could not create GitHub repo");
157
+ s2.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
- s.stop("GitHub repo created");
162
+ s2.stop("GitHub repo created");
163
163
  }
164
- s = p2.spinner();
165
- s.start("Pushing code to GitHub...");
164
+ s2 = p2.spinner();
165
+ s2.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
- s.stop(`Waiting for GitHub to propagate...`);
171
+ s2.stop(`Waiting for GitHub to propagate...`);
172
172
  await new Promise((r) => setTimeout(r, delay));
173
- s = p2.spinner();
174
- s.start("Pushing code to GitHub...");
173
+ s2 = p2.spinner();
174
+ s2.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
- s.stop(`Could not push (try manually: git push -u origin ${branch})`);
180
+ s2.stop(`Could not push (try manually: git push -u origin ${branch})`);
181
181
  } else {
182
- s.stop("Code pushed to GitHub");
182
+ s2.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()) {
@@ -372,28 +372,28 @@ async function runDeployPipeline(options) {
372
372
  p3.log.success(`Signed in${vercelUser ? ` as ${pc3.bold(vercelUser)}` : ""}`);
373
373
  await vercelLink(projectDir);
374
374
  if (githubRepoUrl) {
375
- const s = p3.spinner();
376
- s.start("Connecting GitHub to Vercel (auto-deploy on push)...");
375
+ const s2 = p3.spinner();
376
+ s2.start("Connecting GitHub to Vercel (auto-deploy on push)...");
377
377
  const connectResult = exec(`vercel git connect ${githubRepoUrl}`, projectDir, 3e4);
378
378
  if (connectResult.success) {
379
- s.stop("Connected \u2014 every git push will auto-deploy");
379
+ s2.stop("Connected \u2014 every git push will auto-deploy");
380
380
  } else {
381
- s.stop("Auto-connect failed (connect manually in Vercel dashboard \u2192 Git)");
381
+ s2.stop("Auto-connect failed (connect manually in Vercel dashboard \u2192 Git)");
382
382
  }
383
383
  }
384
384
  if (databaseUrl) {
385
- let s = p3.spinner();
386
- s.start("Setting DATABASE_URL \u2192 production...");
385
+ let s2 = p3.spinner();
386
+ s2.start("Setting DATABASE_URL \u2192 production...");
387
387
  vercelEnvSet("DATABASE_URL", databaseUrl, "production", projectDir);
388
- s.stop("DATABASE_URL \u2192 production \u2713");
389
- s = p3.spinner();
390
- s.start("Setting DATABASE_URL \u2192 preview...");
388
+ s2.stop("DATABASE_URL \u2192 production \u2713");
389
+ s2 = p3.spinner();
390
+ s2.start("Setting DATABASE_URL \u2192 preview...");
391
391
  vercelEnvSet("DATABASE_URL", databaseUrl, "preview", projectDir);
392
- s.stop("DATABASE_URL \u2192 preview \u2713");
393
- s = p3.spinner();
394
- s.start("Setting DATABASE_URL \u2192 development...");
392
+ s2.stop("DATABASE_URL \u2192 preview \u2713");
393
+ s2 = p3.spinner();
394
+ s2.start("Setting DATABASE_URL \u2192 development...");
395
395
  vercelEnvSet("DATABASE_URL", databaseUrl, "development", projectDir);
396
- s.stop("DATABASE_URL \u2192 development \u2713");
396
+ s2.stop("DATABASE_URL \u2192 development \u2713");
397
397
  }
398
398
  productionUrl = await vercelDeploy(projectDir);
399
399
  if (!productionUrl) {
@@ -414,33 +414,52 @@ async function runDeployPipeline(options) {
414
414
  `${pc3.bold("1.")} Go to ${pc3.cyan("https://whop.com/dashboard/developer")}`,
415
415
  `${pc3.bold("2.")} Click ${pc3.bold('"Create"')} under "Company API Keys"`,
416
416
  `${pc3.bold("3.")} Give it a name (e.g. "${projectName}")`,
417
- `${pc3.bold("4.")} Click Create ${pc3.dim("(default permissions are fine)")}`,
418
- `${pc3.bold("5.")} Copy the key and paste it below`
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`
419
419
  ].join("\n"),
420
420
  "Whop Company API Key"
421
421
  );
422
422
  openUrl("https://whop.com/dashboard/developer");
423
423
  let apiKey = options.whopCompanyKey ?? "";
424
- if (!apiKey) {
425
- const result = await p3.text({
426
- message: "Paste your Company API key",
427
- placeholder: "paste the key here...",
428
- validate: (v) => !v ? "API key is required" : void 0
429
- });
430
- if (p3.isCancel(result)) {
424
+ let companyId = null;
425
+ for (let attempt = 0; attempt < 3; attempt++) {
426
+ if (!apiKey) {
427
+ 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)",
429
+ placeholder: "paste the key here...",
430
+ validate: (v) => !v ? "API key is required" : void 0
431
+ });
432
+ if (p3.isCancel(result)) {
433
+ return { productionUrl, githubUrl: githubRepoUrl ?? void 0 };
434
+ }
435
+ apiKey = result;
436
+ }
437
+ const s2 = p3.spinner();
438
+ s2.start("Validating API key...");
439
+ companyId = await validateApiKey(apiKey);
440
+ if (companyId) {
441
+ s2.stop(`API key valid (company: ${pc3.dim(companyId)})`);
442
+ break;
443
+ }
444
+ s2.stop("API key invalid or missing permissions");
445
+ if (attempt < 2) {
446
+ p3.log.warning(`Make sure the key's role is set to "Owner" (not Admin).`);
447
+ const retry = await p3.confirm({
448
+ message: "Try a different key?",
449
+ initialValue: true
450
+ });
451
+ if (p3.isCancel(retry) || !retry) {
452
+ return { productionUrl, githubUrl: githubRepoUrl ?? void 0 };
453
+ }
454
+ apiKey = "";
455
+ } else {
456
+ p3.log.error("Could not validate after 3 attempts. Configure Whop manually via the setup wizard.");
431
457
  return { productionUrl, githubUrl: githubRepoUrl ?? void 0 };
432
458
  }
433
- apiKey = result;
434
459
  }
435
- const s = p3.spinner();
436
- s.start("Validating API key...");
437
- const companyId = await validateApiKey(apiKey);
438
460
  if (!companyId) {
439
- s.stop("Invalid API key");
440
- p3.log.error("Check that the key has permissions: developer:create_app, developer:manage_api_key, developer:manage_webhook, company:basic:read");
441
461
  return { productionUrl, githubUrl: githubRepoUrl ?? void 0 };
442
462
  }
443
- s.stop(`API key valid (company: ${pc3.dim(companyId)})`);
444
463
  const redirectUris = [
445
464
  "http://localhost:3000/api/auth/callback",
446
465
  `${productionUrl}/api/auth/callback`
@@ -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-L6ITPGHX.js");
687
+ const { runDeployPipeline } = await import("./deploy-P3HDSFDE.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-X5LIASNE.js";
12
+ } from "./chunk-XTFE7H37.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-X5LIASNE.js";
4
+ } from "./chunk-XTFE7H37.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.5",
3
+ "version": "1.0.6",
4
4
  "description": "Scaffold and manage Whop-powered apps with whop-kit",
5
5
  "type": "module",
6
6
  "license": "MIT",