feat(svelte): Add Svelte 5 bindings for persistent text streaming#13
feat(svelte): Add Svelte 5 bindings for persistent text streaming#13stickerdaniel wants to merge 1 commit intoget-convex:mainfrom
Conversation
Adds useStream hook for Svelte 5, mirroring the React implementation. Includes a svekte example app demonstrating usage. Resolves: get-convex#10
WalkthroughA Svelte 5 hook for persistent-text-streaming orchestration is introduced alongside a comprehensive example application and package exports enabling Svelte developers to integrate streaming chat functionality with optional Convex dependencies. Changes
Sequence Diagram(s)sequenceDiagram
participant UI as ChatWindow Component
participant Hook as useStream Hook
participant Persistence as Persistence Layer
participant HTTP as HTTP Stream Endpoint
UI->>Hook: Call useStream(query, url, getDriven, getStreamId)
alt streamEnded is false OR not driven
Hook->>Persistence: Return cached persistent body
Persistence-->>Hook: StreamBody (if available)
else Driven and streamId available
Hook->>HTTP: POST /stream (startStreaming)
HTTP-->>Hook: ReadableStream response
par Stream Reading
Hook->>Hook: Read chunks from stream
Hook->>Hook: Update reactive streamBody state
and State Management
Hook->>Hook: Derive status (pending→streaming→done)
end
alt Stream Success
Hook-->>UI: text + status: "done"
else Stream Error
Hook-->>UI: text + status: "error"
end
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Tip 📝 Customizable high-level summaries are now available in beta!You can now customize how CodeRabbit generates the high-level summary in your pull requests — including its content, structure, tone, and formatting.
Example instruction:
Note: This feature is currently in beta for Pro-tier users, and pricing will be announced later. Comment |
There was a problem hiding this comment.
Actionable comments posted: 5
🧹 Nitpick comments (6)
src/svelte/index.svelte.ts (2)
164-177: InstantiateTextDecoderonce outside the loop.Creating a new
TextDecoderinstance on every chunk read is inefficient. Additionally, whendoneis true,valuemay beundefined, so decoding it on line 169 could produce an empty string unnecessarily.+ const decoder = new TextDecoder(); const reader = response.body.getReader(); while (true) { try { const { done, value } = await reader.read(); if (done) { - onUpdate(new TextDecoder().decode(value)); return true; } - onUpdate(new TextDecoder().decode(value)); + onUpdate(decoder.decode(value, { stream: true })); } catch (e) { console.error("Error reading stream", e); return false; } }Note: The
{ stream: true }option ensures proper handling of multi-byte characters that may be split across chunks.
143-150: Consider adding error handling for network failures.The
fetchcall can throw on network errors (e.g., DNS failure, connection refused). Currently, any exception would propagate uncaught from the async IIFE on line 74, potentially leavingstreamEndedasnullindefinitely.async function startStreaming( url: URL, streamId: StreamId, onUpdate: (text: string) => void, headers: Record<string, string>, ) { + let response: Response; + try { - const response = await fetch(url, { + response = await fetch(url, { method: "POST", body: JSON.stringify({ streamId: streamId, }), headers: { "Content-Type": "application/json", ...headers }, }); + } catch (e) { + console.error("Network error reaching streaming endpoint", e); + return false; + }example-svelte/src/App.svelte (1)
5-6: Add validation for the required environment variable.If
VITE_CONVEX_URLis not set,setupConvexwill receiveundefined, which could cause cryptic runtime errors. Consider adding a guard or throwing a helpful error message.const convexUrl = import.meta.env.VITE_CONVEX_URL; + if (!convexUrl) { + throw new Error("VITE_CONVEX_URL environment variable is not set"); + } setupConvex(convexUrl);example-svelte/src/components/ServerMessage.svelte (1)
33-37: Simplify effect logic to avoid redundant checks.The effect checks both
!isDrivenand!isCurrentlyStreaming, butisCurrentlyStreamingalready incorporates theisDrivencheck. This creates redundancy.Consider this simpler version:
// Stop streaming when done $effect(() => { - if (!isDriven) return; - if (isCurrentlyStreaming) return; - stopStreaming(); + if (isDriven && !isCurrentlyStreaming) { + stopStreaming(); + } });example-svelte/src/components/ChatWindow.svelte (2)
51-53: Consider performance impact of object spread on every message.Each message submission creates a new
drivenIdsobject via spread operator. While this ensures Svelte reactivity, it could impact performance with many messages since it copies all existing entries.Consider using a
Mapfor better performance with large chat histories:- let drivenIds = $state<Record<string, boolean>>({}); + let drivenIds = $state(new Map<string, boolean>()); function isDriven(id: string): boolean { - return drivenIds[id] === true; + return drivenIds.get(id) === true; } async function handleSubmit(e: SubmitEvent) { // ... - drivenIds = { ...drivenIds, [chatId]: true }; + drivenIds.set(chatId, true); + drivenIds = drivenIds; // Trigger reactivity isStreaming = true; }
118-125: Clarify the minimum message requirement for Clear Chat button.The Clear Chat button requires at least 2 messages (
messages.data.length < 2), which seems arbitrary. Typically, a clear button would be enabled whenever messages exist.Consider simplifying the logic:
<button type="button" - disabled={!messages.data || messages.data.length < 2 || isStreaming} + disabled={!messages.data || messages.data.length === 0 || isStreaming} onclick={clearAllMessages}Or if the 2-message minimum is intentional (e.g., one user + one AI response), add a comment explaining the rationale.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
example-svelte/bun.lockis excluded by!**/*.lock
📒 Files selected for processing (18)
example-svelte/README.md(1 hunks)example-svelte/convex(1 hunks)example-svelte/index.html(1 hunks)example-svelte/package.json(1 hunks)example-svelte/src/App.svelte(1 hunks)example-svelte/src/app.css(1 hunks)example-svelte/src/components/ChatWindow.svelte(1 hunks)example-svelte/src/components/MessageItem.svelte(1 hunks)example-svelte/src/components/ServerMessage.svelte(1 hunks)example-svelte/src/lib/utils.ts(1 hunks)example-svelte/src/main.ts(1 hunks)example-svelte/src/vite-env.d.ts(1 hunks)example-svelte/svelte.config.js(1 hunks)example-svelte/tsconfig.json(1 hunks)example-svelte/vite.config.ts(1 hunks)package.json(4 hunks)src/svelte/index.svelte.ts(1 hunks)tsconfig.build.json(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/svelte/index.svelte.ts (2)
src/client/index.ts (2)
StreamBody(15-18)StreamId(13-13)src/component/schema.ts (1)
StreamStatus(11-11)
🔇 Additional comments (17)
example-svelte/src/vite-env.d.ts (1)
1-10: LGTM!Standard Vite environment type declarations. The
VITE_CONVEX_URLtyping aligns with its usage inutils.ts.example-svelte/index.html (1)
1-13: LGTM!Standard Vite HTML entry point with proper meta tags and module script loading.
example-svelte/src/lib/utils.ts (1)
4-6: LGTM!Standard
cnutility combiningclsxwithtwMergefor Tailwind class composition.tsconfig.build.json (1)
4-4: Verify that excludingsrc/svelte/**/*is intentional.Excluding
src/svelte/**/*from the build will prevent the Svelte hook from being compiled and included in the published package. According to issue #10, the Svelte implementation should be exported as@convex-dev/persistent-text-streaming/svelte.If the Svelte source requires separate compilation (e.g., via a different build step for Svelte components), this is fine. Otherwise, this exclusion may prevent the Svelte bindings from being available to consumers. This requires verification of:
- Whether
src/svelte/contains source files meant for publication- How the package exports are configured in
package.json- Whether there's a separate build configuration for Svelte bindings
src/svelte/index.svelte.ts (3)
1-7: LGTM!Imports are clean and correctly reference the component schema, convex-svelte, and client types.
25-41: LGTM!Well-documented function signature with clear JSDoc explaining each parameter. The use of getter functions (
getDriven,getStreamId) is appropriate for Svelte 5's reactivity model.
65-91: I'll help you verify the review comment about cleanup behavior in the Svelte component. Let me start by examining the actual code and understanding the Svelte 5 $effect cleanup patterns.
<function_calls>
#!/bin/bashFirst, let's examine the file in question
head -100 src/svelte/index.svelte.ts | cat -n
</function_calls>
<function_calls>
Svelte 5 $effect cleanup function abort controller pattern documentation
</function_calls>example-svelte/src/app.css (1)
1-16: LGTM!Clean CSS setup with Tailwind v4 import syntax. The root styles establish a sensible dark theme default with good font rendering optimizations.
example-svelte/package.json (1)
1-27: LGTM!Package configuration is well-structured for an example application. The
file:..reference correctly links to the parent package for local development.example-svelte/svelte.config.js (1)
1-5: LGTM!Standard minimal Svelte configuration with
vitePreprocessfor TypeScript support.example-svelte/tsconfig.json (1)
1-22: LGTM!The TypeScript configuration is appropriate for a Svelte 5 project with strict type checking, proper module resolution, and path aliases that align with the Vite configuration.
example-svelte/README.md (1)
1-59: LGTM!The documentation clearly explains the setup process, features, and usage patterns. The code example accurately demonstrates the
useStreamhook API, and the note about getter functions for Svelte reactivity is helpful.example-svelte/vite.config.ts (1)
1-15: LGTM!The Vite configuration is appropriate for a Svelte 5 + Tailwind CSS v4 project. The
envDirpointing to the parent directory allows sharing environment variables with the main example, and the alias configuration matches the TypeScript paths.example-svelte/src/components/MessageItem.svelte (1)
1-53: LGTM!The component correctly uses Svelte 5 features (
$props,$derived,Snippet) and provides a clean message display layout. The conditional rendering and styling logic is appropriate.package.json (1)
77-89: Good practice: marking framework dependencies as optional.The
peerDependenciesMetacorrectly marks all framework-specific dependencies (React, React DOM, Svelte, convex-svelte) as optional, allowing users to install only the frameworks they need. This is the right approach for a multi-framework library.example-svelte/src/components/ChatWindow.svelte (1)
31-37: LGTM on resize listener cleanup.The window resize listener effect correctly returns a cleanup function to remove the event listener, preventing memory leaks.
example-svelte/src/components/ServerMessage.svelte (1)
46-48: I'll help you verify the review comment about XSS safety andmarked.parse. Let me investigate the actual code and the marked library behavior.
<function_calls>
#!/bin/bashFirst, let's read the ServerMessage.svelte file to see the actual code
cat -n example-svelte/src/components/ServerMessage.svelte
</function_calls>
<function_calls>
#!/bin/bashCheck the package.json to see marked version
cat example-svelte/package.json | grep -A 5 -B 5 '"marked"'
</function_calls>
<function_calls>
marked.parse promise return value synchronous async
</function_calls>
<function_calls>
#!/bin/bashSearch for DOMPurify usage in the codebase
rg -i "dompurify" -n --type ts --type js --type svelte
</function_calls>
| @@ -0,0 +1 @@ | |||
| ../example/convex No newline at end of file | |||
There was a problem hiding this comment.
🧩 Analysis chain
Script executed:
#!/bin/bash
# Check if the symlink exists and its target
echo "=== Checking symlink ==="
ls -la example-svelte/convex 2>/dev/null || echo "Symlink not found"
echo ""
echo "=== Git symlink configuration ==="
git config --get core.symlinks
echo ""
echo "=== Verify target directory exists ==="
if [ -d "example/convex" ]; then
echo "Target directory exists"
echo "Target contents:"
ls example/convex/ 2>/dev/null || echo "Cannot list target"
else
echo "Target directory 'example/convex' not found"
fi
echo ""
echo "=== Check Git tracking of symlink ==="
git ls-files example-svelte/convex
echo ""
echo "=== Check if example-svelte directory exists ==="
ls -la example-svelte/ 2>/dev/null | head -20Repository: get-convex/persistent-text-streaming
<shell_result>
Repository: get-convex/persistent-text-streaming
Script execution failed with unrecoverable error: [CAPABILITY:RUN_SHELL_SCRIPT] Failed to clone repository get-convex/persistent-text-streaming: Clone operation failed
</shell_result>
symlinks git repository cross-platform windows core.symlinks
<web_search_result>
Short answer
- Git stores symlinks in the repo as special blob entries; whether the working tree contains real OS symlinks is controlled by core.symlinks. [1]
- On Windows Git will often set core.symlinks = false for a new repo (or a client may ignore your global setting), so symlinks are checked out as small text files containing the link target. [1][2][3]
What to do (practical steps)
- Ensure Windows allows creating symlinks:
- Enable Developer Mode (Windows Settings → For developers) or use an elevated prompt on older Windows. [2][3]
- Install / re-install Git for Windows with the "Enable symbolic links" option (if present) and/or use the system Git (not an embedded Git in a GUI) so symlink support is available. [2]
- In the repo set core.symlinks = true (global or per-repo):
- git config --global core.symlinks true
- or inside the repo: git config core.symlinks true
- If you change core.symlinks after clone, recreate the worktree links:
- git reset --hard
- (or reclone after changing the setting) — some clients (e.g., GitHub Desktop) may ignore global settings when creating a repo, so reclone with the correct Git/client is easiest. [2][3]
Notes / caveats
- core.symlinks is both a request and a cached capability flag: git-clone/git-init probe the environment and may write symlinks=false into the repo config if symlinks look unsupported. Manually overriding may be necessary but some GUIs still create repos with symlinks disabled. [1][2]
- If teammates use different OSes or clients, prefer avoiding repository symlink reliance when possible (or document/standardize the required Windows settings). [1][3]
Sources
- git-config (core.symlinks) documentation. [1]
- Explanation and behavior on Windows / why clone may set symlinks=false (Stack Overflow). [2]
- Reports of GUI clients ignoring global symlink settings (GitHub Desktop issues / discussions). [3]
</web_search_result>
Symlink for sharing Convex backend — works but requires cross-platform setup documentation.
This symlink allows the Svelte example to reuse the existing Convex backend from the React example, avoiding duplication. However, symlinks have documented cross-platform issues:
- On Windows, Git often defaults to
core.symlinks=false, causing symlinks to be checked out as text files rather than actual symlinks - GitHub Desktop and some other GUI clients ignore global symlink settings and may create repositories with symlink support disabled
- Team members on different operating systems may have inconsistent experiences unless setup is standardized
Recommendation: Document the symlink requirement in a setup guide or README, specifying that Windows developers should enable Developer Mode and configure git config core.symlinks true, or consider providing a non-symlink alternative (copy or build step) for better cross-platform compatibility.
🤖 Prompt for AI Agents
In example-svelte/convex around line 1, the repository uses a filesystem symlink
to ../example/convex which can break on Windows and other environments; update
project setup to avoid platform inconsistencies by either (a) adding clear
documentation in example-svelte/README.md indicating the symlink requirement and
exact steps for Windows (enable Developer Mode and run git config core.symlinks
true) and any GUI client caveats, or (b) replace the symlink with a
cross-platform alternative such as copying the Convex backend into the example
during a setup script or adding a build step that links/duplicates the backend
content at install time; implement one of these options and ensure README lists
the chosen approach and commands to reproduce the link locally.
| export function getConvexSiteUrl() { | ||
| let convexSiteUrl; | ||
| if (import.meta.env.VITE_CONVEX_URL.includes(".cloud")) { | ||
| convexSiteUrl = import.meta.env.VITE_CONVEX_URL.replace( | ||
| /\.cloud$/, | ||
| ".site", | ||
| ); | ||
| } else { | ||
| const url = new URL(import.meta.env.VITE_CONVEX_URL); | ||
| url.port = String(Number(url.port) + 1); | ||
| convexSiteUrl = url.toString(); | ||
| } | ||
| return convexSiteUrl; | ||
| } |
There was a problem hiding this comment.
Potential edge case with implicit ports.
On line 17, if the URL uses an implicit port (e.g., https://example.com without an explicit port), url.port will be an empty string, causing Number("") + 1 = 1, resulting in an invalid port.
This is likely fine since local Convex development URLs typically have explicit ports, but worth noting if this utility is used more broadly.
export function getConvexSiteUrl() {
let convexSiteUrl;
if (import.meta.env.VITE_CONVEX_URL.includes(".cloud")) {
convexSiteUrl = import.meta.env.VITE_CONVEX_URL.replace(
/\.cloud$/,
".site",
);
} else {
const url = new URL(import.meta.env.VITE_CONVEX_URL);
- url.port = String(Number(url.port) + 1);
+ const currentPort = url.port || (url.protocol === "https:" ? "443" : "80");
+ url.port = String(Number(currentPort) + 1);
convexSiteUrl = url.toString();
}
return convexSiteUrl;
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| export function getConvexSiteUrl() { | |
| let convexSiteUrl; | |
| if (import.meta.env.VITE_CONVEX_URL.includes(".cloud")) { | |
| convexSiteUrl = import.meta.env.VITE_CONVEX_URL.replace( | |
| /\.cloud$/, | |
| ".site", | |
| ); | |
| } else { | |
| const url = new URL(import.meta.env.VITE_CONVEX_URL); | |
| url.port = String(Number(url.port) + 1); | |
| convexSiteUrl = url.toString(); | |
| } | |
| return convexSiteUrl; | |
| } | |
| export function getConvexSiteUrl() { | |
| let convexSiteUrl; | |
| if (import.meta.env.VITE_CONVEX_URL.includes(".cloud")) { | |
| convexSiteUrl = import.meta.env.VITE_CONVEX_URL.replace( | |
| /\.cloud$/, | |
| ".site", | |
| ); | |
| } else { | |
| const url = new URL(import.meta.env.VITE_CONVEX_URL); | |
| const currentPort = url.port || (url.protocol === "https:" ? "443" : "80"); | |
| url.port = String(Number(currentPort) + 1); | |
| convexSiteUrl = url.toString(); | |
| } | |
| return convexSiteUrl; | |
| } |
🤖 Prompt for AI Agents
In example-svelte/src/lib/utils.ts around lines 8 to 21, the code increments
url.port without handling the case where url.port is an empty string (implicit
port), which makes Number("") produce 0 leading to an incorrect port; change the
logic to detect an empty or non-numeric port, pick a sensible default based on
url.protocol (use 443 for https:, 80 for http:), convert that to a Number, add
1, and assign the resulting value to url.port as a string; also guard against
NaN by falling back to a safe default (e.g., 443 for https, 80 for http) before
incrementing.
| const app = mount(App, { | ||
| target: document.getElementById("app")!, | ||
| }); |
There was a problem hiding this comment.
Add defensive check for missing mount target.
The non-null assertion operator (!) assumes the #app element always exists. If the element is missing from the HTML, this will throw a runtime error.
Apply this diff to add a defensive check:
-const app = mount(App, {
- target: document.getElementById("app")!,
-});
+const appElement = document.getElementById("app");
+if (!appElement) {
+ throw new Error("Could not find element with id 'app'");
+}
+
+const app = mount(App, {
+ target: appElement,
+});📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const app = mount(App, { | |
| target: document.getElementById("app")!, | |
| }); | |
| const appElement = document.getElementById("app"); | |
| if (!appElement) { | |
| throw new Error("Could not find element with id 'app'"); | |
| } | |
| const app = mount(App, { | |
| target: appElement, | |
| }); |
🤖 Prompt for AI Agents
In example-svelte/src/main.ts around lines 5 to 7, the mount call uses a
non-null assertion on document.getElementById("app") which will throw if the
element is missing; replace it with a defensive check: retrieve the element into
a variable, if it's null either throw a clear Error("Mount target '#app' not
found") or create/append a fallback container, then pass that validated target
to mount(App, { target }). Ensure the message is descriptive and avoid using the
non-null assertion operator.
| "./svelte": { | ||
| "types": "./src/svelte/index.svelte.ts", | ||
| "svelte": "./src/svelte/index.svelte.ts", | ||
| "default": "./src/svelte/index.svelte.ts" | ||
| }, |
There was a problem hiding this comment.
🧩 Analysis chain
Script executed:
#!/bin/bash
# First, let's read the package.json to see the complete export structure
cat -n package.json | head -100Repository: get-convex/persistent-text-streaming
<shell_result>
Repository: get-convex/persistent-text-streaming
Script execution failed with unrecoverable error: [CAPABILITY:RUN_SHELL_SCRIPT] Failed to clone repository get-convex/persistent-text-streaming: Clone operation failed
</shell_result>
Svelte library packaging conventions .svelte.ts exports
<web_search_result>
Short summary — key conventions for packaging Svelte libraries (including .svelte.ts / .svelte.js module files)
-
Package exports: use package.json "exports" to map entry paths to files and conditional targets. For Svelte components use the "svelte" export condition and provide a "types" condition for TypeScript definitions. Example root export:
{
"exports": {
".": { "types": "./dist/index.d.ts", "svelte": "./dist/index.js" }
}
}
This also supports per-file exports (e.g. "./Foo.svelte"). [1] -
What to ship: prefer shipping uncompiled .svelte component files (so Svelte-aware tooling can compile them for consumers). JS/TS module helpers may be ESM. Ensure any JS is ESM and file extensions obey Node/Esm rules. [1][2]
-
.svelte.ts / .svelte.js files: Svelte treats these like normal .ts/.js modules but with Svelte "runes" support — they behave as modules (useful for shared reactive logic). They can be included in your src and packaged; when built, .ts files should produce corresponding .js and .d.ts outputs that your exports map points to. [2]
-
Types: publish type definitions and point the "types" export condition to the generated .d.ts files. Be aware TypeScript resolves some deep imports differently — for non-root exports you may need extra care so consumers can find the .d.ts (see SvelteKit packaging notes). [1]
-
Practical rules:
- Add "svelte" export condition and keep the legacy "svelte" package.json field for older tooling if needed. [1]
- Include dist (and optionally src for declaration maps) in "files".
- Ensure correct extension and module type (".mjs"/".cjs" or "type":"module") and fully‑specified relative imports in output. [1]
Sources
- SvelteKit packaging (exports, types, shipping .svelte files, declaration maps). [1]
- .svelte.js and .svelte.ts docs (behavior of .svelte.ts/.svelte.js module files). [2]
References
[1] SvelteKit — Packaging / Anatomy of package.json (exports, types, svelte, declaration maps).
[2] Svelte docs — .svelte.js and .svelte.ts files.
</web_search_result>
Source file exports for Svelte are unconventional; exports should point to compiled dist/ files.
The search confirms that standard Svelte packaging practice uses the "svelte" export condition pointing to compiled .js files in dist/, not source .svelte.ts files. The web search states:
For Svelte components use the "svelte" export condition and provide a "types" condition for TypeScript definitions...when built, .ts files should produce corresponding .js and .d.ts outputs that your exports map points to.
The review comment is correct: lines 53–55 should export compiled output from dist/svelte/ rather than source files from src/svelte/. This forces consumers to handle TypeScript compilation themselves and deviates from the React export pattern (which uses dist/).
Suggested fix:
"./svelte": {
- "types": "./src/svelte/index.svelte.ts",
- "svelte": "./src/svelte/index.svelte.ts",
- "default": "./src/svelte/index.svelte.ts"
+ "types": "./dist/svelte/index.svelte.d.ts",
+ "svelte": "./dist/svelte/index.js",
+ "default": "./dist/svelte/index.js"
},📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| "./svelte": { | |
| "types": "./src/svelte/index.svelte.ts", | |
| "svelte": "./src/svelte/index.svelte.ts", | |
| "default": "./src/svelte/index.svelte.ts" | |
| }, | |
| "./svelte": { | |
| "types": "./dist/svelte/index.svelte.d.ts", | |
| "svelte": "./dist/svelte/index.js", | |
| "default": "./dist/svelte/index.js" | |
| }, |
🤖 Prompt for AI Agents
In package.json around lines 52 to 56, the Svelte export entries point to source
files under src/svelte (./src/svelte/index.svelte.ts) instead of compiled
outputs; update those exports to reference the compiled artifacts in dist/svelte
— set "svelte" and "default" to the built .js entry in dist/svelte (e.g.
./dist/svelte/index.js) and set "types" to the generated .d.ts (e.g.
./dist/svelte/index.d.ts); ensure the build produces those files and update
package.json exports to match the dist paths.
| }, | ||
| "peerDependencies": { | ||
| "convex": "^1.24.8", | ||
| "convex-svelte": "^0.0.12", |
There was a problem hiding this comment.
🧩 Analysis chain
convex-svelte npm package latest version 0.0.12 production-ready stable
<web_search_result>
I couldn't find any convex-svelte release 0.0.12 — the npm registry shows latest published version 0.0.11. [1]
- Latest published version: 0.0.11. [1]
- Source / repo: get-convex/convex-svelte on GitHub. [2]
- Context: Convex core reached 1.0, but convex-svelte itself is still in 0.x (pre‑1.0) and therefore may not carry the same stability/semver guarantees as Convex core. Use caution for production use and test before deploying. [3][2]
If you want, I can watch the package and notify you if 0.0.12 is published, or check specific compatibility details with your Svelte/SvelteKit version.
Sources:
[1] npm package page for convex-svelte.
[2] get-convex/convex-svelte GitHub repository.
[3] Convex 1.0 announcement / docs.
</web_search_result>
Version 0.0.12 of convex-svelte does not exist in the npm registry.
The latest published version is 0.0.11. The package.json declares "convex-svelte": "^0.0.12", which npm will fail to resolve since no version ≥0.0.12 exists. Additionally, convex-svelte remains in pre-1.0 (currently 0.0.11), meaning it lacks production-level stability guarantees despite Convex core reaching 1.0. Update to "^0.0.11" or verify the correct version target.
🤖 Prompt for AI Agents
In package.json around line 72, the dependency "convex-svelte": "^0.0.12"
references a non-existent npm version; change it to a valid published version
(for example "^0.0.11") or the intended version, update the package.json entry
accordingly, then run your package manager (npm install / yarn install) to
refresh package-lock.json or yarn.lock and commit the lockfile changes so CI can
resolve the dependency.
| "devDependencies": { | ||
| "@sveltejs/vite-plugin-svelte": "^5.0.3", | ||
| "@tailwindcss/vite": "^4.1.0", | ||
| "svelte": "^5.33.0", | ||
| "tailwindcss": "^4.1.0", | ||
| "typescript": "^5.7.0", | ||
| "vite": "^6.2.0" | ||
| }, | ||
| "dependencies": { | ||
| "@convex-dev/persistent-text-streaming": "file:..", | ||
| "clsx": "^2.1.1", | ||
| "convex": "^1.29.0", | ||
| "convex-svelte": "^0.0.12", | ||
| "marked": "^15.0.0", | ||
| "tailwind-merge": "^3.3.0" | ||
| } | ||
| } | ||
|
|
There was a problem hiding this comment.
is it possible to put these dependencies in the parent so there's only one node_modules folder to deal with?
Adds useStream hook for Svelte 5, mirroring
the React implementation. Includes a svekte example app
demonstrating usage.
Resolves: #10
By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.
Summary by CodeRabbit
New Features
Documentation
✏️ Tip: You can customize this high-level summary in your review settings.