rmapi-js 1.1.0 → 2.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/index.js CHANGED
@@ -1,12 +1,17 @@
1
1
  /**
2
2
  * Create and interact with reMarkable cloud.
3
3
  *
4
+ * After getting a device token with the {@link register | `register`} method,
5
+ * persist it and create api instances using {@link remarkable | `remarkable`}.
6
+ * Outside of registration, all relevant methods are in
7
+ * {@link RemarkableApi | `RemarkableApi`}.
8
+ *
4
9
  * @example
5
10
  * A simple fetch
6
11
  * ```ts
7
12
  * import { register, remarkable } from "rmapi-js";
8
13
  *
9
- * const code = "..." // eight letter code from https://my.remarkable.com/device/desktop/connect
14
+ * const code = "..." // eight letter code from https://my.remarkable.com/device/browser/connect
10
15
  * const token = await register(code)
11
16
  * // persist token
12
17
  * const api = await remarkable(token);
@@ -35,19 +40,22 @@
35
40
  * const rootEntries = await api.getEntries(root);
36
41
  * rootEntries.push(entry);
37
42
  * const { hash } = await api.putEntries("", rootEntries);
38
- * await api.putRootHash(hash, gen);
43
+ * const nextGen = await api.putRootHash(hash, gen);
44
+ * await api.syncComplete(nextGen);
39
45
  * ```
40
46
  *
41
47
  * @packageDocumentation
42
48
  */
49
+ import { fromByteArray } from "base64-js";
43
50
  import { v4 as uuid4 } from "uuid";
44
51
  import { concatBuffers, fromHex, toHex } from "./utils";
45
52
  import { validate } from "./validate";
46
53
  const SCHEMA_VERSION = "3";
47
- const AUTH_URL = "https://webapp-production-dot-remarkable-production.appspot.com";
48
- const BLOB_URL = "https://rm-blob-storage-prod.appspot.com";
54
+ const AUTH_HOST = "https://webapp-prod.cloud.remarkable.engineering";
55
+ const SYNC_HOST = "https://internal.cloud.remarkable.com";
49
56
  const GENERATION_HEADER = "x-goog-generation";
50
57
  const GENERATION_RACE_HEADER = "x-goog-if-generation-match";
58
+ const CONTENT_LENGTH_RANGE_HEADER = "x-goog-content-length-range";
51
59
  /** tool options */
