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
106 changes: 105 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ jobs:
"sqlrite-desktop-v$V"
"sqlrite-py-v$V"
"sqlrite-node-v$V"
"sqlrite-notes-v$V"
"sqlrite-wasm-v$V"
"sdk/go/v$V"
"v$V"
Expand Down Expand Up @@ -1154,6 +1155,108 @@ jobs:
See the umbrella release [v${{ needs.detect.outputs.version }}](../../releases/tag/v${{ needs.detect.outputs.version }}) for the full changelog.
generate_release_notes: true

# ---------------------------------------------------------------------------
# Step 3g': publish the `sqlrite-notes` example as a pure-JS npm
# package so users can `npx sqlrite-notes init <dir>` on a fresh
# machine without cloning the repo. (SQLR-64, follow-up from SQLR-40.)
#
# The package itself ships no binaries — it's a thin CLI on top of
# the `@joaoh82/sqlrite` N-API package (which carries the prebuilt
# `.node` binaries via the platform-dispatch shim) and spawns
# `sqlrite-mcp` as a subprocess for the read side. The Node bits
# are platform-agnostic JS modules, so this job is a single ubuntu
# cell instead of the publish-nodejs build matrix.
#
# `needs: publish-nodejs` is load-bearing: the example's
# `@joaoh82/sqlrite` dep pin resolves against the version that
# publish-nodejs just put on npm. Without that ordering, `npx
# sqlrite-notes@<new>` would resolve a slightly-stale engine on
# the first install after release (caret pin floats up *eventually*
# but the npm cache will have served the old one for minutes).
#
# Package name: **unscoped `sqlrite-notes`** (per ticket). The
# similarity rejection that hit `sqlrite` (vs `sqlite`) doesn't
# apply here — `notes` isn't a confusable suffix. If the registry
# ever rejects this on a future bootstrap, fall back to
# `@joaoh82/sqlrite-notes` and update both `package.json` and
# `docs/release-secrets.md`'s trusted-publisher section.
#
# OIDC trusted-publisher setup mirrors publish-nodejs verbatim —
# see that job's comment block for the long-form rationale on why
# `registry-url` is omitted, why we force-upgrade npm to 11.5+, and
# why `--provenance --access public --loglevel verbose` is the
# canonical flag combo.
publish-notes-example:
name: Publish sqlrite-notes example to npm
needs: [detect, tag-all, publish-nodejs]
if: needs.detect.outputs.should_release == 'true'
runs-on: ubuntu-latest
environment: release
permissions:
# OIDC for npm trusted publisher + provenance signing.
id-token: write
# For softprops/action-gh-release at the end.
contents: write
steps:
- uses: actions/checkout@v4

# Same OIDC dance as publish-nodejs — see that job's comment
# block for why we deliberately do NOT set `registry-url:`.
- uses: actions/setup-node@v4
with:
node-version: '20'

- name: Upgrade npm to latest (need 11.5+ for trusted publishing)
run: npm install -g npm@latest

- name: List publish payload + OIDC env diagnostics
working-directory: examples/nodejs-notes
run: |
ls -la
echo "---"
npm --version
echo "---"
echo "ACTIONS_ID_TOKEN_REQUEST_URL is set: ${ACTIONS_ID_TOKEN_REQUEST_URL:+yes}${ACTIONS_ID_TOKEN_REQUEST_URL:-NO}"
echo "ACTIONS_ID_TOKEN_REQUEST_TOKEN is set: ${ACTIONS_ID_TOKEN_REQUEST_TOKEN:+yes}${ACTIONS_ID_TOKEN_REQUEST_TOKEN:-NO}"
echo "---"
# `npm pack --dry-run` prints exactly what will end up in
# the tarball. The `files` whitelist in package.json should
# produce: bin/sqlrite-notes.mjs, src/*.mjs, README.md,
# package.json — nothing else (no test fixtures, no
# node_modules).
npm pack --dry-run

- name: Publish to npm
working-directory: examples/nodejs-notes
run: npm publish --access public --provenance --loglevel verbose

- name: GitHub Release
uses: softprops/action-gh-release@v2
with:
tag_name: sqlrite-notes-v${{ needs.detect.outputs.version }}
name: sqlrite-notes example v${{ needs.detect.outputs.version }}
body: |
Published to npm: https://www.npmjs.com/package/sqlrite-notes/v/${{ needs.detect.outputs.version }}

```bash
# Ingest a folder of markdown notes into a SQLRite database
# — no clone, no Rust toolchain, no env setup beyond an
# optional embedding API key.
npx sqlrite-notes@${{ needs.detect.outputs.version }} init ~/Documents/notes
```

