Skip to content

Overhaul GraphQL client with SDK extensions and refactor entity handling#108

Merged
jfrench9 merged 31 commits intomainfrom
feature/graphql-client-overhaul
Apr 15, 2026
Merged

Overhaul GraphQL client with SDK extensions and refactor entity handling#108
jfrench9 merged 31 commits intomainfrom
feature/graphql-client-overhaul

Conversation

@jfrench9
Copy link
Copy Markdown
Member

Summary

This PR delivers a comprehensive overhaul of the GraphQL client infrastructure, upgrading @robosystems/client to v0.3.1 and integrating SDK extensions for improved token management in GraphQL requests. Alongside the client changes, this PR refactors entity handling across the application, enhances the search experience with GitHub Flavored Markdown support, and updates the Closing Book feature with sidebar navigation and content panels.

Key Changes

GraphQL Client & Auth Core

  • New auth-core/client.ts module (+104 lines): Implements RoboSystemsAuthClient with SDK extensions integration for streamlined token management across all GraphQL requests.
  • Refactored error logging to provide cleaner console warnings when SDK extensions configuration fails.
  • Upgraded @robosystems/client from v0.2.47 → v0.3.1.

Entity Handling Refactor

  • Refactored EntitySelectorDropdown component and its associated test suite (~135 lines changed across component and tests).
  • Updated entity list (entities/content.tsx) and single entity (entity/content.tsx) views with revised data handling patterns.
  • Significant changes to how entities are managed across ledger components (chart-of-accounts, close, schedules, transactions, trial-balance, reports).

Ledger / Closing Book Components

  • Refactored all Closing Book sub-components: AccountRollupsPanel, PeriodClosePanel, SchedulePanel, StatementPanel, StructureSidebar, TrialBalancePanel.
  • Updated corresponding test suites (AccountRollupsPanel.test.tsx, StructureSidebar.test.tsx, TrialBalancePanel.test.tsx) to align with new entity handling patterns.

Search & Markdown Enhancements

  • Integrated remark-gfm plugin into SearchContent component for GitHub Flavored Markdown rendering.
  • Added custom table rendering for improved display of markdown tables in search results.
  • New remark-gfm dependency added to package.json.

Service Offerings & Billing

  • Updated service-offerings-context.tsx to use instance storage limit instead of previous storage usage handling.
  • Removed storage usage handling from UsageContent component.
  • Adjusted graph tier limit tests accordingly (removed 12 lines from graph-tiers.test.ts).

Breaking Changes

⚠️ Potentially breaking:

  • The auth-core client now relies on SDK extensions for token management. Any downstream consumers that directly instantiate or configure the GraphQL client may need to adapt to the new RoboSystemsAuthClient pattern.
  • Entity selector components have a changed API/prop interface — any external usage outside the modified files should be verified.
  • Service offerings context now exposes instance storage limit instead of the previous storage usage properties.

Testing Notes

  • Unit tests updated: 5 test files modified to reflect refactored entity handling and component APIs. Reviewers should verify all tests pass in CI.
  • Manual testing recommended for:
    • Entity selector dropdown behavior across all pages (entities list, entity detail, ledger views, reports).
    • Closing Book flow end-to-end: sidebar navigation → account rollups → trial balance → period close → statements.
    • Search functionality: verify GFM tables render correctly, especially complex markdown with pipes and alignment.
    • Authentication flow: confirm token refresh and SDK extension handshake work correctly across GraphQL mutations and queries.
    • Subscription tier upgrade flow in billing (referenced in commits).

Browser Compatibility

  • remark-gfm processes markdown server-side/at render time and does not introduce browser-specific APIs — no compatibility concerns.
  • Custom table rendering uses standard HTML table elements with existing styling; verify appearance in Safari, Firefox, and Chrome.
  • No new Web APIs or browser-specific features introduced; existing compatibility baseline should be maintained.

Dependencies

Package Change
@robosystems/client 0.2.470.3.1
remark-gfm ✨ New dependency

Diff stats: 28 files changed, +1,138 / -657 lines across 27 commits.


🤖 Generated with Claude Code

