Skip to content

Commit

Permalink
adapt API of watchMany & watchOne to use individual refs
Browse files Browse the repository at this point in the history
  • Loading branch information
maradotwebp committed Oct 10, 2023
1 parent dc1ec55 commit 7f35459
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 109 deletions.
12 changes: 6 additions & 6 deletions packages/vue/src/watchFirst.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Entity, key, PrimaryKeyOf, Query, Table } from "blinkdb";
import { computed, ComputedRef, ref, ToRefs } from "vue";
import { computed, ref, ToRefs } from "vue";
import { QueryResult } from "./types";
import { watchMany } from "./watchMany";

Expand Down Expand Up @@ -46,21 +46,21 @@ export function watchFirst<T extends Entity<T>, P extends PrimaryKeyOf<T>>(
table: Table<T, P>,
queryOrId?: Query<T, P> | T[P]
): ToRefs<QueryResult<T | null>> {
const primaryKeyProperty = key(table);
let result: ComputedRef<QueryResult<T[]>>;
let result: ToRefs<QueryResult<T[]>>;

if (queryOrId === undefined) {
result = watchMany(table);
} else {
const query =
typeof queryOrId === "object"
? queryOrId
: ({ where: { [primaryKeyProperty]: queryOrId } } as unknown as Query<T, P>);
: ({ where: { [key(table)]: queryOrId } } as unknown as Query<T, P>);
result = watchMany(table, query);
}

return {
state: computed(() => result.value.state),
data: computed(() => (result.value.data ? result.value.data[0] ?? null : undefined)),
state: result.state,
data: computed(() => (result.data.value ? result.data.value[0] ?? null : undefined)),
error: ref<undefined>(undefined),
} as ToRefs<QueryResult<T | null>>;
}
44 changes: 22 additions & 22 deletions packages/vue/src/watchMany.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,21 @@ beforeEach(() => {
});

test("shows loading state on first render", async () => {
const [result, app] = withSetup(() => watchMany(userTable));
const [{ state, data }, app] = withSetup(() => watchMany(userTable));

expect(result.value.state).toBe("loading");
expect(result.value.data).toBe(undefined);
expect(state.value).toBe("loading");
expect(data.value).toBe(undefined);

app.unmount();
});

test("shows done state on subsequent renders", async () => {
const [result, app] = withSetup(() => watchMany(userTable));
const [{ state, data }, app] = withSetup(() => watchMany(userTable));

await waitFor(() => {
expect(result.value.state).toBe("done");
expect(state.value).toBe("done");
});
expect(result.value.data).toStrictEqual([]);
expect(data.value).toStrictEqual([]);

app.unmount();
});
Expand All @@ -42,28 +42,28 @@ describe("without filter", () => {
});

it("returns users", async () => {
const [result, app] = withSetup(() => watchMany(userTable));
const [{ state, data }, app] = withSetup(() => watchMany(userTable));

await waitFor(() => {
expect(result.value.state).toBe("done");
expect(state.value).toBe("done");
});
expect(result.value.data).toStrictEqual(users);
expect(data.value).toStrictEqual(users);

app.unmount();
});

