diff --git a/.changeset/small-llamas-dance.md b/.changeset/small-llamas-dance.md new file mode 100644 index 0000000..50f6d3a --- /dev/null +++ b/.changeset/small-llamas-dance.md @@ -0,0 +1,5 @@ +--- +"create-better-t-stack": minor +--- + +add convex for svelte diff --git a/apps/cli/src/constants.ts b/apps/cli/src/constants.ts index cfbcb13..3d12bac 100644 --- a/apps/cli/src/constants.ts +++ b/apps/cli/src/constants.ts @@ -91,7 +91,9 @@ export const dependencyVersionMap = { convex: "^1.23.0", "@convex-dev/react-query": "^0.0.0-alpha.8", + "convex-svelte": "^0.0.11", + "@tanstack/svelte-query": "^5.74.4", "@tanstack/react-query-devtools": "^5.69.0", "@tanstack/react-query": "^5.69.0", } as const; diff --git a/apps/cli/src/helpers/api-setup.ts b/apps/cli/src/helpers/api-setup.ts index 2278f37..8a440a6 100644 --- a/apps/cli/src/helpers/api-setup.ts +++ b/apps/cli/src/helpers/api-setup.ts @@ -1,5 +1,4 @@ import path from "node:path"; -import consola from "consola"; // Import consola import fs from "fs-extra"; import type { AvailableDependencies } from "../constants"; import type { ProjectConfig, ProjectFrontend } from "../types"; @@ -14,16 +13,16 @@ export async function setupApi(config: ProjectConfig): Promise { const webDirExists = await fs.pathExists(webDir); const nativeDirExists = await fs.pathExists(nativeDir); + const hasReactWeb = frontend.some((f) => + ["tanstack-router", "react-router", "tanstack-start", "next"].includes(f), + ); + const hasNuxtWeb = frontend.includes("nuxt"); + const hasSvelteWeb = frontend.includes("svelte"); + if (!isConvex && api !== "none") { const serverDir = path.join(projectDir, "apps/server"); const serverDirExists = await fs.pathExists(serverDir); - const hasReactWeb = frontend.some((f) => - ["tanstack-router", "react-router", "tanstack-start", "next"].includes(f), - ); - const hasNuxtWeb = frontend.includes("nuxt"); - const hasSvelteWeb = frontend.includes("svelte"); - if (serverDirExists) { if (api === "orpc") { await addPackageDependency({ @@ -81,6 +80,7 @@ export async function setupApi(config: ProjectConfig): Promise { "@orpc/svelte-query", "@orpc/client", "@orpc/server", + "@tanstack/svelte-query", ], projectDir: webDir, }); @@ -153,7 +153,6 @@ export async function setupApi(config: ProjectConfig): Promise { } else { } } - } else if (needsReactQuery && isConvex) { } if (isConvex) { @@ -165,6 +164,9 @@ export async function setupApi(config: ProjectConfig): Promise { if (frontend.includes("tanstack-start")) { webDepsToAdd.push("@convex-dev/react-query"); } + if (hasSvelteWeb) { + webDepsToAdd.push("convex-svelte"); + } await addPackageDependency({ dependencies: webDepsToAdd, diff --git a/apps/cli/src/helpers/template-manager.ts b/apps/cli/src/helpers/template-manager.ts index 89693e1..b285a94 100644 --- a/apps/cli/src/helpers/template-manager.ts +++ b/apps/cli/src/helpers/template-manager.ts @@ -578,32 +578,28 @@ export async function setupExamplesTemplate( } } } else if (hasNuxtWeb) { - if (context.api === "orpc") { - const exampleWebNuxtSrc = path.join(exampleBaseDir, "web/nuxt"); - if (await fs.pathExists(exampleWebNuxtSrc)) { - await processAndCopyFiles( - "**/*", - exampleWebNuxtSrc, - webAppDir, - context, - false, - ); - } else { - } + const exampleWebNuxtSrc = path.join(exampleBaseDir, "web/nuxt"); + if (await fs.pathExists(exampleWebNuxtSrc)) { + await processAndCopyFiles( + "**/*", + exampleWebNuxtSrc, + webAppDir, + context, + false, + ); + } else { } } else if (hasSvelteWeb) { - if (context.api === "orpc") { - const exampleWebSvelteSrc = path.join(exampleBaseDir, "web/svelte"); - if (await fs.pathExists(exampleWebSvelteSrc)) { - await processAndCopyFiles( - "**/*", - exampleWebSvelteSrc, - webAppDir, - context, - false, - ); - } else { - } + const exampleWebSvelteSrc = path.join(exampleBaseDir, "web/svelte"); + if (await fs.pathExists(exampleWebSvelteSrc)) { + await processAndCopyFiles( + "**/*", + exampleWebSvelteSrc, + webAppDir, + context, + false, + ); + } else { } } } diff --git a/apps/cli/templates/examples/todo/web/svelte/src/routes/todos/+page.svelte b/apps/cli/templates/examples/todo/web/svelte/src/routes/todos/+page.svelte deleted file mode 100644 index 22023bb..0000000 --- a/apps/cli/templates/examples/todo/web/svelte/src/routes/todos/+page.svelte +++ /dev/null @@ -1,150 +0,0 @@ - - -
-

