175 lines
5.6 KiB
Markdown
175 lines
5.6 KiB
Markdown
# OpenSpec Change: enterprise-api-shared
|
|
|
|
- **Change ID**: enterprise-api-shared
|
|
- **Package**: `@suaveplan/api-shared`
|
|
- **Category**: api/framework
|
|
- **Target path**: `api/framework/api-shared`
|
|
- **Status**: PROPOSED
|
|
- **Date**: 2026-04-24
|
|
- **Reference spec**: `/mnt/s/web/suaveplan/enterprise/api-shared.md`
|
|
|
|
---
|
|
|
|
## Summary
|
|
|
|
Deliver `@suaveplan/api-shared` on the genesis branch from scratch at enterprise quality. The package provides shared utilities, middleware factories, and types consumed by every `@suaveplan/api-plugin-*` package: response helpers (success/error envelopes, pagination), middleware factories (request-id, correlation-id, tenant-context, request-logging), Zod schema utilities (paginated query parsing, sort/filter normalisation), and typed Hono context extensions. Genesis adds structured errors, OTel instrumentation, `@suaveplan/logger` integration, and a full benchmark suite.
|
|
|
|
---
|
|
|
|
## Current-state audit (genesis)
|
|
|
|
The package does not exist on genesis yet — fresh build. No prior source, no test results, no coverage data.
|
|
|
|
---
|
|
|
|
## Available workspace deps on genesis
|
|
|
|
| Package | Role |
|
|
|---|---|
|
|
| `@suaveplan/error` (`workspace:^`) | `ApiSharedError` base + error codes |
|
|
| `@suaveplan/types` (`workspace:^`) | `LoggerLike`, `EventBusLike` |
|
|
| `@suaveplan/logger` (`workspace:^`) | Request-logging middleware |
|
|
| `@suaveplan/api` (`workspace:^`) | `PluginContext` type, `HonoApp` |
|
|
| `@suaveplan/api-schemas` (`workspace:^`) | Pagination / sort / filter Zod schemas |
|
|
| `hono` (`catalog:server`) | Middleware type + context |
|
|
| `@hono/zod-openapi` (`catalog:server`) | Typed route helpers |
|
|
| `zod` (`catalog:forms`) | Schema validation |
|
|
| `@opentelemetry/api` (`catalog:observability`) | Spans + metrics |
|
|
| `tslib` (`catalog:build`) | Runtime helpers |
|
|
|
|
---
|
|
|
|
## Public API surface
|
|
|
|
### Response helpers
|
|
|
|
```ts
|
|
function successResponse<T>(data: T, meta?: ResponseMeta): ApiSuccessResponse<T>
|
|
function errorResponse(error: SuaveplanError): ApiErrorResponse
|
|
function paginatedResponse<T>(items: T[], pagination: PaginationMeta): ApiPaginatedResponse<T>
|
|
function noContentResponse(): Response // 204
|
|
```
|
|
|
|
### Middleware factories
|
|
|
|
```ts
|
|
function requestIdMiddleware(): MiddlewareHandler // X-Request-ID header inject + propagate
|
|
function correlationIdMiddleware(): MiddlewareHandler // X-Correlation-ID propagate
|
|
function tenantContextMiddleware(): MiddlewareHandler // extract tenantId into Hono context
|
|
function requestLoggingMiddleware(logger: LoggerLike): MiddlewareHandler
|
|
function errorHandlerMiddleware(): MiddlewareHandler // converts SuaveplanError → RFC 7807
|
|
```
|
|
|
|
### Schema utilities
|
|
|
|
```ts
|
|
function parsePaginationQuery(query: unknown): PaginationQuery
|
|
function parseSortQuery(query: unknown, allowedFields: string[]): SortQuery
|
|
function parseFilterQuery(query: unknown, allowedFields: string[]): FilterQuery
|
|
```
|
|
|
|
### Types
|
|
|
|
```ts
|
|
interface ApiSuccessResponse<T> { success: true; data: T; meta?: ResponseMeta }
|
|
interface ApiErrorResponse { success: false; error: ApiErrorEnvelope }
|
|
interface ApiPaginatedResponse<T> extends ApiSuccessResponse<T[]> { pagination: PaginationMeta }
|
|
interface PaginationMeta { page: number; pageSize: number; total: number; totalPages: number }
|
|
interface ResponseMeta { requestId?: string; timestamp?: string; [key: string]: unknown }
|
|
```
|
|
|
|
### Error codes
|
|
|
|
```ts
|
|
type ApiSharedErrorCode =
|
|
| "API_SHARED_INVALID_PAGINATION"
|
|
| "API_SHARED_INVALID_SORT"
|
|
| "API_SHARED_INVALID_FILTER"
|
|
| "API_SHARED_MISSING_TENANT"
|
|
```
|
|
|
|
---
|
|
|
|
## Genesis additions
|
|
|
|
1. **RFC 7807 Problem+JSON** error handler middleware — converts `SuaveplanError` to structured problem detail body.
|
|
2. **OTel** — `requestLoggingMiddleware` records `http.request_duration_ms` histogram; correlation-id propagated as span attribute.
|
|
3. **Zod schemas** for all public options (pagination, sort, filter) exported for downstream reuse.
|
|
4. **`@suaveplan/api-schemas` delegation** — `parsePaginationQuery` wraps `@suaveplan/api-schemas`' `PaginationQuerySchema`.
|
|
5. **Benchmark suite** measuring middleware chain overhead.
|
|
|
|
---
|
|
|
|
## File layout
|
|
|
|
```text
|
|
api/framework/api-shared/
|
|
package.json
|
|
tsconfig.json
|
|
vitest.config.ts
|
|
src/
|
|
index.ts
|
|
constants/index.ts
|
|
types/
|
|
common.ts
|
|
common.md
|
|
errors/
|
|
api-shared-errors.ts
|
|
api-shared-errors.md
|
|
api-shared-errors.test.ts
|
|
index.ts
|
|
responses/
|
|
response-helpers/
|
|
response-helpers.ts
|
|
response-helpers.md
|
|
response-helpers.test.ts
|
|
index.ts
|
|
middleware/
|
|
request-id/
|
|
request-id.ts
|
|
request-id.md
|
|
request-id.test.ts
|
|
index.ts
|
|
correlation-id/
|
|
correlation-id.ts
|
|
correlation-id.md
|
|
correlation-id.test.ts
|
|
index.ts
|
|
tenant-context/
|
|
tenant-context.ts
|
|
tenant-context.md
|
|
tenant-context.test.ts
|
|
index.ts
|
|
request-logging/
|
|
request-logging.ts
|
|
request-logging.md
|
|
request-logging.test.ts
|
|
index.ts
|
|
error-handler/
|
|
error-handler.ts
|
|
error-handler.md
|
|
error-handler.test.ts
|
|
index.ts
|
|
schemas/
|
|
pagination/
|
|
pagination.ts
|
|
pagination.md
|
|
pagination.test.ts
|
|
index.ts
|
|
sort-filter/
|
|
sort-filter.ts
|
|
sort-filter.md
|
|
sort-filter.test.ts
|
|
index.ts
|
|
__benchmarks__/
|
|
middleware.bench.ts
|
|
tests/
|
|
integration.test.ts
|
|
```
|
|
|
|
---
|
|
|
|
## Impact
|
|
|
|
Every `api-plugin-*` package imports from `@suaveplan/api-shared`. This package must be published before any plugin can be built. Prerequisites: `@suaveplan/error`, `@suaveplan/types`, `@suaveplan/logger`, `@suaveplan/api`, `@suaveplan/api-schemas`.
|