sqlocal
Version:
SQLocal makes it easy to run SQLite3 in the browser, backed by the origin private file system.
63 lines (54 loc) • 1.58 kB
text/typescript
import { computed, effect, isSignal, signal, type Signal } from '@angular/core';
import type { SQLocal } from '../client.js';
import type { ReactiveQueryStatus, StatementInput } from '../types.js';
/**
* A signal function for using reactive SQL queries in Angular components.
* @see {@link https://sqlocal.dev/api/reactivequery#angular}
*/
export function useReactiveQuery<Result extends Record<string, any>>(
db: SQLocal | Signal<SQLocal>,
query: StatementInput<Result> | Signal<StatementInput<Result>>
): {
data: Signal<Result[]>;
error: Signal<Error | undefined>;
status: Signal<ReactiveQueryStatus>;
} {
const data = signal<Result[]>([]);
const error = signal<Error | undefined>(undefined);
const pending = signal<boolean>(true);
const dbValue = computed(() => (isSignal(db) ? db() : db));
const queryValue = computed(() => (isSignal(query) ? query() : query));
effect(
(onCleanup) => {
const db = dbValue();
const query = queryValue();
pending.set(true);
const subscription = db.reactiveQuery(query).subscribe(
(results) => {
data.set(results);
error.set(undefined);
pending.set(false);
},
(err) => {
error.set(err);
}
);
onCleanup(() => {
subscription.unsubscribe();
});
},
{ allowSignalWrites: true }
);
const status = computed<ReactiveQueryStatus>(() => {
const hasError = !!error();
const isPending = pending();
if (hasError) return 'error';
if (isPending) return 'pending';
return 'ok';
});
return {
data: data.asReadonly(),
error: error.asReadonly(),
status,
};
}