-
Notifications
You must be signed in to change notification settings - Fork 0
refactor: Add new utils package and replace lodash/ramda with es-toolkit/native alternatives #424
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
refactor: Add new utils package and replace lodash/ramda with es-toolkit/native alternatives #424
Conversation
🦋 Changeset detectedLatest commit: d1e6478 The changes in this PR will be included in the next version bump. This PR includes changesets to release 11 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
WalkthroughA comprehensive refactoring effort has been undertaken to replace utility libraries like Ramda and Lodash with a new Changes
Sequence DiagramsequenceDiagram
participant Dev as Developer
participant Utils as @halfdomelabs/utils
participant EsTk as es-toolkit
participant Project as Project Packages
Dev->>Utils: Create new utility package
Utils->>EsTk: Leverage es-toolkit functions
Project->>Utils: Import utility functions
Project->>EsTk: Import additional utility functions
Project->>Project: Replace Ramda/Lodash calls
The sequence diagram illustrates the transition from multiple utility libraries to a centralized utility package with supplementary support from Finishing Touches
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
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)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
🧹 Nitpick comments (7)
packages/project-builder-web/src/pages/apps/new.page.tsx (1)
Line range hint
1-1: Overall Migration AssessmentThe migration from lodash to es-toolkit is largely consistent and well-executed across all files. Key observations:
- Syntax adaptations are consistent (e.g., array syntax for iteratees)
- Most functionality is preserved
- One potential behavioral change in
AdminSectionsForm.tsxwhere the sorting criteria were modifiedConsider documenting these syntax differences between lodash and es-toolkit in your team's migration guide to help other developers with similar migrations.
packages/fastify-generators/src/writers/pothos/args.ts (1)
84-87: Consider adding type assertion for argMap.The
safeMergeAllWithOptionsreturn type might need explicit typing to ensure type safety with the subsequentmapValuesoperation.- const argMap = safeMergeAllWithOptions(argOutputs); + const argMap = safeMergeAllWithOptions(argOutputs) as Record<string, PothosArgOutput>;packages/project-builder-lib/src/references/deserialize-schema.ts (1)
76-77: Consider using native JavaScript features where possible.For simple path access, consider using optional chaining and nullish coalescing instead of the compatibility
get/setfunctions. This could improve performance and reduce dependency on compatibility layers.Example for the parent path access:
-const parentId = parentPath - ? (get(data, parentPath) as string) - : undefined; +const parentId = parentPath + ? data?.[(parentPath as string[])[0]]?.[(parentPath as string[])[1]] as string + : undefined;Note: Only apply this optimization for simple paths where the structure is known. For dynamic deep paths, continue using
get/set.Also applies to: 89-91, 102-102
packages/project-builder-web/src/pages/data/models/_hooks/useModelForm.ts (1)
178-183: Consider simplifying the sort criteria.The sorting implementation is correct but can be simplified since you're only sorting by a single field.
- draftConfig.models = sortBy( - [ - ...draftConfig.models.filter((m) => m.id !== updatedModel.id), - updatedModel, - ], - [(m) => m.name], - ); + draftConfig.models = sortBy( + [ + ...draftConfig.models.filter((m) => m.id !== updatedModel.id), + updatedModel, + ], + (m) => m.name, + );packages/fastify-generators/src/generators/core/fastify-server/index.ts (1)
183-197: Consider simplifying the plugin ordering logic.While the implementation is correct, the switch statement could be simplified using a mapping object for better maintainability.
+ const PRIORITY_MAP = { + EARLY: 0, + MIDDLE: 1, + END: 2, + }; + const orderedPlugins = sortBy(plugins, [ - (plugin) => { - switch (plugin.orderPriority) { - case 'EARLY': { - return 0; - } - case 'END': { - return 2; - } - default: { - return 1; - } - } - }, + (plugin) => PRIORITY_MAP[plugin.orderPriority ?? 'MIDDLE'], ]);packages/core-generators/src/writers/typescript/imports.ts (1)
300-303: Consider adding error handling for merge conflicts.The
safeMergeAllWithOptionsis used withallowEqualValues: true, which might silently ignore merge conflicts. Consider adding explicit error handling for cases where values differ.packages/core-generators/src/writers/typescript/source-file.ts (1)
614-620: LGTM! Array flattening uses native JavaScript API.Good use of native
flat()method. However, consider making the comment more descriptive:- ].flat(/* The depth is always 2 */ 2); + ].flat(/* Flatten nested arrays: [[...], [...]] -> [...] */ 2);
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Lite
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (74)
.changeset/fuzzy-experts-exercise.md(1 hunks).changeset/thin-radios-pretend.md(1 hunks)packages/core-generators/package.json(1 hunks)packages/core-generators/src/generators/node/typescript/index.ts(2 hunks)packages/core-generators/src/writers/typescript/code-entries.ts(2 hunks)packages/core-generators/src/writers/typescript/import-order.ts(1 hunks)packages/core-generators/src/writers/typescript/import-order.unit.test.ts(2 hunks)packages/core-generators/src/writers/typescript/imports.ts(5 hunks)packages/core-generators/src/writers/typescript/source-file.ts(8 hunks)packages/fastify-generators/package.json(1 hunks)packages/fastify-generators/src/generators/core/app-module/index.ts(2 hunks)packages/fastify-generators/src/generators/core/config-service/index.ts(2 hunks)packages/fastify-generators/src/generators/core/fastify-server/index.ts(2 hunks)packages/fastify-generators/src/generators/core/request-service-context/index.ts(3 hunks)packages/fastify-generators/src/generators/core/root-module/index.ts(3 hunks)packages/fastify-generators/src/generators/core/service-context/index.ts(4 hunks)packages/fastify-generators/src/generators/pothos/pothos-enums-file/index.ts(2 hunks)packages/fastify-generators/src/generators/pothos/pothos-types-file/index.ts(2 hunks)packages/fastify-generators/src/generators/prisma/_shared/crud-method/data-method.ts(4 hunks)packages/fastify-generators/src/generators/prisma/embedded-relation-transformer/index.ts(1 hunks)packages/fastify-generators/src/writers/pothos/args.ts(2 hunks)packages/fastify-generators/src/writers/prisma-schema/schema.ts(2 hunks)packages/project-builder-lib/package.json(1 hunks)packages/project-builder-lib/src/compiler/app-compiler-spec.ts(1 hunks)packages/project-builder-lib/src/parser/index.ts(4 hunks)packages/project-builder-lib/src/plugins/imports/loader.ts(3 hunks)packages/project-builder-lib/src/references/deserialize-schema.ts(7 hunks)packages/project-builder-lib/src/references/fix-ref-deletions.ts(5 hunks)packages/project-builder-lib/src/references/ref-builder.ts(7 hunks)packages/project-builder-lib/src/references/serialize-schema.ts(2 hunks)packages/project-builder-lib/src/tools/model-merger/index.ts(3 hunks)packages/project-builder-lib/src/utils/merge.ts(2 hunks)packages/project-builder-lib/src/web/hooks/useResettableForm.ts(3 hunks)packages/project-builder-server/package.json(1 hunks)packages/project-builder-server/src/compiler/backend/fastify.ts(1 hunks)packages/project-builder-server/src/compiler/backend/feature.ts(1 hunks)packages/project-builder-server/src/compiler/web/index.ts(1 hunks)packages/project-builder-web/package.json(0 hunks)packages/project-builder-web/src/app/AppLayout/AppBreadcrumbs.tsx(2 hunks)packages/project-builder-web/src/pages/apps/AppsLayout.page.tsx(1 hunks)packages/project-builder-web/src/pages/apps/edit/admin/AdminEditSectionForm.tsx(2 hunks)packages/project-builder-web/src/pages/apps/edit/admin/AdminSectionsForm.tsx(2 hunks)packages/project-builder-web/src/pages/apps/list.page.tsx(1 hunks)packages/project-builder-web/src/pages/apps/new.page.tsx(2 hunks)packages/project-builder-web/src/pages/data/_layout.tsx(2 hunks)packages/project-builder-web/src/pages/data/enums/EnumsSidebarList.tsx(2 hunks)packages/project-builder-web/src/pages/data/enums/hooks/useEnumForm.tsx(2 hunks)packages/project-builder-web/src/pages/data/models/_components/ModelsSidebarList.tsx(2 hunks)packages/project-builder-web/src/pages/data/models/_hooks/useModelForm.ts(2 hunks)packages/project-builder-web/src/pages/settings/components/FeatureForm.tsx(2 hunks)packages/project-builder-web/src/pages/settings/project-settings.tsx(2 hunks)packages/react-generators/package.json(1 hunks)packages/react-generators/src/generators/admin/admin-crud-edit/index.ts(1 hunks)packages/react-generators/src/generators/admin/admin-crud-embedded-form/index.ts(1 hunks)packages/react-generators/src/generators/apollo/react-apollo/index.ts(2 hunks)packages/react-generators/src/generators/core/_utils/render-routes.ts(2 hunks)packages/react-generators/src/generators/core/react-config/index.ts(2 hunks)packages/react-generators/src/writers/graphql/index.ts(3 hunks)packages/utils/.gitignore(1 hunks)packages/utils/.prettierignore(1 hunks)packages/utils/LICENSE(1 hunks)packages/utils/README.md(1 hunks)packages/utils/eslint.config.js(1 hunks)packages/utils/package.json(1 hunks)packages/utils/prettier.config.js(1 hunks)packages/utils/src/index.ts(1 hunks)packages/utils/src/objects/index.ts(1 hunks)packages/utils/src/objects/safe-merge.ts(2 hunks)packages/utils/src/objects/safe-merge.unit.test.ts(1 hunks)packages/utils/tsconfig.build.json(1 hunks)packages/utils/tsconfig.json(1 hunks)packages/utils/vitest.config.ts(1 hunks)tests/simple/packages/backend/baseplate/.clean/package.json(0 hunks)tests/simple/packages/backend/package.json(0 hunks)
💤 Files with no reviewable changes (3)
- tests/simple/packages/backend/baseplate/.clean/package.json
- tests/simple/packages/backend/package.json
- packages/project-builder-web/package.json
✅ Files skipped from review due to trivial changes (19)
- packages/utils/src/objects/index.ts
- packages/utils/eslint.config.js
- packages/utils/.prettierignore
- packages/utils/vitest.config.ts
- packages/utils/prettier.config.js
- packages/project-builder-server/src/compiler/backend/fastify.ts
- packages/utils/.gitignore
- packages/utils/tsconfig.json
- .changeset/fuzzy-experts-exercise.md
- packages/utils/tsconfig.build.json
- packages/utils/package.json
- packages/react-generators/src/generators/apollo/react-apollo/index.ts
- packages/utils/LICENSE
- packages/react-generators/src/generators/admin/admin-crud-embedded-form/index.ts
- .changeset/thin-radios-pretend.md
- packages/utils/README.md
- packages/project-builder-server/src/compiler/web/index.ts
- packages/utils/src/index.ts
- packages/fastify-generators/src/generators/prisma/embedded-relation-transformer/index.ts
🔇 Additional comments (69)
packages/project-builder-web/src/pages/settings/project-settings.tsx (2)
12-12: LGTM! Import change aligns with refactoring goals.The replacement of lodash's pick with es-toolkit's pick is consistent with the PR objectives.
Line range hint
31-35: Verify es-toolkit's pick behavior matches lodash.The implementation looks correct, but let's ensure es-toolkit's
pickfunction handles edge cases (undefined/null values) similarly to lodash's implementation.Run this script to find other usages and verify consistent behavior:
packages/project-builder-lib/src/utils/merge.ts (1)
1-1: Verify compatibility ofmergeWithfromes-toolkitYou've replaced
R.mergeWithfrom Ramda withmergeWithfromes-toolkit. Ensure thatmergeWithfromes-toolkitprovides the same deep merging capabilities and handles customizer functions as expected.Please review the
mergeWithimplementation ines-toolkitto confirm it aligns with your intended merge behavior.packages/core-generators/src/writers/typescript/import-order.unit.test.ts (1)
34-34: ReplacetoReversed()with supported array reversal methodSame issue as above. Ensure consistent use of array reversal methods for compatibility.
packages/project-builder-lib/src/references/serialize-schema.ts (2)
10-12: Type constraint enhancement improves type safety.The addition of
extends Record<string, unknown>constraint toTValueensures that the function only accepts object types, preventing potential runtime errors.
3-3: Verify es-toolkit/compat functions maintain lodash compatibility.The migration from lodash to es-toolkit/compat functions (
get,set,unset) appears correct. However, let's verify that the behavior remains identical, especially for edge cases.Also applies to: 17-17, 20-20, 25-25, 34-34
✅ Verification successful
es-toolkit/compat functions maintain lodash compatibility ✓
The verification of test files shows comprehensive coverage of edge cases and complex scenarios, including:
- Nested property access
- Optional references
- Parent-child relationships
- Error handling
The functions are used consistently across the codebase in critical serialization/deserialization operations, demonstrating equivalent behavior to lodash.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Search for any tests that verify the behavior of these utility functions rg -l "test.*serialize.*schema" --type tsLength of output: 43
Script:
#!/bin/bash # Find the exact file and nearby tests fd "serialize-schema" --type f # Look for usage patterns of get/set/unset from es-toolkit rg "from 'es-toolkit/compat'" -B1 -A1 --type ts # Search for test files in the project-builder-lib fd "test" --type f --extension ts --extension spec --extension test packages/project-builder-lib/ # Look for actual usage of these functions rg "(?:get|set|unset)\(" --type ts -A 2 packages/project-builder-lib/src/references/Length of output: 8510
Script:
#!/bin/bash # Check the test files for verification of edge cases rg -A 5 "describe|it\(" packages/project-builder-lib/src/references/serialize-schema.unit.test.ts rg -A 5 "describe|it\(" packages/project-builder-lib/src/references/deserialize-schema.unit.test.ts # Look for any imports of lodash in tests for comparison rg "lodash" packages/project-builder-lib/src/references/Length of output: 3034
packages/project-builder-lib/src/web/hooks/useResettableForm.ts (1)
4-4: Verify deep comparison behavior of es-toolkit's isEqual.The replacement of lodash's
isEqualwith es-toolkit's version is used for comparing form values. This is critical for form state management and needs careful verification.Also applies to: 29-29, 41-41
packages/project-builder-web/src/pages/apps/AppsLayout.page.tsx (1)
10-10: Note API difference in es-toolkit's sortBy implementation.The migration from lodash's
sortByto es-toolkit's version required changing the syntax to use an array of key functions. While functionally equivalent, the implementation is different:
- Lodash:
_.sortBy(apps, (m) => m.name)- es-toolkit:
sortBy(apps, [(app) => app.name])Also applies to: 17-17
✅ Verification successful
Migration to es-toolkit's sortBy is complete and consistent
All instances in the codebase follow the new array-based key function pattern required by es-toolkit's sortBy implementation.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Search for other sortBy usage patterns to ensure consistent migration rg "sortBy.*=>" --type tsLength of output: 1196
packages/react-generators/src/generators/core/_utils/render-routes.ts (1)
4-4: Verify grouping behavior with edge cases.The migration from lodash's
groupByto es-toolkit's version handles route grouping. Critical to verify:
- Null/undefined layout key handling
- 'no-layout' default behavior
- Empty groups handling
Also applies to: 13-15
✅ Verification successful
Grouping behavior verified, implementation is correct
The es-toolkit
groupByimplementation properly handles all edge cases:
- Null/undefined layout keys default to 'no-layout' via nullish coalescing
- Missing layouts are validated with clear error messages
- Empty groups are handled naturally by the grouping operation
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Search for tests verifying route grouping behavior rg -A 5 "test.*routes.*group" --type test # Check for other groupBy usage patterns rg "groupBy.*=>" --type tsLength of output: 896
Script:
#!/bin/bash # Find route grouping implementation ast-grep --pattern 'groupBy($array, $fn)' packages/react-generators/src/generators/core/_utils/render-routes.ts # Search for layout key handling rg -A 5 "layout.*key" packages/react-generators/src/generators/core/_utils/render-routes.tsLength of output: 517
packages/project-builder-web/src/pages/apps/list.page.tsx (1)
6-6: LGTM! Note the array syntax for iteratees.The migration from lodash to es-toolkit looks good. Note that es-toolkit's
sortByexpects an array of iteratees, hence the[(app) => app.name]syntax.Also applies to: 14-14
packages/project-builder-web/src/pages/apps/edit/admin/AdminSectionsForm.tsx (1)
6-6: Verify if removing feature-based sorting was intentional.The previous implementation sorted by both
featureandnameproperties, but the new implementation only sorts byname. This changes the display order of sections.If you want to maintain the same sorting behavior, consider:
- const sortedSections = sortBy(appConfig.sections ?? [], [ - (section) => section.name, - ]); + const sortedSections = sortBy(appConfig.sections ?? [], [ + (section) => section.feature, + (section) => section.name, + ]);Also applies to: 25-27
✅ Verification successful
Sorting by name only appears to be an intentional improvement
The simplified sorting by
nameis a reasonable change as:
- No other instances of feature-based section sorting were found in the codebase
- Single-property sorting provides a more predictable and consistent user experience
- The
featureproperty might be optional, making name-based sorting more reliable🏁 Scripts executed
The following scripts were executed for the analysis:
Error: No shell scripts found
Script:
#!/bin/bash # Find section type definition ast-grep --pattern 'type Section = { $$$ }' # Find interface definitions related to sections ast-grep --pattern 'interface $_ { $$$ section$_: $_ $$$ }' # Look for similar sortBy usage patterns rg "sortBy.*section" -A 2 -B 2 # Check if there are any test files related to section sorting fd "test|spec" | rg -i "section.*sort"Length of output: 753
Script:
#!/bin/bash # Look for type definitions with 'section' in broader context ast-grep --pattern 'type $_ = { feature?: $_ name: $_ $$$ }' # Look for documentation about sections rg -i "section" README.md || true rg -i "section" docs/ || true # Find any config schema files fd "schema.json|config.json" | xargs cat # Look for feature-based grouping or sorting rg "feature.*section" -A 2 -B 2Length of output: 5760
packages/project-builder-web/src/pages/data/_layout.tsx (1)
5-5: LGTM! Clean migration to es-toolkit.The migration from lodash's
maxByto es-toolkit'smaxBymaintains identical functionality while reducing dependencies.Also applies to: 18-18
packages/project-builder-web/src/pages/apps/new.page.tsx (1)
17-17: LGTM! Note the explicit iteratee function syntax.The migration from lodash to es-toolkit looks good. Note that while lodash allowed the shorthand string syntax
'name', es-toolkit requires an explicit iteratee function(app) => app.name.Also applies to: 45-45
packages/utils/src/objects/safe-merge.ts (3)
1-8: LGTM! Clean interface design with good documentation.The
MergeOptionsinterface is well-documented and the imports fromes-toolkitalign with the PR's objective of replacing lodash/ramda.
55-66: LGTM! Good backward compatibility.The
safeMergeAllfunction maintains the original API while leveraging the new implementation, making it easier for consumers to migrate.
49-50: Validate array input before flattening.The
flat()operation assumes the input array contains valid elements. Consider adding validation to handle potential edge cases.packages/project-builder-server/src/compiler/backend/feature.ts (1)
12-12: LGTM! Clean import update.The import statement has been correctly updated to use the new
@halfdomelabs/utilspackage, aligning with the PR's objective of centralizing utility functions.packages/fastify-generators/src/writers/pothos/args.ts (1)
4-5: LGTM! Clean utility function migration.The imports have been correctly updated to use
@halfdomelabs/utilsandes-toolkit, aligning with the PR's objective.packages/project-builder-lib/src/compiler/app-compiler-spec.ts (1)
3-4: LGTM! Clean import update.The import statement has been correctly updated to use the new
@halfdomelabs/utilspackage, maintaining the same functionality while aligning with the PR's objective.packages/fastify-generators/src/generators/pothos/pothos-enums-file/index.ts (1)
14-14: LGTM! Correct usage of es-toolkit's sortBy.The replacement of Ramda's sortBy with es-toolkit's version is done correctly. The iteratee function is properly wrapped in an array as required by es-toolkit's API.
Also applies to: 77-77
packages/core-generators/src/writers/typescript/import-order.ts (1)
111-120: Verify browser/node.js compatibility for Array.prototype.toSorted.While the native implementation is more efficient,
Array.prototype.toSorted()is an ES2023 feature that might not be supported in all target environments.Run this script to check the minimum Node.js version in package.json and verify compatibility:
✅ Verification successful
Array.prototype.toSorted() usage is compatible with the codebase requirements
The codebase requires Node.js ^20.0.0 which fully supports this ES2023 feature.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Check Node.js version requirements and verify toSorted support # Note: toSorted requires Node.js >= 20.0.0 # Check engines field in package.json jq -r '.engines.node' package.json # Check if any transpilation/polyfill is configured fd -e js -e json -e yaml -e yml babelLength of output: 82
packages/project-builder-web/src/pages/data/models/_components/ModelsSidebarList.tsx (1)
11-11: LGTM! Consistent usage of es-toolkit's sortBy.The replacement of lodash's sortBy with es-toolkit's version maintains the same functionality and follows the consistent pattern across the codebase.
Also applies to: 35-35
packages/project-builder-web/src/pages/data/enums/EnumsSidebarList.tsx (1)
11-11: LGTM! Consistent usage of es-toolkit's sortBy.The replacement of lodash's sortBy with es-toolkit's version maintains the same functionality and follows the consistent pattern across the codebase.
Also applies to: 35-35
packages/fastify-generators/src/generators/core/app-module/index.ts (1)
10-10: LGTM! Clean replacement of Ramda's mapObjIndexed.The replacement of
R.mapObjIndexedwithmapValuesfrom es-toolkit maintains the same functionality while reducing external dependencies.Also applies to: 78-80
packages/fastify-generators/src/writers/prisma-schema/schema.ts (1)
1-1: LGTM! Clean replacement of Ramda's sortBy.The replacement of
R.sortBywithsortByfrom es-toolkit maintains the same sorting behavior while reducing external dependencies.Also applies to: 128-128
packages/fastify-generators/src/generators/pothos/pothos-types-file/index.ts (1)
13-13: LGTM! Clean replacement of Ramda's sortBy with improved readability.The replacement of
R.sortBywithsortByfrom es-toolkit maintains the same sorting behavior while making the category ordering logic more explicit and easier to understand.Also applies to: 83-90
packages/project-builder-lib/src/references/deserialize-schema.ts (1)
3-4: LGTM! Clean replacement of lodash utilities.The replacements maintain the same functionality while reducing external dependencies:
groupBy,keyBy,uniqfrom es-toolkit coreget,setfrom es-toolkit/compat for path-based operationspackages/project-builder-lib/src/references/fix-ref-deletions.ts (2)
3-4: LGTM! Good separation of imports.The separation between
es-toolkitandes-toolkit/compatimports is correct. Thecompatimports (get,groupBy,set) are for older browser compatibility, whilesortByis from the main package.
53-53: Verify the behavior of replaced utility functions.The replacements look correct, but let's verify that the
es-toolkitfunctions maintain the same behavior as their lodash counterparts, especially for:
get/setwith nested pathsgroupBywith object arrayssortBywith descending order (-o.idx)Also applies to: 70-70, 83-83, 87-87, 92-92, 115-117, 121-123
✅ Verification successful
The es-toolkit utility functions maintain lodash-compatible behavior
The codebase shows consistent usage of es-toolkit utilities that matches lodash patterns:
get/sethandle nested paths correctly (e.g., form error access)groupByworks with object arrays as expected (e.g., entity grouping)sortBysupports both simple keys and complex sorting with descending order🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Search for tests that verify the behavior of these utility functions rg -A 5 "describe.*('(get|set|groupBy|sortBy)"Length of output: 149
Script:
#!/bin/bash # Search for test files rg -l "describe.*['\"].*?(get|set|groupBy|sortBy)" # Search for actual usage patterns of these utilities rg -A 2 "import.*\{.*(get|set|groupBy|sortBy).*\}" # Search for specific usage patterns ast-grep --pattern 'get($_, $_)' ast-grep --pattern 'set($_, $_, $_)' ast-grep --pattern 'groupBy($_, $_)' ast-grep --pattern 'sortBy($_, $_)'Length of output: 51611
packages/react-generators/src/generators/core/react-config/index.ts (1)
95-97: Verify the sorting behavior remains consistent.The replacement of Ramda's
sortBywithes-toolkit'ssortBylooks correct for sorting config entries by key name. However, let's verify that no config entries are using special characters that might sort differently.✅ Verification successful
Sorting behavior verified as consistent
The replacement is safe as the config entries use standard environment variable style naming (e.g., 'VITE_ENVIRONMENT'), and both implementations use standard string comparison for sorting.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Search for config entry definitions to verify key naming patterns rg -A 5 "configEntries.*=.*{"Length of output: 133
Script:
#!/bin/bash # Search for configEntries variable declarations and assignments ast-grep --pattern 'const configEntries = $_' # Search for config entries with properly escaped regex rg -A 5 'configEntries\s*=\s*\{' # Also search for any direct assignments to configEntries rg -A 5 'configEntries\[[^]]+\]\s*='Length of output: 628
Script:
#!/bin/bash # Find ConfigEntry type definition ast-grep --pattern 'type ConfigEntry = $_' ast-grep --pattern 'interface ConfigEntry $_' # Find how configEntryMap is populated rg -B 5 -A 5 'configEntryMap' packages/react-generators/src/generators/core/react-config/index.ts # Look for any key validation or constraints rg -l 'validateConfigKey|validateKey|isValidKey' packages/react-generators/Length of output: 1529
packages/project-builder-web/src/pages/settings/components/FeatureForm.tsx (1)
105-105: LGTM! Simple and correct usage of sortBy.The replacement of lodash's
sortBywithes-toolkit'ssortByis straightforward and correct. The sorting by feature name will maintain the same behavior.packages/project-builder-lib/src/plugins/imports/loader.ts (2)
1-1: LGTM! Clean import of utility functions.The import of
keyByandmapValuesfromes-toolkitis clean and follows the project's new direction of usinges-toolkitinstead of lodash.
42-42: Verify the behavior of keyBy and mapValues in plugin initialization.The replacements look correct, but let's verify that the
es-toolkitfunctions maintain the same behavior as their lodash counterparts, especially in the critical plugin initialization logic:
keyByshould maintain unique keysmapValuesshould handle undefined values correctlyAlso applies to: 45-45, 133-133
✅ Verification successful
The
es-toolkitreplacements forkeyByandmapValuesare safe to useThe unit tests demonstrate that:
- Plugin IDs are properly handled as unique keys
- Dependencies and implementations are correctly mapped and passed between plugins
- The initialization order is maintained as expected
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Search for tests that verify plugin initialization rg -A 5 "describe.*('plugin.*initialization" # Search for edge cases in plugin module definitions ast-grep --pattern 'const $module = { exports: $$$, dependencies: $$$ }'Length of output: 224
Script:
#!/bin/bash # Search for test files related to plugins fd -e test.ts -e spec.ts -e test.js -e spec.js | grep -i "plugin" # Search for keyBy usage in plugin-related files rg "keyBy.*plugin" -A 3 # Search for mapValues usage in plugin-related files rg "mapValues.*plugin" -A 3 # Search for plugin module type definitions or interfaces ast-grep --pattern 'interface PluginModule { $$$ }'Length of output: 1308
Script:
#!/bin/bash # Check the unit test contents cat "packages/project-builder-lib/src/plugins/imports/loader.unit.test.ts" # Look for error handling around plugin IDs rg "duplicate.*plugin|invalid.*plugin" -A 3 # Search for plugin module type definition ast-grep --pattern 'type PluginModule = { $$$ }' # Search for validation functions rg "validate.*plugin|check.*plugin" -A 3Length of output: 3373
packages/project-builder-web/src/pages/data/enums/hooks/useEnumForm.tsx (1)
119-126: Verify the sorting behavior remains consistent.The transition from lodash's
sortByto es-toolkit'ssortBylooks correct. However, ensure that the new sorting implementation maintains the same order as before, especially since es-toolkit'ssortByexpects an array of functions while lodash's version accepted a direct function.✅ Verification successful
Sorting implementation is correctly migrated and consistent
The codebase shows a complete migration to es-toolkit's
sortBywith consistent usage patterns. The enum sorting by name property is implemented uniformly across all enum-related components, maintaining consistent behavior.🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Check for any other instances of lodash's sortBy to ensure consistent migration rg "_.sortBy|lodash.*sortBy" -A 3Length of output: 35
Script:
#!/bin/bash # Search for any sortBy imports or usage with broader patterns echo "=== Searching for sortBy imports ===" rg "import.*sortBy|from.*sortBy" -A 1 echo -e "\n=== Searching for sortBy function calls ===" rg "sortBy\(" -A 2 echo -e "\n=== Checking the specific file history ===" git log -p packages/project-builder-web/src/pages/data/enums/hooks/useEnumForm.tsx | rg -A 5 -B 5 "sortBy"Length of output: 11513
packages/project-builder-lib/src/tools/model-merger/index.ts (2)
Line range hint
150-154: Ensure consistent array comparison behavior.The transition to es-toolkit's
isEqualfor comparingprimaryKeyFieldRefsarrays looks correct. However, verify that the array comparison behavior remains consistent, especially for arrays containing complex objects or when order matters.Consider adding unit tests specifically for array comparison scenarios to ensure the behavior remains consistent across different types of primary key configurations.
63-63: Verify deep equality comparison behavior.The transition from lodash's
isEqualto es-toolkit'sisEquallooks correct. However, ensure that es-toolkit's implementation handles deep object comparison similarly to lodash's version, as this is critical for detecting field changes.✅ Verification successful
Transition to es-toolkit's isEqual is complete and correct
The codebase shows consistent usage of es-toolkit's isEqual (v1.31.0) for deep object comparison across multiple components, including complex nested structures, arrays, and objects, confirming its suitability as a replacement for lodash's isEqual.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Check for any remaining instances of lodash's isEqual rg "_.isEqual|lodash.*isEqual" -A 3Length of output: 37
Script:
#!/bin/bash # Find imports and usages of isEqual rg "import.*isEqual|isEqual\(" -A 2 # Look for es-toolkit package in dependencies fd package.json --exec grep -A 5 "es-toolkit" # Find the actual implementation if available ast-grep --pattern 'function isEqual($_) { $$$ }'Length of output: 5332
packages/fastify-generators/src/generators/core/config-service/index.ts (1)
130-133: Verify config entries remain consistently ordered.The transition from Ramda's
sortByto es-toolkit'ssortBylooks correct. The sorting affects both the configuration object and the generated environment files, so ensure that:
- The order remains consistent across all generated files
- The array-based sorting criteria
[(entry) => entry[0]]maintains the same behavior as before✅ Verification successful
Config entries sorting remains consistent across the codebase
The transition to es-toolkit's
sortByis complete and consistent. The array-based sorting criteria[(entry) => entry[0]]maintains the same behavior, ensuring consistent ordering across all generated files.🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Check for any remaining instances of Ramda's sortBy rg "R.sortBy|ramda.*sortBy" -A 3Length of output: 34
Script:
#!/bin/bash # Check for any sorting-related imports and implementations echo "=== Checking imports ===" rg "import.*sort.*from" -g "*.ts" -g "*.js" echo -e "\n=== Checking config-related files ===" fd "config" -e ts -e js --exec rg -l "sort" echo -e "\n=== Checking test files for sorting assertions ===" fd "test|spec" -e ts -e js --exec rg -l "sort.*config|config.*sort" echo -e "\n=== Examining the config service implementation ===" ast-grep --pattern 'sortBy($$$)'Length of output: 11589
packages/fastify-generators/src/generators/core/request-service-context/index.ts (2)
137-139: Ensure consistent passthrough mapping behavior.The transition to es-toolkit's
mapValuesfor context passthroughs looks correct. However, verify that:
- The callback function receives parameters in the same order
- The mapping behavior remains consistent for all passthrough scenarios
Consider adding unit tests to verify the mapping behavior, especially for edge cases where the order of parameters might affect the outcome.
125-125: Verify context field mapping behavior.The transition from Ramda's
mapObjIndexedto es-toolkit'smapValuesfor context fields looks correct. However, ensure that the mapping maintains the same behavior, especially regarding the order of parameters and access to keys.✅ Verification successful
Mapping behavior transition verified successfully
The transition from
mapObjIndexedtomapValuesis correct. The parameter order and mapping behavior are consistent across multiple generator modules, and the mapper function doesn't require key access.🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Check for any remaining instances of Ramda's mapObjIndexed rg "R.mapObjIndexed|ramda.*mapObjIndexed" -A 3Length of output: 48
Script:
#!/bin/bash # Get the complete context of the mapping operation ast-grep --pattern 'mapValues(contextFields, $_)' -A 5 -B 5 # Look for test files related to request-service-context fd "request-service-context.*test" --type f --exec cat {} # Check for mapValues implementation or usage patterns rg "mapValues.*type" -A 2 -B 2Length of output: 6847
packages/project-builder-web/src/pages/data/models/_hooks/useModelForm.ts (1)
19-19: LGTM! Import change aligns with the refactoring goal.The change from lodash to es-toolkit's sortBy function aligns with the PR objective.
packages/fastify-generators/src/generators/core/service-context/index.ts (2)
17-17: LGTM! Import change aligns with the refactoring goal.The change from ramda to es-toolkit's mapValues function aligns with the PR objective.
109-109: LGTM! Correct usage of mapValues.The mapValues function is correctly used to replace ramda's mapObjIndexed while maintaining the same functionality.
Also applies to: 125-125
packages/fastify-generators/src/generators/core/root-module/index.ts (2)
16-17: LGTM! Import changes align with the refactoring goal.The changes to use es-toolkit and @halfdomelabs/utils align with the PR objective.
156-157: LGTM! Correct usage of new utility functions.The implementation correctly uses:
- mapValues for transforming expressions
- safeMergeAllWithOptions for merging field configurations
Also applies to: 199-199
packages/fastify-generators/src/generators/core/fastify-server/index.ts (1)
17-17: LGTM! Import change aligns with the refactoring goal.The change from ramda to es-toolkit's sortBy function aligns with the PR objective.
packages/react-generators/src/writers/graphql/index.ts (1)
1-1: LGTM! Clean replacement of lodash's isEqual with es-toolkit.The migration from lodash to es-toolkit for the
isEqualfunction is clean and maintains the same functionality.Also applies to: 200-200, 314-314
packages/project-builder-lib/src/parser/index.ts (1)
3-4: LGTM! Clean replacement of ramda utilities with modern alternatives.The migration from ramda to es-toolkit and @halfdomelabs/utils is well-executed:
cloneDeepreplaces ramda's deep clonekeyByreplaces ramda's indexBysafeMergeprovides safe merging capabilitiesAlso applies to: 40-40, 128-128
packages/core-generators/src/generators/node/typescript/index.ts (1)
10-10: LGTM! Clean replacement of ramda's mergeAll.The migration from ramda's mergeAll to @halfdomelabs/utils' safeMergeAll for merging tsconfig.json sections is clean and maintains the same functionality.
Also applies to: 312-312
packages/core-generators/src/writers/typescript/imports.ts (1)
3-4: LGTM! Clean replacement of ramda's array operations with native alternatives.The migration from ramda to native array methods and es-toolkit utilities is well-executed:
- Native
flatMapreplaces ramda's flattenuniqfrom es-toolkit for duplicate filteringAlso applies to: 278-280, 288-290
packages/react-generators/src/generators/admin/admin-crud-edit/index.ts (1)
160-161: Great use of nativeObject.fromEntries!Good replacement of lodash's
zipObjectwith the nativeObject.fromEntries. This change reduces external dependencies while maintaining the same functionality.packages/fastify-generators/src/generators/prisma/_shared/crud-method/data-method.ts (2)
Line range hint
13-14: Well-organized imports from es-toolkit!Good separation of imports between core es-toolkit and compat modules. Using specific imports helps with tree-shaking.
Line range hint
153-159: Good choice usingsafeMergeAllWithOptions!The replacement of Ramda's
mergeAllwithsafeMergeAllWithOptionsprovides better control over the merge behavior and maintains type safety.packages/core-generators/src/writers/typescript/code-entries.ts (1)
55-71: Excellent use of native array methods with es-toolkit'suniq!The changes improve code readability and maintainability by:
- Using native
flat()method for array flattening- Maintaining consistent method chaining
- Leveraging
uniqfrom es-toolkit for efficient deduplicationpackages/project-builder-lib/src/references/ref-builder.ts (2)
Line range hint
431-435: Good use of es-toolkit'sset!Clean replacement of lodash's set utility while maintaining the same functionality for updating nested object properties.
Line range hint
598-637: Verify the entity reference resolution logic.This is a critical section handling entity references and name resolution. While the replacement of lodash utilities with es-toolkit's
keyByandpullis good, please ensure:
- The entity resolution loop behaves correctly with the new
pullimplementation- Edge cases are handled properly (e.g., circular references)
- Error messages are still accurate
✅ Verification successful
Entity reference resolution logic verified successfully
The implementation is robust and safe:
- Circular references are prevented by design through type constraints and validation
- The entity resolution loop has proper termination conditions
- The pull operation is used correctly to maintain the integrity of the pending entities list
- Error handling is comprehensive with specific error messages
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Check for potential circular references in entity definitions ast-grep --pattern 'class $_ { $$$ addEntity($_, $_) { $$$ addEntity($_, $_) $$$ } $$$ }'Length of output: 111
Script:
#!/bin/bash # Check the implementation and usage of pull function rg "pull\(" -A 3 -B 3 # Look for entity resolution patterns and error handling ast-grep --pattern 'throw new Error(`Could not resolve $$$`)' # Check for nameRefPath usage rg "nameRefPath" -A 2 -B 2Length of output: 5631
packages/react-generators/package.json (1)
39-39: LGTM! Dependency changes align with refactoring goals.The addition of es-toolkit and removal of lodash/ramda aligns with the PR's objective of standardizing utility functions.
packages/fastify-generators/package.json (1)
39-42: LGTM! Consistent dependency updates across packages.The addition of @halfdomelabs/utils and es-toolkit, along with the removal of ramda, maintains consistency with the refactoring effort across packages.
packages/project-builder-lib/package.json (1)
42-42: LGTM! Completes the dependency standardization across packages.The addition of @halfdomelabs/utils and es-toolkit completes the standardization of utility functions across all packages.
packages/core-generators/package.json (1)
40-40: LGTM! Dependencies updated correctly.The changes align with the PR objectives by replacing ramda with @halfdomelabs/utils.
packages/project-builder-server/package.json (1)
45-45: LGTM! Dependencies updated correctly.The addition of @halfdomelabs/utils aligns with the PR objectives.
packages/project-builder-web/src/app/AppLayout/AppBreadcrumbs.tsx (1)
5-5: LGTM! Verify the sorting behavior remains unchanged.The replacement of lodash's orderBy with es-toolkit's orderBy maintains the same function signature and should provide identical sorting behavior.
Let's verify that es-toolkit's orderBy maintains the same behavior as lodash:
Also applies to: 37-37
✅ Verification successful
✓ Sorting behavior verified
The migration from lodash to es-toolkit's orderBy is complete and correct. The usage pattern is consistent, and no lodash orderBy imports remain in the codebase.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Verify that es-toolkit's orderBy is used consistently across the codebase # and that there are no remaining lodash orderBy imports # Check for any remaining lodash orderBy imports rg -l "import.*\{.*orderBy.*\}.*from ['\"](lodash|lodash-es)['\"]" # Check for consistent usage pattern of es-toolkit's orderBy rg "orderBy\((.*?),.*\[['\"]\w+['\"]],.*\[['\"]asc['\"]]\)" -A 1Length of output: 344
packages/project-builder-web/src/pages/apps/edit/admin/AdminEditSectionForm.tsx (1)
20-20: LGTM! Note the different usage pattern for es-toolkit's sortBy.The replacement of lodash's sortBy with es-toolkit's sortBy requires a slight modification in usage pattern. The new pattern using an iteratee function
(section) => section.nameis more type-safe than the string shorthand 'name'.Let's verify the consistent usage of es-toolkit's sortBy across the codebase:
Also applies to: 76-83
✅ Verification successful
Verified: es-toolkit's sortBy usage is consistent across the codebase
All instances of sortBy have been migrated from lodash to es-toolkit and follow the new pattern using array-wrapped arrow functions. No remaining lodash sortBy imports found.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Verify that es-toolkit's sortBy is used consistently with the new pattern # and that there are no remaining lodash sortBy imports # Check for any remaining lodash sortBy imports rg -l "import.*\{.*sortBy.*\}.*from ['\"](lodash|lodash-es)['\"]" # Check for consistent usage pattern of es-toolkit's sortBy rg "sortBy\((.*?),.*\[(.*?) =>.*\]" -A 1Length of output: 1810
packages/core-generators/src/writers/typescript/source-file.ts (7)
12-12: LGTM! Import changes align with refactoring goals.The addition of
mapValuesanduniqWithfrom 'es-toolkit' successfully replaces the removed Ramda imports.
Line range hint
140-160: LGTM! Constructor refactoring maintains functionality.The replacement of Ramda's
mapObjIndexedwithmapValuesfrom es-toolkit preserves the original logic while aligning with the refactoring goals.
164-175: LGTM! Data structure initialization uses native JavaScript API.The replacement of Ramda's
fromPairswith nativeObject.fromEntriesis a good choice as it:
- Reduces external dependencies
- Uses well-supported native JavaScript API
- Maintains the same functionality
345-380: LGTM! Consistent refactoring of map operations.The replacement of Ramda's
mapObjIndexedwithmapValuesis consistently applied across all code entry transformations while maintaining type safety and error handling.
629-632: LGTM! Import string handling is clean and concise.The simplified approach to handling import strings improves readability while maintaining the same functionality.
641-641: LGTM! Import flattening uses native array methods.Good use of native
flatMapfor flattening import arrays.
652-653: LGTM! Header block deduplication uses es-toolkit.The replacement of Ramda's uniq with es-toolkit's
uniqWithmaintains the same deduplication logic with the custom comparison function.
| } | ||
| if (typeof a === 'object' && typeof b === 'object') { | ||
| return R.mergeWith(deepMergeRightUniq, a, b); | ||
| return mergeWith(a, b, deepMergeRightUniq); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix array handling in deepMergeRightUniq function
The check typeof a === 'object' && typeof b === 'object' includes arrays because arrays are objects in JavaScript. This means that when both a and b are arrays, the array-specific merge logic might be bypassed, leading to incorrect behavior.
To ensure arrays are handled properly, move the array check before the object check.
Apply this diff to correct the logic:
export function deepMergeRightUniq(a: unknown, b: unknown): unknown {
if (a == null) {
return b;
}
if (b == null) {
return a;
}
+ if (Array.isArray(a) && Array.isArray(b)) {
+ return [...new Set([...(a as unknown[]), ...(b as unknown[])])];
+ }
if (typeof a === 'object' && typeof b === 'object') {
return mergeWith(a, b, deepMergeRightUniq);
}
- if (Array.isArray(a) && Array.isArray(b)) {
- return [...new Set([...(a as unknown[]), ...(b as unknown[])])];
- }
return b;
}📝 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.
| return mergeWith(a, b, deepMergeRightUniq); | |
| export function deepMergeRightUniq(a: unknown, b: unknown): unknown { | |
| if (a == null) { | |
| return b; | |
| } | |
| if (b == null) { | |
| return a; | |
| } | |
| if (Array.isArray(a) && Array.isArray(b)) { | |
| return [...new Set([...(a as unknown[]), ...(b as unknown[])])]; | |
| } | |
| if (typeof a === 'object' && typeof b === 'object') { | |
| return mergeWith(a, b, deepMergeRightUniq); | |
| } | |
| return b; | |
| } |
| './', | ||
| ]); | ||
| expect(sortByImportOrder(R.reverse(input), {})).toEqual([ | ||
| expect(sortByImportOrder(input.toReversed(), {})).toEqual([ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Replace toReversed() with supported array reversal method
The method toReversed() is part of a newer ECMAScript proposal and may not be supported in all environments, potentially causing runtime errors.
Replace input.toReversed() with input.slice().reverse() to ensure compatibility:
expect(sortByImportOrder(input, {})).toEqual([
'fs',
'chalk',
'../foo',
'./bar',
'./',
]);
-expect(sortByImportOrder(input.toReversed(), {})).toEqual([
+expect(sortByImportOrder(input.slice().reverse(), {})).toEqual([
'fs',
'chalk',
'../foo',
'./bar',
'./',
]);📝 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.
| expect(sortByImportOrder(input.toReversed(), {})).toEqual([ | |
| expect(sortByImportOrder(input.slice().reverse(), {})).toEqual([ |
| it('throws an error when keys overlap', () => { | ||
| const items = [{ a: 1 }, { b: 2 }, { b: 3 }]; | ||
| expect(() => safeMergeAll(...items)).toThrowError( | ||
| expect(() => safeMergeAll(items)).toThrowError( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct the function call to safeMergeAll
In this test case, safeMergeAll is called with an array argument, but the function expects individual objects as arguments (spread syntax). Passing the array directly may lead to unexpected behavior.
Adjust the function call to spread the items:
const items = [{ a: 1 }, { b: 2 }, { b: 3 }];
-expect(() => safeMergeAll(items)).toThrowError(
+expect(() => safeMergeAll(...items)).toThrowError(
'Cannot merge key b because it already exists.',
);📝 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.
| expect(() => safeMergeAll(items)).toThrowError( | |
| expect(() => safeMergeAll(...items)).toThrowError( |
Summary by CodeRabbit
Based on the comprehensive summary of changes, here are the release notes:
New Features
@halfdomelabs/utilspackage to centralize utility functions across the codebaseDependency Updates
lodashandramdalibraries withes-toolkitin multiple packages@halfdomelabs/utilsas a workspace dependency across various projectsPerformance Improvements
Refactoring
Licensing