Skip to content

integrate users/me/meta endpoint into the React and NextJs sdks - #49

Open
janithjay wants to merge 1 commit into
thunder-id:mainfrom
janithjay:feat/profile-edit-put
Open

integrate users/me/meta endpoint into the React and NextJs sdks#49
janithjay wants to merge 1 commit into
thunder-id:mainfrom
janithjay:feat/profile-edit-put

Conversation

@janithjay

@janithjay janithjay commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Purpose

Integrates the /users/me/meta schema endpoint into the React (@thunderid/react) and Next.js (@thunderid/nextjs) SDKs. This allows the <UserProfile /> component to dynamically load user profile schema metadata (attribute types, labels, required states, and order) directly from the ThunderID server.

Approach

  • New API Helper: Added getUsersMeMeta.ts in @thunderid/react to perform authenticated requests to the /users/me/meta endpoint.
  • Context & State Management:
    • Updated UserContext and UserProvider to manage and expose the userSchema state.
    • Wired getUsersMeMeta into ThunderIDProvider to automatically fetch user schema metadata upon authentication initialization.
  • Dynamic Profile Component: Updated BaseUserProfile.tsx to construct and render profile field inputs dynamically based on the fetched userSchema metadata.

Related Issues

Related PRs

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 support for retrieving user profile schema metadata.
    • User profiles now dynamically render fields based on available schema definitions.
    • Added required-field and pattern validation with inline editing feedback.
    • Preserved nested attribute values while editing or cancelling changes.
    • Exposed schema metadata through user and authentication contexts.
    • Added a public API for accessing current-user profile metadata.
  • Bug Fixes
    • Improved handling of schema-defined fields and editable profile attributes.

Copilot AI review requested due to automatic review settings August 3, 2026 09:40
@coderabbitai

coderabbitai Bot commented Aug 3, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 134b73c1-720c-42f6-9058-142ad112821d

📥 Commits

Reviewing files that changed from the base of the PR and between 37217b0 and 4bc1a26.

📒 Files selected for processing (9)
  • packages/nextjs/src/client/contexts/ThunderID/ThunderIDProvider.tsx
  • packages/react/src/api/getUsersMeMeta.ts
  • packages/react/src/components/presentation/UserProfile/BaseUserProfile.tsx
  • packages/react/src/components/presentation/UserProfile/UserProfile.tsx
  • packages/react/src/contexts/ThunderID/ThunderIDContext.ts
  • packages/react/src/contexts/ThunderID/ThunderIDProvider.tsx
  • packages/react/src/contexts/User/UserContext.ts
  • packages/react/src/contexts/User/UserProvider.tsx
  • packages/react/src/index.ts
🚧 Files skipped from review as they are similar to previous changes (9)
  • packages/react/src/index.ts
  • packages/nextjs/src/client/contexts/ThunderID/ThunderIDProvider.tsx
  • packages/react/src/components/presentation/UserProfile/UserProfile.tsx
  • packages/react/src/contexts/User/UserContext.ts
  • packages/react/src/contexts/ThunderID/ThunderIDProvider.tsx
  • packages/react/src/contexts/User/UserProvider.tsx
  • packages/react/src/contexts/ThunderID/ThunderIDContext.ts
  • packages/react/src/components/presentation/UserProfile/BaseUserProfile.tsx
  • packages/react/src/api/getUsersMeMeta.ts

📝 Walkthrough

Walkthrough

The React SDK retrieves user schema metadata during authenticated profile synchronization, exposes it through user contexts, and uses it to render and validate editable profile fields. The Next.js provider supplies a null schema by default.

Changes

User schema integration