Todos

- -
- - -
- - {#if isLoadingTodos} -

Loading...

- {:else if !hasTodos} -

No todos yet.

- {:else} -
    - {#each todos as todo (todo.id)} - {@const isToggling = $toggleMutation.isPending && $toggleMutation.variables?.id === todo.id} - {@const isDeleting = $deleteMutation.isPending && $deleteMutation.variables?.id === todo.id} - {@const isDisabled = isToggling || isDeleting} -
  • -
    - handleToggleTodo(todo.id, todo.completed)} - disabled={isDisabled} - /> - -
    - -
  • - {/each} -
- {/if} - - {#if $todosQuery.isError} -

- Error loading: {$todosQuery.error?.message ?? 'Unknown error'} -

- {/if} - {#if $addMutation.isError} -

- Error adding: {$addMutation.error?.message ?? 'Unknown error'} -

- {/if} - {#if $toggleMutation.isError} -

- Error updating: {$toggleMutation.error?.message ?? 'Unknown error'} -

- {/if} - {#if $deleteMutation.isError} -

- Error deleting: {$deleteMutation.error?.message ?? 'Unknown error'} -

- {/if} -
diff --git a/apps/cli/templates/examples/todo/web/svelte/src/routes/todos/+page.svelte.hbs b/apps/cli/templates/examples/todo/web/svelte/src/routes/todos/+page.svelte.hbs new file mode 100644 index 0000000..f2fe062 --- /dev/null +++ b/apps/cli/templates/examples/todo/web/svelte/src/routes/todos/+page.svelte.hbs @@ -0,0 +1,357 @@ +{{#if (eq backend "convex")}} + + +
+

Todos (Convex)

+ +
+ + +
+ + {#if isLoadingTodos} +

Loading...

+ {:else if !hasTodos} +

No todos yet.

+ {:else} +
    + {#each todos as todo (todo._id)} + {@const isTogglingThis = togglingId === todo._id} + {@const isDeletingThis = deletingId === todo._id} + {@const isDisabled = isTogglingThis || isDeletingThis} +
  • +
    + handleToggleTodo(todo._id, todo.completed)} + disabled={isDisabled} + /> + +
    + +
  • + {/each} +
+ {/if} + + {#if todosQuery.error} +

+ Error loading: {todosQuery.error?.message ?? 'Unknown error'} +

+ {/if} + {#if addError} +

+ Error adding: {addError.message ?? 'Unknown error'} +

+ {/if} + {#if toggleError} +

+ Error updating: {toggleError.message ?? 'Unknown error'} +

+ {/if} + {#if deleteError} +

+ Error deleting: {deleteError.message ?? 'Unknown error'} +

+ {/if} +
+{{else}} + + +
+

Todos{{#if (eq api "trpc")}} (tRPC){{/if}}{{#if (eq api "orpc")}} (oRPC){{/if}}

+ +
+ + +
+ + {#if isLoadingTodos} +

Loading...

+ {:else if !hasTodos} +

No todos yet.

+ {:else} +
    + {#each todos as todo (todo.id)} + {@const isToggling = $toggleMutation.isPending && $toggleMutation.variables?.id === todo.id} + {@const isDeleting = $deleteMutation.isPending && $deleteMutation.variables?.id === todo.id} + {@const isDisabled = isToggling || isDeleting} +
  • +
    + handleToggleTodo(todo.id, todo.completed)} + disabled={isDisabled} + /> + +
    + +
  • + {/each} +
+ {/if} + + {#if $todosQuery.isError} +

+ Error loading: {$todosQuery.error?.message ?? 'Unknown error'} +

+ {/if} + {#if $addMutation.isError} +

+ Error adding: {$addMutation.error?.message ?? 'Unknown error'} +

+ {/if} + {#if $toggleMutation.isError} +

+ Error updating: {$toggleMutation.error?.message ?? 'Unknown error'} +

+ {/if} + {#if $deleteMutation.isError} +

+ Error deleting: {$deleteMutation.error?.message ?? 'Unknown error'} +

+ {/if} +
+{{/if}} diff --git a/apps/cli/templates/frontend/svelte/src/routes/+layout.svelte.hbs b/apps/cli/templates/frontend/svelte/src/routes/+layout.svelte.hbs index e45c81d..b8e895d 100644 --- a/apps/cli/templates/frontend/svelte/src/routes/+layout.svelte.hbs +++ b/apps/cli/templates/frontend/svelte/src/routes/+layout.svelte.hbs @@ -1,8 +1,31 @@ +{{#if (eq backend "convex")}} + + +
+
+
+ {@render children()} +
+
+{{else}} + +
+
{TITLE_TEXT}
+
+
+

API Status{{#if (eq api "trpc")}} (tRPC){{/if}}{{#if (eq api "orpc")}} (oRPC){{/if}}

+{{/if}}