Files
pubsub/docs/architecture/build-distribution.md
glm-5.1 8c025c3433 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)
2026-04-30 10:20:41 +00:00

3.6 KiB

status, last_updated
status last_updated
draft 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:

{
  "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 isolationimport 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)
// 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.