Skip to content

add svelte adapter#104

Open
luca-peruzzo wants to merge 11 commits intomainfrom
feature/svelte-adapter
Open

add svelte adapter#104
luca-peruzzo wants to merge 11 commits intomainfrom
feature/svelte-adapter

Conversation

@luca-peruzzo
Copy link
Copy Markdown
Member

@luca-peruzzo luca-peruzzo commented Oct 5, 2025

Summary by CodeRabbit

  • New Features

    • Added Svelte support with single- and multi-provider example apps demonstrating OIDC flows, protected routes, token renewal, auto-logout warning, and provider selection (Google, Microsoft, Keycloak, Auth0).
    • New UI components and pages for login state, provider selection, and diagnostic token views.
  • Documentation

    • Expanded READMEs with setup, configuration, HMR, and state guidance.
  • Chores

    • Added env templates, .gitignore, project configs, HTML entry files, and TypeScript declarations for Svelte examples.
  • Build

    • Package/exports updated to include Svelte bindings and mocks.

@luca-peruzzo luca-peruzzo requested a review from garronej October 5, 2025 20:55
@luca-peruzzo luca-peruzzo self-assigned this Oct 5, 2025
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Oct 5, 2025

Walkthrough

Adds a Svelte adapter and runtime for OIDC (core API, DI factory, context, provider components, hooks), extends build/packaging to emit Svelte artifacts and exports, and introduces two full Svelte example apps (single- and multi-provider) with lazy OIDC-gated boot, routing, UI components, and env samples.

Changes

