8000 feat: expose each query's source file and name it in its errors by colinhacks · Pull Request #34 · colinhacks/reylo · GitHub
[go: up one dir, main page]

Skip to content

feat: expose each query's source file and name it in its errors - #34

Merged
colinhacks merged 2 commits into
mainfrom
query-source
Oct 22, 2026
Merged

colinhacks merged 2 commits into
mainfrom
query-source

Conversation

@colinhacks
Copy link
Copy Markdown
Owner

Each .sql import now knows which file it came from, so an app can tag its logs and traces with it, and Reylo's own errors say which query failed.

  • .source: every build step writes the file's path, relative to the project's root and written with /, into the module, and the query exposes it (getUser.source === "queries/get_user.sql"). Until now the module carried it only when the statement had catalog facts to check, and only for the stale-database error. A query defined by hand with defineQuery has none (undefined).
  • Errors that name the file: Reylo's errors about a parameter's value, a column's value and the row count start with the file: queries/get_user.sql: Expected exactly one row, got 0. The driver's own errors, and Reylo's errors about the client itself, pass through unchanged.
  • Parameter errors get a TypeError subclass of their own, as decode errors already had, so .run() and .runSync() can tell them from the driver's. Both stay TypeErrors, with the same name.
  • The stack's first line takes the file too, written once: V8 writes the stack when it is first read, and Bun when the error is made.
  • Docs: one sentence beside .raw in Usage.

Test plan

  • nub run typecheck
  • nub run test (163 pass; the 35 skipped need the Postgres and MySQL servers CI starts)
  • New test: .source; the row-count, parameter and decode errors named on run and runSync, the stack included; a driver error (UNIQUE constraint failed) and a query with no file left as they were
  • The module test: a statement with no catalog facts still carries source: "queries/one.sql"
  • Under Bun 1.4.3, the message and the stack's first line name the file once
  • site: nub run build

Every build step writes the .sql file's path into the module, and the
query exposes it as .source. Reylo's errors about a parameter's value,
a column's value or the row count start with it; the driver's own
errors pass through unchanged.
Copilot AI balanced review requested due to automatic review settings October 22, 2026 21:10
@vercel
vercel Bot commented Oct 22, 2026 •
Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
reylo Ready Ready Preview Oct 22, 2026 9:17pm UTC

Request Review

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.

@pullfrog pullfrog Bot left a comment
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

ℹ️ No critical issues. One minor typing suggestion inline.

Reviewed changes

I reviewed the full diff of this PR: every .sql module now carries its source, Query exposes it, and Reylo's parameter, decode and row-count errors start with it.

  • source always emitted: sqlModule writes the root-relative path with / for every statement, not only ones with fresh. Every build step (vite, webpack, jest, the register hooks) goes through it.
  • ParameterError: a TypeError subclass that replaces every parameter-value TypeError in src/execute.ts and src/rows.ts. named() in defineQuery uses it with DecodeError to prefix only Reylo's own errors on run, runSync and with.
  • Stack patching: named() rewrites the stack's first line only when the stack was already formatted. I checked on Node 24: V8 picks up the new message if stack hasn't been read yet and keeps the old one if it has, so both branches are needed.
  • Tests: the new execute.test.ts case passes locally. The existing message assertions on loader-built modules (casts, structured, representation) are unanchored regexes, so the new prefix doesn't break them.

Pullfrog  | Fix all ➔ | Fix 👍s ➔ | View workflow run | Using claude-opus-5-5 | 𝕏

Comment thread src/index.ts Resolved
@pullfrog pullfrog Bot left a comment
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

✅ No new issues found. The prior typing suggestion is addressed.

Reviewed changes

Since the last review, one commit narrows the declared type of a .sql import's source.

  • source: string on the mapper's intersection: src/mapper.ts adds readonly source: string beside sql and raw, so app code no longer needs a !. I checked that every build path goes through sqlModule: vite, esbuild, webpack/turbopack, and the register worker used by register and jest. So the non-optional type holds at run time.
  • Not the literal path: keeping string rather than the path itself is the right call. The build resolves the root from the .sql file's own project, and the mapper resolves it from the tsconfig's, so a literal could name the wrong file in a workspace.
  • Docs capture and tests follow: site/scripts/capture-types.ts mirrors the mapper's line, site/lib/sql-modules.json is recaptured, and tests/compiled.test.ts adds source to the texts() filter and to the expected declarations for all three dialects.

Pullfrog  | View workflow run | Using claude-opus-5-5 | 𝕏

@colinhacks
colinhacks merged commit 79f5e3f into main Oct 22, 2026
4 checks passed
@colinhacks
colinhacks deleted the query-source branch October 22, 2026 21:19
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

0