@khorsheed/dsh-reader 0.2.0
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.en.md +90 -0
- package/README.i18n.yaml +6 -0
- package/README.md +90 -0
- package/cordis.patch.yml +13 -0
- package/lib/client.js +15119 -0
- package/lib/index.js +3660 -0
- package/lib/invariant.js +38 -0
- package/lib/typert.host.d.ts +3 -0
- package/lib/typert.host.js +1738 -0
- package/lib/typert.remote-client.d.ts +82 -0
- package/lib/typert.remote-client.js +1115 -0
- package/lib/types/arxiv.d.ts +47 -0
- package/lib/types/arxiv.js +76 -0
- package/lib/types/client/ReaderPane.d.ts +71 -0
- package/lib/types/client/ReaderPane.js +3135 -0
- package/lib/types/client/contract.d.ts +254 -0
- package/lib/types/client/contract.js +1 -0
- package/lib/types/client/definition.d.ts +27 -0
- package/lib/types/client/definition.js +32 -0
- package/lib/types/client/extract-article.d.ts +102 -0
- package/lib/types/client/extract-article.js +1024 -0
- package/lib/types/client/icons.d.ts +27 -0
- package/lib/types/client/icons.js +11 -0
- package/lib/types/client/index.d.ts +34 -0
- package/lib/types/client/index.js +222 -0
- package/lib/types/client/locales.d.ts +391 -0
- package/lib/types/client/locales.js +382 -0
- package/lib/types/client/parse-rss.d.ts +69 -0
- package/lib/types/client/parse-rss.js +656 -0
- package/lib/types/client/quote.d.ts +89 -0
- package/lib/types/client/quote.js +119 -0
- package/lib/types/client/selectors.d.ts +167 -0
- package/lib/types/client/selectors.js +413 -0
- package/lib/types/client/session.d.ts +171 -0
- package/lib/types/client/session.js +223 -0
- package/lib/types/client/store.d.ts +181 -0
- package/lib/types/client/store.js +226 -0
- package/lib/types/client/translate.d.ts +379 -0
- package/lib/types/client/translate.js +873 -0
- package/lib/types/index.d.ts +48 -0
- package/lib/types/index.js +25 -0
- package/lib/types/invariant.d.ts +29 -0
- package/lib/types/invariant.js +38 -0
- package/lib/types/link-resolvers.d.ts +107 -0
- package/lib/types/link-resolvers.js +299 -0
- package/lib/types/remote.d.ts +224 -0
- package/lib/types/remote.js +275 -0
- package/lib/types/schedule.d.ts +78 -0
- package/lib/types/schedule.js +114 -0
- package/lib/types/service.d.ts +633 -0
- package/lib/types/service.js +1697 -0
- package/lib/types/store.d.ts +224 -0
- package/lib/types/store.js +916 -0
- package/lib/types/types.d.ts +710 -0
- package/lib/types/types.js +182 -0
- package/locale/en.json +6 -0
- package/locale/zh.json +6 -0
- package/package.json +128 -0
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
import { type ReaderEntryAnnotation, type ReaderStateDoc, type ReaderTranslationMemoryEntry } from './types.ts';
|
|
2
|
+
/** How many tags one document may define (a vocabulary, not a folksonomy dump). */
|
|
3
|
+
export declare const MAX_TAGS = 200;
|
|
4
|
+
/** How many entries may carry fetched bodies, before the newest-first eviction. */
|
|
5
|
+
export declare const MAX_CACHED_BODIES = 500;
|
|
6
|
+
/** The state file name inside the plugin's state root. */
|
|
7
|
+
export declare const READER_STATE_FILE_NAME = "state.json";
|
|
8
|
+
/** A store failure that the service maps onto a wire outcome. */
|
|
9
|
+
export declare class ReaderStoreError extends Error {
|
|
10
|
+
readonly kind: 'io' | 'corrupt';
|
|
11
|
+
constructor(message: string, kind: 'io' | 'corrupt');
|
|
12
|
+
}
|
|
13
|
+
/** A read result: the document plus the token the next write must present. */
|
|
14
|
+
export interface ReaderStoreRead {
|
|
15
|
+
readonly doc: ReaderStateDoc;
|
|
16
|
+
/**
|
|
17
|
+
* The document's freshness token, or `null` when there is no file yet.
|
|
18
|
+
*
|
|
19
|
+
* Only this process writes the reader's state, so the token exists to make a
|
|
20
|
+
* same-process read-modify-write honest (an external editor between the two
|
|
21
|
+
* is detected) rather than to coordinate writers.
|
|
22
|
+
*/
|
|
23
|
+
readonly version: string | null;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Resolve the state root: an explicit config value wins, then
|
|
27
|
+
* `$DSH_HOME/state/dsh-reader`, then `<cwd>/.dsh-reader`.
|
|
28
|
+
*
|
|
29
|
+
* @param configured - the plugin-provided override, if any.
|
|
30
|
+
* @returns the absolute state root directory.
|
|
31
|
+
*/
|
|
32
|
+
export declare function resolveReaderStateRoot(configured: string | undefined): string;
|
|
33
|
+
/** The empty document. */
|
|
34
|
+
export declare function emptyStateDoc(): ReaderStateDoc;
|
|
35
|
+
/** Serialize the document (trailing newline, the repo's state-file shape). */
|
|
36
|
+
export declare function serializeStateDoc(doc: ReaderStateDoc): string;
|
|
37
|
+
/**
|
|
38
|
+
* Coerce a parsed value into a document, dropping anything unrecognizable
|
|
39
|
+
* rather than trusting the file: this is user-editable state.
|
|
40
|
+
*
|
|
41
|
+
* @param value - the parsed JSON.
|
|
42
|
+
* @returns a valid document.
|
|
43
|
+
*/
|
|
44
|
+
export declare function normalizeStateDoc(value: unknown): ReaderStateDoc;
|
|
45
|
+
/**
|
|
46
|
+
* How many opened entries the recent list keeps.
|
|
47
|
+
*
|
|
48
|
+
* A bounded list is what makes the page useful: the question it answers is
|
|
49
|
+
* "what was I just reading", and a year of history answers it worse than the
|
|
50
|
+
* last hundred items. The cap is also what keeps `state.json` small, since this
|
|
51
|
+
* is the one table that grows with READING rather than with sources.
|
|
52
|
+
*/
|
|
53
|
+
export declare const MAX_RECENT_ENTRIES = 100;
|
|
54
|
+
/**
|
|
55
|
+
* Bound the document's payload bytes without dropping a subscription.
|
|
56
|
+
*
|
|
57
|
+
* Newest-first: the freshest payload is the one the reader is most likely to
|
|
58
|
+
* open, so it survives and the oldest bodies are the ones released. Keeping
|
|
59
|
+
* every source row regardless is deliberate — a source whose body was evicted
|
|
60
|
+
* still refreshes, and dropping subscriptions to save space would be a silent
|
|
61
|
+
* data loss the reader never asked for.
|
|
62
|
+
*
|
|
63
|
+
* @param doc - the document to bound.
|
|
64
|
+
* @returns the bounded document, and whether anything was released.
|
|
65
|
+
*/
|
|
66
|
+
export declare function boundPayloads(doc: ReaderStateDoc): {
|
|
67
|
+
doc: ReaderStateDoc;
|
|
68
|
+
changed: boolean;
|
|
69
|
+
};
|
|
70
|
+
/** Sub-directory holding bodies too large to inline in the document. */
|
|
71
|
+
export declare const READER_BODIES_DIR = "bodies";
|
|
72
|
+
/**
|
|
73
|
+
* The global translation memory's file name inside `bodies/`.
|
|
74
|
+
*
|
|
75
|
+
* One fixed name rather than a per-key hash: the table is a single artifact,
|
|
76
|
+
* rewritten whole by the (already debounced) write path, and referenced from
|
|
77
|
+
* the document's `translationMemory` manifest so `pruneBodies` keeps it.
|
|
78
|
+
*/
|
|
79
|
+
export declare const TRANSLATION_MEMORY_FILE = "translation-memory.json";
|
|
80
|
+
/** Native-fs state store: the deployment's document, not the session's. */
|
|
81
|
+
export declare class ReaderStore {
|
|
82
|
+
private readonly stateRoot;
|
|
83
|
+
private readonly file;
|
|
84
|
+
private readonly bodiesDir;
|
|
85
|
+
/** Set once the root has proven unwritable; the service then goes memory-only. */
|
|
86
|
+
private unwritable;
|
|
87
|
+
/**
|
|
88
|
+
* @param config - optional state-root override.
|
|
89
|
+
*/
|
|
90
|
+
constructor(config?: {
|
|
91
|
+
stateRoot?: string;
|
|
92
|
+
});
|
|
93
|
+
/**
|
|
94
|
+
* Write one body to its own file, atomically, and return the file's name.
|
|
95
|
+
*
|
|
96
|
+
* The name is a digest of the entry id: entry ids are URLs, and a document
|
|
97
|
+
* carrying an absolute path (or a path derived from remote text) is a
|
|
98
|
+
* directory-traversal waiting to happen.
|
|
99
|
+
*
|
|
100
|
+
* @param entryId - the entry the body belongs to.
|
|
101
|
+
* @param html - the normalized body markup.
|
|
102
|
+
* @returns the file name to store in the document.
|
|
103
|
+
*/
|
|
104
|
+
writeBody(entryId: string, html: string): string;
|
|
105
|
+
/**
|
|
106
|
+
* Write one NAMED artifact into `bodies/`, atomically.
|
|
107
|
+
*
|
|
108
|
+
* Unlike {@link writeBody} the name is the caller's, not a hash of an entry
|
|
109
|
+
* id: the global translation memory is one fixed file, not one per entry. The
|
|
110
|
+
* name is validated to a bare file name — this directory must never grow a
|
|
111
|
+
* path.
|
|
112
|
+
*
|
|
113
|
+
* @param name - the bare file name to write.
|
|
114
|
+
* @param content - the file's content.
|
|
115
|
+
* @returns the name written.
|
|
116
|
+
*/
|
|
117
|
+
writeNamedBody(name: string, content: string): string;
|
|
118
|
+
/**
|
|
119
|
+
* Read one body file.
|
|
120
|
+
*
|
|
121
|
+
* @param name - the file name recorded in the document.
|
|
122
|
+
* @returns the markup, or `undefined` when the file is gone or unreadable.
|
|
123
|
+
*/
|
|
124
|
+
readBody(name: string): string | undefined;
|
|
125
|
+
/**
|
|
126
|
+
* Delete body files the document no longer references.
|
|
127
|
+
*
|
|
128
|
+
* Eviction (`maxEntries`), tag edits that drop an annotation, and a hand-edited
|
|
129
|
+
* document all release bodies by REMOVING them from the JSON — which would
|
|
130
|
+
* otherwise leave their files on disk forever. Best-effort by design: a failed
|
|
131
|
+
* sweep must never fail the commit that triggered it.
|
|
132
|
+
*
|
|
133
|
+
* @param doc - the document that was just written.
|
|
134
|
+
* @returns how many files were removed.
|
|
135
|
+
*/
|
|
136
|
+
pruneBodies(doc: ReaderStateDoc): number;
|
|
137
|
+
/** The absolute path of the state file (diagnostics and tests). */
|
|
138
|
+
get path(): string;
|
|
139
|
+
/** Why persistence is unavailable, when it is. */
|
|
140
|
+
get unavailableReason(): string | undefined;
|
|
141
|
+
/**
|
|
142
|
+
* Whether persistence is available.
|
|
143
|
+
*
|
|
144
|
+
* Probed by creating the state root, not by asking a capability: a
|
|
145
|
+
* read-only deployment (a container with no writable home) must degrade to
|
|
146
|
+
* memory-only, and that is only knowable by trying.
|
|
147
|
+
*/
|
|
148
|
+
get available(): boolean;
|
|
149
|
+
/**
|
|
150
|
+
* Read the document tolerantly.
|
|
151
|
+
*
|
|
152
|
+
* @returns the document and its freshness token; a missing file reads as empty.
|
|
153
|
+
* @throws ReaderStoreError when the file exists but does not parse.
|
|
154
|
+
*/
|
|
155
|
+
read(): Promise<ReaderStoreRead>;
|
|
156
|
+
/**
|
|
157
|
+
* Write the document atomically under the token from the last read.
|
|
158
|
+
*
|
|
159
|
+
* @param doc - the document to publish.
|
|
160
|
+
* @param version - the token from the last read (`null` for the first write).
|
|
161
|
+
* @returns the new freshness token.
|
|
162
|
+
*/
|
|
163
|
+
write(doc: ReaderStateDoc, version: string | null): Promise<string>;
|
|
164
|
+
/**
|
|
165
|
+
* Read-modify-write with the one concurrent-edit retry.
|
|
166
|
+
*
|
|
167
|
+
* @param mutate - pure function from the current document to the next one.
|
|
168
|
+
* @returns the document that ended up on disk.
|
|
169
|
+
*/
|
|
170
|
+
update(mutate: (doc: ReaderStateDoc) => ReaderStateDoc): Promise<ReaderStateDoc>;
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Bound the cached article bodies without touching what the reader authored.
|
|
174
|
+
*
|
|
175
|
+
* Newest-first: the article just fetched is the one being read, so the budget
|
|
176
|
+
* releases the older copies. Tags are NOT part of this budget — a tag is a
|
|
177
|
+
* sentence the reader wrote, and losing it to make room for a cached page would
|
|
178
|
+
* be the worst trade in this document.
|
|
179
|
+
*
|
|
180
|
+
* @param doc - the document to bound.
|
|
181
|
+
* @returns the bounded document, and whether anything was released.
|
|
182
|
+
*/
|
|
183
|
+
export declare function boundAnnotations(doc: ReaderStateDoc): {
|
|
184
|
+
doc: ReaderStateDoc;
|
|
185
|
+
changed: boolean;
|
|
186
|
+
};
|
|
187
|
+
/**
|
|
188
|
+
* Drop tags nothing references any more.
|
|
189
|
+
*
|
|
190
|
+
* @param doc - the document to prune.
|
|
191
|
+
* @returns the pruned document, and how many tags went.
|
|
192
|
+
*/
|
|
193
|
+
export declare function pruneOrphanTags(doc: ReaderStateDoc): {
|
|
194
|
+
doc: ReaderStateDoc;
|
|
195
|
+
removed: number;
|
|
196
|
+
};
|
|
197
|
+
/**
|
|
198
|
+
* Bound the two translation tiers to their shared budget, LRU by last use.
|
|
199
|
+
*
|
|
200
|
+
* The eviction list is ONE ordering across the global memory and every entry's
|
|
201
|
+
* segment map: a sentence remembered and a per-entry map are the same kind of
|
|
202
|
+
* thing (a translation that was paid for), so the oldest lastUsedAt goes first
|
|
203
|
+
* regardless of which tier holds it. Two extra rules ride the same walk,
|
|
204
|
+
* because it is the only place both tiers are walked: schema-version mismatches
|
|
205
|
+
* are evicted on sight (the lazy half of "version bump = miss"), and the memory
|
|
206
|
+
* table answers to its own count cap even when the budget has room.
|
|
207
|
+
*
|
|
208
|
+
* Pure over plain records: the service wires the files, this decides.
|
|
209
|
+
*
|
|
210
|
+
* @param memory - the global sentence memory (table content).
|
|
211
|
+
* @param annotations - the document's annotations (entry translations included).
|
|
212
|
+
* @param budgetChars - the shared budget.
|
|
213
|
+
* @returns the bounded records, plus WHICH keys each tier lost (the caller
|
|
214
|
+
* applies the entry evictions to the freshest document inside its commit).
|
|
215
|
+
*/
|
|
216
|
+
export declare function boundTranslations(memory: Record<string, ReaderTranslationMemoryEntry>, annotations: Record<string, ReaderEntryAnnotation>, budgetChars: number): {
|
|
217
|
+
memory: Record<string, ReaderTranslationMemoryEntry>;
|
|
218
|
+
annotations: Record<string, ReaderEntryAnnotation>;
|
|
219
|
+
evictedMemoryKeys: string[];
|
|
220
|
+
evictedEntryIds: string[];
|
|
221
|
+
};
|
|
222
|
+
/** The table's approximate size in characters, for the document's manifest. */
|
|
223
|
+
export declare function memoryTableChars(entries: Record<string, ReaderTranslationMemoryEntry>): number;
|
|
224
|
+
//# sourceMappingURL=store.d.ts.map
|