Set up project structure, source files, and architecture docs
- Copy core source from alkhub_ts/packages/core/pubsub/ with import path fixups (typed_event_target.ts → types.ts, .ts → .js extensions) - Make PubSubPublishArgsByKey exported (was private type, needed by barrel) - Add package.json with sub-path exports and optional peer deps (ioredis) - Add tsup.config.ts with multi-entry + splitting for tree-shaking - Add tsconfig.json, vitest.config.ts, .gitignore - Add AGENTS.md with project conventions and adapter checklist - Add architecture docs following taskgraph/alkhub pattern: docs/architecture/README.md, api-surface.md, event-targets.md, iroh-transport.md, build-distribution.md - Add ADRs: 001-graphql-yoga-fork, 002-tree-shake-pattern - Copy migration research doc to docs/research/migration.md - Dual-license MIT OR Apache-2.0 (matching taskgraph)
This commit is contained in:
113
docs/architecture/build-distribution.md
Normal file
113
docs/architecture/build-distribution.md
Normal file
@@ -0,0 +1,113 @@
|
||||
---
|
||||
status: draft
|
||||
last_updated: 2026-04-30
|
||||
---
|
||||
|
||||
# Build & Distribution
|
||||
|
||||
Dependencies, project structure, tree-shaking, sub-path exports, and build targets.
|
||||
|
||||
## Dependencies
|
||||
|
||||
| Package | Type | Purpose |
|
||||
|---------|------|---------|
|
||||
| `@repeaterjs/repeater` | direct | Small (~3KB). Core async iterable primitive for `subscribe()`. |
|
||||
| `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 other external dependencies. No logger dependency.
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
@alkdev/pubsub/
|
||||
src/
|
||||
index.ts # Barrel: re-exports core API
|
||||
types.ts # TypedEvent, TypedEventTarget, etc.
|
||||
create_pubsub.ts # createPubSub factory
|
||||
operators.ts # filter, map, pipe
|
||||
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-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-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-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)
|
||||
|
||||
```ts
|
||||
// tsup.config.ts
|
||||
import { defineConfig } from 'tsup';
|
||||
|
||||
export default defineConfig({
|
||||
entry: ['src/index.ts', 'src/event-target-redis.ts'],
|
||||
format: ['esm', 'cjs'],
|
||||
dts: true,
|
||||
sourcemap: true,
|
||||
clean: true,
|
||||
splitting: true,
|
||||
target: 'es2022',
|
||||
});
|
||||
```
|
||||
|
||||
## 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.
|
||||
Reference in New Issue
Block a user