// Generated by scripts/generate-manifest.mjs. Do not edit by hand. import type { AddOnCompiled } from '../../../../../types.js' type TemplateRecord = Record type TemplateAddOn = TemplateRecord & { integrations?: Array routes?: Array } type TemplateRenderContext = { [key: string]: any packageManager: any projectName: any typescript: any tailwind: any blank: any js: any jsx: any fileRouter: any codeRouter: any routerOnly: any includeExamples: any addOnEnabled: Record addOnOption: Record addOns: Array integrations: Array routes: Array getPackageManagerAddScript: (...args: Array) => string getPackageManagerRunScript: (...args: Array) => string getPackageManagerExecuteScript: (...args: Array) => string relativePath: (...args: Array) => string integrationImportContent: (...args: Array) => string integrationImportCode: (...args: Array) => string | undefined renderTemplate: (content: string) => string ignoreFile: () => never } type TemplateRenderer = (context: TemplateRenderContext) => string | undefined function __escapeXML(value: unknown) { if (value === undefined || value === null) { return '' } return String(value).replace(/[&<>'"]/g, (character) => { switch (character) { case '&': return '&' case '<': return '<' case '>': return '>' case '"': return '"' case "'": return ''' default: return character } }) } export function getManifestTemplateKey(template: string) { let hash = 0x811c9dc5 for (let i = 0; i < template.length; i++) { hash ^= template.charCodeAt(i) hash = Math.imul(hash, 0x01000193) >>> 0 } return `${hash.toString(16).padStart(8, '0')}:${template.length}` } const templateRenderers: Record = { } export function hasManifestTemplate(template: string) { return getManifestTemplateKey(template) in templateRenderers } export function renderManifestTemplate( template: string, context: TemplateRenderContext, ) { const key = getManifestTemplateKey(template) const renderer = templateRenderers[key] if (!renderer) { throw new Error(`Template ${key} was not precompiled into the manifest`) } return renderer(context) ?? '' } export const addOn = { "name": "DB", "description": "TanStack DB", "phase": "add-on", "type": "add-on", "category": "tanstack", "color": "#F97316", "priority": 48, "modes": [ "file-router" ], "link": "https://tanstack.com/db/latest", "dependsOn": [ "tanstack-query" ], "routes": [ { "icon": "Database", "url": "/demo/db-chat", "name": "DB Chat", "path": "src/routes/demo.db-chat.tsx", "jsName": "DBChatDemo" } ], "id": "db", "version": "0.0.0", "packageAdditions": { "dependencies": { "@tanstack/query-db-collection": "latest", "@tanstack/react-db": "latest", "zod": "^4.3.6" } }, "readmeIsEjs": false, "files": { "src/components/demo.chat-area.tsx": "import { useState } from 'react'\n\nimport { useChat, useMessages } from '#/hooks/demo.useChat'\n\nimport Messages from './demo.messages'\n\nexport default function ChatArea() {\n const { sendMessage } = useChat()\n\n const messages = useMessages()\n\n const [message, setMessage] = useState('')\n const [user, setUser] = useState('Alice')\n\n const postMessage = () => {\n if (message.trim().length) {\n sendMessage(message, user)\n setMessage('')\n }\n }\n\n const handleKeyPress = (e: React.KeyboardEvent) => {\n if (e.key === 'Enter') {\n postMessage()\n }\n }\n\n return (\n <>\n
\n \n
\n\n
\n
\n setUser(e.target.value)}\n className=\"demo-select demo-input-fit text-sm\"\n >\n \n \n \n\n
\n setMessage(e.target.value)}\n onKeyDown={handleKeyPress}\n placeholder=\"Type a message...\"\n className=\"demo-input\"\n />\n
\n\n \n Send\n \n
\n
\n \n )\n}\n", "src/components/demo.messages.tsx": "import type { Message } from '#/db-collections'\n\nexport const getAvatarColor = (username: string) => {\n const colors = [\n 'bg-[var(--lagoon-deep)]',\n 'bg-[var(--palm)]',\n 'bg-[var(--sea-ink-soft)]',\n 'bg-[var(--lagoon)]',\n ]\n const index = username\n .split('')\n .reduce((acc, char) => acc + char.charCodeAt(0), 0)\n return colors[index % colors.length]\n}\n\nexport default function Messages({\n messages,\n user,\n}: {\n messages: Message[]\n user: string\n}) {\n return (\n <>\n {messages.map((msg: Message) => (\n \n \n \n {msg.user.charAt(0).toUpperCase()}\n \n\n \n {msg.user !== user && (\n

\n {msg.user}\n

\n )}\n

{msg.text}

\n \n \n \n ))}\n \n )\n}\n", "src/db-collections/index.ts": "import {\n createCollection,\n localOnlyCollectionOptions,\n} from \"@tanstack/react-db\";\nimport { z } from \"zod\";\n\nconst MessageSchema = z.object({\n id: z.number(),\n text: z.string(),\n user: z.string(),\n});\n\nexport type Message = z.infer;\n\nexport const messagesCollection = createCollection(\n localOnlyCollectionOptions({\n getKey: (message) => message.id,\n schema: MessageSchema,\n })\n);\n", "src/hooks/demo.useChat.ts": "import { useEffect, useRef } from 'react'\nimport { useLiveQuery } from '@tanstack/react-db'\n\nimport { messagesCollection, type Message } from '#/db-collections'\n\nimport type { Collection } from '@tanstack/react-db'\n\nfunction useStreamConnection(\n url: string,\n collection: Collection,\n) {\n const loadedRef = useRef(false)\n\n useEffect(() => {\n const fetchData = async () => {\n if (loadedRef.current) return\n loadedRef.current = true\n\n const response = await fetch(url)\n const reader = response.body?.getReader()\n if (!reader) {\n return\n }\n\n const decoder = new TextDecoder()\n while (true) {\n const { done, value } = await reader.read()\n if (done) break\n for (const chunk of decoder\n .decode(value, { stream: true })\n .split('\\n')\n .filter((chunk) => chunk.length > 0)) {\n collection.insert(JSON.parse(chunk))\n }\n }\n }\n fetchData()\n }, [])\n}\n\nexport function useChat() {\n useStreamConnection('/demo/db-chat-api', messagesCollection)\n\n const sendMessage = (message: string, user: string) => {\n fetch('/demo/db-chat-api', {\n method: 'POST',\n body: JSON.stringify({ text: message.trim(), user: user.trim() }),\n })\n }\n\n return { sendMessage }\n}\n\nexport function useMessages() {\n const { data: messages } = useLiveQuery((q) =>\n q.from({ message: messagesCollection }).select(({ message }) => ({\n ...message,\n })),\n )\n\n return messages as Message[]\n}\n", "src/routes/demo/db-chat-api.ts": "import { createFileRoute } from '@tanstack/react-router'\nimport { json } from '@tanstack/react-start'\n\nimport {\n createCollection,\n localOnlyCollectionOptions,\n} from '@tanstack/react-db'\nimport { z } from 'zod'\n\nconst IncomingMessageSchema = z.object({\n user: z.string(),\n text: z.string(),\n})\n\nconst MessageSchema = IncomingMessageSchema.extend({\n id: z.number(),\n})\n\nexport type Message = z.infer\n\nexport const serverMessagesCollection = createCollection(\n localOnlyCollectionOptions({\n getKey: (message) => message.id,\n schema: MessageSchema,\n }),\n)\n\nlet id = 0\nserverMessagesCollection.insert({\n id: id++,\n user: 'Alice',\n text: 'Hello, how are you?',\n})\nserverMessagesCollection.insert({\n id: id++,\n user: 'Bob',\n text: \"I'm fine, thank you!\",\n})\n\nconst sendMessage = (message: { user: string; text: string }) => {\n serverMessagesCollection.insert({\n id: id++,\n user: message.user,\n text: message.text,\n })\n}\n\nexport const Route = createFileRoute('/demo/db-chat-api')({\n server: {\n handlers: {\n GET: () => {\n const stream = new ReadableStream({\n start(controller) {\n for (const [_id, message] of serverMessagesCollection.state) {\n controller.enqueue(JSON.stringify(message) + '\\n')\n }\n serverMessagesCollection.subscribeChanges((changes) => {\n for (const change of changes) {\n if (change.type === 'insert') {\n controller.enqueue(JSON.stringify(change.value) + '\\n')\n }\n }\n })\n },\n })\n\n return new Response(stream, {\n headers: {\n 'Content-Type': 'application/x-ndjson',\n },\n })\n },\n POST: async ({ request }) => {\n const message = IncomingMessageSchema.safeParse(await request.json())\n if (!message.success) {\n return new Response(message.error.message, { status: 400 })\n }\n sendMessage(message.data)\n return json(message.data)\n },\n },\n },\n})\n", "src/routes/demo/db-chat.tsx": "import { createFileRoute } from '@tanstack/react-router'\n\nimport ChatArea from '#/components/demo.chat-area'\n\nexport const Route = createFileRoute('/demo/db-chat')({\n component: App,\n})\n\nfunction App() {\n return (\n
\n
\n \n
\n
\n )\n}\n" }, "deletedFiles": [], "smallLogo": "" } satisfies AddOnCompiled