Files
operations/docs/architecture/build-distribution.md
glm-5.1 ddc0607b90 docs: clean up ADR-005 architecture docs after envelope implementation
Remove stale ADR-005 drift tables across all architecture docs since
ResponseEnvelope types, factories, detection, and integration points
are now fully implemented in source code. Key changes:

- api-surface.md: Remove ADR-005 drift table (all items implemented),
  retain ADR-006 drift table without execute() return type (now done)
- call-protocol.md: Remove ADR-005 drift table, update ADR-006 table,
  fix CallHandlerConfig to show callMap? (current source)
- adapters.md: Remove 'current source state' and 'implementation
  changes needed' tables for from_mcp and from_openapi, replace with
  current-accurate descriptions of envelope behavior
- response-envelopes.md: Remove 'current source state' blocks,
  update migration checklist to show all code changes completed
- 005-response-envelopes.md: Change status from Draft to Implemented
- 006-unified-invocation-path.md: Update Prerequisites section to note
  ADR-005 is now implemented
- build-distribution.md: Add response-envelope.ts to source layout
- architecture.md: Add response-envelopes.md link and ADR-005/006
  entries to design decisions table
- README.md: Add response-envelopes.md to documents table
- Update last_updated dates on all changed docs
2026-05-11 02:55:13 +00:00

138 lines
4.8 KiB
Markdown

---
status: draft
last_updated: 2026-05-11
---
# Build & Distribution
Dependencies, project structure, sub-path exports, peer deps, and build tooling.
## Dependencies
### Runtime
| Package | Purpose |
|---------|---------|
| `@alkdev/typebox` | Schema system. `Type` for building schemas, `Value` for validation, `KindGuard` for schema assertion. |
| `@alkdev/pubsub` | Call protocol transport. `PendingRequestMap` creates an internal `PubSub` for event routing. Uses `subscribe(type, id)` and `publish(type, id, payload)` API with `EventEnvelope` wrapping. |
| `@logtape/logtape` | Structured logging. Direct import, no wrapper. See [ADR-001](decisions/001-logger-direct-import.md). |
### Peer (Optional)
| Package | Required By | Purpose |
|---------|-------------|---------|
| `@modelcontextprotocol/sdk` | `from_mcp` sub-path | MCP client transport (stdio, HTTP). Dynamic import — only loaded when `createMCPClient` is called. |
### Dev
| Package | Purpose |
|---------|---------|
| `tsup` | Build tool. Dual ESM + CJS with declarations. |
| `typescript` | Type checking (`tsc --noEmit` for lint). |
| `vitest` | Test runner. |
| `@vitest/coverage-v8` | V8 coverage provider. |
| `@modelcontextprotocol/sdk` | Dev dep for MCP tests. Also listed as optional peer. |
| `@types/node` | Node.js type definitions. |
## Project Structure
```
@alkdev/operations/
src/
index.ts # Barrel: re-exports all public API
types.ts # Core types: IOperationDefinition, OperationSpec, OperationType, etc.
registry.ts # OperationRegistry: registerSpec, registerHandler, execute, get, list
validation.ts # assertIsSchema, validateOrThrow, collectErrors, formatValueErrors
response-envelope.ts # ResponseEnvelope types, factories, detection, schemas, unwrap
call.ts # PendingRequestMap, buildCallHandler, CallEventMap, event types
subscribe.ts # subscribe(): direct AsyncGenerator execution
env.ts # buildEnv(): namespace-keyed env with direct/call-protocol modes
error.ts # CallError, InfrastructureErrorCode, mapError
from_schema.ts # FromSchema: JSON Schema → TypeBox conversion
from_openapi.ts # FromOpenAPI, FromOpenAPIFile, FromOpenAPIUrl
from_mcp.ts # createMCPClient, closeMCPClient, MCPClientLoader
scanner.ts # scanOperations: filesystem auto-discovery
test/
# Unit tests per module
docs/
architecture.md
architecture/
README.md
api-surface.md
call-protocol.md
adapters.md
build-distribution.md
decisions/
package.json
tsconfig.json
tsup.config.ts
vitest.config.ts
```
## Sub-Path Exports
```json
{
"exports": {
".": {
"import": { "types": "./dist/index.d.ts", "default": "./dist/index.js" },
"require": { "types": "./dist/index.d.cts", "default": "./dist/index.cjs" }
},
"./from-mcp": {
"import": { "types": "./dist/from-mcp.d.ts", "default": "./dist/from-mcp.js" },
"require": { "types": "./dist/from-mcp.d.cts", "default": "./dist/from-mcp.cjs" }
}
}
}
```
The `./from-mcp` sub-path isolates the MCP SDK peer dependency. Consumers that don't use MCP don't need to install `@modelcontextprotocol/sdk`. See [ADR-003](decisions/003-peer-dep-adapters.md).
The main barrel (`src/index.ts`) re-exports everything including `createMCPClient` and `MCPClientLoader` for convenience. The sub-path exists for explicit dependency isolation, not for excluding from the barrel.
## Build
- **Tool**: `tsup` — produces dual ESM + CJS with declarations
- **Entry points**: `src/index.ts`, `src/from_mcp.ts`
- **Format**: ESM + CJS
- **Target**: `es2022`
- **Splitting**: enabled
```ts
// tsup.config.ts
import { defineConfig } from 'tsup'
export default defineConfig({
entry: ['src/index.ts', 'src/from_mcp.ts'],
format: ['esm', 'cjs'],
dts: true,
sourcemap: true,
clean: true,
splitting: true,
target: 'es2022',
})
```
## Scripts
| Script | Command | Purpose |
|--------|---------|---------|
| `build` | `tsup` | Build ESM + CJS + declarations |
| `lint` | `tsc --noEmit` | Type-check only (no emit) |
| `test` | `vitest run` | Run tests |
| `test:watch` | `vitest` | Watch mode |
| `test:coverage` | `vitest run --coverage` | Coverage report (v8) |
## Testing
- **Runner**: `vitest`
- **Coverage**: `@vitest/coverage-v8`
- **Config**: `vitest.config.ts`
Tests should mock external services (MCP servers, HTTP endpoints) and use injectable FS interfaces (`ScannerFS`, `OpenAPIFS`) rather than real filesystem access.
## Targets
- **Publish**: npm (`@alkdev/operations`)
- **Runtime**: Node 18+, Deno, Bun — pure JS except `from_mcp` which requires `@modelcontextprotocol/sdk`
- **Deno compatibility**: Source is standard TypeScript with no Deno-specific APIs. Runtime-agnostic FS injection means Deno can provide its own `ScannerFS` and `OpenAPIFS` implementations