Skip to content

Releases: evoluhq/evolu

@evolu/web@3.0.0-next.1

07 May 09:59
6f053b2

Choose a tag to compare

Pre-release

Patch Changes

  • c1f97ff: Fixed the SharedWorker fallback on older Chrome Android versions without native SharedWorker support.

    Apps can pass onSharedWorkerUnsupported to show a custom message when another fallback tab is already running:

    createEvoluDeps({
      onSharedWorkerUnsupported: () => {
        alert(
          "This browser supports Evolu in one tab only. Close this tab and use the already open tab.",
        );
      },
    });
  • 63dce92: Updated Task and Run dependency injection API.

    Removed Run.addDeps because every Run now owns its deps. The new API is more flexible and better matches sync Pure DI: deps are passed explicitly where a task is called, can replace existing deps when needed, and can be scoped to an owned disposable Run with run.create(deps).

    • Renamed RunDeps to RunDefaultDeps to describe default Run dependencies more clearly.
    • Replaced Run.addDeps with explicit dependency passing via run(task, deps), run.orThrow(task, deps), and run.create(deps).
    • Allowed explicit deps to override default RunDefaultDeps when needed.

@evolu/react-native@15.0.0-next.2

07 May 09:58
6f053b2

Choose a tag to compare

Pre-release

Patch Changes

  • 63dce92: Updated Task and Run dependency injection API.

    Removed Run.addDeps because every Run now owns its deps. The new API is more flexible and better matches sync Pure DI: deps are passed explicitly where a task is called, can replace existing deps when needed, and can be scoped to an owned disposable Run with run.create(deps).

    • Renamed RunDeps to RunDefaultDeps to describe default Run dependencies more clearly.
    • Replaced Run.addDeps with explicit dependency passing via run(task, deps), run.orThrow(task, deps), and run.create(deps).
    • Allowed explicit deps to override default RunDefaultDeps when needed.

@evolu/nodejs@3.0.0-next.3

07 May 09:59
6f053b2

Choose a tag to compare

Pre-release

Patch Changes

  • 63dce92: Updated Task and Run dependency injection API.

    Removed Run.addDeps because every Run now owns its deps. The new API is more flexible and better matches sync Pure DI: deps are passed explicitly where a task is called, can replace existing deps when needed, and can be scoped to an owned disposable Run with run.create(deps).

    • Renamed RunDeps to RunDefaultDeps to describe default Run dependencies more clearly.
    • Replaced Run.addDeps with explicit dependency passing via run(task, deps), run.orThrow(task, deps), and run.create(deps).
    • Allowed explicit deps to override default RunDefaultDeps when needed.

@evolu/common@8.0.0-next.5

07 May 09:59
6f053b2

Choose a tag to compare

Pre-release

Minor Changes

  • 63dce92: Updated Task and Run dependency injection API.

    Removed Run.addDeps because every Run now owns its deps. The new API is more flexible and better matches sync Pure DI: deps are passed explicitly where a task is called, can replace existing deps when needed, and can be scoped to an owned disposable Run with run.create(deps).

    • Renamed RunDeps to RunDefaultDeps to describe default Run dependencies more clearly.
    • Replaced Run.addDeps with explicit dependency passing via run(task, deps), run.orThrow(task, deps), and run.create(deps).
    • Allowed explicit deps to override default RunDefaultDeps when needed.

Patch Changes

  • 0fbb5e7: Kept SharedWorker Evolu tenants alive briefly after the last instance was released so immediate dispose-and-recreate flows continue using the same local-first runtime.

@evolu/react-native@15.0.0-next.1

30 Apr 15:42
0a900f4

Choose a tag to compare

Pre-release

Minor Changes

  • ef7f242: Added Web Locks helpers in @evolu/common: LockManagerDep,
    testCreateLockManager, and acquireLeaderLock.

    testCreateLockManager is a native-backed test helper because native LockManager cannot be instantiated per test. It isolates lock usage per instance with internal namespacing while preserving visible lock names and native Web Locks behavior in tests.

    acquireLeaderLock acquires an exclusive leader-election lease for a name and returns an async-disposable handle that holds leadership until disposed.

    Added a React Native lockManager ponyfill in @evolu/react-native because React Native does not support Web Locks yet.

@evolu/common@8.0.0-next.4

30 Apr 15:42
0a900f4

Choose a tag to compare

Pre-release

Minor Changes

  • ef7f242: Added Web Locks helpers in @evolu/common: LockManagerDep,
    testCreateLockManager, and acquireLeaderLock.

    testCreateLockManager is a native-backed test helper because native LockManager cannot be instantiated per test. It isolates lock usage per instance with internal namespacing while preserving visible lock names and native Web Locks behavior in tests.

    acquireLeaderLock acquires an exclusive leader-election lease for a name and returns an async-disposable handle that holds leadership until disposed.

    Added a React Native lockManager ponyfill in @evolu/react-native because React Native does not support Web Locks yet.

Patch Changes

  • a70d933: Improved Schedule timing safety and validation.

    Schedule now:

    • Saturates computed delays to valid Millis values instead of throwing on overflow.
    • Handles backwards-clock elapsed deltas without producing invalid branded values.
    • Validates numeric Schedule options.

    Also added:

    • saturateMillis in the Time module for converting numbers to valid Millis values with overflow saturation.
    • NonNegativeFiniteNumber in the Type module for validating non-negative finite numbers.

@evolu/nodejs@3.0.0-next.2

08 Apr 10:54
e1f4744

Choose a tag to compare

Pre-release

Patch Changes

  • 65c1fe6: Documented createTimingSafeEqual in the Node.js crypto module.

