Skip to content

Introduce vendor namespace support across ThunderID SDKs#24

Open
brionmario wants to merge 1 commit into
thunder-id:mainfrom
brionmario:flexible-vendor-config
Open

Introduce vendor namespace support across ThunderID SDKs#24
brionmario wants to merge 1 commit into
thunder-id:mainfrom
brionmario:flexible-vendor-config

Conversation

@brionmario

@brionmario brionmario commented Jul 10, 2026

Copy link
Copy Markdown
Member

Purpose

ATM, ThunderID is hardcoded in some of the SDK components making it hard for adopters to customize.

Approach

  • Added a vendor option to the ThunderIDNuxtConfig interface to allow customization of the vendor namespace used in various contexts.
  • Updated event context handling in the Nuxt SDK to resolve the vendor dynamically from runtime configuration.
  • Refactored session storage keys in React components to use the vendor prefix, ensuring compatibility with white-labeling.
  • Introduced a utility function getVendorPrefix to standardize vendor prefix resolution across the SDK.
  • Modified OAuth redirect logic to incorporate vendor-specific session storage keys for better isolation of state.
  • Enhanced I18nProvider and ThunderIDProvider to accept and utilize the vendor parameter for consistent storage key generation.
  • Updated Vue components to read the vendor prefix from context, allowing standalone usage without a ThunderIDProvider ancestor.

Related Issues

Related PRs

  • N/A

Checklist

  • Followed the contribution guidelines.
  • Manual test round performed and verified.
  • Documentation provided. (Add links if there are any)
  • Tests provided. (Add links if there are any)
    • Unit Tests
    • Integration Tests
  • Breaking changes. (Fill if applicable)
    • Breaking changes section filled.
    • breaking change label added.

Security checks

  • Followed secure coding standards in WSO2 Secure Coding Guidelines
  • Confirmed that this PR doesn't commit any keys, passwords, tokens, usernames, or other secrets.

Summary by CodeRabbit

  • New Features

    • Added configurable vendor namespaces for cookie names, browser storage keys, OAuth state, SSR state, and framework identifiers.
    • Added support for custom session cookie names.
    • Extended JavaScript, Express, Next.js, Nuxt, React, and Vue integrations with vendor-aware configuration.
    • Added a public utility for resolving vendor prefixes.
  • Bug Fixes

    • Authentication, sign-out, protection, redirects, and session restoration now consistently use configured cookie and storage names.
  • Documentation

    • Added configuration guidance and contributor documentation.

@coderabbitai

coderabbitai Bot commented Jul 10, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Ignoring CodeRabbit configuration file changes. For security, only the configuration from the base branch is applied for open source repositories.

📝 Walkthrough

Walkthrough

This PR adds vendor-aware naming across server cookies, browser storage, OAuth flows, framework contexts, i18n state, styles, and Nuxt SSR state. It also introduces shared vendor utilities, explicit cookie-name overrides, updated framework configuration propagation, and repository guidance.

Changes

Vendor namespace propagation

Layer / File(s) Summary
Shared contracts and cookie resolution
packages/node/..., packages/javascript/...
Adds vendor configuration, shared prefix resolution, vendor-derived cookie builders, and explicit cookie-name overrides.
Express cookie integration
packages/express/..., samples/express/...
Express clients and middleware read, write, and clear cookies using resolved per-client names.
JavaScript and framework configuration
packages/javascript/..., packages/nextjs/..., packages/react/..., packages/vue/...
Propagates vendor values through storage managers, providers, contexts, OAuth callbacks, i18n storage, and Vue style IDs.
Nuxt runtime and SSR state
packages/nuxt/...
Scopes Nuxt state keys and Nitro event context by vendor during SSR and hydration.
Repository guidance
.coderabbit.yaml, AGENTS.md, CLAUDE.md
Adds review automation, contributor instructions, vendor naming rules, and shared guidance loading.

Estimated code review effort: 4 (Complex) | ~60 minutes

Possibly related PRs

Suggested reviewers: ThaminduDilshan

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: adding vendor namespace support across the ThunderID SDKs.
Description check ✅ Passed The description follows the template structure and covers purpose, approach, issues, PRs, checklist, and security sections.
Docstring Coverage ✅ Passed Docstring coverage is 85.71% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ 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.

Comment thread packages/node/src/constants/CookieConfig.ts Outdated
Comment thread packages/nuxt/src/runtime/utils/stateKeys.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/nuxt/src/module.ts (1)

112-126: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Add vendor: string to the PublicRuntimeConfig module augmentation.

