import { suivreFonctionImbriquée, faisRien, ignorerNonDéfinis, } from "@constl/utils-ipa"; import { TypedKeyValue, TypedSet } from "@constl/bohr-db"; import { JSONSchemaType } from "ajv"; import { schémaStructureBdCompte, type Constellation, type structureBdCompte, } from "@/client.js"; import { cacheSuivi } from "./décorateursCache.js"; import type { schémaFonctionOublier, schémaFonctionSuivi, élémentsBd, } from "./types.js"; // Obtenu de https://stackoverflow.com/a/54520829 type KeysMatching = { [K in keyof T]-?: T[K] extends V ? K : never; }[keyof T]; export class ComposanteClient { client: Constellation; clef: KeysMatching; typeBd: "keyvalue" | "set"; constructor({ client, clef, typeBd, }: { client: Constellation; clef: KeysMatching; typeBd: "keyvalue" | "set"; }) { this.client = client; this.clef = clef; this.typeBd = typeBd; } async obtIdBd(): Promise { const { idCompte } = await this.client.attendreInitialisée(); const idBd = await this.client.obtIdBd({ nom: this.clef, racine: idCompte, type: this.typeBd, }); if (!idBd) throw new Error("Mal initialisé"); return idBd; } } export class ComposanteClientDic< T extends { [clef: string]: élémentsBd }, > extends ComposanteClient { schémaBdPrincipale: JSONSchemaType; constructor({ client, clef, schémaBdPrincipale, }: { client: Constellation; clef: KeysMatching; schémaBdPrincipale: JSONSchemaType; }) { super({ client, clef, typeBd: "keyvalue", }); this.schémaBdPrincipale = schémaBdPrincipale; } async obtBd(): Promise<{ bd: TypedKeyValue; fOublier: schémaFonctionOublier; }> { const id = await this.obtIdBd(); return await this.client.ouvrirBdTypée({ id, type: "keyvalue", schéma: this.schémaBdPrincipale, }); } @cacheSuivi async suivreBdPrincipale({ idCompte, f, }: { idCompte?: string; f: schémaFonctionSuivi; }): Promise { return await suivreFonctionImbriquée({ fRacine: async ({ fSuivreRacine }) => { return await this.suivreIdBd({ f: fSuivreRacine, idCompte }); }, f: ignorerNonDéfinis(f), fSuivre: async ({ id, fSuivreBd }) => { return await this.client.suivreBdDic({ id, schéma: this.schémaBdPrincipale, f: fSuivreBd, }); }, }); } @cacheSuivi async suivreSousBdDic({ idCompte, clef, schéma, f, }: { idCompte?: string; clef: string; schéma: JSONSchemaType; f: schémaFonctionSuivi; }): Promise { return await suivreFonctionImbriquée({ fRacine: async ({ fSuivreRacine }) => { return await this.suivreIdBd({ f: fSuivreRacine, idCompte }); }, f: ignorerNonDéfinis(f), fSuivre: async ({ id, fSuivreBd }) => { return await this.client.suivreBdDicDeClef({ id, clef, schéma, f: fSuivreBd, }); }, }); } @cacheSuivi async suivreSousBdListe({ idCompte, clef, schéma, f, }: { idCompte?: string; clef: string; schéma: JSONSchemaType; f: schémaFonctionSuivi; }): Promise { return await suivreFonctionImbriquée({ fRacine: async ({ fSuivreRacine }) => { return await this.suivreIdBd({ f: fSuivreRacine, idCompte }); }, f: ignorerNonDéfinis(f), fSuivre: async ({ id, fSuivreBd }) => { return await this.client.suivreBdListeDeClef({ id, clef: clef, f: fSuivreBd, schéma, renvoyerValeur: true, }); }, }); } @cacheSuivi async suivreIdBd({ f, idCompte, }: { f: schémaFonctionSuivi; idCompte?: string; }): Promise { return await suivreFonctionImbriquée({ fRacine: async ({ fSuivreRacine }) => { if (idCompte) { await fSuivreRacine(idCompte); return faisRien; } else { return await this.client.suivreIdCompte({ f: fSuivreRacine }); } }, f: ignorerNonDéfinis(f), fSuivre: async ({ id, fSuivreBd }) => { return await this.client.suivreBdDic({ id, schéma: schémaStructureBdCompte, f: async (données) => { const idBdComposante = données[this.clef]; await fSuivreBd(idBdComposante); }, }); }, }); } } export class ComposanteClientListe< T extends élémentsBd, > extends ComposanteClient { schémaBdPrincipale: JSONSchemaType; constructor({ client, clef, schémaBdPrincipale, }: { client: Constellation; clef: KeysMatching; schémaBdPrincipale: JSONSchemaType; }) { super({ client, clef, typeBd: "set", }); this.schémaBdPrincipale = schémaBdPrincipale; } async obtBd(): Promise<{ bd: TypedSet; fOublier: schémaFonctionOublier; }> { const id = await this.obtIdBd(); return await this.client.ouvrirBdTypée({ id, type: "set", schéma: this.schémaBdPrincipale, }); } @cacheSuivi async suivreBdPrincipale({ idCompte, f, }: { idCompte?: string; f: schémaFonctionSuivi; }): Promise { return await suivreFonctionImbriquée({ fRacine: async ({ fSuivreRacine }) => { return await this.suivreIdBd({ f: fSuivreRacine, idCompte }); }, f: ignorerNonDéfinis(f), fSuivre: async ({ id, fSuivreBd }) => { return await this.client.suivreBdListe({ id, f: fSuivreBd, schéma: this.schémaBdPrincipale, renvoyerValeur: true, }); }, }); } @cacheSuivi async suivreIdBd({ f, idCompte, }: { f: schémaFonctionSuivi; idCompte?: string; }): Promise { return await suivreFonctionImbriquée({ fRacine: async ({ fSuivreRacine }) => { if (idCompte) { await fSuivreRacine(idCompte); return faisRien; } else { return await this.client.suivreIdCompte({ f: fSuivreRacine }); } }, f: ignorerNonDéfinis(f), fSuivre: async ({ id, fSuivreBd }) => { return await this.client.suivreBdDic({ id, schéma: schémaStructureBdCompte, f: async (données) => { const idBdComposante = données[this.clef]; await fSuivreBd(idBdComposante); }, }); }, }); } }