// 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}` } function __render_2051a6d5_789(context: TemplateRenderContext) { const { packageManager, projectName, typescript, tailwind, blank, js, jsx, fileRouter, codeRouter, routerOnly, includeExamples, addOnEnabled, addOnOption, addOns, integrations, routes, getPackageManagerAddScript, getPackageManagerRunScript, getPackageManagerExecuteScript, relativePath, integrationImportContent, integrationImportCode, renderTemplate, ignoreFile, } = context let __output = '' const __append = (value: unknown) => { if (value !== undefined && value !== null) { __output += String(value) } } __append("# PowerSync\n\nThis project includes the PowerSync Web SDK and React hooks.\n\n## Environment\n\nSet these variables in `.env.local`:\n\n- `VITE_POWERSYNC_URL`\n- `VITE_POWERSYNC_TOKEN` for local development only\n\n## What The Add-on Includes\n\n- `src/lib/powersync/AppSchema.ts`\n- `src/lib/powersync/BackendConnector.ts`\n- `src/integrations/powersync/provider.tsx`\n- `src/routes/demo/powersync.tsx`\n\n## Next Steps\n\n1. Replace the development token flow in `src/lib/powersync/BackendConnector.ts` with your real auth flow.\n2. Update the sample schema in `src/lib/powersync/AppSchema.ts` to match your synced tables.\n3. Implement the upload logic in `uploadData()` so local mutations are written back to your backend.\n\nPowerSync setup guidance:\nhttps://docs.powersync.com/client-sdk-references/js-web\n") return __output } function __render_e44c6598_134(context: TemplateRenderContext) { const { packageManager, projectName, typescript, tailwind, blank, js, jsx, fileRouter, codeRouter, routerOnly, includeExamples, addOnEnabled, addOnOption, addOns, integrations, routes, getPackageManagerAddScript, getPackageManagerRunScript, getPackageManagerExecuteScript, relativePath, integrationImportContent, integrationImportCode, renderTemplate, ignoreFile, } = context let __output = '' const __append = (value: unknown) => { if (value !== undefined && value !== null) { __output += String(value) } } __append("{\n \"dependencies\": {\n \"@journeyapps/wa-sqlite\": \"^1.2.6\",\n \"@powersync/react\": \"^1.7.4\",\n \"@powersync/web\": \"^1.26.1\"\n }\n}\n") return __output } const templateRenderers: Record = { "2051a6d5:789": __render_2051a6d5_789, "e44c6598:134": __render_e44c6598_134, } 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": "PowerSync", "description": "Add PowerSync offline sync to your application.", "phase": "add-on", "type": "add-on", "category": "database", "color": "#2563EB", "priority": 55, "link": "https://docs.powersync.com/client-sdk-references/js-web", "modes": [ "file-router" ], "envVars": [ { "name": "VITE_POWERSYNC_URL", "description": "PowerSync instance URL", "required": true, "file": ".env.local" }, { "name": "VITE_POWERSYNC_TOKEN", "description": "Client-visible development token for local testing; VITE_* env vars are exposed to the browser", "required": false, "file": ".env.local" } ], "integrations": [ { "type": "vite-plugin", "path": "powersync-vite-plugin.ts", "jsName": "powersyncVite", "code": "powersyncVite()" }, { "type": "provider", "path": "src/integrations/powersync/provider.tsx", "jsName": "PowerSyncProvider" } ], "routes": [ { "url": "/demo/powersync", "name": "PowerSync", "path": "src/routes/demo/powersync.tsx", "jsName": "PowerSyncDemo" } ], "id": "powersync", "version": "0.0.0", "packageAdditions": {}, "packageTemplate": "{\n \"dependencies\": {\n \"@journeyapps/wa-sqlite\": \"^1.2.6\",\n \"@powersync/react\": \"^1.7.4\",\n \"@powersync/web\": \"^1.26.1\"\n }\n}\n", "readme": "# PowerSync\n\nThis project includes the PowerSync Web SDK and React hooks.\n\n## Environment\n\nSet these variables in `.env.local`:\n\n- `VITE_POWERSYNC_URL`\n- `VITE_POWERSYNC_TOKEN` for local development only\n\n## What The Add-on Includes\n\n- `src/lib/powersync/AppSchema.ts`\n- `src/lib/powersync/BackendConnector.ts`\n- `src/integrations/powersync/provider.tsx`\n- `src/routes/demo/powersync.tsx`\n\n## Next Steps\n\n1. Replace the development token flow in `src/lib/powersync/BackendConnector.ts` with your real auth flow.\n2. Update the sample schema in `src/lib/powersync/AppSchema.ts` to match your synced tables.\n3. Implement the upload logic in `uploadData()` so local mutations are written back to your backend.\n\nPowerSync setup guidance:\nhttps://docs.powersync.com/client-sdk-references/js-web\n", "readmeIsEjs": true, "files": { "_dot_env.local.append": "\nVITE_POWERSYNC_URL=\nVITE_POWERSYNC_TOKEN=\n", "powersync-vite-plugin.ts": "import type { Plugin } from 'vite'\n\nexport default function powersyncVite(): Plugin {\n return {\n name: 'powersync-vite',\n config() {\n return {\n optimizeDeps: {\n exclude: ['@powersync/web'],\n },\n worker: {\n format: 'es',\n },\n }\n },\n }\n}\n", "src/integrations/powersync/provider.tsx": "import type { ReactNode } from 'react'\nimport { PowerSyncContext } from '@powersync/react'\nimport { PowerSyncDatabase, WASQLiteOpenFactory } from '@powersync/web'\n\nimport { AppSchema } from '#/lib/powersync/AppSchema'\nimport { BackendConnector } from '#/lib/powersync/BackendConnector'\n\nconst db = new PowerSyncDatabase({\n database: new WASQLiteOpenFactory({\n dbFilename: 'powersync.db',\n }),\n schema: AppSchema,\n flags: {\n disableSSRWarning: true,\n },\n})\n\nvoid db.connect(new BackendConnector())\n\nexport default function PowerSyncProvider({\n children,\n}: {\n children: ReactNode\n}) {\n return {children}\n}\n", "src/lib/powersync/AppSchema.ts": "import { Schema, Table, column } from '@powersync/web'\n\nconst todos = new Table(\n {\n created_at: column.text,\n description: column.text,\n completed: column.integer,\n },\n { indexes: { created_at: ['created_at'] } },\n)\n\nexport const AppSchema = new Schema({\n todos,\n})\n\nexport type Database = (typeof AppSchema)['types']\nexport type TodoRecord = Database['todos']\n", "src/lib/powersync/BackendConnector.ts": "import {\n type AbstractPowerSyncDatabase,\n type PowerSyncBackendConnector,\n UpdateType,\n} from '@powersync/web'\n\nexport class BackendConnector implements PowerSyncBackendConnector {\n private readonly powersyncUrl = import.meta.env.VITE_POWERSYNC_URL\n private readonly powersyncToken = import.meta.env.VITE_POWERSYNC_TOKEN\n\n async fetchCredentials() {\n if (!this.powersyncUrl || !this.powersyncToken) {\n return null\n }\n\n return {\n endpoint: this.powersyncUrl,\n token: this.powersyncToken,\n }\n }\n\n async uploadData(database: AbstractPowerSyncDatabase): Promise {\n const transaction = await database.getNextCrudTransaction()\n\n if (!transaction) {\n return\n }\n\n try {\n for (const op of transaction.crud) {\n const record = { ...op.opData, id: op.id }\n\n switch (op.op) {\n case UpdateType.PUT:\n console.info('TODO: create record remotely', record)\n break\n case UpdateType.PATCH:\n console.info('TODO: patch record remotely', record)\n break\n case UpdateType.DELETE:\n console.info('TODO: delete record remotely', record)\n break\n }\n }\n\n await transaction.complete()\n } catch (error) {\n console.error('PowerSync uploadData failed', error)\n throw error\n }\n }\n}\n", "src/routes/demo/powersync.tsx": "import { useState } from 'react'\nimport { createFileRoute } from '@tanstack/react-router'\nimport { usePowerSync, useQuery, useStatus } from '@powersync/react'\n\nexport const Route = createFileRoute('/demo/powersync')({\n component: PowerSyncDemo,\n})\n\ntype TodoRow = {\n id: string\n created_at: string\n description: string\n completed: number\n}\n\nfunction PowerSyncDemo() {\n const powerSync = usePowerSync()\n const status = useStatus()\n const { data } = useQuery(\n 'SELECT id, created_at, description, completed FROM todos ORDER BY created_at DESC',\n )\n const todos = (data ?? []) as Array\n const [description, setDescription] = useState('')\n const [error, setError] = useState(null)\n\n async function addTodo(event: React.FormEvent) {\n event.preventDefault()\n\n const nextDescription = description.trim()\n if (!nextDescription) {\n return\n }\n\n try {\n setError(null)\n await powerSync.execute(\n 'INSERT INTO todos (id, created_at, description, completed) VALUES (?, ?, ?, ?)',\n [crypto.randomUUID(), new Date().toISOString(), nextDescription, 0],\n )\n\n setDescription('')\n } catch (error) {\n console.error('Failed to insert PowerSync todo', error)\n setError('Failed to insert row. Please try again.')\n }\n }\n\n return (\n
\n
\n
\n

\n Offline Sync\n

\n

PowerSync

\n

\n This demo writes to the local SQLite database immediately. Replace\n the sample schema and backend connector with your real PowerSync\n configuration.\n

\n
\n\n
\n

\n Connection State\n

\n
\n            {JSON.stringify(status, null, 2)}\n          
\n
\n\n
\n

\n Local Todos\n

\n {error ? (\n

\n {error}\n

\n ) : null}\n \n \n setDescription(event.target.value)}\n placeholder=\"Write to the local PowerSync database\"\n value={description}\n />\n \n \n\n
    \n {todos.length === 0 ? (\n
  • \n No rows yet. Insert one locally, then wire `uploadData()` to\n send it upstream.\n
  • \n ) : (\n todos.map((todo) => (\n
  • \n
    \n
    \n

    \n {todo.description}\n

    \n

    \n {todo.created_at}\n

    \n
    \n \n {todo.completed ? 'done' : 'pending'}\n \n
    \n
  • \n ))\n )}\n
\n
\n
\n
\n )\n}\n" }, "deletedFiles": [], "smallLogo": "\n \n \n \n \n\n" } satisfies AddOnCompiled