The inline type at Line 126 correctly includes vendor: string, but the declare module augmentation for PublicRuntimeConfig.thunderid at Lines 298–309 omits it. This forces downstream consumers to cast useRuntimeConfig().public.thunderid to access vendor — as seen in ThunderIDRoot.ts where runtimeThunderIDConfig is manually typed with vendor?: string. Adding vendor: string to the module augmentation eliminates these workarounds and keeps the type contract consistent.

🔧 Proposed fix
     thunderid: {
       afterSignInUrl: string;
       afterSignOutUrl: string;
       applicationId?: string;
       baseUrl: string;
       clientId: string;
       platform?: ThunderIDNuxtConfig['platform'];
       preferences?: ThunderIDNuxtConfig['preferences'];
       scopes: string | string[];
       signInUrl?: string;
       signUpUrl?: string;
+      tokenRequest?: ThunderIDNuxtConfig['tokenRequest'];
+      vendor: string;
     };
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/nuxt/src/module.ts` around lines 112 - 126, Add vendor: string to
the PublicRuntimeConfig.thunderid module augmentation, matching the inline
configuration type and the existing vendor property. Update the declare module
definition near the PublicRuntimeConfig augmentation so downstream
useRuntimeConfig() consumers receive vendor without manual casts.
🧹 Nitpick comments (2)
packages/node/src/constants/CookieConfig.ts (1)

73-82: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

ESLint @typescript-eslint/unbound-method errors on free-function exports.

Assigning static methods to const variables (CookieConfig.getSessionCookieName) triggers unbound-method lint errors because TypeScript cannot guarantee the methods don't reference this. While these methods reference CookieConfig directly (not this), the lint errors may fail CI. Wrapping in arrow functions resolves the errors without changing behavior.

♻️ Proposed fix: arrow function wrappers
-export const getSessionCookieName = CookieConfig.getSessionCookieName;
+export const getSessionCookieName = (vendor?: string): string => CookieConfig.getSessionCookieName(vendor);

 /** Free-function form of {`@link` CookieConfig.getTempSessionCookieName}. */
-export const getTempSessionCookieName = CookieConfig.getTempSessionCookieName;
+export const getTempSessionCookieName = (vendor?: string): string => CookieConfig.getTempSessionCookieName(vendor);

 /** Free-function form of {`@link` CookieConfig.resolveSessionCookieName}. */
-export const resolveSessionCookieName = CookieConfig.resolveSessionCookieName;
+export const resolveSessionCookieName = (vendor?: string, overrideName?: string): string =>
+  CookieConfig.resolveSessionCookieName(vendor, overrideName);

 /** Free-function form of {`@link` CookieConfig.resolveTempSessionCookieName}. */
-export const resolveTempSessionCookieName = CookieConfig.resolveTempSessionCookieName;
+export const resolveTempSessionCookieName = (vendor?: string, overrideName?: string): string =>
+  CookieConfig.resolveTempSessionCookieName(vendor, overrideName);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/node/src/constants/CookieConfig.ts` around lines 73 - 82, Replace
the direct static-method assignments for getSessionCookieName,
getTempSessionCookieName, resolveSessionCookieName, and
resolveTempSessionCookieName with arrow-function wrappers that invoke the
corresponding CookieConfig methods, preserving their parameters and return
values while avoiding unbound-method lint errors.

Source: Linters/SAST tools

packages/nuxt/src/runtime/utils/stateKeys.ts (1)

36-43: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider centralizing vendor resolution alongside these key helpers.

The useRuntimeConfig().public.thunderid.vendor read is duplicated in ThunderIDRoot.ts, defineThunderIDMiddleware.ts, thunderid.ts, and thunderid-ssr.ts. Some sites use ?? DEFAULT_VENDOR while others rely on the default param of getAuthStateKey/getUserProfileStateKey. Today both paths resolve to DEFAULT_VENDOR, but a future change to the default param could silently desync the keys. A shared resolver removes that risk.

♻️ Optional shared resolver
/**
 * Resolves the active vendor namespace from Nuxt runtime config,
 * falling back to {`@link` DEFAULT_VENDOR}. Use this everywhere a vendor
 * is needed so all callers agree on the same value.
 */
export const resolveVendor = (thunderid?: {vendor?: string}): string => thunderid?.vendor ?? DEFAULT_VENDOR;

