rmapi-js 1.0.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,20 +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);
39
- * await api.syncComplete();
43
+ * const nextGen = await api.putRootHash(hash, gen);
44
+ * await api.syncComplete(nextGen);
40
45
  * ```
41
46
  *
42
47
  * @packageDocumentation
43
48
  */
49
+ import { fromByteArray } from "base64-js";
44
50
  import { v4 as uuid4 } from "uuid";
45
51
  import { concatBuffers, fromHex, toHex } from "./utils";
46
52
  import { validate } from "./validate";
47
53
  const SCHEMA_VERSION = "3";
48
- const AUTH_URL = "https://webapp-production-dot-remarkable-production.appspot.com";
49
- 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";
50
56
  const GENERATION_HEADER = "x-goog-generation";
51
57
  const GENERATION_RACE_HEADER = "x-goog-if-generation-match";
58
+ const CONTENT_LENGTH_RANGE_HEADER = "x-goog-content-length-range";
52
59
  /** tool options */
53
60
  export const builtinTools = [
54
61
  "Ballpoint",
@@ -118,6 +125,12 @@ export const builtinLineHeights = {
118
125
  /** double */
119
126
  xl: 200,
120
127
  };
128
+ const uploadEntrySchema = {
129
+ properties: {
130
+ docID: { type: "string" },
131
+ hash: { type: "string" },
132
+ },
133
+ };
121
134
  const urlResponseSchema = {
122
135
  properties: {
123
136
  relative_path: { type: "string" },
@@ -125,19 +138,22 @@ const urlResponseSchema = {
125
138
  expires: { type: "timestamp" },
126
139
  method: { enum: ["POST", "GET", "PUT", "DELETE"] },
127
140
  },
141
+ optionalProperties: {
142
+ maxuploadsize_bytes: { type: "float64" },
143
+ },
128
144
  };
129
145
  const commonProperties = {
130
146
  visibleName: { type: "string" },
131
- parent: { type: "string" },
132
147
  lastModified: { type: "string" },
133
- version: { type: "int32" },
134
- synced: { type: "boolean" },
135
148
  };
136
149
  const commonOptionalProperties = {
150
+ version: { type: "int32" },
137
151
  pinned: { type: "boolean" },
152
+ synced: { type: "boolean" },
138
153
  modified: { type: "boolean" },
139
154
  deleted: { type: "boolean" },
140
155
  metadatamodified: { type: "boolean" },
156
+ parent: { type: "string" },
141
157
  };
142
158
  const metadataSchema = {
143
159
  discriminator: "type",
@@ -156,6 +172,34 @@ const metadataSchema = {
156
172
  },
157
173
  },
158
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
+ };
159
203
  /** an error that results from a failed request */
160
204
  export class ResponseError extends Error {
161
205
  /** the response status number */
@@ -182,18 +226,18 @@ export class GenerationError extends Error {
182
226
  /**
183
227
  * register a device and get the token needed to access the api
184
228
  *
185
- * 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
186
230
  * the resulting code into this function to get a device token. Persist that
187
231
  * token to use the api.
188
232
  *
189
- * @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`.
190
234
  * @returns the device token necessary for creating an api instace. These never expire so persist as long as necessary.
191
235
  */