@evolu/common@8.0.0-next.3

08 Apr 14:50
96f12d9

Choose a tag to compare

Pre-release

Patch Changes

  • f7d505a: Fixed in-memory transferred message port lifetime so transferred ports stayed usable while ownership moved between wrappers during disposal and re-creation.

@evolu/common@8.0.0-next.2

08 Apr 10:54
e1f4744

Choose a tag to compare

Pre-release

Patch Changes

  • b096543: Added test coverage proving that createSlip21 normalizes numeric path elements to strings.

@evolu/web@3.0.0-next.0

03 Apr 13:20
59569b9

Choose a tag to compare

Pre-release

Major Changes

  • 5a4d172: Updated minimum Node.js version from 22 to 24 (current LTS)

  • 0528425: - Merged @evolu/common/local-first/Platform.ts into @evolu/common/Platform.ts

    • Made @evolu/react-web re-export everything from @evolu/web, allowing React users to install only @evolu/react-web
  • 2abf93d: Refactored SQLite integration to use Task and throw-first semantics

    • Changed createSqlite to Task<Sqlite, never, CreateSqliteDriverDep>
    • Changed CreateSqliteDriver to Task<SqliteDriver>
    • Removed SqliteError from SQLite driver/task APIs
    • Changed Sqlite.exec to return SqliteExecResult directly (no Result<..., SqliteError>)
    • Changed Sqlite.transaction to support callbacks returning either Result<T, E> or void (no SqliteError in the error channel)
    • Changed Sqlite.export to return Uint8Array directly (no Result<..., SqliteError>)
    • Simplified SqliteDriver.exec by removing the isMutation parameter, so the driver determines read vs write internally
    • Replaced options.memory and options.encryptionKey with a discriminated options.mode field ("memory" | "encrypted")
    • Updated Expo and op-sqlite drivers to match the new API
    • Added SQLite schema metadata primitives (SqliteSchema, SqliteIndex, eqSqliteIndex, getSqliteSchema, getSqliteSnapshot)
    • Added testSetupSqlite helper for SQLite tests

    Why SqliteError was removed:

    • In Evolu, SQLite runs in-process. Failures are infrastructure-level and unrecoverable at the call site.
    • Wrapping these failures as Result values did not create meaningful recovery paths; callers still had to fail.
    • The correct behavior is to let such failures throw and surface them through platform createRun global handlers (web, nodejs, react-native), which report uncaught errors via Evolu console.error.
    • Evolu also propagates console.error entries through its messaging layer into the shared evoluError global store, so app-level error subscriptions still receive these failures.

    Boundary handling:

    • At protocol boundaries (for example Protocol ↔ Storage), error handling remains explicit.
    • Since storage implementations may throw, boundary code uses try/catch, logs with console.error(error), and returns protocol-level outcomes.
    • Protocol handles all thrown errors as boundary concerns, without coupling to SQLite-specific error types.
  • 953c1fb: Replaced interface-based symmetric encryption with direct function-based API

    Breaking Changes

    Removed:

    • SymmetricCrypto interface
    • SymmetricCryptoDep interface
    • createSymmetricCrypto() factory function
    • SymmetricCryptoDecryptError error type

    Added:

    • encryptWithXChaCha20Poly1305() - Direct encryption function with explicit algorithm name
    • decryptWithXChaCha20Poly1305() - Direct decryption function
    • XChaCha20Poly1305Ciphertext - Branded type for ciphertext
    • Entropy24 - Branded type for 24-byte nonces
    • DecryptWithXChaCha20Poly1305Error - Algorithm-specific error type
    • xChaCha20Poly1305NonceLength - Constant for nonce length (24)

    Migration Guide

    Before:

    const symmetricCrypto = createSymmetricCrypto({ randomBytes });
    const { nonce, ciphertext } = symmetricCrypto.encrypt(plaintext, key);
    const result = symmetricCrypto.decrypt(ciphertext, key, nonce);

    After:

    const [ciphertext, nonce] = encryptWithXChaCha20Poly1305({ randomBytes })(
      plaintext,
      key,
    );
    const result = decryptWithXChaCha20Poly1305(ciphertext, nonce, key);

    Error handling:

    // Before
    if (!result.ok && result.error.type === "SymmetricCryptoDecryptError") { ... }
    
    // After
    if (!result.ok && result.error.type === "DecryptWithXChaCha20Poly1305Error") { ... }

    Dependency injection:

    // Before
    interface Deps extends SymmetricCryptoDep { ... }
    
    // After - only encrypt needs RandomBytesDep
    interface Deps extends RandomBytesDep { ... }

    Rationale

    This change improves API extensibility by using explicit function names instead of a generic interface. Adding new encryption algorithms (e.g., encryptWithAES256GCM) is now straightforward without breaking existing code.

  • 4be336d: Refactored worker abstraction to support all platforms uniformly:

    • Added platform-agnostic worker interfaces: Worker<Input, Output>, SharedWorker<Input, Output>, MessagePort<Input, Output>, MessageChannel<Input, Output>
    • Added worker-side interfaces: WorkerSelf<Input, Output> and SharedWorkerSelf<Input, Output> for typed worker self wrappers
    • Changed onMessage from a method to a property for consistency with Web APIs
    • Made all worker and message port interfaces Disposable for proper resource cleanup
    • Added default generic parameters (Output = never) for simpler one-way communication patterns
    • Added complete web platform implementations: createWorker, createSharedWorker, createMessageChannel, createWorkerSelf, createSharedWorkerSelf, createMessagePort
    • Added React Native polyfills for Workers and MessageChannel

Patch Changes