Layer / File(s) Summary
User metadata API
packages/react/src/api/getUsersMeMeta.ts, packages/react/src/index.ts
Adds configurable /users/me/meta retrieval with public schema, configuration, and response interfaces. Exports the API from the React package.
Schema context propagation
packages/react/src/contexts/ThunderID/*, packages/react/src/contexts/User/*, packages/nextjs/src/client/contexts/ThunderID/ThunderIDProvider.tsx
Fetches schema metadata during profile synchronization and exposes it through ThunderID and User contexts. Context defaults use null.
Schema-driven profile editing
packages/react/src/components/presentation/UserProfile/*
Builds profile fields from schema metadata, filters credential fields, validates required and regex constraints, displays errors, and preserves fallback rendering.

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

Sequence Diagram(s)

sequenceDiagram
  participant ThunderIDProvider
  participant MetadataAPI
  participant UserProvider
  participant UserProfile
  ThunderIDProvider->>MetadataAPI: Fetch /users/me/meta
  MetadataAPI-->>ThunderIDProvider: Return userSchema
  ThunderIDProvider->>UserProvider: Pass profile and userSchema
  UserProvider-->>UserProfile: Expose userSchema
  UserProfile->>UserProfile: Build and validate schema fields
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ 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%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes integration of the users/me/meta endpoint into the React and Next.js SDKs.
Description check ✅ Passed The description covers the purpose, approach, related work, checklist, testing status, and security checks.
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

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

packages/nextjs/src/client/contexts/ThunderID/ThunderIDProvider.tsx

ESLint skipped: missing config or dependency (missing-dependency). The ESLint configuration references a package that is not available in the sandbox.

packages/react/src/api/getUsersMeMeta.ts

ESLint skipped: missing config or dependency (missing-dependency). The ESLint configuration references a package that is not available in the sandbox.

packages/react/src/components/presentation/UserProfile/BaseUserProfile.tsx

ESLint skipped: the ESLint configuration for this file references a package that is not available in the sandbox.

  • 6 others

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.

@janithjay
janithjay force-pushed the feat/profile-edit-put branch from d28958f to 8519068 Compare August 3, 2026 09:43

@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: 7

🧹 Nitpick comments (4)
packages/react/src/components/presentation/UserProfile/BaseUserProfile.tsx (2)

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

Move the error style into the stylesheet.

The error element uses an inline style with the hardcoded color #d32f2f. Every other element in this component uses the styles object from useStyles(theme, colorScheme). The hardcoded color ignores the theme and the dark color scheme.

Add a fieldError entry to the styles module, and apply the vendor CSS class prefix that the component already uses through withVendorCSSClassPrefix.

🎨 Proposed change
           {fieldErrors[schema.name] && (
-            <div style={{color: '`#d32f2f`', fontSize: '0.8rem', marginTop: '4px', fontWeight: 500}}>
+            <div
+              className={cx(withVendorCSSClassPrefix(bem('user-profile', 'field-error')), styles.fieldError)}
+              role="alert"
+            >
               {fieldErrors[schema.name]}
             </div>
           )}

The role="alert" attribute also makes the validation message reachable for screen reader users.

🤖 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/react/src/components/presentation/UserProfile/BaseUserProfile.tsx`
around lines 626 - 630, Move the inline styling from the field error element in
UserProfile to a new fieldError entry in the useStyles(theme, colorScheme)
styles module, using theme-aware values and the existing
withVendorCSSClassPrefix convention. Apply the resulting prefixed styles class
to the error element and add role="alert" so validation messages are announced
to screen readers.

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

Resolve the ESLint errors reported across the new schema branch.

The tool reports more than forty errors for Lines 680-730, mostly no-explicit-any, no-unsafe-member-access, and no-unsafe-assignment. Typing userSchema as Record<string, AttributeSchema> and typing the map callback removes most of them.

🧹 Proposed typing
-      schemaItems = Object.entries(userSchema)
-        .filter(([key, metaAttr]: [string, any]) => {
+      schemaItems = Object.entries(userSchema as Record<string, AttributeSchema>)
+        .filter(([key, metaAttr]: [string, AttributeSchema]) => {
           if (metaAttr?.credential) return false;
           return shouldShowField(key, true);
         })
-        .map(([key, metaAttr]: [string, any]) => {
+        .map(([key, metaAttr]: [string, AttributeSchema]): Schema => {

Also note Line 173: remove the redundant : boolean annotation on the isSchemaBased default parameter to satisfy no-inferrable-types.

🤖 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/react/src/components/presentation/UserProfile/BaseUserProfile.tsx`
around lines 680 - 730, Resolve the ESLint errors in renderProfileContent by
replacing explicit any usage with the existing AttributeSchema type, typing
userSchema as Record<string, AttributeSchema>, and providing safe types for
Object.entries filter/map callbacks and accessed values. Ensure schemaItems and
derived fields use compatible concrete types without unsafe member access or
assignments. Also remove the redundant boolean annotation from the isSchemaBased
default parameter.

Source: Linters/SAST tools

packages/react/src/contexts/ThunderID/ThunderIDContext.ts (1)

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

Use AttributeSchema instead of Record<string, any> across the schema plumbing. packages/react/src/api/getUsersMeMeta.ts exports AttributeSchema and returns schema?: Record<string, AttributeSchema>, but every downstream layer re-declares the value as Record<string, any>. The producer type is therefore lost at the first hop, and ESLint reports no-explicit-any at each site.

  • packages/react/src/contexts/ThunderID/ThunderIDContext.ts#L219-L222: change userSchema to Record<string, AttributeSchema> | null and import the type.
  • packages/react/src/contexts/ThunderID/ThunderIDProvider.tsx#L87-L87: change the state generic to Record<string, AttributeSchema> | null.
  • packages/react/src/contexts/User/UserContext.ts#L34-L34: change the optional userSchema property to Record<string, AttributeSchema> | null.
  • packages/react/src/contexts/User/UserProvider.tsx#L34-L34: change the userSchema prop to Record<string, AttributeSchema> | null.
  • packages/react/src/components/presentation/UserProfile/BaseUserProfile.tsx#L92-L92: change the userSchema prop to Record<string, AttributeSchema> | null, which also removes the unsafe-access errors in the schema branch.

Note that userSchema is required in ThunderIDContextProps but optional in UserContextProps. Align the optionality as part of this change.

🤖 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/react/src/contexts/ThunderID/ThunderIDContext.ts` around lines 219 -
222, Replace the downstream userSchema types with AttributeSchema from
getUsersMeMeta, preserving the required ThunderIDContextProps field and aligning
UserContextProps with the nullable optional contract. Update
packages/react/src/contexts/ThunderID/ThunderIDContext.ts (219-222),
packages/react/src/contexts/ThunderID/ThunderIDProvider.tsx (87-87),
packages/react/src/contexts/User/UserContext.ts (34-34),
packages/react/src/contexts/User/UserProvider.tsx (34-34), and
packages/react/src/components/presentation/UserProfile/BaseUserProfile.tsx
(92-92) to use Record<string, AttributeSchema> with the appropriate
null/optional modifiers and import the type where needed; no other sites require
changes.

Source: Linters/SAST tools

packages/react/src/api/getUsersMeMeta.ts (1)

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

Move the users metadata helper to the shared API layer.

getUsersMeMeta wraps GET /users/me/meta, but this helper exists only in @thunderid/react while the shared helpers for /users/me profile endpoints live in @thunderid/javascript. Add getUsersMeMeta to the lower package and re-export it through @thunderid/browser so react/vue wrappers can reuse the same API contract.

🤖 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/react/src/api/getUsersMeMeta.ts` around lines 19 - 47, Move the
getUsersMeMeta helper and its related types, including AttributeSchema,
GetUsersMeMetaConfig, and UsersMeMetaResponse, from `@thunderid/react` into
`@thunderid/javascript` alongside the existing /users/me helpers. Re-export the
helper and shared types through `@thunderid/browser`, then update the React
implementation to reuse that shared export while preserving the GET
/users/me/meta contract.

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/react/src/api/getUsersMeMeta.ts`:
- Around line 57-81: Fix the lint violations in the metadata fetch flow around
defaultFetcher and the final res.json return: replace || fallbacks with
nullish-coalescing where appropriate, replace HttpResponse<any> with a typed
response payload, and ensure res.json() returns that typed value without an
unsafe return. Preserve the existing fetch behavior and error handling.
- Around line 49-55: Update getUsersMeMeta to define an explicit missing-baseUrl
behavior: preserve baseUrl-derived requests, but avoid constructing
/users/me/meta when baseUrl is absent and add the required import guard, or
require url for metadata-only calls. If metadata endpoint overrides are
supported, add usersMeMeta to RESOURCE_ENDPOINT_KEYS and pass the resolved
endpoint from ThunderIDProvider via resolveResourceEndpoint.

In `@packages/react/src/components/presentation/UserProfile/BaseUserProfile.tsx`:
- Around line 339-347: Update the field update handler containing payload
construction and onUpdate so it awaits the returned promise and handles
rejection without allowing a floating promise; only call
toggleFieldEdit(fieldName) after onUpdate succeeds, leaving the field open when
the update fails. Adjust the handler’s async/dependency setup as needed while
preserving its existing payload behavior.
- Around line 304-330: Localize the required and regex validation messages in
handleFieldSave using new i18n keys and t calls that pass fieldLabel as the
field interpolation; add the corresponding translation entries. Include t in
handleFieldSave’s useCallback dependency array.
- Around line 685-711: Sort the `Object.entries(userSchema)` results in the
schema branch before filtering or mapping, ordering entries by each attribute’s
numeric `displayOrder` and using the field key as the stable fallback for ties
or missing values. Preserve the existing credential filtering and `schemaItems`
mapping behavior so `BaseUserProfile` renders fields in metadata order.

In `@packages/react/src/contexts/ThunderID/ThunderIDProvider.tsx`:
- Line 575: Update the UserProvider invocation to keep userSchema in only one
source, and memoize the profile object derived from userProfile and userSchema
so its reference remains stable when inputs are unchanged. Preserve the
null/absent userProfile behavior without relying on a non-null assertion, and
ensure the existing UserProvider props continue receiving the intended profile
data.
- Around line 158-166: Update the user-schema lifecycle around the existing
metadata fetch and authentication state handling: call setUserSchema with an
empty or undefined value when no user is signed in, and also clear it in the
catch path when getUsersMeMeta fails. Preserve setting the fetched schema on
successful responses.

---

Nitpick comments:
In `@packages/react/src/api/getUsersMeMeta.ts`:
- Around line 19-47: Move the getUsersMeMeta helper and its related types,
including AttributeSchema, GetUsersMeMetaConfig, and UsersMeMetaResponse, from
`@thunderid/react` into `@thunderid/javascript` alongside the existing /users/me
helpers. Re-export the helper and shared types through `@thunderid/browser`, then
update the React implementation to reuse that shared export while preserving the
GET /users/me/meta contract.

In `@packages/react/src/components/presentation/UserProfile/BaseUserProfile.tsx`:
- Around line 626-630: Move the inline styling from the field error element in
UserProfile to a new fieldError entry in the useStyles(theme, colorScheme)
styles module, using theme-aware values and the existing
withVendorCSSClassPrefix convention. Apply the resulting prefixed styles class
to the error element and add role="alert" so validation messages are announced
to screen readers.
- Around line 680-730: Resolve the ESLint errors in renderProfileContent by
replacing explicit any usage with the existing AttributeSchema type, typing
userSchema as Record<string, AttributeSchema>, and providing safe types for
Object.entries filter/map callbacks and accessed values. Ensure schemaItems and
derived fields use compatible concrete types without unsafe member access or
assignments. Also remove the redundant boolean annotation from the isSchemaBased
default parameter.

In `@packages/react/src/contexts/ThunderID/ThunderIDContext.ts`:
- Around line 219-222: Replace the downstream userSchema types with
AttributeSchema from getUsersMeMeta, preserving the required
ThunderIDContextProps field and aligning UserContextProps with the nullable
optional contract. Update
packages/react/src/contexts/ThunderID/ThunderIDContext.ts (219-222),
packages/react/src/contexts/ThunderID/ThunderIDProvider.tsx (87-87),
packages/react/src/contexts/User/UserContext.ts (34-34),
packages/react/src/contexts/User/UserProvider.tsx (34-34), and
packages/react/src/components/presentation/UserProfile/BaseUserProfile.tsx
(92-92) to use Record<string, AttributeSchema> with the appropriate
null/optional modifiers and import the type where needed; no other sites require
changes.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: ac1d8b94-ee3c-40a3-bb09-ecf476534e66

📥 Commits

Reviewing files that changed from the base of the PR and between 0beef6f and d28958f.

📒 Files selected for processing (9)
  • packages/nextjs/src/client/contexts/ThunderID/ThunderIDProvider.tsx
  • packages/react/src/api/getUsersMeMeta.ts
  • packages/react/src/components/presentation/UserProfile/BaseUserProfile.tsx
  • packages/react/src/components/presentation/UserProfile/UserProfile.tsx
  • packages/react/src/contexts/ThunderID/ThunderIDContext.ts
  • packages/react/src/contexts/ThunderID/ThunderIDProvider.tsx
  • packages/react/src/contexts/User/UserContext.ts
  • packages/react/src/contexts/User/UserProvider.tsx
  • packages/react/src/index.ts

Comment thread packages/react/src/api/getUsersMeMeta.ts Outdated
Comment thread packages/react/src/api/getUsersMeMeta.ts Outdated
Comment thread packages/react/src/contexts/ThunderID/ThunderIDProvider.tsx
Comment thread packages/react/src/contexts/ThunderID/ThunderIDProvider.tsx Outdated

Copilot AI 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.

Pull request overview

This PR adds support for fetching and consuming user profile schema metadata from the /users/me/meta endpoint, enabling @thunderid/react’s <UserProfile /> to render profile fields dynamically (labels, required-ness, ordering, etc.) based on server-provided schema.

Changes:

  • Added a new React API helper (getUsersMeMeta) and exported it from the React package entrypoint.
  • Extended React ThunderID/User contexts and providers to fetch and expose userSchema.
  • Updated the React UserProfile/BaseUserProfile components to render/edit fields based on fetched schema metadata.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
packages/react/src/index.ts Exports the new getUsersMeMeta helper from the React SDK.
packages/react/src/contexts/User/UserProvider.tsx Plumbs userSchema through the User context provider value.
packages/react/src/contexts/User/UserContext.ts Adds userSchema to the User context contract + default value.
packages/react/src/contexts/ThunderID/ThunderIDProvider.tsx Fetches /users/me/meta, stores userSchema, and passes it to downstream providers/contexts.
packages/react/src/contexts/ThunderID/ThunderIDContext.ts Adds userSchema to the ThunderID context contract + default value.
packages/react/src/components/presentation/UserProfile/UserProfile.tsx Passes userSchema from useUser() into BaseUserProfile.
packages/react/src/components/presentation/UserProfile/BaseUserProfile.tsx Renders profile fields dynamically from userSchema and adds required/regex validation handling.
packages/react/src/api/getUsersMeMeta.ts New helper for authenticated GET /users/me/meta.
packages/nextjs/src/client/contexts/ThunderID/ThunderIDProvider.tsx Adds a userSchema field to the bridged React context value (currently hard-coded to null).
Suppressed comments (4)

packages/react/src/contexts/ThunderID/ThunderIDProvider.tsx:575

  • userProfile is initialized as null, so spreading it ({...userProfile!, userSchema}) will throw at runtime on the first render. This used to be safe when passing the value directly.

Pass userProfile through unchanged and keep userSchema as its own prop/source.

              <UserProvider

packages/react/src/contexts/ThunderID/ThunderIDProvider.tsx:163

  • /users/me/meta is always derived from resolvedBaseUrl, but /users/me already supports resource-server overrides via resolveResourceEndpoint('usersMe', config). If endpoints.usersMe is configured, this call will hit the wrong host/path.

Derive the meta URL from the resolved usersMe endpoint instead (append /meta).

        try {
          const metaRes = await getUsersMeMeta({baseUrl: resolvedBaseUrl, instanceId});
          if (metaRes?.schema) {
            setUserSchema(metaRes.schema);
          }

packages/react/src/api/getUsersMeMeta.ts:79

  • The thrown error only includes statusText, which is often empty for non-2xx responses returned by many servers/proxies. Including the status code (and best-effort body) makes this error actionable for SDK consumers.
  return res.json();
};

packages/react/src/contexts/ThunderID/ThunderIDProvider.tsx:166

  • New behavior adds an additional request to /users/me/meta and a new userSchema value flowing through context, but the existing ThunderIDProvider tests only cover /users/me. Adding/adjusting tests to mock and assert the meta fetch (and that userSchema is exposed) would prevent regressions (e.g., double-fetching, wrong URL, stale schema).
        try {
          const metaRes = await getUsersMeMeta({baseUrl: resolvedBaseUrl, instanceId});
          if (metaRes?.schema) {
            setUserSchema(metaRes.schema);
          }
        } catch (err) {
          logger.warn('Failed to fetch user schema metadata from /users/me/meta:', err);
        }

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/react/src/contexts/ThunderID/ThunderIDProvider.tsx
Comment thread packages/react/src/api/getUsersMeMeta.ts Outdated
Comment thread packages/nextjs/src/client/contexts/ThunderID/ThunderIDProvider.tsx
@janithjay
janithjay marked this pull request as draft August 3, 2026 10:54
@janithjay
janithjay force-pushed the feat/profile-edit-put branch from 8519068 to 37217b0 Compare August 3, 2026 12:21
@janithjay
janithjay marked this pull request as ready for review August 3, 2026 12:22

@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.

♻️ Duplicate comments (2)
packages/react/src/components/presentation/UserProfile/BaseUserProfile.tsx (2)

339-347: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Handle the onUpdate rejection and only close the field editor on success.

onUpdate returns a promise. Line 342 does not await it, so a rejection becomes an unhandled promise rejection. toggleFieldEdit(fieldName) at Line 344 also runs immediately, closing the field editor even if the update fails, hiding the failure from the user. A prior review flagged this exact pattern and it was reported as addressed, but the current code still has the unresolved version.

🛡️ Proposed fix
-      let payload: Record<string, any> = {};
+      const payload: Record<string, any> = {};
       set(payload, fieldName, fieldValue);

-      onUpdate(payload);
-
-      toggleFieldEdit(fieldName);
+      void Promise.resolve(onUpdate(payload)).then(() => {
+        toggleFieldEdit(fieldName);
+      });
🤖 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/react/src/components/presentation/UserProfile/BaseUserProfile.tsx`
around lines 339 - 347, Update the field-update callback around onUpdate and
toggleFieldEdit so it awaits the promise returned by onUpdate, handles or
propagates any rejection without creating an unhandled promise, and only calls
toggleFieldEdit(fieldName) after a successful update; keep the editor open when
the update fails.

304-330: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Finish the localization work: use fieldLabel or drop it, and add t to the dependency array.

fieldLabel (Line 305) is computed but never used, matching the ESLint no-unused-vars finding. A previous review asked for the field name to be interpolated into the validation messages (t('...', {field: fieldLabel})); the messages at Lines 311 and 323 still don't take it. Either wire fieldLabel into the t() calls, or remove the dead variable.

Also, t is used at Lines 311 and 323 but is missing from handleFieldSave's dependency array (Line 346). If the active locale changes while this callback exists, it keeps calling the stale t.

Additionally, catch (e) at Line 327 never uses e; drop the binding (catch {}) to satisfy no-unused-vars.

🧹 Proposed fix
-      const strVal = String(fieldValue ?? '').trim();
-      const fieldLabel = schema.displayName || (schema.name ? startCase(schema.name) : 'Field');
+      const strVal = String(fieldValue ?? '').trim();
+      const fieldLabel = schema.displayName ?? (schema.name ? startCase(schema.name) : 'Field');

       // 1. Required validation
       if (schema.required && !strVal) {
         setFieldErrors((prev: Record<string, string>) => ({
           ...prev,
-          [fieldName]: t('validations.required.field.error'),
+          [fieldName]: t('validations.required.field.error', {field: fieldLabel}),
         }));
         return;
       }

       // 2. Regex validation
       if (schema.regex && strVal) {
         try {
           const reg = new RegExp(schema.regex);
           if (!reg.test(strVal)) {
             setFieldErrors((prev: Record<string, string>) => ({
               ...prev,
-              [fieldName]: t('validation.pattern.invalid'),
+              [fieldName]: t('validation.pattern.invalid', {field: fieldLabel}),
             }));
             return;
           }
-        } catch (e) {
+        } catch {
           // ignore invalid regex syntax safely
         }
       }
-    [editedUser, flattenedProfile, profile, onUpdate, toggleFieldEdit],
+    [editedUser, flattenedProfile, profile, onUpdate, toggleFieldEdit, t],
🤖 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/react/src/components/presentation/UserProfile/BaseUserProfile.tsx`
around lines 304 - 330, Update handleFieldSave to use fieldLabel in the required
and pattern validation translation calls with the expected field interpolation,
or remove fieldLabel if interpolation is not supported. Add t to
handleFieldSave’s dependency array so locale changes use the current translator,
and change the unused regex-error catch binding to catch {}.
🧹 Nitpick comments (6)
packages/react/src/contexts/ThunderID/ThunderIDProvider.tsx (1)

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

Type userSchema using the existing AttributeSchema contract instead of Record<string, any>.

Same as the other files: use Record<string, AttributeSchema> (from getUsersMeMeta.ts) instead of Record<string, any> | null for this state.

🤖 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/react/src/contexts/ThunderID/ThunderIDProvider.tsx` at line 87,
Update the userSchema state declaration in ThunderIDProvider to use
Record<string, AttributeSchema> from getUsersMeMeta.ts instead of Record<string,
any> | null, preserving the existing nullable initial state and setter behavior.
packages/react/src/components/presentation/UserProfile/BaseUserProfile.tsx (1)

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

Type userSchema using the existing AttributeSchema contract instead of Record<string, any>.

getUsersMeMeta.ts already defines UsersMeMetaResponse.schema?: Record<string, AttributeSchema> and AttributeSchema. Reuse that type here instead of Record<string, any> | null. This removes most of the no-unsafe-member-access/no-unsafe-assignment ESLint findings at Lines 685-711 in one change and keeps the schema contract consistent from the API layer through to this component.

🤖 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/react/src/components/presentation/UserProfile/BaseUserProfile.tsx`
at line 92, Update the userSchema property in BaseUserProfile to use the
existing AttributeSchema contract, matching UsersMeMetaResponse.schema, and
remove the broad any/null typing while preserving the optional property
behavior.
packages/react/src/contexts/ThunderID/ThunderIDContext.ts (1)

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

Type userSchema using the existing AttributeSchema contract instead of Record<string, any>.

Same as in BaseUserProfile.tsx: reuse Record<string, AttributeSchema> from getUsersMeMeta.ts instead of Record<string, any> | null here, so the schema type stays consistent from the API layer through the context.

🤖 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/react/src/contexts/ThunderID/ThunderIDContext.ts` around lines 219 -
223, Update the userSchema property in ThunderIDContext to use the existing
Record<string, AttributeSchema> contract imported or defined by
getUsersMeMeta.ts, replacing Record<string, any> | null and keeping its
API-to-context typing consistent with BaseUserProfile.tsx.
packages/react/src/contexts/User/UserContext.ts (1)

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

Type userSchema using the existing AttributeSchema contract instead of Record<string, any>.

Same as the other files: reuse Record<string, AttributeSchema> from getUsersMeMeta.ts here as well, to keep the public UserContextProps contract consistent with the API response shape.

🤖 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/react/src/contexts/User/UserContext.ts` at line 34, Update the
userSchema field in UserContextProps to use Record<string, AttributeSchema> from
the existing getUsersMeMeta contract instead of Record<string, any>, preserving
the nullable optional API response shape.
packages/react/src/contexts/User/UserProvider.tsx (2)

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

Type userSchema using the existing AttributeSchema contract instead of Record<string, any>.

Same as the other files: reuse Record<string, AttributeSchema> from getUsersMeMeta.ts for both the profile.userSchema and top-level userSchema fields.

🤖 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/react/src/contexts/User/UserProvider.tsx` around lines 26 - 35,
Update UserProviderProps to use the existing AttributeSchema contract for both
profile.userSchema and the top-level userSchema fields. Replace Record<string,
any> with Record<string, AttributeSchema>, reusing the AttributeSchema type from
getUsersMeMeta.ts and preserving the nullable optional field behavior.

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

Consider dropping the unused profile.userSchema fallback path.

profile?.userSchema ?? userSchema ?? null (Line 79) reads userSchema from two places. The only reviewed producer, ThunderIDProvider.tsx, always passes userSchema as the separate top-level prop and never embeds it into the userProfile state object, so profile.userSchema is currently dead. Keeping two sources with implicit precedence risks confusion if a future caller sets both differently. Consider dropping userSchema from UserProviderProps.profile and relying solely on the top-level userSchema prop, unless another producer outside this review intentionally embeds it in profile.

🤖 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/react/src/contexts/User/UserProvider.tsx` around lines 72 - 82,
Remove the embedded profile.userSchema fallback from UserProvider’s contextValue
construction and rely on the top-level userSchema prop, preserving null as the
final fallback. Update the UserProviderProps profile type to no longer include
userSchema, and adjust any affected references while keeping the existing
context value behavior unchanged.
🤖 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.

Duplicate comments:
In `@packages/react/src/components/presentation/UserProfile/BaseUserProfile.tsx`:
- Around line 339-347: Update the field-update callback around onUpdate and
toggleFieldEdit so it awaits the promise returned by onUpdate, handles or
propagates any rejection without creating an unhandled promise, and only calls
toggleFieldEdit(fieldName) after a successful update; keep the editor open when
the update fails.
- Around line 304-330: Update handleFieldSave to use fieldLabel in the required
and pattern validation translation calls with the expected field interpolation,
or remove fieldLabel if interpolation is not supported. Add t to
handleFieldSave’s dependency array so locale changes use the current translator,
and change the unused regex-error catch binding to catch {}.

---

Nitpick comments:
In `@packages/react/src/components/presentation/UserProfile/BaseUserProfile.tsx`:
- Line 92: Update the userSchema property in BaseUserProfile to use the existing
AttributeSchema contract, matching UsersMeMetaResponse.schema, and remove the
broad any/null typing while preserving the optional property behavior.

In `@packages/react/src/contexts/ThunderID/ThunderIDContext.ts`:
- Around line 219-223: Update the userSchema property in ThunderIDContext to use
the existing Record<string, AttributeSchema> contract imported or defined by
getUsersMeMeta.ts, replacing Record<string, any> | null and keeping its
API-to-context typing consistent with BaseUserProfile.tsx.

In `@packages/react/src/contexts/ThunderID/ThunderIDProvider.tsx`:
- Line 87: Update the userSchema state declaration in ThunderIDProvider to use
Record<string, AttributeSchema> from getUsersMeMeta.ts instead of Record<string,
any> | null, preserving the existing nullable initial state and setter behavior.

In `@packages/react/src/contexts/User/UserContext.ts`:
- Line 34: Update the userSchema field in UserContextProps to use Record<string,
AttributeSchema> from the existing getUsersMeMeta contract instead of
Record<string, any>, preserving the nullable optional API response shape.

In `@packages/react/src/contexts/User/UserProvider.tsx`:
- Around line 26-35: Update UserProviderProps to use the existing
AttributeSchema contract for both profile.userSchema and the top-level
userSchema fields. Replace Record<string, any> with Record<string,
AttributeSchema>, reusing the AttributeSchema type from getUsersMeMeta.ts and
preserving the nullable optional field behavior.
- Around line 72-82: Remove the embedded profile.userSchema fallback from
UserProvider’s contextValue construction and rely on the top-level userSchema
prop, preserving null as the final fallback. Update the UserProviderProps
profile type to no longer include userSchema, and adjust any affected references
while keeping the existing context value behavior unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 655539bc-f217-4983-80b9-7d41f88ad375

📥 Commits

Reviewing files that changed from the base of the PR and between d28958f and 37217b0.

📒 Files selected for processing (9)
  • packages/nextjs/src/client/contexts/ThunderID/ThunderIDProvider.tsx
  • packages/react/src/api/getUsersMeMeta.ts
  • packages/react/src/components/presentation/UserProfile/BaseUserProfile.tsx
  • packages/react/src/components/presentation/UserProfile/UserProfile.tsx
  • packages/react/src/contexts/ThunderID/ThunderIDContext.ts
  • packages/react/src/contexts/ThunderID/ThunderIDProvider.tsx
  • packages/react/src/contexts/User/UserContext.ts
  • packages/react/src/contexts/User/UserProvider.tsx
  • packages/react/src/index.ts
🚧 Files skipped from review as they are similar to previous changes (4)
  • packages/react/src/index.ts
  • packages/nextjs/src/client/contexts/ThunderID/ThunderIDProvider.tsx
  • packages/react/src/components/presentation/UserProfile/UserProfile.tsx
  • packages/react/src/api/getUsersMeMeta.ts

@janithjay
janithjay marked this pull request as draft August 3, 2026 12:33
@janithjay
janithjay force-pushed the feat/profile-edit-put branch from 37217b0 to 8cc117a Compare August 3, 2026 12:59
@janithjay
janithjay marked this pull request as ready for review August 3, 2026 12:59
@janithjay
janithjay force-pushed the feat/profile-edit-put branch from 8cc117a to 4bc1a26 Compare August 4, 2026 04:01
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