Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
3676da8
sync(common-v8): port 19030df Add keyed mutex/semaphore and refactor …
miccy Mar 11, 2026
202c5c7
sync(common-v8): port c96e27a Update deps
miccy Mar 11, 2026
0aaab74
sync(common-v8): port 485ea45 Improve require-pure-annotation rule an…
miccy Mar 11, 2026
5ab9ccc
sync(common-v8): port 9803147 Reduced bundle size with pure annotations
miccy Mar 11, 2026
d7b50cf
sync(common-v8): port dfc84a4 Expanded Ref and Store operations
miccy Mar 11, 2026
f0689a7
sync(common-v8): port ce057ed Add PURE annotations to retryStrategyAws
miccy Mar 11, 2026
80fc73c
sync(common-v8): port 4b2d924 Remove Instances registry and tests
miccy Mar 11, 2026
b84fbde
sync(common-v8): port 864bb43 Refactor Run/Fiber APIs
miccy Mar 11, 2026
24ef20c
sync(common-v8): port d30c2ac Use per-name mutex and map for SharedEvolu
miccy Mar 11, 2026
d6320ca
sync(common-v8): port cd6b74d Rename Evolu Kysely helpers
miccy Mar 11, 2026
999c0fc
sync(common-v8): port 69a55fb Use run.orThrow for sqlite driver
miccy Mar 11, 2026
0370bca
sync(common-v8): port a0b7371 Clarify startTransition test comment
miccy Mar 11, 2026
1738d32
sync(common-v8): port ef36be2 Clarify error-handling docs and platfor…
miccy Mar 11, 2026
489b56f
sync(common-v8): port c803aef Rollback
miccy Mar 11, 2026
caf8503
sync(common-v8): port 617ee37 Add Task style note and fix a bug
miccy Mar 11, 2026
e4aa071
sync(common-v8): port 768356c Document imperative Result composition …
miccy Mar 11, 2026
41f545e
sync(common-v8): port a726b7b Standardize run variable names
miccy Mar 11, 2026
07026bb
fix: stabilize compatibility after common-v8 sync
miccy Mar 11, 2026
ed55473
chore: Update `@angular/build` to `21.2.1` and related Angular devkit…
miccy Mar 11, 2026
beb0aa7
feat: Update dependencies across packages and examples, add the Astro…
miccy Mar 11, 2026
b73a71d
fix: harden resource and keyed semaphore disposal
miccy Mar 11, 2026
70d550c
fix: restore verify after common-v8 sync
miccy Mar 11, 2026
c32892f
fix: harden resources rollback and stabilize verify
miccy Mar 11, 2026
160769b
fix: address automated PR review findings
miccy Mar 11, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions apps/relay/src/startBunRelay.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {
type CreateSqliteDriverDep,
callback,
createSqlite,
getOk,
getOrThrow,
isPromiseLike,
type OwnerId,
ok,
Expand Down Expand Up @@ -99,7 +99,7 @@ export const startBunRelay =
const console = _run.deps.console.child("relay");

const relayName = name ?? SimpleName.orThrow("evolu-relay");
const sqlite = getOk(await stack.use(createSqlite(relayName)));
const sqlite = getOrThrow(await stack.use(createSqlite(relayName)));
const deps = { ..._run.deps, sqlite };

createBaseSqliteStorageTables(deps);
Expand Down
2 changes: 1 addition & 1 deletion biome.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"$schema": "https://biomejs.dev/schemas/2.4.5/schema.json",
"$schema": "https://biomejs.dev/schemas/2.4.6/schema.json",
"vcs": {
"enabled": true,
"clientKind": "git",
Expand Down
242 changes: 165 additions & 77 deletions bun.lock

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions examples/angular-vite-pwa/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@
"generate-pwa-assets": "pwa-assets-generator"
},
"dependencies": {
"@angular/core": "^21.2.1",
"@angular/platform-browser": "^21.2.1",
"@angular/core": "^21.2.2",
"@angular/platform-browser": "^21.2.2",
"@evolu/common": "workspace:*",
"@evolu/web": "workspace:*"
},
"devDependencies": {
"@analogjs/vite-plugin-angular": "^2.3.1",
"@angular/build": "^21.2.1",
"@angular/compiler-cli": "^21.2.1",
"@angular/compiler-cli": "^21.2.2",
"@tailwindcss/vite": "^4.2.1",
"@vite-pwa/assets-generator": "^1.0.2",
"tailwindcss": "^4.2.1",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ const todosQuery = createQuery((db) =>
// (even if defined without nullOr in the schema) to allow schema
// evolution without migrations. Filter nulls with where + $narrowType.
.where("title", "is not", null)
.$narrowType<{ title: Evolu.kysely.NotNull }>()
.$narrowType<{ title: Evolu.KyselyNotNull }>()
// Columns createdAt, updatedAt, isDeleted are auto-added to all tables.
.orderBy("createdAt"),
);
Expand Down
2 changes: 1 addition & 1 deletion examples/react-expo/app/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ const todosQuery = createQuery((db) =>
// (even if defined without nullOr in the schema) to allow schema
// evolution without migrations. Filter nulls with where + $narrowType.
.where("title", "is not", null)
.$narrowType<{ title: Evolu.kysely.NotNull }>()
.$narrowType<{ title: Evolu.KyselyNotNull }>()
// Columns createdAt, updatedAt, isDeleted are auto-added to all tables.
.orderBy("createdAt"),
);
Expand Down
2 changes: 1 addition & 1 deletion examples/react-expo/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
"react-native": "0.84.1",
"react-native-nitro-modules": "0.34.1",
"react-native-quick-crypto": "^1.0.16",
"react-native-safe-area-context": "^5.6.2",
"react-native-safe-area-context": "^5.7.0",
"react-native-screens": "^4.24.0",
"react-native-svg": "15.15.3",
"react-native-web": "^0.21.0",
Expand Down
2 changes: 1 addition & 1 deletion examples/react-nextjs/components/EvoluMinimalExample.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ const todosQuery = createQuery((db) =>
// (even if defined without nullOr in the schema) to allow schema
// evolution without migrations. Filter nulls with where + $narrowType.
.where("title", "is not", null)
.$narrowType<{ title: Evolu.kysely.NotNull }>()
.$narrowType<{ title: Evolu.KyselyNotNull }>()
// Columns createdAt, updatedAt, isDeleted are auto-added to all tables.
.orderBy("createdAt"),
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ const todosQuery = createQuery((db) =>
// (even if defined without nullOr in the schema) to allow schema
// evolution without migrations. Filter nulls with where + $narrowType.
.where("title", "is not", null)
.$narrowType<{ title: Evolu.kysely.NotNull }>()
.$narrowType<{ title: Evolu.KyselyNotNull }>()
// Columns createdAt, updatedAt, isDeleted are auto-added to all tables.
.orderBy("createdAt"),
);
Expand Down
2 changes: 1 addition & 1 deletion examples/svelte-vite-pwa/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"@evolu/web": "workspace:*",
"@sveltejs/vite-plugin-svelte": "^6.2.4",
"@tsconfig/svelte": "^5.0.8",
"svelte": "^5.53.7",
"svelte": "^5.53.10",
"svelte-check": "^4.4.3",
"tslib": "^2.8.1",
"typescript": "^5.9.3",
Expand Down
2 changes: 1 addition & 1 deletion examples/vue-vite-pwa/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"@evolu/common": "workspace:*",
"@evolu/vue": "workspace:*",
"@evolu/web": "workspace:*",
"vue": "^3.5.29",
"vue": "^3.5.30",
"workbox-window": "^7.4.0"
},
"devDependencies": {
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@
"@vitest/browser-playwright": "^4.0.18",
"@vitest/coverage-istanbul": "^4.0.18",
"@vitest/coverage-v8": "^4.0.18",
"turbo": "^2.8.13",
"turbo": "^2.8.16",
"typedoc": "^0.28.17",
"typedoc-plugin-markdown": "^4.10.0",
"typescript": "^5.9.3",
Expand Down
4 changes: 2 additions & 2 deletions packages/common/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
"@noble/hashes": "^2.0.1",
"@scure/bip39": "^2.0.1",
"kysely": "^0.28.11",
"msgpackr": "^1.11.8",
"msgpackr": "^1.11.9",
"zod": "^4.3.6"
},
"publishConfig": {
Expand All @@ -72,7 +72,7 @@
"@types/better-sqlite3": "^7.6.13",
"@types/ws": "^8.18.1",
"better-sqlite3": "^12.6.2",
"fast-check": "^4.5.3",
"fast-check": "^4.6.0",
"playwright": "^1.58.2",
"typescript": "^5.9.3",
"ws": "^8.19.0"
Expand Down
105 changes: 0 additions & 105 deletions packages/common/src/Instances.ts

This file was deleted.

2 changes: 1 addition & 1 deletion packages/common/src/Number.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ export const computeBalancedBuckets = (
*/
export const FibonacciIndex = /*#__PURE__*/ brand(
"FibonacciIndex",
lessThanOrEqualTo(78)(PositiveInt),
/*#__PURE__*/ lessThanOrEqualTo(78)(PositiveInt),
);
export type FibonacciIndex = typeof FibonacciIndex.Type;

Expand Down
98 changes: 64 additions & 34 deletions packages/common/src/Ref.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,26 @@
/**
* Mutable reference container for state management.
* Mutable reference.
*
* @module
*/

import type { Eq } from "./Eq.js";
import type { Store } from "./Store.js";

/**
* `Ref` provides a simple API to hold and update a value, similar to a "ref" in
* functional programming or React. It exposes methods to get, set, and modify
* the current state.
* Mutable reference.
*
* Use a Ref instead of a variable when you want to pass state around as an
* object. If you need subscriptions, see {@link Store}.
* `Ref` holds a mutable value and exposes explicit `get`, `set`, `update`, and
* `modify` operations. Use it when mutable state needs to be passed around as a
* value.
*
* Ref is a valid dependency in Evolu's [Dependency
* Injection](https://evolu.dev/docs/dependency-injection) pattern—use it when
* functions need shared mutable state.
* For reactive state with subscriptions, see {@link Store}.
*
* ### Example
*
* ```ts
* const count = createRef(0);
* count.set(1);
* count.modify((n) => n + 1);
* count.update((n) => n + 1);
* console.log(count.get()); // 2
* ```
*
Expand All @@ -40,37 +36,71 @@ export interface Ref<T> {
/** Returns the current state. */
readonly get: () => T;

/** Sets the state. Returns `true` if the state was updated. */
readonly set: (state: T) => boolean;
/** Sets the state. */
readonly set: (state: T) => void;

/**
* Modifies the state using an updater function. Returns `true` if the state
* was updated.
*/
readonly modify: (updater: (current: T) => T) => boolean;
/** Sets the state and returns the previous state. */
readonly getAndSet: (state: T) => T;

/** Sets the state and returns the current state after the update. */
readonly setAndGet: (state: T) => T;

/** Updates the state. */
readonly update: (updater: (current: T) => T) => void;

/** Updates the state and returns the previous state. */
readonly getAndUpdate: (updater: (current: T) => T) => T;

/** Updates the state and returns the current state after the update. */
readonly updateAndGet: (updater: (current: T) => T) => T;

/** Modifies the state and returns a computed result from the transition. */
readonly modify: <R>(
updater: (current: T) => readonly [result: R, nextState: T],
) => R;
}

/**
* Creates a {@link Ref} with the given initial state.
*
* By default, state is always updated. We can provide an optional {@link Eq}
* function as the second argument to skip updates when the new state equals the
* current state.
*/
export const createRef = <T>(initialState: T, eq?: Eq<T>): Ref<T> => {
/** Creates a {@link Ref} with the given initial state. */
export const createRef = <T>(initialState: T): Ref<T> => {
let currentState = initialState;

const updateState = (newState: T): boolean => {
if (eq?.(newState, currentState)) return false;
currentState = newState;
return true;
};

return {
get: () => currentState,

set: (state) => updateState(state),
set: (state) => {
currentState = state;
},

getAndSet: (state) => {
const previousState = currentState;
currentState = state;
return previousState;
},

setAndGet: (state) => {
currentState = state;
return currentState;
},

update: (updater) => {
currentState = updater(currentState);
},

getAndUpdate: (updater) => {
const previousState = currentState;
currentState = updater(currentState);
return previousState;
},

updateAndGet: (updater) => {
currentState = updater(currentState);
return currentState;
},

modify: (updater) => updateState(updater(currentState)),
modify: (updater) => {
const [result, nextState] = updater(currentState);
currentState = nextState;
return result;
},
};
};
Loading
Loading