Skip to content

Commit 06ba036

Browse files
os-zhuangclaude
andauthored
feat(drivers): driver-turso 迁回本仓公开发布,五个 IDataDriver 统一收进 packages/drivers/ (#4645 Phase A) (#5618)
* feat(drivers): migrate driver-turso back in-repo and collect all IDataDriver packages under packages/drivers/ (#4645) Phase A of the maintainer-ruled two-repo migration (objectstack half). - git mv packages/plugins/driver-{memory,mongodb,sql,sqlite-wasm} -> packages/drivers/* (content unchanged; only repository.directory follows the move) - new packages/drivers/driver-turso, migrated from objectstack-ai/cloud @ bc372e3b, published Apache-2.0 / access: public. multi-tenant routing and vector-poc stay in cloud. - pnpm-workspace glob, check-driver-conformance DRIVERS_DIR, both CI workflows, liveness evidence paths, adr-anchors, docs and source comments follow the move - driver-turso enters the conformance matrix with 3 measured DEBT cells (#5590) - CLI turso refusal message no longer claims the package ships elsewhere (#5602) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WyvqvKMG6asi9aXjKE6xtx * fix(service-analytics): point the incoming applyLike cross-reference at packages/drivers/driver-sql (#4645) `like-pattern.ts` arrived with origin/main (#5567) naming `packages/plugins/driver-sql/src/sql-driver.ts` — the pre-#4645 path. The merge was textually clean because the file is new on main and the move is on this branch, which is the jointly-wrong shape AGENTS.md §10 warns about: nothing conflicts, and the cross-reference the header leans on lands nowhere. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WyvqvKMG6asi9aXjKE6xtx * fix(driver-turso): satisfy the #4918 query-options-erasure ratchet on the migrated tests (#4645) The 15 turso test files arrived from cloud, which predates this repo's `query-options/no-any-erasure` rule (#5600, landed on main after the first merge), and added 52 sites — test surface 267 -> 319. Every one is inside `packages/drivers/driver-turso/src/*.test.ts`; nothing outside turso moved. Both dispositions the rule names, chosen per site, with no assertion touched: - 14 sites TYPED. Ordinary on-contract reads whose only defect was the missing required `QueryAST.object` key (`driver.count('users', { where: { age: 17 } })`, the TEMPORAL_CASES/TEMPORAL_TIME_CASES conformance reads, and the `$not`/`$or` spellings the transport is asserted to ANSWER). Declaring `object` is what driver-memory's conformance suite already does, and it puts `where` back under tsc. - 38 sites `as unknown as QueryAST`. Deliberately off-contract input: values flowing through the suites' `unknown`-typed helpers (`compile`, `refusalOf`, `ids`) and inline literals whose whole point is refusal — `where: 42`, `[]`, `''`, a class instance, bare AST arrays, `{ $or: [null] }`, `{ $not: null }`, non-boolean `$null` comparands. These assert the transport REJECTS them, so the type must be bypassed by name rather than erased. Baseline untouched: 267 is met, not raised. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WyvqvKMG6asi9aXjKE6xtx --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent d275c10 commit 06ba036

232 files changed

Lines changed: 9317 additions & 252 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.changeset/config.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
"@objectstack/driver-sql",
3535
"@objectstack/driver-mongodb",
3636
"@objectstack/driver-sqlite-wasm",
37+
"@objectstack/driver-turso",
3738
"@objectstack/plugin-approvals",
3839
"@objectstack/plugin-audit",
3940
"@objectstack/plugin-auth",
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
---
2+
"@objectstack/driver-turso": minor
3+
"@objectstack/driver-memory": patch
4+
"@objectstack/driver-mongodb": patch
5+
"@objectstack/driver-sql": patch
6+
"@objectstack/driver-sqlite-wasm": patch
7+
---
8+
9+
feat(drivers): `@objectstack/driver-turso` 迁回本仓并公开发布,五个 driver 统一收进 `packages/drivers/` (#4645)
10+
11+
`TursoDriver` 一直以 `extends SqlDriver` 的方式**跨仓库继承**本仓的类,自己却住在闭源的
12+
`objectstack-ai/cloud``publishConfig: restricted`)。而本仓的 runtime 早就把 turso 当一等
13+
公民——`http-dispatcher.ts` 里环境 provisioning 的偏好顺序第一位就是它,`POST /cloud/environments`
14+
`driver` 参数示例是 `memory | turso``objectql/src/engine.ts` 还带着一段 turso 专属的瞬时
15+
`fetch failed` 重试。开源侧的代码路径引用着一个自己仓里既测不到也 grep 不到的 driver,闭源侧则
16+
在每次 pin bump 时追赶父类的重构。维护者裁定把核心迁回本仓、公开 Apache-2.0 发布。
17+
18+
**新包 `@objectstack/driver-turso``packages/drivers/driver-turso`,Apache-2.0,`access: public`**
19+
带着它在 cloud 的全部实现与测试落地:`TursoDriver`(local / replica / remote 三种传输模式)、
20+
`RemoteTransport`(纯 `@libsql/client` 走 HTTP/WebSocket,无原生依赖,可跑 serverless/edge)、
21+
驱动的 spec/Studio 元数据,以及 15 个测试文件 538 条断言——全部 hermetic,默认 CI 下不碰网络、
22+
不要凭据(remote 面走包内的 sqlite stub)。
23+
24+
**留在 cloud(不随迁)**:按租户路由的 `multi-tenant.ts`(云产品差异化能力)及其 schema、
25+
`vector-poc.test.ts`。因此本包的 barrel **不再导出** `createMultiTenantRouter` /
26+
`MultiTenantConfig` / `MultiTenantRouter`,也不导出多租户 schema——它们从来不是这个 driver 的
27+
一部分,只是曾经同包而已。
28+
29+
**目录重组**:五个 `IDataDriver` 实现(`driver-memory` / `driver-mongodb` / `driver-sql` /
30+
`driver-sqlite-wasm` + 迁入的 `driver-turso`)现在都住在 `packages/drivers/`
31+
`knowledge-*``embedder-*` 留在 `packages/plugins/`。四个存量包**内容零改动**,只有
32+
`repository.directory` 随目录更新——包名、入口、导出面、行为全部不变,消费者无需改动任何 import。
33+
34+
这也把 turso 交给了本仓的仓库级守卫:`check:driver-conformance` 从磁盘发现 driver 包,
35+
迁入即入矩阵(5 drivers × 5 case-sets)。它的 temporal 两格是真绿(local 与 remote 双面套件),
36+
filter 组合语义与两个分页 case-set 记为 measured DEBT——remote 传输自带一套 `buildWhereSQL`
37+
`LIMIT`/`OFFSET` 拼装,是独立实现,"继承所以没问题"正是这些共享套件存在来证伪的假设。
38+
补齐工作跟踪在 #5590

.claude/skills/pm-dispatch/SKILL.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -392,7 +392,7 @@ file the fix touches, you have not triaged it yet, and it is not labelable.
392392
| 标签 | 包家族 |
393393
|:--|:--|
394394
| `domain:engine-core` | `packages/objectql``packages/metadata*``packages/platform-objects``packages/core``packages/formula`(CEL / `matches-filter` / RLS 谓词求值)、`plugin-pinyin-search`(`__search` 伴生列由 SchemaRegistry 声明、engine 把它 OR 进 `$search`,落点在编译/查询核心而非任何 driver;全局写钩子同 #4775 锚定) |
395-
| `domain:drivers` | `packages/plugins/driver-*`(`driver-memory` / `driver-mongodb` / `driver-sql` / `driver-sqlite-wasm`) |
395+
| `domain:drivers` | `packages/drivers/driver-*`(`driver-memory` / `driver-mongodb` / `driver-sql` / `driver-sqlite-wasm`) |
396396
| `domain:services` | `packages/services/*``packages/connectors/*``packages/triggers/*`(flow 触发器)、`packages/plugins/plugin-approvals``plugin-webhooks``plugin-email``plugin-reports``embedder-openai``knowledge-memory``knowledge-ragflow` |
397397
| `domain:identity` | `packages/plugins/plugin-auth``plugin-security``plugin-sharing``plugin-audit` |
398398
| `domain:devx` | `packages/lint``packages/sdui-parser`(仅 lint 消费)、`packages/vscode-objectstack``skills/**``content/docs/**``apps/docs``scripts/`(门禁类) |

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -959,7 +959,7 @@ jobs:
959959
- name: Verify capability packages ship a runtime entry (no dts-only / half-built)
960960
run: |
961961
fail=0
962-
for d in packages/triggers/* packages/services/* packages/plugins/*; do
962+
for d in packages/triggers/* packages/services/* packages/drivers/* packages/plugins/*; do
963963
[ -f "$d/package.json" ] || continue
964964
has_build=$(node -p "Boolean((require('./$d/package.json').scripts||{}).build)" 2>/dev/null || echo false)
965965
[ "$has_build" = "true" ] || continue

.github/workflows/lint.yml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -618,8 +618,9 @@ jobs:
618618
# The per-package `typecheck` scripts the coverage gate above requires
619619
# (#4311). tsc resolves workspace imports through each dependency's built
620620
# dist/*.d.ts, so the task carries `dependsOn: ^build` in turbo.json —
621-
# which also builds the handful of nested packages (packages/plugins/*,
622-
# packages/services/*, …) the build step's direct-children glob misses
621+
# which also builds the handful of nested packages (packages/drivers/*,
622+
# packages/plugins/*, packages/services/*, …) the build step's
623+
# direct-children glob misses
623624
# when no example depends on them. Three filters because the bare
624625
# `./packages/*` glob only matches direct children (see the build step's
625626
# comment): the nested group dirs and apps/ (docs) need their own globs.

ARCHITECTURE.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -242,12 +242,13 @@ ObjectStack is organized as a **monorepo** with distinct package layers:
242242
**Dependencies**: `@objectstack/client`, `@objectstack/core`, `@objectstack/spec`
243243
**Peer Dependencies**: `react`
244244

245-
### Plugin Packages
245+
### Driver & Plugin Packages
246246

247-
Located in `packages/plugins/*`:
247+
Drivers (`IDataDriver` implementations) live in `packages/drivers/*`; every other
248+
official plugin lives in `packages/plugins/*`.
248249

249250
#### `@objectstack/driver-memory`
250-
**Location**: `packages/plugins/driver-memory/`
251+
**Location**: `packages/drivers/driver-memory/`
251252
**Role**: In-Memory Driver (Reference Implementation)
252253

253254
- Complete ObjectQL driver implementation

README.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -284,11 +284,12 @@ For the browser, the typed client SDK and React hooks (`useQuery` / `useMutation
284284

285285
| Package | Description |
286286
| :--- | :--- |
287-
| [`@objectstack/driver-memory`](packages/plugins/driver-memory) | In-memory driver (development and testing) |
288-
| [`@objectstack/driver-sql`](packages/plugins/driver-sql) | SQL driver — PostgreSQL, MySQL, SQLite (production) |
289-
| [`@objectstack/driver-mongodb`](packages/plugins/driver-mongodb) | MongoDB driver (native document database) |
287+
| [`@objectstack/driver-memory`](packages/drivers/driver-memory) | In-memory driver (development and testing) |
288+
| [`@objectstack/driver-sql`](packages/drivers/driver-sql) | SQL driver — PostgreSQL, MySQL, SQLite (production) |
289+
| [`@objectstack/driver-mongodb`](packages/drivers/driver-mongodb) | MongoDB driver (native document database) |
290+
| [`@objectstack/driver-turso`](packages/drivers/driver-turso) | Turso / libSQL driver — edge-first SQLite, embedded replicas, remote mode |
290291

291-
> Turso / libSQL driver (`@objectstack/driver-turso`) and the libSQL-backed vector knowledge plugin (`@objectstack/knowledge-turso`) live in the [ObjectStack Cloud](https://github.com/objectstack-ai/cloud) monorepo as of this release.
292+
> The libSQL-backed vector knowledge plugin (`@objectstack/knowledge-turso`) and Turso database-per-tenant routing live in the [ObjectStack Cloud](https://github.com/objectstack-ai/cloud) monorepo.
292293
293294
### Client
294295

content/docs/data-modeling/drivers.mdx

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,13 @@ Drivers can be selected in two ways:
5252
| _(unset, dev mode)_ | SQLite (native, falling back to WASM, then in-memory) | `@objectstack/driver-sql` / `-sqlite-wasm` / `-memory` |
5353

5454
<Callout type="info">
55-
Turso / libSQL (`libsql://`, `*.turso.io`) is **not** supported by the
56-
open-source framework. The CLI recognizes these URLs (mapping them to a
57-
`turso` driver kind), but no bundled driver implements it — so they never
58-
actually connect to Turso.
55+
Turso / libSQL (`libsql://`, `*.turso.io`) is **not** inferred from a URL.
56+
`@objectstack/driver-turso` does live in this repo (`packages/drivers/driver-turso`)
57+
and you can register it yourself — a datasource with `driver: 'turso'` and
58+
`config: { url, authToken }` — but the CLI's URL → driver resolver does not
59+
construct it. A `libsql://` URL therefore fails loudly at boot rather than
60+
silently degrading to SQLite. Whether the inference table should construct it
61+
is tracked in issue #5602.
5962
</Callout>
6063

6164
## Supported Drivers

content/docs/deployment/environment-variables.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ read at startup unless noted otherwise. Boolean variables accept `true` / `false
4747

4848
| Variable | Type | Default | Description |
4949
|:---|:---|:---|:---|
50-
| `OS_DATABASE_URL` | url || Database connection string (e.g. `file:./data.sqlite`, `postgres://…`, `mongodb://…`, `memory://`). `libsql://` (Turso) is not supported. |
50+
| `OS_DATABASE_URL` | url || Database connection string (e.g. `file:./data.sqlite`, `postgres://…`, `mongodb://…`, `memory://`). `libsql://` (Turso) is not inferred — register `@objectstack/driver-turso` explicitly. |
5151
| `OS_DATABASE_DRIVER` | enum | inferred | Force a specific driver when the URL is ambiguous. `memory` \| `sqlite` \| `sqlite-wasm` \| `postgres` \| `mongodb`. |
5252
| `OS_DATABASE_SQLITE_JOURNAL_MODE` | enum | `wal` | Journal mode for **file-backed** SQLite. `wal` (default) lets a dev server and CLI commands share one file without blocking each other, and is what makes the `os migrate` occupancy check reliable. Set to `delete` for SQLite's rollback journal — required when the database lives on a **network filesystem** (NFS/SMB), where WAL cannot work. The setting is applied, not merely skipped: `delete` converts a database that already adopted WAL back. Ignored for `:memory:`, for the WASM SQLite driver, and for non-SQLite drivers. A per-datasource `sqliteJournalMode` in driver config outranks it. See [Journal mode](/docs/data-modeling/drivers#journal-mode-wal-and-cross-process-access). |
5353
| `OS_ALLOW_DRIVER_CONNECT_FAILURE` | boolean | `false` | Escape hatch for the driver-connect boot guard. By default a data driver that fails to connect at startup **refuses the boot** — a server that cannot reach its database must not report itself started and then fail every request. The same guard covers a **declared datasource** that objects bind to via `datasource: '…'`, or an `external` one with `validation.onMismatch: 'fail'`: those objects have no fallback datasource, so an unconnected one means they are all dead. Set to `1` to boot anyway, in an explicitly degraded state logged loudly at startup. There is **no reconnection**: whatever failed stays dead for the process lifetime and every query and schema sync routed to it fails. |

content/docs/deployment/self-hosting.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ workable default:
3232

3333
| Variable | Why it must be set |
3434
|:---|:---|
35-
| `OS_DATABASE_URL` | Without it, data lands in a SQLite file under the ObjectStack home directory (`~/.objectstack`, or `<cwd>/.objectstack` next to a project config) — fine for one box, wrong for containers. Use `postgres://…`, `mongodb://…`, or a mounted `file:…` path (`libsql://` / Turso is **not** supported by the open framework — that driver ships in ObjectStack Cloud). `mongodb://…` is **single-tenant only**: the MongoDB driver has no row-level tenant isolation and refuses to boot unless the tenancy posture is `single` — see [Drivers → Multi-tenancy](/docs/data-modeling/drivers#multi-tenancy-not-supported). |
35+
| `OS_DATABASE_URL` | Without it, data lands in a SQLite file under the ObjectStack home directory (`~/.objectstack`, or `<cwd>/.objectstack` next to a project config) — fine for one box, wrong for containers. Use `postgres://…`, `mongodb://…`, or a mounted `file:…` path (`libsql://` / Turso is **not** inferred from the URL — `@objectstack/driver-turso` is in-repo but must be registered explicitly in your stack config; see [Drivers](/docs/data-modeling/drivers)). `mongodb://…` is **single-tenant only**: the MongoDB driver has no row-level tenant isolation and refuses to boot unless the tenancy posture is `single` — see [Drivers → Multi-tenancy](/docs/data-modeling/drivers#multi-tenancy-not-supported). |
3636
| `OS_AUTH_SECRET` | Session secret for the auth plugin (`AUTH_SECRET` is the legacy alias). Without it, `/api/v1/auth/*` is **silently skipped** — the server runs unauthenticated. |
3737
| `OS_SECRET_KEY` | 32-byte master key encrypting every stored secret (`openssl rand -hex 32`). On a container's ephemeral filesystem the auto-minted key is **lost on restart**, making previously-encrypted secrets undecryptable. |
3838
| `OS_PORT` | `os start` **fails loudly** if the port is busy (it never auto-shifts like `os dev`). Pin it and keep your reverse-proxy upstream in sync. |

0 commit comments

Comments
 (0)