create-100x-mobile 0.5.1 → 0.5.2
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/cli.js +0 -0
- package/dist/commands/new/steps.js +56 -0
- package/dist/commands/new.js +53 -10
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
File without changes
|
|
@@ -18,6 +18,7 @@ exports.writeInstantEnvironment = writeInstantEnvironment;
|
|
|
18
18
|
exports.initializeConvex = initializeConvex;
|
|
19
19
|
exports.ensureExpoPublicConvexUrl = ensureExpoPublicConvexUrl;
|
|
20
20
|
exports.setConvexClerkEnv = setConvexClerkEnv;
|
|
21
|
+
exports.setupCloudflare = setupCloudflare;
|
|
21
22
|
exports.initializeGit = initializeGit;
|
|
22
23
|
exports.runHealthChecks = runHealthChecks;
|
|
23
24
|
const node_path_1 = require("node:path");
|
|
@@ -524,6 +525,61 @@ async function setConvexClerkEnv(projectDir, clerkDomain) {
|
|
|
524
525
|
return false;
|
|
525
526
|
}
|
|
526
527
|
}
|
|
528
|
+
async function setupCloudflare(projectDir) {
|
|
529
|
+
const result = {
|
|
530
|
+
configured: false,
|
|
531
|
+
loggedIn: false,
|
|
532
|
+
deployed: false,
|
|
533
|
+
workerUrl: "",
|
|
534
|
+
};
|
|
535
|
+
// Step 1: cloudflare:configure (alchemy configure)
|
|
536
|
+
try {
|
|
537
|
+
await (0, run_1.run)("bun", ["run", "cloudflare:configure"], { cwd: projectDir });
|
|
538
|
+
result.configured = true;
|
|
539
|
+
}
|
|
540
|
+
catch (error) {
|
|
541
|
+
prompts_1.log.warn(`Cloudflare configure failed: ${toErrorMessage(error)}`);
|
|
542
|
+
prompts_1.log.info(picocolors_1.default.dim("Run manually: bun run cloudflare:configure"));
|
|
543
|
+
return result;
|
|
544
|
+
}
|
|
545
|
+
// Step 2: cloudflare:login (alchemy login)
|
|
546
|
+
try {
|
|
547
|
+
await (0, run_1.run)("bun", ["run", "cloudflare:login"], { cwd: projectDir });
|
|
548
|
+
result.loggedIn = true;
|
|
549
|
+
}
|
|
550
|
+
catch (error) {
|
|
551
|
+
prompts_1.log.warn(`Cloudflare login failed: ${toErrorMessage(error)}`);
|
|
552
|
+
prompts_1.log.info(picocolors_1.default.dim("Run manually: bun run cloudflare:login"));
|
|
553
|
+
return result;
|
|
554
|
+
}
|
|
555
|
+
// Step 3: cloudflare:deploy (alchemy deploy) — capture output for worker URL
|
|
556
|
+
try {
|
|
557
|
+
const deployOutput = await (0, run_1.runCapture)("bun", ["run", "cloudflare:deploy"], { cwd: projectDir });
|
|
558
|
+
result.deployed = true;
|
|
559
|
+
// Try to extract the storageWorkerUrl from the deploy output
|
|
560
|
+
const urlMatch = deployOutput.match(/storageWorkerUrl[:\s]*["']?(https?:\/\/[^\s"']+)["']?/i);
|
|
561
|
+
if (urlMatch?.[1]) {
|
|
562
|
+
result.workerUrl = urlMatch[1];
|
|
563
|
+
// Write the worker URL to .env.local
|
|
564
|
+
const envLocalPath = (0, node_path_1.join)(projectDir, ".env.local");
|
|
565
|
+
let envContents = "";
|
|
566
|
+
try {
|
|
567
|
+
envContents = await (0, fs_1.readTextFile)(envLocalPath);
|
|
568
|
+
}
|
|
569
|
+
catch {
|
|
570
|
+
// .env.local may not exist yet
|
|
571
|
+
}
|
|
572
|
+
envContents = (0, dotenv_1.upsertDotenvVar)(envContents, "EXPO_PUBLIC_STORAGE_WORKER_URL", result.workerUrl);
|
|
573
|
+
await (0, fs_1.writeTextFile)(envLocalPath, envContents);
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
catch (error) {
|
|
577
|
+
prompts_1.log.warn(`Cloudflare deploy failed: ${toErrorMessage(error)}`);
|
|
578
|
+
prompts_1.log.info(picocolors_1.default.dim("Run manually: bun run cloudflare:deploy"));
|
|
579
|
+
return result;
|
|
580
|
+
}
|
|
581
|
+
return result;
|
|
582
|
+
}
|
|
527
583
|
async function initializeGit(projectDir) {
|
|
528
584
|
try {
|
|
529
585
|
await (0, run_1.run)("git", ["init"], { cwd: projectDir });
|
package/dist/commands/new.js
CHANGED
|
@@ -257,9 +257,11 @@ async function cmdNew(rawArgs) {
|
|
|
257
257
|
prompts_1.log.info(picocolors_1.default.dim(`Client name: ${instant.clerkClientName}`));
|
|
258
258
|
prompts_1.log.info(picocolors_1.default.dim(`Clerk publishable key: ${instant.clerkPublishableKey}`));
|
|
259
259
|
}
|
|
260
|
+
const isCloudflareMode = backend === "instantdb" && (0, scaffold_1.isCloudflareInstantAuthMode)(instantAuthMode);
|
|
260
261
|
const totalSteps = 1 + // project generation
|
|
261
262
|
(options.installDependencies ? 2 : 0) +
|
|
262
263
|
(backend === "convex" ? 2 + (clerk.domain ? 1 : 0) : 1) +
|
|
264
|
+
(isCloudflareMode && options.installDependencies ? 1 : 0) + // cloudflare setup
|
|
263
265
|
(options.initializeGit ? 1 : 0) +
|
|
264
266
|
1; // health check
|
|
265
267
|
let currentStep = 0;
|
|
@@ -319,6 +321,7 @@ async function cmdNew(rawArgs) {
|
|
|
319
321
|
else {
|
|
320
322
|
prompts_1.log.info(picocolors_1.default.dim("Skipping dependency installation (--no-install)."));
|
|
321
323
|
}
|
|
324
|
+
let cloudflareSetup = null;
|
|
322
325
|
if (backend === "convex") {
|
|
323
326
|
currentStep++;
|
|
324
327
|
prompts_1.log.step(`Setting up Convex ${stepLabel()}`);
|
|
@@ -348,6 +351,23 @@ async function cmdNew(rawArgs) {
|
|
|
348
351
|
}
|
|
349
352
|
}
|
|
350
353
|
}
|
|
354
|
+
if (isCloudflareMode && options.installDependencies) {
|
|
355
|
+
currentStep++;
|
|
356
|
+
prompts_1.log.step(`Setting up Cloudflare storage ${stepLabel()}`);
|
|
357
|
+
cloudflareSetup = await (0, steps_1.setupCloudflare)(projectDir);
|
|
358
|
+
if (cloudflareSetup.deployed) {
|
|
359
|
+
if (cloudflareSetup.workerUrl) {
|
|
360
|
+
prompts_1.log.success(`Cloudflare deployed. Worker URL: ${picocolors_1.default.cyan(cloudflareSetup.workerUrl)}`);
|
|
361
|
+
}
|
|
362
|
+
else {
|
|
363
|
+
prompts_1.log.success("Cloudflare deployed.");
|
|
364
|
+
prompts_1.log.info(picocolors_1.default.dim("Add the storageWorkerUrl to EXPO_PUBLIC_STORAGE_WORKER_URL in .env.local."));
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
else {
|
|
368
|
+
prompts_1.log.warn("Cloudflare setup did not complete fully.");
|
|
369
|
+
}
|
|
370
|
+
}
|
|
351
371
|
if (options.initializeGit) {
|
|
352
372
|
currentStep++;
|
|
353
373
|
prompts_1.log.step(`Initializing git repository ${stepLabel()}`);
|
|
@@ -372,17 +392,19 @@ async function cmdNew(rawArgs) {
|
|
|
372
392
|
}
|
|
373
393
|
prompts_1.log.info("");
|
|
374
394
|
if (backend === "instantdb") {
|
|
375
|
-
const isCloudflareMode = instant?.authMode && (0, scaffold_1.isCloudflareInstantAuthMode)(instant.authMode);
|
|
376
395
|
const isMagicCodeMode = instant?.authMode && (0, scaffold_1.isMagicCodeInstantAuthMode)(instant.authMode);
|
|
377
396
|
const instantReady = isMagicCodeMode
|
|
378
397
|
? Boolean(instant?.appId)
|
|
379
398
|
: Boolean(instant?.authMode === "clerk" &&
|
|
380
399
|
instant.appId &&
|
|
381
400
|
instant.clerkPublishableKey);
|
|
401
|
+
const cloudflareFullyDeployed = cloudflareSetup?.deployed && cloudflareSetup?.workerUrl;
|
|
382
402
|
if (instantReady) {
|
|
383
|
-
prompts_1.log.success(picocolors_1.default.bold(picocolors_1.default.green(isCloudflareMode
|
|
384
|
-
? "Your app is ready!
|
|
385
|
-
:
|
|
403
|
+
prompts_1.log.success(picocolors_1.default.bold(picocolors_1.default.green(isCloudflareMode && cloudflareFullyDeployed
|
|
404
|
+
? "Your app is ready! Cloudflare storage deployed."
|
|
405
|
+
: isCloudflareMode
|
|
406
|
+
? "Your app is ready! Deploy Cloudflare storage next."
|
|
407
|
+
: "Your app is ready!")));
|
|
386
408
|
}
|
|
387
409
|
else if (isMagicCodeMode) {
|
|
388
410
|
prompts_1.log.success(picocolors_1.default.bold(picocolors_1.default.green(isCloudflareMode
|
|
@@ -402,15 +424,36 @@ async function cmdNew(rawArgs) {
|
|
|
402
424
|
prompts_1.log.info(` ${picocolors_1.default.cyan("bun install")} ${picocolors_1.default.dim("# or npm install")}`);
|
|
403
425
|
prompts_1.log.info(` ${picocolors_1.default.cyan("bunx expo start")}`);
|
|
404
426
|
}
|
|
405
|
-
if (isCloudflareMode) {
|
|
427
|
+
if (isCloudflareMode && !cloudflareFullyDeployed) {
|
|
406
428
|
prompts_1.log.info("");
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
429
|
+
if (!cloudflareSetup || !cloudflareSetup.configured) {
|
|
430
|
+
// Nothing ran — show all steps
|
|
431
|
+
prompts_1.log.info(picocolors_1.default.dim(" Cloudflare setup (run manually):"));
|
|
432
|
+
prompts_1.log.info(picocolors_1.default.dim(" INSTANT_APP_ID is written to .env.local for Alchemy deploys."));
|
|
433
|
+
prompts_1.log.info(` ${picocolors_1.default.cyan("bun run cloudflare:configure")}`);
|
|
434
|
+
prompts_1.log.info(` ${picocolors_1.default.cyan("bun run cloudflare:login")}`);
|
|
435
|
+
prompts_1.log.info(` ${picocolors_1.default.cyan("bun run cloudflare:deploy")}`);
|
|
436
|
+
}
|
|
437
|
+
else if (!cloudflareSetup.loggedIn) {
|
|
438
|
+
prompts_1.log.info(picocolors_1.default.dim(" Cloudflare setup (continue from login):"));
|
|
439
|
+
prompts_1.log.info(` ${picocolors_1.default.cyan("bun run cloudflare:login")}`);
|
|
440
|
+
prompts_1.log.info(` ${picocolors_1.default.cyan("bun run cloudflare:deploy")}`);
|
|
441
|
+
}
|
|
442
|
+
else if (!cloudflareSetup.deployed) {
|
|
443
|
+
prompts_1.log.info(picocolors_1.default.dim(" Cloudflare setup (deploy remaining):"));
|
|
444
|
+
prompts_1.log.info(` ${picocolors_1.default.cyan("bun run cloudflare:deploy")}`);
|
|
445
|
+
}
|
|
446
|
+
else {
|
|
447
|
+
// deployed but worker URL not extracted
|
|
448
|
+
prompts_1.log.info(picocolors_1.default.dim(" Cloudflare deployed but worker URL not detected."));
|
|
449
|
+
}
|
|
412
450
|
prompts_1.log.info(picocolors_1.default.dim(" Add the printed storageWorkerUrl to EXPO_PUBLIC_STORAGE_WORKER_URL in .env.local."));
|
|
413
451
|
}
|
|
452
|
+
else if (isCloudflareMode && cloudflareFullyDeployed) {
|
|
453
|
+
prompts_1.log.info("");
|
|
454
|
+
prompts_1.log.info(` ${picocolors_1.default.green("✓")} Cloudflare Worker URL: ${picocolors_1.default.cyan(cloudflareSetup.workerUrl)}`);
|
|
455
|
+
prompts_1.log.info(picocolors_1.default.dim(" EXPO_PUBLIC_STORAGE_WORKER_URL set in .env.local."));
|
|
456
|
+
}
|
|
414
457
|
if (isMagicCodeMode) {
|
|
415
458
|
if (!instantReady) {
|
|
416
459
|
prompts_1.log.info("");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-100x-mobile",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.2",
|
|
4
4
|
"description": "Scaffold a full-stack mobile app with Expo + Convex + Clerk in seconds",
|
|
5
5
|
"main": "dist/cli.js",
|
|
6
6
|
"bin": {
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"typecheck": "tsc --noEmit",
|
|
14
14
|
"test": "vitest run",
|
|
15
15
|
"check": "npm run typecheck && npm test && npm pack --dry-run",
|
|
16
|
-
"prepublishOnly": "npm run check"
|
|
16
|
+
"prepublishOnly": "npm run build && npm run check"
|
|
17
17
|
},
|
|
18
18
|
"files": [
|
|
19
19
|
"dist"
|