Skip to content

feat: adopt Framework immutable queries and synchronous mappings - #99

Merged
andrewzolotukhin merged 3 commits into
mainfrom
feat/framework-immutable-query-adoption
Oct 1, 2026
Merged

andrewzolotukhin merged 3 commits into
mainfrom
feat/framework-immutable-query-adoption

Conversation

@andrewzolotukhin

@andrewzolotukhin andrewzolotukhin commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Adopt Framework 0.0.0-beta-20261001112349 across Xpenser, including immutable queries and projection-aware synchronous DTO mappings.

Original request

Adopt the newly published Framework beta in Xpenser using the PR workflow. The approved scope includes the complete immutable-query migration and synchronous/projection-derived mapping cleanup, with tests, documentation, and a reviewable preview. Framework itself remains unchanged.

What changed

  • Pin all 15 directly used Framework packages to the exact beta; preserve a single shared schema installation in the lockfile.

  • Capture immutable query branches and return predicate/include callback results. Count and page reads share a filtered source; correlated subqueries use typed references.

  • Separate reusable read definitions, feature-owned mapper modules, and service orchestration. Cache only definitions/registrations per Knex connection using weak references; retain independent transaction/tenant branches.

  • Use query-derived rowSchema and getSyncMapper() for pure DTO conversions. Keep asynchronous database enrichment batched and parallel.

  • Correct storage metadata to match existing migrations: decimal(18,2) amounts, decimal(18,8) rates, and date-only exchange-rate dates. Preserve numeric DTO amounts/rates and YYYY-MM-DD public dates. No database migration or public contract change.

  • Project only public API-key fields and filter owner/revocation in SQL. Keep full credential reads confined to authentication.

  • Update immutable test doubles, database-accurate fixtures, consumer reference documentation, and preview regressions for DTOs and API-key listing/revocation.

  • The temporary framework-consumer-experience.md remains local and is not included in this PR.

  • Use a shared PostgreSQL pool factory with explicit UTC Date parameter encoding. This prevents date-only values shifting under non-UTC host timezones. The driver setting is process-wide; TIMESTAMPTZ instants remain unchanged. CI checks both default and non-UTC processes.

Reasoning

This adopts the beta's actual read contract rather than casting driver values to public DTO types. PostgreSQL regression tests caught and fixed the existing string/date storage mismatch. Shared query definitions avoid rebuilding mapping registrations for every row without sharing user filters or result caches. Application authorization, numbered pagination, enrichment, and money/date conversion policies remain explicit.

Blog post

Skipped: internal dependency/API-consumer refactor with no new public-facing feature.

Validation

  • Clean npm ci --no-audit --no-fund
  • npm run lint
  • npm run typecheck
  • npm test: 1,928 tests in 122 files
  • npm run build
  • npm run test:queries:integration: 29 tests in each of UTC and America/Los_Angeles on isolated PostgreSQL 16, using actual application migrations in disposable schemas
  • Regression coverage: immutable count/page/tenant branches; metadata/mapping executes no SQL; nullable/date/decimal decoding; scoped API-key create/authenticate/revoke; write-returning/rollback; correlated tag pruning; page/count agreement; fixed enrichment query count
  • GitHub: Lint and test — passed on 40793db
  • GitHub: Deploy PR environment — passed on 40793db
  • GitHub: Playwright e2e — 32 passed on 40793db
  • Manual preview: login, isolated budget/category creation, tagged $12.34 transaction, edit to $18.75, reload persistence, budget switching/isolation, transaction deletion, and temporary budget archive/removal. The manual edit initially missed an off-screen save button; scrolling the actual button into view confirmed saving works. Temporary QA data was removed.
  • SigNoz verification of final deployment, 2026-10-01 12:38:42–12:53:56 UTC, scoped to xpenser-api-pr-99 and xpenser-web-pr-99.

Telemetry evidence and limits

  • API and web traces/logs are present, including matching trace IDs on request logs. No ERROR/FATAL logs or migration-related SQL/read-decoding error spans were found in the checked window.
  • Five warning logs correspond to deliberate invalid email-confirmation, missing-vendor, invalid-login, and API-key validation tests (plus the expected Auth.js warning).
  • Seven error-marked client spans were classified: two deliberate 400 validation responses; five optional Brandfetch enrichment failures (two 400s and three configured 2-second timeouts). A timeout trace confirmed vendor creation still returns 201 and the page returns 200. This existing external-provider limitation is not hidden or claimed fixed by the migration.
  • API metrics are present: maximum reported event-loop p99 delay was 12.7 ms, and HTTP request counts increased during QA. This is a preview health check, not a load-test or production performance claim.
  • Web runtime/HTTP metrics explicitly skipped: the existing web setup has no metric-producing instrumentations; Framework's default instrumentation list is empty. Web traces/logs were checked. No bot interaction was exercised; bot unit/build checks passed, and live bot telemetry QA is skipped.

Query-plan timings are diagnostic only; no production latency improvement is claimed from synchronous mapping alone.

Preview regression found and fixed

The first browser run exposed a tagged-transaction write failure: a plain schema query included the ORM-only tag navigation property in generated RETURNING columns. The write now uses a storage-only schema. A new PostgreSQL test reproduces the original failure and verifies tagged transaction creation, replacement, deletion, pruning, and budget isolation; all 29 database tests now pass. A separate non-UTC run also reproduced a calendar-date shift in the driver's default parameter encoding; the shared UTC driver policy fixes it, and both timezone runs pass.

Screenshots / Preview

Preview: https://xpenser-pr-099.cleverbrush.com

No visual design changes. The passing Playwright report artifact includes the transaction screenshot from the typed-query adoption test. Final workflow run.

Manual browser QA independently verified a tagged transaction changing from $12.34 to $18.75, surviving a full reload, and remaining isolated to its budget. Cleanup restored the seeded Main budget as active.

Checklist

  • Changes are limited to Framework adoption and corresponding app tests/docs.
  • Tests and consumer documentation updated.
  • No secrets, local env files, temporary consumer proposal document, or generated build output committed.
  • Public contracts, endpoint metadata, and handlers remain aligned.

@andrewzolotukhin
andrewzolotukhin temporarily deployed to pr-99 October 1, 2026 12:14 — with GitHub Actions Inactive
@andrewzolotukhin
andrewzolotukhin temporarily deployed to pr-99 October 1, 2026 12:28 — with GitHub Actions Inactive
@andrewzolotukhin
andrewzolotukhin temporarily deployed to pr-99 October 1, 2026 12:36 — with GitHub Actions Inactive
@andrewzolotukhin
andrewzolotukhin merged commit 2ec866b into main Oct 1, 2026
4 checks passed
@andrewzolotukhin
andrewzolotukhin deleted the feat/framework-immutable-query-adoption branch October 1, 2026 13:02

This branch was previously deployed

1 inactive deployment
pr-99 — 40793db3 Deployed Oct 1, 2026 by andrewzolotukhin via Deploy PR environment #374
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant