@the_library/public 1.0.0 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +201 -28
- package/assets/branding/pond-enterprise-logo.svg +1 -1
- package/dist/Book-CYyj_y_4.d.ts +621 -0
- package/dist/bookSearchService-YQskauJS.d.ts +300 -0
- package/dist/branding/index.js +1 -66
- package/dist/branding/index.js.map +1 -1
- package/dist/chunk-3XUKOVEF.js +2 -0
- package/dist/chunk-3XUKOVEF.js.map +1 -0
- package/dist/chunk-46FQHZNM.js +2 -0
- package/dist/chunk-46FQHZNM.js.map +1 -0
- package/dist/chunk-7G3BMGV2.js +2 -0
- package/dist/chunk-7G3BMGV2.js.map +1 -0
- package/dist/chunk-D4DXGA2W.js +2 -0
- package/dist/chunk-D4DXGA2W.js.map +1 -0
- package/dist/chunk-EMA2QJTW.js +2 -0
- package/dist/chunk-EMA2QJTW.js.map +1 -0
- package/dist/chunk-FN52YV7L.js +2 -0
- package/dist/chunk-FN52YV7L.js.map +1 -0
- package/dist/chunk-GWQNULP4.js +2 -0
- package/dist/chunk-GWQNULP4.js.map +1 -0
- package/dist/chunk-OELHBR4F.js +2 -0
- package/dist/chunk-OELHBR4F.js.map +1 -0
- package/dist/chunk-PV3X54EU.js +2 -0
- package/dist/chunk-PV3X54EU.js.map +1 -0
- package/dist/chunk-SD3INWZF.js +2 -0
- package/dist/chunk-SD3INWZF.js.map +1 -0
- package/dist/downloader/dl2-sw.js +1 -198
- package/dist/downloader/dl2-sw.js.map +1 -1
- package/dist/downloader/file-worker-v2.js +1 -257
- package/dist/downloader/file-worker-v2.js.map +1 -1
- package/dist/downloader/index.d.ts +30 -2
- package/dist/downloader/index.js +1 -537
- package/dist/downloader/index.js.map +1 -1
- package/dist/downloader/mu-worker-v2.js +1 -196
- package/dist/downloader/mu-worker-v2.js.map +1 -1
- package/dist/downloader/react.d.ts +1 -1
- package/dist/downloader/react.js +1 -31
- package/dist/downloader/react.js.map +1 -1
- package/dist/downloader/solid.d.ts +1 -1
- package/dist/downloader/solid.js +1 -18
- package/dist/downloader/solid.js.map +1 -1
- package/dist/downloader/sw.js +1 -118
- package/dist/downloader/sw.js.map +1 -1
- package/dist/downloader/vue.d.ts +1 -1
- package/dist/downloader/vue.js +1 -18
- package/dist/downloader/vue.js.map +1 -1
- package/dist/enriched-index-T0sDG7JR.d.ts +209 -0
- package/dist/global/public.global.js +68 -0
- package/dist/global/public.manifest.json +484 -0
- package/dist/level-state-DXqglpAX.d.ts +27 -0
- package/dist/models/astro.d.ts +4 -3
- package/dist/models/astro.js +1 -43
- package/dist/models/astro.js.map +1 -1
- package/dist/models/index.d.ts +449 -23
- package/dist/models/index.js +1 -339
- package/dist/models/index.js.map +1 -1
- package/dist/models/models.d.ts +195 -441
- package/dist/models/models.js +1 -45
- package/dist/models/patch-worker.js +1 -542
- package/dist/models/patch-worker.js.map +1 -1
- package/dist/models/react.d.ts +6 -5
- package/dist/models/react.js +1 -72
- package/dist/models/react.js.map +1 -1
- package/dist/models/solid.d.ts +16 -6
- package/dist/models/solid.js +1 -94
- package/dist/models/solid.js.map +1 -1
- package/dist/models/vue.d.ts +89 -7
- package/dist/models/vue.js +1 -97
- package/dist/models/vue.js.map +1 -1
- package/dist/orm-MJTHCG9E.d.ts +1003 -0
- package/dist/{session-vqOnyxga.d.ts → session-JudUKAV7.d.ts} +76 -74
- package/dist/{state-BTsp-E4v.d.ts → state-CkYavOSt.d.ts} +16 -0
- package/dist/{types-Dn0EFMO_.d.ts → types-B-IX3HBn.d.ts} +94 -21
- package/dist/{types-Xb8Ta9tZ.d.ts → types-Blyx2A7F.d.ts} +10 -36
- package/dist/web3/auth.d.ts +89 -0
- package/dist/web3/auth.js +13 -0
- package/dist/web3/auth.js.map +1 -0
- package/dist/web3/index.d.ts +1913 -126
- package/dist/web3/index.js +1 -1019
- package/dist/web3/index.js.map +1 -1
- package/dist/web3/network.d.ts +6 -0
- package/dist/web3/network.js +2 -0
- package/dist/web3/network.js.map +1 -0
- package/dist/web3/registry.d.ts +34 -9
- package/dist/web3/registry.js +1 -22
- package/dist/web3/vue.d.ts +31 -14
- package/dist/web3/vue.js +1 -390
- package/dist/web3/vue.js.map +1 -1
- package/package.json +36 -15
- package/dist/chunk-2HFOWE5R.js +0 -296
- package/dist/chunk-2HFOWE5R.js.map +0 -1
- package/dist/chunk-3L6LH2XK.js +0 -465
- package/dist/chunk-3L6LH2XK.js.map +0 -1
- package/dist/chunk-4CWVFPBN.js +0 -28
- package/dist/chunk-4CWVFPBN.js.map +0 -1
- package/dist/chunk-AGHPATVL.js +0 -65
- package/dist/chunk-AGHPATVL.js.map +0 -1
- package/dist/chunk-JDUYLUDJ.js +0 -4835
- package/dist/chunk-JDUYLUDJ.js.map +0 -1
- package/dist/chunk-OEZK7IX7.js +0 -77
- package/dist/chunk-OEZK7IX7.js.map +0 -1
- package/dist/chunk-PUYDAUCI.js +0 -2873
- package/dist/chunk-PUYDAUCI.js.map +0 -1
- package/dist/chunk-WHWMTS7D.js +0 -99
- package/dist/chunk-WHWMTS7D.js.map +0 -1
- package/dist/chunk-Y7RS6RTM.js +0 -342
- package/dist/chunk-Y7RS6RTM.js.map +0 -1
- package/dist/chunk-ZEZGI2TP.js +0 -197
- package/dist/chunk-ZEZGI2TP.js.map +0 -1
- package/dist/core-dao-core-logo-VDT2I5IW.svg +0 -33
- package/dist/level-state-J3pj64Tr.d.ts +0 -15
- package/dist/models/models_v2.global.js +0 -1
- package/dist/orm-BvkX0aBT.d.ts +0 -507
|
@@ -0,0 +1,1003 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Local-only, non-EVM operations (analytics, local state).
|
|
3
|
+
* EVM-bound mutations use `PatchOperation` from `@the_library/db_schemas`
|
|
4
|
+
* (re-exported in `binary.ts`) — do not add EVM operation variants here.
|
|
5
|
+
*/
|
|
6
|
+
declare enum ActionTypes {
|
|
7
|
+
Visit = 0,
|
|
8
|
+
VisitPart = 1,
|
|
9
|
+
Download = 2,
|
|
10
|
+
Rate = 3,
|
|
11
|
+
RatePart = 4,
|
|
12
|
+
Share = 5,
|
|
13
|
+
SharePart = 6
|
|
14
|
+
}
|
|
15
|
+
declare enum WorkerCommands {
|
|
16
|
+
Init = "init",// Initial load: fetch sidecars + local patches
|
|
17
|
+
SavePatches = "savePatches",
|
|
18
|
+
GetRecord = "getRecord",// LRU on-demand re-hydration (SPEC §2.5)
|
|
19
|
+
LoadLanguage = "loadLanguage"
|
|
20
|
+
}
|
|
21
|
+
declare enum Rating {
|
|
22
|
+
None = 0,
|
|
23
|
+
New = 1,
|
|
24
|
+
Keep = 2,
|
|
25
|
+
Trash = 3,
|
|
26
|
+
Shared = 4
|
|
27
|
+
}
|
|
28
|
+
declare enum WorkerEvent {
|
|
29
|
+
WorkerReady = "workerready",
|
|
30
|
+
WorkerLoadingError = "workerLoadingError",
|
|
31
|
+
DownloadStarted = "downloadStarted",
|
|
32
|
+
DownloadFinished = "downloadFinished",
|
|
33
|
+
DownloadError = "downloadError",
|
|
34
|
+
LevelUpdated = "levelUpdated"
|
|
35
|
+
}
|
|
36
|
+
declare enum DownloadState {
|
|
37
|
+
Unknown = 0,
|
|
38
|
+
Pending = 1,
|
|
39
|
+
InProgress = 2,
|
|
40
|
+
Done = 3,
|
|
41
|
+
Error = 4
|
|
42
|
+
}
|
|
43
|
+
/** Sidecar type byte in the DPM1 wire header (SPEC §4.1). */
|
|
44
|
+
declare enum SidecarType {
|
|
45
|
+
Slim = 0,
|
|
46
|
+
Extended = 1,
|
|
47
|
+
Provenance = 2
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
declare enum PatchOperation {
|
|
51
|
+
EditPropertyString = 1,
|
|
52
|
+
EditPropertyNumber = 2,
|
|
53
|
+
EditInstanceFieldString = 3,
|
|
54
|
+
EditInstanceFieldNumber = 4,
|
|
55
|
+
EditRelation = 5,
|
|
56
|
+
CreateRecord = 7,
|
|
57
|
+
AddInstance = 8,
|
|
58
|
+
MergeProposal = 9,
|
|
59
|
+
DeleteBridge = 10
|
|
60
|
+
}
|
|
61
|
+
declare enum PatchAction {
|
|
62
|
+
Remove = 0,
|
|
63
|
+
Add = 1
|
|
64
|
+
}
|
|
65
|
+
interface BasePatch {
|
|
66
|
+
operation: PatchOperation;
|
|
67
|
+
objectType: number;
|
|
68
|
+
objectId: bigint;
|
|
69
|
+
langId: number;
|
|
70
|
+
}
|
|
71
|
+
interface EditPropertyNumberObj extends BasePatch {
|
|
72
|
+
operation: PatchOperation.EditPropertyNumber;
|
|
73
|
+
propertyId: number;
|
|
74
|
+
value: number;
|
|
75
|
+
/**
|
|
76
|
+
* 2-bit origin code: 0=unset, 1=AI, 2=human, 3=consensus (see orm.ts's
|
|
77
|
+
* Config.defaultProvenance). Optional because a patch decoded from a
|
|
78
|
+
* pre-provenance on-chain word (WIRE_FORMAT_LEGACY, or any WIDE-format word
|
|
79
|
+
* written before this field existed) has no genuine value to report —
|
|
80
|
+
* those decode with `provenance` absent, not fabricated as 0. A WIDE-format
|
|
81
|
+
* word encoded by the current packPatch always carries an explicit value
|
|
82
|
+
* (0 if the author didn't set one).
|
|
83
|
+
*/
|
|
84
|
+
provenance?: number;
|
|
85
|
+
}
|
|
86
|
+
interface EditPropertyStringObj extends BasePatch {
|
|
87
|
+
operation: PatchOperation.EditPropertyString;
|
|
88
|
+
propertyId: number;
|
|
89
|
+
value: string;
|
|
90
|
+
/** See EditPropertyNumberObj.provenance. */
|
|
91
|
+
provenance?: number;
|
|
92
|
+
}
|
|
93
|
+
interface EditInstanceFieldNumberObj extends BasePatch {
|
|
94
|
+
operation: PatchOperation.EditInstanceFieldNumber;
|
|
95
|
+
instanceIndex: number;
|
|
96
|
+
propertyId: number;
|
|
97
|
+
value: number;
|
|
98
|
+
}
|
|
99
|
+
interface EditInstanceFieldStringObj extends BasePatch {
|
|
100
|
+
operation: PatchOperation.EditInstanceFieldString;
|
|
101
|
+
instanceIndex: number;
|
|
102
|
+
propertyId: number;
|
|
103
|
+
value: string;
|
|
104
|
+
}
|
|
105
|
+
interface EditRelationObj extends BasePatch {
|
|
106
|
+
operation: PatchOperation.EditRelation;
|
|
107
|
+
relationId: number;
|
|
108
|
+
action: PatchAction;
|
|
109
|
+
targetId: bigint;
|
|
110
|
+
}
|
|
111
|
+
interface CreateRecordObj extends BasePatch {
|
|
112
|
+
operation: PatchOperation.CreateRecord;
|
|
113
|
+
objectType: number;
|
|
114
|
+
objectId: bigint;
|
|
115
|
+
langId: number;
|
|
116
|
+
}
|
|
117
|
+
interface AddInstanceObj extends BasePatch {
|
|
118
|
+
operation: PatchOperation.AddInstance;
|
|
119
|
+
objectType: number;
|
|
120
|
+
objectId: bigint;
|
|
121
|
+
langId: number;
|
|
122
|
+
instanceIndex: number;
|
|
123
|
+
}
|
|
124
|
+
interface MergeProposalObj extends BasePatch {
|
|
125
|
+
operation: PatchOperation.MergeProposal;
|
|
126
|
+
original: string;
|
|
127
|
+
destSystem: string;
|
|
128
|
+
relationType: 'equivalentWith' | 'childOf' | 'parentOf';
|
|
129
|
+
targetId: number | string;
|
|
130
|
+
confidence: number;
|
|
131
|
+
}
|
|
132
|
+
interface DeleteBridgeObj extends BasePatch {
|
|
133
|
+
operation: PatchOperation.DeleteBridge;
|
|
134
|
+
original: string;
|
|
135
|
+
destinationSystem: string;
|
|
136
|
+
bridgeTypeToDelete: 'equivalentWith' | 'childOf' | 'parentOf';
|
|
137
|
+
targetTagId: number | bigint | string;
|
|
138
|
+
}
|
|
139
|
+
type AnyPatch = EditPropertyNumberObj | EditPropertyStringObj | EditInstanceFieldNumberObj | EditInstanceFieldStringObj | EditRelationObj | CreateRecordObj | AddInstanceObj | MergeProposalObj | DeleteBridgeObj;
|
|
140
|
+
declare enum ActionOperation {
|
|
141
|
+
Download = 6,
|
|
142
|
+
Visit = 11,
|
|
143
|
+
Rate = 12,
|
|
144
|
+
RatePart = 13,
|
|
145
|
+
Share = 14,
|
|
146
|
+
SharePart = 15
|
|
147
|
+
}
|
|
148
|
+
declare const isActionOperation: (op: number) => op is ActionOperation;
|
|
149
|
+
interface BaseActionPatch {
|
|
150
|
+
operation: ActionOperation;
|
|
151
|
+
objectType: number;
|
|
152
|
+
objectId: bigint;
|
|
153
|
+
ts: number;
|
|
154
|
+
}
|
|
155
|
+
interface VisitActionObj extends BaseActionPatch {
|
|
156
|
+
operation: ActionOperation.Visit;
|
|
157
|
+
}
|
|
158
|
+
interface DownloadActionObj extends BaseActionPatch {
|
|
159
|
+
operation: ActionOperation.Download;
|
|
160
|
+
}
|
|
161
|
+
interface RateActionObj extends BaseActionPatch {
|
|
162
|
+
operation: ActionOperation.Rate;
|
|
163
|
+
rate: number;
|
|
164
|
+
}
|
|
165
|
+
interface RatePartActionObj extends BaseActionPatch {
|
|
166
|
+
operation: ActionOperation.RatePart;
|
|
167
|
+
part: number;
|
|
168
|
+
rate: number;
|
|
169
|
+
}
|
|
170
|
+
interface ShareActionObj extends BaseActionPatch {
|
|
171
|
+
operation: ActionOperation.Share;
|
|
172
|
+
socialMediaId: number;
|
|
173
|
+
}
|
|
174
|
+
interface SharePartActionObj extends BaseActionPatch {
|
|
175
|
+
operation: ActionOperation.SharePart;
|
|
176
|
+
part: number;
|
|
177
|
+
socialMediaId: number;
|
|
178
|
+
}
|
|
179
|
+
type AnyActionPatch = VisitActionObj | DownloadActionObj | RateActionObj | RatePartActionObj | ShareActionObj | SharePartActionObj;
|
|
180
|
+
interface EnumLayout {
|
|
181
|
+
bits: number;
|
|
182
|
+
values: string[];
|
|
183
|
+
}
|
|
184
|
+
interface PropLayout {
|
|
185
|
+
name: string;
|
|
186
|
+
type: 'string' | 'number' | 'boolean' | 'enum';
|
|
187
|
+
bits: number;
|
|
188
|
+
enum?: string;
|
|
189
|
+
}
|
|
190
|
+
interface VersionEntry {
|
|
191
|
+
hash: string;
|
|
192
|
+
enums: Record<string, EnumLayout>;
|
|
193
|
+
props: Record<number, PropLayout>;
|
|
194
|
+
instanceFields: Record<number, number[]>;
|
|
195
|
+
}
|
|
196
|
+
interface VersionsFile {
|
|
197
|
+
current: number;
|
|
198
|
+
versions: Record<number, VersionEntry>;
|
|
199
|
+
}
|
|
200
|
+
interface VersionLayout {
|
|
201
|
+
hash: string;
|
|
202
|
+
enums: Record<string, EnumLayout>;
|
|
203
|
+
props: Record<number, PropLayout>;
|
|
204
|
+
instanceFields: Record<number, number[]>;
|
|
205
|
+
}
|
|
206
|
+
interface EvmPayload {
|
|
207
|
+
version: number;
|
|
208
|
+
patches: bigint[];
|
|
209
|
+
textIndex: number[];
|
|
210
|
+
textData: string[];
|
|
211
|
+
}
|
|
212
|
+
declare const LANG_ID_ENCODE: Record<string, number>;
|
|
213
|
+
declare const LANG_ID_DECODE: Record<number, string>;
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Merges all version delta entries up to and including `version`.
|
|
217
|
+
*
|
|
218
|
+
* WARNING: COUPLING CONTRACT
|
|
219
|
+
* \`resolveLayout\` relies on \`computeVersionDelta\` emitting the FULL \`instanceFields\`
|
|
220
|
+
* array for any model that changed. It blindly overwrites the merged layout with the
|
|
221
|
+
* delta entry's array (\`merged.instanceFields[ot] = [...fields]\`). If future
|
|
222
|
+
* optimizations shrink \`versions.json\` by emitting only newly added fields, this
|
|
223
|
+
* function will silently corrupt the field layout by deleting historical fields.
|
|
224
|
+
*/
|
|
225
|
+
declare function resolveLayout(version: number, versionsFile: VersionsFile): VersionLayout;
|
|
226
|
+
declare function packPatch(patch: AnyPatch, layout: VersionLayout): bigint;
|
|
227
|
+
declare function unpackPatch(packed: bigint, layout: VersionLayout): AnyPatch;
|
|
228
|
+
declare function packActionPatch(patch: AnyActionPatch): bigint;
|
|
229
|
+
declare function unpackActionPatch(packed: bigint): AnyActionPatch;
|
|
230
|
+
declare function patchToEvm(patches: (AnyPatch | AnyActionPatch)[], layout: VersionLayout, version: number): EvmPayload;
|
|
231
|
+
declare function evmToPatch(payload: EvmPayload, versionsFile: VersionsFile): (AnyPatch | AnyActionPatch)[];
|
|
232
|
+
|
|
233
|
+
type Lang = string;
|
|
234
|
+
type uid = bigint;
|
|
235
|
+
/**
|
|
236
|
+
* Canonical bigint<->string boundary for wireIds crossing a surface that
|
|
237
|
+
* can't carry bigint natively — JSON (`JSON.stringify` throws on bigint) and
|
|
238
|
+
* IndexedDB keys (bigint isn't a valid IDB key type). Every such boundary
|
|
239
|
+
* should use these two primitives via its own explicit typed transform
|
|
240
|
+
* function, not a generic JSON reviver/replacer or an inline `.toString()` —
|
|
241
|
+
* see optmized-uid/11-wireId-64bits-refactor.md §3 for why a generic reviver
|
|
242
|
+
* breaks on arrays like `authorIds` (a reviver sees the array index as the
|
|
243
|
+
* key, never the field name).
|
|
244
|
+
*/
|
|
245
|
+
declare const toJsonId: (id: uid) => string;
|
|
246
|
+
declare const fromJsonId: (s: string) => uid;
|
|
247
|
+
interface RecordIdentityCluster {
|
|
248
|
+
sfcuid: string;
|
|
249
|
+
native: string;
|
|
250
|
+
aliases: string[];
|
|
251
|
+
wireId: uid;
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Key used in per-language value maps when a value is language-agnostic
|
|
255
|
+
* (patches with langId 0).
|
|
256
|
+
*/
|
|
257
|
+
declare const LANG_AGNOSTIC: Lang;
|
|
258
|
+
/**
|
|
259
|
+
* One embedded instance (e.g. a PDF variant of a Book). Keys are the
|
|
260
|
+
* instanceField names from the schema; `isDefault` is appended by the
|
|
261
|
+
* sidecar writer and is not an instanceField.
|
|
262
|
+
*/
|
|
263
|
+
type InstanceData = Record<string, string | number | boolean | null>;
|
|
264
|
+
/**
|
|
265
|
+
* V2 in-memory ORM tuple. All value maps are per-language (perLang defaults
|
|
266
|
+
* to true in the V2 schema); language-agnostic values use LANG_AGNOSTIC ("").
|
|
267
|
+
*/
|
|
268
|
+
type CommonOrmJson = [
|
|
269
|
+
uid,
|
|
270
|
+
Map<number, Set<uid>>,
|
|
271
|
+
Map<number, Set<uid>>,
|
|
272
|
+
Map<number, Map<Lang, number>>,
|
|
273
|
+
Map<number, Map<Lang, boolean>>,
|
|
274
|
+
Map<number, Map<Lang, string>>,
|
|
275
|
+
Map<Lang, InstanceData[]>
|
|
276
|
+
];
|
|
277
|
+
/**
|
|
278
|
+
* True JSON-text-safe serialization of CommonOrmJson — every uid slot is
|
|
279
|
+
* decimal-string-encoded (the toJsonId convention above) since bigint isn't
|
|
280
|
+
* JSON-serializable. This is what `Orm.toJSON()` emits, and therefore what
|
|
281
|
+
* `JSON.stringify(someRecord)` actually produces (JSON.stringify calls a
|
|
282
|
+
* `toJSON` method before applying any replacer). It is NOT a
|
|
283
|
+
* structured-clone/postMessage format — `CommonOrmJson` itself already
|
|
284
|
+
* survives structured clone natively (bigint is structured-clone-safe), so
|
|
285
|
+
* there's no separate bigint-native "serialized" form needed for that case.
|
|
286
|
+
*/
|
|
287
|
+
type SerializedCommonOrmJson = [
|
|
288
|
+
string,
|
|
289
|
+
Array<[number, Array<string>]>,
|
|
290
|
+
Array<[number, Array<string>]>,
|
|
291
|
+
Array<[number, Array<[Lang, number]>]>,
|
|
292
|
+
Array<[number, Array<[Lang, boolean]>]>,
|
|
293
|
+
Array<[number, Array<[Lang, string]>]>,
|
|
294
|
+
Array<[Lang, InstanceData[]]>
|
|
295
|
+
];
|
|
296
|
+
type PropertyType = 'string' | 'number' | 'boolean' | 'enum';
|
|
297
|
+
interface BaseLocalOp {
|
|
298
|
+
ts: number;
|
|
299
|
+
action: ActionTypes;
|
|
300
|
+
objectType: number;
|
|
301
|
+
objectId: uid;
|
|
302
|
+
}
|
|
303
|
+
interface RateOp extends BaseLocalOp {
|
|
304
|
+
rate: Rating;
|
|
305
|
+
}
|
|
306
|
+
interface PartOp extends BaseLocalOp {
|
|
307
|
+
part: number;
|
|
308
|
+
}
|
|
309
|
+
interface RatePartOp extends PartOp {
|
|
310
|
+
rate: Rating;
|
|
311
|
+
}
|
|
312
|
+
interface ShareOp extends BaseLocalOp {
|
|
313
|
+
socialMediaId: number;
|
|
314
|
+
}
|
|
315
|
+
interface SharePartOp extends PartOp {
|
|
316
|
+
socialMediaId: number;
|
|
317
|
+
}
|
|
318
|
+
type LocalOp = RateOp | RatePartOp | PartOp | ShareOp | SharePartOp | BaseLocalOp;
|
|
319
|
+
/**
|
|
320
|
+
* Anything the patcher queue can hold: EVM-bound V2 patches (`AnyPatch`,
|
|
321
|
+
* discriminated by `operation`) or local analytics ops (discriminated by `action`).
|
|
322
|
+
* Local delivery metadata is never encoded into a wire patch.
|
|
323
|
+
*/
|
|
324
|
+
type QueueItem = (AnyPatch | LocalOp) & {
|
|
325
|
+
eventId?: string;
|
|
326
|
+
sourceStream?: string;
|
|
327
|
+
provenance?: number;
|
|
328
|
+
};
|
|
329
|
+
declare const isEvmPatch: (item: QueueItem) => item is AnyPatch;
|
|
330
|
+
type SidecarUrls = {
|
|
331
|
+
objectType: number;
|
|
332
|
+
lang: Lang;
|
|
333
|
+
slimUrl?: string;
|
|
334
|
+
extendedUrl?: string;
|
|
335
|
+
provUrl?: string;
|
|
336
|
+
aiUrl?: string;
|
|
337
|
+
};
|
|
338
|
+
type InitPayload = {
|
|
339
|
+
cmd: WorkerCommands.Init;
|
|
340
|
+
payload: {
|
|
341
|
+
/** Flattened sidecar URLs for all selected languages. */
|
|
342
|
+
sidecars: Array<SidecarUrls>;
|
|
343
|
+
selectedLangs: Lang[];
|
|
344
|
+
};
|
|
345
|
+
};
|
|
346
|
+
type SavePatchesPayload = {
|
|
347
|
+
cmd: WorkerCommands.SavePatches;
|
|
348
|
+
payload: {
|
|
349
|
+
username: string;
|
|
350
|
+
patches: Array<QueueItem>;
|
|
351
|
+
};
|
|
352
|
+
};
|
|
353
|
+
type GetRecordPayload = {
|
|
354
|
+
cmd: WorkerCommands.GetRecord;
|
|
355
|
+
payload: {
|
|
356
|
+
objectType: number;
|
|
357
|
+
id: uid;
|
|
358
|
+
creatorUsername?: string;
|
|
359
|
+
};
|
|
360
|
+
};
|
|
361
|
+
type LoadLanguagePayload = {
|
|
362
|
+
cmd: WorkerCommands.LoadLanguage;
|
|
363
|
+
payload: {
|
|
364
|
+
lang: Lang;
|
|
365
|
+
sidecars: Array<SidecarUrls>;
|
|
366
|
+
};
|
|
367
|
+
};
|
|
368
|
+
type WorkerPayload = InitPayload | SavePatchesPayload | GetRecordPayload | LoadLanguagePayload;
|
|
369
|
+
interface IThread {
|
|
370
|
+
sendRequest(payload: WorkerPayload, transferables?: Array<any>): Promise<any>;
|
|
371
|
+
}
|
|
372
|
+
type StatSummary = {
|
|
373
|
+
visits: Array<number>;
|
|
374
|
+
rating: Rating;
|
|
375
|
+
socialMediaId: Array<number>;
|
|
376
|
+
downloads: Array<number>;
|
|
377
|
+
parts: {
|
|
378
|
+
[partId: string]: {
|
|
379
|
+
rating: Rating;
|
|
380
|
+
socialMediaId: Array<number>;
|
|
381
|
+
visits: Array<number>;
|
|
382
|
+
};
|
|
383
|
+
};
|
|
384
|
+
};
|
|
385
|
+
interface BookData {
|
|
386
|
+
fileId: string;
|
|
387
|
+
parsed: boolean;
|
|
388
|
+
author: string;
|
|
389
|
+
title: string;
|
|
390
|
+
dimensions: Array<{
|
|
391
|
+
width: number;
|
|
392
|
+
height: number;
|
|
393
|
+
} | null>;
|
|
394
|
+
}
|
|
395
|
+
interface FileRecord {
|
|
396
|
+
id: string;
|
|
397
|
+
creationTime: number;
|
|
398
|
+
sizeKb: number;
|
|
399
|
+
content: Uint8Array;
|
|
400
|
+
local: boolean;
|
|
401
|
+
}
|
|
402
|
+
declare enum BridgeRelation {
|
|
403
|
+
EquivalentWith = 0,
|
|
404
|
+
ChildOf = 1,
|
|
405
|
+
ParentOf = 2
|
|
406
|
+
}
|
|
407
|
+
interface BridgeLink {
|
|
408
|
+
id: number | string;
|
|
409
|
+
confidence: number;
|
|
410
|
+
}
|
|
411
|
+
interface BridgeSystemConversions {
|
|
412
|
+
equivalentWith?: BridgeLink[];
|
|
413
|
+
childOf?: BridgeLink[];
|
|
414
|
+
parentOf?: BridgeLink[];
|
|
415
|
+
}
|
|
416
|
+
interface BridgeDefinition {
|
|
417
|
+
original: string;
|
|
418
|
+
conversions?: Record<string, BridgeSystemConversions>;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
/**
|
|
422
|
+
* V2 model definition — the shape of the enriched JSON files in
|
|
423
|
+
* `@the_library/db_schemas/generated-src/*.json` (frozen numeric IDs).
|
|
424
|
+
*/
|
|
425
|
+
interface SchemaProp {
|
|
426
|
+
name: string;
|
|
427
|
+
type: PropertyType;
|
|
428
|
+
source: 'slim' | 'extended';
|
|
429
|
+
propId: number;
|
|
430
|
+
enum?: string;
|
|
431
|
+
bits?: number;
|
|
432
|
+
nullable?: boolean;
|
|
433
|
+
}
|
|
434
|
+
interface SchemaInstanceField {
|
|
435
|
+
name: string;
|
|
436
|
+
type: PropertyType;
|
|
437
|
+
propId: number;
|
|
438
|
+
enum?: string;
|
|
439
|
+
bits?: number;
|
|
440
|
+
nullable?: boolean;
|
|
441
|
+
identityComponent?: boolean;
|
|
442
|
+
source?: 'slim' | 'extended';
|
|
443
|
+
}
|
|
444
|
+
interface SchemaRelation {
|
|
445
|
+
name: string;
|
|
446
|
+
targetType: string;
|
|
447
|
+
direction: 'has' | 'in';
|
|
448
|
+
cardinality: '1to1' | '1toN';
|
|
449
|
+
inverted: string;
|
|
450
|
+
relationId: number;
|
|
451
|
+
}
|
|
452
|
+
/**
|
|
453
|
+
* Cols field name for a `has`-relation tail. The `authors` relation keeps its
|
|
454
|
+
* historical `authorIds` name for back-compat; every other relation uses its
|
|
455
|
+
* schema name directly (e.g. Tag.tags, Tag.books). Single source of truth for
|
|
456
|
+
* both the codegen (schemaGenerator.ts, which emits `${relationColName(rel)}`
|
|
457
|
+
* as the ExtendedCols field name) and the runtime reader (orm.ts's
|
|
458
|
+
* mergeExtended, which must look up that same field name on the incoming cols
|
|
459
|
+
* object) — they must never drift apart.
|
|
460
|
+
*/
|
|
461
|
+
declare const relationColName: (rel: SchemaRelation) => string;
|
|
462
|
+
interface SchemaIndex {
|
|
463
|
+
name: string;
|
|
464
|
+
keys: string[];
|
|
465
|
+
linkToUidStrategy?: boolean;
|
|
466
|
+
classifier?: {
|
|
467
|
+
type: 'prefix';
|
|
468
|
+
separator: string;
|
|
469
|
+
fallback: string;
|
|
470
|
+
customMappings?: Record<string, string>;
|
|
471
|
+
};
|
|
472
|
+
}
|
|
473
|
+
interface ModelDefinition {
|
|
474
|
+
name: string;
|
|
475
|
+
typePrefix: string;
|
|
476
|
+
objectId: number;
|
|
477
|
+
multipleInstances: boolean;
|
|
478
|
+
uidStrategy?: string | string[];
|
|
479
|
+
instanceUidStrategy?: string | string[];
|
|
480
|
+
isPrivate?: boolean;
|
|
481
|
+
standardPks?: Record<string, string>;
|
|
482
|
+
props: SchemaProp[];
|
|
483
|
+
instanceFields: SchemaInstanceField[];
|
|
484
|
+
relations: SchemaRelation[];
|
|
485
|
+
indexes?: SchemaIndex[];
|
|
486
|
+
}
|
|
487
|
+
declare class SchemaRegistry {
|
|
488
|
+
private static instance;
|
|
489
|
+
private schemas;
|
|
490
|
+
private byName;
|
|
491
|
+
private constructor();
|
|
492
|
+
static getInstance(): SchemaRegistry;
|
|
493
|
+
register(schema: ModelDefinition): void;
|
|
494
|
+
get(id: number): ModelDefinition;
|
|
495
|
+
/** Lookup by model name (relation targetType resolution). */
|
|
496
|
+
getByName(name: string): ModelDefinition | undefined;
|
|
497
|
+
clear(): void;
|
|
498
|
+
}
|
|
499
|
+
declare const Registry: SchemaRegistry;
|
|
500
|
+
|
|
501
|
+
/**
|
|
502
|
+
* Replay/baking metadata: real per-language "was this actually set" state,
|
|
503
|
+
* carried alongside the corpus's flattened display values so both the corpus
|
|
504
|
+
* baker (`@the_library/corpus-builder`) and worker/browser LRU rehydration
|
|
505
|
+
* (`orm.ts`'s `mergeProv`, `reconstructRecord.ts`) can reuse the exact same
|
|
506
|
+
* fallback-resolution rules the live ORM already implements for setters/
|
|
507
|
+
* getters (`resolveLangValue` in orm.ts), instead of each reimplementing an
|
|
508
|
+
* approximation of it.
|
|
509
|
+
*
|
|
510
|
+
* BACKGROUND — why this exists at all (2026-09-08, findings #5/#6 in
|
|
511
|
+
* reviews/2026-09-07/assessment.md, and the follow-up probe documented in
|
|
512
|
+
* reviews/2026-09-07/implementation-p1-5-through-p1-6.md):
|
|
513
|
+
*
|
|
514
|
+
* The published corpus (`BookInput`/`TagInput`/`PersonInput`, see
|
|
515
|
+
* generated-src/*.ts) stores exactly ONE flattened value per property per
|
|
516
|
+
* per-language corpus build (e.g. `book.title` in the `fra` corpus is a
|
|
517
|
+
* single string). The corpus baker (`apply-patches-plain.ts`) runs
|
|
518
|
+
* incrementally: each build call receives only the patches accumulated since
|
|
519
|
+
* the last build (`data/patches.jsonl` is truncated after every successful
|
|
520
|
+
* publish — see apps/book-manager/CLAUDE.md's "Publishing the models_v2
|
|
521
|
+
* corpus" section), plus the PREVIOUS build's already-flattened output as its
|
|
522
|
+
* starting point. That flattened single value is fundamentally ambiguous:
|
|
523
|
+
* given `book.title === 'Arbre'` for the `fra` build, there is no way to tell
|
|
524
|
+
* whether "Arbre" is a genuine, deliberately-authored French title, or
|
|
525
|
+
* whether it is itself a fallback value that leaked in from an English edit
|
|
526
|
+
* because French had never been set yet. The same ambiguity applies to
|
|
527
|
+
* `false`/`0`/`""`: a nullable field's `""` might mean "explicitly cleared"
|
|
528
|
+
* or "never set"; a non-nullable boolean/number's `false`/`0` is completely
|
|
529
|
+
* indistinguishable from "never set" once flattened.
|
|
530
|
+
*
|
|
531
|
+
* A first fix attempt tried to paper over this with a heuristic (checking
|
|
532
|
+
* whether the flattened value was "nullable and non-empty" before allowing a
|
|
533
|
+
* fallback edit to overwrite it). That heuristic could not protect
|
|
534
|
+
* non-nullable fields (`safe`, `deleted`, every `QualityScore`) at all, and
|
|
535
|
+
* could not tell a real translation from a previously-baked fallback either
|
|
536
|
+
* — see the git history of apply-patches-plain.ts around that date for what
|
|
537
|
+
* NOT to reintroduce.
|
|
538
|
+
*
|
|
539
|
+
* The actual fix: export the ORM's REAL internal per-(propId, lang) storage
|
|
540
|
+
* (`Orm._stringValues`/`_numberValues`/`_boolValues`, via `Orm.propertySlots()`)
|
|
541
|
+
* as a small, JSON-serializable side-channel, persist it in the corpus's
|
|
542
|
+
* existing binary "prov" sidecar tier (see serializer.ts's
|
|
543
|
+
* `commonSerializeProv`/`commonDeserializeProv` and this file's
|
|
544
|
+
* `REPLAY_METADATA_COLUMNS`), and restore it into a real headless `Orm`
|
|
545
|
+
* instance before each incremental bake (`apply-patches-plain.ts`). Because
|
|
546
|
+
* `Map.has(lang)` is a real presence check independent of the stored value,
|
|
547
|
+
* `false`/`0`/`""` are now indistinguishable from nothing ONLY when they
|
|
548
|
+
* really are nothing — solving both the cross-language-overwrite bug and the
|
|
549
|
+
* non-nullable-field blind spot structurally, not via a guess.
|
|
550
|
+
*
|
|
551
|
+
* Compatibility limit (documented in implementation-p1-5-through-p1-6.md):
|
|
552
|
+
* a corpus built BEFORE this change has no slots at all. The first time such
|
|
553
|
+
* a record is baked under the new code (`apply-patches-plain.ts`'s
|
|
554
|
+
* `!fresh.has(rec)` bootstrap branch), every one of its current non-null
|
|
555
|
+
* flattened values is conservatively treated as an explicit slot for the
|
|
556
|
+
* CURRENT build's language — including any prior English-fallback-into-French
|
|
557
|
+
* corruption from before this fix existed. This stops the bug from
|
|
558
|
+
* recurring; it cannot retroactively repair history that's already wrong.
|
|
559
|
+
* Only a rebuild from the original patch log (not the already-flattened
|
|
560
|
+
* corpus) can recover genuinely lost translation intent.
|
|
561
|
+
*/
|
|
562
|
+
type PropertySlots = Array<[number, Array<[Lang, string | number | boolean]>]>;
|
|
563
|
+
/**
|
|
564
|
+
* Sidecar column names (as written into the binary "prov" tier — see
|
|
565
|
+
* `serializer.ts`) vs. the in-memory field names used on plain
|
|
566
|
+
* `BookInput`/`TagInput`/`PersonInput` objects while baking. Deliberately
|
|
567
|
+
* DOUBLE-underscored on the wire (`__propertySlots`/`__instanceRemaps`) to
|
|
568
|
+
* keep them visually distinct from the existing single-underscore `_prov`/
|
|
569
|
+
* `_createSeq` bookkeeping fields these plain objects already carry
|
|
570
|
+
* informally (neither of those is declared in the generated `BookInput`
|
|
571
|
+
* etc. interfaces either — this follows the same, pre-existing convention).
|
|
572
|
+
*
|
|
573
|
+
* These are genuinely NEW named columns in the prov sidecar's binary format,
|
|
574
|
+
* not a new sidecar file/tier and not a `SIDECAR_FORMAT_VERSION` bump: the
|
|
575
|
+
* sidecar column format is self-describing (each column writes its own type
|
|
576
|
+
* byte + name string ahead of its data — see enriched-index.ts's
|
|
577
|
+
* `writeSidecar`/`parseSidecar`), so an old reader parsing a new sidecar
|
|
578
|
+
* still parses these columns without error (it just won't know what to do
|
|
579
|
+
* with the data), and a new reader parsing an old sidecar (without these
|
|
580
|
+
* columns) simply sees them as absent — see `commonDeserializeProv`'s
|
|
581
|
+
* `REPLAY_METADATA_COLUMNS` branch in serializer.ts.
|
|
582
|
+
*/
|
|
583
|
+
declare const PROPERTY_SLOTS_COLUMN = "__propertySlots";
|
|
584
|
+
declare const INSTANCE_REMAPS_COLUMN = "__instanceRemaps";
|
|
585
|
+
/** [sidecar column name, in-memory field name] pairs — see the doc comment above. */
|
|
586
|
+
declare const REPLAY_METADATA_COLUMNS: readonly [readonly ["__propertySlots", "_propertySlots"], readonly ["__instanceRemaps", "_instanceRemaps"]];
|
|
587
|
+
/** Base properties (propId 0-7) plus a schema's own `props`, keyed by propId
|
|
588
|
+
* so a schema can override a base entry if it ever needs to (Map dedup keeps
|
|
589
|
+
* the last write per propId — schema.props is spread after baseProperties). */
|
|
590
|
+
declare function scalarProperties(schema: ModelDefinition): SchemaProp[];
|
|
591
|
+
|
|
592
|
+
declare enum LifecycleStatus {
|
|
593
|
+
Provisional = 0,
|
|
594
|
+
Submitted = 1,
|
|
595
|
+
CommunityPending = 2,
|
|
596
|
+
Canonical = 3
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
/** Called after every StatsStore change (a local action, or restored rows added). */
|
|
600
|
+
declare const subscribeStats: (listener: () => void) => (() => void);
|
|
601
|
+
declare const PopulateStatsStore: (operations: Array<LocalOp>) => void;
|
|
602
|
+
declare const DownloadsByType: (objectType: number) => Array<uid>;
|
|
603
|
+
declare const VisitsByType: (objectType: number) => Array<uid>;
|
|
604
|
+
declare const FavoritesByTypes: (objectType: number) => Array<{
|
|
605
|
+
id: uid;
|
|
606
|
+
nbVisits: number;
|
|
607
|
+
rating: Rating;
|
|
608
|
+
}>;
|
|
609
|
+
declare class Stats {
|
|
610
|
+
private objectId;
|
|
611
|
+
protected objectType: number;
|
|
612
|
+
constructor(objectId: uid, objectType: number);
|
|
613
|
+
favoriteParts(): Array<{
|
|
614
|
+
partId: number;
|
|
615
|
+
nbVisits: number;
|
|
616
|
+
rating: Rating;
|
|
617
|
+
}>;
|
|
618
|
+
check(): void;
|
|
619
|
+
visit(): void;
|
|
620
|
+
download(): void;
|
|
621
|
+
get rating(): Rating;
|
|
622
|
+
set rating(rating: Rating);
|
|
623
|
+
share(socialMediaId: number): void;
|
|
624
|
+
ratePart(partId: number, rating: Rating): void;
|
|
625
|
+
visitPart(partId: number): void;
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
interface UidFactory {
|
|
629
|
+
next(): Promise<{
|
|
630
|
+
wireId: bigint;
|
|
631
|
+
}>;
|
|
632
|
+
isUserCreated(wireId: bigint): boolean;
|
|
633
|
+
}
|
|
634
|
+
/**
|
|
635
|
+
* Bit 63 is the user-created scope flag (see optmized-uid/11-wireId-64bits-refactor.md §0).
|
|
636
|
+
* scope(1) + random(63). 0 = canonical, 1 = user-created.
|
|
637
|
+
*/
|
|
638
|
+
declare function isUserCreated(wireId: bigint | number | string): boolean;
|
|
639
|
+
declare class CryptoRandomUidFactory implements UidFactory {
|
|
640
|
+
next(): Promise<{
|
|
641
|
+
wireId: bigint;
|
|
642
|
+
}>;
|
|
643
|
+
isUserCreated(wireId: bigint): boolean;
|
|
644
|
+
}
|
|
645
|
+
declare function loadOrInitUidFactory(db: IDBDatabase): Promise<UidFactory>;
|
|
646
|
+
|
|
647
|
+
declare const Config: {
|
|
648
|
+
readonly userLang: Lang;
|
|
649
|
+
readonly commonLang: Lang;
|
|
650
|
+
readonly defaultProvenance: number | undefined;
|
|
651
|
+
readonly loadAiSidecars: boolean;
|
|
652
|
+
};
|
|
653
|
+
declare function setDefaultLanguage(lang: Lang): void;
|
|
654
|
+
declare function setDefaultProvenance(provenance: number): void;
|
|
655
|
+
declare function setLoadAiSidecars(enabled: boolean): void;
|
|
656
|
+
declare const PROVENANCE_UNSET = 0;
|
|
657
|
+
declare const PROVENANCE_AI = 1;
|
|
658
|
+
declare const PROVENANCE_MANUAL_LOCAL = 2;
|
|
659
|
+
declare const PROVENANCE_CONSENSUS = 3;
|
|
660
|
+
declare const TITLE_PROP = 0;
|
|
661
|
+
declare const DESCRIPTION_PROP = 1;
|
|
662
|
+
declare const ORIGINAL_LANG_PROP = 2;
|
|
663
|
+
declare const AGE_GRADE_BAND_PROP = 3;
|
|
664
|
+
declare const PREVIEW_TX_ID_PROP = 4;
|
|
665
|
+
declare const SAFE_PROP = 5;
|
|
666
|
+
declare const DELETED_PROP = 6;
|
|
667
|
+
declare const LIFECYCLE_STATUS_PROP = 7;
|
|
668
|
+
|
|
669
|
+
/** Decimal-string-encodes every uid — see SerializedCommonOrmJson's own doc comment for why. */
|
|
670
|
+
declare function serializeMapOfSets(map: Map<number, Set<uid>>): Array<[number, Array<string>]>;
|
|
671
|
+
declare function serializeMapOfMaps<V>(mapOfMaps: Map<number, Map<Lang, V>>): Array<[number, Array<[Lang, V]>]>;
|
|
672
|
+
declare const inflateOrmJson: (v2: SerializedCommonOrmJson) => CommonOrmJson;
|
|
673
|
+
interface DeepCollectOptions {
|
|
674
|
+
/** Include deleted/unsafe records — both as final result items and as
|
|
675
|
+
* pass-through nodes during traversal. Default false: a deleted/unsafe
|
|
676
|
+
* node discovered via the hierarchy or a bridge is a dead end (neither
|
|
677
|
+
* its own contributions nor anything beyond it is included). The
|
|
678
|
+
* query's own starting record is exempt from this — it is always
|
|
679
|
+
* processed regardless of its own deleted/safe flags, since the caller
|
|
680
|
+
* explicitly chose it. */
|
|
681
|
+
includeDeleted?: boolean;
|
|
682
|
+
/** Which BridgeRelation types to follow when expanding across bridges.
|
|
683
|
+
* Default [EquivalentWith, ParentOf] — "broader absorbs narrower", the
|
|
684
|
+
* same rule the has-direction hierarchy relation already follows.
|
|
685
|
+
* ChildOf points to something BROADER than the caller and is excluded
|
|
686
|
+
* by default (following it would balloon every leaf query to include
|
|
687
|
+
* an entire foreign classification system) — pass it explicitly to
|
|
688
|
+
* opt in. Pass [] to disable bridge-following entirely. */
|
|
689
|
+
bridgeTypes?: BridgeRelation[];
|
|
690
|
+
}
|
|
691
|
+
declare class Orm extends Stats {
|
|
692
|
+
/** Persisted delivery boundary already included by worker reconstruction. */
|
|
693
|
+
hydratedThrough: number;
|
|
694
|
+
readonly _id: uid;
|
|
695
|
+
protected _boolValues: Map<number, Map<string, boolean>>;
|
|
696
|
+
protected _stringValues: Map<number, Map<string, string>>;
|
|
697
|
+
protected _numberValues: Map<number, Map<string, number>>;
|
|
698
|
+
protected _has: Map<number, Set<bigint>>;
|
|
699
|
+
protected _in: Map<number, Set<bigint>>;
|
|
700
|
+
/** lang -> instance array (BookInstanceData structs, not ORM objects). */
|
|
701
|
+
protected _instances: Map<string, InstanceData[]>;
|
|
702
|
+
/** lang -> propId -> provenance code (2-bit: unset/AI/human/consensus). */
|
|
703
|
+
protected _provenance: Map<string, Map<number, number>>;
|
|
704
|
+
protected _aiResults: Map<string, Map<string, Map<string, Set<{
|
|
705
|
+
ts: number;
|
|
706
|
+
value: any;
|
|
707
|
+
format: string;
|
|
708
|
+
}>>>>;
|
|
709
|
+
/** Bridges to other taxonomy systems */
|
|
710
|
+
bridges?: BridgeDefinition;
|
|
711
|
+
schema: ModelDefinition;
|
|
712
|
+
/**
|
|
713
|
+
* Safe relation accessor for generated model getters. For each relation ID:
|
|
714
|
+
* - If the target record is resident in the LRU cache, it is loaded and included.
|
|
715
|
+
* - If the target record is missing (never loaded, evicted, or a stale sidecar
|
|
716
|
+
* reference), a detailed console warning is emitted and the ID is skipped.
|
|
717
|
+
* The application never crashes from an unresolved relation.
|
|
718
|
+
*
|
|
719
|
+
* Warning format:
|
|
720
|
+
* [ORM] Tag with Id=123 and name="General" has a relationship not met:
|
|
721
|
+
* tags to Id=4718593. With id=4718593 not defined.
|
|
722
|
+
*
|
|
723
|
+
* @param owner The record that owns the relation (used for the log message).
|
|
724
|
+
* @param ids The set of target IDs stored in the relation.
|
|
725
|
+
* @param checker `ModelClass.Has` — returns true when the record is in cache.
|
|
726
|
+
* @param loader `ModelClass.Load` — retrieves the record from cache.
|
|
727
|
+
* @param relationName Human-readable relation name, e.g. `"tags"` or `"inTags"`.
|
|
728
|
+
*/
|
|
729
|
+
protected static _safeRelation<T>(owner: Orm, ids: uid[], checker: (id: uid) => boolean, loader: (id: uid) => T, relationName: string): T[];
|
|
730
|
+
static createNewRequest(id: uid): CommonOrmJson;
|
|
731
|
+
static createNewRecord<T extends Orm>(this: {
|
|
732
|
+
new (json: any, creatorUsername?: string): T;
|
|
733
|
+
type: number;
|
|
734
|
+
}, uidFactory: UidFactory, creatorUsername: string): Promise<T>;
|
|
735
|
+
protected _creatorUsername?: string;
|
|
736
|
+
get creatorUsername(): string;
|
|
737
|
+
constructor(objectType: number, json: CommonOrmJson | SerializedCommonOrmJson, creatorUsername?: string);
|
|
738
|
+
/**
|
|
739
|
+
* `(user:objectId:langId:originalIndex) -> realIndex` pairs, produced by
|
|
740
|
+
* `patchContext.ts`'s `resolveAddInstanceConflict` whenever an incoming
|
|
741
|
+
* `AddInstance` collides with an index another author/device already
|
|
742
|
+
* populated with a genuinely different edition (different `downloadTxId`
|
|
743
|
+
* etc. — see `areInstancesEqual`). Kept as a plain array of tuples, not a
|
|
744
|
+
* `Map`, purely so it round-trips through `JSON.stringify`/`JSON.parse`
|
|
745
|
+
* unchanged for persistence (a `Map` doesn't survive that). Persisted two
|
|
746
|
+
* ways, both consumed the same way:
|
|
747
|
+
* - Live app: `patchContext.ts`'s `InstanceRemapStore` (backed by an
|
|
748
|
+
* IndexedDB `instanceRemaps` object store — see
|
|
749
|
+
* apps/book-manager/specifications/done/record_creation_flow_v2.md
|
|
750
|
+
* §3.3) durably remembers a remap so a device's LATER patches
|
|
751
|
+
* addressed to the old index get silently redirected.
|
|
752
|
+
* - Corpus baking / worker rehydration: this field itself is the
|
|
753
|
+
* durable copy, serialized into the `__instanceRemaps` sidecar column
|
|
754
|
+
* (see propertySlots.ts) so a remap made during one incremental
|
|
755
|
+
* corpus build survives into the next one, even though
|
|
756
|
+
* `data/patches.jsonl` (the source patches) is cleared after every
|
|
757
|
+
* build. Without this, a field-only edit in a LATER build that still
|
|
758
|
+
* referenced the pre-remap index would silently corrupt whichever
|
|
759
|
+
* edition now legitimately occupies that slot — this is exactly what
|
|
760
|
+
* reviews/2026-09-07/implementation-p1-5-through-p1-6.md's "a remap
|
|
761
|
+
* was lost after binary bake/reload" regression test guards against.
|
|
762
|
+
* - `patchContext.ts`'s remap lookup checks BOTH sources (live
|
|
763
|
+
* `instanceRemapStore` first, then this field) so a corpus-restored
|
|
764
|
+
* mapping can inform live replay when local IndexedDB has none yet.
|
|
765
|
+
*/
|
|
766
|
+
instanceRemaps: Array<[string, number]>;
|
|
767
|
+
/**
|
|
768
|
+
* Export the REAL per-(propId, lang) storage — not resolved/flattened
|
|
769
|
+
* values — as a JSON-serializable array. This is the read side of the
|
|
770
|
+
* property-slots mechanism documented in propertySlots.ts: it lets a
|
|
771
|
+
* caller (the corpus baker, or worker rehydration via `mergeProv`)
|
|
772
|
+
* persist "which languages actually have an explicit value for this
|
|
773
|
+
* property" across a serialize/deserialize round trip, so a later
|
|
774
|
+
* `restorePropertySlots()` call can reconstruct a record whose
|
|
775
|
+
* `resolveLangValue`-based fallback behaves identically to a record that
|
|
776
|
+
* was never detached at all.
|
|
777
|
+
*/
|
|
778
|
+
propertySlots(): PropertySlots;
|
|
779
|
+
/**
|
|
780
|
+
* Restore real per-language property state (the inverse of
|
|
781
|
+
* `propertySlots()`), for a headless/detached `Orm` instance that has no
|
|
782
|
+
* other way to acquire it (the corpus baker constructs one from scratch
|
|
783
|
+
* for every record it bakes — see apply-patches-plain.ts).
|
|
784
|
+
*
|
|
785
|
+
* `scope` exists because the corpus baker's restore is asymmetric: for
|
|
786
|
+
* the language it is CURRENTLY building (e.g. baking the `fra` corpus),
|
|
787
|
+
* the persisted `fra` slots must be treated as the complete, authoritative
|
|
788
|
+
* truth for that language — anything not explicitly there really is
|
|
789
|
+
* unset. But OTHER languages' slots (e.g. `eng`) are only useful as
|
|
790
|
+
* fallback data if `fra` turns out to have nothing at all for a given
|
|
791
|
+
* property; they must not silently overwrite anything already restored
|
|
792
|
+
* for the target language. `scope === undefined` is the simpler
|
|
793
|
+
* unscoped case (restoring a complete detached snapshot with no
|
|
794
|
+
* asymmetry, e.g. worker rehydration in `mergeProv`) and clears
|
|
795
|
+
* everything first. With a `scope`, only that language's existing slots
|
|
796
|
+
* are cleared before restoring (so a stale `fra` value from a PRIOR
|
|
797
|
+
* build doesn't linger if bootstrapping fresh state), and the
|
|
798
|
+
* `!values.get(id)?.has(lang)` check on the fallback path guarantees an
|
|
799
|
+
* already-restored `scope` value is never clobbered by another
|
|
800
|
+
* language's slot processed later in the same `slots` array.
|
|
801
|
+
*
|
|
802
|
+
* Why this can't be approximated by checking whether the corpus's
|
|
803
|
+
* flattened value is falsy/empty: see propertySlots.ts's module doc —
|
|
804
|
+
* `false`/`0`/`""` are legitimate explicit values that a heuristic
|
|
805
|
+
* cannot tell apart from "never set". Only replaying the real slots data
|
|
806
|
+
* (a genuine Map keyed by language) preserves that distinction.
|
|
807
|
+
*/
|
|
808
|
+
restorePropertySlots(slots: PropertySlots, scope?: Lang): void;
|
|
809
|
+
/** Complete worker hydration state; unlike toJSON, includes auxiliary tiers. */
|
|
810
|
+
snapshot(): {
|
|
811
|
+
json: SerializedCommonOrmJson;
|
|
812
|
+
instanceRemaps: [string, number][];
|
|
813
|
+
patchOrder: number;
|
|
814
|
+
provenance: Map<string, Map<number, number>>;
|
|
815
|
+
bridges: BridgeDefinition | undefined;
|
|
816
|
+
ai: Map<string, Map<string, Map<string, Set<{
|
|
817
|
+
ts: number;
|
|
818
|
+
value: any;
|
|
819
|
+
format: string;
|
|
820
|
+
}>>>>;
|
|
821
|
+
};
|
|
822
|
+
/** Replace materialized state in place so existing UI references remain valid. */
|
|
823
|
+
replaceSnapshot(state: ReturnType<Orm['snapshot']>): void;
|
|
824
|
+
restoreSnapshot(state: ReturnType<Orm['snapshot']>): void;
|
|
825
|
+
toJSON(): SerializedCommonOrmJson;
|
|
826
|
+
/** Raw cross-language view: company -> model -> lang -> results. */
|
|
827
|
+
getAiResultsAllLangs(): Map<string, Map<string, Map<Lang, Set<{
|
|
828
|
+
ts: number;
|
|
829
|
+
value: any;
|
|
830
|
+
format: string;
|
|
831
|
+
}>>>>;
|
|
832
|
+
/** Per-language view: company -> model -> results, resolved for `lang`
|
|
833
|
+
* (falls back to the session's default language when omitted/null). */
|
|
834
|
+
getAiResults(lang?: Lang | null): Map<string, Map<string, Set<{
|
|
835
|
+
ts: number;
|
|
836
|
+
value: any;
|
|
837
|
+
format: string;
|
|
838
|
+
}>>>;
|
|
839
|
+
/** AI results are per-language: the same record can carry a different assessment per translation. */
|
|
840
|
+
attachAiResult(company: string, modelName: string, lang: Lang, result: any): void;
|
|
841
|
+
get id(): uid;
|
|
842
|
+
protected langOf(langId: number): Lang;
|
|
843
|
+
protected langIdOf(lang?: Lang): number;
|
|
844
|
+
getLoadedLanguages(): Lang[];
|
|
845
|
+
/**
|
|
846
|
+
* Get the uidStrategy array defined in this model's schema.
|
|
847
|
+
* Used to determine which classification systems are supported.
|
|
848
|
+
*/
|
|
849
|
+
protected getUidStrategies(): string[];
|
|
850
|
+
/**
|
|
851
|
+
* Detect which classification system (uidStrategy) this record belongs to.
|
|
852
|
+
* Works by checking which notation/classification fields are populated.
|
|
853
|
+
*
|
|
854
|
+
* Field name mapping uses a convention: "lcc" -> "lccNotation" or special
|
|
855
|
+
* names like "lcc" -> "locCallNumber" for Book. The mapping is determined
|
|
856
|
+
* by the MODEL_CLASSIFICATION_FIELD_MAP in classification-utils.
|
|
857
|
+
*
|
|
858
|
+
* @param fieldMap Optional override mapping of strategy -> field name
|
|
859
|
+
* @returns The detected strategy, or 'unclassified' if none found
|
|
860
|
+
*/
|
|
861
|
+
getClassificationType(fieldMap?: Record<string, string>): string;
|
|
862
|
+
/**
|
|
863
|
+
* Get the default field name mapping for this model's classification systems.
|
|
864
|
+
* Override in subclasses or provide via fieldMap parameter if needed.
|
|
865
|
+
*
|
|
866
|
+
* Default convention: strategy "X" maps to field "xNotation" (e.g., "lcc" -> "lccNotation")
|
|
867
|
+
*/
|
|
868
|
+
protected getDefaultClassificationFieldMap(): Record<string, string>;
|
|
869
|
+
get title(): string;
|
|
870
|
+
set title(value: string);
|
|
871
|
+
getTitle(lang: Lang): string;
|
|
872
|
+
setTitle(value: string, lang: Lang): void;
|
|
873
|
+
get description(): string;
|
|
874
|
+
set description(value: string);
|
|
875
|
+
getDescription(lang: Lang): string;
|
|
876
|
+
setDescription(value: string, lang: Lang): void;
|
|
877
|
+
get originalLang(): string;
|
|
878
|
+
set originalLang(value: string);
|
|
879
|
+
getOriginalLang(lang: Lang): string;
|
|
880
|
+
setOriginalLang(value: string, lang: Lang): void;
|
|
881
|
+
get ageGradeBand(): number;
|
|
882
|
+
set ageGradeBand(value: number);
|
|
883
|
+
get previewTxId(): string;
|
|
884
|
+
set previewTxId(value: string);
|
|
885
|
+
get safe(): boolean;
|
|
886
|
+
set safe(value: boolean);
|
|
887
|
+
get deleted(): boolean;
|
|
888
|
+
set deleted(value: boolean);
|
|
889
|
+
get lifecycleStatus(): LifecycleStatus;
|
|
890
|
+
set lifecycleStatus(value: LifecycleStatus);
|
|
891
|
+
protected dispatchString(propertyId: number, value: string, lang?: Lang): void;
|
|
892
|
+
protected dispatchNumber(propertyId: number, value: number, lang?: Lang): void;
|
|
893
|
+
protected dispatchRelation(relationId: number, action: PatchAction, targetId: uid): void;
|
|
894
|
+
/**
|
|
895
|
+
* Raw in-memory relation mutation: no patch is emitted. Used by the
|
|
896
|
+
* generic inverse propagation in patch() and by generated in-side
|
|
897
|
+
* relation helpers. Idempotent (Set semantics).
|
|
898
|
+
*/
|
|
899
|
+
protected applyRelationRaw(direction: 'has' | 'in', relationId: number, action: PatchAction, targetId: uid, effects?: boolean): void;
|
|
900
|
+
/**
|
|
901
|
+
* Bulk-restores the inverse (`in`) edges implied by this record's forward
|
|
902
|
+
* (`has`) relations onto their target records. The sidecar serializes only
|
|
903
|
+
* the `has` direction (§3.7.1); `mergeExtended` fills `_has`, but the inverse
|
|
904
|
+
* side (`Person.authorOf`, `Tag.inTags`, …) stays empty until this runs.
|
|
905
|
+
*
|
|
906
|
+
* No patch emitted, no reactivity fired (bulk boot path). Idempotent (Set
|
|
907
|
+
* add). Targets must already be materialized — call after a full
|
|
908
|
+
* `hydrateAll` pass (see `rebuildInverseRelations`).
|
|
909
|
+
*/
|
|
910
|
+
restoreInverses(): void;
|
|
911
|
+
/**
|
|
912
|
+
* Looks up an existing child of the `has`-side relation `relationId`
|
|
913
|
+
* whose title (base prop 0) matches `title` after trim + case-fold.
|
|
914
|
+
* Children not materialized in the LRU are skipped — same tolerance as
|
|
915
|
+
* `_safeRelation`. Returns null when no materialized child matches.
|
|
916
|
+
*/
|
|
917
|
+
findChildByTitle(relationId: number, title: string): Orm | null;
|
|
918
|
+
/**
|
|
919
|
+
* Re-hydrates any children of `relationId` evicted from the LRU cache.
|
|
920
|
+
* Without this, `findChildByTitle` silently skips evicted-but-real
|
|
921
|
+
* children (it can only see what's resident), so `getOrCreateChildByTitle`
|
|
922
|
+
* would mint a duplicate instead of finding the existing match — the
|
|
923
|
+
* eviction-driven dup-tag bug. A no-op if the target class was never
|
|
924
|
+
* registered (registerModelClass runs at generated-module load) or
|
|
925
|
+
* nothing is actually missing.
|
|
926
|
+
*/
|
|
927
|
+
private hydrateChildren;
|
|
928
|
+
/**
|
|
929
|
+
* Find-or-create keyed on child title, scoped to this parent. The
|
|
930
|
+
* relation Set already guarantees a child id can only appear once; this
|
|
931
|
+
* extends the uniqueness to titles: if a child titled `title` already
|
|
932
|
+
* exists in `relationId`, it is returned untouched and nothing is
|
|
933
|
+
* created or linked. Otherwise `create` mints the record, its title is
|
|
934
|
+
* set and it is linked to this parent. Titles may still repeat under
|
|
935
|
+
* OTHER parents (e.g. many taxonomy branches each own a "General") —
|
|
936
|
+
* that is deliberate; uniqueness is per parent, not global.
|
|
937
|
+
*/
|
|
938
|
+
getOrCreateChildByTitle<T extends Orm>(relationId: number, title: string, create: () => Promise<T>): Promise<T>;
|
|
939
|
+
/**
|
|
940
|
+
* Generic recursive collector for any "has"/"in" relation, declaratively
|
|
941
|
+
* driven by the schema — no model needs its own copy of this logic (it
|
|
942
|
+
* used to be hand-rolled three separate times in apps/book-manager:
|
|
943
|
+
* topic-actions.ts's collectTopicDownloadTxIds, TopicTree.tsx's
|
|
944
|
+
* countBooksRecursive, ClassificationTree.tsx's countBooks).
|
|
945
|
+
*/
|
|
946
|
+
getBridgedRelationIdsSync(relationId: number, direction: 'has' | 'in', visitedBridges?: Set<string>): Array<uid>;
|
|
947
|
+
/**
|
|
948
|
+
* Walks two axes from `this`, unioning `relationName`'s targets at every
|
|
949
|
+
* node reached on either axis, recursively:
|
|
950
|
+
* - the has-direction self-referential hierarchy relation (e.g.
|
|
951
|
+
* Tag.tags) — UNLESS relationName itself IS that self-referential
|
|
952
|
+
* relation's in-direction counterpart (e.g. Tag.inTags), in which
|
|
953
|
+
* case structural expansion ascends via that relation instead of
|
|
954
|
+
* descending via the has side;
|
|
955
|
+
* - this.bridges (cross-classification-system links), following only
|
|
956
|
+
* the BridgeRelation types in opts.bridgeTypes and resolving each
|
|
957
|
+
* link's id against this record's OWN model type (bridges carry no
|
|
958
|
+
* target-type field — the data model only supports same-type links,
|
|
959
|
+
* e.g. Tag-to-Tag — a non-numeric or unresolvable id is skipped, not
|
|
960
|
+
* thrown, since it may be an external standard's notation with no
|
|
961
|
+
* local record backing it).
|
|
962
|
+
*
|
|
963
|
+
* One visited-node Set spans both axes, so any cycle — pure hierarchy,
|
|
964
|
+
* pure bridge, or mixed — terminates and each node contributes once.
|
|
965
|
+
* See bridgeDeepRelations.test.ts for the full behavioral spec this
|
|
966
|
+
* implements.
|
|
967
|
+
*/
|
|
968
|
+
collectDeepIds(relationName: string, opts?: DeepCollectOptions): Promise<uid[]>;
|
|
969
|
+
/**
|
|
970
|
+
* Applies a V2 patch to the in-memory state. Triggers reactivity.
|
|
971
|
+
*/
|
|
972
|
+
patch(patch: AnyPatch, _isMine?: boolean, effects?: boolean): void;
|
|
973
|
+
protected applyInstancePatch(p: EditInstanceFieldStringObj | EditInstanceFieldNumberObj): void;
|
|
974
|
+
protected getPropType(propId: number): 'string' | 'number' | 'boolean';
|
|
975
|
+
/**
|
|
976
|
+
* Resolve stored values without adding a UI default for an absent
|
|
977
|
+
* string. `getProp` (below) exists for live UI code, which wants an
|
|
978
|
+
* absent string coerced to `''` for convenient rendering. The corpus
|
|
979
|
+
* baker needs the RAW resolved value — including a genuine `undefined`
|
|
980
|
+
* when nothing at all applies — so it can tell "this property resolved
|
|
981
|
+
* to a value" apart from "this property has no applicable slot yet" when
|
|
982
|
+
* deciding whether an edit actually changed anything (see
|
|
983
|
+
* apply-patches-plain.ts's `applied++` bookkeeping, which compares this
|
|
984
|
+
* against the corpus's previous flattened value).
|
|
985
|
+
*/
|
|
986
|
+
resolvedPropertyValue(propId: number, lang: Lang): any;
|
|
987
|
+
getProp(propId: number, lang?: Lang): any;
|
|
988
|
+
/** Direct state write — no patch emitted (used by merge methods). */
|
|
989
|
+
protected setRaw(propId: number, value: any, lang?: Lang): void;
|
|
990
|
+
getInstancesData(lang?: Lang): InstanceData[];
|
|
991
|
+
getDefaultInstanceData(lang?: Lang): InstanceData | undefined;
|
|
992
|
+
/** Direct state write — no patch emitted (used by mergeExtended/mergeSlim). */
|
|
993
|
+
setInstancesRaw(lang: Lang, instances: InstanceData[]): void;
|
|
994
|
+
growInstances(lang: Lang, toIndex: number): void;
|
|
995
|
+
addInstance(lang?: Lang): number;
|
|
996
|
+
getProvenance(propId: number, lang?: Lang): number;
|
|
997
|
+
setProvenanceRaw(lang: Lang, propId: number, value: number): void;
|
|
998
|
+
mergeSlim(cols: any, index: number, lang?: Lang): void;
|
|
999
|
+
mergeExtended(cols: any, index: number, lang?: Lang): void;
|
|
1000
|
+
mergeProv(cols: any, index: number, lang?: Lang): void;
|
|
1001
|
+
}
|
|
1002
|
+
|
|
1003
|
+
export { Registry as $, type AnyActionPatch as A, type BridgeDefinition as B, type CommonOrmJson as C, type DeepCollectOptions as D, type EvmPayload as E, type FileRecord as F, type GetRecordPayload as G, type StatSummary as H, type InstanceData as I, BridgeRelation as J, type BridgeLink as K, type Lang as L, type BridgeSystemConversions as M, type SchemaProp as N, Orm as O, type PropertyType as P, type QueueItem as Q, type RecordIdentityCluster as R, SidecarType as S, type SchemaInstanceField as T, type SchemaRelation as U, type VersionsFile as V, WorkerCommands as W, relationColName as X, type SchemaIndex as Y, type ModelDefinition as Z, SchemaRegistry as _, type SidecarUrls as a, type PropertySlots as a$, PatchOperation as a0, PatchAction as a1, packPatch as a2, unpackPatch as a3, resolveLayout as a4, patchToEvm as a5, evmToPatch as a6, LANG_ID_ENCODE as a7, LANG_ID_DECODE as a8, ActionOperation as a9, VisitsByType as aA, FavoritesByTypes as aB, Stats as aC, type UidFactory as aD, isUserCreated as aE, CryptoRandomUidFactory as aF, loadOrInitUidFactory as aG, LifecycleStatus as aH, Config as aI, setDefaultLanguage as aJ, setDefaultProvenance as aK, setLoadAiSidecars as aL, PROVENANCE_UNSET as aM, PROVENANCE_AI as aN, PROVENANCE_MANUAL_LOCAL as aO, PROVENANCE_CONSENSUS as aP, TITLE_PROP as aQ, DESCRIPTION_PROP as aR, ORIGINAL_LANG_PROP as aS, AGE_GRADE_BAND_PROP as aT, PREVIEW_TX_ID_PROP as aU, SAFE_PROP as aV, DELETED_PROP as aW, LIFECYCLE_STATUS_PROP as aX, serializeMapOfSets as aY, serializeMapOfMaps as aZ, inflateOrmJson as a_, isActionOperation as aa, packActionPatch as ab, unpackActionPatch as ac, type BasePatch as ad, type EditPropertyStringObj as ae, type EditPropertyNumberObj as af, type EditInstanceFieldStringObj as ag, type EditInstanceFieldNumberObj as ah, type EditRelationObj as ai, type CreateRecordObj as aj, type AddInstanceObj as ak, type MergeProposalObj as al, type DeleteBridgeObj as am, type VersionEntry as an, type EnumLayout as ao, type PropLayout as ap, type BaseActionPatch as aq, type VisitActionObj as ar, type DownloadActionObj as as, type RateActionObj as at, type RatePartActionObj as au, type ShareActionObj as av, type SharePartActionObj as aw, subscribeStats as ax, PopulateStatsStore as ay, DownloadsByType as az, type SerializedCommonOrmJson as b, PROPERTY_SLOTS_COLUMN as b0, INSTANCE_REMAPS_COLUMN as b1, REPLAY_METADATA_COLUMNS as b2, scalarProperties as b3, type VersionLayout as c, type IThread as d, type LocalOp as e, type AnyPatch as f, type BookData as g, ActionTypes as h, Rating as i, WorkerEvent as j, DownloadState as k, fromJsonId as l, LANG_AGNOSTIC as m, type BaseLocalOp as n, type RateOp as o, type PartOp as p, type RatePartOp as q, type ShareOp as r, type SharePartOp as s, toJsonId as t, type uid as u, isEvmPatch as v, type InitPayload as w, type SavePatchesPayload as x, type LoadLanguagePayload as y, type WorkerPayload as z };
|