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.
@@ -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>;