rmapi-js 0.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/LICENSE +21 -0
- package/README.md +110 -0
- package/bundle/rmapi-js.cjs.min.js +4 -0
- package/bundle/rmapi-js.esm.min.js +4 -0
- package/bundle/rmapi-js.iife.min.js +4 -0
- package/bundle/rmapi.cjs.min.js +4 -0
- package/bundle/rmapi.esm.min.js +4 -0
- package/bundle/rmapi.iife.min.js +4 -0
- package/dist/index.d.ts +404 -0
- package/dist/index.js +535 -0
- package/dist/utils.d.ts +6 -0
- package/dist/utils.js +24 -0
- package/dist/validate.d.ts +3 -0
- package/dist/validate.js +8 -0
- package/package.json +141 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,404 @@
|
|
|
1
|
+
/** request types */
|
|
2
|
+
export declare type RequestMethod = "POST" | "GET" | "PUT" | "DELETE";
|
|
3
|
+
/** text alignment types */
|
|
4
|
+
export declare type TextAlignment = "justify" | "left";
|
|
5
|
+
/** tool options */
|
|
6
|
+
export declare const builtinTools: readonly ["Ballpoint", "Ballpointv2", "Brush", "Calligraphy", "ClearPage", "EraseSection", "Eraser", "Fineliner", "Finelinerv2", "Highlighter", "Highlighterv2", "Marker", "Markerv2", "Paintbrush", "Paintbrushv2", "Pencilv2", "SharpPencil", "SharpPencilv2", "SolidPen", "ZoomTool"];
|
|
7
|
+
/** font name options */
|
|
8
|
+
export declare const builtinFontNames: readonly ["Maison Neue", "EB Garamond", "Noto Sans", "Noto Serif", "Noto Mono", "Noto Sans UI"];
|
|
9
|
+
/** text scale options */
|
|
10
|
+
export declare const builtinTextScales: {
|
|
11
|
+
/** the smallest */
|
|
12
|
+
readonly xs: 0.7;
|
|
13
|
+
/** small */
|
|
14
|
+
readonly sm: 0.8;
|
|
15
|
+
/** medium / default */
|
|
16
|
+
readonly md: 1;
|
|
17
|
+
/** large */
|
|
18
|
+
readonly lg: 1.2;
|
|
19
|
+
/** extra large */
|
|
20
|
+
readonly xl: 1.5;
|
|
21
|
+
/** double extra large */
|
|
22
|
+
readonly xx: 2;
|
|
23
|
+
};
|
|
24
|
+
/** margin options */
|
|
25
|
+
export declare const builtinMargins: {
|
|
26
|
+
/** small */
|
|
27
|
+
readonly sm: 50;
|
|
28
|
+
/** medium */
|
|
29
|
+
readonly md: 125;
|
|
30
|
+
/** default for read on remarkable */
|
|
31
|
+
readonly rr: 180;
|
|
32
|
+
/** large */
|
|
33
|
+
readonly lg: 200;
|
|
34
|
+
};
|
|
35
|
+
/** line height options */
|
|
36
|
+
export declare const builtinLineHeights: {
|
|
37
|
+
/** default */
|
|
38
|
+
readonly df: -1;
|
|
39
|
+
/** normal */
|
|
40
|
+
readonly md: 100;
|
|
41
|
+
/** half */
|
|
42
|
+
readonly lg: 150;
|
|
43
|
+
/** double */
|
|
44
|
+
readonly xl: 200;
|
|
45
|
+
};
|
|
46
|
+
/** a remarkable entry for a cloud collection */
|
|
47
|
+
export interface CollectionEntry {
|
|
48
|
+
/** collection type */
|
|
49
|
+
type: "80000000";
|
|
50
|
+
/** the hash of the file this points to */
|
|
51
|
+
hash: string;
|
|
52
|
+
/** the unique id of the collection */
|
|
53
|
+
documentId: string;
|
|
54
|
+
/** the number of subfiles */
|
|
55
|
+
subfiles: number;
|
|
56
|
+
/** collections don't have sizes */
|
|
57
|
+
size: 0n;
|
|
58
|
+
}
|
|
59
|
+
/** a remarkable entry for cloud data */
|
|
60
|
+
export interface FileEntry {
|
|
61
|
+
/** file type */
|
|
62
|
+
type: "0";
|
|
63
|
+
/** the hash of the file this points to */
|
|
64
|
+
hash: string;
|
|
65
|
+
/** the unique id of the file */
|
|
66
|
+
documentId: string;
|
|
67
|
+
/** files don't have subfiles */
|
|
68
|
+
subfiles: 0;
|
|
69
|
+
/** size of the file */
|
|
70
|
+
size: bigint;
|
|
71
|
+
}
|
|
72
|
+
/** a remarkable entry for cloud items */
|
|
73
|
+
export declare type Entry = CollectionEntry | FileEntry;
|
|
74
|
+
/** common metadata for documents and collections */
|
|
75
|
+
export interface CommonMetadata {
|
|
76
|
+
/** name of content */
|
|
77
|
+
visibleName: string;
|
|
78
|
+
/** parent uuid or "" for root or "trash" */
|
|
79
|
+
parent: string;
|
|
80
|
+
/** last modified time */
|
|
81
|
+
lastModified: string;
|
|
82
|
+
/** unsure */
|
|
83
|
+
version: number;
|
|
84
|
+
/** unsure */
|
|
85
|
+
pinned?: boolean;
|
|
86
|
+
/** unsure */
|
|
87
|
+
synced: boolean;
|
|
88
|
+
/** unsure */
|
|
89
|
+
modified?: boolean;
|
|
90
|
+
/** if file is deleted */
|
|
91
|
+
deleted?: boolean;
|
|
92
|
+
/** unsure */
|
|
93
|
+
metadatamodified?: boolean;
|
|
94
|
+
}
|
|
95
|
+
/** metadata for collection types */
|
|
96
|
+
export interface CollectionTypeMetadata extends CommonMetadata {
|
|
97
|
+
/** the key for collection types */
|
|
98
|
+
type: "CollectionType";
|
|
99
|
+
}
|
|
100
|
+
/** metadata for document types */
|
|
101
|
+
export interface DocumentTypeMetadata extends CommonMetadata {
|
|
102
|
+
/** the key for document types */
|
|
103
|
+
type: "DocumentType";
|
|
104
|
+
/** last opened time for documents */
|
|
105
|
+
lastOpened?: string;
|
|
106
|
+
/** last opened page for documents */
|
|
107
|
+
lastOpenedPage?: number;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* metadata for a document or collection (folder)
|
|
111
|
+
*
|
|
112
|
+
* This is found in the the `.metadata` file.
|
|
113
|
+
*/
|
|
114
|
+
export declare type Metadata = CollectionTypeMetadata | DocumentTypeMetadata;
|
|
115
|
+
/** extra content metadata */
|
|
116
|
+
export declare type ExtraMetadata = Record<string, string | undefined>;
|
|
117
|
+
/** remarkable file type; empty for notebook */
|
|
118
|
+
export declare type FileType = "pdf" | "epub" | "";
|
|
119
|
+
/** document matrix transform */
|
|
120
|
+
export declare type Transform = Record<`m${1 | 2 | 3}${1 | 2 | 3}`, number>;
|
|
121
|
+
/** content document metadata */
|
|
122
|
+
export interface DocumentMetadata {
|
|
123
|
+
/** document title */
|
|
124
|
+
title?: string;
|
|
125
|
+
/** document authors */
|
|
126
|
+
authors?: string[];
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* content metadata
|
|
130
|
+
*
|
|
131
|
+
* This is found in the `.content` file.
|
|
132
|
+
*/
|
|
133
|
+
export interface Content {
|
|
134
|
+
/** is this a dummy document */
|
|
135
|
+
dummyDocument: boolean;
|
|
136
|
+
/** document metadata */
|
|
137
|
+
documentMetadata?: DocumentMetadata;
|
|
138
|
+
/** extra metadata */
|
|
139
|
+
extraMetadata: ExtraMetadata;
|
|
140
|
+
/** file type */
|
|
141
|
+
fileType: FileType;
|
|
142
|
+
/** font */
|
|
143
|
+
fontName?: string;
|
|
144
|
+
/** last opened page */
|
|
145
|
+
lastOpenedPage: number;
|
|
146
|
+
/** line height */
|
|
147
|
+
lineHeight: number;
|
|
148
|
+
/** page margins in points */
|
|
149
|
+
margins: number;
|
|
150
|
+
/** orientation */
|
|
151
|
+
orientation?: "portrait" | "landscape";
|
|
152
|
+
/** number of pages */
|
|
153
|
+
pageCount: number;
|
|
154
|
+
/** page ids */
|
|
155
|
+
pages: string[];
|
|
156
|
+
/** number to use for the coverage page, -1 for last opened */
|
|
157
|
+
coverPageNumber: number;
|
|
158
|
+
/** text scale */
|
|
159
|
+
textScale: number;
|
|
160
|
+
/** page transform */
|
|
161
|
+
transform?: Transform;
|
|
162
|
+
/** format version */
|
|
163
|
+
formatVersion: number;
|
|
164
|
+
/** text alignment */
|
|
165
|
+
textAlignment?: TextAlignment;
|
|
166
|
+
}
|
|
167
|
+
/** anything that can be awaited */
|
|
168
|
+
export declare type Awaitable<T> = T | PromiseLike<T>;
|
|
169
|
+
/** stripped down version of RequestInit */
|
|
170
|
+
export interface RequestInitLike {
|
|
171
|
+
/** request method */
|
|
172
|
+
readonly method?: RequestMethod | undefined;
|
|
173
|
+
/** request headers */
|
|
174
|
+
readonly headers?: Record<string, string>;
|
|
175
|
+
/** request body */
|
|
176
|
+
readonly body?: ArrayBuffer | string;
|
|
177
|
+
}
|
|
178
|
+
/** stripped down version of Headers */
|
|
179
|
+
export interface HeadersLike {
|
|
180
|
+
/** get a specific header value */
|
|
181
|
+
get(key: string): string | null;
|
|
182
|
+
}
|
|
183
|
+
/** stripped down version of Response */
|
|
184
|
+
export interface ResponseLike {
|
|
185
|
+
/** true if request was successful */
|
|
186
|
+
ok: boolean;
|
|
187
|
+
/** http status */
|
|
188
|
+
status: number;
|
|
189
|
+
/** text associated with status */
|
|
190
|
+
statusText: string;
|
|
191
|
+
/** headers in response */
|
|
192
|
+
headers: HeadersLike;
|
|
193
|
+
/** get response body as text */
|
|
194
|
+
text(): Awaitable<string>;
|
|
195
|
+
/** get response body as an array buffer */
|
|
196
|
+
arrayBuffer(): Awaitable<ArrayBuffer>;
|
|
197
|
+
}
|
|
198
|
+
/** stripped down version of fetch */
|
|
199
|
+
export interface FetchLike {
|
|
200
|
+
(url: string, options?: RequestInitLike | undefined): Awaitable<ResponseLike>;
|
|
201
|
+
}
|
|
202
|
+
/** async storage, map like */
|
|
203
|
+
export interface CacheLike {
|
|
204
|
+
/** get value for key or undefined if missing */
|
|
205
|
+
get(key: string): Awaitable<string | undefined>;
|
|
206
|
+
/** set value for key */
|
|
207
|
+
set(key: string, value: string): Awaitable<void>;
|
|
208
|
+
}
|
|
209
|
+
/** stripped down version of subtle crypto */
|
|
210
|
+
export interface SubtleCryptoLike {
|
|
211
|
+
/** a digest function */
|
|
212
|
+
digest(algorithm: "SHA-256", data: ArrayBuffer): Promise<ArrayBuffer>;
|
|
213
|
+
}
|
|
214
|
+
/** an error that results from a failed request */
|
|
215
|
+
export declare class ResponseError extends Error {
|
|
216
|
+
/** the response status number */
|
|
217
|
+
readonly status: number;
|
|
218
|
+
/** the response status text */
|
|
219
|
+
readonly statusText: string;
|
|
220
|
+
constructor(status: number, statusText: string, message: string);
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* an error that results from trying yp update the wrong generation.
|
|
224
|
+
*
|
|
225
|
+
* If we try to update the root hash of files, but the generation has changed
|
|
226
|
+
* relative to the one we're updating from, this will fail.
|
|
227
|
+
*/
|
|
228
|
+
export declare class GenerationError extends Error {
|
|
229
|
+
constructor();
|
|
230
|
+
}
|
|
231
|
+
/** options for registering with the api */
|
|
232
|
+
export interface RegisterOptions {
|
|
233
|
+
/**
|
|
234
|
+
* the device description to use
|
|
235
|
+
*
|
|
236
|
+
* Using an improper one will results in the registration being rejected.
|
|
237
|
+
*/
|
|
238
|
+
deviceDesc?: string;
|
|
239
|
+
/**
|
|
240
|
+
* the unique id of this device
|
|
241
|
+
*
|
|
242
|
+
* If omitted it will be randomly generated */
|
|
243
|
+
uuid?: string;
|
|
244
|
+
/** The url to user for authorization requests */
|
|
245
|
+
authUrl?: string;
|
|
246
|
+
/** a function for making fetch requests, see {@link RemarkableOptions.fetch} for more info */
|
|
247
|
+
fetch?: FetchLike;
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* register a device and get the token needed to access the api
|
|
251
|
+
*
|
|
252
|
+
* Have users go to `https://my.remarkable.com/device/desktop/connect` and pass
|
|
253
|
+
* the resulting code into this function to get a device token. Persist that
|
|
254
|
+
* token to use the api.
|
|
255
|
+
*
|
|
256
|
+
* @param code - the eight letter code a user got from `https://my.remarkable.com/device/desktop/connect`.
|
|
257
|
+
* @returns the device token necessary for creating an api instace. These never expire so persist as long as necessary.
|
|
258
|
+
*/
|
|
259
|
+
export declare function register(code: string, { deviceDesc, uuid, authUrl, fetch, }?: RegisterOptions): Promise<string>;
|
|
260
|
+
/** options for uploading an epub document */
|
|
261
|
+
export interface PutEpubOptions {
|
|
262
|
+
/** the parent id, default to root */
|
|
263
|
+
parent?: string | undefined;
|
|
264
|
+
/** the margins of the epub 180 is good for articles, 125 for books */
|
|
265
|
+
margins?: number | keyof typeof builtinMargins | undefined;
|
|
266
|
+
/** the height of lines */
|
|
267
|
+
lineHeight?: number | keyof typeof builtinLineHeights | undefined;
|
|
268
|
+
/** the scale of text */
|
|
269
|
+
textScale?: number | keyof typeof builtinTextScales | undefined;
|
|
270
|
+
/** the page orientation */
|
|
271
|
+
orientation?: "portrait" | "landscape" | undefined;
|
|
272
|
+
/** the text alignment */
|
|
273
|
+
textAlignment?: TextAlignment | undefined;
|
|
274
|
+
/** which page should be shone as the cover */
|
|
275
|
+
cover?: "first" | "visited" | undefined;
|
|
276
|
+
/** the font name, should probably come from `builtinFontNames` */
|
|
277
|
+
fontName?: string | undefined;
|
|
278
|
+
/** the tool to have enabled by default */
|
|
279
|
+
lastTool?: string;
|
|
280
|
+
/** set to false to disable notifying other clients of the update */
|
|
281
|
+
notify?: boolean | undefined;
|
|
282
|
+
/**
|
|
283
|
+
* set number of retries for publish
|
|
284
|
+
*
|
|
285
|
+
* The final part of uploading involves update the root hash to include the
|
|
286
|
+
* new contents. If several places are attempting to change content this will
|
|
287
|
+
* fail, so setting a positive number of retries here causes it to retry that
|
|
288
|
+
* final step.
|
|
289
|
+
*/
|
|
290
|
+
retries?: number | undefined;
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* the api for accessing remarkable functions
|
|
294
|
+
*/
|
|
295
|
+
export interface RemarkableApi {
|
|
296
|
+
/** sends a signal to the server that a sync is complete and other devices should update */
|
|
297
|
+
syncComplete(): Promise<void>;
|
|
298
|
+
/**
|
|
299
|
+
* get the root hash and the current generation
|
|
300
|
+
*
|
|
301
|
+
* If this hasn't changed, then neither have any of the files.
|
|
302
|
+
*/
|
|
303
|
+
getRootHash(): Promise<[string, bigint]>;
|
|
304
|
+
/**
|
|
305
|
+
* write the root hash, incrimenting from the current generation
|
|
306
|
+
*
|
|
307
|
+
* This will fail if the current generation isn't equal to the passed in
|
|
308
|
+
* generation. Use this to preven race conditions. If this rejects, refetch
|
|
309
|
+
* the root hash, resync the updates, and then try to put again.
|
|
310
|
+
*
|
|
311
|
+
* @param hash - the hash of the new root collection
|
|
312
|
+
* @param generation - the current generation this builds off of
|
|
313
|
+
* @returns the new generation
|
|
314
|
+
*/
|
|
315
|
+
putRootHash(hash: string, generation: bigint): Promise<bigint>;
|
|
316
|
+
/**
|
|
317
|
+
* get array buffer associated with a hash
|
|
318
|
+
*
|
|
319
|
+
* @param hash - the hash to get text data from
|
|
320
|
+
*/
|
|
321
|
+
getBuffer(hash: string): Promise<ArrayBuffer>;
|
|
322
|
+
/**
|
|
323
|
+
* get text content associated with hash
|
|
324
|
+
*
|
|
325
|
+
* This call uses the cache if provided since contents of a specific hash
|
|
326
|
+
* should never change. This isn't atomic so calling with the same hash in
|
|
327
|
+
* quick succession could result in two requests being fired instead of the
|
|
328
|
+
* second waiting for the first.
|
|
329
|
+
*
|
|
330
|
+
* @param hash - the hash to get text data from
|
|
331
|
+
*/
|
|
332
|
+
getText(hash: string): Promise<string>;
|
|
333
|
+
/** get metadata from hash */
|
|
334
|
+
getMetadata(hash: string): Promise<Metadata>;
|
|
335
|
+
/** get entries from a collection hash */
|
|
336
|
+
getEntries(hash: string): Promise<Entry[]>;
|
|
337
|
+
/** put a reference to a set of entries into the cloud */
|
|
338
|
+
putEntries(documentId: string, entries: Entry[]): Promise<CollectionEntry>;
|
|
339
|
+
/** put a raw buffer in the cloud */
|
|
340
|
+
putBuffer(documentId: string, buffer: Uint8Array): Promise<FileEntry>;
|
|
341
|
+
/**
|
|
342
|
+
* put a raw text in the cloud
|
|
343
|
+
*
|
|
344
|
+
* This is similar to `putBuffer` but will also cache the upload.
|
|
345
|
+
*/
|
|
346
|
+
putText(documentId: string, contents: string): Promise<FileEntry>;
|
|
347
|
+
/**
|
|
348
|
+
* upload an epub
|
|
349
|
+
*
|
|
350
|
+
* @param visibleName - the name to show for the uploaded epub
|
|
351
|
+
* @param buffer - the epub contents
|
|
352
|
+
* @param opts - extra options you can specify at upload
|
|
353
|
+
*/
|
|
354
|
+
putEpub(visibleName: string, buffer: Uint8Array, opts?: PutEpubOptions): Promise<void>;
|
|
355
|
+
}
|
|
356
|
+
/** options for a remarkable instance */
|
|
357
|
+
export interface RemarkableOptions {
|
|
358
|
+
/**
|
|
359
|
+
* the fetch method to use
|
|
360
|
+
*
|
|
361
|
+
* This should loosely conform to the WHATWG fetch, but is relaxed enough that
|
|
362
|
+
* node-fetch also works. This will default to the global definitions of
|
|
363
|
+
* fetch.
|
|
364
|
+
*
|
|
365
|
+
* In node you can either use `"node-fetch"`, or `node --experimental-fetch`
|
|
366
|
+
* for node 17.5 or higher.
|
|
367
|
+
*/
|
|
368
|
+
fetch?: FetchLike;
|
|
369
|
+
/**
|
|
370
|
+
* an optional cache for text requests
|
|
371
|
+
*
|
|
372
|
+
* If you're using the api to sync between a local copy and the cloud, you'll
|
|
373
|
+
* want to keep a cache so that as long as a file's hash doesn't change you
|
|
374
|
+
* don't need to request another copy.
|
|
375
|
+
*
|
|
376
|
+
* @remarks currently there are no mechanisms that actually clear the cache,
|
|
377
|
+
* so be warned if the cache doesn't have an auto clearning mechansim that
|
|
378
|
+
* some old files may stay around for quite a while
|
|
379
|
+
*/
|
|
380
|
+
cache?: CacheLike;
|
|
381
|
+
/**
|
|
382
|
+
* a subtle-crypto-like object
|
|
383
|
+
*
|
|
384
|
+
* This should have a digest function like the api of `crypto.subtle`, it's
|
|
385
|
+
* default value. In node try
|
|
386
|
+
* `import { webcrypto } from "crypto"; global.crypto = webcrypto` or pass in
|
|
387
|
+
* `webcrypto.subtle`.
|
|
388
|
+
*/
|
|
389
|
+
subtle?: SubtleCryptoLike;
|
|
390
|
+
/** the url for making authorization requests */
|
|
391
|
+
authUrl?: string;
|
|
392
|
+
/** the window for making blob requests */
|
|
393
|
+
blobUrl?: string;
|
|
394
|
+
}
|
|
395
|
+
/**
|
|
396
|
+
* create an instance of the api
|
|
397
|
+
*
|
|
398
|
+
* This gets a temporary authentication token with the device token. If
|
|
399
|
+
* requests start failing, simply recreate the api instance.
|
|
400
|
+
*
|
|
401
|
+
* @param deviceToken - the device token proving this api instance is registered. Create one with {@link register}.
|
|
402
|
+
* @returns an api instance
|
|
403
|
+
*/
|
|
404
|
+
export declare function remarkable(deviceToken: string, { fetch, cache, subtle, authUrl, blobUrl, }?: RemarkableOptions): Promise<RemarkableApi>;
|