Branch Info:

  • Source: feature/graphql-client-overhaul
  • Target: main
  • Type: feature

Co-Authored-By: Claude noreply@anthropic.com

jfrench9 added 27 commits March 28, 2026 16:37
…gration

- Reintroduced 'Knowledge Base' navigation item in the sidebar for better accessibility.
- Updated search configuration description and placeholder to reflect broader document search capabilities.
- Adjusted document stats loading logic to skip for shared repositories, improving performance and user experience.
…p description in config.ts

- Upgraded the `@robosystems/client` dependency from version 0.2.38 to 0.2.40 in both package.json and package-lock.json.
- Changed the application description in config.ts from 'Accounting and FP&A Agent' to 'Accounting & Reporting Agent' for clarity.
…on and package-lock.json for enhanced features and stability. Modify app description in config.ts for clarity.
…update service offerings context to use instance storage limit. Adjust related tests to reflect changes in graph tier limits.
- Updated SearchConfig to include semantic search option.
- Enhanced SearchContent component to manage semantic search state and integrate it into the search request.
- Added ToggleSwitch for semantic search in the UI, allowing users to enable or disable this feature.
…age-lock.json for improved functionality. Implement subscription tier upgrade feature in the billing component, including UI updates and task monitoring for upgrade progress.
…GFM) by integrating remark-gfm plugin. Added custom table rendering for improved display of markdown tables.
…nels

- Updated sidebar configuration to include a new "Close" link.
- Added new components for the Closing Book feature, including CloseContent, StructureSidebar, and various panels (AccountRollupsPanel, PeriodClosePanel, SchedulePanel, StatementPanel).
- Implemented data fetching and state management for closing book categories and entries.
- Enhanced user interface with loading states and error handling for better user experience.
- Introduced view mode toggle functionality for rendered and facts views.
- Upgraded @robosystems/client to version 0.3.0, introducing new dependencies for GraphQL integration.
- Refactored entity fetching logic in content components to utilize the new extensions.ledger.getEntity method, improving data handling and reducing API envelope complexity.
- Updated tests to reflect changes in entity structure and ensure compatibility with the new data model.
- Enhanced Chart of Accounts and Period Close components to align with updated data structures and improve overall functionality.
…6f1d66'

git-subtree-dir: src/lib/core
git-subtree-mainline: 4cbeb6f
git-subtree-split: b0c815d
bcbc89d Merge commit '97dfba339149a3b12eb5c57ec1794a606a4a16bd' into feature/new-client-version
177d49b Enhance SearchContent component to support GitHub Flavored Markdown (GFM) by integrating remark-gfm plugin. Added custom table rendering for improved display of markdown tables.
4814338 Update @robosystems/client to version 0.2.47 in package.json and package-lock.json for improved functionality. Implement subscription tier upgrade feature in the billing component, including UI updates and task monitoring for upgrade progress.
e083259 Add semantic search functionality to Search component
8185b09 Refactor UsageContent component to remove storage usage handling and update service offerings context to use instance storage limit. Adjust related tests to reflect changes in graph tier limits.
5180fe3 Merge commit '001c68a121099f81d2ec763c46f6c5f7dea7f54f' into chore/update-client-core
1931702 Merge commit '04fb84ca67736be2c848f7d06b7aeccd0c05c3f2' into chore/update-core
73262d0 Update @robosystems/client dependency to version 0.2.40 and modify app description in config.ts
ce0febb Fix import order in SearchContent component for consistency
92710db Refactor sidebar and search components to enhance knowledge base integration

git-subtree-dir: src/lib/core
git-subtree-split: bcbc89d
0f8c242 Merge commit 'db0292ff6caa5e50f2b167685848d4980aaf3ae0' into feature/new-client-version
7057e08 Merge commit 'e842e528f0097422a30f5e91a6c28545259bb6ec' into feature/new-client-version
fba5502 Merge commit '0f62036f32808efc36fa484933c6cb847f4285a5' into chore/update-client-core
7e8a12b Merge commit '248cb4e9d4dbc9f5e11c720d4fd456c26feaaaa4' into chore/update-core
77c56fc Update @robosystems/client dependency to version 0.2.40 in package.json and package-lock.json for enhanced features and stability. Modify app description in config.ts for clarity.

