Skip to content

[Bug] Ten documented public symbols including migrateInMemoryJournal, wrapEventAsEnvelope and Mailbox are re-exported by no entry point, so the wrap-legacy migration page and the mailbox sample cannot compile against the tarball #1002

Description

@pathosDev

Problem

Ten symbols that the documentation imports from 'actor-ts' are re-exported by no entry
point. They exist in src/, they are compiled into dist/, and the modules that hold
them are reachable from nothing a consumer can name — src/index.ts re-exports the
persistence, CRDT and runtime layers through explicit name lists that omit them, and
there is no ./persistence, ./crdt or ./runtime subpath to reach past the barrel
(see W9-01 / #414).

symbol defined at documented at
migrateInMemoryJournal src/persistence/migration/wrapLegacy.ts:103 persistence/migration/wrap-legacy.mdx:39 + 4 more pages
wrapEventAsEnvelope src/persistence/migration/wrapLegacy.ts:47 persistence/migration/wrap-legacy.mdx:63, recipes.md:255
migrateSnapshotStore src/persistence/migration/wrapLegacy.ts:149 persistence/migration/wrap-legacy.mdx:87, rolling-migration.md:166
formatMigrationResult src/persistence/migration/wrapLegacy.ts:182 persistence/migration/wrap-legacy.mdx:39
SqliteDurableStateStore src/persistence/durable-state-stores/SqliteDurableStateStore.ts:29 persistence/journals/sqlite.mdx:175
SqliteDurableStateStoreOptions src/persistence/durable-state-stores/SqliteDurableStateStoreOptions.ts:51 persistence/journals/sqlite.mdx:175
getSqliteDriver src/runtime/sqlite/index.ts:23 persistence/journals/sqlite.mdx:187
DurableDistributedDataStore src/crdt/DurableDistributedDataStore.ts:25 distributed-data/durable-storage.mdx:119
Mailbox src/internal/Mailbox.ts:37 fundamentals/mailboxes.mdx:57
vectorClock nowhere in src/ persistence/replicated-event-sourcing/overview.mdx:75

vectorClock is a different failure from the other nine: it is not an export that was
forgotten, it is a name that has never existed. The value the barrel does export is
VectorClock (src/index.ts:445), and TypeScript says so directly.

Mailbox is the one with a runnable consequence beyond "does not compile" — the sample
constructs it.

Evidence

The whole wrap-legacy page opens on two unreachable names:

docs/src/content/docs/persistence/migration/wrap-legacy.mdx:39-44
import { migrateInMemoryJournal, formatMigrationResult } from 'actor-ts';

const result = await migrateInMemoryJournal(
  journal,
  (e: { kind: string }) => `BankAccount.${e.kind}`,
);

The mailbox opt-out sample calls a constructor that is not exported:

docs/src/content/docs/fundamentals/mailboxes.mdx:57-62
import { ActorOptions, Mailbox } from 'actor-ts';  // the unbounded base mailbox

// explicit opt-out from the bounded default
const myActorOptions = ActorOptions.create().withMailbox(() => new Mailbox());

system.spawn(MyActor, 'my-actor', myActorOptions);

The SQLite durable-state section is unreachable in both of its fences:

docs/src/content/docs/persistence/journals/sqlite.mdx:175-179
import { SqliteDurableStateStore, SqliteDurableStateStoreOptions } from 'actor-ts';

const stateOptions = SqliteDurableStateStoreOptions.create()
  .withPath('./state.db');
const store = new SqliteDurableStateStore(stateOptions);

The barrel's persistence re-export is an explicit list, which is why an addition to
src/persistence/ does not reach a consumer unless someone remembers to append to it:

src/index.ts:442-452
  ReplicatedEventSourcedActor,
  VectorClock,
  LastWriterWinsResolver,
  CustomMergeResolver,
  eventDispatcher,
  CachedSnapshotStore,
  CachedSnapshotStoreOptions,
  reEncryptObjectStorage,
  InMemoryReEncryptProgressStore,
} from './persistence/index.js';

Proposal

Two mechanically different problems, so two fixes:

  1. The nine that exist — add them to the barrel's export lists (or to the subpaths
    [Feature] Add subpath exports to package.json #414 introduces, if those land first). Note that Mailbox lives under
    src/internal/; either it is public API and should move out of internal/, or the
    mailbox docs should stop telling readers to construct it and show the
    withMailbox-with-a-supplied-variant form instead. Pick one — the current state
    asserts both.
  2. vectorClock — a docs-only fix: the sample means VectorClock. Fixing the case
    is not enough on its own; the surrounding snippet should be checked against the real
    ReplicatedEventSourcedActor surface, since a name that never existed suggests the
    fence was never run.

Neither fix stays fixed without W9-03's guard.

Acceptance sketch

  • Each of the nine existing symbols resolves from a declared entry point of the packed tarball.
  • vectorClock is corrected to VectorClock in EN and DE, and the surrounding snippet compiles.
  • Mailbox is either promoted out of src/internal/ or removed from the documented sample.
  • A check type-checks the documented import surface against the tarball so a barrel omission fails CI.

Verification status

Reproduced by execution. The documented symbol list was generated mechanically from
README.md and docs/src/content/docs/** (319 distinct symbols imported from
'actor-ts'), emitted as one import { X } from 'actor-ts'; per symbol, and compiled
with TypeScript 5.9.3 against the packed tarball installed in a throwaway consumer
(module/moduleResolution: NodeNext, strict, types: ["node"]). A bare unused named
import still raises TS2305/TS2724, so type-only and value exports are both covered.
Exactly ten failed:

check-root.ts(61,10):  error TS2305: Module '"actor-ts"' has no exported member 'DurableDistributedDataStore'.
check-root.ts(138,10): error TS2305: Module '"actor-ts"' has no exported member 'Mailbox'.
check-root.ts(229,10): error TS2724: '"actor-ts"' has no exported member named 'SqliteDurableStateStore'. Did you mean 'MsSqlDurableStateStore'?
check-root.ts(230,10): error TS2724: '"actor-ts"' has no exported member named 'SqliteDurableStateStoreOptions'. Did you mean 'MsSqlDurableStateStoreOptions'?
check-root.ts(281,10): error TS2305: Module '"actor-ts"' has no exported member 'formatMigrationResult'.
check-root.ts(283,10): error TS2305: Module '"actor-ts"' has no exported member 'getSqliteDriver'.
check-root.ts(287,10): error TS2724: '"actor-ts"' has no exported member named 'migrateInMemoryJournal'. Did you mean 'InMemoryJournal'?
check-root.ts(288,10): error TS2724: '"actor-ts"' has no exported member named 'migrateSnapshotStore'. Did you mean 'SqliteSnapshotStore'?
check-root.ts(314,10): error TS2724: '"actor-ts"' has no exported member named 'vectorClock'. Did you mean 'VectorClock'?
check-root.ts(318,10): error TS2305: Module '"actor-ts"' has no exported member 'wrapEventAsEnvelope'.

The same generated check over actor-ts/testkit and actor-ts/devtools produced no
errors, so the gap is specific to the root barrel. git status --porcelain is clean
afterwards.

Related: #414 (add subpath exports) is the mechanism that would make a
./persistence route to these symbols possible; it does not itself list them.

Part of the production-readiness review batch — tracked in #913.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingpriority: highTop priority — high impact, plan nextproduction-goalBlocks or defines the path to production readiness

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions