Skip to content

Add SvelteKit SDK (@thunderid/sveltekit) - #31

Closed
Chamal1120 wants to merge 32 commits into
thunder-id:mainfrom
Chamal1120:sv-package-dev
Closed

Chamal1120 wants to merge 32 commits into
thunder-id:mainfrom
Chamal1120:sv-package-dev

Conversation

@Chamal1120

@Chamal1120 Chamal1120 commented Jul 16, 2026

Copy link
Copy Markdown

Summary

Adds @thunderid/sveltekit — a full SvelteKit SDK following the four-layer architecture spec.

What's included

  • Client layer: ThunderIDSvelteClient extending Browser SDK, Svelte 5 runes (useThunderID, useUser), components (SignInButton, SignOutButton, SignedIn, SignedOut, Loading), AppShell layout
  • Server layer: Hooks (handle), load helper, route handlers (/callback, /signin, /signout), guard for protected routes, session/cookie management
  • Sample app: samples/sveltekit/quickstart — standalone demo with environment setup

Package hierarchy

@thunderid/sveltekit@thunderid/browser@thunderid/javascript

Verification

  • pnpm build
  • pnpm typecheck ✓ (0 errors, 0 warnings)
  • pnpm test — existing unit tests for ThunderIDSvelteClient

BREAKING CHANGE: ThunderIDSvelteClient now extends ThunderIDNodeClient
instead of ThunderIDBrowserClient. Provider accepts ssrData prop for
SSR hydration. Sign-in/out are server-driven via redirect.

Architecture:
- ThunderIDSvelteClient: singleton, extends ThunderIDNodeClient
- Server: session JWT utils, handle hook, load helper, route handlers
- Provider: SSR-first,  hydration from .data
- Composables: delegate auth actions to server endpoints
- Components: SignedIn/SignedOut/Loading control, SignIn/Out/Up buttons

Session management uses jose HS256 cookies matching Nuxt/Next.js pattern.
…tation

Gaps filled:
- Token refresh: maybeRefreshToken() proactively refreshes expiring
  access tokens in hooks; getValidAccessToken() for consumer use
- Org switch: createOrgSwitchHandler() POST handler for org switching
- Route guard: requireServerSession() throws SvelteKit redirect(307)
  when unauthenticated, for use in +page.server.ts load functions
- Type augmentation: app.d.ts augments App.Locals with thunderid:
  ThunderIDSSRData so event.locals.thunderid is typed without casts
…n test

- Add brandingPreference to ThunderIDSSRData, context, provider, composables
- Fetch branding in parallel during handle hook (Gap 7)
- Add 20 unit tests across 3 test files (session, guard, client)
- Fix cookie name assertion to match actual CookieConfig format
Covers installation, SPA quick start, 7-step SvelteKit SSR setup (hook, routes,
load, provider), route guard, org switch, composables, and component reference.
The SDK exports factory functions (createThunderIDHandle, createSignInHandler,
etc.) — README now references the correct names. Also adds a TypeScript setup
section for App.Locals type augmentation.
Uses pnpm create sv@latest (official SvelteKit scaffolding) as the
prerequisite step before the 7-step setup.
…kspace