The example uses `@joaoh82/sqlrite@^${{ needs.detect.outputs.version }}` for storage + retrieval (HNSW + BM25) and spawns [`sqlrite-mcp`](../../releases/tag/sqlrite-mcp-v${{ needs.detect.outputs.version }}) as a subprocess to expose the database to Claude Desktop / any MCP client. Install `sqlrite-mcp` separately — `cargo install sqlrite-mcp` or a prebuilt binary from the MCP release.

Verify package provenance:
```bash
npm audit signatures
```

Full docs: [`examples/nodejs-notes/README.md`](https://github.com/joaoh82/rust_sqlite/blob/main/examples/nodejs-notes/README.md).

See the umbrella release [v${{ needs.detect.outputs.version }}](../../releases/tag/v${{ needs.detect.outputs.version }}) for the full changelog.
generate_release_notes: true

# ---------------------------------------------------------------------------
# Step 3h: build the WASM package via wasm-pack and publish to
# npm as @joaoh82/sqlrite-wasm. (Phase 6h.)
Expand Down Expand Up @@ -1480,7 +1583,7 @@ jobs:
# config if we add one later.
finalize:
name: Finalize umbrella release
needs: [detect, publish-crate, publish-ask, publish-mcp, build-mcp-binaries, publish-ffi, publish-desktop, publish-python, publish-nodejs, publish-wasm, publish-go]
needs: [detect, publish-crate, publish-ask, publish-mcp, build-mcp-binaries, publish-ffi, publish-desktop, publish-python, publish-nodejs, publish-notes-example, publish-wasm, publish-go]
if: needs.detect.outputs.should_release == 'true'
runs-on: ubuntu-latest
steps:
Expand All @@ -1504,6 +1607,7 @@ jobs:
- 🖥️ [Desktop](../../releases/tag/sqlrite-desktop-v${{ needs.detect.outputs.version }}) — unsigned installers for Linux (AppImage + deb), macOS (dmg aarch64), Windows (msi)
- 🐍 [Python](../../releases/tag/sqlrite-py-v${{ needs.detect.outputs.version }}) → [PyPI](https://pypi.org/project/sqlrite/${{ needs.detect.outputs.version }}/) — abi3-py38 wheels for Linux x86_64/aarch64, macOS aarch64, Windows x86_64 + sdist
- 🟢 [Node.js](../../releases/tag/sqlrite-node-v${{ needs.detect.outputs.version }}) → [npm](https://www.npmjs.com/package/@joaoh82/sqlrite/v/${{ needs.detect.outputs.version }}) — N-API bindings with prebuilt `.node` binaries for Linux x86_64/aarch64, macOS aarch64, Windows x86_64
- 📝 [`sqlrite-notes` example](../../releases/tag/sqlrite-notes-v${{ needs.detect.outputs.version }}) → [npm](https://www.npmjs.com/package/sqlrite-notes/v/${{ needs.detect.outputs.version }}) — `npx sqlrite-notes init <dir>` ingests a folder of markdown notes into a SQLRite DB and exposes it to Claude Desktop / any MCP client
- 🌐 [WASM](../../releases/tag/sqlrite-wasm-v${{ needs.detect.outputs.version }}) → [npm](https://www.npmjs.com/package/@joaoh82/sqlrite-wasm/v/${{ needs.detect.outputs.version }}) — browser/bundler-target WebAssembly build via wasm-pack
- 🐹 [Go SDK](../../releases/tag/sdk%2Fgo%2Fv${{ needs.detect.outputs.version }}) → `go get github.com/joaoh82/rust_sqlite/sdk/go@v${{ needs.detect.outputs.version }}` — `database/sql` driver via cgo against `libsqlrite_c`

Expand Down
15 changes: 12 additions & 3 deletions docs/release-plan.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,17 +76,25 @@ GitHub Releases by product ("show me every Python release").
| `sqlrite-mcp` | `sqlrite-mcp-vX.Y.Z` | crates.io + GitHub Release (per-platform binary tarballs) |
| Python SDK | `sqlrite-py-vX.Y.Z` | PyPI + GitHub Release |
| Node.js SDK | `sqlrite-node-vX.Y.Z` | npm (`@joaoh82/sqlrite`) + GitHub Release |
| `sqlrite-notes` example | `sqlrite-notes-vX.Y.Z` | npm (`sqlrite-notes`) + GitHub Release |
| Go SDK | `sdk/go/vX.Y.Z` | Git tag (no registry) + GitHub Release assets |
| WASM | `sqlrite-wasm-vX.Y.Z` | npm (`@joaoh82/sqlrite-wasm`) + GitHub Release |
| Desktop app | `sqlrite-desktop-vX.Y.Z` | GitHub Release (unsigned installers) |
| **Meta** | `vX.Y.Z` | GitHub Release (links to the other nine; acts as the "this was release 0.2.0" anchor) |
| **Meta** | `vX.Y.Z` | GitHub Release (links to the other ten; acts as the "this was release 0.2.0" anchor) |

All ten tags point at the same commit — the merge commit of the
All eleven tags point at the same commit — the merge commit of the
release PR. The meta tag is the umbrella release users can link to
in announcements; the nine per-product tags are for tooling
in announcements; the ten per-product tags are for tooling
(crates.io, Go module proxy, npm dist-tags, etc.) that expects a
specific format.

> **`sqlrite-notes` joined the lockstep wave in v0.10.2 (SQLR-64).** Pure-JS
> CLI on top of `@joaoh82/sqlrite` + `sqlrite-mcp`; published unscoped on
> npm so `npx sqlrite-notes init <dir>` works on a fresh machine.
> `publish-notes-example` runs after `publish-nodejs` because the example
> resolves its `@joaoh82/sqlrite` pin against the version that
> publish-nodejs just put on npm.

> **`sqlrite-ask` joined the lockstep wave in v0.1.17 (Phase 7g.1).** Gets
> its own tag and crates.io publish but ships in lockstep with everything
> else — same version every wave. `publish-ask` runs after `publish-crate`
Expand Down Expand Up @@ -120,6 +128,7 @@ matching new value:
| `desktop/src-tauri/Cargo.toml` | `[package].version` |
| `desktop/src-tauri/tauri.conf.json` | `"version"` (top-level — Tauri reads this for installer names) |
| `desktop/package.json` | `"version"` (top-level) |
| `examples/nodejs-notes/package.json` | `"version"` + `"dependencies"."@joaoh82/sqlrite"` pin (caret) |
| `Cargo.lock` | auto-updated by `cargo build` after the above |

**Go** is not in this list — `sdk/go/go.mod` has no version field.
Expand Down
67 changes: 58 additions & 9 deletions docs/release-secrets.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,12 +102,14 @@ release, status flips to "active".

---

## 3. npm trusted publishers (two packages)
## 3. npm trusted publishers (three packages)

**Why two:** we publish `@joaoh82/sqlrite` (Node.js bindings from
`sdk/nodejs/`) and `@joaoh82/sqlrite-wasm` (browser bindings from
`sdk/wasm/`) as separate npm packages. Each needs its own
trusted-publisher record.
**Why three:** we publish `@joaoh82/sqlrite` (Node.js bindings from
`sdk/nodejs/`), `@joaoh82/sqlrite-wasm` (browser bindings from
`sdk/wasm/`), and `sqlrite-notes` (the chat-with-your-notes example
from `examples/nodejs-notes/`) as separate npm packages. Each needs
its own trusted-publisher record — set up §3a + §3b for the first
two scoped packages and §3c for the unscoped example.

**Why both are scoped:** npm's registry rejects unscoped names
that are too similar to existing popular packages — `sqlrite` is
Expand Down Expand Up @@ -184,6 +186,53 @@ claims". Burned us once on v0.1.7 (typo'd repo name in the
form); kept the form field reference here so the next person
doesn't have to re-debug.

### 3c. `sqlrite-notes` example — third npm package (SQLR-64)

The `examples/nodejs-notes/` example ships as a third npm package
so users can `npx sqlrite-notes init <dir>` on a fresh machine.
The `publish-notes-example` job in `release.yml` handles it
end-to-end with the same OIDC pattern as `publish-nodejs`.

**Why unscoped:** unlike `sqlrite` (rejected as too similar to
`sqlite`), `sqlrite-notes` is far enough from any existing npm
package that the similarity check shouldn't fire. If the
placeholder publish in step 1 below is rejected, fall back to the
scoped form `@joaoh82/sqlrite-notes` — update both
`examples/nodejs-notes/package.json`'s `name` field and the
`npm publish` step / GitHub Release body in `release.yml`.

**Bootstrap (one-time, with your local credentials):**

```bash
mkdir /tmp/sqlrite-notes-placeholder && cd /tmp/sqlrite-notes-placeholder
cat > package.json <<'JSON'
{
"name": "sqlrite-notes",
"version": "0.0.0",
"description": "Placeholder — real package ships from rust_sqlite CI",
"license": "MIT"
}
JSON
npm login # if not already
npm publish
```

If the unscoped name is rejected, retry with `@joaoh82/sqlrite-notes`
and amend the repo per the note above.

**Trusted publisher:**

1. Go to <https://www.npmjs.com/package/sqlrite-notes/access> (or
`…/package/@joaoh82/sqlrite-notes/access` if you fell back to
the scoped name).
2. **Add publisher** with the same field values as `@joaoh82/sqlrite`
above — Organization `joaoh82`, Repository `rust_sqlite`,
Workflow filename `release.yml`, Environment `release`.
3. Save.

**Verify**: status flips from "pending" to "active" after the
first successful CI publish.

---

## 4. GitHub `release` environment
Expand Down Expand Up @@ -286,10 +335,10 @@ Run through this once everything above is done:
- [ ] PyPI trusted-publisher page shows `rust_sqlite` /
`release.yml` / `release` pending for the `sqlrite`
project.
- [ ] npm trusted-publisher page shows the same for both
`@joaoh82/sqlrite` and `@joaoh82/sqlrite-wasm` (assuming
the placeholders are published per §3a — if not, section
3a applies).
- [ ] npm trusted-publisher page shows the same for all three of
`@joaoh82/sqlrite`, `@joaoh82/sqlrite-wasm`, and
`sqlrite-notes` (assuming the placeholders are published per
§3a / §3c — if not, those sections apply).
- [ ] Branch protection on `main` requires 14 status checks + 1
review.
- [ ] Open a dummy PR — the "Merge" button is greyed out until
Expand Down
39 changes: 23 additions & 16 deletions examples/nodejs-notes/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,22 +48,17 @@ straight from the inverted index).

## Install

The example lives inside the SQLRite monorepo for now (the umbrella
ticket SQLR-38 will lift it into its own repo once we've shipped a
few more).

```bash
git clone https://github.com/joaoh82/rust_sqlite
cd rust_sqlite/examples/nodejs-notes
npm install
npx sqlrite-notes init ~/Documents/notes
```

`npm install` pulls **`@joaoh82/sqlrite`** (pinned to `^0.10.0`) with
prebuilt napi-rs binaries for macOS-arm64, Linux x64/arm64, and
Windows x64 — no Rust toolchain required for the Node side.
That's it for the Node side — `npx` downloads `sqlrite-notes`, which
pulls **`@joaoh82/sqlrite`** with prebuilt napi-rs binaries for
macOS-arm64, Linux x64/arm64, and Windows x64. No clone, no
`npm install`, no Rust toolchain required.

`sqlrite-mcp` is a separate Rust binary. Install it once, anywhere
on your `PATH`:
`sqlrite-mcp` is a separate Rust binary used by the `serve`
subcommand. Install it once, anywhere on your `PATH`:

```bash
# from crates.io (~30s):
Expand All @@ -80,19 +75,24 @@ absolute path — `sqlrite-notes serve` will pick it up.

```bash
# 1. Ingest a folder of markdown into a notes.sqlrite database.
node bin/sqlrite-notes.mjs init ~/Documents/notes
npx sqlrite-notes init ~/Documents/notes

# 2. Confirm it works locally — same retrieval shape Claude will see.
node bin/sqlrite-notes.mjs search "what did I learn about CRDTs?"
npx sqlrite-notes search "what did I learn about CRDTs?"

# 3. Wire up Claude Desktop using the snippet printed by `init`
# (also available any time via `sqlrite-notes config`).
# (also available any time via `npx sqlrite-notes config`).

# 4. Open Claude Desktop. The sqlrite-mcp tools appear in the
# tool picker — `bm25_search`, `vector_search`, `query`, `ask`,
# plus `list_tables` / `describe_table` / `schema_dump`.
```

> **Pinning a version.** `npx sqlrite-notes` pulls the latest; pass
> `npx sqlrite-notes@0.10.1 …` (or whichever tag) to lock to a
> specific release. The package ships in lockstep with the SQLRite
> engine, so the version number matches `@joaoh82/sqlrite`'s.

Once you've added the snippet to `claude_desktop_config.json` and
restarted Claude Desktop, run a chat like:

Expand Down Expand Up @@ -275,9 +275,16 @@ Default is 0.5.

## Development

Hacking on the example itself — running tests, editing the CLI,
iterating against a local engine binding — uses the clone path:

```bash
git clone https://github.com/joaoh82/rust_sqlite
cd rust_sqlite/examples/nodejs-notes
npm install
npm test # offline; runs all 40 unit + integration tests
# Iterate against the local sources:
node bin/sqlrite-notes.mjs init ~/Documents/notes
```

The test suite uses `node:test` and exercises:
Expand All @@ -297,7 +304,7 @@ they skip cleanly (with a message) if it isn't.

```
examples/nodejs-notes/
├── package.json # @joaoh82/sqlrite pinned to ^0.10.0
├── package.json # @joaoh82/sqlrite pinned in lockstep with the engine release
├── README.md # this file
├── bin/
│ └── sqlrite-notes.mjs # entry — calls src/cli.mjs
Expand Down
12 changes: 6 additions & 6 deletions examples/nodejs-notes/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading