๐Ÿ“„ src/models/generated-src/Tag.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 { LCCAdapter } from "@the_library/standard-adapters/lcc";
16import { DDCAdapter } from "@the_library/standard-adapters/ddc";
17import { UDCAdapter } from "@the_library/standard-adapters/udc";
18import { CLCAdapter } from "@the_library/standard-adapters/clc";
19import { BBKAdapter } from "@the_library/standard-adapters/bbk";
20import { TLCAdapter } from "@the_library/standard-adapters/tlc";
21import { CCAdapter } from "@the_library/standard-adapters/cc";
22
23const schema = schemas["Tag"] as ModelDefinition;
24
25Registry.register(schema);
26
27/** propName -> propId (provenance column mapping) */
28export const TAG_PROP_IDS: Record<string, number> = { title: 0, description: 1, originalLang: 2, ageGradeBand: 3, previewTxId: 4, safe: 5, deleted: 6, lifecycleStatus: 7, lccNotation: 50, ddcNotation: 49, udcNotation: 51, clcNotation: 52, bbkNotation: 53, tlcNotation: 54, ccNotation: 55 };
29
30export interface TagSlimCols {
31    ids: Uint16Array;
32    titles: (string | null)[];
33    originalLangs: (string | null)[];
34    previewTxIds: (string | null)[];
35    ageGradeBands: Uint8Array;
36    safes: Uint8Array;
37    deleteds: Uint8Array;
38}
39
40export interface TagExtendedCols {
41    ids: Uint16Array;
42    descriptions: (string | null)[];
43    lccNotations: (string | null)[];
44    ddcNotations: (string | null)[];
45    udcNotations: (string | null)[];
46    clcNotations: (string | null)[];
47    bbkNotations: (string | null)[];
48    tlcNotations: (string | null)[];
49    ccNotations: (string | null)[];
50    // Structured relation tails (parsed from the sidecar tail, not columnar):
51    tags?: number[][];
52    books?: number[][];
53}
54
55export interface TagProvCols {
56    ids: Uint16Array;
57    fields: Record<string, Uint8Array>;
58}
59
60export interface TagInput {
61    id: number;
62    title: string | null;
63    description: string | null;
64    originalLang: string | null;
65    previewTxId: string | null;
66    ageGradeBand: number;
67    safe: boolean;
68    deleted: boolean;
69    lccNotation: string | null;
70    ddcNotation: string | null;
71    udcNotation: string | null;
72    clcNotation: string | null;
73    bbkNotation: string | null;
74    tlcNotation: string | null;
75    ccNotation: string | null;
76    tags: number[];
77    books: number[];
78}
79export function serializeTagSlim(records: TagInput[]): ArrayBuffer {
80    return commonSerializeSlim(schema, records, currentLayout());
81}
82export function serializeTagExtended(records: TagInput[]): ArrayBuffer {
83    return commonSerializeExtended(schema, records, currentLayout());
84}
85export function serializeTagProv(records: TagInput[]): ArrayBuffer {
86    return commonSerializeProv(schema, records);
87}
88
89export class Tag extends Orm {
90    static readonly type: number = 2;
91    static readonly UID_STRATEGY = 'standards-first' as const;
92    static readonly STANDARD_PRIORITY = ["lcc","ddc","udc","clc","bbk","tlc","cc"] as const;
93
94    static readonly serializeSlim = serializeTagSlim;
95    static readonly serializeExtended = serializeTagExtended;
96    static readonly serializeProv = serializeTagProv;
97
98    constructor(json: CommonOrmJson | SerializedCommonOrmJson, creatorUsername?: string) {
99        super(Tag.type, json, creatorUsername);
100    }
101
102    /** Synchronous LRU read โ€” throws on miss (use LoadAsync to re-hydrate). */
103    static Load(id: uid, creatorUsername?: string): Tag {
104        return getRecord(Tag.type, id, creatorUsername) as Tag;
105    }
106
107    static Has(id: uid, creatorUsername?: string): boolean {
108        return hasRecord(Tag.type, id, creatorUsername);
109    }
110
111    /** On-demand hydration from the worker after LRU eviction (SPEC ยง2.5). */
112    static async LoadAsync(id: uid, creatorUsername?: string): Promise<Tag> {
113        if (hasRecord(Tag.type, id, creatorUsername)) {
114            return getRecord(Tag.type, id, creatorUsername) as Tag;
115        }
116        const thread = PatchInstance.threadInstance;
117        if (!thread) throw new Error("worker thread not initialized โ€” call PatchInstance.initThread first");
118        const res = await thread.sendRequest({
119            cmd: WorkerCommands.GetRecord,
120            payload: { objectType: Tag.type, id }
121        }) as Array<{ lang: Lang, slim?: TagSlimCols, extended?: TagExtendedCols, prov?: TagProvCols }> | null;
122        if (!res || res.length === 0) throw new Error(`Tag ${id} not found in worker storage`);
123        const record = NewTagWithId(id, creatorUsername);
124        for (const data of res) {
125            if (data.slim) record.mergeSlim(data.slim, 0, data.lang);
126            if (data.extended) record.mergeExtended(data.extended, 0, data.lang);
127            if (data.prov) record.mergeProv(data.prov, 0, data.lang);
128        }
129        return record;
130    }
131
132    get lccNotation(): string | null { return this.getProp(50) ?? null; }
133    set lccNotation(value: string | null) { this.dispatchString(50, value ?? ""); }
134    getLccNotation(lang: Lang): string | null { return this.getProp(50, lang) ?? null; }
135    setLccNotation(value: string | null, lang: Lang) { this.dispatchString(50, value ?? "", lang); }
136
137    get ddcNotation(): string | null { return this.getProp(49) ?? null; }
138    set ddcNotation(value: string | null) { this.dispatchString(49, value ?? ""); }
139    getDdcNotation(lang: Lang): string | null { return this.getProp(49, lang) ?? null; }
140    setDdcNotation(value: string | null, lang: Lang) { this.dispatchString(49, value ?? "", lang); }
141
142    get udcNotation(): string | null { return this.getProp(51) ?? null; }
143    set udcNotation(value: string | null) { this.dispatchString(51, value ?? ""); }
144    getUdcNotation(lang: Lang): string | null { return this.getProp(51, lang) ?? null; }
145    setUdcNotation(value: string | null, lang: Lang) { this.dispatchString(51, value ?? "", lang); }
146
147    get clcNotation(): string | null { return this.getProp(52) ?? null; }
148    set clcNotation(value: string | null) { this.dispatchString(52, value ?? ""); }
149    getClcNotation(lang: Lang): string | null { return this.getProp(52, lang) ?? null; }
150    setClcNotation(value: string | null, lang: Lang) { this.dispatchString(52, value ?? "", lang); }
151
152    get bbkNotation(): string | null { return this.getProp(53) ?? null; }
153    set bbkNotation(value: string | null) { this.dispatchString(53, value ?? ""); }
154    getBbkNotation(lang: Lang): string | null { return this.getProp(53, lang) ?? null; }
155    setBbkNotation(value: string | null, lang: Lang) { this.dispatchString(53, value ?? "", lang); }
156
157    get tlcNotation(): string | null { return this.getProp(54) ?? null; }
158    set tlcNotation(value: string | null) { this.dispatchString(54, value ?? ""); }
159    getTlcNotation(lang: Lang): string | null { return this.getProp(54, lang) ?? null; }
160    setTlcNotation(value: string | null, lang: Lang) { this.dispatchString(54, value ?? "", lang); }
161
162    get ccNotation(): string | null { return this.getProp(55) ?? null; }
163    set ccNotation(value: string | null) { this.dispatchString(55, value ?? ""); }
164    getCcNotation(lang: Lang): string | null { return this.getProp(55, lang) ?? null; }
165    setCcNotation(value: string | null, lang: Lang) { this.dispatchString(55, value ?? "", lang); }
166
167    get inTagsIds(): Array<uid> {
168        return Array.from(this._in.get(0)!.values());
169    }
170
171    get inTags(): Array<Tag> {
172        return this.inTagsIds.map(id => Tag.Load(id));
173    }
174
175    isInTag(id: uid): boolean {
176        return this._in.get(0)!.has(id);
177    }
178
179    addIntoTag(id: uid) {
180        if (this.isInTag(id)) return;
181        const op: EditRelationObj = {
182            operation: PatchOperation.EditRelation,
183            objectType: Tag.type,
184            objectId: id,
185            langId: 0,
186            relationId: 3, // canonical: Tag.tags
187            action: PatchAction.Add,
188            targetId: this.id,
189        };
190        if (hasRecord(Tag.type, id)) {
191            (getRecord(Tag.type, id) as Tag).patch(op);
192        }
193        this.applyRelationRaw('in', 0, PatchAction.Add, id);
194        PatchInstance.addPatch(op);
195    }
196
197    removeFromTag(id: uid) {
198        if (!this.isInTag(id)) return;
199        const op: EditRelationObj = {
200            operation: PatchOperation.EditRelation,
201            objectType: Tag.type,
202            objectId: id,
203            langId: 0,
204            relationId: 3, // canonical: Tag.tags
205            action: PatchAction.Remove,
206            targetId: this.id,
207        };
208        if (hasRecord(Tag.type, id)) {
209            (getRecord(Tag.type, id) as Tag).patch(op);
210        }
211        this.applyRelationRaw('in', 0, PatchAction.Remove, id);
212        PatchInstance.addPatch(op);
213    }
214
215    get tagsIds(): Array<uid> {
216        return Array.from(this._has.get(3)!.values());
217    }
218
219    get tags(): Array<Tag> {
220        return this.tagsIds.map(id => Tag.Load(id));
221    }
222
223    hasTag(id: uid): boolean {
224        return this._has.get(3)!.has(id);
225    }
226
227    addTag(id: uid) {
228        if (this.hasTag(id)) return;
229        this.dispatchRelation(3, PatchAction.Add, id);
230    }
231
232    removeTag(id: uid) {
233        if (!this.hasTag(id)) return;
234        this.dispatchRelation(3, PatchAction.Remove, id);
235    }
236
237    get booksIds(): Array<uid> {
238        return Array.from(this._has.get(4)!.values());
239    }
240
241    get books(): Array<Book> {
242        return this.booksIds.map(id => Book.Load(id));
243    }
244
245    hasBook(id: uid): boolean {
246        return this._has.get(4)!.has(id);
247    }
248
249    addBook(id: uid) {
250        if (this.hasBook(id)) return;
251        this.dispatchRelation(4, PatchAction.Add, id);
252    }
253
254    removeBook(id: uid) {
255        if (!this.hasBook(id)) return;
256        this.dispatchRelation(4, PatchAction.Remove, id);
257    }
258
259
260    // โ”€โ”€ UID methods โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
261    toPID(): string { 
262        const scope = (this.id & 0x80000000) ? 'U' : 'C';
263        return `DL:${scope}:TG:${encodePID('TG', this.id)}`; 
264    }
265    toNativePID(): string { return this.toPID(); }
266
267    static fromPID(pid: string): { wireId: number } | null {
268        try {
269            if (!pid.startsWith('DL:')) return decodePID('TG', pid);
270            const parts = pid.split(':');
271            if (parts.length >= 4 && parts[2] === 'TG') {
272                return decodePID('TG', parts[3]);
273            }
274            return null;
275        } catch {
276            return null;
277        }
278    }
279    // โ”€โ”€ Inherited from lcc standard โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
280    get lccNormalized(): string | null {
281        return this.lccNotation ? LCCAdapter.normalize(this.lccNotation) : null;
282    }
283    validateLcc(): ReturnType<typeof LCCAdapter.validate> {
284        return LCCAdapter.validate(this.lccNotation);
285    }
286    // โ”€โ”€ Inherited from ddc standard โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
287    get ddcNormalized(): string | null {
288        return this.ddcNotation ? DDCAdapter.normalize(this.ddcNotation) : null;
289    }
290    validateDdc(): ReturnType<typeof DDCAdapter.validate> {
291        return DDCAdapter.validate(this.ddcNotation);
292    }
293    // โ”€โ”€ Inherited from udc standard โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
294    get udcNormalized(): string | null {
295        return this.udcNotation ? UDCAdapter.normalize(this.udcNotation) : null;
296    }
297    validateUdc(): ReturnType<typeof UDCAdapter.validate> {
298        return UDCAdapter.validate(this.udcNotation);
299    }
300    // โ”€โ”€ Inherited from clc standard โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
301    get clcNormalized(): string | null {
302        return this.clcNotation ? CLCAdapter.normalize(this.clcNotation) : null;
303    }
304    validateClc(): ReturnType<typeof CLCAdapter.validate> {
305        return CLCAdapter.validate(this.clcNotation);
306    }
307    // โ”€โ”€ Inherited from bbk standard โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
308    get bbkNormalized(): string | null {
309        return this.bbkNotation ? BBKAdapter.normalize(this.bbkNotation) : null;
310    }
311    validateBbk(): ReturnType<typeof BBKAdapter.validate> {
312        return BBKAdapter.validate(this.bbkNotation);
313    }
314    // โ”€โ”€ Inherited from tlc standard โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
315    get tlcNormalized(): string | null {
316        return this.tlcNotation ? TLCAdapter.normalize(this.tlcNotation) : null;
317    }
318    validateTlc(): ReturnType<typeof TLCAdapter.validate> {
319        return TLCAdapter.validate(this.tlcNotation);
320    }
321    // โ”€โ”€ Inherited from cc standard โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
322    get ccNormalized(): string | null {
323        return this.ccNotation ? CCAdapter.normalize(this.ccNotation) : null;
324    }
325    validateCc(): ReturnType<typeof CCAdapter.validate> {
326        return CCAdapter.validate(this.ccNotation);
327    }
328    sfcuid(): string {
329        if (this.lccNotation) return `lcc:${LCCAdapter.normalize(this.lccNotation)}`;
330        if (this.ddcNotation) return `ddc:${DDCAdapter.normalize(this.ddcNotation)}`;
331        if (this.udcNotation) return `udc:${UDCAdapter.normalize(this.udcNotation)}`;
332        if (this.clcNotation) return `clc:${CLCAdapter.normalize(this.clcNotation)}`;
333        if (this.bbkNotation) return `bbk:${BBKAdapter.normalize(this.bbkNotation)}`;
334        if (this.tlcNotation) return `tlc:${TLCAdapter.normalize(this.tlcNotation)}`;
335        if (this.ccNotation) return `cc:${CCAdapter.normalize(this.ccNotation)}`;
336        return this.toNativePID();
337    }
338    get identityCluster(): RecordIdentityCluster {
339        const primary = this.sfcuid();
340        const allAliases = [
341            this.lccNotation ? `lcc:${LCCAdapter.normalize(this.lccNotation)}` : null,
342            this.ddcNotation ? `ddc:${DDCAdapter.normalize(this.ddcNotation)}` : null,
343            this.udcNotation ? `udc:${UDCAdapter.normalize(this.udcNotation)}` : null,
344            this.clcNotation ? `clc:${CLCAdapter.normalize(this.clcNotation)}` : null,
345            this.bbkNotation ? `bbk:${BBKAdapter.normalize(this.bbkNotation)}` : null,
346            this.tlcNotation ? `tlc:${TLCAdapter.normalize(this.tlcNotation)}` : null,
347            this.ccNotation ? `cc:${CCAdapter.normalize(this.ccNotation)}` : null,
348            this.toNativePID()
349        ].filter(Boolean) as string[];
350        return {
351            sfcuid: primary,
352            native: this.toNativePID(),
353            aliases: allAliases.filter(a => a !== primary),
354            wireId: this.id,
355        };
356    }
357
358    // Merge methods are now implemented in Orm using the schema definition.
359
360}
361
362
363export const NewTagWithId = (id: uid, creatorUsername?: string): Tag => {
364    if (hasRecord(Tag.type, id, creatorUsername)) {
365        return getRecord(Tag.type, id, creatorUsername) as Tag;
366    }
367    const record = new Tag(Tag.createNewRequest(id), creatorUsername);
368    addRecord(Tag.type, record, creatorUsername);
369    return record;
370}
371