Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Illiar/feat/app state #2796

Merged
merged 22 commits into from
Oct 30, 2024
Merged

Illiar/feat/app state #2796

merged 22 commits into from
Oct 30, 2024

Conversation

chesterkmr
Copy link
Collaborator

@chesterkmr chesterkmr commented Oct 23, 2024

Summary by CodeRabbit

  • New Features

    • Introduced a new method in CollectionFlowService to retrieve workflow runtime context.
    • Added a method for document OCR processing in WorkflowService.
    • Enhanced the CollectionFlowManager for improved state management and context handling.
    • Added a new function to retrieve steps in order from the UI definition.
  • Improvements

    • Updated error handling and validation in various controllers and services.
    • Enhanced context retrieval process in CollectionFlowController.
    • Improved handling of company information within the JSONForm component.
    • Updated the process tracker to focus on collection flow progress.
    • Updated API plugin configurations to reflect new context structure.
    • Enhanced type safety in the usePageErrors function.
    • Enhanced the logic for step retrieval and sorting in the process tracker.
  • Refactor

    • Streamlined context management and configuration handling across multiple components.
    • Renamed and restructured properties in workflow schemas for better alignment with data formats.
  • Tests

    • Added comprehensive unit tests for CollectionFlowManager and ConfigHelper classes to ensure functionality and error handling.

Copy link

changeset-bot bot commented Oct 23, 2024

⚠️ No Changeset found

Latest commit: acdf6f3

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

Copy link
Contributor

coderabbitai bot commented Oct 23, 2024

Caution

Review failed

The pull request is closed.

Walkthrough

The pull request introduces several modifications across various components and services related to state management and context handling within the application. Key changes include updates to the StateManager component for state initialization, alterations to method signatures in action handlers to specify context types, and enhancements to the CollectionFlowManager for improved context management. Additionally, new schemas and validation mechanisms are introduced, alongside adjustments in the CollectionFlowService to streamline context retrieval. Overall, the changes aim to enhance type safety, clarity, and functionality in state management processes.

Changes

File Change Summary
apps/kyb-app/src/components/organisms/DynamicUI/StateManager/StateManager.tsx Updated initialization of initialMachineState to use initialContext?.collectionFlow?.state?.uiState.
apps/kyb-app/src/components/organisms/DynamicUI/StateManager/components/ActionsHandler/action-handlers/action-handler.abstract.ts Removed generic type parameter from run method, updated context parameter type to CollectionFlowContext, and changed return type to Promise<CollectionFlowContext>. Added import for CollectionFlowContext.
apps/kyb-app/src/components/organisms/DynamicUI/StateManager/components/ActionsHandler/action-handlers/event-dispatcher.handler.ts Updated run method signature to use CollectionFlowContext instead of generic type.
apps/kyb-app/src/components/organisms/DynamicUI/StateManager/components/ActionsHandler/action-handlers/plugin-runner.handler.ts Updated run method signature to use CollectionFlowContext instead of generic type.
apps/kyb-app/src/components/organisms/DynamicUI/StateManager/components/ActionsHandler/action-handlers/value-apply/value-apply.handler.ts Changed return type of run method to ensure it returns a promise consistently.
apps/kyb-app/src/components/organisms/DynamicUI/StateManager/hooks/useMachineLogic/useMachineLogic.ts Updated setContext and getContext methods in StateMachineAPI to use CollectionFlowContext instead of AnyObject.
apps/kyb-app/src/components/organisms/DynamicUI/StateManager/hooks/useStateLogic/useStateLogic.ts Removed imports related to customer data, updated setContext parameter type to CollectionFlowContext.
apps/kyb-app/src/components/organisms/DynamicUI/StateManager/types.ts Changed payload property type in StateManagerContext from AnyObject to CollectionFlowContext.
apps/kyb-app/src/components/organisms/DynamicUI/hooks/useUIStateLogic/hooks/useUIElementsStateLogic/hooks/useUIElementToolsLogic/useUIElementToolsLogic.ts Added imports for context management and updated dependencies in setElementCompleted.
apps/kyb-app/src/components/organisms/UIRenderer/elements/JSONForm/JSONForm.tsx Enhanced data retrieval for companyName and customerCompany to ensure robustness.
apps/kyb-app/src/domains/collection-flow/collection-flow.api.ts Updated fetchFlowContext return type to Promise<CollectionFlowContext> and simplified JSON response structure.
apps/kyb-app/src/domains/collection-flow/types/flow-context.types.ts Replaced CollectionFlowContext definition with DefaultContextSchema. Removed FlowConfig interface.
apps/kyb-app/src/domains/collection-flow/types/index.ts Updated UISchemaConfig to extend CollectionFlowConfig.
packages/common/src/utils/collection-flow-manager/collection-flow-manager.ts Introduced CollectionFlowManager class for managing collection flow context and state.
packages/common/src/utils/collection-flow-manager/helpers/config-helper.ts Introduced ConfigHelper class for managing configuration settings within DefaultContextSchema.
packages/common/src/utils/collection-flow-manager/helpers/state-helper.ts Introduced StateHelper class for managing state of a collection flow context.
services/workflows-service/src/collection-flow/collection-flow.service.ts Added getCollectionFlowContext method to retrieve workflow runtime data context.
services/workflows-service/src/collection-flow/controllers/collection-flow.controller.ts Updated getContext method to use getCollectionFlowContext for context retrieval.
services/workflows-service/src/workflow/workflow.service.ts Restructured createOrUpdateWorkflowRuntime method to initialize CollectionFlowManager and added runOCROnDocument method for document processing.
packages/common/src/consts/index.ts Added CollectionFlowStates constant and TCollectionFlowState type for structured state management.
packages/common/package.json Updated dependencies for the @ballerine/common package.
services/workflows-service/package.json Modified start:debug script to remove --watch flag.

Possibly related PRs

  • Common version release #2447: The changes in this PR involve updates to dependencies, including @ballerine/common, which is relevant to the context of the main PR's modifications to state management and initialization logic.
  • Added custom data to context zod schema #2570: This PR introduces a new optional field to the BaseWorkflowByIdSchema, which may relate to the changes in state management and context handling in the main PR.
  • Added UnifiedApiResponse NOT_AVAILABLE #2586: This PR focuses on dependency updates, including @ballerine/common, which is directly relevant to the changes in the main PR that involve state management and context initialization.
  • Update packages version #2628: The updates in this PR include dependency management, particularly for @ballerine/common, which aligns with the main PR's focus on state management and initialization logic.
  • Changed tsconfig for UI package #2655: This PR updates the TypeScript configuration for the UI package, which may indirectly relate to the changes in state management and context handling in the main PR.
  • Fix merchant screening headers #2667: The updates in this PR include dependency updates, particularly for @ballerine/common, which is relevant to the changes in the main PR regarding state management.
  • feature/refresh_backoffice_packages #2704: This PR involves updates to dependencies, including @ballerine/ui, which may relate to the UI aspects of the changes in the main PR.
  • wf service version bump #2710: This PR focuses on version updates for dependencies, including @ballerine/common, which is relevant to the context of the main PR's modifications.
  • Version bump #2722: This PR includes updates to dependencies, particularly @ballerine/common, which is relevant to the changes in the main PR.
  • feat: added format fallback to date input in ui package #2736: This PR introduces a fallback feature for date inputs in the UI package, which may relate to the overall UI improvements in the main PR.
  • fix: fixed textarea placeholder & bump #2761: This PR includes updates to the @ballerine/ui dependency, which is relevant to the UI aspects of the changes in the main PR.
  • fix: reworked process tracking #2765: This PR modifies the TransitionListener component, which is directly related to the changes in the main PR regarding state management and transitions.
  • Additional swagger documentations #2767: This PR enhances logging and error handling in the workflow service, which may relate to the overall improvements in state management and error handling in the main PR.
  • fixed ubo schema #2778: This PR updates the BaseWorkflowByIdSchema, which is relevant to the changes in state management and context handling in the main PR.
  • fixed match plugin #2781: This PR includes updates to dependencies, particularly @ballerine/common, which is relevant to the changes in the main PR.
  • Illiar/kyb/UI fixes #2784: This PR includes updates to the @ballerine/ui dependency, which may relate to the UI aspects of the changes in the main PR.
  • fix: fixed sync of last step progress & fixed context overrides #2788: This PR focuses on fixing the sync of last step progress, which is directly related to the changes in state management in the main PR.

Suggested reviewers

  • Omri-Levy

🐰 In the meadow, changes bloom,
New flows and states, dispelling gloom.
With context clear and types so bright,
Our code now dances, a joyful sight!
Let's hop along, embrace the cheer,
For every change brings us near! 🌼


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 33

🧹 Outside diff range and nitpick comments (38)
packages/common/src/utils/collection-flow-manager/schemas/config-schema.ts (2)

23-23: Add TSDoc comment for the exported type.

Consider adding documentation to improve code maintainability:

+/**
+ * Configuration type for the Collection Flow Manager.
+ * This type is derived from the CollectionFlowManagerConfigSchema and used for type checking.
+ */
 export type CollectionFlowManagerConfig = Static<typeof CollectionFlowManagerConfigSchema>;

1-23: Consider enhancing schema extensibility and reusability.

To improve the architecture:

  1. Consider extracting common schema patterns into shared utilities
  2. Add schema versioning support for future compatibility
  3. Consider implementing a schema registry pattern for managing multiple related schemas
  4. Add schema validation error handling utilities

This will make the schema system more maintainable and extensible as the collection flow system grows.

packages/common/src/index.ts (2)

Line range hint 4-34: Consider grouping related utility exports together.

The utility exports could be better organized by grouping related functions together. For example:

  • Type checking utilities: isFunction, isInstanceOfFunction, isType, etc.
  • String/URL validation: checkIsUrl, checkIsIsoDate
  • Error handling: isErrorWithCode, isErrorWithMessage

Consider reorganizing the exports alphabetically within their functional groups for better maintainability.


Line range hint 1-64: Consider splitting exports into separate barrel files.

The file is handling multiple concerns (utils, types, schemas, etc.). Consider splitting these into separate barrel files (e.g., utils/index.ts, types/index.ts) for better organization and maintenance.

This would:

  • Improve code organization
  • Make it easier to manage dependencies
  • Reduce the risk of circular dependencies
  • Make it clearer what's being exported from each module
packages/common/src/schemas/documents/collection-flow-context-schema.ts (1)

4-11: Consider improving enum naming consistency and documentation.

The enum values are descriptive, but there are a few suggestions for improvement:

  1. 'inprogress' should be 'inProgress' to follow camelCase convention
  2. Consider adding JSDoc comments to document:
    • The purpose of each state
    • Valid state transitions
    • When each state is triggered

Here's the suggested improvement:

 export enum CollectionFlowStateEnum {
   pending = 'pending',
-  inprogress = 'inprogress',
+  inProgress = 'inProgress',
   approved = 'approved',
   rejected = 'rejected',
   failed = 'failed',
   revision = 'revision',
 }
packages/common/src/utils/collection-flow-manager/helpers/config-helper.ts (1)

1-43: Consider architectural improvements for better maintainability.

  1. Consider implementing a logging interface that can be injected:
interface Logger {
  log(message: string, ...args: any[]): void;
}
  1. Consider implementing an observer pattern or integrating with a state management system to properly track configuration changes.

  2. Consider adding a schema validation library like Zod or Joi for runtime type checking of configuration values.

Would you like assistance in implementing any of these architectural improvements?

apps/kyb-app/src/components/organisms/DynamicUI/hooks/useUIStateLogic/hooks/useUIElementsStateLogic/hooks/useUIElementToolsLogic/useUIElementToolsLogic.ts (3)

9-10: Consider adding type annotations for better type safety.

The destructured values from useStateManagerContext and the payloadRef would benefit from explicit type annotations.

-  const { payload, stateApi } = useStateManagerContext();
-  const payloadRef = useRefValue(payload);
+  const { payload, stateApi } = useStateManagerContext<CollectionFlowContext>();
+  const payloadRef = useRefValue<typeof payload>(payload);

Line range hint 24-30: Verify the necessity of new dependencies.

The setElementCompleted callback has payloadRef and stateApi in its dependency array, but these values don't appear to be used within the function body. This could indicate:

  1. Missing functionality that should use these values
  2. Unnecessary dependencies that could trigger extra re-renders

Either:

  1. Add the missing functionality that uses these dependencies, or
  2. Remove them from the dependency array if they're not needed:
     },
-    [elementsStateRef, payloadRef, stateApi, setUIElementState],
+    [elementsStateRef, setUIElementState],

Line range hint 6-41: Consider optimizing state updates and ref usage.

The hook uses multiple refs and state updates which could be optimized:

  1. elementsStateRef could potentially be replaced with useRefValue
  2. State updates could be batched if multiple elements are being updated

Consider this optimization:

 export const useUIElementToolsLogic = (elementId: string) => {
   const { helpers, state } = useDynamicUIContext();
   const { setUIElementState } = helpers;
   const { payload, stateApi } = useStateManagerContext();
   const payloadRef = useRefValue(payload);
-  const elementsStateRef = useRef(state.elements);
+  const elementsStateRef = useRefValue(state.elements);

-  useEffect(() => {
-    elementsStateRef.current = state.elements;
-  }, [state.elements]);

   // ... rest of the code
apps/kyb-app/src/components/organisms/DynamicUI/StateManager/StateManager.tsx (1)

23-23: Document the state structure change.

The change in state structure from flowConfig.appState to collectionFlow.state.uiState represents a significant architectural change that should be documented.

Add a comment explaining the state structure:

+      // State is now managed through CollectionFlow context instead of flowConfig
+      // to provide better integration with collection-specific state management
       state: initialContext?.collectionFlow?.state?.uiState,
packages/common/src/utils/collection-flow-manager/helpers/config-helper.unit.test.ts (4)

5-12: Consider strengthening the basic instantiation test.

While the test confirms the helper is defined, it could be more robust by:

  1. Verifying the initial state of properties
  2. Using a proper type factory instead of type assertion

Consider this improvement:

test('should be defined with initial state', () => {
  const context: CollectionFlowContextSchema = {
    collectionFlow: { config: {} }
  };
  const configHelper = new ConfigHelper(context);

  expect(configHelper).toBeDefined();
  expect(configHelper.apiUrl).toBeUndefined();
  expect(configHelper.tokenId).toBeUndefined();
});

14-26: Enhance apiUrl test coverage with edge cases.

The current test verifies basic get/set functionality, but consider adding tests for:

  • Invalid URL formats
  • Empty string or undefined values
  • URL normalization (if applicable)

Example additional test cases:

test('should handle invalid apiUrl values', () => {
  const configHelper = new ConfigHelper({
    collectionFlow: { config: {} }
  } as CollectionFlowContextSchema);

  // Test empty string
  configHelper.apiUrl = '';
  expect(configHelper.apiUrl).toBe('');

  // Test undefined
  configHelper.apiUrl = undefined;
  expect(configHelper.apiUrl).toBeUndefined();

  // Test invalid URL (if validation is required)
  configHelper.apiUrl = 'not-a-url';
  // Assert expected behavior
});

28-40: Add validation tests for tokenId.

Consider adding tests to verify:

  • Token format validation (if specific format is required)
  • Empty string or undefined handling
  • Token length constraints

Example additional test cases:

test('should handle edge cases for tokenId', () => {
  const configHelper = new ConfigHelper({
    collectionFlow: { config: {} }
  } as CollectionFlowContextSchema);

  // Test empty string
  configHelper.tokenId = '';
  expect(configHelper.tokenId).toBe('');

  // Test undefined
  configHelper.tokenId = undefined;
  expect(configHelper.tokenId).toBeUndefined();

  // Test token format (if validation is required)
  const validToken = '1234567890';
  configHelper.tokenId = validToken;
  expect(configHelper.tokenId).toBe(validToken);
});

42-62: Add tests for partial config override scenarios.

The current test verifies a complete override, but consider testing:

  • Partial overrides (only apiUrl or only tokenId)
  • Override with undefined values
  • Multiple consecutive overrides

Example additional test:

test('should handle partial override', () => {
  const ctx = {
    collectionFlow: {
      config: {
        apiUrl: 'https://api.example.com',
        tokenId: '1234567890'
      }
    }
  } as CollectionFlowContextSchema;

  const configHelper = new ConfigHelper(ctx);

  // Test partial override
  configHelper.override({ apiUrl: 'https://new-api.example.com' });
  expect(configHelper.apiUrl).toBe('https://new-api.example.com');
  expect(configHelper.tokenId).toBe('1234567890');

  // Test undefined values
  configHelper.override({ tokenId: undefined });
  expect(configHelper.tokenId).toBeUndefined();
});
apps/kyb-app/src/components/organisms/DynamicUI/StateManager/hooks/useMachineLogic/useMachineLogic.ts (1)

Line range hint 31-56: Consider updating context type casting in sendEvent method

The sendEvent method still uses AnyObject for context casting, while the rest of the file has been updated to use CollectionFlowContext. This inconsistency might lead to type-related issues.

Consider updating the type casting:

- const context = machine.getSnapshot().context as AnyObject;
+ const context = machine.getSnapshot().context as CollectionFlowContext;

  machine.overrideContext({
    ...context,
    flowConfig: {
-     ...(context.flowConfig as AnyObject),
+     ...(context.flowConfig),
      appState: nextStateName,
    },
  });
apps/kyb-app/src/components/organisms/DynamicUI/StateManager/components/ActionsHandler/action-handlers/value-apply/value-apply.handler.ts (2)

Line range hint 16-42: Consider revising the state management approach.

The current implementation both mutates state through api.setContext() and returns a context, which could lead to race conditions in concurrent scenarios. Consider either:

  1. Making the handler pure by returning the new context without calling setContext
  2. Making the handler responsible for state management only, returning void

Example of approach #1:

async run<TContext>(
  _: TContext,
  action: Action<ValueApplyParams>,
  api: StateMachineAPI,
): Promise<TContext> {
  const context = structuredClone(api.getContext());

  action?.params?.values?.forEach(params => {
    // ... existing logic ...
  });

  return Promise.resolve(context);
}

Example of approach #2:

async run<TContext>(
  _: TContext,
  action: Action<ValueApplyParams>,
  api: StateMachineAPI,
): Promise<void> {
  const context = structuredClone(api.getContext());

  action?.params?.values?.forEach(params => {
    // ... existing logic ...
  });

  api.setContext(context);
  return Promise.resolve();
}

Based on the results, I can now generate the final response as we have clear evidence about the context types being used in the codebase.

The TContext generic type in value-apply handler should be replaced with CollectionFlowContext

The codebase shows that:

  • The entire application uses CollectionFlowContext type (imported from @/domains/collection-flow/types/flow-context.types)
  • Other action handlers like EventDispatcherHandler and PluginRunnerHandler are already using CollectionFlowContext
  • The value-apply.handler.ts is the only handler still using the generic TContext type

The handler's signature should be updated to:

async run(
  _: CollectionFlowContext,
  action: Action<ValueApplyParams>,
  api: StateMachineAPI,
): Promise<CollectionFlowContext>
🔗 Analysis chain

Line range hint 16-42: Verify the impact of context type changes across the codebase.

Given the codebase-wide migration from generic TContext to CollectionFlowContext, ensure that this handler's generic type parameter aligns with the new type system.


Let me analyze the results and generate additional verification scripts to check for the specific context type being used in the state machine and related components.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the consistency of context type usage across action handlers

# Test 1: Check other action handlers' run method signatures
echo "Checking action handler implementations..."
ast-grep --pattern 'class $_ implements ActionHandler {
  $$$
  run<$_>($_: $_, $_: Action<$_>, $_: $_): Promise<$_> {
    $$$
  }
}'