Cohort / File(s) Summary of edits
Svelte adapter (core)
src/svelte/...
src/svelte/index.svelte.ts, src/svelte/OidcProvider.svelte, src/svelte/OidcContextProvider.svelte, src/svelte/OidcProviderProps.ts, src/svelte/oidc.context.ts
New dependency‑injected Svelte OIDC factory and public API (createSvelteOidc_dependencyInjection / createSvelteOidc), typed OidcSvelte API, mount/use/enforceLogin utilities, OidcProvider UI wrapper and context helpers, and auto-logout countdown hook.
Svelte mock adapter
src/mock/svelte.ts
New helper createMockSvelteOidc delegating to Svelte DI factory with mock implementation.
Build & packaging
package.json, scripts/build.ts
Exports surface extended with ./svelte and ./mock/svelte; peerDeps/meta updated to include Svelte/Angular; build script updated to copy/remove .svelte artifacts and adjusted webpack test pattern.
Svelte examples (single provider)
examples/svelte/...
examples/svelte/.env.local.sample, .gitignore, README.md, index.html, package.json, svelte.config.js, vite.config.ts, tsconfig*.json, src/*
New Vite+Svelte example wiring OIDC (mock or real based on env), lazy startup via oidcEarlyInit, router + protected route, Header, login/register buttons, AutoLogoutWarningOverlay, Protected/Public pages, TypeScript/Vite config and docs.
Svelte examples (multi-provider)
examples/svelte-multi-providers/...
examples/svelte-multi-providers/.env.local.sample, .gitignore, README.md, index.html, package.json, svelte.config.js, vite.config.ts, tsconfig*.json, src/*
New multi‑provider example (Google + Microsoft): initializeOidc for multiple providers, modal provider selection UI, provider-specific context wrappers, guarded protected route pre-hook, diagnostic token decoding page, and app wiring with lazy boot.
Example shared UI & wiring
examples/**/src/components/*, examples/**/src/pages/*, examples/**/src/routes.ts
New shared UI components (Header, LoggedInAuthButton, NotLoggedInAuthButton, AutoLogoutWarningOverlay, SelectProviderDialog, provider wrappers), pages (Public/Protected) and router configurations using enforceLogin / beforeLoad_protectedRoute.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant B as Browser
  participant E as /src/main.ts
  participant O as oidcEarlyInit
  participant L as main.lazy (dynamic)
  participant A as App (mounted)

  B->>E: load /src/main.ts
  E->>O: oidcEarlyInit({ freeze fetch/xhr/ws })
  O-->>E: { shouldLoadApp }
  alt shouldLoadApp == true
    E->>L: dynamic import("./main.lazy")
    L->>A: mount(App, target=#app)
    A-->>B: UI rendered
  else
    E-->>B: app boot withheld (await auth)
  end
Loading
sequenceDiagram
  autonumber
  participant U as User
  participant H as Header
  participant R as Router
  participant C as OIDC API (enforceLogin)
  participant IdP as Identity Provider

  U->>H: click "Protected"
  H->>R: navigate "/protected"
  R->>C: pre-hook → enforceLogin(redirect)
  alt user logged in
    C-->>R: allow navigation
  else not logged in
    C->>IdP: redirect to auth endpoint
    IdP-->>C: redirect back (code/token)
    C-->>R: auth success → allow
  end
  R-->>U: ProtectedPage rendered
Loading
sequenceDiagram
  autonumber
  participant U as User
  participant N as NotLoggedInAuthButton
  participant D as SelectProviderDialog
  participant G as Google OIDC
  participant M as Microsoft OIDC
  participant IdP as Chosen Provider

  U->>N: Click "Login"
  N->>D: open selection dialog
  D-->>N: provider selected
  alt google
    N->>G: login({ doesCurrentHrefRequiresAuth: false })
    G->>IdP: browser redirect to Google
  else microsoft
    N->>M: login({ doesCurrentHrefRequiresAuth: false })
    M->>IdP: browser redirect to Microsoft
  else cancel
    N-->>U: no action
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • keycloak-js polifills #80 — Related changes to Keycloak utilities and issuer handling referenced by example components.
  • Bundle size optimization #81 — Overlapping build and packaging changes for emitting Svelte artifacts and exports; likely to conflict in build logic.

Poem

Ears up, I hop through routes anew,
Two providers, one carrot‑cue—
Tokens hum and dialogs glow,
A countdown whispers, "time to go."
I nudge the login, then off I zoom—hare to the auth flow. 🥕✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title “add svelte adapter” accurately and concisely summarizes the primary objective of this pull request, which is to introduce Svelte integration and corresponding adapter code. It reflects the main change without extraneous detail and is immediately understandable to reviewers.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/svelte-adapter

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 9

🧹 Nitpick comments (3)
examples/svelte/src/Fallback.svelte (1)

1-3: Consider removing the empty script block.

The empty TypeScript script block serves no purpose and can be safely removed to reduce clutter.

Apply this diff:

-<script lang="ts">
-
-</script>
-
 <p>Loading...</p>
src/svelte/OidcProviderProps.ts (1)

15-16: Consider the fragility of coupling to Svelte's mount signature.

Extracting types from Parameters<typeof mount> is valid but tightly couples these types to Svelte's internal mount function signature. If Svelte changes the mount API in a future version, this will break.

Consider adding explicit type definitions or a comment documenting the assumed mount signature:

+// Assumes Svelte mount signature: mount(component: Component, options: { target: Element, props?: Record<string, any> })
 export type OidcProviderProps<
     DecodedIdToken extends Record<string, unknown>,
     AutoLogin extends boolean
 > = {
     App: Parameters<typeof mount>[0];
     appProps: Parameters<typeof mount>[1]["props"];
src/svelte/oidc.context.ts (1)

12-14: Consider adding error handling for missing OIDC context.

If getOidcContext is called outside of an OIDC provider tree, it will return undefined. This could lead to cryptic errors in consuming components.

Consider validating that the context exists:

 export const getOidcContext = <DecodedIdToken extends Record<string, unknown>>() => {
-    return getContext<{ oidc: Oidc<DecodedIdToken> }>(oidcContextKey);
+    const context = getContext<{ oidc: Oidc<DecodedIdToken> }>(oidcContextKey);
+    if (!context) {
+        throw new Error("getOidcContext must be called within an OIDC provider component");
+    }
+    return context;
 };

This provides a clearer error message and fails fast, making debugging easier.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 444f3a3 and 7f2cdf3.

⛔ Files ignored due to path filters (4)
  • examples/svelte/src/assets/svelte.svg is excluded by !**/*.svg
  • examples/svelte/src/assets/vite.svg is excluded by !**/*.svg
  • examples/svelte/yarn.lock is excluded by !**/yarn.lock, !**/*.lock
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (34)
  • examples/svelte/.env.local.sample (1 hunks)
  • examples/svelte/.gitignore (1 hunks)
  • examples/svelte/README.md (1 hunks)
  • examples/svelte/index.html (1 hunks)
  • examples/svelte/package.json (1 hunks)
  • examples/svelte/src/App.svelte (1 hunks)
  • examples/svelte/src/Fallback.svelte (1 hunks)
  • examples/svelte/src/app.css (1 hunks)
  • examples/svelte/src/components/AutoLogoutWarningOverlay.svelte (1 hunks)
  • examples/svelte/src/components/Header.svelte (1 hunks)
  • examples/svelte/src/components/LoggedInAuthButton.svelte (1 hunks)
  • examples/svelte/src/components/NotLoggedInAuthButton.svelte (1 hunks)
  • examples/svelte/src/env.d.ts (1 hunks)
  • examples/svelte/src/lib/Counter.svelte (1 hunks)
  • examples/svelte/src/main.lazy.ts (1 hunks)
  • examples/svelte/src/main.ts (1 hunks)
  • examples/svelte/src/oidc.ts (1 hunks)
  • examples/svelte/src/pages/ProtectedPage.svelte (1 hunks)
  • examples/svelte/src/pages/PublicPage.svelte (1 hunks)
  • examples/svelte/src/routes.ts (1 hunks)
  • examples/svelte/src/vite-env.d.ts (1 hunks)
  • examples/svelte/svelte.config.js (1 hunks)
  • examples/svelte/tsconfig.app.json (1 hunks)
  • examples/svelte/tsconfig.json (1 hunks)
  • examples/svelte/tsconfig.node.json (1 hunks)
  • examples/svelte/vite.config.ts (1 hunks)
  • package.json (4 hunks)
  • scripts/build.ts (3 hunks)
  • src/mock/svelte.ts (1 hunks)
  • src/svelte/OidcProvider.svelte (1 hunks)
  • src/svelte/OidcProviderLogged.svelte (1 hunks)
  • src/svelte/OidcProviderProps.ts (1 hunks)
  • src/svelte/index.svelte.ts (1 hunks)
  • src/svelte/oidc.context.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (5)
src/mock/svelte.ts (3)
src/tools/ValueOrAsyncGetter.ts (1)
  • ValueOrAsyncGetter (1-1)
src/mock/oidc.ts (1)
  • ParamsOfCreateMockOidc (9-28)
src/svelte/index.svelte.ts (1)
  • createSvelteOidc_dependencyInjection (118-395)
examples/svelte/src/main.lazy.ts (1)
examples/react-router-framework/app/root.tsx (1)
  • App (42-56)
src/svelte/index.svelte.ts (8)
src/tools/tsafe/Param0.ts (1)
  • Param0 (6-12)
src/tools/tsafe/Parameters.ts (1)
  • Parameters (2-3)
src/svelte/OidcProviderProps.ts (2)
  • OidcProviderOidcProps (4-9)
  • OidcProviderProps (11-19)
src/tools/ValueOrAsyncGetter.ts (1)
  • ValueOrAsyncGetter (1-1)
src/tools/Deferred.ts (1)
  • Deferred (1-35)
src/svelte/oidc.context.ts (1)
  • getOidcContext (12-14)
src/tools/toFullyQualifiedUrl.ts (1)
  • toFullyQualifiedUrl (13-58)
src/core/Oidc.ts (1)
  • DecodedIdToken_base (135-142)
examples/svelte/src/oidc.ts (2)
src/keycloak/keycloak-js/Keycloak.ts (2)
  • init (80-260)
  • oidc (1052-1063)
examples/multi-providers/src/oidc.tsx (1)
  • getOidc (38-59)
src/svelte/OidcProviderProps.ts (1)
src/tools/tsafe/Parameters.ts (1)
  • Parameters (2-3)
🪛 Biome (2.1.2)
scripts/build.ts

[error] 72-76: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Safe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)

🪛 dotenv-linter (3.3.0)
examples/svelte/.env.local.sample

[warning] 5-5: [UnorderedKey] The VITE_OIDC_CLIENT_ID key should go before the VITE_OIDC_ISSUER_URI key

(UnorderedKey)

🪛 markdownlint-cli2 (0.18.1)
examples/svelte/README.md

38-38: Link text should be descriptive

(MD059, descriptive-link-text)

🔇 Additional comments (19)
scripts/build.ts (1)

322-322: LGTM! Cleanup step correctly removes CJS artifacts.

This appropriately removes the CJS-compiled dist/svelte directory while preserving the ESM Svelte sources in dist/esm/svelte. The force: true flag ensures no error if the directory doesn't exist.

examples/svelte/src/lib/Counter.svelte (1)

1-10: LGTM!

The component correctly uses Svelte 5's $state rune for reactive state management. The implementation is clean and follows Svelte best practices.

examples/svelte/index.html (1)

1-13: LGTM!

Standard Vite + Svelte HTML entry point with proper meta tags and module script loading.

package.json (4)

51-56: LGTM!

The peer dependencies correctly include Angular and Svelte packages with wildcard versions, allowing flexibility for users.


68-76: LGTM!

Properly marks all framework peer dependencies as optional, maintaining the library's framework-agnostic nature.


139-151: LGTM!

The new Svelte and mock Svelte exports follow the established pattern for framework adapters (matching React and Angular exports).


79-104: Unnecessary Zod 3.x compatibility warning
Zod is only imported under src/vendor/backend and the /examples directory; no .parse/.safeParse or ZodError usage was found in the core code. Pinning to ^3.x carries no immediate risk.

src/mock/svelte.ts (1)

5-10: LGTM!

The mock factory correctly follows the dependency injection pattern established in the codebase, delegating to createSvelteOidc_dependencyInjection with the mock OIDC creator. The type parameters are properly constrained.

examples/svelte/src/vite-env.d.ts (1)

1-1: LGTM!

Standard Vite client types reference, correctly configured.

examples/svelte/tsconfig.json (1)

1-4: LGTM!

Standard TypeScript project references configuration, correctly structured.

src/svelte/OidcProviderLogged.svelte (1)

1-10: LGTM!

Clean implementation using Svelte 5 syntax. The component correctly sets the OIDC context and renders children.

examples/svelte/src/App.svelte (1)

1-10: LGTM!

Clean app structure with proper component composition.

examples/svelte/src/main.ts (1)

1-11: LGTM!

The early initialization pattern correctly follows the oidc-spa security-first approach, freezing network APIs before the main app loads to mitigate supply-chain and XSS risks. The conditional lazy loading based on shouldLoadApp is appropriate.

Based on learnings.

examples/svelte/src/components/LoggedInAuthButton.svelte (1)

8-8: Verify that name claim is always present in the ID token.

Direct access to decodedIdToken.name assumes the name claim exists. If the OIDC provider doesn't always include this claim, a runtime error will occur.

Consider adding a fallback or validation:

-    <span>Hello {decodedIdToken.name}</span>
+    <span>Hello {decodedIdToken.name ?? 'User'}</span>

Or validate the ID token shape with Zod to enforce the presence of required claims. Based on learnings.

examples/svelte/tsconfig.app.json (1)

1-21: LGTM!

The TypeScript configuration is well-structured for a Svelte application with appropriate compiler options and includes patterns.

examples/svelte/.env.local.sample (1)

15-15: Verify necessity of VITE_OIDC_CLIENT_SECRET for Google OAuth in an SPA.

OAuth client secrets should not be used in single-page applications, as they cannot be kept confidential in client-side code. Google OAuth for SPAs typically uses the Authorization Code Flow with PKCE without a client secret.

Confirm whether this is truly needed for the Google configuration or if it should be removed to align with SPA security best practices.

examples/svelte/svelte.config.js (1)

1-8: LGTM!

The Svelte configuration correctly uses vitePreprocess from the official Vite plugin, which is the standard approach for integrating Svelte with Vite.

examples/svelte/src/components/Header.svelte (1)

1-35: LGTM!

The Header component correctly integrates OIDC state and routing. The error handling provides helpful feedback to users, and the conditional rendering of authentication buttons based on login state is appropriate.

examples/svelte/tsconfig.node.json (1)

1-26: LGTM!

The Node TypeScript configuration is well-structured with appropriate strict settings for build tooling. The target and module resolution settings align with modern Node.js and bundler requirements.

Comment thread examples/svelte/package.json
Comment thread examples/svelte/README.md Outdated
Comment thread examples/svelte/src/app.css Outdated
Comment thread examples/svelte/src/components/AutoLogoutWarningOverlay.svelte Outdated
Comment thread examples/svelte/src/components/NotLoggedInAuthButton.svelte Outdated
Comment thread examples/svelte/src/main.lazy.ts Outdated
Comment thread examples/svelte/src/pages/ProtectedPage.svelte
Comment thread examples/svelte/src/pages/PublicPage.svelte Outdated
Comment thread scripts/build.ts Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (5)
scripts/build.ts (2)

72-89: Previous review concerns addressed successfully.

The code now properly:

  1. Wraps the Svelte file handling in a block to prevent variable scope leakage
  2. Checks for directory existence before calling readdirSync
  3. Uses explicit path construction for Node.js compatibility

Minor improvement: Change let file to const file on line 82 since the loop variable is never reassigned.

Apply this diff for the minor improvement:

-                    for (let file of svelteFiles) {
+                    for (const file of svelteFiles) {
                         fs.copyFileSync(
                             pathJoin(srcSvelteDirPath, file.name),
                             pathJoin(distDirPath, "svelte", `${file.name}`)

222-222: Revert unnecessary template interpolation.

The change from test: /\.js$/, to test: ${/\.js$/}, is functionally identical (the regex .toString() produces the same string) but adds unnecessary complexity. The original direct literal was clearer.

Apply this diff to restore clarity:

-                                        `        test: ${/\.js$/},`,
+                                        `        test: /\.js$/,`,
examples/svelte/src/components/AutoLogoutWarningOverlay.svelte (1)

10-10: Refactor inline styles into a CSS class.

The extensive inline styles reduce maintainability and readability. Consider extracting them into a <style> block or external stylesheet.

Apply this diff:

+<style>
+    .logout-overlay {
+        position: fixed;
+        top: 0;
+        left: 0;
+        right: 0;
+        bottom: 0;
+        background-color: rgba(0, 0, 0, 0.5);
+        backdrop-filter: blur(10px);
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        z-index: 1000;
+    }
+</style>
+
 {#if $secondsLeft}
-    <div
-        style="position: fixed; top: 0; left: 0; right: 0; bottom: 0; background-color: rgba(0,0,0,0.5); backdrop-filter: blur(10px); display: flex; justify-content: center; align-items: center; z-index: 1000;"
-    >
+    <div class="logout-overlay">
         <div>
src/svelte/OidcProviderProps.ts (2)

16-17: Consider more explicit typing for mount-derived types.

Extracting types via Parameters<typeof mount> couples these declarations to Svelte's internal API shape. If Svelte adjusts the mount signature in a minor release, or if the extracted props property resolves to any, type safety could degrade.

Consider one of the following approaches:

  • Option 1 (recommended): Explicitly define the expected types:
    App: Component;
    appProps?: Record<string, any>;
  • Option 2: Add runtime or compile-time assertions to verify the extracted types match expectations, or document the assumed mount signature more prominently.

This improves clarity and reduces fragility when Svelte evolves.


18-18: Consider a discriminated union for initialization state.

The current union type OidcInitializationError | Oidc<DecodedIdToken> | undefined requires consumers to perform runtime type checks (e.g., instanceof, property checks) to discriminate between states.

A discriminated union with a status or kind field would improve type safety and reduce boilerplate:

oidcOrInitializationError:
  | { status: "loading" }
  | { status: "error"; error: OidcInitializationError }
  | { status: "ready"; oidc: Oidc<DecodedIdToken> };

This pattern enables exhaustive switch statements and better IntelliSense support. However, this refactor can be deferred if the current approach is sufficient for your use case.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7f2cdf3 and f3ce6a2.

📒 Files selected for processing (8)
  • examples/svelte/README.md (1 hunks)
  • examples/svelte/src/Fallback.svelte (1 hunks)
  • examples/svelte/src/app.css (1 hunks)
  • examples/svelte/src/components/AutoLogoutWarningOverlay.svelte (1 hunks)
  • examples/svelte/src/main.lazy.ts (1 hunks)
  • examples/svelte/src/pages/PublicPage.svelte (1 hunks)
  • scripts/build.ts (3 hunks)
  • src/svelte/OidcProviderProps.ts (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • examples/svelte/README.md
🚧 Files skipped from review as they are similar to previous changes (4)
  • examples/svelte/src/main.lazy.ts
  • examples/svelte/src/Fallback.svelte
  • examples/svelte/src/pages/PublicPage.svelte
  • examples/svelte/src/app.css
🧰 Additional context used
🧬 Code graph analysis (1)
src/svelte/OidcProviderProps.ts (1)
src/tools/tsafe/Parameters.ts (1)
  • Parameters (2-3)
🔇 Additional comments (4)
scripts/build.ts (1)

329-329: LGTM! Defensive cleanup prevents stale artifacts.

The removal of dist/svelte at the root level is appropriate defensive cleanup. Since Svelte files are copied to dist/esm/svelte/ during the ESM build, this ensures no stale root-level Svelte directory remains. The force: true flag correctly prevents errors if the directory doesn't exist.

examples/svelte/src/components/AutoLogoutWarningOverlay.svelte (2)

14-14: Previous issue resolved.

The inconsistent store access flagged in the earlier review has been fixed. Line 14 now correctly uses {$secondsLeft} with the $ prefix.


8-17: Verify the intended UX: no dismiss or extend session action.

The overlay displays a countdown but doesn't provide any way for users to dismiss it or extend their session. This may be intentional, but consider whether users should have the option to stay logged in.

If user interaction is needed, you could add a button to extend the session or dismiss the warning. Would you like me to suggest an implementation that includes user controls?

src/svelte/OidcProviderProps.ts (1)

4-9: Clarify ErrorFallback conditional logic
Currently ErrorFallback is only allowed when AutoLogin is true, but initialization errors can occur even in manual-login flows. Should ErrorFallback also be available when AutoLogin is false?

Comment thread examples/svelte/src/components/AutoLogoutWarningOverlay.svelte
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (7)
examples/svelte-multi-providers/src/main.ts (1)

9-11: Consider adding error handling for the dynamic import.

The dynamic import of main.lazy lacks error handling. If the module fails to load, the application will silently fail without user feedback.

Apply this diff to add error handling:

 if (shouldLoadApp) {
-    import("./main.lazy");
+    import("./main.lazy").catch((error) => {
+        console.error("Failed to load application:", error);
+        // Optionally display user-facing error UI
+    });
 }
examples/svelte-multi-providers/src/components/LoggedInAuthButton.svelte (1)

7-10: Add defensive checks for token fields.

Direct access to decodedIdToken.name assumes the field exists. While useOidc_assertUserLoggedIn guarantees a logged-in state, the token shape depends on the OIDC provider configuration.

Apply this diff to handle missing name field:

 <div>
-    <span>Hello {decodedIdToken.name}</span>
+    <span>Hello {decodedIdToken.name ?? "User"}</span>
     &nbsp; &nbsp;
     <button onclick={() => logout({ redirectTo: "home" })}>Logout</button>
 </div>
examples/svelte-multi-providers/src/components/AutoLogoutWarningOverlay.svelte (1)

8-17: Consider adding user interaction options.

The overlay displays a countdown but provides no way for the user to acknowledge their presence or dismiss the warning. This could lead to frustration if a user is actively working but the overlay appears.

Consider adding an interaction button:

 {#if $secondsLeft}
     <div
         style="position: fixed; top: 0; left: 0; right: 0; bottom: 0; background-color: rgba(0,0,0,0.5); backdrop-filter: blur(10px); display: flex; justify-content: center; align-items: center; z-index: 1000;"
     >
         <div>
             <p>Are you still there?</p>
             <p>You will be logged out in {$secondsLeft}</p>
+            <button onclick={() => { /* Reset countdown or make user action */ }}>
+                I'm still here
+            </button>
         </div>
     </div>
 {/if}

