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
24 changes: 24 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# bool-sdk — agent notes

## This repo is PUBLIC (and published to npm)

Everything here ships to the world: source, comments, README, CHANGELOG,
commit messages, PR titles/bodies. Write accordingly.

## Voice

Describe the SDK on its own terms — what an API does and why it's shaped that
way. Keep comments, docs, the README, the CHANGELOG, commit messages, and PRs
self-contained: no references to other products or frameworks as the
explanation for a design (a reader shouldn't need outside context to
understand ours).

## Working here

- `bun install`, `bun test` (hermetic — fetch/fs stubbed or temp dirs),
`bun run typecheck`, `bun run build` (emits `dist/`, ESM + `.d.ts`).
- Add tests in the same change as the code.
- The gateway wire paths (`/_bool/v1/*`) are append-only; keep this SDK in
sync with the gateway routes in the Bool platform repo (`lib/gateway/`).
- Semver discipline is load-bearing: generated apps install from a caret
range on every sandbox boot, so a breaking change requires a major bump.
85 changes: 80 additions & 5 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,80 @@
# Changelog

## 0.2.0-next.16

- `bool create` no longer requires a name — a bare `bool create` generates a
friendly one (e.g. `swift-otter-42`) and scaffolds into a matching folder.
Pass a name to override. Combined with the default API URL (or `BOOL_API_URL`),
`bool create` alone stands up a new todo app + project.

## 0.2.0-next.15

- `bool create` now aborts (exit 1) if the entity push fails, instead of
deploying an app whose data model was never created. It prints how to finish
(`bool entities push` + `bool deploy`) once the cause is fixed.
- The scaffolded todo app shows the real error message instead of
"[object Object]" — bool-sdk throws the raw (often non-Error) error, so the
template now extracts `.message` from it.

## 0.2.0-next.14

- Fix `bool create`: the scaffolded app now lists `@supabase/supabase-js`
(a bool-sdk peer dependency) in its `package.json`, so the deploy/cloud build
can resolve it — previously `vite build` failed with "Rollup failed to resolve
import @supabase/supabase-js". Verified with a real `npm install && vite build`.