192
- 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, } = {}) {
193
237
  if (code.length !== 8) {
194
238
  throw new Error(`code should be length 8, but was ${code.length}`);
195
239
  }
196
- const resp = await fetch(`${authUrl}/token/json/2/device/new`, {
240
+ const resp = await fetch(`${authHost}/token/json/2/device/new`, {
197
241
  method: "POST",
198
242
  headers: {
199
243
  Authorization: "Bearer",
@@ -254,37 +298,45 @@ export function parseEntry(line) {
254
298
  }
255
299
  /** the implementation of that api */
256
300
  class Remarkable {
257
- userToken;
258
- fetch;
259
- cache;
260
- subtle;
261
- blobUrl;
262
- constructor(userToken, fetch, cache, subtle, blobUrl) {
263
- this.userToken = userToken;
264
- this.fetch = fetch;
265
- this.cache = cache;
266
- this.subtle = subtle;
267
- 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;
268
312
  }
269
313
  /** make an authorized request to remarkable */
270
- async authedFetch(url, body, method = "POST") {
271
- const resp = await this.fetch(url, {
314
+ async #authedFetch(url, { body, method = "POST", headers = {}, }) {
315
+ const resp = await this.#fetch(url, {
272
316
  method,
273
317
  headers: {
274
- Authorization: `Bearer ${this.userToken}`,
318
+ Authorization: `Bearer ${this.#userToken}`,
319
+ ...headers,
275
320
  },
276
- body: body && JSON.stringify(body),
321
+ body,
277
322
  });
278
323
  if (!resp.ok) {
279
- 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}`);
280
326
  }
281
327
  else {
282
328
  return resp;
283
329
  }
284
330
  }
285
331
  /** make a signed request to the cloud */
286
- async signedFetch({ url, method }, body, headers) {
287
- 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, {
288
340
  method,
289
341
  body,
290
342
  headers,
@@ -298,29 +350,24 @@ class Remarkable {
298
350
  }
299
351
  }
300
352
  /** get the details for how to make a signed request to remarkable cloud */
301
- async getUrl(relativePath, gen) {
353
+ async #getUrl(relativePath, gen, rootHash) {
302
354
  const key = gen === undefined ? "downloads" : "uploads";
303
- const generation = gen === null || gen === undefined ? undefined : `${gen}`;
304
- const resp = await this.authedFetch(`${this.blobUrl}/api/v1/signed-urls/${key}`, {
305
- http_method: generation === undefined ? "GET" : "PUT",
306
- relative_path: relativePath,
307
- generation,
308
- });
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 });
309
360
  const raw = await resp.text();
310
361
  const res = JSON.parse(raw);
311
362
  validate(urlResponseSchema, res);
312
363
  return res;
313
364
  }
314
- /** sends a signal to the server that a sync is complete and other devices should update */
315
- async syncComplete() {
316
- await this.authedFetch(`${this.blobUrl}/api/v1/sync-complete`);
317
- }
318
365
  /**
319
366
  * get the root hash and the current generation
320
367
  */
321
368
  async getRootHash() {
322
- const signed = await this.getUrl("root");
323
- const resp = await this.signedFetch(signed);
369
+ const signed = await this.#getUrl("root");
370
+ const resp = await this.#signedFetch(signed);
324
371
  const generation = resp.headers.get(GENERATION_HEADER);
325
372
  if (!generation) {
326
373
  throw new Error("no generation header in root hash");
@@ -331,10 +378,10 @@ class Remarkable {
331
378
  * write the root hash, incrementing from the current generation
332
379
  */
333
380
  async putRootHash(hash, generation) {
334
- const signed = await this.getUrl("root", generation);
381
+ const signed = await this.#getUrl("root", generation, hash);
335
382
  let resp;
336
383
  try {
337
- resp = await this.signedFetch(signed, hash, {
384
+ resp = await this.#signedFetch(signed, hash, {
338
385
  [GENERATION_RACE_HEADER]: `${generation}`,
339
386
  });
340
387
  }
@@ -356,23 +403,23 @@ class Remarkable {
356
403
  * get text content associated with hash
357
404
  */
358
405
  async getBuffer(hash) {
359
- const signed = await this.getUrl(hash);
360
- const resp = await this.signedFetch(signed);
406
+ const signed = await this.#getUrl(hash);
407
+ const resp = await this.#signedFetch(signed);
361
408
  return await resp.arrayBuffer();
362
409
  }
363
410
  /**
364
411
  * get text content associated with hash
365
412
  */
366
413
  async getText(hash) {
367
- const cached = this.cache && (await this.cache.get(hash));
414
+ const cached = await this.#cache?.get(hash);
368
415
  if (cached) {
369
416
  return cached;
370
417
  }
371
418
  else {
372
- const signed = await this.getUrl(hash);
373
- const resp = await this.signedFetch(signed);
419
+ const signed = await this.#getUrl(hash);
420
+ const resp = await this.#signedFetch(signed);
374
421
  const raw = await resp.text();
375
- this.cache && (await this.cache.set(hash, raw));
422
+ await this.#cache?.set(hash, raw);
376
423
  return raw;
377
424
  }
378
425
  }
@@ -398,9 +445,9 @@ class Remarkable {
398
445
  return lines.map(parseEntry);
399
446
  }
400
447
  /** upload data to hash */
401
- async putHash(hash, body) {
402
- const signed = await this.getUrl(hash, null);
403
- await this.signedFetch(signed, body);
448
+ async #putHash(hash, body) {
449
+ const signed = await this.#getUrl(hash, null);
450
+ await this.#signedFetch(signed, body);
404
451
  }
405
452
  /** put a reference to a set of entries into the cloud */
406
453
  async putEntries(documentId, entries) {
@@ -408,13 +455,13 @@ class Remarkable {
408
455
  const enc = new TextEncoder();
409
456
  entries.sort((a, b) => a.documentId.localeCompare(b.documentId));
410
457
  const hashes = concatBuffers(entries.map((ent) => fromHex(ent.hash)));
411
- const digest = await this.subtle.digest("SHA-256", hashes);
458
+ const digest = await this.#subtle.digest("SHA-256", hashes);
412
459
  const hash = toHex(digest);
413
460
  const entryContents = entries.map(formatEntry).join("");
414
461
  const contents = `${SCHEMA_VERSION}\n${entryContents}`;
415
462
  const buffer = enc.encode(contents);
416
- await this.putHash(hash, buffer);
417
- this.cache && (await this.cache.set(hash, contents));
463
+ await this.#putHash(hash, buffer);
464
+ await this.#cache?.set(hash, contents);
418
465
  return {
419
466
  hash,
420
467
  type: "80000000",
@@ -425,9 +472,9 @@ class Remarkable {
425
472
  }
426
473
  /** put a raw buffer in the cloud */
427
474
  async putBuffer(documentId, buffer) {
428
- const digest = await this.subtle.digest("SHA-256", buffer);
475
+ const digest = await this.#subtle.digest("SHA-256", buffer);
429
476
  const hash = toHex(digest);
430
- await this.putHash(hash, buffer);
477
+ await this.#putHash(hash, buffer);
431
478
  return {
432
479
  hash,
433
480
  type: "0",
@@ -440,16 +487,20 @@ class Remarkable {
440
487
  async putText(documentId, contents) {
441
488
  const enc = new TextEncoder();
442
489
  const entry = await this.putBuffer(documentId, enc.encode(contents));
443
- this.cache && (await this.cache.set(entry.hash, contents));
490
+ await this.#cache?.set(entry.hash, contents);
444
491
  return entry;
445
492
  }
446
- /** upload an epub */
447
- 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
+ }
448
499
  const documentId = uuid4();
449
500
  const lastModified = `${new Date().valueOf()}`;
450
501
  const entryPromises = [];
451
502
  // upload main document
452
- entryPromises.push(this.putBuffer(`${documentId}.epub`, buffer));
503
+ entryPromises.push(this.putBuffer(`${documentId}.${fileType}`, buffer));
453
504
  // upload metadata
454
505
  const metadata = {
455
506
  type: "DocumentType",
@@ -460,6 +511,15 @@ class Remarkable {
460
511
  lastModified,
461
512
  };
462
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, } = {}) {
463
523
  // upload content file
464
524
  const content = {
465
525
  dummyDocument: false,
@@ -483,12 +543,78 @@ class Remarkable {
483
543
  textAlignment,
484
544
  fontName,
485
545
  };
486
- entryPromises.push(this.putText(`${documentId}.content`, JSON.stringify(content)));
487
- // NOTE we technically get the entries a bit earlier, so could upload this
488
- // before all contents are uploaded, but this also saves us from uploading
489
- // the contents entry before all have uploaded successfully
490
- const entries = await Promise.all(entryPromises);
491
- 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");
492
618
  }
493
619
  }
494
620
  /**
@@ -497,11 +623,12 @@ class Remarkable {
497
623
  * This gets a temporary authentication token with the device token. If
498
624
  * requests start failing, simply recreate the api instance.
499
625
  *
500
- * @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}.
501
628
  * @returns an api instance
502
629
  */
503
- export async function remarkable(deviceToken, { fetch = globalThis.fetch, cache, subtle = globalThis.crypto?.subtle, authUrl = AUTH_URL, blobUrl = BLOB_URL, } = {}) {
504
- 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`, {
505
632
  method: "POST",
506
633
  headers: {
507
634
  Authorization: `Bearer ${deviceToken}`,
@@ -511,5 +638,5 @@ export async function remarkable(deviceToken, { fetch = globalThis.fetch, cache,
511
638
  throw new Error(`couldn't fetch auth token: ${resp.statusText}`);
512
639
  }
513
640
  const userToken = await resp.text();
514
- return new Remarkable(userToken, fetch, cache, subtle, blobUrl);
641
+ return new Remarkable(userToken, fetch, cache, subtle, syncHost);
515
642
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rmapi-js",
3
- "version": "1.0.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.2",
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",
31
- "uuid": "^8.3.2"
30
+ "ajv": "^8.11.2",
31
+ "base64-js": "^1.5.1",
32
+ "jtd": "^0.1.1",
33
+ "uuid": "^9.0.0"
32
34
  },
33
35
  "devDependencies": {
34
- "@babel/core": "^7.18.10",
35
- "@babel/preset-env": "^7.18.10",
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": "^28.1.6",
40
- "@types/node": "^18.6.4",
41
- "@types/uuid": "^8.3.4",
42
- "@typescript-eslint/eslint-plugin": "^5.32.0",
43
- "@typescript-eslint/parser": "^5.32.0",
44
- "@yarnpkg/esbuild-plugin-pnp": "^3.0.0-rc.14",
45
- "babel-jest": "^28.1.3",
46
- "chalk": "^5.0.1",
47
- "esbuild": "^0.14.53",
48
- "eslint": "^8.21.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",
46
+ "@yarnpkg/esbuild-plugin-pnp": "^3.0.0-rc.15",
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": "^26.7.0",
51
- "eslint-plugin-spellcheck": "^0.0.19",
52
- "eslint-plugin-tsdoc": "^0.2.16",
53
- "jest": "^28.1.3",
54
- "jtd": "^0.1.1",
55
- "prettier": "^2.7.1",
56
- "prettier-plugin-organize-imports": "^3.0.2",
57
- "typedoc": "^0.23.10",
58
- "typescript": "^4.7.4"
52
+ "eslint-plugin-jest": "^27.1.7",
53
+ "eslint-plugin-spellcheck": "^0.0.20",
54
+ "eslint-plugin-tsdoc": "^0.2.17",
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});