@abloatai/ablo 0.16.3 → 0.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,16 +1,16 @@
1
1
  # Quickstart
2
2
 
3
3
  Build with Ablo on **the Postgres you already have**. You declare a small Ablo
4
- schema for the models humans and agents edit together, hand the client your
5
- Postgres `DATABASE_URL` (passed explicitly), and coordinate every write through
6
- `ablo.<model>`. In production, your database is the system of record. Ablo is the
7
- transaction layer on top: it registers your connection, commits every write there
8
- behind row-level security, and fans the confirmed rows out to every connected
9
- client.
4
+ schema for the models humans and agents edit together, connect Ablo to your
5
+ database with **logical replication** (`ablo connect`), and coordinate every read
6
+ and claim through `ablo.<model>`. Your database stays the system of record: your
7
+ app keeps writing through its own backend, Ablo tails your write-ahead log (WAL),
8
+ and the confirmed rows fan out to every connected client. Ablo **never runs DDL,
9
+ owns, or migrates your schema**.
10
10
 
11
11
  > No database yet? The hosted **sandbox** can host rows in Ablo's test plane —
12
- > pass an `apiKey` only and omit `databaseUrl`, like Stripe test mode — so you can
13
- > try Ablo before pointing it at your Postgres.
12
+ > pass an `apiKey` only and skip the database setup, like Stripe test mode — so
13
+ > you can try Ablo before connecting your Postgres.
14
14
 
15
15
  ## 1. Install and initialize
16
16
 
@@ -95,15 +95,34 @@ same idiom as tRPC's `typeof appRouter` and Drizzle's `typeof db`; it resolves
95
95
  the typed overload at the call site. Avoid `ReturnType<typeof Ablo>`, which
96
96
  collapses to the untyped client.
97
97
 
98
- ## 3. Point Ablo at your database
98
+ ## 3. Connect your database with `ablo connect`
99
99
 
100
- The client takes your schema, your key, and your `DATABASE_URL`. On first
101
- connect Ablo registers the connection (sent once over TLS, stored sealed, never
102
- echoed back) and from then on commits every write directly to your Postgres.
100
+ Connecting a real database = Postgres logical replication, and `ablo connect` is
101
+ the one way to set it up. Ablo **reads** your WAL and never runs DDL, owns, or
102
+ migrates your schema your app keeps writing through its own backend.
103
+
104
+ ```bash
105
+ # 1. Enable logical decoding (then RESTART Postgres — wal_level is not reloadable)
106
+ # ALTER SYSTEM SET wal_level = 'logical';
107
+ # On RDS/Aurora: set rds.logical_replication = 1 in the parameter group, reboot.
108
+
109
+ # 2. Print the exact publication + replication-role SQL for YOUR Postgres, run it:
110
+ npx ablo connect
111
+
112
+ # 3. Put the replication role's connection string in DATABASE_URL, then validate:
113
+ npx ablo connect --check
114
+ ```
115
+
116
+ `ablo connect` prints the copy-pasteable SQL (a publication named
117
+ `ablo_publication` and a least-privilege `ablo_replicator` role with
118
+ `REPLICATION` + `SELECT`, password you choose). `ablo connect --check` connects to
119
+ `DATABASE_URL` and verifies `wal_level=logical`, the publication, the role's
120
+ `REPLICATION` attribute, and that every published table has a usable
121
+ `REPLICA IDENTITY` — a green checklist or the precise fix per item.
103
122
 
104
123
  ```bash
105
124
  # .env — server runtime only, never the browser
106
- DATABASE_URL=postgres://ablo_app:...@host:5432/db
125
+ DATABASE_URL=postgres://ablo_replicator:<password>@host:5432/db?sslmode=require
107
126
  ABLO_API_KEY=sk_test_...
108
127
  ```
109
128
 
@@ -115,50 +134,18 @@ import { schema } from './schema';
115
134
  export const ablo = Ablo({
116
135
  schema,
117
136
  apiKey: process.env.ABLO_API_KEY,
118
- databaseUrl: process.env.DATABASE_URL, // your Postgres, passed explicitly — rows live here
119
137
  });
