๐Ÿ“„ src/models/generated-src/Person.ts
D-OPEN SOVEREIGN

Documentation & Insights

propName -> propId (provenance column mapping)
Synchronous LRU read โ€” throws on miss (use LoadAsync to re-hydrate).
On-demand hydration from the worker after LRU eviction (SPEC ยง2.5).
1// AUTO-GENERATED by @the_library/db_schemas schemaGenerator โ€” run `pnpm generate` to rebuild.
2import { Orm, Config } from "../orm.ts";
3import { Registry, type ModelDefinition } from "../registry.ts";
4import { PatchOperation, PatchAction, LANG_ID_ENCODE, type EditInstanceFieldNumberObj, type EditInstanceFieldStringObj, type EditRelationObj } from "../binary.ts";
5import { PatchInstance } from "../patcher.ts";
6import { addRecord, getRecord, hasRecord } from "../db.ts";
7import type { uid, Lang, CommonOrmJson, SerializedCommonOrmJson, InstanceData, RecordIdentityCluster } from "../interfaces.ts";
8import { WorkerCommands, SidecarType } from "../enums.ts";
9import { ColumnType, type SidecarInput, type SidecarRelationInput, instanceSpecFromFields } from "../enriched-index.ts";
10import { encodePID, decodePID } from "../pid.ts";
11import { schemas } from "@the_library/db_schemas/schemas";
12import { commonSerializeSlim, commonSerializeExtended, commonSerializeProv } from "../serializer.ts";
13import { currentLayout } from "../versions.ts";
14import { Book } from "./Book.ts";
15import { ISNIAdapter } from "@the_library/standard-adapters/isni";
16import { ORCIDAdapter } from "@the_library/standard-adapters/orcid";
17
18const schema = schemas["Person"] as ModelDefinition;
19
20Registry.register(schema);
21
22/** propName -> propId (provenance column mapping) */
23export const PERSON_PROP_IDS: Record<string, number> = { title: 0, description: 1, originalLang: 2, ageGradeBand: 3, previewTxId: 4, safe: 5, deleted: 6, lifecycleStatus: 7, birthDate: 43, deathDate: 44, nationality: 45, wikiUrl: 46, isniId: 47, orcidId: 48 };
24
25export interface PersonSlimCols {
26    ids: Uint16Array;
27    titles: (string | null)[];
28    originalLangs: (string | null)[];
29    previewTxIds: (string | null)[];
30    ageGradeBands: Uint8Array;
31    safes: Uint8Array;
32    deleteds: Uint8Array;
33}
34
35export interface PersonExtendedCols {
36    ids: Uint16Array;
37    descriptions: (string | null)[];
38    birthDates: (string | null)[];
39    deathDates: (string | null)[];
40    nationalitys: (string | null)[];
41    wikiUrls: (string | null)[];
42    isniIds: (string | null)[];
43    orcidIds: (string | null)[];
44}
45
46export interface PersonProvCols {
47    ids: Uint16Array;
48    fields: Record<string, Uint8Array>;
49}
50
51export interface PersonInput {
52    id: number;
53    title: string | null;
54    description: string | null;
55    originalLang: string | null;
56    previewTxId: string | null;
57    ageGradeBand: number;
58    safe: boolean;
59    deleted: boolean;
60    birthDate: string | null;
61    deathDate: string | null;
62    nationality: string | null;
63    wikiUrl: string | null;
64    isniId: string | null;
65    orcidId: string | null;
66}
67export function serializePersonSlim(records: PersonInput[]): ArrayBuffer {
68    return commonSerializeSlim(schema, records, currentLayout());
69}
70export function serializePersonExtended(records: PersonInput[]): ArrayBuffer {
71    return commonSerializeExtended(schema, records, currentLayout());
72}
73export function serializePersonProv(records: PersonInput[]): ArrayBuffer {
74    return commonSerializeProv(schema, records);
75}
76
77export class Person extends Orm {
78    static readonly type: number = 1;
79    static readonly UID_STRATEGY = 'standards-first' as const;
80    static readonly STANDARD_PRIORITY = ["isni","orcid"] as const;
81
82    static readonly serializeSlim = serializePersonSlim;
83    static readonly serializeExtended = serializePersonExtended;
84    static readonly serializeProv = serializePersonProv;
85
86    constructor(json: CommonOrmJson | SerializedCommonOrmJson, creatorUsername?: string) {
87        super(Person.type, json, creatorUsername);
88    }
89
90    /** Synchronous LRU read โ€” throws on miss (use LoadAsync to re-hydrate). */
91    static Load(id: uid, creatorUsername?: string): Person {
92        return getRecord(Person.type, id, creatorUsername) as Person;
93    }
94
95    static Has(id: uid, creatorUsername?: string): boolean {
96        return hasRecord(Person.type, id, creatorUsername);
97    }
98
99    /** On-demand hydration from the worker after LRU eviction (SPEC ยง2.5). */
100    static async LoadAsync(id: uid, creatorUsername?: string): Promise<Person> {
101        if (hasRecord(Person.type, id, creatorUsername)) {
102            return getRecord(Person.type, id, creatorUsername) as Person;
103        }
104        const thread = PatchInstance.threadInstance;
105        if (!thread) throw new Error("worker thread not initialized โ€” call PatchInstance.initThread first");
106        const res = await thread.sendRequest({
107            cmd: WorkerCommands.GetRecord,
108            payload: { objectType: Person.type, id }
109        }) as Array<{ lang: Lang, slim?: PersonSlimCols, extended?: PersonExtendedCols, prov?: PersonProvCols }> | null;
110        if (!res || res.length === 0) throw new Error(`Person ${id} not found in worker storage`);
111        const record = NewPersonWithId(id, creatorUsername);
112        for (const data of res) {
113            if (data.slim) record.mergeSlim(data.slim, 0, data.lang);
114            if (data.extended) record.mergeExtended(data.extended, 0, data.lang);
115            if (data.prov) record.mergeProv(data.prov, 0, data.lang);
116        }
117        return record;
118    }
119
120    get birthDate(): string { return this.getProp(43); }
121    set birthDate(value: string) { this.dispatchString(43, value); }
122    getBirthDate(lang: Lang): string { return this.getProp(43, lang); }
123    setBirthDate(value: string, lang: Lang) { this.dispatchString(43, value, lang); }
124
125    get deathDate(): string { return this.getProp(44); }
126    set deathDate(value: string) { this.dispatchString(44, value); }
127    getDeathDate(lang: Lang): string { return this.getProp(44, lang); }
128    setDeathDate(value: string, lang: Lang) { this.dispatchString(44, value, lang); }
129
130    get nationality(): string { return this.getProp(45); }
131    set nationality(value: string) { this.dispatchString(45, value); }
132    getNationality(lang: Lang): string { return this.getProp(45, lang); }
133    setNationality(value: string, lang: Lang) { this.dispatchString(45, value, lang); }
134
135    get wikiUrl(): string { return this.getProp(46); }
136    set wikiUrl(value: string) { this.dispatchString(46, value); }
137    getWikiUrl(lang: Lang): string { return this.getProp(46, lang); }
138    setWikiUrl(value: string, lang: Lang) { this.dispatchString(46, value, lang); }
139
140    get isniId(): string | null { return this.getProp(47) ?? null; }
141    set isniId(value: string | null) { this.dispatchString(47, value ?? ""); }
142    getIsniId(lang: Lang): string | null { return this.getProp(47, lang) ?? null; }
143    setIsniId(value: string | null, lang: Lang) { this.dispatchString(47, value ?? "", lang); }
144
145    get orcidId(): string | null { return this.getProp(48) ?? null; }
146    set orcidId(value: string | null) { this.dispatchString(48, value ?? ""); }
147    getOrcidId(lang: Lang): string | null { return this.getProp(48, lang) ?? null; }
148    setOrcidId(value: string | null, lang: Lang) { this.dispatchString(48, value ?? "", lang); }
149
150    get inAuthorOfIds(): Array<uid> {
151        return Array.from(this._in.get(2)!.values());
152    }
153
154    get inAuthorOf(): Array<Book> {
155        return this.inAuthorOfIds.map(id => Book.Load(id));
156    }
157
158    isInAuthorOf(id: uid): boolean {
159        return this._in.get(2)!.has(id);
160    }
161
162    addIntoAuthorOf(id: uid) {
163        if (this.isInAuthorOf(id)) return;
164        const op: EditRelationObj = {
165            operation: PatchOperation.EditRelation,
166            objectType: Book.type,
167            objectId: id,
168            langId: 0,
169            relationId: 1, // canonical: Book.authors
170            action: PatchAction.Add,
171            targetId: this.id,
172        };
173        if (hasRecord(Book.type, id)) {
174            (getRecord(Book.type, id) as Book).patch(op);
175        }
176        this.applyRelationRaw('in', 2, PatchAction.Add, id);
177        PatchInstance.addPatch(op);
178    }
179
180    removeFromAuthorOf(id: uid) {
181        if (!this.isInAuthorOf(id)) return;
182        const op: EditRelationObj = {
183            operation: PatchOperation.EditRelation,
184            objectType: Book.type,
185            objectId: id,
186            langId: 0,
187            relationId: 1, // canonical: Book.authors
188            action: PatchAction.Remove,
189            targetId: this.id,
190        };
191        if (hasRecord(Book.type, id)) {
192            (getRecord(Book.type, id) as Book).patch(op);
193        }
194        this.applyRelationRaw('in', 2, PatchAction.Remove, id);
195        PatchInstance.addPatch(op);
196    }
197
198
199    // โ”€โ”€ UID methods โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
200    toPID(): string { 
201        const scope = (this.id & 0x80000000) ? 'U' : 'C';
202        return `DL:${scope}:PR:${encodePID('PR', this.id)}`; 
203    }
204    toNativePID(): string { return this.toPID(); }
205
206    static fromPID(pid: string): { wireId: number } | null {
207        try {
208            if (!pid.startsWith('DL:')) return decodePID('PR', pid);
209            const parts = pid.split(':');
210            if (parts.length >= 4 && parts[2] === 'PR') {
211                return decodePID('PR', parts[3]);
212            }
213            return null;
214        } catch {
215            return null;
216        }
217    }
218    // โ”€โ”€ Inherited from isni standard โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
219    get isniNormalized(): string | null {
220        return this.isniId ? ISNIAdapter.normalize(this.isniId) : null;
221    }
222    validateIsni(): ReturnType<typeof ISNIAdapter.validate> {
223        return ISNIAdapter.validate(this.isniId);
224    }
225    // โ”€โ”€ Inherited from orcid standard โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
226    get orcidNormalized(): string | null {
227        return this.orcidId ? ORCIDAdapter.normalize(this.orcidId) : null;
228    }
229    validateOrcid(): ReturnType<typeof ORCIDAdapter.validate> {
230        return ORCIDAdapter.validate(this.orcidId);
231    }
232    sfcuid(): string {
233        if (this.isniId) return `isni:${ISNIAdapter.normalize(this.isniId)}`;
234        if (this.orcidId) return `orcid:${ORCIDAdapter.normalize(this.orcidId)}`;
235        return this.toNativePID();
236    }
237    get identityCluster(): RecordIdentityCluster {
238        const primary = this.sfcuid();
239        const allAliases = [
240            this.isniId ? `isni:${ISNIAdapter.normalize(this.isniId)}` : null,
241            this.orcidId ? `orcid:${ORCIDAdapter.normalize(this.orcidId)}` : null,
242            this.toNativePID()
243        ].filter(Boolean) as string[];
244        return {
245            sfcuid: primary,
246            native: this.toNativePID(),
247            aliases: allAliases.filter(a => a !== primary),
248            wireId: this.id,
249        };
250    }
251
252    // Merge methods are now implemented in Orm using the schema definition.
253
254}
255
256
257export const NewPersonWithId = (id: uid, creatorUsername?: string): Person => {
258    if (hasRecord(Person.type, id, creatorUsername)) {
259        return getRecord(Person.type, id, creatorUsername) as Person;
260    }
261    const record = new Person(Person.createNewRequest(id), creatorUsername);
262    addRecord(Person.type, record, creatorUsername);
263    return record;
264}
265