📄 src/models/registry.ts
D-OPEN SOVEREIGN

Documentation & Insights

V2 model definition — the shape of the enriched JSON files in
`@the_library/db_schemas/generated-src/*.json` (frozen numeric IDs).
Cols field name for a `has`-relation tail. The `authors` relation keeps its
historical `authorIds` name for back-compat; every other relation uses its
schema name directly (e.g. Tag.tags, Tag.books). Single source of truth for
both the codegen (schemaGenerator.ts, which emits `${relationColName(rel)}`
as the ExtendedCols field name) and the runtime reader (orm.ts's
mergeExtended, which must look up that same field name on the incoming cols
object) — they must never drift apart.
Lookup by model name (relation targetType resolution).
1/*
2 * Copyright (c) 2026 DataPond D-Library Pty Ltd. ("The Sanctuary")
3 * Non-Profit Public Library — The World Library
4 * 
5 * D-SAFE Certification issued by POND Enterprise.
6 * Published under the D-Open Code Sovereign Licence v1.0 framework
7 * DataPond D-Library All exclusive Right reserved on modifiying the code - CC Attribution to data pond, Non modifiable, Non Commercial.
8 * https://registry.world.bibliotech.com/licence
9 * Source code donated to DataPond D-Library by it's author: data pond.
10 * 
11 * Technical Guardian ("The Shield"): Pond Enterprise Pty Ltd. (ACN 694 747 987)
12 * All liability claims about D-SAFE certification issues coming from the published D-Safe direction must be addressed with Pond Enterprise Pty Ltd.
13 * Code Modification automatically voids the certified liability protection provided by Pond Enterprise.
14 */
15import type { PropertyType } from "./interfaces.ts";
16
17/**
18 * V2 model definition — the shape of the enriched JSON files in
19 * `@the_library/db_schemas/generated-src/*.json` (frozen numeric IDs).
20 */
21export interface SchemaProp {
22    name: string;
23    type: PropertyType;
24    source: 'slim' | 'extended';
25    propId: number;
26    enum?: string;
27    bits?: number;
28    nullable?: boolean;
29}
30
31export interface SchemaInstanceField {
32    name: string;
33    type: PropertyType;
34    propId: number;
35    enum?: string;
36    bits?: number;
37    nullable?: boolean;
38    identityComponent?: boolean;
39    source?: 'slim' | 'extended';
40}
41
42export interface SchemaRelation {
43    name: string;
44    targetType: string;
45    direction: 'has' | 'in';
46    inverted: string;
47    relationId: number;
48}
49
50/**
51 * Cols field name for a `has`-relation tail. The `authors` relation keeps its
52 * historical `authorIds` name for back-compat; every other relation uses its
53 * schema name directly (e.g. Tag.tags, Tag.books). Single source of truth for
54 * both the codegen (schemaGenerator.ts, which emits `${relationColName(rel)}`
55 * as the ExtendedCols field name) and the runtime reader (orm.ts's
56 * mergeExtended, which must look up that same field name on the incoming cols
57 * object) — they must never drift apart.
58 */
59export const relationColName = (rel: SchemaRelation): string =>
60    rel.name === 'authors' ? 'authorIds' : rel.name;
61
62export interface ModelDefinition {
63    name: string;
64    typePrefix: string;
65    objectId: number;
66    multipleInstances: boolean;
67    uidStrategy?: string | string[];
68    instanceUidStrategy?: string | string[];
69    standardPks?: Record<string, string>;
70    props: SchemaProp[];
71    instanceFields: SchemaInstanceField[];
72    relations: SchemaRelation[];
73}
74
75export class SchemaRegistry {
76    private static instance: SchemaRegistry;
77    private schemas: Map<number, ModelDefinition> = new Map();
78    private byName: Map<string, ModelDefinition> = new Map();
79
80    private constructor() { }
81
82    public static getInstance(): SchemaRegistry {
83        if (!SchemaRegistry.instance) {
84            SchemaRegistry.instance = new SchemaRegistry();
85        }
86        return SchemaRegistry.instance;
87    }
88
89    public register(schema: ModelDefinition): void {
90        this.schemas.set(schema.objectId, schema);
91        this.byName.set(schema.name, schema);
92    }
93
94    public get(id: number): ModelDefinition {
95        const schema = this.schemas.get(id);
96        if (!schema) {
97            console.warn(`[SchemaRegistry] No schema registered for type ID ${id}. Returning generic placeholder.`);
98            return { name: 'Generic', typePrefix: 'XX', objectId: id, multipleInstances: false, props: [], instanceFields: [], relations: [] };
99        }
100        return schema;
101    }
102
103    /** Lookup by model name (relation targetType resolution). */
104    public getByName(name: string): ModelDefinition | undefined {
105        return this.byName.get(name);
106    }
107
108    public clear(): void {
109        this.schemas.clear();
110        this.byName.clear();
111    }
112}
113
114export const Registry = SchemaRegistry.getInstance();
115