rmapi-js 10.0.1 → 10.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +5 -5
- package/dist/raw.d.ts +6 -1
- package/dist/raw.js +6 -2
- package/dist/rmapi-js.esm.min.js +5 -5
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -348,7 +348,7 @@ class Remarkable {
|
|
|
348
348
|
]);
|
|
349
349
|
// now upload a new root entry
|
|
350
350
|
rootEntries.push(collectionEntry);
|
|
351
|
-
const [rootEntry, uploadRoot] = await this.raw.putEntries("root", rootEntries,
|
|
351
|
+
const [rootEntry, uploadRoot] = await this.raw.putEntries("root", rootEntries, 4);
|
|
352
352
|
// before updating the root hash, first upload everything
|
|
353
353
|
await Promise.all([
|
|
354
354
|
uploadContent,
|
|
@@ -402,7 +402,7 @@ class Remarkable {
|
|
|
402
402
|
]);
|
|
403
403
|
// now upload a new root entry
|
|
404
404
|
rootEntries.push(collectionEntry);
|
|
405
|
-
const [rootEntry, uploadRoot] = await this.raw.putEntries("root", rootEntries,
|
|
405
|
+
const [rootEntry, uploadRoot] = await this.raw.putEntries("root", rootEntries, 4);
|
|
406
406
|
// before updating the root hash, first upload everything
|
|
407
407
|
await Promise.all([
|
|
408
408
|
uploadContent,
|
|
@@ -459,7 +459,7 @@ class Remarkable {
|
|
|
459
459
|
throw new Error(`expected type ${expectedType} but got ${meta.type} for hash ${hash}`);
|
|
460
460
|
}
|
|
461
461
|
entries[hashInd] = newEnt;
|
|
462
|
-
const [rootEntry, uploadRoot] = await this.raw.putEntries("root", entries,
|
|
462
|
+
const [rootEntry, uploadRoot] = await this.raw.putEntries("root", entries, 4);
|
|
463
463
|
await Promise.all([uploadEnt, uploadRoot]);
|
|
464
464
|
await this.#putRootHash(rootEntry.hash, generation);
|
|
465
465
|
return { hash: newEnt.hash };
|
|
@@ -501,7 +501,7 @@ class Remarkable {
|
|
|
501
501
|
}
|
|
502
502
|
const [newEnt, uploadEnt] = await this.#editMetaRaw(hashEnt.id, hash, update, schemaVersion);
|
|
503
503
|
entries[hashInd] = newEnt;
|
|
504
|
-
const [rootEntry, uploadRoot] = await this.raw.putEntries("root", entries,
|
|
504
|
+
const [rootEntry, uploadRoot] = await this.raw.putEntries("root", entries, 4);
|
|
505
505
|
await Promise.all([uploadEnt, uploadRoot]);
|
|
506
506
|
await this.#putRootHash(rootEntry.hash, generation);
|
|
507
507
|
return { hash: newEnt.hash };
|
|
@@ -547,7 +547,7 @@ class Remarkable {
|
|
|
547
547
|
uploads.push(upload);
|
|
548
548
|
result[toUpdate[i].hash] = newEnt.hash;
|
|
549
549
|
}
|
|
550
|
-
const [rootEntry, uploadRoot] = await this.raw.putEntries("root", newEntries,
|
|
550
|
+
const [rootEntry, uploadRoot] = await this.raw.putEntries("root", newEntries, 4);
|
|
551
551
|
await Promise.all([Promise.all(uploads), uploadRoot]);
|
|
552
552
|
await this.#putRootHash(rootEntry.hash, generation);
|
|
553
553
|
return { hashes: result };
|
package/dist/raw.d.ts
CHANGED
|
@@ -216,7 +216,7 @@ export interface CommonDocumentContent {
|
|
|
216
216
|
/** a mapping from page number to page id in pages */
|
|
217
217
|
redirectionPageMap?: number[];
|
|
218
218
|
/** ostensibly the size in bytes of the file, but this differs from other measurements */
|
|
219
|
-
sizeInBytes
|
|
219
|
+
sizeInBytes?: string;
|
|
220
220
|
/** text alignment for this document */
|
|
221
221
|
textAlignment: TextAlignment;
|
|
222
222
|
/**
|
|
@@ -549,6 +549,11 @@ export interface RawRemarkableApi {
|
|
|
549
549
|
* 3. append this entry to the root entry and call this again to update this root list
|
|
550
550
|
* 4. put the new root hash
|
|
551
551
|
*
|
|
552
|
+
* NOTE: reMarkable currently rejects newly written schema 3 root indexes
|
|
553
|
+
* with a 400 "Software must be updated" error, even for accounts that still
|
|
554
|
+
* report schema 3, so the root list should always be written as schema 4. A
|
|
555
|
+
* warning is logged if a schema 3 root index is written.
|
|
556
|
+
*
|
|
552
557
|
* @param id - the id of the list to upload - this should be the item id if
|
|
553
558
|
* uploading an item list, or "root" if uploading a new root list.
|
|
554
559
|
* @param entries - the entries to upload
|
package/dist/raw.js
CHANGED
|
@@ -77,7 +77,6 @@ const documentContentRequired = {
|
|
|
77
77
|
lineHeight: int32(),
|
|
78
78
|
orientation: enumeration("portrait", "landscape"),
|
|
79
79
|
pageCount: uint32(),
|
|
80
|
-
sizeInBytes: string(),
|
|
81
80
|
textAlignment: enumeration("", "justify", "left"),
|
|
82
81
|
textScale: float64(),
|
|
83
82
|
};
|
|
@@ -101,6 +100,7 @@ const documentContentOptional = {
|
|
|
101
100
|
pages: nullable(elements(string())),
|
|
102
101
|
pageTags: elements(pageTag),
|
|
103
102
|
redirectionPageMap: elements(int32()),
|
|
103
|
+
sizeInBytes: string(),
|
|
104
104
|
transform: properties(undefined, {
|
|
105
105
|
m11: float64(),
|
|
106
106
|
m12: float64(),
|
|
@@ -420,6 +420,9 @@ export class RawRemarkable {
|
|
|
420
420
|
}
|
|
421
421
|
}
|
|
422
422
|
async putEntries(id, entries, schemaVersion) {
|
|
423
|
+
if (id === "root" && schemaVersion === 3) {
|
|
424
|
+
console.warn('writing a schema 3 root index, which reMarkable rejects with a 400 "Software must be updated" error; write the root index with schema version 4 instead');
|
|
425
|
+
}
|
|
423
426
|
// NOTE v3 collections have a special hash function, the hash of their
|
|
424
427
|
// contents, so this needs to be different
|
|
425
428
|
entries.sort((a, b) => a.id.localeCompare(b.id));
|
|
@@ -430,7 +433,8 @@ export class RawRemarkable {
|
|
|
430
433
|
records.push(`0:${name}:${entries.length}:${size}\n`);
|
|
431
434
|
}
|
|
432
435
|
for (const { hash, type, id, subfiles, size } of entries) {
|
|
433
|
-
|
|
436
|
+
const lineType = schemaVersion === 4 ? 0 : type;
|
|
437
|
+
records.push(`${hash}:${lineType}:${id}:${subfiles}:${size}\n`);
|
|
434
438
|
}
|
|
435
439
|
const enc = new TextEncoder();
|
|
436
440
|
const entryBuff = enc.encode(records.join(""));
|
package/dist/rmapi-js.esm.min.js
CHANGED
|
@@ -9,15 +9,15 @@ While trying to validate:
|
|
|
9
9
|
${$}
|
|
10
10
|
|
|
11
11
|
Against schema:
|
|
12
|
-
${X}`)}else return!0}}class NX extends S0{#Q;definitions;nullable=!0;constructor(Q){super();this.#Q=Q,this.definitions=Q.definitions}*pathErrors(Q){if(Q!==null)for(let[q,$]of this.#Q.pathErrors(Q))yield[q,`${$} or ${$2(Q)} is not null`]}fuzz(){return v6(0.1)?null:this.#Q.fuzz()}schema(){return{...this.#Q.schema(),nullable:!0}}}function E6(Q){return new NX(Q)}class yZ extends S0{#Q;#q;definitions;nullable;constructor(Q,q){super();this.#Q=Q,this.#q=q,this.definitions=Q.definitions,this.nullable=Q.nullable}*pathErrors(Q){yield*this.#Q.pathErrors(Q)}fuzz(){return this.#Q.fuzz()}schema(){return{...this.#Q.schema(),metadata:this.#q}}}class DX extends S0{*pathErrors(Q){if(Q===void 0)yield[[],"value is undefined"]}fuzz(){return k8([()=>null,v6,m4,()=>i1(V2()),()=>Array(V2()).fill(null).map(()=>this.fuzz()),()=>Object.fromEntries(Array(V2()).fill(null).map(()=>[i1(V2(3)),this.fuzz()]))])()}schema(){return{}}}function AX(){return new DX}class OX extends S0{*pathErrors(Q){if(typeof Q!=="boolean")yield[[],`${$2(Q)} is not a boolean`]}fuzz(){return v6()}schema(){return{type:"boolean"}}}function w1(){return new OX}class g8 extends S0{#Q;#q;#$;constructor(Q){super();this.#Q=Q,[this.#q,this.#$]=SZ[Q]}*pathErrors(Q){if(typeof Q!=="number")yield[[],`${$2(Q)} is not a number`];else if(Q%1!==0)yield[[],`${Q.toPrecision()} is not an integer`];else if(Q<this.#q)yield[[],`${Q.toFixed()} is less than ${this.#q.toFixed()}`];else if(Q>=this.#$)yield[[],`${Q.toFixed()} is greater than ${(this.#$-1).toFixed()}`]}fuzz(){return CX(this.#q,this.#$)}schema(){return{type:this.#Q}}}function y8(){return new g8("uint8")}function z2(){return new g8("int32")}function o1(){return new g8("uint32")}class RX extends S0{#Q;constructor(Q){super();this.#Q=Q}*pathErrors(Q){if(typeof Q!=="number")yield[[],`${$2(Q)} is not number, expected a float`]}fuzz(){return m4()}schema(){return{type:this.#Q}}}function O0(){return new RX("float64")}class xX extends S0{*pathErrors(Q){if(typeof Q!=="string")yield[[],`${$2(Q)} is not a string`]}fuzz(){return i1(V2(3))}schema(){return{type:"string"}}}function F0(){return new xX}class TX extends S0{*pathErrors(Q){if(typeof Q!=="string")yield[[],`${$2(Q)} is not a string`];else if(!xZ(Q))yield[[],`${Q} is not a valid timestamp`]}fuzz(){return new Date(Math.random()*3153600000000).toISOString()}schema(){return{type:"timestamp"}}}function vX(){return new TX}class EX extends S0{#Q;#q;constructor(Q,q){super();this.#Q=Q,this.#q=q}*pathErrors(Q){if(typeof Q!=="string")yield[[],`${$2(Q)} is not a string`];else if(!this.#q.has(Q))yield[[],`${Q} is not one of ${this.#Q.join(", ")}`]}fuzz(){return k8(this.#Q)}schema(){return{enum:[...this.#Q]}}}function C2(...Q){let q=new Set(Q);if(q.size!==Q.length)throw Error("enum can't contain duplicates");else return new EX(Q,q)}class SX extends S0{#Q;constructor(Q){super();this.#Q=Q}*pathErrors(Q){if(!Array.isArray(Q))yield[[],`${$2(Q)} is not an array`];else for(let[q,$]of Q.entries())for(let[X,Y]of this.#Q.pathErrors($))X.push(`[${q.toFixed()}]`),yield[X,Y]}fuzz(){return Array(V2()).fill(null).map(()=>this.#Q.fuzz())}schema(){return{elements:this.#Q.schema()}}}function h0(Q){if(Q.definitions)throw Error("definitions can only exist on a root schema");else return new SX(Q)}class kX extends S0{#Q;constructor(Q){super();this.#Q=Q}*pathErrors(Q){if(!S8(Q))yield[[],`${$2(Q)} is not a record`];else for(let[q,$]of Object.entries(Q))for(let[X,Y]of this.#Q.pathErrors($))X.push(l1(q)),yield[X,Y]}fuzz(){return Object.fromEntries(Array(V2()).fill(null).map(()=>[i1(V2(3)),this.#Q.fuzz()]))}schema(){return{values:this.#Q.schema()}}}function S6(Q){if(Q.definitions)throw Error("definitions can only exist on a root schema");else return new kX(Q)}class gX extends S0{#Q;#q;#$;keys;constructor(Q,q,$,X){super();this.#Q=Q,this.#q=q,this.#$=$,this.keys=X}*pathErrors(Q){if(!S8(Q))yield[[],`${$2(Q)} is not a record`];else{if(this.#Q)for(let[q,$]of this.#Q){let X=Q[q];if(X===void 0)yield[[],`required key '${q}' is missing`];else for(let[Y,J]of $.pathErrors(X))Y.push(l1(q)),yield[Y,J]}if(this.#q){for(let[q,$]of this.#q)if(Q[q]!==void 0)for(let[X,Y]of $.pathErrors(Q[q]))X.push(l1(q)),yield[X,Y]}if(!this.#$){for(let q of Object.keys(Q))if(!this.keys.has(q))yield[[l1(q)],`'${q}' is not a valid property and additional properties are not allowed`]}}}fuzz(){let Q=E8(this.#Q??[],([X,Y])=>[X,Y.fuzz()]),q=E8(kZ(this.#q??[],()=>v6()),([X,Y])=>[X,Y.fuzz()]),$=this.#$?E8(gZ(V2()),()=>[i1(V2(3)),k8([()=>null,v6,m4,()=>i1(V2()),()=>[],()=>({})])()]):[];return Object.fromEntries(IX(Q,q,$))}schema(){let Q={};if(this.#Q)Q.properties=Object.fromEntries(this.#Q.map(([q,$])=>[q,$.schema()]));if(this.#q)Q.optionalProperties=Object.fromEntries(this.#q.map(([q,$])=>[q,$.schema()]));if(this.#$)Q.additionalProperties=!0;return Q}}function fZ(Q,q,$){let X=new Set(E8(IX(Q??[],q??[]),([Y])=>Y));if(Q?.some(([,Y])=>Y.definitions))throw Error("definitions can only exist on a root schema");else if(q?.some(([,Y])=>Y.definitions))throw Error("definitions can only exist on a root schema");else if(X.size!==(Q?.length??0)+(q?.length??0))throw Error("properties and optionalProperties keys must be unique");else return new gX(Q,q,$??!1,X)}function C0(Q,q,$){return fZ(Q?Object.entries(Q):void 0,q?Object.entries(q):void 0,$)}class hZ extends S0{#Q;#q;#$;constructor(Q,q,$){super();this.#Q=Q,this.#q=q,this.#$=$}guard(Q){if(!S8(Q))return!1;let{[this.#Q]:q,...$}=Q;if(typeof q!=="string")return!1;return this.#q[q]?.guard($)??!1}*pathErrors(Q){if(!S8(Q))yield[[],`${$2(Q)} is not an object`];else{let{[this.#Q]:q,...$}=Q;if(q===void 0)yield[[],`discriminator key '${this.#Q}' is missing`];else if(typeof q!=="string")yield[[l1(this.#Q)],`${$2(q)} is not a string`];else{let X=this.#q[q];if(X===void 0)yield[[l1(this.#Q)],`'${q}' is not a valid discriminator value (${Object.keys(this.#q).join(", ")})`];else yield*X.pathErrors($)}}}fuzz(){let[Q,q]=k8(this.#$);return{...q.fuzz(),[this.#Q]:Q}}schema(){let Q=Object.fromEntries(this.#$.map(([q,$])=>[q,$.schema()]));return{discriminator:this.#Q,mapping:Q}}}class yX extends S0{#Q;#q;definitions=!0;constructor(Q,q){super();this.#Q=Q,this.#q=q}*pathErrors(Q){yield*this.#q.pathErrors(Q)}fuzz(){return this.#q.fuzz()}schema(){let Q=Object.fromEntries(Object.entries(this.#Q).map(([q,$])=>[q,$.schema()]));return{...this.#q.schema(),definitions:Q}}}class fX extends S0{#Q;#q;constructor(Q,q){super();this.#Q=Q,this.#q=q}*pathErrors(Q){yield*this.#q.pathErrors(Q)}fuzz(){return this.#q.fuzz()}schema(){return{ref:this.#Q}}}class hX{#Q;#q;constructor(Q,q){this.#Q=Q,this.#q=q}def(Q,q){let $=q(this.#q);return new hX({...this.#Q,[Q]:$},{...this.#q,[Q]:new fX(Q,$)})}build(Q){return new yX(this.#Q,Q(this.#q))}}class _Z extends S0{#Q;#q;constructor(Q,q){super();this.#q=Q,this.#Q=q}#$(){let Q=this.#q[this.#Q];if(Q===void 0)throw Error(`ref ${this.#Q} was not in definitions after ref builder was finished`);else return Q}*pathErrors(Q){yield*this.#$().pathErrors(Q)}fuzz(){return this.#$().fuzz()}schema(){return{ref:this.#Q}}}var bZ=new Uint8Array(16);function d4(){return crypto.getRandomValues(bZ)}var k0=[];for(let Q=0;Q<256;++Q)k0.push((Q+256).toString(16).slice(1));function _X(Q,q=0){return(k0[Q[q+0]]+k0[Q[q+1]]+k0[Q[q+2]]+k0[Q[q+3]]+"-"+k0[Q[q+4]]+k0[Q[q+5]]+"-"+k0[Q[q+6]]+k0[Q[q+7]]+"-"+k0[Q[q+8]]+k0[Q[q+9]]+"-"+k0[Q[q+10]]+k0[Q[q+11]]+k0[Q[q+12]]+k0[Q[q+13]]+k0[Q[q+14]]+k0[Q[q+15]]).toLowerCase()}function uZ(Q,q,$){if(!q&&!Q&&crypto.randomUUID)return crypto.randomUUID();return cZ(Q,q,$)}function cZ(Q,q,$){Q=Q||{};let X=Q.random??Q.rng?.()??d4();if(X.length<16)throw Error("Random bytes length must be >= 16");if(X[6]=X[6]&15|64,X[8]=X[8]&63|128,q){if($=$||0,$<0||$+16>q.length)throw RangeError(`UUID byte range ${$}:${$+15} is out of buffer bounds`);for(let Y=0;Y<16;++Y)q[$+Y]=X[Y];return q}return _X(X)}var n1=uZ;class I2 extends Error{field;regex;constructor(Q,q,$){super($);this.field=Q,this.regex=q}}class k6 extends Error{hash;constructor(Q){super(`'${Q}' not found in the root hash`);this.hash=Q}}class l4 extends Map{#Q;#q=0;constructor(Q,q=[]){super();this.#Q=Q;for(let[$,X]of q)this.set($,X)}get(Q){let q=super.get(Q);if(q!==void 0)super.delete(Q),super.set(Q,q);return q}set(Q,q){let $=super.get(Q);if($===void 0)this.#q+=Q.length;else if($!==null)this.#q-=$.length;if(q!==null)this.#q+=q.length;super.delete(Q);let X;while(this.#q>this.#Q&&(X=this.entries().next().value)){let[Y,J]=X;if(super.delete(Y),this.#q-=Y.length,J!==null)this.#q-=J.length}return super.set(Q,q),this}delete(Q){let q=super.get(Q);if(q===void 0)return!1;if(super.delete(Q),q!==null)this.#q-=q.length;return this.#q-=Q.length,!0}clear(){super.clear(),this.#q=0}}var eK=V5(uX(),1);function cX(Q){let q=Q.reduce((Y,J)=>Y+J.length,0),$=new Uint8Array(q),X=0;for(let Y of Q)$.set(Y,X),X+=Y.length;return $}var kC=V5(sK(),1),$5=/^[0-9a-f]{64}$/,QU=C0({name:F0(),timestamp:O0()},void 0,!0),xw=C0({name:F0(),pageId:F0(),timestamp:O0()},void 0,!0),Tw=C0(void 0,{authors:h0(F0()),title:F0(),publicationDate:F0(),publisher:F0()},!0),vw=C0({id:F0(),idx:C0({timestamp:F0(),value:F0()},void 0,!0)},{template:C0({timestamp:F0(),value:F0()},void 0,!0),redir:C0({timestamp:F0(),value:z2()},void 0,!0),scrollTime:C0({timestamp:F0(),value:vX()},void 0,!0),verticalScroll:C0({timestamp:F0(),value:O0()},void 0,!0),deleted:C0({timestamp:F0(),value:z2()},void 0,!0)},!0),Ew=C0({lastOpened:C0({timestamp:F0(),value:F0()},void 0,!0),original:C0({timestamp:F0(),value:z2()},void 0,!0),pages:h0(vw),uuids:E6(h0(C0({first:F0(),second:o1()},void 0,!0)))},void 0,!0),Sw=C0(void 0,{tags:h0(QU)}),kw=C0(void 0,{tags:h0(F0())}),qU={coverPageNumber:z2(),documentMetadata:Tw,extraMetadata:S6(F0()),fileType:C2("epub","notebook","pdf"),fontName:F0(),lineHeight:z2(),orientation:C2("portrait","landscape"),pageCount:o1(),sizeInBytes:F0(),textAlignment:C2("","justify","left"),textScale:O0()},$U={cPages:Ew,customZoomCenterX:O0(),customZoomCenterY:O0(),customZoomOrientation:C2("portrait","landscape"),customZoomPageHeight:O0(),customZoomPageWidth:O0(),customZoomScale:O0(),dummyDocument:w1(),formatVersion:y8(),keyboardMetadata:C0({count:o1(),timestamp:O0()},void 0,!0),lastOpenedPage:z2(),margins:o1(),originalPageCount:z2(),pages:E6(h0(F0())),pageTags:h0(xw),redirectionPageMap:h0(z2()),transform:C0(void 0,{m11:O0(),m12:O0(),m13:O0(),m21:O0(),m22:O0(),m23:O0(),m31:O0(),m32:O0(),m33:O0()},!0),viewBackgroundFilter:C2("off","fullpage"),zoomMode:C2("bestFit","customFit","fitToHeight","fitToWidth")},gw=C0(qU,{...$U,tags:h0(QU)},!0),yw=C0(qU,{...$U,tags:h0(F0())},!0),fw=C0({name:F0(),author:F0(),iconData:F0(),categories:h0(F0()),labels:h0(F0()),orientation:C2("portrait","landscape"),templateVersion:F0(),supportedScreens:h0(C2("rm2","rmPP")),constants:h0(S6(z2())),items:h0(AX())},{formatVersion:y8()}),hw=C0({lastModified:F0(),parent:F0(),pinned:w1(),type:C2("DocumentType","CollectionType","TemplateType"),visibleName:F0()},{lastOpened:F0(),lastOpenedPage:z2(),createdTime:F0(),deleted:w1(),metadatamodified:w1(),modified:w1(),synced:w1(),version:o1()},!0),_w=C0({hash:F0(),generation:O0()},void 0,!0),bw=C0({hash:F0(),generation:O0(),schemaVersion:y8()},void 0,!0),uw=C0({docID:F0(),hash:F0()},void 0,!0);async function dQ(Q){let q=await crypto.subtle.digest("SHA-256",Q);return new Uint8Array(q).toHex()}function tK(Q){let[q,$,X,Y,J]=Q.split(":");if(q===void 0||$===void 0||X===void 0||Y===void 0||J===void 0)throw Error(`line '${Q}' was not formatted correctly`);else if($==="80000000"||$==="0")return{hash:q,type:$==="0"?0:80000000,id:X,subfiles:parseInt(Y,10),size:parseInt(J,10)};else throw Error(`line '${Q}' was not formatted correctly`)}class lQ{#Q;#q;#$;#X;constructor(Q,q,$,X){this.#Q=Q,this.#X=q,this.#q=$,this.#$=X}async getRootHash(){let q=await(await this.#Q("GET",`${this.#q}/sync/v4/root`)).text(),$=JSON.parse(q);if(!bw.guardAssert($))throw Error("invalid root hash");let{hash:X,generation:Y,schemaVersion:J}=$;if(J!==3&&J!==4)throw Error(`schema version ${J} not supported`);else if(!Number.isSafeInteger(Y))throw Error(`generation ${Y} was not a safe integer; please file a bug report`);else return[X,Y,J]}async#Y(Q,q){if(!$5.test(q))throw new I2(q,$5,"hash was not a valid hash");let X=await(await this.#Q("GET",`${this.#q}/sync/v3/files/${q}`,{headers:{"rm-filename":Q}})).arrayBuffer();return new Uint8Array(X)}async getHash(Q,q){let $=this.#X.get(q);if($!=null)return new TextEncoder().encode($);else{let X=await this.#Y(Q,q);if(this.#X.get(q)===void 0)this.#X.set(q,null);return X}}async getText(Q,q){let $=this.#X.get(q);if($!=null)return $;else{let X=await this.#Y(Q,q),J=new TextDecoder().decode(X);return this.#X.set(q,J),J}}async getEntries(Q,q){let $=await this.getText(Q,q),[X,...Y]=$.slice(0,-1).split(`
|
|
12
|
+
${X}`)}else return!0}}class NX extends S0{#Q;definitions;nullable=!0;constructor(Q){super();this.#Q=Q,this.definitions=Q.definitions}*pathErrors(Q){if(Q!==null)for(let[q,$]of this.#Q.pathErrors(Q))yield[q,`${$} or ${$2(Q)} is not null`]}fuzz(){return v6(0.1)?null:this.#Q.fuzz()}schema(){return{...this.#Q.schema(),nullable:!0}}}function E6(Q){return new NX(Q)}class yZ extends S0{#Q;#q;definitions;nullable;constructor(Q,q){super();this.#Q=Q,this.#q=q,this.definitions=Q.definitions,this.nullable=Q.nullable}*pathErrors(Q){yield*this.#Q.pathErrors(Q)}fuzz(){return this.#Q.fuzz()}schema(){return{...this.#Q.schema(),metadata:this.#q}}}class DX extends S0{*pathErrors(Q){if(Q===void 0)yield[[],"value is undefined"]}fuzz(){return k8([()=>null,v6,m4,()=>i1(V2()),()=>Array(V2()).fill(null).map(()=>this.fuzz()),()=>Object.fromEntries(Array(V2()).fill(null).map(()=>[i1(V2(3)),this.fuzz()]))])()}schema(){return{}}}function AX(){return new DX}class OX extends S0{*pathErrors(Q){if(typeof Q!=="boolean")yield[[],`${$2(Q)} is not a boolean`]}fuzz(){return v6()}schema(){return{type:"boolean"}}}function w1(){return new OX}class g8 extends S0{#Q;#q;#$;constructor(Q){super();this.#Q=Q,[this.#q,this.#$]=SZ[Q]}*pathErrors(Q){if(typeof Q!=="number")yield[[],`${$2(Q)} is not a number`];else if(Q%1!==0)yield[[],`${Q.toPrecision()} is not an integer`];else if(Q<this.#q)yield[[],`${Q.toFixed()} is less than ${this.#q.toFixed()}`];else if(Q>=this.#$)yield[[],`${Q.toFixed()} is greater than ${(this.#$-1).toFixed()}`]}fuzz(){return CX(this.#q,this.#$)}schema(){return{type:this.#Q}}}function y8(){return new g8("uint8")}function z2(){return new g8("int32")}function o1(){return new g8("uint32")}class RX extends S0{#Q;constructor(Q){super();this.#Q=Q}*pathErrors(Q){if(typeof Q!=="number")yield[[],`${$2(Q)} is not number, expected a float`]}fuzz(){return m4()}schema(){return{type:this.#Q}}}function O0(){return new RX("float64")}class xX extends S0{*pathErrors(Q){if(typeof Q!=="string")yield[[],`${$2(Q)} is not a string`]}fuzz(){return i1(V2(3))}schema(){return{type:"string"}}}function F0(){return new xX}class TX extends S0{*pathErrors(Q){if(typeof Q!=="string")yield[[],`${$2(Q)} is not a string`];else if(!xZ(Q))yield[[],`${Q} is not a valid timestamp`]}fuzz(){return new Date(Math.random()*3153600000000).toISOString()}schema(){return{type:"timestamp"}}}function vX(){return new TX}class EX extends S0{#Q;#q;constructor(Q,q){super();this.#Q=Q,this.#q=q}*pathErrors(Q){if(typeof Q!=="string")yield[[],`${$2(Q)} is not a string`];else if(!this.#q.has(Q))yield[[],`${Q} is not one of ${this.#Q.join(", ")}`]}fuzz(){return k8(this.#Q)}schema(){return{enum:[...this.#Q]}}}function C2(...Q){let q=new Set(Q);if(q.size!==Q.length)throw Error("enum can't contain duplicates");else return new EX(Q,q)}class SX extends S0{#Q;constructor(Q){super();this.#Q=Q}*pathErrors(Q){if(!Array.isArray(Q))yield[[],`${$2(Q)} is not an array`];else for(let[q,$]of Q.entries())for(let[X,Y]of this.#Q.pathErrors($))X.push(`[${q.toFixed()}]`),yield[X,Y]}fuzz(){return Array(V2()).fill(null).map(()=>this.#Q.fuzz())}schema(){return{elements:this.#Q.schema()}}}function h0(Q){if(Q.definitions)throw Error("definitions can only exist on a root schema");else return new SX(Q)}class kX extends S0{#Q;constructor(Q){super();this.#Q=Q}*pathErrors(Q){if(!S8(Q))yield[[],`${$2(Q)} is not a record`];else for(let[q,$]of Object.entries(Q))for(let[X,Y]of this.#Q.pathErrors($))X.push(l1(q)),yield[X,Y]}fuzz(){return Object.fromEntries(Array(V2()).fill(null).map(()=>[i1(V2(3)),this.#Q.fuzz()]))}schema(){return{values:this.#Q.schema()}}}function S6(Q){if(Q.definitions)throw Error("definitions can only exist on a root schema");else return new kX(Q)}class gX extends S0{#Q;#q;#$;keys;constructor(Q,q,$,X){super();this.#Q=Q,this.#q=q,this.#$=$,this.keys=X}*pathErrors(Q){if(!S8(Q))yield[[],`${$2(Q)} is not a record`];else{if(this.#Q)for(let[q,$]of this.#Q){let X=Q[q];if(X===void 0)yield[[],`required key '${q}' is missing`];else for(let[Y,J]of $.pathErrors(X))Y.push(l1(q)),yield[Y,J]}if(this.#q){for(let[q,$]of this.#q)if(Q[q]!==void 0)for(let[X,Y]of $.pathErrors(Q[q]))X.push(l1(q)),yield[X,Y]}if(!this.#$){for(let q of Object.keys(Q))if(!this.keys.has(q))yield[[l1(q)],`'${q}' is not a valid property and additional properties are not allowed`]}}}fuzz(){let Q=E8(this.#Q??[],([X,Y])=>[X,Y.fuzz()]),q=E8(kZ(this.#q??[],()=>v6()),([X,Y])=>[X,Y.fuzz()]),$=this.#$?E8(gZ(V2()),()=>[i1(V2(3)),k8([()=>null,v6,m4,()=>i1(V2()),()=>[],()=>({})])()]):[];return Object.fromEntries(IX(Q,q,$))}schema(){let Q={};if(this.#Q)Q.properties=Object.fromEntries(this.#Q.map(([q,$])=>[q,$.schema()]));if(this.#q)Q.optionalProperties=Object.fromEntries(this.#q.map(([q,$])=>[q,$.schema()]));if(this.#$)Q.additionalProperties=!0;return Q}}function fZ(Q,q,$){let X=new Set(E8(IX(Q??[],q??[]),([Y])=>Y));if(Q?.some(([,Y])=>Y.definitions))throw Error("definitions can only exist on a root schema");else if(q?.some(([,Y])=>Y.definitions))throw Error("definitions can only exist on a root schema");else if(X.size!==(Q?.length??0)+(q?.length??0))throw Error("properties and optionalProperties keys must be unique");else return new gX(Q,q,$??!1,X)}function C0(Q,q,$){return fZ(Q?Object.entries(Q):void 0,q?Object.entries(q):void 0,$)}class hZ extends S0{#Q;#q;#$;constructor(Q,q,$){super();this.#Q=Q,this.#q=q,this.#$=$}guard(Q){if(!S8(Q))return!1;let{[this.#Q]:q,...$}=Q;if(typeof q!=="string")return!1;return this.#q[q]?.guard($)??!1}*pathErrors(Q){if(!S8(Q))yield[[],`${$2(Q)} is not an object`];else{let{[this.#Q]:q,...$}=Q;if(q===void 0)yield[[],`discriminator key '${this.#Q}' is missing`];else if(typeof q!=="string")yield[[l1(this.#Q)],`${$2(q)} is not a string`];else{let X=this.#q[q];if(X===void 0)yield[[l1(this.#Q)],`'${q}' is not a valid discriminator value (${Object.keys(this.#q).join(", ")})`];else yield*X.pathErrors($)}}}fuzz(){let[Q,q]=k8(this.#$);return{...q.fuzz(),[this.#Q]:Q}}schema(){let Q=Object.fromEntries(this.#$.map(([q,$])=>[q,$.schema()]));return{discriminator:this.#Q,mapping:Q}}}class yX extends S0{#Q;#q;definitions=!0;constructor(Q,q){super();this.#Q=Q,this.#q=q}*pathErrors(Q){yield*this.#q.pathErrors(Q)}fuzz(){return this.#q.fuzz()}schema(){let Q=Object.fromEntries(Object.entries(this.#Q).map(([q,$])=>[q,$.schema()]));return{...this.#q.schema(),definitions:Q}}}class fX extends S0{#Q;#q;constructor(Q,q){super();this.#Q=Q,this.#q=q}*pathErrors(Q){yield*this.#q.pathErrors(Q)}fuzz(){return this.#q.fuzz()}schema(){return{ref:this.#Q}}}class hX{#Q;#q;constructor(Q,q){this.#Q=Q,this.#q=q}def(Q,q){let $=q(this.#q);return new hX({...this.#Q,[Q]:$},{...this.#q,[Q]:new fX(Q,$)})}build(Q){return new yX(this.#Q,Q(this.#q))}}class _Z extends S0{#Q;#q;constructor(Q,q){super();this.#q=Q,this.#Q=q}#$(){let Q=this.#q[this.#Q];if(Q===void 0)throw Error(`ref ${this.#Q} was not in definitions after ref builder was finished`);else return Q}*pathErrors(Q){yield*this.#$().pathErrors(Q)}fuzz(){return this.#$().fuzz()}schema(){return{ref:this.#Q}}}var bZ=new Uint8Array(16);function d4(){return crypto.getRandomValues(bZ)}var k0=[];for(let Q=0;Q<256;++Q)k0.push((Q+256).toString(16).slice(1));function _X(Q,q=0){return(k0[Q[q+0]]+k0[Q[q+1]]+k0[Q[q+2]]+k0[Q[q+3]]+"-"+k0[Q[q+4]]+k0[Q[q+5]]+"-"+k0[Q[q+6]]+k0[Q[q+7]]+"-"+k0[Q[q+8]]+k0[Q[q+9]]+"-"+k0[Q[q+10]]+k0[Q[q+11]]+k0[Q[q+12]]+k0[Q[q+13]]+k0[Q[q+14]]+k0[Q[q+15]]).toLowerCase()}function uZ(Q,q,$){if(!q&&!Q&&crypto.randomUUID)return crypto.randomUUID();return cZ(Q,q,$)}function cZ(Q,q,$){Q=Q||{};let X=Q.random??Q.rng?.()??d4();if(X.length<16)throw Error("Random bytes length must be >= 16");if(X[6]=X[6]&15|64,X[8]=X[8]&63|128,q){if($=$||0,$<0||$+16>q.length)throw RangeError(`UUID byte range ${$}:${$+15} is out of buffer bounds`);for(let Y=0;Y<16;++Y)q[$+Y]=X[Y];return q}return _X(X)}var n1=uZ;class I2 extends Error{field;regex;constructor(Q,q,$){super($);this.field=Q,this.regex=q}}class k6 extends Error{hash;constructor(Q){super(`'${Q}' not found in the root hash`);this.hash=Q}}class l4 extends Map{#Q;#q=0;constructor(Q,q=[]){super();this.#Q=Q;for(let[$,X]of q)this.set($,X)}get(Q){let q=super.get(Q);if(q!==void 0)super.delete(Q),super.set(Q,q);return q}set(Q,q){let $=super.get(Q);if($===void 0)this.#q+=Q.length;else if($!==null)this.#q-=$.length;if(q!==null)this.#q+=q.length;super.delete(Q);let X;while(this.#q>this.#Q&&(X=this.entries().next().value)){let[Y,J]=X;if(super.delete(Y),this.#q-=Y.length,J!==null)this.#q-=J.length}return super.set(Q,q),this}delete(Q){let q=super.get(Q);if(q===void 0)return!1;if(super.delete(Q),q!==null)this.#q-=q.length;return this.#q-=Q.length,!0}clear(){super.clear(),this.#q=0}}var eK=V5(uX(),1);function cX(Q){let q=Q.reduce((Y,J)=>Y+J.length,0),$=new Uint8Array(q),X=0;for(let Y of Q)$.set(Y,X),X+=Y.length;return $}var kC=V5(sK(),1),$5=/^[0-9a-f]{64}$/,QU=C0({name:F0(),timestamp:O0()},void 0,!0),xw=C0({name:F0(),pageId:F0(),timestamp:O0()},void 0,!0),Tw=C0(void 0,{authors:h0(F0()),title:F0(),publicationDate:F0(),publisher:F0()},!0),vw=C0({id:F0(),idx:C0({timestamp:F0(),value:F0()},void 0,!0)},{template:C0({timestamp:F0(),value:F0()},void 0,!0),redir:C0({timestamp:F0(),value:z2()},void 0,!0),scrollTime:C0({timestamp:F0(),value:vX()},void 0,!0),verticalScroll:C0({timestamp:F0(),value:O0()},void 0,!0),deleted:C0({timestamp:F0(),value:z2()},void 0,!0)},!0),Ew=C0({lastOpened:C0({timestamp:F0(),value:F0()},void 0,!0),original:C0({timestamp:F0(),value:z2()},void 0,!0),pages:h0(vw),uuids:E6(h0(C0({first:F0(),second:o1()},void 0,!0)))},void 0,!0),Sw=C0(void 0,{tags:h0(QU)}),kw=C0(void 0,{tags:h0(F0())}),qU={coverPageNumber:z2(),documentMetadata:Tw,extraMetadata:S6(F0()),fileType:C2("epub","notebook","pdf"),fontName:F0(),lineHeight:z2(),orientation:C2("portrait","landscape"),pageCount:o1(),textAlignment:C2("","justify","left"),textScale:O0()},$U={cPages:Ew,customZoomCenterX:O0(),customZoomCenterY:O0(),customZoomOrientation:C2("portrait","landscape"),customZoomPageHeight:O0(),customZoomPageWidth:O0(),customZoomScale:O0(),dummyDocument:w1(),formatVersion:y8(),keyboardMetadata:C0({count:o1(),timestamp:O0()},void 0,!0),lastOpenedPage:z2(),margins:o1(),originalPageCount:z2(),pages:E6(h0(F0())),pageTags:h0(xw),redirectionPageMap:h0(z2()),sizeInBytes:F0(),transform:C0(void 0,{m11:O0(),m12:O0(),m13:O0(),m21:O0(),m22:O0(),m23:O0(),m31:O0(),m32:O0(),m33:O0()},!0),viewBackgroundFilter:C2("off","fullpage"),zoomMode:C2("bestFit","customFit","fitToHeight","fitToWidth")},gw=C0(qU,{...$U,tags:h0(QU)},!0),yw=C0(qU,{...$U,tags:h0(F0())},!0),fw=C0({name:F0(),author:F0(),iconData:F0(),categories:h0(F0()),labels:h0(F0()),orientation:C2("portrait","landscape"),templateVersion:F0(),supportedScreens:h0(C2("rm2","rmPP")),constants:h0(S6(z2())),items:h0(AX())},{formatVersion:y8()}),hw=C0({lastModified:F0(),parent:F0(),pinned:w1(),type:C2("DocumentType","CollectionType","TemplateType"),visibleName:F0()},{lastOpened:F0(),lastOpenedPage:z2(),createdTime:F0(),deleted:w1(),metadatamodified:w1(),modified:w1(),synced:w1(),version:o1()},!0),_w=C0({hash:F0(),generation:O0()},void 0,!0),bw=C0({hash:F0(),generation:O0(),schemaVersion:y8()},void 0,!0),uw=C0({docID:F0(),hash:F0()},void 0,!0);async function dQ(Q){let q=await crypto.subtle.digest("SHA-256",Q);return new Uint8Array(q).toHex()}function tK(Q){let[q,$,X,Y,J]=Q.split(":");if(q===void 0||$===void 0||X===void 0||Y===void 0||J===void 0)throw Error(`line '${Q}' was not formatted correctly`);else if($==="80000000"||$==="0")return{hash:q,type:$==="0"?0:80000000,id:X,subfiles:parseInt(Y,10),size:parseInt(J,10)};else throw Error(`line '${Q}' was not formatted correctly`)}class lQ{#Q;#q;#$;#X;constructor(Q,q,$,X){this.#Q=Q,this.#X=q,this.#q=$,this.#$=X}async getRootHash(){let q=await(await this.#Q("GET",`${this.#q}/sync/v4/root`)).text(),$=JSON.parse(q);if(!bw.guardAssert($))throw Error("invalid root hash");let{hash:X,generation:Y,schemaVersion:J}=$;if(J!==3&&J!==4)throw Error(`schema version ${J} not supported`);else if(!Number.isSafeInteger(Y))throw Error(`generation ${Y} was not a safe integer; please file a bug report`);else return[X,Y,J]}async#Y(Q,q){if(!$5.test(q))throw new I2(q,$5,"hash was not a valid hash");let X=await(await this.#Q("GET",`${this.#q}/sync/v3/files/${q}`,{headers:{"rm-filename":Q}})).arrayBuffer();return new Uint8Array(X)}async getHash(Q,q){let $=this.#X.get(q);if($!=null)return new TextEncoder().encode($);else{let X=await this.#Y(Q,q);if(this.#X.get(q)===void 0)this.#X.set(q,null);return X}}async getText(Q,q){let $=this.#X.get(q);if($!=null)return $;else{let X=await this.#Y(Q,q),J=new TextDecoder().decode(X);return this.#X.set(q,J),J}}async getEntries(Q,q){let $=await this.getText(Q,q),[X,...Y]=$.slice(0,-1).split(`
|
|
13
13
|
`);if(X==="3")return{entries:Y.map(tK)};else if(X==="4"){let[J,...K]=Y;if(!J)throw Error("missing info line for schema version 4");let[U,G,V,z]=J.split(":");if(U!=="0"||G===void 0||V===void 0||z===void 0)throw Error(`schema 4 info line '${J}' was not formatted correctly`);let H=K.map(tK);if(parseInt(V,10)!==H.length)throw Error(`schema 4 expected ${V} entries, but found ${H.length}`);else return{entries:H,id:G,size:parseInt(z,10)}}else throw Error(`schema version ${X} not supported`)}async getContent(Q,q){let $=await this.getText(Q,q),X=JSON.parse($),Y=[];for(let[K,U]of[["collection",Sw],["legacy collection",kw],["template",fw],["document",gw],["legacy document",yw]])try{if(U.guardAssert(X))return X}catch(G){let V=G instanceof Error?G.message:"unknown error type";Y.push(`Couldn't validate as ${K} because:
|
|
14
14
|
${V}`)}let J=Y.join(`
|
|
15
15
|
|
|
16
16
|
or
|
|
17
17
|
|
|
18
|
-
`);throw Error(`invalid content: ${J}`)}async getMetadata(Q,q){let $=await this.getText(Q,q),X=JSON.parse($);if(!hw.guardAssert(X))throw Error("invalid metadata");return X}async putRootHash(Q,q,$=!0){if(!Number.isSafeInteger(q))throw Error(`generation ${q} was not a safe integer`);else if(!$5.test(Q))throw new I2(Q,$5,"rootHash was not a valid hash");let X=JSON.stringify({hash:Q,generation:q,broadcast:$}),J=await(await this.#Q("PUT",`${this.#q}/sync/v3/root`,{body:X})).text(),K=JSON.parse(J);if(!_w.guardAssert(K))throw Error("invalid root hash");let{hash:U,generation:G}=K;if(Number.isSafeInteger(G))return[U,G];else throw Error(`new generation ${G} was not a safe integer; please file a bug report`)}async#J(Q,q,$){if(!this.#X.has(q)){let X=eK.default.buf($,0),Y=new ArrayBuffer(4);new DataView(Y).setInt32(0,X,!1);let J=new Uint8Array(Y).toBase64();if(await this.#Q("PUT",`${this.#q}/sync/v3/files/${q}`,{body:$,headers:{"rm-filename":Q,"x-goog-hash":`crc32c=${J}`}}),this.#X.get(q)===void 0)this.#X.set(q,null)}}async putFile(Q,q){let $=await dQ(q);return[{id:Q,hash:$,type:0,subfiles:0,size:q.length},this.#J(Q,$,q)]}async putText(Q,q){let X=new TextEncoder().encode(q),[Y,J]=await this.putFile(Q,X);return[Y,J.then(()=>{this.#X.set(Y.hash,q)})]}async putContent(Q,q){if(!Q.endsWith(".content"))throw Error(`id ${Q} did not end with '.content'`);else return await this.putText(Q,JSON.stringify(q))}async putMetadata(Q,q){if(!Q.endsWith(".metadata"))throw Error(`id ${Q} did not end with '.metadata'`);else return await this.putText(Q,JSON.stringify(q))}async putEntries(Q,q,$){q.sort((V,z)=>V.id.localeCompare(z.id));let X=q.reduce((V,z)=>V+z.size,0),Y=[`${$}
|
|
18
|
+
`);throw Error(`invalid content: ${J}`)}async getMetadata(Q,q){let $=await this.getText(Q,q),X=JSON.parse($);if(!hw.guardAssert(X))throw Error("invalid metadata");return X}async putRootHash(Q,q,$=!0){if(!Number.isSafeInteger(q))throw Error(`generation ${q} was not a safe integer`);else if(!$5.test(Q))throw new I2(Q,$5,"rootHash was not a valid hash");let X=JSON.stringify({hash:Q,generation:q,broadcast:$}),J=await(await this.#Q("PUT",`${this.#q}/sync/v3/root`,{body:X})).text(),K=JSON.parse(J);if(!_w.guardAssert(K))throw Error("invalid root hash");let{hash:U,generation:G}=K;if(Number.isSafeInteger(G))return[U,G];else throw Error(`new generation ${G} was not a safe integer; please file a bug report`)}async#J(Q,q,$){if(!this.#X.has(q)){let X=eK.default.buf($,0),Y=new ArrayBuffer(4);new DataView(Y).setInt32(0,X,!1);let J=new Uint8Array(Y).toBase64();if(await this.#Q("PUT",`${this.#q}/sync/v3/files/${q}`,{body:$,headers:{"rm-filename":Q,"x-goog-hash":`crc32c=${J}`}}),this.#X.get(q)===void 0)this.#X.set(q,null)}}async putFile(Q,q){let $=await dQ(q);return[{id:Q,hash:$,type:0,subfiles:0,size:q.length},this.#J(Q,$,q)]}async putText(Q,q){let X=new TextEncoder().encode(q),[Y,J]=await this.putFile(Q,X);return[Y,J.then(()=>{this.#X.set(Y.hash,q)})]}async putContent(Q,q){if(!Q.endsWith(".content"))throw Error(`id ${Q} did not end with '.content'`);else return await this.putText(Q,JSON.stringify(q))}async putMetadata(Q,q){if(!Q.endsWith(".metadata"))throw Error(`id ${Q} did not end with '.metadata'`);else return await this.putText(Q,JSON.stringify(q))}async putEntries(Q,q,$){if(Q==="root"&&$===3)console.warn('writing a schema 3 root index, which reMarkable rejects with a 400 "Software must be updated" error; write the root index with schema version 4 instead');q.sort((V,z)=>V.id.localeCompare(z.id));let X=q.reduce((V,z)=>V+z.size,0),Y=[`${$}
|
|
19
19
|
`];if($===4){let V=Q==="root"?".":Q;Y.push(`0:${V}:${q.length}:${X}
|
|
20
|
-
`)}for(let{hash:V,type:z,id:H,subfiles:j,size:Z}of q)Y.push(`${V}:${
|
|
21
|
-
`)
|
|
20
|
+
`)}for(let{hash:V,type:z,id:H,subfiles:j,size:Z}of q){let h=$===4?0:z;Y.push(`${V}:${h}:${H}:${j}:${Z}
|
|
21
|
+
`)}let K=new TextEncoder().encode(Y.join("")),U;if($===3){let V=[];for(let{hash:z}of q)V.push(Uint8Array.fromHex(z));U=await dQ(cX(V))}else if($===4)U=await dQ(K);else throw Error(`unsupported schema version ${$}`);return[{id:Q,hash:U,type:$>3?0:80000000,subfiles:q.length,size:X},this.#J(`${Q}.docSchema`,U,K)]}async uploadFile(Q,q,$){let Y=new TextEncoder().encode(JSON.stringify({file_name:Q})).toBase64(),K=await(await this.#Q("POST",`${this.#$}/doc/v2/files`,{body:q,headers:{"Content-Type":$,"rm-meta":Y,"rm-source":"RoR-Browser"}})).json();if(!uw.guardAssert(K))throw Error("invalid upload response");let{docID:U,hash:G}=K;return{id:U,hash:G}}dumpCache(){return JSON.stringify(Object.fromEntries(this.#X))}clearCache(){this.#X.clear()}}var YU="https://webapp-prod.cloud.remarkable.engineering",cw="https://eu.tectonic.remarkable.com",pw="https://internal.cloud.remarkable.com",t2=/^([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}||trash)$/;class iQ extends Error{constructor(){super("root generation was stale; try put again")}}class oQ extends Error{status;statusText;constructor(Q,q,$){super($);this.status=Q,this.statusText=q}}async function uC(Q,{deviceDesc:q="browser-chrome",uuid:$=n1(),authHost:X=YU}={}){if(Q.length!==8)throw Error(`code should be length 8, but was ${Q.length}`);let Y=await fetch(`${X}/token/json/2/device/new`,{method:"POST",headers:{Authorization:"Bearer"},body:JSON.stringify({code:Q,deviceDesc:q,deviceID:$})});if(!Y.ok)throw new oQ(Y.status,Y.statusText,"couldn't register api");else return await Y.text()}class JU{#Q;#q;raw;#$;constructor(Q,q,$,X){this.#Q=Q,this.#q=X,this.raw=new lQ((Y,J,{body:K,headers:U}={})=>this.#J(J,{method:Y,body:K,headers:U}),X,q,$)}async#X(Q=!1){if(Q||this.#$===void 0)this.#$=await this.raw.getRootHash();return this.#$}async#Y(Q,q){try{let[$,X]=await this.raw.putRootHash(Q,q),[,,Y]=this.#$;this.#$=[$,X,Y]}catch($){if($ instanceof iQ)this.#$=void 0;throw $}}async#J(Q,{body:q,method:$="POST",headers:X={}}){let Y=await fetch(Q,{method:$,headers:{Authorization:`Bearer ${this.#Q}`,...X},body:q});if(!Y.ok){let J=await Y.text();if(J===`{"message":"precondition failed"}
|
|
22
22
|
`)throw new iQ;else throw new oQ(Y.status,Y.statusText,`failed reMarkable request: ${J}`)}else return Y}async#G({hash:Q,id:q}){let{entries:$}=await this.raw.getEntries(`${q}.docSchema`,Q),X=$.find((Z)=>Z.id.endsWith(".metadata")),Y=$.find((Z)=>Z.id.endsWith(".content"));if(X===void 0)throw Error(`couldn't find metadata for hash ${Q}`);let[{visibleName:J,lastModified:K,pinned:U,parent:G,lastOpened:V,new:z,source:H},j]=await Promise.all([this.raw.getMetadata(X.id,X.hash),Y===void 0?Promise.resolve({fileType:void 0,tags:void 0}):this.raw.getContent(Y.id,Y.hash)]);if("templateVersion"in j)return{id:q,hash:Q,visibleName:J,lastModified:K,new:z,pinned:U,source:H,parent:G,type:"TemplateType"};else if(j.fileType===void 0)return{id:q,hash:Q,visibleName:J,lastModified:K,pinned:U,parent:G,tags:j.tags,type:"CollectionType"};else return{id:q,hash:Q,visibleName:J,lastModified:K,pinned:U,parent:G,tags:j.tags,lastOpened:V??"",fileType:j.fileType,type:"DocumentType"}}async listItems(Q=!1){let q=await this.listIds(Q);return await Promise.all(q.map(($)=>this.#G($)))}async listIds(Q=!1){let[q]=await this.#X(Q),{entries:$}=await this.raw.getEntries("root.docSchema",q);return $.map(({id:X,hash:Y})=>({id:X,hash:Y}))}async getContent(Q,q){let{entries:$}=await this.raw.getEntries(`${Q}.docSchema`,q),[X]=$.filter((Y)=>Y.id.endsWith(".content"));if(X===void 0)throw Error(`couldn't find contents for hash ${q}`);else return await this.raw.getContent(X.id,X.hash)}async getMetadata(Q,q){let{entries:$}=await this.raw.getEntries(`${Q}.docSchema`,q),[X]=$.filter((Y)=>Y.id.endsWith(".metadata"));if(X===void 0)throw Error(`couldn't find metadata for hash ${q}`);else return await this.raw.getMetadata(X.id,X.hash)}async getPdf(Q,q){let{entries:$}=await this.raw.getEntries(`${Q}.docSchema`,q),[X]=$.filter((Y)=>Y.id.endsWith(".pdf"));if(X===void 0)throw Error(`couldn't find pdf for hash ${q}`);else return await this.raw.getHash(X.id,X.hash)}async getEpub(Q,q){let{entries:$}=await this.raw.getEntries(`${Q}.docSchema`,q),[X]=$.filter((Y)=>Y.id.endsWith(".epub"));if(X===void 0)throw Error(`couldn't find epub for hash ${q}`);else return await this.raw.getHash(X.id,X.hash)}async getDocument(Q,q){let{entries:$}=await this.raw.getEntries(`${Q}.docSchema`,q),X=new XU.default;for(let Y of $)X.file(Y.id,this.raw.getHash(Y.id,Y.hash));return X.generateAsync({type:"uint8array"})}async#V(Q,q,$,{refresh:X,parent:Y="",pinned:J=!1,zoomMode:K="bestFit",viewBackgroundFilter:U,textScale:G=1,textAlignment:V="justify",fontName:z="",coverPageNumber:H=-1,authors:j,title:Z,publicationDate:h,publisher:g,extraMetadata:C={},lineHeight:N=-1,margins:W=125,orientation:M="portrait",tags:w}){if(Y&&!t2.test(Y))throw new I2(Y,t2,"parent must be a valid document id");let I=n1(),f=new Date,E={parent:Y,pinned:J,lastModified:(+f).toFixed(),createdTime:(+f).toFixed(),type:"DocumentType",visibleName:Q,lastOpened:"0",lastOpenedPage:0},d={coverPageNumber:H,documentMetadata:{authors:j,title:Z,publicationDate:h,publisher:g},extraMetadata:C,lineHeight:N,margins:W,orientation:M,fileType:q,formatVersion:1,tags:w?.map((u)=>({name:u,timestamp:+f}))??[],fontName:z,textAlignment:V,textScale:G,zoomMode:K,viewBackgroundFilter:U,originalPageCount:1,pageCount:1,pageTags:[],pages:[n1()],redirectionPageMap:[0],sizeInBytes:$.length.toFixed()},[[R,x],[D,L],[S,y],[v,a],[Q0,Y0,B0]]=await Promise.all([this.raw.putContent(`${I}.content`,d),this.raw.putMetadata(`${I}.metadata`,E),this.raw.putText(`${I}.pagedata`,`
|
|
23
|
-
`),this.raw.putFile(`${I}.${q}`,$),this.#X(X)]),[[c,U0],{entries:P}]=await Promise.all([this.raw.putEntries(I,[R,D,S,v],B0),this.raw.getEntries("root.docSchema",Q0)]);P.push(c);let[l,$0]=await this.raw.putEntries("root",P,
|
|
23
|
+
`),this.raw.putFile(`${I}.${q}`,$),this.#X(X)]),[[c,U0],{entries:P}]=await Promise.all([this.raw.putEntries(I,[R,D,S,v],B0),this.raw.getEntries("root.docSchema",Q0)]);P.push(c);let[l,$0]=await this.raw.putEntries("root",P,4);return await Promise.all([x,L,y,a,U0,$0]),await this.#Y(l.hash,Y0),{id:I,hash:c.hash}}async putPdf(Q,q,$={}){return await this.#V(Q,"pdf",q,$)}async putEpub(Q,q,$={}){return await this.#V(Q,"epub",q,$)}async putFolder(Q,{parent:q=""}={},$=!1){if(q&&!t2.test(q))throw new I2(q,t2,"parent must be a valid document id");let X=n1(),Y=new Date,J={tags:[]},K={lastModified:(+Y).toFixed(),createdTime:(+Y).toFixed(),parent:q,pinned:!1,type:"CollectionType",visibleName:Q},[[U,G],[V,z],[H,j,Z]]=await Promise.all([this.raw.putContent(`${X}.content`,J),this.raw.putMetadata(`${X}.metadata`,K),this.#X($)]),[[h,g],{entries:C}]=await Promise.all([this.raw.putEntries(X,[U,V],Z),this.raw.getEntries("root.docSchema",H)]);C.push(h);let[N,W]=await this.raw.putEntries("root",C,4);return await Promise.all([G,z,g,W]),await this.#Y(N.hash,j),{id:X,hash:h.hash}}async uploadEpub(Q,q){return await this.raw.uploadFile(Q,q,"application/epub+zip")}async uploadPdf(Q,q){return await this.raw.uploadFile(Q,q,"application/pdf")}async uploadFolder(Q){return await this.raw.uploadFile(Q,new Uint8Array(0),"folder")}async#W(Q,q,$,X){let{entries:Y}=await this.raw.getEntries(`${Q}.docSchema`,q),J=Y.findIndex((Z)=>Z.id.endsWith(".content")),K=Y[J];if(K===void 0)throw Error("internal error: couldn't find content in entry hash");let U=await this.raw.getContent(K.id,K.hash);Object.assign(U,$);let[G,V]=await this.raw.putContent(K.id,U);Y[J]=G;let[z,H]=await this.raw.putEntries(Q,Y,X),j=Promise.all([V,H]);return[z,j]}async#K(Q,q,$,X){let[Y,J,K]=await this.#X(X),{entries:U}=await this.raw.getEntries("root.docSchema",Y),G=U.findIndex((g)=>g.hash===Q),V=U[G];if(V===void 0)throw new k6(Q);let[[z,H],j]=await Promise.all([this.#W(V.id,Q,q,K),this.getMetadata(V.id,Q)]);if(j.type!==$)throw Error(`expected type ${$} but got ${j.type} for hash ${Q}`);U[G]=z;let[Z,h]=await this.raw.putEntries("root",U,4);return await Promise.all([H,h]),await this.#Y(Z.hash,J),{hash:z.hash}}async updateDocument(Q,q,$=!1){return await this.#K(Q,q,"DocumentType",$)}async updateCollection(Q,q,$=!1){return await this.#K(Q,q,"CollectionType",$)}async updateTemplate(Q,q,$=!1){return await this.#K(Q,q,"TemplateType",$)}async#z(Q,q,$,X){let{entries:Y}=await this.raw.getEntries(`${Q}.docSchema`,q),J=Y.findIndex((Z)=>Z.id.endsWith(".metadata")),K=Y[J];if(K===void 0)throw Error("internal error: couldn't find metadata in entry hash");let U=await this.raw.getMetadata(K.id,K.hash);Object.assign(U,$);let[G,V]=await this.raw.putMetadata(K.id,U);Y[J]=G;let[z,H]=await this.raw.putEntries(Q,Y,X),j=Promise.all([V,H]);return[z,j]}async#U(Q,q,$=!1){let[X,Y,J]=await this.#X($),{entries:K}=await this.raw.getEntries("root.docSchema",X),U=K.findIndex((Z)=>Z.hash===Q),G=K[U];if(G===void 0)throw new k6(Q);let[V,z]=await this.#z(G.id,Q,q,J);K[U]=V;let[H,j]=await this.raw.putEntries("root",K,4);return await Promise.all([z,j]),await this.#Y(H.hash,Y),{hash:V.hash}}async move(Q,q,$=!1){if(!t2.test(q))throw new I2(q,t2,"parent must be a valid document id");return await this.#U(Q,{parent:q},$)}async delete(Q,q=!1){return await this.move(Q,"trash",q)}async rename(Q,q,$=!1){return await this.#U(Q,{visibleName:q},$)}async stared(Q,q,$=!1){return await this.#U(Q,{pinned:q},$)}async bulkMove(Q,q,$=!1){if(!t2.test(q))throw new I2(q,t2,"parent must be a valid document id");let[X,Y,J]=await this.#X($),{entries:K}=await this.raw.getEntries("root.docSchema",X),U=new Set(Q),G=[],V=[];for(let g of K)(U.has(g.hash)?G:V).push(g);let z=await Promise.all(G.map(({id:g,hash:C})=>this.#z(g,C,{parent:q},J))),H=[],j={};for(let[g,[C,N]]of z.entries())V.push(C),H.push(N),j[G[g].hash]=C.hash;let[Z,h]=await this.raw.putEntries("root",V,4);return await Promise.all([Promise.all(H),h]),await this.#Y(Z.hash,Y),{hashes:j}}async bulkDelete(Q,q=!1){return await this.bulkMove(Q,"trash",q)}dumpCache(){return this.raw.dumpCache()}async pruneCache(Q){let[q]=await this.#X(Q),$=new Set(this.#q.keys()),Y=[(await this.raw.getEntries("root.docSchema",q)).entries],J=[];while(Y.length){for(let U of Y)for(let{hash:G,type:V,id:z}of U)if($.add(G),V===80000000)J.push(this.raw.getEntries(`${z}.docSchema`,G));Y=(await Promise.all(J)).map((U)=>U.entries),J=[]}for(let K of $)this.#q.delete(K)}clearCache(){this.raw.clearCache()}}var mw=S6(E6(F0()));async function dw(Q,{authHost:q=YU}={}){let $=await fetch(`${q}/token/json/2/user/new`,{method:"POST",headers:{Authorization:`Bearer ${Q}`}});if(!$.ok)throw Error(`couldn't fetch auth token: ${$.statusText}`);return await $.text()}function lw(Q,{rawHost:q=cw,uploadHost:$=pw,cache:X,maxCacheSize:Y=1/0}={}){let J=JSON.parse(X??"{}");if(mw.guard(J)){let K=Object.entries(J),U=Y===1/0?new Map(K):new l4(Y,K);return new JU(Q,q,$,U)}throw Error("cache was not a valid cache (json string mapping); your cache must be corrupted somehow. Either initialize remarkable without a cache, or fix its format.")}async function cC(Q,q={}){let{authHost:$,rawHost:X,uploadHost:Y,cache:J,maxCacheSize:K,syncHost:U}=q??{},G=await dw(Q,{authHost:$});return lw(G,{rawHost:X,uploadHost:Y,cache:J,maxCacheSize:K,syncHost:U})}export{lw as session,cC as remarkable,uC as register,dw as auth,I2 as ValidationError,oQ as ResponseError,k6 as HashNotFoundError,iQ as GenerationError};
|