Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .changeset/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
"@objectstack/driver-sql",
"@objectstack/driver-mongodb",
"@objectstack/driver-sqlite-wasm",
"@objectstack/driver-turso",
"@objectstack/plugin-approvals",
"@objectstack/plugin-audit",
"@objectstack/plugin-auth",
Expand Down
38 changes: 38 additions & 0 deletions .changeset/drivers-dir-and-turso-migration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
---
"@objectstack/driver-turso": minor
"@objectstack/driver-memory": patch
"@objectstack/driver-mongodb": patch
"@objectstack/driver-sql": patch
"@objectstack/driver-sqlite-wasm": patch
---

feat(drivers): `@objectstack/driver-turso` 迁回本仓并公开发布,五个 driver 统一收进 `packages/drivers/` (#4645)

`TursoDriver` 一直以 `extends SqlDriver` 的方式**跨仓库继承**本仓的类,自己却住在闭源的
`objectstack-ai/cloud`(`publishConfig: restricted`)。而本仓的 runtime 早就把 turso 当一等
公民——`http-dispatcher.ts` 里环境 provisioning 的偏好顺序第一位就是它,`POST /cloud/environments`
的 `driver` 参数示例是 `memory | turso`,`objectql/src/engine.ts` 还带着一段 turso 专属的瞬时
`fetch failed` 重试。开源侧的代码路径引用着一个自己仓里既测不到也 grep 不到的 driver,闭源侧则
在每次 pin bump 时追赶父类的重构。维护者裁定把核心迁回本仓、公开 Apache-2.0 发布。

**新包 `@objectstack/driver-turso`(`packages/drivers/driver-turso`,Apache-2.0,`access: public`)**
带着它在 cloud 的全部实现与测试落地:`TursoDriver`(local / replica / remote 三种传输模式)、
`RemoteTransport`(纯 `@libsql/client` 走 HTTP/WebSocket,无原生依赖,可跑 serverless/edge)、
驱动的 spec/Studio 元数据,以及 15 个测试文件 538 条断言——全部 hermetic,默认 CI 下不碰网络、
不要凭据(remote 面走包内的 sqlite stub)。

**留在 cloud(不随迁)**:按租户路由的 `multi-tenant.ts`(云产品差异化能力)及其 schema、
`vector-poc.test.ts`。因此本包的 barrel **不再导出** `createMultiTenantRouter` /
`MultiTenantConfig` / `MultiTenantRouter`,也不导出多租户 schema——它们从来不是这个 driver 的
一部分,只是曾经同包而已。

**目录重组**:五个 `IDataDriver` 实现(`driver-memory` / `driver-mongodb` / `driver-sql` /
`driver-sqlite-wasm` + 迁入的 `driver-turso`)现在都住在 `packages/drivers/`,
`knowledge-*` 与 `embedder-*` 留在 `packages/plugins/`。四个存量包**内容零改动**,只有
`repository.directory` 随目录更新——包名、入口、导出面、行为全部不变,消费者无需改动任何 import。

这也把 turso 交给了本仓的仓库级守卫:`check:driver-conformance` 从磁盘发现 driver 包,
迁入即入矩阵(5 drivers × 5 case-sets)。它的 temporal 两格是真绿(local 与 remote 双面套件),
filter 组合语义与两个分页 case-set 记为 measured DEBT——remote 传输自带一套 `buildWhereSQL` 与
`LIMIT`/`OFFSET` 拼装,是独立实现,"继承所以没问题"正是这些共享套件存在来证伪的假设。
补齐工作跟踪在 #5590。
2 changes: 1 addition & 1 deletion .claude/skills/pm-dispatch/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,7 @@ file the fix touches, you have not triaged it yet, and it is not labelable.
| 标签 | 包家族 |
|:--|:--|
| `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 锚定) |
| `domain:drivers` | `packages/plugins/driver-*`(`driver-memory` / `driver-mongodb` / `driver-sql` / `driver-sqlite-wasm`) |
| `domain:drivers` | `packages/drivers/driver-*`(`driver-memory` / `driver-mongodb` / `driver-sql` / `driver-sqlite-wasm`) |
| `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` |
| `domain:identity` | `packages/plugins/plugin-auth`、`plugin-security`、`plugin-sharing`、`plugin-audit` |
| `domain:devx` | `packages/lint`、`packages/sdui-parser`(仅 lint 消费)、`packages/vscode-objectstack`、`skills/**`、`content/docs/**`、`apps/docs`、`scripts/`(门禁类) |
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -959,7 +959,7 @@ jobs:
- name: Verify capability packages ship a runtime entry (no dts-only / half-built)
run: |
fail=0
for d in packages/triggers/* packages/services/* packages/plugins/*; do
for d in packages/triggers/* packages/services/* packages/drivers/* packages/plugins/*; do
[ -f "$d/package.json" ] || continue
has_build=$(node -p "Boolean((require('./$d/package.json').scripts||{}).build)" 2>/dev/null || echo false)
[ "$has_build" = "true" ] || continue
Expand Down
5 changes: 3 additions & 2 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -618,8 +618,9 @@ jobs:
# The per-package `typecheck` scripts the coverage gate above requires
# (#4311). tsc resolves workspace imports through each dependency's built
# dist/*.d.ts, so the task carries `dependsOn: ^build` in turbo.json —
# which also builds the handful of nested packages (packages/plugins/*,
# packages/services/*, …) the build step's direct-children glob misses
# which also builds the handful of nested packages (packages/drivers/*,
# packages/plugins/*, packages/services/*, …) the build step's
# direct-children glob misses
# when no example depends on them. Three filters because the bare
# `./packages/*` glob only matches direct children (see the build step's
# comment): the nested group dirs and apps/ (docs) need their own globs.
Expand Down
7 changes: 4 additions & 3 deletions ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -242,12 +242,13 @@ ObjectStack is organized as a **monorepo** with distinct package layers:
**Dependencies**: `@objectstack/client`, `@objectstack/core`, `@objectstack/spec`
**Peer Dependencies**: `react`

### Plugin Packages
### Driver & Plugin Packages

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

#### `@objectstack/driver-memory`
**Location**: `packages/plugins/driver-memory/`
**Location**: `packages/drivers/driver-memory/`
**Role**: In-Memory Driver (Reference Implementation)

- Complete ObjectQL driver implementation
Expand Down
9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -284,11 +284,12 @@ For the browser, the typed client SDK and React hooks (`useQuery` / `useMutation

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

> 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.
> 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.

### Client

Expand Down
11 changes: 7 additions & 4 deletions content/docs/data-modeling/drivers.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,13 @@ Drivers can be selected in two ways:
| _(unset, dev mode)_ | SQLite (native, falling back to WASM, then in-memory) | `@objectstack/driver-sql` / `-sqlite-wasm` / `-memory` |

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

## Supported Drivers
Expand Down
2 changes: 1 addition & 1 deletion content/docs/deployment/environment-variables.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ read at startup unless noted otherwise. Boolean variables accept `true` / `false

| Variable | Type | Default | Description |
|:---|:---|:---|:---|
| `OS_DATABASE_URL` | url | — | Database connection string (e.g. `file:./data.sqlite`, `postgres://…`, `mongodb://…`, `memory://`). `libsql://` (Turso) is not supported. |
| `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. |
| `OS_DATABASE_DRIVER` | enum | inferred | Force a specific driver when the URL is ambiguous. `memory` \| `sqlite` \| `sqlite-wasm` \| `postgres` \| `mongodb`. |
| `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). |
| `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. |
Expand Down
2 changes: 1 addition & 1 deletion content/docs/deployment/self-hosting.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ workable default:

| Variable | Why it must be set |
|:---|:---|
| `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). |
| `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). |
| `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. |
| `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. |
| `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. |
Expand Down
4 changes: 2 additions & 2 deletions content/docs/getting-started/glossary.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,8 @@ The fundamental unit of data modeling in ObjectStack. Roughly equivalent to a "T

### Driver
An adapter plugin in the Data Protocol runtime stack that allows the Data Layer to communicate with a specific underlying storage engine.
* *Example (this repo):* `@objectstack/driver-sql` (Postgres / MySQL / SQLite via Knex), `@objectstack/driver-mongodb`, `@objectstack/driver-memory` (in-memory, for testing), `@objectstack/driver-sqlite-wasm`.
* *Cloud distribution:* `@objectstack/driver-turso` (edge-first SQLite) ships separately, not in this repository.
* *Example (this repo):* `@objectstack/driver-sql` (Postgres / MySQL / SQLite via Knex), `@objectstack/driver-mongodb`, `@objectstack/driver-memory` (in-memory, for testing), `@objectstack/driver-sqlite-wasm`, `@objectstack/driver-turso` (edge-first SQLite / libSQL).
* All of them live under `packages/drivers/`. Turso *database-per-tenant routing* — a layer above the driver, not part of it — is a cloud product capability and ships separately.

### AST (Abstract Syntax Tree)
The intermediate representation of a query or schema. The Data Protocol parses a JSON request into an AST before the Driver translates it into SQL/NoSQL queries. This allows for security validation and optimization before execution.
Expand Down
26 changes: 20 additions & 6 deletions content/docs/plugins/packages.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ description: Complete guide to all ObjectStack packages, services, drivers, plug

# Package Overview

ObjectStack is organized into **72 package manifests** across multiple categories. This guide provides an overview of the framework packages, services, drivers, plugins, and adapters in the [framework repository](https://github.com/objectstack-ai/objectstack/tree/main/packages).
ObjectStack is organized into **73 package manifests** across multiple categories. This guide provides an overview of the framework packages, services, drivers, plugins, and adapters in the [framework repository](https://github.com/objectstack-ai/objectstack/tree/main/packages).

### Package categories at a glance

Expand All @@ -14,7 +14,7 @@ ObjectStack is organized into **72 package manifests** across multiple categorie
| **Core runtime** | 9 | `spec`, `core`, `runtime`, `types`, `metadata`, `objectql`, `rest`, `formula`, `platform-objects` |
| **Client / DX** | 5 | `client`, `client-react`, `cli`, `create-objectstack`, `vscode-objectstack` |
| **Framework adapters** | 1 | `hono` (other frameworks: build a thin adapter on `HttpDispatcher` — see below) |
| **Drivers** | 4 | `driver-memory`, `driver-sql`, `driver-sqlite-wasm`, `driver-mongodb` |
| **Drivers** | 5 | `driver-memory`, `driver-sql`, `driver-sqlite-wasm`, `driver-mongodb`, `driver-turso` |
| **Plugins** | 18 | `plugin-auth`, `plugin-security`, `plugin-audit`, `plugin-approvals`, `plugin-sharing`, `plugin-email`, `plugin-webhooks`, `plugin-reports`, `plugin-hono-server`, `plugin-dev`, `plugin-pinyin-search`, `mcp`, trigger plugins (`trigger-api`, `trigger-record-change`, `trigger-schedule`), and knowledge/embedder plugins (`knowledge-memory`, `knowledge-ragflow`, `embedder-openai`) |
| **Platform services** | 16 | `service-analytics`, `service-automation`, `service-cache`, `service-cluster`, `service-cluster-redis`, `service-datasource`, `service-i18n`, `service-job`, `service-knowledge`, `service-messaging`, `service-package`, `service-queue`, `service-realtime`, `service-settings`, `service-sms`, `service-storage` |

Expand Down Expand Up @@ -145,7 +145,7 @@ import { useQuery, useMutation } from '@objectstack/client-react';

- **Purpose**: Fast in-memory data storage with full ObjectQL support
- **When to use**: Development, testing, demos (data is lost on restart)
- **README**: [View README](https://github.com/objectstack-ai/objectstack/blob/main/packages/plugins/driver-memory/README.md)
- **README**: [View README](https://github.com/objectstack-ai/objectstack/blob/main/packages/drivers/driver-memory/README.md)

```typescript
import { InMemoryDriver } from '@objectstack/driver-memory';
Expand All @@ -158,7 +158,7 @@ import { InMemoryDriver } from '@objectstack/driver-memory';
- **Purpose**: Production-ready SQL database support with migrations
- **Supports**: PostgreSQL, MySQL, SQLite, and all Knex-compatible databases
- **When to use**: Traditional relational database deployments
- **README**: [View README](https://github.com/objectstack-ai/objectstack/blob/main/packages/plugins/driver-sql/README.md)
- **README**: [View README](https://github.com/objectstack-ai/objectstack/blob/main/packages/drivers/driver-sql/README.md)

```typescript
import { SqlDriver } from '@objectstack/driver-sql';
Expand All @@ -175,7 +175,7 @@ const driver = new SqlDriver({
- **Purpose**: SQLite running entirely in WebAssembly (no native bindings), with optional `fs`-backed persistence
- **Modes**: In-memory (`:memory:`) or a file path persisted via the `persist` option
- **When to use**: Environments without native SQLite, edge/browser runtimes, lightweight local-first storage
- **README**: [View README](https://github.com/objectstack-ai/objectstack/blob/main/packages/plugins/driver-sqlite-wasm/README.md)
- **README**: [View README](https://github.com/objectstack-ai/objectstack/blob/main/packages/drivers/driver-sqlite-wasm/README.md)

```typescript
import { SqliteWasmDriver } from '@objectstack/driver-sqlite-wasm';
Expand All @@ -189,7 +189,21 @@ const driver = new SqliteWasmDriver({ filename: ':memory:' });
- **Purpose**: Native MongoDB driver for ObjectQL with document-flavored objects
- **When to use**: Existing MongoDB infrastructure, document-shaped data — **single-tenant deployments only**
- **Not supported**: row-level tenant isolation. The driver refuses to boot when the tenancy posture is not `single` — see [Drivers → Multi-tenancy](/docs/data-modeling/drivers#multi-tenancy-not-supported)
- **README**: [View README](https://github.com/objectstack-ai/objectstack/blob/main/packages/plugins/driver-mongodb/README.md)
- **README**: [View README](https://github.com/objectstack-ai/objectstack/blob/main/packages/drivers/driver-mongodb/README.md)

### @objectstack/driver-turso

**Turso / libSQL Driver** — Edge-first SQLite with embedded replicas and a remote transport.

- **Purpose**: Turso/libSQL storage; extends `SqlDriver`, so all CRUD, schema, filtering and aggregation logic is inherited rather than duplicated
- **Modes**: `local` (file / `:memory:` via better-sqlite3), `replica` (local file synced from a remote database), `remote` (pure `@libsql/client` over HTTP/WebSocket — no native bindings, so it runs on serverless/edge)
- **When to use**: Globally distributed reads, edge deployments, or a serverless runtime where native SQLite is unavailable
- **README**: [View README](https://github.com/objectstack-ai/objectstack/blob/main/packages/drivers/driver-turso/README.md)

```typescript
import { TursoDriver } from '@objectstack/driver-turso';
const driver = new TursoDriver({ url: 'libsql://my-db.turso.io', authToken: process.env.TURSO_AUTH_TOKEN });
```

---

Expand Down
Loading
Loading