create-better-fullstack 2.1.8 → 2.2.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.
- package/dist/{add-handler-ztNjzoMN.mjs → add-handler-CE3XIs3y.mjs} +8 -8
- package/dist/{addons-setup-LaAj43NP.mjs → addons-setup-DR924M7b.mjs} +1 -1
- package/dist/addons-setup-Du2VSv8V.mjs +7 -0
- package/dist/{analytics-DVltG11u.mjs → analytics-BXlOG6u6.mjs} +1 -1
- package/dist/{bts-config-DQVWvPDs.mjs → bts-config-B_HhcMXL.mjs} +30 -0
- package/dist/cli.mjs +2 -2
- package/dist/{config-processing-D9-F2Us9.mjs → config-processing-DJisMeW-.mjs} +17 -1
- package/dist/{doctor-a4ca3SMd.mjs → doctor-Cc7sLuow.mjs} +2 -2
- package/dist/{file-formatter-gvmrpd-g.mjs → file-formatter-BgbfpYf4.mjs} +442 -22
- package/dist/{gen-CCClL7Ve.mjs → gen-BZ0QCxCC.mjs} +1 -1
- package/dist/{generated-checks-BV9jol5h.mjs → generated-checks-CbioGjCh.mjs} +1 -1
- package/dist/index.d.mts +461 -183
- package/dist/index.mjs +20 -9
- package/dist/{install-dependencies-RoUyaE8o.mjs → install-dependencies-D__bmW4k.mjs} +86 -18
- package/dist/{mcp-492OkjcS.mjs → mcp-DNKAo8nO.mjs} +5 -5
- package/dist/mcp-entry.mjs +37 -225
- package/dist/{registry-DSf2CEaU.mjs → registry-Cm3D45oT.mjs} +1 -1
- package/dist/run-C_S7ujfY.mjs +15 -0
- package/dist/{run-T6g1jkfy.mjs → run-DmN7QRt5.mjs} +1155 -292
- package/dist/scaffold-manifest-ByKtMhTd.mjs +4 -0
- package/dist/{scaffold-manifest-Dyi0voqE.mjs → scaffold-manifest-CNFz-lmH.mjs} +34 -5
- package/dist/{update-DJ8CI5KW.mjs → update-B270pWHc.mjs} +182 -25
- package/package.json +6 -6
- package/dist/addons-setup-DnLjAzTw.mjs +0 -7
- package/dist/run-CD8f7PHh.mjs +0 -15
- package/dist/scaffold-manifest-DGRyepdb.mjs +0 -4
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { _ as DEFAULT_UI_LIBRARY_BY_FRONTEND, b as types_exports, c as getGraphBackendDeployInstructions, d as getGraphSummary, g as DEFAULT_CONFIG, h as BUILDER_URL, i as readBtsConfigFromFile, l as getGraphBackendUrl, m as getLatestCLIVersion, o as writeBtsConfig, p as hasGraphPart, t as buildBtsConfigForPersistence, u as getGraphPart, v as getDefaultConfig, y as getUserPkgManager } from "./bts-config-
|
|
2
|
+
import { _ as DEFAULT_UI_LIBRARY_BY_FRONTEND, b as types_exports, c as getGraphBackendDeployInstructions, d as getGraphSummary, g as DEFAULT_CONFIG, h as BUILDER_URL, i as readBtsConfigFromFile, l as getGraphBackendUrl, m as getLatestCLIVersion, o as writeBtsConfig, p as hasGraphPart, t as buildBtsConfigForPersistence, u as getGraphPart, v as getDefaultConfig, y as getUserPkgManager } from "./bts-config-B_HhcMXL.mjs";
|
|
3
3
|
import { t as renderTitle } from "./render-title-zvyKC1ej.mjs";
|
|
4
4
|
import { a as handleError, c as isSilent, d as setLastPromptShownUI, i as exitWithError, l as runWithContextAsync, n as UserCancelledError, o as didLastPromptShowUI, r as exitCancelled, s as isFirstPrompt, t as CLIError, u as setIsFirstPrompt } from "./errors-ns_o2OKg.mjs";
|
|
5
5
|
import { t as canPromptInteractively } from "./prompt-environment-BR0Kkw2W.mjs";
|
|
6
|
-
import { a as trackProjectCreation, i as trackEvent, n as isTelemetryEnabled, o as getPersistedTelemetryPreference, r as maybeShowTelemetryNotice, s as setTelemetryPreference, t as hasTelemetryEnvOverride } from "./analytics-
|
|
7
|
-
import {
|
|
8
|
-
import { _ as
|
|
9
|
-
import { n as commandExists, t as runGeneratedChecks } from "./generated-checks-
|
|
10
|
-
import { a as getTemplateConfig, i as validateArrayOptions, n as getProvidedFlags, o as getTemplateDescription, r as processFlags, s as generateReproducibleCommand, t as applyEffectBackendDefaults } from "./config-processing-
|
|
11
|
-
import {
|
|
12
|
-
import { n as getPackageExecutionArgs, r as addPackageDependency, t as setupAddons } from "./addons-setup-
|
|
6
|
+
import { a as trackProjectCreation, i as trackEvent, n as isTelemetryEnabled, o as getPersistedTelemetryPreference, r as maybeShowTelemetryNotice, s as setTelemetryPreference, t as hasTelemetryEnvOverride } from "./analytics-BXlOG6u6.mjs";
|
|
7
|
+
import { C as CreateCommandInputSchema, _ as isExampleChatSdkAllowed$1, b as requiresChatSdkVercelAI, d as allowedApisForFrontends$1, g as isExampleAIAllowed$1, h as hasWebStyling$1, i as validateFullConfig, m as getCompatibleUILibraries$1, n as formatProject, p as getCompatibleCSSFrameworks$1, r as validateConfigForProgrammaticUse, u as resolveCompatibilityAdjustments, v as isFrontendAllowedWithBackend$1, w as CreateCommandOptionsSchema, x as splitFrontends$1, y as isWebFrontend$1 } from "./file-formatter-BgbfpYf4.mjs";
|
|
8
|
+
import { _ as GO_BACK_SYMBOL, a as runMavenTests, c as applyDependencyVersionChannel, d as getAppPlatformsChoice, f as isCancel$1, g as setIsFirstPrompt$1, h as navigableSelect, i as runGradleTests, l as getAddonsChoice, m as navigableMultiselect, n as runCargoBuild, o as runMixCompile, p as navigableConfirm, r as runGoModTidy, s as runUvSync, t as installDependencies, v as isGoBack } from "./install-dependencies-D__bmW4k.mjs";
|
|
9
|
+
import { n as commandExists, t as runGeneratedChecks } from "./generated-checks-CbioGjCh.mjs";
|
|
10
|
+
import { a as getTemplateConfig, i as validateArrayOptions, n as getProvidedFlags, o as getTemplateDescription, r as processFlags, s as generateReproducibleCommand, t as applyEffectBackendDefaults } from "./config-processing-DJisMeW-.mjs";
|
|
11
|
+
import { n as collectStructuredBaselines, s as recordScaffoldManifest } from "./scaffold-manifest-CNFz-lmH.mjs";
|
|
12
|
+
import { n as getPackageExecutionArgs, r as addPackageDependency, t as setupAddons } from "./addons-setup-DR924M7b.mjs";
|
|
13
13
|
import { cancel, confirm, intro, isCancel, log, note, outro, select, spinner, text } from "@clack/prompts";
|
|
14
14
|
import { createRouterClient, os } from "@orpc/server";
|
|
15
15
|
import pc from "picocolors";
|
|
@@ -269,6 +269,16 @@ const AI_PROMPT_OPTIONS = [
|
|
|
269
269
|
label: "OpenAI Agents SDK",
|
|
270
270
|
hint: "Official multi-agent framework with handoffs and guardrails"
|
|
271
271
|
},
|
|
272
|
+
{
|
|
273
|
+
value: "openai-sdk",
|
|
274
|
+
label: "OpenAI SDK",
|
|
275
|
+
hint: "Official OpenAI JavaScript and TypeScript client"
|
|
276
|
+
},
|
|
277
|
+
{
|
|
278
|
+
value: "anthropic-sdk",
|
|
279
|
+
label: "Anthropic SDK",
|
|
280
|
+
hint: "Official Anthropic TypeScript client for Claude"
|
|
281
|
+
},
|
|
272
282
|
{
|
|
273
283
|
value: "google-adk",
|
|
274
284
|
label: "Google ADK",
|
|
@@ -305,11 +315,14 @@ const AI_PROMPT_OPTIONS = [
|
|
|
305
315
|
hint: "No AI SDK"
|
|
306
316
|
}
|
|
307
317
|
];
|
|
308
|
-
function resolveAIPrompt(
|
|
309
|
-
return createStaticSinglePromptResolution(AI_PROMPT_OPTIONS, "none", ai);
|
|
318
|
+
function resolveAIPrompt(context = {}) {
|
|
319
|
+
return createStaticSinglePromptResolution(["none", "convex"].includes(context.backend ?? "") ? AI_PROMPT_OPTIONS.filter((option) => option.value !== "openai-sdk" && option.value !== "anthropic-sdk") : AI_PROMPT_OPTIONS, "none", context.ai);
|
|
310
320
|
}
|
|
311
|
-
async function getAIChoice(ai) {
|
|
312
|
-
const resolution = resolveAIPrompt(
|
|
321
|
+
async function getAIChoice(ai, backend) {
|
|
322
|
+
const resolution = resolveAIPrompt({
|
|
323
|
+
ai,
|
|
324
|
+
backend
|
|
325
|
+
});
|
|
313
326
|
if (!resolution.shouldPrompt) return resolution.autoValue ?? "none";
|
|
314
327
|
const response = await navigableSelect({
|
|
315
328
|
message: "Select AI SDK",
|
|
@@ -574,6 +587,7 @@ function resolveAuthPrompt(context = {}) {
|
|
|
574
587
|
{ value: "auth0" },
|
|
575
588
|
{ value: "workos" },
|
|
576
589
|
{ value: "kinde" },
|
|
590
|
+
{ value: "passport" },
|
|
577
591
|
{ value: "none" }
|
|
578
592
|
];
|
|
579
593
|
const supportedOptions = (0, types_exports.getSupportedCapabilityOptions)("auth", {
|
|
@@ -854,6 +868,11 @@ const CMS_PROMPT_OPTIONS = [
|
|
|
854
868
|
label: "Keystatic",
|
|
855
869
|
hint: "Git-backed CMS for Markdown, JSON, and YAML content"
|
|
856
870
|
},
|
|
871
|
+
{
|
|
872
|
+
value: "contentful",
|
|
873
|
+
label: "Contentful",
|
|
874
|
+
hint: "Hosted headless CMS with a typed JavaScript delivery client"
|
|
875
|
+
},
|
|
857
876
|
{
|
|
858
877
|
value: "none",
|
|
859
878
|
label: "None",
|
|
@@ -861,28 +880,44 @@ const CMS_PROMPT_OPTIONS = [
|
|
|
861
880
|
}
|
|
862
881
|
];
|
|
863
882
|
function resolveCMSPrompt(context = {}) {
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
883
|
+
const compatibleOptions = context.frontends?.some((frontend) => ["vanilla-vite", "vue"].includes(frontend)) ? CMS_PROMPT_OPTIONS.filter((option) => ["contentful", "none"].includes(option.value)) : CMS_PROMPT_OPTIONS;
|
|
884
|
+
if (context.backend === "none" || context.backend === "convex") {
|
|
885
|
+
const options = compatibleOptions.filter((option) => ["contentful", "none"].includes(option.value));
|
|
886
|
+
if ((context.frontends?.some((frontend) => frontend !== "none" && isWebFrontend$1(frontend)) ?? false) && (context.cms === void 0 || context.cms === "contentful")) return context.cms === "contentful" ? {
|
|
887
|
+
shouldPrompt: false,
|
|
888
|
+
mode: "single",
|
|
889
|
+
options,
|
|
890
|
+
autoValue: "contentful"
|
|
891
|
+
} : {
|
|
892
|
+
shouldPrompt: true,
|
|
893
|
+
mode: "single",
|
|
894
|
+
options,
|
|
895
|
+
initialValue: "none"
|
|
896
|
+
};
|
|
897
|
+
return {
|
|
898
|
+
shouldPrompt: false,
|
|
899
|
+
mode: "single",
|
|
900
|
+
options: [],
|
|
901
|
+
autoValue: "none"
|
|
902
|
+
};
|
|
903
|
+
}
|
|
870
904
|
return context.cms !== void 0 ? {
|
|
871
905
|
shouldPrompt: false,
|
|
872
906
|
mode: "single",
|
|
873
|
-
options:
|
|
874
|
-
autoValue: context.cms
|
|
907
|
+
options: compatibleOptions,
|
|
908
|
+
autoValue: compatibleOptions.some((option) => option.value === context.cms) ? context.cms : "none"
|
|
875
909
|
} : {
|
|
876
910
|
shouldPrompt: true,
|
|
877
911
|
mode: "single",
|
|
878
|
-
options:
|
|
912
|
+
options: compatibleOptions,
|
|
879
913
|
initialValue: "none"
|
|
880
914
|
};
|
|
881
915
|
}
|
|
882
|
-
async function getCMSChoice(cms, backend) {
|
|
916
|
+
async function getCMSChoice(cms, backend, frontends) {
|
|
883
917
|
const resolution = resolveCMSPrompt({
|
|
884
918
|
cms,
|
|
885
|
-
backend
|
|
919
|
+
backend,
|
|
920
|
+
frontends
|
|
886
921
|
});
|
|
887
922
|
if (!resolution.shouldPrompt) return resolution.autoValue ?? "none";
|
|
888
923
|
const response = await navigableSelect({
|
|
@@ -914,6 +949,11 @@ const sharedServiceSection = {
|
|
|
914
949
|
]
|
|
915
950
|
};
|
|
916
951
|
const typescriptSections = [
|
|
952
|
+
{
|
|
953
|
+
id: "app-platforms",
|
|
954
|
+
label: "App Platforms",
|
|
955
|
+
promptKeys: ["appPlatforms"]
|
|
956
|
+
},
|
|
917
957
|
{
|
|
918
958
|
id: "ui-styling",
|
|
919
959
|
label: "UI & Styling",
|
|
@@ -1148,7 +1188,10 @@ const CONFIG_SCOPE_REGISTRY = {
|
|
|
1148
1188
|
"dbSetup",
|
|
1149
1189
|
"goOrm",
|
|
1150
1190
|
"goApi",
|
|
1151
|
-
"goAuth"
|
|
1191
|
+
"goAuth",
|
|
1192
|
+
"goValidation",
|
|
1193
|
+
"goMigrations",
|
|
1194
|
+
"goDI"
|
|
1152
1195
|
],
|
|
1153
1196
|
sections: [
|
|
1154
1197
|
sharedServiceSection,
|
|
@@ -1158,7 +1201,9 @@ const CONFIG_SCOPE_REGISTRY = {
|
|
|
1158
1201
|
promptKeys: [
|
|
1159
1202
|
"goCli",
|
|
1160
1203
|
"goConfig",
|
|
1161
|
-
"goLogging"
|
|
1204
|
+
"goLogging",
|
|
1205
|
+
"goTemplating",
|
|
1206
|
+
"goProtoTooling"
|
|
1162
1207
|
]
|
|
1163
1208
|
},
|
|
1164
1209
|
{
|
|
@@ -1172,8 +1217,12 @@ const CONFIG_SCOPE_REGISTRY = {
|
|
|
1172
1217
|
},
|
|
1173
1218
|
{
|
|
1174
1219
|
id: "quality",
|
|
1175
|
-
label: "Testing & Observability",
|
|
1176
|
-
promptKeys: [
|
|
1220
|
+
label: "Quality, Testing & Observability",
|
|
1221
|
+
promptKeys: [
|
|
1222
|
+
"goQuality",
|
|
1223
|
+
"goTesting",
|
|
1224
|
+
"goObservability"
|
|
1225
|
+
]
|
|
1177
1226
|
}
|
|
1178
1227
|
]
|
|
1179
1228
|
},
|
|
@@ -1269,13 +1318,27 @@ const CONFIG_SCOPE_REGISTRY = {
|
|
|
1269
1318
|
promptKeys: [
|
|
1270
1319
|
"elixirTesting",
|
|
1271
1320
|
"elixirQuality",
|
|
1272
|
-
"elixirObservability"
|
|
1321
|
+
"elixirObservability",
|
|
1322
|
+
"elixirDocumentation"
|
|
1323
|
+
]
|
|
1324
|
+
},
|
|
1325
|
+
{
|
|
1326
|
+
id: "runtime",
|
|
1327
|
+
label: "Internationalization, Runtime & Clustering",
|
|
1328
|
+
promptKeys: [
|
|
1329
|
+
"elixirI18n",
|
|
1330
|
+
"elixirHttpServer",
|
|
1331
|
+
"elixirClustering"
|
|
1273
1332
|
]
|
|
1274
1333
|
},
|
|
1275
1334
|
{
|
|
1276
1335
|
id: "deploy-libraries",
|
|
1277
1336
|
label: "Deployment & Libraries",
|
|
1278
|
-
promptKeys: [
|
|
1337
|
+
promptKeys: [
|
|
1338
|
+
"elixirDeploy",
|
|
1339
|
+
"elixirApplicationFramework",
|
|
1340
|
+
"elixirLibraries"
|
|
1341
|
+
]
|
|
1279
1342
|
}
|
|
1280
1343
|
]
|
|
1281
1344
|
}
|
|
@@ -1310,6 +1373,7 @@ function shouldAskConfigPromptKey(ecosystem, key, scope, selectedSectionIds) {
|
|
|
1310
1373
|
}
|
|
1311
1374
|
function getDefaultPromptValue(key) {
|
|
1312
1375
|
if (key === "astroIntegration") return void 0;
|
|
1376
|
+
if (key === "appPlatforms") return [];
|
|
1313
1377
|
const defaults = getDefaultConfig();
|
|
1314
1378
|
if (key === "shadcnOptions") return {
|
|
1315
1379
|
shadcnBase: defaults.shadcnBase,
|
|
@@ -1382,13 +1446,17 @@ const CSS_FRAMEWORK_OPTIONS = {
|
|
|
1382
1446
|
label: "PostCSS Only",
|
|
1383
1447
|
hint: "Minimal setup with just PostCSS"
|
|
1384
1448
|
},
|
|
1449
|
+
"styled-components": {
|
|
1450
|
+
label: "styled-components",
|
|
1451
|
+
hint: "CSS-in-JS with tagged template literals for React"
|
|
1452
|
+
},
|
|
1385
1453
|
none: {
|
|
1386
1454
|
label: "None",
|
|
1387
1455
|
hint: "Plain CSS without preprocessors"
|
|
1388
1456
|
}
|
|
1389
1457
|
};
|
|
1390
1458
|
function resolveCSSFrameworkPrompt(context = {}) {
|
|
1391
|
-
const compatibleFrameworks = getCompatibleCSSFrameworks$1(context.uiLibrary);
|
|
1459
|
+
const compatibleFrameworks = getCompatibleCSSFrameworks$1(context.uiLibrary, context.frontends);
|
|
1392
1460
|
if (context.cssFramework !== void 0) return {
|
|
1393
1461
|
shouldPrompt: false,
|
|
1394
1462
|
mode: "single",
|
|
@@ -1397,7 +1465,7 @@ function resolveCSSFrameworkPrompt(context = {}) {
|
|
|
1397
1465
|
label: CSS_FRAMEWORK_OPTIONS[fw].label,
|
|
1398
1466
|
hint: CSS_FRAMEWORK_OPTIONS[fw].hint
|
|
1399
1467
|
})),
|
|
1400
|
-
autoValue:
|
|
1468
|
+
autoValue: context.cssFramework
|
|
1401
1469
|
};
|
|
1402
1470
|
return {
|
|
1403
1471
|
shouldPrompt: true,
|
|
@@ -1410,10 +1478,11 @@ function resolveCSSFrameworkPrompt(context = {}) {
|
|
|
1410
1478
|
initialValue: compatibleFrameworks.includes("tailwind") ? "tailwind" : compatibleFrameworks[0]
|
|
1411
1479
|
};
|
|
1412
1480
|
}
|
|
1413
|
-
async function getCSSFrameworkChoice(cssFramework, uiLibrary) {
|
|
1481
|
+
async function getCSSFrameworkChoice(cssFramework, uiLibrary, frontends) {
|
|
1414
1482
|
const resolution = resolveCSSFrameworkPrompt({
|
|
1415
1483
|
cssFramework,
|
|
1416
|
-
uiLibrary
|
|
1484
|
+
uiLibrary,
|
|
1485
|
+
frontends
|
|
1417
1486
|
});
|
|
1418
1487
|
if (!resolution.shouldPrompt) return resolution.autoValue ?? "none";
|
|
1419
1488
|
const selected = await navigableSelect({
|
|
@@ -1930,6 +1999,90 @@ const getDotnetValidationChoice = (value) => makeChoice$1("Select .NET validatio
|
|
|
1930
1999
|
const getDotnetCachingChoice = (value) => makeChoice$1("Select .NET caching", CACHING_OPTIONS$1, "none", value);
|
|
1931
2000
|
const getDotnetDeployChoice = (value) => makeChoice$1("Select .NET deploy target", DEPLOY_OPTIONS$1, "docker", value);
|
|
1932
2001
|
|
|
2002
|
+
//#endregion
|
|
2003
|
+
//#region src/prompts/ecosystem.ts
|
|
2004
|
+
const ECOSYSTEM_PROMPT_OPTIONS = [
|
|
2005
|
+
{
|
|
2006
|
+
value: "typescript",
|
|
2007
|
+
label: "TypeScript",
|
|
2008
|
+
hint: "Full-stack TypeScript web with React, Vue, Svelte, and more"
|
|
2009
|
+
},
|
|
2010
|
+
{
|
|
2011
|
+
value: "react-native",
|
|
2012
|
+
label: "React Native",
|
|
2013
|
+
hint: "Expo and React Native mobile apps with native integrations"
|
|
2014
|
+
},
|
|
2015
|
+
{
|
|
2016
|
+
value: "rust",
|
|
2017
|
+
label: "Rust",
|
|
2018
|
+
hint: "Rust ecosystem with Axum, Leptos, and more"
|
|
2019
|
+
},
|
|
2020
|
+
{
|
|
2021
|
+
value: "python",
|
|
2022
|
+
label: "Python",
|
|
2023
|
+
hint: "Python ecosystem with FastAPI, Django, and AI/ML tools"
|
|
2024
|
+
},
|
|
2025
|
+
{
|
|
2026
|
+
value: "go",
|
|
2027
|
+
label: "Go",
|
|
2028
|
+
hint: "Go ecosystem with Gin, Echo, GORM, and more"
|
|
2029
|
+
},
|
|
2030
|
+
{
|
|
2031
|
+
value: "java",
|
|
2032
|
+
label: "Java",
|
|
2033
|
+
hint: "Java ecosystem with Spring Boot, Maven, Gradle, and more"
|
|
2034
|
+
},
|
|
2035
|
+
{
|
|
2036
|
+
value: "dotnet",
|
|
2037
|
+
label: ".NET",
|
|
2038
|
+
hint: "ASP.NET Core ecosystem with Minimal APIs, EF Core, SignalR, and more"
|
|
2039
|
+
},
|
|
2040
|
+
{
|
|
2041
|
+
value: "elixir",
|
|
2042
|
+
label: "Elixir",
|
|
2043
|
+
hint: "Elixir ecosystem with Phoenix, LiveView, Ecto, and more"
|
|
2044
|
+
}
|
|
2045
|
+
];
|
|
2046
|
+
async function getEcosystemChoice(ecosystem) {
|
|
2047
|
+
if (ecosystem !== void 0) return ecosystem;
|
|
2048
|
+
const response = await navigableSelect({
|
|
2049
|
+
message: "Select ecosystem",
|
|
2050
|
+
options: ECOSYSTEM_PROMPT_OPTIONS,
|
|
2051
|
+
initialValue: "typescript"
|
|
2052
|
+
});
|
|
2053
|
+
if (isCancel$1(response)) return exitCancelled("Operation cancelled");
|
|
2054
|
+
return response;
|
|
2055
|
+
}
|
|
2056
|
+
|
|
2057
|
+
//#endregion
|
|
2058
|
+
//#region src/prompts/effect.ts
|
|
2059
|
+
async function getEffectChoice(effect) {
|
|
2060
|
+
if (effect !== void 0) return effect;
|
|
2061
|
+
const response = await navigableSelect({
|
|
2062
|
+
message: "Select Effect services",
|
|
2063
|
+
options: [
|
|
2064
|
+
{
|
|
2065
|
+
value: "effect",
|
|
2066
|
+
label: "Effect Core",
|
|
2067
|
+
hint: "Add Effect services and layers to the selected stack"
|
|
2068
|
+
},
|
|
2069
|
+
{
|
|
2070
|
+
value: "effect-full",
|
|
2071
|
+
label: "Effect Platform + SQL",
|
|
2072
|
+
hint: "Core plus Platform, browser/server adapters, SQL, and Vitest integration"
|
|
2073
|
+
},
|
|
2074
|
+
{
|
|
2075
|
+
value: "none",
|
|
2076
|
+
label: "None",
|
|
2077
|
+
hint: "No additional Effect services"
|
|
2078
|
+
}
|
|
2079
|
+
],
|
|
2080
|
+
initialValue: "none"
|
|
2081
|
+
});
|
|
2082
|
+
if (isCancel$1(response)) return exitCancelled("Operation cancelled");
|
|
2083
|
+
return response;
|
|
2084
|
+
}
|
|
2085
|
+
|
|
1933
2086
|
//#endregion
|
|
1934
2087
|
//#region src/prompts/elixir-ecosystem.ts
|
|
1935
2088
|
function makeChoice(message, options, defaultValue, value) {
|
|
@@ -1982,6 +2135,16 @@ const ORM_OPTIONS = [
|
|
|
1982
2135
|
label: "Ecto",
|
|
1983
2136
|
hint: "Ecto schemas and changesets without SQL repo wiring"
|
|
1984
2137
|
},
|
|
2138
|
+
{
|
|
2139
|
+
value: "myxql",
|
|
2140
|
+
label: "MyXQL",
|
|
2141
|
+
hint: "Ecto SQL with MySQL and MariaDB"
|
|
2142
|
+
},
|
|
2143
|
+
{
|
|
2144
|
+
value: "ecto_sqlite3",
|
|
2145
|
+
label: "ecto_sqlite3",
|
|
2146
|
+
hint: "Embedded SQLite through Ecto SQL"
|
|
2147
|
+
},
|
|
1985
2148
|
{
|
|
1986
2149
|
value: "none",
|
|
1987
2150
|
label: "None",
|
|
@@ -2004,6 +2167,11 @@ const AUTH_OPTIONS = [
|
|
|
2004
2167
|
label: "Guardian",
|
|
2005
2168
|
hint: "JWT authentication foundation"
|
|
2006
2169
|
},
|
|
2170
|
+
{
|
|
2171
|
+
value: "pow",
|
|
2172
|
+
label: "Pow",
|
|
2173
|
+
hint: "Database-backed Phoenix authentication"
|
|
2174
|
+
},
|
|
2007
2175
|
{
|
|
2008
2176
|
value: "none",
|
|
2009
2177
|
label: "None",
|
|
@@ -2026,6 +2194,11 @@ const API_OPTIONS = [
|
|
|
2026
2194
|
label: "gRPC",
|
|
2027
2195
|
hint: "grpc-elixir endpoint (run protoc codegen for stubs)"
|
|
2028
2196
|
},
|
|
2197
|
+
{
|
|
2198
|
+
value: "open_api_spex",
|
|
2199
|
+
label: "OpenApiSpex",
|
|
2200
|
+
hint: "OpenAPI schemas, validation, and Swagger UI"
|
|
2201
|
+
},
|
|
2029
2202
|
{
|
|
2030
2203
|
value: "none",
|
|
2031
2204
|
label: "None",
|
|
@@ -2043,6 +2216,21 @@ const LIBRARY_OPTIONS = [
|
|
|
2043
2216
|
label: "Nx",
|
|
2044
2217
|
hint: "Numerical Elixir: tensors and ML on the BEAM"
|
|
2045
2218
|
},
|
|
2219
|
+
{
|
|
2220
|
+
value: "ex_aws",
|
|
2221
|
+
label: "ExAws",
|
|
2222
|
+
hint: "AWS clients including S3, SQS, and SNS"
|
|
2223
|
+
},
|
|
2224
|
+
{
|
|
2225
|
+
value: "floki",
|
|
2226
|
+
label: "Floki",
|
|
2227
|
+
hint: "HTML parsing and transformation"
|
|
2228
|
+
},
|
|
2229
|
+
{
|
|
2230
|
+
value: "rustler",
|
|
2231
|
+
label: "Rustler",
|
|
2232
|
+
hint: "Safe Rust native extensions for the BEAM"
|
|
2233
|
+
},
|
|
2046
2234
|
{
|
|
2047
2235
|
value: "none",
|
|
2048
2236
|
label: "None",
|
|
@@ -2121,6 +2309,11 @@ const HTTP_OPTIONS = [
|
|
|
2121
2309
|
label: "Finch",
|
|
2122
2310
|
hint: "Pooled HTTP client"
|
|
2123
2311
|
},
|
|
2312
|
+
{
|
|
2313
|
+
value: "tesla",
|
|
2314
|
+
label: "Tesla",
|
|
2315
|
+
hint: "Middleware-based HTTP client"
|
|
2316
|
+
},
|
|
2124
2317
|
{
|
|
2125
2318
|
value: "none",
|
|
2126
2319
|
label: "None",
|
|
@@ -2136,15 +2329,23 @@ const JSON_OPTIONS = [{
|
|
|
2136
2329
|
label: "None",
|
|
2137
2330
|
hint: "No JSON library"
|
|
2138
2331
|
}];
|
|
2139
|
-
const EMAIL_OPTIONS = [
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2332
|
+
const EMAIL_OPTIONS = [
|
|
2333
|
+
{
|
|
2334
|
+
value: "swoosh",
|
|
2335
|
+
label: "Swoosh",
|
|
2336
|
+
hint: "Phoenix email library"
|
|
2337
|
+
},
|
|
2338
|
+
{
|
|
2339
|
+
value: "bamboo",
|
|
2340
|
+
label: "Bamboo",
|
|
2341
|
+
hint: "Adapter-based transactional email"
|
|
2342
|
+
},
|
|
2343
|
+
{
|
|
2344
|
+
value: "none",
|
|
2345
|
+
label: "None",
|
|
2346
|
+
hint: "No email library"
|
|
2347
|
+
}
|
|
2348
|
+
];
|
|
2148
2349
|
const CACHING_OPTIONS = [
|
|
2149
2350
|
{
|
|
2150
2351
|
value: "cachex",
|
|
@@ -2156,6 +2357,11 @@ const CACHING_OPTIONS = [
|
|
|
2156
2357
|
label: "Nebulex",
|
|
2157
2358
|
hint: "Cache abstraction"
|
|
2158
2359
|
},
|
|
2360
|
+
{
|
|
2361
|
+
value: "redix",
|
|
2362
|
+
label: "Redix",
|
|
2363
|
+
hint: "Resilient Redis client"
|
|
2364
|
+
},
|
|
2159
2365
|
{
|
|
2160
2366
|
value: "none",
|
|
2161
2367
|
label: "None",
|
|
@@ -2178,6 +2384,11 @@ const OBSERVABILITY_OPTIONS = [
|
|
|
2178
2384
|
label: "PromEx",
|
|
2179
2385
|
hint: "Prometheus metrics for Phoenix"
|
|
2180
2386
|
},
|
|
2387
|
+
{
|
|
2388
|
+
value: "sentry",
|
|
2389
|
+
label: "Sentry",
|
|
2390
|
+
hint: "Exception and performance monitoring"
|
|
2391
|
+
},
|
|
2181
2392
|
{
|
|
2182
2393
|
value: "none",
|
|
2183
2394
|
label: "None",
|
|
@@ -2205,6 +2416,16 @@ const TESTING_OPTIONS = [
|
|
|
2205
2416
|
label: "Wallaby",
|
|
2206
2417
|
hint: "Browser acceptance testing"
|
|
2207
2418
|
},
|
|
2419
|
+
{
|
|
2420
|
+
value: "stream_data",
|
|
2421
|
+
label: "StreamData",
|
|
2422
|
+
hint: "Property-based testing with shrinking"
|
|
2423
|
+
},
|
|
2424
|
+
{
|
|
2425
|
+
value: "ex_machina",
|
|
2426
|
+
label: "ExMachina",
|
|
2427
|
+
hint: "Factories for Ecto-backed tests"
|
|
2428
|
+
},
|
|
2208
2429
|
{
|
|
2209
2430
|
value: "none",
|
|
2210
2431
|
label: "None",
|
|
@@ -2227,12 +2448,75 @@ const QUALITY_OPTIONS = [
|
|
|
2227
2448
|
label: "Sobelow",
|
|
2228
2449
|
hint: "Phoenix security analysis"
|
|
2229
2450
|
},
|
|
2451
|
+
{
|
|
2452
|
+
value: "excoveralls",
|
|
2453
|
+
label: "ExCoveralls",
|
|
2454
|
+
hint: "Coverage reports and CI integration"
|
|
2455
|
+
},
|
|
2456
|
+
{
|
|
2457
|
+
value: "mix_audit",
|
|
2458
|
+
label: "MixAudit",
|
|
2459
|
+
hint: "Audit Hex dependencies for vulnerabilities"
|
|
2460
|
+
},
|
|
2230
2461
|
{
|
|
2231
2462
|
value: "none",
|
|
2232
2463
|
label: "None",
|
|
2233
2464
|
hint: "No code quality tool"
|
|
2234
2465
|
}
|
|
2235
2466
|
];
|
|
2467
|
+
const I18N_OPTIONS = [{
|
|
2468
|
+
value: "gettext",
|
|
2469
|
+
label: "Gettext",
|
|
2470
|
+
hint: "Canonical Phoenix localization"
|
|
2471
|
+
}, {
|
|
2472
|
+
value: "none",
|
|
2473
|
+
label: "None",
|
|
2474
|
+
hint: "No localization layer"
|
|
2475
|
+
}];
|
|
2476
|
+
const HTTP_SERVER_OPTIONS = [
|
|
2477
|
+
{
|
|
2478
|
+
value: "bandit",
|
|
2479
|
+
label: "Bandit",
|
|
2480
|
+
hint: "Modern pure-Elixir HTTP/WebSocket server"
|
|
2481
|
+
},
|
|
2482
|
+
{
|
|
2483
|
+
value: "cowboy",
|
|
2484
|
+
label: "Cowboy",
|
|
2485
|
+
hint: "Established Erlang HTTP server"
|
|
2486
|
+
},
|
|
2487
|
+
{
|
|
2488
|
+
value: "none",
|
|
2489
|
+
label: "None",
|
|
2490
|
+
hint: "No HTTP server dependency"
|
|
2491
|
+
}
|
|
2492
|
+
];
|
|
2493
|
+
const APPLICATION_FRAMEWORK_OPTIONS = [{
|
|
2494
|
+
value: "ash",
|
|
2495
|
+
label: "Ash Framework",
|
|
2496
|
+
hint: "Resource-oriented application framework"
|
|
2497
|
+
}, {
|
|
2498
|
+
value: "none",
|
|
2499
|
+
label: "None",
|
|
2500
|
+
hint: "No application framework"
|
|
2501
|
+
}];
|
|
2502
|
+
const DOCUMENTATION_OPTIONS = [{
|
|
2503
|
+
value: "ex_doc",
|
|
2504
|
+
label: "ExDoc",
|
|
2505
|
+
hint: "Generate HTML and EPUB API documentation"
|
|
2506
|
+
}, {
|
|
2507
|
+
value: "none",
|
|
2508
|
+
label: "None",
|
|
2509
|
+
hint: "No documentation generator"
|
|
2510
|
+
}];
|
|
2511
|
+
const CLUSTERING_OPTIONS = [{
|
|
2512
|
+
value: "libcluster",
|
|
2513
|
+
label: "libcluster",
|
|
2514
|
+
hint: "Automatic BEAM cluster formation"
|
|
2515
|
+
}, {
|
|
2516
|
+
value: "none",
|
|
2517
|
+
label: "None",
|
|
2518
|
+
hint: "No cluster topology"
|
|
2519
|
+
}];
|
|
2236
2520
|
const DEPLOY_OPTIONS = [
|
|
2237
2521
|
{
|
|
2238
2522
|
value: "docker",
|
|
@@ -2274,6 +2558,11 @@ const resolveElixirCachingPrompt = (value) => createStaticSinglePromptResolution
|
|
|
2274
2558
|
const resolveElixirObservabilityPrompt = (value) => createStaticSinglePromptResolution(OBSERVABILITY_OPTIONS, "telemetry", value);
|
|
2275
2559
|
const resolveElixirTestingPrompt = (value) => createStaticSinglePromptResolution(TESTING_OPTIONS, "ex_unit", value);
|
|
2276
2560
|
const resolveElixirQualityPrompt = (value) => createStaticSinglePromptResolution(QUALITY_OPTIONS, "credo", value);
|
|
2561
|
+
const resolveElixirI18nPrompt = (value) => createStaticSinglePromptResolution(I18N_OPTIONS, "none", value);
|
|
2562
|
+
const resolveElixirHttpServerPrompt = (value) => createStaticSinglePromptResolution(HTTP_SERVER_OPTIONS, "cowboy", value);
|
|
2563
|
+
const resolveElixirApplicationFrameworkPrompt = (value) => createStaticSinglePromptResolution(APPLICATION_FRAMEWORK_OPTIONS, "none", value);
|
|
2564
|
+
const resolveElixirDocumentationPrompt = (value) => createStaticSinglePromptResolution(DOCUMENTATION_OPTIONS, "none", value);
|
|
2565
|
+
const resolveElixirClusteringPrompt = (value) => createStaticSinglePromptResolution(CLUSTERING_OPTIONS, "none", value);
|
|
2277
2566
|
const resolveElixirDeployPrompt = (value) => createStaticSinglePromptResolution(DEPLOY_OPTIONS, "none", value);
|
|
2278
2567
|
const getElixirWebFrameworkChoice = (value) => makeChoice("Select Elixir web framework", WEB_FRAMEWORK_OPTIONS, "phoenix", value);
|
|
2279
2568
|
const getElixirOrmChoice = (value) => makeChoice("Select Elixir database layer", ORM_OPTIONS, "ecto-sql", value);
|
|
@@ -2289,93 +2578,14 @@ const getElixirCachingChoice = (value) => makeChoice("Select Elixir caching", CA
|
|
|
2289
2578
|
const getElixirObservabilityChoice = (value) => makeChoice("Select Elixir observability", OBSERVABILITY_OPTIONS, "telemetry", value);
|
|
2290
2579
|
const getElixirTestingChoice = (value) => makeChoice("Select Elixir testing", TESTING_OPTIONS, "ex_unit", value);
|
|
2291
2580
|
const getElixirQualityChoice = (value) => makeChoice("Select Elixir code quality", QUALITY_OPTIONS, "credo", value);
|
|
2581
|
+
const getElixirI18nChoice = (value) => makeChoice("Select Elixir localization", I18N_OPTIONS, "none", value);
|
|
2582
|
+
const getElixirHttpServerChoice = (value) => makeChoice("Select Elixir HTTP server", HTTP_SERVER_OPTIONS, "cowboy", value);
|
|
2583
|
+
const getElixirApplicationFrameworkChoice = (value) => makeChoice("Select Elixir application framework", APPLICATION_FRAMEWORK_OPTIONS, "none", value);
|
|
2584
|
+
const getElixirDocumentationChoice = (value) => makeChoice("Select Elixir documentation", DOCUMENTATION_OPTIONS, "none", value);
|
|
2585
|
+
const getElixirClusteringChoice = (value) => makeChoice("Select Elixir clustering", CLUSTERING_OPTIONS, "none", value);
|
|
2292
2586
|
const getElixirDeployChoice = (value) => makeChoice("Select Elixir deploy target", DEPLOY_OPTIONS, "none", value);
|
|
2293
2587
|
const getElixirLibrariesChoice = (value) => makeMultiChoice("Select Elixir libraries", LIBRARY_OPTIONS, [], value);
|
|
2294
2588
|
|
|
2295
|
-
//#endregion
|
|
2296
|
-
//#region src/prompts/ecosystem.ts
|
|
2297
|
-
const ECOSYSTEM_PROMPT_OPTIONS = [
|
|
2298
|
-
{
|
|
2299
|
-
value: "typescript",
|
|
2300
|
-
label: "TypeScript",
|
|
2301
|
-
hint: "Full-stack TypeScript web with React, Vue, Svelte, and more"
|
|
2302
|
-
},
|
|
2303
|
-
{
|
|
2304
|
-
value: "react-native",
|
|
2305
|
-
label: "React Native",
|
|
2306
|
-
hint: "Expo and React Native mobile apps with native integrations"
|
|
2307
|
-
},
|
|
2308
|
-
{
|
|
2309
|
-
value: "rust",
|
|
2310
|
-
label: "Rust",
|
|
2311
|
-
hint: "Rust ecosystem with Axum, Leptos, and more"
|
|
2312
|
-
},
|
|
2313
|
-
{
|
|
2314
|
-
value: "python",
|
|
2315
|
-
label: "Python",
|
|
2316
|
-
hint: "Python ecosystem with FastAPI, Django, and AI/ML tools"
|
|
2317
|
-
},
|
|
2318
|
-
{
|
|
2319
|
-
value: "go",
|
|
2320
|
-
label: "Go",
|
|
2321
|
-
hint: "Go ecosystem with Gin, Echo, GORM, and more"
|
|
2322
|
-
},
|
|
2323
|
-
{
|
|
2324
|
-
value: "java",
|
|
2325
|
-
label: "Java",
|
|
2326
|
-
hint: "Java ecosystem with Spring Boot, Maven, Gradle, and more"
|
|
2327
|
-
},
|
|
2328
|
-
{
|
|
2329
|
-
value: "dotnet",
|
|
2330
|
-
label: ".NET",
|
|
2331
|
-
hint: "ASP.NET Core ecosystem with Minimal APIs, EF Core, SignalR, and more"
|
|
2332
|
-
},
|
|
2333
|
-
{
|
|
2334
|
-
value: "elixir",
|
|
2335
|
-
label: "Elixir",
|
|
2336
|
-
hint: "Elixir ecosystem with Phoenix, LiveView, Ecto, and more"
|
|
2337
|
-
}
|
|
2338
|
-
];
|
|
2339
|
-
async function getEcosystemChoice(ecosystem) {
|
|
2340
|
-
if (ecosystem !== void 0) return ecosystem;
|
|
2341
|
-
const response = await navigableSelect({
|
|
2342
|
-
message: "Select ecosystem",
|
|
2343
|
-
options: ECOSYSTEM_PROMPT_OPTIONS,
|
|
2344
|
-
initialValue: "typescript"
|
|
2345
|
-
});
|
|
2346
|
-
if (isCancel$1(response)) return exitCancelled("Operation cancelled");
|
|
2347
|
-
return response;
|
|
2348
|
-
}
|
|
2349
|
-
|
|
2350
|
-
//#endregion
|
|
2351
|
-
//#region src/prompts/effect.ts
|
|
2352
|
-
async function getEffectChoice(effect) {
|
|
2353
|
-
if (effect !== void 0) return effect;
|
|
2354
|
-
const response = await navigableSelect({
|
|
2355
|
-
message: "Select Effect services",
|
|
2356
|
-
options: [
|
|
2357
|
-
{
|
|
2358
|
-
value: "effect",
|
|
2359
|
-
label: "Effect Core",
|
|
2360
|
-
hint: "Add Effect services and layers to the selected stack"
|
|
2361
|
-
},
|
|
2362
|
-
{
|
|
2363
|
-
value: "effect-full",
|
|
2364
|
-
label: "Effect Platform + SQL",
|
|
2365
|
-
hint: "Core plus Platform, browser/server adapters, SQL, and Vitest integration"
|
|
2366
|
-
},
|
|
2367
|
-
{
|
|
2368
|
-
value: "none",
|
|
2369
|
-
label: "None",
|
|
2370
|
-
hint: "No additional Effect services"
|
|
2371
|
-
}
|
|
2372
|
-
],
|
|
2373
|
-
initialValue: "none"
|
|
2374
|
-
});
|
|
2375
|
-
if (isCancel$1(response)) return exitCancelled("Operation cancelled");
|
|
2376
|
-
return response;
|
|
2377
|
-
}
|
|
2378
|
-
|
|
2379
2589
|
//#endregion
|
|
2380
2590
|
//#region src/prompts/email.ts
|
|
2381
2591
|
const EMAIL_PROMPT_OPTIONS = [
|
|
@@ -2695,6 +2905,16 @@ const WEB_FRONTEND_PROMPT_OPTIONS = [
|
|
|
2695
2905
|
label: "React + Vite",
|
|
2696
2906
|
hint: "Client-routed React SPA powered by Vite"
|
|
2697
2907
|
},
|
|
2908
|
+
{
|
|
2909
|
+
value: "vanilla-vite",
|
|
2910
|
+
label: "Vite (Vanilla TypeScript)",
|
|
2911
|
+
hint: "Framework-free TypeScript, HTML, and CSS powered by Vite"
|
|
2912
|
+
},
|
|
2913
|
+
{
|
|
2914
|
+
value: "vue",
|
|
2915
|
+
label: "Vue 3 + Vite",
|
|
2916
|
+
hint: "Standalone Vue 3 SPA powered by Vite"
|
|
2917
|
+
},
|
|
2698
2918
|
{
|
|
2699
2919
|
value: "next",
|
|
2700
2920
|
label: "Next.js",
|
|
@@ -2909,6 +3129,21 @@ const GO_WEB_FRAMEWORK_PROMPT_OPTIONS = [
|
|
|
2909
3129
|
label: "net/http",
|
|
2910
3130
|
hint: "Go 1.22+ standard-library routing (ServeMux), zero dependencies"
|
|
2911
3131
|
},
|
|
3132
|
+
{
|
|
3133
|
+
value: "go-zero",
|
|
3134
|
+
label: "go-zero",
|
|
3135
|
+
hint: "API-first microservice framework with resilience and code generation"
|
|
3136
|
+
},
|
|
3137
|
+
{
|
|
3138
|
+
value: "kratos",
|
|
3139
|
+
label: "Kratos",
|
|
3140
|
+
hint: "Cloud-native HTTP/gRPC framework with middleware and lifecycle management"
|
|
3141
|
+
},
|
|
3142
|
+
{
|
|
3143
|
+
value: "httprouter",
|
|
3144
|
+
label: "HttpRouter",
|
|
3145
|
+
hint: "Minimal high-performance radix-tree HTTP router"
|
|
3146
|
+
},
|
|
2912
3147
|
{
|
|
2913
3148
|
value: "none",
|
|
2914
3149
|
label: "None",
|
|
@@ -2936,6 +3171,11 @@ const GO_ORM_PROMPT_OPTIONS = [
|
|
|
2936
3171
|
label: "Bun",
|
|
2937
3172
|
hint: "SQL-first Go ORM by uptrace with a lightweight query builder"
|
|
2938
3173
|
},
|
|
3174
|
+
{
|
|
3175
|
+
value: "sqlx",
|
|
3176
|
+
label: "sqlx",
|
|
3177
|
+
hint: "Lightweight database/sql extensions with named queries and struct scanning"
|
|
3178
|
+
},
|
|
2939
3179
|
{
|
|
2940
3180
|
value: "none",
|
|
2941
3181
|
label: "None",
|
|
@@ -2953,6 +3193,21 @@ const GO_API_PROMPT_OPTIONS = [
|
|
|
2953
3193
|
label: "gqlgen",
|
|
2954
3194
|
hint: "Schema-first GraphQL server with code generation"
|
|
2955
3195
|
},
|
|
3196
|
+
{
|
|
3197
|
+
value: "grpc-gateway",
|
|
3198
|
+
label: "grpc-gateway",
|
|
3199
|
+
hint: "REST/JSON gateway for protobuf-defined services"
|
|
3200
|
+
},
|
|
3201
|
+
{
|
|
3202
|
+
value: "connect-go",
|
|
3203
|
+
label: "Connect-Go",
|
|
3204
|
+
hint: "Protobuf RPC over gRPC, gRPC-Web, and HTTP/1.1"
|
|
3205
|
+
},
|
|
3206
|
+
{
|
|
3207
|
+
value: "oapi-codegen",
|
|
3208
|
+
label: "oapi-codegen",
|
|
3209
|
+
hint: "Generate typed Go clients and servers from OpenAPI contracts"
|
|
3210
|
+
},
|
|
2956
3211
|
{
|
|
2957
3212
|
value: "none",
|
|
2958
3213
|
label: "None",
|
|
@@ -3024,6 +3279,11 @@ const GO_AUTH_PROMPT_OPTIONS = [
|
|
|
3024
3279
|
label: "Goth",
|
|
3025
3280
|
hint: "OAuth social login for 30+ providers (Google, GitHub, ...)"
|
|
3026
3281
|
},
|
|
3282
|
+
{
|
|
3283
|
+
value: "oauth2",
|
|
3284
|
+
label: "golang.org/x/oauth2",
|
|
3285
|
+
hint: "Canonical OAuth2 client foundation for authorization-code and service flows"
|
|
3286
|
+
},
|
|
3027
3287
|
{
|
|
3028
3288
|
value: "none",
|
|
3029
3289
|
label: "None",
|
|
@@ -3125,6 +3385,21 @@ const GO_TESTING_PROMPT_OPTIONS = [
|
|
|
3125
3385
|
label: "GoMock",
|
|
3126
3386
|
hint: "Interface mock generation via mockgen"
|
|
3127
3387
|
},
|
|
3388
|
+
{
|
|
3389
|
+
value: "testcontainers",
|
|
3390
|
+
label: "Testcontainers for Go",
|
|
3391
|
+
hint: "Disposable real databases and services for integration tests"
|
|
3392
|
+
},
|
|
3393
|
+
{
|
|
3394
|
+
value: "ginkgo-gomega",
|
|
3395
|
+
label: "Ginkgo + Gomega",
|
|
3396
|
+
hint: "BDD test runner and expressive matcher library"
|
|
3397
|
+
},
|
|
3398
|
+
{
|
|
3399
|
+
value: "mockery",
|
|
3400
|
+
label: "mockery",
|
|
3401
|
+
hint: "Generate typed interface mocks with a reproducible project config"
|
|
3402
|
+
},
|
|
3128
3403
|
{
|
|
3129
3404
|
value: "none",
|
|
3130
3405
|
label: "None",
|
|
@@ -3159,6 +3434,16 @@ const GO_MESSAGE_QUEUE_PROMPT_OPTIONS = [
|
|
|
3159
3434
|
label: "Watermill",
|
|
3160
3435
|
hint: "Event-driven framework over Kafka, RabbitMQ, Pub/Sub, and more"
|
|
3161
3436
|
},
|
|
3437
|
+
{
|
|
3438
|
+
value: "kafka-go",
|
|
3439
|
+
label: "kafka-go",
|
|
3440
|
+
hint: "Idiomatic Kafka producer, consumer, and consumer-group client"
|
|
3441
|
+
},
|
|
3442
|
+
{
|
|
3443
|
+
value: "asynq",
|
|
3444
|
+
label: "Asynq",
|
|
3445
|
+
hint: "Redis-backed background jobs with retries, scheduling, and priorities"
|
|
3446
|
+
},
|
|
3162
3447
|
{
|
|
3163
3448
|
value: "none",
|
|
3164
3449
|
label: "None",
|
|
@@ -3199,14 +3484,76 @@ const GO_CONFIG_PROMPT_OPTIONS = [
|
|
|
3199
3484
|
hint: "Environment variables only"
|
|
3200
3485
|
}
|
|
3201
3486
|
];
|
|
3202
|
-
const GO_OBSERVABILITY_PROMPT_OPTIONS = [
|
|
3203
|
-
|
|
3204
|
-
|
|
3205
|
-
|
|
3487
|
+
const GO_OBSERVABILITY_PROMPT_OPTIONS = [
|
|
3488
|
+
{
|
|
3489
|
+
value: "opentelemetry",
|
|
3490
|
+
label: "OpenTelemetry",
|
|
3491
|
+
hint: "Official OTel SDK: traces and metrics with OTLP export"
|
|
3492
|
+
},
|
|
3493
|
+
{
|
|
3494
|
+
value: "prometheus",
|
|
3495
|
+
label: "Prometheus",
|
|
3496
|
+
hint: "Standard Prometheus metrics collectors and HTTP exposition"
|
|
3497
|
+
},
|
|
3498
|
+
{
|
|
3499
|
+
value: "none",
|
|
3500
|
+
label: "None",
|
|
3501
|
+
hint: "No tracing/metrics SDK"
|
|
3502
|
+
}
|
|
3503
|
+
];
|
|
3504
|
+
const GO_VALIDATION_PROMPT_OPTIONS = [{
|
|
3505
|
+
value: "validator",
|
|
3506
|
+
label: "go-playground/validator",
|
|
3507
|
+
hint: "Struct and field validation used by major Go web frameworks"
|
|
3206
3508
|
}, {
|
|
3207
3509
|
value: "none",
|
|
3208
3510
|
label: "None",
|
|
3209
|
-
hint: "No
|
|
3511
|
+
hint: "No validation helper"
|
|
3512
|
+
}];
|
|
3513
|
+
const GO_QUALITY_PROMPT_OPTIONS = [{
|
|
3514
|
+
value: "golangci-lint",
|
|
3515
|
+
label: "golangci-lint",
|
|
3516
|
+
hint: "Fast multi-linter with a checked-in CI-ready configuration"
|
|
3517
|
+
}, {
|
|
3518
|
+
value: "none",
|
|
3519
|
+
label: "None",
|
|
3520
|
+
hint: "No additional quality tooling"
|
|
3521
|
+
}];
|
|
3522
|
+
const GO_MIGRATIONS_PROMPT_OPTIONS = [{
|
|
3523
|
+
value: "golang-migrate",
|
|
3524
|
+
label: "golang-migrate",
|
|
3525
|
+
hint: "Versioned database migrations across PostgreSQL, MySQL, SQLite, and more"
|
|
3526
|
+
}, {
|
|
3527
|
+
value: "none",
|
|
3528
|
+
label: "None",
|
|
3529
|
+
hint: "No migration tooling"
|
|
3530
|
+
}];
|
|
3531
|
+
const GO_TEMPLATING_PROMPT_OPTIONS = [{
|
|
3532
|
+
value: "templ",
|
|
3533
|
+
label: "templ",
|
|
3534
|
+
hint: "Type-safe Go-native HTML components and code generation"
|
|
3535
|
+
}, {
|
|
3536
|
+
value: "none",
|
|
3537
|
+
label: "None",
|
|
3538
|
+
hint: "No server-side templating"
|
|
3539
|
+
}];
|
|
3540
|
+
const GO_PROTO_TOOLING_PROMPT_OPTIONS = [{
|
|
3541
|
+
value: "buf",
|
|
3542
|
+
label: "Buf",
|
|
3543
|
+
hint: "Protobuf linting, breaking-change checks, dependencies, and generation"
|
|
3544
|
+
}, {
|
|
3545
|
+
value: "none",
|
|
3546
|
+
label: "None",
|
|
3547
|
+
hint: "No protobuf toolchain"
|
|
3548
|
+
}];
|
|
3549
|
+
const GO_DI_PROMPT_OPTIONS = [{
|
|
3550
|
+
value: "fx",
|
|
3551
|
+
label: "Uber Fx",
|
|
3552
|
+
hint: "Lifecycle-aware dependency injection for modular Go services"
|
|
3553
|
+
}, {
|
|
3554
|
+
value: "none",
|
|
3555
|
+
label: "None",
|
|
3556
|
+
hint: "No dependency injection framework"
|
|
3210
3557
|
}];
|
|
3211
3558
|
function resolveGoTestingPrompt(goTesting) {
|
|
3212
3559
|
return createStaticMultiPromptResolution(GO_TESTING_PROMPT_OPTIONS, [], goTesting);
|
|
@@ -3293,6 +3640,90 @@ async function getGoObservabilityChoice(goObservability) {
|
|
|
3293
3640
|
if (isCancel$1(response)) return exitCancelled("Operation cancelled");
|
|
3294
3641
|
return response;
|
|
3295
3642
|
}
|
|
3643
|
+
function resolveGoValidationPrompt(goValidation) {
|
|
3644
|
+
return createStaticSinglePromptResolution(GO_VALIDATION_PROMPT_OPTIONS, "none", goValidation);
|
|
3645
|
+
}
|
|
3646
|
+
async function getGoValidationChoice(goValidation) {
|
|
3647
|
+
const resolution = resolveGoValidationPrompt(goValidation);
|
|
3648
|
+
if (!resolution.shouldPrompt) return resolution.autoValue ?? "none";
|
|
3649
|
+
const response = await navigableSelect({
|
|
3650
|
+
message: "Select Go validation library",
|
|
3651
|
+
options: resolution.options,
|
|
3652
|
+
initialValue: resolution.initialValue
|
|
3653
|
+
});
|
|
3654
|
+
if (isCancel$1(response)) return exitCancelled("Operation cancelled");
|
|
3655
|
+
return response;
|
|
3656
|
+
}
|
|
3657
|
+
function resolveGoQualityPrompt(goQuality) {
|
|
3658
|
+
return createStaticSinglePromptResolution(GO_QUALITY_PROMPT_OPTIONS, "none", goQuality);
|
|
3659
|
+
}
|
|
3660
|
+
async function getGoQualityChoice(goQuality) {
|
|
3661
|
+
const resolution = resolveGoQualityPrompt(goQuality);
|
|
3662
|
+
if (!resolution.shouldPrompt) return resolution.autoValue ?? "none";
|
|
3663
|
+
const response = await navigableSelect({
|
|
3664
|
+
message: "Select Go code quality tooling",
|
|
3665
|
+
options: resolution.options,
|
|
3666
|
+
initialValue: resolution.initialValue
|
|
3667
|
+
});
|
|
3668
|
+
if (isCancel$1(response)) return exitCancelled("Operation cancelled");
|
|
3669
|
+
return response;
|
|
3670
|
+
}
|
|
3671
|
+
function resolveGoMigrationsPrompt(goMigrations) {
|
|
3672
|
+
return createStaticSinglePromptResolution(GO_MIGRATIONS_PROMPT_OPTIONS, "none", goMigrations);
|
|
3673
|
+
}
|
|
3674
|
+
async function getGoMigrationsChoice(goMigrations) {
|
|
3675
|
+
const resolution = resolveGoMigrationsPrompt(goMigrations);
|
|
3676
|
+
if (!resolution.shouldPrompt) return resolution.autoValue ?? "none";
|
|
3677
|
+
const response = await navigableSelect({
|
|
3678
|
+
message: "Select Go database migration tooling",
|
|
3679
|
+
options: resolution.options,
|
|
3680
|
+
initialValue: resolution.initialValue
|
|
3681
|
+
});
|
|
3682
|
+
if (isCancel$1(response)) return exitCancelled("Operation cancelled");
|
|
3683
|
+
return response;
|
|
3684
|
+
}
|
|
3685
|
+
function resolveGoTemplatingPrompt(goTemplating) {
|
|
3686
|
+
return createStaticSinglePromptResolution(GO_TEMPLATING_PROMPT_OPTIONS, "none", goTemplating);
|
|
3687
|
+
}
|
|
3688
|
+
async function getGoTemplatingChoice(goTemplating) {
|
|
3689
|
+
const resolution = resolveGoTemplatingPrompt(goTemplating);
|
|
3690
|
+
if (!resolution.shouldPrompt) return resolution.autoValue ?? "none";
|
|
3691
|
+
const response = await navigableSelect({
|
|
3692
|
+
message: "Select Go templating library",
|
|
3693
|
+
options: resolution.options,
|
|
3694
|
+
initialValue: resolution.initialValue
|
|
3695
|
+
});
|
|
3696
|
+
if (isCancel$1(response)) return exitCancelled("Operation cancelled");
|
|
3697
|
+
return response;
|
|
3698
|
+
}
|
|
3699
|
+
function resolveGoProtoToolingPrompt(goProtoTooling) {
|
|
3700
|
+
return createStaticSinglePromptResolution(GO_PROTO_TOOLING_PROMPT_OPTIONS, "none", goProtoTooling);
|
|
3701
|
+
}
|
|
3702
|
+
async function getGoProtoToolingChoice(goProtoTooling) {
|
|
3703
|
+
const resolution = resolveGoProtoToolingPrompt(goProtoTooling);
|
|
3704
|
+
if (!resolution.shouldPrompt) return resolution.autoValue ?? "none";
|
|
3705
|
+
const response = await navigableSelect({
|
|
3706
|
+
message: "Select Go protobuf tooling",
|
|
3707
|
+
options: resolution.options,
|
|
3708
|
+
initialValue: resolution.initialValue
|
|
3709
|
+
});
|
|
3710
|
+
if (isCancel$1(response)) return exitCancelled("Operation cancelled");
|
|
3711
|
+
return response;
|
|
3712
|
+
}
|
|
3713
|
+
function resolveGoDIPrompt(goDI) {
|
|
3714
|
+
return createStaticSinglePromptResolution(GO_DI_PROMPT_OPTIONS, "none", goDI);
|
|
3715
|
+
}
|
|
3716
|
+
async function getGoDIChoice(goDI) {
|
|
3717
|
+
const resolution = resolveGoDIPrompt(goDI);
|
|
3718
|
+
if (!resolution.shouldPrompt) return resolution.autoValue ?? "none";
|
|
3719
|
+
const response = await navigableSelect({
|
|
3720
|
+
message: "Select Go dependency injection",
|
|
3721
|
+
options: resolution.options,
|
|
3722
|
+
initialValue: resolution.initialValue
|
|
3723
|
+
});
|
|
3724
|
+
if (isCancel$1(response)) return exitCancelled("Operation cancelled");
|
|
3725
|
+
return response;
|
|
3726
|
+
}
|
|
3296
3727
|
|
|
3297
3728
|
//#endregion
|
|
3298
3729
|
//#region src/prompts/i18n.ts
|
|
@@ -4704,6 +5135,16 @@ const RUST_WEB_FRAMEWORK_PROMPT_OPTIONS = [
|
|
|
4704
5135
|
label: "Loco",
|
|
4705
5136
|
hint: "The Rails of Rust: opinionated full-stack framework (runs DB-free too)"
|
|
4706
5137
|
},
|
|
5138
|
+
{
|
|
5139
|
+
value: "warp",
|
|
5140
|
+
label: "Warp",
|
|
5141
|
+
hint: "Composable, filter-based async web framework"
|
|
5142
|
+
},
|
|
5143
|
+
{
|
|
5144
|
+
value: "salvo",
|
|
5145
|
+
label: "Salvo",
|
|
5146
|
+
hint: "Batteries-included async framework with OpenAPI and HTTP/3 support"
|
|
5147
|
+
},
|
|
4707
5148
|
{
|
|
4708
5149
|
value: "none",
|
|
4709
5150
|
label: "None",
|
|
@@ -4721,6 +5162,11 @@ const RUST_FRONTEND_PROMPT_OPTIONS = [
|
|
|
4721
5162
|
label: "Dioxus",
|
|
4722
5163
|
hint: "Fullstack, cross-platform UI library for Rust"
|
|
4723
5164
|
},
|
|
5165
|
+
{
|
|
5166
|
+
value: "yew",
|
|
5167
|
+
label: "Yew",
|
|
5168
|
+
hint: "Mature React-like framework for client-side Rust/WASM applications"
|
|
5169
|
+
},
|
|
4724
5170
|
{
|
|
4725
5171
|
value: "none",
|
|
4726
5172
|
label: "None",
|
|
@@ -4743,6 +5189,21 @@ const RUST_ORM_PROMPT_OPTIONS = [
|
|
|
4743
5189
|
label: "Diesel",
|
|
4744
5190
|
hint: "Safe, extensible ORM with compile-time query validation"
|
|
4745
5191
|
},
|
|
5192
|
+
{
|
|
5193
|
+
value: "mongodb",
|
|
5194
|
+
label: "MongoDB Rust Driver",
|
|
5195
|
+
hint: "Official async MongoDB driver with typed BSON support"
|
|
5196
|
+
},
|
|
5197
|
+
{
|
|
5198
|
+
value: "rusqlite",
|
|
5199
|
+
label: "rusqlite",
|
|
5200
|
+
hint: "Ergonomic embedded SQLite access"
|
|
5201
|
+
},
|
|
5202
|
+
{
|
|
5203
|
+
value: "tokio-postgres",
|
|
5204
|
+
label: "tokio-postgres",
|
|
5205
|
+
hint: "Native asynchronous PostgreSQL client without an ORM"
|
|
5206
|
+
},
|
|
4746
5207
|
{
|
|
4747
5208
|
value: "none",
|
|
4748
5209
|
label: "None",
|
|
@@ -4760,6 +5221,11 @@ const RUST_API_PROMPT_OPTIONS = [
|
|
|
4760
5221
|
label: "async-graphql",
|
|
4761
5222
|
hint: "High-performance GraphQL server library"
|
|
4762
5223
|
},
|
|
5224
|
+
{
|
|
5225
|
+
value: "jsonrpsee",
|
|
5226
|
+
label: "jsonrpsee",
|
|
5227
|
+
hint: "Async JSON-RPC server and client framework"
|
|
5228
|
+
},
|
|
4763
5229
|
{
|
|
4764
5230
|
value: "none",
|
|
4765
5231
|
label: "None",
|
|
@@ -4868,6 +5334,41 @@ const RUST_LIBRARIES_PROMPT_OPTIONS = [
|
|
|
4868
5334
|
value: "insta",
|
|
4869
5335
|
label: "Insta",
|
|
4870
5336
|
hint: "Snapshot testing for Rust"
|
|
5337
|
+
},
|
|
5338
|
+
{
|
|
5339
|
+
value: "rand",
|
|
5340
|
+
label: "rand",
|
|
5341
|
+
hint: "Randomness, sampling, and test-data generation"
|
|
5342
|
+
},
|
|
5343
|
+
{
|
|
5344
|
+
value: "regex",
|
|
5345
|
+
label: "regex",
|
|
5346
|
+
hint: "Fast, safe regular expressions with linear-time matching"
|
|
5347
|
+
},
|
|
5348
|
+
{
|
|
5349
|
+
value: "rayon",
|
|
5350
|
+
label: "Rayon",
|
|
5351
|
+
hint: "Data parallelism for CPU-bound iterators and collections"
|
|
5352
|
+
},
|
|
5353
|
+
{
|
|
5354
|
+
value: "itertools",
|
|
5355
|
+
label: "Itertools",
|
|
5356
|
+
hint: "Additional iterator adaptors, grouping, and collection helpers"
|
|
5357
|
+
},
|
|
5358
|
+
{
|
|
5359
|
+
value: "rstest",
|
|
5360
|
+
label: "rstest",
|
|
5361
|
+
hint: "Fixture-based and parameterized Rust tests"
|
|
5362
|
+
},
|
|
5363
|
+
{
|
|
5364
|
+
value: "cargo-nextest",
|
|
5365
|
+
label: "cargo-nextest",
|
|
5366
|
+
hint: "Fast, isolated test runner with CI-friendly profiles"
|
|
5367
|
+
},
|
|
5368
|
+
{
|
|
5369
|
+
value: "cargo-audit",
|
|
5370
|
+
label: "cargo-audit",
|
|
5371
|
+
hint: "RustSec vulnerability auditing for Cargo dependencies"
|
|
4871
5372
|
}
|
|
4872
5373
|
];
|
|
4873
5374
|
const RUST_LOGGING_PROMPT_OPTIONS = [
|
|
@@ -5063,6 +5564,16 @@ async function getRustAuthChoice(rustAuth) {
|
|
|
5063
5564
|
label: "Torii",
|
|
5064
5565
|
hint: "Auth framework with passwords, sessions, and pluggable storage"
|
|
5065
5566
|
},
|
|
5567
|
+
{
|
|
5568
|
+
value: "openidconnect",
|
|
5569
|
+
label: "OpenID Connect",
|
|
5570
|
+
hint: "Strongly typed OIDC discovery, authorization, and token flows"
|
|
5571
|
+
},
|
|
5572
|
+
{
|
|
5573
|
+
value: "tower-sessions",
|
|
5574
|
+
label: "tower-sessions",
|
|
5575
|
+
hint: "Tower and Axum session middleware with pluggable stores"
|
|
5576
|
+
},
|
|
5066
5577
|
{
|
|
5067
5578
|
value: "none",
|
|
5068
5579
|
label: "None",
|
|
@@ -5096,15 +5607,28 @@ async function getRustMessageQueueChoice(rustMessageQueue) {
|
|
|
5096
5607
|
if (rustMessageQueue !== void 0) return rustMessageQueue;
|
|
5097
5608
|
const response = await navigableSelect({
|
|
5098
5609
|
message: "Select Rust message queue",
|
|
5099
|
-
options: [
|
|
5100
|
-
|
|
5101
|
-
|
|
5102
|
-
|
|
5103
|
-
|
|
5104
|
-
|
|
5105
|
-
|
|
5106
|
-
|
|
5107
|
-
|
|
5610
|
+
options: [
|
|
5611
|
+
{
|
|
5612
|
+
value: "lapin",
|
|
5613
|
+
label: "Lapin",
|
|
5614
|
+
hint: "Async RabbitMQ (AMQP) client"
|
|
5615
|
+
},
|
|
5616
|
+
{
|
|
5617
|
+
value: "rdkafka",
|
|
5618
|
+
label: "rdkafka",
|
|
5619
|
+
hint: "High-performance Kafka client backed by librdkafka"
|
|
5620
|
+
},
|
|
5621
|
+
{
|
|
5622
|
+
value: "async-nats",
|
|
5623
|
+
label: "async-nats",
|
|
5624
|
+
hint: "Async NATS and JetStream client for cloud-native messaging"
|
|
5625
|
+
},
|
|
5626
|
+
{
|
|
5627
|
+
value: "none",
|
|
5628
|
+
label: "None",
|
|
5629
|
+
hint: "No message queue"
|
|
5630
|
+
}
|
|
5631
|
+
],
|
|
5108
5632
|
initialValue: "none"
|
|
5109
5633
|
});
|
|
5110
5634
|
if (isCancel$1(response)) return exitCancelled("Operation cancelled");
|
|
@@ -5114,15 +5638,23 @@ async function getRustObservabilityChoice(rustObservability) {
|
|
|
5114
5638
|
if (rustObservability !== void 0) return rustObservability;
|
|
5115
5639
|
const response = await navigableSelect({
|
|
5116
5640
|
message: "Select Rust observability",
|
|
5117
|
-
options: [
|
|
5118
|
-
|
|
5119
|
-
|
|
5120
|
-
|
|
5121
|
-
|
|
5122
|
-
|
|
5123
|
-
|
|
5124
|
-
|
|
5125
|
-
|
|
5641
|
+
options: [
|
|
5642
|
+
{
|
|
5643
|
+
value: "opentelemetry",
|
|
5644
|
+
label: "OpenTelemetry",
|
|
5645
|
+
hint: "Official OTel SDK with OTLP/HTTP export"
|
|
5646
|
+
},
|
|
5647
|
+
{
|
|
5648
|
+
value: "metrics",
|
|
5649
|
+
label: "metrics",
|
|
5650
|
+
hint: "Lightweight metrics facade with a Prometheus exporter"
|
|
5651
|
+
},
|
|
5652
|
+
{
|
|
5653
|
+
value: "none",
|
|
5654
|
+
label: "None",
|
|
5655
|
+
hint: "No tracing/metrics SDK"
|
|
5656
|
+
}
|
|
5657
|
+
],
|
|
5126
5658
|
initialValue: "none"
|
|
5127
5659
|
});
|
|
5128
5660
|
if (isCancel$1(response)) return exitCancelled("Operation cancelled");
|
|
@@ -5143,6 +5675,11 @@ async function getRustTemplatingChoice(rustTemplating) {
|
|
|
5143
5675
|
label: "Tera",
|
|
5144
5676
|
hint: "Runtime Jinja2-style templates with dynamic loading"
|
|
5145
5677
|
},
|
|
5678
|
+
{
|
|
5679
|
+
value: "minijinja",
|
|
5680
|
+
label: "MiniJinja",
|
|
5681
|
+
hint: "Lightweight Jinja-compatible runtime template engine"
|
|
5682
|
+
},
|
|
5146
5683
|
{
|
|
5147
5684
|
value: "none",
|
|
5148
5685
|
label: "None",
|
|
@@ -5852,6 +6389,7 @@ async function gatherMultiEcosystemConfig(flags, projectName, projectDir, relati
|
|
|
5852
6389
|
const baseConfig = getDefaultConfig();
|
|
5853
6390
|
const configScope = !hasMultiStackPromptFlags(flags) ? promptValue(await getConfigScopeChoice()) : "full";
|
|
5854
6391
|
const typeScriptSections = configScope === "custom" ? promptValue(await getConfigSectionsChoice("typescript", [], [
|
|
6392
|
+
"app-platforms",
|
|
5855
6393
|
"ui-styling",
|
|
5856
6394
|
"deploy",
|
|
5857
6395
|
"addons-examples"
|
|
@@ -5863,6 +6401,15 @@ async function gatherMultiEcosystemConfig(flags, projectName, projectDir, relati
|
|
|
5863
6401
|
}));
|
|
5864
6402
|
const frontendList = [frontend];
|
|
5865
6403
|
const astroIntegration = frontend === "astro" ? promptValue(await getAstroIntegrationChoice(flags.astroIntegration)) : void 0;
|
|
6404
|
+
const nativeFrontend = promptValue(await navigableSelect({
|
|
6405
|
+
message: "Add a native mobile app? (React Native ecosystem)",
|
|
6406
|
+
options: [{
|
|
6407
|
+
value: "none",
|
|
6408
|
+
label: "None",
|
|
6409
|
+
hint: "web app only"
|
|
6410
|
+
}, ...NATIVE_FRONTEND_PROMPT_OPTIONS],
|
|
6411
|
+
initialValue: "none"
|
|
6412
|
+
}));
|
|
5866
6413
|
const uiLibrary = hasWebStyling$1(frontendList) ? await scopedPromptValue("typescript", "uiLibrary", configScope, typeScriptSections, () => getUILibraryChoice(flags.uiLibrary, frontendList, astroIntegration)) : "none";
|
|
5867
6414
|
const shadcnOptions = uiLibrary === "shadcn-ui" ? shouldAskConfigPromptKey("typescript", "shadcnOptions", configScope, typeScriptSections) ? promptValue(await getShadcnOptions({
|
|
5868
6415
|
shadcnBase: flags.shadcnBase,
|
|
@@ -5873,10 +6420,16 @@ async function gatherMultiEcosystemConfig(flags, projectName, projectDir, relati
|
|
|
5873
6420
|
shadcnFont: flags.shadcnFont,
|
|
5874
6421
|
shadcnRadius: flags.shadcnRadius
|
|
5875
6422
|
})) : getDefaultPromptValue("shadcnOptions") : void 0;
|
|
5876
|
-
const cssFramework = hasWebStyling$1(frontendList) ? await scopedPromptValue("typescript", "cssFramework", configScope, typeScriptSections, () => getCSSFrameworkChoice(flags.cssFramework, uiLibrary)) : "none";
|
|
6423
|
+
const cssFramework = hasWebStyling$1(frontendList) ? await scopedPromptValue("typescript", "cssFramework", configScope, typeScriptSections, () => getCSSFrameworkChoice(flags.cssFramework, uiLibrary, frontendList)) : "none";
|
|
5877
6424
|
const backendEcosystem = await selectBackendEcosystem();
|
|
5878
6425
|
const backendSections = configScope === "custom" ? promptValue(await getConfigSectionsChoice(backendEcosystem)) : [];
|
|
5879
6426
|
const stackPartSpecs = [`frontend:typescript:${frontend}`];
|
|
6427
|
+
if (nativeFrontend !== "none") {
|
|
6428
|
+
stackPartSpecs.push(`mobile:react-native:${nativeFrontend}`);
|
|
6429
|
+
stackPartSpecs.push("mobile.navigation:react-native:expo-router");
|
|
6430
|
+
if (nativeFrontend === "native-uniwind") stackPartSpecs.push("mobile.ui:react-native:uniwind");
|
|
6431
|
+
if (nativeFrontend === "native-unistyles") stackPartSpecs.push("mobile.ui:react-native:unistyles");
|
|
6432
|
+
}
|
|
5880
6433
|
const backendChoices = {};
|
|
5881
6434
|
let database = "none";
|
|
5882
6435
|
let dbSetup = "none";
|
|
@@ -5898,6 +6451,16 @@ async function gatherMultiEcosystemConfig(flags, projectName, projectDir, relati
|
|
|
5898
6451
|
const goCaching = goWebFramework === "none" ? "none" : await scopedPromptValue("go", "goCaching", configScope, backendSections, () => getGoCachingChoice(flags.goCaching));
|
|
5899
6452
|
const goConfig = goWebFramework === "none" ? "none" : await scopedPromptValue("go", "goConfig", configScope, backendSections, () => getGoConfigChoice(flags.goConfig));
|
|
5900
6453
|
const goObservability = goWebFramework === "none" ? "none" : await scopedPromptValue("go", "goObservability", configScope, backendSections, () => getGoObservabilityChoice(flags.goObservability));
|
|
6454
|
+
const goValidation = goWebFramework === "none" ? "none" : await scopedPromptValue("go", "goValidation", configScope, backendSections, () => getGoValidationChoice(flags.goValidation));
|
|
6455
|
+
const goQuality = goWebFramework === "none" ? "none" : await scopedPromptValue("go", "goQuality", configScope, backendSections, () => getGoQualityChoice(flags.goQuality));
|
|
6456
|
+
const goMigrations = goWebFramework === "none" || ![
|
|
6457
|
+
"sqlite",
|
|
6458
|
+
"postgres",
|
|
6459
|
+
"mysql"
|
|
6460
|
+
].includes(database) ? "none" : await scopedPromptValue("go", "goMigrations", configScope, backendSections, () => getGoMigrationsChoice(flags.goMigrations));
|
|
6461
|
+
const goTemplating = goWebFramework === "none" ? "none" : await scopedPromptValue("go", "goTemplating", configScope, backendSections, () => getGoTemplatingChoice(flags.goTemplating));
|
|
6462
|
+
const goProtoTooling = goWebFramework === "none" ? "none" : await scopedPromptValue("go", "goProtoTooling", configScope, backendSections, () => getGoProtoToolingChoice(flags.goProtoTooling));
|
|
6463
|
+
const goDI = goWebFramework === "none" ? "none" : await scopedPromptValue("go", "goDI", configScope, backendSections, () => getGoDIChoice(flags.goDI));
|
|
5901
6464
|
Object.assign(backendChoices, {
|
|
5902
6465
|
goWebFramework,
|
|
5903
6466
|
goOrm,
|
|
@@ -5910,7 +6473,13 @@ async function gatherMultiEcosystemConfig(flags, projectName, projectDir, relati
|
|
|
5910
6473
|
goMessageQueue,
|
|
5911
6474
|
goCaching,
|
|
5912
6475
|
goConfig,
|
|
5913
|
-
goObservability
|
|
6476
|
+
goObservability,
|
|
6477
|
+
goValidation,
|
|
6478
|
+
goQuality,
|
|
6479
|
+
goMigrations,
|
|
6480
|
+
goTemplating,
|
|
6481
|
+
goProtoTooling,
|
|
6482
|
+
goDI
|
|
5914
6483
|
});
|
|
5915
6484
|
if (goWebFramework !== "none") stackPartSpecs.push(`backend:go:${goWebFramework}`);
|
|
5916
6485
|
if (goOrm !== "none") stackPartSpecs.push(`backend.orm:go:${goOrm}`);
|
|
@@ -5922,6 +6491,12 @@ async function gatherMultiEcosystemConfig(flags, projectName, projectDir, relati
|
|
|
5922
6491
|
if (goCaching !== "none") stackPartSpecs.push(`backend.caching:go:${goCaching}`);
|
|
5923
6492
|
if (goConfig !== "none") stackPartSpecs.push(`backend.config:go:${goConfig}`);
|
|
5924
6493
|
if (goObservability !== "none") stackPartSpecs.push(`backend.observability:go:${goObservability}`);
|
|
6494
|
+
if (goValidation !== "none") stackPartSpecs.push(`backend.validation:go:${goValidation}`);
|
|
6495
|
+
if (goQuality !== "none") stackPartSpecs.push(`backend.codeQuality:go:${goQuality}`);
|
|
6496
|
+
if (goMigrations !== "none") stackPartSpecs.push(`backend.migrations:go:${goMigrations}`);
|
|
6497
|
+
if (goTemplating !== "none") stackPartSpecs.push(`backend.templating:go:${goTemplating}`);
|
|
6498
|
+
if (goProtoTooling !== "none") stackPartSpecs.push(`backend.buildTool:go:${goProtoTooling}`);
|
|
6499
|
+
if (goDI !== "none") stackPartSpecs.push(`backend.libraries:go:${goDI}`);
|
|
5925
6500
|
}
|
|
5926
6501
|
if (backendEcosystem === "rust") {
|
|
5927
6502
|
const rustWebFramework = promptValue(await getRustWebFrameworkChoice(flags.rustWebFramework));
|
|
@@ -6108,6 +6683,11 @@ async function gatherMultiEcosystemConfig(flags, projectName, projectDir, relati
|
|
|
6108
6683
|
const elixirObservability = elixirWebFramework === "none" ? "none" : await scopedPromptValue("elixir", "elixirObservability", configScope, backendSections, () => getElixirObservabilityChoice(flags.elixirObservability));
|
|
6109
6684
|
const elixirTesting = elixirWebFramework === "none" ? "none" : await scopedPromptValue("elixir", "elixirTesting", configScope, backendSections, () => getElixirTestingChoice(flags.elixirTesting));
|
|
6110
6685
|
const elixirQuality = elixirWebFramework === "none" ? "none" : await scopedPromptValue("elixir", "elixirQuality", configScope, backendSections, () => getElixirQualityChoice(flags.elixirQuality));
|
|
6686
|
+
const elixirI18n = elixirWebFramework === "none" ? "none" : await scopedPromptValue("elixir", "elixirI18n", configScope, backendSections, () => getElixirI18nChoice(flags.elixirI18n));
|
|
6687
|
+
const elixirHttpServer = elixirWebFramework === "none" ? "none" : await scopedPromptValue("elixir", "elixirHttpServer", configScope, backendSections, () => getElixirHttpServerChoice(flags.elixirHttpServer));
|
|
6688
|
+
const elixirApplicationFramework = await scopedPromptValue("elixir", "elixirApplicationFramework", configScope, backendSections, () => getElixirApplicationFrameworkChoice(flags.elixirApplicationFramework));
|
|
6689
|
+
const elixirDocumentation = await scopedPromptValue("elixir", "elixirDocumentation", configScope, backendSections, () => getElixirDocumentationChoice(flags.elixirDocumentation));
|
|
6690
|
+
const elixirClustering = elixirWebFramework === "none" ? "none" : await scopedPromptValue("elixir", "elixirClustering", configScope, backendSections, () => getElixirClusteringChoice(flags.elixirClustering));
|
|
6111
6691
|
const elixirDeploy = elixirWebFramework === "none" ? "none" : await scopedPromptValue("elixir", "elixirDeploy", configScope, backendSections, () => getElixirDeployChoice(flags.elixirDeploy));
|
|
6112
6692
|
const elixirLibraries = elixirWebFramework === "none" ? [] : await scopedPromptValue("elixir", "elixirLibraries", configScope, backendSections, () => getElixirLibrariesChoice(flags.elixirLibraries));
|
|
6113
6693
|
Object.assign(backendChoices, {
|
|
@@ -6125,6 +6705,11 @@ async function gatherMultiEcosystemConfig(flags, projectName, projectDir, relati
|
|
|
6125
6705
|
elixirObservability,
|
|
6126
6706
|
elixirTesting,
|
|
6127
6707
|
elixirQuality,
|
|
6708
|
+
elixirI18n,
|
|
6709
|
+
elixirHttpServer,
|
|
6710
|
+
elixirApplicationFramework,
|
|
6711
|
+
elixirDocumentation,
|
|
6712
|
+
elixirClustering,
|
|
6128
6713
|
elixirDeploy,
|
|
6129
6714
|
elixirLibraries
|
|
6130
6715
|
});
|
|
@@ -6138,13 +6723,19 @@ async function gatherMultiEcosystemConfig(flags, projectName, projectDir, relati
|
|
|
6138
6723
|
if (elixirCaching !== "none") stackPartSpecs.push(`backend.caching:elixir:${elixirCaching}`);
|
|
6139
6724
|
if (elixirObservability !== "none") stackPartSpecs.push(`backend.observability:elixir:${elixirObservability}`);
|
|
6140
6725
|
if (elixirTesting !== "none") stackPartSpecs.push(`backend.testing:elixir:${elixirTesting}`);
|
|
6726
|
+
if (elixirI18n !== "none") stackPartSpecs.push(`backend.i18n:elixir:${elixirI18n}`);
|
|
6727
|
+
if (elixirHttpServer !== "none") stackPartSpecs.push(`backend.runtime:elixir:${elixirHttpServer}`);
|
|
6728
|
+
if (elixirApplicationFramework !== "none") stackPartSpecs.push(`backend.libraries:elixir:${elixirApplicationFramework}`);
|
|
6729
|
+
if (elixirDocumentation !== "none") stackPartSpecs.push(`backend.documentation:elixir:${elixirDocumentation}`);
|
|
6730
|
+
if (elixirClustering !== "none") stackPartSpecs.push(`backend.config:elixir:${elixirClustering}`);
|
|
6141
6731
|
if (elixirDeploy !== "none") stackPartSpecs.push(`backend.deploy:elixir:${elixirDeploy}`);
|
|
6142
6732
|
for (const library of elixirLibraries) if (library !== "none") stackPartSpecs.push(`backend.libraries:elixir:${library}`);
|
|
6143
6733
|
}
|
|
6144
6734
|
if (database !== "none") stackPartSpecs.push(`database:universal:${database}`);
|
|
6145
6735
|
const stackParts = (0, types_exports.parseStackPartSpecs)(stackPartSpecs, "selected");
|
|
6146
6736
|
const graphPartial = (0, types_exports.stackPartsToLegacyProjectConfigPartial)(stackParts);
|
|
6147
|
-
const
|
|
6737
|
+
const appPlatforms = await scopedPromptValue("typescript", "appPlatforms", configScope, typeScriptSections, () => getAppPlatformsChoice(flags.addons, frontendList));
|
|
6738
|
+
const addons = await scopedPromptValue("typescript", "addons", configScope, typeScriptSections, () => getAddonsChoice(flags.addons, frontendList, "none", "none", "bun", "none"));
|
|
6148
6739
|
const webDeploy = await scopedPromptValue("typescript", "webDeploy", configScope, typeScriptSections, () => getDeploymentChoice(flags.webDeploy, "bun", "none", frontendList));
|
|
6149
6740
|
const serverDeploy = shouldAskConfigPromptKey("typescript", "serverDeploy", configScope, typeScriptSections) ? await selectServerDeployment(flags.serverDeploy) : getDefaultPromptValue("serverDeploy");
|
|
6150
6741
|
const aiDocs = promptValue(await getAiDocsChoice(flags.aiDocs));
|
|
@@ -6160,7 +6751,7 @@ async function gatherMultiEcosystemConfig(flags, projectName, projectDir, relati
|
|
|
6160
6751
|
projectDir,
|
|
6161
6752
|
relativePath,
|
|
6162
6753
|
ecosystem: "typescript",
|
|
6163
|
-
frontend: frontendList,
|
|
6754
|
+
frontend: nativeFrontend === "none" ? frontendList : [...frontendList, nativeFrontend],
|
|
6164
6755
|
backend: "none",
|
|
6165
6756
|
runtime: "none",
|
|
6166
6757
|
database,
|
|
@@ -6171,7 +6762,7 @@ async function gatherMultiEcosystemConfig(flags, projectName, projectDir, relati
|
|
|
6171
6762
|
uiLibrary,
|
|
6172
6763
|
...shadcnOptions,
|
|
6173
6764
|
cssFramework,
|
|
6174
|
-
addons,
|
|
6765
|
+
addons: Array.from(new Set([...appPlatforms, ...addons])),
|
|
6175
6766
|
examples: [],
|
|
6176
6767
|
dbSetup,
|
|
6177
6768
|
webDeploy,
|
|
@@ -6397,53 +6988,17 @@ function resolveORMPrompt(context) {
|
|
|
6397
6988
|
}
|
|
6398
6989
|
async function getORMChoice(orm, hasDatabase, database, backend, runtime) {
|
|
6399
6990
|
const resolution = resolveORMPrompt({
|
|
6400
|
-
orm,
|
|
6401
|
-
hasDatabase,
|
|
6402
|
-
database,
|
|
6403
|
-
backend,
|
|
6404
|
-
runtime
|
|
6405
|
-
});
|
|
6406
|
-
if (!resolution.shouldPrompt) return resolution.autoValue ?? "none";
|
|
6407
|
-
const response = await navigableSelect({
|
|
6408
|
-
message: "Select ORM",
|
|
6409
|
-
options: resolution.options,
|
|
6410
|
-
initialValue: resolution.initialValue
|
|
6411
|
-
});
|
|
6412
|
-
if (isCancel$1(response)) return exitCancelled("Operation cancelled");
|
|
6413
|
-
return response;
|
|
6414
|
-
}
|
|
6415
|
-
|
|
6416
|
-
//#endregion
|
|
6417
|
-
//#region src/prompts/workspace-shape.ts
|
|
6418
|
-
const SINGLE_APP_WEB_FRONTENDS = new Set(["next", "tanstack-start"]);
|
|
6419
|
-
/**
|
|
6420
|
-
* The flat single-app layout only makes sense for a "thin self" app: backend
|
|
6421
|
-
* `self` with exactly one Next.js or TanStack Start web frontend. For anything
|
|
6422
|
-
* else we never prompt and resolve to `monorepo` (the compatibility engine and
|
|
6423
|
-
* generator also normalize non-qualifying stacks back to monorepo).
|
|
6424
|
-
*/
|
|
6425
|
-
function stackCanUseSingleApp(backend, frontend) {
|
|
6426
|
-
if (backend !== "self") return false;
|
|
6427
|
-
const webFrontends = frontend.filter((f) => f && f !== "none");
|
|
6428
|
-
if (webFrontends.length !== 1) return false;
|
|
6429
|
-
return SINGLE_APP_WEB_FRONTENDS.has(webFrontends[0]);
|
|
6430
|
-
}
|
|
6431
|
-
async function getWorkspaceShapeChoice(workspaceShape, backend, frontend) {
|
|
6432
|
-
if (!stackCanUseSingleApp(backend, frontend ?? [])) return "monorepo";
|
|
6433
|
-
if (workspaceShape !== void 0) return workspaceShape;
|
|
6434
|
-
if (!canPromptInteractively()) return "monorepo";
|
|
6991
|
+
orm,
|
|
6992
|
+
hasDatabase,
|
|
6993
|
+
database,
|
|
6994
|
+
backend,
|
|
6995
|
+
runtime
|
|
6996
|
+
});
|
|
6997
|
+
if (!resolution.shouldPrompt) return resolution.autoValue ?? "none";
|
|
6435
6998
|
const response = await navigableSelect({
|
|
6436
|
-
message: "
|
|
6437
|
-
options:
|
|
6438
|
-
|
|
6439
|
-
label: "Monorepo",
|
|
6440
|
-
hint: "apps/* + packages/* workspaces (recommended)"
|
|
6441
|
-
}, {
|
|
6442
|
-
value: "single-app",
|
|
6443
|
-
label: "Single app",
|
|
6444
|
-
hint: "Flat app at the repo root (no workspaces)"
|
|
6445
|
-
}],
|
|
6446
|
-
initialValue: "monorepo"
|
|
6999
|
+
message: "Select ORM",
|
|
7000
|
+
options: resolution.options,
|
|
7001
|
+
initialValue: resolution.initialValue
|
|
6447
7002
|
});
|
|
6448
7003
|
if (isCancel$1(response)) return exitCancelled("Operation cancelled");
|
|
6449
7004
|
return response;
|
|
@@ -6521,6 +7076,14 @@ function resolvePaymentsPrompt(context = {}) {
|
|
|
6521
7076
|
label: "None",
|
|
6522
7077
|
hint: "No payments integration"
|
|
6523
7078
|
});
|
|
7079
|
+
if (context.backend !== "convex") {
|
|
7080
|
+
const insertAt = options.findIndex((option) => option.value === "dodo");
|
|
7081
|
+
options.splice(insertAt, 0, {
|
|
7082
|
+
value: "paypal",
|
|
7083
|
+
label: "PayPal",
|
|
7084
|
+
hint: "PayPal JavaScript SDK buttons with server-side Orders API helpers."
|
|
7085
|
+
});
|
|
7086
|
+
}
|
|
6524
7087
|
if (isRevenueCatCompatible) options.push({
|
|
6525
7088
|
value: "revenuecat",
|
|
6526
7089
|
label: "RevenueCat",
|
|
@@ -6611,6 +7174,11 @@ const REALTIME_PROMPT_OPTIONS = [
|
|
|
6611
7174
|
label: "Socket.IO",
|
|
6612
7175
|
hint: "Real-time bidirectional communication with fallbacks"
|
|
6613
7176
|
},
|
|
7177
|
+
{
|
|
7178
|
+
value: "ws",
|
|
7179
|
+
label: "ws",
|
|
7180
|
+
hint: "Lightweight standards-based WebSocket server and client"
|
|
7181
|
+
},
|
|
6614
7182
|
{
|
|
6615
7183
|
value: "partykit",
|
|
6616
7184
|
label: "PartyKit",
|
|
@@ -6649,15 +7217,16 @@ function resolveRealtimePrompt(context = {}) {
|
|
|
6649
7217
|
options: [],
|
|
6650
7218
|
autoValue: "none"
|
|
6651
7219
|
};
|
|
7220
|
+
const options = context.backend === "express" ? REALTIME_PROMPT_OPTIONS : REALTIME_PROMPT_OPTIONS.filter((option) => option.value !== "ws");
|
|
6652
7221
|
return context.realtime !== void 0 ? {
|
|
6653
7222
|
shouldPrompt: false,
|
|
6654
7223
|
mode: "single",
|
|
6655
|
-
options
|
|
7224
|
+
options,
|
|
6656
7225
|
autoValue: context.realtime
|
|
6657
7226
|
} : {
|
|
6658
7227
|
shouldPrompt: true,
|
|
6659
7228
|
mode: "single",
|
|
6660
|
-
options
|
|
7229
|
+
options,
|
|
6661
7230
|
initialValue: "none"
|
|
6662
7231
|
};
|
|
6663
7232
|
}
|
|
@@ -6845,6 +7414,11 @@ const TESTING_PROMPT_OPTIONS = [
|
|
|
6845
7414
|
label: "Jest",
|
|
6846
7415
|
hint: "Classic testing framework with wide ecosystem"
|
|
6847
7416
|
},
|
|
7417
|
+
{
|
|
7418
|
+
value: "mocha",
|
|
7419
|
+
label: "Mocha",
|
|
7420
|
+
hint: "Flexible Node.js test framework with TypeScript support via tsx"
|
|
7421
|
+
},
|
|
6848
7422
|
{
|
|
6849
7423
|
value: "cypress",
|
|
6850
7424
|
label: "Cypress",
|
|
@@ -6945,8 +7519,11 @@ const PROMPT_RESOLVER_REGISTRY = {
|
|
|
6945
7519
|
},
|
|
6946
7520
|
ai: {
|
|
6947
7521
|
schemaValues: types_exports.AI_VALUES,
|
|
6948
|
-
resolve: ({ value } = {}) => resolveAIPrompt(
|
|
6949
|
-
|
|
7522
|
+
resolve: ({ value, backend } = {}) => resolveAIPrompt({
|
|
7523
|
+
ai: value,
|
|
7524
|
+
backend
|
|
7525
|
+
}),
|
|
7526
|
+
coverageContexts: [{ backend: "hono" }, { backend: "none" }]
|
|
6950
7527
|
},
|
|
6951
7528
|
animation: {
|
|
6952
7529
|
schemaValues: types_exports.ANIMATION_VALUES,
|
|
@@ -6964,15 +7541,23 @@ const PROMPT_RESOLVER_REGISTRY = {
|
|
|
6964
7541
|
auth: {
|
|
6965
7542
|
schemaValues: types_exports.AUTH_VALUES,
|
|
6966
7543
|
resolve: resolveAuthPrompt,
|
|
6967
|
-
coverageContexts: [
|
|
6968
|
-
|
|
6969
|
-
|
|
6970
|
-
|
|
6971
|
-
|
|
6972
|
-
|
|
6973
|
-
|
|
6974
|
-
|
|
6975
|
-
|
|
7544
|
+
coverageContexts: [
|
|
7545
|
+
{
|
|
7546
|
+
ecosystem: "typescript",
|
|
7547
|
+
backend: "self",
|
|
7548
|
+
frontend: ["next"]
|
|
7549
|
+
},
|
|
7550
|
+
{
|
|
7551
|
+
ecosystem: "typescript",
|
|
7552
|
+
backend: "express",
|
|
7553
|
+
frontend: ["react-vite"]
|
|
7554
|
+
},
|
|
7555
|
+
{
|
|
7556
|
+
ecosystem: "go",
|
|
7557
|
+
backend: "none",
|
|
7558
|
+
frontend: []
|
|
7559
|
+
}
|
|
7560
|
+
]
|
|
6976
7561
|
},
|
|
6977
7562
|
caching: {
|
|
6978
7563
|
schemaValues: types_exports.CACHING_VALUES,
|
|
@@ -6987,12 +7572,32 @@ const PROMPT_RESOLVER_REGISTRY = {
|
|
|
6987
7572
|
cms: {
|
|
6988
7573
|
schemaValues: types_exports.CMS_VALUES,
|
|
6989
7574
|
resolve: resolveCMSPrompt,
|
|
6990
|
-
coverageContexts: [
|
|
7575
|
+
coverageContexts: [
|
|
7576
|
+
{ backend: "hono" },
|
|
7577
|
+
{
|
|
7578
|
+
backend: "none",
|
|
7579
|
+
frontends: ["vue"]
|
|
7580
|
+
},
|
|
7581
|
+
{
|
|
7582
|
+
backend: "none",
|
|
7583
|
+
frontends: []
|
|
7584
|
+
}
|
|
7585
|
+
]
|
|
6991
7586
|
},
|
|
6992
7587
|
cssFramework: {
|
|
6993
7588
|
schemaValues: types_exports.CSS_FRAMEWORK_VALUES,
|
|
6994
7589
|
resolve: resolveCSSFrameworkPrompt,
|
|
6995
|
-
coverageContexts: [
|
|
7590
|
+
coverageContexts: [
|
|
7591
|
+
{ frontends: ["react-vite"] },
|
|
7592
|
+
{
|
|
7593
|
+
uiLibrary: "none",
|
|
7594
|
+
frontends: ["vue"]
|
|
7595
|
+
},
|
|
7596
|
+
{
|
|
7597
|
+
uiLibrary: "radix-ui",
|
|
7598
|
+
frontends: ["react-vite"]
|
|
7599
|
+
}
|
|
7600
|
+
]
|
|
6996
7601
|
},
|
|
6997
7602
|
database: {
|
|
6998
7603
|
schemaValues: types_exports.DATABASE_VALUES,
|
|
@@ -7077,7 +7682,11 @@ const PROMPT_RESOLVER_REGISTRY = {
|
|
|
7077
7682
|
realtime: {
|
|
7078
7683
|
schemaValues: types_exports.REALTIME_VALUES,
|
|
7079
7684
|
resolve: resolveRealtimePrompt,
|
|
7080
|
-
coverageContexts: [
|
|
7685
|
+
coverageContexts: [
|
|
7686
|
+
{ backend: "express" },
|
|
7687
|
+
{ backend: "hono" },
|
|
7688
|
+
{ backend: "none" }
|
|
7689
|
+
]
|
|
7081
7690
|
},
|
|
7082
7691
|
runtime: {
|
|
7083
7692
|
schemaValues: types_exports.RUNTIME_VALUES,
|
|
@@ -7269,6 +7878,36 @@ const PROMPT_RESOLVER_REGISTRY = {
|
|
|
7269
7878
|
resolve: ({ value } = {}) => resolveGoAuthPrompt(value),
|
|
7270
7879
|
coverageContexts: [{}]
|
|
7271
7880
|
},
|
|
7881
|
+
goValidation: {
|
|
7882
|
+
schemaValues: types_exports.GO_VALIDATION_VALUES,
|
|
7883
|
+
resolve: ({ value } = {}) => resolveGoValidationPrompt(value),
|
|
7884
|
+
coverageContexts: [{}]
|
|
7885
|
+
},
|
|
7886
|
+
goQuality: {
|
|
7887
|
+
schemaValues: types_exports.GO_QUALITY_VALUES,
|
|
7888
|
+
resolve: ({ value } = {}) => resolveGoQualityPrompt(value),
|
|
7889
|
+
coverageContexts: [{}]
|
|
7890
|
+
},
|
|
7891
|
+
goMigrations: {
|
|
7892
|
+
schemaValues: types_exports.GO_MIGRATIONS_VALUES,
|
|
7893
|
+
resolve: ({ value } = {}) => resolveGoMigrationsPrompt(value),
|
|
7894
|
+
coverageContexts: [{}]
|
|
7895
|
+
},
|
|
7896
|
+
goTemplating: {
|
|
7897
|
+
schemaValues: types_exports.GO_TEMPLATING_VALUES,
|
|
7898
|
+
resolve: ({ value } = {}) => resolveGoTemplatingPrompt(value),
|
|
7899
|
+
coverageContexts: [{}]
|
|
7900
|
+
},
|
|
7901
|
+
goProtoTooling: {
|
|
7902
|
+
schemaValues: types_exports.GO_PROTO_TOOLING_VALUES,
|
|
7903
|
+
resolve: ({ value } = {}) => resolveGoProtoToolingPrompt(value),
|
|
7904
|
+
coverageContexts: [{}]
|
|
7905
|
+
},
|
|
7906
|
+
goDI: {
|
|
7907
|
+
schemaValues: types_exports.GO_DI_VALUES,
|
|
7908
|
+
resolve: ({ value } = {}) => resolveGoDIPrompt(value),
|
|
7909
|
+
coverageContexts: [{}]
|
|
7910
|
+
},
|
|
7272
7911
|
javaWebFramework: {
|
|
7273
7912
|
schemaValues: types_exports.JAVA_WEB_FRAMEWORK_VALUES,
|
|
7274
7913
|
resolve: ({ value } = {}) => resolveJavaWebFrameworkPrompt(value),
|
|
@@ -7419,6 +8058,31 @@ const PROMPT_RESOLVER_REGISTRY = {
|
|
|
7419
8058
|
resolve: ({ value } = {}) => resolveElixirQualityPrompt(value),
|
|
7420
8059
|
coverageContexts: [{}]
|
|
7421
8060
|
},
|
|
8061
|
+
elixirI18n: {
|
|
8062
|
+
schemaValues: types_exports.ELIXIR_I18N_VALUES,
|
|
8063
|
+
resolve: ({ value } = {}) => resolveElixirI18nPrompt(value),
|
|
8064
|
+
coverageContexts: [{}]
|
|
8065
|
+
},
|
|
8066
|
+
elixirHttpServer: {
|
|
8067
|
+
schemaValues: types_exports.ELIXIR_HTTP_SERVER_VALUES,
|
|
8068
|
+
resolve: ({ value } = {}) => resolveElixirHttpServerPrompt(value),
|
|
8069
|
+
coverageContexts: [{}]
|
|
8070
|
+
},
|
|
8071
|
+
elixirApplicationFramework: {
|
|
8072
|
+
schemaValues: types_exports.ELIXIR_APPLICATION_FRAMEWORK_VALUES,
|
|
8073
|
+
resolve: ({ value } = {}) => resolveElixirApplicationFrameworkPrompt(value),
|
|
8074
|
+
coverageContexts: [{}]
|
|
8075
|
+
},
|
|
8076
|
+
elixirDocumentation: {
|
|
8077
|
+
schemaValues: types_exports.ELIXIR_DOCUMENTATION_VALUES,
|
|
8078
|
+
resolve: ({ value } = {}) => resolveElixirDocumentationPrompt(value),
|
|
8079
|
+
coverageContexts: [{}]
|
|
8080
|
+
},
|
|
8081
|
+
elixirClustering: {
|
|
8082
|
+
schemaValues: types_exports.ELIXIR_CLUSTERING_VALUES,
|
|
8083
|
+
resolve: ({ value } = {}) => resolveElixirClusteringPrompt(value),
|
|
8084
|
+
coverageContexts: [{}]
|
|
8085
|
+
},
|
|
7422
8086
|
elixirDeploy: {
|
|
7423
8087
|
schemaValues: types_exports.ELIXIR_DEPLOY_VALUES,
|
|
7424
8088
|
resolve: ({ value } = {}) => resolveElixirDeployPrompt(value),
|
|
@@ -7521,6 +8185,66 @@ async function getSearchChoice(search, backend, ecosystem) {
|
|
|
7521
8185
|
return response;
|
|
7522
8186
|
}
|
|
7523
8187
|
|
|
8188
|
+
//#endregion
|
|
8189
|
+
//#region src/prompts/server-deploy.ts
|
|
8190
|
+
async function getServerDeploymentChoice(deployment, runtime, backend, _webDeploy) {
|
|
8191
|
+
if (deployment !== void 0) return deployment;
|
|
8192
|
+
if (backend === "none" || backend === "convex") return "none";
|
|
8193
|
+
if (backend !== "hono") return "none";
|
|
8194
|
+
if (runtime === "workers") return "cloudflare";
|
|
8195
|
+
const response = await navigableSelect({
|
|
8196
|
+
message: "Select server deployment",
|
|
8197
|
+
options: getServerDeploymentOptions(runtime),
|
|
8198
|
+
initialValue: DEFAULT_CONFIG.serverDeploy
|
|
8199
|
+
});
|
|
8200
|
+
if (isCancel$1(response)) return exitCancelled("Operation cancelled");
|
|
8201
|
+
return response;
|
|
8202
|
+
}
|
|
8203
|
+
function getServerDeploymentOptions(runtime) {
|
|
8204
|
+
return [
|
|
8205
|
+
{
|
|
8206
|
+
value: "none",
|
|
8207
|
+
label: "None",
|
|
8208
|
+
hint: "Skip server deployment setup"
|
|
8209
|
+
},
|
|
8210
|
+
{
|
|
8211
|
+
value: "railway",
|
|
8212
|
+
label: "Railway",
|
|
8213
|
+
hint: "Deploy with Railway cloud development platform"
|
|
8214
|
+
},
|
|
8215
|
+
{
|
|
8216
|
+
value: "fly",
|
|
8217
|
+
label: "Fly.io",
|
|
8218
|
+
hint: "Deploy globally with Fly.io edge platform"
|
|
8219
|
+
},
|
|
8220
|
+
{
|
|
8221
|
+
value: "render",
|
|
8222
|
+
label: "Render",
|
|
8223
|
+
hint: "Deploy with Render's Blueprint and Docker builds"
|
|
8224
|
+
},
|
|
8225
|
+
...runtime === "node" ? [{
|
|
8226
|
+
value: "netlify",
|
|
8227
|
+
label: "Netlify",
|
|
8228
|
+
hint: "Deploy Hono APIs with Netlify Functions"
|
|
8229
|
+
}] : [],
|
|
8230
|
+
{
|
|
8231
|
+
value: "docker",
|
|
8232
|
+
label: "Docker",
|
|
8233
|
+
hint: "Container-based deployment with Dockerfile"
|
|
8234
|
+
},
|
|
8235
|
+
{
|
|
8236
|
+
value: "sst",
|
|
8237
|
+
label: "SST",
|
|
8238
|
+
hint: "Deploy to AWS with SST (Serverless Stack)"
|
|
8239
|
+
},
|
|
8240
|
+
{
|
|
8241
|
+
value: "vercel",
|
|
8242
|
+
label: "Vercel",
|
|
8243
|
+
hint: "Deploy to Vercel's edge network with zero config"
|
|
8244
|
+
}
|
|
8245
|
+
];
|
|
8246
|
+
}
|
|
8247
|
+
|
|
7524
8248
|
//#endregion
|
|
7525
8249
|
//#region src/prompts/vector-db.ts
|
|
7526
8250
|
const VECTOR_DB_PROMPT_OPTIONS = [
|
|
@@ -7593,64 +8317,40 @@ async function getVectorDbChoice(vectorDb, backend, ecosystem) {
|
|
|
7593
8317
|
}
|
|
7594
8318
|
|
|
7595
8319
|
//#endregion
|
|
7596
|
-
//#region src/prompts/
|
|
7597
|
-
|
|
7598
|
-
|
|
7599
|
-
|
|
7600
|
-
|
|
7601
|
-
|
|
8320
|
+
//#region src/prompts/workspace-shape.ts
|
|
8321
|
+
const SINGLE_APP_WEB_FRONTENDS = new Set(["next", "tanstack-start"]);
|
|
8322
|
+
/**
|
|
8323
|
+
* The flat single-app layout only makes sense for a "thin self" app: backend
|
|
8324
|
+
* `self` with exactly one Next.js or TanStack Start web frontend. For anything
|
|
8325
|
+
* else we never prompt and resolve to `monorepo` (the compatibility engine and
|
|
8326
|
+
* generator also normalize non-qualifying stacks back to monorepo).
|
|
8327
|
+
*/
|
|
8328
|
+
function stackCanUseSingleApp(backend, frontend) {
|
|
8329
|
+
if (backend !== "self") return false;
|
|
8330
|
+
const webFrontends = frontend.filter((f) => f && f !== "none");
|
|
8331
|
+
if (webFrontends.length !== 1) return false;
|
|
8332
|
+
return SINGLE_APP_WEB_FRONTENDS.has(webFrontends[0]);
|
|
8333
|
+
}
|
|
8334
|
+
async function getWorkspaceShapeChoice(workspaceShape, backend, frontend) {
|
|
8335
|
+
if (!stackCanUseSingleApp(backend, frontend ?? [])) return "monorepo";
|
|
8336
|
+
if (workspaceShape !== void 0) return workspaceShape;
|
|
8337
|
+
if (!canPromptInteractively()) return "monorepo";
|
|
7602
8338
|
const response = await navigableSelect({
|
|
7603
|
-
message: "
|
|
7604
|
-
options:
|
|
7605
|
-
|
|
8339
|
+
message: "Choose workspace layout",
|
|
8340
|
+
options: [{
|
|
8341
|
+
value: "monorepo",
|
|
8342
|
+
label: "Monorepo",
|
|
8343
|
+
hint: "apps/* + packages/* workspaces (recommended)"
|
|
8344
|
+
}, {
|
|
8345
|
+
value: "single-app",
|
|
8346
|
+
label: "Single app",
|
|
8347
|
+
hint: "Flat app at the repo root (no workspaces)"
|
|
8348
|
+
}],
|
|
8349
|
+
initialValue: "monorepo"
|
|
7606
8350
|
});
|
|
7607
8351
|
if (isCancel$1(response)) return exitCancelled("Operation cancelled");
|
|
7608
8352
|
return response;
|
|
7609
8353
|
}
|
|
7610
|
-
function getServerDeploymentOptions(runtime) {
|
|
7611
|
-
return [
|
|
7612
|
-
{
|
|
7613
|
-
value: "none",
|
|
7614
|
-
label: "None",
|
|
7615
|
-
hint: "Skip server deployment setup"
|
|
7616
|
-
},
|
|
7617
|
-
{
|
|
7618
|
-
value: "railway",
|
|
7619
|
-
label: "Railway",
|
|
7620
|
-
hint: "Deploy with Railway cloud development platform"
|
|
7621
|
-
},
|
|
7622
|
-
{
|
|
7623
|
-
value: "fly",
|
|
7624
|
-
label: "Fly.io",
|
|
7625
|
-
hint: "Deploy globally with Fly.io edge platform"
|
|
7626
|
-
},
|
|
7627
|
-
{
|
|
7628
|
-
value: "render",
|
|
7629
|
-
label: "Render",
|
|
7630
|
-
hint: "Deploy with Render's Blueprint and Docker builds"
|
|
7631
|
-
},
|
|
7632
|
-
...runtime === "node" ? [{
|
|
7633
|
-
value: "netlify",
|
|
7634
|
-
label: "Netlify",
|
|
7635
|
-
hint: "Deploy Hono APIs with Netlify Functions"
|
|
7636
|
-
}] : [],
|
|
7637
|
-
{
|
|
7638
|
-
value: "docker",
|
|
7639
|
-
label: "Docker",
|
|
7640
|
-
hint: "Container-based deployment with Dockerfile"
|
|
7641
|
-
},
|
|
7642
|
-
{
|
|
7643
|
-
value: "sst",
|
|
7644
|
-
label: "SST",
|
|
7645
|
-
hint: "Deploy to AWS with SST (Serverless Stack)"
|
|
7646
|
-
},
|
|
7647
|
-
{
|
|
7648
|
-
value: "vercel",
|
|
7649
|
-
label: "Vercel",
|
|
7650
|
-
hint: "Deploy to Vercel's edge network with zero config"
|
|
7651
|
-
}
|
|
7652
|
-
];
|
|
7653
|
-
}
|
|
7654
8354
|
|
|
7655
8355
|
//#endregion
|
|
7656
8356
|
//#region src/prompts/config-prompts.ts
|
|
@@ -7674,6 +8374,7 @@ const CONFIG_PROMPT_ENTRY_KEY_MAP = {
|
|
|
7674
8374
|
configSections: true,
|
|
7675
8375
|
frontend: true,
|
|
7676
8376
|
astroIntegration: true,
|
|
8377
|
+
appPlatforms: true,
|
|
7677
8378
|
uiLibrary: true,
|
|
7678
8379
|
shadcnOptions: true,
|
|
7679
8380
|
cssFramework: true,
|
|
@@ -7758,6 +8459,12 @@ const CONFIG_PROMPT_ENTRY_KEY_MAP = {
|
|
|
7758
8459
|
goCaching: true,
|
|
7759
8460
|
goConfig: true,
|
|
7760
8461
|
goObservability: true,
|
|
8462
|
+
goValidation: true,
|
|
8463
|
+
goQuality: true,
|
|
8464
|
+
goMigrations: true,
|
|
8465
|
+
goTemplating: true,
|
|
8466
|
+
goProtoTooling: true,
|
|
8467
|
+
goDI: true,
|
|
7761
8468
|
javaWebFramework: true,
|
|
7762
8469
|
javaLanguage: true,
|
|
7763
8470
|
javaBuildTool: true,
|
|
@@ -7792,6 +8499,11 @@ const CONFIG_PROMPT_ENTRY_KEY_MAP = {
|
|
|
7792
8499
|
elixirObservability: true,
|
|
7793
8500
|
elixirTesting: true,
|
|
7794
8501
|
elixirQuality: true,
|
|
8502
|
+
elixirI18n: true,
|
|
8503
|
+
elixirHttpServer: true,
|
|
8504
|
+
elixirApplicationFramework: true,
|
|
8505
|
+
elixirDocumentation: true,
|
|
8506
|
+
elixirClustering: true,
|
|
7795
8507
|
elixirDeploy: true,
|
|
7796
8508
|
elixirLibraries: true,
|
|
7797
8509
|
aiDocs: true,
|
|
@@ -7868,7 +8580,8 @@ function getPromptResolutionValue(key, results, flags) {
|
|
|
7868
8580
|
},
|
|
7869
8581
|
cssFramework: {
|
|
7870
8582
|
cssFramework: flags.cssFramework,
|
|
7871
|
-
uiLibrary: results.uiLibrary
|
|
8583
|
+
uiLibrary: results.uiLibrary,
|
|
8584
|
+
frontends
|
|
7872
8585
|
},
|
|
7873
8586
|
forms: {
|
|
7874
8587
|
forms: flags.forms,
|
|
@@ -7977,6 +8690,10 @@ async function gatherConfig(flags, projectName, projectDir, relativePath) {
|
|
|
7977
8690
|
if (results.frontend?.includes("astro")) return getAstroIntegrationChoice(flags.astroIntegration);
|
|
7978
8691
|
return Promise.resolve(void 0);
|
|
7979
8692
|
},
|
|
8693
|
+
appPlatforms: ({ results }) => {
|
|
8694
|
+
if (results.ecosystem !== "typescript") return Promise.resolve([]);
|
|
8695
|
+
return getAppPlatformsChoice(flags.addons, results.frontend);
|
|
8696
|
+
},
|
|
7980
8697
|
uiLibrary: ({ results }) => {
|
|
7981
8698
|
if (results.ecosystem !== "typescript") return Promise.resolve("none");
|
|
7982
8699
|
if (hasWebStyling$1(results.frontend)) return getUILibraryChoice(flags.uiLibrary, results.frontend, results.astroIntegration);
|
|
@@ -7996,7 +8713,7 @@ async function gatherConfig(flags, projectName, projectDir, relativePath) {
|
|
|
7996
8713
|
},
|
|
7997
8714
|
cssFramework: ({ results }) => {
|
|
7998
8715
|
if (results.ecosystem !== "typescript") return Promise.resolve("none");
|
|
7999
|
-
if (hasWebStyling$1(results.frontend)) return getCSSFrameworkChoice(flags.cssFramework, results.uiLibrary);
|
|
8716
|
+
if (hasWebStyling$1(results.frontend)) return getCSSFrameworkChoice(flags.cssFramework, results.uiLibrary, results.frontend);
|
|
8000
8717
|
return Promise.resolve("none");
|
|
8001
8718
|
},
|
|
8002
8719
|
backend: ({ results }) => {
|
|
@@ -8046,7 +8763,7 @@ async function gatherConfig(flags, projectName, projectDir, relativePath) {
|
|
|
8046
8763
|
const nonTypeScriptAddons = (flags.addons ?? []).filter((addon) => addon === "docker-compose" || addon === "devcontainer" || addon === "github-actions");
|
|
8047
8764
|
return Promise.resolve(nonTypeScriptAddons);
|
|
8048
8765
|
}
|
|
8049
|
-
return getAddonsChoice(flags.addons, results.frontend, results.auth, results.backend, results.runtime);
|
|
8766
|
+
return getAddonsChoice(flags.addons, results.frontend, results.auth, results.backend, results.runtime, results.api);
|
|
8050
8767
|
},
|
|
8051
8768
|
examples: ({ results }) => {
|
|
8052
8769
|
if (results.ecosystem !== "typescript") return Promise.resolve([]);
|
|
@@ -8067,7 +8784,7 @@ async function gatherConfig(flags, projectName, projectDir, relativePath) {
|
|
|
8067
8784
|
ai: ({ results }) => {
|
|
8068
8785
|
if (results.ecosystem !== "typescript") return Promise.resolve("none");
|
|
8069
8786
|
if (flags.ai === void 0 && results.examples?.includes("chat-sdk") && requiresChatSdkVercelAI(results.backend, results.frontend, results.runtime)) return Promise.resolve("vercel-ai");
|
|
8070
|
-
return getAIChoice(flags.ai);
|
|
8787
|
+
return getAIChoice(flags.ai, results.backend);
|
|
8071
8788
|
},
|
|
8072
8789
|
validation: ({ results }) => {
|
|
8073
8790
|
if (results.ecosystem !== "typescript") return Promise.resolve("none");
|
|
@@ -8120,7 +8837,7 @@ async function gatherConfig(flags, projectName, projectDir, relativePath) {
|
|
|
8120
8837
|
},
|
|
8121
8838
|
cms: ({ results }) => {
|
|
8122
8839
|
if (results.ecosystem !== "typescript") return Promise.resolve("none");
|
|
8123
|
-
return getCMSChoice(flags.cms, results.backend);
|
|
8840
|
+
return getCMSChoice(flags.cms, results.backend, results.frontend);
|
|
8124
8841
|
},
|
|
8125
8842
|
caching: ({ results }) => {
|
|
8126
8843
|
if (results.ecosystem === "react-native" || results.ecosystem === "elixir") return Promise.resolve("none");
|
|
@@ -8344,6 +9061,34 @@ async function gatherConfig(flags, projectName, projectDir, relativePath) {
|
|
|
8344
9061
|
if (results.ecosystem !== "go") return Promise.resolve("none");
|
|
8345
9062
|
return getGoObservabilityChoice(flags.goObservability);
|
|
8346
9063
|
},
|
|
9064
|
+
goValidation: ({ results }) => {
|
|
9065
|
+
if (results.ecosystem !== "go") return Promise.resolve("none");
|
|
9066
|
+
return getGoValidationChoice(flags.goValidation);
|
|
9067
|
+
},
|
|
9068
|
+
goQuality: ({ results }) => {
|
|
9069
|
+
if (results.ecosystem !== "go") return Promise.resolve("none");
|
|
9070
|
+
return getGoQualityChoice(flags.goQuality);
|
|
9071
|
+
},
|
|
9072
|
+
goMigrations: ({ results }) => {
|
|
9073
|
+
if (results.ecosystem !== "go" || !results.database || ![
|
|
9074
|
+
"sqlite",
|
|
9075
|
+
"postgres",
|
|
9076
|
+
"mysql"
|
|
9077
|
+
].includes(results.database)) return Promise.resolve("none");
|
|
9078
|
+
return getGoMigrationsChoice(flags.goMigrations);
|
|
9079
|
+
},
|
|
9080
|
+
goTemplating: ({ results }) => {
|
|
9081
|
+
if (results.ecosystem !== "go") return Promise.resolve("none");
|
|
9082
|
+
return getGoTemplatingChoice(flags.goTemplating);
|
|
9083
|
+
},
|
|
9084
|
+
goProtoTooling: ({ results }) => {
|
|
9085
|
+
if (results.ecosystem !== "go") return Promise.resolve("none");
|
|
9086
|
+
return getGoProtoToolingChoice(flags.goProtoTooling);
|
|
9087
|
+
},
|
|
9088
|
+
goDI: ({ results }) => {
|
|
9089
|
+
if (results.ecosystem !== "go") return Promise.resolve("none");
|
|
9090
|
+
return getGoDIChoice(flags.goDI);
|
|
9091
|
+
},
|
|
8347
9092
|
javaWebFramework: ({ results }) => {
|
|
8348
9093
|
if (results.ecosystem !== "java") return Promise.resolve("none");
|
|
8349
9094
|
return getJavaWebFrameworkChoice(flags.javaWebFramework);
|
|
@@ -8509,6 +9254,26 @@ async function gatherConfig(flags, projectName, projectDir, relativePath) {
|
|
|
8509
9254
|
if (results.ecosystem !== "elixir") return Promise.resolve("none");
|
|
8510
9255
|
return getElixirQualityChoice(flags.elixirQuality);
|
|
8511
9256
|
},
|
|
9257
|
+
elixirI18n: ({ results }) => {
|
|
9258
|
+
if (results.ecosystem !== "elixir") return Promise.resolve("none");
|
|
9259
|
+
return getElixirI18nChoice(flags.elixirI18n);
|
|
9260
|
+
},
|
|
9261
|
+
elixirHttpServer: ({ results }) => {
|
|
9262
|
+
if (results.ecosystem !== "elixir") return Promise.resolve("none");
|
|
9263
|
+
return getElixirHttpServerChoice(flags.elixirHttpServer);
|
|
9264
|
+
},
|
|
9265
|
+
elixirApplicationFramework: ({ results }) => {
|
|
9266
|
+
if (results.ecosystem !== "elixir") return Promise.resolve("none");
|
|
9267
|
+
return getElixirApplicationFrameworkChoice(flags.elixirApplicationFramework);
|
|
9268
|
+
},
|
|
9269
|
+
elixirDocumentation: ({ results }) => {
|
|
9270
|
+
if (results.ecosystem !== "elixir") return Promise.resolve("none");
|
|
9271
|
+
return getElixirDocumentationChoice(flags.elixirDocumentation);
|
|
9272
|
+
},
|
|
9273
|
+
elixirClustering: ({ results }) => {
|
|
9274
|
+
if (results.ecosystem !== "elixir") return Promise.resolve("none");
|
|
9275
|
+
return getElixirClusteringChoice(flags.elixirClustering);
|
|
9276
|
+
},
|
|
8512
9277
|
elixirDeploy: ({ results }) => {
|
|
8513
9278
|
if (results.ecosystem !== "elixir") return Promise.resolve("none");
|
|
8514
9279
|
return getElixirDeployChoice(flags.elixirDeploy);
|
|
@@ -8543,7 +9308,7 @@ async function gatherConfig(flags, projectName, projectDir, relativePath) {
|
|
|
8543
9308
|
payments: result.payments,
|
|
8544
9309
|
email: result.email,
|
|
8545
9310
|
effect: result.effect,
|
|
8546
|
-
addons: result.addons,
|
|
9311
|
+
addons: Array.from(new Set([...result.appPlatforms ?? [], ...result.addons])),
|
|
8547
9312
|
examples: result.examples,
|
|
8548
9313
|
git: result.git,
|
|
8549
9314
|
packageManager: result.packageManager,
|
|
@@ -8621,6 +9386,12 @@ async function gatherConfig(flags, projectName, projectDir, relativePath) {
|
|
|
8621
9386
|
goCaching: result.goCaching,
|
|
8622
9387
|
goConfig: result.goConfig,
|
|
8623
9388
|
goObservability: result.goObservability,
|
|
9389
|
+
goValidation: result.goValidation,
|
|
9390
|
+
goQuality: result.goQuality,
|
|
9391
|
+
goMigrations: result.goMigrations,
|
|
9392
|
+
goTemplating: result.goTemplating,
|
|
9393
|
+
goProtoTooling: result.goProtoTooling,
|
|
9394
|
+
goDI: result.goDI,
|
|
8624
9395
|
javaWebFramework: result.javaWebFramework,
|
|
8625
9396
|
javaLanguage: result.javaLanguage,
|
|
8626
9397
|
javaBuildTool: result.javaBuildTool,
|
|
@@ -8655,6 +9426,11 @@ async function gatherConfig(flags, projectName, projectDir, relativePath) {
|
|
|
8655
9426
|
elixirObservability: result.elixirObservability,
|
|
8656
9427
|
elixirTesting: result.elixirTesting,
|
|
8657
9428
|
elixirQuality: result.elixirQuality,
|
|
9429
|
+
elixirI18n: result.elixirI18n,
|
|
9430
|
+
elixirHttpServer: result.elixirHttpServer,
|
|
9431
|
+
elixirApplicationFramework: result.elixirApplicationFramework,
|
|
9432
|
+
elixirDocumentation: result.elixirDocumentation,
|
|
9433
|
+
elixirClustering: result.elixirClustering,
|
|
8658
9434
|
elixirDeploy: result.elixirDeploy,
|
|
8659
9435
|
elixirLibraries: result.elixirLibraries,
|
|
8660
9436
|
aiDocs: result.aiDocs
|
|
@@ -8905,6 +9681,11 @@ function displayConfig(config) {
|
|
|
8905
9681
|
if (config.elixirObservability && config.elixirObservability !== "none") configDisplay.push(`${pc.blue("Elixir Observability:")} ${String(config.elixirObservability)}`);
|
|
8906
9682
|
if (config.elixirTesting && config.elixirTesting !== "none") configDisplay.push(`${pc.blue("Elixir Testing:")} ${String(config.elixirTesting)}`);
|
|
8907
9683
|
if (config.elixirQuality && config.elixirQuality !== "none") configDisplay.push(`${pc.blue("Elixir Quality:")} ${String(config.elixirQuality)}`);
|
|
9684
|
+
if (config.elixirI18n && config.elixirI18n !== "none") configDisplay.push(`${pc.blue("Elixir I18n:")} ${String(config.elixirI18n)}`);
|
|
9685
|
+
if (config.elixirHttpServer && config.elixirHttpServer !== "none") configDisplay.push(`${pc.blue("Elixir HTTP Server:")} ${String(config.elixirHttpServer)}`);
|
|
9686
|
+
if (config.elixirApplicationFramework && config.elixirApplicationFramework !== "none") configDisplay.push(`${pc.blue("Elixir Application Framework:")} ${String(config.elixirApplicationFramework)}`);
|
|
9687
|
+
if (config.elixirDocumentation && config.elixirDocumentation !== "none") configDisplay.push(`${pc.blue("Elixir Documentation:")} ${String(config.elixirDocumentation)}`);
|
|
9688
|
+
if (config.elixirClustering && config.elixirClustering !== "none") configDisplay.push(`${pc.blue("Elixir Clustering:")} ${String(config.elixirClustering)}`);
|
|
8908
9689
|
if (config.elixirDeploy && config.elixirDeploy !== "none") configDisplay.push(`${pc.blue("Elixir Deploy:")} ${String(config.elixirDeploy)}`);
|
|
8909
9690
|
}
|
|
8910
9691
|
if (config.observability !== void 0) configDisplay.push(`${pc.blue("Observability:")} ${String(config.observability)}`);
|
|
@@ -10694,7 +11475,11 @@ function displayRustInstructions(config) {
|
|
|
10694
11475
|
if (rustWebFramework && rustWebFramework !== "none") output += `${pc.cyan("•")} Web Framework: ${{
|
|
10695
11476
|
actix: "Actix Web",
|
|
10696
11477
|
axum: "Axum",
|
|
10697
|
-
rocket: "Rocket"
|
|
11478
|
+
rocket: "Rocket",
|
|
11479
|
+
poem: "Poem",
|
|
11480
|
+
loco: "Loco",
|
|
11481
|
+
warp: "Warp",
|
|
11482
|
+
salvo: "Salvo"
|
|
10698
11483
|
}[rustWebFramework] || rustWebFramework}\n`;
|
|
10699
11484
|
if (rustFrontend && rustFrontend !== "none") output += `${pc.cyan("•")} Frontend: ${{
|
|
10700
11485
|
leptos: "Leptos",
|
|
@@ -10704,11 +11489,15 @@ function displayRustInstructions(config) {
|
|
|
10704
11489
|
if (rustOrm && rustOrm !== "none") output += `${pc.cyan("•")} Database: ${{
|
|
10705
11490
|
diesel: "Diesel",
|
|
10706
11491
|
sqlx: "SQLx",
|
|
10707
|
-
"sea-orm": "SeaORM"
|
|
11492
|
+
"sea-orm": "SeaORM",
|
|
11493
|
+
mongodb: "MongoDB Rust Driver",
|
|
11494
|
+
rusqlite: "rusqlite",
|
|
11495
|
+
"tokio-postgres": "tokio-postgres"
|
|
10708
11496
|
}[rustOrm] || rustOrm}\n`;
|
|
10709
11497
|
if (rustApi && rustApi !== "none") output += `${pc.cyan("•")} API: ${{
|
|
10710
11498
|
"async-graphql": "async-graphql",
|
|
10711
|
-
|
|
11499
|
+
tonic: "Tonic",
|
|
11500
|
+
jsonrpsee: "jsonrpsee"
|
|
10712
11501
|
}[rustApi] || rustApi}\n`;
|
|
10713
11502
|
if (rustCli && rustCli !== "none") output += `${pc.cyan("•")} CLI: ${{
|
|
10714
11503
|
clap: "Clap",
|
|
@@ -10744,7 +11533,7 @@ function displayRustInstructions(config) {
|
|
|
10744
11533
|
consola$1.box(output);
|
|
10745
11534
|
}
|
|
10746
11535
|
function displayGoInstructions(config) {
|
|
10747
|
-
const { relativePath, depsInstalled, goWebFramework, goOrm, goApi, goCli, goLogging, goAuth } = config;
|
|
11536
|
+
const { relativePath, depsInstalled, goWebFramework, goOrm, goApi, goCli, goLogging, goAuth, goTesting, goMessageQueue, goObservability, goValidation, goQuality, goMigrations, goTemplating, goProtoTooling, goDI } = config;
|
|
10748
11537
|
const cdCmd = `cd ${relativePath}`;
|
|
10749
11538
|
let output = `${pc.bold("Next steps")}\n${pc.cyan("1.")} ${cdCmd}\n`;
|
|
10750
11539
|
let stepCounter = 2;
|
|
@@ -10755,14 +11544,25 @@ function displayGoInstructions(config) {
|
|
|
10755
11544
|
gin: "Gin",
|
|
10756
11545
|
echo: "Echo",
|
|
10757
11546
|
fiber: "Fiber",
|
|
10758
|
-
chi: "Chi"
|
|
11547
|
+
chi: "Chi",
|
|
11548
|
+
stdlib: "net/http",
|
|
11549
|
+
"go-zero": "go-zero",
|
|
11550
|
+
kratos: "Kratos",
|
|
11551
|
+
httprouter: "HttpRouter"
|
|
10759
11552
|
}[goWebFramework] || goWebFramework}\n`;
|
|
10760
11553
|
if (goOrm && goOrm !== "none") output += `${pc.cyan("•")} Database: ${{
|
|
10761
11554
|
gorm: "GORM",
|
|
10762
11555
|
sqlc: "sqlc",
|
|
10763
|
-
ent: "Ent"
|
|
11556
|
+
ent: "Ent",
|
|
11557
|
+
bun: "Bun",
|
|
11558
|
+
sqlx: "sqlx"
|
|
10764
11559
|
}[goOrm] || goOrm}\n`;
|
|
10765
|
-
if (goApi && goApi !== "none") output += `${pc.cyan("•")} API: ${{
|
|
11560
|
+
if (goApi && goApi !== "none") output += `${pc.cyan("•")} API: ${{
|
|
11561
|
+
"grpc-go": "gRPC-Go",
|
|
11562
|
+
"grpc-gateway": "grpc-gateway",
|
|
11563
|
+
"connect-go": "Connect-Go",
|
|
11564
|
+
"oapi-codegen": "oapi-codegen"
|
|
11565
|
+
}[goApi] || goApi}\n`;
|
|
10766
11566
|
if (goCli && goCli !== "none") output += `${pc.cyan("•")} CLI: ${{
|
|
10767
11567
|
cobra: "Cobra",
|
|
10768
11568
|
bubbletea: "Bubble Tea",
|
|
@@ -10775,8 +11575,25 @@ function displayGoInstructions(config) {
|
|
|
10775
11575
|
}[goLogging] || goLogging}\n`;
|
|
10776
11576
|
if (goAuth && goAuth !== "none") output += `${pc.cyan("•")} Auth: ${{
|
|
10777
11577
|
casbin: "Casbin",
|
|
10778
|
-
jwt: "golang-jwt"
|
|
11578
|
+
jwt: "golang-jwt",
|
|
11579
|
+
goth: "Goth",
|
|
11580
|
+
oauth2: "x/oauth2"
|
|
10779
11581
|
}[goAuth] || goAuth}\n`;
|
|
11582
|
+
const extras = [
|
|
11583
|
+
["Testing", goTesting],
|
|
11584
|
+
["Messaging", goMessageQueue],
|
|
11585
|
+
["Observability", goObservability],
|
|
11586
|
+
["Validation", goValidation],
|
|
11587
|
+
["Code Quality", goQuality],
|
|
11588
|
+
["Migrations", goMigrations],
|
|
11589
|
+
["Templating", goTemplating],
|
|
11590
|
+
["Protobuf Tooling", goProtoTooling],
|
|
11591
|
+
["Dependency Injection", goDI]
|
|
11592
|
+
];
|
|
11593
|
+
for (const [label, value] of extras) {
|
|
11594
|
+
const rendered = Array.isArray(value) ? value.filter((item) => item !== "none").join(", ") : value;
|
|
11595
|
+
if (rendered && rendered !== "none") output += `${pc.cyan("•")} ${label}: ${rendered}\n`;
|
|
11596
|
+
}
|
|
10780
11597
|
output += `\n${pc.bold("Common Go commands:")}\n`;
|
|
10781
11598
|
output += `${pc.cyan("•")} Build: go build ./...\n`;
|
|
10782
11599
|
output += `${pc.cyan("•")} Run: go run cmd/server/main.go\n`;
|
|
@@ -11071,7 +11888,7 @@ async function createProject(options, cliInput = {}) {
|
|
|
11071
11888
|
await applyDependencyVersionChannel(projectDir, options.versionChannel);
|
|
11072
11889
|
await writeBtsConfig(options);
|
|
11073
11890
|
await formatProject(projectDir);
|
|
11074
|
-
await recordScaffoldManifest(projectDir);
|
|
11891
|
+
await recordScaffoldManifest(projectDir, { baselines: collectStructuredBaselines(result.tree) });
|
|
11075
11892
|
if (!isSilent()) log.success("Project template successfully scaffolded!");
|
|
11076
11893
|
if (options.install && (options.ecosystem === "typescript" || options.ecosystem === "react-native")) {
|
|
11077
11894
|
const result$1 = await installDependencies({
|
|
@@ -11234,6 +12051,8 @@ function getYesBaseConfig(flagConfig) {
|
|
|
11234
12051
|
frontend: ["native-bare"],
|
|
11235
12052
|
addons: [],
|
|
11236
12053
|
examples: [],
|
|
12054
|
+
database: "none",
|
|
12055
|
+
orm: "none",
|
|
11237
12056
|
auth: "none",
|
|
11238
12057
|
payments: "none",
|
|
11239
12058
|
email: "none",
|
|
@@ -11271,6 +12090,11 @@ function getYesBaseConfig(flagConfig) {
|
|
|
11271
12090
|
mobileDeepLinking: "none"
|
|
11272
12091
|
};
|
|
11273
12092
|
}
|
|
12093
|
+
function reportCompatibilityAdjustments(adjustments) {
|
|
12094
|
+
if (isSilent() || adjustments.length === 0) return;
|
|
12095
|
+
log.warn(pc.yellow("Adjusted incompatible options (use --yolo to bypass):"));
|
|
12096
|
+
for (const adjustment of adjustments) log.message(pc.yellow(` ${adjustment}`));
|
|
12097
|
+
}
|
|
11274
12098
|
function shouldPromptForVersionChannel(input, hasConfigBase) {
|
|
11275
12099
|
if (input.yes || input.part?.length || hasConfigBase || input.versionChannel !== void 0 || isSilent()) return false;
|
|
11276
12100
|
return canPromptInteractively();
|
|
@@ -11437,6 +12261,12 @@ async function createProjectHandler(input, options = {}) {
|
|
|
11437
12261
|
goCaching: "none",
|
|
11438
12262
|
goConfig: "none",
|
|
11439
12263
|
goObservability: "none",
|
|
12264
|
+
goValidation: "none",
|
|
12265
|
+
goQuality: "none",
|
|
12266
|
+
goMigrations: "none",
|
|
12267
|
+
goTemplating: "none",
|
|
12268
|
+
goProtoTooling: "none",
|
|
12269
|
+
goDI: "none",
|
|
11440
12270
|
javaWebFramework: "none",
|
|
11441
12271
|
javaBuildTool: "none",
|
|
11442
12272
|
javaOrm: "none",
|
|
@@ -11470,6 +12300,11 @@ async function createProjectHandler(input, options = {}) {
|
|
|
11470
12300
|
elixirObservability: "none",
|
|
11471
12301
|
elixirTesting: "none",
|
|
11472
12302
|
elixirQuality: "none",
|
|
12303
|
+
elixirI18n: "none",
|
|
12304
|
+
elixirHttpServer: "none",
|
|
12305
|
+
elixirApplicationFramework: "none",
|
|
12306
|
+
elixirDocumentation: "none",
|
|
12307
|
+
elixirClustering: "none",
|
|
11473
12308
|
elixirDeploy: "none",
|
|
11474
12309
|
elixirLibraries: [],
|
|
11475
12310
|
aiDocs: []
|
|
@@ -11529,6 +12364,20 @@ async function createProjectHandler(input, options = {}) {
|
|
|
11529
12364
|
relativePath: currentPathInput,
|
|
11530
12365
|
versionChannel
|
|
11531
12366
|
};
|
|
12367
|
+
if (!cliInput.yolo && !isSilent()) {
|
|
12368
|
+
const { changes, adjustments } = resolveCompatibilityAdjustments(config);
|
|
12369
|
+
if (adjustments.length > 0) {
|
|
12370
|
+
config = {
|
|
12371
|
+
...config,
|
|
12372
|
+
...changes
|
|
12373
|
+
};
|
|
12374
|
+
cliInput = {
|
|
12375
|
+
...cliInput,
|
|
12376
|
+
...changes
|
|
12377
|
+
};
|
|
12378
|
+
reportCompatibilityAdjustments(adjustments);
|
|
12379
|
+
}
|
|
12380
|
+
}
|
|
11532
12381
|
validateConfigCompatibility(config, providedFlags, cliInput);
|
|
11533
12382
|
const yesPreflight = validatePreflightConfig(config);
|
|
11534
12383
|
if (yesPreflight.hasWarnings && !isSilent()) displayPreflightWarnings(yesPreflight);
|
|
@@ -11548,6 +12397,20 @@ async function createProjectHandler(input, options = {}) {
|
|
|
11548
12397
|
...await gatherConfig(flagConfig, finalBaseName, finalResolvedPath, currentPathInput),
|
|
11549
12398
|
versionChannel
|
|
11550
12399
|
};
|
|
12400
|
+
if (!cliInput.yolo && !isSilent()) {
|
|
12401
|
+
const { changes, adjustments } = resolveCompatibilityAdjustments(config);
|
|
12402
|
+
if (adjustments.length > 0) {
|
|
12403
|
+
config = {
|
|
12404
|
+
...config,
|
|
12405
|
+
...changes
|
|
12406
|
+
};
|
|
12407
|
+
cliInput = {
|
|
12408
|
+
...cliInput,
|
|
12409
|
+
...changes
|
|
12410
|
+
};
|
|
12411
|
+
reportCompatibilityAdjustments(adjustments);
|
|
12412
|
+
}
|
|
12413
|
+
}
|
|
11551
12414
|
validateConfigCompatibility(config, providedFlags, cliInput);
|
|
11552
12415
|
}
|
|
11553
12416
|
normalizeKotlinJavaSelection(config);
|
|
@@ -11811,7 +12674,7 @@ const router = os.router({
|
|
|
11811
12674
|
}
|
|
11812
12675
|
}),
|
|
11813
12676
|
add: os.meta({ description: "Add addons, deploy targets, or stack capabilities to an existing Better Fullstack project using its bts.jsonc config" }).input(AddCommandInputSchema).handler(async ({ input }) => {
|
|
11814
|
-
const { addHandler } = await import("./add-handler-
|
|
12677
|
+
const { addHandler } = await import("./add-handler-CE3XIs3y.mjs");
|
|
11815
12678
|
await addHandler(input);
|
|
11816
12679
|
}),
|
|
11817
12680
|
history: os.meta({ description: "Show history of scaffolded projects with reproducible commands" }).input(z.object({
|
|
@@ -11860,7 +12723,7 @@ const router = os.router({
|
|
|
11860
12723
|
})
|
|
11861
12724
|
])).handler(async ({ input }) => {
|
|
11862
12725
|
const [kind, name, options] = input;
|
|
11863
|
-
const { genCommand } = await import("./gen-
|
|
12726
|
+
const { genCommand } = await import("./gen-BZ0QCxCC.mjs");
|
|
11864
12727
|
await genCommand({
|
|
11865
12728
|
kind,
|
|
11866
12729
|
name,
|
|
@@ -11878,7 +12741,7 @@ const router = os.router({
|
|
|
11878
12741
|
})
|
|
11879
12742
|
])).handler(async ({ input }) => {
|
|
11880
12743
|
const [action, source, options] = input;
|
|
11881
|
-
const { registryHandler } = await import("./registry-
|
|
12744
|
+
const { registryHandler } = await import("./registry-Cm3D45oT.mjs");
|
|
11882
12745
|
await registryHandler({
|
|
11883
12746
|
action,
|
|
11884
12747
|
source,
|
|
@@ -11895,7 +12758,7 @@ const router = os.router({
|
|
|
11895
12758
|
recordBaseline: z.boolean().optional().default(false).describe("Adopt the current on-disk state as the scaffold baseline (for projects created before the update engine)")
|
|
11896
12759
|
})])).handler(async ({ input }) => {
|
|
11897
12760
|
const [projectDir, options] = input;
|
|
11898
|
-
const { updateCommand } = await import("./update-
|
|
12761
|
+
const { updateCommand } = await import("./update-B270pWHc.mjs");
|
|
11899
12762
|
await updateCommand({
|
|
11900
12763
|
projectDir,
|
|
11901
12764
|
...options
|
|
@@ -11907,7 +12770,7 @@ const router = os.router({
|
|
|
11907
12770
|
}),
|
|
11908
12771
|
doctor: os.meta({ description: "Diagnose a scaffolded Better Fullstack project: verify its bts.jsonc, installed dependencies, required env vars, and run ecosystem build/type checks" }).input(ProjectCheckInputSchema).handler(async ({ input }) => {
|
|
11909
12772
|
const [projectDir, options] = input;
|
|
11910
|
-
const { doctorCommand } = await import("./doctor-
|
|
12773
|
+
const { doctorCommand } = await import("./doctor-Cc7sLuow.mjs");
|
|
11911
12774
|
await doctorCommand({
|
|
11912
12775
|
projectDir,
|
|
11913
12776
|
...options
|
|
@@ -11915,7 +12778,7 @@ const router = os.router({
|
|
|
11915
12778
|
}),
|
|
11916
12779
|
check: os.meta({ description: "Check a scaffolded Better Fullstack project for config, dependency, env, and generated build/type drift" }).input(ProjectCheckInputSchema).handler(async ({ input }) => {
|
|
11917
12780
|
const [projectDir, options] = input;
|
|
11918
|
-
const { doctorCommand } = await import("./doctor-
|
|
12781
|
+
const { doctorCommand } = await import("./doctor-Cc7sLuow.mjs");
|
|
11919
12782
|
await doctorCommand({
|
|
11920
12783
|
projectDir,
|
|
11921
12784
|
...options
|
|
@@ -11926,7 +12789,7 @@ const router = os.router({
|
|
|
11926
12789
|
ecosystem: z.string().optional().describe("Force an ecosystem (typescript, react-native, rust, go, python, java, ...)"),
|
|
11927
12790
|
json: z.boolean().default(false).describe("Output the recommendation as JSON")
|
|
11928
12791
|
})).handler(async ({ input }) => {
|
|
11929
|
-
const { recommendStackFromBrief } = await import("./mcp-
|
|
12792
|
+
const { recommendStackFromBrief } = await import("./mcp-DNKAo8nO.mjs");
|
|
11930
12793
|
const result = recommendStackFromBrief(input.brief, input.ecosystem);
|
|
11931
12794
|
if (input.json) {
|
|
11932
12795
|
log.message(JSON.stringify(result, null, 2));
|
|
@@ -12002,7 +12865,7 @@ async function builder() {
|
|
|
12002
12865
|
return caller.builder();
|
|
12003
12866
|
}
|
|
12004
12867
|
async function add(input, options) {
|
|
12005
|
-
const { addHandler } = await import("./add-handler-
|
|
12868
|
+
const { addHandler } = await import("./add-handler-CE3XIs3y.mjs");
|
|
12006
12869
|
return addHandler(input, {
|
|
12007
12870
|
silent: true,
|
|
12008
12871
|
telemetrySource: options?.telemetrySource ?? "programmatic"
|