Callers then use getAuthStateKey(resolveVendor(useRuntimeConfig().public.thunderid)).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/nuxt/src/runtime/utils/stateKeys.ts` around lines 36 - 43,
Centralize vendor fallback logic by adding a shared resolveVendor helper near
getAuthStateKey and getUserProfileStateKey, returning thunderid.vendor or
DEFAULT_VENDOR. Update ThunderIDRoot, defineThunderIDMiddleware, thunderid, and
thunderid-ssr to use resolveVendor before generating state keys or otherwise
resolving the vendor, ensuring all callers share the same fallback behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/node/src/constants/CookieConfig.ts`:
- Around line 26-27: Update CookieConfig.getSessionCookieName and
getTempSessionCookieName to treat an empty or falsy vendor as
VendorConstants.VENDOR_PREFIX rather than relying only on the default parameter,
ensuring both cookie names retain the vendor namespace.

---

Outside diff comments:
In `@packages/nuxt/src/module.ts`:
- Around line 112-126: Add vendor: string to the PublicRuntimeConfig.thunderid
module augmentation, matching the inline configuration type and the existing
vendor property. Update the declare module definition near the
PublicRuntimeConfig augmentation so downstream useRuntimeConfig() consumers
receive vendor without manual casts.

---

Nitpick comments:
In `@packages/node/src/constants/CookieConfig.ts`:
- Around line 73-82: Replace the direct static-method assignments for
getSessionCookieName, getTempSessionCookieName, resolveSessionCookieName, and
resolveTempSessionCookieName with arrow-function wrappers that invoke the
corresponding CookieConfig methods, preserving their parameters and return
values while avoiding unbound-method lint errors.

In `@packages/nuxt/src/runtime/utils/stateKeys.ts`:
- Around line 36-43: Centralize vendor fallback logic by adding a shared
resolveVendor helper near getAuthStateKey and getUserProfileStateKey, returning
thunderid.vendor or DEFAULT_VENDOR. Update ThunderIDRoot,
defineThunderIDMiddleware, thunderid, and thunderid-ssr to use resolveVendor
before generating state keys or otherwise resolving the vendor, ensuring all
callers share the same fallback behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: c5a0ba7b-38fa-4f4c-8c9e-eb137cf3c490

📥 Commits

Reviewing files that changed from the base of the PR and between a4866f0 and 99e3df1.

📒 Files selected for processing (42)
  • packages/express/src/ThunderIDExpressClient.ts
  • packages/express/src/constants/CookieConfig.ts
  • packages/express/src/index.ts
  • packages/express/src/middleware/authentication.ts
  • packages/express/src/middleware/protect.ts
  • packages/express/src/models/config.ts
  • packages/javascript/src/StorageManager.ts
  • packages/javascript/src/ThunderIDJavaScriptClient.ts
  • packages/javascript/src/models/config.ts
  • packages/nextjs/src/client/contexts/ThunderID/ThunderIDProvider.tsx
  • packages/nextjs/src/utils/SessionManager.ts
  • packages/nextjs/src/utils/decorateConfigWithNextEnv.ts
  • packages/node/src/constants/CookieConfig.ts
  • packages/node/src/index.ts
  • packages/node/src/models/config.ts
  • packages/nuxt/src/module.ts
  • packages/nuxt/src/runtime/components/ThunderIDRoot.ts
  • packages/nuxt/src/runtime/middleware/defineThunderIDMiddleware.ts
  • packages/nuxt/src/runtime/plugins/thunderid.ts
  • packages/nuxt/src/runtime/server/plugins/thunderid-ssr.ts
  • packages/nuxt/src/runtime/server/utils/event-context.ts
  • packages/nuxt/src/runtime/types.ts
  • packages/nuxt/src/runtime/utils/stateKeys.ts
  • packages/react/src/components/auth/Callback/OAuthCallback.tsx
  • packages/react/src/components/auth/Callback/TokenCallback.tsx
  • packages/react/src/components/presentation/auth/AcceptInvite/BaseAcceptInvite.tsx
  • packages/react/src/components/presentation/auth/SignIn/SignIn.tsx
  • packages/react/src/contexts/I18n/I18nProvider.tsx
  • packages/react/src/contexts/ThunderID/ThunderIDContext.ts
  • packages/react/src/contexts/ThunderID/ThunderIDProvider.tsx
  • packages/react/src/utils/getVendorPrefix.ts
  • packages/react/src/utils/oauth.ts
  • packages/vue/src/components/auth/Callback.ts
  • packages/vue/src/components/auth/sign-in/SignIn.ts
  • packages/vue/src/components/presentation/accept-invite/BaseAcceptInvite.ts
  • packages/vue/src/models/contexts.ts
  • packages/vue/src/plugins/ThunderIDPlugin.ts
  • packages/vue/src/providers/I18nProvider.ts
  • packages/vue/src/providers/ThunderIDProvider.ts
  • packages/vue/src/styles/injectStyles.ts
  • packages/vue/src/utils/getVendorPrefix.ts
  • packages/vue/src/utils/oauth.ts

