create-better-fullstack 2.1.0 → 2.1.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-better-fullstack",
3
- "version": "2.1.0",
3
+ "version": "2.1.2",
4
4
  "description": "Scaffold production-ready fullstack apps in seconds. Pick your stack from 425 options — the CLI wires everything together.",
5
5
  "keywords": [
6
6
  "algolia",
@@ -128,8 +128,8 @@
128
128
  "prepublishOnly": "npm run build"
129
129
  },
130
130
  "dependencies": {
131
- "@better-fullstack/template-generator": "^2.1.0",
132
- "@better-fullstack/types": "^2.1.0",
131
+ "@better-fullstack/template-generator": "^2.1.2",
132
+ "@better-fullstack/types": "^2.1.2",
133
133
  "@clack/core": "^0.5.0",
134
134
  "@clack/prompts": "^1.6.0",
135
135
  "@orpc/server": "^1.14.6",
@@ -1,6 +0,0 @@
1
- #!/usr/bin/env node
2
- import "./bts-config-InNcw1aJ.mjs";
3
- import "./errors-ns_o2OKg.mjs";
4
- import { t as setupAddons } from "./addons-setup-uSvqHagW.mjs";
5
-
6
- export { setupAddons };
@@ -1,86 +0,0 @@
1
- #!/usr/bin/env node
2
- import { cancel } from "@clack/prompts";
3
- import pc from "picocolors";
4
- import { AsyncLocalStorage } from "node:async_hooks";
5
- import consola from "consola";
6
-
7
- //#region src/utils/context.ts
8
- const cliStorage = new AsyncLocalStorage();
9
- function defaultContext() {
10
- return {
11
- navigation: {
12
- isFirstPrompt: false,
13
- lastPromptShownUI: false
14
- },
15
- silent: false
16
- };
17
- }
18
- function getContext() {
19
- const ctx = cliStorage.getStore();
20
- if (!ctx) return defaultContext();
21
- return ctx;
22
- }
23
- function tryGetContext() {
24
- return cliStorage.getStore();
25
- }
26
- function isSilent() {
27
- return getContext().silent;
28
- }
29
- function isFirstPrompt() {
30
- return getContext().navigation.isFirstPrompt;
31
- }
32
- function didLastPromptShowUI() {
33
- return getContext().navigation.lastPromptShownUI;
34
- }
35
- function setIsFirstPrompt(value) {
36
- const ctx = tryGetContext();
37
- if (ctx) ctx.navigation.isFirstPrompt = value;
38
- }
39
- function setLastPromptShownUI(value) {
40
- const ctx = tryGetContext();
41
- if (ctx) ctx.navigation.lastPromptShownUI = value;
42
- }
43
- async function runWithContextAsync(options, fn) {
44
- const ctx = {
45
- navigation: {
46
- isFirstPrompt: false,
47
- lastPromptShownUI: false
48
- },
49
- silent: options.silent ?? false
50
- };
51
- return cliStorage.run(ctx, fn);
52
- }
53
-
54
- //#endregion
55
- //#region src/utils/errors.ts
56
- var UserCancelledError = class extends Error {
57
- constructor(message = "Operation cancelled") {
58
- super(message);
59
- this.name = "UserCancelledError";
60
- }
61
- };
62
- var CLIError = class extends Error {
63
- constructor(message) {
64
- super(message);
65
- this.name = "CLIError";
66
- }
67
- };
68
- function exitWithError(message) {
69
- if (isSilent()) throw new CLIError(message);
70
- consola.error(pc.red(message));
71
- process.exit(1);
72
- }
73
- function exitCancelled(message = "Operation cancelled") {
74
- if (isSilent()) throw new UserCancelledError(message);
75
- cancel(pc.red(message));
76
- process.exit(1);
77
- }
78
- function handleError(error, fallbackMessage) {
79
- const message = error instanceof Error ? error.message : fallbackMessage || String(error);
80
- if (isSilent()) throw error instanceof Error ? error : new Error(message);
81
- consola.error(pc.red(message));
82
- process.exit(1);
83
- }
84
-
85
- //#endregion
86
- export { handleError as a, isSilent as c, setLastPromptShownUI as d, exitWithError as i, runWithContextAsync as l, UserCancelledError as n, didLastPromptShowUI as o, exitCancelled as r, isFirstPrompt as s, CLIError as t, setIsFirstPrompt as u };
@@ -1,5 +0,0 @@
1
- #!/usr/bin/env node
2
- import "./bts-config-InNcw1aJ.mjs";
3
- import { n as startMcpServer, t as getMcpGraphPreview } from "./mcp-entry.mjs";
4
-
5
- export { startMcpServer };
@@ -1,10 +0,0 @@
1
- #!/usr/bin/env node
2
- import "./bts-config-InNcw1aJ.mjs";
3
- import { a as docs, c as sponsors, i as createBtsCli, l as telemetry, n as builder, o as history, r as create, s as router, t as add } from "./run-Cqy-n1iT.mjs";
4
- import "./render-title-zvyKC1ej.mjs";
5
- import "./errors-ns_o2OKg.mjs";
6
- import "./addons-setup-uSvqHagW.mjs";
7
- import "./install-dependencies-CDjTNvIV.mjs";
8
- import "./generated-checks-CUhFFfVo.mjs";
9
-
10
- export { createBtsCli };
@@ -1,489 +0,0 @@
1
- #!/usr/bin/env node
2
- import { v as hasGraphPart, y as types_exports } from "./bts-config-InNcw1aJ.mjs";
3
-
4
- //#region src/utils/generate-reproducible-command.ts
5
- function getBaseCommand(packageManager) {
6
- switch (packageManager) {
7
- case "bun": return "bun create better-fullstack@latest";
8
- case "pnpm": return "pnpm create better-fullstack@latest";
9
- case "yarn": return "yarn create better-fullstack@latest";
10
- case "npm":
11
- default: return "npx create-better-fullstack@latest";
12
- }
13
- }
14
- function formatArrayFlag(flag, values) {
15
- const normalizedValues = values.filter((value) => value !== "none");
16
- if (normalizedValues.length === 0) return `--${flag} none`;
17
- return `--${flag} ${normalizedValues.join(" ")}`;
18
- }
19
- function appendCommonFlags(flags, config) {
20
- if (config.aiDocs && config.aiDocs.length > 0) flags.push(formatArrayFlag("ai-docs", config.aiDocs));
21
- else flags.push("--ai-docs none");
22
- flags.push(config.git ? "--git" : "--no-git");
23
- flags.push(`--package-manager ${config.packageManager}`);
24
- if (config.versionChannel !== "stable") flags.push(`--version-channel ${config.versionChannel}`);
25
- flags.push(config.install ? "--install" : "--no-install");
26
- }
27
- function hasGraphPrimaryPart(config, role, ecosystem) {
28
- return config.stackParts?.some((part) => part.source !== "provided" && part.role === role && !part.ownerPartId && (!ecosystem || part.ecosystem === ecosystem));
29
- }
30
- function hasOwnedGraphPart(config, ownerRole, role, ecosystem, toolId) {
31
- const owner = config.stackParts?.find((part) => part.source !== "provided" && part.role === ownerRole && !part.ownerPartId && (!ecosystem || part.ecosystem === ecosystem));
32
- if (!owner) return false;
33
- return Boolean(config.stackParts?.some((part) => part.source !== "provided" && part.role === role && part.ownerPartId === owner.id && (!ecosystem || part.ecosystem === ecosystem) && (!toolId || part.toolId === toolId)));
34
- }
35
- function hasGraphAddonPart(config, addon) {
36
- const binding = (0, types_exports.getAddonStackPartBinding)(addon);
37
- if (!binding) return false;
38
- if (!binding.ownerRole) return Boolean(config.stackParts?.some((part) => part.source !== "provided" && part.role === binding.role && part.ecosystem === binding.ecosystem && part.toolId === addon && !part.ownerPartId));
39
- const owner = config.stackParts?.find((part) => part.source !== "provided" && part.role === binding.ownerRole && !part.ownerPartId && part.ecosystem === binding.ecosystem);
40
- if (!owner) return false;
41
- return Boolean(config.stackParts?.some((part) => part.source !== "provided" && part.role === binding.role && part.ecosystem === binding.ecosystem && part.toolId === addon && part.ownerPartId === owner.id));
42
- }
43
- function hasGraphExamplePart(config, example) {
44
- return Boolean(config.stackParts?.some((part) => part.source !== "provided" && part.role === "examples" && part.ecosystem === "universal" && part.toolId === example && !part.ownerPartId));
45
- }
46
- function hasGraphArrayParts(config, values, hasPart) {
47
- const normalizedValues = values.filter((value) => value !== "none");
48
- return normalizedValues.length > 0 && normalizedValues.every((value) => hasPart(config, value));
49
- }
50
- function appendChangedStringFlag(flags, flag, value, defaultValue) {
51
- if (value !== defaultValue) flags.push(`--${flag} ${value}`);
52
- }
53
- function appendChangedGraphStringFlag(flags, config, role, ecosystem, flag, value, defaultValue) {
54
- if (hasGraphPart(config, role, ecosystem)) return;
55
- appendChangedStringFlag(flags, flag, value, defaultValue);
56
- }
57
- function appendChangedOwnedGraphStringFlag(flags, config, ownerRole, role, ecosystem, flag, value, defaultValue) {
58
- if (hasOwnedGraphPart(config, ownerRole, role, ecosystem, value)) return;
59
- appendChangedStringFlag(flags, flag, value, defaultValue);
60
- }
61
- function hasOwnedGraphArrayParts(config, ownerRole, role, ecosystem, values) {
62
- const normalizedValues = values.filter((value) => value !== "none");
63
- if (normalizedValues.length === 0) return false;
64
- return normalizedValues.every((value) => hasOwnedGraphPart(config, ownerRole, role, ecosystem, value));
65
- }
66
- function appendChangedOwnedGraphArrayFlag(flags, config, ownerRole, role, ecosystem, flag, values, defaultValues) {
67
- if (hasOwnedGraphArrayParts(config, ownerRole, role, ecosystem, values)) return;
68
- appendChangedArrayFlag(flags, flag, values, defaultValues);
69
- }
70
- function appendChangedArrayFlag(flags, flag, values, defaultValues) {
71
- if (values.length !== defaultValues.length || values.some((value, index) => value !== defaultValues[index])) flags.push(formatArrayFlag(flag, values));
72
- }
73
- function appendAstroIntegrationFlag(flags, config) {
74
- if (config.frontend.includes("astro") && config.astroIntegration !== "none") flags.push(`--astro-integration ${config.astroIntegration}`);
75
- }
76
- function appendGraphExtraFlags(flags, config) {
77
- if (!hasGraphArrayParts(config, config.addons, hasGraphAddonPart)) appendChangedArrayFlag(flags, "addons", config.addons, ["turborepo"]);
78
- if (!hasGraphArrayParts(config, config.examples, hasGraphExamplePart)) appendChangedArrayFlag(flags, "examples", config.examples, []);
79
- if (hasGraphPrimaryPart(config, "database")) appendChangedOwnedGraphStringFlag(flags, config, "database", "dbSetup", "universal", "db-setup", config.dbSetup, "none");
80
- else appendChangedStringFlag(flags, "db-setup", config.dbSetup, "none");
81
- if (hasGraphPrimaryPart(config, "frontend", "typescript")) {
82
- appendAstroIntegrationFlag(flags, config);
83
- appendChangedOwnedGraphStringFlag(flags, config, "frontend", "deploy", "typescript", "web-deploy", config.webDeploy, "none");
84
- appendChangedGraphStringFlag(flags, config, "css", "typescript", "css-framework", config.cssFramework, "tailwind");
85
- appendChangedGraphStringFlag(flags, config, "ui", "typescript", "ui-library", config.uiLibrary, "shadcn-ui");
86
- if (config.uiLibrary === "shadcn-ui") {
87
- appendChangedStringFlag(flags, "shadcn-base", config.shadcnBase ?? "radix", "radix");
88
- appendChangedStringFlag(flags, "shadcn-style", config.shadcnStyle ?? "nova", "nova");
89
- appendChangedStringFlag(flags, "shadcn-icon-library", config.shadcnIconLibrary ?? "lucide", "lucide");
90
- appendChangedStringFlag(flags, "shadcn-color-theme", config.shadcnColorTheme ?? "neutral", "neutral");
91
- appendChangedStringFlag(flags, "shadcn-base-color", config.shadcnBaseColor ?? "neutral", "neutral");
92
- appendChangedStringFlag(flags, "shadcn-font", config.shadcnFont ?? "inter", "inter");
93
- appendChangedStringFlag(flags, "shadcn-radius", config.shadcnRadius ?? "default", "default");
94
- }
95
- appendChangedGraphStringFlag(flags, config, "stateManagement", "typescript", "state-management", config.stateManagement, "none");
96
- appendChangedGraphStringFlag(flags, config, "forms", "typescript", "forms", config.forms, "react-hook-form");
97
- appendChangedStringFlag(flags, "validation", config.validation, "zod");
98
- appendChangedStringFlag(flags, "testing", config.testing, "vitest");
99
- appendChangedGraphStringFlag(flags, config, "animation", "typescript", "animation", config.animation, "none");
100
- appendChangedGraphStringFlag(flags, config, "fileUpload", "typescript", "file-upload", config.fileUpload, "none");
101
- appendChangedGraphStringFlag(flags, config, "i18n", "typescript", "i18n", config.i18n, "none");
102
- appendChangedGraphStringFlag(flags, config, "analytics", "typescript", "analytics", config.analytics, "none");
103
- }
104
- if (hasGraphPrimaryPart(config, "frontend", "typescript") || hasGraphPrimaryPart(config, "backend", "typescript")) {
105
- if (hasGraphPrimaryPart(config, "backend", "typescript")) {
106
- appendChangedOwnedGraphStringFlag(flags, config, "backend", "runtime", "typescript", "runtime", config.runtime, "bun");
107
- appendChangedOwnedGraphStringFlag(flags, config, "backend", "deploy", "typescript", "server-deploy", config.serverDeploy, "none");
108
- } else appendChangedStringFlag(flags, "server-deploy", config.serverDeploy, "none");
109
- appendChangedGraphStringFlag(flags, config, "payments", "typescript", "payments", config.payments, "none");
110
- appendChangedGraphStringFlag(flags, config, "email", "typescript", "email", config.email, "none");
111
- appendChangedStringFlag(flags, "effect", config.effect, "none");
112
- appendChangedGraphStringFlag(flags, config, "ai", "typescript", "ai", config.ai, "none");
113
- appendChangedGraphStringFlag(flags, config, "realtime", "typescript", "realtime", config.realtime, "none");
114
- appendChangedGraphStringFlag(flags, config, "jobQueue", "typescript", "job-queue", config.jobQueue, "none");
115
- appendChangedGraphStringFlag(flags, config, "logging", "typescript", "logging", config.logging, "none");
116
- appendChangedGraphStringFlag(flags, config, "observability", "typescript", "observability", config.observability, "none");
117
- appendChangedGraphStringFlag(flags, config, "featureFlags", "typescript", "feature-flags", config.featureFlags, "none");
118
- appendChangedGraphStringFlag(flags, config, "caching", "typescript", "caching", config.caching, "none");
119
- appendChangedGraphStringFlag(flags, config, "rateLimit", "typescript", "rate-limit", config.rateLimit, "none");
120
- appendChangedGraphStringFlag(flags, config, "cms", "typescript", "cms", config.cms, "none");
121
- appendChangedGraphStringFlag(flags, config, "search", "typescript", "search", config.search, "none");
122
- appendChangedGraphStringFlag(flags, config, "vectorDb", "typescript", "vectorDb", config.vectorDb, "none");
123
- appendChangedGraphStringFlag(flags, config, "fileStorage", "typescript", "file-storage", config.fileStorage, "none");
124
- }
125
- if (hasGraphPrimaryPart(config, "mobile")) {
126
- appendChangedOwnedGraphStringFlag(flags, config, "mobile", "navigation", "react-native", "mobile-navigation", config.mobileNavigation, "expo-router");
127
- appendChangedOwnedGraphStringFlag(flags, config, "mobile", "ui", "react-native", "mobile-ui", config.mobileUI, "none");
128
- appendChangedOwnedGraphStringFlag(flags, config, "mobile", "storage", "react-native", "mobile-storage", config.mobileStorage, "none");
129
- appendChangedOwnedGraphStringFlag(flags, config, "mobile", "testing", "react-native", "mobile-testing", config.mobileTesting, "none");
130
- appendChangedStringFlag(flags, "mobile-push", config.mobilePush, "none");
131
- appendChangedStringFlag(flags, "mobile-ota", config.mobileOTA, "none");
132
- appendChangedStringFlag(flags, "mobile-deep-linking", config.mobileDeepLinking, "none");
133
- }
134
- if (hasGraphPrimaryPart(config, "frontend", "rust")) appendChangedStringFlag(flags, "rust-frontend", config.rustFrontend, "none");
135
- if (hasGraphPrimaryPart(config, "backend", "rust")) {
136
- appendChangedOwnedGraphStringFlag(flags, config, "backend", "cli", "rust", "rust-cli", config.rustCli, "none");
137
- appendChangedOwnedGraphArrayFlag(flags, config, "backend", "libraries", "rust", "rust-libraries", config.rustLibraries, []);
138
- appendChangedOwnedGraphStringFlag(flags, config, "backend", "logging", "rust", "rust-logging", config.rustLogging, "tracing");
139
- appendChangedOwnedGraphStringFlag(flags, config, "backend", "errorHandling", "rust", "rust-error-handling", config.rustErrorHandling, "anyhow-thiserror");
140
- appendChangedOwnedGraphStringFlag(flags, config, "backend", "caching", "rust", "rust-caching", config.rustCaching, "none");
141
- }
142
- if (hasGraphPrimaryPart(config, "backend", "python")) {
143
- appendChangedOwnedGraphStringFlag(flags, config, "backend", "validation", "python", "python-validation", config.pythonValidation, "none");
144
- appendChangedOwnedGraphArrayFlag(flags, config, "backend", "ai", "python", "python-ai", config.pythonAi, []);
145
- appendChangedOwnedGraphStringFlag(flags, config, "backend", "jobQueue", "python", "python-task-queue", config.pythonTaskQueue, "none");
146
- appendChangedOwnedGraphStringFlag(flags, config, "backend", "api", "python", "python-graphql", config.pythonGraphql, "none");
147
- appendChangedOwnedGraphStringFlag(flags, config, "backend", "codeQuality", "python", "python-quality", config.pythonQuality, "none");
148
- }
149
- if (hasGraphPrimaryPart(config, "backend", "go")) {
150
- appendChangedOwnedGraphStringFlag(flags, config, "backend", "cli", "go", "go-cli", config.goCli, "none");
151
- appendChangedOwnedGraphStringFlag(flags, config, "backend", "logging", "go", "go-logging", config.goLogging, "none");
152
- }
153
- if (hasGraphPrimaryPart(config, "backend", "java")) {
154
- appendChangedOwnedGraphStringFlag(flags, config, "backend", "buildTool", "java", "java-build-tool", config.javaBuildTool, "maven");
155
- appendChangedOwnedGraphArrayFlag(flags, config, "backend", "libraries", "java", "java-libraries", config.javaLibraries, []);
156
- appendChangedOwnedGraphArrayFlag(flags, config, "backend", "testing", "java", "java-testing-libraries", config.javaTestingLibraries, ["junit5"]);
157
- }
158
- if (hasGraphPrimaryPart(config, "backend", "elixir")) {
159
- appendChangedGraphStringFlag(flags, config, "realtime", "elixir", "elixir-realtime", config.elixirRealtime, "channels");
160
- appendChangedGraphStringFlag(flags, config, "jobQueue", "elixir", "elixir-jobs", config.elixirJobs, "none");
161
- appendChangedGraphStringFlag(flags, config, "validation", "elixir", "elixir-validation", config.elixirValidation, "ecto-changesets");
162
- appendChangedOwnedGraphStringFlag(flags, config, "backend", "httpClient", "elixir", "elixir-http", config.elixirHttp, "req");
163
- appendChangedStringFlag(flags, "elixir-json", config.elixirJson, "jason");
164
- appendChangedGraphStringFlag(flags, config, "email", "elixir", "elixir-email", config.elixirEmail, "none");
165
- appendChangedGraphStringFlag(flags, config, "caching", "elixir", "elixir-caching", config.elixirCaching, "none");
166
- appendChangedGraphStringFlag(flags, config, "observability", "elixir", "elixir-observability", config.elixirObservability, "telemetry");
167
- appendChangedGraphStringFlag(flags, config, "testing", "elixir", "elixir-testing", config.elixirTesting, "ex_unit");
168
- appendChangedOwnedGraphStringFlag(flags, config, "backend", "codeQuality", "elixir", "elixir-quality", config.elixirQuality, "credo");
169
- appendChangedGraphStringFlag(flags, config, "deploy", "elixir", "elixir-deploy", config.elixirDeploy, "none");
170
- }
171
- }
172
- function appendSharedNonTypeScriptFlags(flags, config) {
173
- flags.push(`--email ${config.email}`);
174
- flags.push(`--observability ${config.observability}`);
175
- flags.push(`--caching ${config.caching}`);
176
- flags.push(`--search ${config.search}`);
177
- flags.push(formatArrayFlag("addons", config.addons));
178
- flags.push(formatArrayFlag("examples", config.examples));
179
- flags.push(`--db-setup ${config.dbSetup}`);
180
- flags.push(`--web-deploy ${config.webDeploy}`);
181
- flags.push(`--server-deploy ${config.serverDeploy}`);
182
- }
183
- function getTypeScriptFlags(config) {
184
- const flags = [];
185
- if (config.frontend && config.frontend.length > 0) flags.push(`--frontend ${config.frontend.join(" ")}`);
186
- else flags.push("--frontend none");
187
- appendAstroIntegrationFlag(flags, config);
188
- flags.push(`--backend ${config.backend}`);
189
- flags.push(`--runtime ${config.runtime}`);
190
- flags.push(`--database ${config.database}`);
191
- flags.push(`--orm ${config.orm}`);
192
- flags.push(`--api ${config.api}`);
193
- flags.push(`--auth ${config.auth}`);
194
- flags.push(`--payments ${config.payments}`);
195
- flags.push(`--email ${config.email}`);
196
- flags.push(`--file-upload ${config.fileUpload}`);
197
- flags.push(`--effect ${config.effect}`);
198
- flags.push(`--css-framework ${config.cssFramework}`);
199
- flags.push(`--ui-library ${config.uiLibrary}`);
200
- if (config.uiLibrary === "shadcn-ui") {
201
- flags.push(`--shadcn-base ${config.shadcnBase}`);
202
- flags.push(`--shadcn-style ${config.shadcnStyle}`);
203
- flags.push(`--shadcn-icon-library ${config.shadcnIconLibrary}`);
204
- flags.push(`--shadcn-color-theme ${config.shadcnColorTheme}`);
205
- flags.push(`--shadcn-base-color ${config.shadcnBaseColor}`);
206
- flags.push(`--shadcn-font ${config.shadcnFont}`);
207
- flags.push(`--shadcn-radius ${config.shadcnRadius}`);
208
- }
209
- flags.push(`--ai ${config.ai}`);
210
- flags.push(`--state-management ${config.stateManagement}`);
211
- flags.push(`--forms ${config.forms}`);
212
- flags.push(`--validation ${config.validation}`);
213
- flags.push(`--testing ${config.testing}`);
214
- flags.push(`--animation ${config.animation}`);
215
- flags.push(`--realtime ${config.realtime}`);
216
- flags.push(`--job-queue ${config.jobQueue}`);
217
- flags.push(`--logging ${config.logging}`);
218
- flags.push(`--observability ${config.observability}`);
219
- flags.push(`--feature-flags ${config.featureFlags}`);
220
- flags.push(`--caching ${config.caching}`);
221
- flags.push(`--rate-limit ${config.rateLimit}`);
222
- flags.push(`--i18n ${config.i18n}`);
223
- flags.push(`--cms ${config.cms}`);
224
- flags.push(`--search ${config.search}`);
225
- flags.push(`--vector-db ${config.vectorDb}`);
226
- flags.push(`--file-storage ${config.fileStorage}`);
227
- flags.push(`--mobile-navigation ${config.mobileNavigation}`);
228
- flags.push(`--mobile-ui ${config.mobileUI}`);
229
- flags.push(`--mobile-storage ${config.mobileStorage}`);
230
- flags.push(`--mobile-testing ${config.mobileTesting}`);
231
- flags.push(`--mobile-push ${config.mobilePush}`);
232
- flags.push(`--mobile-ota ${config.mobileOTA}`);
233
- flags.push(`--mobile-deep-linking ${config.mobileDeepLinking}`);
234
- if (config.addons && config.addons.length > 0) flags.push(`--addons ${config.addons.join(" ")}`);
235
- else flags.push("--addons none");
236
- if (config.examples && config.examples.length > 0) flags.push(`--examples ${config.examples.join(" ")}`);
237
- else flags.push("--examples none");
238
- flags.push(`--db-setup ${config.dbSetup}`);
239
- flags.push(`--web-deploy ${config.webDeploy}`);
240
- flags.push(`--server-deploy ${config.serverDeploy}`);
241
- appendCommonFlags(flags, config);
242
- return flags;
243
- }
244
- function getReactNativeFlags(config) {
245
- const flags = ["--ecosystem react-native"];
246
- if (config.frontend && config.frontend.length > 0) flags.push(`--frontend ${config.frontend.join(" ")}`);
247
- else flags.push("--frontend native-bare");
248
- flags.push(`--auth ${config.auth}`);
249
- flags.push(`--mobile-navigation ${config.mobileNavigation}`);
250
- flags.push(`--mobile-ui ${config.mobileUI}`);
251
- flags.push(`--mobile-storage ${config.mobileStorage}`);
252
- flags.push(`--mobile-testing ${config.mobileTesting}`);
253
- flags.push(`--mobile-push ${config.mobilePush}`);
254
- flags.push(`--mobile-ota ${config.mobileOTA}`);
255
- flags.push(`--mobile-deep-linking ${config.mobileDeepLinking}`);
256
- appendCommonFlags(flags, config);
257
- return flags;
258
- }
259
- function getRustFlags(config) {
260
- const flags = ["--ecosystem rust"];
261
- flags.push(`--rust-web-framework ${config.rustWebFramework}`);
262
- flags.push(`--rust-frontend ${config.rustFrontend}`);
263
- flags.push(`--rust-orm ${config.rustOrm}`);
264
- flags.push(`--rust-api ${config.rustApi}`);
265
- flags.push(`--rust-cli ${config.rustCli}`);
266
- flags.push(formatArrayFlag("rust-libraries", config.rustLibraries));
267
- flags.push(`--rust-logging ${config.rustLogging}`);
268
- flags.push(`--rust-error-handling ${config.rustErrorHandling}`);
269
- flags.push(`--rust-caching ${config.rustCaching}`);
270
- flags.push(`--rust-auth ${config.rustAuth}`);
271
- flags.push(`--rust-realtime ${config.rustRealtime}`);
272
- flags.push(`--rust-message-queue ${config.rustMessageQueue}`);
273
- flags.push(`--rust-observability ${config.rustObservability}`);
274
- flags.push(`--rust-templating ${config.rustTemplating}`);
275
- appendSharedNonTypeScriptFlags(flags, config);
276
- appendCommonFlags(flags, config);
277
- return flags;
278
- }
279
- function getPythonFlags(config) {
280
- const flags = ["--ecosystem python"];
281
- flags.push(`--python-web-framework ${config.pythonWebFramework}`);
282
- flags.push(`--python-orm ${config.pythonOrm}`);
283
- flags.push(`--python-validation ${config.pythonValidation}`);
284
- flags.push(formatArrayFlag("python-ai", config.pythonAi));
285
- flags.push(`--python-auth ${config.pythonAuth}`);
286
- flags.push(`--python-api ${config.pythonApi}`);
287
- flags.push(`--python-task-queue ${config.pythonTaskQueue}`);
288
- flags.push(`--python-graphql ${config.pythonGraphql}`);
289
- flags.push(`--python-quality ${config.pythonQuality}`);
290
- flags.push(formatArrayFlag("python-testing", config.pythonTesting));
291
- flags.push(`--python-caching ${config.pythonCaching}`);
292
- flags.push(`--python-realtime ${config.pythonRealtime}`);
293
- flags.push(`--python-observability ${config.pythonObservability}`);
294
- flags.push(formatArrayFlag("python-cli", config.pythonCli));
295
- appendSharedNonTypeScriptFlags(flags, config);
296
- appendCommonFlags(flags, config);
297
- return flags;
298
- }
299
- function getGoFlags(config) {
300
- const flags = ["--ecosystem go"];
301
- flags.push(`--go-web-framework ${config.goWebFramework}`);
302
- flags.push(`--go-orm ${config.goOrm}`);
303
- flags.push(`--go-api ${config.goApi}`);
304
- flags.push(`--go-cli ${config.goCli}`);
305
- flags.push(`--go-logging ${config.goLogging}`);
306
- flags.push(`--go-auth ${config.goAuth}`);
307
- flags.push(formatArrayFlag("go-testing", config.goTesting));
308
- flags.push(`--go-realtime ${config.goRealtime}`);
309
- flags.push(`--go-message-queue ${config.goMessageQueue}`);
310
- flags.push(`--go-caching ${config.goCaching}`);
311
- flags.push(`--go-config ${config.goConfig}`);
312
- flags.push(`--go-observability ${config.goObservability}`);
313
- flags.push(`--auth ${config.auth}`);
314
- appendSharedNonTypeScriptFlags(flags, config);
315
- appendCommonFlags(flags, config);
316
- return flags;
317
- }
318
- function getJavaFlags(config) {
319
- const flags = ["--ecosystem java"];
320
- flags.push(`--java-web-framework ${config.javaWebFramework}`);
321
- flags.push(`--java-build-tool ${config.javaBuildTool}`);
322
- flags.push(`--java-orm ${config.javaOrm}`);
323
- flags.push(`--java-auth ${config.javaAuth}`);
324
- flags.push(`--java-api ${config.javaApi}`);
325
- flags.push(`--java-logging ${config.javaLogging}`);
326
- flags.push(formatArrayFlag("java-libraries", config.javaLibraries));
327
- flags.push(formatArrayFlag("java-testing-libraries", config.javaTestingLibraries));
328
- appendSharedNonTypeScriptFlags(flags, config);
329
- appendCommonFlags(flags, config);
330
- return flags;
331
- }
332
- function getDotnetFlags(config) {
333
- const flags = ["--ecosystem dotnet"];
334
- flags.push(`--dotnet-web-framework ${config.dotnetWebFramework}`);
335
- flags.push(`--dotnet-orm ${config.dotnetOrm}`);
336
- flags.push(`--dotnet-auth ${config.dotnetAuth}`);
337
- flags.push(`--dotnet-api ${config.dotnetApi}`);
338
- flags.push(formatArrayFlag("dotnet-testing", config.dotnetTesting));
339
- flags.push(`--dotnet-job-queue ${config.dotnetJobQueue}`);
340
- flags.push(`--dotnet-realtime ${config.dotnetRealtime}`);
341
- flags.push(formatArrayFlag("dotnet-observability", config.dotnetObservability));
342
- flags.push(`--dotnet-validation ${config.dotnetValidation}`);
343
- flags.push(`--dotnet-caching ${config.dotnetCaching}`);
344
- flags.push(`--dotnet-deploy ${config.dotnetDeploy}`);
345
- appendCommonFlags(flags, config);
346
- return flags;
347
- }
348
- function getElixirFlags(config) {
349
- const flags = ["--ecosystem elixir"];
350
- flags.push(`--elixir-web-framework ${config.elixirWebFramework}`);
351
- flags.push(`--elixir-orm ${config.elixirOrm}`);
352
- flags.push(`--elixir-auth ${config.elixirAuth}`);
353
- flags.push(`--elixir-api ${config.elixirApi}`);
354
- flags.push(`--elixir-realtime ${config.elixirRealtime}`);
355
- flags.push(`--elixir-jobs ${config.elixirJobs}`);
356
- flags.push(`--elixir-validation ${config.elixirValidation}`);
357
- flags.push(`--elixir-http ${config.elixirHttp}`);
358
- flags.push(`--elixir-json ${config.elixirJson}`);
359
- flags.push(`--elixir-email ${config.elixirEmail}`);
360
- flags.push(`--elixir-caching ${config.elixirCaching}`);
361
- flags.push(`--elixir-observability ${config.elixirObservability}`);
362
- flags.push(`--elixir-testing ${config.elixirTesting}`);
363
- flags.push(`--elixir-quality ${config.elixirQuality}`);
364
- flags.push(`--elixir-deploy ${config.elixirDeploy}`);
365
- flags.push(formatArrayFlag("elixir-libraries", config.elixirLibraries));
366
- appendCommonFlags(flags, config);
367
- return flags;
368
- }
369
- function generateReproducibleCommand(config) {
370
- let flags;
371
- if (config.stackParts && config.stackParts.length > 0) {
372
- flags = config.stackParts.filter((part) => part.source !== "provided").map((part) => `--part ${(0, types_exports.formatStackPartSpec)(part, config.stackParts ?? [])}`);
373
- appendGraphExtraFlags(flags, config);
374
- appendCommonFlags(flags, config);
375
- return `${getBaseCommand(config.packageManager)}${config.relativePath ? ` ${config.relativePath}` : ""} ${flags.join(" ")}`;
376
- }
377
- switch (config.ecosystem) {
378
- case "react-native":
379
- flags = getReactNativeFlags(config);
380
- break;
381
- case "rust":
382
- flags = getRustFlags(config);
383
- break;
384
- case "python":
385
- flags = getPythonFlags(config);
386
- break;
387
- case "go":
388
- flags = getGoFlags(config);
389
- break;
390
- case "java":
391
- flags = getJavaFlags(config);
392
- break;
393
- case "dotnet":
394
- flags = getDotnetFlags(config);
395
- break;
396
- case "elixir":
397
- flags = getElixirFlags(config);
398
- break;
399
- case "typescript":
400
- default:
401
- flags = getTypeScriptFlags(config);
402
- break;
403
- }
404
- return `${getBaseCommand(config.packageManager)}${config.relativePath ? ` ${config.relativePath}` : ""} ${flags.join(" ")}`;
405
- }
406
-
407
- //#endregion
408
- //#region src/utils/templates.ts
409
- const TEMPLATE_PRESETS = {
410
- mern: {
411
- database: "mongodb",
412
- orm: "mongoose",
413
- backend: "express",
414
- runtime: "node",
415
- frontend: ["react-router"],
416
- api: "orpc",
417
- auth: "better-auth",
418
- payments: "none",
419
- addons: ["turborepo"],
420
- examples: ["none"],
421
- dbSetup: "mongodb-atlas",
422
- webDeploy: "none",
423
- serverDeploy: "none"
424
- },
425
- pern: {
426
- database: "postgres",
427
- orm: "drizzle",
428
- backend: "express",
429
- runtime: "node",
430
- frontend: ["tanstack-router"],
431
- api: "trpc",
432
- auth: "better-auth",
433
- payments: "none",
434
- addons: ["turborepo"],
435
- examples: ["none"],
436
- dbSetup: "none",
437
- webDeploy: "none",
438
- serverDeploy: "none"
439
- },
440
- t3: {
441
- database: "postgres",
442
- orm: "prisma",
443
- backend: "self",
444
- runtime: "none",
445
- frontend: ["next"],
446
- api: "trpc",
447
- auth: "better-auth",
448
- payments: "none",
449
- addons: ["biome", "turborepo"],
450
- examples: ["none"],
451
- dbSetup: "none",
452
- webDeploy: "none",
453
- serverDeploy: "none"
454
- },
455
- uniwind: {
456
- database: "none",
457
- orm: "none",
458
- backend: "none",
459
- runtime: "none",
460
- frontend: ["native-uniwind"],
461
- api: "none",
462
- auth: "none",
463
- payments: "none",
464
- addons: ["none"],
465
- examples: ["none"],
466
- dbSetup: "none",
467
- webDeploy: "none",
468
- serverDeploy: "none"
469
- },
470
- none: null
471
- };
472
- function getTemplateConfig(template) {
473
- if (template === "none" || !template) return null;
474
- const config = TEMPLATE_PRESETS[template];
475
- if (!config) throw new Error(`Unknown template: ${template}`);
476
- return config;
477
- }
478
- function getTemplateDescription(template) {
479
- return {
480
- mern: "MongoDB + Express + React + Node.js - Classic MERN stack",
481
- pern: "PostgreSQL + Express + React + Node.js - Popular PERN stack",
482
- t3: "T3 Stack - Next.js + tRPC + Prisma + PostgreSQL + Better Auth",
483
- uniwind: "Expo + Uniwind native app with no backend services",
484
- none: "No template - Full customization"
485
- }[template] || "";
486
- }
487
-
488
- //#endregion
489
- export { getTemplateDescription as n, generateReproducibleCommand as r, getTemplateConfig as t };