rmapi-js 8.0.0 → 8.1.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/index.d.ts +59 -3
- package/dist/index.js +47 -15
- package/dist/rmapi-js.esm.min.js +15 -10
- package/package.json +13 -12
package/dist/index.d.ts
CHANGED
|
@@ -99,8 +99,19 @@ export interface DocumentType extends EntryCommon {
|
|
|
99
99
|
/** the timestamp of the last time this entry was opened */
|
|
100
100
|
lastOpened: string;
|
|
101
101
|
}
|
|
102
|
+
/** a template, such as from methods.remarkable.com */
|
|
103
|
+
export interface TemplateType extends EntryCommon {
|
|
104
|
+
/** the key to identify this as a template */
|
|
105
|
+
type: "TemplateType";
|
|
106
|
+
/** the timestamp of when the template was added/created */
|
|
107
|
+
createdTime?: string;
|
|
108
|
+
/** where this template was installed from */
|
|
109
|
+
source?: string;
|
|
110
|
+
/** indicates if this is a newly-installed template */
|
|
111
|
+
new?: boolean;
|
|
112
|
+
}
|
|
102
113
|
/** a remarkable entry for cloud items */
|
|
103
|
-
export type Entry = CollectionEntry | DocumentType;
|
|
114
|
+
export type Entry = CollectionEntry | DocumentType | TemplateType;
|
|
104
115
|
/** an simple entry without any extra information */
|
|
105
116
|
export interface SimpleEntry {
|
|
106
117
|
/** the document id */
|
|
@@ -360,8 +371,45 @@ export interface DocumentContent {
|
|
|
360
371
|
*/
|
|
361
372
|
viewBackgroundFilter?: BackgroundFilter;
|
|
362
373
|
}
|
|
374
|
+
/**
|
|
375
|
+
* content metadata, stored with the "content" extension
|
|
376
|
+
*
|
|
377
|
+
* This largely contains description of how to render the document, rather than
|
|
378
|
+
* metadata about it.
|
|
379
|
+
*/
|
|
380
|
+
export interface TemplateContent {
|
|
381
|
+
/** the template name */
|
|
382
|
+
name: string;
|
|
383
|
+
/** the template's author */
|
|
384
|
+
author: string;
|
|
385
|
+
/** Base64-encoded SVG icon image */
|
|
386
|
+
iconData: string;
|
|
387
|
+
/** category names this template belongs to (eg: "Planning", "Productivity") */
|
|
388
|
+
categories: string[];
|
|
389
|
+
/** labels associated with this template (eg: "Project management") */
|
|
390
|
+
labels: string[];
|
|
391
|
+
/** the orientation of this template */
|
|
392
|
+
orientation: "portrait" | "landscape";
|
|
393
|
+
/** semantic version for this template */
|
|
394
|
+
templateVersion: string;
|
|
395
|
+
/** template configuration format version (currently just `1`) */
|
|
396
|
+
formatVersion: number;
|
|
397
|
+
/**
|
|
398
|
+
* which screens the template supports:
|
|
399
|
+
*
|
|
400
|
+
* - `rm2`: reMarkable 2
|
|
401
|
+
* - `rmPP`: reMarkable Paper Pro
|
|
402
|
+
*/
|
|
403
|
+
supportedScreens: ("rm2" | "rmPP")[];
|
|
404
|
+
/** constant values used by the commands in `items` */
|
|
405
|
+
constants?: {
|
|
406
|
+
[name: string]: number;
|
|
407
|
+
}[];
|
|
408
|
+
/** the template definition, an SVG-like DSL in JSON */
|
|
409
|
+
items: object[];
|
|
410
|
+
}
|
|
363
411
|
/** content metadata for any item */
|
|
364
|
-
export type Content = CollectionContent | DocumentContent;
|
|
412
|
+
export type Content = CollectionContent | DocumentContent | TemplateContent;
|
|
365
413
|
/**
|
|
366
414
|
* item level metadata
|
|
367
415
|
*
|
|
@@ -399,7 +447,15 @@ export interface Metadata {
|
|
|
399
447
|
* DocumentType is a document, an epub, pdf, or notebook, CollectionType is a
|
|
400
448
|
* folder.
|
|
401
449
|
*/
|
|
402
|
-
type: "DocumentType" | "CollectionType";
|
|
450
|
+
type: "DocumentType" | "CollectionType" | "TemplateType";
|
|
451
|
+
/** whether this is this a newly-installed template */
|
|
452
|
+
new?: boolean;
|
|
453
|
+
/**
|
|
454
|
+
* the provider from which this item was obtained/installed
|
|
455
|
+
*
|
|
456
|
+
* Example: a template from "com.remarkable.methods".
|
|
457
|
+
*/
|
|
458
|
+
source?: string;
|
|
403
459
|
/** [speculative] metadata version, always 0 */
|
|
404
460
|
version?: number;
|
|
405
461
|
/** the visible name of the item, what it's called on the reMarkable */
|
package/dist/index.js
CHANGED
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
import { fromByteArray } from "base64-js";
|
|
55
55
|
import CRC32C from "crc-32/crc32c";
|
|
56
56
|
import JSZip from "jszip";
|
|
57
|
-
import { boolean, elements, enumeration, float64, int32, nullable, properties, string, timestamp, uint32, uint8, values, } from "jtd-ts";
|
|
57
|
+
import { boolean, elements, empty, enumeration, float64, int32, nullable, properties, string, timestamp, uint32, uint8, values, } from "jtd-ts";
|
|
58
58
|
import { v4 as uuid4 } from "uuid";
|
|
59
59
|
import { LruCache } from "./lru";
|
|
60
60
|
const AUTH_HOST = "https://webapp-prod.cloud.remarkable.engineering";
|
|
@@ -201,6 +201,19 @@ const cPages = properties({
|
|
|
201
201
|
const collectionContent = properties(undefined, {
|
|
202
202
|
tags: elements(tag),
|
|
203
203
|
});
|
|
204
|
+
const templateContent = properties({
|
|
205
|
+
name: string(),
|
|
206
|
+
author: string(),
|
|
207
|
+
iconData: string(),
|
|
208
|
+
categories: elements(string()),
|
|
209
|
+
labels: elements(string()),
|
|
210
|
+
orientation: enumeration("portrait", "landscape"),
|
|
211
|
+
templateVersion: string(),
|
|
212
|
+
formatVersion: uint8(),
|
|
213
|
+
supportedScreens: elements(enumeration("rm2", "rmPP")),
|
|
214
|
+
constants: elements(values(int32())),
|
|
215
|
+
items: elements(empty()),
|
|
216
|
+
});
|
|
204
217
|
const documentContent = properties({
|
|
205
218
|
coverPageNumber: int32(),
|
|
206
219
|
documentMetadata,
|
|
@@ -253,7 +266,7 @@ const metadata = properties({
|
|
|
253
266
|
lastModified: string(),
|
|
254
267
|
parent: string(),
|
|
255
268
|
pinned: boolean(),
|
|
256
|
-
type: enumeration("DocumentType", "CollectionType"),
|
|
269
|
+
type: enumeration("DocumentType", "CollectionType", "TemplateType"),
|
|
257
270
|
visibleName: string(),
|
|
258
271
|
}, {
|
|
259
272
|
lastOpened: string(),
|
|
@@ -399,18 +412,24 @@ class RawRemarkable {
|
|
|
399
412
|
const raw = await this.getText(hash);
|
|
400
413
|
const loaded = JSON.parse(raw);
|
|
401
414
|
// jtd can't verify non-discriminated unions, in this case, we have fileType
|
|
402
|
-
// defined or not. As a result, we
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
415
|
+
// defined or not. As a result, we try each, and concatenate the errors at the end
|
|
416
|
+
const errors = [];
|
|
417
|
+
for (const [name, valid] of [
|
|
418
|
+
["collection", collectionContent],
|
|
419
|
+
["template", templateContent],
|
|
420
|
+
["document", documentContent],
|
|
421
|
+
]) {
|
|
422
|
+
try {
|
|
423
|
+
if (valid.guardAssert(loaded))
|
|
424
|
+
return loaded;
|
|
425
|
+
}
|
|
426
|
+
catch (ex) {
|
|
427
|
+
const msg = ex instanceof Error ? ex.message : "unknown error type";
|
|
428
|
+
errors.push(`Couldn't validate as ${name} because:\n${msg}`);
|
|
429
|
+
}
|
|
413
430
|
}
|
|
431
|
+
const joined = errors.join("\n\nor\n\n");
|
|
432
|
+
throw new Error(`invalid content: ${joined}`);
|
|
414
433
|
}
|
|
415
434
|
async getMetadata(hash) {
|
|
416
435
|
const raw = await this.getText(hash);
|
|
@@ -604,11 +623,24 @@ class Remarkable {
|
|
|
604
623
|
else if (contentEnt === undefined) {
|
|
605
624
|
throw new Error(`couldn't find content for hash ${hash}`);
|
|
606
625
|
}
|
|
607
|
-
const [{ visibleName, lastModified, pinned, parent, lastOpened }, content] = await Promise.all([
|
|
626
|
+
const [{ visibleName, lastModified, pinned, parent, lastOpened, new: isNew, source, }, content,] = await Promise.all([
|
|
608
627
|
this.raw.getMetadata(metaEnt.hash),
|
|
609
628
|
this.raw.getContent(contentEnt.hash),
|
|
610
629
|
]);
|
|
611
|
-
if (
|
|
630
|
+
if ("templateVersion" in content) {
|
|
631
|
+
return {
|
|
632
|
+
id,
|
|
633
|
+
hash,
|
|
634
|
+
visibleName,
|
|
635
|
+
lastModified,
|
|
636
|
+
new: isNew,
|
|
637
|
+
pinned,
|
|
638
|
+
source,
|
|
639
|
+
parent,
|
|
640
|
+
type: "TemplateType",
|
|
641
|
+
};
|
|
642
|
+
}
|
|
643
|
+
else if (content.fileType === undefined) {
|
|
612
644
|
return {
|
|
613
645
|
id,
|
|
614
646
|
hash,
|