create-better-fullstack 1.6.0 → 1.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -8
- package/dist/addons-setup-CBK1Htlc.mjs +5 -0
- package/dist/{addons-setup--oB72n29.mjs → addons-setup-DQa6TRrx.mjs} +174 -104
- package/dist/{bts-config-snHxP_EH.mjs → bts-config-B_rZ4_sj.mjs} +21 -73
- package/dist/cli.mjs +1 -1
- package/dist/index.d.mts +99 -9
- package/dist/index.mjs +2611 -1198
- package/dist/{mcp-Bx_Esljk.mjs → mcp-CuEEG8e5.mjs} +1 -1
- package/dist/mcp-entry.mjs +88 -21
- package/dist/virtual.d.mts +1 -1
- package/package.json +24 -9
- package/dist/addons-setup-By7Kqjss.mjs +0 -5
package/dist/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { t as __reExport } from "./chunk-CCII7kTE.mjs";
|
|
3
|
-
import { a as DEFAULT_CONFIG, c as getDefaultConfig, i as getLatestCLIVersion, l as getUserPkgManager, n as updateBtsConfig, o as DEFAULT_UI_LIBRARY_BY_FRONTEND, r as writeBtsConfig, t as readBtsConfig } from "./bts-config-
|
|
4
|
-
import { _ as
|
|
3
|
+
import { a as DEFAULT_CONFIG, c as getDefaultConfig, i as getLatestCLIVersion, l as getUserPkgManager, n as updateBtsConfig, o as DEFAULT_UI_LIBRARY_BY_FRONTEND, r as writeBtsConfig, t as readBtsConfig } from "./bts-config-B_rZ4_sj.mjs";
|
|
4
|
+
import { _ as setIsFirstPrompt$1, a as canPromptInteractively, c as CLIError, d as exitWithError, f as handleError, g as runWithContextAsync, h as isSilent, l as UserCancelledError, m as isFirstPrompt, o as getPackageExecutionArgs, p as didLastPromptShowUI, s as addPackageDependency, t as setupAddons, u as exitCancelled, v as setLastPromptShownUI } from "./addons-setup-DQa6TRrx.mjs";
|
|
5
5
|
import { cancel, confirm, intro, isCancel, log, outro, select, spinner, text } from "@clack/prompts";
|
|
6
6
|
import { createRouterClient, os } from "@orpc/server";
|
|
7
7
|
import pc from "picocolors";
|
|
@@ -10,11 +10,11 @@ import z from "zod";
|
|
|
10
10
|
import envPaths from "env-paths";
|
|
11
11
|
import fs from "fs-extra";
|
|
12
12
|
import path from "node:path";
|
|
13
|
+
import { allowedApisForFrontends, getCompatibleAddons, getCompatibleCSSFrameworks, getCompatibleUILibraries, getLocalWebDevPort, hasWebStyling, isExampleAIAllowed, isExampleChatSdkAllowed, isFrontendAllowedWithBackend, isWebFrontend, requiresChatSdkVercelAIForSelection, splitFrontends, validateAddonCompatibility } from "@better-fullstack/types";
|
|
13
14
|
import { ECOSYSTEM_GROUPS, EMBEDDED_TEMPLATES, EMBEDDED_TEMPLATES as EMBEDDED_TEMPLATES$1, TEMPLATE_COUNT, VirtualFileSystem, VirtualFileSystem as VirtualFileSystem$1, checkAllVersions, generateCliReport, generateVirtualProject, generateVirtualProject as generateVirtualProject$1, listEcosystems, processAddonTemplates, processAddonsDeps, validatePreflightConfig } from "@better-fullstack/template-generator";
|
|
14
15
|
import gradient from "gradient-string";
|
|
15
16
|
import path$1 from "path";
|
|
16
17
|
import { writeTreeToFilesystem } from "@better-fullstack/template-generator/fs-writer";
|
|
17
|
-
import { allowedApisForFrontends, getCompatibleAddons, getCompatibleCSSFrameworks, getCompatibleUILibraries, getLocalWebDevPort, hasWebStyling, isExampleAIAllowed, isExampleChatSdkAllowed, isFrontendAllowedWithBackend, isWebFrontend, requiresChatSdkVercelAIForSelection, splitFrontends, validateAddonCompatibility } from "@better-fullstack/types";
|
|
18
18
|
import consola, { consola as consola$1 } from "consola";
|
|
19
19
|
import { ConfirmPrompt, GroupMultiSelectPrompt, MultiSelectPrompt, SelectPrompt, isCancel as isCancel$1 } from "@clack/core";
|
|
20
20
|
import { $, execa } from "execa";
|
|
@@ -354,6 +354,100 @@ var types_exports = {};
|
|
|
354
354
|
import * as import__better_fullstack_types from "@better-fullstack/types";
|
|
355
355
|
__reExport(types_exports, import__better_fullstack_types);
|
|
356
356
|
|
|
357
|
+
//#endregion
|
|
358
|
+
//#region src/create-command-input.ts
|
|
359
|
+
const CreateCommandOptionsSchema = z.object({
|
|
360
|
+
template: types_exports.TemplateSchema.optional().describe("Use a predefined template"),
|
|
361
|
+
yes: z.boolean().optional().default(false).describe("Use default configuration"),
|
|
362
|
+
yolo: z.boolean().optional().default(false).describe("(WARNING - NOT RECOMMENDED) Bypass validations and compatibility checks"),
|
|
363
|
+
verbose: z.boolean().optional().default(false).describe("Show detailed result information"),
|
|
364
|
+
dryRun: z.boolean().optional().default(false).describe("Preview generated file tree without writing to disk"),
|
|
365
|
+
ecosystem: types_exports.EcosystemSchema.optional().describe("Language ecosystem (typescript, rust, python, go, or java)"),
|
|
366
|
+
database: types_exports.DatabaseSchema.optional(),
|
|
367
|
+
orm: types_exports.ORMSchema.optional(),
|
|
368
|
+
auth: types_exports.AuthSchema.optional(),
|
|
369
|
+
payments: types_exports.PaymentsSchema.optional(),
|
|
370
|
+
email: types_exports.EmailSchema.optional(),
|
|
371
|
+
fileUpload: types_exports.FileUploadSchema.optional(),
|
|
372
|
+
effect: types_exports.EffectSchema.optional(),
|
|
373
|
+
stateManagement: types_exports.StateManagementSchema.optional(),
|
|
374
|
+
validation: types_exports.ValidationSchema.optional(),
|
|
375
|
+
forms: types_exports.FormsSchema.optional(),
|
|
376
|
+
testing: types_exports.TestingSchema.optional(),
|
|
377
|
+
ai: types_exports.AISchema.optional(),
|
|
378
|
+
realtime: types_exports.RealtimeSchema.optional(),
|
|
379
|
+
jobQueue: types_exports.JobQueueSchema.optional(),
|
|
380
|
+
animation: types_exports.AnimationSchema.optional(),
|
|
381
|
+
logging: types_exports.LoggingSchema.optional(),
|
|
382
|
+
observability: types_exports.ObservabilitySchema.optional(),
|
|
383
|
+
featureFlags: types_exports.FeatureFlagsSchema.optional().describe("Feature flags provider"),
|
|
384
|
+
analytics: types_exports.AnalyticsSchema.optional().describe("Privacy-focused analytics"),
|
|
385
|
+
cms: types_exports.CMSSchema.optional().describe("Headless CMS solution"),
|
|
386
|
+
caching: types_exports.CachingSchema.optional().describe("Caching solution"),
|
|
387
|
+
i18n: types_exports.I18nSchema.optional().describe("Internationalization (i18n) library"),
|
|
388
|
+
search: types_exports.SearchSchema.optional().describe("Search engine solution"),
|
|
389
|
+
fileStorage: types_exports.FileStorageSchema.optional().describe("File storage solution (S3, R2)"),
|
|
390
|
+
frontend: z.array(types_exports.FrontendSchema).optional(),
|
|
391
|
+
astroIntegration: types_exports.AstroIntegrationSchema.optional().describe("Astro UI framework integration (react, vue, svelte, solid)"),
|
|
392
|
+
addons: z.array(types_exports.AddonsSchema).optional(),
|
|
393
|
+
examples: z.array(types_exports.ExamplesSchema).optional(),
|
|
394
|
+
git: z.boolean().optional(),
|
|
395
|
+
packageManager: types_exports.PackageManagerSchema.optional(),
|
|
396
|
+
install: z.boolean().optional(),
|
|
397
|
+
versionChannel: types_exports.VersionChannelSchema.optional().describe("Dependency version channel (stable, latest, beta)"),
|
|
398
|
+
dbSetup: types_exports.DatabaseSetupSchema.optional(),
|
|
399
|
+
backend: types_exports.BackendSchema.optional(),
|
|
400
|
+
runtime: types_exports.RuntimeSchema.optional(),
|
|
401
|
+
api: types_exports.APISchema.optional(),
|
|
402
|
+
cssFramework: types_exports.CSSFrameworkSchema.optional(),
|
|
403
|
+
uiLibrary: types_exports.UILibrarySchema.optional(),
|
|
404
|
+
shadcnBase: types_exports.ShadcnBaseSchema.optional().describe("shadcn/ui headless library (radix, base)"),
|
|
405
|
+
shadcnStyle: types_exports.ShadcnStyleSchema.optional().describe("shadcn/ui visual style (vega, nova, maia, lyra, mira)"),
|
|
406
|
+
shadcnIconLibrary: types_exports.ShadcnIconLibrarySchema.optional().describe("shadcn/ui icon library (lucide, tabler, hugeicons, phosphor, remixicon)"),
|
|
407
|
+
shadcnColorTheme: types_exports.ShadcnColorThemeSchema.optional().describe("shadcn/ui color theme (neutral, blue, violet, etc.)"),
|
|
408
|
+
shadcnBaseColor: types_exports.ShadcnBaseColorSchema.optional().describe("shadcn/ui base neutral color (neutral, stone, zinc, gray)"),
|
|
409
|
+
shadcnFont: types_exports.ShadcnFontSchema.optional().describe("shadcn/ui font (inter, geist, figtree, etc.)"),
|
|
410
|
+
shadcnRadius: types_exports.ShadcnRadiusSchema.optional().describe("shadcn/ui border radius (default, none, small, medium, large)"),
|
|
411
|
+
webDeploy: types_exports.WebDeploySchema.optional(),
|
|
412
|
+
serverDeploy: types_exports.ServerDeploySchema.optional(),
|
|
413
|
+
directoryConflict: types_exports.DirectoryConflictSchema.optional(),
|
|
414
|
+
renderTitle: z.boolean().optional(),
|
|
415
|
+
disableAnalytics: z.boolean().optional().default(false).describe("Disable analytics"),
|
|
416
|
+
manualDb: z.boolean().optional().default(false).describe("Skip automatic/manual database setup prompt and use manual setup"),
|
|
417
|
+
rustWebFramework: types_exports.RustWebFrameworkSchema.optional().describe("Rust web framework (axum, actix-web)"),
|
|
418
|
+
rustFrontend: types_exports.RustFrontendSchema.optional().describe("Rust WASM frontend (leptos, dioxus)"),
|
|
419
|
+
rustOrm: types_exports.RustOrmSchema.optional().describe("Rust ORM/database (sea-orm, sqlx)"),
|
|
420
|
+
rustApi: types_exports.RustApiSchema.optional().describe("Rust API layer (tonic, async-graphql)"),
|
|
421
|
+
rustCli: types_exports.RustCliSchema.optional().describe("Rust CLI tools (clap, ratatui)"),
|
|
422
|
+
rustLibraries: z.array(types_exports.RustLibrariesSchema).optional().describe("Rust core libraries"),
|
|
423
|
+
rustLogging: types_exports.RustLoggingSchema.optional().describe("Rust logging (tracing, env-logger)"),
|
|
424
|
+
rustErrorHandling: types_exports.RustErrorHandlingSchema.optional().describe("Rust error handling (anyhow-thiserror, eyre)"),
|
|
425
|
+
rustCaching: types_exports.RustCachingSchema.optional().describe("Rust caching (moka, redis)"),
|
|
426
|
+
rustAuth: types_exports.RustAuthSchema.optional().describe("Rust auth (oauth2)"),
|
|
427
|
+
pythonWebFramework: types_exports.PythonWebFrameworkSchema.optional().describe("Python web framework (fastapi, django)"),
|
|
428
|
+
pythonOrm: types_exports.PythonOrmSchema.optional().describe("Python ORM/database (sqlalchemy, sqlmodel)"),
|
|
429
|
+
pythonValidation: types_exports.PythonValidationSchema.optional().describe("Python validation (pydantic)"),
|
|
430
|
+
pythonAi: z.array(types_exports.PythonAiSchema).optional().describe("Python AI/ML frameworks"),
|
|
431
|
+
pythonAuth: types_exports.PythonAuthSchema.optional().describe("Python auth library (authlib, jwt)"),
|
|
432
|
+
pythonTaskQueue: types_exports.PythonTaskQueueSchema.optional().describe("Python task queue (celery)"),
|
|
433
|
+
pythonGraphql: types_exports.PythonGraphqlSchema.optional().describe("Python GraphQL framework (strawberry)"),
|
|
434
|
+
pythonQuality: types_exports.PythonQualitySchema.optional().describe("Python code quality (ruff)"),
|
|
435
|
+
goWebFramework: types_exports.GoWebFrameworkSchema.optional().describe("Go web framework (gin, echo, fiber)"),
|
|
436
|
+
goOrm: types_exports.GoOrmSchema.optional().describe("Go ORM/database (gorm, sqlc)"),
|
|
437
|
+
goApi: types_exports.GoApiSchema.optional().describe("Go API layer (grpc-go)"),
|
|
438
|
+
goCli: types_exports.GoCliSchema.optional().describe("Go CLI tools (cobra, bubbletea)"),
|
|
439
|
+
goLogging: types_exports.GoLoggingSchema.optional().describe("Go logging (zap, zerolog, slog)"),
|
|
440
|
+
goAuth: types_exports.GoAuthSchema.optional().describe("Go auth (casbin, jwt)"),
|
|
441
|
+
javaWebFramework: types_exports.JavaWebFrameworkSchema.optional().describe("Java web framework (spring-boot, none)"),
|
|
442
|
+
javaBuildTool: types_exports.JavaBuildToolSchema.optional().describe("Java build tool (maven, gradle, none)"),
|
|
443
|
+
javaOrm: types_exports.JavaOrmSchema.optional().describe("Java ORM/database (spring-data-jpa)"),
|
|
444
|
+
javaAuth: types_exports.JavaAuthSchema.optional().describe("Java auth (spring-security)"),
|
|
445
|
+
javaLibraries: z.array(types_exports.JavaLibrariesSchema).optional().describe("Java application libraries"),
|
|
446
|
+
javaTestingLibraries: z.array(types_exports.JavaTestingLibrariesSchema).optional().describe("Java testing libraries"),
|
|
447
|
+
aiDocs: z.array(types_exports.AiDocsSchema).optional().describe("AI documentation files (claude-md, agents-md, cursorrules)")
|
|
448
|
+
});
|
|
449
|
+
const CreateCommandInputSchema = z.tuple([types_exports.ProjectNameSchema.optional(), CreateCommandOptionsSchema]);
|
|
450
|
+
|
|
357
451
|
//#endregion
|
|
358
452
|
//#region src/utils/error-formatter.ts
|
|
359
453
|
function getCategoryTitle(category) {
|
|
@@ -1341,12 +1435,23 @@ async function applyDependencyVersionChannel(projectDir, channel) {
|
|
|
1341
1435
|
|
|
1342
1436
|
//#endregion
|
|
1343
1437
|
//#region src/helpers/core/install-dependencies.ts
|
|
1438
|
+
function getInstallEnvironment(packageManager) {
|
|
1439
|
+
if (packageManager !== "yarn") return;
|
|
1440
|
+
return {
|
|
1441
|
+
YARN_ENABLE_HARDENED_MODE: "0",
|
|
1442
|
+
YARN_ENABLE_IMMUTABLE_INSTALLS: "false"
|
|
1443
|
+
};
|
|
1444
|
+
}
|
|
1344
1445
|
async function installDependencies({ projectDir, packageManager }) {
|
|
1345
1446
|
const s = spinner();
|
|
1346
1447
|
try {
|
|
1347
1448
|
s.start(`Running ${packageManager} install...`);
|
|
1348
1449
|
await $({
|
|
1349
1450
|
cwd: projectDir,
|
|
1451
|
+
env: {
|
|
1452
|
+
...process.env,
|
|
1453
|
+
...getInstallEnvironment(packageManager)
|
|
1454
|
+
},
|
|
1350
1455
|
stderr: "inherit"
|
|
1351
1456
|
})`${packageManager} install`;
|
|
1352
1457
|
s.stop("Dependencies installed successfully");
|
|
@@ -1397,6 +1502,36 @@ async function runGoModTidy({ projectDir }) {
|
|
|
1397
1502
|
if (error instanceof Error) consola.error(pc.red(`go mod tidy error: ${error.message}`));
|
|
1398
1503
|
}
|
|
1399
1504
|
}
|
|
1505
|
+
async function runMavenTests({ projectDir }) {
|
|
1506
|
+
const s = spinner();
|
|
1507
|
+
const mvnw = process.platform === "win32" ? "mvnw.cmd" : "./mvnw";
|
|
1508
|
+
try {
|
|
1509
|
+
s.start("Running Maven tests...");
|
|
1510
|
+
await $({
|
|
1511
|
+
cwd: projectDir,
|
|
1512
|
+
stderr: "inherit"
|
|
1513
|
+
})`${mvnw} test`;
|
|
1514
|
+
s.stop("Maven tests completed");
|
|
1515
|
+
} catch (error) {
|
|
1516
|
+
s.stop(pc.red("Maven tests failed"));
|
|
1517
|
+
if (error instanceof Error) consola.error(pc.red(`Maven test error: ${error.message}`));
|
|
1518
|
+
}
|
|
1519
|
+
}
|
|
1520
|
+
async function runGradleTests({ projectDir }) {
|
|
1521
|
+
const s = spinner();
|
|
1522
|
+
const gradlew = process.platform === "win32" ? "gradlew.bat" : "./gradlew";
|
|
1523
|
+
try {
|
|
1524
|
+
s.start("Running Gradle tests...");
|
|
1525
|
+
await $({
|
|
1526
|
+
cwd: projectDir,
|
|
1527
|
+
stderr: "inherit"
|
|
1528
|
+
})`${gradlew} test`;
|
|
1529
|
+
s.stop("Gradle tests completed");
|
|
1530
|
+
} catch (error) {
|
|
1531
|
+
s.stop(pc.red("Gradle tests failed"));
|
|
1532
|
+
if (error instanceof Error) consola.error(pc.red(`Gradle test error: ${error.message}`));
|
|
1533
|
+
}
|
|
1534
|
+
}
|
|
1400
1535
|
|
|
1401
1536
|
//#endregion
|
|
1402
1537
|
//#region src/helpers/core/add-handler.ts
|
|
@@ -1535,70 +1670,104 @@ async function collectPackageJsonPaths(projectDir) {
|
|
|
1535
1670
|
return results;
|
|
1536
1671
|
}
|
|
1537
1672
|
|
|
1673
|
+
//#endregion
|
|
1674
|
+
//#region src/prompts/prompt-contract.ts
|
|
1675
|
+
function createStaticSinglePromptResolution(options, initialValue, selectedValue) {
|
|
1676
|
+
return selectedValue !== void 0 ? {
|
|
1677
|
+
shouldPrompt: false,
|
|
1678
|
+
mode: "single",
|
|
1679
|
+
options,
|
|
1680
|
+
autoValue: selectedValue
|
|
1681
|
+
} : {
|
|
1682
|
+
shouldPrompt: true,
|
|
1683
|
+
mode: "single",
|
|
1684
|
+
options,
|
|
1685
|
+
initialValue
|
|
1686
|
+
};
|
|
1687
|
+
}
|
|
1688
|
+
function createStaticMultiPromptResolution(options, initialValue, selectedValue) {
|
|
1689
|
+
return selectedValue !== void 0 ? {
|
|
1690
|
+
shouldPrompt: false,
|
|
1691
|
+
mode: "multiple",
|
|
1692
|
+
options,
|
|
1693
|
+
autoValue: selectedValue
|
|
1694
|
+
} : {
|
|
1695
|
+
shouldPrompt: true,
|
|
1696
|
+
mode: "multiple",
|
|
1697
|
+
options,
|
|
1698
|
+
initialValue
|
|
1699
|
+
};
|
|
1700
|
+
}
|
|
1701
|
+
|
|
1538
1702
|
//#endregion
|
|
1539
1703
|
//#region src/prompts/ai.ts
|
|
1704
|
+
const AI_PROMPT_OPTIONS = [
|
|
1705
|
+
{
|
|
1706
|
+
value: "vercel-ai",
|
|
1707
|
+
label: "Vercel AI SDK",
|
|
1708
|
+
hint: "The AI Toolkit for TypeScript - supports OpenAI, Anthropic, Google, etc."
|
|
1709
|
+
},
|
|
1710
|
+
{
|
|
1711
|
+
value: "mastra",
|
|
1712
|
+
label: "Mastra",
|
|
1713
|
+
hint: "TypeScript-native AI agent framework with workflows"
|
|
1714
|
+
},
|
|
1715
|
+
{
|
|
1716
|
+
value: "voltagent",
|
|
1717
|
+
label: "VoltAgent",
|
|
1718
|
+
hint: "AI Agent framework with memory, workflows, and observability"
|
|
1719
|
+
},
|
|
1720
|
+
{
|
|
1721
|
+
value: "langgraph",
|
|
1722
|
+
label: "LangGraph.js",
|
|
1723
|
+
hint: "Graph-based agent orchestration with stateful workflows"
|
|
1724
|
+
},
|
|
1725
|
+
{
|
|
1726
|
+
value: "openai-agents",
|
|
1727
|
+
label: "OpenAI Agents SDK",
|
|
1728
|
+
hint: "Official multi-agent framework with handoffs and guardrails"
|
|
1729
|
+
},
|
|
1730
|
+
{
|
|
1731
|
+
value: "google-adk",
|
|
1732
|
+
label: "Google ADK",
|
|
1733
|
+
hint: "Code-first agent development kit for building AI agents"
|
|
1734
|
+
},
|
|
1735
|
+
{
|
|
1736
|
+
value: "modelfusion",
|
|
1737
|
+
label: "ModelFusion",
|
|
1738
|
+
hint: "Type-safe AI library for multi-provider text generation"
|
|
1739
|
+
},
|
|
1740
|
+
{
|
|
1741
|
+
value: "langchain",
|
|
1742
|
+
label: "LangChain",
|
|
1743
|
+
hint: "Build context-aware reasoning applications"
|
|
1744
|
+
},
|
|
1745
|
+
{
|
|
1746
|
+
value: "llamaindex",
|
|
1747
|
+
label: "LlamaIndex",
|
|
1748
|
+
hint: "Data framework for LLM applications"
|
|
1749
|
+
},
|
|
1750
|
+
{
|
|
1751
|
+
value: "tanstack-ai",
|
|
1752
|
+
label: "TanStack AI",
|
|
1753
|
+
hint: "Unified LLM interface for AI-powered apps (Alpha)"
|
|
1754
|
+
},
|
|
1755
|
+
{
|
|
1756
|
+
value: "none",
|
|
1757
|
+
label: "None",
|
|
1758
|
+
hint: "No AI SDK"
|
|
1759
|
+
}
|
|
1760
|
+
];
|
|
1761
|
+
function resolveAIPrompt(ai) {
|
|
1762
|
+
return createStaticSinglePromptResolution(AI_PROMPT_OPTIONS, "none", ai);
|
|
1763
|
+
}
|
|
1540
1764
|
async function getAIChoice(ai) {
|
|
1541
|
-
|
|
1765
|
+
const resolution = resolveAIPrompt(ai);
|
|
1766
|
+
if (!resolution.shouldPrompt) return resolution.autoValue ?? "none";
|
|
1542
1767
|
const response = await navigableSelect({
|
|
1543
1768
|
message: "Select AI SDK",
|
|
1544
|
-
options:
|
|
1545
|
-
|
|
1546
|
-
value: "vercel-ai",
|
|
1547
|
-
label: "Vercel AI SDK",
|
|
1548
|
-
hint: "The AI Toolkit for TypeScript - supports OpenAI, Anthropic, Google, etc."
|
|
1549
|
-
},
|
|
1550
|
-
{
|
|
1551
|
-
value: "mastra",
|
|
1552
|
-
label: "Mastra",
|
|
1553
|
-
hint: "TypeScript-native AI agent framework with workflows"
|
|
1554
|
-
},
|
|
1555
|
-
{
|
|
1556
|
-
value: "voltagent",
|
|
1557
|
-
label: "VoltAgent",
|
|
1558
|
-
hint: "AI Agent framework with memory, workflows, and observability"
|
|
1559
|
-
},
|
|
1560
|
-
{
|
|
1561
|
-
value: "langgraph",
|
|
1562
|
-
label: "LangGraph.js",
|
|
1563
|
-
hint: "Graph-based agent orchestration with stateful workflows"
|
|
1564
|
-
},
|
|
1565
|
-
{
|
|
1566
|
-
value: "openai-agents",
|
|
1567
|
-
label: "OpenAI Agents SDK",
|
|
1568
|
-
hint: "Official multi-agent framework with handoffs and guardrails"
|
|
1569
|
-
},
|
|
1570
|
-
{
|
|
1571
|
-
value: "google-adk",
|
|
1572
|
-
label: "Google ADK",
|
|
1573
|
-
hint: "Code-first agent development kit for building AI agents"
|
|
1574
|
-
},
|
|
1575
|
-
{
|
|
1576
|
-
value: "modelfusion",
|
|
1577
|
-
label: "ModelFusion",
|
|
1578
|
-
hint: "Type-safe AI library for multi-provider text generation"
|
|
1579
|
-
},
|
|
1580
|
-
{
|
|
1581
|
-
value: "langchain",
|
|
1582
|
-
label: "LangChain",
|
|
1583
|
-
hint: "Build context-aware reasoning applications"
|
|
1584
|
-
},
|
|
1585
|
-
{
|
|
1586
|
-
value: "llamaindex",
|
|
1587
|
-
label: "LlamaIndex",
|
|
1588
|
-
hint: "Data framework for LLM applications"
|
|
1589
|
-
},
|
|
1590
|
-
{
|
|
1591
|
-
value: "tanstack-ai",
|
|
1592
|
-
label: "TanStack AI",
|
|
1593
|
-
hint: "Unified LLM interface for AI-powered apps (Alpha)"
|
|
1594
|
-
},
|
|
1595
|
-
{
|
|
1596
|
-
value: "none",
|
|
1597
|
-
label: "None",
|
|
1598
|
-
hint: "No AI SDK"
|
|
1599
|
-
}
|
|
1600
|
-
],
|
|
1601
|
-
initialValue: "none"
|
|
1769
|
+
options: resolution.options,
|
|
1770
|
+
initialValue: resolution.initialValue
|
|
1602
1771
|
});
|
|
1603
1772
|
if (isCancel$1(response)) return exitCancelled("Operation cancelled");
|
|
1604
1773
|
return response;
|
|
@@ -1642,10 +1811,20 @@ async function getAiDocsChoice(aiDocs) {
|
|
|
1642
1811
|
|
|
1643
1812
|
//#endregion
|
|
1644
1813
|
//#region src/prompts/animation.ts
|
|
1645
|
-
|
|
1646
|
-
if (animation !== void 0) return
|
|
1647
|
-
|
|
1648
|
-
|
|
1814
|
+
function resolveAnimationPrompt(context = {}) {
|
|
1815
|
+
if (context.animation !== void 0) return {
|
|
1816
|
+
shouldPrompt: false,
|
|
1817
|
+
mode: "single",
|
|
1818
|
+
options: [],
|
|
1819
|
+
autoValue: context.animation
|
|
1820
|
+
};
|
|
1821
|
+
const { web } = splitFrontends$1(context.frontends);
|
|
1822
|
+
if (web.length === 0) return {
|
|
1823
|
+
shouldPrompt: false,
|
|
1824
|
+
mode: "single",
|
|
1825
|
+
options: [],
|
|
1826
|
+
autoValue: "none"
|
|
1827
|
+
};
|
|
1649
1828
|
const isReact = web.some((f) => [
|
|
1650
1829
|
"tanstack-router",
|
|
1651
1830
|
"react-router",
|
|
@@ -1684,10 +1863,23 @@ async function getAnimationChoice(animation, frontends) {
|
|
|
1684
1863
|
label: "None",
|
|
1685
1864
|
hint: "Skip animation library setup"
|
|
1686
1865
|
});
|
|
1687
|
-
|
|
1688
|
-
|
|
1866
|
+
return {
|
|
1867
|
+
shouldPrompt: true,
|
|
1868
|
+
mode: "single",
|
|
1689
1869
|
options,
|
|
1690
1870
|
initialValue: "none"
|
|
1871
|
+
};
|
|
1872
|
+
}
|
|
1873
|
+
async function getAnimationChoice(animation, frontends) {
|
|
1874
|
+
const resolution = resolveAnimationPrompt({
|
|
1875
|
+
animation,
|
|
1876
|
+
frontends
|
|
1877
|
+
});
|
|
1878
|
+
if (!resolution.shouldPrompt) return resolution.autoValue ?? "none";
|
|
1879
|
+
const response = await navigableSelect({
|
|
1880
|
+
message: "Select animation library",
|
|
1881
|
+
options: resolution.options,
|
|
1882
|
+
initialValue: resolution.initialValue
|
|
1691
1883
|
});
|
|
1692
1884
|
if (isCancel$1(response)) return exitCancelled("Operation cancelled");
|
|
1693
1885
|
return response;
|
|
@@ -1695,47 +1887,72 @@ async function getAnimationChoice(animation, frontends) {
|
|
|
1695
1887
|
|
|
1696
1888
|
//#endregion
|
|
1697
1889
|
//#region src/prompts/api.ts
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1890
|
+
const API_PROMPT_OPTION_MAP = {
|
|
1891
|
+
trpc: {
|
|
1892
|
+
value: "trpc",
|
|
1893
|
+
label: "tRPC",
|
|
1894
|
+
hint: "End-to-end typesafe APIs made easy"
|
|
1895
|
+
},
|
|
1896
|
+
orpc: {
|
|
1897
|
+
value: "orpc",
|
|
1898
|
+
label: "oRPC",
|
|
1899
|
+
hint: "End-to-end type-safe APIs that adhere to OpenAPI standards"
|
|
1900
|
+
},
|
|
1901
|
+
"ts-rest": {
|
|
1902
|
+
value: "ts-rest",
|
|
1903
|
+
label: "ts-rest",
|
|
1904
|
+
hint: "RPC-like client, contract, and server implementation for REST APIs"
|
|
1905
|
+
},
|
|
1906
|
+
garph: {
|
|
1907
|
+
value: "garph",
|
|
1908
|
+
label: "Garph",
|
|
1909
|
+
hint: "Fullstack GraphQL framework with end-to-end type safety"
|
|
1910
|
+
},
|
|
1911
|
+
"graphql-yoga": {
|
|
1912
|
+
value: "graphql-yoga",
|
|
1913
|
+
label: "GraphQL Yoga",
|
|
1914
|
+
hint: "Batteries-included GraphQL server with Pothos schema builder"
|
|
1915
|
+
},
|
|
1916
|
+
none: {
|
|
1917
|
+
value: "none",
|
|
1918
|
+
label: "None",
|
|
1919
|
+
hint: "No API layer (e.g. for full-stack frameworks like Next.js with Route Handlers)"
|
|
1920
|
+
}
|
|
1921
|
+
};
|
|
1922
|
+
function resolveApiPrompt(context = {}) {
|
|
1923
|
+
if (context.backend === "convex" || context.backend === "none") return {
|
|
1924
|
+
shouldPrompt: false,
|
|
1925
|
+
mode: "single",
|
|
1926
|
+
options: [],
|
|
1927
|
+
autoValue: "none"
|
|
1928
|
+
};
|
|
1929
|
+
const allowedOptions = allowedApisForFrontends$1(context.frontend ?? [], context.astroIntegration);
|
|
1930
|
+
const options = allowedOptions.map((value) => API_PROMPT_OPTION_MAP[value]);
|
|
1931
|
+
if (context.api !== void 0) return {
|
|
1932
|
+
shouldPrompt: false,
|
|
1933
|
+
mode: "single",
|
|
1934
|
+
options,
|
|
1935
|
+
autoValue: allowedOptions.includes(context.api) ? context.api : allowedOptions[0] ?? "none"
|
|
1733
1936
|
};
|
|
1734
|
-
|
|
1937
|
+
return {
|
|
1938
|
+
shouldPrompt: true,
|
|
1939
|
+
mode: "single",
|
|
1940
|
+
options,
|
|
1941
|
+
initialValue: allowedOptions[0] ?? "none"
|
|
1942
|
+
};
|
|
1943
|
+
}
|
|
1944
|
+
async function getApiChoice(api, frontend, backend, astroIntegration) {
|
|
1945
|
+
const resolution = resolveApiPrompt({
|
|
1946
|
+
api,
|
|
1947
|
+
frontend,
|
|
1948
|
+
backend,
|
|
1949
|
+
astroIntegration
|
|
1950
|
+
});
|
|
1951
|
+
if (!resolution.shouldPrompt) return resolution.autoValue ?? "none";
|
|
1735
1952
|
const apiType = await navigableSelect({
|
|
1736
1953
|
message: "Select API type",
|
|
1737
|
-
options:
|
|
1738
|
-
initialValue:
|
|
1954
|
+
options: resolution.options,
|
|
1955
|
+
initialValue: resolution.initialValue
|
|
1739
1956
|
});
|
|
1740
1957
|
if (isCancel$1(apiType)) return exitCancelled("Operation cancelled");
|
|
1741
1958
|
return apiType;
|
|
@@ -1743,38 +1960,43 @@ async function getApiChoice(Api, frontend, backend, astroIntegration) {
|
|
|
1743
1960
|
|
|
1744
1961
|
//#endregion
|
|
1745
1962
|
//#region src/prompts/astro-integration.ts
|
|
1963
|
+
const ASTRO_INTEGRATION_PROMPT_OPTIONS = [
|
|
1964
|
+
{
|
|
1965
|
+
value: "react",
|
|
1966
|
+
label: "React",
|
|
1967
|
+
hint: "Full React component support (required for tRPC)"
|
|
1968
|
+
},
|
|
1969
|
+
{
|
|
1970
|
+
value: "vue",
|
|
1971
|
+
label: "Vue",
|
|
1972
|
+
hint: "Vue 3 component support"
|
|
1973
|
+
},
|
|
1974
|
+
{
|
|
1975
|
+
value: "svelte",
|
|
1976
|
+
label: "Svelte",
|
|
1977
|
+
hint: "Svelte component support"
|
|
1978
|
+
},
|
|
1979
|
+
{
|
|
1980
|
+
value: "solid",
|
|
1981
|
+
label: "Solid",
|
|
1982
|
+
hint: "SolidJS component support"
|
|
1983
|
+
},
|
|
1984
|
+
{
|
|
1985
|
+
value: "none",
|
|
1986
|
+
label: "None",
|
|
1987
|
+
hint: "Astro components only (no client-side JS framework)"
|
|
1988
|
+
}
|
|
1989
|
+
];
|
|
1990
|
+
function resolveAstroIntegrationPrompt(astroIntegration) {
|
|
1991
|
+
return createStaticSinglePromptResolution(ASTRO_INTEGRATION_PROMPT_OPTIONS, "react", astroIntegration);
|
|
1992
|
+
}
|
|
1746
1993
|
async function getAstroIntegrationChoice(astroIntegration) {
|
|
1747
|
-
|
|
1994
|
+
const resolution = resolveAstroIntegrationPrompt(astroIntegration);
|
|
1995
|
+
if (!resolution.shouldPrompt) return resolution.autoValue ?? "none";
|
|
1748
1996
|
const response = await navigableSelect({
|
|
1749
1997
|
message: "Choose Astro UI framework integration",
|
|
1750
|
-
options:
|
|
1751
|
-
|
|
1752
|
-
value: "react",
|
|
1753
|
-
label: "React",
|
|
1754
|
-
hint: "Full React component support (required for tRPC)"
|
|
1755
|
-
},
|
|
1756
|
-
{
|
|
1757
|
-
value: "vue",
|
|
1758
|
-
label: "Vue",
|
|
1759
|
-
hint: "Vue 3 component support"
|
|
1760
|
-
},
|
|
1761
|
-
{
|
|
1762
|
-
value: "svelte",
|
|
1763
|
-
label: "Svelte",
|
|
1764
|
-
hint: "Svelte component support"
|
|
1765
|
-
},
|
|
1766
|
-
{
|
|
1767
|
-
value: "solid",
|
|
1768
|
-
label: "Solid",
|
|
1769
|
-
hint: "SolidJS component support"
|
|
1770
|
-
},
|
|
1771
|
-
{
|
|
1772
|
-
value: "none",
|
|
1773
|
-
label: "None",
|
|
1774
|
-
hint: "Astro components only (no client-side JS framework)"
|
|
1775
|
-
}
|
|
1776
|
-
],
|
|
1777
|
-
initialValue: "react"
|
|
1998
|
+
options: resolution.options,
|
|
1999
|
+
initialValue: resolution.initialValue
|
|
1778
2000
|
});
|
|
1779
2001
|
if (isCancel$1(response)) return exitCancelled("Operation cancelled");
|
|
1780
2002
|
return response;
|
|
@@ -1782,8 +2004,7 @@ async function getAstroIntegrationChoice(astroIntegration) {
|
|
|
1782
2004
|
|
|
1783
2005
|
//#endregion
|
|
1784
2006
|
//#region src/prompts/auth.ts
|
|
1785
|
-
|
|
1786
|
-
if (auth !== void 0) return auth;
|
|
2007
|
+
function resolveAuthPrompt(context = {}) {
|
|
1787
2008
|
const authOptionOrder = [
|
|
1788
2009
|
{ value: "better-auth" },
|
|
1789
2010
|
{ value: "go-better-auth" },
|
|
@@ -1795,23 +2016,49 @@ async function getAuthChoice(auth, backend, frontend, ecosystem = "typescript")
|
|
|
1795
2016
|
{ value: "none" }
|
|
1796
2017
|
];
|
|
1797
2018
|
const supportedOptions = (0, types_exports.getSupportedCapabilityOptions)("auth", {
|
|
1798
|
-
ecosystem,
|
|
1799
|
-
backend,
|
|
1800
|
-
frontend
|
|
2019
|
+
ecosystem: context.ecosystem ?? "typescript",
|
|
2020
|
+
backend: context.backend,
|
|
2021
|
+
frontend: context.frontend
|
|
1801
2022
|
});
|
|
1802
2023
|
const options = authOptionOrder.flatMap(({ value }) => {
|
|
1803
2024
|
const option = supportedOptions.find((candidate) => candidate.id === value);
|
|
1804
|
-
return option ? [
|
|
1805
|
-
});
|
|
1806
|
-
if (options.length === 1 && options[0]?.id === "none") return "none";
|
|
1807
|
-
const response = await navigableSelect({
|
|
1808
|
-
message: "Select authentication provider",
|
|
1809
|
-
options: options.map((option) => ({
|
|
2025
|
+
return option ? [{
|
|
1810
2026
|
value: option.id,
|
|
1811
2027
|
label: option.label,
|
|
1812
2028
|
hint: option.promptHint
|
|
1813
|
-
}
|
|
1814
|
-
|
|
2029
|
+
}] : [];
|
|
2030
|
+
});
|
|
2031
|
+
if (context.auth !== void 0) return {
|
|
2032
|
+
shouldPrompt: false,
|
|
2033
|
+
mode: "single",
|
|
2034
|
+
options,
|
|
2035
|
+
autoValue: context.auth
|
|
2036
|
+
};
|
|
2037
|
+
if (options.length === 1 && options[0]?.value === "none") return {
|
|
2038
|
+
shouldPrompt: false,
|
|
2039
|
+
mode: "single",
|
|
2040
|
+
options,
|
|
2041
|
+
autoValue: "none"
|
|
2042
|
+
};
|
|
2043
|
+
return {
|
|
2044
|
+
shouldPrompt: true,
|
|
2045
|
+
mode: "single",
|
|
2046
|
+
options,
|
|
2047
|
+
initialValue: options.some((option) => option.value === DEFAULT_CONFIG.auth) ? DEFAULT_CONFIG.auth : options.find((option) => option.value !== "none")?.value ?? "none"
|
|
2048
|
+
};
|
|
2049
|
+
}
|
|
2050
|
+
async function getAuthChoice(auth, backend, frontend, ecosystem = "typescript") {
|
|
2051
|
+
const resolution = resolveAuthPrompt({
|
|
2052
|
+
auth,
|
|
2053
|
+
backend,
|
|
2054
|
+
frontend,
|
|
2055
|
+
ecosystem
|
|
2056
|
+
});
|
|
2057
|
+
if (!resolution.shouldPrompt) return resolution.autoValue ?? "none";
|
|
2058
|
+
const response = await navigableSelect({
|
|
2059
|
+
message: "Select authentication provider",
|
|
2060
|
+
options: resolution.options,
|
|
2061
|
+
initialValue: resolution.initialValue
|
|
1815
2062
|
});
|
|
1816
2063
|
if (isCancel$1(response)) return exitCancelled("Operation cancelled");
|
|
1817
2064
|
return response;
|
|
@@ -1827,67 +2074,108 @@ const FULLSTACK_FRONTENDS = [
|
|
|
1827
2074
|
"svelte",
|
|
1828
2075
|
"solid-start"
|
|
1829
2076
|
];
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
const hasIncompatibleFrontend = frontends?.some((f) => f === "solid" || f === "solid-start");
|
|
1833
|
-
const hasFullstackFrontend = frontends?.some((f) => FULLSTACK_FRONTENDS.includes(f));
|
|
1834
|
-
const backendOptions = [];
|
|
1835
|
-
if (hasFullstackFrontend) backendOptions.push({
|
|
2077
|
+
const BACKEND_PROMPT_OPTIONS = [
|
|
2078
|
+
{
|
|
1836
2079
|
value: "self",
|
|
1837
2080
|
label: "Self (Fullstack)",
|
|
1838
2081
|
hint: "Use frontend's built-in api routes"
|
|
1839
|
-
}
|
|
1840
|
-
|
|
2082
|
+
},
|
|
2083
|
+
{
|
|
1841
2084
|
value: "hono",
|
|
1842
2085
|
label: "Hono",
|
|
1843
2086
|
hint: "Lightweight, ultrafast web framework"
|
|
1844
|
-
},
|
|
2087
|
+
},
|
|
2088
|
+
{
|
|
1845
2089
|
value: "express",
|
|
1846
2090
|
label: "Express",
|
|
1847
2091
|
hint: "Fast, unopinionated, minimalist web framework for Node.js"
|
|
1848
|
-
},
|
|
2092
|
+
},
|
|
2093
|
+
{
|
|
1849
2094
|
value: "fastify",
|
|
1850
2095
|
label: "Fastify",
|
|
1851
2096
|
hint: "Fast, low-overhead web framework for Node.js"
|
|
1852
|
-
},
|
|
2097
|
+
},
|
|
2098
|
+
{
|
|
1853
2099
|
value: "elysia",
|
|
1854
2100
|
label: "Elysia",
|
|
1855
2101
|
hint: "Ergonomic web framework for building backend servers"
|
|
1856
|
-
},
|
|
2102
|
+
},
|
|
2103
|
+
{
|
|
1857
2104
|
value: "fets",
|
|
1858
2105
|
label: "feTS",
|
|
1859
2106
|
hint: "TypeScript HTTP Framework with e2e type-safety"
|
|
1860
|
-
},
|
|
2107
|
+
},
|
|
2108
|
+
{
|
|
1861
2109
|
value: "nestjs",
|
|
1862
2110
|
label: "NestJS",
|
|
1863
2111
|
hint: "Progressive Node.js framework for scalable applications"
|
|
1864
|
-
},
|
|
2112
|
+
},
|
|
2113
|
+
{
|
|
1865
2114
|
value: "adonisjs",
|
|
1866
2115
|
label: "AdonisJS",
|
|
1867
2116
|
hint: "Full-featured MVC framework for Node.js"
|
|
1868
|
-
},
|
|
2117
|
+
},
|
|
2118
|
+
{
|
|
1869
2119
|
value: "nitro",
|
|
1870
2120
|
label: "Nitro",
|
|
1871
2121
|
hint: "Universal server framework from UnJS"
|
|
1872
|
-
},
|
|
2122
|
+
},
|
|
2123
|
+
{
|
|
1873
2124
|
value: "encore",
|
|
1874
2125
|
label: "Encore",
|
|
1875
2126
|
hint: "Backend development platform with built-in infrastructure"
|
|
1876
|
-
}
|
|
1877
|
-
|
|
2127
|
+
},
|
|
2128
|
+
{
|
|
1878
2129
|
value: "convex",
|
|
1879
2130
|
label: "Convex",
|
|
1880
2131
|
hint: "Reactive backend-as-a-service platform"
|
|
1881
|
-
}
|
|
1882
|
-
|
|
2132
|
+
},
|
|
2133
|
+
{
|
|
1883
2134
|
value: "none",
|
|
1884
2135
|
label: "None",
|
|
1885
2136
|
hint: "No backend server"
|
|
2137
|
+
}
|
|
2138
|
+
];
|
|
2139
|
+
function resolveBackendPrompt(context = {}) {
|
|
2140
|
+
const hasIncompatibleFrontend = context.frontends?.some((frontend) => frontend === "solid" || frontend === "solid-start");
|
|
2141
|
+
const hasFullstackFrontend = context.frontends?.some((frontend) => FULLSTACK_FRONTENDS.includes(frontend));
|
|
2142
|
+
const availableValues = new Set([
|
|
2143
|
+
...hasFullstackFrontend ? ["self"] : [],
|
|
2144
|
+
"hono",
|
|
2145
|
+
"express",
|
|
2146
|
+
"fastify",
|
|
2147
|
+
"elysia",
|
|
2148
|
+
"fets",
|
|
2149
|
+
"nestjs",
|
|
2150
|
+
"adonisjs",
|
|
2151
|
+
"nitro",
|
|
2152
|
+
"encore",
|
|
2153
|
+
...!hasIncompatibleFrontend ? ["convex"] : [],
|
|
2154
|
+
"none"
|
|
2155
|
+
]);
|
|
2156
|
+
const options = BACKEND_PROMPT_OPTIONS.filter((option) => availableValues.has(option.value));
|
|
2157
|
+
return context.backendFramework !== void 0 ? {
|
|
2158
|
+
shouldPrompt: false,
|
|
2159
|
+
mode: "single",
|
|
2160
|
+
options,
|
|
2161
|
+
autoValue: context.backendFramework
|
|
2162
|
+
} : {
|
|
2163
|
+
shouldPrompt: true,
|
|
2164
|
+
mode: "single",
|
|
2165
|
+
options,
|
|
2166
|
+
initialValue: hasFullstackFrontend ? "self" : DEFAULT_CONFIG.backend
|
|
2167
|
+
};
|
|
2168
|
+
}
|
|
2169
|
+
async function getBackendFrameworkChoice(backendFramework, frontends) {
|
|
2170
|
+
const resolution = resolveBackendPrompt({
|
|
2171
|
+
backendFramework,
|
|
2172
|
+
frontends
|
|
1886
2173
|
});
|
|
2174
|
+
if (!resolution.shouldPrompt) return resolution.autoValue ?? "none";
|
|
1887
2175
|
const response = await navigableSelect({
|
|
1888
2176
|
message: "Select backend",
|
|
1889
|
-
options:
|
|
1890
|
-
initialValue:
|
|
2177
|
+
options: resolution.options,
|
|
2178
|
+
initialValue: resolution.initialValue
|
|
1891
2179
|
});
|
|
1892
2180
|
if (isCancel$1(response)) return exitCancelled("Operation cancelled");
|
|
1893
2181
|
return response;
|
|
@@ -1895,21 +2183,44 @@ async function getBackendFrameworkChoice(backendFramework, frontends) {
|
|
|
1895
2183
|
|
|
1896
2184
|
//#endregion
|
|
1897
2185
|
//#region src/prompts/caching.ts
|
|
2186
|
+
const CACHING_PROMPT_OPTIONS = [{
|
|
2187
|
+
value: "upstash-redis",
|
|
2188
|
+
label: "Upstash Redis",
|
|
2189
|
+
hint: "Serverless Redis with REST API for edge and serverless"
|
|
2190
|
+
}, {
|
|
2191
|
+
value: "none",
|
|
2192
|
+
label: "None",
|
|
2193
|
+
hint: "Skip caching layer setup"
|
|
2194
|
+
}];
|
|
2195
|
+
function resolveCachingPrompt(context = {}) {
|
|
2196
|
+
if (context.backend === "none" || context.backend === "convex") return {
|
|
2197
|
+
shouldPrompt: false,
|
|
2198
|
+
mode: "single",
|
|
2199
|
+
options: [],
|
|
2200
|
+
autoValue: "none"
|
|
2201
|
+
};
|
|
2202
|
+
return context.caching !== void 0 ? {
|
|
2203
|
+
shouldPrompt: false,
|
|
2204
|
+
mode: "single",
|
|
2205
|
+
options: CACHING_PROMPT_OPTIONS,
|
|
2206
|
+
autoValue: context.caching
|
|
2207
|
+
} : {
|
|
2208
|
+
shouldPrompt: true,
|
|
2209
|
+
mode: "single",
|
|
2210
|
+
options: CACHING_PROMPT_OPTIONS,
|
|
2211
|
+
initialValue: "none"
|
|
2212
|
+
};
|
|
2213
|
+
}
|
|
1898
2214
|
async function getCachingChoice(caching, backend) {
|
|
1899
|
-
|
|
1900
|
-
|
|
2215
|
+
const resolution = resolveCachingPrompt({
|
|
2216
|
+
caching,
|
|
2217
|
+
backend
|
|
2218
|
+
});
|
|
2219
|
+
if (!resolution.shouldPrompt) return resolution.autoValue ?? "none";
|
|
1901
2220
|
const response = await navigableSelect({
|
|
1902
2221
|
message: "Select caching solution",
|
|
1903
|
-
options:
|
|
1904
|
-
|
|
1905
|
-
label: "Upstash Redis",
|
|
1906
|
-
hint: "Serverless Redis with REST API for edge and serverless"
|
|
1907
|
-
}, {
|
|
1908
|
-
value: "none",
|
|
1909
|
-
label: "None",
|
|
1910
|
-
hint: "Skip caching layer setup"
|
|
1911
|
-
}],
|
|
1912
|
-
initialValue: "none"
|
|
2222
|
+
options: resolution.options,
|
|
2223
|
+
initialValue: resolution.initialValue
|
|
1913
2224
|
});
|
|
1914
2225
|
if (isCancel$1(response)) return exitCancelled("Operation cancelled");
|
|
1915
2226
|
return response;
|
|
@@ -1917,39 +2228,62 @@ async function getCachingChoice(caching, backend) {
|
|
|
1917
2228
|
|
|
1918
2229
|
//#endregion
|
|
1919
2230
|
//#region src/prompts/cms.ts
|
|
2231
|
+
const CMS_PROMPT_OPTIONS = [
|
|
2232
|
+
{
|
|
2233
|
+
value: "payload",
|
|
2234
|
+
label: "Payload",
|
|
2235
|
+
hint: "TypeScript-first headless CMS with Next.js integration"
|
|
2236
|
+
},
|
|
2237
|
+
{
|
|
2238
|
+
value: "sanity",
|
|
2239
|
+
label: "Sanity",
|
|
2240
|
+
hint: "Real-time collaborative CMS with schema-as-code"
|
|
2241
|
+
},
|
|
2242
|
+
{
|
|
2243
|
+
value: "strapi",
|
|
2244
|
+
label: "Strapi",
|
|
2245
|
+
hint: "Open-source headless CMS with admin panel"
|
|
2246
|
+
},
|
|
2247
|
+
{
|
|
2248
|
+
value: "tinacms",
|
|
2249
|
+
label: "TinaCMS",
|
|
2250
|
+
hint: "Git-backed headless CMS with visual editing"
|
|
2251
|
+
},
|
|
2252
|
+
{
|
|
2253
|
+
value: "none",
|
|
2254
|
+
label: "None",
|
|
2255
|
+
hint: "Skip headless CMS setup"
|
|
2256
|
+
}
|
|
2257
|
+
];
|
|
2258
|
+
function resolveCMSPrompt(context = {}) {
|
|
2259
|
+
if (context.backend === "none" || context.backend === "convex") return {
|
|
2260
|
+
shouldPrompt: false,
|
|
2261
|
+
mode: "single",
|
|
2262
|
+
options: [],
|
|
2263
|
+
autoValue: "none"
|
|
2264
|
+
};
|
|
2265
|
+
return context.cms !== void 0 ? {
|
|
2266
|
+
shouldPrompt: false,
|
|
2267
|
+
mode: "single",
|
|
2268
|
+
options: CMS_PROMPT_OPTIONS,
|
|
2269
|
+
autoValue: context.cms
|
|
2270
|
+
} : {
|
|
2271
|
+
shouldPrompt: true,
|
|
2272
|
+
mode: "single",
|
|
2273
|
+
options: CMS_PROMPT_OPTIONS,
|
|
2274
|
+
initialValue: "none"
|
|
2275
|
+
};
|
|
2276
|
+
}
|
|
1920
2277
|
async function getCMSChoice(cms, backend) {
|
|
1921
|
-
|
|
1922
|
-
|
|
2278
|
+
const resolution = resolveCMSPrompt({
|
|
2279
|
+
cms,
|
|
2280
|
+
backend
|
|
2281
|
+
});
|
|
2282
|
+
if (!resolution.shouldPrompt) return resolution.autoValue ?? "none";
|
|
1923
2283
|
const response = await navigableSelect({
|
|
1924
2284
|
message: "Select headless CMS",
|
|
1925
|
-
options:
|
|
1926
|
-
|
|
1927
|
-
value: "payload",
|
|
1928
|
-
label: "Payload",
|
|
1929
|
-
hint: "TypeScript-first headless CMS with Next.js integration"
|
|
1930
|
-
},
|
|
1931
|
-
{
|
|
1932
|
-
value: "sanity",
|
|
1933
|
-
label: "Sanity",
|
|
1934
|
-
hint: "Real-time collaborative CMS with schema-as-code"
|
|
1935
|
-
},
|
|
1936
|
-
{
|
|
1937
|
-
value: "strapi",
|
|
1938
|
-
label: "Strapi",
|
|
1939
|
-
hint: "Open-source headless CMS with admin panel"
|
|
1940
|
-
},
|
|
1941
|
-
{
|
|
1942
|
-
value: "tinacms",
|
|
1943
|
-
label: "TinaCMS",
|
|
1944
|
-
hint: "Git-backed headless CMS with visual editing"
|
|
1945
|
-
},
|
|
1946
|
-
{
|
|
1947
|
-
value: "none",
|
|
1948
|
-
label: "None",
|
|
1949
|
-
hint: "Skip headless CMS setup"
|
|
1950
|
-
}
|
|
1951
|
-
],
|
|
1952
|
-
initialValue: "none"
|
|
2285
|
+
options: resolution.options,
|
|
2286
|
+
initialValue: resolution.initialValue
|
|
1953
2287
|
});
|
|
1954
2288
|
if (isCancel$1(response)) return exitCancelled("Operation cancelled");
|
|
1955
2289
|
return response;
|
|
@@ -1979,17 +2313,39 @@ const CSS_FRAMEWORK_OPTIONS = {
|
|
|
1979
2313
|
hint: "Plain CSS without preprocessors"
|
|
1980
2314
|
}
|
|
1981
2315
|
};
|
|
1982
|
-
|
|
1983
|
-
const compatibleFrameworks = getCompatibleCSSFrameworks$1(uiLibrary);
|
|
1984
|
-
if (cssFramework !== void 0) return
|
|
1985
|
-
|
|
1986
|
-
|
|
2316
|
+
function resolveCSSFrameworkPrompt(context = {}) {
|
|
2317
|
+
const compatibleFrameworks = getCompatibleCSSFrameworks$1(context.uiLibrary);
|
|
2318
|
+
if (context.cssFramework !== void 0) return {
|
|
2319
|
+
shouldPrompt: false,
|
|
2320
|
+
mode: "single",
|
|
2321
|
+
options: compatibleFrameworks.map((fw) => ({
|
|
2322
|
+
value: fw,
|
|
2323
|
+
label: CSS_FRAMEWORK_OPTIONS[fw].label,
|
|
2324
|
+
hint: CSS_FRAMEWORK_OPTIONS[fw].hint
|
|
2325
|
+
})),
|
|
2326
|
+
autoValue: compatibleFrameworks.includes(context.cssFramework) ? context.cssFramework : compatibleFrameworks[0]
|
|
2327
|
+
};
|
|
2328
|
+
return {
|
|
2329
|
+
shouldPrompt: true,
|
|
2330
|
+
mode: "single",
|
|
1987
2331
|
options: compatibleFrameworks.map((fw) => ({
|
|
1988
2332
|
value: fw,
|
|
1989
2333
|
label: CSS_FRAMEWORK_OPTIONS[fw].label,
|
|
1990
2334
|
hint: CSS_FRAMEWORK_OPTIONS[fw].hint
|
|
1991
2335
|
})),
|
|
1992
2336
|
initialValue: compatibleFrameworks.includes("tailwind") ? "tailwind" : compatibleFrameworks[0]
|
|
2337
|
+
};
|
|
2338
|
+
}
|
|
2339
|
+
async function getCSSFrameworkChoice(cssFramework, uiLibrary) {
|
|
2340
|
+
const resolution = resolveCSSFrameworkPrompt({
|
|
2341
|
+
cssFramework,
|
|
2342
|
+
uiLibrary
|
|
2343
|
+
});
|
|
2344
|
+
if (!resolution.shouldPrompt) return resolution.autoValue ?? "none";
|
|
2345
|
+
const selected = await navigableSelect({
|
|
2346
|
+
message: "Select CSS framework",
|
|
2347
|
+
options: resolution.options,
|
|
2348
|
+
initialValue: resolution.initialValue
|
|
1993
2349
|
});
|
|
1994
2350
|
if (isCancel$1(selected)) return exitCancelled("Operation cancelled");
|
|
1995
2351
|
return selected;
|
|
@@ -1997,9 +2353,19 @@ async function getCSSFrameworkChoice(cssFramework, uiLibrary) {
|
|
|
1997
2353
|
|
|
1998
2354
|
//#endregion
|
|
1999
2355
|
//#region src/prompts/database.ts
|
|
2000
|
-
|
|
2001
|
-
if (backend === "convex" || backend === "none") return
|
|
2002
|
-
|
|
2356
|
+
function resolveDatabasePrompt(context = {}) {
|
|
2357
|
+
if (context.backend === "convex" || context.backend === "none") return {
|
|
2358
|
+
shouldPrompt: false,
|
|
2359
|
+
mode: "single",
|
|
2360
|
+
options: [],
|
|
2361
|
+
autoValue: "none"
|
|
2362
|
+
};
|
|
2363
|
+
if (context.database !== void 0) return {
|
|
2364
|
+
shouldPrompt: false,
|
|
2365
|
+
mode: "single",
|
|
2366
|
+
options: [],
|
|
2367
|
+
autoValue: context.database
|
|
2368
|
+
};
|
|
2003
2369
|
const databaseOptions = [
|
|
2004
2370
|
{
|
|
2005
2371
|
value: "none",
|
|
@@ -2022,7 +2388,7 @@ async function getDatabaseChoice(database, backend, runtime) {
|
|
|
2022
2388
|
hint: "popular open-source relational database system"
|
|
2023
2389
|
}
|
|
2024
2390
|
];
|
|
2025
|
-
if (runtime !== "workers") {
|
|
2391
|
+
if (context.runtime !== "workers") {
|
|
2026
2392
|
databaseOptions.push({
|
|
2027
2393
|
value: "mongodb",
|
|
2028
2394
|
label: "MongoDB",
|
|
@@ -2039,10 +2405,24 @@ async function getDatabaseChoice(database, backend, runtime) {
|
|
|
2039
2405
|
hint: "in-memory data store for caching, sessions, and real-time features"
|
|
2040
2406
|
});
|
|
2041
2407
|
}
|
|
2042
|
-
|
|
2043
|
-
|
|
2408
|
+
return {
|
|
2409
|
+
shouldPrompt: true,
|
|
2410
|
+
mode: "single",
|
|
2044
2411
|
options: databaseOptions,
|
|
2045
2412
|
initialValue: DEFAULT_CONFIG.database
|
|
2413
|
+
};
|
|
2414
|
+
}
|
|
2415
|
+
async function getDatabaseChoice(database, backend, runtime) {
|
|
2416
|
+
const resolution = resolveDatabasePrompt({
|
|
2417
|
+
database,
|
|
2418
|
+
backend,
|
|
2419
|
+
runtime
|
|
2420
|
+
});
|
|
2421
|
+
if (!resolution.shouldPrompt) return resolution.autoValue ?? "none";
|
|
2422
|
+
const response = await navigableSelect({
|
|
2423
|
+
message: "Select database",
|
|
2424
|
+
options: resolution.options,
|
|
2425
|
+
initialValue: resolution.initialValue
|
|
2046
2426
|
});
|
|
2047
2427
|
if (isCancel$1(response)) return exitCancelled("Operation cancelled");
|
|
2048
2428
|
return response;
|
|
@@ -2050,18 +2430,33 @@ async function getDatabaseChoice(database, backend, runtime) {
|
|
|
2050
2430
|
|
|
2051
2431
|
//#endregion
|
|
2052
2432
|
//#region src/prompts/database-setup.ts
|
|
2053
|
-
|
|
2054
|
-
if (backend === "convex") return
|
|
2055
|
-
|
|
2056
|
-
|
|
2433
|
+
function resolveDBSetupPrompt(context) {
|
|
2434
|
+
if (context.backend === "convex") return {
|
|
2435
|
+
shouldPrompt: false,
|
|
2436
|
+
mode: "single",
|
|
2437
|
+
options: [],
|
|
2438
|
+
autoValue: "none"
|
|
2439
|
+
};
|
|
2440
|
+
if (context.dbSetup !== void 0) return {
|
|
2441
|
+
shouldPrompt: false,
|
|
2442
|
+
mode: "single",
|
|
2443
|
+
options: [],
|
|
2444
|
+
autoValue: context.dbSetup
|
|
2445
|
+
};
|
|
2446
|
+
if (context.databaseType === "none") return {
|
|
2447
|
+
shouldPrompt: false,
|
|
2448
|
+
mode: "single",
|
|
2449
|
+
options: [],
|
|
2450
|
+
autoValue: "none"
|
|
2451
|
+
};
|
|
2057
2452
|
let options = [];
|
|
2058
|
-
if (databaseType === "sqlite") options = [
|
|
2453
|
+
if (context.databaseType === "sqlite") options = [
|
|
2059
2454
|
{
|
|
2060
2455
|
value: "turso",
|
|
2061
2456
|
label: "Turso",
|
|
2062
2457
|
hint: "SQLite for Production. Powered by libSQL"
|
|
2063
2458
|
},
|
|
2064
|
-
...runtime === "workers" ? [{
|
|
2459
|
+
...context.runtime === "workers" ? [{
|
|
2065
2460
|
value: "d1",
|
|
2066
2461
|
label: "Cloudflare D1",
|
|
2067
2462
|
hint: "Cloudflare's managed, serverless database with SQLite's SQL semantics"
|
|
@@ -2072,7 +2467,7 @@ async function getDBSetupChoice(databaseType, dbSetup, _orm, backend, runtime) {
|
|
|
2072
2467
|
hint: "Manual setup"
|
|
2073
2468
|
}
|
|
2074
2469
|
];
|
|
2075
|
-
else if (databaseType === "postgres") options = [
|
|
2470
|
+
else if (context.databaseType === "postgres") options = [
|
|
2076
2471
|
{
|
|
2077
2472
|
value: "neon",
|
|
2078
2473
|
label: "Neon Postgres",
|
|
@@ -2104,7 +2499,7 @@ async function getDBSetupChoice(databaseType, dbSetup, _orm, backend, runtime) {
|
|
|
2104
2499
|
hint: "Manual setup"
|
|
2105
2500
|
}
|
|
2106
2501
|
];
|
|
2107
|
-
else if (databaseType === "mysql") options = [
|
|
2502
|
+
else if (context.databaseType === "mysql") options = [
|
|
2108
2503
|
{
|
|
2109
2504
|
value: "planetscale",
|
|
2110
2505
|
label: "PlanetScale",
|
|
@@ -2121,7 +2516,7 @@ async function getDBSetupChoice(databaseType, dbSetup, _orm, backend, runtime) {
|
|
|
2121
2516
|
hint: "Manual setup"
|
|
2122
2517
|
}
|
|
2123
2518
|
];
|
|
2124
|
-
else if (databaseType === "mongodb") options = [
|
|
2519
|
+
else if (context.databaseType === "mongodb") options = [
|
|
2125
2520
|
{
|
|
2126
2521
|
value: "mongodb-atlas",
|
|
2127
2522
|
label: "MongoDB Atlas",
|
|
@@ -2138,7 +2533,7 @@ async function getDBSetupChoice(databaseType, dbSetup, _orm, backend, runtime) {
|
|
|
2138
2533
|
hint: "Manual setup"
|
|
2139
2534
|
}
|
|
2140
2535
|
];
|
|
2141
|
-
else if (databaseType === "redis") options = [
|
|
2536
|
+
else if (context.databaseType === "redis") options = [
|
|
2142
2537
|
{
|
|
2143
2538
|
value: "upstash",
|
|
2144
2539
|
label: "Upstash",
|
|
@@ -2155,11 +2550,32 @@ async function getDBSetupChoice(databaseType, dbSetup, _orm, backend, runtime) {
|
|
|
2155
2550
|
hint: "Manual setup"
|
|
2156
2551
|
}
|
|
2157
2552
|
];
|
|
2158
|
-
else return
|
|
2159
|
-
|
|
2160
|
-
|
|
2553
|
+
else return {
|
|
2554
|
+
shouldPrompt: false,
|
|
2555
|
+
mode: "single",
|
|
2556
|
+
options: [],
|
|
2557
|
+
autoValue: "none"
|
|
2558
|
+
};
|
|
2559
|
+
return {
|
|
2560
|
+
shouldPrompt: true,
|
|
2561
|
+
mode: "single",
|
|
2161
2562
|
options,
|
|
2162
2563
|
initialValue: "none"
|
|
2564
|
+
};
|
|
2565
|
+
}
|
|
2566
|
+
async function getDBSetupChoice(databaseType, dbSetup, _orm, backend, runtime) {
|
|
2567
|
+
const resolution = resolveDBSetupPrompt({
|
|
2568
|
+
databaseType,
|
|
2569
|
+
dbSetup,
|
|
2570
|
+
orm: _orm,
|
|
2571
|
+
backend,
|
|
2572
|
+
runtime
|
|
2573
|
+
});
|
|
2574
|
+
if (!resolution.shouldPrompt) return resolution.autoValue ?? "none";
|
|
2575
|
+
const response = await navigableSelect({
|
|
2576
|
+
message: `Select ${databaseType} setup option`,
|
|
2577
|
+
options: resolution.options,
|
|
2578
|
+
initialValue: resolution.initialValue
|
|
2163
2579
|
});
|
|
2164
2580
|
if (isCancel$1(response)) return exitCancelled("Operation cancelled");
|
|
2165
2581
|
return response;
|
|
@@ -2230,60 +2646,82 @@ async function getEffectChoice(effect) {
|
|
|
2230
2646
|
|
|
2231
2647
|
//#endregion
|
|
2232
2648
|
//#region src/prompts/email.ts
|
|
2649
|
+
const EMAIL_PROMPT_OPTIONS = [
|
|
2650
|
+
{
|
|
2651
|
+
value: "resend",
|
|
2652
|
+
label: "Resend",
|
|
2653
|
+
hint: "Email for developers. Includes React Email components."
|
|
2654
|
+
},
|
|
2655
|
+
{
|
|
2656
|
+
value: "react-email",
|
|
2657
|
+
label: "React Email",
|
|
2658
|
+
hint: "Build emails using React components (no sending service)."
|
|
2659
|
+
},
|
|
2660
|
+
{
|
|
2661
|
+
value: "nodemailer",
|
|
2662
|
+
label: "Nodemailer",
|
|
2663
|
+
hint: "Classic Node.js email sending library."
|
|
2664
|
+
},
|
|
2665
|
+
{
|
|
2666
|
+
value: "postmark",
|
|
2667
|
+
label: "Postmark",
|
|
2668
|
+
hint: "Transactional email service with high deliverability."
|
|
2669
|
+
},
|
|
2670
|
+
{
|
|
2671
|
+
value: "sendgrid",
|
|
2672
|
+
label: "SendGrid",
|
|
2673
|
+
hint: "Email delivery and marketing platform by Twilio."
|
|
2674
|
+
},
|
|
2675
|
+
{
|
|
2676
|
+
value: "aws-ses",
|
|
2677
|
+
label: "AWS SES",
|
|
2678
|
+
hint: "Amazon Simple Email Service for scalable email."
|
|
2679
|
+
},
|
|
2680
|
+
{
|
|
2681
|
+
value: "mailgun",
|
|
2682
|
+
label: "Mailgun",
|
|
2683
|
+
hint: "Email API service for sending and tracking emails."
|
|
2684
|
+
},
|
|
2685
|
+
{
|
|
2686
|
+
value: "plunk",
|
|
2687
|
+
label: "Plunk",
|
|
2688
|
+
hint: "Open-source email platform for developers."
|
|
2689
|
+
},
|
|
2690
|
+
{
|
|
2691
|
+
value: "none",
|
|
2692
|
+
label: "None",
|
|
2693
|
+
hint: "No email integration"
|
|
2694
|
+
}
|
|
2695
|
+
];
|
|
2696
|
+
function resolveEmailPrompt(context = {}) {
|
|
2697
|
+
if (context.backend === "none" || context.backend === "convex") return {
|
|
2698
|
+
shouldPrompt: false,
|
|
2699
|
+
mode: "single",
|
|
2700
|
+
options: [],
|
|
2701
|
+
autoValue: "none"
|
|
2702
|
+
};
|
|
2703
|
+
return context.email !== void 0 ? {
|
|
2704
|
+
shouldPrompt: false,
|
|
2705
|
+
mode: "single",
|
|
2706
|
+
options: EMAIL_PROMPT_OPTIONS,
|
|
2707
|
+
autoValue: context.email
|
|
2708
|
+
} : {
|
|
2709
|
+
shouldPrompt: true,
|
|
2710
|
+
mode: "single",
|
|
2711
|
+
options: EMAIL_PROMPT_OPTIONS,
|
|
2712
|
+
initialValue: DEFAULT_CONFIG.email ?? "none"
|
|
2713
|
+
};
|
|
2714
|
+
}
|
|
2233
2715
|
async function getEmailChoice(email, backend) {
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2716
|
+
const resolution = resolveEmailPrompt({
|
|
2717
|
+
email,
|
|
2718
|
+
backend
|
|
2719
|
+
});
|
|
2720
|
+
if (!resolution.shouldPrompt) return resolution.autoValue ?? "none";
|
|
2237
2721
|
const response = await navigableSelect({
|
|
2238
2722
|
message: "Select email solution",
|
|
2239
|
-
options:
|
|
2240
|
-
|
|
2241
|
-
value: "resend",
|
|
2242
|
-
label: "Resend",
|
|
2243
|
-
hint: "Email for developers. Includes React Email components."
|
|
2244
|
-
},
|
|
2245
|
-
{
|
|
2246
|
-
value: "react-email",
|
|
2247
|
-
label: "React Email",
|
|
2248
|
-
hint: "Build emails using React components (no sending service)."
|
|
2249
|
-
},
|
|
2250
|
-
{
|
|
2251
|
-
value: "nodemailer",
|
|
2252
|
-
label: "Nodemailer",
|
|
2253
|
-
hint: "Classic Node.js email sending library."
|
|
2254
|
-
},
|
|
2255
|
-
{
|
|
2256
|
-
value: "postmark",
|
|
2257
|
-
label: "Postmark",
|
|
2258
|
-
hint: "Transactional email service with high deliverability."
|
|
2259
|
-
},
|
|
2260
|
-
{
|
|
2261
|
-
value: "sendgrid",
|
|
2262
|
-
label: "SendGrid",
|
|
2263
|
-
hint: "Email delivery and marketing platform by Twilio."
|
|
2264
|
-
},
|
|
2265
|
-
{
|
|
2266
|
-
value: "aws-ses",
|
|
2267
|
-
label: "AWS SES",
|
|
2268
|
-
hint: "Amazon Simple Email Service for scalable email."
|
|
2269
|
-
},
|
|
2270
|
-
{
|
|
2271
|
-
value: "mailgun",
|
|
2272
|
-
label: "Mailgun",
|
|
2273
|
-
hint: "Email API service for sending and tracking emails."
|
|
2274
|
-
},
|
|
2275
|
-
{
|
|
2276
|
-
value: "plunk",
|
|
2277
|
-
label: "Plunk",
|
|
2278
|
-
hint: "Open-source email platform for developers."
|
|
2279
|
-
},
|
|
2280
|
-
{
|
|
2281
|
-
value: "none",
|
|
2282
|
-
label: "None",
|
|
2283
|
-
hint: "No email integration"
|
|
2284
|
-
}
|
|
2285
|
-
],
|
|
2286
|
-
initialValue: DEFAULT_CONFIG.email ?? "none"
|
|
2723
|
+
options: resolution.options,
|
|
2724
|
+
initialValue: resolution.initialValue
|
|
2287
2725
|
});
|
|
2288
2726
|
if (isCancel$1(response)) return exitCancelled("Operation cancelled");
|
|
2289
2727
|
return response;
|
|
@@ -2349,34 +2787,57 @@ async function getFileStorageChoice(fileStorage, backend) {
|
|
|
2349
2787
|
|
|
2350
2788
|
//#endregion
|
|
2351
2789
|
//#region src/prompts/file-upload.ts
|
|
2790
|
+
const FILE_UPLOAD_PROMPT_OPTIONS = [
|
|
2791
|
+
{
|
|
2792
|
+
value: "uploadthing",
|
|
2793
|
+
label: "UploadThing",
|
|
2794
|
+
hint: "TypeScript-first file uploads with built-in validation"
|
|
2795
|
+
},
|
|
2796
|
+
{
|
|
2797
|
+
value: "filepond",
|
|
2798
|
+
label: "FilePond",
|
|
2799
|
+
hint: "Flexible file upload with image preview and drag & drop"
|
|
2800
|
+
},
|
|
2801
|
+
{
|
|
2802
|
+
value: "uppy",
|
|
2803
|
+
label: "Uppy",
|
|
2804
|
+
hint: "Modular file uploader with resumable uploads and plugins"
|
|
2805
|
+
},
|
|
2806
|
+
{
|
|
2807
|
+
value: "none",
|
|
2808
|
+
label: "None",
|
|
2809
|
+
hint: "Skip file upload integration"
|
|
2810
|
+
}
|
|
2811
|
+
];
|
|
2812
|
+
function resolveFileUploadPrompt(context = {}) {
|
|
2813
|
+
if (context.backend === "none" || context.backend === "convex") return {
|
|
2814
|
+
shouldPrompt: false,
|
|
2815
|
+
mode: "single",
|
|
2816
|
+
options: [],
|
|
2817
|
+
autoValue: "none"
|
|
2818
|
+
};
|
|
2819
|
+
return context.fileUpload !== void 0 ? {
|
|
2820
|
+
shouldPrompt: false,
|
|
2821
|
+
mode: "single",
|
|
2822
|
+
options: FILE_UPLOAD_PROMPT_OPTIONS,
|
|
2823
|
+
autoValue: context.fileUpload
|
|
2824
|
+
} : {
|
|
2825
|
+
shouldPrompt: true,
|
|
2826
|
+
mode: "single",
|
|
2827
|
+
options: FILE_UPLOAD_PROMPT_OPTIONS,
|
|
2828
|
+
initialValue: "none"
|
|
2829
|
+
};
|
|
2830
|
+
}
|
|
2352
2831
|
async function getFileUploadChoice(fileUpload, backend) {
|
|
2353
|
-
|
|
2354
|
-
|
|
2832
|
+
const resolution = resolveFileUploadPrompt({
|
|
2833
|
+
fileUpload,
|
|
2834
|
+
backend
|
|
2835
|
+
});
|
|
2836
|
+
if (!resolution.shouldPrompt) return resolution.autoValue ?? "none";
|
|
2355
2837
|
const response = await navigableSelect({
|
|
2356
2838
|
message: "Select file upload solution",
|
|
2357
|
-
options:
|
|
2358
|
-
|
|
2359
|
-
value: "uploadthing",
|
|
2360
|
-
label: "UploadThing",
|
|
2361
|
-
hint: "TypeScript-first file uploads with built-in validation"
|
|
2362
|
-
},
|
|
2363
|
-
{
|
|
2364
|
-
value: "filepond",
|
|
2365
|
-
label: "FilePond",
|
|
2366
|
-
hint: "Flexible file upload with image preview and drag & drop"
|
|
2367
|
-
},
|
|
2368
|
-
{
|
|
2369
|
-
value: "uppy",
|
|
2370
|
-
label: "Uppy",
|
|
2371
|
-
hint: "Modular file uploader with resumable uploads and plugins"
|
|
2372
|
-
},
|
|
2373
|
-
{
|
|
2374
|
-
value: "none",
|
|
2375
|
-
label: "None",
|
|
2376
|
-
hint: "Skip file upload integration"
|
|
2377
|
-
}
|
|
2378
|
-
],
|
|
2379
|
-
initialValue: "none"
|
|
2839
|
+
options: resolution.options,
|
|
2840
|
+
initialValue: resolution.initialValue
|
|
2380
2841
|
});
|
|
2381
2842
|
if (isCancel$1(response)) return exitCancelled("Operation cancelled");
|
|
2382
2843
|
return response;
|
|
@@ -2384,10 +2845,20 @@ async function getFileUploadChoice(fileUpload, backend) {
|
|
|
2384
2845
|
|
|
2385
2846
|
//#endregion
|
|
2386
2847
|
//#region src/prompts/forms.ts
|
|
2387
|
-
|
|
2388
|
-
if (forms !== void 0) return
|
|
2389
|
-
|
|
2390
|
-
|
|
2848
|
+
function resolveFormsPrompt(context = {}) {
|
|
2849
|
+
if (context.forms !== void 0) return {
|
|
2850
|
+
shouldPrompt: false,
|
|
2851
|
+
mode: "single",
|
|
2852
|
+
options: [],
|
|
2853
|
+
autoValue: context.forms
|
|
2854
|
+
};
|
|
2855
|
+
const { web } = splitFrontends$1(context.frontends);
|
|
2856
|
+
if (web.length === 0) return {
|
|
2857
|
+
shouldPrompt: false,
|
|
2858
|
+
mode: "single",
|
|
2859
|
+
options: [],
|
|
2860
|
+
autoValue: "none"
|
|
2861
|
+
};
|
|
2391
2862
|
const isReact = web.some((f) => [
|
|
2392
2863
|
"tanstack-router",
|
|
2393
2864
|
"react-router",
|
|
@@ -2432,10 +2903,23 @@ async function getFormsChoice(forms, frontends) {
|
|
|
2432
2903
|
label: "None",
|
|
2433
2904
|
hint: "Build custom form handling"
|
|
2434
2905
|
});
|
|
2906
|
+
return {
|
|
2907
|
+
shouldPrompt: true,
|
|
2908
|
+
mode: "single",
|
|
2909
|
+
options,
|
|
2910
|
+
initialValue: isReact ? "react-hook-form" : options.find((option) => option.value !== "none")?.value ?? "none"
|
|
2911
|
+
};
|
|
2912
|
+
}
|
|
2913
|
+
async function getFormsChoice(forms, frontends) {
|
|
2914
|
+
const resolution = resolveFormsPrompt({
|
|
2915
|
+
forms,
|
|
2916
|
+
frontends
|
|
2917
|
+
});
|
|
2918
|
+
if (!resolution.shouldPrompt) return resolution.autoValue ?? "none";
|
|
2435
2919
|
const response = await navigableSelect({
|
|
2436
2920
|
message: "Select form library",
|
|
2437
|
-
options,
|
|
2438
|
-
initialValue:
|
|
2921
|
+
options: resolution.options,
|
|
2922
|
+
initialValue: resolution.initialValue
|
|
2439
2923
|
});
|
|
2440
2924
|
if (isCancel$1(response)) return exitCancelled("Operation cancelled");
|
|
2441
2925
|
return response;
|
|
@@ -2443,8 +2927,119 @@ async function getFormsChoice(forms, frontends) {
|
|
|
2443
2927
|
|
|
2444
2928
|
//#endregion
|
|
2445
2929
|
//#region src/prompts/frontend.ts
|
|
2930
|
+
const WEB_FRONTEND_PROMPT_OPTIONS = [
|
|
2931
|
+
{
|
|
2932
|
+
value: "tanstack-router",
|
|
2933
|
+
label: "TanStack Router",
|
|
2934
|
+
hint: "Modern and scalable routing for React Applications"
|
|
2935
|
+
},
|
|
2936
|
+
{
|
|
2937
|
+
value: "react-router",
|
|
2938
|
+
label: "React Router",
|
|
2939
|
+
hint: "A user-obsessed, standards-focused, multi-strategy router"
|
|
2940
|
+
},
|
|
2941
|
+
{
|
|
2942
|
+
value: "react-vite",
|
|
2943
|
+
label: "React + Vite",
|
|
2944
|
+
hint: "Client-routed React SPA powered by Vite"
|
|
2945
|
+
},
|
|
2946
|
+
{
|
|
2947
|
+
value: "next",
|
|
2948
|
+
label: "Next.js",
|
|
2949
|
+
hint: "The React Framework for the Web"
|
|
2950
|
+
},
|
|
2951
|
+
{
|
|
2952
|
+
value: "nuxt",
|
|
2953
|
+
label: "Nuxt",
|
|
2954
|
+
hint: "The Progressive Web Framework for Vue.js"
|
|
2955
|
+
},
|
|
2956
|
+
{
|
|
2957
|
+
value: "svelte",
|
|
2958
|
+
label: "SvelteKit",
|
|
2959
|
+
hint: "Full-stack Svelte framework with SSR and server routes"
|
|
2960
|
+
},
|
|
2961
|
+
{
|
|
2962
|
+
value: "solid",
|
|
2963
|
+
label: "Solid",
|
|
2964
|
+
hint: "Simple and performant reactivity for building user interfaces"
|
|
2965
|
+
},
|
|
2966
|
+
{
|
|
2967
|
+
value: "solid-start",
|
|
2968
|
+
label: "SolidStart",
|
|
2969
|
+
hint: "Full-stack Solid framework with SSR and API routes"
|
|
2970
|
+
},
|
|
2971
|
+
{
|
|
2972
|
+
value: "astro",
|
|
2973
|
+
label: "Astro",
|
|
2974
|
+
hint: "Content-focused with Island Architecture"
|
|
2975
|
+
},
|
|
2976
|
+
{
|
|
2977
|
+
value: "tanstack-start",
|
|
2978
|
+
label: "TanStack Start",
|
|
2979
|
+
hint: "SSR, Server Functions, API Routes and more with TanStack Router"
|
|
2980
|
+
},
|
|
2981
|
+
{
|
|
2982
|
+
value: "qwik",
|
|
2983
|
+
label: "Qwik",
|
|
2984
|
+
hint: "Resumable framework with instant load times"
|
|
2985
|
+
},
|
|
2986
|
+
{
|
|
2987
|
+
value: "angular",
|
|
2988
|
+
label: "Angular",
|
|
2989
|
+
hint: "Enterprise-grade TypeScript framework by Google"
|
|
2990
|
+
},
|
|
2991
|
+
{
|
|
2992
|
+
value: "redwood",
|
|
2993
|
+
label: "RedwoodJS",
|
|
2994
|
+
hint: "Opinionated fullstack (React + GraphQL + Prisma)"
|
|
2995
|
+
},
|
|
2996
|
+
{
|
|
2997
|
+
value: "fresh",
|
|
2998
|
+
label: "Fresh",
|
|
2999
|
+
hint: "Deno-native framework with islands architecture"
|
|
3000
|
+
}
|
|
3001
|
+
];
|
|
3002
|
+
const NATIVE_FRONTEND_PROMPT_OPTIONS = [
|
|
3003
|
+
{
|
|
3004
|
+
value: "native-bare",
|
|
3005
|
+
label: "Bare",
|
|
3006
|
+
hint: "Bare Expo without styling library"
|
|
3007
|
+
},
|
|
3008
|
+
{
|
|
3009
|
+
value: "native-uniwind",
|
|
3010
|
+
label: "Uniwind",
|
|
3011
|
+
hint: "Fastest Tailwind bindings for React Native with HeroUI Native"
|
|
3012
|
+
},
|
|
3013
|
+
{
|
|
3014
|
+
value: "native-unistyles",
|
|
3015
|
+
label: "Unistyles",
|
|
3016
|
+
hint: "Consistent styling for React Native"
|
|
3017
|
+
}
|
|
3018
|
+
];
|
|
3019
|
+
function resolveFrontendPrompt(context = {}) {
|
|
3020
|
+
const options = [...WEB_FRONTEND_PROMPT_OPTIONS.filter((option) => isFrontendAllowedWithBackend$1(option.value, context.backend, context.auth)), ...NATIVE_FRONTEND_PROMPT_OPTIONS];
|
|
3021
|
+
return context.frontendOptions !== void 0 ? {
|
|
3022
|
+
shouldPrompt: false,
|
|
3023
|
+
mode: "multiple",
|
|
3024
|
+
options,
|
|
3025
|
+
autoValue: context.frontendOptions
|
|
3026
|
+
} : {
|
|
3027
|
+
shouldPrompt: true,
|
|
3028
|
+
mode: "multiple",
|
|
3029
|
+
options,
|
|
3030
|
+
initialValue: DEFAULT_CONFIG.frontend
|
|
3031
|
+
};
|
|
3032
|
+
}
|
|
2446
3033
|
async function getFrontendChoice(frontendOptions, backend, auth) {
|
|
2447
|
-
|
|
3034
|
+
const resolution = resolveFrontendPrompt({
|
|
3035
|
+
frontendOptions,
|
|
3036
|
+
backend,
|
|
3037
|
+
auth
|
|
3038
|
+
});
|
|
3039
|
+
if (!resolution.shouldPrompt) return resolution.autoValue ?? [];
|
|
3040
|
+
const allowedValues = new Set(resolution.options.map((option) => option.value));
|
|
3041
|
+
const initialValues = resolution.initialValue ?? DEFAULT_CONFIG.frontend;
|
|
3042
|
+
const initialTypes = [...initialValues.some((value) => WEB_FRONTEND_PROMPT_OPTIONS.some((option) => option.value === value)) ? ["web"] : [], ...initialValues.some((value) => NATIVE_FRONTEND_PROMPT_OPTIONS.some((option) => option.value === value)) ? ["native"] : []];
|
|
2448
3043
|
while (true) {
|
|
2449
3044
|
const wasFirstPrompt = isFirstPrompt();
|
|
2450
3045
|
const frontendTypes = await navigableMultiselect({
|
|
@@ -2459,7 +3054,7 @@ async function getFrontendChoice(frontendOptions, backend, auth) {
|
|
|
2459
3054
|
hint: "Create a React Native/Expo app"
|
|
2460
3055
|
}],
|
|
2461
3056
|
required: false,
|
|
2462
|
-
initialValues: ["web"]
|
|
3057
|
+
initialValues: initialTypes.length > 0 ? [...initialTypes] : ["web"]
|
|
2463
3058
|
});
|
|
2464
3059
|
if (isGoBack(frontendTypes)) return GO_BACK_SYMBOL;
|
|
2465
3060
|
if (isCancel$1(frontendTypes)) return exitCancelled("Operation cancelled");
|
|
@@ -2467,81 +3062,12 @@ async function getFrontendChoice(frontendOptions, backend, auth) {
|
|
|
2467
3062
|
const result = [];
|
|
2468
3063
|
let shouldRestart = false;
|
|
2469
3064
|
if (frontendTypes.includes("web")) {
|
|
3065
|
+
const webOptions = WEB_FRONTEND_PROMPT_OPTIONS.filter((option) => allowedValues.has(option.value));
|
|
3066
|
+
const initialWebValue = initialValues.find((value) => webOptions.some((option) => option.value === value)) ?? webOptions[0]?.value;
|
|
2470
3067
|
const webFramework = await navigableSelect({
|
|
2471
3068
|
message: "Select web framework",
|
|
2472
|
-
options:
|
|
2473
|
-
|
|
2474
|
-
value: "tanstack-router",
|
|
2475
|
-
label: "TanStack Router",
|
|
2476
|
-
hint: "Modern and scalable routing for React Applications"
|
|
2477
|
-
},
|
|
2478
|
-
{
|
|
2479
|
-
value: "react-router",
|
|
2480
|
-
label: "React Router",
|
|
2481
|
-
hint: "A user‑obsessed, standards‑focused, multi‑strategy router"
|
|
2482
|
-
},
|
|
2483
|
-
{
|
|
2484
|
-
value: "react-vite",
|
|
2485
|
-
label: "React + Vite",
|
|
2486
|
-
hint: "Client-routed React SPA powered by Vite"
|
|
2487
|
-
},
|
|
2488
|
-
{
|
|
2489
|
-
value: "next",
|
|
2490
|
-
label: "Next.js",
|
|
2491
|
-
hint: "The React Framework for the Web"
|
|
2492
|
-
},
|
|
2493
|
-
{
|
|
2494
|
-
value: "nuxt",
|
|
2495
|
-
label: "Nuxt",
|
|
2496
|
-
hint: "The Progressive Web Framework for Vue.js"
|
|
2497
|
-
},
|
|
2498
|
-
{
|
|
2499
|
-
value: "svelte",
|
|
2500
|
-
label: "SvelteKit",
|
|
2501
|
-
hint: "Full-stack Svelte framework with SSR and server routes"
|
|
2502
|
-
},
|
|
2503
|
-
{
|
|
2504
|
-
value: "solid",
|
|
2505
|
-
label: "Solid",
|
|
2506
|
-
hint: "Simple and performant reactivity for building user interfaces"
|
|
2507
|
-
},
|
|
2508
|
-
{
|
|
2509
|
-
value: "solid-start",
|
|
2510
|
-
label: "SolidStart",
|
|
2511
|
-
hint: "Full-stack Solid framework with SSR and API routes"
|
|
2512
|
-
},
|
|
2513
|
-
{
|
|
2514
|
-
value: "astro",
|
|
2515
|
-
label: "Astro",
|
|
2516
|
-
hint: "Content-focused with Island Architecture"
|
|
2517
|
-
},
|
|
2518
|
-
{
|
|
2519
|
-
value: "tanstack-start",
|
|
2520
|
-
label: "TanStack Start",
|
|
2521
|
-
hint: "SSR, Server Functions, API Routes and more with TanStack Router"
|
|
2522
|
-
},
|
|
2523
|
-
{
|
|
2524
|
-
value: "qwik",
|
|
2525
|
-
label: "Qwik",
|
|
2526
|
-
hint: "Resumable framework with instant load times"
|
|
2527
|
-
},
|
|
2528
|
-
{
|
|
2529
|
-
value: "angular",
|
|
2530
|
-
label: "Angular",
|
|
2531
|
-
hint: "Enterprise-grade TypeScript framework by Google"
|
|
2532
|
-
},
|
|
2533
|
-
{
|
|
2534
|
-
value: "redwood",
|
|
2535
|
-
label: "RedwoodJS",
|
|
2536
|
-
hint: "Opinionated fullstack (React + GraphQL + Prisma)"
|
|
2537
|
-
},
|
|
2538
|
-
{
|
|
2539
|
-
value: "fresh",
|
|
2540
|
-
label: "Fresh",
|
|
2541
|
-
hint: "Deno-native framework with islands architecture"
|
|
2542
|
-
}
|
|
2543
|
-
].filter((option) => isFrontendAllowedWithBackend$1(option.value, backend, auth)),
|
|
2544
|
-
initialValue: DEFAULT_CONFIG.frontend[0]
|
|
3069
|
+
options: webOptions,
|
|
3070
|
+
...initialWebValue ? { initialValue: initialWebValue } : {}
|
|
2545
3071
|
});
|
|
2546
3072
|
if (isGoBack(webFramework)) shouldRestart = true;
|
|
2547
3073
|
else if (isCancel$1(webFramework)) return exitCancelled("Operation cancelled");
|
|
@@ -2552,26 +3078,12 @@ async function getFrontendChoice(frontendOptions, backend, auth) {
|
|
|
2552
3078
|
continue;
|
|
2553
3079
|
}
|
|
2554
3080
|
if (frontendTypes.includes("native")) {
|
|
3081
|
+
const nativeOptions = NATIVE_FRONTEND_PROMPT_OPTIONS.filter((option) => allowedValues.has(option.value));
|
|
3082
|
+
const initialNativeValue = initialValues.find((value) => nativeOptions.some((option) => option.value === value)) ?? nativeOptions[0]?.value;
|
|
2555
3083
|
const nativeFramework = await navigableSelect({
|
|
2556
3084
|
message: "Choose native",
|
|
2557
|
-
options:
|
|
2558
|
-
|
|
2559
|
-
value: "native-bare",
|
|
2560
|
-
label: "Bare",
|
|
2561
|
-
hint: "Bare Expo without styling library"
|
|
2562
|
-
},
|
|
2563
|
-
{
|
|
2564
|
-
value: "native-uniwind",
|
|
2565
|
-
label: "Uniwind",
|
|
2566
|
-
hint: "Fastest Tailwind bindings for React Native with HeroUI Native"
|
|
2567
|
-
},
|
|
2568
|
-
{
|
|
2569
|
-
value: "native-unistyles",
|
|
2570
|
-
label: "Unistyles",
|
|
2571
|
-
hint: "Consistent styling for React Native"
|
|
2572
|
-
}
|
|
2573
|
-
],
|
|
2574
|
-
initialValue: "native-bare"
|
|
3085
|
+
options: nativeOptions,
|
|
3086
|
+
...initialNativeValue ? { initialValue: initialNativeValue } : {}
|
|
2575
3087
|
});
|
|
2576
3088
|
if (isGoBack(nativeFramework)) if (frontendTypes.includes("web")) shouldRestart = true;
|
|
2577
3089
|
else {
|
|
@@ -2603,144 +3115,200 @@ async function getGitChoice(git) {
|
|
|
2603
3115
|
|
|
2604
3116
|
//#endregion
|
|
2605
3117
|
//#region src/prompts/go-ecosystem.ts
|
|
3118
|
+
const GO_WEB_FRAMEWORK_PROMPT_OPTIONS = [
|
|
3119
|
+
{
|
|
3120
|
+
value: "gin",
|
|
3121
|
+
label: "Gin",
|
|
3122
|
+
hint: "High-performance HTTP web framework with martini-like API"
|
|
3123
|
+
},
|
|
3124
|
+
{
|
|
3125
|
+
value: "echo",
|
|
3126
|
+
label: "Echo",
|
|
3127
|
+
hint: "High performance, minimalist Go web framework"
|
|
3128
|
+
},
|
|
3129
|
+
{
|
|
3130
|
+
value: "fiber",
|
|
3131
|
+
label: "Fiber",
|
|
3132
|
+
hint: "Express-inspired web framework built on Fasthttp"
|
|
3133
|
+
},
|
|
3134
|
+
{
|
|
3135
|
+
value: "chi",
|
|
3136
|
+
label: "Chi",
|
|
3137
|
+
hint: "Lightweight, zero-dependency router built on net/http"
|
|
3138
|
+
},
|
|
3139
|
+
{
|
|
3140
|
+
value: "none",
|
|
3141
|
+
label: "None",
|
|
3142
|
+
hint: "No web framework"
|
|
3143
|
+
}
|
|
3144
|
+
];
|
|
3145
|
+
const GO_ORM_PROMPT_OPTIONS = [
|
|
3146
|
+
{
|
|
3147
|
+
value: "gorm",
|
|
3148
|
+
label: "GORM",
|
|
3149
|
+
hint: "The fantastic ORM library for Golang"
|
|
3150
|
+
},
|
|
3151
|
+
{
|
|
3152
|
+
value: "sqlc",
|
|
3153
|
+
label: "sqlc",
|
|
3154
|
+
hint: "Generate type-safe Go code from SQL"
|
|
3155
|
+
},
|
|
3156
|
+
{
|
|
3157
|
+
value: "ent",
|
|
3158
|
+
label: "Ent",
|
|
3159
|
+
hint: "Code-first ORM by Meta with graph traversal API, 15k+ stars"
|
|
3160
|
+
},
|
|
3161
|
+
{
|
|
3162
|
+
value: "none",
|
|
3163
|
+
label: "None",
|
|
3164
|
+
hint: "No ORM/database layer"
|
|
3165
|
+
}
|
|
3166
|
+
];
|
|
3167
|
+
const GO_API_PROMPT_OPTIONS = [{
|
|
3168
|
+
value: "grpc-go",
|
|
3169
|
+
label: "gRPC-Go",
|
|
3170
|
+
hint: "The Go implementation of gRPC"
|
|
3171
|
+
}, {
|
|
3172
|
+
value: "none",
|
|
3173
|
+
label: "None",
|
|
3174
|
+
hint: "No API layer"
|
|
3175
|
+
}];
|
|
3176
|
+
const GO_CLI_PROMPT_OPTIONS = [
|
|
3177
|
+
{
|
|
3178
|
+
value: "cobra",
|
|
3179
|
+
label: "Cobra",
|
|
3180
|
+
hint: "Library for creating powerful modern CLI applications"
|
|
3181
|
+
},
|
|
3182
|
+
{
|
|
3183
|
+
value: "bubbletea",
|
|
3184
|
+
label: "Bubble Tea",
|
|
3185
|
+
hint: "Powerful TUI framework based on The Elm Architecture"
|
|
3186
|
+
},
|
|
3187
|
+
{
|
|
3188
|
+
value: "none",
|
|
3189
|
+
label: "None",
|
|
3190
|
+
hint: "No CLI tools"
|
|
3191
|
+
}
|
|
3192
|
+
];
|
|
3193
|
+
const GO_LOGGING_PROMPT_OPTIONS = [
|
|
3194
|
+
{
|
|
3195
|
+
value: "zap",
|
|
3196
|
+
label: "Zap",
|
|
3197
|
+
hint: "Blazing fast, structured, leveled logging in Go"
|
|
3198
|
+
},
|
|
3199
|
+
{
|
|
3200
|
+
value: "zerolog",
|
|
3201
|
+
label: "Zerolog",
|
|
3202
|
+
hint: "Zero-allocation JSON logger, fastest in benchmarks"
|
|
3203
|
+
},
|
|
3204
|
+
{
|
|
3205
|
+
value: "slog",
|
|
3206
|
+
label: "slog",
|
|
3207
|
+
hint: "Go 1.21+ stdlib structured logging (no external dependency)"
|
|
3208
|
+
},
|
|
3209
|
+
{
|
|
3210
|
+
value: "none",
|
|
3211
|
+
label: "None",
|
|
3212
|
+
hint: "No logging library"
|
|
3213
|
+
}
|
|
3214
|
+
];
|
|
3215
|
+
const GO_AUTH_PROMPT_OPTIONS = [
|
|
3216
|
+
{
|
|
3217
|
+
value: "casbin",
|
|
3218
|
+
label: "Casbin",
|
|
3219
|
+
hint: "Model-based authorization (ACL, RBAC, ABAC) via config files"
|
|
3220
|
+
},
|
|
3221
|
+
{
|
|
3222
|
+
value: "jwt",
|
|
3223
|
+
label: "golang-jwt",
|
|
3224
|
+
hint: "JWT token creation and validation with HMAC/RSA/ECDSA signing"
|
|
3225
|
+
},
|
|
3226
|
+
{
|
|
3227
|
+
value: "none",
|
|
3228
|
+
label: "None",
|
|
3229
|
+
hint: "No authentication library"
|
|
3230
|
+
}
|
|
3231
|
+
];
|
|
3232
|
+
function resolveGoWebFrameworkPrompt(goWebFramework) {
|
|
3233
|
+
return createStaticSinglePromptResolution(GO_WEB_FRAMEWORK_PROMPT_OPTIONS, "gin", goWebFramework);
|
|
3234
|
+
}
|
|
2606
3235
|
async function getGoWebFrameworkChoice(goWebFramework) {
|
|
2607
|
-
|
|
3236
|
+
const resolution = resolveGoWebFrameworkPrompt(goWebFramework);
|
|
3237
|
+
if (!resolution.shouldPrompt) return resolution.autoValue ?? "none";
|
|
2608
3238
|
const response = await navigableSelect({
|
|
2609
3239
|
message: "Select Go web framework",
|
|
2610
|
-
options:
|
|
2611
|
-
|
|
2612
|
-
value: "gin",
|
|
2613
|
-
label: "Gin",
|
|
2614
|
-
hint: "High-performance HTTP web framework with martini-like API"
|
|
2615
|
-
},
|
|
2616
|
-
{
|
|
2617
|
-
value: "echo",
|
|
2618
|
-
label: "Echo",
|
|
2619
|
-
hint: "High performance, minimalist Go web framework"
|
|
2620
|
-
},
|
|
2621
|
-
{
|
|
2622
|
-
value: "fiber",
|
|
2623
|
-
label: "Fiber",
|
|
2624
|
-
hint: "Express-inspired web framework built on Fasthttp"
|
|
2625
|
-
},
|
|
2626
|
-
{
|
|
2627
|
-
value: "chi",
|
|
2628
|
-
label: "Chi",
|
|
2629
|
-
hint: "Lightweight, zero-dependency router built on net/http"
|
|
2630
|
-
},
|
|
2631
|
-
{
|
|
2632
|
-
value: "none",
|
|
2633
|
-
label: "None",
|
|
2634
|
-
hint: "No web framework"
|
|
2635
|
-
}
|
|
2636
|
-
],
|
|
2637
|
-
initialValue: "gin"
|
|
3240
|
+
options: resolution.options,
|
|
3241
|
+
initialValue: resolution.initialValue
|
|
2638
3242
|
});
|
|
2639
3243
|
if (isCancel$1(response)) return exitCancelled("Operation cancelled");
|
|
2640
3244
|
return response;
|
|
2641
3245
|
}
|
|
3246
|
+
function resolveGoOrmPrompt(goOrm) {
|
|
3247
|
+
return createStaticSinglePromptResolution(GO_ORM_PROMPT_OPTIONS, "gorm", goOrm);
|
|
3248
|
+
}
|
|
2642
3249
|
async function getGoOrmChoice(goOrm) {
|
|
2643
|
-
|
|
3250
|
+
const resolution = resolveGoOrmPrompt(goOrm);
|
|
3251
|
+
if (!resolution.shouldPrompt) return resolution.autoValue ?? "none";
|
|
2644
3252
|
const response = await navigableSelect({
|
|
2645
3253
|
message: "Select Go ORM/database layer",
|
|
2646
|
-
options:
|
|
2647
|
-
|
|
2648
|
-
value: "gorm",
|
|
2649
|
-
label: "GORM",
|
|
2650
|
-
hint: "The fantastic ORM library for Golang"
|
|
2651
|
-
},
|
|
2652
|
-
{
|
|
2653
|
-
value: "sqlc",
|
|
2654
|
-
label: "sqlc",
|
|
2655
|
-
hint: "Generate type-safe Go code from SQL"
|
|
2656
|
-
},
|
|
2657
|
-
{
|
|
2658
|
-
value: "ent",
|
|
2659
|
-
label: "Ent",
|
|
2660
|
-
hint: "Code-first ORM by Meta with graph traversal API, 15k+ stars"
|
|
2661
|
-
},
|
|
2662
|
-
{
|
|
2663
|
-
value: "none",
|
|
2664
|
-
label: "None",
|
|
2665
|
-
hint: "No ORM/database layer"
|
|
2666
|
-
}
|
|
2667
|
-
],
|
|
2668
|
-
initialValue: "gorm"
|
|
3254
|
+
options: resolution.options,
|
|
3255
|
+
initialValue: resolution.initialValue
|
|
2669
3256
|
});
|
|
2670
3257
|
if (isCancel$1(response)) return exitCancelled("Operation cancelled");
|
|
2671
3258
|
return response;
|
|
2672
3259
|
}
|
|
3260
|
+
function resolveGoApiPrompt(goApi) {
|
|
3261
|
+
return createStaticSinglePromptResolution(GO_API_PROMPT_OPTIONS, "none", goApi);
|
|
3262
|
+
}
|
|
2673
3263
|
async function getGoApiChoice(goApi) {
|
|
2674
|
-
|
|
3264
|
+
const resolution = resolveGoApiPrompt(goApi);
|
|
3265
|
+
if (!resolution.shouldPrompt) return resolution.autoValue ?? "none";
|
|
2675
3266
|
const response = await navigableSelect({
|
|
2676
3267
|
message: "Select Go API layer",
|
|
2677
|
-
options:
|
|
2678
|
-
|
|
2679
|
-
label: "gRPC-Go",
|
|
2680
|
-
hint: "The Go implementation of gRPC"
|
|
2681
|
-
}, {
|
|
2682
|
-
value: "none",
|
|
2683
|
-
label: "None",
|
|
2684
|
-
hint: "No API layer"
|
|
2685
|
-
}],
|
|
2686
|
-
initialValue: "none"
|
|
3268
|
+
options: resolution.options,
|
|
3269
|
+
initialValue: resolution.initialValue
|
|
2687
3270
|
});
|
|
2688
3271
|
if (isCancel$1(response)) return exitCancelled("Operation cancelled");
|
|
2689
3272
|
return response;
|
|
2690
3273
|
}
|
|
3274
|
+
function resolveGoCliPrompt(goCli) {
|
|
3275
|
+
return createStaticSinglePromptResolution(GO_CLI_PROMPT_OPTIONS, "none", goCli);
|
|
3276
|
+
}
|
|
2691
3277
|
async function getGoCliChoice(goCli) {
|
|
2692
|
-
|
|
3278
|
+
const resolution = resolveGoCliPrompt(goCli);
|
|
3279
|
+
if (!resolution.shouldPrompt) return resolution.autoValue ?? "none";
|
|
2693
3280
|
const response = await navigableSelect({
|
|
2694
3281
|
message: "Select Go CLI tools",
|
|
2695
|
-
options:
|
|
2696
|
-
|
|
2697
|
-
value: "cobra",
|
|
2698
|
-
label: "Cobra",
|
|
2699
|
-
hint: "Library for creating powerful modern CLI applications"
|
|
2700
|
-
},
|
|
2701
|
-
{
|
|
2702
|
-
value: "bubbletea",
|
|
2703
|
-
label: "Bubble Tea",
|
|
2704
|
-
hint: "Powerful TUI framework based on The Elm Architecture"
|
|
2705
|
-
},
|
|
2706
|
-
{
|
|
2707
|
-
value: "none",
|
|
2708
|
-
label: "None",
|
|
2709
|
-
hint: "No CLI tools"
|
|
2710
|
-
}
|
|
2711
|
-
],
|
|
2712
|
-
initialValue: "none"
|
|
3282
|
+
options: resolution.options,
|
|
3283
|
+
initialValue: resolution.initialValue
|
|
2713
3284
|
});
|
|
2714
3285
|
if (isCancel$1(response)) return exitCancelled("Operation cancelled");
|
|
2715
3286
|
return response;
|
|
2716
3287
|
}
|
|
3288
|
+
function resolveGoLoggingPrompt(goLogging) {
|
|
3289
|
+
return createStaticSinglePromptResolution(GO_LOGGING_PROMPT_OPTIONS, "zap", goLogging);
|
|
3290
|
+
}
|
|
2717
3291
|
async function getGoLoggingChoice(goLogging) {
|
|
2718
|
-
|
|
3292
|
+
const resolution = resolveGoLoggingPrompt(goLogging);
|
|
3293
|
+
if (!resolution.shouldPrompt) return resolution.autoValue ?? "none";
|
|
2719
3294
|
const response = await navigableSelect({
|
|
2720
3295
|
message: "Select Go logging library",
|
|
2721
|
-
options:
|
|
2722
|
-
|
|
2723
|
-
|
|
2724
|
-
|
|
2725
|
-
|
|
2726
|
-
|
|
2727
|
-
|
|
2728
|
-
|
|
2729
|
-
|
|
2730
|
-
|
|
2731
|
-
|
|
2732
|
-
|
|
2733
|
-
|
|
2734
|
-
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
{
|
|
2738
|
-
value: "none",
|
|
2739
|
-
label: "None",
|
|
2740
|
-
hint: "No logging library"
|
|
2741
|
-
}
|
|
2742
|
-
],
|
|
2743
|
-
initialValue: "zap"
|
|
3296
|
+
options: resolution.options,
|
|
3297
|
+
initialValue: resolution.initialValue
|
|
3298
|
+
});
|
|
3299
|
+
if (isCancel$1(response)) return exitCancelled("Operation cancelled");
|
|
3300
|
+
return response;
|
|
3301
|
+
}
|
|
3302
|
+
function resolveGoAuthPrompt(goAuth) {
|
|
3303
|
+
return createStaticSinglePromptResolution(GO_AUTH_PROMPT_OPTIONS, "none", goAuth);
|
|
3304
|
+
}
|
|
3305
|
+
async function getGoAuthChoice(goAuth) {
|
|
3306
|
+
const resolution = resolveGoAuthPrompt(goAuth);
|
|
3307
|
+
if (!resolution.shouldPrompt) return resolution.autoValue ?? "none";
|
|
3308
|
+
const response = await navigableSelect({
|
|
3309
|
+
message: "Select Go authentication library",
|
|
3310
|
+
options: resolution.options,
|
|
3311
|
+
initialValue: resolution.initialValue
|
|
2744
3312
|
});
|
|
2745
3313
|
if (isCancel$1(response)) return exitCancelled("Operation cancelled");
|
|
2746
3314
|
return response;
|
|
@@ -2788,7 +3356,7 @@ async function commandExists(command) {
|
|
|
2788
3356
|
|
|
2789
3357
|
//#endregion
|
|
2790
3358
|
//#region src/prompts/install.ts
|
|
2791
|
-
async function getinstallChoice(install, ecosystem) {
|
|
3359
|
+
async function getinstallChoice(install, ecosystem, javaBuildTool) {
|
|
2792
3360
|
if (install !== void 0) return install;
|
|
2793
3361
|
if (ecosystem === "rust") {
|
|
2794
3362
|
if (!await commandExists("cargo")) {
|
|
@@ -2826,6 +3394,22 @@ async function getinstallChoice(install, ecosystem) {
|
|
|
2826
3394
|
if (isCancel$1(response$1)) return exitCancelled("Operation cancelled");
|
|
2827
3395
|
return response$1;
|
|
2828
3396
|
}
|
|
3397
|
+
if (ecosystem === "java") {
|
|
3398
|
+
if (!await commandExists("java")) {
|
|
3399
|
+
log.warn("Java is not installed. Please install a JDK from https://adoptium.net/ or your preferred vendor.");
|
|
3400
|
+
return false;
|
|
3401
|
+
}
|
|
3402
|
+
if (javaBuildTool === "none") {
|
|
3403
|
+
log.warn("No Java build tool selected. Skipping Java install verification.");
|
|
3404
|
+
return false;
|
|
3405
|
+
}
|
|
3406
|
+
const response$1 = await navigableConfirm({
|
|
3407
|
+
message: `Run ${javaBuildTool === "gradle" ? "./gradlew test" : "./mvnw test"}?`,
|
|
3408
|
+
initialValue: DEFAULT_CONFIG.install
|
|
3409
|
+
});
|
|
3410
|
+
if (isCancel$1(response$1)) return exitCancelled("Operation cancelled");
|
|
3411
|
+
return response$1;
|
|
3412
|
+
}
|
|
2829
3413
|
const response = await navigableConfirm({
|
|
2830
3414
|
message: "Install dependencies?",
|
|
2831
3415
|
initialValue: DEFAULT_CONFIG.install
|
|
@@ -2834,41 +3418,298 @@ async function getinstallChoice(install, ecosystem) {
|
|
|
2834
3418
|
return response;
|
|
2835
3419
|
}
|
|
2836
3420
|
|
|
3421
|
+
//#endregion
|
|
3422
|
+
//#region src/prompts/java-ecosystem.ts
|
|
3423
|
+
const JAVA_WEB_FRAMEWORK_PROMPT_OPTIONS = [{
|
|
3424
|
+
value: "spring-boot",
|
|
3425
|
+
label: "Spring Boot",
|
|
3426
|
+
hint: "Production-grade Java framework with embedded server and auto-configuration"
|
|
3427
|
+
}, {
|
|
3428
|
+
value: "none",
|
|
3429
|
+
label: "None",
|
|
3430
|
+
hint: "No Java web framework"
|
|
3431
|
+
}];
|
|
3432
|
+
const JAVA_BUILD_TOOL_PROMPT_OPTIONS = [
|
|
3433
|
+
{
|
|
3434
|
+
value: "maven",
|
|
3435
|
+
label: "Maven",
|
|
3436
|
+
hint: "Convention-based build tool with Maven Wrapper support"
|
|
3437
|
+
},
|
|
3438
|
+
{
|
|
3439
|
+
value: "gradle",
|
|
3440
|
+
label: "Gradle",
|
|
3441
|
+
hint: "Flexible build tool with Gradle Wrapper support"
|
|
3442
|
+
},
|
|
3443
|
+
{
|
|
3444
|
+
value: "none",
|
|
3445
|
+
label: "None",
|
|
3446
|
+
hint: "No Java build tool"
|
|
3447
|
+
}
|
|
3448
|
+
];
|
|
3449
|
+
const JAVA_ORM_PROMPT_OPTIONS = [{
|
|
3450
|
+
value: "spring-data-jpa",
|
|
3451
|
+
label: "Spring Data JPA",
|
|
3452
|
+
hint: "Repository abstraction built on JPA/Hibernate"
|
|
3453
|
+
}, {
|
|
3454
|
+
value: "none",
|
|
3455
|
+
label: "None",
|
|
3456
|
+
hint: "No Java ORM/database layer"
|
|
3457
|
+
}];
|
|
3458
|
+
const JAVA_AUTH_PROMPT_OPTIONS = [{
|
|
3459
|
+
value: "spring-security",
|
|
3460
|
+
label: "Spring Security",
|
|
3461
|
+
hint: "Authentication and authorization for Spring applications"
|
|
3462
|
+
}, {
|
|
3463
|
+
value: "none",
|
|
3464
|
+
label: "None",
|
|
3465
|
+
hint: "No Java authentication library"
|
|
3466
|
+
}];
|
|
3467
|
+
const JAVA_TESTING_LIBRARY_PROMPT_OPTIONS = [
|
|
3468
|
+
{
|
|
3469
|
+
value: "junit5",
|
|
3470
|
+
label: "JUnit 5",
|
|
3471
|
+
hint: "Modern Java unit testing platform"
|
|
3472
|
+
},
|
|
3473
|
+
{
|
|
3474
|
+
value: "mockito",
|
|
3475
|
+
label: "Mockito",
|
|
3476
|
+
hint: "Mocking framework for isolated unit tests"
|
|
3477
|
+
},
|
|
3478
|
+
{
|
|
3479
|
+
value: "testcontainers",
|
|
3480
|
+
label: "Testcontainers",
|
|
3481
|
+
hint: "Disposable Docker-based integration tests"
|
|
3482
|
+
},
|
|
3483
|
+
{
|
|
3484
|
+
value: "assertj",
|
|
3485
|
+
label: "AssertJ",
|
|
3486
|
+
hint: "Fluent assertions for Java tests"
|
|
3487
|
+
},
|
|
3488
|
+
{
|
|
3489
|
+
value: "rest-assured",
|
|
3490
|
+
label: "REST Assured",
|
|
3491
|
+
hint: "DSL for HTTP API and REST endpoint tests"
|
|
3492
|
+
},
|
|
3493
|
+
{
|
|
3494
|
+
value: "wiremock",
|
|
3495
|
+
label: "WireMock",
|
|
3496
|
+
hint: "HTTP service stubs for integration tests"
|
|
3497
|
+
},
|
|
3498
|
+
{
|
|
3499
|
+
value: "awaitility",
|
|
3500
|
+
label: "Awaitility",
|
|
3501
|
+
hint: "Wait helpers for asynchronous Java tests"
|
|
3502
|
+
},
|
|
3503
|
+
{
|
|
3504
|
+
value: "archunit",
|
|
3505
|
+
label: "ArchUnit",
|
|
3506
|
+
hint: "Architecture rules for Java package boundaries"
|
|
3507
|
+
},
|
|
3508
|
+
{
|
|
3509
|
+
value: "jqwik",
|
|
3510
|
+
label: "jqwik",
|
|
3511
|
+
hint: "Property-based testing on the JUnit Platform"
|
|
3512
|
+
},
|
|
3513
|
+
{
|
|
3514
|
+
value: "none",
|
|
3515
|
+
label: "None",
|
|
3516
|
+
hint: "No extra testing libraries"
|
|
3517
|
+
}
|
|
3518
|
+
];
|
|
3519
|
+
const JAVA_LIBRARY_PROMPT_OPTIONS = [
|
|
3520
|
+
{
|
|
3521
|
+
value: "spring-actuator",
|
|
3522
|
+
label: "Spring Actuator",
|
|
3523
|
+
hint: "Production health, metrics, and diagnostics endpoints"
|
|
3524
|
+
},
|
|
3525
|
+
{
|
|
3526
|
+
value: "spring-validation",
|
|
3527
|
+
label: "Spring Validation",
|
|
3528
|
+
hint: "Bean validation for request and entity constraints"
|
|
3529
|
+
},
|
|
3530
|
+
{
|
|
3531
|
+
value: "flyway",
|
|
3532
|
+
label: "Flyway",
|
|
3533
|
+
hint: "Versioned SQL database migrations for JPA-backed apps"
|
|
3534
|
+
},
|
|
3535
|
+
{
|
|
3536
|
+
value: "liquibase",
|
|
3537
|
+
label: "Liquibase",
|
|
3538
|
+
hint: "Database change management for JPA-backed apps"
|
|
3539
|
+
},
|
|
3540
|
+
{
|
|
3541
|
+
value: "springdoc-openapi",
|
|
3542
|
+
label: "Springdoc OpenAPI",
|
|
3543
|
+
hint: "OpenAPI and Swagger UI documentation for Spring MVC APIs"
|
|
3544
|
+
},
|
|
3545
|
+
{
|
|
3546
|
+
value: "lombok",
|
|
3547
|
+
label: "Lombok",
|
|
3548
|
+
hint: "Annotation processor for reducing Java boilerplate"
|
|
3549
|
+
},
|
|
3550
|
+
{
|
|
3551
|
+
value: "mapstruct",
|
|
3552
|
+
label: "MapStruct",
|
|
3553
|
+
hint: "Compile-time generated mappers for DTO and entity conversions"
|
|
3554
|
+
},
|
|
3555
|
+
{
|
|
3556
|
+
value: "caffeine",
|
|
3557
|
+
label: "Caffeine",
|
|
3558
|
+
hint: "High-performance in-memory caching through Spring Cache"
|
|
3559
|
+
},
|
|
3560
|
+
{
|
|
3561
|
+
value: "none",
|
|
3562
|
+
label: "None",
|
|
3563
|
+
hint: "No extra Java libraries"
|
|
3564
|
+
}
|
|
3565
|
+
];
|
|
3566
|
+
function resolveJavaWebFrameworkPrompt(javaWebFramework) {
|
|
3567
|
+
return createStaticSinglePromptResolution(JAVA_WEB_FRAMEWORK_PROMPT_OPTIONS, "spring-boot", javaWebFramework);
|
|
3568
|
+
}
|
|
3569
|
+
async function getJavaWebFrameworkChoice(javaWebFramework) {
|
|
3570
|
+
const resolution = resolveJavaWebFrameworkPrompt(javaWebFramework);
|
|
3571
|
+
if (!resolution.shouldPrompt) return resolution.autoValue ?? "none";
|
|
3572
|
+
const response = await navigableSelect({
|
|
3573
|
+
message: "Select Java web framework",
|
|
3574
|
+
options: resolution.options,
|
|
3575
|
+
initialValue: resolution.initialValue
|
|
3576
|
+
});
|
|
3577
|
+
if (isCancel$1(response)) return exitCancelled("Operation cancelled");
|
|
3578
|
+
return response;
|
|
3579
|
+
}
|
|
3580
|
+
function resolveJavaBuildToolPrompt(javaBuildTool) {
|
|
3581
|
+
return createStaticSinglePromptResolution(JAVA_BUILD_TOOL_PROMPT_OPTIONS, "maven", javaBuildTool);
|
|
3582
|
+
}
|
|
3583
|
+
async function getJavaBuildToolChoice(javaBuildTool) {
|
|
3584
|
+
const resolution = resolveJavaBuildToolPrompt(javaBuildTool);
|
|
3585
|
+
if (!resolution.shouldPrompt) return resolution.autoValue ?? "none";
|
|
3586
|
+
const response = await navigableSelect({
|
|
3587
|
+
message: "Select Java build tool",
|
|
3588
|
+
options: resolution.options,
|
|
3589
|
+
initialValue: resolution.initialValue
|
|
3590
|
+
});
|
|
3591
|
+
if (isCancel$1(response)) return exitCancelled("Operation cancelled");
|
|
3592
|
+
return response;
|
|
3593
|
+
}
|
|
3594
|
+
function resolveJavaOrmPrompt(javaOrm) {
|
|
3595
|
+
return createStaticSinglePromptResolution(JAVA_ORM_PROMPT_OPTIONS, "none", javaOrm);
|
|
3596
|
+
}
|
|
3597
|
+
async function getJavaOrmChoice(javaOrm) {
|
|
3598
|
+
const resolution = resolveJavaOrmPrompt(javaOrm);
|
|
3599
|
+
if (!resolution.shouldPrompt) return resolution.autoValue ?? "none";
|
|
3600
|
+
const response = await navigableSelect({
|
|
3601
|
+
message: "Select Java ORM/database layer",
|
|
3602
|
+
options: resolution.options,
|
|
3603
|
+
initialValue: resolution.initialValue
|
|
3604
|
+
});
|
|
3605
|
+
if (isCancel$1(response)) return exitCancelled("Operation cancelled");
|
|
3606
|
+
return response;
|
|
3607
|
+
}
|
|
3608
|
+
function resolveJavaAuthPrompt(javaAuth) {
|
|
3609
|
+
return createStaticSinglePromptResolution(JAVA_AUTH_PROMPT_OPTIONS, "none", javaAuth);
|
|
3610
|
+
}
|
|
3611
|
+
async function getJavaAuthChoice(javaAuth) {
|
|
3612
|
+
const resolution = resolveJavaAuthPrompt(javaAuth);
|
|
3613
|
+
if (!resolution.shouldPrompt) return resolution.autoValue ?? "none";
|
|
3614
|
+
const response = await navigableSelect({
|
|
3615
|
+
message: "Select Java authentication library",
|
|
3616
|
+
options: resolution.options,
|
|
3617
|
+
initialValue: resolution.initialValue
|
|
3618
|
+
});
|
|
3619
|
+
if (isCancel$1(response)) return exitCancelled("Operation cancelled");
|
|
3620
|
+
return response;
|
|
3621
|
+
}
|
|
3622
|
+
function resolveJavaLibrariesPrompt(javaLibraries) {
|
|
3623
|
+
return createStaticMultiPromptResolution(JAVA_LIBRARY_PROMPT_OPTIONS, [], javaLibraries);
|
|
3624
|
+
}
|
|
3625
|
+
async function getJavaLibrariesChoice(javaLibraries) {
|
|
3626
|
+
const resolution = resolveJavaLibrariesPrompt(javaLibraries);
|
|
3627
|
+
if (!resolution.shouldPrompt) return resolution.autoValue ?? [];
|
|
3628
|
+
const response = await navigableMultiselect({
|
|
3629
|
+
message: "Select Java application libraries",
|
|
3630
|
+
options: resolution.options,
|
|
3631
|
+
required: false,
|
|
3632
|
+
initialValues: resolution.initialValue
|
|
3633
|
+
});
|
|
3634
|
+
if (isCancel$1(response)) return exitCancelled("Operation cancelled");
|
|
3635
|
+
if (response.includes("none")) return [];
|
|
3636
|
+
return response;
|
|
3637
|
+
}
|
|
3638
|
+
function resolveJavaTestingLibrariesPrompt(javaTestingLibraries) {
|
|
3639
|
+
return createStaticMultiPromptResolution(JAVA_TESTING_LIBRARY_PROMPT_OPTIONS, ["junit5"], javaTestingLibraries);
|
|
3640
|
+
}
|
|
3641
|
+
async function getJavaTestingLibrariesChoice(javaTestingLibraries) {
|
|
3642
|
+
const resolution = resolveJavaTestingLibrariesPrompt(javaTestingLibraries);
|
|
3643
|
+
if (!resolution.shouldPrompt) return resolution.autoValue ?? [];
|
|
3644
|
+
const response = await navigableMultiselect({
|
|
3645
|
+
message: "Select Java testing libraries",
|
|
3646
|
+
options: resolution.options,
|
|
3647
|
+
required: false,
|
|
3648
|
+
initialValues: resolution.initialValue
|
|
3649
|
+
});
|
|
3650
|
+
if (isCancel$1(response)) return exitCancelled("Operation cancelled");
|
|
3651
|
+
if (response.includes("none")) return [];
|
|
3652
|
+
return response;
|
|
3653
|
+
}
|
|
3654
|
+
|
|
2837
3655
|
//#endregion
|
|
2838
3656
|
//#region src/prompts/job-queue.ts
|
|
3657
|
+
const JOB_QUEUE_PROMPT_OPTIONS = [
|
|
3658
|
+
{
|
|
3659
|
+
value: "bullmq",
|
|
3660
|
+
label: "BullMQ",
|
|
3661
|
+
hint: "Redis-backed job queue for background tasks and scheduling"
|
|
3662
|
+
},
|
|
3663
|
+
{
|
|
3664
|
+
value: "trigger-dev",
|
|
3665
|
+
label: "Trigger.dev",
|
|
3666
|
+
hint: "Background jobs as code with serverless execution"
|
|
3667
|
+
},
|
|
3668
|
+
{
|
|
3669
|
+
value: "inngest",
|
|
3670
|
+
label: "Inngest",
|
|
3671
|
+
hint: "Event-driven functions with built-in queuing and scheduling"
|
|
3672
|
+
},
|
|
3673
|
+
{
|
|
3674
|
+
value: "temporal",
|
|
3675
|
+
label: "Temporal",
|
|
3676
|
+
hint: "Durable workflow orchestration for reliable distributed systems"
|
|
3677
|
+
},
|
|
3678
|
+
{
|
|
3679
|
+
value: "none",
|
|
3680
|
+
label: "None",
|
|
3681
|
+
hint: "Skip job queue/background worker setup"
|
|
3682
|
+
}
|
|
3683
|
+
];
|
|
3684
|
+
function resolveJobQueuePrompt(context = {}) {
|
|
3685
|
+
if (context.backend === "none" || context.backend === "convex") return {
|
|
3686
|
+
shouldPrompt: false,
|
|
3687
|
+
mode: "single",
|
|
3688
|
+
options: [],
|
|
3689
|
+
autoValue: "none"
|
|
3690
|
+
};
|
|
3691
|
+
return context.jobQueue !== void 0 ? {
|
|
3692
|
+
shouldPrompt: false,
|
|
3693
|
+
mode: "single",
|
|
3694
|
+
options: JOB_QUEUE_PROMPT_OPTIONS,
|
|
3695
|
+
autoValue: context.jobQueue
|
|
3696
|
+
} : {
|
|
3697
|
+
shouldPrompt: true,
|
|
3698
|
+
mode: "single",
|
|
3699
|
+
options: JOB_QUEUE_PROMPT_OPTIONS,
|
|
3700
|
+
initialValue: "none"
|
|
3701
|
+
};
|
|
3702
|
+
}
|
|
2839
3703
|
async function getJobQueueChoice(jobQueue, backend) {
|
|
2840
|
-
|
|
2841
|
-
|
|
3704
|
+
const resolution = resolveJobQueuePrompt({
|
|
3705
|
+
jobQueue,
|
|
3706
|
+
backend
|
|
3707
|
+
});
|
|
3708
|
+
if (!resolution.shouldPrompt) return resolution.autoValue ?? "none";
|
|
2842
3709
|
const response = await navigableSelect({
|
|
2843
3710
|
message: "Select job queue solution",
|
|
2844
|
-
options:
|
|
2845
|
-
|
|
2846
|
-
value: "bullmq",
|
|
2847
|
-
label: "BullMQ",
|
|
2848
|
-
hint: "Redis-backed job queue for background tasks and scheduling"
|
|
2849
|
-
},
|
|
2850
|
-
{
|
|
2851
|
-
value: "trigger-dev",
|
|
2852
|
-
label: "Trigger.dev",
|
|
2853
|
-
hint: "Background jobs as code with serverless execution"
|
|
2854
|
-
},
|
|
2855
|
-
{
|
|
2856
|
-
value: "inngest",
|
|
2857
|
-
label: "Inngest",
|
|
2858
|
-
hint: "Event-driven functions with built-in queuing and scheduling"
|
|
2859
|
-
},
|
|
2860
|
-
{
|
|
2861
|
-
value: "temporal",
|
|
2862
|
-
label: "Temporal",
|
|
2863
|
-
hint: "Durable workflow orchestration for reliable distributed systems"
|
|
2864
|
-
},
|
|
2865
|
-
{
|
|
2866
|
-
value: "none",
|
|
2867
|
-
label: "None",
|
|
2868
|
-
hint: "Skip job queue/background worker setup"
|
|
2869
|
-
}
|
|
2870
|
-
],
|
|
2871
|
-
initialValue: "none"
|
|
3711
|
+
options: resolution.options,
|
|
3712
|
+
initialValue: resolution.initialValue
|
|
2872
3713
|
});
|
|
2873
3714
|
if (isCancel$1(response)) return exitCancelled("Operation cancelled");
|
|
2874
3715
|
return response;
|
|
@@ -2876,29 +3717,52 @@ async function getJobQueueChoice(jobQueue, backend) {
|
|
|
2876
3717
|
|
|
2877
3718
|
//#endregion
|
|
2878
3719
|
//#region src/prompts/logging.ts
|
|
3720
|
+
const LOGGING_PROMPT_OPTIONS = [
|
|
3721
|
+
{
|
|
3722
|
+
value: "pino",
|
|
3723
|
+
label: "Pino",
|
|
3724
|
+
hint: "Fast JSON logger with minimal overhead"
|
|
3725
|
+
},
|
|
3726
|
+
{
|
|
3727
|
+
value: "winston",
|
|
3728
|
+
label: "Winston",
|
|
3729
|
+
hint: "Flexible logging library with multiple transports"
|
|
3730
|
+
},
|
|
3731
|
+
{
|
|
3732
|
+
value: "none",
|
|
3733
|
+
label: "None",
|
|
3734
|
+
hint: "Skip logging framework setup"
|
|
3735
|
+
}
|
|
3736
|
+
];
|
|
3737
|
+
function resolveLoggingPrompt(context = {}) {
|
|
3738
|
+
if (context.backend === "none" || context.backend === "convex") return {
|
|
3739
|
+
shouldPrompt: false,
|
|
3740
|
+
mode: "single",
|
|
3741
|
+
options: [],
|
|
3742
|
+
autoValue: "none"
|
|
3743
|
+
};
|
|
3744
|
+
return context.logging !== void 0 ? {
|
|
3745
|
+
shouldPrompt: false,
|
|
3746
|
+
mode: "single",
|
|
3747
|
+
options: LOGGING_PROMPT_OPTIONS,
|
|
3748
|
+
autoValue: context.logging
|
|
3749
|
+
} : {
|
|
3750
|
+
shouldPrompt: true,
|
|
3751
|
+
mode: "single",
|
|
3752
|
+
options: LOGGING_PROMPT_OPTIONS,
|
|
3753
|
+
initialValue: "none"
|
|
3754
|
+
};
|
|
3755
|
+
}
|
|
2879
3756
|
async function getLoggingChoice(logging, backend) {
|
|
2880
|
-
|
|
2881
|
-
|
|
3757
|
+
const resolution = resolveLoggingPrompt({
|
|
3758
|
+
logging,
|
|
3759
|
+
backend
|
|
3760
|
+
});
|
|
3761
|
+
if (!resolution.shouldPrompt) return resolution.autoValue ?? "none";
|
|
2882
3762
|
const response = await navigableSelect({
|
|
2883
3763
|
message: "Select logging framework",
|
|
2884
|
-
options:
|
|
2885
|
-
|
|
2886
|
-
value: "pino",
|
|
2887
|
-
label: "Pino",
|
|
2888
|
-
hint: "Fast JSON logger with minimal overhead"
|
|
2889
|
-
},
|
|
2890
|
-
{
|
|
2891
|
-
value: "winston",
|
|
2892
|
-
label: "Winston",
|
|
2893
|
-
hint: "Flexible logging library with multiple transports"
|
|
2894
|
-
},
|
|
2895
|
-
{
|
|
2896
|
-
value: "none",
|
|
2897
|
-
label: "None",
|
|
2898
|
-
hint: "Skip logging framework setup"
|
|
2899
|
-
}
|
|
2900
|
-
],
|
|
2901
|
-
initialValue: "none"
|
|
3764
|
+
options: resolution.options,
|
|
3765
|
+
initialValue: resolution.initialValue
|
|
2902
3766
|
});
|
|
2903
3767
|
if (isCancel$1(response)) return exitCancelled("Operation cancelled");
|
|
2904
3768
|
return response;
|
|
@@ -2963,34 +3827,57 @@ async function navigableGroup(prompts, opts) {
|
|
|
2963
3827
|
|
|
2964
3828
|
//#endregion
|
|
2965
3829
|
//#region src/prompts/observability.ts
|
|
3830
|
+
const OBSERVABILITY_PROMPT_OPTIONS = [
|
|
3831
|
+
{
|
|
3832
|
+
value: "opentelemetry",
|
|
3833
|
+
label: "OpenTelemetry",
|
|
3834
|
+
hint: "Observability framework for traces, metrics, and logs"
|
|
3835
|
+
},
|
|
3836
|
+
{
|
|
3837
|
+
value: "sentry",
|
|
3838
|
+
label: "Sentry",
|
|
3839
|
+
hint: "Error tracking and performance monitoring"
|
|
3840
|
+
},
|
|
3841
|
+
{
|
|
3842
|
+
value: "grafana",
|
|
3843
|
+
label: "Grafana",
|
|
3844
|
+
hint: "Prometheus metrics for Grafana dashboards and alerting"
|
|
3845
|
+
},
|
|
3846
|
+
{
|
|
3847
|
+
value: "none",
|
|
3848
|
+
label: "None",
|
|
3849
|
+
hint: "Skip observability/tracing setup"
|
|
3850
|
+
}
|
|
3851
|
+
];
|
|
3852
|
+
function resolveObservabilityPrompt(context = {}) {
|
|
3853
|
+
if (context.backend === "none" || context.backend === "convex") return {
|
|
3854
|
+
shouldPrompt: false,
|
|
3855
|
+
mode: "single",
|
|
3856
|
+
options: [],
|
|
3857
|
+
autoValue: "none"
|
|
3858
|
+
};
|
|
3859
|
+
return context.observability !== void 0 ? {
|
|
3860
|
+
shouldPrompt: false,
|
|
3861
|
+
mode: "single",
|
|
3862
|
+
options: OBSERVABILITY_PROMPT_OPTIONS,
|
|
3863
|
+
autoValue: context.observability
|
|
3864
|
+
} : {
|
|
3865
|
+
shouldPrompt: true,
|
|
3866
|
+
mode: "single",
|
|
3867
|
+
options: OBSERVABILITY_PROMPT_OPTIONS,
|
|
3868
|
+
initialValue: "none"
|
|
3869
|
+
};
|
|
3870
|
+
}
|
|
2966
3871
|
async function getObservabilityChoice(observability, backend) {
|
|
2967
|
-
|
|
2968
|
-
|
|
3872
|
+
const resolution = resolveObservabilityPrompt({
|
|
3873
|
+
observability,
|
|
3874
|
+
backend
|
|
3875
|
+
});
|
|
3876
|
+
if (!resolution.shouldPrompt) return resolution.autoValue ?? "none";
|
|
2969
3877
|
const response = await navigableSelect({
|
|
2970
3878
|
message: "Select observability solution",
|
|
2971
|
-
options:
|
|
2972
|
-
|
|
2973
|
-
value: "opentelemetry",
|
|
2974
|
-
label: "OpenTelemetry",
|
|
2975
|
-
hint: "Observability framework for traces, metrics, and logs"
|
|
2976
|
-
},
|
|
2977
|
-
{
|
|
2978
|
-
value: "sentry",
|
|
2979
|
-
label: "Sentry",
|
|
2980
|
-
hint: "Error tracking and performance monitoring"
|
|
2981
|
-
},
|
|
2982
|
-
{
|
|
2983
|
-
value: "grafana",
|
|
2984
|
-
label: "Grafana",
|
|
2985
|
-
hint: "Prometheus metrics for Grafana dashboards and alerting"
|
|
2986
|
-
},
|
|
2987
|
-
{
|
|
2988
|
-
value: "none",
|
|
2989
|
-
label: "None",
|
|
2990
|
-
hint: "Skip observability/tracing setup"
|
|
2991
|
-
}
|
|
2992
|
-
],
|
|
2993
|
-
initialValue: "none"
|
|
3879
|
+
options: resolution.options,
|
|
3880
|
+
initialValue: resolution.initialValue
|
|
2994
3881
|
});
|
|
2995
3882
|
if (isCancel$1(response)) return exitCancelled("Operation cancelled");
|
|
2996
3883
|
return response;
|
|
@@ -3035,15 +3922,29 @@ const ormOptions = {
|
|
|
3035
3922
|
hint: "Mature ORM with wide adoption"
|
|
3036
3923
|
}
|
|
3037
3924
|
};
|
|
3038
|
-
|
|
3039
|
-
if (backend === "convex") return
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
|
|
3925
|
+
function resolveORMPrompt(context) {
|
|
3926
|
+
if (context.backend === "convex" || !context.hasDatabase) return {
|
|
3927
|
+
shouldPrompt: false,
|
|
3928
|
+
mode: "single",
|
|
3929
|
+
options: [],
|
|
3930
|
+
autoValue: "none"
|
|
3931
|
+
};
|
|
3932
|
+
if (context.database === "edgedb" || context.database === "redis") return {
|
|
3933
|
+
shouldPrompt: false,
|
|
3934
|
+
mode: "single",
|
|
3935
|
+
options: [],
|
|
3936
|
+
autoValue: "none"
|
|
3937
|
+
};
|
|
3938
|
+
if (context.orm !== void 0) return {
|
|
3939
|
+
shouldPrompt: false,
|
|
3940
|
+
mode: "single",
|
|
3941
|
+
options: [],
|
|
3942
|
+
autoValue: context.orm
|
|
3943
|
+
};
|
|
3944
|
+
return {
|
|
3945
|
+
shouldPrompt: true,
|
|
3946
|
+
mode: "single",
|
|
3947
|
+
options: context.database === "mongodb" ? [ormOptions.prisma, ormOptions.mongoose] : [
|
|
3047
3948
|
ormOptions.drizzle,
|
|
3048
3949
|
ormOptions.prisma,
|
|
3049
3950
|
ormOptions.typeorm,
|
|
@@ -3051,7 +3952,22 @@ async function getORMChoice(orm, hasDatabase, database, backend, runtime) {
|
|
|
3051
3952
|
ormOptions.mikroorm,
|
|
3052
3953
|
ormOptions.sequelize
|
|
3053
3954
|
],
|
|
3054
|
-
initialValue: database === "mongodb" ? "prisma" : runtime === "workers" ? "drizzle" : DEFAULT_CONFIG.orm
|
|
3955
|
+
initialValue: context.database === "mongodb" ? "prisma" : context.runtime === "workers" ? "drizzle" : DEFAULT_CONFIG.orm
|
|
3956
|
+
};
|
|
3957
|
+
}
|
|
3958
|
+
async function getORMChoice(orm, hasDatabase, database, backend, runtime) {
|
|
3959
|
+
const resolution = resolveORMPrompt({
|
|
3960
|
+
orm,
|
|
3961
|
+
hasDatabase,
|
|
3962
|
+
database,
|
|
3963
|
+
backend,
|
|
3964
|
+
runtime
|
|
3965
|
+
});
|
|
3966
|
+
if (!resolution.shouldPrompt) return resolution.autoValue ?? "none";
|
|
3967
|
+
const response = await navigableSelect({
|
|
3968
|
+
message: "Select ORM",
|
|
3969
|
+
options: resolution.options,
|
|
3970
|
+
initialValue: resolution.initialValue
|
|
3055
3971
|
});
|
|
3056
3972
|
if (isCancel$1(response)) return exitCancelled("Operation cancelled");
|
|
3057
3973
|
return response;
|
|
@@ -3093,10 +4009,20 @@ async function getPackageManagerChoice(packageManager) {
|
|
|
3093
4009
|
|
|
3094
4010
|
//#endregion
|
|
3095
4011
|
//#region src/prompts/payments.ts
|
|
3096
|
-
|
|
3097
|
-
if (payments !== void 0) return
|
|
3098
|
-
|
|
3099
|
-
|
|
4012
|
+
function resolvePaymentsPrompt(context = {}) {
|
|
4013
|
+
if (context.payments !== void 0) return {
|
|
4014
|
+
shouldPrompt: false,
|
|
4015
|
+
mode: "single",
|
|
4016
|
+
options: [],
|
|
4017
|
+
autoValue: context.payments
|
|
4018
|
+
};
|
|
4019
|
+
if (context.backend === "none") return {
|
|
4020
|
+
shouldPrompt: false,
|
|
4021
|
+
mode: "single",
|
|
4022
|
+
options: [],
|
|
4023
|
+
autoValue: "none"
|
|
4024
|
+
};
|
|
4025
|
+
const isPolarCompatible = context.auth === "better-auth" && (context.frontends?.length === 0 || splitFrontends$1(context.frontends).web.length > 0);
|
|
3100
4026
|
const options = [];
|
|
3101
4027
|
if (isPolarCompatible) options.push({
|
|
3102
4028
|
value: "polar",
|
|
@@ -3124,10 +4050,25 @@ async function getPaymentsChoice(payments, auth, backend, frontends) {
|
|
|
3124
4050
|
label: "None",
|
|
3125
4051
|
hint: "No payments integration"
|
|
3126
4052
|
});
|
|
3127
|
-
|
|
3128
|
-
|
|
4053
|
+
return {
|
|
4054
|
+
shouldPrompt: true,
|
|
4055
|
+
mode: "single",
|
|
3129
4056
|
options,
|
|
3130
4057
|
initialValue: DEFAULT_CONFIG.payments
|
|
4058
|
+
};
|
|
4059
|
+
}
|
|
4060
|
+
async function getPaymentsChoice(payments, auth, backend, frontends) {
|
|
4061
|
+
const resolution = resolvePaymentsPrompt({
|
|
4062
|
+
payments,
|
|
4063
|
+
auth,
|
|
4064
|
+
backend,
|
|
4065
|
+
frontends
|
|
4066
|
+
});
|
|
4067
|
+
if (!resolution.shouldPrompt) return resolution.autoValue ?? "none";
|
|
4068
|
+
const response = await navigableSelect({
|
|
4069
|
+
message: "Select payments provider",
|
|
4070
|
+
options: resolution.options,
|
|
4071
|
+
initialValue: resolution.initialValue
|
|
3131
4072
|
});
|
|
3132
4073
|
if (isCancel$1(response)) return exitCancelled("Operation cancelled");
|
|
3133
4074
|
return response;
|
|
@@ -3135,210 +4076,255 @@ async function getPaymentsChoice(payments, auth, backend, frontends) {
|
|
|
3135
4076
|
|
|
3136
4077
|
//#endregion
|
|
3137
4078
|
//#region src/prompts/python-ecosystem.ts
|
|
4079
|
+
const PYTHON_WEB_FRAMEWORK_PROMPT_OPTIONS = [
|
|
4080
|
+
{
|
|
4081
|
+
value: "fastapi",
|
|
4082
|
+
label: "FastAPI",
|
|
4083
|
+
hint: "Modern, fast (high-performance) web framework for building APIs"
|
|
4084
|
+
},
|
|
4085
|
+
{
|
|
4086
|
+
value: "django",
|
|
4087
|
+
label: "Django",
|
|
4088
|
+
hint: "High-level Python web framework with batteries included"
|
|
4089
|
+
},
|
|
4090
|
+
{
|
|
4091
|
+
value: "flask",
|
|
4092
|
+
label: "Flask",
|
|
4093
|
+
hint: "Lightweight WSGI web framework with minimal boilerplate"
|
|
4094
|
+
},
|
|
4095
|
+
{
|
|
4096
|
+
value: "litestar",
|
|
4097
|
+
label: "Litestar",
|
|
4098
|
+
hint: "High-performance ASGI framework with class-based controllers"
|
|
4099
|
+
},
|
|
4100
|
+
{
|
|
4101
|
+
value: "none",
|
|
4102
|
+
label: "None",
|
|
4103
|
+
hint: "No web framework"
|
|
4104
|
+
}
|
|
4105
|
+
];
|
|
4106
|
+
const PYTHON_ORM_PROMPT_OPTIONS = [
|
|
4107
|
+
{
|
|
4108
|
+
value: "sqlalchemy",
|
|
4109
|
+
label: "SQLAlchemy",
|
|
4110
|
+
hint: "The SQL toolkit and ORM for Python"
|
|
4111
|
+
},
|
|
4112
|
+
{
|
|
4113
|
+
value: "sqlmodel",
|
|
4114
|
+
label: "SQLModel",
|
|
4115
|
+
hint: "SQL databases in Python with Pydantic and SQLAlchemy"
|
|
4116
|
+
},
|
|
4117
|
+
{
|
|
4118
|
+
value: "tortoise-orm",
|
|
4119
|
+
label: "Tortoise ORM",
|
|
4120
|
+
hint: "Async-first ORM with Django-like API"
|
|
4121
|
+
},
|
|
4122
|
+
{
|
|
4123
|
+
value: "none",
|
|
4124
|
+
label: "None",
|
|
4125
|
+
hint: "No ORM/database layer"
|
|
4126
|
+
}
|
|
4127
|
+
];
|
|
4128
|
+
const PYTHON_VALIDATION_PROMPT_OPTIONS = [{
|
|
4129
|
+
value: "pydantic",
|
|
4130
|
+
label: "Pydantic",
|
|
4131
|
+
hint: "Data validation using Python type hints"
|
|
4132
|
+
}, {
|
|
4133
|
+
value: "none",
|
|
4134
|
+
label: "None",
|
|
4135
|
+
hint: "No validation library"
|
|
4136
|
+
}];
|
|
4137
|
+
const PYTHON_AI_PROMPT_OPTIONS = [
|
|
4138
|
+
{
|
|
4139
|
+
value: "none",
|
|
4140
|
+
label: "None",
|
|
4141
|
+
hint: "No AI/ML framework"
|
|
4142
|
+
},
|
|
4143
|
+
{
|
|
4144
|
+
value: "langchain",
|
|
4145
|
+
label: "LangChain",
|
|
4146
|
+
hint: "Building applications with LLMs through composability"
|
|
4147
|
+
},
|
|
4148
|
+
{
|
|
4149
|
+
value: "llamaindex",
|
|
4150
|
+
label: "LlamaIndex",
|
|
4151
|
+
hint: "Data framework for LLM applications"
|
|
4152
|
+
},
|
|
4153
|
+
{
|
|
4154
|
+
value: "openai-sdk",
|
|
4155
|
+
label: "OpenAI SDK",
|
|
4156
|
+
hint: "Official OpenAI Python client"
|
|
4157
|
+
},
|
|
4158
|
+
{
|
|
4159
|
+
value: "anthropic-sdk",
|
|
4160
|
+
label: "Anthropic SDK",
|
|
4161
|
+
hint: "Official Anthropic Claude API client"
|
|
4162
|
+
},
|
|
4163
|
+
{
|
|
4164
|
+
value: "langgraph",
|
|
4165
|
+
label: "LangGraph",
|
|
4166
|
+
hint: "Graph-based agent orchestration"
|
|
4167
|
+
},
|
|
4168
|
+
{
|
|
4169
|
+
value: "crewai",
|
|
4170
|
+
label: "CrewAI",
|
|
4171
|
+
hint: "Multi-agent orchestration framework"
|
|
4172
|
+
}
|
|
4173
|
+
];
|
|
4174
|
+
const PYTHON_AUTH_PROMPT_OPTIONS = [
|
|
4175
|
+
{
|
|
4176
|
+
value: "authlib",
|
|
4177
|
+
label: "Authlib",
|
|
4178
|
+
hint: "Comprehensive auth library — OAuth1/2, OIDC, JWS, JWK, JWT"
|
|
4179
|
+
},
|
|
4180
|
+
{
|
|
4181
|
+
value: "jwt",
|
|
4182
|
+
label: "JWT (python-jose)",
|
|
4183
|
+
hint: "Simple JWT token creation and verification"
|
|
4184
|
+
},
|
|
4185
|
+
{
|
|
4186
|
+
value: "none",
|
|
4187
|
+
label: "None",
|
|
4188
|
+
hint: "No authentication library"
|
|
4189
|
+
}
|
|
4190
|
+
];
|
|
4191
|
+
const PYTHON_TASK_QUEUE_PROMPT_OPTIONS = [{
|
|
4192
|
+
value: "celery",
|
|
4193
|
+
label: "Celery",
|
|
4194
|
+
hint: "Distributed task queue for Python"
|
|
4195
|
+
}, {
|
|
4196
|
+
value: "none",
|
|
4197
|
+
label: "None",
|
|
4198
|
+
hint: "No task queue"
|
|
4199
|
+
}];
|
|
4200
|
+
const PYTHON_GRAPHQL_PROMPT_OPTIONS = [{
|
|
4201
|
+
value: "strawberry",
|
|
4202
|
+
label: "Strawberry",
|
|
4203
|
+
hint: "Python GraphQL library using dataclasses and type hints"
|
|
4204
|
+
}, {
|
|
4205
|
+
value: "none",
|
|
4206
|
+
label: "None",
|
|
4207
|
+
hint: "No GraphQL framework"
|
|
4208
|
+
}];
|
|
4209
|
+
const PYTHON_QUALITY_PROMPT_OPTIONS = [{
|
|
4210
|
+
value: "ruff",
|
|
4211
|
+
label: "Ruff",
|
|
4212
|
+
hint: "An extremely fast Python linter and formatter"
|
|
4213
|
+
}, {
|
|
4214
|
+
value: "none",
|
|
4215
|
+
label: "None",
|
|
4216
|
+
hint: "No code quality tools"
|
|
4217
|
+
}];
|
|
4218
|
+
function resolvePythonWebFrameworkPrompt(pythonWebFramework) {
|
|
4219
|
+
return createStaticSinglePromptResolution(PYTHON_WEB_FRAMEWORK_PROMPT_OPTIONS, "fastapi", pythonWebFramework);
|
|
4220
|
+
}
|
|
3138
4221
|
async function getPythonWebFrameworkChoice(pythonWebFramework) {
|
|
3139
|
-
|
|
4222
|
+
const resolution = resolvePythonWebFrameworkPrompt(pythonWebFramework);
|
|
4223
|
+
if (!resolution.shouldPrompt) return resolution.autoValue ?? "none";
|
|
3140
4224
|
const response = await navigableSelect({
|
|
3141
4225
|
message: "Select Python web framework",
|
|
3142
|
-
options:
|
|
3143
|
-
|
|
3144
|
-
value: "fastapi",
|
|
3145
|
-
label: "FastAPI",
|
|
3146
|
-
hint: "Modern, fast (high-performance) web framework for building APIs"
|
|
3147
|
-
},
|
|
3148
|
-
{
|
|
3149
|
-
value: "django",
|
|
3150
|
-
label: "Django",
|
|
3151
|
-
hint: "High-level Python web framework with batteries included"
|
|
3152
|
-
},
|
|
3153
|
-
{
|
|
3154
|
-
value: "flask",
|
|
3155
|
-
label: "Flask",
|
|
3156
|
-
hint: "Lightweight WSGI web framework with minimal boilerplate"
|
|
3157
|
-
},
|
|
3158
|
-
{
|
|
3159
|
-
value: "litestar",
|
|
3160
|
-
label: "Litestar",
|
|
3161
|
-
hint: "High-performance ASGI framework with class-based controllers"
|
|
3162
|
-
},
|
|
3163
|
-
{
|
|
3164
|
-
value: "none",
|
|
3165
|
-
label: "None",
|
|
3166
|
-
hint: "No web framework"
|
|
3167
|
-
}
|
|
3168
|
-
],
|
|
3169
|
-
initialValue: "fastapi"
|
|
4226
|
+
options: resolution.options,
|
|
4227
|
+
initialValue: resolution.initialValue
|
|
3170
4228
|
});
|
|
3171
4229
|
if (isCancel$1(response)) return exitCancelled("Operation cancelled");
|
|
3172
4230
|
return response;
|
|
3173
4231
|
}
|
|
4232
|
+
function resolvePythonOrmPrompt(pythonOrm) {
|
|
4233
|
+
return createStaticSinglePromptResolution(PYTHON_ORM_PROMPT_OPTIONS, "sqlalchemy", pythonOrm);
|
|
4234
|
+
}
|
|
3174
4235
|
async function getPythonOrmChoice(pythonOrm) {
|
|
3175
|
-
|
|
4236
|
+
const resolution = resolvePythonOrmPrompt(pythonOrm);
|
|
4237
|
+
if (!resolution.shouldPrompt) return resolution.autoValue ?? "none";
|
|
3176
4238
|
const response = await navigableSelect({
|
|
3177
4239
|
message: "Select Python ORM/database layer",
|
|
3178
|
-
options:
|
|
3179
|
-
|
|
3180
|
-
value: "sqlalchemy",
|
|
3181
|
-
label: "SQLAlchemy",
|
|
3182
|
-
hint: "The SQL toolkit and ORM for Python"
|
|
3183
|
-
},
|
|
3184
|
-
{
|
|
3185
|
-
value: "sqlmodel",
|
|
3186
|
-
label: "SQLModel",
|
|
3187
|
-
hint: "SQL databases in Python with Pydantic and SQLAlchemy"
|
|
3188
|
-
},
|
|
3189
|
-
{
|
|
3190
|
-
value: "none",
|
|
3191
|
-
label: "None",
|
|
3192
|
-
hint: "No ORM/database layer"
|
|
3193
|
-
}
|
|
3194
|
-
],
|
|
3195
|
-
initialValue: "sqlalchemy"
|
|
4240
|
+
options: resolution.options,
|
|
4241
|
+
initialValue: resolution.initialValue
|
|
3196
4242
|
});
|
|
3197
4243
|
if (isCancel$1(response)) return exitCancelled("Operation cancelled");
|
|
3198
4244
|
return response;
|
|
3199
4245
|
}
|
|
4246
|
+
function resolvePythonValidationPrompt(pythonValidation) {
|
|
4247
|
+
return createStaticSinglePromptResolution(PYTHON_VALIDATION_PROMPT_OPTIONS, "pydantic", pythonValidation);
|
|
4248
|
+
}
|
|
3200
4249
|
async function getPythonValidationChoice(pythonValidation) {
|
|
3201
|
-
|
|
4250
|
+
const resolution = resolvePythonValidationPrompt(pythonValidation);
|
|
4251
|
+
if (!resolution.shouldPrompt) return resolution.autoValue ?? "none";
|
|
3202
4252
|
const response = await navigableSelect({
|
|
3203
4253
|
message: "Select Python validation library",
|
|
3204
|
-
options:
|
|
3205
|
-
|
|
3206
|
-
label: "Pydantic",
|
|
3207
|
-
hint: "Data validation using Python type hints"
|
|
3208
|
-
}, {
|
|
3209
|
-
value: "none",
|
|
3210
|
-
label: "None",
|
|
3211
|
-
hint: "No validation library"
|
|
3212
|
-
}],
|
|
3213
|
-
initialValue: "pydantic"
|
|
4254
|
+
options: resolution.options,
|
|
4255
|
+
initialValue: resolution.initialValue
|
|
3214
4256
|
});
|
|
3215
4257
|
if (isCancel$1(response)) return exitCancelled("Operation cancelled");
|
|
3216
4258
|
return response;
|
|
3217
4259
|
}
|
|
4260
|
+
function resolvePythonAiPrompt(pythonAi) {
|
|
4261
|
+
return createStaticMultiPromptResolution(PYTHON_AI_PROMPT_OPTIONS, [], pythonAi);
|
|
4262
|
+
}
|
|
3218
4263
|
async function getPythonAiChoice(pythonAi) {
|
|
3219
|
-
|
|
4264
|
+
const resolution = resolvePythonAiPrompt(pythonAi);
|
|
4265
|
+
if (!resolution.shouldPrompt) return resolution.autoValue ?? [];
|
|
3220
4266
|
const response = await navigableMultiselect({
|
|
3221
4267
|
message: "Select Python AI/ML frameworks",
|
|
3222
|
-
options:
|
|
3223
|
-
{
|
|
3224
|
-
value: "none",
|
|
3225
|
-
label: "None",
|
|
3226
|
-
hint: "No AI/ML framework"
|
|
3227
|
-
},
|
|
3228
|
-
{
|
|
3229
|
-
value: "langchain",
|
|
3230
|
-
label: "LangChain",
|
|
3231
|
-
hint: "Building applications with LLMs through composability"
|
|
3232
|
-
},
|
|
3233
|
-
{
|
|
3234
|
-
value: "llamaindex",
|
|
3235
|
-
label: "LlamaIndex",
|
|
3236
|
-
hint: "Data framework for LLM applications"
|
|
3237
|
-
},
|
|
3238
|
-
{
|
|
3239
|
-
value: "openai-sdk",
|
|
3240
|
-
label: "OpenAI SDK",
|
|
3241
|
-
hint: "Official OpenAI Python client"
|
|
3242
|
-
},
|
|
3243
|
-
{
|
|
3244
|
-
value: "anthropic-sdk",
|
|
3245
|
-
label: "Anthropic SDK",
|
|
3246
|
-
hint: "Official Anthropic Claude API client"
|
|
3247
|
-
},
|
|
3248
|
-
{
|
|
3249
|
-
value: "langgraph",
|
|
3250
|
-
label: "LangGraph",
|
|
3251
|
-
hint: "Graph-based agent orchestration"
|
|
3252
|
-
},
|
|
3253
|
-
{
|
|
3254
|
-
value: "crewai",
|
|
3255
|
-
label: "CrewAI",
|
|
3256
|
-
hint: "Multi-agent orchestration framework"
|
|
3257
|
-
}
|
|
3258
|
-
],
|
|
4268
|
+
options: resolution.options,
|
|
3259
4269
|
required: false,
|
|
3260
|
-
initialValues:
|
|
4270
|
+
initialValues: resolution.initialValue
|
|
3261
4271
|
});
|
|
3262
4272
|
if (isCancel$1(response)) return exitCancelled("Operation cancelled");
|
|
3263
4273
|
if (response.includes("none")) return [];
|
|
3264
4274
|
return response;
|
|
3265
4275
|
}
|
|
4276
|
+
function resolvePythonAuthPrompt(pythonAuth) {
|
|
4277
|
+
return createStaticSinglePromptResolution(PYTHON_AUTH_PROMPT_OPTIONS, "none", pythonAuth);
|
|
4278
|
+
}
|
|
3266
4279
|
async function getPythonAuthChoice(pythonAuth) {
|
|
3267
|
-
|
|
4280
|
+
const resolution = resolvePythonAuthPrompt(pythonAuth);
|
|
4281
|
+
if (!resolution.shouldPrompt) return resolution.autoValue ?? "none";
|
|
3268
4282
|
const response = await navigableSelect({
|
|
3269
4283
|
message: "Select Python authentication library",
|
|
3270
|
-
options:
|
|
3271
|
-
|
|
3272
|
-
value: "authlib",
|
|
3273
|
-
label: "Authlib",
|
|
3274
|
-
hint: "Comprehensive auth library — OAuth1/2, OIDC, JWS, JWK, JWT"
|
|
3275
|
-
},
|
|
3276
|
-
{
|
|
3277
|
-
value: "jwt",
|
|
3278
|
-
label: "JWT (python-jose)",
|
|
3279
|
-
hint: "Simple JWT token creation and verification"
|
|
3280
|
-
},
|
|
3281
|
-
{
|
|
3282
|
-
value: "none",
|
|
3283
|
-
label: "None",
|
|
3284
|
-
hint: "No authentication library"
|
|
3285
|
-
}
|
|
3286
|
-
],
|
|
3287
|
-
initialValue: "none"
|
|
4284
|
+
options: resolution.options,
|
|
4285
|
+
initialValue: resolution.initialValue
|
|
3288
4286
|
});
|
|
3289
4287
|
if (isCancel$1(response)) return exitCancelled("Operation cancelled");
|
|
3290
4288
|
return response;
|
|
3291
4289
|
}
|
|
4290
|
+
function resolvePythonTaskQueuePrompt(pythonTaskQueue) {
|
|
4291
|
+
return createStaticSinglePromptResolution(PYTHON_TASK_QUEUE_PROMPT_OPTIONS, "none", pythonTaskQueue);
|
|
4292
|
+
}
|
|
3292
4293
|
async function getPythonTaskQueueChoice(pythonTaskQueue) {
|
|
3293
|
-
|
|
4294
|
+
const resolution = resolvePythonTaskQueuePrompt(pythonTaskQueue);
|
|
4295
|
+
if (!resolution.shouldPrompt) return resolution.autoValue ?? "none";
|
|
3294
4296
|
const response = await navigableSelect({
|
|
3295
4297
|
message: "Select Python task queue",
|
|
3296
|
-
options:
|
|
3297
|
-
|
|
3298
|
-
label: "Celery",
|
|
3299
|
-
hint: "Distributed task queue for Python"
|
|
3300
|
-
}, {
|
|
3301
|
-
value: "none",
|
|
3302
|
-
label: "None",
|
|
3303
|
-
hint: "No task queue"
|
|
3304
|
-
}],
|
|
3305
|
-
initialValue: "none"
|
|
4298
|
+
options: resolution.options,
|
|
4299
|
+
initialValue: resolution.initialValue
|
|
3306
4300
|
});
|
|
3307
4301
|
if (isCancel$1(response)) return exitCancelled("Operation cancelled");
|
|
3308
4302
|
return response;
|
|
3309
4303
|
}
|
|
4304
|
+
function resolvePythonGraphqlPrompt(pythonGraphql) {
|
|
4305
|
+
return createStaticSinglePromptResolution(PYTHON_GRAPHQL_PROMPT_OPTIONS, "none", pythonGraphql);
|
|
4306
|
+
}
|
|
3310
4307
|
async function getPythonGraphqlChoice(pythonGraphql) {
|
|
3311
|
-
|
|
4308
|
+
const resolution = resolvePythonGraphqlPrompt(pythonGraphql);
|
|
4309
|
+
if (!resolution.shouldPrompt) return resolution.autoValue ?? "none";
|
|
3312
4310
|
const response = await navigableSelect({
|
|
3313
4311
|
message: "Select Python GraphQL framework",
|
|
3314
|
-
options:
|
|
3315
|
-
|
|
3316
|
-
label: "Strawberry",
|
|
3317
|
-
hint: "Python GraphQL library using dataclasses and type hints"
|
|
3318
|
-
}, {
|
|
3319
|
-
value: "none",
|
|
3320
|
-
label: "None",
|
|
3321
|
-
hint: "No GraphQL framework"
|
|
3322
|
-
}],
|
|
3323
|
-
initialValue: "none"
|
|
4312
|
+
options: resolution.options,
|
|
4313
|
+
initialValue: resolution.initialValue
|
|
3324
4314
|
});
|
|
3325
4315
|
if (isCancel$1(response)) return exitCancelled("Operation cancelled");
|
|
3326
4316
|
return response;
|
|
3327
4317
|
}
|
|
4318
|
+
function resolvePythonQualityPrompt(pythonQuality) {
|
|
4319
|
+
return createStaticSinglePromptResolution(PYTHON_QUALITY_PROMPT_OPTIONS, "ruff", pythonQuality);
|
|
4320
|
+
}
|
|
3328
4321
|
async function getPythonQualityChoice(pythonQuality) {
|
|
3329
|
-
|
|
4322
|
+
const resolution = resolvePythonQualityPrompt(pythonQuality);
|
|
4323
|
+
if (!resolution.shouldPrompt) return resolution.autoValue ?? "none";
|
|
3330
4324
|
const response = await navigableSelect({
|
|
3331
4325
|
message: "Select Python code quality tool",
|
|
3332
|
-
options:
|
|
3333
|
-
|
|
3334
|
-
label: "Ruff",
|
|
3335
|
-
hint: "An extremely fast Python linter and formatter"
|
|
3336
|
-
}, {
|
|
3337
|
-
value: "none",
|
|
3338
|
-
label: "None",
|
|
3339
|
-
hint: "No code quality tools"
|
|
3340
|
-
}],
|
|
3341
|
-
initialValue: "ruff"
|
|
4326
|
+
options: resolution.options,
|
|
4327
|
+
initialValue: resolution.initialValue
|
|
3342
4328
|
});
|
|
3343
4329
|
if (isCancel$1(response)) return exitCancelled("Operation cancelled");
|
|
3344
4330
|
return response;
|
|
@@ -3346,49 +4332,72 @@ async function getPythonQualityChoice(pythonQuality) {
|
|
|
3346
4332
|
|
|
3347
4333
|
//#endregion
|
|
3348
4334
|
//#region src/prompts/realtime.ts
|
|
4335
|
+
const REALTIME_PROMPT_OPTIONS = [
|
|
4336
|
+
{
|
|
4337
|
+
value: "socket-io",
|
|
4338
|
+
label: "Socket.IO",
|
|
4339
|
+
hint: "Real-time bidirectional communication with fallbacks"
|
|
4340
|
+
},
|
|
4341
|
+
{
|
|
4342
|
+
value: "partykit",
|
|
4343
|
+
label: "PartyKit",
|
|
4344
|
+
hint: "Edge-native multiplayer infrastructure on Cloudflare"
|
|
4345
|
+
},
|
|
4346
|
+
{
|
|
4347
|
+
value: "ably",
|
|
4348
|
+
label: "Ably",
|
|
4349
|
+
hint: "Real-time messaging platform with pub/sub and presence"
|
|
4350
|
+
},
|
|
4351
|
+
{
|
|
4352
|
+
value: "pusher",
|
|
4353
|
+
label: "Pusher",
|
|
4354
|
+
hint: "Real-time communication APIs with channels and events"
|
|
4355
|
+
},
|
|
4356
|
+
{
|
|
4357
|
+
value: "liveblocks",
|
|
4358
|
+
label: "Liveblocks",
|
|
4359
|
+
hint: "Collaboration infrastructure for multiplayer experiences"
|
|
4360
|
+
},
|
|
4361
|
+
{
|
|
4362
|
+
value: "yjs",
|
|
4363
|
+
label: "Y.js",
|
|
4364
|
+
hint: "CRDT library for real-time collaboration with conflict-free sync"
|
|
4365
|
+
},
|
|
4366
|
+
{
|
|
4367
|
+
value: "none",
|
|
4368
|
+
label: "None",
|
|
4369
|
+
hint: "Skip real-time/WebSocket integration"
|
|
4370
|
+
}
|
|
4371
|
+
];
|
|
4372
|
+
function resolveRealtimePrompt(context = {}) {
|
|
4373
|
+
if (context.backend === "none" || context.backend === "convex") return {
|
|
4374
|
+
shouldPrompt: false,
|
|
4375
|
+
mode: "single",
|
|
4376
|
+
options: [],
|
|
4377
|
+
autoValue: "none"
|
|
4378
|
+
};
|
|
4379
|
+
return context.realtime !== void 0 ? {
|
|
4380
|
+
shouldPrompt: false,
|
|
4381
|
+
mode: "single",
|
|
4382
|
+
options: REALTIME_PROMPT_OPTIONS,
|
|
4383
|
+
autoValue: context.realtime
|
|
4384
|
+
} : {
|
|
4385
|
+
shouldPrompt: true,
|
|
4386
|
+
mode: "single",
|
|
4387
|
+
options: REALTIME_PROMPT_OPTIONS,
|
|
4388
|
+
initialValue: "none"
|
|
4389
|
+
};
|
|
4390
|
+
}
|
|
3349
4391
|
async function getRealtimeChoice(realtime, backend) {
|
|
3350
|
-
|
|
3351
|
-
|
|
4392
|
+
const resolution = resolveRealtimePrompt({
|
|
4393
|
+
realtime,
|
|
4394
|
+
backend
|
|
4395
|
+
});
|
|
4396
|
+
if (!resolution.shouldPrompt) return resolution.autoValue ?? "none";
|
|
3352
4397
|
const response = await navigableSelect({
|
|
3353
4398
|
message: "Select real-time solution",
|
|
3354
|
-
options:
|
|
3355
|
-
|
|
3356
|
-
value: "socket-io",
|
|
3357
|
-
label: "Socket.IO",
|
|
3358
|
-
hint: "Real-time bidirectional communication with fallbacks"
|
|
3359
|
-
},
|
|
3360
|
-
{
|
|
3361
|
-
value: "partykit",
|
|
3362
|
-
label: "PartyKit",
|
|
3363
|
-
hint: "Edge-native multiplayer infrastructure on Cloudflare"
|
|
3364
|
-
},
|
|
3365
|
-
{
|
|
3366
|
-
value: "ably",
|
|
3367
|
-
label: "Ably",
|
|
3368
|
-
hint: "Real-time messaging platform with pub/sub and presence"
|
|
3369
|
-
},
|
|
3370
|
-
{
|
|
3371
|
-
value: "pusher",
|
|
3372
|
-
label: "Pusher",
|
|
3373
|
-
hint: "Real-time communication APIs with channels and events"
|
|
3374
|
-
},
|
|
3375
|
-
{
|
|
3376
|
-
value: "liveblocks",
|
|
3377
|
-
label: "Liveblocks",
|
|
3378
|
-
hint: "Collaboration infrastructure for multiplayer experiences"
|
|
3379
|
-
},
|
|
3380
|
-
{
|
|
3381
|
-
value: "yjs",
|
|
3382
|
-
label: "Y.js",
|
|
3383
|
-
hint: "CRDT library for real-time collaboration with conflict-free sync"
|
|
3384
|
-
},
|
|
3385
|
-
{
|
|
3386
|
-
value: "none",
|
|
3387
|
-
label: "None",
|
|
3388
|
-
hint: "Skip real-time/WebSocket integration"
|
|
3389
|
-
}
|
|
3390
|
-
],
|
|
3391
|
-
initialValue: "none"
|
|
4399
|
+
options: resolution.options,
|
|
4400
|
+
initialValue: resolution.initialValue
|
|
3392
4401
|
});
|
|
3393
4402
|
if (isCancel$1(response)) return exitCancelled("Operation cancelled");
|
|
3394
4403
|
return response;
|
|
@@ -3396,27 +4405,53 @@ async function getRealtimeChoice(realtime, backend) {
|
|
|
3396
4405
|
|
|
3397
4406
|
//#endregion
|
|
3398
4407
|
//#region src/prompts/runtime.ts
|
|
3399
|
-
|
|
3400
|
-
|
|
3401
|
-
if (runtime !== void 0) return runtime;
|
|
3402
|
-
const runtimeOptions = [{
|
|
4408
|
+
const RUNTIME_PROMPT_OPTIONS = [
|
|
4409
|
+
{
|
|
3403
4410
|
value: "bun",
|
|
3404
4411
|
label: "Bun",
|
|
3405
4412
|
hint: "Fast all-in-one JavaScript runtime"
|
|
3406
|
-
},
|
|
4413
|
+
},
|
|
4414
|
+
{
|
|
3407
4415
|
value: "node",
|
|
3408
4416
|
label: "Node.js",
|
|
3409
4417
|
hint: "Traditional Node.js runtime"
|
|
3410
|
-
}
|
|
3411
|
-
|
|
4418
|
+
},
|
|
4419
|
+
{
|
|
3412
4420
|
value: "workers",
|
|
3413
4421
|
label: "Cloudflare Workers",
|
|
3414
4422
|
hint: "Edge runtime on Cloudflare's global network"
|
|
4423
|
+
}
|
|
4424
|
+
];
|
|
4425
|
+
function resolveRuntimePrompt(context = {}) {
|
|
4426
|
+
if (context.backend === "convex" || context.backend === "none" || context.backend === "self") return {
|
|
4427
|
+
shouldPrompt: false,
|
|
4428
|
+
mode: "single",
|
|
4429
|
+
options: [],
|
|
4430
|
+
autoValue: "none"
|
|
4431
|
+
};
|
|
4432
|
+
const options = RUNTIME_PROMPT_OPTIONS.filter((option) => option.value !== "workers" || context.backend === "hono");
|
|
4433
|
+
return context.runtime !== void 0 ? {
|
|
4434
|
+
shouldPrompt: false,
|
|
4435
|
+
mode: "single",
|
|
4436
|
+
options,
|
|
4437
|
+
autoValue: context.runtime
|
|
4438
|
+
} : {
|
|
4439
|
+
shouldPrompt: true,
|
|
4440
|
+
mode: "single",
|
|
4441
|
+
options,
|
|
4442
|
+
initialValue: DEFAULT_CONFIG.runtime
|
|
4443
|
+
};
|
|
4444
|
+
}
|
|
4445
|
+
async function getRuntimeChoice(runtime, backend) {
|
|
4446
|
+
const resolution = resolveRuntimePrompt({
|
|
4447
|
+
runtime,
|
|
4448
|
+
backend
|
|
3415
4449
|
});
|
|
4450
|
+
if (!resolution.shouldPrompt) return resolution.autoValue ?? "none";
|
|
3416
4451
|
const response = await navigableSelect({
|
|
3417
4452
|
message: "Select runtime",
|
|
3418
|
-
options:
|
|
3419
|
-
initialValue:
|
|
4453
|
+
options: resolution.options,
|
|
4454
|
+
initialValue: resolution.initialValue
|
|
3420
4455
|
});
|
|
3421
4456
|
if (isCancel$1(response)) return exitCancelled("Operation cancelled");
|
|
3422
4457
|
return response;
|
|
@@ -3424,261 +4459,324 @@ async function getRuntimeChoice(runtime, backend) {
|
|
|
3424
4459
|
|
|
3425
4460
|
//#endregion
|
|
3426
4461
|
//#region src/prompts/rust-ecosystem.ts
|
|
4462
|
+
const RUST_WEB_FRAMEWORK_PROMPT_OPTIONS = [
|
|
4463
|
+
{
|
|
4464
|
+
value: "axum",
|
|
4465
|
+
label: "Axum",
|
|
4466
|
+
hint: "Ergonomic and modular web framework from Tokio"
|
|
4467
|
+
},
|
|
4468
|
+
{
|
|
4469
|
+
value: "actix-web",
|
|
4470
|
+
label: "Actix Web",
|
|
4471
|
+
hint: "Powerful, pragmatic, and extremely fast web framework"
|
|
4472
|
+
},
|
|
4473
|
+
{
|
|
4474
|
+
value: "rocket",
|
|
4475
|
+
label: "Rocket",
|
|
4476
|
+
hint: "Convention-over-configuration web framework, 25k+ stars"
|
|
4477
|
+
},
|
|
4478
|
+
{
|
|
4479
|
+
value: "none",
|
|
4480
|
+
label: "None",
|
|
4481
|
+
hint: "No web framework"
|
|
4482
|
+
}
|
|
4483
|
+
];
|
|
4484
|
+
const RUST_FRONTEND_PROMPT_OPTIONS = [
|
|
4485
|
+
{
|
|
4486
|
+
value: "leptos",
|
|
4487
|
+
label: "Leptos",
|
|
4488
|
+
hint: "Build fast web applications with Rust"
|
|
4489
|
+
},
|
|
4490
|
+
{
|
|
4491
|
+
value: "dioxus",
|
|
4492
|
+
label: "Dioxus",
|
|
4493
|
+
hint: "Fullstack, cross-platform UI library for Rust"
|
|
4494
|
+
},
|
|
4495
|
+
{
|
|
4496
|
+
value: "none",
|
|
4497
|
+
label: "None",
|
|
4498
|
+
hint: "No Rust frontend (API only)"
|
|
4499
|
+
}
|
|
4500
|
+
];
|
|
4501
|
+
const RUST_ORM_PROMPT_OPTIONS = [
|
|
4502
|
+
{
|
|
4503
|
+
value: "sea-orm",
|
|
4504
|
+
label: "SeaORM",
|
|
4505
|
+
hint: "Async & dynamic ORM for Rust"
|
|
4506
|
+
},
|
|
4507
|
+
{
|
|
4508
|
+
value: "sqlx",
|
|
4509
|
+
label: "SQLx",
|
|
4510
|
+
hint: "Async SQL toolkit with compile-time checked queries"
|
|
4511
|
+
},
|
|
4512
|
+
{
|
|
4513
|
+
value: "diesel",
|
|
4514
|
+
label: "Diesel",
|
|
4515
|
+
hint: "Safe, extensible ORM with compile-time query validation"
|
|
4516
|
+
},
|
|
4517
|
+
{
|
|
4518
|
+
value: "none",
|
|
4519
|
+
label: "None",
|
|
4520
|
+
hint: "No database layer"
|
|
4521
|
+
}
|
|
4522
|
+
];
|
|
4523
|
+
const RUST_API_PROMPT_OPTIONS = [
|
|
4524
|
+
{
|
|
4525
|
+
value: "tonic",
|
|
4526
|
+
label: "Tonic",
|
|
4527
|
+
hint: "gRPC implementation for Rust"
|
|
4528
|
+
},
|
|
4529
|
+
{
|
|
4530
|
+
value: "async-graphql",
|
|
4531
|
+
label: "async-graphql",
|
|
4532
|
+
hint: "High-performance GraphQL server library"
|
|
4533
|
+
},
|
|
4534
|
+
{
|
|
4535
|
+
value: "none",
|
|
4536
|
+
label: "None",
|
|
4537
|
+
hint: "REST API only"
|
|
4538
|
+
}
|
|
4539
|
+
];
|
|
4540
|
+
const RUST_CLI_PROMPT_OPTIONS = [
|
|
4541
|
+
{
|
|
4542
|
+
value: "clap",
|
|
4543
|
+
label: "Clap",
|
|
4544
|
+
hint: "Command Line Argument Parser for Rust"
|
|
4545
|
+
},
|
|
4546
|
+
{
|
|
4547
|
+
value: "ratatui",
|
|
4548
|
+
label: "Ratatui",
|
|
4549
|
+
hint: "Build rich terminal user interfaces"
|
|
4550
|
+
},
|
|
4551
|
+
{
|
|
4552
|
+
value: "none",
|
|
4553
|
+
label: "None",
|
|
4554
|
+
hint: "No CLI tools"
|
|
4555
|
+
}
|
|
4556
|
+
];
|
|
4557
|
+
const RUST_LIBRARIES_PROMPT_OPTIONS = [
|
|
4558
|
+
{
|
|
4559
|
+
value: "serde",
|
|
4560
|
+
label: "Serde",
|
|
4561
|
+
hint: "Serialization framework for Rust"
|
|
4562
|
+
},
|
|
4563
|
+
{
|
|
4564
|
+
value: "validator",
|
|
4565
|
+
label: "Validator",
|
|
4566
|
+
hint: "Struct validation derive macros"
|
|
4567
|
+
},
|
|
4568
|
+
{
|
|
4569
|
+
value: "jsonwebtoken",
|
|
4570
|
+
label: "jsonwebtoken",
|
|
4571
|
+
hint: "JWT encoding/decoding library"
|
|
4572
|
+
},
|
|
4573
|
+
{
|
|
4574
|
+
value: "argon2",
|
|
4575
|
+
label: "Argon2",
|
|
4576
|
+
hint: "Password hashing library"
|
|
4577
|
+
},
|
|
4578
|
+
{
|
|
4579
|
+
value: "tokio-test",
|
|
4580
|
+
label: "Tokio Test",
|
|
4581
|
+
hint: "Testing utilities for Tokio"
|
|
4582
|
+
},
|
|
4583
|
+
{
|
|
4584
|
+
value: "mockall",
|
|
4585
|
+
label: "Mockall",
|
|
4586
|
+
hint: "Powerful mocking library for Rust"
|
|
4587
|
+
}
|
|
4588
|
+
];
|
|
4589
|
+
const RUST_LOGGING_PROMPT_OPTIONS = [
|
|
4590
|
+
{
|
|
4591
|
+
value: "tracing",
|
|
4592
|
+
label: "Tracing",
|
|
4593
|
+
hint: "Structured, composable instrumentation framework from Tokio"
|
|
4594
|
+
},
|
|
4595
|
+
{
|
|
4596
|
+
value: "env-logger",
|
|
4597
|
+
label: "env_logger",
|
|
4598
|
+
hint: "Simple logger configured via environment variables"
|
|
4599
|
+
},
|
|
4600
|
+
{
|
|
4601
|
+
value: "none",
|
|
4602
|
+
label: "None",
|
|
4603
|
+
hint: "No logging library"
|
|
4604
|
+
}
|
|
4605
|
+
];
|
|
4606
|
+
const RUST_ERROR_HANDLING_PROMPT_OPTIONS = [
|
|
4607
|
+
{
|
|
4608
|
+
value: "anyhow-thiserror",
|
|
4609
|
+
label: "anyhow + thiserror",
|
|
4610
|
+
hint: "anyhow for application errors, thiserror for custom error types"
|
|
4611
|
+
},
|
|
4612
|
+
{
|
|
4613
|
+
value: "eyre",
|
|
4614
|
+
label: "eyre + color-eyre",
|
|
4615
|
+
hint: "Customizable error reports with pretty backtraces via color-eyre"
|
|
4616
|
+
},
|
|
4617
|
+
{
|
|
4618
|
+
value: "none",
|
|
4619
|
+
label: "None",
|
|
4620
|
+
hint: "No error handling library (uses standard library only)"
|
|
4621
|
+
}
|
|
4622
|
+
];
|
|
4623
|
+
const RUST_CACHING_PROMPT_OPTIONS = [
|
|
4624
|
+
{
|
|
4625
|
+
value: "moka",
|
|
4626
|
+
label: "Moka",
|
|
4627
|
+
hint: "High-performance concurrent in-memory cache (Caffeine-inspired)"
|
|
4628
|
+
},
|
|
4629
|
+
{
|
|
4630
|
+
value: "redis",
|
|
4631
|
+
label: "Redis",
|
|
4632
|
+
hint: "Redis client with async support and connection pooling"
|
|
4633
|
+
},
|
|
4634
|
+
{
|
|
4635
|
+
value: "none",
|
|
4636
|
+
label: "None",
|
|
4637
|
+
hint: "No caching library"
|
|
4638
|
+
}
|
|
4639
|
+
];
|
|
4640
|
+
function resolveRustWebFrameworkPrompt(rustWebFramework) {
|
|
4641
|
+
return createStaticSinglePromptResolution(RUST_WEB_FRAMEWORK_PROMPT_OPTIONS, "axum", rustWebFramework);
|
|
4642
|
+
}
|
|
3427
4643
|
async function getRustWebFrameworkChoice(rustWebFramework) {
|
|
3428
|
-
|
|
4644
|
+
const resolution = resolveRustWebFrameworkPrompt(rustWebFramework);
|
|
4645
|
+
if (!resolution.shouldPrompt) return resolution.autoValue ?? "none";
|
|
3429
4646
|
const response = await navigableSelect({
|
|
3430
4647
|
message: "Select Rust web framework",
|
|
3431
|
-
options:
|
|
3432
|
-
|
|
3433
|
-
value: "axum",
|
|
3434
|
-
label: "Axum",
|
|
3435
|
-
hint: "Ergonomic and modular web framework from Tokio"
|
|
3436
|
-
},
|
|
3437
|
-
{
|
|
3438
|
-
value: "actix-web",
|
|
3439
|
-
label: "Actix Web",
|
|
3440
|
-
hint: "Powerful, pragmatic, and extremely fast web framework"
|
|
3441
|
-
},
|
|
3442
|
-
{
|
|
3443
|
-
value: "rocket",
|
|
3444
|
-
label: "Rocket",
|
|
3445
|
-
hint: "Convention-over-configuration web framework, 25k+ stars"
|
|
3446
|
-
},
|
|
3447
|
-
{
|
|
3448
|
-
value: "none",
|
|
3449
|
-
label: "None",
|
|
3450
|
-
hint: "No web framework"
|
|
3451
|
-
}
|
|
3452
|
-
],
|
|
3453
|
-
initialValue: "axum"
|
|
4648
|
+
options: resolution.options,
|
|
4649
|
+
initialValue: resolution.initialValue
|
|
3454
4650
|
});
|
|
3455
4651
|
if (isCancel$1(response)) return exitCancelled("Operation cancelled");
|
|
3456
4652
|
return response;
|
|
3457
4653
|
}
|
|
4654
|
+
function resolveRustFrontendPrompt(rustFrontend) {
|
|
4655
|
+
return createStaticSinglePromptResolution(RUST_FRONTEND_PROMPT_OPTIONS, "none", rustFrontend);
|
|
4656
|
+
}
|
|
3458
4657
|
async function getRustFrontendChoice(rustFrontend) {
|
|
3459
|
-
|
|
4658
|
+
const resolution = resolveRustFrontendPrompt(rustFrontend);
|
|
4659
|
+
if (!resolution.shouldPrompt) return resolution.autoValue ?? "none";
|
|
3460
4660
|
const response = await navigableSelect({
|
|
3461
4661
|
message: "Select Rust frontend framework",
|
|
3462
|
-
options:
|
|
3463
|
-
|
|
3464
|
-
value: "leptos",
|
|
3465
|
-
label: "Leptos",
|
|
3466
|
-
hint: "Build fast web applications with Rust"
|
|
3467
|
-
},
|
|
3468
|
-
{
|
|
3469
|
-
value: "dioxus",
|
|
3470
|
-
label: "Dioxus",
|
|
3471
|
-
hint: "Fullstack, cross-platform UI library for Rust"
|
|
3472
|
-
},
|
|
3473
|
-
{
|
|
3474
|
-
value: "none",
|
|
3475
|
-
label: "None",
|
|
3476
|
-
hint: "No Rust frontend (API only)"
|
|
3477
|
-
}
|
|
3478
|
-
],
|
|
3479
|
-
initialValue: "none"
|
|
3480
|
-
});
|
|
3481
|
-
if (isCancel$1(response)) return exitCancelled("Operation cancelled");
|
|
3482
|
-
return response;
|
|
3483
|
-
}
|
|
3484
|
-
async function getRustOrmChoice(rustOrm) {
|
|
3485
|
-
if (rustOrm !== void 0) return rustOrm;
|
|
3486
|
-
const response = await navigableSelect({
|
|
3487
|
-
message: "Select Rust ORM/database layer",
|
|
3488
|
-
options: [
|
|
3489
|
-
{
|
|
3490
|
-
value: "sea-orm",
|
|
3491
|
-
label: "SeaORM",
|
|
3492
|
-
hint: "Async & dynamic ORM for Rust"
|
|
3493
|
-
},
|
|
3494
|
-
{
|
|
3495
|
-
value: "sqlx",
|
|
3496
|
-
label: "SQLx",
|
|
3497
|
-
hint: "Async SQL toolkit with compile-time checked queries"
|
|
3498
|
-
},
|
|
3499
|
-
{
|
|
3500
|
-
value: "diesel",
|
|
3501
|
-
label: "Diesel",
|
|
3502
|
-
hint: "Safe, extensible ORM with compile-time query validation"
|
|
3503
|
-
},
|
|
3504
|
-
{
|
|
3505
|
-
value: "none",
|
|
3506
|
-
label: "None",
|
|
3507
|
-
hint: "No database layer"
|
|
3508
|
-
}
|
|
3509
|
-
],
|
|
3510
|
-
initialValue: "none"
|
|
4662
|
+
options: resolution.options,
|
|
4663
|
+
initialValue: resolution.initialValue
|
|
3511
4664
|
});
|
|
3512
4665
|
if (isCancel$1(response)) return exitCancelled("Operation cancelled");
|
|
3513
4666
|
return response;
|
|
3514
4667
|
}
|
|
4668
|
+
function resolveRustOrmPrompt(rustOrm) {
|
|
4669
|
+
return createStaticSinglePromptResolution(RUST_ORM_PROMPT_OPTIONS, "none", rustOrm);
|
|
4670
|
+
}
|
|
4671
|
+
async function getRustOrmChoice(rustOrm) {
|
|
4672
|
+
const resolution = resolveRustOrmPrompt(rustOrm);
|
|
4673
|
+
if (!resolution.shouldPrompt) return resolution.autoValue ?? "none";
|
|
4674
|
+
const response = await navigableSelect({
|
|
4675
|
+
message: "Select Rust ORM/database layer",
|
|
4676
|
+
options: resolution.options,
|
|
4677
|
+
initialValue: resolution.initialValue
|
|
4678
|
+
});
|
|
4679
|
+
if (isCancel$1(response)) return exitCancelled("Operation cancelled");
|
|
4680
|
+
return response;
|
|
4681
|
+
}
|
|
4682
|
+
function resolveRustApiPrompt(rustApi) {
|
|
4683
|
+
return createStaticSinglePromptResolution(RUST_API_PROMPT_OPTIONS, "none", rustApi);
|
|
4684
|
+
}
|
|
3515
4685
|
async function getRustApiChoice(rustApi) {
|
|
3516
|
-
|
|
4686
|
+
const resolution = resolveRustApiPrompt(rustApi);
|
|
4687
|
+
if (!resolution.shouldPrompt) return resolution.autoValue ?? "none";
|
|
3517
4688
|
const response = await navigableSelect({
|
|
3518
4689
|
message: "Select Rust API layer",
|
|
3519
|
-
options:
|
|
3520
|
-
|
|
3521
|
-
value: "tonic",
|
|
3522
|
-
label: "Tonic",
|
|
3523
|
-
hint: "gRPC implementation for Rust"
|
|
3524
|
-
},
|
|
3525
|
-
{
|
|
3526
|
-
value: "async-graphql",
|
|
3527
|
-
label: "async-graphql",
|
|
3528
|
-
hint: "High-performance GraphQL server library"
|
|
3529
|
-
},
|
|
3530
|
-
{
|
|
3531
|
-
value: "none",
|
|
3532
|
-
label: "None",
|
|
3533
|
-
hint: "REST API only"
|
|
3534
|
-
}
|
|
3535
|
-
],
|
|
3536
|
-
initialValue: "none"
|
|
4690
|
+
options: resolution.options,
|
|
4691
|
+
initialValue: resolution.initialValue
|
|
3537
4692
|
});
|
|
3538
4693
|
if (isCancel$1(response)) return exitCancelled("Operation cancelled");
|
|
3539
4694
|
return response;
|
|
3540
4695
|
}
|
|
4696
|
+
function resolveRustCliPrompt(rustCli) {
|
|
4697
|
+
return createStaticSinglePromptResolution(RUST_CLI_PROMPT_OPTIONS, "none", rustCli);
|
|
4698
|
+
}
|
|
3541
4699
|
async function getRustCliChoice(rustCli) {
|
|
3542
|
-
|
|
4700
|
+
const resolution = resolveRustCliPrompt(rustCli);
|
|
4701
|
+
if (!resolution.shouldPrompt) return resolution.autoValue ?? "none";
|
|
3543
4702
|
const response = await navigableSelect({
|
|
3544
4703
|
message: "Select Rust CLI tools",
|
|
3545
|
-
options:
|
|
3546
|
-
|
|
3547
|
-
value: "clap",
|
|
3548
|
-
label: "Clap",
|
|
3549
|
-
hint: "Command Line Argument Parser for Rust"
|
|
3550
|
-
},
|
|
3551
|
-
{
|
|
3552
|
-
value: "ratatui",
|
|
3553
|
-
label: "Ratatui",
|
|
3554
|
-
hint: "Build rich terminal user interfaces"
|
|
3555
|
-
},
|
|
3556
|
-
{
|
|
3557
|
-
value: "none",
|
|
3558
|
-
label: "None",
|
|
3559
|
-
hint: "No CLI tools"
|
|
3560
|
-
}
|
|
3561
|
-
],
|
|
3562
|
-
initialValue: "none"
|
|
4704
|
+
options: resolution.options,
|
|
4705
|
+
initialValue: resolution.initialValue
|
|
3563
4706
|
});
|
|
3564
4707
|
if (isCancel$1(response)) return exitCancelled("Operation cancelled");
|
|
3565
4708
|
return response;
|
|
3566
4709
|
}
|
|
4710
|
+
function resolveRustLibrariesPrompt(rustLibraries) {
|
|
4711
|
+
return createStaticMultiPromptResolution(RUST_LIBRARIES_PROMPT_OPTIONS, [], rustLibraries);
|
|
4712
|
+
}
|
|
3567
4713
|
async function getRustLibrariesChoice(rustLibraries) {
|
|
3568
|
-
|
|
4714
|
+
const resolution = resolveRustLibrariesPrompt(rustLibraries);
|
|
4715
|
+
if (!resolution.shouldPrompt) return resolution.autoValue ?? [];
|
|
3569
4716
|
const response = await navigableMultiselect({
|
|
3570
4717
|
message: "Select Rust libraries",
|
|
3571
|
-
options:
|
|
3572
|
-
{
|
|
3573
|
-
value: "serde",
|
|
3574
|
-
label: "Serde",
|
|
3575
|
-
hint: "Serialization framework for Rust"
|
|
3576
|
-
},
|
|
3577
|
-
{
|
|
3578
|
-
value: "validator",
|
|
3579
|
-
label: "Validator",
|
|
3580
|
-
hint: "Struct validation derive macros"
|
|
3581
|
-
},
|
|
3582
|
-
{
|
|
3583
|
-
value: "jsonwebtoken",
|
|
3584
|
-
label: "jsonwebtoken",
|
|
3585
|
-
hint: "JWT encoding/decoding library"
|
|
3586
|
-
},
|
|
3587
|
-
{
|
|
3588
|
-
value: "argon2",
|
|
3589
|
-
label: "Argon2",
|
|
3590
|
-
hint: "Password hashing library"
|
|
3591
|
-
},
|
|
3592
|
-
{
|
|
3593
|
-
value: "tokio-test",
|
|
3594
|
-
label: "Tokio Test",
|
|
3595
|
-
hint: "Testing utilities for Tokio"
|
|
3596
|
-
},
|
|
3597
|
-
{
|
|
3598
|
-
value: "mockall",
|
|
3599
|
-
label: "Mockall",
|
|
3600
|
-
hint: "Powerful mocking library for Rust"
|
|
3601
|
-
}
|
|
3602
|
-
],
|
|
4718
|
+
options: resolution.options,
|
|
3603
4719
|
required: false,
|
|
3604
|
-
initialValues:
|
|
4720
|
+
initialValues: resolution.initialValue
|
|
3605
4721
|
});
|
|
3606
4722
|
if (isCancel$1(response)) return exitCancelled("Operation cancelled");
|
|
3607
4723
|
return response;
|
|
3608
4724
|
}
|
|
4725
|
+
function resolveRustLoggingPrompt(rustLogging) {
|
|
4726
|
+
return createStaticSinglePromptResolution(RUST_LOGGING_PROMPT_OPTIONS, "tracing", rustLogging);
|
|
4727
|
+
}
|
|
3609
4728
|
async function getRustLoggingChoice(rustLogging) {
|
|
3610
|
-
|
|
4729
|
+
const resolution = resolveRustLoggingPrompt(rustLogging);
|
|
4730
|
+
if (!resolution.shouldPrompt) return resolution.autoValue ?? "none";
|
|
3611
4731
|
const response = await navigableSelect({
|
|
3612
4732
|
message: "Select Rust logging library",
|
|
3613
|
-
options:
|
|
3614
|
-
|
|
3615
|
-
value: "tracing",
|
|
3616
|
-
label: "Tracing",
|
|
3617
|
-
hint: "Structured, composable instrumentation framework from Tokio"
|
|
3618
|
-
},
|
|
3619
|
-
{
|
|
3620
|
-
value: "env-logger",
|
|
3621
|
-
label: "env_logger",
|
|
3622
|
-
hint: "Simple logger configured via environment variables"
|
|
3623
|
-
},
|
|
3624
|
-
{
|
|
3625
|
-
value: "none",
|
|
3626
|
-
label: "None",
|
|
3627
|
-
hint: "No logging library"
|
|
3628
|
-
}
|
|
3629
|
-
],
|
|
3630
|
-
initialValue: "tracing"
|
|
4733
|
+
options: resolution.options,
|
|
4734
|
+
initialValue: resolution.initialValue
|
|
3631
4735
|
});
|
|
3632
4736
|
if (isCancel$1(response)) return exitCancelled("Operation cancelled");
|
|
3633
4737
|
return response;
|
|
3634
4738
|
}
|
|
4739
|
+
function resolveRustErrorHandlingPrompt(rustErrorHandling) {
|
|
4740
|
+
return createStaticSinglePromptResolution(RUST_ERROR_HANDLING_PROMPT_OPTIONS, "anyhow-thiserror", rustErrorHandling);
|
|
4741
|
+
}
|
|
3635
4742
|
async function getRustErrorHandlingChoice(rustErrorHandling) {
|
|
3636
|
-
|
|
4743
|
+
const resolution = resolveRustErrorHandlingPrompt(rustErrorHandling);
|
|
4744
|
+
if (!resolution.shouldPrompt) return resolution.autoValue ?? "none";
|
|
3637
4745
|
const response = await navigableSelect({
|
|
3638
4746
|
message: "Select Rust error handling library",
|
|
3639
|
-
options:
|
|
3640
|
-
|
|
3641
|
-
value: "anyhow-thiserror",
|
|
3642
|
-
label: "anyhow + thiserror",
|
|
3643
|
-
hint: "anyhow for application errors, thiserror for custom error types"
|
|
3644
|
-
},
|
|
3645
|
-
{
|
|
3646
|
-
value: "eyre",
|
|
3647
|
-
label: "eyre + color-eyre",
|
|
3648
|
-
hint: "Customizable error reports with pretty backtraces via color-eyre"
|
|
3649
|
-
},
|
|
3650
|
-
{
|
|
3651
|
-
value: "none",
|
|
3652
|
-
label: "None",
|
|
3653
|
-
hint: "No error handling library (uses standard library only)"
|
|
3654
|
-
}
|
|
3655
|
-
],
|
|
3656
|
-
initialValue: "anyhow-thiserror"
|
|
4747
|
+
options: resolution.options,
|
|
4748
|
+
initialValue: resolution.initialValue
|
|
3657
4749
|
});
|
|
3658
4750
|
if (isCancel$1(response)) return exitCancelled("Operation cancelled");
|
|
3659
4751
|
return response;
|
|
3660
4752
|
}
|
|
4753
|
+
function resolveRustCachingPrompt(rustCaching) {
|
|
4754
|
+
return createStaticSinglePromptResolution(RUST_CACHING_PROMPT_OPTIONS, "none", rustCaching);
|
|
4755
|
+
}
|
|
3661
4756
|
async function getRustCachingChoice(rustCaching) {
|
|
3662
|
-
|
|
4757
|
+
const resolution = resolveRustCachingPrompt(rustCaching);
|
|
4758
|
+
if (!resolution.shouldPrompt) return resolution.autoValue ?? "none";
|
|
3663
4759
|
const response = await navigableSelect({
|
|
3664
4760
|
message: "Select Rust caching library",
|
|
3665
|
-
options:
|
|
3666
|
-
|
|
3667
|
-
|
|
3668
|
-
|
|
3669
|
-
|
|
3670
|
-
|
|
3671
|
-
|
|
3672
|
-
|
|
3673
|
-
|
|
3674
|
-
|
|
3675
|
-
|
|
3676
|
-
|
|
3677
|
-
|
|
3678
|
-
|
|
3679
|
-
|
|
3680
|
-
|
|
3681
|
-
|
|
4761
|
+
options: resolution.options,
|
|
4762
|
+
initialValue: resolution.initialValue
|
|
4763
|
+
});
|
|
4764
|
+
if (isCancel$1(response)) return exitCancelled("Operation cancelled");
|
|
4765
|
+
return response;
|
|
4766
|
+
}
|
|
4767
|
+
async function getRustAuthChoice(rustAuth) {
|
|
4768
|
+
if (rustAuth !== void 0) return rustAuth;
|
|
4769
|
+
const response = await navigableSelect({
|
|
4770
|
+
message: "Select Rust authentication library",
|
|
4771
|
+
options: [{
|
|
4772
|
+
value: "oauth2",
|
|
4773
|
+
label: "OAuth2",
|
|
4774
|
+
hint: "OAuth2 client with authorization code, PKCE, and token exchange flows"
|
|
4775
|
+
}, {
|
|
4776
|
+
value: "none",
|
|
4777
|
+
label: "None",
|
|
4778
|
+
hint: "No authentication library"
|
|
4779
|
+
}],
|
|
3682
4780
|
initialValue: "none"
|
|
3683
4781
|
});
|
|
3684
4782
|
if (isCancel$1(response)) return exitCancelled("Operation cancelled");
|
|
@@ -4123,10 +5221,20 @@ async function promptShadcnRadius() {
|
|
|
4123
5221
|
|
|
4124
5222
|
//#endregion
|
|
4125
5223
|
//#region src/prompts/state-management.ts
|
|
4126
|
-
|
|
4127
|
-
if (stateManagement !== void 0) return
|
|
4128
|
-
|
|
4129
|
-
|
|
5224
|
+
function resolveStateManagementPrompt(context = {}) {
|
|
5225
|
+
if (context.stateManagement !== void 0) return {
|
|
5226
|
+
shouldPrompt: false,
|
|
5227
|
+
mode: "single",
|
|
5228
|
+
options: [],
|
|
5229
|
+
autoValue: context.stateManagement
|
|
5230
|
+
};
|
|
5231
|
+
const { web } = splitFrontends$1(context.frontends);
|
|
5232
|
+
if (web.length === 0) return {
|
|
5233
|
+
shouldPrompt: false,
|
|
5234
|
+
mode: "single",
|
|
5235
|
+
options: [],
|
|
5236
|
+
autoValue: "none"
|
|
5237
|
+
};
|
|
4130
5238
|
const isReact = web.some((f) => [
|
|
4131
5239
|
"tanstack-router",
|
|
4132
5240
|
"react-router",
|
|
@@ -4180,10 +5288,23 @@ async function getStateManagementChoice(stateManagement, frontends) {
|
|
|
4180
5288
|
label: "None",
|
|
4181
5289
|
hint: "Skip state management setup"
|
|
4182
5290
|
});
|
|
4183
|
-
|
|
4184
|
-
|
|
5291
|
+
return {
|
|
5292
|
+
shouldPrompt: true,
|
|
5293
|
+
mode: "single",
|
|
4185
5294
|
options,
|
|
4186
5295
|
initialValue: "none"
|
|
5296
|
+
};
|
|
5297
|
+
}
|
|
5298
|
+
async function getStateManagementChoice(stateManagement, frontends) {
|
|
5299
|
+
const resolution = resolveStateManagementPrompt({
|
|
5300
|
+
stateManagement,
|
|
5301
|
+
frontends
|
|
5302
|
+
});
|
|
5303
|
+
if (!resolution.shouldPrompt) return resolution.autoValue ?? "none";
|
|
5304
|
+
const response = await navigableSelect({
|
|
5305
|
+
message: "Select state management",
|
|
5306
|
+
options: resolution.options,
|
|
5307
|
+
initialValue: resolution.initialValue
|
|
4187
5308
|
});
|
|
4188
5309
|
if (isCancel$1(response)) return exitCancelled("Operation cancelled");
|
|
4189
5310
|
return response;
|
|
@@ -4191,43 +5312,48 @@ async function getStateManagementChoice(stateManagement, frontends) {
|
|
|
4191
5312
|
|
|
4192
5313
|
//#endregion
|
|
4193
5314
|
//#region src/prompts/testing.ts
|
|
5315
|
+
const TESTING_PROMPT_OPTIONS = [
|
|
5316
|
+
{
|
|
5317
|
+
value: "vitest",
|
|
5318
|
+
label: "Vitest",
|
|
5319
|
+
hint: "Blazing fast Vite-native unit test framework"
|
|
5320
|
+
},
|
|
5321
|
+
{
|
|
5322
|
+
value: "vitest-playwright",
|
|
5323
|
+
label: "Vitest + Playwright",
|
|
5324
|
+
hint: "Both unit and E2E testing for complete coverage"
|
|
5325
|
+
},
|
|
5326
|
+
{
|
|
5327
|
+
value: "playwright",
|
|
5328
|
+
label: "Playwright",
|
|
5329
|
+
hint: "End-to-end testing framework by Microsoft"
|
|
5330
|
+
},
|
|
5331
|
+
{
|
|
5332
|
+
value: "jest",
|
|
5333
|
+
label: "Jest",
|
|
5334
|
+
hint: "Classic testing framework with wide ecosystem"
|
|
5335
|
+
},
|
|
5336
|
+
{
|
|
5337
|
+
value: "cypress",
|
|
5338
|
+
label: "Cypress",
|
|
5339
|
+
hint: "E2E testing with time travel debugging"
|
|
5340
|
+
},
|
|
5341
|
+
{
|
|
5342
|
+
value: "none",
|
|
5343
|
+
label: "None",
|
|
5344
|
+
hint: "Skip testing framework setup"
|
|
5345
|
+
}
|
|
5346
|
+
];
|
|
5347
|
+
function resolveTestingPrompt(testing) {
|
|
5348
|
+
return createStaticSinglePromptResolution(TESTING_PROMPT_OPTIONS, "vitest", testing);
|
|
5349
|
+
}
|
|
4194
5350
|
async function getTestingChoice(testing) {
|
|
4195
|
-
|
|
5351
|
+
const resolution = resolveTestingPrompt(testing);
|
|
5352
|
+
if (!resolution.shouldPrompt) return resolution.autoValue ?? "none";
|
|
4196
5353
|
const response = await navigableSelect({
|
|
4197
5354
|
message: "Select testing framework",
|
|
4198
|
-
options:
|
|
4199
|
-
|
|
4200
|
-
value: "vitest",
|
|
4201
|
-
label: "Vitest",
|
|
4202
|
-
hint: "Blazing fast Vite-native unit test framework"
|
|
4203
|
-
},
|
|
4204
|
-
{
|
|
4205
|
-
value: "vitest-playwright",
|
|
4206
|
-
label: "Vitest + Playwright",
|
|
4207
|
-
hint: "Both unit and E2E testing for complete coverage"
|
|
4208
|
-
},
|
|
4209
|
-
{
|
|
4210
|
-
value: "playwright",
|
|
4211
|
-
label: "Playwright",
|
|
4212
|
-
hint: "End-to-end testing framework by Microsoft"
|
|
4213
|
-
},
|
|
4214
|
-
{
|
|
4215
|
-
value: "jest",
|
|
4216
|
-
label: "Jest",
|
|
4217
|
-
hint: "Classic testing framework with wide ecosystem"
|
|
4218
|
-
},
|
|
4219
|
-
{
|
|
4220
|
-
value: "cypress",
|
|
4221
|
-
label: "Cypress",
|
|
4222
|
-
hint: "E2E testing with time travel debugging"
|
|
4223
|
-
},
|
|
4224
|
-
{
|
|
4225
|
-
value: "none",
|
|
4226
|
-
label: "None",
|
|
4227
|
-
hint: "Skip testing framework setup"
|
|
4228
|
-
}
|
|
4229
|
-
],
|
|
4230
|
-
initialValue: "vitest"
|
|
5355
|
+
options: resolution.options,
|
|
5356
|
+
initialValue: resolution.initialValue
|
|
4231
5357
|
});
|
|
4232
5358
|
if (isCancel$1(response)) return exitCancelled("Operation cancelled");
|
|
4233
5359
|
return response;
|
|
@@ -4285,21 +5411,48 @@ const UI_LIBRARY_OPTIONS = {
|
|
|
4285
5411
|
hint: "No UI component library"
|
|
4286
5412
|
}
|
|
4287
5413
|
};
|
|
4288
|
-
|
|
4289
|
-
const { web } = splitFrontends$1(frontends);
|
|
4290
|
-
if (web.length === 0) return
|
|
4291
|
-
|
|
4292
|
-
|
|
4293
|
-
|
|
4294
|
-
|
|
4295
|
-
|
|
4296
|
-
|
|
4297
|
-
|
|
5414
|
+
function resolveUILibraryPrompt(context = {}) {
|
|
5415
|
+
const { web } = splitFrontends$1(context.frontends);
|
|
5416
|
+
if (web.length === 0) return {
|
|
5417
|
+
shouldPrompt: false,
|
|
5418
|
+
mode: "single",
|
|
5419
|
+
options: [],
|
|
5420
|
+
autoValue: "none"
|
|
5421
|
+
};
|
|
5422
|
+
const compatibleLibraries = getCompatibleUILibraries$1(context.frontends, context.astroIntegration);
|
|
5423
|
+
if (context.uiLibrary !== void 0) return {
|
|
5424
|
+
shouldPrompt: false,
|
|
5425
|
+
mode: "single",
|
|
5426
|
+
options: compatibleLibraries.map((lib) => ({
|
|
5427
|
+
value: lib,
|
|
5428
|
+
label: UI_LIBRARY_OPTIONS[lib].label,
|
|
5429
|
+
hint: UI_LIBRARY_OPTIONS[lib].hint
|
|
5430
|
+
})),
|
|
5431
|
+
autoValue: compatibleLibraries.includes(context.uiLibrary) ? context.uiLibrary : compatibleLibraries[0]
|
|
5432
|
+
};
|
|
4298
5433
|
const defaultLib = DEFAULT_UI_LIBRARY_BY_FRONTEND[web[0]];
|
|
5434
|
+
return {
|
|
5435
|
+
shouldPrompt: true,
|
|
5436
|
+
mode: "single",
|
|
5437
|
+
options: compatibleLibraries.map((lib) => ({
|
|
5438
|
+
value: lib,
|
|
5439
|
+
label: UI_LIBRARY_OPTIONS[lib].label,
|
|
5440
|
+
hint: UI_LIBRARY_OPTIONS[lib].hint
|
|
5441
|
+
})),
|
|
5442
|
+
initialValue: compatibleLibraries.includes(defaultLib) ? defaultLib : compatibleLibraries[0]
|
|
5443
|
+
};
|
|
5444
|
+
}
|
|
5445
|
+
async function getUILibraryChoice(uiLibrary, frontends, astroIntegration) {
|
|
5446
|
+
const resolution = resolveUILibraryPrompt({
|
|
5447
|
+
uiLibrary,
|
|
5448
|
+
frontends,
|
|
5449
|
+
astroIntegration
|
|
5450
|
+
});
|
|
5451
|
+
if (!resolution.shouldPrompt) return resolution.autoValue ?? "none";
|
|
4299
5452
|
const selected = await navigableSelect({
|
|
4300
5453
|
message: "Select UI component library",
|
|
4301
|
-
options,
|
|
4302
|
-
initialValue:
|
|
5454
|
+
options: resolution.options,
|
|
5455
|
+
initialValue: resolution.initialValue
|
|
4303
5456
|
});
|
|
4304
5457
|
if (isCancel$1(selected)) return exitCancelled("Operation cancelled");
|
|
4305
5458
|
return selected;
|
|
@@ -4307,53 +5460,58 @@ async function getUILibraryChoice(uiLibrary, frontends, astroIntegration) {
|
|
|
4307
5460
|
|
|
4308
5461
|
//#endregion
|
|
4309
5462
|
//#region src/prompts/validation.ts
|
|
5463
|
+
const VALIDATION_PROMPT_OPTIONS = [
|
|
5464
|
+
{
|
|
5465
|
+
value: "zod",
|
|
5466
|
+
label: "Zod",
|
|
5467
|
+
hint: "TypeScript-first schema validation (recommended)"
|
|
5468
|
+
},
|
|
5469
|
+
{
|
|
5470
|
+
value: "valibot",
|
|
5471
|
+
label: "Valibot",
|
|
5472
|
+
hint: "Smaller bundle alternative to Zod (~1KB)"
|
|
5473
|
+
},
|
|
5474
|
+
{
|
|
5475
|
+
value: "arktype",
|
|
5476
|
+
label: "ArkType",
|
|
5477
|
+
hint: "TypeScript-first validation, 2-4x faster than Zod"
|
|
5478
|
+
},
|
|
5479
|
+
{
|
|
5480
|
+
value: "typebox",
|
|
5481
|
+
label: "TypeBox",
|
|
5482
|
+
hint: "JSON Schema type builder for TypeScript"
|
|
5483
|
+
},
|
|
5484
|
+
{
|
|
5485
|
+
value: "typia",
|
|
5486
|
+
label: "Typia",
|
|
5487
|
+
hint: "Super-fast validation via compile-time transform"
|
|
5488
|
+
},
|
|
5489
|
+
{
|
|
5490
|
+
value: "runtypes",
|
|
5491
|
+
label: "Runtypes",
|
|
5492
|
+
hint: "Runtime type validation with composable validators"
|
|
5493
|
+
},
|
|
5494
|
+
{
|
|
5495
|
+
value: "effect-schema",
|
|
5496
|
+
label: "@effect/schema",
|
|
5497
|
+
hint: "Effect ecosystem schema validation with powerful transformations"
|
|
5498
|
+
},
|
|
5499
|
+
{
|
|
5500
|
+
value: "none",
|
|
5501
|
+
label: "None",
|
|
5502
|
+
hint: "Use Zod internally only (no additional library)"
|
|
5503
|
+
}
|
|
5504
|
+
];
|
|
5505
|
+
function resolveValidationPrompt(validation) {
|
|
5506
|
+
return createStaticSinglePromptResolution(VALIDATION_PROMPT_OPTIONS, "zod", validation);
|
|
5507
|
+
}
|
|
4310
5508
|
async function getValidationChoice(validation) {
|
|
4311
|
-
|
|
5509
|
+
const resolution = resolveValidationPrompt(validation);
|
|
5510
|
+
if (!resolution.shouldPrompt) return resolution.autoValue ?? "none";
|
|
4312
5511
|
const response = await navigableSelect({
|
|
4313
5512
|
message: "Select validation library",
|
|
4314
|
-
options:
|
|
4315
|
-
|
|
4316
|
-
value: "zod",
|
|
4317
|
-
label: "Zod",
|
|
4318
|
-
hint: "TypeScript-first schema validation (recommended)"
|
|
4319
|
-
},
|
|
4320
|
-
{
|
|
4321
|
-
value: "valibot",
|
|
4322
|
-
label: "Valibot",
|
|
4323
|
-
hint: "Smaller bundle alternative to Zod (~1KB)"
|
|
4324
|
-
},
|
|
4325
|
-
{
|
|
4326
|
-
value: "arktype",
|
|
4327
|
-
label: "ArkType",
|
|
4328
|
-
hint: "TypeScript-first validation, 2-4x faster than Zod"
|
|
4329
|
-
},
|
|
4330
|
-
{
|
|
4331
|
-
value: "typebox",
|
|
4332
|
-
label: "TypeBox",
|
|
4333
|
-
hint: "JSON Schema type builder for TypeScript"
|
|
4334
|
-
},
|
|
4335
|
-
{
|
|
4336
|
-
value: "typia",
|
|
4337
|
-
label: "Typia",
|
|
4338
|
-
hint: "Super-fast validation via compile-time transform"
|
|
4339
|
-
},
|
|
4340
|
-
{
|
|
4341
|
-
value: "runtypes",
|
|
4342
|
-
label: "Runtypes",
|
|
4343
|
-
hint: "Runtime type validation with composable validators"
|
|
4344
|
-
},
|
|
4345
|
-
{
|
|
4346
|
-
value: "effect-schema",
|
|
4347
|
-
label: "@effect/schema",
|
|
4348
|
-
hint: "Effect ecosystem schema validation with powerful transformations"
|
|
4349
|
-
},
|
|
4350
|
-
{
|
|
4351
|
-
value: "none",
|
|
4352
|
-
label: "None",
|
|
4353
|
-
hint: "Use Zod internally only (no additional library)"
|
|
4354
|
-
}
|
|
4355
|
-
],
|
|
4356
|
-
initialValue: "zod"
|
|
5513
|
+
options: resolution.options,
|
|
5514
|
+
initialValue: resolution.initialValue
|
|
4357
5515
|
});
|
|
4358
5516
|
if (isCancel$1(response)) return exitCancelled("Operation cancelled");
|
|
4359
5517
|
return response;
|
|
@@ -4622,6 +5780,10 @@ async function gatherConfig(flags, projectName, projectDir, relativePath) {
|
|
|
4622
5780
|
if (results.ecosystem !== "rust") return Promise.resolve("none");
|
|
4623
5781
|
return getRustCachingChoice(flags.rustCaching);
|
|
4624
5782
|
},
|
|
5783
|
+
rustAuth: ({ results }) => {
|
|
5784
|
+
if (results.ecosystem !== "rust") return Promise.resolve("none");
|
|
5785
|
+
return getRustAuthChoice(flags.rustAuth);
|
|
5786
|
+
},
|
|
4625
5787
|
pythonWebFramework: ({ results }) => {
|
|
4626
5788
|
if (results.ecosystem !== "python") return Promise.resolve("none");
|
|
4627
5789
|
return getPythonWebFrameworkChoice(flags.pythonWebFramework);
|
|
@@ -4674,13 +5836,45 @@ async function gatherConfig(flags, projectName, projectDir, relativePath) {
|
|
|
4674
5836
|
if (results.ecosystem !== "go") return Promise.resolve("none");
|
|
4675
5837
|
return getGoLoggingChoice(flags.goLogging);
|
|
4676
5838
|
},
|
|
5839
|
+
goAuth: ({ results }) => {
|
|
5840
|
+
if (results.ecosystem !== "go") return Promise.resolve("none");
|
|
5841
|
+
return getGoAuthChoice(flags.goAuth);
|
|
5842
|
+
},
|
|
5843
|
+
javaWebFramework: ({ results }) => {
|
|
5844
|
+
if (results.ecosystem !== "java") return Promise.resolve("none");
|
|
5845
|
+
return getJavaWebFrameworkChoice(flags.javaWebFramework);
|
|
5846
|
+
},
|
|
5847
|
+
javaBuildTool: ({ results }) => {
|
|
5848
|
+
if (results.ecosystem !== "java") return Promise.resolve("none");
|
|
5849
|
+
return getJavaBuildToolChoice(flags.javaBuildTool);
|
|
5850
|
+
},
|
|
5851
|
+
javaOrm: ({ results }) => {
|
|
5852
|
+
if (results.ecosystem !== "java") return Promise.resolve("none");
|
|
5853
|
+
if (results.javaWebFramework !== "spring-boot" || results.javaBuildTool === "none") return Promise.resolve("none");
|
|
5854
|
+
return getJavaOrmChoice(flags.javaOrm);
|
|
5855
|
+
},
|
|
5856
|
+
javaAuth: ({ results }) => {
|
|
5857
|
+
if (results.ecosystem !== "java") return Promise.resolve("none");
|
|
5858
|
+
if (results.javaWebFramework !== "spring-boot" || results.javaBuildTool === "none") return Promise.resolve("none");
|
|
5859
|
+
return getJavaAuthChoice(flags.javaAuth);
|
|
5860
|
+
},
|
|
5861
|
+
javaLibraries: ({ results }) => {
|
|
5862
|
+
if (results.ecosystem !== "java") return Promise.resolve([]);
|
|
5863
|
+
if (results.javaWebFramework !== "spring-boot" || results.javaBuildTool === "none") return Promise.resolve([]);
|
|
5864
|
+
return getJavaLibrariesChoice(flags.javaLibraries);
|
|
5865
|
+
},
|
|
5866
|
+
javaTestingLibraries: ({ results }) => {
|
|
5867
|
+
if (results.ecosystem !== "java") return Promise.resolve([]);
|
|
5868
|
+
if (results.javaBuildTool === "none") return Promise.resolve([]);
|
|
5869
|
+
return getJavaTestingLibrariesChoice(flags.javaTestingLibraries);
|
|
5870
|
+
},
|
|
4677
5871
|
aiDocs: () => getAiDocsChoice(flags.aiDocs),
|
|
4678
5872
|
git: () => getGitChoice(flags.git),
|
|
4679
5873
|
packageManager: ({ results }) => {
|
|
4680
|
-
if (results.ecosystem === "rust" || results.ecosystem === "python" || results.ecosystem === "go") return Promise.resolve(flags.packageManager ?? getUserPkgManager());
|
|
5874
|
+
if (results.ecosystem === "rust" || results.ecosystem === "python" || results.ecosystem === "go" || results.ecosystem === "java") return Promise.resolve(flags.packageManager ?? getUserPkgManager());
|
|
4681
5875
|
return getPackageManagerChoice(flags.packageManager);
|
|
4682
5876
|
},
|
|
4683
|
-
install: ({ results }) => getinstallChoice(flags.install, results.ecosystem)
|
|
5877
|
+
install: ({ results }) => getinstallChoice(flags.install, results.ecosystem, results.javaBuildTool)
|
|
4684
5878
|
}, { onCancel: () => exitCancelled("Operation cancelled") });
|
|
4685
5879
|
return {
|
|
4686
5880
|
projectName,
|
|
@@ -4736,6 +5930,7 @@ async function gatherConfig(flags, projectName, projectDir, relativePath) {
|
|
|
4736
5930
|
rustLogging: result.rustLogging,
|
|
4737
5931
|
rustErrorHandling: result.rustErrorHandling,
|
|
4738
5932
|
rustCaching: result.rustCaching,
|
|
5933
|
+
rustAuth: result.rustAuth,
|
|
4739
5934
|
pythonWebFramework: result.pythonWebFramework,
|
|
4740
5935
|
pythonOrm: result.pythonOrm,
|
|
4741
5936
|
pythonValidation: result.pythonValidation,
|
|
@@ -4749,6 +5944,13 @@ async function gatherConfig(flags, projectName, projectDir, relativePath) {
|
|
|
4749
5944
|
goApi: result.goApi,
|
|
4750
5945
|
goCli: result.goCli,
|
|
4751
5946
|
goLogging: result.goLogging,
|
|
5947
|
+
goAuth: result.goAuth,
|
|
5948
|
+
javaWebFramework: result.javaWebFramework,
|
|
5949
|
+
javaBuildTool: result.javaBuildTool,
|
|
5950
|
+
javaOrm: result.javaOrm,
|
|
5951
|
+
javaAuth: result.javaAuth,
|
|
5952
|
+
javaLibraries: result.javaLibraries,
|
|
5953
|
+
javaTestingLibraries: result.javaTestingLibraries,
|
|
4752
5954
|
aiDocs: result.aiDocs
|
|
4753
5955
|
};
|
|
4754
5956
|
}
|
|
@@ -5028,6 +6230,7 @@ function getRustFlags(config) {
|
|
|
5028
6230
|
flags.push(`--rust-logging ${config.rustLogging}`);
|
|
5029
6231
|
flags.push(`--rust-error-handling ${config.rustErrorHandling}`);
|
|
5030
6232
|
flags.push(`--rust-caching ${config.rustCaching}`);
|
|
6233
|
+
flags.push(`--rust-auth ${config.rustAuth}`);
|
|
5031
6234
|
appendSharedNonTypeScriptFlags(flags, config);
|
|
5032
6235
|
appendCommonFlags(flags, config);
|
|
5033
6236
|
return flags;
|
|
@@ -5053,11 +6256,24 @@ function getGoFlags(config) {
|
|
|
5053
6256
|
flags.push(`--go-api ${config.goApi}`);
|
|
5054
6257
|
flags.push(`--go-cli ${config.goCli}`);
|
|
5055
6258
|
flags.push(`--go-logging ${config.goLogging}`);
|
|
6259
|
+
flags.push(`--go-auth ${config.goAuth}`);
|
|
5056
6260
|
flags.push(`--auth ${config.auth}`);
|
|
5057
6261
|
appendSharedNonTypeScriptFlags(flags, config);
|
|
5058
6262
|
appendCommonFlags(flags, config);
|
|
5059
6263
|
return flags;
|
|
5060
6264
|
}
|
|
6265
|
+
function getJavaFlags(config) {
|
|
6266
|
+
const flags = ["--ecosystem java"];
|
|
6267
|
+
flags.push(`--java-web-framework ${config.javaWebFramework}`);
|
|
6268
|
+
flags.push(`--java-build-tool ${config.javaBuildTool}`);
|
|
6269
|
+
flags.push(`--java-orm ${config.javaOrm}`);
|
|
6270
|
+
flags.push(`--java-auth ${config.javaAuth}`);
|
|
6271
|
+
flags.push(formatArrayFlag("java-libraries", config.javaLibraries));
|
|
6272
|
+
flags.push(formatArrayFlag("java-testing-libraries", config.javaTestingLibraries));
|
|
6273
|
+
appendSharedNonTypeScriptFlags(flags, config);
|
|
6274
|
+
appendCommonFlags(flags, config);
|
|
6275
|
+
return flags;
|
|
6276
|
+
}
|
|
5061
6277
|
function generateReproducibleCommand(config) {
|
|
5062
6278
|
let flags;
|
|
5063
6279
|
switch (config.ecosystem) {
|
|
@@ -5070,6 +6286,9 @@ function generateReproducibleCommand(config) {
|
|
|
5070
6286
|
case "go":
|
|
5071
6287
|
flags = getGoFlags(config);
|
|
5072
6288
|
break;
|
|
6289
|
+
case "java":
|
|
6290
|
+
flags = getJavaFlags(config);
|
|
6291
|
+
break;
|
|
5073
6292
|
case "typescript":
|
|
5074
6293
|
default:
|
|
5075
6294
|
flags = getTypeScriptFlags(config);
|
|
@@ -5316,6 +6535,7 @@ function processFlags(options, projectName) {
|
|
|
5316
6535
|
if (options.rustLogging !== void 0) config.rustLogging = options.rustLogging;
|
|
5317
6536
|
if (options.rustErrorHandling !== void 0) config.rustErrorHandling = options.rustErrorHandling;
|
|
5318
6537
|
if (options.rustCaching !== void 0) config.rustCaching = options.rustCaching;
|
|
6538
|
+
if (options.rustAuth !== void 0) config.rustAuth = options.rustAuth;
|
|
5319
6539
|
if (options.pythonWebFramework !== void 0) config.pythonWebFramework = options.pythonWebFramework;
|
|
5320
6540
|
if (options.pythonOrm !== void 0) config.pythonOrm = options.pythonOrm;
|
|
5321
6541
|
if (options.pythonValidation !== void 0) config.pythonValidation = options.pythonValidation;
|
|
@@ -5329,6 +6549,13 @@ function processFlags(options, projectName) {
|
|
|
5329
6549
|
if (options.goApi !== void 0) config.goApi = options.goApi;
|
|
5330
6550
|
if (options.goCli !== void 0) config.goCli = options.goCli;
|
|
5331
6551
|
if (options.goLogging !== void 0) config.goLogging = options.goLogging;
|
|
6552
|
+
if (options.goAuth !== void 0) config.goAuth = options.goAuth;
|
|
6553
|
+
if (options.javaWebFramework !== void 0) config.javaWebFramework = options.javaWebFramework;
|
|
6554
|
+
if (options.javaBuildTool !== void 0) config.javaBuildTool = options.javaBuildTool;
|
|
6555
|
+
if (options.javaOrm !== void 0) config.javaOrm = options.javaOrm;
|
|
6556
|
+
if (options.javaAuth !== void 0) config.javaAuth = options.javaAuth;
|
|
6557
|
+
if (options.javaLibraries !== void 0) config.javaLibraries = processArrayOption(options.javaLibraries);
|
|
6558
|
+
if (options.javaTestingLibraries !== void 0) config.javaTestingLibraries = processArrayOption(options.javaTestingLibraries);
|
|
5332
6559
|
return config;
|
|
5333
6560
|
}
|
|
5334
6561
|
function getProvidedFlags(options) {
|
|
@@ -5342,6 +6569,11 @@ function validateArrayOptions(options) {
|
|
|
5342
6569
|
validateNoneExclusivity(options.frontend, "frontend options");
|
|
5343
6570
|
validateNoneExclusivity(options.addons, "addons");
|
|
5344
6571
|
validateNoneExclusivity(options.examples, "examples");
|
|
6572
|
+
validateNoneExclusivity(options.aiDocs, "ai docs");
|
|
6573
|
+
validateNoneExclusivity(options.rustLibraries, "rust libraries");
|
|
6574
|
+
validateNoneExclusivity(options.pythonAi, "python ai libraries");
|
|
6575
|
+
validateNoneExclusivity(options.javaLibraries, "java libraries");
|
|
6576
|
+
validateNoneExclusivity(options.javaTestingLibraries, "java testing libraries");
|
|
5345
6577
|
}
|
|
5346
6578
|
|
|
5347
6579
|
//#endregion
|
|
@@ -5777,6 +7009,41 @@ function validateFrontendConstraints(config, providedFlags) {
|
|
|
5777
7009
|
validateWebDeployRequiresWebFrontend(config.webDeploy, hasWebFrontendFlag);
|
|
5778
7010
|
}
|
|
5779
7011
|
function validateApiConstraints(_config, _options) {}
|
|
7012
|
+
function validateJavaConstraints(config, providedFlags = /* @__PURE__ */ new Set()) {
|
|
7013
|
+
if (config.ecosystem !== "java") return;
|
|
7014
|
+
const hasSpringBoot = config.javaWebFramework === "spring-boot";
|
|
7015
|
+
const hasNoBuildTool = config.javaBuildTool === "none";
|
|
7016
|
+
const hasJavaLibraries = (config.javaLibraries ?? []).some((library) => library !== "none");
|
|
7017
|
+
const hasJavaTestingLibraries = (config.javaTestingLibraries ?? []).some((library) => library !== "none");
|
|
7018
|
+
const hasSpringOnlyFeatures = config.javaOrm !== "none" || config.javaAuth !== "none" || hasJavaLibraries;
|
|
7019
|
+
if (hasNoBuildTool && hasSpringBoot) incompatibilityError({
|
|
7020
|
+
message: "Spring Boot requires Maven or Gradle in the Java scaffold.",
|
|
7021
|
+
provided: {
|
|
7022
|
+
"java-web-framework": config.javaWebFramework ?? "none",
|
|
7023
|
+
"java-build-tool": config.javaBuildTool ?? "none"
|
|
7024
|
+
},
|
|
7025
|
+
suggestions: ["Use --java-build-tool maven or --java-build-tool gradle with Spring Boot", "Use --java-web-framework none for a plain Java source-only scaffold"]
|
|
7026
|
+
});
|
|
7027
|
+
if ((config.javaWebFramework === "none" || hasNoBuildTool) && hasSpringOnlyFeatures) incompatibilityError({
|
|
7028
|
+
message: "Spring-only Java features require the Spring Boot scaffold with Maven or Gradle.",
|
|
7029
|
+
provided: {
|
|
7030
|
+
"java-web-framework": config.javaWebFramework ?? "none",
|
|
7031
|
+
"java-build-tool": config.javaBuildTool ?? "none",
|
|
7032
|
+
"java-orm": config.javaOrm ?? "none",
|
|
7033
|
+
"java-auth": config.javaAuth ?? "none",
|
|
7034
|
+
"java-libraries": (config.javaLibraries ?? []).join(" ") || "none"
|
|
7035
|
+
},
|
|
7036
|
+
suggestions: ["Use --java-web-framework spring-boot and a real build tool for Spring features", "Clear --java-orm, --java-auth, and --java-libraries when using plain Java"]
|
|
7037
|
+
});
|
|
7038
|
+
if (hasNoBuildTool && hasJavaTestingLibraries) incompatibilityError({
|
|
7039
|
+
message: "Java testing libraries require Maven or Gradle to manage test dependencies.",
|
|
7040
|
+
provided: {
|
|
7041
|
+
"java-build-tool": config.javaBuildTool ?? "none",
|
|
7042
|
+
"java-testing-libraries": (config.javaTestingLibraries ?? []).join(" ") || "none"
|
|
7043
|
+
},
|
|
7044
|
+
suggestions: ["Use --java-build-tool maven or --java-build-tool gradle to enable JUnit/Mockito/Testcontainers", "Set --java-testing-libraries none for a source-only plain Java scaffold"]
|
|
7045
|
+
});
|
|
7046
|
+
}
|
|
5780
7047
|
function validateShadcnConstraints(config, providedFlags) {
|
|
5781
7048
|
const shadcnFlagMap = {
|
|
5782
7049
|
shadcnBase: "--shadcn-base",
|
|
@@ -5809,6 +7076,7 @@ function validateFullConfig(config, providedFlags, options) {
|
|
|
5809
7076
|
validateBackendConstraints(config, providedFlags, options);
|
|
5810
7077
|
validateFrontendConstraints(config, providedFlags);
|
|
5811
7078
|
/* @__PURE__ */ validateApiConstraints(config, options);
|
|
7079
|
+
validateJavaConstraints(config, providedFlags);
|
|
5812
7080
|
validateServerDeployRequiresBackend(config.serverDeploy, config.backend);
|
|
5813
7081
|
validateSelfBackendCompatibility(providedFlags, options, config);
|
|
5814
7082
|
validateWorkersCompatibility(providedFlags, options, config);
|
|
@@ -5844,6 +7112,7 @@ function validateConfigForProgrammaticUse(config) {
|
|
|
5844
7112
|
validateDatabaseOrmAuth(config);
|
|
5845
7113
|
if (config.frontend && config.frontend.length > 0) ensureSingleWebAndNative(config.frontend);
|
|
5846
7114
|
validateApiFrontendCompatibility(config.api, config.frontend, config.astroIntegration);
|
|
7115
|
+
validateJavaConstraints(config);
|
|
5847
7116
|
validatePaymentsCompatibility(config.payments, config.auth, config.backend, config.frontend);
|
|
5848
7117
|
if (config.addons && config.addons.length > 0) validateAddonsAgainstFrontends(config.addons, config.frontend, config.auth);
|
|
5849
7118
|
validateExamplesCompatibility(config.examples ?? [], config.backend, config.frontend ?? [], config.runtime, config.ai);
|
|
@@ -6150,6 +7419,12 @@ async function setupMongoDBAtlas(config, cliInput) {
|
|
|
6150
7419
|
displayManualSetupInstructions$4();
|
|
6151
7420
|
return;
|
|
6152
7421
|
}
|
|
7422
|
+
if (!canPromptInteractively()) {
|
|
7423
|
+
log.info("MongoDB Atlas manual setup selected (non-interactive mode)");
|
|
7424
|
+
await writeEnvFile$4(projectDir, backend);
|
|
7425
|
+
displayManualSetupInstructions$4();
|
|
7426
|
+
return;
|
|
7427
|
+
}
|
|
6153
7428
|
const mode = await select({
|
|
6154
7429
|
message: "MongoDB Atlas setup: choose mode",
|
|
6155
7430
|
options: [{
|
|
@@ -6302,6 +7577,11 @@ async function setupNeonPostgres(config, cliInput) {
|
|
|
6302
7577
|
displayManualSetupInstructions$3(backend === "self" ? "apps/web" : "apps/server");
|
|
6303
7578
|
return;
|
|
6304
7579
|
}
|
|
7580
|
+
if (!canPromptInteractively()) {
|
|
7581
|
+
await writeEnvFile$3(projectDir, backend);
|
|
7582
|
+
displayManualSetupInstructions$3(backend === "self" ? "apps/web" : "apps/server");
|
|
7583
|
+
return;
|
|
7584
|
+
}
|
|
6305
7585
|
const mode = await select({
|
|
6306
7586
|
message: "Neon setup: choose mode",
|
|
6307
7587
|
options: [{
|
|
@@ -6346,7 +7626,7 @@ async function setupNeonPostgres(config, cliInput) {
|
|
|
6346
7626
|
const regionId = await select({
|
|
6347
7627
|
message: "Select a region for your Neon project:",
|
|
6348
7628
|
options: NEON_REGIONS,
|
|
6349
|
-
initialValue: NEON_REGIONS[0]
|
|
7629
|
+
initialValue: NEON_REGIONS[0]?.value ?? "aws-us-east-1"
|
|
6350
7630
|
});
|
|
6351
7631
|
if (isCancel(projectName) || isCancel(regionId)) return exitCancelled("Operation cancelled");
|
|
6352
7632
|
const neonConfig = await createNeonProject(projectName, regionId, packageManager);
|
|
@@ -6455,11 +7735,11 @@ const AVAILABLE_REGIONS = [
|
|
|
6455
7735
|
async function setupWithCreateDb(serverDir, packageManager) {
|
|
6456
7736
|
try {
|
|
6457
7737
|
log.info("Starting Prisma Postgres setup with create-db.");
|
|
6458
|
-
const selectedRegion = await select({
|
|
7738
|
+
const selectedRegion = canPromptInteractively() ? await select({
|
|
6459
7739
|
message: "Select your preferred region:",
|
|
6460
7740
|
options: AVAILABLE_REGIONS,
|
|
6461
7741
|
initialValue: "ap-southeast-1"
|
|
6462
|
-
});
|
|
7742
|
+
}) : "ap-southeast-1";
|
|
6463
7743
|
if (isCancel(selectedRegion)) return null;
|
|
6464
7744
|
const createDbArgs = getPackageExecutionArgs(packageManager, `create-db@latest --json --region ${selectedRegion}`);
|
|
6465
7745
|
const s = spinner();
|
|
@@ -6522,6 +7802,11 @@ async function setupPrismaPostgres(config, cliInput) {
|
|
|
6522
7802
|
displayManualSetupInstructions$2(backend === "self" ? "apps/web" : "apps/server");
|
|
6523
7803
|
return;
|
|
6524
7804
|
}
|
|
7805
|
+
if (!canPromptInteractively()) {
|
|
7806
|
+
await writeEnvFile$2(projectDir, backend);
|
|
7807
|
+
displayManualSetupInstructions$2(backend === "self" ? "apps/web" : "apps/server");
|
|
7808
|
+
return;
|
|
7809
|
+
}
|
|
6525
7810
|
const setupMode = await select({
|
|
6526
7811
|
message: "Prisma Postgres setup: choose mode",
|
|
6527
7812
|
options: [{
|
|
@@ -6657,6 +7942,11 @@ async function setupSupabase(config, cliInput) {
|
|
|
6657
7942
|
await writeSupabaseEnvFile(projectDir, backend, "");
|
|
6658
7943
|
return;
|
|
6659
7944
|
}
|
|
7945
|
+
if (!canPromptInteractively()) {
|
|
7946
|
+
displayManualSupabaseInstructions();
|
|
7947
|
+
await writeSupabaseEnvFile(projectDir, backend, "");
|
|
7948
|
+
return;
|
|
7949
|
+
}
|
|
6660
7950
|
const mode = await select({
|
|
6661
7951
|
message: "Supabase setup: choose mode",
|
|
6662
7952
|
options: [{
|
|
@@ -6846,6 +8136,11 @@ async function setupTurso(config, cliInput) {
|
|
|
6846
8136
|
displayManualSetupInstructions$1();
|
|
6847
8137
|
return;
|
|
6848
8138
|
}
|
|
8139
|
+
if (!canPromptInteractively()) {
|
|
8140
|
+
await writeEnvFile$1(projectDir, backend);
|
|
8141
|
+
displayManualSetupInstructions$1();
|
|
8142
|
+
return;
|
|
8143
|
+
}
|
|
6849
8144
|
const mode = await select({
|
|
6850
8145
|
message: "Turso setup: choose mode",
|
|
6851
8146
|
options: [{
|
|
@@ -6968,6 +8263,12 @@ async function setupUpstash(config, cliInput) {
|
|
|
6968
8263
|
displayManualSetupInstructions();
|
|
6969
8264
|
return;
|
|
6970
8265
|
}
|
|
8266
|
+
if (!canPromptInteractively()) {
|
|
8267
|
+
log.info("Upstash Redis manual setup selected (non-interactive mode)");
|
|
8268
|
+
await writeEnvFile(projectDir, backend);
|
|
8269
|
+
displayManualSetupInstructions();
|
|
8270
|
+
return;
|
|
8271
|
+
}
|
|
6971
8272
|
const mode = await select({
|
|
6972
8273
|
message: "Upstash Redis setup: choose mode",
|
|
6973
8274
|
options: [{
|
|
@@ -7176,6 +8477,10 @@ async function displayPostInstallInstructions(config) {
|
|
|
7176
8477
|
displayGoInstructions(config);
|
|
7177
8478
|
return;
|
|
7178
8479
|
}
|
|
8480
|
+
if (ecosystem === "java") {
|
|
8481
|
+
displayJavaInstructions(config);
|
|
8482
|
+
return;
|
|
8483
|
+
}
|
|
7179
8484
|
if (ecosystem === "python") {
|
|
7180
8485
|
displayPythonInstructions(config);
|
|
7181
8486
|
return;
|
|
@@ -7445,6 +8750,8 @@ function displayRustInstructions(config) {
|
|
|
7445
8750
|
moka: "Moka",
|
|
7446
8751
|
redis: "Redis"
|
|
7447
8752
|
}[rustCaching] || rustCaching}\n`;
|
|
8753
|
+
const { rustAuth } = config;
|
|
8754
|
+
if (rustAuth && rustAuth !== "none") output += `${pc.cyan("•")} Auth: ${{ oauth2: "OAuth2" }[rustAuth] || rustAuth}\n`;
|
|
7448
8755
|
output += `\n${pc.bold("Common Cargo commands:")}\n`;
|
|
7449
8756
|
output += `${pc.cyan("•")} Build: cargo build\n`;
|
|
7450
8757
|
output += `${pc.cyan("•")} Run: cargo run\n`;
|
|
@@ -7458,7 +8765,7 @@ function displayRustInstructions(config) {
|
|
|
7458
8765
|
consola$1.box(output);
|
|
7459
8766
|
}
|
|
7460
8767
|
function displayGoInstructions(config) {
|
|
7461
|
-
const { relativePath, depsInstalled, goWebFramework, goOrm, goApi, goCli, goLogging } = config;
|
|
8768
|
+
const { relativePath, depsInstalled, goWebFramework, goOrm, goApi, goCli, goLogging, goAuth } = config;
|
|
7462
8769
|
const cdCmd = `cd ${relativePath}`;
|
|
7463
8770
|
let output = `${pc.bold("Next steps")}\n${pc.cyan("1.")} ${cdCmd}\n`;
|
|
7464
8771
|
let stepCounter = 2;
|
|
@@ -7486,6 +8793,10 @@ function displayGoInstructions(config) {
|
|
|
7486
8793
|
zerolog: "Zerolog",
|
|
7487
8794
|
slog: "slog"
|
|
7488
8795
|
}[goLogging] || goLogging}\n`;
|
|
8796
|
+
if (goAuth && goAuth !== "none") output += `${pc.cyan("•")} Auth: ${{
|
|
8797
|
+
casbin: "Casbin",
|
|
8798
|
+
jwt: "golang-jwt"
|
|
8799
|
+
}[goAuth] || goAuth}\n`;
|
|
7489
8800
|
output += `\n${pc.bold("Common Go commands:")}\n`;
|
|
7490
8801
|
output += `${pc.cyan("•")} Build: go build ./...\n`;
|
|
7491
8802
|
output += `${pc.cyan("•")} Run: go run cmd/server/main.go\n`;
|
|
@@ -7501,6 +8812,162 @@ function displayGoInstructions(config) {
|
|
|
7501
8812
|
output += pc.dim("Your star helps other developers discover the project.");
|
|
7502
8813
|
consola$1.box(output);
|
|
7503
8814
|
}
|
|
8815
|
+
const JAVA_GROUP_ID = "com.example";
|
|
8816
|
+
const JAVA_RESERVED_WORDS = new Set([
|
|
8817
|
+
"abstract",
|
|
8818
|
+
"assert",
|
|
8819
|
+
"boolean",
|
|
8820
|
+
"break",
|
|
8821
|
+
"byte",
|
|
8822
|
+
"case",
|
|
8823
|
+
"catch",
|
|
8824
|
+
"char",
|
|
8825
|
+
"class",
|
|
8826
|
+
"const",
|
|
8827
|
+
"continue",
|
|
8828
|
+
"default",
|
|
8829
|
+
"do",
|
|
8830
|
+
"double",
|
|
8831
|
+
"else",
|
|
8832
|
+
"enum",
|
|
8833
|
+
"extends",
|
|
8834
|
+
"final",
|
|
8835
|
+
"finally",
|
|
8836
|
+
"float",
|
|
8837
|
+
"for",
|
|
8838
|
+
"goto",
|
|
8839
|
+
"if",
|
|
8840
|
+
"implements",
|
|
8841
|
+
"import",
|
|
8842
|
+
"instanceof",
|
|
8843
|
+
"int",
|
|
8844
|
+
"interface",
|
|
8845
|
+
"long",
|
|
8846
|
+
"native",
|
|
8847
|
+
"new",
|
|
8848
|
+
"non-sealed",
|
|
8849
|
+
"package",
|
|
8850
|
+
"private",
|
|
8851
|
+
"protected",
|
|
8852
|
+
"public",
|
|
8853
|
+
"return",
|
|
8854
|
+
"sealed",
|
|
8855
|
+
"short",
|
|
8856
|
+
"static",
|
|
8857
|
+
"strictfp",
|
|
8858
|
+
"super",
|
|
8859
|
+
"switch",
|
|
8860
|
+
"synchronized",
|
|
8861
|
+
"this",
|
|
8862
|
+
"throw",
|
|
8863
|
+
"throws",
|
|
8864
|
+
"transient",
|
|
8865
|
+
"try",
|
|
8866
|
+
"void",
|
|
8867
|
+
"volatile",
|
|
8868
|
+
"while",
|
|
8869
|
+
"yield",
|
|
8870
|
+
"record",
|
|
8871
|
+
"permits",
|
|
8872
|
+
"true",
|
|
8873
|
+
"false",
|
|
8874
|
+
"null"
|
|
8875
|
+
]);
|
|
8876
|
+
function sanitizeJavaPackageSuffix(projectName) {
|
|
8877
|
+
const alphanumericOnly = projectName.trim().toLowerCase().replace(/[^a-z0-9]+/g, "");
|
|
8878
|
+
const withLetterPrefix = /^[a-z]/.test(alphanumericOnly) ? alphanumericOnly : `app${alphanumericOnly}`;
|
|
8879
|
+
return (JAVA_RESERVED_WORDS.has(withLetterPrefix) ? `app${withLetterPrefix}` : withLetterPrefix) || "app";
|
|
8880
|
+
}
|
|
8881
|
+
function getJavaMainClass(projectName) {
|
|
8882
|
+
return `${JAVA_GROUP_ID}.${sanitizeJavaPackageSuffix(projectName)}.Application`;
|
|
8883
|
+
}
|
|
8884
|
+
function getJavaMainSourcePath(projectName) {
|
|
8885
|
+
return `src/main/java/${getJavaMainClass(projectName).replace(/\./g, "/")}.java`;
|
|
8886
|
+
}
|
|
8887
|
+
function displayJavaInstructions(config) {
|
|
8888
|
+
const { projectName, relativePath, depsInstalled, javaWebFramework, javaBuildTool, javaOrm, javaAuth, javaLibraries, javaTestingLibraries } = config;
|
|
8889
|
+
const cdCmd = `cd ${relativePath}`;
|
|
8890
|
+
const isSpringBoot = javaWebFramework === "spring-boot" && javaBuildTool !== "none";
|
|
8891
|
+
const rawJavaLibraries = isSpringBoot ? javaLibraries.filter((library) => library !== "none") : [];
|
|
8892
|
+
const rawJavaLibrarySet = new Set(rawJavaLibraries);
|
|
8893
|
+
const jpaRequiredJavaLibraries = new Set(["flyway", "liquibase"]);
|
|
8894
|
+
const effectiveJavaLibraries = [];
|
|
8895
|
+
for (const library of rawJavaLibraries) {
|
|
8896
|
+
if (jpaRequiredJavaLibraries.has(library) && javaOrm !== "spring-data-jpa") continue;
|
|
8897
|
+
if (library === "liquibase" && rawJavaLibrarySet.has("flyway")) continue;
|
|
8898
|
+
effectiveJavaLibraries.push(library);
|
|
8899
|
+
}
|
|
8900
|
+
const effectiveJavaTestingLibraries = javaBuildTool === "none" ? [] : javaTestingLibraries.filter((library) => library !== "none");
|
|
8901
|
+
const buildToolCommand = javaBuildTool === "none" ? null : javaBuildTool === "gradle" ? process.platform === "win32" ? "gradlew.bat" : "./gradlew" : process.platform === "win32" ? "mvnw.cmd" : "./mvnw";
|
|
8902
|
+
const runCommand = buildToolCommand ? isSpringBoot ? javaBuildTool === "gradle" ? `${buildToolCommand} bootRun` : `${buildToolCommand} spring-boot:run` : javaBuildTool === "gradle" ? `${buildToolCommand} run` : `${buildToolCommand} exec:java` : null;
|
|
8903
|
+
const packageCommand = buildToolCommand ? javaBuildTool === "gradle" ? `${buildToolCommand} build` : `${buildToolCommand} package` : null;
|
|
8904
|
+
const sourceCompileCommand = buildToolCommand ? null : `javac -d out ${getJavaMainSourcePath(projectName)}`;
|
|
8905
|
+
const sourceRunCommand = buildToolCommand ? null : `java -cp out ${getJavaMainClass(projectName)}`;
|
|
8906
|
+
let output = `${pc.bold("Next steps")}\n${pc.cyan("1.")} ${cdCmd}\n`;
|
|
8907
|
+
let stepCounter = 2;
|
|
8908
|
+
if (!depsInstalled && buildToolCommand && effectiveJavaTestingLibraries.length > 0) output += `${pc.cyan(`${stepCounter++}.`)} ${buildToolCommand} test\n`;
|
|
8909
|
+
if (runCommand) output += `${pc.cyan(`${stepCounter++}.`)} ${runCommand}\n`;
|
|
8910
|
+
else if (sourceCompileCommand && sourceRunCommand) {
|
|
8911
|
+
output += `${pc.cyan(`${stepCounter++}.`)} ${sourceCompileCommand}\n`;
|
|
8912
|
+
output += `${pc.cyan(`${stepCounter++}.`)} ${sourceRunCommand}\n`;
|
|
8913
|
+
} else output += `${pc.cyan(`${stepCounter++}.`)} Add Maven or Gradle, then run the app\n`;
|
|
8914
|
+
output += `\n${pc.bold("Your Java project includes:")}\n`;
|
|
8915
|
+
if (isSpringBoot) output += `${pc.cyan("•")} Web Framework: ${{ "spring-boot": "Spring Boot" }[javaWebFramework] || javaWebFramework}\n`;
|
|
8916
|
+
else output += `${pc.cyan("•")} Scaffold: Plain Java\n`;
|
|
8917
|
+
if (javaBuildTool && javaBuildTool !== "none") output += `${pc.cyan("•")} Build Tool: ${{
|
|
8918
|
+
maven: "Maven Wrapper",
|
|
8919
|
+
gradle: "Gradle Wrapper"
|
|
8920
|
+
}[javaBuildTool] || javaBuildTool}\n`;
|
|
8921
|
+
else output += `${pc.cyan("•")} Build Tool: None\n`;
|
|
8922
|
+
if (isSpringBoot && javaOrm && javaOrm !== "none") output += `${pc.cyan("•")} ORM: ${{ "spring-data-jpa": "Spring Data JPA" }[javaOrm] || javaOrm}\n`;
|
|
8923
|
+
if (isSpringBoot && javaAuth && javaAuth !== "none") output += `${pc.cyan("•")} Auth: ${{ "spring-security": "Spring Security" }[javaAuth] || javaAuth}\n`;
|
|
8924
|
+
if (effectiveJavaLibraries.length > 0) {
|
|
8925
|
+
const libraryNames = {
|
|
8926
|
+
"spring-actuator": "Spring Actuator",
|
|
8927
|
+
"spring-validation": "Spring Validation",
|
|
8928
|
+
flyway: "Flyway",
|
|
8929
|
+
liquibase: "Liquibase",
|
|
8930
|
+
"springdoc-openapi": "Springdoc OpenAPI",
|
|
8931
|
+
lombok: "Lombok",
|
|
8932
|
+
mapstruct: "MapStruct",
|
|
8933
|
+
caffeine: "Caffeine"
|
|
8934
|
+
};
|
|
8935
|
+
const libraryList = effectiveJavaLibraries.map((library) => libraryNames[library] || library).join(", ");
|
|
8936
|
+
output += `${pc.cyan("•")} Libraries: ${libraryList}\n`;
|
|
8937
|
+
}
|
|
8938
|
+
if (effectiveJavaTestingLibraries.length > 0) {
|
|
8939
|
+
const testingNames = {
|
|
8940
|
+
junit5: "JUnit 5",
|
|
8941
|
+
mockito: "Mockito",
|
|
8942
|
+
testcontainers: "Testcontainers",
|
|
8943
|
+
assertj: "AssertJ",
|
|
8944
|
+
"rest-assured": "REST Assured",
|
|
8945
|
+
wiremock: "WireMock",
|
|
8946
|
+
awaitility: "Awaitility",
|
|
8947
|
+
archunit: "ArchUnit",
|
|
8948
|
+
jqwik: "jqwik"
|
|
8949
|
+
};
|
|
8950
|
+
const testingList = effectiveJavaTestingLibraries.map((library) => testingNames[library] || library).join(", ");
|
|
8951
|
+
output += `${pc.cyan("•")} Testing: ${testingList}\n`;
|
|
8952
|
+
}
|
|
8953
|
+
output += `\n${pc.bold("Common Java commands:")}\n`;
|
|
8954
|
+
if (buildToolCommand && runCommand && packageCommand) {
|
|
8955
|
+
if (effectiveJavaTestingLibraries.length > 0) output += `${pc.cyan("•")} Test: ${buildToolCommand} test\n`;
|
|
8956
|
+
output += `${pc.cyan("•")} Run: ${runCommand}\n`;
|
|
8957
|
+
output += `${pc.cyan("•")} Package: ${packageCommand}\n`;
|
|
8958
|
+
} else if (sourceCompileCommand && sourceRunCommand) {
|
|
8959
|
+
output += `${pc.cyan("•")} Compile: ${sourceCompileCommand}\n`;
|
|
8960
|
+
output += `${pc.cyan("•")} Run: ${sourceRunCommand}\n`;
|
|
8961
|
+
} else output += `${pc.cyan("•")} Configure Maven or Gradle before running build commands\n`;
|
|
8962
|
+
if (isSpringBoot) {
|
|
8963
|
+
output += `\n${pc.bold("Your project will be available at:")}\n`;
|
|
8964
|
+
output += `${pc.cyan("•")} API: http://localhost:8080\n`;
|
|
8965
|
+
}
|
|
8966
|
+
output += `\n${pc.bold("Enjoying Better Fullstack?")} Help us grow — star the repo!\n`;
|
|
8967
|
+
output += `${pc.cyan("https://github.com/Marve10s/Better-Fullstack")}\n`;
|
|
8968
|
+
output += pc.dim("Your star helps other developers discover the project.");
|
|
8969
|
+
consola$1.box(output);
|
|
8970
|
+
}
|
|
7504
8971
|
function displayPythonInstructions(config) {
|
|
7505
8972
|
const { relativePath, depsInstalled, pythonWebFramework, pythonOrm, pythonValidation, pythonAi, pythonTaskQueue, pythonQuality } = config;
|
|
7506
8973
|
const cdCmd = `cd ${relativePath}`;
|
|
@@ -7521,7 +8988,8 @@ function displayPythonInstructions(config) {
|
|
|
7521
8988
|
}[pythonWebFramework] || pythonWebFramework}\n`;
|
|
7522
8989
|
if (pythonOrm && pythonOrm !== "none") output += `${pc.cyan("•")} ORM: ${{
|
|
7523
8990
|
sqlalchemy: "SQLAlchemy",
|
|
7524
|
-
sqlmodel: "SQLModel"
|
|
8991
|
+
sqlmodel: "SQLModel",
|
|
8992
|
+
"tortoise-orm": "Tortoise ORM"
|
|
7525
8993
|
}[pythonOrm] || pythonOrm}\n`;
|
|
7526
8994
|
if (pythonValidation && pythonValidation !== "none") output += `${pc.cyan("•")} Validation: ${{ pydantic: "Pydantic" }[pythonValidation] || pythonValidation}\n`;
|
|
7527
8995
|
if (pythonAi && pythonAi.length > 0 && !pythonAi.includes("none")) {
|
|
@@ -7566,6 +9034,7 @@ async function createProject(options, cliInput = {}) {
|
|
|
7566
9034
|
if (!result.success || !result.tree) throw new Error(result.error || "Failed to generate project templates");
|
|
7567
9035
|
await writeTreeToFilesystem(result.tree, projectDir);
|
|
7568
9036
|
await setPackageManagerVersion(projectDir, options.packageManager);
|
|
9037
|
+
await ensurePackageManagerProjectFiles(projectDir, options.packageManager);
|
|
7569
9038
|
if (!isConvex && options.database !== "none") await setupDatabase(options, cliInput);
|
|
7570
9039
|
if (options.addons.length > 0 && options.addons[0] !== "none") await setupAddons(options);
|
|
7571
9040
|
await applyDependencyVersionChannel(projectDir, options.versionChannel);
|
|
@@ -7579,6 +9048,8 @@ async function createProject(options, cliInput = {}) {
|
|
|
7579
9048
|
if (options.install && options.ecosystem === "rust") await runCargoBuild({ projectDir });
|
|
7580
9049
|
if (options.install && options.ecosystem === "python") await runUvSync({ projectDir });
|
|
7581
9050
|
if (options.install && options.ecosystem === "go") await runGoModTidy({ projectDir });
|
|
9051
|
+
if (options.install && options.ecosystem === "java" && options.javaBuildTool !== "none") if (options.javaBuildTool === "gradle") await runGradleTests({ projectDir });
|
|
9052
|
+
else await runMavenTests({ projectDir });
|
|
7582
9053
|
await initializeGit(projectDir, options.git);
|
|
7583
9054
|
if (!isSilent()) await displayPostInstallInstructions({
|
|
7584
9055
|
...options,
|
|
@@ -7610,12 +9081,18 @@ async function setPackageManagerVersion(projectDir, packageManager) {
|
|
|
7610
9081
|
await fs.writeJson(pkgJsonPath, pkgJson, { spaces: 2 });
|
|
7611
9082
|
}
|
|
7612
9083
|
}
|
|
9084
|
+
async function ensurePackageManagerProjectFiles(projectDir, packageManager) {
|
|
9085
|
+
if (packageManager !== "yarn") return;
|
|
9086
|
+
const yarnLockPath = path.join(projectDir, "yarn.lock");
|
|
9087
|
+
if (await fs.pathExists(yarnLockPath)) return;
|
|
9088
|
+
await fs.writeFile(yarnLockPath, "");
|
|
9089
|
+
}
|
|
7613
9090
|
|
|
7614
9091
|
//#endregion
|
|
7615
9092
|
//#region src/helpers/core/command-handlers.ts
|
|
7616
9093
|
function shouldPromptForVersionChannel(input) {
|
|
7617
9094
|
if (input.yes || input.versionChannel !== void 0 || isSilent()) return false;
|
|
7618
|
-
return
|
|
9095
|
+
return canPromptInteractively();
|
|
7619
9096
|
}
|
|
7620
9097
|
async function createProjectHandler(input, options = {}) {
|
|
7621
9098
|
const { silent = false } = options;
|
|
@@ -7707,6 +9184,7 @@ async function createProjectHandler(input, options = {}) {
|
|
|
7707
9184
|
rustLogging: "none",
|
|
7708
9185
|
rustErrorHandling: "none",
|
|
7709
9186
|
rustCaching: "none",
|
|
9187
|
+
rustAuth: "none",
|
|
7710
9188
|
cms: "none",
|
|
7711
9189
|
caching: "none",
|
|
7712
9190
|
i18n: "none",
|
|
@@ -7727,6 +9205,13 @@ async function createProjectHandler(input, options = {}) {
|
|
|
7727
9205
|
goApi: "none",
|
|
7728
9206
|
goCli: "none",
|
|
7729
9207
|
goLogging: "none",
|
|
9208
|
+
goAuth: "none",
|
|
9209
|
+
javaWebFramework: "none",
|
|
9210
|
+
javaBuildTool: "none",
|
|
9211
|
+
javaOrm: "none",
|
|
9212
|
+
javaAuth: "none",
|
|
9213
|
+
javaLibraries: [],
|
|
9214
|
+
javaTestingLibraries: [],
|
|
7730
9215
|
aiDocs: []
|
|
7731
9216
|
},
|
|
7732
9217
|
reproducibleCommand: "",
|
|
@@ -7991,93 +9476,13 @@ function displaySponsorsBox(sponsors$1) {
|
|
|
7991
9476
|
|
|
7992
9477
|
//#endregion
|
|
7993
9478
|
//#region src/index.ts
|
|
9479
|
+
const OPTION_ENTRY_COUNT = Object.values(types_exports.OPTION_CATEGORY_METADATA).reduce((sum, metadata) => sum + metadata.options.length, 0);
|
|
7994
9480
|
const router = os.router({
|
|
7995
9481
|
create: os.meta({
|
|
7996
|
-
description:
|
|
9482
|
+
description: `Scaffold a new Better Fullstack project from ${OPTION_ENTRY_COUNT} compatible stack options`,
|
|
7997
9483
|
default: true,
|
|
7998
9484
|
negateBooleans: true
|
|
7999
|
-
}).input(
|
|
8000
|
-
template: types_exports.TemplateSchema.optional().describe("Use a predefined template"),
|
|
8001
|
-
yes: z.boolean().optional().default(false).describe("Use default configuration"),
|
|
8002
|
-
yolo: z.boolean().optional().default(false).describe("(WARNING - NOT RECOMMENDED) Bypass validations and compatibility checks"),
|
|
8003
|
-
verbose: z.boolean().optional().default(false).describe("Show detailed result information"),
|
|
8004
|
-
dryRun: z.boolean().optional().default(false).describe("Preview generated file tree without writing to disk"),
|
|
8005
|
-
ecosystem: types_exports.EcosystemSchema.optional().describe("Language ecosystem (typescript, rust, python, or go)"),
|
|
8006
|
-
database: types_exports.DatabaseSchema.optional(),
|
|
8007
|
-
orm: types_exports.ORMSchema.optional(),
|
|
8008
|
-
auth: types_exports.AuthSchema.optional(),
|
|
8009
|
-
payments: types_exports.PaymentsSchema.optional(),
|
|
8010
|
-
email: types_exports.EmailSchema.optional(),
|
|
8011
|
-
fileUpload: types_exports.FileUploadSchema.optional(),
|
|
8012
|
-
effect: types_exports.EffectSchema.optional(),
|
|
8013
|
-
stateManagement: types_exports.StateManagementSchema.optional(),
|
|
8014
|
-
validation: types_exports.ValidationSchema.optional(),
|
|
8015
|
-
forms: types_exports.FormsSchema.optional(),
|
|
8016
|
-
testing: types_exports.TestingSchema.optional(),
|
|
8017
|
-
ai: types_exports.AISchema.optional(),
|
|
8018
|
-
realtime: types_exports.RealtimeSchema.optional(),
|
|
8019
|
-
jobQueue: types_exports.JobQueueSchema.optional(),
|
|
8020
|
-
animation: types_exports.AnimationSchema.optional(),
|
|
8021
|
-
logging: types_exports.LoggingSchema.optional(),
|
|
8022
|
-
observability: types_exports.ObservabilitySchema.optional(),
|
|
8023
|
-
featureFlags: types_exports.FeatureFlagsSchema.optional().describe("Feature flags provider"),
|
|
8024
|
-
analytics: types_exports.AnalyticsSchema.optional().describe("Privacy-focused analytics"),
|
|
8025
|
-
cms: types_exports.CMSSchema.optional().describe("Headless CMS solution"),
|
|
8026
|
-
caching: types_exports.CachingSchema.optional().describe("Caching solution"),
|
|
8027
|
-
i18n: types_exports.I18nSchema.optional().describe("Internationalization (i18n) library"),
|
|
8028
|
-
search: types_exports.SearchSchema.optional().describe("Search engine solution"),
|
|
8029
|
-
fileStorage: types_exports.FileStorageSchema.optional().describe("File storage solution (S3, R2)"),
|
|
8030
|
-
frontend: z.array(types_exports.FrontendSchema).optional(),
|
|
8031
|
-
astroIntegration: types_exports.AstroIntegrationSchema.optional().describe("Astro UI framework integration (react, vue, svelte, solid)"),
|
|
8032
|
-
addons: z.array(types_exports.AddonsSchema).optional(),
|
|
8033
|
-
examples: z.array(types_exports.ExamplesSchema).optional(),
|
|
8034
|
-
git: z.boolean().optional(),
|
|
8035
|
-
packageManager: types_exports.PackageManagerSchema.optional(),
|
|
8036
|
-
install: z.boolean().optional(),
|
|
8037
|
-
versionChannel: types_exports.VersionChannelSchema.optional().describe("Dependency version channel (stable, latest, beta)"),
|
|
8038
|
-
dbSetup: types_exports.DatabaseSetupSchema.optional(),
|
|
8039
|
-
backend: types_exports.BackendSchema.optional(),
|
|
8040
|
-
runtime: types_exports.RuntimeSchema.optional(),
|
|
8041
|
-
api: types_exports.APISchema.optional(),
|
|
8042
|
-
cssFramework: types_exports.CSSFrameworkSchema.optional(),
|
|
8043
|
-
uiLibrary: types_exports.UILibrarySchema.optional(),
|
|
8044
|
-
shadcnBase: types_exports.ShadcnBaseSchema.optional().describe("shadcn/ui headless library (radix, base)"),
|
|
8045
|
-
shadcnStyle: types_exports.ShadcnStyleSchema.optional().describe("shadcn/ui visual style (vega, nova, maia, lyra, mira)"),
|
|
8046
|
-
shadcnIconLibrary: types_exports.ShadcnIconLibrarySchema.optional().describe("shadcn/ui icon library (lucide, tabler, hugeicons, phosphor, remixicon)"),
|
|
8047
|
-
shadcnColorTheme: types_exports.ShadcnColorThemeSchema.optional().describe("shadcn/ui color theme (neutral, blue, violet, etc.)"),
|
|
8048
|
-
shadcnBaseColor: types_exports.ShadcnBaseColorSchema.optional().describe("shadcn/ui base neutral color (neutral, stone, zinc, gray)"),
|
|
8049
|
-
shadcnFont: types_exports.ShadcnFontSchema.optional().describe("shadcn/ui font (inter, geist, figtree, etc.)"),
|
|
8050
|
-
shadcnRadius: types_exports.ShadcnRadiusSchema.optional().describe("shadcn/ui border radius (default, none, small, medium, large)"),
|
|
8051
|
-
webDeploy: types_exports.WebDeploySchema.optional(),
|
|
8052
|
-
serverDeploy: types_exports.ServerDeploySchema.optional(),
|
|
8053
|
-
directoryConflict: types_exports.DirectoryConflictSchema.optional(),
|
|
8054
|
-
renderTitle: z.boolean().optional(),
|
|
8055
|
-
disableAnalytics: z.boolean().optional().default(false).describe("Disable analytics"),
|
|
8056
|
-
manualDb: z.boolean().optional().default(false).describe("Skip automatic/manual database setup prompt and use manual setup"),
|
|
8057
|
-
rustWebFramework: types_exports.RustWebFrameworkSchema.optional().describe("Rust web framework (axum, actix-web)"),
|
|
8058
|
-
rustFrontend: types_exports.RustFrontendSchema.optional().describe("Rust WASM frontend (leptos, dioxus)"),
|
|
8059
|
-
rustOrm: types_exports.RustOrmSchema.optional().describe("Rust ORM/database (sea-orm, sqlx)"),
|
|
8060
|
-
rustApi: types_exports.RustApiSchema.optional().describe("Rust API layer (tonic, async-graphql)"),
|
|
8061
|
-
rustCli: types_exports.RustCliSchema.optional().describe("Rust CLI tools (clap, ratatui)"),
|
|
8062
|
-
rustLibraries: z.array(types_exports.RustLibrariesSchema).optional().describe("Rust core libraries"),
|
|
8063
|
-
rustLogging: types_exports.RustLoggingSchema.optional().describe("Rust logging (tracing, env-logger)"),
|
|
8064
|
-
rustErrorHandling: types_exports.RustErrorHandlingSchema.optional().describe("Rust error handling (anyhow-thiserror, eyre)"),
|
|
8065
|
-
rustCaching: types_exports.RustCachingSchema.optional().describe("Rust caching (moka, redis)"),
|
|
8066
|
-
pythonWebFramework: types_exports.PythonWebFrameworkSchema.optional().describe("Python web framework (fastapi, django)"),
|
|
8067
|
-
pythonOrm: types_exports.PythonOrmSchema.optional().describe("Python ORM/database (sqlalchemy, sqlmodel)"),
|
|
8068
|
-
pythonValidation: types_exports.PythonValidationSchema.optional().describe("Python validation (pydantic)"),
|
|
8069
|
-
pythonAi: z.array(types_exports.PythonAiSchema).optional().describe("Python AI/ML frameworks"),
|
|
8070
|
-
pythonAuth: types_exports.PythonAuthSchema.optional().describe("Python auth library (authlib, jwt)"),
|
|
8071
|
-
pythonTaskQueue: types_exports.PythonTaskQueueSchema.optional().describe("Python task queue (celery)"),
|
|
8072
|
-
pythonGraphql: types_exports.PythonGraphqlSchema.optional().describe("Python GraphQL framework (strawberry)"),
|
|
8073
|
-
pythonQuality: types_exports.PythonQualitySchema.optional().describe("Python code quality (ruff)"),
|
|
8074
|
-
goWebFramework: types_exports.GoWebFrameworkSchema.optional().describe("Go web framework (gin, echo, fiber)"),
|
|
8075
|
-
goOrm: types_exports.GoOrmSchema.optional().describe("Go ORM/database (gorm, sqlc)"),
|
|
8076
|
-
goApi: types_exports.GoApiSchema.optional().describe("Go API layer (grpc-go)"),
|
|
8077
|
-
goCli: types_exports.GoCliSchema.optional().describe("Go CLI tools (cobra, bubbletea)"),
|
|
8078
|
-
goLogging: types_exports.GoLoggingSchema.optional().describe("Go logging (zap, zerolog, slog)"),
|
|
8079
|
-
aiDocs: z.array(types_exports.AiDocsSchema).optional().describe("AI documentation files (claude-md, agents-md, cursorrules)")
|
|
8080
|
-
})])).handler(async ({ input }) => {
|
|
9485
|
+
}).input(CreateCommandInputSchema).handler(async ({ input }) => {
|
|
8081
9486
|
const [projectName, options] = input;
|
|
8082
9487
|
const result = await createProjectHandler({
|
|
8083
9488
|
projectName,
|
|
@@ -8309,6 +9714,7 @@ async function createVirtual(options) {
|
|
|
8309
9714
|
rustLogging: options.rustLogging || (options.ecosystem === "rust" ? "tracing" : "none"),
|
|
8310
9715
|
rustErrorHandling: options.rustErrorHandling || (options.ecosystem === "rust" ? "anyhow-thiserror" : "none"),
|
|
8311
9716
|
rustCaching: options.rustCaching || "none",
|
|
9717
|
+
rustAuth: options.rustAuth || "none",
|
|
8312
9718
|
pythonWebFramework: options.pythonWebFramework || "none",
|
|
8313
9719
|
pythonOrm: options.pythonOrm || "none",
|
|
8314
9720
|
pythonValidation: options.pythonValidation || "none",
|
|
@@ -8322,6 +9728,13 @@ async function createVirtual(options) {
|
|
|
8322
9728
|
goApi: options.goApi || "none",
|
|
8323
9729
|
goCli: options.goCli || "none",
|
|
8324
9730
|
goLogging: options.goLogging || "none",
|
|
9731
|
+
goAuth: options.goAuth || "none",
|
|
9732
|
+
javaWebFramework: options.javaWebFramework || (options.ecosystem === "java" ? "spring-boot" : "none"),
|
|
9733
|
+
javaBuildTool: options.javaBuildTool || (options.ecosystem === "java" ? "maven" : "none"),
|
|
9734
|
+
javaOrm: options.javaOrm || "none",
|
|
9735
|
+
javaAuth: options.javaAuth || "none",
|
|
9736
|
+
javaLibraries: options.javaLibraries || [],
|
|
9737
|
+
javaTestingLibraries: options.javaTestingLibraries || (options.ecosystem === "java" ? ["junit5"] : []),
|
|
8325
9738
|
aiDocs: options.aiDocs || ["claude-md"]
|
|
8326
9739
|
},
|
|
8327
9740
|
templates: EMBEDDED_TEMPLATES$1
|