# @burdenoff/sdk-libs

Modular SDK library shared across all Burdenoff product SDKs (Node/TypeScript).

Each module under `src/modules/<name>/` exports an `SdkModule` with `attach(ctx) -> API`. Product SDKs (`@vibecontrols/sdk-node`, `@botlit/sdk-node`, etc.) become thin shells that pick which modules to mount. Sister to [`@burdenoff/cli-sdk`](https://github.com/algoshred/cli-sdk).

## Architecture

- **Core** (`src/core/`): `SdkContext` prop bag, `SdkModule` contract, `BaseGraphQLClient` (dual workspace+global gateway), `AuthStore` with pluggable `TokenStore` (`InMemory`, `File`, `Env`), error hierarchy with token redaction, `ModuleRegistry` for cross-module access.
- **Modules** (`src/modules/<name>/`): `index.ts` (default-exports `SdkModule`), `operations.ts` (hand-written `gql` strings), `api.ts` (the class returned by `attach`), `types.ts` (re-exports from `__generated__/`), `__generated__/types.ts` (codegen output, gitignored).
- **Hard rules**: Modules NEVER import each other directly — use `ctx.modules.get<API>('id')`. Modules NEVER call `process.exit` or write secrets to logs.

## Build

- **tsup** dual ESM+CJS, multi-entry, `dts: true`. Entries: `src/index.ts`, `src/core/index.ts`, `src/modules/*/index.ts`.
- `external`: `graphql`, `graphql-request`, `graphql-ws` (peer deps).
- Subpath imports: `@burdenoff/sdk-libs/core`, `@burdenoff/sdk-libs/modules/<name>`.

## Commands

```bash
bun install
bun run dev               # tsup watch
bun run build             # tsup once
bun run sanity            # format:check + lint + typecheck + build + test
bun run test              # vitest run
bun run codegen           # GraphQL types from pinned Hive supergraph
bun run parity:check      # cross-language manifest diff vs sdk-libs-python
bun run publish:verdaccio # alpha tag to internal Verdaccio
```

## Adding a module

1. `mkdir src/modules/<name>` with `index.ts`, `operations.ts`, `api.ts`, `types.ts`.
2. Default-export an `SdkModule<API>` from `index.ts`.
3. Add the module to `schema/modules.yaml` (operations + dependsOn).
4. Mirror in `~/products/sdk-libs-python/` in the same PR pair.
5. tsup picks it up automatically (`src/modules/*/index.ts` glob).

## Testing

- Unit (`tests/unit/`): pure logic — arg parsers, response transformers, gql doc builders. No HTTP. Vitest, <5s.
- Integration (`tests/integration/`): MSW intercepts GraphQL requests. Mock factories derived from `__generated__/types`. Schema rename breaks mock = test fail.
- E2E (`tests/e2e/`): real svc + state, run nightly. Mirrors `~/products/vibecontrols/vibecontrols-doctor/scripts/test-*-crud.sh`.
- Parity (`tests/parity/<scenario>.yaml`): same scenario file run by node + python. CI fails if shapes diverge.

## Reference

- `~/products/burdenoff-be-sdk-node/` — reference for tsup multi-entry + verdaccio publish.
- `~/products/cli-sdk/` — sister CLI SDK.
- `~/products/vibecontrols/vibecontrols-sdk-node/` — first consumer (thin shell).
- `~/products/dev/audit/index/vibecontrols.md` — 23-module ground-truth.
