Create a row in the database and returns a new ID. The first argument is the table name, and the second is an object.
The third optional argument, the onComplete callback, is generally unnecessary because creating a row cannot fail. Still, UI libraries can use it to ensure the DOM is updated if we want to manipulate it, for example, to focus an element.
Evolu does not use SQL for mutations to ensure data can be safely and predictably merged without conflicts.
Explicit mutations also allow Evolu to automatically add and update a few
useful columns common to all tables. Those columns are: createdAt,
updatedAt, and isDeleted.
Create or update a row in the database and return the existing ID. The first argument is the table name, and the second is an object.
This function is useful when we already have an id and want to create a
new row or update an existing one.
The third optional argument, the onComplete callback, is generally unnecessary because updating a row cannot fail. Still, UI libraries can use it to ensure the DOM is updated if we want to manipulate it, for example, to focus an element.
Evolu does not use SQL for mutations to ensure data can be safely and predictably merged without conflicts.
Explicit mutations also allow Evolu to automatically add and update a few
useful columns common to all tables. Those columns are: createdAt,
updatedAt, and isDeleted.
ReadonlycreateCreate type-safe SQL Query.
Evolu uses Kysely - the type-safe SQL query builder for TypeScript. See https://kysely.dev.
ReadonlyensureEnsure tables and columns defined in EvoluSchema exist in the database.
This function is for hot/live reloading.
ReadonlyexportExport SQLite database as Uint8Array.
ReadonlygetGet EvoluError.
ReadonlygetGet Owner.
ReadonlygetGet Query QueryResult.
ReadonlygetGet SyncState.
ReadonlyloadLoad an array of Query queries and return an array of
QueryResult promises. It's like queries.map(loadQuery) but with
proper types for returned promises.
ReadonlyloadLoad Query and return a promise with QueryResult.
A returned promise always resolves successfully because there is no reason why loading should fail. All data are local, and the query is typed. A serious unexpected Evolu error shall be handled with subscribeError.
Loading is batched, and returned promises are cached, so there is no need for an additional cache. Evolu's internal cache is invalidated on mutation.
The returned promise is enriched with special status and value properties
for the upcoming React use Hook, but other UI libraries can also leverage
them. Speaking of React, there are two essential React Suspense-related
patterns that every developer should be aware of—passing promises to
children and caching over mutations.
With promises passed to children, we can load a query as soon as possible, but we don't have to use the returned promise immediately. That's useful for prefetching, which is generally not necessary for local-first apps but can be if a query takes a long time to load.
Caching over mutation is a pattern that every developer should know. As we said, Evolu caches promise until a mutation happens. A query loaded after that will return a new pending promise. That's okay for general usage but not for UI with React Suspense because a mutation would suspend rerendered queries on a page, and that's not a good UX.
We call this pattern "caching over mutation" because it has no globally accepted name yet. React RFC for React Cache does not exist yet.
For better UX, a query must be subscribed for updates. This way, instead of Suspense flashes, the user sees new data immediately because Evolu replaces cached promises with fresh, already resolved new ones.
If you are curious why Evolu does not do that for all queries by default, the answer is simple: performance. Tracking changes is costly and meaningful only for visible (hence subscribed) queries anyway. To subscribe to a query, use subscribeQuery.
ReadonlyreloadReload the app in a platform-specific way. For browsers, this will reload all tabs using Evolu. For native apps, it will restart the app.
ReadonlyresetDelete Owner and all their data from the current device. After the deletion, Evolu will purge the application state. For browsers, this will reload all tabs using Evolu. For native apps, it will restart the app.
Reloading can be turned off via options if you want to provide a different UX.
ReadonlyrestoreRestore Owner with all their synced data. It uses resetOwner, so be careful.
ReadonlysocketReadonlysubscribeSubscribe to EvoluError changes.
ReadonlysubscribeSubscribe to Owner changes.
ReadonlysubscribeSubscribe to Query QueryResult changes.
ReadonlysubscribeSubscribe to SyncState changes.
Update a row in the database and return the existing ID. The first argument is the table name, and the second is an object.
The third optional argument, the onComplete callback, is generally unnecessary because updating a row cannot fail. Still, UI libraries can use it to ensure the DOM is updated if we want to manipulate it, for example, to focus an element.
Evolu does not use SQL for mutations to ensure data can be safely and predictably merged without conflicts.
Explicit mutations also allow Evolu to automatically add and update a few
useful columns common to all tables. Those columns are: createdAt,
updatedAt, and isDeleted.
The Evolu interface provides a type-safe SQL query building and state management defined by a database schema. It leverages Kysely for creating SQL queries in TypeScript, enabling operations such as data querying, loading, subscription to data changes, and mutations (create, update, createOrUpdate). It also includes functionalities for error handling, syncing state management, and owner data manipulation. Specifically, Evolu allows: