rmapi-js 9.0.3 → 10.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/dist/index.d.ts +14 -9
- package/dist/index.js +32 -32
- package/dist/raw.d.ts +38 -14
- package/dist/raw.js +31 -22
- package/dist/rmapi-js.esm.min.js +12 -12
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type BackgroundFilter, type CollectionContent, type Content, type DocumentContent, type Metadata, type Orientation, type RawRemarkableApi, type SimpleEntry, type Tag, type TemplateContent, type TextAlignment, type ZoomMode } from "./raw";
|
|
2
2
|
export { HashNotFoundError, ValidationError } from "./error";
|
|
3
|
-
export type { BackgroundFilter, CollectionContent, Content, CPageNumberValue, CPagePage, CPageStringValue, CPages, CPageUUID, DocumentContent, DocumentMetadata, Entries, FileType, KeyboardMetadata, Metadata, Orientation, PageTag, RawEntry, RawRemarkableApi, SchemaVersion, SimpleEntry, Tag, TemplateContent, TextAlignment, UploadMimeType, ZoomMode, } from "./raw";
|
|
3
|
+
export type { BackgroundFilter, CollectionContent, Content, CPageNumberValue, CPagePage, CPageStringValue, CPages, CPageUUID, DocumentContent, DocumentMetadata, Entries, FileType, KeyboardMetadata, LegacyCollectionContent, LegacyDocumentContent, Metadata, Orientation, PageTag, RawEntry, RawRemarkableApi, SchemaVersion, SimpleEntry, Tag, TemplateContent, TextAlignment, UploadMimeType, ZoomMode, } from "./raw";
|
|
4
4
|
/** common properties shared by collections and documents */
|
|
5
5
|
export interface EntryCommon {
|
|
6
6
|
/** the document id, a uuid4 */
|
|
@@ -21,7 +21,7 @@ export interface EntryCommon {
|
|
|
21
21
|
*/
|
|
22
22
|
parent?: string;
|
|
23
23
|
/** any tags the entry might have */
|
|
24
|
-
tags?: Tag[];
|
|
24
|
+
tags?: Tag[] | string[];
|
|
25
25
|
}
|
|
26
26
|
/** a folder, referred to in the api as a collection */
|
|
27
27
|
export interface CollectionEntry extends EntryCommon {
|
|
@@ -228,10 +228,11 @@ export interface RemarkableApi {
|
|
|
228
228
|
* the low-level api to get the raw text of the `.content` file in the
|
|
229
229
|
* `RawEntry` for this hash.
|
|
230
230
|
*
|
|
231
|
+
* @param id - the id of the item (as returned by `listIds`)
|
|
231
232
|
* @param hash - the hash of the item to get content for
|
|
232
233
|
* @returns the content
|
|
233
234
|
*/
|
|
234
|
-
getContent(hash: string): Promise<Content>;
|
|
235
|
+
getContent(id: string, hash: string): Promise<Content>;
|
|
235
236
|
/**
|
|
236
237
|
* get the metadata from an item hash
|
|
237
238
|
*
|
|
@@ -243,30 +244,33 @@ export interface RemarkableApi {
|
|
|
243
244
|
* the low-level api to get the raw text of the `.metadata` file in the
|
|
244
245
|
* `RawEntry` for this hash.
|
|
245
246
|
*
|
|
247
|
+
* @param id - the id of the item (as returned by `listIds`)
|
|
246
248
|
* @param hash - the hash of the item to get metadata for
|
|
247
249
|
* @returns the metadata
|
|
248
250
|
*/
|
|
249
|
-
getMetadata(hash: string): Promise<Metadata>;
|
|
251
|
+
getMetadata(id: string, hash: string): Promise<Metadata>;
|
|
250
252
|
/**
|
|
251
253
|
* get the pdf associated with a document hash
|
|
252
254
|
*
|
|
253
255
|
* This returns the raw input pdf, not the rendered pdf with any markup.
|
|
254
256
|
*
|
|
257
|
+
* @param id - the id of the document (as returned by `listIds`)
|
|
255
258
|
* @param hash - the hash of the document to get the pdf for (e.g. the hash
|
|
256
259
|
* received from `listItems`)
|
|
257
260
|
* @returns the pdf bytes
|
|
258
261
|
*/
|
|
259
|
-
getPdf(hash: string): Promise<Uint8Array>;
|
|
262
|
+
getPdf(id: string, hash: string): Promise<Uint8Array>;
|
|
260
263
|
/**
|
|
261
264
|
* get the epub associated with a document hash
|
|
262
265
|
*
|
|
263
266
|
* This returns the raw input epub if a document was created from an epub.
|
|
264
267
|
*
|
|
265
|
-
* @param
|
|
268
|
+
* @param id - the id of the document (as returned by `listIds`)
|
|
269
|
+
* @param hash - the hash of the document to get the epub for (e.g. the hash
|
|
266
270
|
* received from `listItems`)
|
|
267
271
|
* @returns the epub bytes
|
|
268
272
|
*/
|
|
269
|
-
getEpub(hash: string): Promise<Uint8Array>;
|
|
273
|
+
getEpub(id: string, hash: string): Promise<Uint8Array>;
|
|
270
274
|
/**
|
|
271
275
|
* get the entire contents of a remarkable document
|
|
272
276
|
*
|
|
@@ -278,10 +282,11 @@ export interface RemarkableApi {
|
|
|
278
282
|
* of the document, but this format isn't understood enoguh to reput this on a
|
|
279
283
|
* different remarkable, so that functionality is currently disabled.
|
|
280
284
|
*
|
|
281
|
-
* @param
|
|
285
|
+
* @param id - the id of the document (as returned by `listIds`)
|
|
286
|
+
* @param hash - the hash of the document to get contents for (e.g. the
|
|
282
287
|
* hash received from `listItems`)
|
|
283
288
|
*/
|
|
284
|
-
getDocument(hash: string): Promise<Uint8Array>;
|
|
289
|
+
getDocument(id: string, hash: string): Promise<Uint8Array>;
|
|
285
290
|
/**
|
|
286
291
|
* use the low-level api to add a pdf document
|
|
287
292
|
*
|
package/dist/index.js
CHANGED
|
@@ -180,18 +180,18 @@ class Remarkable {
|
|
|
180
180
|
}
|
|
181
181
|
}
|
|
182
182
|
async #convertEntry({ hash, id }) {
|
|
183
|
-
const { entries } = await this.raw.getEntries(hash);
|
|
183
|
+
const { entries } = await this.raw.getEntries(`${id}.docSchema`, hash);
|
|
184
184
|
const metaEnt = entries.find((ent) => ent.id.endsWith(".metadata"));
|
|
185
185
|
const contentEnt = entries.find((ent) => ent.id.endsWith(".content"));
|
|
186
186
|
if (metaEnt === undefined) {
|
|
187
187
|
throw new Error(`couldn't find metadata for hash ${hash}`);
|
|
188
188
|
}
|
|
189
189
|
const [{ visibleName, lastModified, pinned, parent, lastOpened, new: isNew, source, }, content,] = await Promise.all([
|
|
190
|
-
this.raw.getMetadata(metaEnt.hash),
|
|
190
|
+
this.raw.getMetadata(metaEnt.id, metaEnt.hash),
|
|
191
191
|
// collections don't always have content, since content only lists tags
|
|
192
192
|
contentEnt === undefined
|
|
193
193
|
? Promise.resolve({ fileType: undefined, tags: undefined })
|
|
194
|
-
: this.raw.getContent(contentEnt.hash),
|
|
194
|
+
: this.raw.getContent(contentEnt.id, contentEnt.hash),
|
|
195
195
|
]);
|
|
196
196
|
if ("templateVersion" in content) {
|
|
197
197
|
return {
|
|
@@ -240,55 +240,55 @@ class Remarkable {
|
|
|
240
240
|
}
|
|
241
241
|
async listIds(refresh = false) {
|
|
242
242
|
const [hash] = await this.#getRootHash(refresh);
|
|
243
|
-
const { entries } = await this.raw.getEntries(hash);
|
|
243
|
+
const { entries } = await this.raw.getEntries("root.docSchema", hash);
|
|
244
244
|
return entries.map(({ id, hash }) => ({ id, hash }));
|
|
245
245
|
}
|
|
246
|
-
async getContent(hash) {
|
|
247
|
-
const { entries } = await this.raw.getEntries(hash);
|
|
246
|
+
async getContent(id, hash) {
|
|
247
|
+
const { entries } = await this.raw.getEntries(`${id}.docSchema`, hash);
|
|
248
248
|
const [cont] = entries.filter((e) => e.id.endsWith(".content"));
|
|
249
249
|
if (cont === undefined) {
|
|
250
250
|
throw new Error(`couldn't find contents for hash ${hash}`);
|
|
251
251
|
}
|
|
252
252
|
else {
|
|
253
|
-
return await this.raw.getContent(cont.hash);
|
|
253
|
+
return await this.raw.getContent(cont.id, cont.hash);
|
|
254
254
|
}
|
|
255
255
|
}
|
|
256
|
-
async getMetadata(hash) {
|
|
257
|
-
const { entries } = await this.raw.getEntries(hash);
|
|
256
|
+
async getMetadata(id, hash) {
|
|
257
|
+
const { entries } = await this.raw.getEntries(`${id}.docSchema`, hash);
|
|
258
258
|
const [meta] = entries.filter((e) => e.id.endsWith(".metadata"));
|
|
259
259
|
if (meta === undefined) {
|
|
260
260
|
throw new Error(`couldn't find metadata for hash ${hash}`);
|
|
261
261
|
}
|
|
262
262
|
else {
|
|
263
|
-
return await this.raw.getMetadata(meta.hash);
|
|
263
|
+
return await this.raw.getMetadata(meta.id, meta.hash);
|
|
264
264
|
}
|
|
265
265
|
}
|
|
266
|
-
async getPdf(hash) {
|
|
267
|
-
const { entries } = await this.raw.getEntries(hash);
|
|
266
|
+
async getPdf(id, hash) {
|
|
267
|
+
const { entries } = await this.raw.getEntries(`${id}.docSchema`, hash);
|
|
268
268
|
const [pdf] = entries.filter((e) => e.id.endsWith(".pdf"));
|
|
269
269
|
if (pdf === undefined) {
|
|
270
270
|
throw new Error(`couldn't find pdf for hash ${hash}`);
|
|
271
271
|
}
|
|
272
272
|
else {
|
|
273
|
-
return await this.raw.getHash(pdf.hash);
|
|
273
|
+
return await this.raw.getHash(pdf.id, pdf.hash);
|
|
274
274
|
}
|
|
275
275
|
}
|
|
276
|
-
async getEpub(hash) {
|
|
277
|
-
const { entries } = await this.raw.getEntries(hash);
|
|
276
|
+
async getEpub(id, hash) {
|
|
277
|
+
const { entries } = await this.raw.getEntries(`${id}.docSchema`, hash);
|
|
278
278
|
const [epub] = entries.filter((e) => e.id.endsWith(".epub"));
|
|
279
279
|
if (epub === undefined) {
|
|
280
280
|
throw new Error(`couldn't find epub for hash ${hash}`);
|
|
281
281
|
}
|
|
282
282
|
else {
|
|
283
|
-
return await this.raw.getHash(epub.hash);
|
|
283
|
+
return await this.raw.getHash(epub.id, epub.hash);
|
|
284
284
|
}
|
|
285
285
|
}
|
|
286
|
-
async getDocument(hash) {
|
|
287
|
-
const { entries } = await this.raw.getEntries(hash);
|
|
286
|
+
async getDocument(id, hash) {
|
|
287
|
+
const { entries } = await this.raw.getEntries(`${id}.docSchema`, hash);
|
|
288
288
|
const zip = new JSZip();
|
|
289
289
|
for (const entry of entries) {
|
|
290
290
|
// TODO if this is .metadata we might want to assert type === "DocumentType"
|
|
291
|
-
zip.file(entry.id, this.raw.getHash(entry.hash));
|
|
291
|
+
zip.file(entry.id, this.raw.getHash(entry.id, entry.hash));
|
|
292
292
|
}
|
|
293
293
|
return zip.generateAsync({ type: "uint8array" });
|
|
294
294
|
}
|
|
@@ -344,7 +344,7 @@ class Remarkable {
|
|
|
344
344
|
// now fetch root entries and upload this file entry
|
|
345
345
|
const [[collectionEntry, uploadCollection], { entries: rootEntries }] = await Promise.all([
|
|
346
346
|
this.raw.putEntries(id, [contentEntry, metadataEntry, pagedataEntry, fileEntry], schemaVersion),
|
|
347
|
-
this.raw.getEntries(rootHash),
|
|
347
|
+
this.raw.getEntries("root.docSchema", rootHash),
|
|
348
348
|
]);
|
|
349
349
|
// now upload a new root entry
|
|
350
350
|
rootEntries.push(collectionEntry);
|
|
@@ -398,7 +398,7 @@ class Remarkable {
|
|
|
398
398
|
// now fetch root entries and upload this file entry
|
|
399
399
|
const [[collectionEntry, uploadCollection], { entries: rootEntries }] = await Promise.all([
|
|
400
400
|
this.raw.putEntries(id, [contentEntry, metadataEntry], schemaVersion),
|
|
401
|
-
this.raw.getEntries(rootHash),
|
|
401
|
+
this.raw.getEntries("root.docSchema", rootHash),
|
|
402
402
|
]);
|
|
403
403
|
// now upload a new root entry
|
|
404
404
|
rootEntries.push(collectionEntry);
|
|
@@ -428,13 +428,13 @@ class Remarkable {
|
|
|
428
428
|
}
|
|
429
429
|
/** edit just a content entry */
|
|
430
430
|
async #editContentRaw(id, hash, update, schemaVersion) {
|
|
431
|
-
const { entries } = await this.raw.getEntries(hash);
|
|
431
|
+
const { entries } = await this.raw.getEntries(`${id}.docSchema`, hash);
|
|
432
432
|
const contInd = entries.findIndex((ent) => ent.id.endsWith(".content"));
|
|
433
433
|
const contEntry = entries[contInd];
|
|
434
434
|
if (contEntry === undefined) {
|
|
435
435
|
throw new Error("internal error: couldn't find content in entry hash");
|
|
436
436
|
}
|
|
437
|
-
const cont = await this.raw.getContent(contEntry.hash);
|
|
437
|
+
const cont = await this.raw.getContent(contEntry.id, contEntry.hash);
|
|
438
438
|
Object.assign(cont, update);
|
|
439
439
|
const [newContEntry, uploadCont] = await this.raw.putContent(contEntry.id, cont);
|
|
440
440
|
entries[contInd] = newContEntry;
|
|
@@ -445,7 +445,7 @@ class Remarkable {
|
|
|
445
445
|
/** fully sync a content edit */
|
|
446
446
|
async #editContent(hash, update, expectedType, refresh) {
|
|
447
447
|
const [rootHash, generation, schemaVersion] = await this.#getRootHash(refresh);
|
|
448
|
-
const { entries } = await this.raw.getEntries(rootHash);
|
|
448
|
+
const { entries } = await this.raw.getEntries("root.docSchema", rootHash);
|
|
449
449
|
const hashInd = entries.findIndex((ent) => ent.hash === hash);
|
|
450
450
|
const hashEnt = entries[hashInd];
|
|
451
451
|
if (hashEnt === undefined) {
|
|
@@ -453,7 +453,7 @@ class Remarkable {
|
|
|
453
453
|
}
|
|
454
454
|
const [[newEnt, uploadEnt], meta] = await Promise.all([
|
|
455
455
|
this.#editContentRaw(hashEnt.id, hash, update, schemaVersion),
|
|
456
|
-
this.getMetadata(hash),
|
|
456
|
+
this.getMetadata(hashEnt.id, hash),
|
|
457
457
|
]);
|
|
458
458
|
if (meta.type !== expectedType) {
|
|
459
459
|
throw new Error(`expected type ${expectedType} but got ${meta.type} for hash ${hash}`);
|
|
@@ -477,13 +477,13 @@ class Remarkable {
|
|
|
477
477
|
return await this.#editContent(hash, content, "TemplateType", refresh);
|
|
478
478
|
}
|
|
479
479
|
async #editMetaRaw(id, hash, update, schemaVersion) {
|
|
480
|
-
const { entries } = await this.raw.getEntries(hash);
|
|
480
|
+
const { entries } = await this.raw.getEntries(`${id}.docSchema`, hash);
|
|
481
481
|
const metaInd = entries.findIndex((ent) => ent.id.endsWith(".metadata"));
|
|
482
482
|
const metaEntry = entries[metaInd];
|
|
483
483
|
if (metaEntry === undefined) {
|
|
484
484
|
throw new Error("internal error: couldn't find metadata in entry hash");
|
|
485
485
|
}
|
|
486
|
-
const meta = await this.raw.getMetadata(metaEntry.hash);
|
|
486
|
+
const meta = await this.raw.getMetadata(metaEntry.id, metaEntry.hash);
|
|
487
487
|
Object.assign(meta, update);
|
|
488
488
|
const [newMetaEntry, uploadMeta] = await this.raw.putMetadata(metaEntry.id, meta);
|
|
489
489
|
entries[metaInd] = newMetaEntry;
|
|
@@ -493,7 +493,7 @@ class Remarkable {
|
|
|
493
493
|
}
|
|
494
494
|
async #editMeta(hash, update, refresh = false) {
|
|
495
495
|
const [rootHash, generation, schemaVersion] = await this.#getRootHash(refresh);
|
|
496
|
-
const { entries } = await this.raw.getEntries(rootHash);
|
|
496
|
+
const { entries } = await this.raw.getEntries("root.docSchema", rootHash);
|
|
497
497
|
const hashInd = entries.findIndex((ent) => ent.hash === hash);
|
|
498
498
|
const hashEnt = entries[hashInd];
|
|
499
499
|
if (hashEnt === undefined) {
|
|
@@ -531,7 +531,7 @@ class Remarkable {
|
|
|
531
531
|
throw new ValidationError(parent, idReg, "parent must be a valid document id");
|
|
532
532
|
}
|
|
533
533
|
const [rootHash, generation, schemaVersion] = await this.#getRootHash(refresh);
|
|
534
|
-
const { entries } = await this.raw.getEntries(rootHash);
|
|
534
|
+
const { entries } = await this.raw.getEntries("root.docSchema", rootHash);
|
|
535
535
|
const hashSet = new Set(hashes);
|
|
536
536
|
const toUpdate = [];
|
|
537
537
|
const newEntries = [];
|
|
@@ -568,15 +568,15 @@ class Remarkable {
|
|
|
568
568
|
// should only go one step) to track all hashes encountered
|
|
569
569
|
// NOTE that we could increase the cache in this process, or it's possible
|
|
570
570
|
// for other calls to increase the cache with misc values.
|
|
571
|
-
const base = await this.raw.getEntries(rootHash);
|
|
571
|
+
const base = await this.raw.getEntries("root.docSchema", rootHash);
|
|
572
572
|
let entries = [base.entries];
|
|
573
573
|
let nextEntries = [];
|
|
574
574
|
while (entries.length) {
|
|
575
575
|
for (const entryList of entries) {
|
|
576
|
-
for (const { hash, type } of entryList) {
|
|
576
|
+
for (const { hash, type, id } of entryList) {
|
|
577
577
|
toDelete.add(hash);
|
|
578
578
|
if (type === 80000000) {
|
|
579
|
-
nextEntries.push(this.raw.getEntries(hash));
|
|
579
|
+
nextEntries.push(this.raw.getEntries(`${id}.docSchema`, hash));
|
|
580
580
|
}
|
|
581
581
|
}
|
|
582
582
|
}
|
package/dist/raw.d.ts
CHANGED
|
@@ -147,13 +147,21 @@ export interface CollectionContent {
|
|
|
147
147
|
/** collections don't have a file type */
|
|
148
148
|
fileType?: undefined;
|
|
149
149
|
}
|
|
150
|
+
/** legacy collection content can store tags as raw strings */
|
|
151
|
+
export interface LegacyCollectionContent {
|
|
152
|
+
/** the legacy tag names for the collection */
|
|
153
|
+
tags?: string[];
|
|
154
|
+
/** collections don't have a file type */
|
|
155
|
+
fileType?: undefined;
|
|
156
|
+
}
|
|
150
157
|
/**
|
|
151
158
|
* content metadata, stored with the "content" extension
|
|
152
159
|
*
|
|
153
160
|
* This largely contains description of how to render the document, rather than
|
|
154
161
|
* metadata about it.
|
|
155
162
|
*/
|
|
156
|
-
|
|
163
|
+
/** fields shared by current and legacy document content payloads */
|
|
164
|
+
export interface CommonDocumentContent {
|
|
157
165
|
/**
|
|
158
166
|
* which page to use for the thumbnail
|
|
159
167
|
*
|
|
@@ -209,8 +217,6 @@ export interface DocumentContent {
|
|
|
209
217
|
redirectionPageMap?: number[];
|
|
210
218
|
/** ostensibly the size in bytes of the file, but this differs from other measurements */
|
|
211
219
|
sizeInBytes: string;
|
|
212
|
-
/** document tags for this document */
|
|
213
|
-
tags?: Tag[];
|
|
214
220
|
/** text alignment for this document */
|
|
215
221
|
textAlignment: TextAlignment;
|
|
216
222
|
/**
|
|
@@ -269,6 +275,16 @@ export interface DocumentContent {
|
|
|
269
275
|
*/
|
|
270
276
|
viewBackgroundFilter?: BackgroundFilter;
|
|
271
277
|
}
|
|
278
|
+
/** document content with modern structured tag payloads */
|
|
279
|
+
export interface DocumentContent extends CommonDocumentContent {
|
|
280
|
+
/** document tags for this document */
|
|
281
|
+
tags?: Tag[];
|
|
282
|
+
}
|
|
283
|
+
/** legacy document content can store tags as raw strings */
|
|
284
|
+
export interface LegacyDocumentContent extends CommonDocumentContent {
|
|
285
|
+
/** the legacy tag names for this document */
|
|
286
|
+
tags?: string[];
|
|
287
|
+
}
|
|
272
288
|
/**
|
|
273
289
|
* content metadata, stored with the "content" extension
|
|
274
290
|
*
|
|
@@ -307,7 +323,7 @@ export interface TemplateContent {
|
|
|
307
323
|
items: object[];
|
|
308
324
|
}
|
|
309
325
|
/** content metadata for any item */
|
|
310
|
-
export type Content = CollectionContent | DocumentContent | TemplateContent;
|
|
326
|
+
export type Content = CollectionContent | LegacyCollectionContent | DocumentContent | LegacyDocumentContent | TemplateContent;
|
|
311
327
|
/**
|
|
312
328
|
* item level metadata
|
|
313
329
|
*
|
|
@@ -431,50 +447,58 @@ export interface RawRemarkableApi {
|
|
|
431
447
|
/**
|
|
432
448
|
* get the raw binary data associated with a hash
|
|
433
449
|
*
|
|
450
|
+
* @param fileName - the logical file name (`<id>.<ext>` for files, or
|
|
451
|
+
* `<id>.docSchema` / `"root.docSchema"` for entry indexes). reMarkable
|
|
452
|
+
* validates this against the rm-filename header.
|
|
434
453
|
* @param hash - the hash to get the data for
|
|
435
454
|
* @returns the data
|
|
436
455
|
*/
|
|
437
|
-
getHash(hash: string): Promise<Uint8Array>;
|
|
456
|
+
getHash(fileName: string, hash: string): Promise<Uint8Array>;
|
|
438
457
|
/**
|
|
439
458
|
* get raw text data associated with a hash
|
|
440
459
|
*
|
|
441
460
|
* We assume text data are small, and so cache the entire text. If you want to
|
|
442
461
|
* avoid this, use {@link getHash | `getHash`} combined with a TextDecoder.
|
|
443
462
|
|
|
463
|
+
* @param fileName - the logical file name (see {@link getHash})
|
|
444
464
|
* @param hash - the hash to get text for
|
|
445
465
|
* @returns the text
|
|
446
466
|
*/
|
|
447
|
-
getText(hash: string): Promise<string>;
|
|
467
|
+
getText(fileName: string, hash: string): Promise<string>;
|
|
448
468
|
/**
|
|
449
469
|
* get the entries associated with a list hash
|
|
450
470
|
*
|
|
451
471
|
* A list hash is the root hash, or any hash with the type 80000000. NOTE
|
|
452
472
|
* these are hashed differently than files.
|
|
453
473
|
|
|
474
|
+
* @param fileName - `"root.docSchema"` for the root, or `"<id>.docSchema"`
|
|
475
|
+
* for a sub-document's entry index
|
|
454
476
|
* @param hash - the hash to get entries for
|
|
455
477
|
* @returns the entries
|
|
456
478
|
*/
|
|
457
|
-
getEntries(hash: string): Promise<Entries>;
|
|
479
|
+
getEntries(fileName: string, hash: string): Promise<Entries>;
|
|
458
480
|
/**
|
|
459
481
|
* get the parsed and validated `Content` of a content hash
|
|
460
482
|
*
|
|
461
483
|
* Use {@link getText | `getText`} combined with `JSON.parse` to bypass
|
|
462
484
|
* validation
|
|
463
485
|
|
|
486
|
+
* @param fileName - typically `"<id>.content"`
|
|
464
487
|
* @param hash - the hash to get Content for
|
|
465
488
|
* @returns the content
|
|
466
489
|
*/
|
|
467
|
-
getContent(hash: string): Promise<Content>;
|
|
490
|
+
getContent(fileName: string, hash: string): Promise<Content>;
|
|
468
491
|
/**
|
|
469
492
|
* get the parsed and validated `Metadata` of a metadata hash
|
|
470
493
|
*
|
|
471
494
|
* Use {@link getText | `getText`} combined with `JSON.parse` to bypass
|
|
472
495
|
* validation
|
|
473
496
|
|
|
497
|
+
* @param fileName - typically `"<id>.metadata"`
|
|
474
498
|
* @param hash - the hash to get Metadata for
|
|
475
499
|
* @returns the metadata
|
|
476
500
|
*/
|
|
477
|
-
getMetadata(hash: string): Promise<Metadata>;
|
|
501
|
+
getMetadata(fileName: string, hash: string): Promise<Metadata>;
|
|
478
502
|
/**
|
|
479
503
|
* update the current root hash
|
|
480
504
|
*
|
|
@@ -564,11 +588,11 @@ export declare class RawRemarkable implements RawRemarkableApi {
|
|
|
564
588
|
constructor(authedFetch: AuthedFetch, cache: Map<string, string | null>, rawHost: string, uploadHost: string);
|
|
565
589
|
/** make an authorized request to remarkable */
|
|
566
590
|
getRootHash(): Promise<[string, number, SchemaVersion]>;
|
|
567
|
-
getHash(hash: string): Promise<Uint8Array>;
|
|
568
|
-
getText(hash: string): Promise<string>;
|
|
569
|
-
getEntries(hash: string): Promise<Entries>;
|
|
570
|
-
getContent(hash: string): Promise<Content>;
|
|
571
|
-
getMetadata(hash: string): Promise<Metadata>;
|
|
591
|
+
getHash(fileName: string, hash: string): Promise<Uint8Array>;
|
|
592
|
+
getText(fileName: string, hash: string): Promise<string>;
|
|
593
|
+
getEntries(fileName: string, hash: string): Promise<Entries>;
|
|
594
|
+
getContent(fileName: string, hash: string): Promise<Content>;
|
|
595
|
+
getMetadata(fileName: string, hash: string): Promise<Metadata>;
|
|
572
596
|
putRootHash(hash: string, generation: number, broadcast?: boolean): Promise<[string, number]>;
|
|
573
597
|
putFile(id: string, bytes: Uint8Array): Promise<[RawEntry, Promise<void>]>;
|
|
574
598
|
putText(id: string, text: string): Promise<[RawEntry, Promise<void>]>;
|
package/dist/raw.js
CHANGED
|
@@ -65,7 +65,10 @@ const cPages = properties({
|
|
|
65
65
|
const collectionContent = properties(undefined, {
|
|
66
66
|
tags: elements(tag),
|
|
67
67
|
});
|
|
68
|
-
const
|
|
68
|
+
const legacyCollectionContent = properties(undefined, {
|
|
69
|
+
tags: elements(string()),
|
|
70
|
+
});
|
|
71
|
+
const documentContentRequired = {
|
|
69
72
|
coverPageNumber: int32(),
|
|
70
73
|
documentMetadata,
|
|
71
74
|
extraMetadata: values(string()),
|
|
@@ -77,7 +80,8 @@ const documentContent = properties({
|
|
|
77
80
|
sizeInBytes: string(),
|
|
78
81
|
textAlignment: enumeration("", "justify", "left"),
|
|
79
82
|
textScale: float64(),
|
|
80
|
-
}
|
|
83
|
+
};
|
|
84
|
+
const documentContentOptional = {
|
|
81
85
|
cPages,
|
|
82
86
|
customZoomCenterX: float64(),
|
|
83
87
|
customZoomCenterY: float64(),
|
|
@@ -97,7 +101,6 @@ const documentContent = properties({
|
|
|
97
101
|
pages: nullable(elements(string())),
|
|
98
102
|
pageTags: elements(pageTag),
|
|
99
103
|
redirectionPageMap: elements(int32()),
|
|
100
|
-
tags: elements(tag),
|
|
101
104
|
transform: properties(undefined, {
|
|
102
105
|
m11: float64(),
|
|
103
106
|
m12: float64(),
|
|
@@ -112,6 +115,14 @@ const documentContent = properties({
|
|
|
112
115
|
// eslint-disable-next-line spellcheck/spell-checker
|
|
113
116
|
viewBackgroundFilter: enumeration("off", "fullpage"),
|
|
114
117
|
zoomMode: enumeration("bestFit", "customFit", "fitToHeight", "fitToWidth"),
|
|
118
|
+
};
|
|
119
|
+
const documentContent = properties(documentContentRequired, {
|
|
120
|
+
...documentContentOptional,
|
|
121
|
+
tags: elements(tag),
|
|
122
|
+
}, true);
|
|
123
|
+
const legacyDocumentContent = properties(documentContentRequired, {
|
|
124
|
+
...documentContentOptional,
|
|
125
|
+
tags: elements(string()),
|
|
115
126
|
}, true);
|
|
116
127
|
const templateContent = properties({
|
|
117
128
|
name: string(),
|
|
@@ -222,23 +233,23 @@ export class RawRemarkable {
|
|
|
222
233
|
return [hash, generation, schemaVersion];
|
|
223
234
|
}
|
|
224
235
|
}
|
|
225
|
-
async #getHash(hash) {
|
|
236
|
+
async #getHash(fileName, hash) {
|
|
226
237
|
if (!hashReg.test(hash)) {
|
|
227
238
|
throw new ValidationError(hash, hashReg, "hash was not a valid hash");
|
|
228
239
|
}
|
|
229
|
-
const resp = await this.#authedFetch("GET", `${this.#rawHost}/sync/v3/files/${hash}
|
|
240
|
+
const resp = await this.#authedFetch("GET", `${this.#rawHost}/sync/v3/files/${hash}`, { headers: { "rm-filename": fileName } });
|
|
230
241
|
// TODO switch to `.bytes()`.
|
|
231
242
|
const raw = await resp.arrayBuffer();
|
|
232
243
|
return new Uint8Array(raw);
|
|
233
244
|
}
|
|
234
|
-
async getHash(hash) {
|
|
245
|
+
async getHash(fileName, hash) {
|
|
235
246
|
const cached = this.#cache.get(hash);
|
|
236
247
|
if (cached != null) {
|
|
237
248
|
const enc = new TextEncoder();
|
|
238
249
|
return enc.encode(cached);
|
|
239
250
|
}
|
|
240
251
|
else {
|
|
241
|
-
const res = await this.#getHash(hash);
|
|
252
|
+
const res = await this.#getHash(fileName, hash);
|
|
242
253
|
// mark that we know hash exists
|
|
243
254
|
const cacheVal = this.#cache.get(hash);
|
|
244
255
|
if (cacheVal === undefined) {
|
|
@@ -247,22 +258,22 @@ export class RawRemarkable {
|
|
|
247
258
|
return res;
|
|
248
259
|
}
|
|
249
260
|
}
|
|
250
|
-
async getText(hash) {
|
|
261
|
+
async getText(fileName, hash) {
|
|
251
262
|
const cached = this.#cache.get(hash);
|
|
252
263
|
if (cached != null) {
|
|
253
264
|
return cached;
|
|
254
265
|
}
|
|
255
266
|
else {
|
|
256
267
|
// NOTE two simultaneous requests will fetch twice
|
|
257
|
-
const raw = await this.#getHash(hash);
|
|
268
|
+
const raw = await this.#getHash(fileName, hash);
|
|
258
269
|
const dec = new TextDecoder();
|
|
259
270
|
const res = dec.decode(raw);
|
|
260
271
|
this.#cache.set(hash, res);
|
|
261
272
|
return res;
|
|
262
273
|
}
|
|
263
274
|
}
|
|
264
|
-
async getEntries(hash) {
|
|
265
|
-
const rawFile = await this.getText(hash);
|
|
275
|
+
async getEntries(fileName, hash) {
|
|
276
|
+
const rawFile = await this.getText(fileName, hash);
|
|
266
277
|
const [version, ...rest] = rawFile.slice(0, -1).split("\n");
|
|
267
278
|
if (version === "3") {
|
|
268
279
|
return { entries: rest.map(parseRawEntryLine) };
|
|
@@ -290,16 +301,18 @@ export class RawRemarkable {
|
|
|
290
301
|
throw new Error(`schema version ${version} not supported`);
|
|
291
302
|
}
|
|
292
303
|
}
|
|
293
|
-
async getContent(hash) {
|
|
294
|
-
const raw = await this.getText(hash);
|
|
304
|
+
async getContent(fileName, hash) {
|
|
305
|
+
const raw = await this.getText(fileName, hash);
|
|
295
306
|
const loaded = JSON.parse(raw);
|
|
296
307
|
// jtd can't verify non-discriminated unions, in this case, we have fileType
|
|
297
308
|
// defined or not. As a result, we try each, and concatenate the errors at the end
|
|
298
309
|
const errors = [];
|
|
299
310
|
for (const [name, valid] of [
|
|
300
311
|
["collection", collectionContent],
|
|
312
|
+
["legacy collection", legacyCollectionContent],
|
|
301
313
|
["template", templateContent],
|
|
302
314
|
["document", documentContent],
|
|
315
|
+
["legacy document", legacyDocumentContent],
|
|
303
316
|
]) {
|
|
304
317
|
try {
|
|
305
318
|
if (valid.guardAssert(loaded))
|
|
@@ -313,8 +326,8 @@ export class RawRemarkable {
|
|
|
313
326
|
const joined = errors.join("\n\nor\n\n");
|
|
314
327
|
throw new Error(`invalid content: ${joined}`);
|
|
315
328
|
}
|
|
316
|
-
async getMetadata(hash) {
|
|
317
|
-
const raw = await this.getText(hash);
|
|
329
|
+
async getMetadata(fileName, hash) {
|
|
330
|
+
const raw = await this.getText(fileName, hash);
|
|
318
331
|
const loaded = JSON.parse(raw);
|
|
319
332
|
if (!metadata.guardAssert(loaded))
|
|
320
333
|
throw Error("invalid metadata");
|
|
@@ -345,7 +358,7 @@ export class RawRemarkable {
|
|
|
345
358
|
throw new Error(`new generation ${newGen} was not a safe integer; please file a bug report`);
|
|
346
359
|
}
|
|
347
360
|
}
|
|
348
|
-
async #putFile(
|
|
361
|
+
async #putFile(fileName, hash, bytes) {
|
|
349
362
|
// if the hash is already in the cache, writing is pointless
|
|
350
363
|
if (!this.#cache.has(hash)) {
|
|
351
364
|
const crc = CRC32C.buf(bytes, 0);
|
|
@@ -376,7 +389,7 @@ export class RawRemarkable {
|
|
|
376
389
|
subfiles: 0,
|
|
377
390
|
size: bytes.length,
|
|
378
391
|
};
|
|
379
|
-
return [res, this.#putFile(
|
|
392
|
+
return [res, this.#putFile(id, hash, bytes)];
|
|
380
393
|
}
|
|
381
394
|
async putText(id, text) {
|
|
382
395
|
const enc = new TextEncoder();
|
|
@@ -444,11 +457,7 @@ export class RawRemarkable {
|
|
|
444
457
|
subfiles: entries.length,
|
|
445
458
|
size,
|
|
446
459
|
};
|
|
447
|
-
return [
|
|
448
|
-
res,
|
|
449
|
-
// NOTE when monitoring requests, this had the extension .docSchema appended, but I'm not entirely sure why
|
|
450
|
-
this.#putFile(hash, `${id}.docSchema`, entryBuff),
|
|
451
|
-
];
|
|
460
|
+
return [res, this.#putFile(`${id}.docSchema`, hash, entryBuff)];
|
|
452
461
|
}
|
|
453
462
|
async uploadFile(visibleName, bytes, mime) {
|
|
454
463
|
const enc = new TextEncoder();
|