create-better-fullstack 2.1.7 → 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-D9I7NdES.mjs → run-DmN7QRt5.mjs} +1231 -346
- 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-buK4aZS8.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",
|
|
@@ -2268,113 +2552,39 @@ const resolveElixirRealtimePrompt = (value) => createStaticSinglePromptResolutio
|
|
|
2268
2552
|
const resolveElixirJobsPrompt = (value) => createStaticSinglePromptResolution(JOB_OPTIONS, "none", value);
|
|
2269
2553
|
const resolveElixirValidationPrompt = (value) => createStaticSinglePromptResolution(VALIDATION_OPTIONS, "ecto-changesets", value);
|
|
2270
2554
|
const resolveElixirHttpPrompt = (value) => createStaticSinglePromptResolution(HTTP_OPTIONS, "req", value);
|
|
2271
|
-
const resolveElixirJsonPrompt = (value) => createStaticSinglePromptResolution(JSON_OPTIONS, "jason", value);
|
|
2272
|
-
const resolveElixirEmailPrompt = (value) => createStaticSinglePromptResolution(EMAIL_OPTIONS, "none", value);
|
|
2273
|
-
const resolveElixirCachingPrompt = (value) => createStaticSinglePromptResolution(CACHING_OPTIONS, "none", value);
|
|
2274
|
-
const resolveElixirObservabilityPrompt = (value) => createStaticSinglePromptResolution(OBSERVABILITY_OPTIONS, "telemetry", value);
|
|
2275
|
-
const resolveElixirTestingPrompt = (value) => createStaticSinglePromptResolution(TESTING_OPTIONS, "ex_unit", value);
|
|
2276
|
-
const resolveElixirQualityPrompt = (value) => createStaticSinglePromptResolution(QUALITY_OPTIONS, "credo", value);
|
|
2277
|
-
const
|
|
2278
|
-
const
|
|
2279
|
-
const
|
|
2280
|
-
const
|
|
2281
|
-
const
|
|
2282
|
-
const
|
|
2283
|
-
const
|
|
2284
|
-
const
|
|
2285
|
-
const
|
|
2286
|
-
const
|
|
2287
|
-
const
|
|
2288
|
-
const
|
|
2289
|
-
const
|
|
2290
|
-
const
|
|
2291
|
-
const
|
|
2292
|
-
const
|
|
2293
|
-
const
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
const
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
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
|
-
}
|
|
2555
|
+
const resolveElixirJsonPrompt = (value) => createStaticSinglePromptResolution(JSON_OPTIONS, "jason", value);
|
|
2556
|
+
const resolveElixirEmailPrompt = (value) => createStaticSinglePromptResolution(EMAIL_OPTIONS, "none", value);
|
|
2557
|
+
const resolveElixirCachingPrompt = (value) => createStaticSinglePromptResolution(CACHING_OPTIONS, "none", value);
|
|
2558
|
+
const resolveElixirObservabilityPrompt = (value) => createStaticSinglePromptResolution(OBSERVABILITY_OPTIONS, "telemetry", value);
|
|
2559
|
+
const resolveElixirTestingPrompt = (value) => createStaticSinglePromptResolution(TESTING_OPTIONS, "ex_unit", value);
|
|
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);
|
|
2566
|
+
const resolveElixirDeployPrompt = (value) => createStaticSinglePromptResolution(DEPLOY_OPTIONS, "none", value);
|
|
2567
|
+
const getElixirWebFrameworkChoice = (value) => makeChoice("Select Elixir web framework", WEB_FRAMEWORK_OPTIONS, "phoenix", value);
|
|
2568
|
+
const getElixirOrmChoice = (value) => makeChoice("Select Elixir database layer", ORM_OPTIONS, "ecto-sql", value);
|
|
2569
|
+
const getElixirAuthChoice = (value) => makeChoice("Select Elixir auth", AUTH_OPTIONS, "none", value);
|
|
2570
|
+
const getElixirApiChoice = (value) => makeChoice("Select Elixir API layer", API_OPTIONS, "rest", value);
|
|
2571
|
+
const getElixirRealtimeChoice = (value) => makeChoice("Select Elixir realtime feature", REALTIME_OPTIONS, "channels", value);
|
|
2572
|
+
const getElixirJobsChoice = (value) => makeChoice("Select Elixir jobs layer", JOB_OPTIONS, "none", value);
|
|
2573
|
+
const getElixirValidationChoice = (value) => makeChoice("Select Elixir validation", VALIDATION_OPTIONS, "ecto-changesets", value);
|
|
2574
|
+
const getElixirHttpChoice = (value) => makeChoice("Select Elixir HTTP client", HTTP_OPTIONS, "req", value);
|
|
2575
|
+
const getElixirJsonChoice = (value) => makeChoice("Select Elixir JSON library", JSON_OPTIONS, "jason", value);
|
|
2576
|
+
const getElixirEmailChoice = (value) => makeChoice("Select Elixir email library", EMAIL_OPTIONS, "none", value);
|
|
2577
|
+
const getElixirCachingChoice = (value) => makeChoice("Select Elixir caching", CACHING_OPTIONS, "none", value);
|
|
2578
|
+
const getElixirObservabilityChoice = (value) => makeChoice("Select Elixir observability", OBSERVABILITY_OPTIONS, "telemetry", value);
|
|
2579
|
+
const getElixirTestingChoice = (value) => makeChoice("Select Elixir testing", TESTING_OPTIONS, "ex_unit", value);
|
|
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);
|
|
2586
|
+
const getElixirDeployChoice = (value) => makeChoice("Select Elixir deploy target", DEPLOY_OPTIONS, "none", value);
|
|
2587
|
+
const getElixirLibrariesChoice = (value) => makeMultiChoice("Select Elixir libraries", LIBRARY_OPTIONS, [], value);
|
|
2378
2588
|
|
|
2379
2589
|
//#endregion
|
|
2380
2590
|
//#region src/prompts/email.ts
|
|
@@ -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
|
|
@@ -3698,11 +4129,11 @@ async function getJavaLanguageChoice(javaLanguage) {
|
|
|
3698
4129
|
if (isCancel$1(response)) return exitCancelled("Operation cancelled");
|
|
3699
4130
|
return response;
|
|
3700
4131
|
}
|
|
3701
|
-
function resolveJavaBuildToolPrompt(javaBuildTool) {
|
|
3702
|
-
return createStaticSinglePromptResolution(JAVA_BUILD_TOOL_PROMPT_OPTIONS, "maven", javaBuildTool);
|
|
4132
|
+
function resolveJavaBuildToolPrompt(javaBuildTool, javaLanguage) {
|
|
4133
|
+
return createStaticSinglePromptResolution(javaLanguage === "kotlin" ? JAVA_BUILD_TOOL_PROMPT_OPTIONS.filter((option) => option.value !== "none") : JAVA_BUILD_TOOL_PROMPT_OPTIONS, "maven", javaBuildTool);
|
|
3703
4134
|
}
|
|
3704
|
-
async function getJavaBuildToolChoice(javaBuildTool) {
|
|
3705
|
-
const resolution = resolveJavaBuildToolPrompt(javaBuildTool);
|
|
4135
|
+
async function getJavaBuildToolChoice(javaBuildTool, javaLanguage) {
|
|
4136
|
+
const resolution = resolveJavaBuildToolPrompt(javaBuildTool, javaLanguage);
|
|
3706
4137
|
if (!resolution.shouldPrompt) return resolution.autoValue ?? "none";
|
|
3707
4138
|
const response = await navigableSelect({
|
|
3708
4139
|
message: "Select Java build tool",
|
|
@@ -3712,11 +4143,11 @@ async function getJavaBuildToolChoice(javaBuildTool) {
|
|
|
3712
4143
|
if (isCancel$1(response)) return exitCancelled("Operation cancelled");
|
|
3713
4144
|
return response;
|
|
3714
4145
|
}
|
|
3715
|
-
function resolveJavaOrmPrompt(javaOrm) {
|
|
3716
|
-
return createStaticSinglePromptResolution(JAVA_ORM_PROMPT_OPTIONS, "none", javaOrm);
|
|
4146
|
+
function resolveJavaOrmPrompt(javaOrm, javaLanguage) {
|
|
4147
|
+
return createStaticSinglePromptResolution(javaLanguage === "kotlin" ? JAVA_ORM_PROMPT_OPTIONS.filter((option) => option.value !== "jooq" && option.value !== "mybatis") : JAVA_ORM_PROMPT_OPTIONS, "none", javaOrm);
|
|
3717
4148
|
}
|
|
3718
|
-
async function getJavaOrmChoice(javaOrm) {
|
|
3719
|
-
const resolution = resolveJavaOrmPrompt(javaOrm);
|
|
4149
|
+
async function getJavaOrmChoice(javaOrm, javaLanguage) {
|
|
4150
|
+
const resolution = resolveJavaOrmPrompt(javaOrm, javaLanguage);
|
|
3720
4151
|
if (!resolution.shouldPrompt) return resolution.autoValue ?? "none";
|
|
3721
4152
|
const response = await navigableSelect({
|
|
3722
4153
|
message: "Select Java ORM/database layer",
|
|
@@ -3740,11 +4171,11 @@ async function getJavaAuthChoice(javaAuth) {
|
|
|
3740
4171
|
if (isCancel$1(response)) return exitCancelled("Operation cancelled");
|
|
3741
4172
|
return response;
|
|
3742
4173
|
}
|
|
3743
|
-
function resolveJavaLibrariesPrompt(javaLibraries) {
|
|
3744
|
-
return createStaticMultiPromptResolution(JAVA_LIBRARY_PROMPT_OPTIONS, [], javaLibraries);
|
|
4174
|
+
function resolveJavaLibrariesPrompt(javaLibraries, javaLanguage) {
|
|
4175
|
+
return createStaticMultiPromptResolution(javaLanguage === "kotlin" ? JAVA_LIBRARY_PROMPT_OPTIONS.filter((option) => !types_exports.KOTLIN_DROPPED_JAVA_LIBRARIES.has(option.value)) : JAVA_LIBRARY_PROMPT_OPTIONS, [], javaLibraries);
|
|
3745
4176
|
}
|
|
3746
|
-
async function getJavaLibrariesChoice(javaLibraries) {
|
|
3747
|
-
const resolution = resolveJavaLibrariesPrompt(javaLibraries);
|
|
4177
|
+
async function getJavaLibrariesChoice(javaLibraries, javaLanguage) {
|
|
4178
|
+
const resolution = resolveJavaLibrariesPrompt(javaLibraries, javaLanguage);
|
|
3748
4179
|
if (!resolution.shouldPrompt) return resolution.autoValue ?? [];
|
|
3749
4180
|
const response = await navigableMultiselect({
|
|
3750
4181
|
message: "Select Java application libraries",
|
|
@@ -3756,11 +4187,11 @@ async function getJavaLibrariesChoice(javaLibraries) {
|
|
|
3756
4187
|
if (response.includes("none")) return [];
|
|
3757
4188
|
return response;
|
|
3758
4189
|
}
|
|
3759
|
-
function resolveJavaTestingLibrariesPrompt(javaTestingLibraries) {
|
|
3760
|
-
return createStaticMultiPromptResolution(JAVA_TESTING_LIBRARY_PROMPT_OPTIONS, ["junit5"], javaTestingLibraries);
|
|
4190
|
+
function resolveJavaTestingLibrariesPrompt(javaTestingLibraries, javaLanguage) {
|
|
4191
|
+
return createStaticMultiPromptResolution(javaLanguage === "kotlin" ? JAVA_TESTING_LIBRARY_PROMPT_OPTIONS.filter((option) => !types_exports.KOTLIN_UNSUPPORTED_JAVA_TESTING_LIBRARIES.has(option.value)) : JAVA_TESTING_LIBRARY_PROMPT_OPTIONS, ["junit5"], javaTestingLibraries);
|
|
3761
4192
|
}
|
|
3762
|
-
async function getJavaTestingLibrariesChoice(javaTestingLibraries) {
|
|
3763
|
-
const resolution = resolveJavaTestingLibrariesPrompt(javaTestingLibraries);
|
|
4193
|
+
async function getJavaTestingLibrariesChoice(javaTestingLibraries, javaLanguage) {
|
|
4194
|
+
const resolution = resolveJavaTestingLibrariesPrompt(javaTestingLibraries, javaLanguage);
|
|
3764
4195
|
if (!resolution.shouldPrompt) return resolution.autoValue ?? [];
|
|
3765
4196
|
const response = await navigableMultiselect({
|
|
3766
4197
|
message: "Select Java testing libraries",
|
|
@@ -3811,11 +4242,11 @@ const JAVA_LOGGING_PROMPT_OPTIONS = [
|
|
|
3811
4242
|
hint: "Spring Boot logging defaults"
|
|
3812
4243
|
}
|
|
3813
4244
|
];
|
|
3814
|
-
function resolveJavaApiPrompt(javaApi) {
|
|
3815
|
-
return createStaticSinglePromptResolution(JAVA_API_PROMPT_OPTIONS, "none", javaApi);
|
|
4245
|
+
function resolveJavaApiPrompt(javaApi, javaLanguage) {
|
|
4246
|
+
return createStaticSinglePromptResolution(javaLanguage === "kotlin" ? JAVA_API_PROMPT_OPTIONS.filter((option) => option.value !== "grpc" && option.value !== "openapi-generator") : JAVA_API_PROMPT_OPTIONS, "none", javaApi);
|
|
3816
4247
|
}
|
|
3817
|
-
async function getJavaApiChoice(javaApi) {
|
|
3818
|
-
const resolution = resolveJavaApiPrompt(javaApi);
|
|
4248
|
+
async function getJavaApiChoice(javaApi, javaLanguage) {
|
|
4249
|
+
const resolution = resolveJavaApiPrompt(javaApi, javaLanguage);
|
|
3819
4250
|
if (!resolution.shouldPrompt) return resolution.autoValue ?? "none";
|
|
3820
4251
|
const response = await navigableSelect({
|
|
3821
4252
|
message: "Select Java API layer",
|
|
@@ -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));
|
|
@@ -6016,17 +6591,17 @@ async function gatherMultiEcosystemConfig(flags, projectName, projectDir, relati
|
|
|
6016
6591
|
if (backendEcosystem === "java") {
|
|
6017
6592
|
const javaWebFramework = promptValue(await getJavaWebFrameworkChoice(flags.javaWebFramework));
|
|
6018
6593
|
const javaLanguage = javaWebFramework !== "spring-boot" ? "java" : flags.javaLanguage !== void 0 ? promptValue(await getJavaLanguageChoice(flags.javaLanguage)) : flags.javaWebFramework !== void 0 ? "java" : promptValue(await getJavaLanguageChoice(flags.javaLanguage));
|
|
6019
|
-
const javaBuildTool = promptValue(await getJavaBuildToolChoice(flags.javaBuildTool));
|
|
6594
|
+
const javaBuildTool = promptValue(await getJavaBuildToolChoice(flags.javaBuildTool, javaLanguage));
|
|
6020
6595
|
if (javaWebFramework !== "none" && javaBuildTool !== "none") {
|
|
6021
6596
|
const databaseConfig = await selectDatabaseConfig(flags);
|
|
6022
6597
|
database = databaseConfig.database;
|
|
6023
6598
|
dbSetup = databaseConfig.dbSetup;
|
|
6024
6599
|
}
|
|
6025
|
-
const javaOrm = database === "none" || javaWebFramework !== "spring-boot" || javaBuildTool === "none" ? "none" : promptValue(await getJavaOrmChoice(flags.javaOrm));
|
|
6600
|
+
const javaOrm = database === "none" || javaWebFramework !== "spring-boot" || javaBuildTool === "none" ? "none" : promptValue(await getJavaOrmChoice(flags.javaOrm, javaLanguage));
|
|
6026
6601
|
const javaAuth = javaWebFramework !== "spring-boot" || javaBuildTool === "none" ? "none" : promptValue(await getJavaAuthChoice(flags.javaAuth));
|
|
6027
|
-
const javaLibraries = javaWebFramework !== "spring-boot" || javaBuildTool === "none" ? [] : await scopedPromptValue("java", "javaLibraries", configScope, backendSections, () => getJavaLibrariesChoice(flags.javaLibraries));
|
|
6028
|
-
const javaTestingLibraries = await scopedPromptValue("java", "javaTestingLibraries", configScope, backendSections, () => getJavaTestingLibrariesChoice(flags.javaTestingLibraries));
|
|
6029
|
-
const javaApi = javaWebFramework !== "spring-boot" || javaBuildTool === "none" ? "none" : promptValue(await getJavaApiChoice(flags.javaApi));
|
|
6602
|
+
const javaLibraries = javaWebFramework !== "spring-boot" || javaBuildTool === "none" ? [] : await scopedPromptValue("java", "javaLibraries", configScope, backendSections, () => getJavaLibrariesChoice(flags.javaLibraries, javaLanguage));
|
|
6603
|
+
const javaTestingLibraries = await scopedPromptValue("java", "javaTestingLibraries", configScope, backendSections, () => getJavaTestingLibrariesChoice(flags.javaTestingLibraries, javaLanguage));
|
|
6604
|
+
const javaApi = javaWebFramework !== "spring-boot" || javaBuildTool === "none" ? "none" : promptValue(await getJavaApiChoice(flags.javaApi, javaLanguage));
|
|
6030
6605
|
const javaLogging = javaWebFramework !== "spring-boot" || javaBuildTool === "none" ? "none" : await scopedPromptValue("java", "javaLogging", configScope, backendSections, () => getJavaLoggingChoice(flags.javaLogging));
|
|
6031
6606
|
Object.assign(backendChoices, {
|
|
6032
6607
|
javaLanguage,
|
|
@@ -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,
|
|
@@ -6413,42 +7004,6 @@ async function getORMChoice(orm, hasDatabase, database, backend, runtime) {
|
|
|
6413
7004
|
return response;
|
|
6414
7005
|
}
|
|
6415
7006
|
|
|
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";
|
|
6435
|
-
const response = await navigableSelect({
|
|
6436
|
-
message: "Choose workspace layout",
|
|
6437
|
-
options: [{
|
|
6438
|
-
value: "monorepo",
|
|
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"
|
|
6447
|
-
});
|
|
6448
|
-
if (isCancel$1(response)) return exitCancelled("Operation cancelled");
|
|
6449
|
-
return response;
|
|
6450
|
-
}
|
|
6451
|
-
|
|
6452
7007
|
//#endregion
|
|
6453
7008
|
//#region src/prompts/payments.ts
|
|
6454
7009
|
function resolvePaymentsPrompt(context = {}) {
|
|
@@ -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);
|
|
@@ -8351,18 +9096,31 @@ async function gatherConfig(flags, projectName, projectDir, relativePath) {
|
|
|
8351
9096
|
javaLanguage: ({ results }) => {
|
|
8352
9097
|
if (results.ecosystem !== "java") return Promise.resolve("java");
|
|
8353
9098
|
if (results.javaWebFramework !== "spring-boot") return Promise.resolve("java");
|
|
9099
|
+
const kotlinBlocker = (0, types_exports.getKotlinJavaIncompatibilityReason)({
|
|
9100
|
+
javaWebFramework: results.javaWebFramework,
|
|
9101
|
+
javaBuildTool: "maven",
|
|
9102
|
+
email: results.email,
|
|
9103
|
+
search: results.search,
|
|
9104
|
+
caching: results.caching,
|
|
9105
|
+
observability: results.observability
|
|
9106
|
+
});
|
|
9107
|
+
if (kotlinBlocker) {
|
|
9108
|
+
if (flags.javaLanguage === "kotlin") log.warn(`JVM language set to Java: ${kotlinBlocker}`);
|
|
9109
|
+
else if (flags.javaLanguage === void 0 && flags.javaWebFramework === void 0) log.info(`Kotlin not offered: ${kotlinBlocker}`);
|
|
9110
|
+
return Promise.resolve("java");
|
|
9111
|
+
}
|
|
8354
9112
|
if (flags.javaLanguage !== void 0) return getJavaLanguageChoice(flags.javaLanguage);
|
|
8355
9113
|
if (flags.javaWebFramework !== void 0) return Promise.resolve("java");
|
|
8356
9114
|
return getJavaLanguageChoice(flags.javaLanguage);
|
|
8357
9115
|
},
|
|
8358
9116
|
javaBuildTool: ({ results }) => {
|
|
8359
9117
|
if (results.ecosystem !== "java") return Promise.resolve("none");
|
|
8360
|
-
return getJavaBuildToolChoice(flags.javaBuildTool);
|
|
9118
|
+
return getJavaBuildToolChoice(flags.javaBuildTool, results.javaLanguage);
|
|
8361
9119
|
},
|
|
8362
9120
|
javaOrm: ({ results }) => {
|
|
8363
9121
|
if (results.ecosystem !== "java") return Promise.resolve("none");
|
|
8364
9122
|
if (results.javaWebFramework !== "spring-boot" || results.javaBuildTool === "none") return Promise.resolve("none");
|
|
8365
|
-
return getJavaOrmChoice(flags.javaOrm);
|
|
9123
|
+
return getJavaOrmChoice(flags.javaOrm, results.javaLanguage);
|
|
8366
9124
|
},
|
|
8367
9125
|
javaAuth: ({ results }) => {
|
|
8368
9126
|
if (results.ecosystem !== "java") return Promise.resolve("none");
|
|
@@ -8372,7 +9130,7 @@ async function gatherConfig(flags, projectName, projectDir, relativePath) {
|
|
|
8372
9130
|
javaApi: ({ results }) => {
|
|
8373
9131
|
if (results.ecosystem !== "java") return Promise.resolve("none");
|
|
8374
9132
|
if (results.javaWebFramework !== "spring-boot") return Promise.resolve("none");
|
|
8375
|
-
return getJavaApiChoice(flags.javaApi);
|
|
9133
|
+
return getJavaApiChoice(flags.javaApi, results.javaLanguage);
|
|
8376
9134
|
},
|
|
8377
9135
|
javaLogging: ({ results }) => {
|
|
8378
9136
|
if (results.ecosystem !== "java") return Promise.resolve("none");
|
|
@@ -8382,12 +9140,12 @@ async function gatherConfig(flags, projectName, projectDir, relativePath) {
|
|
|
8382
9140
|
javaLibraries: ({ results }) => {
|
|
8383
9141
|
if (results.ecosystem !== "java") return Promise.resolve([]);
|
|
8384
9142
|
if (results.javaWebFramework !== "spring-boot" || results.javaBuildTool === "none") return Promise.resolve([]);
|
|
8385
|
-
return getJavaLibrariesChoice(flags.javaLibraries);
|
|
9143
|
+
return getJavaLibrariesChoice(flags.javaLibraries, results.javaLanguage);
|
|
8386
9144
|
},
|
|
8387
9145
|
javaTestingLibraries: ({ results }) => {
|
|
8388
9146
|
if (results.ecosystem !== "java") return Promise.resolve([]);
|
|
8389
9147
|
if (results.javaBuildTool === "none") return Promise.resolve([]);
|
|
8390
|
-
return getJavaTestingLibrariesChoice(flags.javaTestingLibraries);
|
|
9148
|
+
return getJavaTestingLibrariesChoice(flags.javaTestingLibraries, results.javaLanguage);
|
|
8391
9149
|
},
|
|
8392
9150
|
dotnetWebFramework: ({ results }) => {
|
|
8393
9151
|
if (results.ecosystem !== "dotnet") return Promise.resolve("none");
|
|
@@ -8496,6 +9254,26 @@ async function gatherConfig(flags, projectName, projectDir, relativePath) {
|
|
|
8496
9254
|
if (results.ecosystem !== "elixir") return Promise.resolve("none");
|
|
8497
9255
|
return getElixirQualityChoice(flags.elixirQuality);
|
|
8498
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
|
+
},
|
|
8499
9277
|
elixirDeploy: ({ results }) => {
|
|
8500
9278
|
if (results.ecosystem !== "elixir") return Promise.resolve("none");
|
|
8501
9279
|
return getElixirDeployChoice(flags.elixirDeploy);
|
|
@@ -8530,7 +9308,7 @@ async function gatherConfig(flags, projectName, projectDir, relativePath) {
|
|
|
8530
9308
|
payments: result.payments,
|
|
8531
9309
|
email: result.email,
|
|
8532
9310
|
effect: result.effect,
|
|
8533
|
-
addons: result.addons,
|
|
9311
|
+
addons: Array.from(new Set([...result.appPlatforms ?? [], ...result.addons])),
|
|
8534
9312
|
examples: result.examples,
|
|
8535
9313
|
git: result.git,
|
|
8536
9314
|
packageManager: result.packageManager,
|
|
@@ -8608,6 +9386,12 @@ async function gatherConfig(flags, projectName, projectDir, relativePath) {
|
|
|
8608
9386
|
goCaching: result.goCaching,
|
|
8609
9387
|
goConfig: result.goConfig,
|
|
8610
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,
|
|
8611
9395
|
javaWebFramework: result.javaWebFramework,
|
|
8612
9396
|
javaLanguage: result.javaLanguage,
|
|
8613
9397
|
javaBuildTool: result.javaBuildTool,
|
|
@@ -8642,6 +9426,11 @@ async function gatherConfig(flags, projectName, projectDir, relativePath) {
|
|
|
8642
9426
|
elixirObservability: result.elixirObservability,
|
|
8643
9427
|
elixirTesting: result.elixirTesting,
|
|
8644
9428
|
elixirQuality: result.elixirQuality,
|
|
9429
|
+
elixirI18n: result.elixirI18n,
|
|
9430
|
+
elixirHttpServer: result.elixirHttpServer,
|
|
9431
|
+
elixirApplicationFramework: result.elixirApplicationFramework,
|
|
9432
|
+
elixirDocumentation: result.elixirDocumentation,
|
|
9433
|
+
elixirClustering: result.elixirClustering,
|
|
8645
9434
|
elixirDeploy: result.elixirDeploy,
|
|
8646
9435
|
elixirLibraries: result.elixirLibraries,
|
|
8647
9436
|
aiDocs: result.aiDocs
|
|
@@ -8892,6 +9681,11 @@ function displayConfig(config) {
|
|
|
8892
9681
|
if (config.elixirObservability && config.elixirObservability !== "none") configDisplay.push(`${pc.blue("Elixir Observability:")} ${String(config.elixirObservability)}`);
|
|
8893
9682
|
if (config.elixirTesting && config.elixirTesting !== "none") configDisplay.push(`${pc.blue("Elixir Testing:")} ${String(config.elixirTesting)}`);
|
|
8894
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)}`);
|
|
8895
9689
|
if (config.elixirDeploy && config.elixirDeploy !== "none") configDisplay.push(`${pc.blue("Elixir Deploy:")} ${String(config.elixirDeploy)}`);
|
|
8896
9690
|
}
|
|
8897
9691
|
if (config.observability !== void 0) configDisplay.push(`${pc.blue("Observability:")} ${String(config.observability)}`);
|
|
@@ -8945,6 +9739,17 @@ function displayConfig(config) {
|
|
|
8945
9739
|
return configDisplay.join("\n");
|
|
8946
9740
|
}
|
|
8947
9741
|
|
|
9742
|
+
//#endregion
|
|
9743
|
+
//#region src/utils/open-url.ts
|
|
9744
|
+
async function openUrl(url) {
|
|
9745
|
+
const platform = process.platform;
|
|
9746
|
+
if (platform === "darwin") await $({ stdio: "ignore" })`open ${url}`;
|
|
9747
|
+
else if (platform === "win32") {
|
|
9748
|
+
const escapedUrl = url.replace(/&/g, "^&");
|
|
9749
|
+
await $({ stdio: "ignore" })`cmd /c start "" ${escapedUrl}`;
|
|
9750
|
+
} else await $({ stdio: "ignore" })`xdg-open ${url}`;
|
|
9751
|
+
}
|
|
9752
|
+
|
|
8948
9753
|
//#endregion
|
|
8949
9754
|
//#region src/utils/preflight-display.ts
|
|
8950
9755
|
function displayPreflightWarnings({ warnings }) {
|
|
@@ -9048,17 +9853,6 @@ async function setupProjectDirectory(finalPathInput, shouldClearDirectory) {
|
|
|
9048
9853
|
};
|
|
9049
9854
|
}
|
|
9050
9855
|
|
|
9051
|
-
//#endregion
|
|
9052
|
-
//#region src/utils/open-url.ts
|
|
9053
|
-
async function openUrl(url) {
|
|
9054
|
-
const platform = process.platform;
|
|
9055
|
-
if (platform === "darwin") await $({ stdio: "ignore" })`open ${url}`;
|
|
9056
|
-
else if (platform === "win32") {
|
|
9057
|
-
const escapedUrl = url.replace(/&/g, "^&");
|
|
9058
|
-
await $({ stdio: "ignore" })`cmd /c start "" ${escapedUrl}`;
|
|
9059
|
-
} else await $({ stdio: "ignore" })`xdg-open ${url}`;
|
|
9060
|
-
}
|
|
9061
|
-
|
|
9062
9856
|
//#endregion
|
|
9063
9857
|
//#region src/validation.ts
|
|
9064
9858
|
const CORE_STACK_FLAGS = new Set([
|
|
@@ -10681,7 +11475,11 @@ function displayRustInstructions(config) {
|
|
|
10681
11475
|
if (rustWebFramework && rustWebFramework !== "none") output += `${pc.cyan("•")} Web Framework: ${{
|
|
10682
11476
|
actix: "Actix Web",
|
|
10683
11477
|
axum: "Axum",
|
|
10684
|
-
rocket: "Rocket"
|
|
11478
|
+
rocket: "Rocket",
|
|
11479
|
+
poem: "Poem",
|
|
11480
|
+
loco: "Loco",
|
|
11481
|
+
warp: "Warp",
|
|
11482
|
+
salvo: "Salvo"
|
|
10685
11483
|
}[rustWebFramework] || rustWebFramework}\n`;
|
|
10686
11484
|
if (rustFrontend && rustFrontend !== "none") output += `${pc.cyan("•")} Frontend: ${{
|
|
10687
11485
|
leptos: "Leptos",
|
|
@@ -10691,11 +11489,15 @@ function displayRustInstructions(config) {
|
|
|
10691
11489
|
if (rustOrm && rustOrm !== "none") output += `${pc.cyan("•")} Database: ${{
|
|
10692
11490
|
diesel: "Diesel",
|
|
10693
11491
|
sqlx: "SQLx",
|
|
10694
|
-
"sea-orm": "SeaORM"
|
|
11492
|
+
"sea-orm": "SeaORM",
|
|
11493
|
+
mongodb: "MongoDB Rust Driver",
|
|
11494
|
+
rusqlite: "rusqlite",
|
|
11495
|
+
"tokio-postgres": "tokio-postgres"
|
|
10695
11496
|
}[rustOrm] || rustOrm}\n`;
|
|
10696
11497
|
if (rustApi && rustApi !== "none") output += `${pc.cyan("•")} API: ${{
|
|
10697
11498
|
"async-graphql": "async-graphql",
|
|
10698
|
-
|
|
11499
|
+
tonic: "Tonic",
|
|
11500
|
+
jsonrpsee: "jsonrpsee"
|
|
10699
11501
|
}[rustApi] || rustApi}\n`;
|
|
10700
11502
|
if (rustCli && rustCli !== "none") output += `${pc.cyan("•")} CLI: ${{
|
|
10701
11503
|
clap: "Clap",
|
|
@@ -10731,7 +11533,7 @@ function displayRustInstructions(config) {
|
|
|
10731
11533
|
consola$1.box(output);
|
|
10732
11534
|
}
|
|
10733
11535
|
function displayGoInstructions(config) {
|
|
10734
|
-
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;
|
|
10735
11537
|
const cdCmd = `cd ${relativePath}`;
|
|
10736
11538
|
let output = `${pc.bold("Next steps")}\n${pc.cyan("1.")} ${cdCmd}\n`;
|
|
10737
11539
|
let stepCounter = 2;
|
|
@@ -10742,14 +11544,25 @@ function displayGoInstructions(config) {
|
|
|
10742
11544
|
gin: "Gin",
|
|
10743
11545
|
echo: "Echo",
|
|
10744
11546
|
fiber: "Fiber",
|
|
10745
|
-
chi: "Chi"
|
|
11547
|
+
chi: "Chi",
|
|
11548
|
+
stdlib: "net/http",
|
|
11549
|
+
"go-zero": "go-zero",
|
|
11550
|
+
kratos: "Kratos",
|
|
11551
|
+
httprouter: "HttpRouter"
|
|
10746
11552
|
}[goWebFramework] || goWebFramework}\n`;
|
|
10747
11553
|
if (goOrm && goOrm !== "none") output += `${pc.cyan("•")} Database: ${{
|
|
10748
11554
|
gorm: "GORM",
|
|
10749
11555
|
sqlc: "sqlc",
|
|
10750
|
-
ent: "Ent"
|
|
11556
|
+
ent: "Ent",
|
|
11557
|
+
bun: "Bun",
|
|
11558
|
+
sqlx: "sqlx"
|
|
10751
11559
|
}[goOrm] || goOrm}\n`;
|
|
10752
|
-
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`;
|
|
10753
11566
|
if (goCli && goCli !== "none") output += `${pc.cyan("•")} CLI: ${{
|
|
10754
11567
|
cobra: "Cobra",
|
|
10755
11568
|
bubbletea: "Bubble Tea",
|
|
@@ -10762,8 +11575,25 @@ function displayGoInstructions(config) {
|
|
|
10762
11575
|
}[goLogging] || goLogging}\n`;
|
|
10763
11576
|
if (goAuth && goAuth !== "none") output += `${pc.cyan("•")} Auth: ${{
|
|
10764
11577
|
casbin: "Casbin",
|
|
10765
|
-
jwt: "golang-jwt"
|
|
11578
|
+
jwt: "golang-jwt",
|
|
11579
|
+
goth: "Goth",
|
|
11580
|
+
oauth2: "x/oauth2"
|
|
10766
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
|
+
}
|
|
10767
11597
|
output += `\n${pc.bold("Common Go commands:")}\n`;
|
|
10768
11598
|
output += `${pc.cyan("•")} Build: go build ./...\n`;
|
|
10769
11599
|
output += `${pc.cyan("•")} Run: go run cmd/server/main.go\n`;
|
|
@@ -11058,7 +11888,7 @@ async function createProject(options, cliInput = {}) {
|
|
|
11058
11888
|
await applyDependencyVersionChannel(projectDir, options.versionChannel);
|
|
11059
11889
|
await writeBtsConfig(options);
|
|
11060
11890
|
await formatProject(projectDir);
|
|
11061
|
-
await recordScaffoldManifest(projectDir);
|
|
11891
|
+
await recordScaffoldManifest(projectDir, { baselines: collectStructuredBaselines(result.tree) });
|
|
11062
11892
|
if (!isSilent()) log.success("Project template successfully scaffolded!");
|
|
11063
11893
|
if (options.install && (options.ecosystem === "typescript" || options.ecosystem === "react-native")) {
|
|
11064
11894
|
const result$1 = await installDependencies({
|
|
@@ -11221,6 +12051,8 @@ function getYesBaseConfig(flagConfig) {
|
|
|
11221
12051
|
frontend: ["native-bare"],
|
|
11222
12052
|
addons: [],
|
|
11223
12053
|
examples: [],
|
|
12054
|
+
database: "none",
|
|
12055
|
+
orm: "none",
|
|
11224
12056
|
auth: "none",
|
|
11225
12057
|
payments: "none",
|
|
11226
12058
|
email: "none",
|
|
@@ -11258,10 +12090,23 @@ function getYesBaseConfig(flagConfig) {
|
|
|
11258
12090
|
mobileDeepLinking: "none"
|
|
11259
12091
|
};
|
|
11260
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
|
+
}
|
|
11261
12098
|
function shouldPromptForVersionChannel(input, hasConfigBase) {
|
|
11262
12099
|
if (input.yes || input.part?.length || hasConfigBase || input.versionChannel !== void 0 || isSilent()) return false;
|
|
11263
12100
|
return canPromptInteractively();
|
|
11264
12101
|
}
|
|
12102
|
+
function normalizeKotlinJavaSelection(config) {
|
|
12103
|
+
if (!config.stackParts?.some((part) => part.role === "backend" && part.ecosystem === "java" && !part.ownerPartId && part.source !== "provided") && config.ecosystem !== "java" || config.javaLanguage !== "kotlin") return;
|
|
12104
|
+
const kotlinBlocker = (0, types_exports.getKotlinJavaIncompatibilityReason)(config);
|
|
12105
|
+
if (!kotlinBlocker) return;
|
|
12106
|
+
config.javaLanguage = "java";
|
|
12107
|
+
if (config.stackParts) config.stackParts = config.stackParts.filter((part) => !(part.role === "language" && part.ecosystem === "java" && part.toolId === "kotlin" && part.source !== "provided"));
|
|
12108
|
+
if (!isSilent()) log.warn(pc.yellow(`JVM language set to Java: ${kotlinBlocker}`));
|
|
12109
|
+
}
|
|
11265
12110
|
async function createProjectHandler(input, options = {}) {
|
|
11266
12111
|
const { silent = false } = options;
|
|
11267
12112
|
return runWithContextAsync({ silent }, async () => {
|
|
@@ -11416,6 +12261,12 @@ async function createProjectHandler(input, options = {}) {
|
|
|
11416
12261
|
goCaching: "none",
|
|
11417
12262
|
goConfig: "none",
|
|
11418
12263
|
goObservability: "none",
|
|
12264
|
+
goValidation: "none",
|
|
12265
|
+
goQuality: "none",
|
|
12266
|
+
goMigrations: "none",
|
|
12267
|
+
goTemplating: "none",
|
|
12268
|
+
goProtoTooling: "none",
|
|
12269
|
+
goDI: "none",
|
|
11419
12270
|
javaWebFramework: "none",
|
|
11420
12271
|
javaBuildTool: "none",
|
|
11421
12272
|
javaOrm: "none",
|
|
@@ -11449,6 +12300,11 @@ async function createProjectHandler(input, options = {}) {
|
|
|
11449
12300
|
elixirObservability: "none",
|
|
11450
12301
|
elixirTesting: "none",
|
|
11451
12302
|
elixirQuality: "none",
|
|
12303
|
+
elixirI18n: "none",
|
|
12304
|
+
elixirHttpServer: "none",
|
|
12305
|
+
elixirApplicationFramework: "none",
|
|
12306
|
+
elixirDocumentation: "none",
|
|
12307
|
+
elixirClustering: "none",
|
|
11452
12308
|
elixirDeploy: "none",
|
|
11453
12309
|
elixirLibraries: [],
|
|
11454
12310
|
aiDocs: []
|
|
@@ -11508,6 +12364,20 @@ async function createProjectHandler(input, options = {}) {
|
|
|
11508
12364
|
relativePath: currentPathInput,
|
|
11509
12365
|
versionChannel
|
|
11510
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
|
+
}
|
|
11511
12381
|
validateConfigCompatibility(config, providedFlags, cliInput);
|
|
11512
12382
|
const yesPreflight = validatePreflightConfig(config);
|
|
11513
12383
|
if (yesPreflight.hasWarnings && !isSilent()) displayPreflightWarnings(yesPreflight);
|
|
@@ -11527,8 +12397,23 @@ async function createProjectHandler(input, options = {}) {
|
|
|
11527
12397
|
...await gatherConfig(flagConfig, finalBaseName, finalResolvedPath, currentPathInput),
|
|
11528
12398
|
versionChannel
|
|
11529
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
|
+
}
|
|
11530
12414
|
validateConfigCompatibility(config, providedFlags, cliInput);
|
|
11531
12415
|
}
|
|
12416
|
+
normalizeKotlinJavaSelection(config);
|
|
11532
12417
|
const preflight = validatePreflightConfig(config);
|
|
11533
12418
|
if (preflight.hasWarnings && !isSilent()) displayPreflightWarnings(preflight);
|
|
11534
12419
|
if (input.dryRun) {
|
|
@@ -11789,7 +12674,7 @@ const router = os.router({
|
|
|
11789
12674
|
}
|
|
11790
12675
|
}),
|
|
11791
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 }) => {
|
|
11792
|
-
const { addHandler } = await import("./add-handler-
|
|
12677
|
+
const { addHandler } = await import("./add-handler-CE3XIs3y.mjs");
|
|
11793
12678
|
await addHandler(input);
|
|
11794
12679
|
}),
|
|
11795
12680
|
history: os.meta({ description: "Show history of scaffolded projects with reproducible commands" }).input(z.object({
|
|
@@ -11838,7 +12723,7 @@ const router = os.router({
|
|
|
11838
12723
|
})
|
|
11839
12724
|
])).handler(async ({ input }) => {
|
|
11840
12725
|
const [kind, name, options] = input;
|
|
11841
|
-
const { genCommand } = await import("./gen-
|
|
12726
|
+
const { genCommand } = await import("./gen-BZ0QCxCC.mjs");
|
|
11842
12727
|
await genCommand({
|
|
11843
12728
|
kind,
|
|
11844
12729
|
name,
|
|
@@ -11856,7 +12741,7 @@ const router = os.router({
|
|
|
11856
12741
|
})
|
|
11857
12742
|
])).handler(async ({ input }) => {
|
|
11858
12743
|
const [action, source, options] = input;
|
|
11859
|
-
const { registryHandler } = await import("./registry-
|
|
12744
|
+
const { registryHandler } = await import("./registry-Cm3D45oT.mjs");
|
|
11860
12745
|
await registryHandler({
|
|
11861
12746
|
action,
|
|
11862
12747
|
source,
|
|
@@ -11873,7 +12758,7 @@ const router = os.router({
|
|
|
11873
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)")
|
|
11874
12759
|
})])).handler(async ({ input }) => {
|
|
11875
12760
|
const [projectDir, options] = input;
|
|
11876
|
-
const { updateCommand } = await import("./update-
|
|
12761
|
+
const { updateCommand } = await import("./update-B270pWHc.mjs");
|
|
11877
12762
|
await updateCommand({
|
|
11878
12763
|
projectDir,
|
|
11879
12764
|
...options
|
|
@@ -11885,7 +12770,7 @@ const router = os.router({
|
|
|
11885
12770
|
}),
|
|
11886
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 }) => {
|
|
11887
12772
|
const [projectDir, options] = input;
|
|
11888
|
-
const { doctorCommand } = await import("./doctor-
|
|
12773
|
+
const { doctorCommand } = await import("./doctor-Cc7sLuow.mjs");
|
|
11889
12774
|
await doctorCommand({
|
|
11890
12775
|
projectDir,
|
|
11891
12776
|
...options
|
|
@@ -11893,7 +12778,7 @@ const router = os.router({
|
|
|
11893
12778
|
}),
|
|
11894
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 }) => {
|
|
11895
12780
|
const [projectDir, options] = input;
|
|
11896
|
-
const { doctorCommand } = await import("./doctor-
|
|
12781
|
+
const { doctorCommand } = await import("./doctor-Cc7sLuow.mjs");
|
|
11897
12782
|
await doctorCommand({
|
|
11898
12783
|
projectDir,
|
|
11899
12784
|
...options
|
|
@@ -11904,7 +12789,7 @@ const router = os.router({
|
|
|
11904
12789
|
ecosystem: z.string().optional().describe("Force an ecosystem (typescript, react-native, rust, go, python, java, ...)"),
|
|
11905
12790
|
json: z.boolean().default(false).describe("Output the recommendation as JSON")
|
|
11906
12791
|
})).handler(async ({ input }) => {
|
|
11907
|
-
const { recommendStackFromBrief } = await import("./mcp-
|
|
12792
|
+
const { recommendStackFromBrief } = await import("./mcp-DNKAo8nO.mjs");
|
|
11908
12793
|
const result = recommendStackFromBrief(input.brief, input.ecosystem);
|
|
11909
12794
|
if (input.json) {
|
|
11910
12795
|
log.message(JSON.stringify(result, null, 2));
|
|
@@ -11980,7 +12865,7 @@ async function builder() {
|
|
|
11980
12865
|
return caller.builder();
|
|
11981
12866
|
}
|
|
11982
12867
|
async function add(input, options) {
|
|
11983
|
-
const { addHandler } = await import("./add-handler-
|
|
12868
|
+
const { addHandler } = await import("./add-handler-CE3XIs3y.mjs");
|
|
11984
12869
|
return addHandler(input, {
|
|
11985
12870
|
silent: true,
|
|
11986
12871
|
telemetrySource: options?.telemetrySource ?? "programmatic"
|