git-subtree-dir: src/lib/core
git-subtree-split: 0f8c242
…ency for enhanced markdown support. Refactor auth-core client to integrate SDK extensions for improved token management in GraphQL requests.
…ency for enhanced markdown support. Refactor auth-core client to integrate SDK extensions for improved token management in GraphQL requests.
… warnings for SDK extensions configuration failures.
… warnings for SDK extensions configuration failures.
…697414'

git-subtree-dir: src/lib/core
git-subtree-mainline: e1812f5
git-subtree-split: 87f1b57
@jfrench9
Copy link
Copy Markdown
Member Author

@claude please review this PR

@claude
Copy link
Copy Markdown

claude Bot commented Apr 14, 2026

Claude finished @jfrench9's task in 2m 4s —— View job


PR Review: Overhaul GraphQL client with SDK extensions and refactor entity handling

Tasks:

  • Gather context and understand PR scope
  • Read key changed files
  • Analyze git diff for the branch
  • Provide comprehensive review feedback

This is a large, multi-concern PR. The entity handling refactor and Closing Book components are well-executed; the main concerns are concentrated in the new auth-core/client.ts module.


Critical Issues

1. Global singleton mutation in auth-core/client.ts

The most significant problem in this PR. this.client = client assigns the shared module singleton to the instance field — there is no copy. Then configureClientWithAuth overwrites the singleton's methods in place:

// src/lib/core/auth-core/client.ts:203-207
this.client.get = wrapWithAuthAndErrorHandling(originalGet, 'GET')
this.client.post = wrapWithAuthAndErrorHandling(originalPost, 'POST')
this.client.put = wrapWithAuthAndErrorHandling(originalPut, 'PUT')
this.client.patch = wrapWithAuthAndErrorHandling(originalPatch, 'PATCH')
this.client.delete = wrapWithAuthAndErrorHandling(originalDelete, 'DELETE')

Every module that imports client from @robosystems/client — including any code that uses it directly — will silently get the wrapped version after the first RoboSystemsAuthClient is constructed. If the constructor is called more than once (re-renders, HMR, tests), each call captures the already-wrapped method as originalPost, creating nested wrapper chains that grow unboundedly.

Recommendation: Either clone the client object before wrapping methods, or use a request interceptor/middleware API if the SDK exposes one. If the SDK doesn't, consider wrapping at the call site rather than mutating the singleton. Fix this →


2. Massive code duplication in token-update pattern

The same ~15-line block that creates a RoboSystemsExtensions instance and calls setSDKExtensionsConfig appears identically in login, register, ssoComplete, and refreshSession. That's ~60 lines of copied logic. A bug fix in one location won't be applied to the others.

// Duplicated in lines ~228-253, ~299-325, ~455-490, ~638-664
if (RoboSystemsExtensions) {
  const extensions = new RoboSystemsExtensions({ ... })
  if (typeof window !== 'undefined') {
    ;(window as any).__roboSystemsExtensions = extensions
  }
}
if (setSDKExtensionsConfig) {
  setSDKExtensionsConfig({ ... })
}

Recommendation: Extract to private updateExtensionsToken(token: string): void. Fix this →


Major Issues

3. methodName parameter in wrapWithAuthAndErrorHandling is dead code