# Test 2: Check for any remaining generic TContext usage
echo "Checking for generic TContext usage..."
rg "TContext" --type ts

Length of output: 11677


Script:

#!/bin/bash
# Check for CollectionFlowContext usage and its definition
echo "Checking CollectionFlowContext usage..."
rg "CollectionFlowContext" --type ts -A 2

# Check for ActionHandler interface definition to understand the expected context type
echo "Checking ActionHandler interface definition..."
ast-grep --pattern 'interface ActionHandler {
  $$$
}'

# Check other value-apply related files for context type usage
echo "Checking value-apply related files..."
fd "value-apply" --type f --exec rg "TContext|CollectionFlowContext" --type ts {}

Length of output: 30989

apps/kyb-app/src/components/organisms/DynamicUI/StateManager/hooks/useStateLogic/useStateLogic.ts (2)

Line range hint 43-56: Fix potential race condition in context updates

The contextRef update inside setState could lead to race conditions if React batches multiple state updates. Consider updating the ref before calling setState:

 const setContext = useCallback(
   (newContext: CollectionFlowContext) => {
     const newCtx = { ...newContext };
     machineApi.setContext(newCtx);
+    const nextState = { payload: newCtx, machineState: prev.machineState, isPluginLoading: prev.isPluginLoading };
+    contextRef.current = nextState;
 
     setState(prev => {
-      const nextState = { ...prev, payload: newCtx };
-      contextRef.current = nextState;
-
       return nextState;
     });
 
     return newCtx;
   },
   [machineApi, contextRef],
 );

Line range hint 60-73: Standardize error handling and loading state management

The invokePlugin function lacks error handling and uses a different loading state approach compared to sendEvent. Consider standardizing the implementation:

 const invokePlugin = useCallback(
   async (pluginName: string) => {
+    helpers.setLoading(true);
     setState(prev => ({ ...prev, isPluginLoading: true }));
 
-    await machineApi.invokePlugin(pluginName);
+    try {
+      await machineApi.invokePlugin(pluginName);
 
-    setState({
-      machineState: machineApi.getState(),
-      payload: machineApi.getContext(),
-      isPluginLoading: false,
-    });
+      setState({
+        machineState: machineApi.getState(),
+        payload: machineApi.getContext(),
+        isPluginLoading: false,
+      });
+    } catch (error) {
+      console.error(
+        `Error occurred while invoking plugin ${pluginName}`,
+        isErrorWithMessage(error) ? error.message : error,
+      );
+      throw error;
+    } finally {
+      helpers.setLoading(false);
+      setState(prev => ({ ...prev, isPluginLoading: false }));
+    }
   },
-  [machineApi],
+  [machineApi, helpers],
 );
packages/common/src/utils/collection-flow-manager/helpers/state-helper.unit.test.ts (4)

15-31: Enhance error handling test coverage.

While the basic error cases are covered, consider adding tests for:

  • Null/undefined collectionFlow
  • Null/undefined state within collectionFlow
  • Invalid state structure
describe('state helper will throw', () => {
  test('if collectionFlow is null', () => {
    expect(() => new StateHelper({ collectionFlow: null } as CollectionFlowContextSchema)).toThrow();
  });

  test('if state is null', () => {
    expect(() => new StateHelper({ collectionFlow: { state: null } } as CollectionFlowContextSchema)).toThrow();
  });
});

32-53: Improve test readability and type handling.

The test cases are good but could benefit from:

  1. More descriptive test names that explain the expected behavior
  2. A shared test fixture to reduce type assertion complexity
