mirror of
https://github.com/FranP-code/create-better-t-stack.git
synced 2025-10-12 23:52:15 +00:00
add solid
This commit is contained in:
@@ -17,13 +17,15 @@ export async function getAddonsChoice(
|
||||
|
||||
const hasCompatiblePwaFrontend =
|
||||
frontends?.includes("react-router") ||
|
||||
frontends?.includes("tanstack-router");
|
||||
frontends?.includes("tanstack-router") ||
|
||||
frontends?.includes("solid");
|
||||
|
||||
const hasCompatibleTauriFrontend =
|
||||
frontends?.includes("react-router") ||
|
||||
frontends?.includes("tanstack-router") ||
|
||||
frontends?.includes("nuxt") ||
|
||||
frontends?.includes("svelte");
|
||||
frontends?.includes("svelte") ||
|
||||
frontends?.includes("solid");
|
||||
|
||||
const allPossibleOptions: AddonOption[] = [
|
||||
{
|
||||
|
||||
@@ -16,6 +16,7 @@ export async function getApiChoice(
|
||||
|
||||
const includesNuxt = frontend?.includes("nuxt");
|
||||
const includesSvelte = frontend?.includes("svelte");
|
||||
const includesSolid = frontend?.includes("solid");
|
||||
|
||||
let apiOptions = [
|
||||
{
|
||||
@@ -30,13 +31,13 @@ export async function getApiChoice(
|
||||
},
|
||||
];
|
||||
|
||||
if (includesNuxt || includesSvelte) {
|
||||
if (includesNuxt || includesSvelte || includesSolid) {
|
||||
apiOptions = [
|
||||
{
|
||||
value: "orpc" as const,
|
||||
label: "oRPC",
|
||||
hint: `End-to-end type-safe APIs (Required for ${
|
||||
includesNuxt ? "Nuxt" : "Svelte"
|
||||
includesNuxt ? "Nuxt" : includesSvelte ? "Svelte" : "Solid"
|
||||
} frontend)`,
|
||||
},
|
||||
];
|
||||
@@ -45,7 +46,10 @@ export async function getApiChoice(
|
||||
const apiType = await select<ProjectApi>({
|
||||
message: "Select API type",
|
||||
options: apiOptions,
|
||||
initialValue: includesNuxt || includesSvelte ? "orpc" : DEFAULT_CONFIG.api,
|
||||
initialValue:
|
||||
includesNuxt || includesSvelte || includesSolid
|
||||
? "orpc"
|
||||
: DEFAULT_CONFIG.api,
|
||||
});
|
||||
|
||||
if (isCancel(apiType)) {
|
||||
@@ -53,7 +57,7 @@ export async function getApiChoice(
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
if ((includesNuxt || includesSvelte) && apiType !== "orpc") {
|
||||
if ((includesNuxt || includesSvelte || includesSolid) && apiType !== "orpc") {
|
||||
return "orpc";
|
||||
}
|
||||
|
||||
|
||||
@@ -1,43 +1,62 @@
|
||||
import { cancel, isCancel, select } from "@clack/prompts";
|
||||
import pc from "picocolors";
|
||||
import { DEFAULT_CONFIG } from "../constants";
|
||||
import type { ProjectBackend } from "../types";
|
||||
import type { ProjectBackend, ProjectFrontend } from "../types";
|
||||
|
||||
export async function getBackendFrameworkChoice(
|
||||
backendFramework?: ProjectBackend,
|
||||
frontends?: ProjectFrontend[],
|
||||
): Promise<ProjectBackend> {
|
||||
if (backendFramework !== undefined) return backendFramework;
|
||||
|
||||
const hasIncompatibleFrontend = frontends?.some(
|
||||
(f) => f === "nuxt" || f === "solid",
|
||||
);
|
||||
|
||||
const backendOptions: Array<{
|
||||
value: ProjectBackend;
|
||||
label: string;
|
||||
hint: string;
|
||||
}> = [
|
||||
{
|
||||
value: "hono" as const,
|
||||
label: "Hono",
|
||||
hint: "Lightweight, ultrafast web framework",
|
||||
},
|
||||
{
|
||||
value: "next" as const,
|
||||
label: "Next.js",
|
||||
hint: "Full-stack framework with API routes",
|
||||
},
|
||||
{
|
||||
value: "express" as const,
|
||||
label: "Express",
|
||||
hint: "Fast, unopinionated, minimalist web framework for Node.js",
|
||||
},
|
||||
{
|
||||
value: "elysia" as const,
|
||||
label: "Elysia",
|
||||
hint: "Ergonomic web framework for building backend servers",
|
||||
},
|
||||
];
|
||||
|
||||
if (!hasIncompatibleFrontend) {
|
||||
backendOptions.push({
|
||||
value: "convex" as const,
|
||||
label: "Convex",
|
||||
hint: "Reactive backend-as-a-service platform",
|
||||
});
|
||||
}
|
||||
|
||||
let initialValue = DEFAULT_CONFIG.backend;
|
||||
if (hasIncompatibleFrontend && initialValue === "convex") {
|
||||
initialValue = "hono";
|
||||
}
|
||||
|
||||
const response = await select<ProjectBackend>({
|
||||
message: "Select backend framework",
|
||||
options: [
|
||||
{
|
||||
value: "hono",
|
||||
label: "Hono",
|
||||
hint: "Lightweight, ultrafast web framework",
|
||||
},
|
||||
{
|
||||
value: "next",
|
||||
label: "Next.js",
|
||||
hint: "Full-stack framework with API routes",
|
||||
},
|
||||
{
|
||||
value: "express",
|
||||
label: "Express",
|
||||
hint: "Fast, unopinionated, minimalist web framework for Node.js",
|
||||
},
|
||||
{
|
||||
value: "elysia",
|
||||
label: "Elysia",
|
||||
hint: "Ergonomic web framework for building backend servers",
|
||||
},
|
||||
{
|
||||
value: "convex",
|
||||
label: "Convex",
|
||||
hint: "Reactive backend-as-a-service platform",
|
||||
},
|
||||
],
|
||||
initialValue: DEFAULT_CONFIG.backend,
|
||||
options: backendOptions,
|
||||
initialValue,
|
||||
});
|
||||
|
||||
if (isCancel(response)) {
|
||||
|
||||
@@ -53,8 +53,10 @@ export async function gatherConfig(
|
||||
projectName: async () => {
|
||||
return getProjectName(flags.projectName);
|
||||
},
|
||||
frontend: () => getFrontendChoice(flags.frontend),
|
||||
backend: () => getBackendFrameworkChoice(flags.backend),
|
||||
frontend: ({ results }) =>
|
||||
getFrontendChoice(flags.frontend, flags.backend),
|
||||
backend: ({ results }) =>
|
||||
getBackendFrameworkChoice(flags.backend, results.frontend),
|
||||
runtime: ({ results }) =>
|
||||
getRuntimeChoice(flags.runtime, results.backend),
|
||||
database: ({ results }) =>
|
||||
|
||||
@@ -37,6 +37,7 @@ export async function getExamplesChoice(
|
||||
"next",
|
||||
"nuxt",
|
||||
"svelte",
|
||||
"solid",
|
||||
].includes(f),
|
||||
) ?? false;
|
||||
const noFrontendSelected = !frontends || frontends.length === 0;
|
||||
@@ -52,7 +53,7 @@ export async function getExamplesChoice(
|
||||
},
|
||||
];
|
||||
|
||||
if (backend !== "elysia") {
|
||||
if (backend !== "elysia" && !frontends?.includes("solid")) {
|
||||
options.push({
|
||||
value: "ai" as const,
|
||||
label: "AI Chat",
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { cancel, isCancel, multiselect, select } from "@clack/prompts";
|
||||
import pc from "picocolors";
|
||||
import { DEFAULT_CONFIG } from "../constants";
|
||||
import type { ProjectFrontend } from "../types";
|
||||
import type { ProjectBackend, ProjectFrontend } from "../types";
|
||||
|
||||
export async function getFrontendChoice(
|
||||
frontendOptions?: ProjectFrontend[],
|
||||
backend?: ProjectBackend,
|
||||
): Promise<ProjectFrontend[]> {
|
||||
if (frontendOptions !== undefined) return frontendOptions;
|
||||
|
||||
@@ -23,17 +24,7 @@ export async function getFrontendChoice(
|
||||
},
|
||||
],
|
||||
required: false,
|
||||
initialValues: DEFAULT_CONFIG.frontend.some(
|
||||
(f) =>
|
||||
f === "tanstack-router" ||
|
||||
f === "react-router" ||
|
||||
f === "tanstack-start" ||
|
||||
f === "next" ||
|
||||
f === "nuxt" ||
|
||||
f === "svelte",
|
||||
)
|
||||
? ["web"]
|
||||
: [],
|
||||
initialValues: ["web"],
|
||||
});
|
||||
|
||||
if (isCancel(frontendTypes)) {
|
||||
@@ -44,50 +35,55 @@ export async function getFrontendChoice(
|
||||
const result: ProjectFrontend[] = [];
|
||||
|
||||
if (frontendTypes.includes("web")) {
|
||||
const allWebOptions = [
|
||||
{
|
||||
value: "tanstack-router" as const,
|
||||
label: "TanStack Router",
|
||||
hint: "Modern and scalable routing for React Applications",
|
||||
},
|
||||
{
|
||||
value: "react-router" as const,
|
||||
label: "React Router",
|
||||
hint: "A user‑obsessed, standards‑focused, multi‑strategy router",
|
||||
},
|
||||
{
|
||||
value: "next" as const,
|
||||
label: "Next.js",
|
||||
hint: "The React Framework for the Web",
|
||||
},
|
||||
{
|
||||
value: "nuxt" as const,
|
||||
label: "Nuxt",
|
||||
hint: "The Progressive Web Framework for Vue.js",
|
||||
},
|
||||
{
|
||||
value: "svelte" as const,
|
||||
label: "Svelte",
|
||||
hint: "web development for the rest of us",
|
||||
},
|
||||
{
|
||||
value: "solid" as const,
|
||||
label: "Solid",
|
||||
hint: "Simple and performant reactivity for building user interfaces",
|
||||
},
|
||||
{
|
||||
value: "tanstack-start" as const,
|
||||
label: "TanStack Start (beta)",
|
||||
hint: "SSR, Server Functions, API Routes and more with TanStack Router",
|
||||
},
|
||||
];
|
||||
|
||||
const webOptions = allWebOptions.filter((option) => {
|
||||
if (backend === "convex") {
|
||||
return option.value !== "nuxt" && option.value !== "solid";
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
const webFramework = await select<ProjectFrontend>({
|
||||
message: "Choose frontend framework",
|
||||
options: [
|
||||
{
|
||||
value: "tanstack-router",
|
||||
label: "TanStack Router",
|
||||
hint: "Modern and scalable routing for React Applications",
|
||||
},
|
||||
{
|
||||
value: "react-router",
|
||||
label: "React Router",
|
||||
hint: "A user‑obsessed, standards‑focused, multi‑strategy router",
|
||||
},
|
||||
{
|
||||
value: "next",
|
||||
label: "Next.js",
|
||||
hint: "The React Framework for the Web",
|
||||
},
|
||||
{
|
||||
value: "nuxt",
|
||||
label: "Nuxt",
|
||||
hint: "The Progressive Web Framework for Vue.js",
|
||||
},
|
||||
{
|
||||
value: "svelte",
|
||||
label: "Svelte",
|
||||
hint: "web development for the rest of us",
|
||||
},
|
||||
{
|
||||
value: "tanstack-start",
|
||||
label: "TanStack Start (beta)",
|
||||
hint: "SSR, Server Functions, API Routes and more with TanStack Router",
|
||||
},
|
||||
],
|
||||
initialValue:
|
||||
DEFAULT_CONFIG.frontend.find(
|
||||
(f) =>
|
||||
f === "tanstack-router" ||
|
||||
f === "react-router" ||
|
||||
f === "tanstack-start" ||
|
||||
f === "next" ||
|
||||
f === "nuxt" ||
|
||||
f === "svelte",
|
||||
) || "tanstack-router",
|
||||
options: webOptions,
|
||||
initialValue: DEFAULT_CONFIG.frontend[0],
|
||||
});
|
||||
|
||||
if (isCancel(webFramework)) {
|
||||
|
||||
Reference in New Issue
Block a user