Something went wrong. Try again.
a tool for shared writing and social publishing
Something went wrong. Try again.
2.9 kB · 89 lines
TypeScript
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990import { PostgresJsDatabase } from "drizzle-orm/postgres-js";import * as driz from "drizzle-orm";import type { Fact } from ".";import { replicache_clients } from "drizzle/schema";import type { Attribute, FilterAttributes } from "./attributes";import { ReadTransaction, WriteTransaction } from "replicache";import { PgTransaction } from "drizzle-orm/pg-core";
export function FactWithIndexes(f: Fact<Attribute>) { let indexes: { eav: string; vae?: string; } = { eav: `${f.entity}-${f.attribute}-${f.id}`, }; if ( f.data.type === "reference" || f.data.type === "ordered-reference" || f.data.type === "spatial-reference" ) indexes.vae = `${f.data.value}-${f.attribute}`; return { ...f, indexes };}
export async function getClientGroup( db: PgTransaction<any, any, any>, clientGroupID: string,): Promise<{ [clientID: string]: number }> { let data = await db .select() .from(replicache_clients) .where(driz.eq(replicache_clients.client_group, clientGroupID)); if (!data) return {}; return data.reduce( (acc, clientRecord) => { acc[clientRecord.client_id] = clientRecord.last_mutation; return acc; }, {} as { [clientID: string]: number }, );}
export const scanIndex = (tx: ReadTransaction) => ({ async eav<A extends Attribute>(entity: string, attribute: A | "") { return ( ( await tx .scan<Fact<A>>({ indexName: "eav", prefix: `${entity}-${attribute}` }) // Hack rn because of the rich bluesky-post type .toArray() ).filter((f) => attribute === "" || f.attribute === attribute) ); }, async vae< A extends keyof FilterAttributes<{ type: "reference" | "ordered-reference" | "spatial-reference"; }>, >(entity: string, attribute: A) { return ( await tx .scan<Fact<A>>({ indexName: "vae", prefix: `${entity}-${attribute}` }) .toArray() ).filter((f) => f.attribute === attribute); },});
export const scanIndexLocal = (initialFacts: Fact<any>[]) => ({ eav<A extends Attribute>(entity: string, attribute: A) { return initialFacts.filter( (f) => f.entity === entity && f.attribute === attribute, ) as SafeArray<Fact<A>>; },});
// Base utility type for making types compatible with ReadonlyJSONObjectexport type AsReadonlyJSONObject<T> = T & { [key: string]: undefined;};
// Recursive utility type for nested objectsexport type DeepAsReadonlyJSONValue<T> = T extends object ? T extends Array<infer U> ? ReadonlyArray<DeepAsReadonlyJSONValue<U>> // Handle arrays : AsReadonlyJSONObject<{ [K in keyof T]: DeepAsReadonlyJSONValue<T[K]>; }> : T extends string | number | boolean | null ? T // Primitive types that already match ReadonlyJSONValue : never; // For other types that can't be converted