it("updates on changes", async () => {
const [result, app] = withSetup(() => watchMany(userTable));
const [{ state, data }, app] = withSetup(() => watchMany(userTable));

await waitFor(() => {
expect(result.value.state).toBe("done");
expect(state.value).toBe("done");
});

const newUser: User = { id: "4", name: "Delta" };
await insert(userTable, newUser);

await waitFor(() => {
expect(result.value.data).toStrictEqual([...users, newUser]);
expect(data.value).toStrictEqual([...users, newUser]);
});

app.unmount();
Expand All @@ -76,59 +76,59 @@ describe("with filter", () => {
});

it("returns users", async () => {
const [result, app] = withSetup(() => {
const [{ state, data }, app] = withSetup(() => {
return watchMany(userTable, { where: { name: { in: ["Alice", "Bob", "Elise"] } } });
});

await waitFor(() => {
expect(result.value.state).toBe("done");
expect(state.value).toBe("done");
});

expect(result.value.data).toStrictEqual(
expect(data.value).toStrictEqual(
users.filter((u) => ["Alice", "Bob"].includes(u.name))
);

app.unmount();
});

it("doesn't update on changes not matching the query", async () => {
const [result, app] = withSetup(() => {
const [{ state, data }, app] = withSetup(() => {
return watchMany(userTable, { where: { name: { in: ["Alice", "Bob", "Elise"] } } });
});

await waitFor(() => {
expect(result.value.state).toBe("done");
expect(state.value).toBe("done");
});

const newUser: User = { id: "4", name: "Delta" };
await insert(userTable, newUser);

await waitFor(() => {
expect(result.value.state).toBe("done");
expect(state.value).toBe("done");
});

expect(result.value.data).toStrictEqual(
expect(data.value).toStrictEqual(
users.filter((u) => ["Alice", "Bob"].includes(u.name))
);

app.unmount();
});

it("updates on changes matching the query", async () => {
const [result, app] = withSetup(() => {
const [{ state, data }, app] = withSetup(() => {
return watchMany(userTable, { where: { name: { in: ["Alice", "Bob", "Elise"] } } });
});

await waitFor(() => {
expect(result.value.state).toBe("done");
expect(state.value).toBe("done");
});

const newUser: User = { id: "4", name: "Elise" };
await insert(userTable, newUser);

await new Promise((res) => setTimeout(res, 100));

expect(result.value.data).toStrictEqual([
expect(data.value).toStrictEqual([
...users.filter((u) => ["Alice", "Bob"].includes(u.name)),
newUser,
]);
Expand Down
28 changes: 12 additions & 16 deletions packages/vue/src/watchMany.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Entity, PrimaryKeyOf, Query, Table, watch } from "blinkdb";
import { computed, ComputedRef, onBeforeMount, onBeforeUnmount, ref } from "vue";
import { computed, onBeforeMount, onBeforeUnmount, ref, ToRefs } from "vue";
import { QueryResult } from "./types";

/**
Expand All @@ -10,7 +10,7 @@ import { QueryResult } from "./types";
*/
export function watchMany<T extends Entity<T>, P extends PrimaryKeyOf<T>>(
table: Table<T, P>
): ComputedRef<QueryResult<T[]>>;
): ToRefs<QueryResult<T[]>>;

/**
* Retrieve all entities from `table` that match the given `filter`.
Expand All @@ -32,36 +32,32 @@ export function watchMany<T extends Entity<T>, P extends PrimaryKeyOf<T>>(
export function watchMany<T extends Entity<T>, P extends PrimaryKeyOf<T>>(
table: Table<T, P>,
query: Query<T, P>
): ComputedRef<QueryResult<T[]>>;
): ToRefs<QueryResult<T[]>>;

export function watchMany<T extends Entity<T>, P extends PrimaryKeyOf<T>>(
table: Table<T, P>,
query?: Query<T, P>
): ComputedRef<QueryResult<T[]>> {
const state = ref<T[]>();
): ToRefs<QueryResult<T[]>> {
const result = ref<T[]>();
let dispose: (() => void) | undefined = undefined;

onBeforeMount(async () => {
if (query) {
dispose = await watch<T, P>(table, query, (items) => {
state.value = items;
result.value = items;
});
} else {
dispose = await watch<T, P>(table, (items) => {
state.value = items;
result.value = items;
});
}
});

onBeforeUnmount(() => dispose?.());

return computed(
() =>
({
data: state.value,
state: state.value === undefined ? "loading" : "done",
error: undefined,
} as QueryResult<T[]>),
{ onTrigger: console.log }
);
return {
data: result,
state: computed(() => (result.value === undefined ? "loading" : "done")),
error: ref(undefined),
} as ToRefs<QueryResult<T[]>>;
}
Loading

0 comments on commit 7f35459

Please sign in to comment.