-    test('if uiState is in progress', () => {
+    test('should allow updating uiState when valid steps exist in progress', () => {

Also, consider extracting the test context into a shared fixture:

const createTestContext = (progress: Record<string, { isCompleted: boolean }>) => ({
  collectionFlow: {
    state: {
      uiState: 'step1',
      progress
    }
  }
} as CollectionFlowContextSchema);

54-81: Add comprehensive state validation tests.

Consider adding tests for:

  1. Each possible enum value
  2. State transitions between different enum values
  3. State persistence after updates
test.each(Object.values(CollectionFlowStateEnum))('should accept valid state: %s', (state) => {
  const stateHelper = new StateHelper({
    collectionFlow: { state: {} }
  } as CollectionFlowContextSchema);
  
  stateHelper.collectionFlowState = state;
  expect(stateHelper.collectionFlowState).toBe(state);
});

82-97: Expand override method test coverage.

The current test only covers a basic case. Consider adding tests for:

  1. Partial overrides (only uiState or only collectionFlowState)
  2. Invalid override values
  3. Multiple consecutive overrides
describe('override', () => {
  test('should allow partial override of uiState only', () => {
    // Test implementation
  });
  
  test('should allow partial override of collectionFlowState only', () => {
    // Test implementation
  });
  
  test('should maintain consistency across multiple overrides', () => {
    // Test implementation
  });
});
apps/kyb-app/src/components/organisms/UIRenderer/elements/JSONForm/JSONForm.tsx (1)

Line range hint 77-85: Address technical debt in form data transformation logic.

The TODO comment indicates that this logic should be moved to jmespath. Additionally, the current implementation:

  1. Mutates the payload directly using set
  2. Contains multiple type assertions and potential type safety issues
  3. Handles business logic inside a UI component

Consider:

  1. Moving this transformation logic to a dedicated service/helper
  2. Using jmespath for consistent data access patterns
  3. Implementing proper type guards instead of type assertions

Would you like help creating a separate service for handling these transformations?

services/workflows-service/src/collection-flow/controllers/collection-flow.controller.ts (3)

63-63: LGTM! Consider adding error handling.

The change improves the architecture by delegating context retrieval to the CollectionFlowService, which aligns with the single responsibility principle and the PR's goal of enhancing state management.

Consider adding error handling to gracefully handle cases where context retrieval fails:

 @common.Get('/context')
 async getContext(@TokenScope() tokenScope: ITokenScope) {
-  return this.service.getCollectionFlowContext(tokenScope);
+  try {
+    return await this.service.getCollectionFlowContext(tokenScope);
+  } catch (error) {
+    throw new common.InternalServerErrorException('Failed to retrieve collection flow context');
+  }
 }

Line range hint 91-105: Remove or implement the commented-out method.

Since this PR is marked as WIP, please either:

  1. Implement the updateFlowConfiguration method if it's needed
  2. Remove the commented code if it's no longer required

Line range hint 146-190: Consider abstracting common event handling logic.

Multiple methods (updateContextById, finishFlow, resubmitFlow) share similar event handling patterns using workflowService.event(). Consider creating a helper method to reduce code duplication:

private async emitWorkflowEvent(
  tokenScope: ITokenScope,
  eventName: string,
  payload?: Record<string, unknown>,
) {
  return this.workflowService.event(
    {
      id: tokenScope.workflowRuntimeDataId,
      name: eventName,
      payload,
    },
    [tokenScope.projectId],
    tokenScope.projectId,
  );
}

This would simplify the event-emitting methods:

@common.Post('/send-event')
async finishFlow(@TokenScope() tokenScope: ITokenScope, @common.Body() body: FinishFlowDto) {
  return this.emitWorkflowEvent(tokenScope, body.eventName);
}

@common.Post('resubmit')
async resubmitFlow(@TokenScope() tokenScope: ITokenScope) {
  return this.emitWorkflowEvent(tokenScope, 'RESUBMITTED');
}
packages/common/src/utils/collection-flow-manager/collection-flow-manager.unit.test.ts (3)

12-16: Enhance invalid config test cases.

The current test only checks one generic invalid case. Consider adding specific test cases for different types of invalid configurations to better document the requirements.

// Example additional test cases:
it('fails with missing apiUrl', () => {
  expect(() => new CollectionFlowManager({} as CollectionFlowContextSchema, {
    tokenId: '1234',
    steps: []
  } as any)).toThrow('Invalid collection flow manager config.');
});

it('fails with missing steps', () => {
  expect(() => new CollectionFlowManager({} as CollectionFlowContextSchema, {
    apiUrl: 'https://api.example.com',
    tokenId: '1234'
  } as any)).toThrow('Invalid collection flow manager config.');
});

32-40: Add edge cases for flow state tests.

Consider adding test cases for:

  • Flow with undefined state
  • Flow with empty state object
  • Flow with invalid uiState value
test('when state is undefined', () => {
  const manager = new CollectionFlowManager({
    collectionFlow: {}
  } as CollectionFlowContextSchema);
  expect(manager.isStarted()).toBe(false);
});

test('when uiState is invalid', () => {
  const manager = new CollectionFlowManager({
    collectionFlow: { state: { uiState: 'invalid_step' } }
  } as CollectionFlowContextSchema);
  expect(() => manager.isStarted()).toThrow();
});

42-75: Enhance context validation in update tests.

The current tests verify basic properties but should also validate:

  • Complete state structure
  • Steps initialization
  • Default values

Add these assertions to the existing test:

expect(context.collectionFlow?.state).toEqual({
  uiState: undefined,
  progress: {
    step1: {
      isCompleted: false,
    }
  }
});
expect(context.collectionFlow?.config?.steps).toHaveLength(1);
packages/common/src/utils/collection-flow-manager/helpers/state-helper.ts (4)

22-23: Implement a proper logging mechanism instead of console.log

Using console.log is not recommended for production code as it lacks control over log levels and outputs. Consider using a logging library like winston or bunyan to provide better logging practices.

Apply this diff to replace console.log with a logging utility:

- console.log(`UI State transition from ${this.uiState} to ${uiState}`);
+ logger.info(`UI State transition from ${this.uiState} to ${uiState}`);

Ensure you import and configure the logger at the beginning of your file:

+ import logger from 'path-to-your-logger';

39-41: Replace console.log with a structured logging solution

Consistent with previous logging suggestions, replace console.log with a logging library to handle different log levels and outputs effectively.

Apply this diff to update the logging statement:

- console.log(
+ logger.info(
     `Collection flow state transition from ${this.collectionFlowState} to ${collectionFlowState}`,
   );

67-68: Utilize a logging library instead of console.log statements

For consistent logging, replace console.log with your chosen logging utility.

- console.log(`Step: ${step} isCompleted: ${isCompleted}`);
+ logger.info(`Step: ${step} isCompleted: ${isCompleted}`);

80-80: Switch to a logging framework for state override notifications

As with previous instances, replace console.log with your logging utility to maintain consistent logging practices.

- console.log('StateHelper, context override', this.context.collectionFlow!.state);
+ logger.info('StateHelper, context override', this.context.collectionFlow?.state);
apps/kyb-app/src/pages/CollectionFlow/CollectionFlow.tsx (1)

133-135: Replace console.log statements with a proper logging mechanism

Using console.log in production code is discouraged as it may expose sensitive information and is not suitable for error tracking or monitoring.

Consider using a dedicated logging library or framework that allows you to manage log levels and outputs appropriately.

services/workflows-service/src/workflow/workflow.service.ts (3)

Line range hint 2099-2112: Clarify Error Messages for Missing ballerineFileId

In the documentFetchPagesContentPromise, when ballerineFileId is missing, the thrown error message is "Cannot run document OCR on document without pages," which may not accurately reflect the issue. Provide a more specific error message to aid in debugging and improve clarity.

Apply this diff to improve the error message:

 if (!ballerineFileId) {
-    throw new BadRequestException('Cannot run document OCR on document without pages');
+    throw new BadRequestException('Document page is missing a valid ballerineFileId');
 }

Line range hint 2086-2145: Ensure Robust Exception Handling in runOCROnDocument Method

The runOCROnDocument method performs multiple asynchronous operations and relies on external services. Confirm that all potential exceptions are properly handled, and consider adding try-catch blocks where necessary to prevent unhandled exceptions and to provide informative error responses.


1469-1487: Validate uiSchema.elements Before Initializing CollectionFlowManager

Ensure that uiSchema.elements is properly defined and valid before using it to initialize CollectionFlowManager. Adding validation checks can prevent potential runtime errors if uiSchema.elements is undefined or malformed.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 177b19f and cb8ee44.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (34)
  • apps/kyb-app/src/components/organisms/DynamicUI/StateManager/StateManager.tsx (1 hunks)
  • apps/kyb-app/src/components/organisms/DynamicUI/StateManager/components/ActionsHandler/action-handlers/action-handler.abstract.ts (1 hunks)
  • apps/kyb-app/src/components/organisms/DynamicUI/StateManager/components/ActionsHandler/action-handlers/event-dispatcher.handler.ts (2 hunks)
  • apps/kyb-app/src/components/organisms/DynamicUI/StateManager/components/ActionsHandler/action-handlers/plugin-runner.handler.ts (2 hunks)
  • apps/kyb-app/src/components/organisms/DynamicUI/StateManager/components/ActionsHandler/action-handlers/value-apply/value-apply.handler.ts (1 hunks)
  • apps/kyb-app/src/components/organisms/DynamicUI/StateManager/hooks/useMachineLogic/useMachineLogic.ts (3 hunks)
  • apps/kyb-app/src/components/organisms/DynamicUI/StateManager/hooks/useStateLogic/useStateLogic.ts (1 hunks)
  • apps/kyb-app/src/components/organisms/DynamicUI/StateManager/types.ts (1 hunks)
  • apps/kyb-app/src/components/organisms/DynamicUI/hooks/useUIStateLogic/hooks/useUIElementsStateLogic/hooks/useUIElementToolsLogic/useUIElementToolsLogic.ts (2 hunks)
  • apps/kyb-app/src/components/organisms/UIRenderer/elements/JSONForm/JSONForm.tsx (1 hunks)
  • apps/kyb-app/src/domains/collection-flow/collection-flow.api.ts (2 hunks)
  • apps/kyb-app/src/domains/collection-flow/types/flow-context.types.ts (1 hunks)
  • apps/kyb-app/src/domains/collection-flow/types/index.ts (2 hunks)
  • apps/kyb-app/src/helpers/prepareInitialUIState.ts (2 hunks)
  • apps/kyb-app/src/pages/CollectionFlow/CollectionFlow.tsx (3 hunks)
  • packages/common/package.json (2 hunks)
  • packages/common/rollup.config.ts (5 hunks)
  • packages/common/src/index.ts (2 hunks)
  • packages/common/src/schemas/documents/collection-flow-context-schema.ts (1 hunks)
  • packages/common/src/schemas/documents/default-context-schema.ts (1 hunks)
  • packages/common/src/schemas/index.ts (2 hunks)
  • packages/common/src/utils/collection-flow-manager/collection-flow-manager.ts (1 hunks)
  • packages/common/src/utils/collection-flow-manager/collection-flow-manager.unit.test.ts (1 hunks)
  • packages/common/src/utils/collection-flow-manager/helpers/config-helper.ts (1 hunks)
  • packages/common/src/utils/collection-flow-manager/helpers/config-helper.unit.test.ts (1 hunks)
  • packages/common/src/utils/collection-flow-manager/helpers/state-helper.ts (1 hunks)
  • packages/common/src/utils/collection-flow-manager/helpers/state-helper.unit.test.ts (1 hunks)
  • packages/common/src/utils/collection-flow-manager/index.ts (1 hunks)
  • packages/common/src/utils/collection-flow-manager/schemas/config-schema.ts (1 hunks)
  • packages/common/vitest.config.ts (1 hunks)
  • services/workflows-service/prisma/data-migrations (1 hunks)
  • services/workflows-service/src/collection-flow/collection-flow.service.ts (2 hunks)
  • services/workflows-service/src/collection-flow/controllers/collection-flow.controller.ts (1 hunks)
  • services/workflows-service/src/workflow/workflow.service.ts (6 hunks)
✅ Files skipped from review due to trivial changes (2)
  • packages/common/src/utils/collection-flow-manager/index.ts
  • services/workflows-service/prisma/data-migrations
🧰 Additional context used
🔇 Additional comments (48)
apps/kyb-app/src/domains/collection-flow/types/flow-context.types.ts (2)

Line range hint 6-12: LGTM! Interfaces maintain backward compatibility.

The unchanged CollectionFlowConfig and CollectionFlowContextData interfaces properly reference the new CollectionFlowContext type while maintaining their existing structure. This helps ensure a smoother migration path.


2-2: Verify the migration to CollectionFlowContextSchema across the codebase.

The change to use CollectionFlowContextSchema from @ballerine/common is a significant architectural improvement that centralizes the schema definition. However, this is a breaking change that requires verification of all consumers.

Let's verify the schema usage across the codebase:

Also applies to: 4-4

✅ Verification successful

Based on the shell script results, I can now provide a final response:

Migration to CollectionFlowContextSchema is properly implemented across the codebase

The verification shows that:

  1. The schema is consistently imported from @ballerine/common across all relevant files
  2. All files using CollectionFlowContext have been properly updated to use the new schema
  3. The old context properties usage (appState, customerCompany) are not found in the codebase
  4. The only remaining flowConfig and stepsProgress usages are in:
    • UI definition scripts (template strings)
    • Web UI SDK loading component
    • Submit button component (setting progress state)

These usages are valid and expected as they represent either configuration templates or UI-specific functionality.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that all files using CollectionFlowContext are properly updated

# Test 1: Find all files that import or use CollectionFlowContext
echo "=== Files importing or using CollectionFlowContext ==="
rg -l "CollectionFlowContext"

# Test 2: Check for any remaining direct usage of the old context properties
echo -e "\n=== Potential usage of old context properties ==="
rg "flowConfig\." 
rg "appState\." 
rg "customerCompany\."
rg "stepsProgress\."

# Test 3: Verify all imports of the new schema
echo -e "\n=== Files importing CollectionFlowContextSchema ==="
rg "CollectionFlowContextSchema"

Length of output: 15474

apps/kyb-app/src/components/organisms/DynamicUI/StateManager/components/ActionsHandler/action-handlers/action-handler.abstract.ts (1)

3-3: LGTM!

Clean addition of the CollectionFlowContext import, maintaining proper import organization.

apps/kyb-app/src/components/organisms/DynamicUI/StateManager/components/ActionsHandler/action-handlers/plugin-runner.handler.ts (2)

4-4: LGTM! Good improvement in type safety.

The explicit import and use of CollectionFlowContext instead of a generic type enhances type safety and maintains consistency with the broader state management refactor.


13-13: Verify the impact of removing generic context type.

The change from generic TContext to specific CollectionFlowContext is a breaking change. While this aligns with the standardization effort, we should verify that all plugin runners are compatible with this context type.

apps/kyb-app/src/components/organisms/DynamicUI/StateManager/components/ActionsHandler/action-handlers/event-dispatcher.handler.ts (2)

4-4: LGTM!

Clean import that aligns with the standardization of CollectionFlowContext usage across the codebase.


Line range hint 13-18: Verify StateMachineAPI contract compatibility.

The method signature change from generic type to CollectionFlowContext looks good. However, let's verify the StateMachineAPI contract to ensure type compatibility.

✅ Verification successful

Let me try a different approach to verify the StateMachineAPI contract.


Based on the search results, I can now provide a definitive response about the StateMachineAPI contract compatibility:

StateMachineAPI contract is fully compatible with the changes

The interface definition in useMachineLogic.ts shows that:

  • getContext() returns CollectionFlowContext
  • sendEvent(eventName: string) accepts only the event name parameter

The event-dispatcher handler's implementation correctly:

  • Uses CollectionFlowContext as the context type
  • Calls api.sendEvent(eventName) with just the event name
  • Returns the context via api.getContext()

All type signatures align perfectly with the StateMachineAPI interface contract.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify StateMachineAPI interface compatibility with CollectionFlowContext

# Test 1: Check if StateMachineAPI.getContext returns CollectionFlowContext
ast-grep --pattern 'interface StateMachineAPI {
  $$$
  getContext(): $_
  $$$
}'

# Test 2: Check if sendEvent method accepts context parameter in its signature
ast-grep --pattern 'interface StateMachineAPI {
  $$$
  sendEvent($_): $_
  $$$
}'

Length of output: 168


Script:

#!/bin/bash
# Search for StateMachineAPI interface definition
rg "interface StateMachineAPI" -A 10

# Also search for any type definitions or implementations related to StateMachineAPI
rg "StateMachineAPI" -A 3 -B 3

Length of output: 23417

apps/kyb-app/src/components/organisms/DynamicUI/StateManager/types.ts (1)

14-14: LGTM! Type safety improvement noted.

The change from AnyObject to CollectionFlowContext enhances type safety and aligns with the existing usage of CollectionFlowContext in StateManagerProps. This is a positive change that makes the types more specific and maintainable.

Let's verify the impact on consuming code:

✅ Verification successful

Let's gather more specific information about how the StateManagerContext is being used in these files.

The previous search showed many files using StateManagerContext, but we need to understand:

  1. How the context is consumed (destructuring, direct access)
  2. What type annotations are used with payload
  3. Whether there are any existing type constraints

This will help us verify if the type change is safe and compatible with existing usage patterns.


Let's search for more specific information about the CollectionFlowContext type and its usage.

This will help us understand:

  1. The definition and structure of CollectionFlowContext
  2. How the state manager context is consumed and used
  3. How payload updates are handled in the state management system

This information will help us verify if the type change from AnyObject to CollectionFlowContext is safe and compatible with existing usage patterns.


Based on the gathered information, I can now provide a final response about the type change from AnyObject to CollectionFlowContext.

Type change is safe and consistent with the codebase

The change from AnyObject to CollectionFlowContext for the payload property in StateManagerContext is safe and well-aligned with the codebase for the following reasons:

  1. CollectionFlowContext is already the expected type throughout the codebase:

    • It's used in the state manager's hooks (useStateLogic.ts, useMachineLogic.ts)
    • The API returns CollectionFlowContext (collection-flow.api.ts)
    • Components like JSONForm and StepperUI expect CollectionFlowContext
  2. The type is properly defined:

    • It's imported from @ballerine/common as CollectionFlowContextSchema
    • It's re-exported in the domain types as CollectionFlowContext
  3. All consumers are already handling this type:

    • State updates in useStateLogic.ts use CollectionFlowContext
    • Action handlers expect CollectionFlowContext
    • The machine context is typed as CollectionFlowContext

The change actually makes the type more accurate by removing the overly permissive AnyObject type, matching the actual runtime type that's being used throughout the application.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Find all usages of StateManagerContext to ensure they can handle CollectionFlowContext

# Search for files importing or using StateManagerContext
rg -l "StateManagerContext" 

# Search for direct access to the payload property
rg -A 3 "context\.payload" 

Length of output: 2581


Script:

#!/bin/bash
# Search for usage patterns of StateManagerContext to understand how payload is accessed
ast-grep --pattern 'useContext($state)' --pattern-type ts
ast-grep --pattern 'const { payload } = $expr' --pattern-type ts
ast-grep --pattern 'payload: $expr' --pattern-type ts

# Look for specific imports of StateManagerContext
rg "import.*StateManagerContext" -A 1

# Search for direct payload access patterns
rg "payload\s*[:=]" --type ts

Length of output: 24230


Script:

#!/bin/bash
# Search for CollectionFlowContext definition and usage
rg "CollectionFlowContext" -A 3

# Search for specific state manager context usage patterns
rg "useStateManagerContext.*=.*" -A 2

# Look for state updates in the codebase
rg "setState.*payload" -A 2

Length of output: 38543

apps/kyb-app/src/helpers/prepareInitialUIState.ts (2)

4-4: LGTM: Import statement is correctly placed and utilized.


23-23: Document the early return condition and verify state management.

The purpose of the early return condition isn't immediately clear. Consider adding a comment explaining why we return an empty state when the first page's state name matches the UI state.

Let's verify how this state management pattern is used across the codebase:

✅ Verification successful

Let me gather more context about the state management pattern by examining the related files.


Based on the gathered context, I can now generate the final response since I have enough information about the state management pattern across the codebase.

Early return is valid but needs documentation for clarity

The early return condition is part of a consistent state management pattern used across the codebase where:

  • CollectionFlowManager tracks the UI state through collectionFlow?.state?.uiState
  • StateManager component uses this state for machine initialization
  • The early return in prepareInitialUIState specifically handles the initial state when we're at the first page, avoiding unnecessary element initialization

Consider adding a comment like:

// Return empty initial state when we're still at the first page to avoid premature element initialization
if (pages[0]?.stateName === context.collectionFlow?.state?.uiState) return initialUIState;
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for similar state management patterns and potential inconsistencies

# Search for similar state access patterns
rg -l "collectionFlow\?\.state\?\.uiState" 

# Look for other early returns based on state
ast-grep --pattern 'if ($condition) return $state'

Length of output: 302


Script:

#!/bin/bash
# Check the implementation in collection-flow-manager
rg -A 10 "collectionFlow\?\.state\?\.uiState" packages/common/src/utils/collection-flow-manager/collection-flow-manager.ts

# Check the StateManager component implementation
rg -A 10 "collectionFlow\?\.state\?\.uiState" apps/kyb-app/src/components/organisms/DynamicUI/StateManager/StateManager.tsx

# Look at the full context of prepareInitialUIState
cat apps/kyb-app/src/helpers/prepareInitialUIState.ts

Length of output: 1926

packages/common/src/index.ts (2)

42-52: Verify type compatibility with removed types.

The removal of ObjectValues type (as mentioned in the AI summary) while adding CollectionFlowContextSchema suggests a shift in type organization.

Let's verify there are no breaking changes:

#!/bin/bash
# Check for any remaining usage of the removed ObjectValues type
rg "ObjectValues[^a-zA-Z]"

# Look for potential type dependencies
rg "CollectionFlowContextSchema"

37-38: Verify the new collection-flow-manager export usage.

The addition of this new module export suggests significant changes to collection flow management.

Let's verify the usage and potential impact:

✅ Verification successful

Let me gather more specific information about the collection-flow-manager usage and implementation.

The previous results show that CollectionFlowContextSchema is used in multiple places, but we need to understand the actual implementation and usage of the collection-flow-manager to verify its impact.


Based on the implementation details gathered, I can now provide a final response:

The collection-flow-manager export is a safe addition with minimal impact

The collection-flow-manager is a self-contained utility class that manages collection flow state and configuration. It's designed to be opt-in, meaning:

  • It requires explicit initialization via the start() method
  • It maintains its own isolated context
  • It's only imported in packages/common/src/index.ts and has no direct consumers in the codebase yet

The implementation shows it's a new feature addition rather than a modification of existing functionality, making it safe to export.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for existing imports of collection-flow-manager
rg -l "from ['\"].*\/collection-flow-manager['\"]"

# Check the implementation to understand the exported functionality
ast-grep --pattern 'export * from "./utils/collection-flow-manager"'

Length of output: 16126


Script:

#!/bin/bash
# Check for direct imports of collection-flow-manager
rg "from.*collection-flow-manager['\"]"

# Check the implementation of collection-flow-manager
fd "collection-flow-manager.ts" --exec cat {}

# Check for any tests that might indicate the functionality
fd "collection-flow-manager.test.ts" --exec cat {}
fd "collection-flow-manager.spec.ts" --exec cat {}

Length of output: 3601

packages/common/src/schemas/index.ts (2)

12-12: LGTM!

The re-organization of existing exports maintains consistency and doesn't introduce any breaking changes.

Also applies to: 13-16, 26-26


1-5: Verify the integration of new CollectionFlow exports.

The new exports look good and follow proper TypeScript naming conventions. However, let's verify that these new types are being used consistently across the codebase.

✅ Verification successful

Based on the shell script results, I can now generate the final response as we have comprehensive information about the usage of these new exports across the codebase.

New CollectionFlow exports are properly integrated and used consistently

The new exports are well-integrated across the codebase with proper usage patterns:

  • CollectionFlowStateEnum is used consistently in:
    • Collection flow manager utilities for state management
    • Unit tests validating state transitions
    • KYB app's CollectionFlow component for rendering different states
  • CollectionFlowContextSchema is properly utilized in:
    • Workflow service for context management
    • Collection flow manager and its helper classes
    • Type definitions in the KYB app
  • collectionFlowContextSchema serves as the base schema definition and is correctly imported where needed

The exports follow a clean architecture pattern where the schema definitions are centralized and consumed appropriately across different layers of the application.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the usage of new CollectionFlow types across the codebase
# Expected: Find references to these types in components and services

echo "Checking CollectionFlowStateEnum usage:"
rg "CollectionFlowStateEnum" -A 2

echo "Checking CollectionFlowContextSchema usage:"
rg "CollectionFlowContextSchema" -A 2

echo "Checking collectionFlowContextSchema usage:"
rg "collectionFlowContextSchema" -A 2

Length of output: 24645

packages/common/src/schemas/documents/collection-flow-context-schema.ts (3)

1-2: LGTM! Appropriate use of TypeBox for schema validation.

The imports are well-structured, utilizing TypeBox for runtime type validation while extending the default context schema.


43-43: LGTM! Proper type export using TypeBox Static utility.

The type export correctly derives the TypeScript type from the schema definition.


1-43: Verify schema integration with dependent components.

The schema is referenced by multiple components mentioned in the summary. Let's verify the integration:

✅ Verification successful

Based on the shell script results, I can now generate the final response:

Schema and enum integration is properly maintained across the codebase

The verification shows that:

  • The schema and enum are correctly imported and used across multiple components in packages/common, services/workflows-service, and apps/kyb-app
  • All enum values are properly referenced using CollectionFlowStateEnum in the codebase
  • While there are hardcoded string literals matching enum values in workflow definitions and service layers, this is expected as they represent different domain concepts (workflow states vs UI states)

The schema integration appears to be consistent and well-maintained, with no issues found in the dependent components.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the usage of CollectionFlowContextSchema and CollectionFlowStateEnum

# Test 1: Check imports of the schema
echo "Checking schema imports..."
rg -l "CollectionFlowContextSchema|CollectionFlowStateEnum"

# Test 2: Verify correct enum value usage
echo "Checking enum value usage..."
rg "CollectionFlowStateEnum\.[a-zA-Z]+" -A 1

# Test 3: Check for any hardcoded strings that should use the enum
echo "Checking for potential missed enum usage..."
rg "'(pending|inprogress|approved|rejected|failed|revision)'" --type ts

Length of output: 22211

apps/kyb-app/src/components/organisms/DynamicUI/hooks/useUIStateLogic/hooks/useUIElementsStateLogic/hooks/useUIElementToolsLogic/useUIElementToolsLogic.ts (1)

2-3: Verify import dependencies to prevent circular references.

The new imports from the StateManager and hooks directory could potentially create circular dependencies.

✅ Verification successful

Let me gather more information about the import structure to make a more informed decision.


Based on the results, I can now generate the final response:

The import structure is safe and does not create circular dependencies

The analysis of the codebase shows that:

  • The StateProvider is a simple context provider that doesn't import from the hooks directory
  • The useRefValue is a standalone utility hook with no dependencies on DynamicUI components
  • The only reference to useUIElementToolsLogic is from TransitionListener.tsx which is a consumer, not a dependency
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for potential circular dependencies in the import chain
# Expected: No circular references between StateManager, hooks, and current file

# Test 1: Check if StateManager imports from current directory
rg -l "from.*useUIElementToolsLogic" --glob "apps/kyb-app/src/components/organisms/DynamicUI/StateManager/**"

# Test 2: Check if useRefValue hook has dependencies on current directory
rg -l "from.*useUIElementToolsLogic" --glob "apps/kyb-app/src/hooks/**"

Length of output: 185


Script:

#!/bin/bash
# Let's check the actual content of these files to understand the dependency structure

# Check the StateManager context provider implementation
echo "=== StateManager Context Implementation ==="
fd "StateProvider.ts" apps/kyb-app/src/components/organisms/DynamicUI/StateManager/ --exec cat {}

# Check the useRefValue hook implementation
echo -e "\n=== useRefValue Hook Implementation ==="
fd "useRefValue.ts" apps/kyb-app/src/hooks/ --exec cat {}

# Check if there are any other imports of useUIElementToolsLogic in the DynamicUI folder
echo -e "\n=== References to useUIElementToolsLogic in DynamicUI ==="
rg "from.*useUIElementToolsLogic" apps/kyb-app/src/components/organisms/DynamicUI/

Length of output: 1687

apps/kyb-app/src/domains/collection-flow/collection-flow.api.ts (2)

10-10: LGTM! Import changes align with the new context structure.

The import statement correctly reflects the simplified context structure, removing unused types and importing only the necessary CollectionFlowContext.


67-71: Verify the impact of return type changes.

The function's return type has changed from containing both context and config to directly returning CollectionFlowContext. This is a breaking change that could affect existing consumers.

Let's verify the usage of this function:

packages/common/src/schemas/documents/default-context-schema.ts (2)

Line range hint 15-43: LGTM! Schema structure remains unchanged.

The schema definitions (defaultInputContextSchema, defaultContextSchema, and DefaultContextSchema type) are well-structured and maintain their existing functionality while supporting the broader CollectionFlowContext integration.


4-4: Verify schema import paths after reorganization.

The import statements have been reorganized, with some schemas moved to a new location. Let's verify that all imports are correctly resolved after this reorganization.

Also applies to: 7-10, 12-12

✅ Verification successful

Since all the imported schema files are found in their expected locations under packages/common/src/schemas/documents/schemas/, I can now generate the final response.

Import paths are correctly organized and resolved ✓

All schema files referenced in the import statements exist in their new locations under the schemas/ subdirectory:

  • business-information-plugin-schema.ts
  • aml-schema.ts
  • documents-schema.ts
  • entity-schema.ts
  • kyc-session-plugin-schema.ts
  • ubo-plugin-schema.ts
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that all imported schema files exist in their new locations

# Test: Check if all schema files exist
echo "Verifying schema file locations..."
fd --type f --extension ts "business-information-plugin-schema.ts|aml-schema.ts|documents-schema.ts|entity-schema.ts|kyc-session-plugin-schema.ts|ubo-plugin-schema.ts" --exec echo "Found: {}"

Length of output: 741

apps/kyb-app/src/components/organisms/DynamicUI/StateManager/StateManager.tsx (1)

23-23: ⚠️ Potential issue

Verify state migration and add type safety checks.

The state access pattern has changed from flowConfig.appState to collectionFlow.state.uiState. This could lead to undefined states if the migration isn't complete.

Consider adding type safety:

-      state: initialContext?.collectionFlow?.state?.uiState,
+      state: initialContext?.collectionFlow?.state?.uiState ?? {},
✅ Verification successful

Let me try a different search strategy to verify the state migration patterns.

This should give us a better understanding of:

  1. The context around both state patterns
  2. Whether there's a mix of old and new patterns
  3. The type definitions that govern these structures

Based on the search results, I can now provide a final response:

State migration is part of a larger CollectionFlow context refactoring

The change from flowConfig.appState to collectionFlow.state.uiState is part of a well-structured migration to use CollectionFlowContext throughout the codebase. The search results show:

  1. The new pattern is consistently used across the codebase with proper type definitions and validation:

    • CollectionFlowManager class handles state management
    • StateHelper class provides type-safe state access
    • Proper interfaces and schemas are defined in the codebase
  2. The old flowConfig pattern is only used for API URL configurations and tokens, not for state management anymore.

  3. The state access is protected by the StateHelper class which includes null checks and validation, making the optional chaining in the code appropriate for the initialization phase.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that all components have migrated to the new state structure
# and no components are still trying to access flowConfig.appState

# Check for old state access pattern
echo "Checking for old state access pattern..."
rg -l "flowConfig\.appState"

# Check for new state access pattern adoption
echo "Checking for new state access pattern adoption..."
rg -l "collectionFlow\.state\.uiState"

Length of output: 271


Script:

#!/bin/bash
# Search for any references to flowConfig and collectionFlow in the codebase
echo "Searching for flowConfig references..."
rg "flowConfig" -A 2 -B 2

echo -e "\nSearching for collectionFlow references..."
rg "collectionFlow" -A 2 -B 2

# Also check for any TypeScript interfaces or types related to these
echo -e "\nSearching for related type definitions..."
ast-grep --pattern 'interface $_ {
  $$$
  flowConfig?: $_
  $$$
}'

ast-grep --pattern 'interface $_ {
  $$$
  collectionFlow?: $_
  $$$
}'

Length of output: 105712

packages/common/src/utils/collection-flow-manager/helpers/config-helper.unit.test.ts (1)

1-4: LGTM! Imports are well-organized.

The necessary imports are correctly defined, including the schema type and testing utilities.

apps/kyb-app/src/components/organisms/DynamicUI/StateManager/hooks/useMachineLogic/useMachineLogic.ts (5)

1-2: LGTM! Import changes align with type safety improvements

The addition of CollectionFlowContext import and reorganization of imports enhance type safety and maintain good import ordering.


10-11: LGTM! Enhanced type safety in API interface

The change from AnyObject to CollectionFlowContext improves type safety and makes the API contract more explicit.


Line range hint 59-64: LGTM! Consistent type implementation in setContext

The implementation correctly uses the CollectionFlowContext type and maintains a clean, straightforward implementation.


72-72: LGTM! Consistent type casting in getContext

The type casting to CollectionFlowContext maintains consistency with the interface definition and enhances type safety.


1-1: Verify compatibility with hook consumers

The change from AnyObject to CollectionFlowContext is a breaking change that might affect consumers of this hook.

Let's verify the usage:

Also applies to: 10-11

packages/common/package.json (2)

46-46: LGTM: Valid addition of @rollup/plugin-json.

The addition of @rollup/plugin-json is appropriate for handling JSON imports in the rollup configuration.


50-50: LGTM: Proper type definitions for crypto-js.

The @types/crypto-js version (^4.2.2) correctly aligns with the runtime dependency [email protected].

apps/kyb-app/src/components/organisms/DynamicUI/StateManager/hooks/useStateLogic/useStateLogic.ts (1)

43-50: Improve type safety for context initialization

While the change to CollectionFlowContext type improves type safety, the initialization could be strengthened:

  1. The empty object default for initialContext might not satisfy CollectionFlowContext requirements
  2. The type assertion when setting context (as CollectionFlowContext) could mask type errors

Let's verify the structure of CollectionFlowContext:

apps/kyb-app/src/domains/collection-flow/types/index.ts (2)

5-5: Verify the imported type's implementation.

The import of CollectionFlowConfig is part of the broader context management changes. Let's verify its implementation.

✅ Verification successful

Let me generate better scripts to verify the imported type's implementation.


Let me try different commands without typescript file type specification since it's not recognized.


Import statement is correctly implemented and used

The verification shows that:

  1. CollectionFlowConfig is properly defined in flow-context.types.ts as an interface with an optional uiOptions property
  2. The import is correctly used in index.ts where UISchemaConfig extends it
  3. The type is also used consistently in the CollectionFlowContextData interface
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the CollectionFlowConfig type definition and its usage
# Expected: Find the type definition and other potential usages

# Check the type definition
echo "Checking CollectionFlowConfig definition:"
rg -t typescript "export.*CollectionFlowConfig" 

# Check other usages
echo -e "\nChecking other usages:"
rg -t typescript "CollectionFlowConfig[^.]" -A 2

Length of output: 382


Script:

#!/bin/bash
# Check the type definition in the relative path
echo "Checking CollectionFlowConfig in flow-context.types.ts:"
rg -t typescript "export.*CollectionFlowConfig" apps/kyb-app/src/domains/collection-flow/types/flow-context.types.ts

# Check the content of the types directory
echo -e "\nListing files in the types directory:"
ls -la apps/kyb-app/src/domains/collection-flow/types/

# Check all usages of CollectionFlowConfig
echo -e "\nChecking all usages of CollectionFlowConfig:"
rg -t typescript "CollectionFlowConfig" apps/kyb-app/src/domains/collection-flow/types/

Length of output: 958


Script:

#!/bin/bash
# Check the content of flow-context.types.ts
echo "Checking content of flow-context.types.ts:"
cat apps/kyb-app/src/domains/collection-flow/types/flow-context.types.ts

# Check all usages of CollectionFlowConfig in the types directory
echo -e "\nChecking all usages of CollectionFlowConfig:"
rg "CollectionFlowConfig" apps/kyb-app/src/domains/collection-flow/types/

Length of output: 1167


136-139: Interface extension looks good but verify implementations.

The extension of CollectionFlowConfig aligns with the PR's goal of enhancing type safety and context management. However, since this is a breaking change, we should verify all implementations.

✅ Verification successful

Let me try a different approach to find the implementations with corrected syntax.


Let me try one more search with corrected file type and more specific patterns:


Based on the search results, I can now provide a final response:

Interface extension is safe and already properly implemented

The search results show that UISchemaConfig is only used in two ways:

  • As a type definition in apps/kyb-app/src/domains/collection-flow/types/index.ts
  • As part of the UISchema interface where it's used as a type for the config property

The supportedLanguages property is already being used correctly in:

  • The workflows service configuration (services/workflows-service/scripts/workflows/dynamic-ui-workflow.ts)
  • The language picker component (apps/kyb-app/src/components/layouts/AppShell/LanguagePicker.tsx)

No breaking changes or implementation updates are needed as the existing code already conforms to the interface requirements.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Find all implementations of UISchemaConfig to ensure they're updated
# Expected: Locate all places where UISchemaConfig is instantiated

# Find direct usage of UISchemaConfig
echo "Checking UISchemaConfig implementations:"
rg -t typescript "UISchemaConfig.*=.*{" -A 5

# Find interface implementations
echo -e "\nChecking interface implementations:"
ast-grep --pattern 'const $_ : UISchemaConfig = $_'

Length of output: 382


Script:

#!/bin/bash
# Search for UISchemaConfig usage with proper regex escaping
echo "Checking UISchemaConfig usage:"
rg -t typescript "UISchemaConfig" -B 2 -A 2

# Search for type annotations and assignments
echo -e "\nChecking type annotations:"
ast-grep --pattern '$_: UISchemaConfig'

# Search for object literals that might implement the interface
echo -e "\nChecking object assignments:"
ast-grep --pattern 'const $_ = {
  kybOnExitAction: $_,
  supportedLanguages: $_
}'