// src/lib/core/auth-core/client.ts:150-153
const wrapWithAuthAndErrorHandling = (
  originalMethod: Function | undefined,
  methodName: string  // declared but never referenced in the function body
) => {

The methodName string is accepted but never used — not in logs, not in error messages. Either use it for richer error context or remove it. Fix this →

4. Fragile 401 detection via string matching

// src/lib/core/auth-core/client.ts:176-179
error?.status === 401 ||
error?.response?.status === 401 ||
error?.message?.toLowerCase().includes('unauthorized') ||
error?.message?.toLowerCase().includes('401')

Any error whose message happens to contain "unauthorized" (e.g., a rate-limit response body, a validation error with that word) will silently clear the user's session and throw TokenExpiredError. The numeric status checks are sufficient; the string checks add false-positive risk.

5. Dead code: (window as any).__roboSystemsExtensions

// src/lib/core/auth-core/client.ts:237-239
if (typeof window !== 'undefined') {
  ;(window as any).__roboSystemsExtensions = extensions
}

This stores a RoboSystemsExtensions instance as a raw any on window. If it's consumed somewhere, the consumer should be importing from a shared module — not reading from a global. If nothing reads it, it should be removed. A quick codebase search turned up no consumer.

6. Unnecessary network call during logout

// src/lib/core/auth-core/client.ts:362-370
// "verify logout" — result is silently discarded
try {
  this.clearAuthCache()
  await this.getCurrentUser()  // network call
} catch (verifyError) {
  // This is expected
}

This adds a network round-trip on every logout whose result is always thrown away. clearAuthCache() already ensures the next getCurrentUser() call from the app will get a fresh (401) result. The verification block can be removed entirely.


Minor Issues

7. require() in an async method

// src/lib/core/auth-core/client.ts:114
const { getToken, getValidToken } = require('./token-storage')

This uses CommonJS require() inside an async method that already uses import() elsewhere in the same file (lines 88, 184, 358). While it works, it's inconsistent — const { getToken, getValidToken } = await import('./token-storage') would be the ESM-consistent approach.

8. as any suppressing TypeScript errors

// src/lib/core/auth-core/client.ts:702, 852
body: { email } as any,
// ...
await (resendVerificationEmail as any)({ ... })

These as any casts suggest the SDK's TypeScript types don't precisely match the actual call signature. This is worth an upstream issue to the @robosystems/client SDK team, or properly-typed wrapper functions here.

9. Silent fallback in StructureSidebar.itemToSelected

// src/app/(app)/ledger/close/components/StructureSidebar.tsx:49-51
default:
  return { type: 'period_close' }

An unknown itemType from the backend silently falls through to period_close. At minimum this should log a warning so future item types don't disappear silently.

10. formatCurrency(0) inconsistency between the two trial balance views

  • ledger/close/components/TrialBalancePanel.tsx:49 → returns '–' for zero
  • ledger/trial-balance/content.tsx:84 → returns '$0.00' for zero

Users who navigate between the two views will see different zero representations. The utility function should be shared and behavior consistent.


What's Well Done

  • EntitySelectorDropdown refactor: The new Promise.allSettled loading pattern is correct and the entity validation/sync logic is clean. The ESLint disable comment at line 100 is well-documented.
  • remark-gfm integration in SearchContent: Clean implementation. Custom table renderers with overflow-x scroll are a good touch for financial tables.
  • Closing Book sidebar architecture: StructureSidebar / SelectedItem type union is a clean discriminated union pattern, and CloseContent delegates well to sub-panels.
  • Test coverage: The EntitySelectorDropdown tests cover all meaningful paths including API failures. Mocking extensions.ledger.getEntity at the right level (not the underlying SDK) is correct.
  • getValidToken token provider callback: The approach of registering a tokenProvider callback rather than seeding a static token is the right design to handle rotation without cache invalidation.

Summary

The core concern is in auth-core/client.ts — specifically the global singleton mutation (#1) and the duplicated token-update pattern (#2). Both should be addressed before merge. Items #3#6 are medium-priority cleanup. Items #7#10 are low-priority polish.
| Branch: feature/graphql-client-overhaul

…by introducing a method to synchronize the auth token with the extensions configuration. This change enhances token management during authentication processes, ensuring that React hooks remain authenticated across transitions.
…by introducing a method to synchronize the auth token with the extensions configuration. This change enhances token management during authentication processes, ensuring that React hooks remain authenticated across transitions.
…06d0d8'

git-subtree-dir: src/lib/core
git-subtree-mainline: 7a42350
git-subtree-split: 4f902ba
…se structure. Updated field names from snake_case to camelCase for consistency and to prevent silent failures in item selection.
@jfrench9 jfrench9 merged commit e85cf7e into main Apr 15, 2026
3 checks passed
@jfrench9 jfrench9 deleted the feature/graphql-client-overhaul branch April 15, 2026 02:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant