Skip to content

Commit 9a66209

Browse files
Version Packages (preview)
1 parent e9239b9 commit 9a66209

17 files changed

Lines changed: 349 additions & 47 deletions

File tree

.changeset/pre.json

Lines changed: 9 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -15,44 +15,23 @@
1515
"@evolu/react-web": "1.0.0",
1616
"@evolu/svelte": "1.0.0",
1717
"@evolu/tsconfig": "0.0.2",
18-
"@evolu/web": "1.0.0"
18+
"@evolu/web": "1.0.0",
19+
"@evolu/relay": "1.1.1",
20+
"@example/angular-vite-pwa": "0.0.0"
1921
},
2022
"changesets": [
2123
"blue-lions-tease",
22-
"calm-melons-accept",
23-
"cute-breads-count",
24-
"dry-cobras-listen",
25-
"dull-poets-wash",
26-
"easy-radios-decide",
27-
"easy-rivers-dig",
28-
"fast-peas-laugh",
29-
"forty-doors-stay",
30-
"heavy-parts-own",
31-
"hot-peas-own",
32-
"major-insects-cough",
33-
"mean-rats-start",
34-
"modern-zebras-clean",
35-
"ninety-rockets-listen",
24+
"busy-planets-joke",
25+
"common-ads-serve",
26+
"heavy-mugs-tickle",
27+
"lazy-clouds-exist",
3628
"plenty-carrots-lead",
37-
"plenty-lemons-march",
38-
"ready-stars-stop",
39-
"rich-garlics-sort",
4029
"rotten-gifts-write",
41-
"seven-cups-stand",
42-
"shaggy-phones-march",
43-
"shy-bats-carry",
44-
"slick-comics-give",
45-
"slow-lemons-go",
46-
"small-lights-go",
47-
"small-women-repeat",
48-
"small-years-visit",
4930
"solid-cameras-study",
31+
"some-internal-improvements",
5032
"some-rice-do",
51-
"tall-hands-leave",
52-
"tall-hands-swim",
53-
"tiny-clowns-worry",
33+
"tricky-wings-join",
5434
"true-teams-wash",
55-
"twenty-friends-bake",
5635
"two-shrimps-yawn",
5736
"yummy-cups-drop"
5837
]

apps/relay/CHANGELOG.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# @evolu/relay
2+
3+
## 1.1.2-preview.0
4+
5+
### Patch Changes
6+
7+
- Updated dependencies [eec5d8e]
8+
- Updated dependencies [eec5d8e]
9+
- Updated dependencies [eec5d8e]
10+
- Updated dependencies [eec5d8e]
11+
- Updated dependencies [5c05d2e]
12+
- Updated dependencies [eec5d8e]
13+
- @evolu/common@6.0.1-preview.20
14+
- @evolu/nodejs@1.0.1-preview.8

apps/relay/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@evolu/relay",
3-
"version": "1.1.1",
3+
"version": "1.1.2-preview.0",
44
"private": true,
55
"type": "module",
66
"scripts": {

packages/common/CHANGELOG.md

Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,203 @@
11
# @evolu/common
22

3+
## 6.0.1-preview.20
4+
5+
### Patch Changes
6+
7+
- eec5d8e: Add Task, async helpers, and concurrency primitives
8+
- `Task<T, E>` - Lazy, cancellable Promise that returns typed Result instead of throwing
9+
- `toTask()` - Convert async functions to Tasks with AbortSignal support
10+
- `wait()` - Delay execution with Duration strings (e.g., "5m", "2h 30m")
11+
- `timeout()` - Add timeout behavior to any Task
12+
- `retry()` - Retry failed operations with exponential backoff and jitter
13+
- `createSemaphore()` - Limit concurrent operations to a specified count
14+
- `createMutex()` - Ensure mutual exclusion (one operation at a time)
15+
16+
**Duration Support:**
17+
- Type-safe duration strings with compile-time validation
18+
- Support for milliseconds, seconds, minutes, hours, and days
19+
- Logical combinations like "1h 30m" or "2s 500ms"
20+
21+
Tasks provide precise type safety for cancellation - AbortError is only included in the error union when an AbortSignal is actually provided. All operations are designed to work together seamlessly for complex async workflows.
22+
23+
## Examples
24+
25+
### toTask
26+
27+
```ts
28+
// Convert an async function to a Task<Result<T, E>> with AbortSignal support
29+
const fetchTask = (url: string) =>
30+
toTask((context) =>
31+
tryAsync(
32+
() => fetch(url, { signal: context?.signal ?? null })
33+
(error) => ({ type: "FetchError", error }),
34+
),
35+
);
36+
37+
const result = await fetchTask("/api")(/* optional: { signal } */);
38+
```
39+
40+
### wait
41+
42+
```ts
43+
// Delay for a duration string or NonNegativeInt milliseconds
44+
await wait("50ms")();
45+
```
46+
47+
### timeout
48+
49+
```ts
50+
const slow = toTask(async () => ok("done"));
51+
const withTimeout = timeout("200ms", slow);
52+
const r = await withTimeout(); // Result<string, TimeoutError>
53+
```
54+
55+
### retry
56+
57+
```ts
58+
interface FetchError {
59+
readonly type: "FetchError";
60+
readonly error: unknown;
61+
}
62+
const task = fetchTask("/api");
63+
const withRetry = retry({ retries: PositiveInt.orThrow(3) }, task);
64+
const r = await withRetry(); // Result<Response, FetchError | RetryError<FetchError>>
65+
```
66+
67+
### createSemaphore
68+
69+
```ts
70+
const semaphore = createSemaphore(3);
71+
const run = (i: number) =>
72+
semaphore.withPermit(() => wait("50ms")().then(() => i));
73+
const results = await Promise.all([1, 2, 3, 4, 5].map(run)); // [1,2,3,4,5]
74+
```
75+
76+
### createMutex
77+
78+
```ts
79+
const mutex = createMutex();
80+
const seq = (i: number) =>
81+
mutex.withLock(async () => {
82+
await wait("10ms")();
83+
return i;
84+
});
85+
const results = await Promise.all([1, 2, 3].map(seq)); // executes one at a time
86+
```
87+
88+
- eec5d8e: Replace Mnemonic with OwnerSecret
89+
90+
OwnerSecret is the fundamental cryptographic primitive from which all owner keys are derived via SLIP-21. Mnemonic is just a representation of this underlying entropy. This change makes the type system more accurate and the cryptographic relationships clearer.
91+
92+
- eec5d8e: Replace NanoID with Evolu Id
93+
94+
Evolu now uses its own ID format instead of NanoID:
95+
- **Evolu Id**: 16 random bytes from a cryptographically secure random generator, encoded as 22-character Base64Url string (128 bits of entropy)
96+
- **Breaking change**: ID format changes from 21 to 22 characters
97+
- **Why**: Provides standard binary serialization (16 bytes), more entropy than NanoID (128 bits vs ~126 bits), and native Base64Url encoding support across platforms
98+
99+
See the `Id` type documentation for detailed design rationale comparing to NanoID, UUID v4, and UUID v7.
100+
101+
- eec5d8e: Replace `subscribeAppOwner` and `getAppOwner` with `appOwner` promise
102+
103+
The app owner is now accessed via a promise (`evolu.appOwner`) instead of subscription-based methods. This simplifies the API and aligns with modern async patterns.
104+
105+
**Breaking changes:**
106+
- Removed `evolu.subscribeAppOwner()` and `evolu.getAppOwner()`
107+
- Removed `useAppOwner()` hook from `@evolu/react`
108+
- Added `evolu.appOwner` promise that resolves to `AppOwner`
109+
- Updated `appOwnerState()` in `@evolu/svelte` to return promise-based state
110+
111+
**Migration:**
112+
113+
```ts
114+
// Before
115+
const unsubscribe = evolu.subscribeAppOwner(() => {
116+
const owner = evolu.getAppOwner();
117+
});
118+
119+
// After
120+
const owner = await evolu.appOwner;
121+
```
122+
123+
For React, use the `use` hook:
124+
125+
```ts
126+
// Before
127+
import { useAppOwner } from "@evolu/react";
128+
const appOwner = useAppOwner();
129+
130+
// After
131+
import { use } from "react";
132+
const evolu = useEvolu();
133+
const appOwner = use(evolu.appOwner);
134+
```
135+
136+
- eec5d8e: # Transport-Based Configuration System
137+
138+
# Transport-Based Configuration System
139+
140+
**BREAKING CHANGE**: Replaced `syncUrl` with flexible `transport` property supporting single transport or array of transports for multiple sync endpoints.
141+
142+
## What Changed
143+
- **Removed** `syncUrl` property from Evolu config
144+
- **Added** `transport` property accepting a single `Transport` object or array of `Transport` objects
145+
- **Added** `Transport` type union with initial WebSocket support
146+
- **Updated** sync system to support Nostr-style relay pools with simultaneous connections
147+
- **Updated** all examples and documentation to use new transport configuration
148+
149+
## Migration Guide
150+
151+
**Before:**
152+
153+
```ts
154+
const evolu = createEvolu(deps)(Schema, {
155+
syncUrl: "wss://relay.example.com",
156+
});
157+
```
158+
159+
**After (single transport):**
160+
161+
```ts
162+
const evolu = createEvolu(deps)(Schema, {
163+
transport: { type: "WebSocket", url: "wss://relay.example.com" },
164+
});
165+
```
166+
167+
**After (multiple transports):**
168+
169+
```ts
170+
const evolu = createEvolu(deps)(Schema, {
171+
transport: [
172+
{ type: "WebSocket", url: "wss://relay1.example.com" },
173+
{ type: "WebSocket", url: "wss://relay2.example.com" },
174+
],
175+
});
176+
```
177+
178+
## Benefits
179+
- **Single or multiple relay support**: Use one transport for simplicity or multiple for redundancy
180+
- **Intuitive API**: Singular property name that accepts both single item and array
181+
- **Future extensibility**: Ready for upcoming transport types (FetchRelay, Bluetooth, LocalNetwork)
182+
- **Nostr-style resilience**: Messages broadcast to all connected relays simultaneously when using arrays
183+
- **Type safety**: Full TypeScript support for transport configurations
184+
185+
## Future Transport Types
186+
187+
The new system is designed to support upcoming transport types:
188+
- `FetchRelay`: HTTP-based polling for environments without WebSocket support
189+
- `Bluetooth`: P2P sync for offline collaboration
190+
- `LocalNetwork`: LAN/mesh sync for local networks
191+
192+
## Technical Details
193+
- Single transports are automatically normalized to arrays internally
194+
- CRDT messages are sent to all connected transports simultaneously
195+
- Duplicate message handling relies on CRDT idempotency (no deduplication needed)
196+
- WebSocket connections auto-reconnect independently
197+
- Backwards compatibility removed (preview version breaking change)
198+
199+
This change provides an intuitive API that scales from simple single-transport setups to complex multi-transport configurations, positioning Evolu for a more resilient, multi-transport future.
200+
3201
## 6.0.1-preview.19
4202

5203
### Patch Changes

packages/common/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@evolu/common",
3-
"version": "6.0.1-preview.19",
3+
"version": "6.0.1-preview.20",
44
"description": "TypeScript library and local-first framework",
55
"keywords": [
66
"evolu",

packages/nodejs/CHANGELOG.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,17 @@
11
# @evolu/nodejs
22

3+
## 1.0.1-preview.8
4+
5+
### Patch Changes
6+
7+
- 5c05d2e: Internal improvements and dependency updates
8+
- Updated dependencies [eec5d8e]
9+
- Updated dependencies [eec5d8e]
10+
- Updated dependencies [eec5d8e]
11+
- Updated dependencies [eec5d8e]
12+
- Updated dependencies [eec5d8e]
13+
- @evolu/common@6.0.1-preview.20
14+
315
## 1.0.1-preview.7
416

517
### Patch Changes

packages/nodejs/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@evolu/nodejs",
3-
"version": "1.0.1-preview.7",
3+
"version": "1.0.1-preview.8",
44
"description": "Evolu for Node.js",
55
"author": "Daniel Steigerwald <daniel@steigerwald.cz>",
66
"license": "MIT",
@@ -40,7 +40,7 @@
4040
"vitest": "^4.0.4"
4141
},
4242
"peerDependencies": {
43-
"@evolu/common": "^6.0.1-preview.19"
43+
"@evolu/common": "^6.0.1-preview.20"
4444
},
4545
"engines": {
4646
"node": ">=22.0.0"

packages/react-native/CHANGELOG.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,18 @@
11
# @evolu/react-native
22

3+
## 12.0.1-preview.5
4+
5+
### Patch Changes
6+
7+
- 5c05d2e: Internal improvements and dependency updates
8+
- Updated dependencies [eec5d8e]
9+
- Updated dependencies [eec5d8e]
10+
- Updated dependencies [eec5d8e]
11+
- Updated dependencies [eec5d8e]
12+
- Updated dependencies [eec5d8e]
13+
- @evolu/common@6.0.1-preview.20
14+
- @evolu/react@9.0.1-preview.5
15+
316
## 12.0.1-preview.4
417

518
### Patch Changes

packages/react-native/package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@evolu/react-native",
3-
"version": "12.0.1-preview.4",
3+
"version": "12.0.1-preview.5",
44
"description": "Evolu for React Native and Expo",
55
"keywords": [
66
"evolu",
@@ -68,8 +68,8 @@
6868
"vitest": "^4.0.4"
6969
},
7070
"peerDependencies": {
71-
"@evolu/common": "^6.0.1-preview.19",
72-
"@evolu/react": "^9.0.1-preview.4",
71+
"@evolu/common": "^6.0.1-preview.20",
72+
"@evolu/react": "^9.0.1-preview.5",
7373
"@op-engineering/op-sqlite": ">=12",
7474
"expo": ">=54",
7575
"expo-sqlite": ">=15",

packages/react-web/CHANGELOG.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,19 @@
11
# @evolu/react-web
22

3+
## 1.0.1-preview.4
4+
5+
### Patch Changes
6+
7+
- 5c05d2e: Internal improvements and dependency updates
8+
- Updated dependencies [eec5d8e]
9+
- Updated dependencies [eec5d8e]
10+
- Updated dependencies [eec5d8e]
11+
- Updated dependencies [eec5d8e]
12+
- Updated dependencies [5c05d2e]
13+
- Updated dependencies [eec5d8e]
14+
- @evolu/common@6.0.1-preview.20
15+
- @evolu/web@1.0.1-preview.6
16+
317
## 1.0.1-preview.3
418

519
### Patch Changes

0 commit comments

Comments
 (0)