120
138
  ```
121
139
 
122
- `databaseUrl` is not auto-read from the environment you pass it explicitly
123
- (as above). If a `DATABASE_URL` is set for another tool, `Ablo()` ignores it
124
- unless you wire it in like this.
125
-
126
- Use a dedicated **non-superuser role** for the connection — Ablo enforces
127
- tenant isolation with row-level security, so the server rejects superuser or
128
- `BYPASSRLS` roles outright (`database_role_cannot_enforce_rls`).
129
-
130
- > **Neon / Supabase note:** the connection string those dashboards hand you
131
- > uses the database OWNER role (e.g. `neondb_owner`), which is `BYPASSRLS` —
132
- > Ablo will reject it. You don't have to fix that by hand: `npx ablo dev`
133
- > (next step) detects the unsafe role and offers to create the scoped one for
134
- > you — from your machine, so the owner credential never reaches Ablo. It
135
- > writes the new `DATABASE_URL` into your env file (the generated password is
136
- > never printed).
137
- >
138
- > Prefer to do it manually? The equivalent SQL:
139
- >
140
- > ```sql
141
- > CREATE ROLE ablo_app LOGIN PASSWORD '<strong password>'
142
- > NOSUPERUSER NOBYPASSRLS NOCREATEDB NOCREATEROLE;
143
- > GRANT CREATE, CONNECT ON DATABASE <your_db> TO ablo_app;
144
- > GRANT CREATE, USAGE ON SCHEMA public TO ablo_app;
145
- > ```
146
- >
147
- > Then swap the user/password in the dashboard's string:
148
- > `postgres://ablo_app:<password>@<same-host>/<same-db>?sslmode=require`.
149
-
150
- Don't want a connection string to leave your infrastructure? Keep
151
- `DATABASE_URL` in your app only and expose one signed **Data Source endpoint**
152
- built from an ORM adapter instead — same product, same writes, see
153
- [Connect Your Database](./data-sources.md). In that setup, omit `databaseUrl`
154
- from `Ablo(...)`.
140
+ The full setup, the honest footprint (publication + slot + `REPLICATION` role +
141
+ the `wal_level` restart + slot/WAL retention Ablo monitors), and the Preview
142
+ status of the WAL runtime are in [Connect Your Database](./data-sources.md).
155
143
 
156
144
  ## 4. Push the schema, then map it to tables
157
145
 
158
146
  ```bash
159
- npx ablo push # checks your DATABASE_URL role, pushes the schema (sandbox),
160
- # and writes ABLO_API_KEY to .env.local. Add --watch to
161
- # re-push on every save.
147
+ npx ablo push # pushes the schema definition and writes ABLO_API_KEY to
148
+ # .env.local. Add --watch to re-push on every save.
162
149
  ```
163
150
 
164
151
  `ablo push` uploads the schema *definition* — model names, fields, types. That
@@ -166,21 +153,22 @@ metadata is what tells Ablo which models to coordinate. Skipping it makes every
166
153
  write to a new or changed model fail with `server_execute_unknown_model` — that
167
154
  error literally means "run `npx ablo push`."
168
155
 
169
- Now Ablo needs real Postgres tables behind those models. Two ways, depending on
170
- who owns the tables:
156
+ Now map those models to your real Postgres tables. **Your migration tool owns the
157
+ tables** Ablo reads them, it does not create or migrate them:
158
+
159
+ - Run `npx ablo pull` to import the shape of your existing tables (created by
160
+ Prisma, Drizzle, or hand-written migrations) into your schema, or
161
+ `npx ablo check` to verify your schema and the live tables agree. Keep managing
162
+ the tables with your own migration tool; Ablo syncs the subset of models you
163
+ declared and reports the rest as "ignored / owned by you."
171
164
 
172
- - **Adopt existing tables (the common case).** Most teams already have the
173
- tables created by Prisma, Drizzle, or hand-written migrations. Run
174
- `npx ablo pull` to import their shape into your schema, or `npx ablo check`
175
- to verify your schema and the live tables agree. Keep managing the tables
176
- with your own migration tool; Ablo just syncs the subset of models you
177
- declared.
178
- - **Let Ablo provision them.** If Ablo should own the tables, `npx ablo migrate`
179
- creates your synced-model tables (with row-level security) in the registered
180
- database. Your other tables are left untouched.
165
+ > **Optional escape hatch:** if you have no tables yet and want Ablo to scaffold
166
+ > them, `npx ablo migrate` can create your synced-model tables for you. This is
167
+ > not the happy path connecting a real database is `ablo connect` (step 3), and
168
+ > your own migrations stay in charge of your schema.
181
169
 
182
170
  Nothing runs locally — there is no dev server to start. Your app talks to Ablo's
183
- hosted API with the sandbox key; the rows land in your database.
171
+ hosted API; the rows live in your database.
184
172
 
185
173
  ## 5. Write through the model
186
174
 
@@ -279,5 +267,5 @@ Keep using the schema client for app and agent writes.
279
267
  - [Schema Contract](./schema-contract.md) explains what the schema drives across SDK, React, agents, Data Source, and schema push.
280
268
  - [Guarantees](./guarantees.md) explains what confirmed writes and stale checks mean.
281
269
  - [Client Behavior](./client-behavior.md) covers errors, retries, and public imports.
282
- - [Connect Your Database](./data-sources.md) covers both connection shapes — `databaseUrl` and the signed Data Source endpoint.
270
+ - [Connect Your Database](./data-sources.md) covers the logical-replication connect path end to end — `ablo connect`, the honest footprint, and the WAL runtime's Preview status.
283
271
  - [AI SDK Tool](./examples/ai-sdk-tool.md) shows the same write path inside a tool call.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abloatai/ablo",
3
- "version": "0.16.3",
3
+ "version": "0.18.0",
4
4
  "description": "The Collaboration Layer For AI Agents",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",