最新资讯
nytimes.com 美众议院共和党领袖要求 Nvidia 黄仁勋闭门简报 pub.towardsai.net 忘掉我:为记忆而设计的系统中的删除难题 unite.ai Airbnb 计划推出覆盖规划、预订与客服的 AI 旅行 agent techcrunch.com Airbnb 称将于 2027 年上半年推出 AI 旅行代理 theverge.com Perplexity 推出面向工作的 AI 代理 Teammates unite.ai Five9 拟以约3.25亿美元收购 Level AI,扩展客服AI分销渠道 unite.ai Serve Robotics 向物理AI公司开放车队软件与数据 wired.com 聊天机器人广告时代到来:哪些做法有效、哪些无效 techmeme.com METR:Anthropic 删减了评估报告中最具信息量的证据 unite.ai 微软借助 AI 修复更多 Windows 漏洞,但补丁部署仍滞后 bloomberg.com Cloudflare 上调年度利润预期,AI 推动网络需求 theinformation.com Anthropic 为 Claude 推出个人理财功能
多元动态
登录 注册
开源工具 github.com · @colinhacks

Reylo v0.3.0 发布:支持 Durable Object SQL 存储并修正类型推断

原文 我的收藏

Reylo 0.3.0 的官方发布说明称,该版本可在 Durable Object 的 SQL 存储上运行查询,并会按 package.json 中列出的 SQLite 驱动(better-sqlite3、@libsql/client、sqlite3、@tursodatabase/database)校验语句;同时为 SQLite 全文检索函数补全类型,并修正 Postgres 和 MySQL 上若干过窄的类型推断。说明还提示,依赖旧类型的代码可能需要增加 null 检查。

AI推荐理由 官方发布说明,信息密度较高:新增对 Durable Object SQL 存储的支持、按项目实际 SQLite 驱动校验语句、为 FTS5/FTS4 函数补全类型,并修正 Postgres/MySQL 若干过窄类型(可能要求调用方补 null 检查)。局限是面向 TypeScript SQL 查询工具的细分开发者,影响面有限,且未提供性能或采用数据。

62

正文

