@docmentis/udoc-server 0.0.0-stage → 0.8.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/LICENSE-APACHE +202 -0
- package/LICENSE-MIT +21 -0
- package/README.md +41 -2
- package/config.example.toml +26 -0
- package/dist/collaboration.d.ts +25 -0
- package/dist/collaboration.d.ts.map +1 -0
- package/dist/collaboration.js +348 -0
- package/dist/collaboration.js.map +1 -0
- package/dist/config.d.ts +30 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +87 -0
- package/dist/config.js.map +1 -0
- package/dist/document.d.ts +29 -0
- package/dist/document.d.ts.map +1 -0
- package/dist/document.js +308 -0
- package/dist/document.js.map +1 -0
- package/dist/http.d.ts +44 -0
- package/dist/http.d.ts.map +1 -0
- package/dist/http.js +96 -0
- package/dist/http.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/main.d.ts +3 -0
- package/dist/main.d.ts.map +1 -0
- package/dist/main.js +105 -0
- package/dist/main.js.map +1 -0
- package/dist/package.d.ts +5 -0
- package/dist/package.d.ts.map +1 -0
- package/dist/package.js +116 -0
- package/dist/package.js.map +1 -0
- package/dist/route.d.ts +56 -0
- package/dist/route.d.ts.map +1 -0
- package/dist/route.js +126 -0
- package/dist/route.js.map +1 -0
- package/dist/server.d.ts +45 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +103 -0
- package/dist/server.js.map +1 -0
- package/dist/session-pool.d.ts +19 -0
- package/dist/session-pool.d.ts.map +1 -0
- package/dist/session-pool.js +95 -0
- package/dist/session-pool.js.map +1 -0
- package/dist/store.d.ts +115 -0
- package/dist/store.d.ts.map +1 -0
- package/dist/store.js +441 -0
- package/dist/store.js.map +1 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +10 -0
- package/dist/version.js.map +1 -0
- package/package.json +76 -5
package/dist/store.js
ADDED
|
@@ -0,0 +1,441 @@
|
|
|
1
|
+
// Where udoc-server keeps each document between sessions.
|
|
2
|
+
//
|
|
3
|
+
// A document is kept as its original — the upload, byte for byte, in the
|
|
4
|
+
// format it was imported as — and its checkpoints, each the udoc package one
|
|
5
|
+
// checkpoint saved: `v0`, the baseline its import produced with every id
|
|
6
|
+
// already minted, then one more each time it is checkpointed
|
|
7
|
+
// (docs/design/core-save.md). Every later session reopens the latest.
|
|
8
|
+
//
|
|
9
|
+
// The latest checkpoint is also read an entry at a time, for streaming: its
|
|
10
|
+
// description, a part, a blob, each addressed by its route — the server API's
|
|
11
|
+
// own terms (see docs/design/node-streaming.md), which a store maps to
|
|
12
|
+
// wherever it keeps them. A part or a blob is read deflated, the form it is
|
|
13
|
+
// sent in.
|
|
14
|
+
//
|
|
15
|
+
// Once the document is edited, it also has an edit log: every edit made, which
|
|
16
|
+
// is a package's own `crdt` entity — opening applies it — but kept apart from
|
|
17
|
+
// the checkpoints, because it is written on every edit and a checkpoint only
|
|
18
|
+
// once. It holds every edit since the import, so it replays over any
|
|
19
|
+
// checkpoint, and a checkpoint leaves it as it is.
|
|
20
|
+
//
|
|
21
|
+
// An edit that inserts a picture also brings the picture's image: an opaque
|
|
22
|
+
// part, whose id the edit log carries but not its content
|
|
23
|
+
// (docs/design/core-editor-opaque-part.md). Each such part, and each blob it
|
|
24
|
+
// carries, is kept beside the checkpoints by its route — written once, since
|
|
25
|
+
// an opaque part never changes and a blob's key is its content — until a
|
|
26
|
+
// checkpoint holds it.
|
|
27
|
+
import { randomUUID } from "node:crypto";
|
|
28
|
+
import { link, mkdir, readFile, readdir, rename, rm, stat, writeFile } from "node:fs/promises";
|
|
29
|
+
import { dirname, join } from "node:path";
|
|
30
|
+
import { buffer } from "node:stream/consumers";
|
|
31
|
+
import { promisify } from "node:util";
|
|
32
|
+
import { deflateRaw } from "node:zlib";
|
|
33
|
+
import { UDocError, isFileFormat } from "@docmentis/udoc-node";
|
|
34
|
+
import { fromBufferPromise, openPromise } from "yauzl";
|
|
35
|
+
/**
|
|
36
|
+
* A route's segments under `…/package` (docs/design/node-streaming.md): a
|
|
37
|
+
* part's kind in kebab-case and plural, its id's key — `replica-counter` in
|
|
38
|
+
* hex — and a blob's key. A route is held to them before it reaches a store,
|
|
39
|
+
* so none names a path outside.
|
|
40
|
+
*/
|
|
41
|
+
export const KINDS = /[a-z0-9]+(?:-[a-z0-9]+)*/;
|
|
42
|
+
export const PART_ID = /[0-9a-f]+-[0-9a-f]+/;
|
|
43
|
+
export const BLOB_KEY = /[0-9a-f]+/;
|
|
44
|
+
/** An id that is safe as a file name. No dot, so no id can name a staged write. */
|
|
45
|
+
const FILE_SAFE_ID = /^[A-Za-z0-9_-]+$/;
|
|
46
|
+
/**
|
|
47
|
+
* A document's original is `original.<format>`; its checkpoints are
|
|
48
|
+
* `checkpoints/v<version>.udoc`, the latest the highest; its edit log, once it
|
|
49
|
+
* has one, is `crdt.loro`, the name a package's own entry for it has.
|
|
50
|
+
*/
|
|
51
|
+
const ORIGINAL = "original";
|
|
52
|
+
const CHECKPOINTS_DIR = "checkpoints";
|
|
53
|
+
const CHECKPOINT_FILE = /^v(\d+)\.udoc$/;
|
|
54
|
+
const LOG_FILE = "crdt.loro";
|
|
55
|
+
/**
|
|
56
|
+
* Where the opaque parts edits brought are kept, each deflated at
|
|
57
|
+
* `opaque-parts/<kinds>/<partId>`; the blobs they carry are at `blobs/<key>`.
|
|
58
|
+
*/
|
|
59
|
+
const OPAQUE_PARTS_DIR = "opaque-parts";
|
|
60
|
+
const BLOBS_DIR = "blobs";
|
|
61
|
+
/**
|
|
62
|
+
* A part's entry in a package, `parts/<snake_kind>_<id-key>.json`, and a
|
|
63
|
+
* blob's, `blobs/<key>` with whatever extension it was written with. The key
|
|
64
|
+
* holds no `_`, so the kind is everything before the last one.
|
|
65
|
+
*/
|
|
66
|
+
const PART_ENTRY = new RegExp(`^parts/([a-z0-9]+(?:_[a-z0-9]+)*)_(${PART_ID.source})\\.json$`);
|
|
67
|
+
const BLOB_ENTRY = new RegExp(`^blobs/(${BLOB_KEY.source})(?:\\.[^/]*)?$`);
|
|
68
|
+
/** The compression method of a zip entry kept deflated. */
|
|
69
|
+
const DEFLATE = 8;
|
|
70
|
+
const deflate = promisify(deflateRaw);
|
|
71
|
+
/**
|
|
72
|
+
* A {@link DocumentStore} over a directory: one directory per document, named
|
|
73
|
+
* by its id, holding its original, its checkpoints and its edit log.
|
|
74
|
+
*/
|
|
75
|
+
export class DirectoryDocumentStore {
|
|
76
|
+
#directory;
|
|
77
|
+
constructor(directory) {
|
|
78
|
+
this.#directory = directory;
|
|
79
|
+
}
|
|
80
|
+
async put(id, document) {
|
|
81
|
+
const path = this.#path(id);
|
|
82
|
+
await mkdir(this.#directory, { recursive: true });
|
|
83
|
+
// Both are written into a directory aside and renamed into place
|
|
84
|
+
// together, so a reader never meets half a document, and a crash
|
|
85
|
+
// mid-write leaves none. A directory can't be renamed over one that
|
|
86
|
+
// holds files, so an id already kept stays as it was.
|
|
87
|
+
const staged = `${path}.${randomUUID()}.partial`;
|
|
88
|
+
try {
|
|
89
|
+
await mkdir(staged);
|
|
90
|
+
await writeFile(join(staged, `${ORIGINAL}.${document.original.format}`), document.original.bytes);
|
|
91
|
+
await mkdir(join(staged, CHECKPOINTS_DIR));
|
|
92
|
+
await writeFile(join(staged, CHECKPOINTS_DIR, "v0.udoc"), document.checkpoint);
|
|
93
|
+
await rename(staged, path);
|
|
94
|
+
}
|
|
95
|
+
catch (error) {
|
|
96
|
+
await rm(staged, { recursive: true, force: true });
|
|
97
|
+
throw error;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
async getOriginal(id) {
|
|
101
|
+
const path = this.#path(id);
|
|
102
|
+
let names;
|
|
103
|
+
try {
|
|
104
|
+
names = await readdir(path);
|
|
105
|
+
}
|
|
106
|
+
catch (error) {
|
|
107
|
+
if (isNotFound(error))
|
|
108
|
+
return undefined;
|
|
109
|
+
throw error;
|
|
110
|
+
}
|
|
111
|
+
for (const name of names) {
|
|
112
|
+
const format = name.startsWith(`${ORIGINAL}.`) ? name.slice(ORIGINAL.length + 1) : undefined;
|
|
113
|
+
if (format !== undefined && isFileFormat(format)) {
|
|
114
|
+
return { bytes: await readFile(join(path, name)), format };
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
throw new Error(`document ${id} is kept without its original`);
|
|
118
|
+
}
|
|
119
|
+
async getCheckpoint(id) {
|
|
120
|
+
const [latest] = await this.#checkpoints(id);
|
|
121
|
+
return latest === undefined ? undefined : readFile(latest);
|
|
122
|
+
}
|
|
123
|
+
async putCheckpoint(id, version, checkpoint) {
|
|
124
|
+
const path = this.#path(id);
|
|
125
|
+
const kept = join(path, CHECKPOINTS_DIR, `v${version}.udoc`);
|
|
126
|
+
// Written aside, then linked into place, which refuses a version kept
|
|
127
|
+
// already: once there, it is the latest, whole.
|
|
128
|
+
const staged = `${kept}.${randomUUID()}.partial`;
|
|
129
|
+
try {
|
|
130
|
+
await writeFile(staged, checkpoint, { flag: "wx" });
|
|
131
|
+
await link(staged, kept);
|
|
132
|
+
}
|
|
133
|
+
catch (error) {
|
|
134
|
+
if (isNotFound(error))
|
|
135
|
+
throw new Error(`no document ${JSON.stringify(id)} with checkpoints is kept`);
|
|
136
|
+
if (isAlreadyKept(error))
|
|
137
|
+
throw new Error(`document ${JSON.stringify(id)} keeps checkpoint v${version} already`);
|
|
138
|
+
throw error;
|
|
139
|
+
}
|
|
140
|
+
finally {
|
|
141
|
+
await rm(staged, { force: true });
|
|
142
|
+
}
|
|
143
|
+
// What it holds is served from it now. Forgotten only after it is in
|
|
144
|
+
// place, so a crash between leaves an opaque part kept twice, never
|
|
145
|
+
// one kept nowhere.
|
|
146
|
+
const zip = await fromBufferPromise(Buffer.from(checkpoint.buffer, checkpoint.byteOffset, checkpoint.byteLength), {
|
|
147
|
+
lazyEntries: true,
|
|
148
|
+
});
|
|
149
|
+
try {
|
|
150
|
+
for await (const entry of zip.eachEntry()) {
|
|
151
|
+
const route = keptRouteOf(entry.fileName);
|
|
152
|
+
if (route !== undefined)
|
|
153
|
+
await rm(join(path, route), { force: true });
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
finally {
|
|
157
|
+
zip.close();
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
async getDescription(id) {
|
|
161
|
+
const metadata = await this.#readCheckpointEntry(id, "");
|
|
162
|
+
if (!metadata)
|
|
163
|
+
return undefined;
|
|
164
|
+
// The checkpoint's own envelope, written by the engine this server runs.
|
|
165
|
+
// Every number is read whole, as a `bigint`, so a frontier's peers
|
|
166
|
+
// keep every bit.
|
|
167
|
+
const { documentType, sourceFormat, sourceDelimiter, baselineVersion, baselineFrontier } = JSON.parse(new TextDecoder().decode(metadata), (_key, value, context) => typeof value === "number" && context?.source !== undefined ? BigInt(context.source) : value);
|
|
168
|
+
const frontier = baselineFrontier ?? ((await this.#hasLog(id)) ? [] : undefined);
|
|
169
|
+
return {
|
|
170
|
+
docType: documentType,
|
|
171
|
+
...(sourceFormat !== undefined ? { sourceFormat } : {}),
|
|
172
|
+
...(sourceDelimiter !== undefined ? { sourceDelimiter } : {}),
|
|
173
|
+
baselineVersion: Number(baselineVersion),
|
|
174
|
+
...(frontier !== undefined ? { baselineFrontier: frontier } : {}),
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
async getPart(id, kinds, partId) {
|
|
178
|
+
return this.#readPart(id, `${kinds}/${partId}`, join(OPAQUE_PARTS_DIR, kinds, partId));
|
|
179
|
+
}
|
|
180
|
+
async getBlob(id, key) {
|
|
181
|
+
return this.#readPart(id, `blobs/${key}`, join(BLOBS_DIR, key));
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Document `id`'s part or blob at `route`, deflated: its latest
|
|
185
|
+
* checkpoint's; else the one kept beside the checkpoints at `kept`; else
|
|
186
|
+
* the newest earlier checkpoint's that has it. Once a checkpoint holds an
|
|
187
|
+
* opaque part, it is kept beside them no longer, and a later checkpoint
|
|
188
|
+
* holds it only if something showed it then — yet an undo can show it
|
|
189
|
+
* again.
|
|
190
|
+
*/
|
|
191
|
+
async #readPart(id, route, kept) {
|
|
192
|
+
const [latest, ...earlier] = await this.#checkpoints(id);
|
|
193
|
+
if (latest !== undefined) {
|
|
194
|
+
const entry = await this.#readEntry(latest, route, true);
|
|
195
|
+
if (entry)
|
|
196
|
+
return entry;
|
|
197
|
+
}
|
|
198
|
+
const keptBeside = await this.#readKept(id, kept);
|
|
199
|
+
if (keptBeside)
|
|
200
|
+
return keptBeside;
|
|
201
|
+
for (const checkpoint of earlier) {
|
|
202
|
+
const entry = await this.#readEntry(checkpoint, route, true);
|
|
203
|
+
if (entry)
|
|
204
|
+
return entry;
|
|
205
|
+
}
|
|
206
|
+
return undefined;
|
|
207
|
+
}
|
|
208
|
+
async putOpaqueParts(id, parts) {
|
|
209
|
+
const path = this.#path(id);
|
|
210
|
+
// Nothing here creates the document's directory, so a document
|
|
211
|
+
// forgotten meanwhile stays forgotten.
|
|
212
|
+
try {
|
|
213
|
+
await stat(path);
|
|
214
|
+
}
|
|
215
|
+
catch (error) {
|
|
216
|
+
if (isNotFound(error))
|
|
217
|
+
throw new UDocError("notFound", `no document ${JSON.stringify(id)} is kept`);
|
|
218
|
+
throw error;
|
|
219
|
+
}
|
|
220
|
+
// Sent by a client: bytes that aren't a zip are its to answer for.
|
|
221
|
+
const zip = await fromBufferPromise(Buffer.from(parts.buffer, parts.byteOffset, parts.byteLength), {
|
|
222
|
+
lazyEntries: true,
|
|
223
|
+
}).catch((error) => {
|
|
224
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
225
|
+
throw new UDocError("malformed", `the opaque parts aren't a zip: ${reason}`, undefined, { cause: error });
|
|
226
|
+
});
|
|
227
|
+
try {
|
|
228
|
+
for await (const entry of zip.eachEntry()) {
|
|
229
|
+
const route = keptRouteOf(entry.fileName);
|
|
230
|
+
if (route === undefined)
|
|
231
|
+
continue;
|
|
232
|
+
const kept = join(path, route);
|
|
233
|
+
await mkdir(dirname(kept), { recursive: true });
|
|
234
|
+
// Written aside and renamed into place, so a reader meets the
|
|
235
|
+
// whole entry or none. A route names its content, so one kept
|
|
236
|
+
// already is the same bytes, renamed over.
|
|
237
|
+
const staged = `${kept}.${randomUUID()}.partial`;
|
|
238
|
+
try {
|
|
239
|
+
await writeFile(staged, await deflatedEntry(zip, entry), { flag: "wx" });
|
|
240
|
+
await rename(staged, kept);
|
|
241
|
+
}
|
|
242
|
+
catch (error) {
|
|
243
|
+
await rm(staged, { force: true });
|
|
244
|
+
throw error;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
finally {
|
|
249
|
+
zip.close();
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
/** The file kept at `route` beside document `id`'s checkpoints, or `undefined` when there is none. */
|
|
253
|
+
async #readKept(id, route) {
|
|
254
|
+
try {
|
|
255
|
+
return await readFile(join(this.#path(id), route));
|
|
256
|
+
}
|
|
257
|
+
catch (error) {
|
|
258
|
+
if (isNotFound(error))
|
|
259
|
+
return undefined;
|
|
260
|
+
throw error;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
/** The paths of document `id`'s checkpoints, the latest first; none when it has none. */
|
|
264
|
+
async #checkpoints(id) {
|
|
265
|
+
const directory = join(this.#path(id), CHECKPOINTS_DIR);
|
|
266
|
+
let names;
|
|
267
|
+
try {
|
|
268
|
+
names = await readdir(directory);
|
|
269
|
+
}
|
|
270
|
+
catch (error) {
|
|
271
|
+
if (isNotFound(error))
|
|
272
|
+
return [];
|
|
273
|
+
throw error;
|
|
274
|
+
}
|
|
275
|
+
return names
|
|
276
|
+
.flatMap((name) => {
|
|
277
|
+
const version = CHECKPOINT_FILE.exec(name)?.[1];
|
|
278
|
+
return version === undefined ? [] : [{ version: Number(version), path: join(directory, name) }];
|
|
279
|
+
})
|
|
280
|
+
.sort((a, b) => b.version - a.version)
|
|
281
|
+
.map(({ path }) => path);
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* The entry of document `id`'s latest checkpoint at `route`, read as
|
|
285
|
+
* `#readEntry` reads one, or `undefined` when it has none or there is no
|
|
286
|
+
* checkpoint.
|
|
287
|
+
*/
|
|
288
|
+
async #readCheckpointEntry(id, route, deflated = false) {
|
|
289
|
+
const [latest] = await this.#checkpoints(id);
|
|
290
|
+
return latest === undefined ? undefined : this.#readEntry(latest, route, deflated);
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* The entry of the checkpoint at `checkpoint` at `route` (see
|
|
294
|
+
* {@link routeOf}), or `undefined` when it has none. Reads the zip's
|
|
295
|
+
* central directory and that one entry: inflated, or — `deflated` — as the
|
|
296
|
+
* zip keeps it, deflated, so nothing is compressed again; one kept stored
|
|
297
|
+
* is deflated now.
|
|
298
|
+
*/
|
|
299
|
+
async #readEntry(checkpoint, route, deflated = false) {
|
|
300
|
+
let zip;
|
|
301
|
+
try {
|
|
302
|
+
zip = await openPromise(checkpoint, { lazyEntries: true, autoClose: false });
|
|
303
|
+
}
|
|
304
|
+
catch (error) {
|
|
305
|
+
if (isNotFound(error))
|
|
306
|
+
return undefined;
|
|
307
|
+
throw error;
|
|
308
|
+
}
|
|
309
|
+
try {
|
|
310
|
+
for await (const entry of zip.eachEntry()) {
|
|
311
|
+
if (routeOf(entry.fileName) !== route)
|
|
312
|
+
continue;
|
|
313
|
+
if (deflated && entry.compressionMethod === DEFLATE) {
|
|
314
|
+
return await buffer(await zip.openReadStreamPromise(entry, { decodeFileData: false }));
|
|
315
|
+
}
|
|
316
|
+
const bytes = await buffer(await zip.openReadStreamPromise(entry));
|
|
317
|
+
return deflated ? await deflate(bytes) : bytes;
|
|
318
|
+
}
|
|
319
|
+
return undefined;
|
|
320
|
+
}
|
|
321
|
+
finally {
|
|
322
|
+
zip.close();
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
async getLog(id) {
|
|
326
|
+
try {
|
|
327
|
+
return await readFile(join(this.#path(id), LOG_FILE));
|
|
328
|
+
}
|
|
329
|
+
catch (error) {
|
|
330
|
+
if (!isNotFound(error))
|
|
331
|
+
throw error;
|
|
332
|
+
}
|
|
333
|
+
return this.#readCheckpointEntry(id, LOG_FILE);
|
|
334
|
+
}
|
|
335
|
+
async putLog(id, log) {
|
|
336
|
+
const path = join(this.#path(id), LOG_FILE);
|
|
337
|
+
// Written aside and renamed over the one kept, so a reader meets the old
|
|
338
|
+
// log or the new, never part of one. Neither creates the document's
|
|
339
|
+
// directory, so a document forgotten meanwhile stays forgotten.
|
|
340
|
+
const staged = `${path}.${randomUUID()}.partial`;
|
|
341
|
+
try {
|
|
342
|
+
await writeFile(staged, log, { flag: "wx" });
|
|
343
|
+
await rename(staged, path);
|
|
344
|
+
}
|
|
345
|
+
catch (error) {
|
|
346
|
+
await rm(staged, { force: true });
|
|
347
|
+
if (isNotFound(error))
|
|
348
|
+
throw new Error(`no document ${JSON.stringify(id)} is kept`);
|
|
349
|
+
throw error;
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
async #hasLog(id) {
|
|
353
|
+
try {
|
|
354
|
+
await stat(join(this.#path(id), LOG_FILE));
|
|
355
|
+
return true;
|
|
356
|
+
}
|
|
357
|
+
catch (error) {
|
|
358
|
+
if (isNotFound(error))
|
|
359
|
+
return false;
|
|
360
|
+
throw error;
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
async delete(id) {
|
|
364
|
+
try {
|
|
365
|
+
await rm(this.#path(id), { recursive: true });
|
|
366
|
+
return true;
|
|
367
|
+
}
|
|
368
|
+
catch (error) {
|
|
369
|
+
if (isNotFound(error))
|
|
370
|
+
return false;
|
|
371
|
+
throw error;
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
#path(id) {
|
|
375
|
+
if (!FILE_SAFE_ID.test(id))
|
|
376
|
+
throw new Error(`not a document id: ${JSON.stringify(id)}`);
|
|
377
|
+
return join(this.#directory, id);
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
/**
|
|
381
|
+
* The route a package entry is served at, relative to the package: `""` for
|
|
382
|
+
* `metadata.json`, `<kinds>/<partId>` for a part, `blobs/<key>` for a blob,
|
|
383
|
+
* `crdt.loro` for the edit log, and `undefined` for anything not served.
|
|
384
|
+
*/
|
|
385
|
+
function routeOf(entry) {
|
|
386
|
+
if (entry === "metadata.json")
|
|
387
|
+
return "";
|
|
388
|
+
if (entry === LOG_FILE)
|
|
389
|
+
return LOG_FILE;
|
|
390
|
+
const part = PART_ENTRY.exec(entry);
|
|
391
|
+
if (part)
|
|
392
|
+
return `${pluralKebab(part[1])}/${part[2]}`;
|
|
393
|
+
const blob = BLOB_ENTRY.exec(entry);
|
|
394
|
+
if (blob)
|
|
395
|
+
return `blobs/${blob[1]}`;
|
|
396
|
+
return undefined;
|
|
397
|
+
}
|
|
398
|
+
/**
|
|
399
|
+
* Where an entry of an `opaque parts` zip is kept, relative to the document's
|
|
400
|
+
* directory: a part's entry at `opaque-parts/<kinds>/<partId>`, and a blob at
|
|
401
|
+
* `blobs/<key>`. Anything else — the zip's own list of what it carries — is not
|
|
402
|
+
* kept. Every segment is checked against its pattern, so no entry names a path
|
|
403
|
+
* outside.
|
|
404
|
+
*/
|
|
405
|
+
function keptRouteOf(entry) {
|
|
406
|
+
const part = PART_ENTRY.exec(entry);
|
|
407
|
+
if (part)
|
|
408
|
+
return join(OPAQUE_PARTS_DIR, pluralKebab(part[1]), part[2]);
|
|
409
|
+
const blob = BLOB_ENTRY.exec(entry);
|
|
410
|
+
if (blob)
|
|
411
|
+
return join(BLOBS_DIR, blob[1]);
|
|
412
|
+
return undefined;
|
|
413
|
+
}
|
|
414
|
+
/** `entry` of `zip`, deflated: as the zip keeps it when it keeps it deflated, else deflated now. */
|
|
415
|
+
async function deflatedEntry(zip, entry) {
|
|
416
|
+
if (entry.compressionMethod === DEFLATE) {
|
|
417
|
+
return buffer(await zip.openReadStreamPromise(entry, { decodeFileData: false }));
|
|
418
|
+
}
|
|
419
|
+
return deflate(await buffer(await zip.openReadStreamPromise(entry)));
|
|
420
|
+
}
|
|
421
|
+
/**
|
|
422
|
+
* A kind's route segment from its snake_case entry name: kebab-case, plural. A
|
|
423
|
+
* kind already plural stays as it is, and so does a `…data` kind, whose noun is
|
|
424
|
+
* uncounted — the rule the engine's `RemotePackageLoader` applies to the same
|
|
425
|
+
* kind (docs/design/node-streaming.md).
|
|
426
|
+
*/
|
|
427
|
+
function pluralKebab(snakeKind) {
|
|
428
|
+
const kebab = snakeKind.replaceAll("_", "-");
|
|
429
|
+
const uncounted = kebab.endsWith("s") || kebab.split("-").at(-1) === "data";
|
|
430
|
+
return uncounted ? kebab : `${kebab}s`;
|
|
431
|
+
}
|
|
432
|
+
function isNotFound(error) {
|
|
433
|
+
return codeOf(error) === "ENOENT";
|
|
434
|
+
}
|
|
435
|
+
function isAlreadyKept(error) {
|
|
436
|
+
return codeOf(error) === "EEXIST";
|
|
437
|
+
}
|
|
438
|
+
function codeOf(error) {
|
|
439
|
+
return typeof error === "object" && error !== null ? error.code : undefined;
|
|
440
|
+
}
|
|
441
|
+
//# sourceMappingURL=store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAWA,eAAO,MAAM,eAAe,QAAmB,CAAC"}
|
package/dist/version.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// This package's version, reported to the engine as the wrapper version so a
|
|
2
|
+
// permit request and a usage event can name what produced them.
|
|
3
|
+
//
|
|
4
|
+
// Read from the `package.json` npm ships beside `dist` — the one place a
|
|
5
|
+
// release bumps — so it is always the version actually running. `../` is the
|
|
6
|
+
// package root from `src` and from `dist` alike.
|
|
7
|
+
import { readFileSync } from "node:fs";
|
|
8
|
+
const manifest = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8"));
|
|
9
|
+
export const WRAPPER_VERSION = manifest.version;
|
|
10
|
+
//# sourceMappingURL=version.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version.js","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,gEAAgE;AAChE,EAAE;AACF,yEAAyE;AACzE,6EAA6E;AAC7E,iDAAiD;AAEjD,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEvC,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,GAAG,CAAC,iBAAiB,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,CAAwB,CAAC;AAEtH,MAAM,CAAC,MAAM,eAAe,GAAG,QAAQ,CAAC,OAAO,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,77 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
"name": "@docmentis/udoc-server",
|
|
3
|
+
"version": "0.8.0",
|
|
4
|
+
"description": "Self-hosted document server for remote access, rendering, and collaboration.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"document-server",
|
|
7
|
+
"server",
|
|
8
|
+
"http",
|
|
9
|
+
"websocket",
|
|
10
|
+
"collaboration",
|
|
11
|
+
"real-time",
|
|
12
|
+
"document",
|
|
13
|
+
"pdf",
|
|
14
|
+
"docx",
|
|
15
|
+
"pptx",
|
|
16
|
+
"xlsx",
|
|
17
|
+
"word",
|
|
18
|
+
"powerpoint",
|
|
19
|
+
"excel",
|
|
20
|
+
"office",
|
|
21
|
+
"render",
|
|
22
|
+
"docmentis",
|
|
23
|
+
"udoc",
|
|
24
|
+
"webassembly",
|
|
25
|
+
"wasm"
|
|
26
|
+
],
|
|
27
|
+
"homepage": "https://www.docmentis.com/docs",
|
|
28
|
+
"license": "MIT OR Apache-2.0",
|
|
29
|
+
"repository": {
|
|
30
|
+
"type": "git",
|
|
31
|
+
"url": "git+https://github.com/docMentis/docmentis-udoc.git",
|
|
32
|
+
"directory": "packages/udoc-server"
|
|
33
|
+
},
|
|
34
|
+
"type": "module",
|
|
35
|
+
"files": [
|
|
36
|
+
"dist",
|
|
37
|
+
"config.example.toml",
|
|
38
|
+
"LICENSE-MIT",
|
|
39
|
+
"LICENSE-APACHE"
|
|
40
|
+
],
|
|
41
|
+
"publishConfig": {
|
|
42
|
+
"access": "public"
|
|
43
|
+
},
|
|
44
|
+
"main": "./dist/index.js",
|
|
45
|
+
"types": "./dist/index.d.ts",
|
|
46
|
+
"exports": {
|
|
47
|
+
".": {
|
|
48
|
+
"types": "./dist/index.d.ts",
|
|
49
|
+
"import": "./dist/index.js"
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
"bin": {
|
|
53
|
+
"udoc-server": "dist/main.js"
|
|
54
|
+
},
|
|
55
|
+
"engines": {
|
|
56
|
+
"node": ">=22.18"
|
|
57
|
+
},
|
|
58
|
+
"scripts": {
|
|
59
|
+
"dev": "tsc -p tsconfig.json --watch",
|
|
60
|
+
"build": "npm run clean && node scripts/check-version.mjs && tsc -p tsconfig.json && chmod +x dist/main.js",
|
|
61
|
+
"typecheck": "tsc -p tsconfig.json --noEmit && tsc -p tsconfig.test.json",
|
|
62
|
+
"test": "node --test \"test/**/*.test.ts\"",
|
|
63
|
+
"clean": "rm -rf dist"
|
|
64
|
+
},
|
|
65
|
+
"dependencies": {
|
|
66
|
+
"@docmentis/udoc-node": "0.8.0",
|
|
67
|
+
"smol-toml": "^1.9.0",
|
|
68
|
+
"ws": "^8.21.3",
|
|
69
|
+
"yauzl": "^3.4.0"
|
|
70
|
+
},
|
|
71
|
+
"devDependencies": {
|
|
72
|
+
"@types/ws": "^8.18.1",
|
|
73
|
+
"@types/yauzl": "^3.4.0",
|
|
74
|
+
"@types/yazl": "^3.3.1",
|
|
75
|
+
"yazl": "^3.3.1"
|
|
76
|
+
}
|
|
77
|
+
}
|