Comment thread packages/node/src/constants/CookieConfig.ts Outdated
- Added a `vendor` option to the ThunderIDNuxtConfig interface to allow customization of the vendor namespace used in various contexts.
- Updated event context handling in the Nuxt SDK to resolve the vendor dynamically from runtime configuration.
- Refactored session storage keys in React components to use the vendor prefix, ensuring compatibility with white-labeling.
- Introduced a utility function `getVendorPrefix` to standardize vendor prefix resolution across the SDK.
- Modified OAuth redirect logic to incorporate vendor-specific session storage keys for better isolation of state.
- Enhanced I18nProvider and ThunderIDProvider to accept and utilize the vendor parameter for consistent storage key generation.
- Updated Vue components to read the vendor prefix from context, allowing standalone usage without a ThunderIDProvider ancestor.
@brionmario brionmario force-pushed the flexible-vendor-config branch from 99e3df1 to 3cfb3ac Compare July 10, 2026 13:37

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 6

🧹 Nitpick comments (1)
packages/nuxt/src/runtime/utils/stateKeys.ts (1)

30-30: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use getVendorPrefix(vendor) instead of a default parameter fallback.

Both functions resolve the vendor namespace via a default parameter (vendor: string = VendorConstants.VENDOR_PREFIX), but the coding guidelines require using getVendorPrefix(vendor) as the single resolution mechanism for brand-scoped namespaces. This ensures consistency and future-proofs against changes in the prefix resolution logic.

As per coding guidelines: "When a brand-scoped namespace is genuinely required, resolve it with getVendorPrefix(vendor) rather than hardcoding a brand literal or repeating an inline vendor ?? 'thunderid' fallback."

♻️ Proposed refactor to use getVendorPrefix
 import {VendorConstants} from '`@thunderid/node`';
+import {getVendorPrefix} from '`@thunderid/node`';

 /**
  * Shared `useState` key for the ThunderID auth state (`ThunderIDAuthState`).
  *
  * Must stay in sync across `runtime/plugins/thunderid.ts`,
  * `runtime/components/ThunderIDRoot.ts`, and
  * `runtime/middleware/defineThunderIDMiddleware.ts` — all three must resolve
  * the same `vendor` (from `useRuntimeConfig().public.thunderid.vendor`) to
  * read/write the same reactive state.
  */
-export const getAuthStateKey = (vendor: string = VendorConstants.VENDOR_PREFIX): string => `${vendor}:auth`;
+export const getAuthStateKey = (vendor?: string): string => `${getVendorPrefix(vendor)}:auth`;

 /**
  * Shared `useState` key for the SSR-hydrated user profile (`UserProfile | null`).
  *
  * Must stay in sync across the same three files as {`@link` getAuthStateKey}.
  */
 export const getUserProfileStateKey = (vendor: string = VendorConstants.VENDOR_PREFIX): string =>
-  `${vendor}:user-profile`;
+export const getUserProfileStateKey = (vendor?: string): string =>
+  `${getVendorPrefix(vendor)}:user-profile`;

If VendorConstants is no longer referenced after this change, remove it from the import.

Also applies to: 37-37

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/nuxt/src/runtime/utils/stateKeys.ts` at line 30, Replace the default
vendor fallback in both getAuthStateKey and the function at the referenced
second location with getVendorPrefix(vendor), using its result to build the
namespace key. Remove the VendorConstants import if it is no longer used.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/javascript/src/ThunderIDJavaScriptClient.ts`:
- Around line 101-103: Replace the inline vendor fallback in the
ThunderIDJavaScriptClient initialization with getVendorPrefix(vendor). Add
vendor to the AuthClientConfig type if it is a supported option, then read it
directly from fullConfig and remove the (fullConfig as any) cast before passing
the resolved prefix to StorageManager.

In `@packages/nuxt/src/runtime/components/ThunderIDRoot.ts`:
- Around line 69-74: Resolve the optional vendor before generating state keys in
ThunderIDRoot: import and call getVendorPrefix(vendor), then pass the resulting
definite vendor value to getUserProfileStateKey and getAuthStateKey. Verify the
helper is exported by the appropriate package and use it consistently so the
component matches the plugin’s fallback behavior.