52
60
  export const builtinTools = [
53
61
  "Ballpoint",
@@ -117,6 +125,12 @@ export const builtinLineHeights = {
117
125
  /** double */
118
126
  xl: 200,
119
127
  };
128
+ const uploadEntrySchema = {
129
+ properties: {
130
+ docID: { type: "string" },
131
+ hash: { type: "string" },
132
+ },
133
+ };
120
134
  const urlResponseSchema = {
121
135
  properties: {
122
136
  relative_path: { type: "string" },
@@ -124,19 +138,22 @@ const urlResponseSchema = {
124
138
  expires: { type: "timestamp" },
125
139
  method: { enum: ["POST", "GET", "PUT", "DELETE"] },
126
140
  },
141
+ optionalProperties: {
142
+ maxuploadsize_bytes: { type: "float64" },
143
+ },
127
144
  };
128
145
  const commonProperties = {
129
146
  visibleName: { type: "string" },
130
- parent: { type: "string" },
131
147
  lastModified: { type: "string" },
132
- version: { type: "int32" },
133
- synced: { type: "boolean" },
134
148
  };
135
149
  const commonOptionalProperties = {
150
+ version: { type: "int32" },
136
151
  pinned: { type: "boolean" },
152
+ synced: { type: "boolean" },
137
153
  modified: { type: "boolean" },
138
154
  deleted: { type: "boolean" },
139
155
  metadatamodified: { type: "boolean" },
156
+ parent: { type: "string" },
140
157
  };
141
158
  const metadataSchema = {
142
159
  discriminator: "type",
@@ -155,6 +172,34 @@ const metadataSchema = {
155
172
  },
156
173
  },
157
174
  };
175
+ const baseMetadataProperties = {
176
+ id: { type: "string" },
177
+ hash: { type: "string" },
178
+ };
179
+ const metadataEntrySchema = {
180
+ discriminator: "type",
181
+ mapping: {
182
+ CollectionType: {
183
+ properties: {
184
+ ...commonProperties,
185
+ ...baseMetadataProperties,
186
+ },
187
+ optionalProperties: commonOptionalProperties,
188
+ },
189
+ DocumentType: {
190
+ properties: {
191
+ ...commonProperties,
192
+ ...baseMetadataProperties,
193
+ fileType: { enum: ["notebook", "epub", "pdf", ""] },
194
+ },
195
+ optionalProperties: {
196
+ ...commonOptionalProperties,
197
+ lastOpened: { type: "string" },
198
+ lastOpenedPage: { type: "int32" },
199
+ },
200
+ },
201
+ },
202
+ };
158
203
  /** an error that results from a failed request */
159
204
  export class ResponseError extends Error {
160
205
  /** the response status number */
@@ -181,18 +226,18 @@ export class GenerationError extends Error {
181
226
  /**
182
227
  * register a device and get the token needed to access the api
183
228
  *
184
- * Have users go to `https://my.remarkable.com/device/desktop/connect` and pass
229
+ * Have users go to `https://my.remarkable.com/device/browser/connect` and pass
185
230
  * the resulting code into this function to get a device token. Persist that
186
231
  * token to use the api.
187
232
  *
188
- * @param code - the eight letter code a user got from `https://my.remarkable.com/device/desktop/connect`.
233
+ * @param code - the eight letter code a user got from `https://my.remarkable.com/device/browser/connect`.
189
234
  * @returns the device token necessary for creating an api instace. These never expire so persist as long as necessary.
190
235
  */
191
- export async function register(code, { deviceDesc = "desktop-linux", uuid = uuid4(), authUrl = AUTH_URL, fetch = globalThis.fetch, } = {}) {
236
+ export async function register(code, { deviceDesc = "browser-chrome", uuid = uuid4(), authHost = AUTH_HOST, fetch = globalThis.fetch, } = {}) {
192
237
  if (code.length !== 8) {
193
238
  throw new Error(`code should be length 8, but was ${code.length}`);
194
239
  }
195
- const resp = await fetch(`${authUrl}/token/json/2/device/new`, {
240
+ const resp = await fetch(`${authHost}/token/json/2/device/new`, {
196
241
  method: "POST",
197
242
  headers: {
198
243
  Authorization: "Bearer",
@@ -253,37 +298,45 @@ export function parseEntry(line) {
253
298
  }
254
299
  /** the implementation of that api */
255
300
  class Remarkable {
256
- userToken;
257
- fetch;
258
- cache;
259
- subtle;
260
- blobUrl;
261
- constructor(userToken, fetch, cache, subtle, blobUrl) {
262
- this.userToken = userToken;
263
- this.fetch = fetch;
264
- this.cache = cache;
265
- this.subtle = subtle;
266
- this.blobUrl = blobUrl;
301
+ #userToken;
302
+ #fetch;
303
+ #cache;
304
+ #subtle;
305
+ #syncHost;
306
+ constructor(userToken, fetch, cache, subtle, syncHost) {
307
+ this.#userToken = userToken;
308
+ this.#fetch = fetch;
309
+ this.#cache = cache;
310
+ this.#subtle = subtle;
311
+ this.#syncHost = syncHost;
267
312
  }
268
313
  /** make an authorized request to remarkable */
269
- async authedFetch(url, body, method = "POST") {
270
- const resp = await this.fetch(url, {
314
+ async #authedFetch(url, { body, method = "POST", headers = {}, }) {
315
+ const resp = await this.#fetch(url, {
271
316
  method,
272
317
  headers: {
273
- Authorization: `Bearer ${this.userToken}`,
318
+ Authorization: `Bearer ${this.#userToken}`,
319
+ ...headers,
274
320
  },
275
- body: body && JSON.stringify(body),
321
+ body,
276
322
  });
277
323
  if (!resp.ok) {
278
- throw new ResponseError(resp.status, resp.statusText, "failed reMarkable request");
324
+ const msg = await resp.text();
325
+ throw new ResponseError(resp.status, resp.statusText, `failed reMarkable request: ${msg}`);
279
326
  }
280
327
  else {
281
328
  return resp;
282
329
  }
283
330
  }
284
331
  /** make a signed request to the cloud */
285
- async signedFetch({ url, method }, body, headers) {
286
- const resp = await this.fetch(url, {
332
+ async #signedFetch({ url, method, maxuploadsize_bytes }, body, add_headers = {}) {
333
+ const headers = maxuploadsize_bytes
334
+ ? {
335
+ ...add_headers,
336
+ [CONTENT_LENGTH_RANGE_HEADER]: `0,${maxuploadsize_bytes}`,
337
+ }
338
+ : add_headers;
339
+ const resp = await this.#fetch(url, {
287
340
  method,
288
341
  body,
289
342
  headers,
@@ -297,14 +350,13 @@ class Remarkable {
297
350
  }
298
351
  }
299
352
  /** get the details for how to make a signed request to remarkable cloud */
300
- async getUrl(relativePath, gen) {
353
+ async #getUrl(relativePath, gen, rootHash) {
301
354
  const key = gen === undefined ? "downloads" : "uploads";
302
- const generation = gen === null || gen === undefined ? undefined : `${gen}`;
303
- const resp = await this.authedFetch(`${this.blobUrl}/api/v1/signed-urls/${key}`, {
304
- http_method: generation === undefined ? "GET" : "PUT",
305
- relative_path: relativePath,
306
- generation,
307
- });
355
+ // NOTE this is done manually to serialize the bigints appropriately
356
+ const body = rootHash
357
+ ? `{ "http_method": "PUT", "relative_path": "${relativePath}", "root_schema": "${rootHash}", "generation": ${gen} }`
358
+ : JSON.stringify({ http_method: "GET", relative_path: relativePath });
359
+ const resp = await this.#authedFetch(`${this.#syncHost}/sync/v2/signed-urls/${key}`, { body });
308
360
  const raw = await resp.text();
309
361
  const res = JSON.parse(raw);
310
362
  validate(urlResponseSchema, res);
@@ -314,8 +366,8 @@ class Remarkable {
314
366
  * get the root hash and the current generation
315
367
  */
316
368
  async getRootHash() {
317
- const signed = await this.getUrl("root");
318
- const resp = await this.signedFetch(signed);
369
+ const signed = await this.#getUrl("root");
370
+ const resp = await this.#signedFetch(signed);
319
371
  const generation = resp.headers.get(GENERATION_HEADER);
320
372
  if (!generation) {
321
373
  throw new Error("no generation header in root hash");
@@ -326,10 +378,10 @@ class Remarkable {
326
378
  * write the root hash, incrementing from the current generation
327
379
  */
328
380
  async putRootHash(hash, generation) {
329
- const signed = await this.getUrl("root", generation);
381
+ const signed = await this.#getUrl("root", generation, hash);
330
382
  let resp;
331
383
  try {
332
- resp = await this.signedFetch(signed, hash, {
384
+ resp = await this.#signedFetch(signed, hash, {
333
385
  [GENERATION_RACE_HEADER]: `${generation}`,
334
386
  });
335
387
  }
@@ -351,23 +403,23 @@ class Remarkable {
351
403
  * get text content associated with hash
352
404
  */
353
405
  async getBuffer(hash) {
354
- const signed = await this.getUrl(hash);
355
- const resp = await this.signedFetch(signed);
406
+ const signed = await this.#getUrl(hash);
407
+ const resp = await this.#signedFetch(signed);
356
408
  return await resp.arrayBuffer();
357
409
  }
358
410
  /**
359
411
  * get text content associated with hash
360
412
  */
361
413
  async getText(hash) {
362
- const cached = this.cache && (await this.cache.get(hash));
414
+ const cached = await this.#cache?.get(hash);
363
415
  if (cached) {
364
416
  return cached;
365
417
  }
366
418
  else {
367
- const signed = await this.getUrl(hash);
368
- const resp = await this.signedFetch(signed);
419
+ const signed = await this.#getUrl(hash);
420
+ const resp = await this.#signedFetch(signed);
369
421
  const raw = await resp.text();
370
- this.cache && (await this.cache.set(hash, raw));
422
+ await this.#cache?.set(hash, raw);
371
423
  return raw;
372
424
  }
373
425
  }
@@ -393,9 +445,9 @@ class Remarkable {
393
445
  return lines.map(parseEntry);
394
446
  }
395
447
  /** upload data to hash */
396
- async putHash(hash, body) {
397
- const signed = await this.getUrl(hash, null);
398
- await this.signedFetch(signed, body);
448
+ async #putHash(hash, body) {
449
+ const signed = await this.#getUrl(hash, null);
450
+ await this.#signedFetch(signed, body);
399
451
  }
400
452
  /** put a reference to a set of entries into the cloud */
401
453
  async putEntries(documentId, entries) {
@@ -403,13 +455,13 @@ class Remarkable {
403
455
  const enc = new TextEncoder();
404
456
  entries.sort((a, b) => a.documentId.localeCompare(b.documentId));
405
457
  const hashes = concatBuffers(entries.map((ent) => fromHex(ent.hash)));
406
- const digest = await this.subtle.digest("SHA-256", hashes);
458
+ const digest = await this.#subtle.digest("SHA-256", hashes);
407
459
  const hash = toHex(digest);
408
460
  const entryContents = entries.map(formatEntry).join("");
409
461
  const contents = `${SCHEMA_VERSION}\n${entryContents}`;
410
462
  const buffer = enc.encode(contents);
411
- await this.putHash(hash, buffer);
412
- this.cache && (await this.cache.set(hash, contents));
463
+ await this.#putHash(hash, buffer);
464
+ await this.#cache?.set(hash, contents);
413
465
  return {
414
466
  hash,
415
467
  type: "80000000",
@@ -420,9 +472,9 @@ class Remarkable {
420
472
  }
421
473
  /** put a raw buffer in the cloud */
422
474
  async putBuffer(documentId, buffer) {
423
- const digest = await this.subtle.digest("SHA-256", buffer);
475
+ const digest = await this.#subtle.digest("SHA-256", buffer);
424
476
  const hash = toHex(digest);
425
- await this.putHash(hash, buffer);
477
+ await this.#putHash(hash, buffer);
426
478
  return {
427
479
  hash,
428
480
  type: "0",
@@ -435,16 +487,20 @@ class Remarkable {
435
487
  async putText(documentId, contents) {
436
488
  const enc = new TextEncoder();
437
489
  const entry = await this.putBuffer(documentId, enc.encode(contents));
438
- this.cache && (await this.cache.set(entry.hash, contents));
490
+ await this.#cache?.set(entry.hash, contents);
439
491
  return entry;
440
492
  }
441
- /** upload an epub */
442
- async putEpub(visibleName, buffer, { parent = "", margins = 125, orientation, textAlignment, textScale = 1, lineHeight = -1, fontName = "", cover = "visited", lastTool, } = {}) {
493
+ /** upload a content file */
494
+ async #putContent(visibleName, buffer, fileType, parent, content) {
495
+ /* istanbul ignore if */
496
+ if (content.fileType !== fileType) {
497
+ throw new Error(`internal error: fileTypes don't match: ${fileType}, ${content.fileType}`);
498
+ }
443
499
  const documentId = uuid4();
444
500
  const lastModified = `${new Date().valueOf()}`;
445
501
  const entryPromises = [];
446
502
  // upload main document
447
- entryPromises.push(this.putBuffer(`${documentId}.epub`, buffer));
503
+ entryPromises.push(this.putBuffer(`${documentId}.${fileType}`, buffer));
448
504
  // upload metadata
449
505
  const metadata = {
450
506
  type: "DocumentType",
@@ -455,6 +511,15 @@ class Remarkable {
455
511
  lastModified,
456
512
  };
457
513
  entryPromises.push(this.putText(`${documentId}.metadata`, JSON.stringify(metadata)));
514
+ entryPromises.push(this.putText(`${documentId}.content`, JSON.stringify(content)));
515
+ // NOTE we technically get the entries a bit earlier, so could upload this
516
+ // before all contents are uploaded, but this also saves us from uploading
517
+ // the contents entry before all have uploaded successfully
518
+ const entries = await Promise.all(entryPromises);
519
+ return await this.putEntries(documentId, entries);
520
+ }
521
+ /** upload an epub */
522
+ async putEpub(visibleName, buffer, { parent = "", margins = 125, orientation, textAlignment, textScale = 1, lineHeight = -1, fontName = "", cover = "visited", lastTool, } = {}) {
458
523
  // upload content file
459
524
  const content = {
460
525
  dummyDocument: false,
@@ -478,12 +543,78 @@ class Remarkable {
478
543
  textAlignment,
479
544
  fontName,
480
545
  };
481
- entryPromises.push(this.putText(`${documentId}.content`, JSON.stringify(content)));
482
- // NOTE we technically get the entries a bit earlier, so could upload this
483
- // before all contents are uploaded, but this also saves us from uploading
484
- // the contents entry before all have uploaded successfully
485
- const entries = await Promise.all(entryPromises);
486
- return await this.putEntries(documentId, entries);
546
+ return await this.#putContent(visibleName, buffer, "epub", parent, content);
547
+ }
548
+ /** upload a pdf */
549
+ async putPdf(visibleName, buffer, { parent = "", orientation, cover = "first", lastTool } = {}) {
550
+ // upload content file
551
+ const content = {
552
+ dummyDocument: false,
553
+ extraMetadata: {
554
+ LastTool: lastTool,
555
+ },
556
+ fileType: "pdf",
557
+ pageCount: 0,
558
+ lastOpenedPage: 0,
559
+ lineHeight: -1,
560
+ margins: 125,
561
+ textScale: 1,
562
+ pages: [],
563
+ coverPageNumber: cover === "first" ? 0 : -1,
564
+ formatVersion: 1,
565
+ orientation,
566
+ };
567
+ return await this.#putContent(visibleName, buffer, "pdf", parent, content);
568
+ }
569
+ /** send sync complete request */
570
+ async syncComplete(generation) {
571
+ // NOTE this is done manually to properly serialize the bigint
572
+ const body = `{ "generation": ${generation} }`;
573
+ await this.#authedFetch(`${this.#syncHost}/sync/v2/sync-complete`, {
574
+ body,
575
+ });
576
+ }
577
+ /** get entries and metadata for all files */
578
+ async getEntriesMetadata() {
579
+ const resp = await this.#authedFetch(`${this.#syncHost}/doc/v2/files`, {
580
+ method: "GET",
581
+ headers: {
582
+ "rm-source": "RoR-Browser",
583
+ },
584
+ });
585
+ const raw = await resp.text();
586
+ const res = JSON.parse(raw);
587
+ const schema = {
588
+ elements: metadataEntrySchema,
589
+ };
590
+ validate(schema, res);
591
+ return res;
592
+ }
593
+ /** upload a file */
594
+ async #uploadFile(visibleName, buffer, contentType) {
595
+ const encoder = new TextEncoder();
596
+ const meta = encoder.encode(JSON.stringify({ file_name: visibleName }));
597
+ const resp = await this.#authedFetch(`${this.#syncHost}/doc/v2/files`, {
598
+ body: buffer,
599
+ headers: {
600
+ "content-type": contentType,
601
+ "rm-meta": fromByteArray(meta),
602
+ "rm-source": "RoR-Browser",
603
+ },
604
+ });
605
+ const raw = await resp.text();
606
+ const res = JSON.parse(raw);
607
+ validate(uploadEntrySchema, res);
608
+ return res;
609
+ }
610
+ /** upload an epub */
611
+ async uploadEpub(visibleName, buffer) {
612
+ return await this.#uploadFile(visibleName, buffer, "application/epub+zip");
613
+ }
614
+ /** upload a pdf */
615
+ async uploadPdf(visibleName, buffer) {
616
+ // TODO why doesn't this work
617
+ return await this.#uploadFile(visibleName, buffer, "application/pdf");
487
618
  }
488
619
  }
489
620
  /**
@@ -492,11 +623,12 @@ class Remarkable {
492
623
  * This gets a temporary authentication token with the device token. If
493
624
  * requests start failing, simply recreate the api instance.
494
625
  *
495
- * @param deviceToken - the device token proving this api instance is registered. Create one with {@link register}.
626
+ * @param deviceToken - the device token proving this api instance is
627
+ * registered. Create one with {@link register}.
496
628
  * @returns an api instance
497
629
  */
498
- export async function remarkable(deviceToken, { fetch = globalThis.fetch, cache, subtle = globalThis.crypto?.subtle, authUrl = AUTH_URL, blobUrl = BLOB_URL, } = {}) {
499
- const resp = await fetch(`${authUrl}/token/json/2/user/new`, {
630
+ export async function remarkable(deviceToken, { fetch = globalThis.fetch, cache, subtle = globalThis.crypto?.subtle, authHost = AUTH_HOST, syncHost = SYNC_HOST, } = {}) {
631
+ const resp = await fetch(`${authHost}/token/json/2/user/new`, {
500
632
  method: "POST",
501
633
  headers: {
502
634
  Authorization: `Bearer ${deviceToken}`,
@@ -506,5 +638,5 @@ export async function remarkable(deviceToken, { fetch = globalThis.fetch, cache,
506
638
  throw new Error(`couldn't fetch auth token: ${resp.statusText}`);
507
639
  }
508
640
  const userToken = await resp.text();
509
- return new Remarkable(userToken, fetch, cache, subtle, blobUrl);
641
+ return new Remarkable(userToken, fetch, cache, subtle, syncHost);
510
642
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rmapi-js",
3
- "version": "1.1.0",
3
+ "version": "2.0.0",
4
4
  "description": "JavaScript implementation of the reMarkable 1.5 api",
5
5
  "repository": "git@github.com:erikbrinkman/rmapi-js.git",
6
6
  "author": "Erik Brinkman <erik.brinkman@gmail.com>",
@@ -8,54 +8,55 @@
8
8
  "keywords": [
9
9
  "remarkable"
10
10
  ],
11
- "types": "dist/index.d.ts",
11
+ "types": "./dist/index.d.ts",
12
12
  "module": "bundle/rmapi-js.esm.min.js",
13
13
  "main": "bundle/rmapi-js.cjs.min.js",
14
14
  "unpkg": "bundle/rmapi-js.iife.min.js",
15
15
  "files": [
16
- "/bundle/*.js",
17
- "/dist/**/*.js",
18
- "/dist/**/*.d.ts"
16
+ "./bundle/*.js",
17
+ "./dist/**/*.js",
18
+ "./dist/**/*.d.ts"
19
19
  ],
20
- "packageManager": "yarn@3.2.4",
20
+ "packageManager": "yarn@3.3.1",
21
21
  "scripts": {
22
22
  "doc": "typedoc",
23
- "fmt": "prettier --cache --write 'src/*.ts' '*.json' 'bundle.mjs'",
24
- "lint": "tsc && eslint --cache 'src/*.ts' 'bundle.mjs' && typedoc --emit none",
23
+ "fmt": "prettier --cache --write 'src/*.ts' '*.json' bundle.mjs",
24
+ "lint": "tsc && eslint --cache 'src/*.ts' bundle.mjs && typedoc --emit none",
25
25
  "test": "jest --coverage",
26
26
  "build": "tsc -p tsconfig.build.json && yarn node bundle.mjs",
27
27
  "prepack": "yarn lint && yarn test && yarn build"
28
28
  },
29
29
  "dependencies": {
30
- "ajv": "^8.11.0",
30
+ "ajv": "^8.11.2",
31
+ "base64-js": "^1.5.1",
32
+ "jtd": "^0.1.1",
31
33
  "uuid": "^9.0.0"
32
34
  },
33
35
  "devDependencies": {
34
- "@babel/core": "^7.19.3",
35
- "@babel/preset-env": "^7.19.3",
36
+ "@babel/core": "^7.20.7",
37
+ "@babel/preset-env": "^7.20.2",
36
38
  "@babel/preset-typescript": "^7.18.6",
37
- "@types/babel__core": "^7.1.19",
39
+ "@types/babel__core": "^7.1.20",
38
40
  "@types/babel__preset-env": "^7.9.2",
39
- "@types/jest": "^29.1.2",
40
- "@types/node": "^18.8.3",
41
- "@types/uuid": "^8.3.4",
42
- "@typescript-eslint/eslint-plugin": "^5.39.0",
43
- "@typescript-eslint/parser": "^5.39.0",
41
+ "@types/jest": "^29.2.4",
42
+ "@types/node": "^18.11.18",
43
+ "@types/uuid": "^9.0.0",
44
+ "@typescript-eslint/eslint-plugin": "^5.47.1",
45
+ "@typescript-eslint/parser": "^5.47.1",
44
46
  "@yarnpkg/esbuild-plugin-pnp": "^3.0.0-rc.15",
45
- "babel-jest": "^29.1.2",
46
- "chalk": "^5.1.0",
47
- "esbuild": "^0.15.10",
48
- "eslint": "^8.24.0",
47
+ "babel-jest": "^29.3.1",
48
+ "chalk": "^5.2.0",
49
+ "esbuild": "^0.16.10",
50
+ "eslint": "^8.30.0",
49
51
  "eslint-config-prettier": "^8.5.0",
50
- "eslint-plugin-jest": "^27.1.1",
51
- "eslint-plugin-spellcheck": "^0.0.19",
52
+ "eslint-plugin-jest": "^27.1.7",
53
+ "eslint-plugin-spellcheck": "^0.0.20",
52
54
  "eslint-plugin-tsdoc": "^0.2.17",
53
- "jest": "^29.1.2",
54
- "jtd": "^0.1.1",
55
- "prettier": "^2.7.1",
56
- "prettier-plugin-organize-imports": "^3.1.1",
57
- "typedoc": "^0.23.15",
58
- "typescript": "^4.8.4"
55
+ "jest": "^29.3.1",
56
+ "prettier": "^2.8.1",
57
+ "prettier-plugin-organize-imports": "^3.2.1",
58
+ "typedoc": "^0.23.23",
59
+ "typescript": "^4.9.4"
59
60
  },
60
61
  "prettier": {
61
62
  "plugins": [
@@ -121,6 +122,7 @@
121
122
  "Paintbrushv",
122
123
  "Pencilv",
123
124
  "authed",
125
+ "bigints",
124
126
  "ebooks",
125
127
  "epub",
126
128
  "fineliner",
@@ -128,6 +130,7 @@
128
130
  "iife",
129
131
  "incrementing",
130
132
  "linux",
133
+ "macos",
131
134
  "rmapi",
132
135
  "subfiles",
133
136
  "urls",
@@ -1,4 +0,0 @@
1
- var ct=Object.create;var H=Object.defineProperty;var pt=Object.getOwnPropertyDescriptor;var yt=Object.getOwnPropertyNames;var gt=Object.getPrototypeOf,mt=Object.prototype.hasOwnProperty;var d=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),ht=(e,t)=>{for(var r in t)H(e,r,{get:t[r],enumerable:!0})},Pe=(e,t,r,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of yt(t))!mt.call(e,n)&&n!==r&&H(e,n,{get:()=>t[n],enumerable:!(i=pt(t,n))||i.enumerable});return e};var Te=(e,t,r)=>(r=e!=null?ct(gt(e)):{},Pe(t||!e||!e.__esModule?H(r,"default",{value:e,enumerable:!0}):r,e)),vt=e=>Pe(H({},"__esModule",{value:!0}),e);var ue=d(fe=>{"use strict";Object.defineProperty(fe,"__esModule",{value:!0});fe.default=xt;var bt=_t(require("crypto"));function _t(e){return e&&e.__esModule?e:{default:e}}var z=new Uint8Array(256),j=z.length;function xt(){return j>z.length-16&&(bt.default.randomFillSync(z),j=0),z.slice(j,j+=16)}});var Ee=d(J=>{"use strict";Object.defineProperty(J,"__esModule",{value:!0});J.default=void 0;var wt=/^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i;J.default=wt});var B=d(V=>{"use strict";Object.defineProperty(V,"__esModule",{value:!0});V.default=void 0;var Pt=Tt(Ee());function Tt(e){return e&&e.__esModule?e:{default:e}}function Et(e){return typeof e=="string"&&Pt.default.test(e)}var Ot=Et;V.default=Ot});var N=d(G=>{"use strict";Object.defineProperty(G,"__esModule",{value:!0});G.default=void 0;var kt=At(B());function At(e){return e&&e.__esModule?e:{default:e}}var y=[];for(let e=0;e<256;++e)y.push((e+256).toString(16).substr(1));function St(e,t=0){let r=(y[e[t+0]]+y[e[t+1]]+y[e[t+2]]+y[e[t+3]]+"-"+y[e[t+4]]+y[e[t+5]]+"-"+y[e[t+6]]+y[e[t+7]]+"-"+y[e[t+8]]+y[e[t+9]]+"-"+y[e[t+10]]+y[e[t+11]]+y[e[t+12]]+y[e[t+13]]+y[e[t+14]]+y[e[t+15]]).toLowerCase();if(!(0,kt.default)(r))throw TypeError("Stringified UUID is invalid");return r}var Mt=St;G.default=Mt});var Ae=d(Y=>{"use strict";Object.defineProperty(Y,"__esModule",{value:!0});Y.default=void 0;var Rt=ke(ue()),Ft=ke(N());function ke(e){return e&&e.__esModule?e:{default:e}}var Oe,le,de=0,ce=0;function qt(e,t,r){let i=t&&r||0,n=t||new Array(16);e=e||{};let s=e.node||Oe,o=e.clockseq!==void 0?e.clockseq:le;if(s==null||o==null){let l=e.random||(e.rng||Rt.default)();s==null&&(s=Oe=[l[0]|1,l[1],l[2],l[3],l[4],l[5]]),o==null&&(o=le=(l[6]<<8|l[7])&16383)}let a=e.msecs!==void 0?e.msecs:Date.now(),f=e.nsecs!==void 0?e.nsecs:ce+1,c=a-de+(f-ce)/1e4;if(c<0&&e.clockseq===void 0&&(o=o+1&16383),(c<0||a>de)&&e.nsecs===void 0&&(f=0),f>=1e4)throw new Error("uuid.v1(): Can't create more than 10M uuids/sec");de=a,ce=f,le=o,a+=122192928e5;let p=((a&268435455)*1e4+f)%4294967296;n[i++]=p>>>24&255,n[i++]=p>>>16&255,n[i++]=p>>>8&255,n[i++]=p&255;let b=a/4294967296*1e4&268435455;n[i++]=b>>>8&255,n[i++]=b&255,n[i++]=b>>>24&15|16,n[i++]=b>>>16&255,n[i++]=o>>>8|128,n[i++]=o&255;for(let l=0;l<6;++l)n[i+l]=s[l];return t||(0,Ft.default)(n)}var It=qt;Y.default=It});var pe=d(Z=>{"use strict";Object.defineProperty(Z,"__esModule",{value:!0});Z.default=void 0;var Dt=Ut(B());function Ut(e){return e&&e.__esModule?e:{default:e}}function Lt(e){if(!(0,Dt.default)(e))throw TypeError("Invalid UUID");let t,r=new Uint8Array(16);return r[0]=(t=parseInt(e.slice(0,8),16))>>>24,r[1]=t>>>16&255,r[2]=t>>>8&255,r[3]=t&255,r[4]=(t=parseInt(e.slice(9,13),16))>>>8,r[5]=t&255,r[6]=(t=parseInt(e.slice(14,18),16))>>>8,r[7]=t&255,r[8]=(t=parseInt(e.slice(19,23),16))>>>8,r[9]=t&255,r[10]=(t=parseInt(e.slice(24,36),16))/1099511627776&255,r[11]=t/4294967296&255,r[12]=t>>>24&255,r[13]=t>>>16&255,r[14]=t>>>8&255,r[15]=t&255,r}var Bt=Lt;Z.default=Bt});var ye=d(O=>{"use strict";Object.defineProperty(O,"__esModule",{value:!0});O.default=Ht;O.URL=O.DNS=void 0;var Nt=Se(N()),Ct=Se(pe());function Se(e){return e&&e.__esModule?e:{default:e}}function $t(e){e=unescape(encodeURIComponent(e));let t=[];for(let r=0;r<e.length;++r)t.push(e.charCodeAt(r));return t}var Me="6ba7b810-9dad-11d1-80b4-00c04fd430c8";O.DNS=Me;var Re="6ba7b811-9dad-11d1-80b4-00c04fd430c8";O.URL=Re;function Ht(e,t,r){function i(n,s,o,a){if(typeof n=="string"&&(n=$t(n)),typeof s=="string"&&(s=(0,Ct.default)(s)),s.length!==16)throw TypeError("Namespace must be array-like (16 iterable integer values, 0-255)");let f=new Uint8Array(16+n.length);if(f.set(s),f.set(n,s.length),f=r(f),f[6]=f[6]&15|t,f[8]=f[8]&63|128,o){a=a||0;for(let c=0;c<16;++c)o[a+c]=f[c];return o}return(0,Nt.default)(f)}try{i.name=e}catch{}return i.DNS=Me,i.URL=Re,i}});var Fe=d(W=>{"use strict";Object.defineProperty(W,"__esModule",{value:!0});W.default=void 0;var jt=zt(require("crypto"));function zt(e){return e&&e.__esModule?e:{default:e}}function Jt(e){return Array.isArray(e)?e=Buffer.from(e):typeof e=="string"&&(e=Buffer.from(e,"utf8")),jt.default.createHash("md5").update(e).digest()}var Vt=Jt;W.default=Vt});var Ie=d(K=>{"use strict";Object.defineProperty(K,"__esModule",{value:!0});K.default=void 0;var Gt=qe(ye()),Yt=qe(Fe());function qe(e){return e&&e.__esModule?e:{default:e}}var Zt=(0,Gt.default)("v3",48,Yt.default),Wt=Zt;K.default=Wt});var Ue=d(Q=>{"use strict";Object.defineProperty(Q,"__esModule",{value:!0});Q.default=void 0;var Kt=De(ue()),Qt=De(N());function De(e){return e&&e.__esModule?e:{default:e}}function Xt(e,t,r){e=e||{};let i=e.random||(e.rng||Kt.default)();if(i[6]=i[6]&15|64,i[8]=i[8]&63|128,t){r=r||0;for(let n=0;n<16;++n)t[r+n]=i[n];return t}return(0,Qt.default)(i)}var er=Xt;Q.default=er});var Le=d(X=>{"use strict";Object.defineProperty(X,"__esModule",{value:!0});X.default=void 0;var tr=rr(require("crypto"));function rr(e){return e&&e.__esModule?e:{default:e}}function nr(e){return Array.isArray(e)?e=Buffer.from(e):typeof e=="string"&&(e=Buffer.from(e,"utf8")),tr.default.createHash("sha1").update(e).digest()}var ir=nr;X.default=ir});var Ne=d(ee=>{"use strict";Object.defineProperty(ee,"__esModule",{value:!0});ee.default=void 0;var sr=Be(ye()),or=Be(Le());function Be(e){return e&&e.__esModule?e:{default:e}}var ar=(0,sr.default)("v5",80,or.default),fr=ar;ee.default=fr});var Ce=d(te=>{"use strict";Object.defineProperty(te,"__esModule",{value:!0});te.default=void 0;var ur="00000000-0000-0000-0000-000000000000";te.default=ur});var $e=d(re=>{"use strict";Object.defineProperty(re,"__esModule",{value:!0});re.default=void 0;var lr=dr(B());function dr(e){return e&&e.__esModule?e:{default:e}}function cr(e){if(!(0,lr.default)(e))throw TypeError("Invalid UUID");return parseInt(e.substr(14,1),16)}var pr=cr;re.default=pr});var He=d(x=>{"use strict";Object.defineProperty(x,"__esModule",{value:!0});Object.defineProperty(x,"v1",{enumerable:!0,get:function(){return yr.default}});Object.defineProperty(x,"v3",{enumerable:!0,get:function(){return gr.default}});Object.defineProperty(x,"v4",{enumerable:!0,get:function(){return mr.default}});Object.defineProperty(x,"v5",{enumerable:!0,get:function(){return hr.default}});Object.defineProperty(x,"NIL",{enumerable:!0,get:function(){return vr.default}});Object.defineProperty(x,"version",{enumerable:!0,get:function(){return br.default}});Object.defineProperty(x,"validate",{enumerable:!0,get:function(){return _r.default}});Object.defineProperty(x,"stringify",{enumerable:!0,get:function(){return xr.default}});Object.defineProperty(x,"parse",{enumerable:!0,get:function(){return wr.default}});var yr=P(Ae()),gr=P(Ie()),mr=P(Ue()),hr=P(Ne()),vr=P(Ce()),br=P($e()),_r=P(B()),xr=P(N()),wr=P(pe());function P(e){return e&&e.__esModule?e:{default:e}}});var ve=d(u=>{"use strict";var Je=u&&u.__rest||function(e,t){var r={};for(var i in e)Object.prototype.hasOwnProperty.call(e,i)&&t.indexOf(i)<0&&(r[i]=e[i]);if(e!=null&&typeof Object.getOwnPropertySymbols=="function")for(var n=0,i=Object.getOwnPropertySymbols(e);n<i.length;n++)t.indexOf(i[n])<0&&Object.prototype.propertyIsEnumerable.call(e,i[n])&&(r[i[n]]=e[i[n]]);return r};Object.defineProperty(u,"__esModule",{value:!0});u.isSchema=u.isValidSchema=u.isDiscriminatorForm=u.isValuesForm=u.isPropertiesForm=u.isElementsForm=u.isEnumForm=u.isTypeForm=u.isRefForm=u.isEmptyForm=void 0;function Pr(e){let{definitions:t,nullable:r,metadata:i}=e,n=Je(e,["definitions","nullable","metadata"]);return Object.keys(n).length===0}u.isEmptyForm=Pr;function Ve(e){return"ref"in e}u.isRefForm=Ve;function Tr(e){return"type"in e}u.isTypeForm=Tr;function Ge(e){return"enum"in e}u.isEnumForm=Ge;function Ye(e){return"elements"in e}u.isElementsForm=Ye;function he(e){return"properties"in e||"optionalProperties"in e}u.isPropertiesForm=he;function Ze(e){return"values"in e}u.isValuesForm=Ze;function We(e){return"discriminator"in e}u.isDiscriminatorForm=We;function k(e,t){if(t===void 0&&(t=e),e.definitions!==void 0){if(t!==e)return!1;for(let r of Object.values(e.definitions))if(!k(r,t))return!1}if(Ve(e)&&!(e.ref in(t.definitions||{}))||Ge(e)&&(e.enum.length===0||e.enum.length!==new Set(e.enum).size))return!1;if(Ye(e))return k(e.elements,t);if(he(e)){for(let r of Object.values(e.properties||{}))if(!k(r,t))return!1;for(let r of Object.values(e.optionalProperties||{}))if(!k(r,t))return!1;for(let r of Object.keys(e.properties||{}))if(r in(e.optionalProperties||{}))return!1}if(Ze(e))return k(e.values,t);if(We(e)){for(let r of Object.values(e.mapping))if(!k(r,t)||!he(r)||r.nullable||e.discriminator in(r.properties||{})||e.discriminator in(r.optionalProperties||{}))return!1}return!0}u.isValidSchema=k;var Er=[[!1,!1,!1,!1,!1,!1,!1,!1,!1,!1],[!0,!1,!1,!1,!1,!1,!1,!1,!1,!1],[!1,!0,!1,!1,!1,!1,!1,!1,!1,!1],[!1,!1,!0,!1,!1,!1,!1,!1,!1,!1],[!1,!1,!1,!0,!1,!1,!1,!1,!1,!1],[!1,!1,!1,!1,!0,!1,!1,!1,!1,!1],[!1,!1,!1,!1,!1,!0,!1,!1,!1,!1],[!1,!1,!1,!1,!0,!0,!1,!1,!1,!1],[!1,!1,!1,!1,!0,!1,!0,!1,!1,!1],[!1,!1,!1,!1,!1,!0,!0,!1,!1,!1],[!1,!1,!1,!1,!0,!0,!0,!1,!1,!1],[!1,!1,!1,!1,!1,!1,!1,!0,!1,!1],[!1,!1,!1,!1,!1,!1,!1,!1,!0,!0]],Or=["boolean","float32","float64","int8","uint8","int16","uint16","int32","uint32","string","timestamp"];function A(e){if(typeof e!="object"||Array.isArray(e)||e===null)return!1;let t=e,{definitions:r=void 0,nullable:i=void 0,metadata:n=void 0,ref:s=void 0,type:o=void 0,enum:a=void 0,elements:f=void 0,properties:c=void 0,optionalProperties:p=void 0,additionalProperties:b=void 0,values:l=void 0,discriminator:I=void 0,mapping:_=void 0}=t,se=Je(t,["definitions","nullable","metadata","ref","type","enum","elements","properties","optionalProperties","additionalProperties","values","discriminator","mapping"]),D=[s!==void 0,o!==void 0,a!==void 0,f!==void 0,c!==void 0,p!==void 0,b!==void 0,l!==void 0,I!==void 0,_!==void 0],L=!1;for(let v of Er)L=L||v.every((oe,ae)=>oe===D[ae]);if(!L)return!1;if(r!==void 0){if(typeof r!="object"||Array.isArray(r)||r===null)return!1;for(let v of Object.values(r))if(!A(v))return!1}if(i!==void 0&&typeof i!="boolean"||n!==void 0&&(typeof n!="object"||Array.isArray(n)||n===null)||s!==void 0&&typeof s!="string"||o!==void 0&&(typeof o!="string"||!Or.includes(o))||a!==void 0&&(!Array.isArray(a)||!a.every(v=>typeof v=="string"))||f!==void 0&&!A(f))return!1;if(c!==void 0){if(typeof c!="object"||Array.isArray(c)||c===null)return!1;for(let v of Object.values(c))if(!A(v))return!1}if(p!==void 0){if(typeof p!="object"||Array.isArray(p)||p===null)return!1;for(let v of Object.values(p))if(!A(v))return!1}if(b!==void 0&&typeof b!="boolean"||l!==void 0&&!A(l)||I!==void 0&&typeof I!="string")return!1;if(_!==void 0){if(typeof _!="object"||Array.isArray(_)||_===null)return!1;for(let v of Object.values(_))if(!A(v))return!1}return Object.keys(se).length===0}u.isSchema=A});var Ke=d(be=>{"use strict";Object.defineProperty(be,"__esModule",{value:!0});var kr=/^(\d{4})-(\d{2})-(\d{2})[tT](\d{2}):(\d{2}):(\d{2})(\.\d+)?([zZ]|((\+|-)(\d{2}):(\d{2})))$/;function Ar(e){let t=e.match(kr);if(t===null)return!1;let r=parseInt(t[1],10),i=parseInt(t[2],10),n=parseInt(t[3],10),s=parseInt(t[4],10),o=parseInt(t[5],10),a=parseInt(t[6],10);return!(i>12||n>Sr(r,i)||s>23||o>59||a>60)}be.default=Ar;function Sr(e,t){return t===2?Mr(e)?29:28:Rr[t]}function Mr(e){return e%4===0&&(e%100!==0||e%400===0)}var Rr=[0,31,0,31,30,31,30,31,31,30,31,30,31]});var Qe=d(T=>{"use strict";var Fr=T&&T.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(T,"__esModule",{value:!0});T.validate=T.MaxDepthExceededError=void 0;var qr=Fr(Ke()),S=ve(),ne=class extends Error{};T.MaxDepthExceededError=ne;var ie=class extends Error{};function Ir(e,t,r){let i={errors:[],instanceTokens:[],schemaTokens:[[]],root:e,config:r||{maxDepth:0,maxErrors:0}};try{F(i,e,t)}catch(n){if(!(n instanceof ie))throw n}return i.errors}T.validate=Ir;function F(e,t,r,i){if(!(t.nullable&&r===null)){if(S.isRefForm(t)){if(e.schemaTokens.length===e.config.maxDepth)throw new ne;e.schemaTokens.push(["definitions",t.ref]),F(e,e.root.definitions[t.ref],r),e.schemaTokens.pop()}else if(S.isTypeForm(t)){switch(g(e,"type"),t.type){case"boolean":typeof r!="boolean"&&m(e);break;case"float32":case"float64":typeof r!="number"&&m(e);break;case"int8":U(e,r,-128,127);break;case"uint8":U(e,r,0,255);break;case"int16":U(e,r,-32768,32767);break;case"uint16":U(e,r,0,65535);break;case"int32":U(e,r,-2147483648,2147483647);break;case"uint32":U(e,r,0,4294967295);break;case"string":typeof r!="string"&&m(e);break;case"timestamp":typeof r!="string"?m(e):qr.default(r)||m(e);break}h(e)}else if(S.isEnumForm(t))g(e,"enum"),(typeof r!="string"||!t.enum.includes(r))&&m(e),h(e);else if(S.isElementsForm(t)){if(g(e,"elements"),Array.isArray(r))for(let[n,s]of r.entries())M(e,n.toString()),F(e,t.elements,s),R(e);else m(e);h(e)}else if(S.isPropertiesForm(t))if(typeof r=="object"&&r!==null&&!Array.isArray(r)){if(t.properties!==void 0){g(e,"properties");for(let[n,s]of Object.entries(t.properties))g(e,n),r.hasOwnProperty(n)?(M(e,n),F(e,s,r[n]),R(e)):m(e),h(e);h(e)}if(t.optionalProperties!==void 0){g(e,"optionalProperties");for(let[n,s]of Object.entries(t.optionalProperties))g(e,n),r.hasOwnProperty(n)&&(M(e,n),F(e,s,r[n]),R(e)),h(e);h(e)}if(t.additionalProperties!==!0)for(let n of Object.keys(r)){let s=t.properties&&n in t.properties,o=t.optionalProperties&&n in t.optionalProperties;!s&&!o&&n!==i&&(M(e,n),m(e),R(e))}}else t.properties!==void 0?g(e,"properties"):g(e,"optionalProperties"),m(e),h(e);else if(S.isValuesForm(t)){if(g(e,"values"),typeof r=="object"&&r!==null&&!Array.isArray(r))for(let[n,s]of Object.entries(r))M(e,n),F(e,t.values,s),R(e);else m(e);h(e)}else if(S.isDiscriminatorForm(t))if(typeof r=="object"&&r!==null&&!Array.isArray(r))if(r.hasOwnProperty(t.discriminator)){let n=r[t.discriminator];typeof n=="string"?n in t.mapping?(g(e,"mapping"),g(e,n),F(e,t.mapping[n],r,t.discriminator),h(e),h(e)):(g(e,"mapping"),M(e,t.discriminator),m(e),R(e),h(e)):(g(e,"discriminator"),M(e,t.discriminator),m(e),R(e),h(e))}else g(e,"discriminator"),m(e),h(e);else g(e,"discriminator"),m(e),h(e)}}function U(e,t,r,i){(typeof t!="number"||!Number.isInteger(t)||t<r||t>i)&&m(e)}function M(e,t){e.instanceTokens.push(t)}function R(e){e.instanceTokens.pop()}function g(e,t){e.schemaTokens[e.schemaTokens.length-1].push(t)}function h(e){e.schemaTokens[e.schemaTokens.length-1].pop()}function m(e){if(e.errors.push({instancePath:[...e.instanceTokens],schemaPath:[...e.schemaTokens[e.schemaTokens.length-1]]}),e.errors.length===e.config.maxErrors)throw new ie}});var et=d(E=>{"use strict";var Dr=E&&E.__createBinding||(Object.create?function(e,t,r,i){i===void 0&&(i=r),Object.defineProperty(e,i,{enumerable:!0,get:function(){return t[r]}})}:function(e,t,r,i){i===void 0&&(i=r),e[i]=t[r]}),Xe=E&&E.__exportStar||function(e,t){for(var r in e)r!=="default"&&!t.hasOwnProperty(r)&&Dr(t,e,r)};Object.defineProperty(E,"__esModule",{value:!0});Xe(ve(),E);Xe(Qe(),E)});var Vr={};ht(Vr,{GenerationError:()=>C,ResponseError:()=>q,builtinFontNames:()=>Nr,builtinLineHeights:()=>ut,builtinMargins:()=>ft,builtinTextScales:()=>at,builtinTools:()=>Br,register:()=>Hr,remarkable:()=>Jr});module.exports=vt(Vr);var w=Te(He(),1),ln=w.default.v1,dn=w.default.v3,ge=w.default.v4,cn=w.default.v5,pn=w.default.NIL,yn=w.default.version,gn=w.default.validate,mn=w.default.stringify,hn=w.default.parse;function me(e){return[...new Uint8Array(e)].map(t=>t.toString(16).padStart(2,"0")).join("")}function je(e){return new Uint8Array((e.match(/../g)??[]).map(t=>parseInt(t,16)))}function ze(e){let t=0;for(let n of e)t+=n.length;let r=new Uint8Array(t),i=0;for(let n of e)r.set(n,i),i+=n.length;return r}var tt=Te(et());function _e(e,t){if((0,tt.validate)(e,t).length)throw new Error(`couldn't validate schema: ${JSON.stringify(t)} didn't match schema ${JSON.stringify(e)}`)}var rt="3",ot="https://webapp-production-dot-remarkable-production.appspot.com",Ur="https://rm-blob-storage-prod.appspot.com",nt="x-goog-generation",Lr="x-goog-if-generation-match",Br=["Ballpoint","Ballpointv2","Brush","Calligraphy","ClearPage","EraseSection","Eraser","Fineliner","Finelinerv2","Highlighter","Highlighterv2","Marker","Markerv2","Paintbrush","Paintbrushv2","Pencilv2","SharpPencil","SharpPencilv2","SolidPen","ZoomTool"],Nr=["Maison Neue","EB Garamond","Noto Sans","Noto Serif","Noto Mono","Noto Sans UI"],at={xs:.7,sm:.8,md:1,lg:1.2,xl:1.5,xx:2},ft={sm:50,md:125,rr:180,lg:200},ut={df:-1,md:100,lg:150,xl:200},Cr={properties:{relative_path:{type:"string"},url:{type:"string"},expires:{type:"timestamp"},method:{enum:["POST","GET","PUT","DELETE"]}}},it={visibleName:{type:"string"},parent:{type:"string"},lastModified:{type:"string"},version:{type:"int32"},synced:{type:"boolean"}},st={pinned:{type:"boolean"},modified:{type:"boolean"},deleted:{type:"boolean"},metadatamodified:{type:"boolean"}},$r={discriminator:"type",mapping:{CollectionType:{properties:it,optionalProperties:st},DocumentType:{properties:it,optionalProperties:{...st,lastOpened:{type:"string"},lastOpenedPage:{type:"int32"}}}}},q=class extends Error{constructor(r,i,n){super(n);this.status=r,this.statusText=i}},C=class extends Error{constructor(){super("Generation preconditions failed. This means the current state is out of date with the cloud and needs to be re-synced.")}};async function Hr(e,{deviceDesc:t="desktop-linux",uuid:r=ge(),authUrl:i=ot,fetch:n=globalThis.fetch}={}){if(e.length!==8)throw new Error(`code should be length 8, but was ${e.length}`);let s=await n(`${i}/token/json/2/device/new`,{method:"POST",headers:{Authorization:"Bearer"},body:JSON.stringify({code:e,deviceDesc:t,deviceID:r})});if(s.ok)return await s.text();throw new q(s.status,s.statusText,"couldn't register api")}function jr({hash:e,type:t,documentId:r,subfiles:i,size:n}){return`${e}:${t}:${r}:${i}:${n}
2
- `}function zr(e){let[t,r,i,n,s]=e.split(":");if(t===void 0||r===void 0||i===void 0||n===void 0||s===void 0)throw new Error(`entries line didn't contain five fields: '${e}'`);if(r==="80000000"){if(s!=="0")throw new Error(`collection type entry had nonzero size: ${s}`);return{hash:t,type:r,documentId:i,subfiles:parseInt(n),size:0n}}else if(r==="0"){if(n!=="0")throw new Error(`file type entry had nonzero number of subfiles: ${n}`);return{hash:t,type:r,documentId:i,subfiles:0,size:BigInt(s)}}else throw new Error(`entries line contained invalid type: ${r}`)}var xe=class{constructor(t,r,i,n,s){this.userToken=t;this.fetch=r;this.cache=i;this.subtle=n;this.blobUrl=s}async authedFetch(t,r,i="POST"){let n=await this.fetch(t,{method:i,headers:{Authorization:`Bearer ${this.userToken}`},body:r&&JSON.stringify(r)});if(n.ok)return n;throw new q(n.status,n.statusText,"failed reMarkable request")}async signedFetch({url:t,method:r},i,n){let s=await this.fetch(t,{method:r,body:i,headers:n});if(s.ok)return s;{let o=await s.text();throw new q(s.status,s.statusText,o)}}async getUrl(t,r){let i=r===void 0?"downloads":"uploads",n=r==null?void 0:`${r}`,o=await(await this.authedFetch(`${this.blobUrl}/api/v1/signed-urls/${i}`,{http_method:n===void 0?"GET":"PUT",relative_path:t,generation:n})).text(),a=JSON.parse(o);return _e(Cr,a),a}async syncComplete(){await this.authedFetch(`${this.blobUrl}/api/v1/sync-complete`)}async getRootHash(){let t=await this.getUrl("root"),r=await this.signedFetch(t),i=r.headers.get(nt);if(!i)throw new Error("no generation header in root hash");return[await r.text(),BigInt(i)]}async putRootHash(t,r){let i=await this.getUrl("root",r),n;try{n=await this.signedFetch(i,t,{[Lr]:`${r}`})}catch(o){throw o instanceof q&&o.status===412?new C:o}let s=n.headers.get(nt);if(!s)throw new Error("no generation header in root hash");return BigInt(s)}async getBuffer(t){let r=await this.getUrl(t);return await(await this.signedFetch(r)).arrayBuffer()}async getText(t){let r=this.cache&&await this.cache.get(t);if(r)return r;{let i=await this.getUrl(t),s=await(await this.signedFetch(i)).text();return this.cache&&await this.cache.set(t,s),s}}async getMetadata(t){let r=await this.getText(t),i=JSON.parse(r);return _e($r,i),i}async getEntries(t){let r=await this.getText(t),[i,...n]=r.slice(0,-1).split(`
3
- `);if(i!==rt)throw new Error(`got unexpected schema version: ${i}`);return n.map(zr)}async putHash(t,r){let i=await this.getUrl(t,null);await this.signedFetch(i,r)}async putEntries(t,r){let i=new TextEncoder;r.sort((p,b)=>p.documentId.localeCompare(b.documentId));let n=ze(r.map(p=>je(p.hash))),s=await this.subtle.digest("SHA-256",n),o=me(s),a=r.map(jr).join(""),f=`${rt}
4
- ${a}`,c=i.encode(f);return await this.putHash(o,c),this.cache&&await this.cache.set(o,f),{hash:o,type:"80000000",documentId:t,subfiles:r.length,size:0n}}async putBuffer(t,r){let i=await this.subtle.digest("SHA-256",r),n=me(i);return await this.putHash(n,r),{hash:n,type:"0",documentId:t,subfiles:0,size:BigInt(r.length)}}async putText(t,r){let i=new TextEncoder,n=await this.putBuffer(t,i.encode(r));return this.cache&&await this.cache.set(n.hash,r),n}async putEpub(t,r,{parent:i="",margins:n=125,orientation:s,textAlignment:o,textScale:a=1,lineHeight:f=-1,fontName:c="",cover:p="visited",lastTool:b,notify:l=!0,retries:I=3}={}){let _=ge(),se=`${new Date().valueOf()}`,D=[];D.push(this.putBuffer(`${_}.epub`,r));let L={type:"DocumentType",visibleName:t,version:0,parent:i,synced:!0,lastModified:se};D.push(this.putText(`${_}.metadata`,JSON.stringify(L)));let v={dummyDocument:!1,extraMetadata:{LastTool:b},fileType:"epub",pageCount:0,lastOpenedPage:0,lineHeight:typeof f=="string"?ut[f]:f,margins:typeof n=="string"?ft[n]:n,textScale:typeof a=="string"?at[a]:a,pages:[],coverPageNumber:p==="first"?0:-1,formatVersion:1,orientation:s,textAlignment:o,fontName:c};D.push(this.putText(`${_}.content`,JSON.stringify(v)));let oe=await Promise.all(D),ae=await this.putEntries(_,oe);for(;;--I)try{let[$,lt]=await this.getRootHash(),we=await this.getEntries($);we.push(ae);let{hash:dt}=await this.putEntries("",we);await this.putRootHash(dt,lt);break}catch($){if(I<=0||!($ instanceof C))throw $}l&&await this.syncComplete()}};async function Jr(e,{fetch:t=globalThis.fetch,cache:r,subtle:i=globalThis.crypto?.subtle,authUrl:n=ot,blobUrl:s=Ur}={}){let o=await t(`${n}/token/json/2/user/new`,{method:"POST",headers:{Authorization:`Bearer ${e}`}});if(!o.ok)throw new Error(`couldn't fetch auth token: ${o.statusText}`);let a=await o.text();return new xe(a,t,r,i,s)}0&&(module.exports={GenerationError,ResponseError,builtinFontNames,builtinLineHeights,builtinMargins,builtinTextScales,builtinTools,register,remarkable});