@tanstack/create 0.49.1 → 0.49.3
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/CHANGELOG.md +13 -0
- package/LICENSE +21 -0
- package/dist/file-helpers.js +3 -1
- package/dist/frameworks/react/add-ons/ai/assets/src/data/demo-guitars.ts +93 -0
- package/dist/frameworks/react/add-ons/ai/assets/src/hooks/demo-useAudioRecorder.ts +85 -0
- package/dist/frameworks/react/add-ons/ai/assets/src/hooks/demo-useTTS.ts +78 -0
- package/dist/frameworks/react/add-ons/ai/assets/src/lib/demo-ai-hook.ts +22 -0
- package/dist/frameworks/react/add-ons/ai/assets/src/lib/demo-guitar-tools.ts +40 -0
- package/dist/frameworks/react/add-ons/ai/assets/src/routes/demo/api.ai.chat.ts +99 -0
- package/dist/frameworks/react/add-ons/ai/assets/src/routes/demo/api.ai.image.ts +72 -0
- package/dist/frameworks/react/add-ons/ai/assets/src/routes/demo/api.ai.structured.ts +136 -0
- package/dist/frameworks/react/add-ons/ai/assets/src/routes/demo/api.ai.transcription.ts +89 -0
- package/dist/frameworks/react/add-ons/ai/assets/src/routes/demo/api.ai.tts.ts +81 -0
- package/dist/frameworks/react/add-ons/better-auth/assets/src/lib/auth-client.ts +3 -0
- package/dist/frameworks/react/add-ons/better-auth/assets/src/lib/auth.ts +9 -0
- package/dist/frameworks/react/add-ons/better-auth/assets/src/routes/api/auth/$.ts +11 -0
- package/dist/frameworks/react/add-ons/convex/assets/convex/schema.ts +14 -0
- package/dist/frameworks/react/add-ons/convex/assets/convex/todos.ts +43 -0
- package/dist/frameworks/react/add-ons/db/assets/src/db-collections/index.ts +20 -0
- package/dist/frameworks/react/add-ons/db/assets/src/hooks/demo.useChat.ts +62 -0
- package/dist/frameworks/react/add-ons/db/assets/src/routes/demo/db-chat-api.ts +83 -0
- package/dist/frameworks/react/add-ons/form/assets/src/hooks/demo.form-context.ts +4 -0
- package/dist/frameworks/react/add-ons/form/assets/src/hooks/demo.form.ts +22 -0
- package/dist/frameworks/react/add-ons/mcp/assets/src/mcp-todos.ts +51 -0
- package/dist/frameworks/react/add-ons/mcp/assets/src/routes/demo/api.mcp-todos.ts +37 -0
- package/dist/frameworks/react/add-ons/mcp/assets/src/routes/{mcp.js → mcp.ts} +27 -17
- package/dist/frameworks/react/add-ons/mcp/assets/src/utils/mcp-handler.ts +61 -0
- package/dist/frameworks/react/add-ons/neon/assets/neon-vite-plugin.ts +10 -0
- package/dist/frameworks/react/add-ons/neon/assets/src/db.ts +13 -0
- package/dist/frameworks/react/add-ons/oRPC/assets/src/orpc/client.ts +29 -0
- package/dist/frameworks/react/add-ons/oRPC/assets/src/orpc/router/index.ts +6 -0
- package/dist/frameworks/react/add-ons/oRPC/assets/src/orpc/router/todos.ts +20 -0
- package/dist/frameworks/react/add-ons/oRPC/assets/src/orpc/schema.ts +6 -0
- package/dist/frameworks/react/add-ons/oRPC/assets/src/{polyfill.js → polyfill.ts} +4 -1
- package/dist/frameworks/react/add-ons/oRPC/assets/src/routes/api.$.ts +77 -0
- package/dist/frameworks/react/add-ons/oRPC/assets/src/routes/api.rpc.$.ts +29 -0
- package/dist/frameworks/react/add-ons/shadcn/assets/src/lib/utils.ts +6 -0
- package/dist/frameworks/react/add-ons/start/assets/src/data/demo.punk-songs.ts +13 -0
- package/dist/frameworks/react/add-ons/start/assets/src/routes/demo/api.names.ts +10 -0
- package/dist/frameworks/react/add-ons/store/assets/src/lib/demo-store.ts +13 -0
- package/dist/frameworks/react/add-ons/storybook/assets/_dot_storybook/main.ts +17 -0
- package/dist/frameworks/react/add-ons/storybook/assets/_dot_storybook/preview.ts +15 -0
- package/dist/frameworks/react/add-ons/storybook/assets/src/components/storybook/button.stories.ts +67 -0
- package/dist/{types/frameworks/react/add-ons/storybook/assets/src/components/storybook/index.d.ts → frameworks/react/add-ons/storybook/assets/src/components/storybook/index.ts} +4 -0
- package/dist/frameworks/react/add-ons/storybook/assets/src/components/storybook/input.stories.ts +43 -0
- package/dist/frameworks/react/add-ons/storybook/assets/src/components/storybook/radio-group.stories.ts +53 -0
- package/dist/frameworks/react/add-ons/storybook/assets/src/components/storybook/slider.stories.ts +55 -0
- package/dist/frameworks/{solid/add-ons/strapi/assets/src/lib/strapiClient.js → react/add-ons/strapi/assets/src/lib/strapiClient.ts} +3 -1
- package/dist/frameworks/react/add-ons/t3env/assets/src/env.ts +39 -0
- package/dist/frameworks/react/add-ons/tRPC/assets/src/integrations/trpc/{init.js → init.ts} +3 -1
- package/dist/frameworks/react/add-ons/tRPC/assets/src/integrations/trpc/react.ts +4 -0
- package/dist/frameworks/react/add-ons/tRPC/assets/src/integrations/trpc/router.ts +27 -0
- package/dist/frameworks/react/add-ons/table/assets/src/data/demo-table-data.ts +50 -0
- package/dist/frameworks/react/examples/events/assets/content-collections.ts +56 -0
- package/dist/frameworks/react/examples/events/assets/src/lib/conference-ai-hook.ts +26 -0
- package/dist/frameworks/react/examples/events/assets/src/lib/conference-tools.ts +210 -0
- package/dist/frameworks/react/examples/events/assets/src/lib/utils.ts +6 -0
- package/dist/frameworks/react/examples/events/assets/src/routes/api.remy-chat.ts +121 -0
- package/dist/frameworks/react/examples/resume/assets/content-collections.ts +36 -0
- package/dist/frameworks/react/examples/resume/assets/src/lib/resume-ai-hook.ts +21 -0
- package/dist/frameworks/react/examples/resume/assets/src/lib/resume-tools.ts +165 -0
- package/dist/frameworks/react/examples/resume/assets/src/lib/utils.ts +6 -0
- package/dist/frameworks/react/examples/resume/assets/src/routes/api.resume-chat.ts +110 -0
- package/dist/frameworks/solid/add-ons/better-auth/assets/src/lib/auth-client.ts +3 -0
- package/dist/frameworks/solid/add-ons/better-auth/assets/src/lib/auth.ts +9 -0
- package/dist/frameworks/solid/add-ons/better-auth/assets/src/routes/api/auth/$.ts +11 -0
- package/dist/frameworks/solid/add-ons/convex/assets/convex/schema.ts +14 -0
- package/dist/frameworks/solid/add-ons/convex/assets/convex/todos.ts +43 -0
- package/dist/frameworks/solid/add-ons/solid-ui/assets/src/lib/utils.ts +6 -0
- package/dist/frameworks/solid/add-ons/store/assets/src/lib/demo-store.ts +13 -0
- package/dist/frameworks/{react/add-ons/strapi/assets/src/lib/strapiClient.js → solid/add-ons/strapi/assets/src/lib/strapiClient.ts} +3 -1
- package/dist/frameworks/solid/add-ons/t3env/assets/src/env.ts +39 -0
- package/dist/frameworks/solid/examples/tanchat/assets/ai-streaming-server/src/index.ts +102 -0
- package/dist/frameworks/solid/examples/tanchat/assets/src/lib/demo-store.ts +13 -0
- package/dist/frameworks/solid/examples/tanchat/assets/src/store/demo.hooks.ts +17 -0
- package/dist/frameworks/solid/examples/tanchat/assets/src/store/demo.store.ts +133 -0
- package/dist/special-steps/post-init-script.js +6 -6
- package/package.json +11 -12
- package/src/file-helpers.ts +4 -1
- package/src/special-steps/post-init-script.ts +6 -6
- package/tests/copy-assets.test.ts +53 -0
- package/tests/file-helper.test.ts +19 -0
- package/tests/special-steps.test.ts +12 -12
- package/dist/frameworks/react/add-ons/ai/assets/src/data/demo-guitars.js +0 -67
- package/dist/frameworks/react/add-ons/ai/assets/src/hooks/demo-useAudioRecorder.js +0 -70
- package/dist/frameworks/react/add-ons/ai/assets/src/hooks/demo-useTTS.js +0 -66
- package/dist/frameworks/react/add-ons/ai/assets/src/lib/demo-ai-hook.js +0 -11
- package/dist/frameworks/react/add-ons/ai/assets/src/lib/demo-guitar-tools.js +0 -32
- package/dist/frameworks/react/add-ons/ai/assets/src/routes/demo/api.ai.chat.js +0 -87
- package/dist/frameworks/react/add-ons/ai/assets/src/routes/demo/api.ai.image.js +0 -55
- package/dist/frameworks/react/add-ons/ai/assets/src/routes/demo/api.ai.structured.js +0 -116
- package/dist/frameworks/react/add-ons/ai/assets/src/routes/demo/api.ai.transcription.js +0 -73
- package/dist/frameworks/react/add-ons/ai/assets/src/routes/demo/api.ai.tts.js +0 -58
- package/dist/frameworks/react/add-ons/better-auth/assets/src/lib/auth-client.js +0 -2
- package/dist/frameworks/react/add-ons/better-auth/assets/src/lib/auth.js +0 -8
- package/dist/frameworks/react/add-ons/better-auth/assets/src/routes/api/auth/$.js +0 -10
- package/dist/frameworks/react/add-ons/convex/assets/convex/schema.js +0 -13
- package/dist/frameworks/react/add-ons/convex/assets/convex/todos.js +0 -39
- package/dist/frameworks/react/add-ons/db/assets/src/db-collections/index.js +0 -11
- package/dist/frameworks/react/add-ons/db/assets/src/hooks/demo.useChat.js +0 -47
- package/dist/frameworks/react/add-ons/db/assets/src/routes/demo/db-chat-api.js +0 -68
- package/dist/frameworks/react/add-ons/form/assets/src/hooks/demo.form-context.js +0 -2
- package/dist/frameworks/react/add-ons/form/assets/src/hooks/demo.form.js +0 -15
- package/dist/frameworks/react/add-ons/mcp/assets/src/mcp-todos.js +0 -40
- package/dist/frameworks/react/add-ons/mcp/assets/src/routes/demo/api.mcp-todos.js +0 -36
- package/dist/frameworks/react/add-ons/mcp/assets/src/utils/mcp-handler.js +0 -41
- package/dist/frameworks/react/add-ons/neon/assets/neon-vite-plugin.js +0 -9
- package/dist/frameworks/react/add-ons/neon/assets/src/db.js +0 -11
- package/dist/frameworks/react/add-ons/oRPC/assets/src/orpc/client.js +0 -21
- package/dist/frameworks/react/add-ons/oRPC/assets/src/orpc/router/index.js +0 -5
- package/dist/frameworks/react/add-ons/oRPC/assets/src/orpc/router/todos.js +0 -17
- package/dist/frameworks/react/add-ons/oRPC/assets/src/orpc/schema.js +0 -5
- package/dist/frameworks/react/add-ons/oRPC/assets/src/routes/api.$.js +0 -71
- package/dist/frameworks/react/add-ons/oRPC/assets/src/routes/api.rpc.$.js +0 -24
- package/dist/frameworks/react/add-ons/shadcn/assets/src/lib/utils.js +0 -5
- package/dist/frameworks/react/add-ons/start/assets/src/data/demo.punk-songs.js +0 -12
- package/dist/frameworks/react/add-ons/start/assets/src/routes/demo/api.names.js +0 -9
- package/dist/frameworks/react/add-ons/store/assets/src/lib/demo-store.js +0 -10
- package/dist/frameworks/react/add-ons/storybook/assets/_dot_storybook/main.js +0 -15
- package/dist/frameworks/react/add-ons/storybook/assets/_dot_storybook/preview.js +0 -12
- package/dist/frameworks/react/add-ons/storybook/assets/src/components/storybook/button.stories.js +0 -55
- package/dist/frameworks/react/add-ons/storybook/assets/src/components/storybook/index.js +0 -5
- package/dist/frameworks/react/add-ons/storybook/assets/src/components/storybook/input.stories.js +0 -35
- package/dist/frameworks/react/add-ons/storybook/assets/src/components/storybook/radio-group.stories.js +0 -45
- package/dist/frameworks/react/add-ons/storybook/assets/src/components/storybook/slider.stories.js +0 -46
- package/dist/frameworks/react/add-ons/t3env/assets/src/env.js +0 -34
- package/dist/frameworks/react/add-ons/tRPC/assets/src/integrations/trpc/react.js +0 -2
- package/dist/frameworks/react/add-ons/tRPC/assets/src/integrations/trpc/router.js +0 -20
- package/dist/frameworks/react/add-ons/table/assets/src/data/demo-table-data.js +0 -35
- package/dist/frameworks/react/examples/events/assets/content-collections.js +0 -53
- package/dist/frameworks/react/examples/events/assets/src/lib/conference-ai-hook.js +0 -16
- package/dist/frameworks/react/examples/events/assets/src/lib/conference-tools.js +0 -177
- package/dist/frameworks/react/examples/events/assets/src/lib/utils.js +0 -5
- package/dist/frameworks/react/examples/events/assets/src/routes/api.remy-chat.js +0 -103
- package/dist/frameworks/react/examples/resume/assets/content-collections.js +0 -33
- package/dist/frameworks/react/examples/resume/assets/src/lib/resume-ai-hook.js +0 -11
- package/dist/frameworks/react/examples/resume/assets/src/lib/resume-tools.js +0 -135
- package/dist/frameworks/react/examples/resume/assets/src/lib/utils.js +0 -5
- package/dist/frameworks/react/examples/resume/assets/src/routes/api.resume-chat.js +0 -92
- package/dist/frameworks/solid/add-ons/better-auth/assets/src/lib/auth-client.js +0 -2
- package/dist/frameworks/solid/add-ons/better-auth/assets/src/lib/auth.js +0 -8
- package/dist/frameworks/solid/add-ons/better-auth/assets/src/routes/api/auth/$.js +0 -10
- package/dist/frameworks/solid/add-ons/convex/assets/convex/schema.js +0 -13
- package/dist/frameworks/solid/add-ons/convex/assets/convex/todos.js +0 -39
- package/dist/frameworks/solid/add-ons/solid-ui/assets/src/lib/utils.js +0 -5
- package/dist/frameworks/solid/add-ons/store/assets/src/lib/demo-store.js +0 -10
- package/dist/frameworks/solid/add-ons/t3env/assets/src/env.js +0 -34
- package/dist/frameworks/solid/examples/tanchat/assets/ai-streaming-server/src/index.js +0 -73
- package/dist/frameworks/solid/examples/tanchat/assets/src/lib/demo-store.js +0 -10
- package/dist/frameworks/solid/examples/tanchat/assets/src/store/demo.hooks.js +0 -12
- package/dist/frameworks/solid/examples/tanchat/assets/src/store/demo.store.js +0 -92
- package/dist/types/frameworks/react/add-ons/ai/assets/src/data/demo-guitars.d.ts +0 -10
- package/dist/types/frameworks/react/add-ons/ai/assets/src/hooks/demo-useAudioRecorder.d.ts +0 -9
- package/dist/types/frameworks/react/add-ons/ai/assets/src/hooks/demo-useTTS.d.ts +0 -8
- package/dist/types/frameworks/react/add-ons/ai/assets/src/lib/demo-ai-hook.d.ts +0 -5
- package/dist/types/frameworks/react/add-ons/ai/assets/src/lib/demo-guitar-tools.d.ts +0 -3
- package/dist/types/frameworks/react/add-ons/ai/assets/src/routes/demo/api.ai.chat.d.ts +0 -1
- package/dist/types/frameworks/react/add-ons/ai/assets/src/routes/demo/api.ai.image.d.ts +0 -1
- package/dist/types/frameworks/react/add-ons/ai/assets/src/routes/demo/api.ai.structured.d.ts +0 -83
- package/dist/types/frameworks/react/add-ons/ai/assets/src/routes/demo/api.ai.transcription.d.ts +0 -1
- package/dist/types/frameworks/react/add-ons/ai/assets/src/routes/demo/api.ai.tts.d.ts +0 -1
- package/dist/types/frameworks/react/add-ons/better-auth/assets/src/lib/auth-client.d.ts +0 -1
- package/dist/types/frameworks/react/add-ons/better-auth/assets/src/lib/auth.d.ts +0 -1
- package/dist/types/frameworks/react/add-ons/better-auth/assets/src/routes/api/auth/$.d.ts +0 -1
- package/dist/types/frameworks/react/add-ons/convex/assets/convex/schema.d.ts +0 -2
- package/dist/types/frameworks/react/add-ons/convex/assets/convex/todos.d.ts +0 -4
- package/dist/types/frameworks/react/add-ons/db/assets/src/db-collections/index.d.ts +0 -17
- package/dist/types/frameworks/react/add-ons/db/assets/src/hooks/demo.useChat.d.ts +0 -5
- package/dist/types/frameworks/react/add-ons/db/assets/src/routes/demo/db-chat-api.d.ts +0 -19
- package/dist/types/frameworks/react/add-ons/form/assets/src/hooks/demo.form-context.d.ts +0 -1
- package/dist/types/frameworks/react/add-ons/form/assets/src/hooks/demo.form.d.ts +0 -1
- package/dist/types/frameworks/react/add-ons/mcp/assets/src/mcp-todos.d.ts +0 -7
- package/dist/types/frameworks/react/add-ons/mcp/assets/src/routes/demo/api.mcp-todos.d.ts +0 -1
- package/dist/types/frameworks/react/add-ons/mcp/assets/src/routes/mcp.d.ts +0 -1
- package/dist/types/frameworks/react/add-ons/mcp/assets/src/utils/mcp-handler.d.ts +0 -2
- package/dist/types/frameworks/react/add-ons/neon/assets/neon-vite-plugin.d.ts +0 -2
- package/dist/types/frameworks/react/add-ons/neon/assets/src/db.d.ts +0 -1
- package/dist/types/frameworks/react/add-ons/oRPC/assets/src/orpc/client.d.ts +0 -4
- package/dist/types/frameworks/react/add-ons/oRPC/assets/src/orpc/router/index.d.ts +0 -5
- package/dist/types/frameworks/react/add-ons/oRPC/assets/src/orpc/router/todos.d.ts +0 -2
- package/dist/types/frameworks/react/add-ons/oRPC/assets/src/orpc/schema.d.ts +0 -11
- package/dist/types/frameworks/react/add-ons/oRPC/assets/src/polyfill.d.ts +0 -1
- package/dist/types/frameworks/react/add-ons/oRPC/assets/src/routes/api.$.d.ts +0 -2
- package/dist/types/frameworks/react/add-ons/oRPC/assets/src/routes/api.rpc.$.d.ts +0 -2
- package/dist/types/frameworks/react/add-ons/shadcn/assets/src/lib/utils.d.ts +0 -2
- package/dist/types/frameworks/react/add-ons/start/assets/src/data/demo.punk-songs.d.ts +0 -1
- package/dist/types/frameworks/react/add-ons/start/assets/src/routes/demo/api.names.d.ts +0 -1
- package/dist/types/frameworks/react/add-ons/store/assets/src/lib/demo-store.d.ts +0 -2
- package/dist/types/frameworks/react/add-ons/storybook/assets/_dot_storybook/main.d.ts +0 -3
- package/dist/types/frameworks/react/add-ons/storybook/assets/_dot_storybook/preview.d.ts +0 -4
- package/dist/types/frameworks/react/add-ons/storybook/assets/src/components/storybook/button.stories.d.ts +0 -11
- package/dist/types/frameworks/react/add-ons/storybook/assets/src/components/storybook/input.stories.d.ts +0 -7
- package/dist/types/frameworks/react/add-ons/storybook/assets/src/components/storybook/radio-group.stories.d.ts +0 -7
- package/dist/types/frameworks/react/add-ons/storybook/assets/src/components/storybook/slider.stories.d.ts +0 -8
- package/dist/types/frameworks/react/add-ons/strapi/assets/src/lib/strapiClient.d.ts +0 -2
- package/dist/types/frameworks/react/add-ons/t3env/assets/src/env.d.ts +0 -1
- package/dist/types/frameworks/react/add-ons/tRPC/assets/src/integrations/trpc/init.d.ts +0 -2
- package/dist/types/frameworks/react/add-ons/tRPC/assets/src/integrations/trpc/react.d.ts +0 -1
- package/dist/types/frameworks/react/add-ons/tRPC/assets/src/integrations/trpc/router.d.ts +0 -2
- package/dist/types/frameworks/react/add-ons/table/assets/src/data/demo-table-data.d.ts +0 -11
- package/dist/types/frameworks/react/examples/events/assets/content-collections.d.ts +0 -2
- package/dist/types/frameworks/react/examples/events/assets/src/lib/conference-ai-hook.d.ts +0 -5
- package/dist/types/frameworks/react/examples/events/assets/src/lib/conference-tools.d.ts +0 -10
- package/dist/types/frameworks/react/examples/events/assets/src/lib/utils.d.ts +0 -2
- package/dist/types/frameworks/react/examples/events/assets/src/routes/api.remy-chat.d.ts +0 -1
- package/dist/types/frameworks/react/examples/resume/assets/content-collections.d.ts +0 -2
- package/dist/types/frameworks/react/examples/resume/assets/src/lib/resume-ai-hook.d.ts +0 -5
- package/dist/types/frameworks/react/examples/resume/assets/src/lib/resume-tools.d.ts +0 -8
- package/dist/types/frameworks/react/examples/resume/assets/src/lib/utils.d.ts +0 -2
- package/dist/types/frameworks/react/examples/resume/assets/src/routes/api.resume-chat.d.ts +0 -1
- package/dist/types/frameworks/solid/add-ons/better-auth/assets/src/lib/auth-client.d.ts +0 -1
- package/dist/types/frameworks/solid/add-ons/better-auth/assets/src/lib/auth.d.ts +0 -1
- package/dist/types/frameworks/solid/add-ons/better-auth/assets/src/routes/api/auth/$.d.ts +0 -1
- package/dist/types/frameworks/solid/add-ons/convex/assets/convex/schema.d.ts +0 -2
- package/dist/types/frameworks/solid/add-ons/convex/assets/convex/todos.d.ts +0 -4
- package/dist/types/frameworks/solid/add-ons/solid-ui/assets/src/lib/utils.d.ts +0 -2
- package/dist/types/frameworks/solid/add-ons/store/assets/src/lib/demo-store.d.ts +0 -2
- package/dist/types/frameworks/solid/add-ons/strapi/assets/src/lib/strapiClient.d.ts +0 -2
- package/dist/types/frameworks/solid/add-ons/t3env/assets/src/env.d.ts +0 -1
- package/dist/types/frameworks/solid/examples/tanchat/assets/ai-streaming-server/src/index.d.ts +0 -1
- package/dist/types/frameworks/solid/examples/tanchat/assets/src/lib/demo-store.d.ts +0 -2
- package/dist/types/frameworks/solid/examples/tanchat/assets/src/store/demo.hooks.d.ts +0 -23
- package/dist/types/frameworks/solid/examples/tanchat/assets/src/store/demo.store.d.ts +0 -40
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs'
|
|
2
|
+
import { resolve, dirname } from 'node:path'
|
|
3
|
+
import { fileURLToPath } from 'node:url'
|
|
4
|
+
import { describe, expect, it } from 'vitest'
|
|
5
|
+
|
|
6
|
+
const __dirname = dirname(fileURLToPath(import.meta.url))
|
|
7
|
+
const distDir = resolve(__dirname, '../dist')
|
|
8
|
+
|
|
9
|
+
describe('copy-assets', () => {
|
|
10
|
+
it('should copy .ts asset files to dist', () => {
|
|
11
|
+
// Regression test: .ts files in assets directories must be copied
|
|
12
|
+
// See: https://github.com/TanStack/cli/issues/XXX
|
|
13
|
+
const tsAssetFiles = [
|
|
14
|
+
'frameworks/react/add-ons/t3env/assets/src/env.ts',
|
|
15
|
+
'frameworks/react/add-ons/tRPC/assets/src/integrations/trpc/init.ts',
|
|
16
|
+
'frameworks/solid/add-ons/convex/assets/convex/schema.ts',
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
for (const file of tsAssetFiles) {
|
|
20
|
+
const fullPath = resolve(distDir, file)
|
|
21
|
+
expect(existsSync(fullPath), `Expected ${file} to exist in dist`).toBe(
|
|
22
|
+
true,
|
|
23
|
+
)
|
|
24
|
+
}
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
it('should copy .tsx asset files to dist', () => {
|
|
28
|
+
const tsxAssetFiles = [
|
|
29
|
+
'frameworks/react/add-ons/tRPC/assets/src/routes/demo/trpc-todo.tsx',
|
|
30
|
+
'frameworks/solid/add-ons/convex/assets/src/routes/demo/convex.tsx',
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
for (const file of tsxAssetFiles) {
|
|
34
|
+
const fullPath = resolve(distDir, file)
|
|
35
|
+
expect(existsSync(fullPath), `Expected ${file} to exist in dist`).toBe(
|
|
36
|
+
true,
|
|
37
|
+
)
|
|
38
|
+
}
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
it('should copy .d.ts files to dist', () => {
|
|
42
|
+
const dtsFiles = [
|
|
43
|
+
'frameworks/react/add-ons/convex/assets/convex/_generated/api.d.ts',
|
|
44
|
+
]
|
|
45
|
+
|
|
46
|
+
for (const file of dtsFiles) {
|
|
47
|
+
const fullPath = resolve(distDir, file)
|
|
48
|
+
expect(existsSync(fullPath), `Expected ${file} to exist in dist`).toBe(
|
|
49
|
+
true,
|
|
50
|
+
)
|
|
51
|
+
}
|
|
52
|
+
})
|
|
53
|
+
})
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
isDirectory,
|
|
7
7
|
readFileHelper,
|
|
8
8
|
relativePath,
|
|
9
|
+
toCleanPath,
|
|
9
10
|
} from '../src/file-helpers.js'
|
|
10
11
|
|
|
11
12
|
vi.mock('node:fs', () => fs)
|
|
@@ -15,6 +16,24 @@ beforeEach(() => {
|
|
|
15
16
|
vol.reset()
|
|
16
17
|
})
|
|
17
18
|
|
|
19
|
+
describe('toCleanPath', () => {
|
|
20
|
+
it('should strip Unix-style leading slash', () => {
|
|
21
|
+
expect(toCleanPath('/projects/my-app/src/file.ts', '/projects/my-app')).toBe(
|
|
22
|
+
'src/file.ts',
|
|
23
|
+
)
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
it('should strip Windows-style leading backslash', () => {
|
|
27
|
+
expect(
|
|
28
|
+
toCleanPath('C:\\Projects\\my-app\\src\\file.ts', 'C:\\Projects\\my-app'),
|
|
29
|
+
).toBe('src\\file.ts')
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
it('should handle paths without leading separator', () => {
|
|
33
|
+
expect(toCleanPath('/projects/my-app', '/projects/my-app')).toBe('')
|
|
34
|
+
})
|
|
35
|
+
})
|
|
36
|
+
|
|
18
37
|
describe('relativePath', () => {
|
|
19
38
|
it('relative path with the same directory and strip extension', () => {
|
|
20
39
|
expect(relativePath('src/utils.ts', 'src/index.ts', true)).toBe('./index')
|
|
@@ -34,10 +34,10 @@ describe('Special Steps', () => {
|
|
|
34
34
|
})
|
|
35
35
|
|
|
36
36
|
describe('postInitScript', () => {
|
|
37
|
-
it('should run post-
|
|
37
|
+
it('should run post-create-init script when it exists', async () => {
|
|
38
38
|
const mockPackageJson = {
|
|
39
39
|
scripts: {
|
|
40
|
-
'post-
|
|
40
|
+
'post-create-init': 'echo "Running post-create-init"',
|
|
41
41
|
},
|
|
42
42
|
}
|
|
43
43
|
|
|
@@ -51,12 +51,12 @@ describe('Special Steps', () => {
|
|
|
51
51
|
expect(mockEnvironment.startStep).toHaveBeenCalledWith({
|
|
52
52
|
id: 'post-init-script',
|
|
53
53
|
type: 'command',
|
|
54
|
-
message: 'Running post-
|
|
54
|
+
message: 'Running post-create-init script...',
|
|
55
55
|
})
|
|
56
56
|
|
|
57
57
|
expect(mockEnvironment.execute).toHaveBeenCalledWith(
|
|
58
58
|
'npm',
|
|
59
|
-
['run', 'post-
|
|
59
|
+
['run', 'post-create-init'],
|
|
60
60
|
'/test/project',
|
|
61
61
|
{ inherit: true },
|
|
62
62
|
)
|
|
@@ -74,12 +74,12 @@ describe('Special Steps', () => {
|
|
|
74
74
|
|
|
75
75
|
expect(mockEnvironment.warn).toHaveBeenCalledWith(
|
|
76
76
|
'Warning',
|
|
77
|
-
'No package.json found, skipping post-
|
|
77
|
+
'No package.json found, skipping post-create-init script',
|
|
78
78
|
)
|
|
79
79
|
expect(mockEnvironment.execute).not.toHaveBeenCalled()
|
|
80
80
|
})
|
|
81
81
|
|
|
82
|
-
it('should skip when post-
|
|
82
|
+
it('should skip when post-create-init script does not exist', async () => {
|
|
83
83
|
const mockPackageJson = {
|
|
84
84
|
scripts: {
|
|
85
85
|
build: 'echo "Building"',
|
|
@@ -100,10 +100,10 @@ describe('Special Steps', () => {
|
|
|
100
100
|
it('should handle different package managers', async () => {
|
|
101
101
|
const packageManagers = ['yarn', 'pnpm', 'bun', 'deno'] as const
|
|
102
102
|
const expectedCommands = {
|
|
103
|
-
yarn: { command: 'yarn', args: ['run', 'post-
|
|
104
|
-
pnpm: { command: 'pnpm', args: ['post-
|
|
105
|
-
bun: { command: 'bun', args: ['--bun', 'run', 'post-
|
|
106
|
-
deno: { command: 'deno', args: ['task', 'post-
|
|
103
|
+
yarn: { command: 'yarn', args: ['run', 'post-create-init'] },
|
|
104
|
+
pnpm: { command: 'pnpm', args: ['post-create-init'] },
|
|
105
|
+
bun: { command: 'bun', args: ['--bun', 'run', 'post-create-init'] },
|
|
106
|
+
deno: { command: 'deno', args: ['task', 'post-create-init'] },
|
|
107
107
|
}
|
|
108
108
|
|
|
109
109
|
for (const pm of packageManagers) {
|
|
@@ -111,7 +111,7 @@ describe('Special Steps', () => {
|
|
|
111
111
|
vi.clearAllMocks()
|
|
112
112
|
vi.spyOn(mockEnvironment, 'exists').mockReturnValue(true)
|
|
113
113
|
vi.mocked(fs.readFileSync).mockReturnValue(
|
|
114
|
-
JSON.stringify({ scripts: { 'post-
|
|
114
|
+
JSON.stringify({ scripts: { 'post-create-init': 'test' } }),
|
|
115
115
|
)
|
|
116
116
|
|
|
117
117
|
await postInitScript(mockEnvironment, mockOptions)
|
|
@@ -133,7 +133,7 @@ describe('Special Steps', () => {
|
|
|
133
133
|
|
|
134
134
|
vi.spyOn(mockEnvironment, 'exists').mockReturnValue(true)
|
|
135
135
|
vi.mocked(fs.readFileSync).mockReturnValue(
|
|
136
|
-
JSON.stringify({ scripts: { 'post-
|
|
136
|
+
JSON.stringify({ scripts: { 'post-create-init': 'test' } }),
|
|
137
137
|
)
|
|
138
138
|
|
|
139
139
|
await runSpecialSteps(mockEnvironment, mockOptions, specialSteps)
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
const guitars = [
|
|
2
|
-
{
|
|
3
|
-
id: 1,
|
|
4
|
-
name: 'TanStack Ukelele',
|
|
5
|
-
image: '/example-ukelele-tanstack.jpg',
|
|
6
|
-
description: "Introducing the TanStack Signature Ukulele—a beautifully handcrafted concert ukulele that combines exceptional sound quality with distinctive style. Featuring a warm, resonant koa-wood body with natural grain patterns, this instrument delivers the rich, mellow tones Hawaii is famous for. The exclusive TanStack palm tree inlay on the soundhole adds a unique touch of island flair, while the matching branded headstock makes this a true collector's piece for developers and musicians alike. Whether you're a beginner looking for a quality starter instrument or an experienced player wanting something special, the TanStack Ukulele brings together craftsmanship, character, and that unmistakable tropical spirit.",
|
|
7
|
-
shortDescription: 'Premium koa-wood ukulele featuring exclusive TanStack branding, perfect for beach vibes and island-inspired melodies.',
|
|
8
|
-
price: 299,
|
|
9
|
-
},
|
|
10
|
-
{
|
|
11
|
-
id: 2,
|
|
12
|
-
name: 'Video Game Guitar',
|
|
13
|
-
image: '/example-guitar-video-games.jpg',
|
|
14
|
-
description: "The Video Game Guitar is a unique acoustic guitar that features a design inspired by video games. It has a sleek, high-gloss finish and a comfortable playability. The guitar's ergonomic body and fast neck profile ensure comfortable playability for hours on end.",
|
|
15
|
-
shortDescription: 'A unique electric guitar with a video game design, high-gloss finish, and comfortable playability.',
|
|
16
|
-
price: 699,
|
|
17
|
-
},
|
|
18
|
-
{
|
|
19
|
-
id: 3,
|
|
20
|
-
name: 'Superhero Guitar',
|
|
21
|
-
image: '/example-guitar-superhero.jpg',
|
|
22
|
-
description: "The Superhero Guitar is a bold black electric guitar that stands out with its unique superhero logo design. Its sleek, high-gloss finish and powerful pickups make it perfect for high-energy performances. The guitar's ergonomic body and fast neck profile ensure comfortable playability for hours on end.",
|
|
23
|
-
shortDescription: 'A bold black electric guitar with a unique superhero logo, high-gloss finish, and powerful pickups.',
|
|
24
|
-
price: 699,
|
|
25
|
-
},
|
|
26
|
-
{
|
|
27
|
-
id: 4,
|
|
28
|
-
name: 'Motherboard Guitar',
|
|
29
|
-
image: '/example-guitar-motherboard.jpg',
|
|
30
|
-
description: "This guitar is a tribute to the motherboard of a computer. It's a unique and stylish instrument that will make you feel like a hacker. The intricate circuit-inspired design features actual LED lights that pulse with your playing intensity, while the neck is inlaid with binary code patterns that glow under stage lights. Each pickup has been custom-wound to produce tones ranging from clean digital precision to glitched-out distortion, perfect for electronic music fusion. The Motherboard Guitar seamlessly bridges the gap between traditional craftsmanship and cutting-edge technology, making it the ultimate instrument for the digital age musician.",
|
|
31
|
-
shortDescription: 'A tech-inspired electric guitar featuring LED lights and binary code inlays that glow under stage lights.',
|
|
32
|
-
price: 649,
|
|
33
|
-
},
|
|
34
|
-
{
|
|
35
|
-
id: 5,
|
|
36
|
-
name: 'Racing Guitar',
|
|
37
|
-
image: '/example-guitar-racing.jpg',
|
|
38
|
-
description: "Engineered for speed and precision, the Racing Guitar embodies the spirit of motorsport in every curve and contour. Its aerodynamic body, painted in classic racing stripes and high-gloss finish, is crafted from lightweight materials that allow for effortless play during extended performances. The custom low-action setup and streamlined neck profile enable lightning-fast fretwork, while specially designed pickups deliver a high-octane tone that cuts through any mix. Built with performance-grade hardware including racing-inspired control knobs and checkered flag inlays, this guitar isn't just played—it's driven to the limits of musical possibility.",
|
|
39
|
-
shortDescription: 'A lightweight, aerodynamic guitar with racing stripes and a low-action setup designed for speed and precision.',
|
|
40
|
-
price: 679,
|
|
41
|
-
},
|
|
42
|
-
{
|
|
43
|
-
id: 6,
|
|
44
|
-
name: 'Steamer Trunk Guitar',
|
|
45
|
-
image: '/example-guitar-steamer-trunk.jpg',
|
|
46
|
-
description: 'The Steamer Trunk Guitar is a semi-hollow body instrument that exudes vintage charm and character. Crafted from reclaimed antique luggage wood, it features brass hardware that adds a touch of elegance and durability. The fretboard is adorned with a world map inlay, making it a unique piece that tells a story of travel and adventure.',
|
|
47
|
-
shortDescription: 'A semi-hollow body guitar with brass hardware and a world map inlay, crafted from reclaimed antique luggage wood.',
|
|
48
|
-
price: 629,
|
|
49
|
-
},
|
|
50
|
-
{
|
|
51
|
-
id: 7,
|
|
52
|
-
name: "Travelin' Man Guitar",
|
|
53
|
-
image: '/example-guitar-traveling.jpg',
|
|
54
|
-
description: "The Travelin' Man Guitar is an acoustic masterpiece adorned with vintage postcards from around the world. Each postcard tells a story of adventure and wanderlust, making this guitar a unique piece of art. Its rich, resonant tones and comfortable playability make it perfect for musicians who love to travel and perform.",
|
|
55
|
-
shortDescription: 'An acoustic guitar with vintage postcards, rich tones, and comfortable playability.',
|
|
56
|
-
price: 499,
|
|
57
|
-
},
|
|
58
|
-
{
|
|
59
|
-
id: 8,
|
|
60
|
-
name: 'Flowerly Love Guitar',
|
|
61
|
-
image: '/example-guitar-flowers.jpg',
|
|
62
|
-
description: "The Flowerly Love Guitar is an acoustic masterpiece adorned with intricate floral designs on its body. Each flower is hand-painted, adding a touch of nature's beauty to the instrument. Its warm, resonant tones make it perfect for both intimate performances and larger gatherings.",
|
|
63
|
-
shortDescription: 'An acoustic guitar with hand-painted floral designs and warm, resonant tones.',
|
|
64
|
-
price: 599,
|
|
65
|
-
},
|
|
66
|
-
];
|
|
67
|
-
export default guitars;
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import { useCallback, useRef, useState } from 'react';
|
|
2
|
-
/**
|
|
3
|
-
* Hook for recording audio and transcribing it via the transcription API.
|
|
4
|
-
*/
|
|
5
|
-
export function useAudioRecorder() {
|
|
6
|
-
const [isRecording, setIsRecording] = useState(false);
|
|
7
|
-
const [isTranscribing, setIsTranscribing] = useState(false);
|
|
8
|
-
const mediaRecorderRef = useRef(null);
|
|
9
|
-
const chunksRef = useRef([]);
|
|
10
|
-
const startRecording = useCallback(async () => {
|
|
11
|
-
try {
|
|
12
|
-
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
|
|
13
|
-
const mediaRecorder = new MediaRecorder(stream, {
|
|
14
|
-
mimeType: 'audio/webm;codecs=opus',
|
|
15
|
-
});
|
|
16
|
-
mediaRecorderRef.current = mediaRecorder;
|
|
17
|
-
chunksRef.current = [];
|
|
18
|
-
mediaRecorder.ondataavailable = (e) => {
|
|
19
|
-
if (e.data.size > 0) {
|
|
20
|
-
chunksRef.current.push(e.data);
|
|
21
|
-
}
|
|
22
|
-
};
|
|
23
|
-
mediaRecorder.start();
|
|
24
|
-
setIsRecording(true);
|
|
25
|
-
}
|
|
26
|
-
catch (error) {
|
|
27
|
-
console.error('Failed to start recording:', error);
|
|
28
|
-
alert('Could not access microphone. Please check permissions.');
|
|
29
|
-
}
|
|
30
|
-
}, []);
|
|
31
|
-
const stopRecording = useCallback(async () => {
|
|
32
|
-
return new Promise((resolve) => {
|
|
33
|
-
const mediaRecorder = mediaRecorderRef.current;
|
|
34
|
-
if (!mediaRecorder) {
|
|
35
|
-
resolve(null);
|
|
36
|
-
return;
|
|
37
|
-
}
|
|
38
|
-
mediaRecorder.onstop = async () => {
|
|
39
|
-
setIsRecording(false);
|
|
40
|
-
setIsTranscribing(true);
|
|
41
|
-
const audioBlob = new Blob(chunksRef.current, { type: 'audio/webm' });
|
|
42
|
-
// Stop all tracks
|
|
43
|
-
mediaRecorder.stream.getTracks().forEach((track) => track.stop());
|
|
44
|
-
try {
|
|
45
|
-
const formData = new FormData();
|
|
46
|
-
formData.append('audio', new File([audioBlob], 'recording.webm', { type: 'audio/webm' }));
|
|
47
|
-
formData.append('model', 'whisper-1');
|
|
48
|
-
const response = await fetch('/demo/api/transcription', {
|
|
49
|
-
method: 'POST',
|
|
50
|
-
body: formData,
|
|
51
|
-
});
|
|
52
|
-
if (!response.ok) {
|
|
53
|
-
const errorData = await response.json();
|
|
54
|
-
throw new Error(errorData.error || 'Transcription failed');
|
|
55
|
-
}
|
|
56
|
-
const result = await response.json();
|
|
57
|
-
setIsTranscribing(false);
|
|
58
|
-
resolve(result.text || null);
|
|
59
|
-
}
|
|
60
|
-
catch (error) {
|
|
61
|
-
console.error('Transcription error:', error);
|
|
62
|
-
setIsTranscribing(false);
|
|
63
|
-
resolve(null);
|
|
64
|
-
}
|
|
65
|
-
};
|
|
66
|
-
mediaRecorder.stop();
|
|
67
|
-
});
|
|
68
|
-
}, []);
|
|
69
|
-
return { isRecording, isTranscribing, startRecording, stopRecording };
|
|
70
|
-
}
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
import { useCallback, useRef, useState } from 'react';
|
|
2
|
-
/**
|
|
3
|
-
* Hook for text-to-speech playback via the TTS API.
|
|
4
|
-
*/
|
|
5
|
-
export function useTTS() {
|
|
6
|
-
const [playingId, setPlayingId] = useState(null);
|
|
7
|
-
const audioRef = useRef(null);
|
|
8
|
-
const speak = useCallback(async (text, id) => {
|
|
9
|
-
// Stop any currently playing audio
|
|
10
|
-
if (audioRef.current) {
|
|
11
|
-
audioRef.current.pause();
|
|
12
|
-
audioRef.current = null;
|
|
13
|
-
}
|
|
14
|
-
setPlayingId(id);
|
|
15
|
-
try {
|
|
16
|
-
const response = await fetch('/demo/api/tts', {
|
|
17
|
-
method: 'POST',
|
|
18
|
-
headers: { 'Content-Type': 'application/json' },
|
|
19
|
-
body: JSON.stringify({
|
|
20
|
-
text,
|
|
21
|
-
voice: 'nova',
|
|
22
|
-
model: 'tts-1',
|
|
23
|
-
format: 'mp3',
|
|
24
|
-
}),
|
|
25
|
-
});
|
|
26
|
-
if (!response.ok) {
|
|
27
|
-
const errorData = await response.json();
|
|
28
|
-
throw new Error(errorData.error || 'TTS failed');
|
|
29
|
-
}
|
|
30
|
-
const result = await response.json();
|
|
31
|
-
// Convert base64 to audio and play
|
|
32
|
-
const audioData = atob(result.audio);
|
|
33
|
-
const bytes = new Uint8Array(audioData.length);
|
|
34
|
-
for (let i = 0; i < audioData.length; i++) {
|
|
35
|
-
bytes[i] = audioData.charCodeAt(i);
|
|
36
|
-
}
|
|
37
|
-
const blob = new Blob([bytes], { type: result.contentType });
|
|
38
|
-
const url = URL.createObjectURL(blob);
|
|
39
|
-
const audio = new Audio(url);
|
|
40
|
-
audioRef.current = audio;
|
|
41
|
-
audio.onended = () => {
|
|
42
|
-
URL.revokeObjectURL(url);
|
|
43
|
-
setPlayingId(null);
|
|
44
|
-
audioRef.current = null;
|
|
45
|
-
};
|
|
46
|
-
audio.onerror = () => {
|
|
47
|
-
URL.revokeObjectURL(url);
|
|
48
|
-
setPlayingId(null);
|
|
49
|
-
audioRef.current = null;
|
|
50
|
-
};
|
|
51
|
-
await audio.play();
|
|
52
|
-
}
|
|
53
|
-
catch (error) {
|
|
54
|
-
console.error('TTS error:', error);
|
|
55
|
-
setPlayingId(null);
|
|
56
|
-
}
|
|
57
|
-
}, []);
|
|
58
|
-
const stop = useCallback(() => {
|
|
59
|
-
if (audioRef.current) {
|
|
60
|
-
audioRef.current.pause();
|
|
61
|
-
audioRef.current = null;
|
|
62
|
-
}
|
|
63
|
-
setPlayingId(null);
|
|
64
|
-
}, []);
|
|
65
|
-
return { playingId, speak, stop };
|
|
66
|
-
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { fetchServerSentEvents, useChat, createChatClientOptions, } from '@tanstack/ai-react';
|
|
2
|
-
import { clientTools } from '@tanstack/ai-client';
|
|
3
|
-
import { recommendGuitarToolDef } from '@/lib/demo-guitar-tools';
|
|
4
|
-
const recommendGuitarToolClient = recommendGuitarToolDef.client(({ id }) => ({
|
|
5
|
-
id: +id,
|
|
6
|
-
}));
|
|
7
|
-
const chatOptions = createChatClientOptions({
|
|
8
|
-
connection: fetchServerSentEvents('/demo/api/ai/chat'),
|
|
9
|
-
tools: clientTools(recommendGuitarToolClient),
|
|
10
|
-
});
|
|
11
|
-
export const useGuitarRecommendationChat = () => useChat(chatOptions);
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { toolDefinition } from '@tanstack/ai';
|
|
2
|
-
import { z } from 'zod';
|
|
3
|
-
import guitars from '@/data/demo-guitars';
|
|
4
|
-
// Tool definition for getting guitars
|
|
5
|
-
export const getGuitarsToolDef = toolDefinition({
|
|
6
|
-
name: 'getGuitars',
|
|
7
|
-
description: 'Get all products from the database',
|
|
8
|
-
inputSchema: z.object({}),
|
|
9
|
-
outputSchema: z.array(z.object({
|
|
10
|
-
id: z.number(),
|
|
11
|
-
name: z.string(),
|
|
12
|
-
image: z.string(),
|
|
13
|
-
description: z.string(),
|
|
14
|
-
shortDescription: z.string(),
|
|
15
|
-
price: z.number(),
|
|
16
|
-
})),
|
|
17
|
-
});
|
|
18
|
-
// Server implementation
|
|
19
|
-
export const getGuitars = getGuitarsToolDef.server(() => guitars);
|
|
20
|
-
// Tool definition for guitar recommendation
|
|
21
|
-
export const recommendGuitarToolDef = toolDefinition({
|
|
22
|
-
name: 'recommendGuitar',
|
|
23
|
-
description: 'REQUIRED tool to display a guitar recommendation to the user. This tool MUST be used whenever recommending a guitar - do NOT write recommendations yourself. This displays the guitar in a special appealing format with a buy button.',
|
|
24
|
-
inputSchema: z.object({
|
|
25
|
-
id: z
|
|
26
|
-
.union([z.string(), z.number()])
|
|
27
|
-
.describe('The ID of the guitar to recommend (from the getGuitars results)'),
|
|
28
|
-
}),
|
|
29
|
-
outputSchema: z.object({
|
|
30
|
-
id: z.number(),
|
|
31
|
-
}),
|
|
32
|
-
});
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
import { createFileRoute } from '@tanstack/react-router';
|
|
2
|
-
import { chat, maxIterations, toServerSentEventsResponse } from '@tanstack/ai';
|
|
3
|
-
import { anthropicText } from '@tanstack/ai-anthropic';
|
|
4
|
-
import { openaiText } from '@tanstack/ai-openai';
|
|
5
|
-
import { geminiText } from '@tanstack/ai-gemini';
|
|
6
|
-
import { ollamaText } from '@tanstack/ai-ollama';
|
|
7
|
-
import { getGuitars, recommendGuitarToolDef } from '@/lib/demo-guitar-tools';
|
|
8
|
-
const SYSTEM_PROMPT = `You are a helpful assistant for a store that sells guitars.
|
|
9
|
-
|
|
10
|
-
CRITICAL INSTRUCTIONS - YOU MUST FOLLOW THIS EXACT WORKFLOW:
|
|
11
|
-
|
|
12
|
-
When a user asks for a guitar recommendation:
|
|
13
|
-
1. FIRST: Use the getGuitars tool (no parameters needed)
|
|
14
|
-
2. SECOND: Use the recommendGuitar tool with the ID of the guitar you want to recommend
|
|
15
|
-
3. NEVER write a recommendation directly - ALWAYS use the recommendGuitar tool
|
|
16
|
-
|
|
17
|
-
IMPORTANT:
|
|
18
|
-
- The recommendGuitar tool will display the guitar in a special, appealing format
|
|
19
|
-
- You MUST use recommendGuitar for ANY guitar recommendation
|
|
20
|
-
- ONLY recommend guitars from our inventory (use getGuitars first)
|
|
21
|
-
- The recommendGuitar tool has a buy button - this is how customers purchase
|
|
22
|
-
- Do NOT describe the guitar yourself - let the recommendGuitar tool do it
|
|
23
|
-
`;
|
|
24
|
-
export const Route = createFileRoute('/demo/api/ai/chat')({
|
|
25
|
-
server: {
|
|
26
|
-
handlers: {
|
|
27
|
-
POST: async ({ request }) => {
|
|
28
|
-
// Capture request signal before reading body (it may be aborted after body is consumed)
|
|
29
|
-
const requestSignal = request.signal;
|
|
30
|
-
// If request is already aborted, return early
|
|
31
|
-
if (requestSignal.aborted) {
|
|
32
|
-
return new Response(null, { status: 499 }); // 499 = Client Closed Request
|
|
33
|
-
}
|
|
34
|
-
const abortController = new AbortController();
|
|
35
|
-
try {
|
|
36
|
-
const body = await request.json();
|
|
37
|
-
const { messages } = body;
|
|
38
|
-
// Determine the best available provider
|
|
39
|
-
let provider = 'ollama';
|
|
40
|
-
let model = 'mistral:7b';
|
|
41
|
-
if (process.env.ANTHROPIC_API_KEY) {
|
|
42
|
-
provider = 'anthropic';
|
|
43
|
-
model = 'claude-haiku-4-5';
|
|
44
|
-
}
|
|
45
|
-
else if (process.env.OPENAI_API_KEY) {
|
|
46
|
-
provider = 'openai';
|
|
47
|
-
model = 'gpt-4o';
|
|
48
|
-
}
|
|
49
|
-
else if (process.env.GEMINI_API_KEY) {
|
|
50
|
-
provider = 'gemini';
|
|
51
|
-
model = 'gemini-2.0-flash-exp';
|
|
52
|
-
}
|
|
53
|
-
// Adapter factory pattern for multi-vendor support
|
|
54
|
-
const adapterConfig = {
|
|
55
|
-
anthropic: () => anthropicText((model || 'claude-haiku-4-5')),
|
|
56
|
-
openai: () => openaiText((model || 'gpt-4o')),
|
|
57
|
-
gemini: () => geminiText((model || 'gemini-2.0-flash-exp')),
|
|
58
|
-
ollama: () => ollamaText((model || 'mistral:7b')),
|
|
59
|
-
};
|
|
60
|
-
const adapter = adapterConfig[provider]();
|
|
61
|
-
const stream = chat({
|
|
62
|
-
adapter,
|
|
63
|
-
tools: [
|
|
64
|
-
getGuitars, // Server tool
|
|
65
|
-
recommendGuitarToolDef, // No server execute - client will handle
|
|
66
|
-
],
|
|
67
|
-
systemPrompts: [SYSTEM_PROMPT],
|
|
68
|
-
agentLoopStrategy: maxIterations(5),
|
|
69
|
-
messages,
|
|
70
|
-
abortController,
|
|
71
|
-
});
|
|
72
|
-
return toServerSentEventsResponse(stream, { abortController });
|
|
73
|
-
}
|
|
74
|
-
catch (error) {
|
|
75
|
-
// If request was aborted, return early (don't send error response)
|
|
76
|
-
if (error.name === 'AbortError' || abortController.signal.aborted) {
|
|
77
|
-
return new Response(null, { status: 499 }); // 499 = Client Closed Request
|
|
78
|
-
}
|
|
79
|
-
return new Response(JSON.stringify({ error: 'Failed to process chat request' }), {
|
|
80
|
-
status: 500,
|
|
81
|
-
headers: { 'Content-Type': 'application/json' },
|
|
82
|
-
});
|
|
83
|
-
}
|
|
84
|
-
},
|
|
85
|
-
},
|
|
86
|
-
},
|
|
87
|
-
});
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import { createFileRoute } from '@tanstack/react-router';
|
|
2
|
-
import { generateImage, createImageOptions } from '@tanstack/ai';
|
|
3
|
-
import { openaiImage } from '@tanstack/ai-openai';
|
|
4
|
-
export const Route = createFileRoute('/demo/api/ai/image')({
|
|
5
|
-
server: {
|
|
6
|
-
handlers: {
|
|
7
|
-
POST: async ({ request }) => {
|
|
8
|
-
const body = await request.json();
|
|
9
|
-
const { prompt, numberOfImages = 1, size = '1024x1024' } = body;
|
|
10
|
-
if (!prompt || prompt.trim().length === 0) {
|
|
11
|
-
return new Response(JSON.stringify({
|
|
12
|
-
error: 'Prompt is required',
|
|
13
|
-
}), {
|
|
14
|
-
status: 400,
|
|
15
|
-
headers: { 'Content-Type': 'application/json' },
|
|
16
|
-
});
|
|
17
|
-
}
|
|
18
|
-
if (!process.env.OPENAI_API_KEY) {
|
|
19
|
-
return new Response(JSON.stringify({
|
|
20
|
-
error: 'OPENAI_API_KEY is not configured',
|
|
21
|
-
}), {
|
|
22
|
-
status: 500,
|
|
23
|
-
headers: { 'Content-Type': 'application/json' },
|
|
24
|
-
});
|
|
25
|
-
}
|
|
26
|
-
try {
|
|
27
|
-
const options = createImageOptions({
|
|
28
|
-
adapter: openaiImage('gpt-image-1'),
|
|
29
|
-
});
|
|
30
|
-
const result = await generateImage({
|
|
31
|
-
...options,
|
|
32
|
-
prompt,
|
|
33
|
-
numberOfImages,
|
|
34
|
-
size,
|
|
35
|
-
});
|
|
36
|
-
return new Response(JSON.stringify({
|
|
37
|
-
images: result.images,
|
|
38
|
-
model: 'gpt-image-1',
|
|
39
|
-
}), {
|
|
40
|
-
status: 200,
|
|
41
|
-
headers: { 'Content-Type': 'application/json' },
|
|
42
|
-
});
|
|
43
|
-
}
|
|
44
|
-
catch (error) {
|
|
45
|
-
return new Response(JSON.stringify({
|
|
46
|
-
error: error.message || 'An error occurred',
|
|
47
|
-
}), {
|
|
48
|
-
status: 500,
|
|
49
|
-
headers: { 'Content-Type': 'application/json' },
|
|
50
|
-
});
|
|
51
|
-
}
|
|
52
|
-
},
|
|
53
|
-
},
|
|
54
|
-
},
|
|
55
|
-
});
|