In `@packages/nuxt/src/runtime/middleware/defineThunderIDMiddleware.ts`:
- Around line 71-72: Apply the same vendor fallback used by ThunderIDRoot to the
vendor resolution in defineThunderIDMiddleware, ensuring it always produces the
identical definite string value as the plugin before passing it to
getAuthStateKey and useState.

In `@packages/nuxt/src/runtime/plugins/thunderid.ts`:
- Line 76: Replace the inline fallback in the vendor initialization with
getVendorPrefix(vendor), matching the centralized vendor resolution used by
ThunderIDJavaScriptClient.ts; update imports as needed.

In `@packages/nuxt/src/runtime/server/plugins/thunderid-ssr.ts`:
- Line 126: Replace the inline vendor fallback in the vendor initialization with
getVendorPrefix(publicConfig?.vendor), and update imports if needed so the
helper is available.

In `@packages/nuxt/src/runtime/server/utils/event-context.ts`:
- Line 63: Replace the inline vendor fallback in the vendor initialization with
getVendorPrefix(publicConfig?.vendor), and update any related imports so the
existing helper is used consistently.

---

Nitpick comments:
In `@packages/nuxt/src/runtime/utils/stateKeys.ts`:
- Line 30: Replace the default vendor fallback in both getAuthStateKey and the
function at the referenced second location with getVendorPrefix(vendor), using
its result to build the namespace key. Remove the VendorConstants import if it
is no longer used.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 6f2bcdb3-6d61-4b6b-9df4-8b861e530e6a

📥 Commits

Reviewing files that changed from the base of the PR and between 99e3df1 and 3cfb3ac.

📒 Files selected for processing (45)
  • .coderabbit.yaml
  • AGENTS.md
  • CLAUDE.md
  • packages/express/src/ThunderIDExpressClient.ts
  • packages/express/src/constants/CookieConfig.ts
  • packages/express/src/index.ts
  • packages/express/src/middleware/authentication.ts
  • packages/express/src/middleware/protect.ts
  • packages/express/src/models/config.ts
  • packages/javascript/src/StorageManager.ts
  • packages/javascript/src/ThunderIDJavaScriptClient.ts
  • packages/javascript/src/index.ts
  • packages/javascript/src/models/config.ts
  • packages/javascript/src/utils/getVendorPrefix.ts
  • packages/nextjs/src/client/contexts/ThunderID/ThunderIDProvider.tsx
  • packages/nextjs/src/utils/SessionManager.ts
  • packages/nextjs/src/utils/decorateConfigWithNextEnv.ts
  • packages/node/src/constants/CookieConfig.ts
  • packages/node/src/models/config.ts
  • packages/nuxt/src/module.ts
  • packages/nuxt/src/runtime/components/ThunderIDRoot.ts
  • packages/nuxt/src/runtime/middleware/defineThunderIDMiddleware.ts
  • packages/nuxt/src/runtime/plugins/thunderid.ts
  • packages/nuxt/src/runtime/server/plugins/thunderid-ssr.ts
  • packages/nuxt/src/runtime/server/utils/event-context.ts
  • packages/nuxt/src/runtime/types.ts
  • packages/nuxt/src/runtime/utils/stateKeys.ts
  • packages/react/src/components/auth/Callback/OAuthCallback.tsx
  • packages/react/src/components/auth/Callback/TokenCallback.tsx
  • packages/react/src/components/presentation/auth/AcceptInvite/BaseAcceptInvite.tsx
  • packages/react/src/components/presentation/auth/SignIn/SignIn.tsx
  • packages/react/src/contexts/I18n/I18nProvider.tsx
  • packages/react/src/contexts/ThunderID/ThunderIDContext.ts
  • packages/react/src/contexts/ThunderID/ThunderIDProvider.tsx
  • packages/react/src/utils/oauth.ts
  • packages/vue/src/components/auth/Callback.ts
  • packages/vue/src/components/auth/sign-in/SignIn.ts
  • packages/vue/src/components/presentation/accept-invite/BaseAcceptInvite.ts
  • packages/vue/src/models/contexts.ts
  • packages/vue/src/plugins/ThunderIDPlugin.ts
  • packages/vue/src/providers/I18nProvider.ts
  • packages/vue/src/providers/ThunderIDProvider.ts
  • packages/vue/src/styles/injectStyles.ts
  • packages/vue/src/utils/oauth.ts
  • samples/express/quickstart/index.mjs
