rmapi-js 11.2.0 → 12.0.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/dist/raw.d.ts CHANGED
@@ -25,11 +25,19 @@ export type RequestMethod = "POST" | "GET" | "PUT" | "DELETE" | "PATCH" | "OPTIO
25
25
  export type UploadMimeType = "application/pdf" | "application/epub+zip" | "folder";
26
26
  /** the schema version */
27
27
  export type SchemaVersion = 3 | 4;
28
- /** an simple entry without any extra information */
29
- export interface SimpleEntry {
30
- /** the document id */
28
+ /**
29
+ * a reference to stored cloud data: an id paired with the hash of its state
30
+ *
31
+ * This is the canonical way to point at something in the cloud. The `id` names
32
+ * *what*: a document's uuid at the high level, or a stored file name (like
33
+ * `<id>.content`) at the low level. The `hash` names *which version*, and
34
+ * changes every time that data mutates. Reads take one of these, and mutations
35
+ * return a fresh one with the new hash.
36
+ */
37
+ export interface ItemRef {
38
+ /** the id of the referenced data: a document uuid, or a stored file name */
31
39
  id: string;
32
- /** the document hash */
40
+ /** the hash of the referenced state */
33
41
  hash: string;
34
42
  }
35
43
  /**
@@ -40,13 +48,9 @@ export interface SimpleEntry {
40
48
  * files, the high level entry will have the same hash and id as the low-level
41
49
  * entry for that collection.
42
50
  */
43
- export interface RawEntry {
51
+ export interface RawEntry extends ItemRef {
44
52
  /** 80000000 for schema 3 collection type or 0 for schema 4 or schema 3 files or */
45
53
  type: 80000000 | 0;
46
- /** the hash of the collection this points to */
47
- hash: string;
48
- /** the unique id of the collection */
49
- id: string;
50
54
  /** the number of subfiles */
51
55
  subfiles: number;
52
56
  /** the total size of everything in the collection */
@@ -410,6 +414,10 @@ export interface Metadata {
410
414
  }
411
415
  /** parse and validate the json text of a `.metadata` file */
412
416
  export declare function parseMetadata(text: string): Metadata;
417
+ type AuthedFetch = (method: RequestMethod, url: string, init?: {
418
+ body?: string | Uint8Array;
419
+ headers?: Record<string, string>;
420
+ }) => Promise<Response>;
413
421
  /**
414
422
  * access to the low-level reMarkable api
415
423
  *
@@ -469,7 +477,10 @@ export declare function parseMetadata(text: string): Metadata;
469
477
  *
470
478
  * Generally all hashes are 64 character hex strings, and all ids are uuid4.
471
479
  */
472
- export interface RawRemarkableApi {
480
+ export declare class RawRemarkable {
481
+ #private;
482
+ constructor(authedFetch: AuthedFetch, cache: Map<string, string | null>, rawHost: string, uploadHost: string);
483
+ /** make an authorized request to remarkable */
473
484
  /**
474
485
  * gets the root hash and the current generation
475
486
  *
@@ -482,66 +493,62 @@ export interface RawRemarkableApi {
482
493
  /**
483
494
  * get the raw binary data associated with a hash
484
495
  *
485
- * @param fileName - the logical file name (`<id>.<ext>` for files, or
486
- * `<id>.docSchema` / `"root.docSchema"` for entry indexes). reMarkable
487
- * validates this against the rm-filename header.
488
- * @param hash - the hash to get the data for
496
+ * @param ref - a reference to the stored file. Its `id` is the logical file
497
+ * name (`<id>.<ext>` for files, or `<id>.docSchema` / `"root.docSchema"`
498
+ * for entry indexes), which reMarkable validates against the rm-filename
499
+ * header. Sub-entries from {@link getEntries | `getEntries`} can be passed
500
+ * directly.
489
501
  * @returns the data
490
502
  */
491
- getHash(fileName: string, hash: string): Promise<Uint8Array>;
503
+ getHash({ id: fileName, hash }: ItemRef): Promise<Uint8Array>;
492
504
  /**
493
505
  * get raw text data associated with a hash
494
506
  *
495
507
  * We assume text data are small, and so cache the entire text. If you want to
496
508
  * avoid this, use {@link getHash | `getHash`} combined with a TextDecoder.
497
-
498
- * @param fileName - the logical file name (see {@link getHash})
499
- * @param hash - the hash to get text for
509
+ *
510
+ * @param ref - a reference to the stored file (see {@link getHash})
500
511
  * @returns the text
501
512
  */
502
- getText(fileName: string, hash: string): Promise<string>;
513
+ getText({ id: fileName, hash }: ItemRef): Promise<string>;
503
514
  /**
504
515
  * get the entries associated with a list hash
505
516
  *
506
517
  * A list hash is the root hash, or any hash with the type 80000000. NOTE
507
518
  * these are hashed differently than files.
508
-
509
- * @param fileName - `"root.docSchema"` for the root, or `"<id>.docSchema"`
510
- * for a sub-document's entry index
511
- * @param hash - the hash to get entries for
519
+ *
520
+ * @param ref - a reference whose `id` is `"root.docSchema"` for the root, or
521
+ * `"<id>.docSchema"` for a sub-document's entry index
512
522
  * @returns the entries
513
523
  */
514
- getEntries(fileName: string, hash: string): Promise<Entries>;
524
+ getEntries(ref: ItemRef): Promise<Entries>;
515
525
  /**
516
526
  * get the parsed and validated `Content` of a content hash
517
527
  *
518
528
  * Use {@link getText | `getText`} combined with `JSON.parse` to bypass
519
529
  * validation
520
-
521
- * @param fileName - typically `"<id>.content"`
522
- * @param hash - the hash to get Content for
530
+ *
531
+ * @param ref - a reference to the stored file, typically `"<id>.content"`
523
532
  * @returns the content
524
533
  */
525
- getContent(fileName: string, hash: string): Promise<Content>;
534
+ getContent(ref: ItemRef): Promise<Content>;
526
535
  /**
527
536
  * get the parsed and validated `Metadata` of a metadata hash
528
537
  *
529
538
  * Use {@link getText | `getText`} combined with `JSON.parse` to bypass
530
539
  * validation
531
-
532
- * @param fileName - typically `"<id>.metadata"`
533
- * @param hash - the hash to get Metadata for
540
+ *
541
+ * @param ref - a reference to the stored file, typically `"<id>.metadata"`
534
542
  * @returns the metadata
535
543
  */
536
- getMetadata(fileName: string, hash: string): Promise<Metadata>;
544
+ getMetadata(ref: ItemRef): Promise<Metadata>;
537
545
  /**
538
546
  * get the parsed reMarkable lines (`.rm`) drawing of a page hash
539
-
540
- * @param fileName - typically `"<id>/<pageid>.rm"`
541
- * @param hash - the hash to get the page for
547
+ *
548
+ * @param ref - a reference to the stored file, typically `"<id>/<pageid>.rm"`
542
549
  * @returns the parsed page
543
550
  */
544
- getRm(fileName: string, hash: string): Promise<RmPage>;
551
+ getRm(ref: ItemRef): Promise<RmPage>;
545
552
  /**
546
553
  * the same as {@link putFile | `putFile`} but rendering an `RmPage` to `.rm`
547
554
  * bytes
@@ -585,7 +592,7 @@ export interface RawRemarkableApi {
585
592
  */
586
593
  putFile(fileName: string, bytes: Uint8Array): Promise<[RawEntry, Promise<void>]>;
587
594
  /** the same as {@link putFile | `putFile`} but with caching for text */
588
- putText(fileName: string, content: string): Promise<[RawEntry, Promise<void>]>;
595
+ putText(fileName: string, text: string): Promise<[RawEntry, Promise<void>]>;
589
596
  /** the same as {@link putText | `putText`} but with extra validation for Content */
590
597
  putContent(fileName: string, content: Content): Promise<[RawEntry, Promise<void>]>;
591
598
  /** the same as {@link putText | `putText`} but with extra validation for Metadata */
@@ -624,10 +631,10 @@ export interface RawRemarkableApi {
624
631
  * @param visibleName - the name of the file as it should appear on the reMarkable
625
632
  * @param bytes - the bytes of the file to upload
626
633
  * @param mime - the mime type of the file to upload
627
-
634
+
628
635
  * @returns a simple entry with the id and hash of the uploaded file
629
636
  */
630
- uploadFile(visibleName: string, bytes: Uint8Array, mime: UploadMimeType): Promise<SimpleEntry>;
637
+ uploadFile(visibleName: string, bytes: Uint8Array, mime: UploadMimeType): Promise<ItemRef>;
631
638
  /**
632
639
  * dump the current cache to a string to preserve between session
633
640
  *
@@ -637,30 +644,4 @@ export interface RawRemarkableApi {
637
644
  /** completely clear the cache */
638
645
  clearCache(): void;
639
646
  }
640
- type AuthedFetch = (method: RequestMethod, url: string, init?: {
641
- body?: string | Uint8Array;
642
- headers?: Record<string, string>;
643
- }) => Promise<Response>;
644
- export declare class RawRemarkable implements RawRemarkableApi {
645
- #private;
646
- constructor(authedFetch: AuthedFetch, cache: Map<string, string | null>, rawHost: string, uploadHost: string);
647
- /** make an authorized request to remarkable */
648
- getRootHash(): Promise<[string, number, SchemaVersion]>;
649
- getHash(fileName: string, hash: string): Promise<Uint8Array>;
650
- getText(fileName: string, hash: string): Promise<string>;
651
- getEntries(fileName: string, hash: string): Promise<Entries>;
652
- getContent(fileName: string, hash: string): Promise<Content>;
653
- getMetadata(fileName: string, hash: string): Promise<Metadata>;
654
- getRm(fileName: string, hash: string): Promise<RmPage>;
655
- putRm(fileName: string, page: RmPageV5): Promise<[RawEntry, Promise<void>]>;
656
- putRootHash(hash: string, generation: number, broadcast?: boolean): Promise<[string, number]>;
657
- putFile(fileName: string, bytes: Uint8Array): Promise<[RawEntry, Promise<void>]>;
658
- putText(fileName: string, text: string): Promise<[RawEntry, Promise<void>]>;
659
- putContent(fileName: string, content: Content): Promise<[RawEntry, Promise<void>]>;
660
- putMetadata(fileName: string, metadata: Metadata): Promise<[RawEntry, Promise<void>]>;
661
- putEntries(id: string, entries: readonly RawEntry[], schemaVersion: SchemaVersion): Promise<[RawEntry, Promise<void>]>;
662
- uploadFile(visibleName: string, bytes: Uint8Array, mime: UploadMimeType): Promise<SimpleEntry>;
663
- dumpCache(): string;
664
- clearCache(): void;
665
- }
666
- export {};
647
+ export type { RawRemarkable as RawRemarkableApi };
package/dist/raw.js CHANGED
@@ -233,7 +233,7 @@ const rootHash = z
233
233
  schemaVersion: z.number().int().nonnegative(),
234
234
  })
235
235
  .passthrough();
236
- const nativeSimpleEntry = z
236
+ const nativeItemRef = z
237
237
  .object({
238
238
  docID: z.string(),
239
239
  hash: z.string(),
@@ -267,6 +267,65 @@ function parseRawEntryLine(line) {
267
267
  throw new Error(`line '${line}' was not formatted correctly`);
268
268
  }
269
269
  }
270
+ /**
271
+ * access to the low-level reMarkable api
272
+ *
273
+ * This class gives more granualar access to the reMarkable cloud, but is more
274
+ * dangerous.
275
+ *
276
+ * ## Overview
277
+ *
278
+ * reMarkable uses an immutable file system, where each file is referenced by
279
+ * the 32 byte sha256 hash of its contents. Each file also has an id used to
280
+ * keep track of updates, so to "update" a file, you upload a new file, and
281
+ * change the hash associated with it's id.
282
+ *
283
+ * Each "item" (a document or a collection) is actually a list of files.
284
+ * The whole reMarkable state is then a list of these lists. Finally, the hash
285
+ * of that list is called the rootHash. To update anything, you have to update
286
+ * the root hash to point to a new list of updated items.
287
+ *
288
+ * This can be dangerous, as corrupting the root hash can destroy all of your
289
+ * files. It is therefore highly recommended to save your current root hash
290
+ * ({@link getRootHash | `getRootHash`}) before using this api to attempt file
291
+ * writes, so you can recover a previous "snapshot" should anything go wrong.
292
+ *
293
+ * ## Items
294
+ *
295
+ * Each item is a collection of individual files. Using
296
+ * {@link getEntries | `getEntries`} on the root hash will give you a list
297
+ * entries that correspond to items. Using `getEntries` on any of those items
298
+ * will get you the files that make up that item.
299
+ *
300
+ * The documented files are:
301
+ * - `<docid>.pdf` - a raw pdf document
302
+ * - `<docid>.epub` - a raw epub document
303
+ * - `<docid>.content` - a json file roughly describing document properties (see {@link DocumentContent | `DocumentContent`})
304
+ * - `<docid>.metadata` - metadata about the document (see {@link Metadata | `Metadata`})
305
+ * - `<docid>.pagedata` - a text file where each line is the template of that page
306
+ * - `<docid>/<pageid>.rm` - [speculative] raw remarkable vectors, text, etc
307
+ * - `<docid>/<pageid>-metadata.json` - [speculative] metadata about the individual page
308
+ * - `<docid>.highlights/<pageid>.json` - [speculative] highlights on the page
309
+ *
310
+ * Some items will have both a `.pdf` and `.epub` file, likely due to preparing
311
+ * for export. Collections only have `.content` and `.metadata` files, with
312
+ * `.content` only containing tags.
313
+ *
314
+ * ## Caching
315
+ *
316
+ * Since everything is tied to the hash of it's contents, we can agressively
317
+ * cache results. We assume that text contents are "small" and so fully cache
318
+ * them, where as binary files we treat as large and only store that we know
319
+ * they exist to prevent future writes.
320
+ *
321
+ * By default, this only persists as long as the api instance is alive. However,
322
+ * for performance reasons, you should call {@link dumpCache | `dumpCache`} to
323
+ * persist the cache between sessions.
324
+ *
325
+ * @remarks
326
+ *
327
+ * Generally all hashes are 64 character hex strings, and all ids are uuid4.
328
+ */
270
329
  export class RawRemarkable {
271
330
  #authedFetch;
272
331
  #rawHost;
@@ -288,6 +347,14 @@ export class RawRemarkable {
288
347
  this.#uploadHost = uploadHost;
289
348
  }
290
349
  /** make an authorized request to remarkable */
350
+ /**
351
+ * gets the root hash and the current generation
352
+ *
353
+ * When calling `putRootHash`, you should pass the generation you got from
354
+ * this call. That way you tell reMarkable you're updating the previous state.
355
+ *
356
+ * @returns the root hash and the current generation
357
+ */
291
358
  async getRootHash() {
292
359
  const res = await this.#authedFetch("GET", `${this.#rawHost}/sync/v4/root`);
293
360
  const raw = await res.text();
@@ -312,7 +379,17 @@ export class RawRemarkable {
312
379
  const raw = await resp.arrayBuffer();
313
380
  return new Uint8Array(raw);
314
381
  }
315
- async getHash(fileName, hash) {
382
+ /**
383
+ * get the raw binary data associated with a hash
384
+ *
385
+ * @param ref - a reference to the stored file. Its `id` is the logical file
386
+ * name (`<id>.<ext>` for files, or `<id>.docSchema` / `"root.docSchema"`
387
+ * for entry indexes), which reMarkable validates against the rm-filename
388
+ * header. Sub-entries from {@link getEntries | `getEntries`} can be passed
389
+ * directly.
390
+ * @returns the data
391
+ */
392
+ async getHash({ id: fileName, hash }) {
316
393
  const cached = this.#cache.get(hash);
317
394
  if (cached != null) {
318
395
  const enc = new TextEncoder();
@@ -328,7 +405,16 @@ export class RawRemarkable {
328
405
  return res;
329
406
  }
330
407
  }
331
- async getText(fileName, hash) {
408
+ /**
409
+ * get raw text data associated with a hash
410
+ *
411
+ * We assume text data are small, and so cache the entire text. If you want to
412
+ * avoid this, use {@link getHash | `getHash`} combined with a TextDecoder.
413
+ *
414
+ * @param ref - a reference to the stored file (see {@link getHash})
415
+ * @returns the text
416
+ */
417
+ async getText({ id: fileName, hash }) {
332
418
  const cached = this.#cache.get(hash);
333
419
  if (cached != null) {
334
420
  return cached;
@@ -342,8 +428,18 @@ export class RawRemarkable {
342
428
  return res;
343
429
  }
344
430
  }
345
- async getEntries(fileName, hash) {
346
- const rawFile = await this.getText(fileName, hash);
431
+ /**
432
+ * get the entries associated with a list hash
433
+ *
434
+ * A list hash is the root hash, or any hash with the type 80000000. NOTE
435
+ * these are hashed differently than files.
436
+ *
437
+ * @param ref - a reference whose `id` is `"root.docSchema"` for the root, or
438
+ * `"<id>.docSchema"` for a sub-document's entry index
439
+ * @returns the entries
440
+ */
441
+ async getEntries(ref) {
442
+ const rawFile = await this.getText(ref);
347
443
  const [version, ...rest] = rawFile.slice(0, -1).split("\n");
348
444
  if (version === "3") {
349
445
  return { entries: rest.map(parseRawEntryLine) };
@@ -371,20 +467,50 @@ export class RawRemarkable {
371
467
  throw new Error(`schema version ${version} not supported`);
372
468
  }
373
469
  }
374
- async getContent(fileName, hash) {
375
- const raw = await this.getText(fileName, hash);
470
+ /**
471
+ * get the parsed and validated `Content` of a content hash
472
+ *
473
+ * Use {@link getText | `getText`} combined with `JSON.parse` to bypass
474
+ * validation
475
+ *
476
+ * @param ref - a reference to the stored file, typically `"<id>.content"`
477
+ * @returns the content
478
+ */
479
+ async getContent(ref) {
480
+ const raw = await this.getText(ref);
376
481
  const loaded = JSON.parse(raw);
377
482
  return content.parse(loaded);
378
483
  }
379
- async getMetadata(fileName, hash) {
380
- const raw = await this.getText(fileName, hash);
484
+ /**
485
+ * get the parsed and validated `Metadata` of a metadata hash
486
+ *
487
+ * Use {@link getText | `getText`} combined with `JSON.parse` to bypass
488
+ * validation
489
+ *
490
+ * @param ref - a reference to the stored file, typically `"<id>.metadata"`
491
+ * @returns the metadata
492
+ */
493
+ async getMetadata(ref) {
494
+ const raw = await this.getText(ref);
381
495
  const loaded = JSON.parse(raw);
382
496
  return metadata.parse(loaded);
383
497
  }
384
- async getRm(fileName, hash) {
385
- const bytes = await this.getHash(fileName, hash);
498
+ /**
499
+ * get the parsed reMarkable lines (`.rm`) drawing of a page hash
500
+ *
501
+ * @param ref - a reference to the stored file, typically `"<id>/<pageid>.rm"`
502
+ * @returns the parsed page
503
+ */
504
+ async getRm(ref) {
505
+ const bytes = await this.getHash(ref);
386
506
  return parseRm(bytes);
387
507
  }
508
+ /**
509
+ * the same as {@link putFile | `putFile`} but rendering an `RmPage` to `.rm`
510
+ * bytes
511
+ *
512
+ * Only version 3 and 5 pages can be rendered; version 6 pages are read-only.
513
+ */
388
514
  async putRm(fileName, page) {
389
515
  if (!fileName.endsWith(".rm")) {
390
516
  throw new Error(`fileName ${fileName} did not end with '.rm'`);
@@ -393,6 +519,25 @@ export class RawRemarkable {
393
519
  return await this.putFile(fileName, serializeRm(page));
394
520
  }
395
521
  }
522
+ /**
523
+ * update the current root hash
524
+ *
525
+ * This will fail if generation doesn't match the current server generation.
526
+ * This ensures that you are updating what you expect. IF you get a
527
+ * {@link GenerationError | `GenerationError`}, that indicates that the server
528
+ * was updated after you last got the generation. You should call
529
+ * {@link getRootHash | `getRootHash`} and then recompute the changes you want
530
+ * from the new root hash. If you ignore the update hash value and just call
531
+ * `putRootHash` again, you will overwrite the changes made by the other
532
+ * update.
533
+ *
534
+ * @param hash - the new root hash
535
+ * @param generation - the generation of the current root hash
536
+ * @param broadcast - [unknown] an option in the request
537
+ *
538
+ * @throws GenerationError if the generation doesn't match the current server generation
539
+ * @returns the new root hash and the new generation
540
+ */
396
541
  async putRootHash(hash, generation, broadcast = true) {
397
542
  if (!Number.isSafeInteger(generation)) {
398
543
  throw new Error(`generation ${generation} was not a safe integer`);
@@ -437,6 +582,20 @@ export class RawRemarkable {
437
582
  }
438
583
  }
439
584
  }
585
+ /**
586
+ * put a raw onto the server
587
+ *
588
+ * This returns the new expeced entry of the file you uploaded, and a promise
589
+ * to finish the upload successful. By splitting these two operations you can
590
+ * start using the uploaded entry while file finishes uploading.
591
+ *
592
+ * NOTE: This won't update the state of the reMarkable until this entry is
593
+ * incorporated into the root hash.
594
+ *
595
+ * @param fileName - the file name to upload (e.g. `<id>.pdf`)
596
+ * @param bytes - the bytes to upload
597
+ * @returns the new entry and a promise to finish the upload
598
+ */
440
599
  async putFile(fileName, bytes) {
441
600
  const hash = await digest(bytes);
442
601
  const res = {
@@ -448,6 +607,7 @@ export class RawRemarkable {
448
607
  };
449
608
  return [res, this.#putFile(fileName, hash, bytes)];
450
609
  }
610
+ /** the same as {@link putFile | `putFile`} but with caching for text */
451
611
  async putText(fileName, text) {
452
612
  const enc = new TextEncoder();
453
613
  const bytes = enc.encode(text);
@@ -460,6 +620,7 @@ export class RawRemarkable {
460
620
  }),
461
621
  ];
462
622
  }
623
+ /** the same as {@link putText | `putText`} but with extra validation for Content */
463
624
  async putContent(fileName, content) {
464
625
  if (!fileName.endsWith(".content")) {
465
626
  throw new Error(`fileName ${fileName} did not end with '.content'`);
@@ -468,6 +629,7 @@ export class RawRemarkable {
468
629
  return await this.putText(fileName, JSON.stringify(content));
469
630
  }
470
631
  }
632
+ /** the same as {@link putText | `putText`} but with extra validation for Metadata */
471
633
  async putMetadata(fileName, metadata) {
472
634
  if (!fileName.endsWith(".metadata")) {
473
635
  throw new Error(`fileName ${fileName} did not end with '.metadata'`);
@@ -476,6 +638,29 @@ export class RawRemarkable {
476
638
  return await this.putText(fileName, JSON.stringify(metadata));
477
639
  }
478
640
  }
641
+ /**
642
+ * put a set of entries to make an entry list file
643
+ *
644
+ * To fully upload an item:
645
+ * 1. upload all the constituent files and metadata
646
+ * 2. call this with all of the entries
647
+ * 3. append this entry to the root entry and call this again to update this root list
648
+ * 4. put the new root hash
649
+ *
650
+ * NOTE: reMarkable currently rejects newly written schema 3 root indexes
651
+ * with a 400 "Software must be updated" error, even for accounts that still
652
+ * report schema 3, so the root list should always be written as schema 4. A
653
+ * warning is logged if a schema 3 root index is written.
654
+ *
655
+ * @param id - the id of the list to upload - this should be the item id if
656
+ * uploading an item list, or "root" if uploading a new root list. Note the
657
+ * asymmetry with {@link getEntries | `getEntries`}: `getEntries` takes the
658
+ * full `"<id>.docSchema"` file name, whereas `putEntries` takes the bare id
659
+ * and appends `.docSchema` (and special-cases `"root"`) itself.
660
+ * @param entries - the entries to upload
661
+ *
662
+ * @returns the new list entry and a promise to finish the upload
663
+ */
479
664
  async putEntries(id, entries, schemaVersion) {
480
665
  if (id === "root" && schemaVersion === 3) {
481
666
  console.warn('writing a schema 3 root index, which reMarkable rejects with a 400 "Software must be updated" error; write the root index with schema version 4 instead');
@@ -520,6 +705,19 @@ export class RawRemarkable {
520
705
  };
521
706
  return [res, this.#putFile(`${id}.docSchema`, hash, entryBuff)];
522
707
  }
708
+ /**
709
+ * upload a file to the reMarkable cloud using the simple api
710
+ *
711
+ * This api is the same as used by the native reMarkable extension and works
712
+ * even if the backend schema version is version 4. Setting mime to "folder"
713
+ * allows folder creation.
714
+ *
715
+ * @param visibleName - the name of the file as it should appear on the reMarkable
716
+ * @param bytes - the bytes of the file to upload
717
+ * @param mime - the mime type of the file to upload
718
+
719
+ * @returns a simple entry with the id and hash of the uploaded file
720
+ */
523
721
  async uploadFile(visibleName, bytes, mime) {
524
722
  const enc = new TextEncoder();
525
723
  const meta = enc
@@ -534,12 +732,18 @@ export class RawRemarkable {
534
732
  },
535
733
  });
536
734
  const loaded = (await resp.json());
537
- const { docID, hash } = nativeSimpleEntry.parse(loaded);
735
+ const { docID, hash } = nativeItemRef.parse(loaded);
538
736
  return { id: docID, hash };
539
737
  }
738
+ /**
739
+ * dump the current cache to a string to preserve between session
740
+ *
741
+ * @returns a serialized version of the cache to pass to a new api instance
742
+ */
540
743
  dumpCache() {
541
744
  return JSON.stringify(Object.fromEntries(this.#cache));
542
745
  }
746
+ /** completely clear the cache */
543
747
  clearCache() {
544
748
  this.#cache.clear();
545
749
  }