Official release notes (https://github.com/colinhacks/reylo/releases/tag/v0.3.0) Reylo 0.3.0 runs on a Durable Object's SQL storage, checks SQLite statements against your app's own drivers, types SQLite's full-text search, names the query's file in its errors, and fixes several types that were wrong on Postgres and MySQL. Install `reylo` and your database's engine at 0.3.0 together. > [!NOTE] > Three of the fixes below widen a type that was too narrow, where the database could return a value the type ruled out: a `select *` over a left-joined `with` query on Postgres, a JSON `coalesce` with a default other than `'[]'` on Postgres, and a scalar subquery whose `with` shadows a table on MySQL. Code that relied on the old types may need a null check. ### Running queries - Durable Objects: `.run()` and `.runSync()` take a SQLite-backed Durable Object's `ctx.storage.sql`, as they take D1's binding, inside `ctx.storage.transactionSync()` too. An integer past 2^53, which the storage returns rounded, is refused, as on D1, and a BLOB comes back as a `Uint8Array`. - Every query exposes the file it came from as `.source`, relative to the project's root, so an app can tag its logs and traces with it: `getUser.source` is `"queries/get_user.sql"`. - Reylo's errors about a parameter's value, a column's value or the row count now start with the query's file, as in `queries/get_user.sql: Expected exactly one row, got 0`. The driver's own errors pass through unchanged. ### Type check - On SQLite, the type check also prepares each statement on the SQLite drivers your `package.json` lists (`better-sqlite3`, `@libsql/client`, `sqlite3`, `@tursodatabase/database`), whose SQLite may be older than Reylo's. A statement one of them refuses is an error at the place SQLite names, such as `json_pretty` on libSQL, which runs SQLite 3.45: ``` queries/pretty.sql(1,12): error reylo6: @libsql/client runs SQLite 3.45.1, which refuses this statement: no such function: json_pretty ``` ### Inference on SQLite - The full-text search functions are typed: FTS5's `bm25` is a `number`, `highlight` and `snippet` are `string | null`, and FTS4's `offsets` is a `string` and `matchinfo` a `Uint8Array`. They were `unknown`. ### Inference on Postgres - A `select *` over a `with` query on the nullable side of an outer join types that query's columns as nullable. They were typed from the table inside the query, non-null where every row can be null. - A JSON `coalesce(x, default)` keeps the shape of `x` only where `x` is never null, or where it is an array and the default is `'[]'`. Under any other default it is JSON of unknown shape: over no rows, `coalesce(jsonb_agg(id), '{}')` returns `{}`, which the old `number[]` ruled out. ### Inference on MySQL - A derived table's columns keep what Reylo infers about its query alone, so a count or a non-null column read through a derived table stays non-null. A column computed on the null-extended side of an outer join, such as `d.next` in `left join (select user_id, id + 1 as next from posts) d`, is now nullable, where the server's flag had it non-null. - A scalar subquery with a `with` of its own is typed as it would be with the `with` outside it, so `(with r as (select id from posts) select count(id) from r)` is non-null and the JSON it builds is typed. Where that `with` shadows a table, its columns are typed from the `with` query rather than from the table. ### For agents - An agent skill, `using-reylo`, carries the rules an agent needs in a Reylo project once it is set up. Install it with `npx skills add colinhacks/reylo --skill using-reylo`. Repository README (current repository documentation, not release changes) Import .sql files into your TypeScript code with full type inference Read the docs → If you have a file like this: ```sql -- get_author.sql select u.id, u.name, count(p.id)::int as post_count from users u left join posts p on p.user_id = u.id where u.id = :id::int group by u.id ``` You can import it directly from a TypeScript file like this: ```ts // main.ts import postgres from "postgres"; import getAuthor from "./get_author.sql"; const db = postgres(process.env.DATABASE_URL); const author = await getAuthor.run(db, { id: 1 }); // { id: number; name: string; post_count: number } | null ``` Reylo is powered by TypeScript [content mappers](https://github.com/microsoft/typescript-go/pull/4712), introduced in TypeScript 7.1 (currently [in beta](https://devblogs.microsoft.com/typescript/announcing-typescript-7-1-beta/)), which let you dynamically define static types for external file types and integrate them directly into TypeScript compilation. Reylo is the perfect option for the agent era: - 💪 **The full power of SQL** — any statement, function, operator or syntax your database supports, in its own dialect. - 🌵 **DRY** — the types come from the SQL itself: no hand-written row types, no schema file to keep in sync. - 🎯 **Checked against your database** — a misspelled column, a wrong parameter or a dropped table is a type error, in `tsc` and in your editor. - 🤖 **Agent-friendly** — each fact lives in one place, so an agent cannot leave a stale type behind, and the type check finds every caller it missed. - 🧩 **Postgres, MySQL and SQLite** — bring your own driver: `pg`, postgres.js, `mysql2`, `better-sqlite3`, `Bun.sql`, Cloudflare D1 and [more](#supported-drivers). - ⚡ **No codegen** — the type checker asks Reylo directly: no generated files, no watcher. ## Setup To install Reylo, you'll need: - **TypeScript 7.1 (currently in beta).** The first release with content mappers. - **Node 24 or later.** - **A running dev database.** Postgres, MySQL 8.0.22 or later, or a SQLite file: Reylo reads your current schema from it. Install Reylo, the engine for your database and TypeScript 7.1: ```sh npm install reylo npm install -D @reylosql/postgres # or mysql, sqlite npm install -D typescript@beta ``` Add Reylo to `tsconfig.json`, for `.sql` files and for its project file, `.reylo.yaml` or `.reylo.yml`: ```jsonc // tsconfig.json { "compilerOptions": { /* ... */ }, "contentMappers": [ { "package": "reylo", "extensions": [".sql", ".reylo.yaml", ".reylo.yml"] } ] } ``` Then type-check with `--runExternalCode`, which lets `tsc` run content mappers: ```jsonc // package.json { "scripts": { "typecheck": "tsc --noEmit --runExternalCode" } } ``` Point Reylo at your dev database with `DATABASE_URL`, in your environment or in `.env`. Its scheme tells Reylo which database you use: ```sh # .env DATABASE_URL=postgres://localhost:5432/app # or mysql://…, or file:./app.db for SQLite ``` To make `.sql` imports work at run time too, load Reylo where your code runs. On Node: ```sh node --env-file=.env --import reylo/register main.ts ``` For Bun, Nub, Vite, Next.js, esbuild, webpack, Rspack, Cloudflare Workers and Jest, add [the plugin for your setup](https://reylo.dev/#plugins), or copy its complete [example project](https://github.com/colinhacks/reylo/tree/main/examples). To see the types as you type, set up [your editor](https://reylo.dev/#editors). ## Usage Write a query in a `.sql` file, import it, and run it with your database driver: ```sql -- get_user.sql select id, name, email from users where id = :id::int ``` ```ts import getUser from "./get_user.sql"; const user = await getUser.run(db, { id: 1 }); // { id: number; name: string; email: string | null } | null ``` Name each parameter with a colon, and give it a type with a cast where the query doesn't pin one down. Pass `.run()` your driver's client: a pool, a client, or a connection or transaction taken from one. It resolves to the rows, shaped by how many the query can return: | The query | Resolves to | | --- | --- | | A match on a primary or unique key, or `limit 1` | `Row \| null` | | An aggregate without `group by`, a one-row `insert … returning` | `Row` | | An `insert`, `update` or `delete` without `returning` | `void` | | Anything else | `Row[]` | An imported query also has `.runSync()`, `.with()`, `.sql` and `.raw` ([Usage](https://reylo.dev/#usage)). ## What Reylo infers To type a query, Reylo has your dev database prepare it, without running it, and reads back the type of every column and parameter. On top of that, it infers: - **Nulls** — a column is nullable unless its schema, a join or a `where` test rules null out. - **Cardinality** — a match on a unique key is one row or `null`, and an aggregate is exactly one row. - **Unions** — an enum, or a column whose check constraint lists its values, is a union of them. - **JSON** — JSON the query builds, and a JSON column with a JSON Schema check, keep their shape. Each has examples in [Inference](https://reylo.dev/#inference). ## Supported drivers Reylo is bring-your-own-driver. Pass `.run()` a client from any of these, or a Drizzle database over one: - **Postgres** — `pg`, postgres.js, `Bun.sql`, PGlite, Neon, `pg-promise`, `@vercel/postgres` - **MySQL** — `mysql2`, PlanetScale, `Bun.sql` - **SQLite** — `better-sqlite3`, `node:sqlite`, `Bun.sql`, libSQL, Turso, Cloudflare D1, `sqlite3`, `sqlite` ## Documentation [reylo.dev](https://reylo.dev) covers the rest: every plugin and editor, configuration, errors, each database's data types and edge cases, and advanced examples. Agents can read it all as Markdown at [reylo.dev/llms.txt](https://reylo.dev/llms.txt). ## License [MIT](LICENSE)

来源报道 · 1 篇 · 以下链接均前往原始媒体

← 返回精选动态 原文

更多内容