💤 Files with no reviewable changes (1)
  • packages/express/src/constants/CookieConfig.ts
✅ Files skipped from review due to trivial changes (2)
  • CLAUDE.md
  • packages/express/src/models/config.ts
🚧 Files skipped from review as they are similar to previous changes (8)
  • packages/vue/src/plugins/ThunderIDPlugin.ts
  • packages/node/src/models/config.ts
  • packages/express/src/index.ts
  • packages/vue/src/models/contexts.ts
  • packages/javascript/src/StorageManager.ts
  • packages/javascript/src/models/config.ts
  • packages/react/src/components/auth/Callback/TokenCallback.tsx
  • packages/vue/src/components/auth/sign-in/SignIn.ts

Comment on lines +101 to +103
const vendor = (fullConfig as any).vendor ?? VendorConstants.VENDOR_PREFIX;

this.storageManager = new StorageManager<T>(storageKey, store);
this.storageManager = new StorageManager<T>(storageKey, store, vendor);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Use getVendorPrefix(vendor) instead of repeating the inline fallback.

The coding guidelines explicitly say to resolve vendor namespaces with getVendorPrefix(vendor) rather than repeating an inline vendor ?? 'thunderid' fallback. Line 101 does exactly this pattern. Additionally, (fullConfig as any).vendor bypasses type safety — if vendor is now a supported config option, it should be declared on the AuthClientConfig type so the as any cast is unnecessary.

As per coding guidelines: "When a brand-scoped namespace is genuinely required, resolve it with getVendorPrefix(vendor) rather than hardcoding a brand literal or repeating an inline vendor ?? 'thunderid' fallback."

♻️ Proposed refactor
-    const vendor = (fullConfig as any).vendor ?? VendorConstants.VENDOR_PREFIX;
-
-    this.storageManager = new StorageManager<T>(storageKey, store, vendor);
+    const vendor = getVendorPrefix((fullConfig as any).vendor);
+
+    this.storageManager = new StorageManager<T>(storageKey, store, vendor);

If vendor is added to AuthClientConfig<T>, the cast can be removed entirely:

-    const vendor = getVendorPrefix((fullConfig as any).vendor);
+    const vendor = getVendorPrefix(fullConfig.vendor);
📝 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.

Suggested change
const vendor = (fullConfig as any).vendor ?? VendorConstants.VENDOR_PREFIX;
this.storageManager = new StorageManager<T>(storageKey, store);
this.storageManager = new StorageManager<T>(storageKey, store, vendor);
const vendor = getVendorPrefix((fullConfig as any).vendor);
this.storageManager = new StorageManager<T>(storageKey, store, vendor);
🧰 Tools
🪛 ESLint

[error] 101-101: Unsafe assignment of an any value.

(@typescript-eslint/no-unsafe-assignment)


[error] 101-101: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 101-101: Unsafe member access .vendor on an any value.

(@typescript-eslint/no-unsafe-member-access)


[error] 103-103: Unsafe argument of type any assigned to a parameter of type string.

