Files
pubsub/docs/architecture/build-distribution.md
glm-5.1 de7fc88f99 Simplify to transport-only: remove call protocol, add EventEnvelope, expand stream operators
- Remove src/call.ts (PendingRequestMap, CallEventSchema, CallError) — call protocol belongs in @alkdev/operations
- Add EventEnvelope type ({ type, id, payload }) as the cross-platform serialization contract
- Simplify createPubSub: replace PubSubPublishArgsByKey tuple model with PubSubEventMap; publish(type, id, payload) and subscribe(type, id) use explicit id for topic scoping
- Update Redis adapter to serialize/deserialize full EventEnvelope
- Expand operators: add take, reduce, toArray, batch, dedupe, window, flat, groupBy, chain, join
- Remove @alkdev/typebox runtime dependency (was only used by call.ts)
- Remove ./call sub-path export from package.json and tsup config
- Update all architecture docs to reflect transport-only scope, add Worker adapter, remove call protocol references
- Remove docs/architecture/call-protocol.md
- Update AGENTS.md with new source layout and transport-only principle
2026-05-01 19:40:25 +00:00

105 lines
3.8 KiB
Markdown

---
status: draft
last_updated: 2026-05-01
---
# Build & Distribution
Dependencies, project structure, tree-shaking, sub-path exports, and build targets.
## Dependencies
No runtime dependencies. The `Repeater` class is inlined from `@repeaterjs/repeater` (MIT) — no external package required.
| Package | Type | Purpose |
|---------|------|---------|
| (none) | runtime | — |
| `ioredis` | peer (optional) | Redis client. Only imported by `event-target-redis.ts`. Type-only import at compile time. |
| `@rayhanadev/iroh` | peer (optional, future) | Iroh NAPI-RS binding. Only imported by `event-target-iroh.ts`. |
No logger dependency. No TypeBox dependency (call protocol and schemas moved to `@alkdev/operations`).
## Project Structure
```
@alkdev/pubsub/
src/
index.ts # Barrel: re-exports core API + operators
types.ts # TypedEvent, TypedEventTarget, EventEnvelope
create_pubsub.ts # createPubSub factory (adapted from graphql-yoga)
operators.ts # filter, map, pipe, take, reduce, toArray,
# batch, dedupe, window, flat, groupBy, chain, join
repeater.ts # Inlined from @repeaterjs/repeater (MIT)
event-target-redis.ts # createRedisEventTarget (peer dep: ioredis)
# Future adapters (each is its own entry point + peer dep island):
# event-target-websocket.ts # (peer dep: none, web standard)
# event-target-worker.ts # (peer dep: none, web standard)
# event-target-iroh.ts # (peer dep: @rayhanadev/iroh)
test/
create_pubsub.test.ts
operators.test.ts
event-target-redis.test.ts
# event-target-websocket.test.ts
# event-target-worker.test.ts
# event-target-iroh.test.ts
docs/
architecture.md
architecture/
research/
package.json
tsconfig.json
tsup.config.ts
vitest.config.ts
```
## Sub-Path Exports
We use explicit sub-path exports rather than barrel-only + tree-shaking. Each adapter is importable by its own path:
```json
{
"exports": {
".": { ... },
"./event-target-redis": { ... },
"./event-target-websocket": { ... },
"./event-target-worker": { ... },
"./event-target-iroh": { ... }
}
}
```
### Why Sub-Path Exports
- **Explicit** — doesn't rely on bundler tree-shaking behavior
- **Peer dep isolation** — `import from '@alkdev/pubsub/event-target-redis'` makes the dependency on ioredis explicit at the import site
- **Consistent with typemap pattern** — typemap's peer deps (zod, valibot, typebox) are each their own module; sub-path exports make this explicit at the package boundary
Sub-path entries are added as adapters are implemented. The barrel `index.ts` also re-exports everything for convenience — consumers who want tree-shaking can import from the barrel and rely on their bundler.
## Peer Dependencies
| Peer Dep | Required By | Optional |
|----------|-------------|----------|
| `ioredis@^5.0.0` | `event-target-redis` | Yes |
| `@rayhanadev/iroh` | `event-target-iroh` (future) | Yes |
Optional peer deps means `npm install @alkdev/pubsub` does NOT install ioredis or iroh. Consumers opt in by installing the peer dep and importing from the sub-path.
## Build
- **Tool**: `tsup` — produces dual ESM + CJS with declarations automatically
- **Entry points**: `src/index.ts`, `src/event-target-redis.ts`, plus future adapters
- **Format**: ESM + CJS
- **Target**: `es2022`
- **Splitting**: enabled (tsup code splitting for shared chunks)
## Testing
- **Runner**: `vitest` — matches taskgraph, natural fit with tsup/Node build pipeline
- **Config**: `vitest.config.ts` with `globals: true`
## Targets
- **Publish**: npm (`@alkdev/pubsub`)
- **Runtime**: Node 18+, Deno, Bun — pure JS (except iroh adapter which requires NAPI-RS)
- **Deno compatibility**: Source is standard TypeScript with no Deno-specific APIs. Deno can import from npm or JSR.