Initial Commit

This commit is contained in:
2026-05-27 23:29:53 +01:00
commit fbc70f96e6
10000 changed files with 1102152 additions and 0 deletions

View File

@@ -0,0 +1,86 @@
# OpenSpec Change: enterprise-api-plugin-graphql
- **Change ID**: enterprise-api-plugin-graphql
- **Package**: `@suaveplan/api-plugin-graphql`
- **Category**: api/data
- **Target path**: `api/data/api-plugin-graphql`
- **Status**: PROPOSED
- **Date**: 2026-04-24
- **Reference spec**: `/mnt/s/web/suaveplan/enterprise/api-plugin-graphql.md`
---
## Summary
Deliver `@suaveplan/api-plugin-graphql` on the genesis branch from scratch at enterprise quality. GraphQL plugin for `@suaveplan/api`: schema-first with type-safe resolvers, query depth and complexity limiting, persisted queries, DataLoader-based N+1 prevention, subscription support over SSE/WebSocket, query cost analysis, auth integration (`@context.user`), per-operation rate limiting, and an introspection toggle (disabled in production). Routes: `POST /graphql`, `GET /graphql` (GraphiQL in dev). Built on `graphql-js` with a lightweight schema-builder abstraction. Events: `graphql:operation:completed`, `graphql:error`.
---
## Available workspace deps on genesis
| Package | Role |
|---|---|
| `@suaveplan/api` (`workspace:^`) | `definePlugin` |
| `@suaveplan/api-shared` (`workspace:^`) | Helpers |
| `@suaveplan/api-plugin-auth` (`workspace:^`) | `requireAuth` |
| `@suaveplan/events` (`workspace:^`) | Event bus (subscriptions fan-out) |
| `@suaveplan/rate-limiter` (`workspace:^`) | Per-operation rate limits |
| `@suaveplan/error` (`workspace:^`) | `GraphqlPluginError` hierarchy |
| `graphql` (`catalog:server`) | GraphQL execution engine |
| `hono` + `zod` | Routes/schemas |
| `@opentelemetry/api` | OTel |
---
## Public API surface
```ts
function createGraphqlPlugin(schema: GraphQLSchema, config?: GraphqlPluginConfig): PluginDescriptor
interface GraphqlPluginConfig {
path?: string // default: /graphql
introspection?: boolean // default: false in production
maxDepth?: number
maxComplexity?: number
persistedQueries?: PersistedQueryStore
playground?: boolean
}
// Helper for building typed resolvers:
function createResolver<TRoot, TArgs, TContext, TResult>(
fn: (root: TRoot, args: TArgs, ctx: TContext) => Promise<TResult>
): typeof fn
```
### Error codes
```ts
type GraphqlPluginErrorCode =
| "GRAPHQL_QUERY_TOO_DEEP"
| "GRAPHQL_QUERY_TOO_COMPLEX"
| "GRAPHQL_PERSISTED_QUERY_NOT_FOUND"
| "GRAPHQL_EXECUTION_ERROR"
| "GRAPHQL_PARSE_ERROR"
```
---
## File layout
```text
api/data/api-plugin-graphql/
package.json tsconfig.json vitest.config.ts
src/
index.ts events.ts types/ errors/
core/depth-limiter/ core/complexity/ core/dataloader/ core/persisted-queries/
middleware/auth-context/
routes/graphql/
utils/schema-helpers.ts
tests/integration.test.ts
```
---
## Impact
Prerequisites: `@suaveplan/api`, `@suaveplan/api-plugin-auth`, `@suaveplan/events`, `@suaveplan/rate-limiter`, `graphql`.

View File

@@ -0,0 +1,73 @@
# Tasks: enterprise-api-plugin-graphql
**Change ID**: enterprise-api-plugin-graphql
**Package**: `@suaveplan/api-plugin-graphql`
**Target path**: `api/data/api-plugin-graphql`
**Prerequisite packages on Verdaccio**: `@suaveplan/api`, `@suaveplan/api-shared`, `@suaveplan/api-plugin-auth`, `@suaveplan/events`, `@suaveplan/rate-limiter`, `@suaveplan/error`, `graphql` (external)
---
## 0. Pre-flight (non-negotiable)
- [ ] 0.1 Confirm clean working tree (`git status` reports nothing) and no in-flight worktrees with uncommitted work (`git worktree list` then `git status` in each)
- [ ] 0.2 If any worktrees exist under `.claude/worktrees/`, account for each one: still-active agent, work-pending-merge, or stale-and-prune. Stale worktrees MUST be removed (`git worktree remove`) before opening a new one — code that has been lost twice on main is the failure mode this guards against.
- [ ] 0.3 Confirm the package set in `MANIFEST.md` matches `find packages -maxdepth 3 -name package.json` count. Drift here means a prior change archived without regenerating the manifest.
## 1. Scaffold + types + errors + events
- [ ] Create directory; `package.json` v0.0.0; `graphql` in deps (catalog); standard tooling.
- [ ] Types: `GraphqlPluginConfig` (Zod), `PersistedQueryStore`, `GraphqlContext`, `OperationResult`.
- [ ] Errors: 5-code union + registration. Test + doc.
- [ ] Events: `GraphqlEventMap` (graphql:operation:completed, graphql:error).
---
## 2. Core: depth limiter
- [ ] `buildMaxDepthRule(maxDepth: number): ValidationRule` — GraphQL validation rule that rejects queries deeper than `maxDepth`. Test + doc.
---
## 3. Core: complexity analysis
- [ ] `buildComplexityRule(maxComplexity: number, fieldComplexities?: Record<string, number>): ValidationRule` — scores query and rejects over threshold. Test + doc.
---
## 4. Core: DataLoader factory
- [ ] `createDataLoader<K, V>(batchFn)` — thin wrapper ensuring all resolvers use DataLoader for N+1 prevention. Test + doc.
---
## 5. Core: persisted queries
- [ ] `PersistedQueryStore` interface: `get(hash: string): Promise<string | null>`, `set(hash, query): Promise<void>`.
- [ ] `MemoryPersistedQueryStore` default. Test + doc.
---
## 6. Auth context middleware
- [ ] Extract JWT user from `requireAuth`; make available as `ctx.user` in GraphQL execution context.
- [ ] Test + doc.
---
## 7. Routes
- [ ] `POST /graphql` — parse body; apply persisted-query lookup if `extensions.persistedQuery` present; validate (depth + complexity + auth); execute; record OTel span + counters; emit event.
- [ ] `GET /graphql` — serve GraphiQL HTML if `config.playground` and `NODE_ENV !== 'production'`.
- [ ] Rate limit per operation type on `POST /graphql`.
- [ ] Route `.test.ts` + `.md`.
---
## 8. Plugin factory + integration tests + publish
- [ ] `createGraphqlPlugin(schema, config?)`: `definePlugin`, `dependencies: ["auth"]`.
- [ ] `onInit`: register configured middleware; disable introspection in production.
- [ ] Integration: execute simple query → depth limit rejected → persisted query found + executed.
- [ ] `bunx turbo lint typecheck test --filter=@suaveplan/api-plugin-graphql` — green; 100% coverage.
- [ ] `bun scripts/publish.ts --package @suaveplan/api-plugin-graphql`.
- [ ] Archive → `openspec/archive/2026-04-24-enterprise-api-plugin-graphql/`.