@just-be/deploy 0.4.0 → 0.6.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.
Files changed (3) hide show
  1. package/README.md +12 -3
  2. package/index.ts +104 -5
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -5,15 +5,24 @@ Deploy static sites and setup routing for the wildcard subdomain service.
5
5
  ## Requirements
6
6
 
7
7
  - [Bun](https://bun.sh/) runtime
8
- - [Wrangler](https://developers.cloudflare.com/workers/wrangler/) CLI configured with Cloudflare credentials
9
8
  - A Cloudflare Workers wildcard subdomain service with R2 and KV configured
10
9
 
10
+ ## Authentication
11
+
12
+ The script will automatically run `wrangler login` if you're not authenticated with Cloudflare. This will open a browser window for OAuth authentication.
13
+
14
+ Alternatively, you can set the `CLOUDFLARE_API_TOKEN` environment variable:
15
+
16
+ ```bash
17
+ export CLOUDFLARE_API_TOKEN="your-api-token"
18
+ ```
19
+
11
20
  ## Configuration
12
21
 
13
22
  The deploy script requires access to:
14
23
 
15
- - **KV namespace** for routing rules (default: `6118ae3b937c4883b3c582dfef8a0c05`)
16
- - **R2 bucket** for static file storage (default: `content-bucket`)
24
+ - **KV namespace** for routing rules
25
+ - **R2 bucket** for static file storage
17
26
 
18
27
  ### Environment Variables
19
28
 
package/index.ts CHANGED
@@ -7,6 +7,16 @@
7
7
  * bunx @just-be/deploy # Looks for deploy.json in current directory
8
8
  * bunx @just-be/deploy path/to/config.json # Deploy with specific config file
9
9
  * bunx @just-be/deploy preview <subdomain> # Preview deploy with branch name suffix
10
+ * bunx @just-be/deploy --version # Show version
11
+ *
12
+ * Authentication:
13
+ * The script will automatically run 'wrangler login' if you're not authenticated.
14
+ * Alternatively, set CLOUDFLARE_API_TOKEN environment variable.
15
+ *
16
+ * Environment Variables:
17
+ * R2_BUCKET_NAME # R2 bucket name
18
+ * KV_NAMESPACE_ID # KV namespace ID
19
+ * DEBUG # Set to "1" or "true" to enable verbose error output
10
20
  *
11
21
  * Example deploy.json:
12
22
  * {
@@ -37,6 +47,7 @@ import { readdir, stat, access } from "fs/promises";
37
47
  import { join, relative, resolve } from "path";
38
48
  import { intro, outro, spinner } from "@clack/prompts";
39
49
  import { z } from "zod";
50
+ import packageJson from "./package.json" with { type: "json" };
40
51
  import {
41
52
  StaticConfigSchema,
42
53
  RedirectConfigSchema,
@@ -47,6 +58,7 @@ import {
47
58
 
48
59
  const BUCKET_NAME = process.env.R2_BUCKET_NAME || "content-bucket";
49
60
  const KV_NAMESPACE_ID = process.env.KV_NAMESPACE_ID || "6118ae3b937c4883b3c582dfef8a0c05";
61
+ const DEBUG = process.env.DEBUG === "1" || process.env.DEBUG === "true";
50
62
 
51
63
  /**
52
64
  * Run wrangler command using bunx to ensure it resolves from package dependencies
@@ -167,7 +179,34 @@ async function uploadToR2(localPath: string, r2Key: string): Promise<boolean> {
167
179
  await wrangler`r2 object put ${BUCKET_NAME}/${r2Key} --file ${localPath}`;
168
180
  return true;
169
181
  } catch (error) {
170
- console.error(`\nFailed to upload ${localPath}:`, error);
182
+ if (DEBUG) {
183
+ console.error(`\nFailed to upload ${localPath}:`);
184
+ console.error("Error details:", error);
185
+ if (error instanceof Error) {
186
+ console.error("Stack trace:", error.stack);
187
+ }
188
+ } else {
189
+ console.error(`\nFailed to upload ${localPath}:`, error);
190
+ }
191
+ return false;
192
+ }
193
+ }
194
+
195
+ /**
196
+ * Check if user is authenticated with wrangler
197
+ */
198
+ async function validateWranglerAuth(): Promise<boolean> {
199
+ try {
200
+ await wrangler`whoami`.quiet();
201
+ return true;
202
+ } catch (error) {
203
+ if (DEBUG) {
204
+ console.error("\nWrangler auth validation failed:");
205
+ console.error("Error details:", error);
206
+ if (error instanceof Error) {
207
+ console.error("Stack trace:", error.stack);
208
+ }
209
+ }
171
210
  return false;
172
211
  }
173
212
  }
@@ -179,7 +218,15 @@ async function validateKVAccess(): Promise<boolean> {
179
218
  try {
180
219
  await wrangler`kv key list --namespace-id ${KV_NAMESPACE_ID}`.quiet();
181
220
  return true;
182
- } catch {
221
+ } catch (error) {
222
+ if (DEBUG) {
223
+ console.error("\nKV access validation failed:");
224
+ console.error("Error details:", error);
225
+ if (error instanceof Error) {
226
+ console.error("Stack trace:", error.stack);
227
+ }
228
+ console.error(`Namespace ID: ${KV_NAMESPACE_ID}`);
229
+ }
183
230
  return false;
184
231
  }
185
232
  }
@@ -192,6 +239,13 @@ async function getCurrentBranch(): Promise<string> {
192
239
  const result = await $`git rev-parse --abbrev-ref HEAD`.text();
193
240
  return result.trim();
194
241
  } catch (error) {
242
+ if (DEBUG) {
243
+ console.error("\nFailed to get current git branch:");
244
+ console.error("Error details:", error);
245
+ if (error instanceof Error) {
246
+ console.error("Stack trace:", error.stack);
247
+ }
248
+ }
195
249
  throw new Error("Failed to get current git branch. Are you in a git repository?");
196
250
  }
197
251
  }
@@ -394,13 +448,50 @@ async function deploy() {
394
448
  console.log(`\nFound ${config.rules.length} rule(s) to deploy`);
395
449
  }
396
450
 
397
- // Validate KV access before starting
451
+ // Check wrangler authentication first
398
452
  const s = spinner();
453
+ s.start("Checking wrangler authentication");
454
+ const isAuthenticated = await validateWranglerAuth();
455
+ if (!isAuthenticated) {
456
+ s.stop("Not authenticated with wrangler");
457
+ console.log("\nAuthenticating with Cloudflare...");
458
+ console.log("This will open a browser window for you to authorize access.\n");
459
+
460
+ try {
461
+ await wrangler`login`;
462
+ console.log("\n✓ Successfully authenticated!");
463
+
464
+ // Verify authentication worked
465
+ s.start("Verifying authentication");
466
+ const isNowAuthenticated = await validateWranglerAuth();
467
+ if (!isNowAuthenticated) {
468
+ s.stop("Error: Authentication verification failed");
469
+ console.error("\nIf you prefer to use an API token instead:");
470
+ console.error(" export CLOUDFLARE_API_TOKEN=your-token");
471
+ process.exit(1);
472
+ }
473
+ s.stop("✓ Authentication verified");
474
+ } catch {
475
+ console.error("\n❌ Authentication failed");
476
+ console.error("\nAlternatively, you can set up an API token:");
477
+ console.error(" export CLOUDFLARE_API_TOKEN=your-token");
478
+ process.exit(1);
479
+ }
480
+ } else {
481
+ s.stop("✓ Wrangler authenticated");
482
+ }
483
+
484
+ // Validate KV access
399
485
  s.start("Validating KV access");
400
486
  const hasKVAccess = await validateKVAccess();
401
487
  if (!hasKVAccess) {
402
488
  s.stop("Error: Cannot access KV namespace");
403
- console.error("Check wrangler configuration and permissions.");
489
+ console.error("\nCheck that you have permission to access the KV namespace.");
490
+ console.error(`KV Namespace ID: ${KV_NAMESPACE_ID}`);
491
+ console.error("\nYou may need to:");
492
+ console.error(" 1. Verify the namespace ID is correct");
493
+ console.error(" 2. Ensure your account has access to this KV namespace");
494
+ console.error(" 3. Check wrangler.toml configuration if using one");
404
495
  process.exit(1);
405
496
  }
406
497
  s.stop("✓ KV access validated");
@@ -432,8 +523,16 @@ async function deploy() {
432
523
  outro("\n✅ Deployment complete!\n\nDeployed sites:\n" + deployedSubdomains.join("\n"));
433
524
  }
434
525
 
435
- // Only run deploy() when this file is executed directly, not when imported
526
+ // Only run when this file is executed directly, not when imported
436
527
  if (import.meta.main) {
528
+ const args = Bun.argv.slice(2);
529
+
530
+ // Handle version command
531
+ if (args[0] === "--version" || args[0] === "-v") {
532
+ console.log(packageJson.version);
533
+ process.exit(0);
534
+ }
535
+
437
536
  deploy().catch((error) => {
438
537
  console.error("\n❌ Fatal error:", error);
439
538
  process.exit(1);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@just-be/deploy",
3
- "version": "0.4.0",
3
+ "version": "0.6.0",
4
4
  "description": "Deploy static sites to Cloudflare R2 with subdomain routing",
5
5
  "type": "module",
6
6
  "bin": {