first commit

This commit is contained in:
2026-05-29 08:20:56 +01:00
commit 949299f58d
6368 changed files with 527176 additions and 0 deletions

View File

@@ -0,0 +1,48 @@
# `service/db-port.ts`
## Purpose
Declares `SiteDb`, the structural database port that `SiteService` and `DomainResolverService` consume. suaveplan's foundation `DatabaseAdapter` (`@suaveplan/db`) only owns `query` / `execute`, so the typed CRUD surface (`create`, `update`) we need for `site` records is sourced from `@suaveplan/surrealdb`'s `SurrealAdapter`. Centralising the port here lets the services depend on a single structural shape rather than `SurrealAdapter` directly, which keeps the unit tests free of testcontainer requirements and keeps the production wiring honest: any `SurrealAdapter` instance satisfies this shape by construction.
## Features
- One structural interface — `SiteDb` — exposing `query` (positional bindings), `create` (typed), `update` (typed).
- No runtime imports — pure type module.
- Lets tests supply minimal fakes without crafting a full `DatabaseAdapter`.
## Usage: Basic
```ts
import type { SiteDb } from "@suaveplan/api-plugin-site/service/db-port";
const fake: SiteDb = {
query: async () => [],
create: async (_t, d) => ({ ...d, id: "site:1" }),
update: async () => null,
};
```
## Usage: Advanced
```ts
import type { SurrealAdapter } from "@suaveplan/surrealdb";
import type { SiteDb } from "@suaveplan/api-plugin-site/service/db-port";
// Production wiring — the live SurrealAdapter satisfies SiteDb structurally.
function wire(db: SurrealAdapter): SiteDb {
return db;
}
```
## API Reference
- `interface SiteDb` —
- `query<T>(sql, params?): Promise<T[]>` — positional binds (`$p0...`).
- `create<T>(table, data): Promise<T & { id: string }>` — typed create.
- `update<T>(table, id, data): Promise<T | null>` — typed merge.
## Implementation Notes
- `query` bindings are positional because the `DatabaseAdapter.query` signature is `(sql, params?: readonly unknown[])`. The site plugin's SurQL statements are written with `$p0`, `$p1`, ... accordingly.
- The port deliberately omits transaction / migrate / connect surface — services don't need it. Adding new methods to the port is a breaking change and follows the OpenSpec workflow.
- The port is structural — adopters do not need to extend or implement an interface explicitly.