(@typescript-eslint/no-unsafe-argument)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/javascript/src/ThunderIDJavaScriptClient.ts` around lines 101 - 103,
Replace the inline vendor fallback in the ThunderIDJavaScriptClient
initialization with getVendorPrefix(vendor). Add vendor to the AuthClientConfig
type if it is a supported option, then read it directly from fullConfig and
remove the (fullConfig as any) cast before passing the resolved prefix to
StorageManager.

Source: Coding guidelines

Comment on lines +69 to +74
const vendor: string | undefined = runtimeThunderIDConfig?.vendor;

// ── Read SSR-hydrated state keys (seeded by the Nuxt plugin) ────────────
const userProfileState: Ref<UserProfile | null> = useState<UserProfile | null>('thunderid:user-profile');
const userProfileState: Ref<UserProfile | null> = useState<UserProfile | null>(getUserProfileStateKey(vendor));
// Used by onUpdateProfile to keep the top-level auth user claim in sync.
const authState: Ref<ThunderIDAuthState> = useState<ThunderIDAuthState>('thunderid:auth');
const authState: Ref<ThunderIDAuthState> = useState<ThunderIDAuthState>(getAuthStateKey(vendor));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Apply vendor fallback to prevent useState key mismatch with the plugin.

vendor is typed as string | undefined here, but the plugin (thunderid.ts line 76) and SSR plugin (thunderid-ssr.ts line 126) both resolve it to a definite string via ?? VendorConstants.VENDOR_PREFIX. If vendor is undefined at runtime, ThunderIDRoot calls getAuthStateKey(undefined) while the plugin calls getAuthStateKey('thunderid'), causing them to read/write different useState keys and breaking SSR hydration.

Use getVendorPrefix(vendor) to centralize the fallback and comply with the coding guidelines: "resolve it with getVendorPrefix(vendor) rather than … repeating an inline vendor ?? 'thunderid' fallback."

🔒 Proposed fix
-    const vendor: string | undefined = runtimeThunderIDConfig?.vendor;
+    const vendor: string = getVendorPrefix(runtimeThunderIDConfig?.vendor);

This requires importing getVendorPrefix — verify it is exported from @thunderid/node or @thunderid/javascript.

🧰 Tools
🪛 ESLint

[error] This rule requires the strictNullChecks compiler option to be turned on to function correctly.

(@typescript-eslint/prefer-nullish-coalescing)


[error] 72-72: Unsafe assignment of an error typed value.

(@typescript-eslint/no-unsafe-assignment)


[error] 72-72: 'UserProfile' is an 'error' type that acts as 'any' and overrides all other types in this union type.

(@typescript-eslint/no-redundant-type-constituents)


[error] 72-72: Unsafe call of a type that could not be resolved.

(@typescript-eslint/no-unsafe-call)


[error] 72-72: 'UserProfile' is an 'error' type that acts as 'any' and overrides all other types in this union type.

(@typescript-eslint/no-redundant-type-constituents)


[error] 74-74: Unsafe assignment of an error typed value.

(@typescript-eslint/no-unsafe-assignment)


[error] 74-74: Unsafe call of a type that could not be resolved.

(@typescript-eslint/no-unsafe-call)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/nuxt/src/runtime/components/ThunderIDRoot.ts` around lines 69 - 74,
Resolve the optional vendor before generating state keys in ThunderIDRoot:
import and call getVendorPrefix(vendor), then pass the resulting definite vendor
value to getUserProfileStateKey and getAuthStateKey. Verify the helper is
exported by the appropriate package and use it consistently so the component
matches the plugin’s fallback behavior.

Source: Coding guidelines

Comment on lines +71 to +72
const vendor: string | undefined = (useRuntimeConfig().public.thunderid as {vendor?: string} | undefined)?.vendor;
const authState: Ref<ThunderIDAuthState> = useState<ThunderIDAuthState>(getAuthStateKey(vendor));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Apply vendor fallback to prevent useState key mismatch with the plugin.

Same issue as ThunderIDRoot.ts: vendor is string | undefined without a fallback, while the plugin resolves it to a definite string. If vendor is undefined, the middleware reads a different useState key than the plugin writes, causing auth checks to fail silently.

🔒 Proposed fix
-    const vendor: string | undefined = (useRuntimeConfig().public.thunderid as {vendor?: string} | undefined)?.vendor;
+    const vendor: string = getVendorPrefix(
+      (useRuntimeConfig().public.thunderid as {vendor?: string} | undefined)?.vendor,
+    );
📝 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.

Suggested change
const vendor: string | undefined = (useRuntimeConfig().public.thunderid as {vendor?: string} | undefined)?.vendor;
const authState: Ref<ThunderIDAuthState> = useState<ThunderIDAuthState>(getAuthStateKey(vendor));
const vendor: string = getVendorPrefix(
(useRuntimeConfig().public.thunderid as {vendor?: string} | undefined)?.vendor,
);
const authState: Ref<ThunderIDAuthState> = useState<ThunderIDAuthState>(getAuthStateKey(vendor));
🧰 Tools
🪛 ESLint

[error] This rule requires the strictNullChecks compiler option to be turned on to function correctly.

(@typescript-eslint/prefer-nullish-coalescing)


[error] 71-71: Unsafe call of a type that could not be resolved.

(@typescript-eslint/no-unsafe-call)


[error] 71-71: Unsafe member access .public on a type that cannot be resolved.

(@typescript-eslint/no-unsafe-member-access)


[error] 72-72: Unsafe assignment of an error typed value.

(@typescript-eslint/no-unsafe-assignment)


[error] 72-72: Unsafe call of a type that could not be resolved.

(@typescript-eslint/no-unsafe-call)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/nuxt/src/runtime/middleware/defineThunderIDMiddleware.ts` around
lines 71 - 72, Apply the same vendor fallback used by ThunderIDRoot to the
vendor resolution in defineThunderIDMiddleware, ensuring it always produces the
identical definite string value as the plugin before passing it to
getAuthStateKey and useState.

Source: Coding guidelines

vendor?: string;
};

const vendor: string = publicConfig.vendor ?? VendorConstants.VENDOR_PREFIX;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Use getVendorPrefix(vendor) instead of the inline fallback.

Same guideline violation as flagged in ThunderIDJavaScriptClient.ts — this inline vendor ?? VendorConstants.VENDOR_PREFIX pattern should be replaced with getVendorPrefix(vendor) to centralize vendor resolution.

♻️ Proposed refactor
-  const vendor: string = publicConfig.vendor ?? VendorConstants.VENDOR_PREFIX;
+  const vendor: string = getVendorPrefix(publicConfig.vendor);
🧰 Tools
🪛 ESLint

[error] This rule requires the strictNullChecks compiler option to be turned on to function correctly.

(@typescript-eslint/prefer-nullish-coalescing)


[error] 76-76: Unsafe assignment of an error typed value.

(@typescript-eslint/no-unsafe-assignment)


[error] 76-76: Unsafe member access .VENDOR_PREFIX on a type that cannot be resolved.

(@typescript-eslint/no-unsafe-member-access)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/nuxt/src/runtime/plugins/thunderid.ts` at line 76, Replace the
inline fallback in the vendor initialization with getVendorPrefix(vendor),
matching the centralized vendor resolution used by ThunderIDJavaScriptClient.ts;
update imports as needed.

Source: Coding guidelines

const sessionSecret: string | undefined = process.env.THUNDERID_SESSION_SECRET || config.thunderid?.sessionSecret;
// Vendor namespace for `event.context[vendor]` — must match the key the
// Nuxt plugin (`runtime/plugins/thunderid.ts`) reads from.
const vendor: string = publicConfig?.vendor ?? VendorConstants.VENDOR_PREFIX;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Use getVendorPrefix(vendor) instead of the inline fallback.

Same guideline violation — replace the inline publicConfig?.vendor ?? VendorConstants.VENDOR_PREFIX with getVendorPrefix(publicConfig?.vendor).

♻️ Proposed refactor
-    const vendor: string = publicConfig?.vendor ?? VendorConstants.VENDOR_PREFIX;
+    const vendor: string = getVendorPrefix(publicConfig?.vendor);
🧰 Tools
🪛 ESLint

[error] This rule requires the strictNullChecks compiler option to be turned on to function correctly.

(@typescript-eslint/prefer-nullish-coalescing)


[error] 126-126: Unsafe assignment of an error typed value.

(@typescript-eslint/no-unsafe-assignment)


[error] 126-126: Unsafe member access .VENDOR_PREFIX on a type that cannot be resolved.

(@typescript-eslint/no-unsafe-member-access)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/nuxt/src/runtime/server/plugins/thunderid-ssr.ts` at line 126,
Replace the inline vendor fallback in the vendor initialization with
getVendorPrefix(publicConfig?.vendor), and update imports if needed so the
helper is available.

Source: Coding guidelines

const publicConfig: ThunderIDNuxtConfig | undefined = useRuntimeConfig(event).public.thunderid as
| ThunderIDNuxtConfig
| undefined;
const vendor: string = publicConfig?.vendor ?? VendorConstants.VENDOR_PREFIX;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Use getVendorPrefix(vendor) instead of the inline fallback.

Same guideline violation — replace the inline publicConfig?.vendor ?? VendorConstants.VENDOR_PREFIX with getVendorPrefix(publicConfig?.vendor).

♻️ Proposed refactor
-  const vendor: string = publicConfig?.vendor ?? VendorConstants.VENDOR_PREFIX;
+  const vendor: string = getVendorPrefix(publicConfig?.vendor);
🧰 Tools
🪛 ESLint

[error] This rule requires the strictNullChecks compiler option to be turned on to function correctly.

(@typescript-eslint/prefer-nullish-coalescing)


[error] 63-63: Unsafe assignment of an error typed value.

(@typescript-eslint/no-unsafe-assignment)


[error] 63-63: Unsafe member access .VENDOR_PREFIX on a type that cannot be resolved.

(@typescript-eslint/no-unsafe-member-access)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/nuxt/src/runtime/server/utils/event-context.ts` at line 63, Replace
the inline vendor fallback in the vendor initialization with
getVendorPrefix(publicConfig?.vendor), and update any related imports so the
existing helper is used consistently.

Source: Coding guidelines

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