API reference / @evolu/common / Evolu/Internal / Evolu

Interface: Evolu<S>

Defined in: packages/common/src/Evolu/Evolu.ts:65

Type Parameters

Type ParameterDefault type
S extends EvoluSchemaEvoluSchema

Properties

PropertyModifierTypeDescriptionDefined in
createQueryreadonlyCreateQuery<S>Create type-safe SQL Query. Evolu uses Kysely - the type-safe SQL query builder for TypeScript. See https://kysely.dev. All this function does is compile the Kysely query and serialize it into a unique string. Both operations are fast and cheap. For mutations, use Evolu#insert and Evolu#update. ### Example const allTodos = evolu.createQuery((db) => db.selectFrom("todo").selectAll(), ); const todoById = (id: TodoId) => evolu.createQuery((db) => db.selectFrom("todo").selectAll().where("id", "=", id), );packages/common/src/Evolu/Evolu.ts:107
exportDatabasereadonly() => Promise<Uint8Array<ArrayBufferLike>>Export SQLite database file as Uint8Array.packages/common/src/Evolu/Evolu.ts:440
getAppOwnerreadonly() => | null | AppOwnerGet AppOwner. ### Example const unsubscribe = evolu.subscribeAppOwner(() => { const owner = evolu.getAppOwner(); });packages/common/src/Evolu/Evolu.ts:228
getErrorreadonly() => | null | EvoluErrorGet EvoluError.packages/common/src/Evolu/Evolu.ts:81
getQueryRowsreadonly<R>(query) => QueryRows<R>Get QueryRows. ### Example const unsubscribe = evolu.subscribeQuery(allTodos)(() => { const rows = evolu.getQueryRows(allTodos); });packages/common/src/Evolu/Evolu.ts:202
getSyncStatereadonly() => SyncStateGet SyncState. ### Example const unsubscribe = evolu.subscribeSyncState(() => { const syncState = evolu.getSyncState(); });packages/common/src/Evolu/Evolu.ts:254
insertpublicMutation<S, "insert">Inserts a row into the database and returns a Result with the new Id. The first argument is the table name, and the second is an object containing the row data. An optional third argument provides mutation options including an onComplete callback and onlyValidate flag. Returns a Result type - use .ok to check if the insertion succeeded, and .value.id to access the generated ID on success, or .error to handle validation errors. 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 DefaultColumns. ### Example const result = evolu.insert("todo", { title: "Learn Evolu", isCompleted: false, }); if (result.ok) { console.log("Todo created with ID:", result.value.id); } else { console.error("Validation error:", result.error); } // With onComplete callback evolu.insert( "todo", { title: "Another todo" }, { onComplete: () => { console.log("Insert completed"); }, }, );packages/common/src/Evolu/Evolu.ts:298
loadQueriesreadonly<R, Q>(queries) => [...QueriesToQueryRowsPromises<Q>[]]Load an array of Query queries and return an array of QueryRows promises. It's like queries.map(loadQuery) but with proper types for returned promises. ### Example evolu.loadQueries([allTodos, todoById(1)]);packages/common/src/Evolu/Evolu.ts:174
loadQueryreadonly<R>(query) => Promise<QueryRows<R>>Load Query and return a promise with QueryRows. 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 Evolu#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 Evolu#subscribeQuery. ### Example const allTodos = evolu.createQuery((db) => db.selectFrom("todo").selectAll(), ); evolu.loadQuery(allTodos).then(({ rows }) => { console.log(rows); });packages/common/src/Evolu/Evolu.ts:161
reloadAppreadonly() => voidReload the app in a platform-specific way. For browsers, this will reload all tabs using Evolu. For native apps, it will restart the app.packages/common/src/Evolu/Evolu.ts:437
resetAppOwnerreadonly(options?) => Promise<void>Delete AppOwner 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.packages/common/src/Evolu/Evolu.ts:418
restoreAppOwnerreadonly(mnemonic, options?) => Promise<void>Restore AppOwner with all their synced data. It uses Evolu#resetAppOwner, so be careful.packages/common/src/Evolu/Evolu.ts:426
subscribeAppOwnerreadonlyStoreSubscribeSubscribe to AppOwner changes. ### Example const unsubscribe = evolu.subscribeAppOwner(() => { const owner = evolu.getAppOwner(); });packages/common/src/Evolu/Evolu.ts:215
subscribeErrorreadonlyStoreSubscribeSubscribe to EvoluError changes. ### Example const unsubscribe = evolu.subscribeError(() => { const error = evolu.getError(); console.log(error); });packages/common/src/Evolu/Evolu.ts:78
subscribeQueryreadonly(query) => StoreSubscribeSubscribe to Query QueryRows changes. ### Example const unsubscribe = evolu.subscribeQuery(allTodos)(() => { const rows = evolu.getQueryRows(allTodos); });packages/common/src/Evolu/Evolu.ts:189
subscribeSyncStatereadonlyStoreSubscribeSubscribe to SyncState changes. ### Example const unsubscribe = evolu.subscribeSyncState(() => { const syncState = evolu.getSyncState(); });packages/common/src/Evolu/Evolu.ts:241
updatepublicMutation<S, "update">Updates a row in the database and returns a Result with the existing Id. The first argument is the table name, and the second is an object containing the row data including the required id field. An optional third argument provides mutation options including an onComplete callback and onlyValidate flag. Returns a Result type - use .ok to check if the update succeeded, and .value.id to access the ID on success, or .error to handle validation errors. 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 DefaultColumns. ### Example const result = evolu.update("todo", { id: todoId, title: "Updated title", isCompleted: true, }); if (result.ok) { console.log("Todo updated with ID:", result.value.id); } else { console.error("Validation error:", result.error); } // To delete a row, set isDeleted to true evolu.update("todo", { id: todoId, isDeleted: true }); // With onComplete callback evolu.update( "todo", { id: todoId, title: "New title" }, { onComplete: () => { console.log("Update completed"); }, }, );packages/common/src/Evolu/Evolu.ts:347
upsertpublicMutation<S, "upsert">Upserts a row in the database and returns a Result with the existing Id. The first argument is the table name, and the second is an object containing the row data including the required id field. An optional third argument provides mutation options including an onComplete callback and onlyValidate flag. This function allows you to use custom IDs and optionally set createdAt, which is useful for external systems, data migrations, or when the same row may already be created on a different device. Returns a Result type - use .ok to check if the upsert succeeded, and .value.id to access the ID on success, or .error to handle validation errors. 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 DefaultColumns. ### Example // Use deterministic ID for stable upserts across devices const stableId = createIdFromString("my-todo-1"); const result = evolu.upsert("todo", { id: stableId, title: "Learn Evolu", isCompleted: false, }); if (result.ok) { console.log("Todo upserted with ID:", result.value.id); } else { console.error("Validation error:", result.error); } // Data migration with custom createdAt evolu.upsert("todo", { id: externalId, title: "Migrated todo", createdAt: new Date("2023-01-01"), // Preserve original timestamp }); // With onComplete callback evolu.upsert( "todo", { id: stableId, title: "Updated title" }, { onComplete: () => { console.log("Upsert completed"); }, }, );packages/common/src/Evolu/Evolu.ts:407

Was this page helpful?