Skip to content

fix: refactor install method to instead be free functions#441

Merged
wschurman merged 1 commit intomainfrom
wschurman/02-13-fix_refactor_install_method_to_instead_be_free_functions
Feb 16, 2026
Merged

fix: refactor install method to instead be free functions#441
wschurman merged 1 commit intomainfrom
wschurman/02-13-fix_refactor_install_method_to_instead_be_free_functions

Conversation

@wschurman
Copy link
Member

@wschurman wschurman commented Feb 13, 2026

Why

Asked claude extended thinking to analyze the installExtensions monkey-patching strategy we went with in #410 and compare it to other typescript ORM libraries.

It said essentially that it was ok, but most modern libraries choose not to do it that way, and instead recommended "free functions" (TIL about that term) to instantiate the loaders. (knexLoader(BlahEntity, vc))

Working with it even more, I came up with an even better method on top of free functions to keep the BlahEntity.knexLoader(vc) syntax. The strategy is to:

  1. Convert to free functions (this PR).
  2. Add PostgresEntity/ReadonlyPostgresEntity subclasses that application entities can extend that implement the static extension methods.
  3. Revert the codemod change from this PR to keep the codemod to prefer the BlahEntity.knexLoader(vc) syntax since most applications should use the subclasses (though it's not strictly necessary if they prefer the free function at callsites).
  4. Revert the codemod in the integration tests to express better syntax pattern.

How

Claude did most of this, but broadly speaking the strategy is to have the free functions, and then instead of patching the prototypes/classes for singleton caching, use a WeakMap where the core package singleton is the key and the value is the new knex-specific object.

Test Plan

Run all tests.

@wschurman wschurman force-pushed the wschurman/02-13-fix_refactor_install_method_to_instead_be_free_functions branch from a8ac359 to 3d89f3d Compare February 13, 2026 21:43
@codecov
Copy link

codecov bot commented Feb 13, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (3d4aa0e) to head (8f2c103).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##              main      #441    +/-   ##
==========================================
  Coverage   100.00%   100.00%            
==========================================
  Files          109       107     -2     
  Lines        16142     15713   -429     
  Branches      1419      1412     -7     
==========================================
- Hits         16142     15713   -429     
Flag Coverage Δ
integration 23.05% <98.71%> (-4.24%) ⬇️
unittest 95.02% <100.00%> (+0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@ide
Copy link
Member

ide commented Feb 15, 2026

The main tradeoff that comes to mind is (lack of) multiple inheritance. Maybe it doesn't matter because entities are backed by only one type of database.

@wschurman wschurman mentioned this pull request Feb 15, 2026
@wschurman wschurman force-pushed the wschurman/02-13-fix_refactor_install_method_to_instead_be_free_functions branch from bced9f8 to 429ae05 Compare February 16, 2026 00:06
@wschurman wschurman force-pushed the wschurman/02-13-fix_add_default_for_tselectedfields_for_application-instantiated_types branch from 0938147 to 2a319a4 Compare February 16, 2026 00:06
Copy link
Member Author

It's a valid tradeoff and one that if it is important enough for an application they can opt to just use the free functions added here instead of the base classes (they're equivalent as shown by the tests in the PR that adds the subclasses). For Expo's server, we use subclasses already for all our entities.

It'd be cool if mixins were officially supported in TS/JS. The other option is a higher-order component function (closest thing to mixins), something like:

class BlahEntity extends Entity { ... }

export default withKnexLoaders(BlahEntity)

But the key is that these approaches all require the free functions added here, and for now the subclass approach matches most closely to what the Expo server will need.

Copy link
Member Author

wschurman commented Feb 16, 2026

Merge activity

  • Feb 16, 8:58 PM UTC: A user started a stack merge that includes this pull request via Graphite.
  • Feb 16, 9:11 PM UTC: Graphite rebased this pull request as part of a merge.
  • Feb 16, 9:14 PM UTC: @wschurman merged this pull request with Graphite.

@wschurman wschurman changed the base branch from wschurman/02-13-fix_add_default_for_tselectedfields_for_application-instantiated_types to graphite-base/441 February 16, 2026 21:07
@wschurman wschurman changed the base branch from graphite-base/441 to main February 16, 2026 21:10
@wschurman wschurman force-pushed the wschurman/02-13-fix_refactor_install_method_to_instead_be_free_functions branch from 429ae05 to 8f2c103 Compare February 16, 2026 21:11
@wschurman wschurman merged commit 51d632d into main Feb 16, 2026
3 checks passed
@wschurman wschurman deleted the wschurman/02-13-fix_refactor_install_method_to_instead_be_free_functions branch February 16, 2026 21:14
wschurman added a commit that referenced this pull request Feb 16, 2026
…nexLoader methods (#442)

# Why

This is part 2 of the refactor described in #441.

It adds subclasses of Entity and ReadonlyEntity that supply the static `knexLoader` methods to keep the ergonomics of the extension but without the monkey-patching.

# How

Add subclasses, add test.

# Test Plan

Run test.
wschurman added a commit that referenced this pull request Feb 16, 2026
… again via subclass (#443)

# Why

Part 3 of the refactor from #441.

This reverts the codemod back to use the `BlahEntity.knexLoader(vc)` syntax.

# How

`git revert`

# Test Plan

Run the tests in codemod.
wschurman added a commit that referenced this pull request Feb 16, 2026
# Why

Part 4 of #441. This reverts the test changes to use the better pattern, though both work equivalently and are both tested.

# How

Update tests.

# Test Plan

Run tests
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

Comments