Note: `bool create` / `bool entities push` also need the platform's
`POST /api/projects/[id]/entities` endpoint (added in codehs/bool#488). Without
it the entity push returns HTTP 405.

## 0.2.0-next.13

- New `bool create <name> [--path <dir>] [--deploy]` — scaffold a new Bool
project and a working todo-list app in one command. Creates the project
(`POST /api/projects`), writes a self-contained Vite + React todo app wired to
the project through `bool-sdk`, links it (`bool.config.json` + `.env.bool` +
types), and declares a public `todos` entity so the deployed app works with no
sign-in. `--deploy` publishes it immediately.

## 0.2.0-next.12

- CLI: fail with a clear message instead of crashing when the API returns a
non-JSON `2xx` response. This happens when `--api-url` points at a host that
serves the HTML app shell (e.g. the Bool API isn't deployed there yet) — the
`link`, `entities`, and `entities pull` commands previously threw an
unhandled `TypeError` (`Cannot read properties of null`). They now report
`expected a JSON response … — check --api-url` and exit 1.

## 0.2.0-next.11

Local development: use a Bool project as a managed backend from your own
machine, and publish back to Bool — without leaving your editor.

- `createBoolClient({ ..., apiKey })` — a Bool data API key (`boolsk_` project
admin key, or a `boolk_` end-user key) is sent as the `api_key` header on
every gateway call (db, users, ai), so the client now works from anywhere:
Node scripts, a local Vite app, CI. Without `apiKey`, behavior is unchanged.
- New CLI (`npx bool-sdk <command>`, zero dependencies):
- `link --project <id>` — connects a local folder to a Bool project. Writes
`bool.config.json` (public connection config), puts the project's admin
data key in `.env.bool` (gitignored; owner only), and pulls entity types.
- `types` — regenerates `bool/types.d.ts` from the project's entity schemas,
so `bool.entities.<name>` is fully typed locally.
- `entities` — prints the project's declared entities + fields.
- `entities pull` / `entities push` — round-trip the entity schema files
(`bool/entities/*.jsonc`) between the project and disk: pull writes them
verbatim, push declares every local file on the project (additive
migrations server-side; per-file results and warnings reported).
- `deploy` — zips the app source (node_modules/.git/env files excluded) and
publishes it on Bool via the drop pipeline: Bool builds in the cloud and
the project URL stays stable.
- Platform calls authenticate with a personal access token (`--token` or
`BOOL_TOKEN`).

Requires the local-dev endpoints in the Bool platform repo
(`/api/projects/[id]/connection`, `/api/projects/[id]/entities/types`,
`POST /api/drops`).

## 0.2.0-next.10

Adds `bool.ai` — the AI battery. A deployed app can call a model with NO API key
Expand Down Expand Up @@ -40,7 +115,7 @@ already-created app on the stable `^0.1.0` range too.

## 0.2.0-next.8

Adds per-user API keys (Base44 convention): the gateway's `/users/me` lazily
Adds per-user API keys: the gateway's `/users/me` lazily
mints and returns a personal `api_key` for the signed-in end user.

- `BoolUser.apiKey?: string` — typed access to the key.
Expand All @@ -53,7 +128,7 @@ change that accepts `api_key` and stamps `sub` accordingly.

## 0.2.0-next.7

- **Entities pagination cap raised 1000 → 5000, matching Base44.** `list` and
- **Entities pagination cap raised 1000 → 5000.** `list` and
`filter` still page (50 rows by default) but now allow up to 5000 rows per
call. A `limit` above the cap **throws** instead of silently truncating, so
over-large reads fail loudly rather than returning a partial result the caller
Expand All @@ -72,7 +147,7 @@ app renders its sign-in screen rather than a blank page. Adds a regression test.

## 0.2.0

Adds the **entities data layer** — a Base44-parity data API over the gateway so
Adds the **entities data layer** — a high-level data API over the gateway so
apps read/write data without touching Supabase, SQL, or credentials directly:

```ts
Expand All @@ -82,7 +157,7 @@ await bool.entities.todos.update(one.id, { done: true });
await bool.entities.todos.filter({ status: "active", count: { $gte: 10 } });
```

`bool.entities.<table>` mirrors Base44's entity surface one-to-one:
`bool.entities.<table>` exposes the full entity surface:
- **Reads:** `list`, `filter`, `get` — with `sort` (`-col`), `limit`, `skip`,
and `fields` (column selection).
- **Writes:** `create`, `bulkCreate`, `update`, `bulkUpdate`, `delete`.
Expand All @@ -96,7 +171,7 @@ await bool.entities.todos.filter({ status: "active", count: { $gte: 10 } });
Methods return row data directly and throw on error. Additive and
backward-compatible — `bool.db` / `supabase` still work.

Known gaps vs. Base44 (documented, follow-ups): `updateMany` with
Known gaps (documented, follow-ups): `updateMany` with
`$inc/$mul/$push/$pull` is read-modify-write (not atomic under concurrent
writers — a Postgres RPC would make it atomic); `$size` (filter by array
length) isn't expressible over PostgREST and is omitted.
Expand Down
1 change: 1 addition & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
@AGENTS.md
74 changes: 73 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ tested, and upgradable independently of any one app.
## What it does

- **Entities data API.** `client.entities.<table>` is the recommended way to
read/write data — a one-to-one mirror of Base44's entity surface: `list`,
read/write data — a simple, high-level entity surface: `list`,
`filter`, `get`, `create`, `bulkCreate`, `update`, `bulkUpdate`, `updateMany`,
`delete`, `deleteMany`, `importEntities`, `subscribe`. It hides Supabase/SQL
entirely; methods return rows directly and throw on error:
Expand Down Expand Up @@ -68,6 +68,78 @@ tested, and upgradable independently of any one app.
`useBoolAuth()`, `<AuthGate>`, and the headless `useSignInForm()` state
machine that login forms bind to.

## Local Development (Your Own Machine)

Build an app on your computer, use a Bool project as your backend, then
publish to `https://<slug>.bool.so`. This is the one case where you install
the SDK yourself.

### Quick Start

```bash
npm install bool-sdk
export BOOL_TOKEN=bool_live_xxxxx # from Bool → Settings → Access tokens

npx bool link --project <id> # connect to a Bool project
npx bool entities push --dir bool/entities # push schema changes
npx bool deploy # publish when ready
```

**Three new files after `link`:**
- `bool.config.json` — project metadata (commit this)
- `.env.bool` — admin key (gitignore, keep secret)
- `bool/types.d.ts` — TypeScript types (auto-updated)

**Then in your app:**

```ts
import { createBoolClient } from "bool-sdk";
import config from "./bool.config.json";

export const bool = createBoolClient({
supabaseUrl: config.supabaseUrl,
supabaseAnonKey: config.supabaseAnonKey,
schema: config.schema,
appOrigin: config.appOrigin,
slug: config.slug,
apiKey: process.env.BOOL_API_KEY, // from .env.bool
});

// Now use your data
const todos = await bool.entities.todos.list();
```

### Documentation

Complete guides and API reference at **[bool.com/docs](https://bool.com/docs)**:

- **[Local Development](https://bool.com/docs/local-development)** — complete
walkthrough with use cases, workflows, and tips
- **[CLI Reference](https://bool.com/docs/cli)** — command-line tools
- **[SDK Reference](https://bool.com/docs/sdk-reference)** — API documentation
- **[Data Design](https://bool.com/docs/database)** — schema patterns and
privacy

### Admin Key Gotcha

When using the admin key (`apiKey`), on a **private** entity (one with
`user_id` owner field), you must set `user_id` explicitly:

```ts
// ❌ Fails on private entity (NOT NULL constraint)
await bool.entities.tasks.create({ title: "Task" });

// ✅ Works
await bool.entities.tasks.create({ title: "Task", user_id: userId });
```

The admin key has no user identity, so it can't default `user_id`. End-user
clients and `boolk_` keys carry the user and default automatically.

Coding agents can do all of the above through Bool's MCP server instead
(`list_entities`, `define_entity`, `list_records`, `get_entity_types`,
`get_project_connection`, …) — see the platform docs.

## Usage

```ts
Expand Down
7 changes: 5 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
{
"name": "bool-sdk",
"version": "0.2.0-next.10",
"description": "Client SDK for apps built on Bool — gateway data access, end-user auth, the AI battery, and the React auth layer.",
"version": "0.2.0-next.16",
"description": "Client SDK for apps built on Bool — gateway data access, end-user auth, the AI battery, the React auth layer, and the local-dev CLI (link, types, deploy).",
"type": "module",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"bin": {
"bool": "./dist/cli-entry.js"
},
"exports": {
".": {
"types": "./dist/index.d.ts",
Expand Down
6 changes: 6 additions & 0 deletions src/cli-entry.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#!/usr/bin/env node
// npm bin entry for the bool-sdk CLI (package.json "bin"). All logic lives in
// cli.ts so tests can drive it with stubbed deps.
import { runCli } from "./cli.js";

process.exit(await runCli(process.argv.slice(2)));
Loading
Loading