@donotdev/cli 0.0.16 → 0.0.17
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/dependencies-matrix.json +33 -129
- package/dist/bin/commands/bump.js +9 -2
- package/dist/bin/commands/create-app.js +195 -40
- package/dist/bin/commands/create-project.js +195 -40
- package/dist/bin/commands/deploy.js +51 -20
- package/dist/bin/commands/doctor.js +249 -56
- package/dist/bin/commands/emu.js +18 -20
- package/dist/bin/commands/make-admin.js +30 -10
- package/dist/bin/commands/setup.js +512 -122
- package/dist/bin/commands/type-check.d.ts.map +1 -1
- package/dist/bin/commands/type-check.js +7 -3
- package/dist/bin/commands/type-check.js.map +1 -1
- package/dist/bin/donotdev.js +26 -14
- package/dist/index.js +264 -80
- package/package.json +1 -1
- package/templates/root-consumer/guides/dndev/ENV_SETUP.md.example +6 -6
- package/templates/root-consumer/guides/dndev/INDEX.md.example +2 -2
- package/templates/root-consumer/guides/dndev/SETUP_AUTH.md.example +13 -6
- package/templates/root-consumer/guides/dndev/SETUP_CRUD.md.example +149 -1086
- package/templates/root-consumer/guides/dndev/SETUP_FIREBASE.md.example +68 -16
- package/templates/root-consumer/guides/dndev/SETUP_FUNCTIONS.md.example +6 -111
- package/templates/root-consumer/guides/dndev/SETUP_SUPABASE.md.example +123 -32
- package/templates/root-consumer/guides/dndev/SETUP_VERCEL.md.example +108 -91
- package/templates/root-consumer/guides/dndev/advanced/EMULATORS.md.example +2 -2
- package/dist/bin/commands/firebase-setup.d.ts +0 -6
- package/dist/bin/commands/firebase-setup.d.ts.map +0 -1
- package/dist/bin/commands/firebase-setup.js +0 -7
- package/dist/bin/commands/firebase-setup.js.map +0 -1
- package/dist/bin/commands/supabase-setup.d.ts +0 -6
- package/dist/bin/commands/supabase-setup.d.ts.map +0 -1
- package/dist/bin/commands/supabase-setup.js +0 -7
- package/dist/bin/commands/supabase-setup.js.map +0 -1
|
@@ -8447,7 +8447,9 @@ var init_error_handling = __esm({
|
|
|
8447
8447
|
// packages/tooling/src/cli/setup/types.ts
|
|
8448
8448
|
function computeOverallStatus(steps) {
|
|
8449
8449
|
const hasFailure = steps.some((s) => s.status === "failed");
|
|
8450
|
-
const allSuccess = steps.every(
|
|
8450
|
+
const allSuccess = steps.every(
|
|
8451
|
+
(s) => s.status === "success" || s.status === "skipped"
|
|
8452
|
+
);
|
|
8451
8453
|
if (hasFailure) return "failed";
|
|
8452
8454
|
if (allSuccess) return "success";
|
|
8453
8455
|
return "partial";
|
|
@@ -8831,9 +8833,17 @@ var init_firebase = __esm({
|
|
|
8831
8833
|
const framework = ctx.app?.framework === "nextjs" ? "nextjs" : "vite";
|
|
8832
8834
|
try {
|
|
8833
8835
|
await checkPrerequisites();
|
|
8834
|
-
steps.push({
|
|
8836
|
+
steps.push({
|
|
8837
|
+
name: "Prerequisites",
|
|
8838
|
+
status: "success",
|
|
8839
|
+
message: "Firebase CLI installed and logged in"
|
|
8840
|
+
});
|
|
8835
8841
|
} catch (err) {
|
|
8836
|
-
steps.push({
|
|
8842
|
+
steps.push({
|
|
8843
|
+
name: "Prerequisites",
|
|
8844
|
+
status: "failed",
|
|
8845
|
+
message: getErrorMessage(err)
|
|
8846
|
+
});
|
|
8837
8847
|
return { provider: "firebase", steps, overallStatus: "failed" };
|
|
8838
8848
|
}
|
|
8839
8849
|
let projectId;
|
|
@@ -8841,38 +8851,78 @@ var init_firebase = __esm({
|
|
|
8841
8851
|
const project = await selectOrCreateProject();
|
|
8842
8852
|
projectId = project.projectId;
|
|
8843
8853
|
log.info(`Using Firebase project: ${projectId}`);
|
|
8844
|
-
steps.push({
|
|
8854
|
+
steps.push({
|
|
8855
|
+
name: "Project selection",
|
|
8856
|
+
status: "success",
|
|
8857
|
+
message: `Project: ${projectId}`
|
|
8858
|
+
});
|
|
8845
8859
|
} catch (err) {
|
|
8846
|
-
steps.push({
|
|
8860
|
+
steps.push({
|
|
8861
|
+
name: "Project selection",
|
|
8862
|
+
status: "failed",
|
|
8863
|
+
message: getErrorMessage(err)
|
|
8864
|
+
});
|
|
8847
8865
|
return { provider: "firebase", steps, overallStatus: "failed" };
|
|
8848
8866
|
}
|
|
8849
8867
|
try {
|
|
8850
8868
|
const sdkConfig = await ensureWebApp(projectId);
|
|
8851
|
-
steps.push({
|
|
8869
|
+
steps.push({
|
|
8870
|
+
name: "SDK config",
|
|
8871
|
+
status: "success",
|
|
8872
|
+
message: "Web app config retrieved"
|
|
8873
|
+
});
|
|
8852
8874
|
if (!ctx.dryRun) {
|
|
8853
8875
|
writeEnvFile(ctx.appDir, sdkConfig, framework);
|
|
8854
|
-
steps.push({
|
|
8876
|
+
steps.push({
|
|
8877
|
+
name: "Write .env",
|
|
8878
|
+
status: "success",
|
|
8879
|
+
message: `Firebase config written to ${ctx.appDir}/.env`
|
|
8880
|
+
});
|
|
8855
8881
|
} else {
|
|
8856
|
-
steps.push({
|
|
8882
|
+
steps.push({
|
|
8883
|
+
name: "Write .env",
|
|
8884
|
+
status: "skipped",
|
|
8885
|
+
message: "Dry run \u2014 .env not written"
|
|
8886
|
+
});
|
|
8857
8887
|
}
|
|
8858
8888
|
} catch (err) {
|
|
8859
|
-
steps.push({
|
|
8889
|
+
steps.push({
|
|
8890
|
+
name: "SDK config",
|
|
8891
|
+
status: "failed",
|
|
8892
|
+
message: getErrorMessage(err)
|
|
8893
|
+
});
|
|
8860
8894
|
}
|
|
8861
8895
|
try {
|
|
8862
8896
|
if (!ctx.dryRun) {
|
|
8863
8897
|
updateFirebaserc(ctx.projectRoot, projectId);
|
|
8864
8898
|
}
|
|
8865
|
-
steps.push({
|
|
8899
|
+
steps.push({
|
|
8900
|
+
name: ".firebaserc",
|
|
8901
|
+
status: ctx.dryRun ? "skipped" : "success",
|
|
8902
|
+
message: "Updated with project ID"
|
|
8903
|
+
});
|
|
8866
8904
|
} catch (err) {
|
|
8867
|
-
steps.push({
|
|
8905
|
+
steps.push({
|
|
8906
|
+
name: ".firebaserc",
|
|
8907
|
+
status: "failed",
|
|
8908
|
+
message: getErrorMessage(err)
|
|
8909
|
+
});
|
|
8868
8910
|
}
|
|
8869
8911
|
try {
|
|
8870
8912
|
if (!ctx.dryRun) {
|
|
8871
8913
|
updateFirebaseJson(ctx.projectRoot, projectId);
|
|
8872
8914
|
}
|
|
8873
|
-
steps.push({
|
|
8915
|
+
steps.push({
|
|
8916
|
+
name: "firebase.json",
|
|
8917
|
+
status: ctx.dryRun ? "skipped" : "success",
|
|
8918
|
+
message: "Placeholders replaced"
|
|
8919
|
+
});
|
|
8874
8920
|
} catch (err) {
|
|
8875
|
-
steps.push({
|
|
8921
|
+
steps.push({
|
|
8922
|
+
name: "firebase.json",
|
|
8923
|
+
status: "failed",
|
|
8924
|
+
message: getErrorMessage(err)
|
|
8925
|
+
});
|
|
8876
8926
|
}
|
|
8877
8927
|
Me(
|
|
8878
8928
|
[
|
|
@@ -8913,7 +8963,11 @@ var init_firebase = __esm({
|
|
|
8913
8963
|
message: "Enable Auth + Firestore in Firebase Console",
|
|
8914
8964
|
coachingTopic: "firebase-enable-services"
|
|
8915
8965
|
});
|
|
8916
|
-
return {
|
|
8966
|
+
return {
|
|
8967
|
+
provider: "firebase",
|
|
8968
|
+
steps,
|
|
8969
|
+
overallStatus: computeOverallStatus(steps)
|
|
8970
|
+
};
|
|
8917
8971
|
}
|
|
8918
8972
|
};
|
|
8919
8973
|
}
|
|
@@ -8922,9 +8976,7 @@ var init_firebase = __esm({
|
|
|
8922
8976
|
// packages/tooling/src/utils/supabase-management.ts
|
|
8923
8977
|
import { execSync } from "node:child_process";
|
|
8924
8978
|
function extractProjectRef(supabaseUrl) {
|
|
8925
|
-
const match = supabaseUrl.match(
|
|
8926
|
-
/https?:\/\/([a-z0-9]+)\.supabase\.co/
|
|
8927
|
-
);
|
|
8979
|
+
const match = supabaseUrl.match(/https?:\/\/([a-z0-9]+)\.supabase\.co/);
|
|
8928
8980
|
if (!match?.[1]) {
|
|
8929
8981
|
throw new Error(
|
|
8930
8982
|
`Cannot extract project ref from URL: ${supabaseUrl}. Expected format: https://<ref>.supabase.co`
|
|
@@ -8958,7 +9010,9 @@ async function cleanupOldEntityMigrations(supabaseDir, latestFile) {
|
|
|
8958
9010
|
`${cmd} migration repair --status reverted ${timestamps.join(" ")}`,
|
|
8959
9011
|
{ cwd: projectRoot, stdio: "pipe", env: { ...process.env } }
|
|
8960
9012
|
);
|
|
8961
|
-
log.info(
|
|
9013
|
+
log.info(
|
|
9014
|
+
`Repaired ${timestamps.length} old entity migration(s) in remote`
|
|
9015
|
+
);
|
|
8962
9016
|
} catch (error2) {
|
|
8963
9017
|
log.debug(
|
|
8964
9018
|
`Migration repair skipped: ${error2 instanceof Error ? error2.message : String(error2)}`
|
|
@@ -9119,7 +9173,9 @@ var init_base_generator = __esm({
|
|
|
9119
9173
|
);
|
|
9120
9174
|
}
|
|
9121
9175
|
}
|
|
9122
|
-
log.info(
|
|
9176
|
+
log.info(
|
|
9177
|
+
`Found ${foundEntities.length} entities: ${foundEntities.join(", ")}`
|
|
9178
|
+
);
|
|
9123
9179
|
await this.generateAdditionalFiles(result);
|
|
9124
9180
|
await this.cleanup(result);
|
|
9125
9181
|
this.logSummary(result);
|
|
@@ -9962,7 +10018,10 @@ ${triggerSql}
|
|
|
9962
10018
|
const entityFileName = getBasename(entityFilePath, ".ts");
|
|
9963
10019
|
try {
|
|
9964
10020
|
const entityModule = await this.importModule(entityFilePath);
|
|
9965
|
-
const entity = this.extractEntityFromModule(
|
|
10021
|
+
const entity = this.extractEntityFromModule(
|
|
10022
|
+
entityModule,
|
|
10023
|
+
entityFileName
|
|
10024
|
+
);
|
|
9966
10025
|
if (entity?.name && entity?.collection) {
|
|
9967
10026
|
entities.push({ entity, fileName: entityFileName });
|
|
9968
10027
|
}
|
|
@@ -10039,7 +10098,11 @@ function writeEnvFile2(appDir, supabaseUrl, supabasePublicKey, framework) {
|
|
|
10039
10098
|
}
|
|
10040
10099
|
const existingLines = existingContent.split("\n");
|
|
10041
10100
|
const preserved = [];
|
|
10042
|
-
const supabaseKeys = /* @__PURE__ */ new Set([
|
|
10101
|
+
const supabaseKeys = /* @__PURE__ */ new Set([
|
|
10102
|
+
"SUPABASE_URL",
|
|
10103
|
+
"SUPABASE_PUBLIC_KEY",
|
|
10104
|
+
"SUPABASE_ANON_KEY"
|
|
10105
|
+
]);
|
|
10043
10106
|
for (const line of existingLines) {
|
|
10044
10107
|
const trimmed = line.trim();
|
|
10045
10108
|
const isSupabaseVar = [...supabaseKeys].some(
|
|
@@ -10132,7 +10195,9 @@ function detectSecretKey(appDir) {
|
|
|
10132
10195
|
for (const line of lines) {
|
|
10133
10196
|
const trimmed = line.trim();
|
|
10134
10197
|
if (trimmed.startsWith("SUPABASE_SECRET_KEY=") || trimmed.startsWith("SUPABASE_SERVICE_ROLE_KEY=")) {
|
|
10135
|
-
const match = trimmed.match(
|
|
10198
|
+
const match = trimmed.match(
|
|
10199
|
+
/^SUPABASE_(?:SECRET|SERVICE_ROLE)_KEY=(.+)$/
|
|
10200
|
+
);
|
|
10136
10201
|
if (match && match[1]) {
|
|
10137
10202
|
return match[1].trim();
|
|
10138
10203
|
}
|
|
@@ -10162,7 +10227,10 @@ async function generateCrudFunction(supabaseDir, projectRoot) {
|
|
|
10162
10227
|
const entitiesDir = joinPath(projectRoot, "entities");
|
|
10163
10228
|
const indexPath = joinPath(entitiesDir, "index.ts");
|
|
10164
10229
|
if (pathExists(indexPath)) {
|
|
10165
|
-
const relativePath = getRelativePathBetween(crudDir, indexPath).replace(
|
|
10230
|
+
const relativePath = getRelativePathBetween(crudDir, indexPath).replace(
|
|
10231
|
+
/\\/g,
|
|
10232
|
+
"/"
|
|
10233
|
+
);
|
|
10166
10234
|
templateContent = templateContent.replace(
|
|
10167
10235
|
/\/\/ import \* as entities from '\.\.\/_shared\/entities\.ts';\n/,
|
|
10168
10236
|
""
|
|
@@ -10278,7 +10346,9 @@ async function main3(options = {}) {
|
|
|
10278
10346
|
s.stop("Failed to generate SQL migrations");
|
|
10279
10347
|
}
|
|
10280
10348
|
} catch (error2) {
|
|
10281
|
-
log.error(
|
|
10349
|
+
log.error(
|
|
10350
|
+
`SQL generation failed: ${error2 instanceof Error ? error2.message : String(error2)}`
|
|
10351
|
+
);
|
|
10282
10352
|
}
|
|
10283
10353
|
}
|
|
10284
10354
|
} else {
|
|
@@ -10288,7 +10358,9 @@ async function main3(options = {}) {
|
|
|
10288
10358
|
try {
|
|
10289
10359
|
await cleanupOldEntityMigrations(supabaseDir, generatedEntityFile);
|
|
10290
10360
|
} catch (error2) {
|
|
10291
|
-
log.warn(
|
|
10361
|
+
log.warn(
|
|
10362
|
+
`Could not clean old entity migrations: ${error2 instanceof Error ? error2.message : String(error2)}`
|
|
10363
|
+
);
|
|
10292
10364
|
}
|
|
10293
10365
|
}
|
|
10294
10366
|
let migrationsPushed = false;
|
|
@@ -10316,7 +10388,9 @@ async function main3(options = {}) {
|
|
|
10316
10388
|
try {
|
|
10317
10389
|
await generateCrudFunction(supabaseDir, projectRoot);
|
|
10318
10390
|
} catch (error2) {
|
|
10319
|
-
log.warn(
|
|
10391
|
+
log.warn(
|
|
10392
|
+
`Could not patch CRUD function: ${error2 instanceof Error ? error2.message : String(error2)}`
|
|
10393
|
+
);
|
|
10320
10394
|
}
|
|
10321
10395
|
const steps = [];
|
|
10322
10396
|
steps.push("\u2705 Credentials validated from .env");
|
|
@@ -10341,7 +10415,9 @@ async function main3(options = {}) {
|
|
|
10341
10415
|
].join("\n"),
|
|
10342
10416
|
title
|
|
10343
10417
|
);
|
|
10344
|
-
Se(
|
|
10418
|
+
Se(
|
|
10419
|
+
hasErrors ? "Setup incomplete \u2014 see errors above." : "Supabase setup done."
|
|
10420
|
+
);
|
|
10345
10421
|
}
|
|
10346
10422
|
var supabase_default, supabaseWizard;
|
|
10347
10423
|
var init_supabase = __esm({
|
|
@@ -10390,10 +10466,18 @@ var init_supabase = __esm({
|
|
|
10390
10466
|
return { provider: "supabase", steps, overallStatus: "failed" };
|
|
10391
10467
|
}
|
|
10392
10468
|
const supabaseUrl = existingConfig.url;
|
|
10393
|
-
steps.push({
|
|
10469
|
+
steps.push({
|
|
10470
|
+
name: "Public credentials",
|
|
10471
|
+
status: "success",
|
|
10472
|
+
message: `URL: ${supabaseUrl}`
|
|
10473
|
+
});
|
|
10394
10474
|
const secretKey = detectSecretKey(ctx.appDir);
|
|
10395
10475
|
if (secretKey) {
|
|
10396
|
-
steps.push({
|
|
10476
|
+
steps.push({
|
|
10477
|
+
name: "Secret key",
|
|
10478
|
+
status: "success",
|
|
10479
|
+
message: "Detected in functions/.env"
|
|
10480
|
+
});
|
|
10397
10481
|
} else {
|
|
10398
10482
|
const supabaseDir = joinPath(ctx.appDir, "supabase");
|
|
10399
10483
|
const functionsEnvPath = joinPath(supabaseDir, "functions", ".env");
|
|
@@ -10417,9 +10501,17 @@ var init_supabase = __esm({
|
|
|
10417
10501
|
try {
|
|
10418
10502
|
const projectRef = extractProjectRef(supabaseUrl);
|
|
10419
10503
|
ensureProjectLinked(ctx.appDir, projectRef);
|
|
10420
|
-
steps.push({
|
|
10504
|
+
steps.push({
|
|
10505
|
+
name: "CLI link",
|
|
10506
|
+
status: "success",
|
|
10507
|
+
message: "Supabase CLI linked"
|
|
10508
|
+
});
|
|
10421
10509
|
} catch (err) {
|
|
10422
|
-
steps.push({
|
|
10510
|
+
steps.push({
|
|
10511
|
+
name: "CLI link",
|
|
10512
|
+
status: "failed",
|
|
10513
|
+
message: getErrorMessage(err)
|
|
10514
|
+
});
|
|
10423
10515
|
}
|
|
10424
10516
|
} else {
|
|
10425
10517
|
steps.push({ name: "CLI link", status: "skipped", message: "Dry run" });
|
|
@@ -10439,7 +10531,11 @@ var init_supabase = __esm({
|
|
|
10439
10531
|
message: "Review custom RLS policies in dashboard",
|
|
10440
10532
|
coachingTopic: "supabase-rls"
|
|
10441
10533
|
});
|
|
10442
|
-
return {
|
|
10534
|
+
return {
|
|
10535
|
+
provider: "supabase",
|
|
10536
|
+
steps,
|
|
10537
|
+
overallStatus: computeOverallStatus(steps)
|
|
10538
|
+
};
|
|
10443
10539
|
}
|
|
10444
10540
|
};
|
|
10445
10541
|
}
|
|
@@ -10484,14 +10580,22 @@ var init_vercel = __esm({
|
|
|
10484
10580
|
if (!isVercelInstalled()) {
|
|
10485
10581
|
log.error("Vercel CLI is not installed.");
|
|
10486
10582
|
log.info("Install it with: npm install -g vercel");
|
|
10487
|
-
steps.push({
|
|
10583
|
+
steps.push({
|
|
10584
|
+
name: "Vercel CLI",
|
|
10585
|
+
status: "failed",
|
|
10586
|
+
message: "Not installed. Run: npm install -g vercel"
|
|
10587
|
+
});
|
|
10488
10588
|
return { provider: "vercel", steps, overallStatus: "failed" };
|
|
10489
10589
|
}
|
|
10490
10590
|
steps.push({ name: "Vercel CLI", status: "success", message: "Installed" });
|
|
10491
10591
|
const token = resolveVercelToken(ctx.appDir);
|
|
10492
10592
|
if (token) {
|
|
10493
10593
|
log.success("VERCEL_TOKEN detected \u2014 no login required");
|
|
10494
|
-
steps.push({
|
|
10594
|
+
steps.push({
|
|
10595
|
+
name: "Auth",
|
|
10596
|
+
status: "success",
|
|
10597
|
+
message: "Token-based auth (VERCEL_TOKEN)"
|
|
10598
|
+
});
|
|
10495
10599
|
} else {
|
|
10496
10600
|
Me(
|
|
10497
10601
|
[
|
|
@@ -10517,28 +10621,52 @@ var init_vercel = __esm({
|
|
|
10517
10621
|
const s = Y2();
|
|
10518
10622
|
s.start("Linking Vercel project...");
|
|
10519
10623
|
try {
|
|
10520
|
-
const result = spawnSync2(
|
|
10521
|
-
|
|
10522
|
-
|
|
10523
|
-
|
|
10524
|
-
|
|
10525
|
-
|
|
10624
|
+
const result = spawnSync2(
|
|
10625
|
+
"vercel",
|
|
10626
|
+
["link", "--yes", "--token", token],
|
|
10627
|
+
{
|
|
10628
|
+
cwd: ctx.appDir,
|
|
10629
|
+
stdio: ["inherit", "pipe", "pipe"],
|
|
10630
|
+
encoding: "utf-8",
|
|
10631
|
+
timeout: 3e4
|
|
10632
|
+
}
|
|
10633
|
+
);
|
|
10526
10634
|
if (result.status === 0) {
|
|
10527
10635
|
s.stop("Vercel project linked");
|
|
10528
|
-
steps.push({
|
|
10636
|
+
steps.push({
|
|
10637
|
+
name: "Project link",
|
|
10638
|
+
status: "success",
|
|
10639
|
+
message: "Linked to Vercel project"
|
|
10640
|
+
});
|
|
10529
10641
|
} else {
|
|
10530
10642
|
s.stop("Vercel link failed");
|
|
10531
10643
|
const stderr = result.stderr?.trim() || "Unknown error";
|
|
10532
|
-
steps.push({
|
|
10644
|
+
steps.push({
|
|
10645
|
+
name: "Project link",
|
|
10646
|
+
status: "failed",
|
|
10647
|
+
message: stderr
|
|
10648
|
+
});
|
|
10533
10649
|
}
|
|
10534
10650
|
} catch (err) {
|
|
10535
10651
|
s.stop("Vercel link failed");
|
|
10536
|
-
steps.push({
|
|
10652
|
+
steps.push({
|
|
10653
|
+
name: "Project link",
|
|
10654
|
+
status: "failed",
|
|
10655
|
+
message: getErrorMessage(err)
|
|
10656
|
+
});
|
|
10537
10657
|
}
|
|
10538
10658
|
} else if (!token) {
|
|
10539
|
-
steps.push({
|
|
10659
|
+
steps.push({
|
|
10660
|
+
name: "Project link",
|
|
10661
|
+
status: "skipped",
|
|
10662
|
+
message: "No token \u2014 cannot link"
|
|
10663
|
+
});
|
|
10540
10664
|
} else {
|
|
10541
|
-
steps.push({
|
|
10665
|
+
steps.push({
|
|
10666
|
+
name: "Project link",
|
|
10667
|
+
status: "skipped",
|
|
10668
|
+
message: "Dry run"
|
|
10669
|
+
});
|
|
10542
10670
|
}
|
|
10543
10671
|
Me(
|
|
10544
10672
|
[
|
|
@@ -10551,7 +10679,11 @@ var init_vercel = __esm({
|
|
|
10551
10679
|
].join("\n"),
|
|
10552
10680
|
"Deployment"
|
|
10553
10681
|
);
|
|
10554
|
-
return {
|
|
10682
|
+
return {
|
|
10683
|
+
provider: "vercel",
|
|
10684
|
+
steps,
|
|
10685
|
+
overallStatus: computeOverallStatus(steps)
|
|
10686
|
+
};
|
|
10555
10687
|
}
|
|
10556
10688
|
};
|
|
10557
10689
|
}
|
|
@@ -10622,13 +10754,16 @@ var init_stripe = __esm({
|
|
|
10622
10754
|
const envPath = joinPath(ctx.appDir, ".env");
|
|
10623
10755
|
if (pathExists(envPath)) {
|
|
10624
10756
|
const content = readSync(envPath, { format: "text" });
|
|
10625
|
-
if (typeof content === "string" && content.includes("STRIPE_"))
|
|
10757
|
+
if (typeof content === "string" && content.includes("STRIPE_"))
|
|
10758
|
+
return true;
|
|
10626
10759
|
}
|
|
10627
10760
|
const pkgPath = joinPath(ctx.appDir, "package.json");
|
|
10628
10761
|
if (pathExists(pkgPath)) {
|
|
10629
10762
|
const pkg = readSync(pkgPath, { format: "json" });
|
|
10630
10763
|
if (pkg && typeof pkg === "object") {
|
|
10631
|
-
const deps = {
|
|
10764
|
+
const deps = {
|
|
10765
|
+
...pkg.dependencies
|
|
10766
|
+
};
|
|
10632
10767
|
if (deps["@donotdev/billing"]) return true;
|
|
10633
10768
|
}
|
|
10634
10769
|
}
|
|
@@ -10642,7 +10777,11 @@ var init_stripe = __esm({
|
|
|
10642
10777
|
const existingPk = readEnvValue(envPath, `${prefix}STRIPE_PUBLISHABLE_KEY`);
|
|
10643
10778
|
let publishableKey = existingPk;
|
|
10644
10779
|
if (existingPk && isValidPublishableKey(existingPk)) {
|
|
10645
|
-
steps.push({
|
|
10780
|
+
steps.push({
|
|
10781
|
+
name: "Publishable key",
|
|
10782
|
+
status: "success",
|
|
10783
|
+
message: "Found in .env"
|
|
10784
|
+
});
|
|
10646
10785
|
} else {
|
|
10647
10786
|
const pk = await askForInput(
|
|
10648
10787
|
"Stripe publishable key (pk_test_... or pk_live_...)",
|
|
@@ -10654,17 +10793,34 @@ var init_stripe = __esm({
|
|
|
10654
10793
|
log.success("Wrote STRIPE_PUBLISHABLE_KEY to .env");
|
|
10655
10794
|
}
|
|
10656
10795
|
publishableKey = pk;
|
|
10657
|
-
steps.push({
|
|
10796
|
+
steps.push({
|
|
10797
|
+
name: "Publishable key",
|
|
10798
|
+
status: "success",
|
|
10799
|
+
message: "Written to .env"
|
|
10800
|
+
});
|
|
10658
10801
|
} else {
|
|
10659
|
-
steps.push({
|
|
10802
|
+
steps.push({
|
|
10803
|
+
name: "Publishable key",
|
|
10804
|
+
status: "failed",
|
|
10805
|
+
message: "Invalid format \u2014 must start with pk_test_ or pk_live_"
|
|
10806
|
+
});
|
|
10660
10807
|
}
|
|
10661
10808
|
}
|
|
10662
|
-
const functionsEnvPath = joinPath(
|
|
10809
|
+
const functionsEnvPath = joinPath(
|
|
10810
|
+
ctx.appDir,
|
|
10811
|
+
"supabase",
|
|
10812
|
+
"functions",
|
|
10813
|
+
".env"
|
|
10814
|
+
);
|
|
10663
10815
|
const altFunctionsEnvPath = joinPath(ctx.appDir, "functions", ".env");
|
|
10664
10816
|
const secretEnvPath = pathExists(functionsEnvPath) ? functionsEnvPath : altFunctionsEnvPath;
|
|
10665
10817
|
const existingSk = readEnvValue(secretEnvPath, "STRIPE_SECRET_KEY");
|
|
10666
10818
|
if (existingSk && isValidSecretKey(existingSk)) {
|
|
10667
|
-
steps.push({
|
|
10819
|
+
steps.push({
|
|
10820
|
+
name: "Secret key",
|
|
10821
|
+
status: "success",
|
|
10822
|
+
message: "Found in functions/.env"
|
|
10823
|
+
});
|
|
10668
10824
|
} else {
|
|
10669
10825
|
const sk = await ge({
|
|
10670
10826
|
message: "Stripe secret key (sk_test_... or sk_live_...):"
|
|
@@ -10674,14 +10830,26 @@ var init_stripe = __esm({
|
|
|
10674
10830
|
writeEnvVar(secretEnvPath, "STRIPE_SECRET_KEY", sk);
|
|
10675
10831
|
log.success("Wrote STRIPE_SECRET_KEY to functions/.env");
|
|
10676
10832
|
}
|
|
10677
|
-
steps.push({
|
|
10833
|
+
steps.push({
|
|
10834
|
+
name: "Secret key",
|
|
10835
|
+
status: "success",
|
|
10836
|
+
message: "Written to functions/.env"
|
|
10837
|
+
});
|
|
10678
10838
|
} else {
|
|
10679
|
-
steps.push({
|
|
10839
|
+
steps.push({
|
|
10840
|
+
name: "Secret key",
|
|
10841
|
+
status: "failed",
|
|
10842
|
+
message: "STRIPE_SECRET_KEY has invalid format"
|
|
10843
|
+
});
|
|
10680
10844
|
}
|
|
10681
10845
|
}
|
|
10682
10846
|
const existingWh = readEnvValue(secretEnvPath, "STRIPE_WEBHOOK_SECRET");
|
|
10683
10847
|
if (existingWh && isValidWebhookSecret(existingWh)) {
|
|
10684
|
-
steps.push({
|
|
10848
|
+
steps.push({
|
|
10849
|
+
name: "Webhook secret",
|
|
10850
|
+
status: "success",
|
|
10851
|
+
message: "Found in functions/.env"
|
|
10852
|
+
});
|
|
10685
10853
|
} else {
|
|
10686
10854
|
Me(
|
|
10687
10855
|
[
|
|
@@ -10706,7 +10874,11 @@ var init_stripe = __esm({
|
|
|
10706
10874
|
coachingTopic: "stripe-webhook"
|
|
10707
10875
|
});
|
|
10708
10876
|
}
|
|
10709
|
-
return {
|
|
10877
|
+
return {
|
|
10878
|
+
provider: "stripe",
|
|
10879
|
+
steps,
|
|
10880
|
+
overallStatus: computeOverallStatus(steps)
|
|
10881
|
+
};
|
|
10710
10882
|
}
|
|
10711
10883
|
};
|
|
10712
10884
|
}
|
|
@@ -10818,7 +10990,11 @@ var init_oauth = __esm({
|
|
|
10818
10990
|
}))
|
|
10819
10991
|
);
|
|
10820
10992
|
if (selected.length === 0) {
|
|
10821
|
-
steps.push({
|
|
10993
|
+
steps.push({
|
|
10994
|
+
name: "OAuth",
|
|
10995
|
+
status: "skipped",
|
|
10996
|
+
message: "No providers selected"
|
|
10997
|
+
});
|
|
10822
10998
|
return { provider: "oauth", steps, overallStatus: "success" };
|
|
10823
10999
|
}
|
|
10824
11000
|
for (const providerId of selected) {
|
|
@@ -10843,7 +11019,11 @@ var init_oauth = __esm({
|
|
|
10843
11019
|
coachingTopic: `oauth-${provider.id}`
|
|
10844
11020
|
});
|
|
10845
11021
|
}
|
|
10846
|
-
return {
|
|
11022
|
+
return {
|
|
11023
|
+
provider: "oauth",
|
|
11024
|
+
steps,
|
|
11025
|
+
overallStatus: computeOverallStatus(steps)
|
|
11026
|
+
};
|
|
10847
11027
|
}
|
|
10848
11028
|
};
|
|
10849
11029
|
}
|
|
@@ -10868,10 +11048,14 @@ function detectAuthProviders(ctx) {
|
|
|
10868
11048
|
if (!pathExists(candidate)) continue;
|
|
10869
11049
|
const content = readSync(candidate, { format: "text" });
|
|
10870
11050
|
if (typeof content !== "string") continue;
|
|
10871
|
-
if (content.includes("google") || content.includes("Google"))
|
|
10872
|
-
|
|
10873
|
-
if (content.includes("
|
|
10874
|
-
|
|
11051
|
+
if (content.includes("google") || content.includes("Google"))
|
|
11052
|
+
providers.push("google");
|
|
11053
|
+
if (content.includes("github") || content.includes("GitHub"))
|
|
11054
|
+
providers.push("github");
|
|
11055
|
+
if (content.includes("apple") || content.includes("Apple"))
|
|
11056
|
+
providers.push("apple");
|
|
11057
|
+
if (content.includes("facebook") || content.includes("Facebook"))
|
|
11058
|
+
providers.push("facebook");
|
|
10875
11059
|
break;
|
|
10876
11060
|
}
|
|
10877
11061
|
return [...new Set(providers)];
|
|
@@ -10962,7 +11146,11 @@ var init_auth = __esm({
|
|
|
10962
11146
|
coachingTopic: "auth-supabase"
|
|
10963
11147
|
});
|
|
10964
11148
|
}
|
|
10965
|
-
return {
|
|
11149
|
+
return {
|
|
11150
|
+
provider: "auth",
|
|
11151
|
+
steps,
|
|
11152
|
+
overallStatus: computeOverallStatus(steps)
|
|
11153
|
+
};
|
|
10966
11154
|
}
|
|
10967
11155
|
};
|
|
10968
11156
|
}
|
|
@@ -11007,7 +11195,11 @@ var init_check_env = __esm({
|
|
|
11007
11195
|
const envPath = joinPath(ctx.appDir, ".env");
|
|
11008
11196
|
const examplePath = joinPath(ctx.appDir, ".env.example");
|
|
11009
11197
|
if (!pathExists(envPath)) {
|
|
11010
|
-
results.push({
|
|
11198
|
+
results.push({
|
|
11199
|
+
name: ".env file",
|
|
11200
|
+
status: "fail",
|
|
11201
|
+
message: "Not found \u2014 run dndev setup"
|
|
11202
|
+
});
|
|
11011
11203
|
return results;
|
|
11012
11204
|
}
|
|
11013
11205
|
results.push({ name: ".env file", status: "pass", message: "Found" });
|
|
@@ -11055,9 +11247,17 @@ var init_check_env = __esm({
|
|
|
11055
11247
|
return /^\.env(\*|\..*)?$/.test(trimmed);
|
|
11056
11248
|
});
|
|
11057
11249
|
if (hasEnvIgnore) {
|
|
11058
|
-
results.push({
|
|
11250
|
+
results.push({
|
|
11251
|
+
name: ".gitignore",
|
|
11252
|
+
status: "pass",
|
|
11253
|
+
message: ".env is gitignored"
|
|
11254
|
+
});
|
|
11059
11255
|
} else {
|
|
11060
|
-
results.push({
|
|
11256
|
+
results.push({
|
|
11257
|
+
name: ".gitignore",
|
|
11258
|
+
status: "warn",
|
|
11259
|
+
message: ".env might not be gitignored \u2014 verify manually"
|
|
11260
|
+
});
|
|
11061
11261
|
}
|
|
11062
11262
|
}
|
|
11063
11263
|
}
|
|
@@ -11094,12 +11294,24 @@ var init_check_firebase = __esm({
|
|
|
11094
11294
|
timeout: 1e4
|
|
11095
11295
|
});
|
|
11096
11296
|
if (result.status === 0) {
|
|
11097
|
-
results.push({
|
|
11297
|
+
results.push({
|
|
11298
|
+
name: "Firebase CLI",
|
|
11299
|
+
status: "pass",
|
|
11300
|
+
message: result.stdout.trim()
|
|
11301
|
+
});
|
|
11098
11302
|
} else {
|
|
11099
|
-
results.push({
|
|
11303
|
+
results.push({
|
|
11304
|
+
name: "Firebase CLI",
|
|
11305
|
+
status: "fail",
|
|
11306
|
+
message: "Not installed"
|
|
11307
|
+
});
|
|
11100
11308
|
}
|
|
11101
11309
|
} catch {
|
|
11102
|
-
results.push({
|
|
11310
|
+
results.push({
|
|
11311
|
+
name: "Firebase CLI",
|
|
11312
|
+
status: "fail",
|
|
11313
|
+
message: "Not installed"
|
|
11314
|
+
});
|
|
11103
11315
|
}
|
|
11104
11316
|
const rcPath = joinPath(ctx.projectRoot, ".firebaserc");
|
|
11105
11317
|
if (pathExists(rcPath)) {
|
|
@@ -11110,15 +11322,31 @@ var init_check_firebase = __esm({
|
|
|
11110
11322
|
const projects = rc?.projects;
|
|
11111
11323
|
const projectId = projects && typeof projects === "object" ? projects.default : void 0;
|
|
11112
11324
|
if (projectId && typeof projectId === "string") {
|
|
11113
|
-
results.push({
|
|
11325
|
+
results.push({
|
|
11326
|
+
name: ".firebaserc",
|
|
11327
|
+
status: "pass",
|
|
11328
|
+
message: `Project: ${projectId}`
|
|
11329
|
+
});
|
|
11114
11330
|
} else {
|
|
11115
|
-
results.push({
|
|
11331
|
+
results.push({
|
|
11332
|
+
name: ".firebaserc",
|
|
11333
|
+
status: "warn",
|
|
11334
|
+
message: "No default project set"
|
|
11335
|
+
});
|
|
11116
11336
|
}
|
|
11117
11337
|
} catch {
|
|
11118
|
-
results.push({
|
|
11338
|
+
results.push({
|
|
11339
|
+
name: ".firebaserc",
|
|
11340
|
+
status: "warn",
|
|
11341
|
+
message: "Invalid JSON"
|
|
11342
|
+
});
|
|
11119
11343
|
}
|
|
11120
11344
|
} else {
|
|
11121
|
-
results.push({
|
|
11345
|
+
results.push({
|
|
11346
|
+
name: ".firebaserc",
|
|
11347
|
+
status: "fail",
|
|
11348
|
+
message: "Missing \u2014 run dndev setup firebase"
|
|
11349
|
+
});
|
|
11122
11350
|
}
|
|
11123
11351
|
const framework = ctx.app?.framework ?? "vite";
|
|
11124
11352
|
const prefix = framework === "nextjs" ? "NEXT_PUBLIC_" : "VITE_";
|
|
@@ -11126,16 +11354,34 @@ var init_check_firebase = __esm({
|
|
|
11126
11354
|
if (pathExists(envPath)) {
|
|
11127
11355
|
const content = readSync(envPath, { format: "text" });
|
|
11128
11356
|
if (typeof content === "string") {
|
|
11129
|
-
const requiredKeys = [
|
|
11130
|
-
|
|
11357
|
+
const requiredKeys = [
|
|
11358
|
+
"FIREBASE_API_KEY",
|
|
11359
|
+
"FIREBASE_PROJECT_ID",
|
|
11360
|
+
"FIREBASE_AUTH_DOMAIN"
|
|
11361
|
+
];
|
|
11362
|
+
const missing = requiredKeys.filter(
|
|
11363
|
+
(key) => !content.includes(`${prefix}${key}=`)
|
|
11364
|
+
);
|
|
11131
11365
|
if (missing.length === 0) {
|
|
11132
|
-
results.push({
|
|
11366
|
+
results.push({
|
|
11367
|
+
name: "Firebase .env",
|
|
11368
|
+
status: "pass",
|
|
11369
|
+
message: "All required keys present"
|
|
11370
|
+
});
|
|
11133
11371
|
} else {
|
|
11134
|
-
results.push({
|
|
11372
|
+
results.push({
|
|
11373
|
+
name: "Firebase .env",
|
|
11374
|
+
status: "fail",
|
|
11375
|
+
message: `Missing: ${missing.join(", ")}`
|
|
11376
|
+
});
|
|
11135
11377
|
}
|
|
11136
11378
|
}
|
|
11137
11379
|
} else {
|
|
11138
|
-
results.push({
|
|
11380
|
+
results.push({
|
|
11381
|
+
name: "Firebase .env",
|
|
11382
|
+
status: "fail",
|
|
11383
|
+
message: ".env file not found"
|
|
11384
|
+
});
|
|
11139
11385
|
}
|
|
11140
11386
|
const saKeyPaths = [
|
|
11141
11387
|
joinPath(ctx.appDir, "service-account-key.json"),
|
|
@@ -11143,9 +11389,17 @@ var init_check_firebase = __esm({
|
|
|
11143
11389
|
];
|
|
11144
11390
|
const saFound = saKeyPaths.some((p2) => pathExists(p2));
|
|
11145
11391
|
if (saFound) {
|
|
11146
|
-
results.push({
|
|
11392
|
+
results.push({
|
|
11393
|
+
name: "Service account key",
|
|
11394
|
+
status: "pass",
|
|
11395
|
+
message: "Found"
|
|
11396
|
+
});
|
|
11147
11397
|
} else {
|
|
11148
|
-
results.push({
|
|
11398
|
+
results.push({
|
|
11399
|
+
name: "Service account key",
|
|
11400
|
+
status: "warn",
|
|
11401
|
+
message: "Not found (needed for deploy/emu)"
|
|
11402
|
+
});
|
|
11149
11403
|
}
|
|
11150
11404
|
return results;
|
|
11151
11405
|
}
|
|
@@ -11183,42 +11437,82 @@ var init_check_supabase = __esm({
|
|
|
11183
11437
|
timeout: 1e4
|
|
11184
11438
|
});
|
|
11185
11439
|
if (result.status === 0) {
|
|
11186
|
-
results.push({
|
|
11440
|
+
results.push({
|
|
11441
|
+
name: "Supabase CLI",
|
|
11442
|
+
status: "pass",
|
|
11443
|
+
message: result.stdout.trim()
|
|
11444
|
+
});
|
|
11187
11445
|
} else {
|
|
11188
|
-
results.push({
|
|
11446
|
+
results.push({
|
|
11447
|
+
name: "Supabase CLI",
|
|
11448
|
+
status: "warn",
|
|
11449
|
+
message: "Not installed (needed for migrations)"
|
|
11450
|
+
});
|
|
11189
11451
|
}
|
|
11190
11452
|
} catch {
|
|
11191
|
-
results.push({
|
|
11453
|
+
results.push({
|
|
11454
|
+
name: "Supabase CLI",
|
|
11455
|
+
status: "warn",
|
|
11456
|
+
message: "Not installed"
|
|
11457
|
+
});
|
|
11192
11458
|
}
|
|
11193
11459
|
const configPath = joinPath(ctx.appDir, "supabase", "config.toml");
|
|
11194
11460
|
if (pathExists(configPath)) {
|
|
11195
11461
|
results.push({ name: "config.toml", status: "pass", message: "Found" });
|
|
11196
11462
|
} else {
|
|
11197
|
-
results.push({
|
|
11463
|
+
results.push({
|
|
11464
|
+
name: "config.toml",
|
|
11465
|
+
status: "warn",
|
|
11466
|
+
message: "Missing (expected at supabase/config.toml)"
|
|
11467
|
+
});
|
|
11198
11468
|
}
|
|
11199
11469
|
const envPath = joinPath(ctx.appDir, ".env");
|
|
11200
11470
|
if (pathExists(envPath)) {
|
|
11201
11471
|
const content = readSync(envPath, { format: "text" });
|
|
11202
11472
|
if (typeof content === "string") {
|
|
11203
|
-
const urlMatch = content.match(
|
|
11473
|
+
const urlMatch = content.match(
|
|
11474
|
+
new RegExp(`${prefix}SUPABASE_URL=(.+)`)
|
|
11475
|
+
);
|
|
11204
11476
|
const url = urlMatch?.[1]?.trim();
|
|
11205
11477
|
if (url && isValidSupabaseUrl(url)) {
|
|
11206
11478
|
results.push({ name: "Supabase URL", status: "pass", message: url });
|
|
11207
11479
|
} else if (url) {
|
|
11208
|
-
results.push({
|
|
11480
|
+
results.push({
|
|
11481
|
+
name: "Supabase URL",
|
|
11482
|
+
status: "fail",
|
|
11483
|
+
message: "Invalid URL format"
|
|
11484
|
+
});
|
|
11209
11485
|
} else {
|
|
11210
|
-
results.push({
|
|
11486
|
+
results.push({
|
|
11487
|
+
name: "Supabase URL",
|
|
11488
|
+
status: "fail",
|
|
11489
|
+
message: "Missing in .env"
|
|
11490
|
+
});
|
|
11211
11491
|
}
|
|
11212
|
-
const keyMatch = content.match(
|
|
11492
|
+
const keyMatch = content.match(
|
|
11493
|
+
new RegExp(`${prefix}SUPABASE_(?:PUBLIC_KEY|ANON_KEY)=(.+)`)
|
|
11494
|
+
);
|
|
11213
11495
|
const key = keyMatch?.[1]?.trim();
|
|
11214
11496
|
if (key && isValidPublicKey(key)) {
|
|
11215
|
-
results.push({
|
|
11497
|
+
results.push({
|
|
11498
|
+
name: "Supabase public key",
|
|
11499
|
+
status: "pass",
|
|
11500
|
+
message: "Present"
|
|
11501
|
+
});
|
|
11216
11502
|
} else {
|
|
11217
|
-
results.push({
|
|
11503
|
+
results.push({
|
|
11504
|
+
name: "Supabase public key",
|
|
11505
|
+
status: "fail",
|
|
11506
|
+
message: "Missing in .env"
|
|
11507
|
+
});
|
|
11218
11508
|
}
|
|
11219
11509
|
}
|
|
11220
11510
|
} else {
|
|
11221
|
-
results.push({
|
|
11511
|
+
results.push({
|
|
11512
|
+
name: "Supabase .env",
|
|
11513
|
+
status: "fail",
|
|
11514
|
+
message: ".env file not found"
|
|
11515
|
+
});
|
|
11222
11516
|
}
|
|
11223
11517
|
const functionsEnvCandidates = [
|
|
11224
11518
|
joinPath(ctx.appDir, "supabase", "functions", ".env"),
|
|
@@ -11230,12 +11524,20 @@ var init_check_supabase = __esm({
|
|
|
11230
11524
|
const content = readSync(fenvPath, { format: "text" });
|
|
11231
11525
|
if (typeof content === "string" && content.match(/SUPABASE_(?:SECRET|SERVICE_ROLE)_KEY=.+/)) {
|
|
11232
11526
|
secretFound = true;
|
|
11233
|
-
results.push({
|
|
11527
|
+
results.push({
|
|
11528
|
+
name: "Secret key",
|
|
11529
|
+
status: "pass",
|
|
11530
|
+
message: `Found in ${fenvPath.split("/").pop()}`
|
|
11531
|
+
});
|
|
11234
11532
|
break;
|
|
11235
11533
|
}
|
|
11236
11534
|
}
|
|
11237
11535
|
if (!secretFound) {
|
|
11238
|
-
results.push({
|
|
11536
|
+
results.push({
|
|
11537
|
+
name: "Secret key",
|
|
11538
|
+
status: "warn",
|
|
11539
|
+
message: "Not found (needed for migrations + deploy)"
|
|
11540
|
+
});
|
|
11239
11541
|
}
|
|
11240
11542
|
return results;
|
|
11241
11543
|
}
|
|
@@ -11293,7 +11595,8 @@ var init_check_stripe = __esm({
|
|
|
11293
11595
|
const envPath = joinPath(ctx.appDir, ".env");
|
|
11294
11596
|
if (pathExists(envPath)) {
|
|
11295
11597
|
const content = readSync(envPath, { format: "text" });
|
|
11296
|
-
if (typeof content === "string" && content.includes("STRIPE_PUBLISHABLE_KEY"))
|
|
11598
|
+
if (typeof content === "string" && content.includes("STRIPE_PUBLISHABLE_KEY"))
|
|
11599
|
+
return true;
|
|
11297
11600
|
}
|
|
11298
11601
|
return false;
|
|
11299
11602
|
},
|
|
@@ -11308,12 +11611,24 @@ var init_check_stripe = __esm({
|
|
|
11308
11611
|
if (pk) {
|
|
11309
11612
|
if (pk.startsWith("pk_test_") || pk.startsWith("pk_live_")) {
|
|
11310
11613
|
pkMode = pk.startsWith("pk_test_") ? "test" : "live";
|
|
11311
|
-
results.push({
|
|
11614
|
+
results.push({
|
|
11615
|
+
name: "Publishable key",
|
|
11616
|
+
status: "pass",
|
|
11617
|
+
message: `Valid (${pkMode} mode)`
|
|
11618
|
+
});
|
|
11312
11619
|
} else {
|
|
11313
|
-
results.push({
|
|
11620
|
+
results.push({
|
|
11621
|
+
name: "Publishable key",
|
|
11622
|
+
status: "fail",
|
|
11623
|
+
message: "Invalid format \u2014 must start with pk_test_ or pk_live_"
|
|
11624
|
+
});
|
|
11314
11625
|
}
|
|
11315
11626
|
} else {
|
|
11316
|
-
results.push({
|
|
11627
|
+
results.push({
|
|
11628
|
+
name: "Publishable key",
|
|
11629
|
+
status: "fail",
|
|
11630
|
+
message: "Missing in .env"
|
|
11631
|
+
});
|
|
11317
11632
|
}
|
|
11318
11633
|
let skMode = null;
|
|
11319
11634
|
if (functionsEnvPath) {
|
|
@@ -11321,33 +11636,69 @@ var init_check_stripe = __esm({
|
|
|
11321
11636
|
if (sk) {
|
|
11322
11637
|
if (sk.startsWith("sk_test_") || sk.startsWith("sk_live_") || sk.startsWith("rk_test_") || sk.startsWith("rk_live_")) {
|
|
11323
11638
|
skMode = sk.includes("_test_") ? "test" : "live";
|
|
11324
|
-
results.push({
|
|
11639
|
+
results.push({
|
|
11640
|
+
name: "Secret key",
|
|
11641
|
+
status: "pass",
|
|
11642
|
+
message: `Valid (${skMode} mode)`
|
|
11643
|
+
});
|
|
11325
11644
|
} else {
|
|
11326
|
-
results.push({
|
|
11645
|
+
results.push({
|
|
11646
|
+
name: "Secret key",
|
|
11647
|
+
status: "fail",
|
|
11648
|
+
message: "STRIPE_SECRET_KEY has invalid format"
|
|
11649
|
+
});
|
|
11327
11650
|
}
|
|
11328
11651
|
} else {
|
|
11329
|
-
results.push({
|
|
11652
|
+
results.push({
|
|
11653
|
+
name: "Secret key",
|
|
11654
|
+
status: "warn",
|
|
11655
|
+
message: "Not found in functions/.env"
|
|
11656
|
+
});
|
|
11330
11657
|
}
|
|
11331
11658
|
} else {
|
|
11332
|
-
results.push({
|
|
11659
|
+
results.push({
|
|
11660
|
+
name: "Secret key",
|
|
11661
|
+
status: "warn",
|
|
11662
|
+
message: "No functions/.env found"
|
|
11663
|
+
});
|
|
11333
11664
|
}
|
|
11334
11665
|
if (functionsEnvPath) {
|
|
11335
11666
|
const wh = readEnvValue2(functionsEnvPath, "STRIPE_WEBHOOK_SECRET");
|
|
11336
11667
|
if (wh) {
|
|
11337
11668
|
if (wh.startsWith("whsec_")) {
|
|
11338
|
-
results.push({
|
|
11669
|
+
results.push({
|
|
11670
|
+
name: "Webhook secret",
|
|
11671
|
+
status: "pass",
|
|
11672
|
+
message: "Valid format"
|
|
11673
|
+
});
|
|
11339
11674
|
} else {
|
|
11340
|
-
results.push({
|
|
11675
|
+
results.push({
|
|
11676
|
+
name: "Webhook secret",
|
|
11677
|
+
status: "fail",
|
|
11678
|
+
message: "STRIPE_WEBHOOK_SECRET has invalid format"
|
|
11679
|
+
});
|
|
11341
11680
|
}
|
|
11342
11681
|
} else {
|
|
11343
|
-
results.push({
|
|
11682
|
+
results.push({
|
|
11683
|
+
name: "Webhook secret",
|
|
11684
|
+
status: "warn",
|
|
11685
|
+
message: "Not found \u2014 webhooks won't verify"
|
|
11686
|
+
});
|
|
11344
11687
|
}
|
|
11345
11688
|
}
|
|
11346
11689
|
if (pkMode && skMode) {
|
|
11347
11690
|
if (pkMode !== skMode) {
|
|
11348
|
-
results.push({
|
|
11691
|
+
results.push({
|
|
11692
|
+
name: "Key mode",
|
|
11693
|
+
status: "warn",
|
|
11694
|
+
message: `Publishable key is ${pkMode} but secret key is ${skMode}`
|
|
11695
|
+
});
|
|
11349
11696
|
} else {
|
|
11350
|
-
results.push({
|
|
11697
|
+
results.push({
|
|
11698
|
+
name: "Key mode",
|
|
11699
|
+
status: "pass",
|
|
11700
|
+
message: `Both keys are ${pkMode}`
|
|
11701
|
+
});
|
|
11351
11702
|
}
|
|
11352
11703
|
}
|
|
11353
11704
|
return results;
|
|
@@ -11374,13 +11725,18 @@ var init_check_auth = __esm({
|
|
|
11374
11725
|
const pkgPath = joinPath(ctx.appDir, "package.json");
|
|
11375
11726
|
if (pathExists(pkgPath)) {
|
|
11376
11727
|
const content = readSync(pkgPath, { format: "text" });
|
|
11377
|
-
if (typeof content === "string" && content.includes("@donotdev/auth"))
|
|
11728
|
+
if (typeof content === "string" && content.includes("@donotdev/auth"))
|
|
11729
|
+
return true;
|
|
11378
11730
|
}
|
|
11379
11731
|
return false;
|
|
11380
11732
|
},
|
|
11381
11733
|
async run(ctx) {
|
|
11382
11734
|
const results = [];
|
|
11383
|
-
results.push({
|
|
11735
|
+
results.push({
|
|
11736
|
+
name: "@donotdev/auth",
|
|
11737
|
+
status: "pass",
|
|
11738
|
+
message: "Installed"
|
|
11739
|
+
});
|
|
11384
11740
|
const candidates = [
|
|
11385
11741
|
joinPath(ctx.appDir, "src", "providers.ts"),
|
|
11386
11742
|
joinPath(ctx.appDir, "src", "providers.tsx"),
|
|
@@ -11397,10 +11753,14 @@ var init_check_auth = __esm({
|
|
|
11397
11753
|
const content = readSync(providerFile, { format: "text" });
|
|
11398
11754
|
if (typeof content === "string") {
|
|
11399
11755
|
const providers = [];
|
|
11400
|
-
if (content.includes("email") || content.includes("Email"))
|
|
11401
|
-
|
|
11402
|
-
if (content.includes("
|
|
11403
|
-
|
|
11756
|
+
if (content.includes("email") || content.includes("Email"))
|
|
11757
|
+
providers.push("email");
|
|
11758
|
+
if (content.includes("google") || content.includes("Google"))
|
|
11759
|
+
providers.push("google");
|
|
11760
|
+
if (content.includes("github") || content.includes("GitHub"))
|
|
11761
|
+
providers.push("github");
|
|
11762
|
+
if (content.includes("apple") || content.includes("Apple"))
|
|
11763
|
+
providers.push("apple");
|
|
11404
11764
|
if (providers.length > 0) {
|
|
11405
11765
|
results.push({
|
|
11406
11766
|
name: "Auth providers",
|
|
@@ -11410,7 +11770,11 @@ var init_check_auth = __esm({
|
|
|
11410
11770
|
}
|
|
11411
11771
|
}
|
|
11412
11772
|
} else {
|
|
11413
|
-
results.push({
|
|
11773
|
+
results.push({
|
|
11774
|
+
name: "Providers config",
|
|
11775
|
+
status: "warn",
|
|
11776
|
+
message: "No providers.ts found \u2014 auth may not work"
|
|
11777
|
+
});
|
|
11414
11778
|
}
|
|
11415
11779
|
const hasFirebase = pathExists(joinPath(ctx.projectRoot, ".firebaserc"));
|
|
11416
11780
|
const hasSupabase = pathExists(joinPath(ctx.appDir, "supabase"));
|
|
@@ -11429,7 +11793,11 @@ var init_check_auth = __esm({
|
|
|
11429
11793
|
detail: "Run dndev setup auth for setup coaching"
|
|
11430
11794
|
});
|
|
11431
11795
|
} else {
|
|
11432
|
-
results.push({
|
|
11796
|
+
results.push({
|
|
11797
|
+
name: "Backend",
|
|
11798
|
+
status: "warn",
|
|
11799
|
+
message: "No backend detected for auth"
|
|
11800
|
+
});
|
|
11433
11801
|
}
|
|
11434
11802
|
return results;
|
|
11435
11803
|
}
|
|
@@ -11483,7 +11851,9 @@ async function main4(options = {}) {
|
|
|
11483
11851
|
let hasFail = false;
|
|
11484
11852
|
const registry = options.check ? CHECK_REGISTRY.filter((e2) => e2.id === options.check) : CHECK_REGISTRY;
|
|
11485
11853
|
if (options.check && registry.length === 0) {
|
|
11486
|
-
log.error(
|
|
11854
|
+
log.error(
|
|
11855
|
+
`Unknown check: ${options.check}. Available: ${CHECK_REGISTRY.map((e2) => e2.id).join(", ")}`
|
|
11856
|
+
);
|
|
11487
11857
|
Se("Doctor aborted.");
|
|
11488
11858
|
return 1;
|
|
11489
11859
|
}
|
|
@@ -11517,7 +11887,9 @@ async function main4(options = {}) {
|
|
|
11517
11887
|
if (warnings > 0) summaryParts.push(`${warnings} warning(s)`);
|
|
11518
11888
|
if (fails > 0) summaryParts.push(`${fails} failure(s)`);
|
|
11519
11889
|
const exitCode = hasFail ? 1 : 0;
|
|
11520
|
-
Se(
|
|
11890
|
+
Se(
|
|
11891
|
+
hasFail ? `Health check failed: ${summaryParts.join(", ")}` : `All clear: ${summaryParts.join(", ")}`
|
|
11892
|
+
);
|
|
11521
11893
|
return exitCode;
|
|
11522
11894
|
}
|
|
11523
11895
|
var CHECK_REGISTRY, STATUS_ICONS, doctor_default;
|
|
@@ -11530,9 +11902,18 @@ var init_doctor = __esm({
|
|
|
11530
11902
|
init_pathResolver();
|
|
11531
11903
|
CHECK_REGISTRY = [
|
|
11532
11904
|
{ id: "env", load: async () => (await Promise.resolve().then(() => (init_check_env(), check_env_exports))).envCheck },
|
|
11533
|
-
{
|
|
11534
|
-
|
|
11535
|
-
|
|
11905
|
+
{
|
|
11906
|
+
id: "firebase",
|
|
11907
|
+
load: async () => (await Promise.resolve().then(() => (init_check_firebase(), check_firebase_exports))).firebaseCheck
|
|
11908
|
+
},
|
|
11909
|
+
{
|
|
11910
|
+
id: "supabase",
|
|
11911
|
+
load: async () => (await Promise.resolve().then(() => (init_check_supabase(), check_supabase_exports))).supabaseCheck
|
|
11912
|
+
},
|
|
11913
|
+
{
|
|
11914
|
+
id: "stripe",
|
|
11915
|
+
load: async () => (await Promise.resolve().then(() => (init_check_stripe(), check_stripe_exports))).stripeCheck
|
|
11916
|
+
},
|
|
11536
11917
|
{ id: "auth", load: async () => (await Promise.resolve().then(() => (init_check_auth(), check_auth_exports))).authCheck }
|
|
11537
11918
|
];
|
|
11538
11919
|
STATUS_ICONS = {
|
|
@@ -11570,7 +11951,14 @@ var WIZARD_REGISTRY = {
|
|
|
11570
11951
|
oauth: async () => (await Promise.resolve().then(() => (init_oauth(), oauth_exports))).oauthWizard,
|
|
11571
11952
|
auth: async () => (await Promise.resolve().then(() => (init_auth(), auth_exports))).authWizard
|
|
11572
11953
|
};
|
|
11573
|
-
var WIZARD_ORDER = [
|
|
11954
|
+
var WIZARD_ORDER = [
|
|
11955
|
+
"firebase",
|
|
11956
|
+
"supabase",
|
|
11957
|
+
"vercel",
|
|
11958
|
+
"stripe",
|
|
11959
|
+
"auth",
|
|
11960
|
+
"oauth"
|
|
11961
|
+
];
|
|
11574
11962
|
var STATUS_ICONS2 = {
|
|
11575
11963
|
success: "\u2705",
|
|
11576
11964
|
// green check
|
|
@@ -11637,7 +12025,9 @@ async function main5(options = {}) {
|
|
|
11637
12025
|
}
|
|
11638
12026
|
if (relevant.length === 0) {
|
|
11639
12027
|
log.warn("No providers detected in this project.");
|
|
11640
|
-
log.info(
|
|
12028
|
+
log.info(
|
|
12029
|
+
`Available providers: ${Object.keys(WIZARD_REGISTRY).join(", ")}`
|
|
12030
|
+
);
|
|
11641
12031
|
log.info("Run: dndev setup <provider>");
|
|
11642
12032
|
Se("Nothing to set up.");
|
|
11643
12033
|
return 0;
|