Verify whether the OIDC library's useAutoLogoutWarningCountdown hook provides a method to reset or acknowledge the countdown.

examples/svelte-multi-providers/src/components/NotLoggedInAuthButton.svelte (1)

18-18: Consider dynamic button text.

The button text "Login with Google or Microsoft" is hardcoded, but askUserToSelectProvider() suggests the available providers might be configurable. If the provider list can vary, consider making the button text dynamic to reflect the actual available providers.

src/svelte/index.svelte.ts (2)

456-467: Preserve autoLogin-conditioned API types without @ts-expect-error

Hardcoding false erodes type guarantees (e.g., presence of enforceLogin). Cast the assembled object to the correct conditional type and drop the error suppression.

Apply this diff:

-    const oidcSvelteApi: OidcSvelteApi<DecodedIdToken, false> = {
+    const oidcSvelteApi = {
         initializeOidc,
         OidcContextProvider,
         mountOidc,
         useOidc: useOidc as any,
         getOidc,
         enforceLogin
-    };
-
-    // @ts-expect-error: We know what we are doing
-    return oidcSvelteApi;
+    } as OidcSvelteApi<
+        DecodedIdToken,
+        ParamsOfCreateOidc extends { autoLogin?: true | undefined } ? true : false
+    >;
+    return oidcSvelteApi;