Length of output: 3142


Script:

#!/bin/bash
# Search for UISchemaConfig in TypeScript and JavaScript files
echo "Checking UISchemaConfig usage:"
rg --type-add 'ts:*.{ts,tsx}' --type ts "UISchemaConfig" -B 2 -A 2

# Search specifically in the collection-flow directory
echo -e "\nChecking collection-flow directory:"
fd . apps/kyb-app/src/domains/collection-flow -t f -e ts -e tsx -x rg "UISchemaConfig" -B 2 -A 2 {}

# Search for config objects that might implement the interface
echo -e "\nChecking potential implementations:"
rg --type-add 'ts:*.{ts,tsx}' --type ts "supportedLanguages.*\[" -B 2 -A 2

Length of output: 3606

packages/common/src/utils/collection-flow-manager/helpers/state-helper.unit.test.ts (1)

1-5: LGTM! Clean and focused imports.

The imports are well-organized and include all necessary dependencies for testing.

apps/kyb-app/src/components/organisms/UIRenderer/elements/JSONForm/JSONForm.tsx (1)

81-83: ⚠️ Potential issue

Improve type safety and null checks in company information handling.

The current implementation has several areas that could be improved:

  1. The type assertion (payload as CollectionFlowContext) is unsafe and could lead to runtime errors if the payload doesn't match the expected type.
  2. The nested optional chaining could benefit from a more robust default value strategy.

Consider applying these improvements:

- companyName: get(payload, 'entity.data.companyName', '') as string,
- customerCompany: (payload as CollectionFlowContext).collectionFlow
-   ?.additionalInformation?.customerCompany,
+ companyName: get(payload, 'entity.data.companyName', '') as string,
+ customerCompany: get(payload, 'collectionFlow.additionalInformation.customerCompany', null),

Let's verify the CollectionFlowContext type usage across the codebase:

✅ Verification successful

Let me gather more information about the CollectionFlowContext type definition and its usage to make a more informed decision.

The previous results show that CollectionFlowContext is used consistently across the codebase, but we need to understand its type definition and any existing type guards to make a proper recommendation about type safety.


Let me check one more thing to understand the type definition of CollectionFlowContext in the codebase.

This will help us understand how CollectionFlowContext is defined and if there are any existing type guards that we should be using instead of type assertions.


Based on the gathered information, I can now provide the final response:

Type assertion is appropriate, but safer access pattern recommended

The type assertion to CollectionFlowContext is actually valid here since:

  1. CollectionFlowContext is properly defined as an alias to CollectionFlowContextSchema from @ballerine/common
  2. The type is consistently used across the codebase for context handling
  3. The payload comes from a context that's already typed as CollectionFlowContext

However, the suggested improvement to use get() for nested property access is still valuable for runtime safety:

customerCompany: get(payload, 'collectionFlow.additionalInformation.customerCompany', null),

This maintains type safety while providing better null/undefined handling at runtime.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for consistent CollectionFlowContext type usage
# Expected: Find other locations where payload is cast to CollectionFlowContext

# Search for CollectionFlowContext type assertions
rg "as CollectionFlowContext" -A 2

# Search for CollectionFlowContext type usage in type definitions
ast-grep --pattern "type $_ = $$$CollectionFlowContext$$$"

Length of output: 10468


Script:

#!/bin/bash
# Search for CollectionFlowContext type definition
ast-grep --pattern "type CollectionFlowContext = $_"

# Search for CollectionFlowContext interface definition
ast-grep --pattern "interface CollectionFlowContext $_"

# Search for imports of CollectionFlowContext
rg "import.*CollectionFlowContext.*from" -A 1

# Search for type guards or type checks for CollectionFlowContext
rg "isCollectionFlowContext|CollectionFlowContext\)" -A 2

Length of output: 7491


Script:

#!/bin/bash
# Get the content of the flow-context.types.ts file
cat apps/kyb-app/src/domains/collection-flow/types/flow-context.types.ts

# Check if there are any type guards in the codebase
rg "function is.*CollectionFlow" -A 3

Length of output: 487

packages/common/rollup.config.ts (2)

8-8: LGTM: JSON plugin import added correctly.

The import statement for the JSON plugin is properly placed with other plugin imports.


110-110: LGTM: JSON plugin consistently integrated across build formats.

The json() plugin is correctly added to all relevant build configurations (ESM, CJS, UMD Dev, and UMD Prod), ensuring JSON files can be imported as modules across different output formats.

Let's verify the JSON plugin usage in the codebase:

Also applies to: 133-133, 156-156, 185-185

✅ Verification successful

Based on the results, I can now generate the final response:

JSON plugin is justified by multiple JSON imports across the codebase

The verification confirms that the JSON plugin is necessary as there are multiple JSON imports throughout the codebase, including:

  • Translation files (.../translation.json)
  • Package configuration (package.json)
  • Country/nationality data from i18n-iso-countries and i18n-nationality
  • Theme configuration (theme.json)
  • Toast configurations and other localization files
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for JSON imports in the codebase to validate the need for @rollup/plugin-json

# Test: Search for JSON imports. Expect: Find .json file imports that justify the plugin addition
rg -t ts -t js "from ['\"].*\.json['\"]|import.*\.json['\"]"

Length of output: 1873

packages/common/src/utils/collection-flow-manager/collection-flow-manager.unit.test.ts (1)

1-158: Verify test coverage for CollectionFlowManager.

Let's ensure we have adequate test coverage for the CollectionFlowManager class.

✅ Verification successful

Let me analyze the test coverage by searching for the implementation of CollectionFlowManager.


Let me search for the actual implementation file to analyze the methods and their test coverage.


Let me try a different approach to view the implementation file directly.


Based on the implementation and test files, I can now provide a final response about the test coverage.

Test coverage for CollectionFlowManager is comprehensive and adequate.

The test suite covers all public methods and critical functionality:

  1. Constructor and initialization

    • Basic instantiation
    • Invalid config handling
  2. isStarted() method

    • Verification of started state based on uiState
  3. start() method

    • Success cases with config
    • Failure case when already started
    • Context mutation verification
    • Progress state initialization
  4. config() method

    • Success case with proper initialization
    • Failure case when config is not set
  5. state() method

    • Success case with proper initialization
    • Failure case when state is not set

The only method not explicitly tested is updateAdditionalInformation(), but this is a simple setter method with logging, and its functionality is implicitly tested through the context manipulation tests.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for all public methods in CollectionFlowManager
echo "Searching for public methods in CollectionFlowManager..."
ast-grep --pattern 'class CollectionFlowManager {
  $$$
  $method($_) {
    $$$
  }
  $$$
}'

# Search for error conditions in the implementation
echo "Searching for error conditions that might need testing..."
rg "throw|Error" --type ts

Length of output: 149604


Script:

#!/bin/bash
# Search for CollectionFlowManager implementation
echo "Searching for CollectionFlowManager implementation..."
ast-grep --pattern 'class CollectionFlowManager {
  $$$
}'

# Search for CollectionFlowManager interface/type definitions
echo "Searching for CollectionFlowManager interface/type definitions..."
rg "interface.*CollectionFlowManager|type.*CollectionFlowManager" --type ts

Length of output: 563


Script:

#!/bin/bash
# Search for the implementation file
echo "Searching for CollectionFlowManager implementation file..."
fd "collection-flow-manager.ts" --type f

# If found, let's look at its content
echo "Searching for public methods in the implementation..."
rg "^[[:space:]]*(?:public|protected).*\(" --type ts --pcre2 packages/common/src/utils/collection-flow-manager/collection-flow-manager.ts || true

Length of output: 508


Script:

#!/bin/bash
# View the implementation file content
echo "Viewing CollectionFlowManager implementation..."
cat packages/common/src/utils/collection-flow-manager/collection-flow-manager.ts

# View the test file content for comparison
echo -e "\nViewing test file content..."
cat packages/common/src/utils/collection-flow-manager/collection-flow-manager.unit.test.ts

Length of output: 8591

services/workflows-service/src/collection-flow/collection-flow.service.ts (2)

21-21: LGTM: Import statement aligns with CollectionFlow context integration.

The addition of CollectionFlowContextSchema import is consistent with the PR's objective of enhancing type safety and improving state management.


290-298: 🛠️ Refactor suggestion

Consider enhancing type safety, error handling, and documentation.

While the method implementation is straightforward, there are several areas for improvement:

  1. The method selects more fields than necessary (state and config) when only context is being returned
  2. Missing error handling for potential undefined context
  3. Lacks JSDoc documentation explaining the method's purpose and usage
  4. No runtime type validation of the returned context

Consider applying these improvements:

+  /**
+   * Retrieves the collection flow context for a given workflow runtime
+   * @param tokenScope - The token scope containing workflow and project information
+   * @returns The strongly typed collection flow context
+   * @throws {NotFoundException} When workflow runtime data is not found
+   */
   async getCollectionFlowContext(tokenScope: ITokenScope): Promise<CollectionFlowContextSchema> {
     const workflowRuntimeData = await this.workflowService.getWorkflowRuntimeDataById(
       tokenScope.workflowRuntimeDataId,
-      { select: { context: true, state: true, config: true } },
+      { select: { context: true } },
       [tokenScope.projectId],
     );
 
+    if (!workflowRuntimeData.context) {
+      throw new NotFoundException('Collection flow context not found');
+    }
+
     return workflowRuntimeData.context;
   }

Let's verify the usage of this method to ensure proper error handling in consumers:

packages/common/src/utils/collection-flow-manager/helpers/state-helper.ts (1)

75-83: 🛠️ Refactor suggestion

Avoid direct state replacement without validation

The override method replaces the entire state without any validation, which might lead to inconsistencies or invalid states. Consider adding validation to ensure the new state adheres to the expected schema.

Would you like assistance in implementing state validation? If so, we can create a method to validate the state against the CollectionFlowContextSchema.

apps/kyb-app/src/pages/CollectionFlow/CollectionFlow.tsx (4)

31-31: Imports are correctly added

The CollectionFlowManager and CollectionFlowStateEnum are appropriately imported from @ballerine/common.


96-99: Conditional rendering for Approved state is correct

The condition correctly checks if the collectionFlowState is approved and renders the <Approved /> component accordingly. The optional chaining and equality check are used appropriately.


101-104: Conditional rendering for Rejected state is correct

Similarly, the condition checks if the collectionFlowState is rejected and renders the <Rejected /> component. The use of optional chaining and the equality check are correct.


74-78: ⚠️ Potential issue

Fix syntax error in initialContext definition

The useMemo hook should return an object. Currently, the spread operator is used without wrapping it inside an object literal or including a return statement, which will cause a syntax error.

Apply this diff to fix the syntax error:

const initialContext: CollectionFlowContext = useMemo(() => {
+  return {
    ...context,
+  } as CollectionFlowContext;
}, [context]);

Likely invalid or redundant comment.

services/workflows-service/src/workflow/workflow.service.ts (2)

1474-1478: ⚠️ Potential issue

Potential PII Exposure: Storing Customer Details in Metadata

The customer details (customerId, customerNormalizedName, customerName) are being stored in the workflow context's metadata. Ensure that including this sensitive information is necessary and that appropriate security measures are in place to protect it from unauthorized access or exposure.


1571-1576: ⚠️ Potential issue

Security Consideration: Handling Tokens in Configuration

Updating the tokenId in collectionFlowManager's configuration may expose sensitive tokens within the workflow context. Verify that tokens are handled securely and are not inadvertently exposed or logged. Consider encrypting sensitive information and ensuring tokens are stored and transmitted securely.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Outside diff range and nitpick comments (3)
packages/common/src/schemas/documents/collection-flow-context-schema.ts (1)

4-17: Consider standardizing the enum value naming convention.

While the states are well-documented, the naming convention could be more consistent:

  • 'inprogress' could be 'in_progress' to follow common naming patterns
  • 'revision' could be 'in_revision' to match the pattern of 'in_progress'
 export enum CollectionFlowStateEnum {
   pending = 'pending',
-  inprogress = 'inprogress',
+  inprogress = 'in_progress',
   approved = 'approved',
   rejected = 'rejected',
-  revision = 'revision',
+  revision = 'in_revision',
   failed = 'failed',
 }
services/workflows-service/src/workflow/workflow.controller.internal.ts (1)

Line range hint 291-310: Consider improving error handling and code structure

While the addition of revision handling is valuable, there are several potential improvements:

  1. The second service call updateWorkflowInRevision should have its own error handling to ensure failures are properly caught and don't result in inconsistent state.
  2. The variable reassignment pattern could be simplified.

Consider refactoring to:

-      let workflowData = await this.service.updateDocumentDecisionById(
+      const workflowData = await this.service.updateDocumentDecisionById(
         {
           workflowId: params?.id,
           documentId: params?.documentId,
           documentsUpdateContextMethod: query.contextUpdateMethod,
         },
         {
           status: data?.decision,
           reason: data?.reason,
           comment: data?.comment,
         },
         projectIds,
         currentProjectId,
       );

       if (data.decision === 'revision') {
-        workflowData = await this.service.updateWorkflowInRevision(params.id, currentProjectId);
+        return await this.service.updateWorkflowInRevision(params.id, currentProjectId);
       }

-      return workflowData;
+      return workflowData;

Also, consider adding documentation to explain the revision workflow and its implications.

services/workflows-service/src/workflow/workflow.service.ts (1)

2183-2194: Enhance state management with validation and error handling.

The state transition logic could be more robust. Consider:

  1. Adding validation for allowed state transitions
  2. Implementing error handling for invalid states
  3. Adding logging for state transitions for better debugging

Example enhancement:

 if (context?.collectionFlow) {
   const collectionFlowManager = new CollectionFlowManager(context);
+  const previousState = collectionFlowManager.state().collectionFlowState;
 
   if (currentState in CollectionFlowStateEnum) {
+    if (!isValidStateTransition(previousState, currentState)) {
+      throw new InvalidStateTransitionError(previousState, currentState);
+    }
     collectionFlowManager.state().collectionFlowState = currentState;
+    logger.info('Collection flow state transition', { 
+      from: previousState, 
+      to: currentState 
+    });
   }
 
   context = collectionFlowManager.context;
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between cb8ee44 and cbd5e63.

📒 Files selected for processing (6)
  • apps/kyb-app/src/helpers/prepareInitialUIState.ts (2 hunks)
  • apps/kyb-app/src/pages/CollectionFlow/CollectionFlow.tsx (4 hunks)
  • packages/common/src/schemas/documents/collection-flow-context-schema.ts (1 hunks)
  • services/workflows-service/package.json (1 hunks)
  • services/workflows-service/src/workflow/workflow.controller.internal.ts (3 hunks)
  • services/workflows-service/src/workflow/workflow.service.ts (8 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/kyb-app/src/helpers/prepareInitialUIState.ts
🔇 Additional comments (6)
packages/common/src/schemas/documents/collection-flow-context-schema.ts (3)

1-2: LGTM! Clean and focused imports.

The imports are minimal and clearly indicate the dependencies needed for the schema definition.


49-49: LGTM! Clean type export.

The type export follows TypeBox best practices and provides a clear type alias for the schema.


19-47: 🛠️ Refactor suggestion

Consider adding runtime validation for critical fields.

While the schema structure is good, consider adding runtime validation for critical fields to prevent potential issues:

  1. Add min/max length constraints for tokenId
  2. Add pattern validation for progress record keys
  3. Consider making collectionFlowState required instead of optional since it's crucial for flow control
 export const collectionFlowContextSchema = Type.Composite([
   defaultContextSchema,
   Type.Object({
     collectionFlow: Type.Optional(
       Type.Object({
         config: Type.Optional(
           Type.Object({
             apiUrl: Type.String(),
-            tokenId: Type.String(),
+            tokenId: Type.String({ minLength: 1, maxLength: 256 }),
           }),
         ),
-        state: Type.Optional(
+        state: Type.Object({
           Type.Object({
             uiState: Type.String(),
             collectionFlowState: Type.Enum(CollectionFlowStateEnum),
             progress: Type.Optional(
-              Type.Record(Type.String(), Type.Object({ isCompleted: Type.Boolean() })),
+              Type.Record(
+                Type.String({ pattern: '^[a-zA-Z0-9_-]+$' }),
+                Type.Object({ isCompleted: Type.Boolean() })
+              ),
             ),
           }),
         ),
         additionalInformation: Type.Optional(
           Type.Object({
             customerCompany: Type.Optional(Type.String()),
           }),
         ),
       }),
     ),
   }),
 ]);

The previous review comment about enhancing type safety is still valid.

services/workflows-service/src/workflow/workflow.controller.internal.ts (2)

35-38: LGTM: Clean import additions for enhanced validation

The new imports support the implementation of improved request validation using TypeBox and NestJS decorators.


Line range hint 141-167: LGTM: Robust validation implementation

The enhanced validation setup using TypeBox provides comprehensive request validation for both parameters and body, with well-defined error responses. This improvement helps catch invalid inputs early in the request lifecycle.

services/workflows-service/src/workflow/workflow.service.ts (1)

1470-1486: Consider enhancing type safety and validation for CollectionFlowManager initialization.

The initialization looks correct, but consider:

  1. Adding runtime validation for required configuration properties
  2. Using TypeScript utility types to ensure all required properties are provided
  3. Adding error handling for missing UI schema elements

services/workflows-service/package.json Outdated Show resolved Hide resolved
apps/kyb-app/src/pages/CollectionFlow/CollectionFlow.tsx Outdated Show resolved Hide resolved
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 9

🧹 Outside diff range and nitpick comments (4)
packages/common/src/utils/collection-flow-manager/collection-flow-manager.unit.test.ts (3)

32-40: Add edge cases for isStarted() behavior.

The current test only covers the positive case when uiState is set. Consider adding tests for:

  • When uiState is undefined/null
  • When collectionFlow is undefined
  • When state is undefined

Example:

test('returns false when uiState is undefined', () => {
  const manager = new CollectionFlowManager({
    collectionFlow: { state: {} }
  } as DefaultContextSchema);
  expect(manager.isStarted()).toBe(false);
});

42-75: Enhance progress object validation.

While the tests verify basic progress structure, consider adding assertions for:

  • Step progress object schema completeness
  • Handling of multiple steps
  • Progress state for optional/conditional steps

Example:

test('handles multiple steps correctly', () => {
  const manager = new CollectionFlowManager({} as DefaultContextSchema, {
    steps: [
      { stateName: 'step1' },
      { stateName: 'step2', optional: true }
    ]
  });
  const context = manager.start();
  expect(context.collectionFlow?.state?.progress).toEqual({
    step1: { isCompleted: false },
    step2: { isCompleted: false, optional: true }
  });
});

125-158: Add test coverage for StateHelper methods.

While the tests verify state retrieval, they don't cover the actual functionality provided by the StateHelper instance.

Add tests for common StateHelper operations:

  • Getting/setting current step
  • Updating step progress
  • Handling state transitions
  • State validation methods

Example:

test('allows state manipulation via helper', () => {
  const manager = createStartedManager();
  const state = manager.state();
  
  state.setCurrentStep('step1');
  expect(state.getCurrentStep()).toBe('step1');
  
  state.completeStep('step1');
  expect(state.isStepCompleted('step1')).toBe(true);
});
packages/common/src/utils/collection-flow-manager/helpers/state-helper.ts (1)

20-21: Use a dedicated logging utility instead of console.log

To maintain consistent logging practices and better control over log levels across different environments (development, staging, production), consider replacing console.log statements with a dedicated logging library or utility used in your application. This enhances maintainability and provides more flexibility in managing logs.

Apply this diff to update the logging statements:

- console.log(`UI State transition from ${this.uiState} to ${uiState}`);
+ Logger.info(`UI State transition from ${this.uiState} to ${uiState}`);

...

- console.log(
-   `Collection flow state transition from ${this.collectionFlowState} to ${collectionFlowState}`,
- );
+ Logger.info(
+   `Collection flow state transition from ${this.collectionFlowState} to ${collectionFlowState}`,
+ );

...

- console.log(`Step: ${step} isCompleted: ${isCompleted}`);
+ Logger.info(`Step: ${step} isCompleted: ${isCompleted}`);

...

- console.log('StateHelper, context override', this.context.collectionFlow!.state);
+ Logger.debug('StateHelper, context override', this.context.collectionFlow!.state);

Assuming Logger is the logging utility in your application.

Also applies to: 37-39, 65-65, 76-76

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between cbd5e63 and da574f6.

📒 Files selected for processing (14)
  • apps/kyb-app/src/domains/collection-flow/types/flow-context.types.ts (1 hunks)
  • apps/kyb-app/src/pages/CollectionFlow/CollectionFlow.tsx (4 hunks)
  • packages/common/src/consts/index.ts (1 hunks)
  • packages/common/src/index.ts (3 hunks)
  • packages/common/src/schemas/documents/default-context-schema.ts (2 hunks)
  • packages/common/src/schemas/index.ts (2 hunks)
  • packages/common/src/utils/collection-flow-manager/collection-flow-manager.ts (1 hunks)
  • packages/common/src/utils/collection-flow-manager/collection-flow-manager.unit.test.ts (1 hunks)
  • packages/common/src/utils/collection-flow-manager/helpers/config-helper.ts (1 hunks)
  • packages/common/src/utils/collection-flow-manager/helpers/state-helper.ts (1 hunks)
  • packages/common/src/utils/collection-flow-manager/helpers/state-helper.unit.test.ts (1 hunks)
  • services/workflows-service/src/collection-flow/collection-flow.service.ts (2 hunks)
  • services/workflows-service/src/workflow/workflow.controller.internal.ts (3 hunks)
  • services/workflows-service/src/workflow/workflow.service.ts (8 hunks)
🚧 Files skipped from review as they are similar to previous changes (7)
  • apps/kyb-app/src/domains/collection-flow/types/flow-context.types.ts
  • packages/common/src/index.ts
  • packages/common/src/schemas/index.ts
  • packages/common/src/utils/collection-flow-manager/helpers/config-helper.ts
  • packages/common/src/utils/collection-flow-manager/helpers/state-helper.unit.test.ts
  • services/workflows-service/src/collection-flow/collection-flow.service.ts
  • services/workflows-service/src/workflow/workflow.controller.internal.ts
🔇 Additional comments (15)
packages/common/src/utils/collection-flow-manager/collection-flow-manager.ts (2)

19-21: LGTM! Clean implementation of state check.

The method effectively uses optional chaining to safely check the flow state.


62-76: LGTM! Well-structured helper implementation.

Good use of helper classes and null checks before returning instances.

packages/common/src/consts/index.ts (1)

191-191: Verify type usage across the codebase.

The type definition follows the correct pattern. However, since this is a new type that will be used for state management, we should verify its integration.

Let's check how this type is being used:

✅ Verification successful

Based on the search results, I can now generate the final response:

Type is correctly integrated and used in the codebase

The TCollectionFlowState type is properly used in the collection flow manager's state helper implementation and its tests:

  • Used in packages/common/src/utils/collection-flow-manager/helpers/state-helper.ts for type safety
  • Validated against CollectionFlowStates enum in the state helper's setter
  • Test coverage exists in state-helper.unit.test.ts including invalid state handling
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for usages of TCollectionFlowState type
rg "TCollectionFlowState" -A 3

# Search for direct usage of CollectionFlowStates values
rg -e "pending'|'inprogress'|'completed'" -A 3

Length of output: 23562

packages/common/src/utils/collection-flow-manager/collection-flow-manager.unit.test.ts (4)

18-30: LGTM! Good negative test coverage.

The test effectively validates the failure case when attempting to start an already started flow.


77-89: Remove redundant test block.

This test block duplicates assertions already covered in the "context will be updated on start" describe block.


9-9: 🛠️ Refactor suggestion

Create a test factory for DefaultContextSchema.

Multiple instances of type casting empty objects to DefaultContextSchema make the tests brittle and bypass type safety. This pattern appears in several places throughout the test file.

Create a test factory function:

function createTestContext(partial?: Partial<DefaultContextSchema>): DefaultContextSchema {
  return {
    collectionFlow: {
      state: {},
      ...partial?.collectionFlow
    }
  };
}

// Usage:
const manager = new CollectionFlowManager(createTestContext());

Also applies to: 13-13, 64-64


91-123: 🛠️ Refactor suggestion

Reduce setup duplication in config tests.

The config retrieval tests contain duplicated setup code for creating and starting the CollectionFlowManager.

Create a setup helper:

function createStartedManager(config = {}) {
  const manager = new CollectionFlowManager(createTestContext(), {
    apiUrl: 'https://api.example.com',
    tokenId: '1234567890',
    steps: [{ stateName: 'step1' }],
    ...config
  });
  return new CollectionFlowManager(manager.start());
}
apps/kyb-app/src/pages/CollectionFlow/CollectionFlow.tsx (4)

11-14: LGTM: New imports enhance error handling and state management capabilities.

The added imports properly support the new error handling and state management features.

Also applies to: 34-34


109-113: LGTM: Clean state-based conditional rendering.

The implementation properly handles state transitions with type-safe checks.


129-149: Consider cleanup of CollectionFlowManager instance.

The CollectionFlowManager instance is created within the onNext callback but there's no cleanup mechanism. While this might not cause immediate issues, it's good practice to clean up resources, especially if they maintain internal state.

Let's check if CollectionFlowManager needs cleanup:

#!/bin/bash
# Search for cleanup methods in CollectionFlowManager
ast-grep --pattern 'class CollectionFlowManager {
  $$$
  destroy() {
    $$$
  }
  $$$
}'

If CollectionFlowManager has cleanup methods, consider wrapping the instance in a useCallback or moving it outside the callback to prevent unnecessary recreations:

+const handleNext = useCallback(async (tools, prevState, currentState) => {
+  const collectionFlowManager = new CollectionFlowManager(stateApi.getContext());
   // ... rest of the code
+}, [stateApi]);

-onNext={async (tools, prevState, currentState) => {
+onNext={handleNext}

81-91: 🛠️ Refactor suggestion

Enhance type safety in initialContext setup.

The current implementation makes assumptions about the context type without validation.

Let's verify the context structure:

Consider adding runtime validation:

 const initialContext: CollectionFlowContext = useMemo(() => {
+  if (!context || !context.collectionFlow) {
+    throw new Error('Invalid context structure');
+  }
   const collectionFlowManager = new CollectionFlowManager(context as CollectionFlowContext);
services/workflows-service/src/workflow/workflow.service.ts (3)

123-124: LGTM! Well-defined constant for collection flow events.

The constant clearly defines the allowed collection flow event states, following proper naming conventions.


1525-1526: Previous review comment about scattered context updates still applies.

The code continues to show multiple scattered context updates which could lead to inconsistent states.

Also applies to: 1574-1579


1472-1488: Verify the empty token initialization.

While the initialization looks good overall, initializing tokenId as an empty string might cause issues if the token is required for subsequent operations. Consider adding validation or documentation to clarify when the token gets populated.

✅ Verification successful

Let me try a different search strategy to understand the usage of tokenId in the codebase.


Empty tokenId initialization is correct and safe

The empty token initialization is intentional and properly handled in the codebase. The search results show that:

  1. The token is immediately populated after initialization:
collectionFlowManager.config().tokenId = workflowToken.token;
  1. The ConfigHelper class provides proper getter/setter methods for tokenId with validation:
set tokenId(tokenId: string) {
  if (!this.context.collectionFlow?.config) {
    throw new Error('Collection flow config is not set.');
  }
  console.log(`Token ID updated from ${this.tokenId} to ${tokenId}`);
  this.context.collectionFlow.config.tokenId = tokenId;
}
  1. The token is used in API calls only after it's properly set, as evidenced by the UI definition files where it's used in headers and URLs.
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for token usage in collection flow manager
rg -A 3 "tokenId.*=.*''" 

Length of output: 32


Script:

#!/bin/bash
# Search for CollectionFlowManager class definition and usage of tokenId
ast-grep --pattern 'class CollectionFlowManager {
  $$$
}'

# Search for any tokenId references
rg -A 3 "tokenId" 

Length of output: 26265

packages/common/src/schemas/documents/default-context-schema.ts (1)

43-68: LGTM!

The addition of the collectionFlow property enhances the context schema effectively. The structure is well-defined, and the use of optional properties allows for flexible state management. The integration of CollectionFlowStates ensures type safety for the flow state enumeration.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 9

🧹 Outside diff range and nitpick comments (1)
packages/common/CHANGELOG.md (1)

3-8: Enhance the changelog entry with more details.

The changelog entry could be more descriptive to help users understand the impact of these changes. Consider adding:

  • A brief description of what the collection flow manager does
  • Details about the schema updates
  • Any breaking changes or migration steps required
  • Links to relevant documentation or examples

This is particularly important as these changes appear to be part of significant state management improvements.

Example of a more detailed entry:

 ## 0.9.44
 
 ### Patch Changes
 
-Added collection flow manager & updated schema
+- Added collection flow manager for improved state management and context handling
+- Updated schema to support new state management features
+- Breaking changes:
+  * New required fields in state context
+  * Modified method signatures for action handlers
+- Migration guide: [link to docs]
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between da574f6 and d3d16b6.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (29)
  • apps/backoffice-v2/CHANGELOG.md (1 hunks)
  • apps/backoffice-v2/package.json (2 hunks)
  • apps/kyb-app/CHANGELOG.md (1 hunks)
  • apps/kyb-app/package.json (2 hunks)
  • apps/kyb-app/src/components/organisms/UIRenderer/elements/SubmitButton/SubmitButton.tsx (2 hunks)
  • examples/headless-example/CHANGELOG.md (1 hunks)
  • examples/headless-example/package.json (2 hunks)
  • packages/blocks/package.json (1 hunks)
  • packages/blocks/rollup.config.ts (5 hunks)
  • packages/common/CHANGELOG.md (1 hunks)
  • packages/common/package.json (3 hunks)
  • packages/common/src/schemas/documents/default-context-schema.ts (2 hunks)
  • packages/common/src/utils/collection-flow-manager/collection-flow-manager.ts (1 hunks)
  • packages/common/src/utils/collection-flow-manager/collection-flow-manager.unit.test.ts (1 hunks)
  • packages/common/src/utils/collection-flow-manager/helpers/config-helper.ts (1 hunks)
  • packages/common/src/utils/collection-flow-manager/helpers/config-helper.unit.test.ts (1 hunks)
  • packages/common/src/utils/collection-flow-manager/schemas/config-schema.ts (1 hunks)
  • packages/workflow-core/CHANGELOG.md (1 hunks)
  • packages/workflow-core/package.json (2 hunks)
  • sdks/web-ui-sdk/CHANGELOG.md (1 hunks)
  • sdks/web-ui-sdk/package.json (2 hunks)
  • sdks/workflow-browser-sdk/CHANGELOG.md (1 hunks)
  • sdks/workflow-browser-sdk/package.json (2 hunks)
  • sdks/workflow-node-sdk/CHANGELOG.md (1 hunks)
  • sdks/workflow-node-sdk/package.json (2 hunks)
  • services/workflows-service/CHANGELOG.md (1 hunks)
  • services/workflows-service/package.json (3 hunks)
  • services/workflows-service/src/workflow/workflow.service.ts (8 hunks)
  • websites/docs/package.json (1 hunks)
✅ Files skipped from review due to trivial changes (12)
  • apps/backoffice-v2/CHANGELOG.md
  • apps/backoffice-v2/package.json
  • apps/kyb-app/CHANGELOG.md
  • apps/kyb-app/package.json
  • examples/headless-example/CHANGELOG.md
  • examples/headless-example/package.json
  • packages/workflow-core/CHANGELOG.md
  • sdks/web-ui-sdk/CHANGELOG.md
  • sdks/workflow-browser-sdk/CHANGELOG.md
  • sdks/workflow-node-sdk/CHANGELOG.md
  • sdks/workflow-node-sdk/package.json
  • services/workflows-service/CHANGELOG.md
🚧 Files skipped from review as they are similar to previous changes (5)
  • packages/common/package.json
  • packages/common/src/schemas/documents/default-context-schema.ts
  • packages/common/src/utils/collection-flow-manager/collection-flow-manager.unit.test.ts
  • packages/common/src/utils/collection-flow-manager/helpers/config-helper.unit.test.ts
  • packages/common/src/utils/collection-flow-manager/schemas/config-schema.ts
🔇 Additional comments (21)
packages/common/src/utils/collection-flow-manager/helpers/config-helper.ts (4)

3-4: Add context validation in constructor.

The existing review comment about adding constructor validation is still valid. The constructor should validate that the provided context is not null/undefined to fail fast.


6-8: Improve type safety in getter.

The existing review comment about improving getter type safety is still valid. The current implementation uses type assertion which could mask runtime errors.


10-17: Replace console.log with proper logging and improve validation.

The existing review comments about replacing console.log with proper logging and improving validation are still valid.


19-27: Improve override method safety and add security validation.

The existing review comment about improving override method safety is still valid. Additionally, let's verify if the config contains sensitive data:

#!/bin/bash
# Search for sensitive data patterns in config usage
rg -i '(password|secret|key|token|credential).*config' 

If the config contains sensitive data, consider adding validation for required security properties:

interface SecurityConfig {
  tokenId: string;
  apiUrl: string;
  // Add other required security properties
}

function validateSecurityConfig(config: unknown): config is SecurityConfig {
  // Add validation logic
}
sdks/workflow-browser-sdk/package.json (1)

4-4: Consider deferring version bumps until the PR is ready for release.

Since this is marked as a WIP PR, consider whether version bumps should be made at this stage or deferred until the changes are finalized.

Let's check if there are any release-related workflows that might be triggered by version changes:

packages/workflow-core/package.json (1)

4-4: LGTM! Version bump and dependency update look appropriate.

The version increment and dependency update align with the changes being made across multiple packages in the ecosystem.

Also applies to: 34-34

packages/blocks/package.json (1)

49-49: LGTM! Verify rollup configuration for JSON plugin.

The addition of @rollup/plugin-json is appropriate for handling JSON imports.

Let's verify the rollup configuration:

✅ Verification successful

JSON plugin is properly configured in rollup

The @rollup/plugin-json is correctly imported and used in all build configurations:

  • ESM build (line 156)
  • CJS build (line 182)
  • UMD development build (line 213)
  • UMD production build (line 245)
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check if the rollup config properly includes the JSON plugin

# Test: Search for json plugin configuration
rg -A 5 "@rollup/plugin-json" "packages/blocks/rollup.config"

Length of output: 129


Script:

#!/bin/bash
# Let's first find the rollup config file as it might have a different extension
fd "rollup.config" packages/blocks

# Also search for any file containing rollup configuration
fd -e js -e ts -e mjs "rollup" packages/blocks

Length of output: 213


Script:

#!/bin/bash
# Check both rollup config files for json plugin configuration
cat packages/blocks/rollup.config.js packages/blocks/rollup.config.ts

# Also specifically search for json plugin imports in these files
rg -i "json.*plugin" packages/blocks/rollup.config.js packages/blocks/rollup.config.ts

Length of output: 5473

packages/common/src/utils/collection-flow-manager/collection-flow-manager.ts (3)

19-21: LGTM! Clean implementation of state check.

The method effectively uses optional chaining for safe property access and provides a clear boolean response.


61-75: LGTM! Well-implemented helper methods with proper error handling.

Both methods include appropriate null checks and provide clear error messages before returning helper instances.


34-38: ⚠️ Potential issue

Strengthen type safety in state initialization.

The type assertion as string on stateName could lead to runtime errors if steps is empty or undefined. Consider adding proper validation and type guards.

+ if (!this._config?.steps?.length) {
+   throw new Error('Collection flow configuration must contain at least one step.');
+ }

const state: NonNullable<DefaultContextSchema['collectionFlow']>['state'] = {
-  uiState: this._config?.steps[0]?.stateName as string,
+  uiState: this._config.steps[0].stateName,
  collectionFlowState: CollectionFlowStates.pending,
  progress: this.buildProgressState(),
};

Likely invalid or redundant comment.

sdks/web-ui-sdk/package.json (2)

99-99: Verify @ballerine/common upgrade impact.

Since this PR is marked as WIP, please ensure that the upgrade to @ballerine/[email protected] doesn't introduce any breaking changes that could affect the web-ui-sdk.

Let's check for potential breaking changes:

#!/bin/bash
# Description: Look for breaking changes indicators
# Expected: No major version changes or breaking change indicators

# Check for BREAKING CHANGE markers in recent commits
git log --grep="BREAKING CHANGE" -i --since="1 week ago"

# Look for major version bumps in @ballerine/common
rg '"@ballerine/common":\s*"[^"]*"' -g 'package.json'

24-24: LGTM on version bump.

The patch version increment follows semantic versioning principles.

Let's verify the version bump aligns with other package updates:

✅ Verification successful

Version bump to 1.5.45 is appropriate and follows the project's versioning pattern

The version increment from 1.5.44 to 1.5.45 in web-ui-sdk is consistent with:

  • The package's independent versioning scheme (1.x.x)
  • The nature of the changes (patch update)
  • The corresponding update of @ballerine/common dependency from 0.9.43 to 0.9.44
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check version patterns across related packages
# Expected: Consistent version updates across related packages

# Search for version fields in package.json files
rg '"version":\s*"[^"]*"' -g 'package.json'

Length of output: 861


Script:

#!/bin/bash
# Let's check the version fields to verify alignment
rg '"version":\s*"[^"]*"' -g 'package.json'

Length of output: 1481

packages/blocks/rollup.config.ts (2)

16-16: LGTM: JSON plugin import added correctly.

The @rollup/plugin-json import is properly placed with other plugin imports.


111-111: LGTM: JSON plugin consistently integrated across all build formats.

The json() plugin is correctly added to all relevant build configurations (ESM, CJS, UMD dev, and UMD prod), ensuring consistent JSON handling across different module formats.

Also applies to: 134-134, 157-157, 186-186

services/workflows-service/package.json (1)

4-4: LGTM: Coordinated version updates across @ballerine packages.

The version bump and dependency updates are consistently applied across related @ballerine packages, maintaining version alignment within the ecosystem.

Also applies to: 50-52

services/workflows-service/src/workflow/workflow.service.ts (4)

12-14: LGTM: New imports for OCR functionality

The imports are properly organized and necessary for the new OCR functionality.


123-124: LGTM: Well-defined whitelist for collection flow events

The constant clearly defines the allowed states for collection flow transitions.


1524-1525: Previous review comment about context updates is still applicable


1573-1577: Previous review comment about context updates is still applicable

apps/kyb-app/src/components/organisms/UIRenderer/elements/SubmitButton/SubmitButton.tsx (2)

15-15: Approved: Importing CollectionFlowManager and CollectionFlowStates

The import statement correctly brings in CollectionFlowManager and CollectionFlowStates from @ballerine/common, which are utilized in the updated state management logic.


78-78: Verify that updated context is properly synchronized

After setting the new state, the updated context is set with stateApi.setContext(collectionFlowManager.context);. Ensure that this action correctly synchronizes the context across all relevant components and that there are no stale references to the old context.

To confirm that the context is being updated as expected throughout the application, consider checking dependent components or running tests that validate context-dependent functionality.

@chesterkmr chesterkmr changed the title Illiar/feat/app state (WIP) Illiar/feat/app state Oct 28, 2024
@chesterkmr chesterkmr force-pushed the illiar/feat/app-state branch from cb12d31 to b2fc722 Compare October 29, 2024 13:14
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 14

🧹 Outside diff range and nitpick comments (8)
packages/common/src/utils/collection-flow-manager/helpers/config-helper.ts (3)

24-26: Add JSDoc comment explaining steps immutability.

The error message could be more informative about why steps can't be modified after initialization.

+/**
+ * Steps are immutable after initialization to ensure flow consistency.
+ * Modifications to steps during runtime could lead to unexpected behavior.
+ * @throws {Error} Always throws to prevent steps modification
+ */
 set steps(_) {
   throw new Error('Setting steps is not allowed after initialization.');
 }

28-36: Add return type annotation for override method.

The method should explicitly declare its return type for better type safety.

-  override(config: NonNullable<NonNullable<DefaultContextSchema['collectionFlow']>['config']>) {
+  override(
+    config: NonNullable<NonNullable<DefaultContextSchema['collectionFlow']>['config']>,
+  ): DefaultContextSchema {

5-5: Add readonly modifier to context parameter.

The context parameter should be marked as readonly to prevent accidental modifications.

-  constructor(private context: DefaultContextSchema) {}
+  constructor(private readonly context: DefaultContextSchema) {}
apps/kyb-app/src/components/organisms/DynamicUI/Page/hooks/usePageErrors/usePageErrors.ts (3)

4-4: LGTM: Type safety improvement for context parameter.

The change from AnyObject to CollectionFlowContext improves type safety. However, consider extending this improvement to the helper functions.

Consider updating the helper functions to use CollectionFlowContext:

-export const selectDirectors = (context: AnyObject) =>
+export const selectDirectors = (context: CollectionFlowContext) =>
   (context?.entity?.data?.additionalInfo?.directors as AnyObject[]) || [];

-export const selectDirectorsDocuments = (context: unknown): Document[] =>
+export const selectDirectorsDocuments = (context: CollectionFlowContext): Document[] =>

Also applies to: 26-26


Line range hint 47-52: Remove @ts-ignore by improving type definitions.

Multiple ts-ignore comments suggest underlying type safety issues that should be addressed.

Consider creating proper type definitions for the document decision:

interface DocumentDecision {
  status: 'revision' | 'rejected' | 'approved';
  revisionReason?: string;
}

interface DocumentWithDecision extends Document {
  decision?: DocumentDecision;
}

Then update the code:

-          //@ts-ignore
-          !(document?.decision?.status == 'revision' || document?.decision?.status == 'rejected')
+          !(document as DocumentWithDecision)?.decision?.status === 'revision' || 
+          !(document as DocumentWithDecision)?.decision?.status === 'rejected'

Line range hint 65-72: Define error field types as constants.

The error type 'warning' is hardcoded and document ID casting could be improved.

Consider defining an enum or constant for error types and improving ID typing:

enum ErrorFieldType {
  WARNING = 'warning',
  ERROR = 'error'
}

interface DocumentId {
  id: string;
}

// Then update the code:
return {
  fieldId: `document-error-${(document as DocumentId).id}`,
  fieldDestination: `document-error-${(document as DocumentId).id}`,
  message,
  type: ErrorFieldType.WARNING,
};
services/workflows-service/scripts/workflows/runtime/generate-initial-collection-flow-example.ts (1)

87-87: Consider making the workflow version configurable

The workflow version is hardcoded to 1, which might cause issues with version management.

Consider making it configurable:

-      workflowDefinitionVersion: 1,
+      workflowDefinitionVersion: uiDefinition.version ?? 1,
packages/common/src/utils/collection-flow-manager/collection-flow-manager.ts (1)

28-31: Extract default configuration to constants.

Default values are hardcoded. Consider moving them to named constants for better maintainability and reusability.

+ const DEFAULT_CONFIG = {
+   apiUrl: '',
+   steps: [],
+ } as const;

const config: NonNullable<DefaultContextSchema['collectionFlow']>['config'] = {
-   apiUrl: this._config?.apiUrl || '',
-   steps: this._config?.steps || [],
+   apiUrl: this._config?.apiUrl || DEFAULT_CONFIG.apiUrl,
+   steps: this._config?.steps || DEFAULT_CONFIG.steps,
};
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 6ad59bd and cfad964.

📒 Files selected for processing (14)
  • apps/backoffice-v2/src/common/components/molecules/ProcessTracker/hooks/useProcessTracker/process-tracker-adapters/collection-flow.process-tracker.ts (1 hunks)
  • apps/backoffice-v2/src/domains/workflows/fetchers.ts (2 hunks)
  • apps/kyb-app/src/components/layouts/AppShell/Navigation.tsx (1 hunks)
  • apps/kyb-app/src/components/organisms/DynamicUI/Page/hooks/usePageErrors/usePageErrors.ts (2 hunks)
  • apps/kyb-app/src/pages/CollectionFlow/CollectionFlow.tsx (4 hunks)
  • packages/common/src/schemas/documents/default-context-schema.ts (2 hunks)
  • packages/common/src/utils/collection-flow-manager/collection-flow-manager.ts (1 hunks)
  • packages/common/src/utils/collection-flow-manager/helpers/config-helper.ts (1 hunks)
  • packages/common/src/utils/collection-flow-manager/schemas/config-schema.ts (1 hunks)
  • services/workflows-service/package.json (2 hunks)
  • services/workflows-service/prisma/data-migrations (1 hunks)
  • services/workflows-service/scripts/workflows/runtime/generate-initial-collection-flow-example.ts (2 hunks)
  • services/workflows-service/src/collection-flow/helpers/get-steps-in-order.ts (1 hunks)
  • services/workflows-service/src/workflow/workflow.service.ts (9 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
  • packages/common/src/schemas/documents/default-context-schema.ts
  • packages/common/src/utils/collection-flow-manager/schemas/config-schema.ts
  • services/workflows-service/package.json
  • services/workflows-service/prisma/data-migrations
🔇 Additional comments (20)
services/workflows-service/src/collection-flow/helpers/get-steps-in-order.ts (2)

27-27: LGTM!

The transformation logic is clean and uses appropriate 1-based indexing for order numbers.


14-20: ⚠️ Potential issue

Address potential issues in state machine initialization.

Several concerns in the state machine initialization:

  1. Empty runtime ID could cause issues in tracking or debugging
  2. Using any type for definition bypasses type safety
  3. Purpose of empty extensions and workflowContext is unclear

Consider this safer implementation:

   const stateMachine = createWorkflow({
-    runtimeId: '',
+    runtimeId: `steps-order-${Date.now()}`,
     definition: (definition as Prisma.JsonObject).definition as any,
     definitionType: 'statechart-json',
-    extensions: {},
-    workflowContext: {},
+    extensions: undefined,
+    workflowContext: undefined,
   });
apps/backoffice-v2/src/common/components/molecules/ProcessTracker/hooks/useProcessTracker/process-tracker-adapters/collection-flow.process-tracker.ts (1)

50-50: Previous review comment is still applicable.

The suggestion to add an explicit step existence check from the previous review remains valid for this code.

apps/kyb-app/src/components/layouts/AppShell/Navigation.tsx (3)

15-15: LGTM: Clean hook usage

The addition of payload from useStateManagerContext aligns with the broader context management changes.


24-24: Verify edge case handling in isFirstStep determination

The isFirstStep determination now depends on currentPageNumber calculation. While simpler, ensure this handles all edge cases correctly, especially when:

  1. The flow configuration is loading
  2. The step is not found in the configuration
  3. The current page state is transitioning

Let's check for potential edge cases in the codebase:

#!/bin/bash
# Look for other usages of isFirstStep to ensure consistent handling
rg "isFirstStep" --type ts -C 3

# Check for similar navigation conditions that might need alignment
ast-grep --pattern 'if ($_ === 1) { $$$ }'

20-22: ⚠️ Potential issue

Add fallback handling for step resolution

The current implementation might return undefined if the step is not found, which could affect the isFirstStep check. Consider adding explicit fallback handling.

Here's a suggested improvement:

-  const currentPageNumber = payload?.collectionFlow?.config?.steps?.find(
-    step => step.stateName === currentPage?.stateName,
-  )?.orderNumber;
+  const currentPageNumber = payload?.collectionFlow?.config?.steps?.find(
+    step => step.stateName === currentPage?.stateName,
+  )?.orderNumber ?? 1; // Explicit fallback to first step

Let's verify if there are other components relying on this step resolution logic:

services/workflows-service/scripts/workflows/runtime/generate-initial-collection-flow-example.ts (2)

1-3: LGTM: Imports are appropriate for the new functionality

The imports correctly bring in the necessary components for state management and workflow creation.


48-66: Skip: Previous review comment about type safety and hardcoded values is still valid

packages/common/src/utils/collection-flow-manager/collection-flow-manager.ts (4)

19-21: LGTM! Clean and safe implementation.

The method effectively uses optional chaining to safely check the nested state.


62-76: LGTM! Well-structured helper initialization.

Good error handling and separation of concerns using helper classes.


35-39: ⚠️ Potential issue

Improve type safety in state initialization.

The type assertion on stateName could mask potential issues. Consider adding proper validation.

+ if (!this._config?.steps?.length) {
+   throw new Error('Steps configuration is required to start the collection flow.');
+ }

const state: NonNullable<DefaultContextSchema['collectionFlow']>['state'] = {
-   uiState: this._config?.steps[0]?.stateName as string,
+   uiState: this._config.steps[0].stateName,
    collectionFlowState: CollectionFlowStates.pending,
    progress: this.buildProgressState(),
};

Likely invalid or redundant comment.


11-17: ⚠️ Potential issue

Consider making the configuration parameter required.

The _config parameter is marked as optional, but it's essential for the class's core functionality (used in start(), buildProgressState()). Making it required would prevent runtime errors and improve type safety.

- constructor(public context: TContext, private readonly _config?: CollectionFlowManagerConfig) {
+ constructor(public context: TContext, private readonly _config: CollectionFlowManagerConfig) {
-   if (_config && !collectionFlowConfigValidationSchema(_config)) {
+   if (!collectionFlowConfigValidationSchema(_config)) {
      throw new Error('Invalid collection flow manager config.');
    }
    this.context = structuredClone(context);
  }

Likely invalid or redundant comment.

apps/backoffice-v2/src/domains/workflows/fetchers.ts (2)

161-161: LGTM: Appropriate omission of collectionFlow in child workflows.

The omission of collectionFlow from child workflow contexts is correct as it prevents unnecessary nesting and potential circular references.


118-137: Verify schema compatibility with existing state management.

Let's verify that the new collection flow schema is compatible with existing state management components.

✅ Verification successful

Let me analyze the results and gather more specific information about the schema usage.

The initial results show widespread usage across the codebase, but we need to verify the actual implementations to ensure schema compatibility. This will help us understand if the schema changes align with the existing usage patterns.


Based on the comprehensive results, I can now generate the final response:

Schema changes are compatible with existing state management

The new collection flow schema in fetchers.ts aligns perfectly with the existing implementation:

  • The enum values (pending, inprogress, completed, etc.) match all usage across the codebase
  • The state structure (uiState, collectionFlowState, progress) is consistent with the CollectionFlowManager implementation
  • The schema is used consistently in components like:
    • CollectionFlow.tsx for state transitions
    • SubmitButton.tsx for completion handling
    • StateManager.tsx for UI state management
    • Process tracking components for progress visualization
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for potential incompatibilities with the new collection flow schema

# Test 1: Search for direct access to old flowConfig structure
echo "Checking for old flowConfig usage..."
rg -l "flowConfig" --type ts

# Test 2: Search for components that might need updates for the new schema
echo "Checking components using collection flow state..."
rg -l "collectionFlowState|uiState|progress" --type ts

# Test 3: Check for any hardcoded state values that might not match the enum
echo "Checking for hardcoded state values..."
rg -l "'pending'|'inprogress'|'completed'|'approved'|'revision'|'rejected'|'failed'" --type ts

Length of output: 10113


Script:

#!/bin/bash
# Let's check the actual implementation details of collection flow state usage

# Check the specific schema implementations
echo "Checking schema implementations..."
rg -A 10 "collectionFlow.*state" --type ts

# Check for any type definitions using these states
echo "Checking type definitions..."
ast-grep --pattern 'type $_ = {
  $$$
  collectionFlowState
  $$$
}'

# Check for direct state assignments
echo "Checking state assignments..."
rg -A 5 "collectionFlowState.*=" --type ts

Length of output: 44947

apps/kyb-app/src/pages/CollectionFlow/CollectionFlow.tsx (3)

60-62: Skip comment - covered by past review

The previous review comment about improving type safety and readability of getRevisionStateName is still valid.


94-95: Skip comment - covered by past review

The previous review comment about simplifying context usage in prepareInitialUIState is still valid.


132-149: 🛠️ Refactor suggestion

Consider potential race condition in state updates

The state updates are performed sequentially but might be affected by React's state batching. Consider using a single atomic update.

-collectionFlowManager.state().setStepCompletionState(prevState, true);
-collectionFlowManager.state().uiState = currentState;
-
-if (!isAnyStepCompleted) {
-  collectionFlowManager.state().collectionFlowState =
-    CollectionFlowStates.inprogress;
-}
+// Batch state updates
+const state = collectionFlowManager.state();
+state.setStepCompletionState(prevState, true);
+state.uiState = currentState;
+
+if (!isAnyStepCompleted) {
+  state.collectionFlowState = CollectionFlowStates.inprogress;
+}
services/workflows-service/src/workflow/workflow.service.ts (3)

125-126: LGTM! Well-defined constant for workflow states.

The constant is appropriately named and contains the correct set of workflow states.


1524-1525: Previous review comment about scattered context updates is still valid.

The code still has multiple scattered context updates which could lead to inconsistent states.

Please refer to the previous review comment about centralizing context updates and implementing a transaction-like pattern.

Also applies to: 1573-1577, 1583-1590


2183-2206: Previous review comment about refactoring state handling is still valid.

The collection flow state handling logic is complex and could benefit from being refactored into separate methods.

Please refer to the previous review comment about refactoring the state handling logic to improve maintainability.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Outside diff range and nitpick comments (1)
apps/backoffice-v2/src/domains/workflows/fetchers.ts (1)

138-138: Consider adding validation for additionalInformation

The additionalInformation field could benefit from more specific validation to ensure data integrity.

Consider adding validation for known fields or at least ensuring non-empty keys:

- additionalInformation: z.record(z.string(), z.unknown()).optional(),
+ additionalInformation: z.record(
+   z.string().min(1, 'Key must not be empty'),
+   z.unknown()
+ ).optional(),
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between cfad964 and 1c5cdf4.

📒 Files selected for processing (2)
  • apps/backoffice-v2/src/domains/workflows/fetchers.ts (3 hunks)
  • apps/kyb-app/src/components/organisms/DynamicUI/StateManager/hooks/useMachineLogic/useMachineLogic.ts (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/kyb-app/src/components/organisms/DynamicUI/StateManager/hooks/useMachineLogic/useMachineLogic.ts
🔇 Additional comments (3)
apps/backoffice-v2/src/domains/workflows/fetchers.ts (3)

9-9: LGTM: Import of CollectionFlowStates

The import is correctly placed and appropriately used in the schema definition.


162-162: LGTM: Child workflow context update

The omission of collectionFlow from child workflows is correctly implemented and maintains schema consistency.


119-138: Verify migration path for existing workflows

The introduction of the new collectionFlow schema structure might affect existing workflows. Please ensure there's a migration strategy in place.

Let's check for existing workflow data structure:

apps/backoffice-v2/src/domains/workflows/fetchers.ts Outdated Show resolved Hide resolved
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 1c5cdf4 and 325c6f9.

📒 Files selected for processing (1)
  • services/workflows-service/src/workflow/workflow.service.ts (7 hunks)
🔇 Additional comments (2)
services/workflows-service/src/workflow/workflow.service.ts (2)

1552-1567: LGTM: Collection flow initialization is well structured.

The initialization properly sets up the CollectionFlowManager with required configuration and starts the flow.


2173-2196: 🛠️ Refactor suggestion

Simplify collection flow state transition logic.

The current state transition logic is complex and could be simplified for better readability and maintainability.

-      const nextCollectionFlowState = COLLECTION_FLOW_EVENTS_WHITELIST.includes(type)
-        ? type
-        : // Using current state of workflow for approved, rejected, failed
-        COLLECTION_FLOW_EVENTS_WHITELIST.includes(currentState)
-        ? currentState
-        : undefined;
+      const nextCollectionFlowState = determineNextCollectionFlowState(type, currentState);

+      private determineNextCollectionFlowState(type: CollectionFlowEvent, currentState: string): CollectionFlowEvent | undefined {
+        if (COLLECTION_FLOW_EVENTS_WHITELIST.includes(type)) {
+          return type;
+        }
+        
+        return COLLECTION_FLOW_EVENTS_WHITELIST.includes(currentState) ? currentState : undefined;
+      }

Likely invalid or redundant comment.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Outside diff range and nitpick comments (1)
services/workflows-service/scripts/workflows/runtime/generate-initial-collection-flow-example.ts (1)

Line range hint 97-105: Consider making token expiration configurable

The token expiration is hardcoded to 30 days. Consider making this configurable through environment variables or configuration settings to allow for different expiration periods based on deployment requirements.

+const TOKEN_EXPIRATION_DAYS = process.env.TOKEN_EXPIRATION_DAYS || 30;

 const workflowToken = await prismaClient.workflowRuntimeDataToken.create({
   data: {
     endUserId: endUserId,
     token: token,
     workflowRuntimeDataId: workflowRuntime.id,
     projectId: projectId,
-    expiresAt: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000),
+    expiresAt: new Date(Date.now() + TOKEN_EXPIRATION_DAYS * 24 * 60 * 60 * 1000),
   },
 });
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 325c6f9 and f6a4fd3.

📒 Files selected for processing (1)
  • services/workflows-service/scripts/workflows/runtime/generate-initial-collection-flow-example.ts (2 hunks)
🔇 Additional comments (3)
services/workflows-service/scripts/workflows/runtime/generate-initial-collection-flow-example.ts (3)

6-30: Previous review comment about type safety and error handling is still applicable

The concerns about type safety, error handling, and infinite loop risk raised in the previous review have not been addressed.


48-69: Previous review comment about type safety and hardcoded values is still applicable

The concerns about type definitions and hardcoded values in the initialContext object are still valid.


71-83: Previous review comment about error handling and validation is still applicable

The concerns about proper error handling and validation for workflow initialization are still valid.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 9

🧹 Outside diff range and nitpick comments (6)
packages/common/src/utils/collection-flow-manager/helpers/state-helper.ts (1)

4-82: Consider architectural improvements for better maintainability

The StateHelper class could benefit from several architectural improvements:

  1. Implement dependency injection for logging
  2. Use observer pattern for state changes to decouple state updates from logging
  3. Split into smaller, focused classes (e.g., separate UI state, flow state, and progress management)

Example implementation of observer pattern:

interface StateChangeObserver {
  onStateChange(change: { type: string; from: unknown; to: unknown }): void;
}

class StateHelper {
  private observers: StateChangeObserver[] = [];
  
  addObserver(observer: StateChangeObserver) {
    this.observers.push(observer);
  }
  
  private notifyStateChange(type: string, from: unknown, to: unknown) {
    this.observers.forEach(observer => 
      observer.onStateChange({ type, from, to }));
  }
}
packages/common/src/utils/collection-flow-manager/collection-flow-manager.ts (5)

19-21: Add JSDoc documentation and explicit return type.

Consider adding documentation and type annotations for better maintainability and type safety.

+ /**
+  * Checks if the collection flow has been initialized.
+  * @returns {boolean} True if the flow has started, false otherwise.
+  */
- isStarted() {
+ isStarted(): boolean {
    return Boolean(this.context?.collectionFlow?.state?.uiState);
  }

23-54: Enhance method documentation and type safety.

The initialization method could benefit from better documentation and type safety.

+ /**
+  * Initializes the collection flow context with config, state, and additional information.
+  * @throws {Error} If the flow has already been started
+  * @returns {TContext} The initialized context
+  */
- initializeCollectionFlowContext() {
+ initializeCollectionFlowContext(): TContext {

Also, consider validating the initialized context structure before returning:

private validateInitializedContext(context: TContext): void {
  if (!context.collectionFlow?.config || !context.collectionFlow.state) {
    throw new Error('Context initialization failed: invalid structure');
  }
}

62-76: Document helper class capabilities and return types.

Add JSDoc documentation to clarify the purpose and capabilities of the helper classes.

+ /**
+  * Provides access to configuration management capabilities.
+  * @throws {Error} If the collection flow configuration is not set
+  * @returns {ConfigHelper} A helper instance for managing configuration
+  */
- config() {
+ config(): ConfigHelper {

+ /**
+  * Provides access to state management capabilities.
+  * @throws {Error} If the collection flow state is not set
+  * @returns {StateHelper} A helper instance for managing state
+  */
- state() {
+ state(): StateHelper {

88-98: Document progress state structure and return type.

Add documentation to clarify the structure and purpose of the progress state.

+ /**
+  * Builds the initial progress state for all steps in the configuration.
+  * Each step is marked as incomplete by default.
+  * @private
+  * @returns {Record<string, { isCompleted: boolean }>} A map of step names to their completion status
+  */
- private buildProgressState() {
+ private buildProgressState(): Record<string, { isCompleted: boolean }> {

10-99: Consider splitting context management and mutations.

The CollectionFlowManager class currently handles both context storage and mutations. Consider splitting these responsibilities:

  1. Create a separate CollectionFlowContext class to manage the context state
  2. Move mutation methods to a separate CollectionFlowMutator class

This separation would:

  • Make the code more maintainable
  • Make it easier to test
  • Allow for better control over state mutations
  • Enable implementation of different mutation strategies if needed

Example structure:

class CollectionFlowContext<T extends DefaultContextSchema> {
  constructor(private context: T) {}
  getState(): StateHelper { /* ... */ }
  getConfig(): ConfigHelper { /* ... */ }
}

class CollectionFlowMutator<T extends DefaultContextSchema> {
  constructor(private context: CollectionFlowContext<T>) {}
  initializeFlow(): void { /* ... */ }
  updateAdditionalInformation(): void { /* ... */ }
}

// Usage
const context = new CollectionFlowContext(initialContext);
const mutator = new CollectionFlowMutator(context);
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between f6a4fd3 and 250273f.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (12)
  • apps/backoffice-v2/package.json (2 hunks)
  • apps/backoffice-v2/src/domains/workflows/fetchers.ts (3 hunks)
  • apps/kyb-app/src/components/organisms/DynamicUI/Page/hooks/usePageErrors/usePageErrors.ts (2 hunks)
  • apps/kyb-app/src/domains/collection-flow/collection-flow.api.ts (2 hunks)
  • apps/kyb-app/src/helpers/prepareInitialUIState.ts (2 hunks)
  • packages/common/src/utils/collection-flow-manager/collection-flow-manager.ts (1 hunks)
  • packages/common/src/utils/collection-flow-manager/collection-flow-manager.unit.test.ts (1 hunks)
  • packages/common/src/utils/collection-flow-manager/helpers/config-helper.ts (1 hunks)
  • packages/common/src/utils/collection-flow-manager/helpers/state-helper.ts (1 hunks)
  • services/workflows-service/prisma/data-migrations (1 hunks)
  • services/workflows-service/scripts/workflows/runtime/generate-initial-collection-flow-example.ts (2 hunks)
  • services/workflows-service/src/workflow/workflow.service.ts (7 hunks)
🚧 Files skipped from review as they are similar to previous changes (6)
  • apps/backoffice-v2/package.json
  • apps/kyb-app/src/components/organisms/DynamicUI/Page/hooks/usePageErrors/usePageErrors.ts
  • apps/kyb-app/src/domains/collection-flow/collection-flow.api.ts
  • packages/common/src/utils/collection-flow-manager/collection-flow-manager.unit.test.ts
  • packages/common/src/utils/collection-flow-manager/helpers/config-helper.ts
  • services/workflows-service/prisma/data-migrations
🔇 Additional comments (9)
apps/kyb-app/src/helpers/prepareInitialUIState.ts (1)

4-4: LGTM!

The import is correctly placed and properly utilized in the code.

packages/common/src/utils/collection-flow-manager/helpers/state-helper.ts (1)

69-73: Well implemented null-safe step completion check

Good use of optional chaining and nullish coalescing operator for safe property access.

services/workflows-service/scripts/workflows/runtime/generate-initial-collection-flow-example.ts (3)

6-30: Previous review comment about type safety and error handling is still applicable

The existing review comment correctly identified issues with type assertions, error handling, and infinite loop risk in the getStepsInOrder function.


48-69: Previous review comment about type safety and hardcoded values is still applicable

The existing review comment correctly identified issues with type safety and hardcoded values in the initialContext object.


90-90: Verify context structure before database creation

The context is assigned directly from collectionFlowManager without validation.

Let's verify the context structure in the codebase:

✅ Verification successful

Based on the search results, I can now generate the final response:

Context initialization is properly handled before database creation

The code shows that initializeCollectionFlowContext() is called before using the context, and the context follows the DefaultContextSchema type from @ballerine/common. The context is consistently handled across the codebase:

  • Context is initialized via initializeCollectionFlowContext() before being used
  • The workflow service properly spreads and merges the context with metadata
  • The collection flow service has proper type safety through DefaultContextSchema
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for context structure definitions and validations
rg -A 10 "interface CollectionFlowContext" packages/common/src/
rg -A 10 "type CollectionFlowContext" packages/common/src/

Length of output: 126


Script:

#!/bin/bash
# Let's try searching in the services directory and with a broader pattern
rg -A 10 "CollectionFlowContext" services/

# Also search for the manager class to understand context usage
rg -A 5 "class CollectionFlowManager" services/

# Look for context validation patterns
rg "validateContext|validateFlowContext" services/

Length of output: 5174


Script:

#!/bin/bash
# Let's look at the CollectionFlowManager implementation to understand context initialization
rg -A 15 "initializeCollectionFlowContext" services/

# Also search for the context property definition in the manager
ast-grep --pattern 'class $_Manager {
  $$$
  context
  $$$
}'

Length of output: 3832


Script:

#!/bin/bash
# Let's look for the CollectionFlowManager class implementation
rg -A 20 "class CollectionFlowManager" services/

# And search for any type definitions or interfaces related to the context
rg -A 10 "type.*Context|interface.*Context" services/

Length of output: 13012

apps/backoffice-v2/src/domains/workflows/fetchers.ts (2)

9-9: LGTM! Good use of shared enum for type safety.

The import of CollectionFlowStates from the common package ensures consistent state values across the application.


154-154: LGTM! Appropriate omission of collectionFlow from child workflows.

The omission of collectionFlow from child workflows' context is consistent with the schema changes and maintains a clean hierarchy.

services/workflows-service/src/workflow/workflow.service.ts (2)

125-131: Well-structured type definition and constant declaration!

The implementation follows TypeScript best practices by:

  • Using a union type for compile-time safety
  • Making the array readonly to prevent modifications
  • Using const assertion for better type inference

2179-2202: 🛠️ Refactor suggestion

Refactor state management for better maintainability.

The collection flow state management logic is complex and lacks proper error handling and state transition validation.

Consider extracting the state management logic into a dedicated method:

+  private async updateCollectionFlowState(
+    context: any,
+    currentState: string,
+    eventType: string,
+  ): Promise<any> {
+    try {
+      const nextCollectionFlowState = COLLECTION_FLOW_EVENTS_WHITELIST.includes(eventType)
+        ? eventType
+        : COLLECTION_FLOW_EVENTS_WHITELIST.includes(currentState)
+        ? currentState
+        : undefined;
+
+      this.logger.log('Next collection flow state', {
+        nextCollectionFlowState: nextCollectionFlowState || 'N/A',
+      });
+
+      if (!nextCollectionFlowState) return context;
+
+      const collectionFlowManager = new CollectionFlowManager(context);
+
+      if (currentState in CollectionFlowStates) {
+        // Validate state transition
+        if (!this.isValidStateTransition(currentState, nextCollectionFlowState)) {
+          throw new Error(`Invalid state transition from ${currentState} to ${nextCollectionFlowState}`);
+        }
+        collectionFlowManager.state().collectionFlowState = currentState;
+      }
+
+      return collectionFlowManager.context;
+    } catch (error) {
+      this.logger.error('Failed to update collection flow state', {
+        error,
+        currentState,
+        eventType,
+      });
+      throw error;
+    }
+  }

-      let context = snapshot.machine?.context;
-
-      // Checking if event type is candidate for "revision" state
-      const nextCollectionFlowState = COLLECTION_FLOW_EVENTS_WHITELIST.includes(type)
-        ? type
-        : // Using current state of workflow for approved, rejected, failed
-        COLLECTION_FLOW_EVENTS_WHITELIST.includes(currentState)
-        ? currentState
-        : undefined;
-
-      this.logger.log('Next collection flow state', {
-        nextCollectionFlowState: nextCollectionFlowState || 'N/A',
-      });
-
-      if (nextCollectionFlowState) {
-        const collectionFlowManager = new CollectionFlowManager(context);
-
-        if (currentState in CollectionFlowStates) {
-          collectionFlowManager.state().collectionFlowState = currentState;
-        }
-
-        context = collectionFlowManager.context;
-      }
+      const context = await this.updateCollectionFlowState(
+        snapshot.machine?.context,
+        currentState,
+        type,
+      );

Likely invalid or redundant comment.

Comment on lines +7 to +13
const flow = new CollectionFlowManager(context);

const result = flow.state().isStepCompleted(page.stateName!);

if (!page.stateName) return false;

return result;
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix critical logical and safety issues in isPageCompleted.

There are several issues with the current implementation:

  1. The null check is performed after using page.stateName with non-null assertion
  2. The function could return an incorrect result if stateName is null but result is truthy
  3. Creating a new CollectionFlowManager instance for each call is inefficient

Apply this diff to fix the issues:

-export const isPageCompleted = (page: UIPage, context: CollectionFlowContext) => {
-  const flow = new CollectionFlowManager(context);
-
-  const result = flow.state().isStepCompleted(page.stateName!);
-
-  if (!page.stateName) return false;
-
-  return result;
+export const isPageCompleted = (
+  page: UIPage,
+  context: CollectionFlowContext,
+  flow?: CollectionFlowManager
+) => {
+  if (!page.stateName) return false;
+  
+  const flowManager = flow ?? new CollectionFlowManager(context);
+  return flowManager.state().isStepCompleted(page.stateName);
};
📝 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 flow = new CollectionFlowManager(context);
const result = flow.state().isStepCompleted(page.stateName!);
if (!page.stateName) return false;
return result;
export const isPageCompleted = (
page: UIPage,
context: CollectionFlowContext,
flow?: CollectionFlowManager
) => {
if (!page.stateName) return false;
const flowManager = flow ?? new CollectionFlowManager(context);
return flowManager.state().isStepCompleted(page.stateName);
};

@@ -16,7 +23,8 @@ export const prepareInitialUIState = (
isRevision,
elements: {},
};
if (pages[0]?.stateName === context.state) return initialUIState;

if (pages[0]?.stateName === context.collectionFlow?.state?.uiState) return initialUIState;
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Codebase verification

Based on the implementation and usage context, I can now provide the final response:

Early return is incorrect and should be removed

The early return condition is problematic because:

  • It returns an empty elements object when the first page's state matches the UI state
  • This skips the initialization of page states in the elements object, which is required for proper state tracking
  • The function is used in CollectionFlow.tsx to initialize states for all pages, and this early return breaks that requirement

The correct behavior should be to always initialize states for all pages, regardless of the current UI state. Remove the early return condition:

if (pages[0]?.stateName === context.collectionFlow?.state?.uiState) return initialUIState;
🔗 Analysis chain

Verify the early return condition.

The early return when pages[0]?.stateName === context.collectionFlow?.state?.uiState could skip initialization of other pages' states. Please verify if this is the intended behavior.

Let's analyze the usage of this condition:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Search for similar patterns of early returns based on UI state
# to understand if this is a common pattern or potentially incorrect.

echo "Searching for similar UI state checks..."
rg -A 3 "collectionFlow\?\.state\?\.uiState"

echo "Searching for tests that verify this behavior..."
rg -l "prepareInitialUIState.*test"

Length of output: 1494


Script:

#!/bin/bash
# Let's analyze the prepareInitialUIState function implementation and its usage

# First, get the full implementation of prepareInitialUIState
echo "=== prepareInitialUIState implementation ==="
rg -A 20 "^export.*prepareInitialUIState" apps/kyb-app/src/helpers/prepareInitialUIState.ts

# Check where this function is being used
echo -e "\n=== Usage of prepareInitialUIState ==="
rg "prepareInitialUIState"

# Look for state management related tests
echo -e "\n=== State management related tests ==="
fd "state.*test" -t f

Length of output: 1527

Comment on lines +20 to +21
console.log(`UI State transition from ${this.uiState} to ${uiState}`);
this.context.collectionFlow!.state!.uiState = uiState;
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Replace console.log with proper logging utility

Direct console.log usage should be replaced with a proper logging utility that supports different log levels and structured logging.

Consider implementing a logging service:

interface ILogger {
  debug(message: string, context?: Record<string, unknown>): void;
  info(message: string, context?: Record<string, unknown>): void;
  // ... other levels
}

// Then use it like:
this.logger.info('UI State transition', {
  from: this.uiState,
  to: uiState
});

Comment on lines +5 to +9
constructor(private context: DefaultContextSchema) {
if (!this.context.collectionFlow?.state) {
throw new Error('Collection flow state is not set.');
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Enhance constructor validation with more descriptive error handling

While the constructor validates state existence, it could be more robust and provide better error context.

 constructor(private context: DefaultContextSchema) {
-  if (!this.context.collectionFlow?.state) {
-    throw new Error('Collection flow state is not set.');
+  if (!this.context.collectionFlow) {
+    throw new Error('Collection flow is not initialized in context');
+  }
+  if (!this.context.collectionFlow.state) {
+    throw new Error('Collection flow state is not initialized');
   }
 }
📝 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
constructor(private context: DefaultContextSchema) {
if (!this.context.collectionFlow?.state) {
throw new Error('Collection flow state is not set.');
}
}
constructor(private context: DefaultContextSchema) {
if (!this.context.collectionFlow) {
throw new Error('Collection flow is not initialized in context');
}
if (!this.context.collectionFlow.state) {
throw new Error('Collection flow state is not initialized');
}
}

Comment on lines +75 to +81
override(state: NonNullable<NonNullable<DefaultContextSchema['collectionFlow']>['state']>) {
this.context.collectionFlow!.state = state;

console.log('StateHelper, context override', this.context.collectionFlow!.state);

return this.context;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Simplify type definition and add state validation

The type definition is overly complex and the method lacks proper validation of the new state.

-override(state: NonNullable<NonNullable<DefaultContextSchema['collectionFlow']>['state']>) {
+type CollectionFlowState = Required<DefaultContextSchema['collectionFlow']>['state'];
+override(state: CollectionFlowState) {
+  // Validate required properties
+  if (!state.uiState || !state.collectionFlowState || !state.progress) {
+    throw new Error('Invalid state: missing required properties');
+  }
+
   this.context.collectionFlow!.state = state;
 
-  console.log('StateHelper, context override', this.context.collectionFlow!.state);
+  this.logger.info('State override completed', { newState: state });
 
   return this.context;
 }

Committable suggestion was skipped due to low confidence.

Comment on lines +71 to +75
const uiDefinition = await prismaClient.uiDefinition.findFirst({
where: {
workflowDefinitionId,
},
});
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Add error handling for database operations

The database query lacks error handling and proper type checking for the result.

Consider adding proper error handling:

-  const uiDefinition = await prismaClient.uiDefinition.findFirst({
-    where: {
-      workflowDefinitionId,
-    },
-  });
+  const uiDefinition = await prismaClient.uiDefinition.findFirst({
+    where: {
+      workflowDefinitionId,
+    },
+  }).catch(error => {
+    throw new Error(`Failed to fetch UI definition: ${error.message}`);
+  });
+
+  if (!uiDefinition) {
+    throw new Error(`UI definition not found for workflow ${workflowDefinitionId}`);
+  }
📝 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 uiDefinition = await prismaClient.uiDefinition.findFirst({
where: {
workflowDefinitionId,
},
});
const uiDefinition = await prismaClient.uiDefinition.findFirst({
where: {
workflowDefinitionId,
},
}).catch(error => {
throw new Error(`Failed to fetch UI definition: ${error.message}`);
});
if (!uiDefinition) {
throw new Error(`UI definition not found for workflow ${workflowDefinitionId}`);
}

Comment on lines +77 to +83
const collectionFlowManager = new CollectionFlowManager(initialContext, {
apiUrl: env.APP_API_URL,
steps: await getStepsInOrder(uiDefinition as UiDefinition),
});

collectionFlowManager.initializeCollectionFlowContext();

Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Add error handling for CollectionFlowManager operations

The initialization of CollectionFlowManager and its context lacks error handling.

Consider adding proper error handling:

-  const collectionFlowManager = new CollectionFlowManager(initialContext, {
-    apiUrl: env.APP_API_URL,
-    steps: await getStepsInOrder(uiDefinition as UiDefinition),
-  });
-
-  collectionFlowManager.initializeCollectionFlowContext();
+  try {
+    const steps = await getStepsInOrder(uiDefinition);
+    if (!steps.length) {
+      throw new Error('No steps found in UI definition');
+    }
+
+    const collectionFlowManager = new CollectionFlowManager(initialContext, {
+      apiUrl: env.APP_API_URL,
+      steps,
+    });
+
+    collectionFlowManager.initializeCollectionFlowContext();
+  } catch (error) {
+    throw new Error(`Failed to initialize collection flow: ${error.message}`);
+  }
📝 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 collectionFlowManager = new CollectionFlowManager(initialContext, {
apiUrl: env.APP_API_URL,
steps: await getStepsInOrder(uiDefinition as UiDefinition),
});
collectionFlowManager.initializeCollectionFlowContext();
try {
const steps = await getStepsInOrder(uiDefinition);
if (!steps.length) {
throw new Error('No steps found in UI definition');
}
const collectionFlowManager = new CollectionFlowManager(initialContext, {
apiUrl: env.APP_API_URL,
steps,
});
collectionFlowManager.initializeCollectionFlowContext();
} catch (error) {
throw new Error(`Failed to initialize collection flow: ${error.message}`);
}

Comment on lines +119 to +130
collectionFlow: z
.object({
stepsProgress: z
.record(
z.string(),
z.object({
// TODO Until backwards compatibility is handled
number: z.number().default(0),
isCompleted: z.boolean(),
}),
)
.or(z.undefined()),
config: z.object({
apiUrl: z.string().url(),
steps: z.array(z.object({ stateName: z.string(), orderNumber: z.number() })),
}),
state: z.object({
uiState: z.string(),
collectionFlowState: z.enum(Object.values(CollectionFlowStates) as [string, ...string[]]),
progress: z.record(z.string(), z.object({ isCompleted: z.boolean() })),
}),
additionalInformation: z.record(z.string(), z.unknown()).optional(),
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Enhance schema validation for better type safety and data integrity.

While the schema structure is good, consider adding these validations:

  1. Ensure steps array is non-empty
  2. Validate uniqueness of step order numbers
  3. Ensure state names are unique
  4. Validate that progress keys correspond to defined state names

Apply this diff to strengthen the schema:

     collectionFlow: z
       .object({
         config: z.object({
           apiUrl: z.string().url(),
-          steps: z.array(z.object({ stateName: z.string(), orderNumber: z.number() })),
+          steps: z
+            .array(z.object({ 
+              stateName: z.string(),
+              orderNumber: z.number().int().nonnegative()
+            }))
+            .min(1, 'At least one step is required')
+            .refine(
+              steps => new Set(steps.map(s => s.orderNumber)).size === steps.length,
+              'Step order numbers must be unique'
+            )
+            .refine(
+              steps => new Set(steps.map(s => s.stateName)).size === steps.length,
+              'Step state names must be unique'
+            ),
         }),
         state: z.object({
           uiState: z.string(),
           collectionFlowState: z.enum(Object.values(CollectionFlowStates) as [string, ...string[]]),
-          progress: z.record(z.string(), z.object({ isCompleted: z.boolean() })),
+          progress: z.record(
+            z.string(),
+            z.object({ isCompleted: z.boolean() })
+          ).refine(
+            (progress, ctx) => {
+              const stateNames = ctx.parent.config?.steps?.map(s => s.stateName) || [];
+              return Object.keys(progress).every(key => stateNames.includes(key));
+            },
+            'Progress keys must correspond to defined state names'
+          ),
         }),
         additionalInformation: z.record(z.string(), z.unknown()).optional(),
       })
📝 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
collectionFlow: z
.object({
stepsProgress: z
.record(
z.string(),
z.object({
// TODO Until backwards compatibility is handled
number: z.number().default(0),
isCompleted: z.boolean(),
}),
)
.or(z.undefined()),
config: z.object({
apiUrl: z.string().url(),
steps: z.array(z.object({ stateName: z.string(), orderNumber: z.number() })),
}),
state: z.object({
uiState: z.string(),
collectionFlowState: z.enum(Object.values(CollectionFlowStates) as [string, ...string[]]),
progress: z.record(z.string(), z.object({ isCompleted: z.boolean() })),
}),
additionalInformation: z.record(z.string(), z.unknown()).optional(),
collectionFlow: z
.object({
config: z.object({
apiUrl: z.string().url(),
steps: z
.array(z.object({
stateName: z.string(),
orderNumber: z.number().int().nonnegative()
}))
.min(1, 'At least one step is required')
.refine(
steps => new Set(steps.map(s => s.orderNumber)).size === steps.length,
'Step order numbers must be unique'
)
.refine(
steps => new Set(steps.map(s => s.stateName)).size === steps.length,
'Step state names must be unique'
),
}),
state: z.object({
uiState: z.string(),
collectionFlowState: z.enum(Object.values(CollectionFlowStates) as [string, ...string[]]),
progress: z.record(
z.string(),
z.object({ isCompleted: z.boolean() })
).refine(
(progress, ctx) => {
const stateNames = ctx.parent.config?.steps?.map(s => s.stateName) || [];
return Object.keys(progress).every(key => stateNames.includes(key));
},
'Progress keys must correspond to defined state names'
),
}),
additionalInformation: z.record(z.string(), z.unknown()).optional(),
})

Comment on lines +1558 to +1586
// Initializing Collection Flow
const collectionFlowManager = new CollectionFlowManager(
{
...workflowRuntimeData.context,
},
{
apiUrl: env.APP_API_URL,
steps: await getStepsInOrder(uiDefinition as UiDefinition),
additionalInformation: {
customerCompany: customer.displayName,
},
},
);

collectionFlowManager.initializeCollectionFlowContext();

workflowRuntimeData = await this.workflowRuntimeDataRepository.updateStateById(
workflowRuntimeData.id,
{
data: {
context: {
...workflowRuntimeData.context,
...collectionFlowManager.context,
metadata: {
...(workflowRuntimeData.context.metadata ?? {}),
token: workflowToken.token,
collectionFlowUrl: env.COLLECTION_FLOW_URL,
webUiSDKUrl: env.WEB_UI_SDK_URL,
},
},
} as InputJsonValue,
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Add error handling and consolidate context updates.

The collection flow initialization lacks error handling and has scattered context updates that could lead to inconsistent states.

Consider refactoring to:

  1. Add try-catch for CollectionFlowManager initialization
  2. Validate required configuration values
  3. Consolidate context updates
-          // Initializing Collection Flow
-          const collectionFlowManager = new CollectionFlowManager(
-            {
-              ...workflowRuntimeData.context,
-            },
-            {
-              apiUrl: env.APP_API_URL,
-              steps: await getStepsInOrder(uiDefinition as UiDefinition),
-              additionalInformation: {
-                customerCompany: customer.displayName,
-              },
-            },
-          );
-
-          collectionFlowManager.initializeCollectionFlowContext();
-
-          workflowRuntimeData = await this.workflowRuntimeDataRepository.updateStateById(
-            workflowRuntimeData.id,
-            {
-              data: {
-                context: {
-                  ...collectionFlowManager.context,
-                  metadata: {
-                    ...(workflowRuntimeData.context.metadata ?? {}),
-                    token: workflowToken.token,
-                    collectionFlowUrl: env.COLLECTION_FLOW_URL,
-                    webUiSDKUrl: env.WEB_UI_SDK_URL,
-                  },
-                } as InputJsonValue,
-                projectId: currentProjectId,
-              },
-            },
-            transaction,
-          );
+          try {
+            if (!env.APP_API_URL || !env.COLLECTION_FLOW_URL || !env.WEB_UI_SDK_URL) {
+              throw new Error('Missing required environment variables for collection flow');
+            }
+
+            const collectionFlowManager = new CollectionFlowManager(
+              {
+                ...workflowRuntimeData.context,
+              },
+              {
+                apiUrl: env.APP_API_URL,
+                steps: await getStepsInOrder(uiDefinition as UiDefinition),
+                additionalInformation: {
+                  customerCompany: customer.displayName,
+                },
+              },
+            );
+
+            collectionFlowManager.initializeCollectionFlowContext();
+
+            const updatedContext = {
+              ...collectionFlowManager.context,
+              metadata: {
+                ...(workflowRuntimeData.context.metadata ?? {}),
+                token: workflowToken.token,
+                collectionFlowUrl: env.COLLECTION_FLOW_URL,
+                webUiSDKUrl: env.WEB_UI_SDK_URL,
+              },
+            };
+
+            workflowRuntimeData = await this.workflowRuntimeDataRepository.updateStateById(
+              workflowRuntimeData.id,
+              {
+                data: {
+                  context: updatedContext as InputJsonValue,
+                  projectId: currentProjectId,
+                },
+              },
+              transaction,
+            );
+          } catch (error) {
+            this.logger.error('Failed to initialize collection flow', {
+              error,
+              workflowId: workflowRuntimeData.id,
+            });
+            throw new InternalServerErrorException('Failed to initialize collection flow');
+          }
📝 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
// Initializing Collection Flow
const collectionFlowManager = new CollectionFlowManager(
{
...workflowRuntimeData.context,
},
{
apiUrl: env.APP_API_URL,
steps: await getStepsInOrder(uiDefinition as UiDefinition),
additionalInformation: {
customerCompany: customer.displayName,
},
},
);
collectionFlowManager.initializeCollectionFlowContext();
workflowRuntimeData = await this.workflowRuntimeDataRepository.updateStateById(
workflowRuntimeData.id,
{
data: {
context: {
...workflowRuntimeData.context,
...collectionFlowManager.context,
metadata: {
...(workflowRuntimeData.context.metadata ?? {}),
token: workflowToken.token,
collectionFlowUrl: env.COLLECTION_FLOW_URL,
webUiSDKUrl: env.WEB_UI_SDK_URL,
},
},
} as InputJsonValue,
try {
if (!env.APP_API_URL || !env.COLLECTION_FLOW_URL || !env.WEB_UI_SDK_URL) {
throw new Error('Missing required environment variables for collection flow');
}
const collectionFlowManager = new CollectionFlowManager(
{
...workflowRuntimeData.context,
},
{
apiUrl: env.APP_API_URL,
steps: await getStepsInOrder(uiDefinition as UiDefinition),
additionalInformation: {
customerCompany: customer.displayName,
},
},
);
collectionFlowManager.initializeCollectionFlowContext();
const updatedContext = {
...collectionFlowManager.context,
metadata: {
...(workflowRuntimeData.context.metadata ?? {}),
token: workflowToken.token,
collectionFlowUrl: env.COLLECTION_FLOW_URL,
webUiSDKUrl: env.WEB_UI_SDK_URL,
},
};
workflowRuntimeData = await this.workflowRuntimeDataRepository.updateStateById(
workflowRuntimeData.id,
{
data: {
context: updatedContext as InputJsonValue,
projectId: currentProjectId,
},
},
transaction,
);
} catch (error) {
this.logger.error('Failed to initialize collection flow', {
error,
workflowId: workflowRuntimeData.id,
});
throw new InternalServerErrorException('Failed to initialize collection flow');
}

@alonp99 alonp99 merged commit bcdc8a4 into dev Oct 30, 2024
8 of 10 checks passed
@alonp99 alonp99 deleted the illiar/feat/app-state branch October 30, 2024 21: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