- Use npx sv create (official Svelte CLI) instead of pnpm create sv
- Add apps/* to pnpm-workspace.yaml so test apps get deps resolved
- Add apps/ to .gitignore so throwaway test apps don't clutter the repo
- ssrData is passed as a single prop (ssrData={data}), not spread
- Merge step 7 and layout wiring into one complete +layout.svelte example
- Show SignedIn/SignedOut/SignInButton/SignOutButton in the layout
…v fallback

- Add resolveConfig() helper that merges user config with env vars
  (THUNDERID_BASE_URL, THUNDERID_CLIENT_ID, THUNDERID_CLIENT_SECRET,
  THUNDERID_SESSION_SECRET)
- Update createThunderIDHandle to use resolveConfig
- Update createSignInHandler, createCallbackHandler, createSignOutHandler,
  createOrgSwitchHandler — all accept optional config now
- Export resolveConfig from @thunderid/svelte/server
…d token refresh

- Fix sign-in handler: remove broken redirectUri/scope custom params, pass
  client_secret as {{clientSecret}} for IdP-based secret resolution
- Fix callback handler: add try-catch with proper error serialization
  (ThunderIDAuthException does not extend Error)
- Fix orgSwitch handler: same catch pattern for non-Error exceptions
- Add tokenRequest.authMethod default of client_secret_post in config
  (matches IdP expectations for server-side apps)
- Add missing await on getStorageManager().getConfigData() in
  getMyOrganizations and signOut methods
- Add .catch(() => []) on getMyOrganizations call in hooks to handle
  403 gracefully when user lacks org scope
- Update README with /static/private pattern, tokenRequest config,
  and redirect URI setup notes
- IAMError class + ErrorCode enum with 25+ typed error codes
- LoggerAdapter interface + DefaultLogger with PII sanitization
- HTTPS enforcement in initialize() and resolveConfig()
- PKCE flag removed (forced to true)
- RFC 7009 token revocation on sign-out
- signUp() redirect-based implementation
- signInSilently() session-check implementation
- changePassword() skeleton with NOT_IMPLEMENTED error
- Callback.svelte component with loading/error/success states
- reInitialize(), double-init guard, missing config validation
- isLoading() tracking during initialize()
- Logger replaces all bare console.* calls
- All lint errors on new files fixed
…DK spec

- Move apps/test-app/ to samples/apps/sveltekit-b2c/ (spec §17)
- Rename package from test-app to sveltekit-b2c
- Rewrite README with prerequisites, env setup, run instructions
- Add packages/sveltekit/.gitignore (node_modules, .svelte-kit, dist)
- Anchor root .gitignore apps/ rule to /apps/ so samples/apps/ is tracked
- Add samples/** to pnpm-workspace.yaml
- Rename package directory from packages/svelte to packages/sveltekit
- Rename package from @thunderid/svelte to @thunderid/sveltekit
- Add Base* presentation components (12 new components)
- Add EventBus, i18n translations, IdTokenValidator
- Add HTTPAdapter, StorageAdapter
- Enhance server routes (callback, signin, signout, refresh)
- Add sanitizer tests, session tests, guard tests
- Combine CSR (BrowserClient) + SSR (Node SDK) in one package
# Conflicts:
#	.github/workflows/release.yml
#	.gitignore
#	pnpm-lock.yaml
#	pnpm-workspace.yaml
@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown

Important

Review skipped

Too many files!

This PR contains 107 files, which is 57 over the limit of 50.

To get a review, narrow the scope:
• coderabbit review --type committed # exclude uncommitted changes
• coderabbit review --dir # limit to a subdirectory
• coderabbit review --base # compare against a closer base

Upgrade to a paid plan to raise the limit.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: f8acde40-778a-4773-8874-dd62f00c141e

📥 Commits

Reviewing files that changed from the base of the PR and between b6edf2e and e5501db.

⛔ Files ignored due to path filters (4)
  • packages/sveltekit/src/server/app.d.ts is excluded by !**/*.d.ts
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
  • samples/sveltekit/quickstart/src/app.d.ts is excluded by !**/*.d.ts
  • samples/sveltekit/quickstart/src/lib/assets/favicon.svg is excluded by !**/*.svg
📒 Files selected for processing (107)
  • .github/workflows/release.yml
  • .gitignore
  • AGENTS.md
  • README.md
  • packages/sveltekit/.gitignore
  • packages/sveltekit/README.md
  • packages/sveltekit/eslint.config.js
  • packages/sveltekit/package.json
  • packages/sveltekit/src/ThunderID.svelte
  • packages/sveltekit/src/ThunderIDSvelteClient.ts
  • packages/sveltekit/src/__tests__/ThunderIDSvelteClient.test.ts
  • packages/sveltekit/src/__tests__/sanitizer.test.ts
  • packages/sveltekit/src/adapters/HTTPAdapter.ts
  • packages/sveltekit/src/adapters/StorageAdapter.ts
  • packages/sveltekit/src/adapters/index.ts
  • packages/sveltekit/src/api/getSchemas.ts
  • packages/sveltekit/src/api/getScim2Me.ts
  • packages/sveltekit/src/api/index.ts
  • packages/sveltekit/src/components/actions/BaseSignInButton.svelte
  • packages/sveltekit/src/components/actions/BaseSignOutButton.svelte
  • packages/sveltekit/src/components/actions/BaseSignUpButton.svelte
  • packages/sveltekit/src/components/actions/SignInButton.svelte
  • packages/sveltekit/src/components/actions/SignOutButton.svelte
  • packages/sveltekit/src/components/actions/SignUpButton.svelte
  • packages/sveltekit/src/components/auth/Callback.svelte
  • packages/sveltekit/src/components/control/Loading.svelte
  • packages/sveltekit/src/components/control/SignedIn.svelte
  • packages/sveltekit/src/components/control/SignedOut.svelte
  • packages/sveltekit/src/components/presentation/AcceptInvite.svelte
  • packages/sveltekit/src/components/presentation/BaseAcceptInvite.svelte
  • packages/sveltekit/src/components/presentation/BaseInviteUser.svelte
  • packages/sveltekit/src/components/presentation/BaseLanguageSwitcher.svelte
  • packages/sveltekit/src/components/presentation/BaseSignIn.svelte
  • packages/sveltekit/src/components/presentation/BaseSignUp.svelte
  • packages/sveltekit/src/components/presentation/BaseUser.svelte
  • packages/sveltekit/src/components/presentation/BaseUserDropdown.svelte
  • packages/sveltekit/src/components/presentation/BaseUserProfile.svelte
  • packages/sveltekit/src/components/presentation/InviteUser.svelte
  • packages/sveltekit/src/components/presentation/LanguageSwitcher.svelte
  • packages/sveltekit/src/components/presentation/SignIn.svelte
  • packages/sveltekit/src/components/presentation/SignUp.svelte
  • packages/sveltekit/src/components/presentation/User.svelte
  • packages/sveltekit/src/components/presentation/UserDropdown.svelte
  • packages/sveltekit/src/components/presentation/UserProfile.svelte
  • packages/sveltekit/src/composables/useThunderID.ts
  • packages/sveltekit/src/composables/useUser.ts
  • packages/sveltekit/src/context.ts
  • packages/sveltekit/src/errors/IAMError.ts
  • packages/sveltekit/src/errors/index.ts
  • packages/sveltekit/src/events/EventBus.ts
  • packages/sveltekit/src/events/index.ts
  • packages/sveltekit/src/i18n/index.ts
  • packages/sveltekit/src/i18n/translations.ts
  • packages/sveltekit/src/index.ts
  • packages/sveltekit/src/logger/LoggerAdapter.ts
  • packages/sveltekit/src/logger/index.ts
  • packages/sveltekit/src/logger/sanitizer.ts
  • packages/sveltekit/src/models/config.ts
  • packages/sveltekit/src/models/contexts.ts
  • packages/sveltekit/src/models/session.ts
  • packages/sveltekit/src/server/__tests__/guard.test.ts
  • packages/sveltekit/src/server/__tests__/session.test.ts
  • packages/sveltekit/src/server/config.ts
  • packages/sveltekit/src/server/getClient.ts
  • packages/sveltekit/src/server/guard.ts
  • packages/sveltekit/src/server/hooks.ts
  • packages/sveltekit/src/server/index.ts
  • packages/sveltekit/src/server/load.ts
  • packages/sveltekit/src/server/refresh.ts
  • packages/sveltekit/src/server/routes/callback.ts
  • packages/sveltekit/src/server/routes/index.ts
  • packages/sveltekit/src/server/routes/signin.ts
  • packages/sveltekit/src/server/routes/signout.ts
  • packages/sveltekit/src/server/session.ts
  • packages/sveltekit/src/state.svelte.ts
  • packages/sveltekit/src/validation/IdTokenValidator.ts
  • packages/sveltekit/src/validation/index.ts
  • packages/sveltekit/tsconfig.json
  • packages/sveltekit/tsconfig.lib.json
  • packages/sveltekit/vitest.config.ts
  • pnpm-workspace.yaml
  • samples/sveltekit/quickstart/.env.example
  • samples/sveltekit/quickstart/.gitignore
  • samples/sveltekit/quickstart/.npmrc
  • samples/sveltekit/quickstart/.prettierignore
  • samples/sveltekit/quickstart/.prettierrc
  • samples/sveltekit/quickstart/.vscode/extensions.json
  • samples/sveltekit/quickstart/README.md
  • samples/sveltekit/quickstart/package.json
  • samples/sveltekit/quickstart/src/app.html
  • samples/sveltekit/quickstart/src/hooks.server.ts
  • samples/sveltekit/quickstart/src/lib/AppShell.svelte
  • samples/sveltekit/quickstart/src/lib/index.ts
  • samples/sveltekit/quickstart/src/routes/+layout.server.ts
  • samples/sveltekit/quickstart/src/routes/+layout.svelte
  • samples/sveltekit/quickstart/src/routes/+page.svelte
  • samples/sveltekit/quickstart/src/routes/api/auth/callback/+server.ts
  • samples/sveltekit/quickstart/src/routes/api/auth/signin/+server.ts
  • samples/sveltekit/quickstart/src/routes/api/auth/signout/+server.ts
  • samples/sveltekit/quickstart/src/routes/callback/+page.svelte
  • samples/sveltekit/quickstart/src/routes/protected/+page.server.ts
  • samples/sveltekit/quickstart/src/routes/protected/+page.svelte
  • samples/sveltekit/quickstart/static/robots.txt
  • samples/sveltekit/quickstart/thunderid-config/thunderid-config.yaml
  • samples/sveltekit/quickstart/thunderid-config/thunderid.env
  • samples/sveltekit/quickstart/tsconfig.json
  • samples/sveltekit/quickstart/vite.config.ts

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • Review on demand using usage pricing
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@Chamal1120 Chamal1120 changed the title feat(sveltekit): add SvelteKit SDK package Add SvelteKit SDK (@thunderid/sveltekit) Jul 16, 2026
@brionmario

brionmario commented Sep 21, 2026

Copy link
Copy Markdown
Member

Hey @Chamal1120,

Thanks a lot for working on this!

As per our SDK roadmap, we’re currently focused on stabilizing and enriching our existing SDK suite. Because of that, a new SDK isn’t something we want to prioritize at the moment.

That said, you’re welcome to maintain this as a community SDK and publish it under your own npm scope/account. We’re currently working on a process for managing community-maintained tools and how we can list them in our documentation.

In the meantime, let’s keep this in your fork and publish releases from your own npm account.

Suggestion for package name: @scope/thunderid-sveltekit or thunderid-sveltekit

Cheers!

@github-actions

Copy link
Copy Markdown

🔀 Cross-SDK feature parity

Does this change need to ship in the other ThunderID SDKs too? This check stays red until one of these labels answers that:

Label What it asserts
parity/prs-raised The ports exist in every other SDK this change reaches, or are recorded as not applying there.
parity/prs-not-needed Nothing to port: a fix, refactor, docs, CI, dependency bump, release, or a change specific to this platform.

Ports

  • thunder-id/ios-sdks, iOS
  • thunder-id/android-sdks, Android
  • thunder-id/flutter-sdks, Flutter

No sibling SDKs accounted for on this thread yet.

Reply to this comment and the boxes above tick themselves. Nothing needs
editing by hand. For a port, link it in either style:

thunder-id/ios-sdks#123
https://github.com/thunder-id/ios-sdks/pull/123

For an SDK this change does not reach, name it and say so on one line:

thunder-id/ios-sdks: not applicable, the capability has no equivalent there

Where an SDK genuinely does not need this change, say so in a reply rather than leaving it unaccounted for. The contract is in the SDK development specification.

@Chamal1120

Copy link
Copy Markdown
Author

@brionmario Thanks for the response. I'll keep this going on my side. Also it's been a while so I might have to look into the latest source of other SDKs and get mine up to speed.

@brionmario

Copy link
Copy Markdown
Member

@brionmario Thanks for the response. I'll keep this going on my side. Also it's been a while so I might have to look into the latest source of other SDKs and get mine up to speed.

+1.

Also, we’ve moved the spec for generating and updating SDKs to the thunderid repo, and there’s a relevant skill available in the monorepo as well. Each SDK repo also has an AGENTS.md with instructions on referring to the spec and skill when working on the SDKs.

Just FYI.

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.

2 participants