feat(runtime): standalone stack 分派 libsql://,经可选 Turso driver 包 (#5820) - #6272
Merged
Merged
Conversation
…onal Turso driver (#5820) `detectDriverFromUrl()` refused every libSQL URL as an unsupported scheme while `resolveDatabaseUrl()` listed `TURSO_DATABASE_URL` among its URL sources — read it in, cannot dispatch it out. Since #5602 wired `libsql://` for the CLI's `os serve` / `os start`, the same `OS_DATABASE_URL=libsql://…` booted under `os start` and hard-failed under `os migrate`, which boots through this stack. - `libsql://` and `http(s)://*.turso.*` resolve to the `turso` kind — the same two spellings `inferDriverTypeFromUrl` classifies on the CLI side. - The driver comes from the OPTIONAL `@objectstack/driver-turso` package, loaded lazily in `turso-driver-factory.ts` and injected through the host driver-factory seam `DefaultDatasourcePlugin` documents for exactly this case, so connect / bootCritical verdict / escape hatch stay shared. - Package missing ⇒ loud `MissingDriverPackageError` carrying the install command as data; no SQLite fallback (#3276). - `databaseAuthToken` is consumed now (OS_DATABASE_AUTH_TOKEN, then the vendor's TURSO_AUTH_TOKEN) instead of being declared and ignored. - The file docstring's "ships separately in the ObjectStack Cloud distribution" claim expired with #4645; replaced with the facts. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Wbxm29qPKnLf44AbSxizqW
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
Contributor
📓 Docs Drift CheckThis PR changes 1 package(s): 21 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
qq9340100
marked this pull request as ready for review
August 7, 2026 13:10
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #5820
这条路径原来是什么样
packages/runtime/src/standalone-stack.ts的detectDriverFromUrl()不认libsql://,落到末尾的Unsupported database URL schemethrow;同文件resolveDatabaseUrl()却把TURSO_DATABASE_URL列为 URL 来源之一 —— 读得进来、认不出去。#5602 / PR #5819 让 CLI 的os serve/os start真的能从libsql://构造 TursoDriver 之后,同一个OS_DATABASE_URL=libsql://…就有了两种命运:os start正常启动,os migrate(经createStandaloneStack,以及migrate-occupancy-gate.ts的resolveStandaloneDatabase())硬失败。前提重验(逐条实读,基线 origin/main@01faeb13a)
分诊评论的三条锚点在当前 main 上全部仍成立(行号相对 846ed1f 有漂移):
:157Unsupported database URL schemethrowstandalone-stack.ts:156-159:218?? process.env.TURSO_DATABASE_URL?.trim()standalone-stack.ts:218(resolveDatabaseUrl内):26-28docstring「ships separately in the ObjectStack Cloud distribution」standalone-stack.ts:26-29另外补两条实读,它们决定了形态:
packages/drivers/driver-turso/确实在本仓(driver-turso 住在闭源 cloud 仓,却是开源 runtime 点名偏好的默认 driver — 建议把核心迁回本仓 #4645 迁回),src/index.ts:37导出TursoDriver—— docstring 里「ships separately」的理由已经消失,不只是描述失真;standalone-stack.ts:245-247的注释写着databaseAuthToken/OS_DATABASE_AUTH_TOKEN「preserved in the config schema ... no longer consumes them directly」—— 即 auth token 也是同一个「声明了没人读」的组合。没有发现任何 ADR 把 standalone stack 排除在 libSQL 之外(
docs/adr/内 greplibsql/turso无相关裁决),所以按派工的选项 1(口径收敛)实施。实现:与 #5819 同形态(维护者 B-lite 裁决)
detectDriverFromUrl()识别libsql://与http(s)://*.turso.*—— 与 CLIinferDriverTypeFromUrl()逐字同款的两条,刻意保持一致:两个函数对同一个OS_DATABASE_URL回答同一个问题,分叉本身就是本单的病因;@objectstack/driver-turso,在新文件packages/runtime/src/turso-driver-factory.ts里惰性import(),包成DefaultDatasourcePlugin的 host factory —— 那个 seam 的 docstring 本来就是为「宿主的 default 需要一个开源工厂造不出的 driver(cloud 的 turso)」写的。连接路径、bootCriticalfail-fast 判决、OS_ALLOW_DRIVER_CONNECT_FAILURE逃生口、Setup → Datasources 的 retained status 全部与其他 kind 共享,只有构造不同;MissingDriverPackageError,installCommand作为数据字段(不只写在句子里),消息保留原始 import 错误;⛔ 无 SQLite 回退,理由写进消息本身(静默降级会让os migrate的 DDL 落到一个空的本地库,而远端 libSQL 数据原封不动 —— cli:OS_DATABASE_DRIVER=memoryis advertised butserve.tshas no dispatch branch (falls through to SQLite) #3276 的账);Supported schemes:列表随之更新;未知 scheme 仍然 throw(wat://nope的 e2e 钉子packages/cli/test/migrate-exit-code.e2e.test.ts:210只匹配Unsupported database URL scheme子串,未受影响)。TURSO_DATABASE_URL的闭环它一直是
resolveDatabaseUrl()的第三顺位来源。本 PR 之后,「读得进」与「认得出」终于是同一件事:TURSO_DATABASE_URL=libsql://…且未设OS_DATABASE_URL时,resolveStandaloneDatabase()返回{ driver: 'turso' }(有钉子)。选项 2(删掉这个来源)未采纳,理由见 issue 分诊:它等于保留一个前提已不成立的排除。authToken 的来源(实读确认后接上)
os serve读的是process.env.OS_DATABASE_AUTH_TOKEN || process.env.TURSO_AUTH_TOKEN(commands/serve.ts:1041),而--database-auth-token由start.ts:242/dev.ts:323转发进OS_DATABASE_AUTH_TOKEN。standalone stack 因此有完全对应的来源,已接上,优先级逐字对齐:cfg.databaseAuthToken→OS_DATABASE_AUTH_TOKEN→TURSO_AUTH_TOKEN(vendor 名,AGENTS.md 第 9 条明列的第三方例外)。空白值按「没有」处理,不会把authToken: ''递给 driver。刻意没做的事
packages/runtime/package.json,因此pnpm-lock.yaml/pnpm-workspace.yaml零改动(锁文件独占约束)。这不是绕过声明:本仓对「可选 driver 包的动态 import」已有成例 ——service-datasource/src/default-datasource-driver-factory.ts:438用await import('@objectstack/driver-mongodb' as any),而 service-datasource 的 package.json 对它只有 devDependency、没有 peer 声明,靠 tsup external 兜住打包。本 PR 照抄这一形态:specifier 上的as any让 TS 不去解析,packages/runtime/tsup.config.ts的 external 列表加一行让 esbuild 不去打包。测试用替身 importer,不需要装真包。若维护者希望 runtime 也像 CLI 那样显式声明 optional peer,那会动 lockfile,应当单独一单做。libsql://抛 UnsupportedDriverError —— runtime 的 provisioning 却把 turso 排在偏好第一位,两处口径相反 #5602 刚落地的表面)—— 已另立 observation: 可选 Turso driver 的 loader 现在有两份(cli/utils/storage-driver.ts 与 runtime/turso-driver-factory.ts)—— 建议收敛到单一 owner #6268 记录。反向验证(先预测方向,再跑)
预测:识别臂是谓词不是计数,所以标准方向 —— 临时删掉
detectDriverFromUrl()里那两行,应有 5 个用例转红(4 个走 URL 识别的钉子 + 1 个整栈钉子),而两个走 explicit driver 的用例(databaseDriver: 'turso'/OS_DATABASE_DRIVER=turso)绕过识别,应保持绿。实际:5 红 / 26 绿,与预测逐条一致,且红的正是 issue 描述的那句原文:
识别臂已还原(
git diff内不含该临时改动)。测试
新增
packages/runtime/src/standalone-stack.libsql.test.ts(31 例),三层:TURSO_DATABASE_URL/ explicit driver 四条正向;memory://、postgres://、postgresql://、pg://、mongodb://、mongodb+srv://、wasm-sqlite://、file:、裸路径九条阳性对照不回归;wat://nope仍抛 Unsupported;非 Turso 的https://example.com/db仍抛 Unsupported(新臂是窄的);turso/libsql,create()用{ url, authToken }造出驱动、handle 的 connect/disconnect/checkHealth 可用、ownership 留默认;缺席 ⇒MissingDriverPackageError带installCommand数据字段、消息含拒绝理由与原始 import 错误、失败路径里没有任何 sqlite 形状;另有「模块解析得到但没有 TursoDriver 导出」与 CJSdefault形状两例。全程不连真 Turso;createStandaloneStack({ databaseUrl: 'libsql://…' })现在不再以Unsupported database URL scheme收场(本工作区里走缺包臂,因为 driver-turso 刻意不是 runtime 的依赖);同一路径上wat://nope仍然照旧被拒。命令与结果:
另做了一次消费半径清扫:
Supported schemes字样全仓只此一处;detectDriverFromUrl/resolveStandaloneDatabase的仓外消费者只有cli/src/utils/migrate-occupancy-gate.ts(只读sqliteFile,turso 恒为 null)与上面那条 e2e 钉子。changeset
@objectstack/runtimeminor —— 新增了 URL scheme 识别与一个databaseDriver枚举值(可授权面变大),不是纯修复,故 minor 而非 patch。范围外发现(已查重后立单,均未认领)
mysql://与 #5820 的 libsql 同族 ——os migrate抛 Unsupported scheme,而OS_DATABASE_DRIVER的未知值(含mysql)静默落到 SQLite #6265 ——mysql://与本单 libsql 完全同形(CLI 认、standalone 不认,而共享工厂本来就能造 mysql);外加OS_DATABASE_DRIVER的值从来没被校验过,未知值静默落到 SQLite。concrete defect,留给 PM 分诊。finding,无pm:queue)。Generated by Claude Code