Skip to content

refactor(shared): make the argument guards tree-shakeable - #37

Merged
ExorTek merged 1 commit into
masterfrom
refactor/shared-asserts-treeshake
Aug 6, 2026
Merged

refactor(shared): make the argument guards tree-shakeable#37
ExorTek merged 1 commit into
masterfrom
refactor/shared-asserts-treeshake

Conversation

@ExorTek

@ExorTek ExorTek commented Aug 6, 2026

Copy link
Copy Markdown
Owner

Independent. Internal only — no public API changes.

bindAsserts built one object holding all fourteen guards and handed it back. A bundler can include or exclude that function, but it cannot take the object apart, so the destructure list in each internal/guards.js decided nothing about what shipped. Every package that touched the module carried all fourteen: jwks called three and shipped fourteen, and assertBoolean reached fifteen published packages without a single call site anywhere in the repo.

Each guard is now a standalone make… factory taking the package's wrap, and each internal/guards.js imports the ones it calls:

import { makeAssertObject, makeInvalidArgument } from '@exortek/shared/asserts';

const wrap = (message, extra) => new JweError(ErrorCode.INVALID_ARGUMENT, message, extra);

export const assertObject = makeAssertObject(wrap);
export const invalidArgument = makeInvalidArgument(wrap);

Named imports are something a bundler can follow, so the rest is dropped. The composer layer (bindAsserts / defineGuards) is gone — binding a guard is one line now, and the indirection bought nothing.

Measured across the built bundles

package before after
jwk 178 KB 146 KB -18.2%
otp 239 KB 200 KB -16.5%
security 454 KB 411 KB -9.4%
jws 254 KB 236 KB -6.9%
crypto 475 KB 443 KB -6.7%
session 333 KB 311 KB -6.6%
total 2.07 MB 1.88 MB -9.0%

oauth2 is unaffected — it never used this module.

Behaviour is unchanged: same errors, same codes, same messages, and every call site still imports the same names from its local guards module. AGENTS.md's guard convention is rewritten to match, and now says why the import list has to track the call sites rather than leaving it as style.

`bindAsserts` built one object holding all fourteen guards and handed it back.
A bundler can include or exclude that function, but it cannot take the object
apart, so the destructure list in each `internal/guards.js` decided nothing
about what shipped. Every package that touched the module carried all fourteen
guards: jwks called three and shipped fourteen, and `assertBoolean` reached
fifteen published packages without a single call site anywhere in the repo.

Each guard is now a standalone `make…` factory taking the package's `wrap`,
and each `internal/guards.js` imports the ones it calls and binds them. Named
imports are something a bundler can follow, so the rest is dropped. The
composer layer (`bindAsserts` / `defineGuards`) is gone — binding a guard is
now one line, and the indirection bought nothing.

Behaviour is unchanged: same errors, same codes, same messages, and every call
site still imports the same names from its local guards module.

Measured across the built bundles: otp -16.5%, jwk -18.2%, security -9.4%,
jws -6.9%, crypto -6.7%, session -6.6% — about -9% over those packages
together. oauth2 is unaffected because it never used this module.

AGENTS.md's guard convention is rewritten to match, and now says why the
import list has to track the call sites rather than leaving it as style.
Copilot AI lite review requested due to automatic review settings August 6, 2026 09:12

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@ExorTek
ExorTek merged commit 0a94f13 into master Aug 6, 2026
3 checks passed
@ExorTek
ExorTek deleted the refactor/shared-asserts-treeshake branch August 6, 2026 09:27
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