216-219: Typos in error messages

Minor but user-facing; fix spelling to improve DX.

Apply this diff:

-            "You must call initializeOidc only once per provider to intiialize"
+            "You must call initializeOidc only once per provider to initialize"
@@
-                "Oidc not inizitialized, you must call initializeOidc or mountOidc"
+                "OIDC not initialized, you must call initializeOidc or mountOidc"
@@
-            "Oidc not inizitialized, you must call initializeOidc or mountOidc"
+            "OIDC not initialized, you must call initializeOidc or mountOidc"

Also applies to: 270-273, 309-316

examples/svelte-multi-providers/src/oidc.ts (1)

131-157: Route guard logic looks correct; small UX thought

Guard returns true when logged in, throws on preload, otherwise prompts and logs in. Consider returning a redirect boolean when history.back() isn’t desired (e.g., deep-linked protected route). Optional.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f3ce6a2 and 6129c4b.

⛔ Files ignored due to path filters (4)
  • examples/svelte-multi-providers/src/assets/svelte.svg is excluded by !**/*.svg
  • examples/svelte-multi-providers/src/assets/vite.svg is excluded by !**/*.svg
  • examples/svelte-multi-providers/yarn.lock is excluded by !**/yarn.lock, !**/*.lock
  • examples/svelte/yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (36)
  • examples/svelte-multi-providers/.env.local.sample (1 hunks)
  • examples/svelte-multi-providers/.gitignore (1 hunks)
  • examples/svelte-multi-providers/README.md (1 hunks)
  • examples/svelte-multi-providers/index.html (1 hunks)
  • examples/svelte-multi-providers/package.json (1 hunks)
  • examples/svelte-multi-providers/src/App.svelte (1 hunks)
  • examples/svelte-multi-providers/src/app.css (1 hunks)
  • examples/svelte-multi-providers/src/components/AutoLogoutWarningOverlay.svelte (1 hunks)
  • examples/svelte-multi-providers/src/components/Google.svelte (1 hunks)
  • examples/svelte-multi-providers/src/components/Header.svelte (1 hunks)
  • examples/svelte-multi-providers/src/components/LoggedInAuthButton.svelte (1 hunks)
  • examples/svelte-multi-providers/src/components/Microsoft.svelte (1 hunks)
  • examples/svelte-multi-providers/src/components/NotLoggedInAuthButton.svelte (1 hunks)
  • examples/svelte-multi-providers/src/components/SelectProviderDialog.svelte (1 hunks)
  • examples/svelte-multi-providers/src/env.d.ts (1 hunks)
  • examples/svelte-multi-providers/src/main.lazy.ts (1 hunks)
  • examples/svelte-multi-providers/src/main.ts (1 hunks)
  • examples/svelte-multi-providers/src/oidc.ts (1 hunks)
  • examples/svelte-multi-providers/src/pages/ProtectedPage.svelte (1 hunks)
  • examples/svelte-multi-providers/src/pages/PublicPage.svelte (1 hunks)
  • examples/svelte-multi-providers/src/routes.ts (1 hunks)
  • examples/svelte-multi-providers/src/vite-env.d.ts (1 hunks)
  • examples/svelte-multi-providers/svelte.config.js (1 hunks)
  • examples/svelte-multi-providers/tsconfig.app.json (1 hunks)
  • examples/svelte-multi-providers/tsconfig.json (1 hunks)
  • examples/svelte-multi-providers/tsconfig.node.json (1 hunks)
  • examples/svelte-multi-providers/vite.config.ts (1 hunks)
  • examples/svelte/src/App.svelte (1 hunks)
  • examples/svelte/src/env.d.ts (1 hunks)
  • examples/svelte/src/main.lazy.ts (1 hunks)
  • examples/svelte/src/oidc.ts (1 hunks)
  • src/svelte/OidcContextProvider.svelte (1 hunks)
  • src/svelte/OidcProvider.svelte (1 hunks)
  • src/svelte/OidcProviderProps.ts (1 hunks)
  • src/svelte/index.svelte.ts (1 hunks)
  • src/svelte/oidc.context.ts (1 hunks)
✅ Files skipped from review due to trivial changes (6)
  • examples/svelte-multi-providers/index.html
  • examples/svelte-multi-providers/tsconfig.json
  • examples/svelte-multi-providers/src/vite-env.d.ts
  • examples/svelte-multi-providers/src/app.css
  • examples/svelte-multi-providers/README.md
  • examples/svelte-multi-providers/src/pages/PublicPage.svelte
🚧 Files skipped from review as they are similar to previous changes (2)
  • examples/svelte/src/main.lazy.ts
  • examples/svelte/src/App.svelte
🧰 Additional context used
🧬 Code graph analysis (5)
examples/svelte-multi-providers/src/routes.ts (1)
examples/svelte-multi-providers/src/oidc.ts (1)
  • beforeLoad_protectedRoute (131-158)
examples/svelte-multi-providers/src/oidc.ts (1)
src/svelte/index.svelte.ts (2)
  • createSvelteOidc (469-474)
  • OidcSvelte (22-24)
src/svelte/index.svelte.ts (6)
src/tools/tsafe/Param0.ts (1)
  • Param0 (6-12)
src/svelte/OidcProviderProps.ts (2)
  • OidcProviderOidcProps (4-9)
  • OidcProviderProps (12-21)
src/tools/ValueOrAsyncGetter.ts (1)
  • ValueOrAsyncGetter (1-1)
src/tools/Deferred.ts (1)
  • Deferred (1-35)
src/svelte/oidc.context.ts (2)
  • setOidcContext (4-11)
  • getOidcContext (13-17)
src/tools/toFullyQualifiedUrl.ts (1)
  • toFullyQualifiedUrl (13-58)
examples/svelte/src/oidc.ts (2)
src/mock/svelte.ts (1)
  • createMockSvelteOidc (5-10)
src/svelte/index.svelte.ts (1)
  • createSvelteOidc (469-474)
src/svelte/OidcProviderProps.ts (1)
src/tools/tsafe/Parameters.ts (1)
  • Parameters (2-3)
🪛 dotenv-linter (3.3.0)
examples/svelte-multi-providers/.env.local.sample

[warning] 9-9: [UnorderedKey] The VITE_OIDC_CLIENT_ID_MICROSOFT key should go before the VITE_OIDC_ISSUER_URI_MICROSOFT key

(UnorderedKey)


[warning] 14-14: [UnorderedKey] The VITE_OIDC_CLIENT_ID_GOOGLE key should go before the VITE_OIDC_ISSUER_URI_GOOGLE key

(UnorderedKey)


[warning] 15-15: [UnorderedKey] The VITE_OIDC_CLIENT_SECRET_GOOGLE key should go before the VITE_OIDC_ISSUER_URI_GOOGLE key

(UnorderedKey)

🪛 Gitleaks (8.28.0)
examples/svelte-multi-providers/.env.local.sample

[high] 15-15: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

🔇 Additional comments (21)
examples/svelte-multi-providers/.gitignore (1)

1-24: Gitignore entries look solid.

Standard log, build, and editor artifacts are covered, with the VS Code override handled correctly.

examples/svelte-multi-providers/src/env.d.ts (1)

1-10: LGTM!

The ambient type declarations follow the standard Vite pattern for typed environment variable access. The structure is consistent with the single-provider example.

src/svelte/OidcContextProvider.svelte (1)

1-15: LGTM with a note on the prop pattern.

The component correctly sets the OIDC context and renders children. The generic DecodedIdToken parameter enables type-safe token handling.

Note: Passing setOidcContext as a prop (rather than importing it directly) is an uncommon pattern but provides flexibility for testing and dependency injection.

examples/svelte-multi-providers/src/App.svelte (1)

1-19: LGTM!

The multi-provider composition correctly nests the Google and Microsoft provider contexts, allowing both to be available throughout the component tree. The Router and SelectProviderDialog are appropriately positioned as siblings inside the provider wrappers.

examples/svelte-multi-providers/src/main.lazy.ts (1)

1-12: LGTM!

The lazy entry point correctly uses the Svelte 5 mount API, provides clear error handling for the missing DOM element, and exports the mounted app instance for HMR and testing support.

examples/svelte-multi-providers/src/components/Header.svelte (1)

10-12: Review the absolute positioning choice.

The header uses position: absolute which removes it from the document flow and may cause content overlap. Consider whether position: fixed (for a sticky header) or normal flow positioning better suits the layout needs.

If you're seeing layout issues or content being hidden under the header, try:

 <div
-    style="display: flex; justify-content: space-between; align-items: center; position: absolute; top: 0; left: 0; width: 100%;"
+    style="display: flex; justify-content: space-between; align-items: center; position: fixed; top: 0; left: 0; width: 100%; background: white; padding: 1rem; box-shadow: 0 2px 4px rgba(0,0,0,0.1); z-index: 100;"
 >

Or remove absolute positioning entirely and let content flow naturally with appropriate padding/margin on the page content.

examples/svelte-multi-providers/svelte.config.js (1)

1-8: LGTM!

Standard Svelte configuration using vitePreprocess with proper type annotations. This follows the official Svelte + Vite integration pattern.

examples/svelte-multi-providers/package.json (2)

7-7: Verify the prepare script logic.

The prepare script uses a conditional to avoid overwriting an existing .env.local file. The || true ensures the script doesn't fail if the file exists. This is correct, but ensure that the .env.local.sample file exists in the repository so the copy can succeed when needed.


18-18: Verified specified package versions exist on npm. No action required.

examples/svelte-multi-providers/vite.config.ts (1)

1-7: LGTM!

Standard Vite configuration with the Svelte plugin. The use of defineConfig provides type safety, and the configuration follows Vite best practices.

examples/svelte-multi-providers/src/components/Google.svelte (1)

1-33: LGTM!

The component correctly handles the three OIDC initialization states (loading, error, success) with proper type guarding using instanceof for OidcInitializationError. The context provider wrapping in the success state follows the expected pattern for multi-provider OIDC integration.

examples/svelte-multi-providers/src/components/SelectProviderDialog.svelte (1)

1-39: LGTM!

The component correctly uses the evt library for event-driven modal management, properly subscribes/unsubscribes with onDestroy cleanup, and handles the dialog lifecycle appropriately. The default behavior of posting undefined when the dialog is closed (e.g., via ESC key) is a good UX pattern.

examples/svelte/src/env.d.ts (1)

1-10: LGTM!

Standard ambient type declarations for Vite environment variables. This properly extends ImportMeta.env to provide type safety for the OIDC configuration variables used throughout the Svelte examples.

src/svelte/oidc.context.ts (1)

1-17: LGTM!

Type-safe wrappers around Svelte's context API that enable sharing OIDC state across components. The use of symbol-based keys prevents naming collisions, and the generic type parameters provide proper type inference for consumers.

src/svelte/OidcProvider.svelte (1)

1-39: LGTM: Initialization flow, fallbacks, and context provisioning are sound

Props typing, error branching, and context setup look correct.

examples/svelte-multi-providers/src/routes.ts (1)

6-19: Verify default route path and pre-hook cause

  • Is omitting path on the first route the intended way to match the root with this router? Some routers require '' or '/'.
  • pre passes { cause: "" }. If you intended to trigger the “preload” branch, use "preload". Otherwise, current logic will prompt login rather than throw the preload sentinel error.
examples/svelte/src/oidc.ts (1)

12-32: LGTM: Conditional mock/real OIDC wiring

Clean split between mock and real OIDC with correct export surface. The note about autoLogin vs isUserInitiallyLoggedIn is helpful.

src/svelte/OidcProviderProps.ts (1)

4-21: LGTM: Conditional prop types are well-modeled

AutoLogin-based gating of ErrorFallback and mount-derived App/appProps types look good.

src/svelte/index.svelte.ts (1)

235-266: Build config check: .svelte.ts runes

This module uses $state in .svelte.ts. Ensure your Vite/Svelte plugin is configured to transform runes in TS modules (not only .svelte components). If not, this will fail to compile.

Based on learnings

examples/svelte-multi-providers/src/oidc.ts (1)

38-59: LGTM: Multi-provider getOidc flow

Sequential provider check with a precise not-logged-in shape is clear and ergonomic.

examples/svelte-multi-providers/src/pages/ProtectedPage.svelte (1)

106-107: Fix Svelte event binding: use on:click, not onclick

Current handler won’t fire in Svelte.

Apply this diff:

-        <button onclick={() => renewTokens()}>Renew tokens </button>
+        <button on:click={() => renewTokens()}>Renew tokens</button>
⛔ Skipped due to learnings
Learnt from: luca-peruzzo
PR: keycloakify/oidc-spa#104
File: examples/svelte/src/components/NotLoggedInAuthButton.svelte:16-37
Timestamp: 2025-10-06T07:01:46.903Z
Learning: In Svelte 5, event handling syntax changed from directives (e.g., `on:click`) to DOM properties (e.g., `onclick`). The old `on:click` syntax is deprecated. When reviewing Svelte 5 code, `onclick` (and other event properties like `onsubmit`, `onchange`, etc.) are the correct syntax, not `on:click`.

Comment thread examples/svelte-multi-providers/.env.local.sample
Comment thread examples/svelte-multi-providers/src/components/Microsoft.svelte
Comment thread examples/svelte-multi-providers/src/components/NotLoggedInAuthButton.svelte Outdated
Comment thread examples/svelte-multi-providers/tsconfig.node.json
Comment thread src/svelte/index.svelte.ts
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (2)
examples/svelte/src/components/NotLoggedInAuthButton.svelte (1)

1-39: LGTM! Optional: simplify the Login button handler.

The component correctly implements login/register flows for both Keycloak and Auth0 providers. The Svelte 5 onclick syntax is correct (as confirmed by learnings).

Optionally, Line 16 can be simplified:

-    <button onclick={() => login()}>Login</button>
+    <button onclick={login}>Login</button>

This eliminates an unnecessary arrow function wrapper.

src/svelte/index.svelte.ts (1)

401-447: Optional: Add JSDoc to document client-side usage.

The enforceLogin function safely accesses location.href because it's designed for client-side route guards only. Based on learnings, this is correct for the intended use case.

To make this explicit for future maintainers, consider adding a JSDoc comment:

+    /**
+     * Enforces user login for protected routes.
+     * 
+     * **Client-only**: This function should only be called in client-side route guards.
+     * It is not safe for server-side rendering (SSR) contexts.
+     * 
+     * @param loaderParams - Parameters containing request URL or location
+     * @returns Promise resolving to true if login check passes
+     */
     async function enforceLogin(loaderParams: {

Based on learnings

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6129c4b and 085c0ba.

📒 Files selected for processing (3)
  • examples/svelte-multi-providers/src/components/NotLoggedInAuthButton.svelte (1 hunks)
  • examples/svelte/src/components/NotLoggedInAuthButton.svelte (1 hunks)
  • src/svelte/index.svelte.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • examples/svelte-multi-providers/src/components/NotLoggedInAuthButton.svelte
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-10-06T14:55:09.648Z
Learnt from: luca-peruzzo
PR: keycloakify/oidc-spa#104
File: src/svelte/index.svelte.ts:431-433
Timestamp: 2025-10-06T14:55:09.648Z
Learning: In the oidc-spa Svelte adapter, the `enforceLogin` function is designed for client-side route guards only and is not intended for server-side rendering (SSR) contexts. It safely accesses `location.href` because it runs exclusively in browser environments with client-side routers like mateothegreat/svelte5-router.

Applied to files:

  • src/svelte/index.svelte.ts
📚 Learning: 2025-10-06T07:01:46.903Z
Learnt from: luca-peruzzo
PR: keycloakify/oidc-spa#104
File: examples/svelte/src/components/NotLoggedInAuthButton.svelte:16-37
Timestamp: 2025-10-06T07:01:46.903Z
Learning: In Svelte 5, event handling syntax changed from directives (e.g., `on:click`) to DOM properties (e.g., `onclick`). The old `on:click` syntax is deprecated. When reviewing Svelte 5 code, `onclick` (and other event properties like `onsubmit`, `onchange`, etc.) are the correct syntax, not `on:click`.

Applied to files:

  • examples/svelte/src/components/NotLoggedInAuthButton.svelte
🧬 Code graph analysis (1)
src/svelte/index.svelte.ts (6)
src/tools/tsafe/Param0.ts (1)
  • Param0 (6-12)
src/svelte/OidcProviderProps.ts (2)
  • OidcProviderOidcProps (4-9)
  • OidcProviderProps (12-21)
src/tools/ValueOrAsyncGetter.ts (1)
  • ValueOrAsyncGetter (1-1)
src/tools/Deferred.ts (1)
  • Deferred (1-35)
src/svelte/oidc.context.ts (2)
  • setOidcContext (4-11)
  • getOidcContext (13-17)
src/tools/toFullyQualifiedUrl.ts (1)
  • toFullyQualifiedUrl (13-58)
🔇 Additional comments (2)
src/svelte/index.svelte.ts (2)

453-459: Type casts are acceptable given the conditional type complexity.

The as any cast on Line 453 and the @ts-expect-error on Line 458 are necessary workarounds for TypeScript's limitations with conditional types in this context. The API surface is correctly typed for consumers.


15-460: Well-structured OIDC adapter implementation.

The overall implementation is solid:

  • Clean separation of concerns with dependency injection
  • Proper lifecycle management with deferred initialization
  • Type-safe API surface with discriminated unions
  • Correct handling of auto-login vs manual login scenarios
  • Proper cleanup of subscriptions in onMount hooks

Comment thread src/svelte/index.svelte.ts Outdated
Comment thread src/svelte/index.svelte.ts
Comment thread src/svelte/index.svelte.ts Outdated
Comment thread src/svelte/index.svelte.ts Outdated
luca-peruzzo and others added 3 commits October 6, 2025 17:01
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (1)
src/svelte/index.svelte.ts (1)

265-266: Fix typo in error message.

"inizitialized" → "initialized".

-                "Oidc not inizitialized, you must call initializeOidc or mountOidc"
+                "Oidc not initialized, you must call initializeOidc or mountOidc"
🧹 Nitpick comments (4)
src/svelte/index.svelte.ts (4)

105-114: Polish doc comments (typos/wording).

Minor fixes for clarity.

-     * NB: this can be used only when having a single OIDC provider and when usign Svelte without svelte-kit.
-     * For a generic initialization referes to `initializeOidc`
+     * NB: this can be used only when having a single OIDC provider and when using Svelte without SvelteKit.
+     * For a generic initialization refer to `initializeOidc`.

401-447: Document client-only usage for enforceLogin.

Clarify SPA-only intent to avoid future SSR misuse.

+    /**
+     * Client-only route guard that enforces login in SPA contexts.
+     * Not intended for SSR/SvelteKit loaders. It may access `location.href`.
+     */
     async function enforceLogin(loaderParams: {

Based on learnings


143-159: Avoid generic name shadowing the imported ParamsOfCreateOidc.

Shadowing hurts readability; rename the generic.

-export function createSvelteOidc_dependencyInjection<
-    DecodedIdToken extends Record<string, unknown>,
-    ParamsOfCreateOidc extends {
+export function createSvelteOidc_dependencyInjection<
+    DecodedIdToken extends Record<string, unknown>,
+    TCreateParams extends {
         autoLogin?: boolean;
     } & (
         | {
-              decodedIdTokenSchema: { parse: (data: unknown) => DecodedIdToken } | undefined;
+              decodedIdTokenSchema: { parse: (data: unknown) => DecodedIdToken } | undefined;
           }
         | {}
     )
 >(
-    paramsOrGetParams: ValueOrAsyncGetter<ParamsOfCreateOidc>,
-    createOidc: (params: ParamsOfCreateOidc) => Promise<Oidc<DecodedIdToken>>
-): OidcSvelteApi<
-    DecodedIdToken,
-    ParamsOfCreateOidc extends { autoLogin?: true | undefined } ? true : false
+    paramsOrGetParams: ValueOrAsyncGetter<TCreateParams>,
+    createOidc: (params: TCreateParams) => Promise<Oidc<DecodedIdToken>>
+): OidcSvelteApi<
+    DecodedIdToken,
+    TCreateParams extends { autoLogin?: true | undefined } ? true : false
 > {

Also update downstream conditional types and parameter annotations accordingly in this function body.


449-460: Remove ts-expect-error; return with a safer cast.

Preserve runtime shape while avoiding suppression comments.

-    const oidcSvelteApi: OidcSvelteApi<DecodedIdToken, false> = {
+    const oidcSvelteApi = {
         initializeOidc,
         OidcContextProvider,
         mountOidc,
-        useOidc: useOidc as any,
+        useOidc: useOidc as any,
         getOidc,
         enforceLogin
     };
 
-    // @ts-expect-error: We know what we are doing
-    return oidcSvelteApi;
+    return oidcSvelteApi as unknown as OidcSvelteApi<
+        DecodedIdToken,
+        TCreateParams extends { autoLogin?: true | undefined } ? true : false
+    >;

Note: Longer-term, consider shaping the returned API conditionally (omit enforceLogin when autoLogin is true) to align types and runtime more strictly.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 085c0ba and b612f5f.

📒 Files selected for processing (1)
  • src/svelte/index.svelte.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-10-06T14:55:09.648Z
Learnt from: luca-peruzzo
PR: keycloakify/oidc-spa#104
File: src/svelte/index.svelte.ts:431-433
Timestamp: 2025-10-06T14:55:09.648Z
Learning: In the oidc-spa Svelte adapter, the `enforceLogin` function is designed for client-side route guards only and is not intended for server-side rendering (SSR) contexts. It safely accesses `location.href` because it runs exclusively in browser environments with client-side routers like mateothegreat/svelte5-router.

Applied to files:

  • src/svelte/index.svelte.ts
🧬 Code graph analysis (1)
src/svelte/index.svelte.ts (6)
src/tools/tsafe/Param0.ts (1)
  • Param0 (6-12)
src/svelte/OidcProviderProps.ts (2)
  • OidcProviderOidcProps (4-9)
  • OidcProviderProps (12-21)
src/tools/ValueOrAsyncGetter.ts (1)
  • ValueOrAsyncGetter (1-1)
src/tools/Deferred.ts (1)
  • Deferred (1-35)
src/svelte/oidc.context.ts (2)
  • setOidcContext (4-11)
  • getOidcContext (13-17)
src/tools/toFullyQualifiedUrl.ts (1)
  • toFullyQualifiedUrl (13-58)
🔇 Additional comments (1)
src/svelte/index.svelte.ts (1)

243-257: Can you confirm that vite-plugin-svelte is configured to process .svelte.ts modules (e.g., via its extensions or include option)? Using $state in src/svelte/index.svelte.ts requires the Svelte compiler to handle that extension. If it isn’t supported, move this logic into a standard .svelte component or use a Svelte store with the mount API.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant