create-better-t-stack 3.7.3-canary.8e4d5716 → 3.7.3-canary.98ba1e7a
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +8 -0
- package/dist/index.d.ts +347 -0
- package/dist/index.js +4 -0
- package/dist/src-yXf02Wox.js +7077 -0
- package/package.json +11 -7
- package/src/cli.ts +0 -3
- package/src/constants.ts +0 -188
- package/src/helpers/addons/addons-setup.ts +0 -226
- package/src/helpers/addons/examples-setup.ts +0 -104
- package/src/helpers/addons/fumadocs-setup.ts +0 -103
- package/src/helpers/addons/ruler-setup.ts +0 -139
- package/src/helpers/addons/starlight-setup.ts +0 -51
- package/src/helpers/addons/tauri-setup.ts +0 -96
- package/src/helpers/addons/ultracite-setup.ts +0 -232
- package/src/helpers/addons/vite-pwa-setup.ts +0 -59
- package/src/helpers/core/add-addons.ts +0 -85
- package/src/helpers/core/add-deployment.ts +0 -102
- package/src/helpers/core/api-setup.ts +0 -280
- package/src/helpers/core/auth-setup.ts +0 -203
- package/src/helpers/core/backend-setup.ts +0 -73
- package/src/helpers/core/command-handlers.ts +0 -354
- package/src/helpers/core/convex-codegen.ts +0 -14
- package/src/helpers/core/create-project.ts +0 -133
- package/src/helpers/core/create-readme.ts +0 -687
- package/src/helpers/core/db-setup.ts +0 -184
- package/src/helpers/core/detect-project-config.ts +0 -41
- package/src/helpers/core/env-setup.ts +0 -449
- package/src/helpers/core/git.ts +0 -31
- package/src/helpers/core/install-dependencies.ts +0 -32
- package/src/helpers/core/payments-setup.ts +0 -48
- package/src/helpers/core/post-installation.ts +0 -383
- package/src/helpers/core/project-config.ts +0 -246
- package/src/helpers/core/runtime-setup.ts +0 -76
- package/src/helpers/core/template-manager.ts +0 -917
- package/src/helpers/core/workspace-setup.ts +0 -184
- package/src/helpers/database-providers/d1-setup.ts +0 -28
- package/src/helpers/database-providers/docker-compose-setup.ts +0 -50
- package/src/helpers/database-providers/mongodb-atlas-setup.ts +0 -186
- package/src/helpers/database-providers/neon-setup.ts +0 -243
- package/src/helpers/database-providers/planetscale-setup.ts +0 -78
- package/src/helpers/database-providers/prisma-postgres-setup.ts +0 -196
- package/src/helpers/database-providers/supabase-setup.ts +0 -218
- package/src/helpers/database-providers/turso-setup.ts +0 -309
- package/src/helpers/deployment/alchemy/alchemy-combined-setup.ts +0 -80
- package/src/helpers/deployment/alchemy/alchemy-next-setup.ts +0 -51
- package/src/helpers/deployment/alchemy/alchemy-nuxt-setup.ts +0 -104
- package/src/helpers/deployment/alchemy/alchemy-react-router-setup.ts +0 -32
- package/src/helpers/deployment/alchemy/alchemy-solid-setup.ts +0 -32
- package/src/helpers/deployment/alchemy/alchemy-svelte-setup.ts +0 -98
- package/src/helpers/deployment/alchemy/alchemy-tanstack-router-setup.ts +0 -33
- package/src/helpers/deployment/alchemy/alchemy-tanstack-start-setup.ts +0 -98
- package/src/helpers/deployment/alchemy/env-dts-setup.ts +0 -76
- package/src/helpers/deployment/alchemy/index.ts +0 -7
- package/src/helpers/deployment/server-deploy-setup.ts +0 -55
- package/src/helpers/deployment/web-deploy-setup.ts +0 -58
- package/src/index.ts +0 -253
- package/src/prompts/addons.ts +0 -178
- package/src/prompts/api.ts +0 -49
- package/src/prompts/auth.ts +0 -84
- package/src/prompts/backend.ts +0 -83
- package/src/prompts/config-prompts.ts +0 -138
- package/src/prompts/database-setup.ts +0 -112
- package/src/prompts/database.ts +0 -57
- package/src/prompts/examples.ts +0 -64
- package/src/prompts/frontend.ts +0 -118
- package/src/prompts/git.ts +0 -16
- package/src/prompts/install.ts +0 -16
- package/src/prompts/orm.ts +0 -53
- package/src/prompts/package-manager.ts +0 -32
- package/src/prompts/payments.ts +0 -50
- package/src/prompts/project-name.ts +0 -86
- package/src/prompts/runtime.ts +0 -47
- package/src/prompts/server-deploy.ts +0 -91
- package/src/prompts/web-deploy.ts +0 -107
- package/src/types.ts +0 -2
- package/src/utils/add-package-deps.ts +0 -57
- package/src/utils/analytics.ts +0 -39
- package/src/utils/better-auth-plugin-setup.ts +0 -71
- package/src/utils/biome-formatter.ts +0 -82
- package/src/utils/bts-config.ts +0 -122
- package/src/utils/command-exists.ts +0 -16
- package/src/utils/compatibility-rules.ts +0 -319
- package/src/utils/compatibility.ts +0 -11
- package/src/utils/config-processing.ts +0 -130
- package/src/utils/config-validation.ts +0 -470
- package/src/utils/display-config.ts +0 -96
- package/src/utils/docker-utils.ts +0 -70
- package/src/utils/errors.ts +0 -32
- package/src/utils/generate-reproducible-command.ts +0 -53
- package/src/utils/get-latest-cli-version.ts +0 -11
- package/src/utils/get-package-manager.ts +0 -13
- package/src/utils/open-url.ts +0 -25
- package/src/utils/package-runner.ts +0 -23
- package/src/utils/project-directory.ts +0 -102
- package/src/utils/project-name-validation.ts +0 -43
- package/src/utils/render-title.ts +0 -48
- package/src/utils/setup-catalogs.ts +0 -192
- package/src/utils/sponsors.ts +0 -101
- package/src/utils/telemetry.ts +0 -19
- package/src/utils/template-processor.ts +0 -64
- package/src/utils/templates.ts +0 -94
- package/src/utils/ts-morph.ts +0 -26
- package/src/validation.ts +0 -117
package/src/prompts/addons.ts
DELETED
|
@@ -1,178 +0,0 @@
|
|
|
1
|
-
import { groupMultiselect, isCancel } from "@clack/prompts";
|
|
2
|
-
import { DEFAULT_CONFIG } from "../constants";
|
|
3
|
-
import { type Addons, AddonsSchema, type Auth, type Frontend } from "../types";
|
|
4
|
-
import { getCompatibleAddons, validateAddonCompatibility } from "../utils/compatibility-rules";
|
|
5
|
-
import { exitCancelled } from "../utils/errors";
|
|
6
|
-
|
|
7
|
-
type AddonOption = {
|
|
8
|
-
value: Addons;
|
|
9
|
-
label: string;
|
|
10
|
-
hint: string;
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
function getAddonDisplay(addon: Addons): { label: string; hint: string } {
|
|
14
|
-
let label: string;
|
|
15
|
-
let hint: string;
|
|
16
|
-
|
|
17
|
-
switch (addon) {
|
|
18
|
-
case "turborepo":
|
|
19
|
-
label = "Turborepo";
|
|
20
|
-
hint = "High-performance build system";
|
|
21
|
-
break;
|
|
22
|
-
case "pwa":
|
|
23
|
-
label = "PWA";
|
|
24
|
-
hint = "Make your app installable and work offline";
|
|
25
|
-
break;
|
|
26
|
-
case "tauri":
|
|
27
|
-
label = "Tauri";
|
|
28
|
-
hint = "Build native desktop apps from your web frontend";
|
|
29
|
-
break;
|
|
30
|
-
case "biome":
|
|
31
|
-
label = "Biome";
|
|
32
|
-
hint = "Format, lint, and more";
|
|
33
|
-
break;
|
|
34
|
-
case "oxlint":
|
|
35
|
-
label = "Oxlint";
|
|
36
|
-
hint = "Rust-powered linter";
|
|
37
|
-
break;
|
|
38
|
-
case "ultracite":
|
|
39
|
-
label = "Ultracite";
|
|
40
|
-
hint = "Zero-config Biome preset with AI integration";
|
|
41
|
-
break;
|
|
42
|
-
case "ruler":
|
|
43
|
-
label = "Ruler";
|
|
44
|
-
hint = "Centralize your AI rules";
|
|
45
|
-
break;
|
|
46
|
-
case "husky":
|
|
47
|
-
label = "Husky";
|
|
48
|
-
hint = "Modern native Git hooks made easy";
|
|
49
|
-
break;
|
|
50
|
-
case "starlight":
|
|
51
|
-
label = "Starlight";
|
|
52
|
-
hint = "Build stellar docs with astro";
|
|
53
|
-
break;
|
|
54
|
-
case "fumadocs":
|
|
55
|
-
label = "Fumadocs";
|
|
56
|
-
hint = "Build excellent documentation site";
|
|
57
|
-
break;
|
|
58
|
-
default:
|
|
59
|
-
label = addon;
|
|
60
|
-
hint = `Add ${addon}`;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
return { label, hint };
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
const ADDON_GROUPS = {
|
|
67
|
-
Documentation: ["starlight", "fumadocs"],
|
|
68
|
-
Linting: ["biome", "oxlint", "ultracite"],
|
|
69
|
-
Other: ["ruler", "turborepo", "pwa", "tauri", "husky"],
|
|
70
|
-
};
|
|
71
|
-
|
|
72
|
-
export async function getAddonsChoice(addons?: Addons[], frontends?: Frontend[], auth?: Auth) {
|
|
73
|
-
if (addons !== undefined) return addons;
|
|
74
|
-
|
|
75
|
-
const allAddons = AddonsSchema.options.filter((addon) => addon !== "none");
|
|
76
|
-
const groupedOptions: Record<string, AddonOption[]> = {
|
|
77
|
-
Documentation: [],
|
|
78
|
-
Linting: [],
|
|
79
|
-
Other: [],
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
const frontendsArray = frontends || [];
|
|
83
|
-
|
|
84
|
-
for (const addon of allAddons) {
|
|
85
|
-
const { isCompatible } = validateAddonCompatibility(addon, frontendsArray, auth);
|
|
86
|
-
if (!isCompatible) continue;
|
|
87
|
-
|
|
88
|
-
const { label, hint } = getAddonDisplay(addon);
|
|
89
|
-
const option = { value: addon, label, hint };
|
|
90
|
-
|
|
91
|
-
if (ADDON_GROUPS.Documentation.includes(addon)) {
|
|
92
|
-
groupedOptions.Documentation.push(option);
|
|
93
|
-
} else if (ADDON_GROUPS.Linting.includes(addon)) {
|
|
94
|
-
groupedOptions.Linting.push(option);
|
|
95
|
-
} else if (ADDON_GROUPS.Other.includes(addon)) {
|
|
96
|
-
groupedOptions.Other.push(option);
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
Object.keys(groupedOptions).forEach((group) => {
|
|
101
|
-
if (groupedOptions[group].length === 0) {
|
|
102
|
-
delete groupedOptions[group];
|
|
103
|
-
}
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
const initialValues = DEFAULT_CONFIG.addons.filter((addonValue) =>
|
|
107
|
-
Object.values(groupedOptions).some((options) =>
|
|
108
|
-
options.some((opt) => opt.value === addonValue),
|
|
109
|
-
),
|
|
110
|
-
);
|
|
111
|
-
|
|
112
|
-
const response = await groupMultiselect<Addons>({
|
|
113
|
-
message: "Select addons",
|
|
114
|
-
options: groupedOptions,
|
|
115
|
-
initialValues: initialValues,
|
|
116
|
-
required: false,
|
|
117
|
-
selectableGroups: false,
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
if (isCancel(response)) return exitCancelled("Operation cancelled");
|
|
121
|
-
|
|
122
|
-
return response;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
export async function getAddonsToAdd(
|
|
126
|
-
frontend: Frontend[],
|
|
127
|
-
existingAddons: Addons[] = [],
|
|
128
|
-
auth?: Auth,
|
|
129
|
-
) {
|
|
130
|
-
const groupedOptions: Record<string, AddonOption[]> = {
|
|
131
|
-
Documentation: [],
|
|
132
|
-
Linting: [],
|
|
133
|
-
Other: [],
|
|
134
|
-
};
|
|
135
|
-
|
|
136
|
-
const frontendArray = frontend || [];
|
|
137
|
-
|
|
138
|
-
const compatibleAddons = getCompatibleAddons(
|
|
139
|
-
AddonsSchema.options.filter((addon) => addon !== "none"),
|
|
140
|
-
frontendArray,
|
|
141
|
-
existingAddons,
|
|
142
|
-
auth,
|
|
143
|
-
);
|
|
144
|
-
|
|
145
|
-
for (const addon of compatibleAddons) {
|
|
146
|
-
const { label, hint } = getAddonDisplay(addon);
|
|
147
|
-
const option = { value: addon, label, hint };
|
|
148
|
-
|
|
149
|
-
if (ADDON_GROUPS.Documentation.includes(addon)) {
|
|
150
|
-
groupedOptions.Documentation.push(option);
|
|
151
|
-
} else if (ADDON_GROUPS.Linting.includes(addon)) {
|
|
152
|
-
groupedOptions.Linting.push(option);
|
|
153
|
-
} else if (ADDON_GROUPS.Other.includes(addon)) {
|
|
154
|
-
groupedOptions.Other.push(option);
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
Object.keys(groupedOptions).forEach((group) => {
|
|
159
|
-
if (groupedOptions[group].length === 0) {
|
|
160
|
-
delete groupedOptions[group];
|
|
161
|
-
}
|
|
162
|
-
});
|
|
163
|
-
|
|
164
|
-
if (Object.keys(groupedOptions).length === 0) {
|
|
165
|
-
return [];
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
const response = await groupMultiselect<Addons>({
|
|
169
|
-
message: "Select addons to add",
|
|
170
|
-
options: groupedOptions,
|
|
171
|
-
required: false,
|
|
172
|
-
selectableGroups: false,
|
|
173
|
-
});
|
|
174
|
-
|
|
175
|
-
if (isCancel(response)) return exitCancelled("Operation cancelled");
|
|
176
|
-
|
|
177
|
-
return response;
|
|
178
|
-
}
|
package/src/prompts/api.ts
DELETED
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import { isCancel, select } from "@clack/prompts";
|
|
2
|
-
import type { API, Backend, Frontend } from "../types";
|
|
3
|
-
import { allowedApisForFrontends } from "../utils/compatibility-rules";
|
|
4
|
-
import { exitCancelled } from "../utils/errors";
|
|
5
|
-
|
|
6
|
-
export async function getApiChoice(
|
|
7
|
-
Api?: API | undefined,
|
|
8
|
-
frontend?: Frontend[],
|
|
9
|
-
backend?: Backend,
|
|
10
|
-
) {
|
|
11
|
-
if (backend === "convex" || backend === "none") {
|
|
12
|
-
return "none";
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
const allowed = allowedApisForFrontends(frontend ?? []);
|
|
16
|
-
|
|
17
|
-
if (Api) {
|
|
18
|
-
return allowed.includes(Api) ? Api : allowed[0];
|
|
19
|
-
}
|
|
20
|
-
const apiOptions = allowed.map((a) =>
|
|
21
|
-
a === "trpc"
|
|
22
|
-
? {
|
|
23
|
-
value: "trpc" as const,
|
|
24
|
-
label: "tRPC",
|
|
25
|
-
hint: "End-to-end typesafe APIs made easy",
|
|
26
|
-
}
|
|
27
|
-
: a === "orpc"
|
|
28
|
-
? {
|
|
29
|
-
value: "orpc" as const,
|
|
30
|
-
label: "oRPC",
|
|
31
|
-
hint: "End-to-end type-safe APIs that adhere to OpenAPI standards",
|
|
32
|
-
}
|
|
33
|
-
: {
|
|
34
|
-
value: "none" as const,
|
|
35
|
-
label: "None",
|
|
36
|
-
hint: "No API layer (e.g. for full-stack frameworks like Next.js with Route Handlers)",
|
|
37
|
-
},
|
|
38
|
-
);
|
|
39
|
-
|
|
40
|
-
const apiType = await select<API>({
|
|
41
|
-
message: "Select API type",
|
|
42
|
-
options: apiOptions,
|
|
43
|
-
initialValue: apiOptions[0].value,
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
if (isCancel(apiType)) return exitCancelled("Operation cancelled");
|
|
47
|
-
|
|
48
|
-
return apiType;
|
|
49
|
-
}
|
package/src/prompts/auth.ts
DELETED
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
import { isCancel, select } from "@clack/prompts";
|
|
2
|
-
import { DEFAULT_CONFIG } from "../constants";
|
|
3
|
-
import type { Auth, Backend } from "../types";
|
|
4
|
-
import { exitCancelled } from "../utils/errors";
|
|
5
|
-
|
|
6
|
-
export async function getAuthChoice(
|
|
7
|
-
auth: Auth | undefined,
|
|
8
|
-
backend?: Backend,
|
|
9
|
-
frontend?: string[],
|
|
10
|
-
) {
|
|
11
|
-
if (auth !== undefined) return auth;
|
|
12
|
-
if (backend === "none") {
|
|
13
|
-
return "none" as Auth;
|
|
14
|
-
}
|
|
15
|
-
if (backend === "convex") {
|
|
16
|
-
const supportedBetterAuthFrontends = frontend?.some((f) =>
|
|
17
|
-
[
|
|
18
|
-
"tanstack-router",
|
|
19
|
-
"tanstack-start",
|
|
20
|
-
"next",
|
|
21
|
-
"native-bare",
|
|
22
|
-
"native-uniwind",
|
|
23
|
-
"native-unistyles",
|
|
24
|
-
].includes(f),
|
|
25
|
-
);
|
|
26
|
-
|
|
27
|
-
const hasClerkCompatibleFrontends = frontend?.some((f) =>
|
|
28
|
-
[
|
|
29
|
-
"react-router",
|
|
30
|
-
"tanstack-router",
|
|
31
|
-
"tanstack-start",
|
|
32
|
-
"next",
|
|
33
|
-
"native-bare",
|
|
34
|
-
"native-uniwind",
|
|
35
|
-
"native-unistyles",
|
|
36
|
-
].includes(f),
|
|
37
|
-
);
|
|
38
|
-
|
|
39
|
-
const options = [];
|
|
40
|
-
|
|
41
|
-
if (supportedBetterAuthFrontends) {
|
|
42
|
-
options.push({
|
|
43
|
-
value: "better-auth",
|
|
44
|
-
label: "Better-Auth",
|
|
45
|
-
hint: "comprehensive auth framework for TypeScript",
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
if (hasClerkCompatibleFrontends) {
|
|
50
|
-
options.push({
|
|
51
|
-
value: "clerk",
|
|
52
|
-
label: "Clerk",
|
|
53
|
-
hint: "More than auth, Complete User Management",
|
|
54
|
-
});
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
options.push({ value: "none", label: "None", hint: "No auth" });
|
|
58
|
-
|
|
59
|
-
const response = await select({
|
|
60
|
-
message: "Select authentication provider",
|
|
61
|
-
options,
|
|
62
|
-
initialValue: "none",
|
|
63
|
-
});
|
|
64
|
-
if (isCancel(response)) return exitCancelled("Operation cancelled");
|
|
65
|
-
return response as Auth;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
const response = await select({
|
|
69
|
-
message: "Select authentication provider",
|
|
70
|
-
options: [
|
|
71
|
-
{
|
|
72
|
-
value: "better-auth",
|
|
73
|
-
label: "Better-Auth",
|
|
74
|
-
hint: "comprehensive auth framework for TypeScript",
|
|
75
|
-
},
|
|
76
|
-
{ value: "none", label: "None" },
|
|
77
|
-
],
|
|
78
|
-
initialValue: DEFAULT_CONFIG.auth,
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
if (isCancel(response)) return exitCancelled("Operation cancelled");
|
|
82
|
-
|
|
83
|
-
return response as Auth;
|
|
84
|
-
}
|
package/src/prompts/backend.ts
DELETED
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
import { isCancel, select } from "@clack/prompts";
|
|
2
|
-
import { DEFAULT_CONFIG } from "../constants";
|
|
3
|
-
import type { Backend, Frontend } from "../types";
|
|
4
|
-
import { exitCancelled } from "../utils/errors";
|
|
5
|
-
|
|
6
|
-
// Temporarily restrict to Next.js and TanStack Start only for backend="self"
|
|
7
|
-
const FULLSTACK_FRONTENDS: readonly Frontend[] = [
|
|
8
|
-
"next",
|
|
9
|
-
"tanstack-start",
|
|
10
|
-
// "nuxt", // TODO: Add support in future update
|
|
11
|
-
// "svelte", // TODO: Add support in future update
|
|
12
|
-
] as const;
|
|
13
|
-
|
|
14
|
-
export async function getBackendFrameworkChoice(
|
|
15
|
-
backendFramework?: Backend,
|
|
16
|
-
frontends?: Frontend[],
|
|
17
|
-
) {
|
|
18
|
-
if (backendFramework !== undefined) return backendFramework;
|
|
19
|
-
|
|
20
|
-
const hasIncompatibleFrontend = frontends?.some((f) => f === "solid");
|
|
21
|
-
const hasFullstackFrontend = frontends?.some((f) => FULLSTACK_FRONTENDS.includes(f));
|
|
22
|
-
|
|
23
|
-
const backendOptions: Array<{
|
|
24
|
-
value: Backend;
|
|
25
|
-
label: string;
|
|
26
|
-
hint: string;
|
|
27
|
-
}> = [];
|
|
28
|
-
|
|
29
|
-
if (hasFullstackFrontend) {
|
|
30
|
-
backendOptions.push({
|
|
31
|
-
value: "self" as const,
|
|
32
|
-
label: "Self (Fullstack)",
|
|
33
|
-
hint: "Use frontend's built-in api routes",
|
|
34
|
-
});
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
backendOptions.push(
|
|
38
|
-
{
|
|
39
|
-
value: "hono" as const,
|
|
40
|
-
label: "Hono",
|
|
41
|
-
hint: "Lightweight, ultrafast web framework",
|
|
42
|
-
},
|
|
43
|
-
{
|
|
44
|
-
value: "express" as const,
|
|
45
|
-
label: "Express",
|
|
46
|
-
hint: "Fast, unopinionated, minimalist web framework for Node.js",
|
|
47
|
-
},
|
|
48
|
-
{
|
|
49
|
-
value: "fastify" as const,
|
|
50
|
-
label: "Fastify",
|
|
51
|
-
hint: "Fast, low-overhead web framework for Node.js",
|
|
52
|
-
},
|
|
53
|
-
{
|
|
54
|
-
value: "elysia" as const,
|
|
55
|
-
label: "Elysia",
|
|
56
|
-
hint: "Ergonomic web framework for building backend servers",
|
|
57
|
-
},
|
|
58
|
-
);
|
|
59
|
-
|
|
60
|
-
if (!hasIncompatibleFrontend) {
|
|
61
|
-
backendOptions.push({
|
|
62
|
-
value: "convex" as const,
|
|
63
|
-
label: "Convex",
|
|
64
|
-
hint: "Reactive backend-as-a-service platform",
|
|
65
|
-
});
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
backendOptions.push({
|
|
69
|
-
value: "none" as const,
|
|
70
|
-
label: "None",
|
|
71
|
-
hint: "No backend server",
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
const response = await select<Backend>({
|
|
75
|
-
message: "Select backend",
|
|
76
|
-
options: backendOptions,
|
|
77
|
-
initialValue: hasFullstackFrontend ? "self" : DEFAULT_CONFIG.backend,
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
if (isCancel(response)) return exitCancelled("Operation cancelled");
|
|
81
|
-
|
|
82
|
-
return response;
|
|
83
|
-
}
|
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
import { group } from "@clack/prompts";
|
|
2
|
-
import type {
|
|
3
|
-
Addons,
|
|
4
|
-
API,
|
|
5
|
-
Auth,
|
|
6
|
-
Backend,
|
|
7
|
-
Database,
|
|
8
|
-
DatabaseSetup,
|
|
9
|
-
Examples,
|
|
10
|
-
Frontend,
|
|
11
|
-
ORM,
|
|
12
|
-
PackageManager,
|
|
13
|
-
Payments,
|
|
14
|
-
ProjectConfig,
|
|
15
|
-
Runtime,
|
|
16
|
-
ServerDeploy,
|
|
17
|
-
WebDeploy,
|
|
18
|
-
} from "../types";
|
|
19
|
-
import { exitCancelled } from "../utils/errors";
|
|
20
|
-
import { getAddonsChoice } from "./addons";
|
|
21
|
-
import { getApiChoice } from "./api";
|
|
22
|
-
import { getAuthChoice } from "./auth";
|
|
23
|
-
import { getBackendFrameworkChoice } from "./backend";
|
|
24
|
-
import { getDatabaseChoice } from "./database";
|
|
25
|
-
import { getDBSetupChoice } from "./database-setup";
|
|
26
|
-
import { getExamplesChoice } from "./examples";
|
|
27
|
-
import { getFrontendChoice } from "./frontend";
|
|
28
|
-
import { getGitChoice } from "./git";
|
|
29
|
-
import { getinstallChoice } from "./install";
|
|
30
|
-
import { getORMChoice } from "./orm";
|
|
31
|
-
import { getPackageManagerChoice } from "./package-manager";
|
|
32
|
-
import { getPaymentsChoice } from "./payments";
|
|
33
|
-
import { getRuntimeChoice } from "./runtime";
|
|
34
|
-
import { getServerDeploymentChoice } from "./server-deploy";
|
|
35
|
-
import { getDeploymentChoice } from "./web-deploy";
|
|
36
|
-
|
|
37
|
-
type PromptGroupResults = {
|
|
38
|
-
frontend: Frontend[];
|
|
39
|
-
backend: Backend;
|
|
40
|
-
runtime: Runtime;
|
|
41
|
-
database: Database;
|
|
42
|
-
orm: ORM;
|
|
43
|
-
api: API;
|
|
44
|
-
auth: Auth;
|
|
45
|
-
payments: Payments;
|
|
46
|
-
addons: Addons[];
|
|
47
|
-
examples: Examples[];
|
|
48
|
-
dbSetup: DatabaseSetup;
|
|
49
|
-
git: boolean;
|
|
50
|
-
packageManager: PackageManager;
|
|
51
|
-
install: boolean;
|
|
52
|
-
webDeploy: WebDeploy;
|
|
53
|
-
serverDeploy: ServerDeploy;
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
export async function gatherConfig(
|
|
57
|
-
flags: Partial<ProjectConfig>,
|
|
58
|
-
projectName: string,
|
|
59
|
-
projectDir: string,
|
|
60
|
-
relativePath: string,
|
|
61
|
-
) {
|
|
62
|
-
const result = await group<PromptGroupResults>(
|
|
63
|
-
{
|
|
64
|
-
frontend: () => getFrontendChoice(flags.frontend, flags.backend, flags.auth),
|
|
65
|
-
backend: ({ results }) => getBackendFrameworkChoice(flags.backend, results.frontend),
|
|
66
|
-
runtime: ({ results }) => getRuntimeChoice(flags.runtime, results.backend),
|
|
67
|
-
database: ({ results }) =>
|
|
68
|
-
getDatabaseChoice(flags.database, results.backend, results.runtime),
|
|
69
|
-
orm: ({ results }) =>
|
|
70
|
-
getORMChoice(
|
|
71
|
-
flags.orm,
|
|
72
|
-
results.database !== "none",
|
|
73
|
-
results.database,
|
|
74
|
-
results.backend,
|
|
75
|
-
results.runtime,
|
|
76
|
-
),
|
|
77
|
-
api: ({ results }) =>
|
|
78
|
-
getApiChoice(flags.api, results.frontend, results.backend) as Promise<API>,
|
|
79
|
-
auth: ({ results }) => getAuthChoice(flags.auth, results.backend, results.frontend),
|
|
80
|
-
payments: ({ results }) =>
|
|
81
|
-
getPaymentsChoice(flags.payments, results.auth, results.backend, results.frontend),
|
|
82
|
-
addons: ({ results }) => getAddonsChoice(flags.addons, results.frontend, results.auth),
|
|
83
|
-
examples: ({ results }) =>
|
|
84
|
-
getExamplesChoice(
|
|
85
|
-
flags.examples,
|
|
86
|
-
results.database,
|
|
87
|
-
results.frontend,
|
|
88
|
-
results.backend,
|
|
89
|
-
results.api,
|
|
90
|
-
) as Promise<Examples[]>,
|
|
91
|
-
dbSetup: ({ results }) =>
|
|
92
|
-
getDBSetupChoice(
|
|
93
|
-
results.database ?? "none",
|
|
94
|
-
flags.dbSetup,
|
|
95
|
-
results.orm,
|
|
96
|
-
results.backend,
|
|
97
|
-
results.runtime,
|
|
98
|
-
),
|
|
99
|
-
webDeploy: ({ results }) =>
|
|
100
|
-
getDeploymentChoice(flags.webDeploy, results.runtime, results.backend, results.frontend),
|
|
101
|
-
serverDeploy: ({ results }) =>
|
|
102
|
-
getServerDeploymentChoice(
|
|
103
|
-
flags.serverDeploy,
|
|
104
|
-
results.runtime,
|
|
105
|
-
results.backend,
|
|
106
|
-
results.webDeploy,
|
|
107
|
-
),
|
|
108
|
-
git: () => getGitChoice(flags.git),
|
|
109
|
-
packageManager: () => getPackageManagerChoice(flags.packageManager),
|
|
110
|
-
install: () => getinstallChoice(flags.install),
|
|
111
|
-
},
|
|
112
|
-
{
|
|
113
|
-
onCancel: () => exitCancelled("Operation cancelled"),
|
|
114
|
-
},
|
|
115
|
-
);
|
|
116
|
-
|
|
117
|
-
return {
|
|
118
|
-
projectName: projectName,
|
|
119
|
-
projectDir: projectDir,
|
|
120
|
-
relativePath: relativePath,
|
|
121
|
-
frontend: result.frontend,
|
|
122
|
-
backend: result.backend,
|
|
123
|
-
runtime: result.runtime,
|
|
124
|
-
database: result.database,
|
|
125
|
-
orm: result.orm,
|
|
126
|
-
auth: result.auth,
|
|
127
|
-
payments: result.payments,
|
|
128
|
-
addons: result.addons,
|
|
129
|
-
examples: result.examples,
|
|
130
|
-
git: result.git,
|
|
131
|
-
packageManager: result.packageManager,
|
|
132
|
-
install: result.install,
|
|
133
|
-
dbSetup: result.dbSetup,
|
|
134
|
-
api: result.api,
|
|
135
|
-
webDeploy: result.webDeploy,
|
|
136
|
-
serverDeploy: result.serverDeploy,
|
|
137
|
-
};
|
|
138
|
-
}
|
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
import { isCancel, select } from "@clack/prompts";
|
|
2
|
-
import type { Backend, DatabaseSetup, ORM, Runtime } from "../types";
|
|
3
|
-
import { exitCancelled } from "../utils/errors";
|
|
4
|
-
|
|
5
|
-
export async function getDBSetupChoice(
|
|
6
|
-
databaseType: string,
|
|
7
|
-
dbSetup: DatabaseSetup | undefined,
|
|
8
|
-
_orm?: ORM,
|
|
9
|
-
backend?: Backend,
|
|
10
|
-
runtime?: Runtime,
|
|
11
|
-
) {
|
|
12
|
-
if (backend === "convex") {
|
|
13
|
-
return "none";
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
if (dbSetup !== undefined) return dbSetup as DatabaseSetup;
|
|
17
|
-
|
|
18
|
-
if (databaseType === "none") {
|
|
19
|
-
return "none";
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
let options: Array<{ value: DatabaseSetup; label: string; hint: string }> = [];
|
|
23
|
-
|
|
24
|
-
if (databaseType === "sqlite") {
|
|
25
|
-
options = [
|
|
26
|
-
{
|
|
27
|
-
value: "turso" as const,
|
|
28
|
-
label: "Turso",
|
|
29
|
-
hint: "SQLite for Production. Powered by libSQL",
|
|
30
|
-
},
|
|
31
|
-
...(runtime === "workers"
|
|
32
|
-
? [
|
|
33
|
-
{
|
|
34
|
-
value: "d1" as const,
|
|
35
|
-
label: "Cloudflare D1",
|
|
36
|
-
hint: "Cloudflare's managed, serverless database with SQLite's SQL semantics",
|
|
37
|
-
},
|
|
38
|
-
]
|
|
39
|
-
: []),
|
|
40
|
-
{ value: "none" as const, label: "None", hint: "Manual setup" },
|
|
41
|
-
];
|
|
42
|
-
} else if (databaseType === "postgres") {
|
|
43
|
-
options = [
|
|
44
|
-
{
|
|
45
|
-
value: "neon" as const,
|
|
46
|
-
label: "Neon Postgres",
|
|
47
|
-
hint: "Serverless Postgres with branching capability",
|
|
48
|
-
},
|
|
49
|
-
{
|
|
50
|
-
value: "planetscale" as const,
|
|
51
|
-
label: "PlanetScale",
|
|
52
|
-
hint: "Postgres & Vitess (MySQL) on NVMe",
|
|
53
|
-
},
|
|
54
|
-
{
|
|
55
|
-
value: "supabase" as const,
|
|
56
|
-
label: "Supabase",
|
|
57
|
-
hint: "Local Supabase stack (requires Docker)",
|
|
58
|
-
},
|
|
59
|
-
{
|
|
60
|
-
value: "prisma-postgres" as const,
|
|
61
|
-
label: "Prisma Postgres",
|
|
62
|
-
hint: "Instant Postgres for Global Applications",
|
|
63
|
-
},
|
|
64
|
-
{
|
|
65
|
-
value: "docker" as const,
|
|
66
|
-
label: "Docker",
|
|
67
|
-
hint: "Run locally with docker compose",
|
|
68
|
-
},
|
|
69
|
-
{ value: "none" as const, label: "None", hint: "Manual setup" },
|
|
70
|
-
];
|
|
71
|
-
} else if (databaseType === "mysql") {
|
|
72
|
-
options = [
|
|
73
|
-
{
|
|
74
|
-
value: "planetscale" as const,
|
|
75
|
-
label: "PlanetScale",
|
|
76
|
-
hint: "MySQL on Vitess (NVMe, HA)",
|
|
77
|
-
},
|
|
78
|
-
{
|
|
79
|
-
value: "docker" as const,
|
|
80
|
-
label: "Docker",
|
|
81
|
-
hint: "Run locally with docker compose",
|
|
82
|
-
},
|
|
83
|
-
{ value: "none" as const, label: "None", hint: "Manual setup" },
|
|
84
|
-
];
|
|
85
|
-
} else if (databaseType === "mongodb") {
|
|
86
|
-
options = [
|
|
87
|
-
{
|
|
88
|
-
value: "mongodb-atlas" as const,
|
|
89
|
-
label: "MongoDB Atlas",
|
|
90
|
-
hint: "The most effective way to deploy MongoDB",
|
|
91
|
-
},
|
|
92
|
-
{
|
|
93
|
-
value: "docker" as const,
|
|
94
|
-
label: "Docker",
|
|
95
|
-
hint: "Run locally with docker compose",
|
|
96
|
-
},
|
|
97
|
-
{ value: "none" as const, label: "None", hint: "Manual setup" },
|
|
98
|
-
];
|
|
99
|
-
} else {
|
|
100
|
-
return "none";
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
const response = await select<DatabaseSetup>({
|
|
104
|
-
message: `Select ${databaseType} setup option`,
|
|
105
|
-
options,
|
|
106
|
-
initialValue: "none",
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
if (isCancel(response)) return exitCancelled("Operation cancelled");
|
|
110
|
-
|
|
111
|
-
return response;
|
|
112
|
-
}
|
package/src/prompts/database.ts
DELETED
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import { isCancel, select } from "@clack/prompts";
|
|
2
|
-
import { DEFAULT_CONFIG } from "../constants";
|
|
3
|
-
import type { Backend, Database, Runtime } from "../types";
|
|
4
|
-
import { exitCancelled } from "../utils/errors";
|
|
5
|
-
|
|
6
|
-
export async function getDatabaseChoice(database?: Database, backend?: Backend, runtime?: Runtime) {
|
|
7
|
-
if (backend === "convex" || backend === "none") {
|
|
8
|
-
return "none";
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
if (database !== undefined) return database;
|
|
12
|
-
|
|
13
|
-
const databaseOptions: Array<{
|
|
14
|
-
value: Database;
|
|
15
|
-
label: string;
|
|
16
|
-
hint: string;
|
|
17
|
-
}> = [
|
|
18
|
-
{
|
|
19
|
-
value: "none",
|
|
20
|
-
label: "None",
|
|
21
|
-
hint: "No database setup",
|
|
22
|
-
},
|
|
23
|
-
{
|
|
24
|
-
value: "sqlite",
|
|
25
|
-
label: "SQLite",
|
|
26
|
-
hint: "lightweight, server-less, embedded relational database",
|
|
27
|
-
},
|
|
28
|
-
{
|
|
29
|
-
value: "postgres",
|
|
30
|
-
label: "PostgreSQL",
|
|
31
|
-
hint: "powerful, open source object-relational database system",
|
|
32
|
-
},
|
|
33
|
-
{
|
|
34
|
-
value: "mysql",
|
|
35
|
-
label: "MySQL",
|
|
36
|
-
hint: "popular open-source relational database system",
|
|
37
|
-
},
|
|
38
|
-
];
|
|
39
|
-
|
|
40
|
-
if (runtime !== "workers") {
|
|
41
|
-
databaseOptions.push({
|
|
42
|
-
value: "mongodb",
|
|
43
|
-
label: "MongoDB",
|
|
44
|
-
hint: "open-source NoSQL database that stores data in JSON-like documents called BSON",
|
|
45
|
-
});
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
const response = await select<Database>({
|
|
49
|
-
message: "Select database",
|
|
50
|
-
options: databaseOptions,
|
|
51
|
-
initialValue: DEFAULT_CONFIG.database,
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
if (isCancel(response)) return exitCancelled("Operation cancelled");
|
|
55
|
-
|
|
56
|
-
return response;
|
|
57
|
-
}
|