@cloudpdf/engine 3.0.0-next.12 → 3.0.0-next.14
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.cjs +244 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +19 -1
- package/dist/index.d.ts +19 -1
- package/dist/index.js +245 -3
- package/dist/index.js.map +1 -1
- package/package.json +5 -4
package/dist/index.cjs
CHANGED
|
@@ -435,6 +435,24 @@ var CloudDocumentFormsService = class {
|
|
|
435
435
|
return this.absorbMutation(result, "form.fieldUpdated");
|
|
436
436
|
});
|
|
437
437
|
}
|
|
438
|
+
setSignatureAppearance(ref, appearance) {
|
|
439
|
+
const rejected = this.rejectIfClosed();
|
|
440
|
+
if (rejected) return rejected;
|
|
441
|
+
return _embedpdf_engine_core_runtime.AbortablePromise.run(async (signal) => {
|
|
442
|
+
const bytes = new ArrayBuffer(appearance.pdf.byteLength);
|
|
443
|
+
new Uint8Array(bytes).set(appearance.pdf);
|
|
444
|
+
const form = buildMutationForm({
|
|
445
|
+
resource: "r0",
|
|
446
|
+
pageIndex: appearance.pageIndex ?? 0
|
|
447
|
+
}, { r0: {
|
|
448
|
+
bytes,
|
|
449
|
+
mimeType: "application/pdf",
|
|
450
|
+
name: "appearance.pdf"
|
|
451
|
+
} });
|
|
452
|
+
const result = await this.http.postMultipartJson(_embedpdf_engine_core_wire.wirePaths.layerFormFieldSignatureAppearance(this.docId, this.layerName, (0, _embedpdf_engine_core_runtime.encodeFieldRefKey)(ref)), form, (raw) => _embedpdf_engine_core_wire.FormFieldUpdateResultSchema.parse(raw), signal);
|
|
453
|
+
return this.absorbMutation(result, "form.fieldUpdated");
|
|
454
|
+
});
|
|
455
|
+
}
|
|
438
456
|
deleteField(ref) {
|
|
439
457
|
const rejected = this.rejectIfClosed();
|
|
440
458
|
if (rejected) return rejected;
|
|
@@ -776,7 +794,8 @@ function queryIdentity(query) {
|
|
|
776
794
|
query.text,
|
|
777
795
|
query.matchCase ? 1 : 0,
|
|
778
796
|
query.matchDiacritics ? 1 : 0,
|
|
779
|
-
query.wholeWord ? 1 : 0
|
|
797
|
+
query.wholeWord ? 1 : 0,
|
|
798
|
+
query.ignoreWhitespace ? 1 : 0
|
|
780
799
|
]);
|
|
781
800
|
}
|
|
782
801
|
//#endregion
|
|
@@ -1015,6 +1034,176 @@ function identityFromClaims(claims) {
|
|
|
1015
1034
|
return Object.keys(out).length > 0 ? out : null;
|
|
1016
1035
|
}
|
|
1017
1036
|
//#endregion
|
|
1037
|
+
//#region src/document/CloudDocumentSignaturesService.ts
|
|
1038
|
+
/**
|
|
1039
|
+
* Cloud-side digital signatures. Two kinds of read, two kinds of URL:
|
|
1040
|
+
*
|
|
1041
|
+
* - The LAYER view (`list`, and `analyze` of the working copy) is pinned
|
|
1042
|
+
* by the manifest's `docVersion`, like every other layer read: a
|
|
1043
|
+
* signature is a layer state change, the immutable URL moves with it.
|
|
1044
|
+
* - Signed BYTES (`contents`, `digest`, `revisionBytes`, and `analyze`
|
|
1045
|
+
* of history) belong to a base VERSION and are content-addressed by
|
|
1046
|
+
* the manifest's `baseSha`: immutable forever, shared by every layer
|
|
1047
|
+
* and every caller.
|
|
1048
|
+
*
|
|
1049
|
+
* Signing is the server's two-phase protocol over the same wire shapes
|
|
1050
|
+
* the local engine uses. `prepare` and `complete` change the manifest in
|
|
1051
|
+
* ways no delta carries (a publish moves `baseSha` itself), so both
|
|
1052
|
+
* refresh it before returning.
|
|
1053
|
+
*/
|
|
1054
|
+
var CloudDocumentSignaturesService = class {
|
|
1055
|
+
constructor(http, docId, layerName, isClosed, manifest, publisher) {
|
|
1056
|
+
this.http = http;
|
|
1057
|
+
this.docId = docId;
|
|
1058
|
+
this.layerName = layerName;
|
|
1059
|
+
this.isClosed = isClosed;
|
|
1060
|
+
this.manifest = manifest;
|
|
1061
|
+
this.publisher = publisher;
|
|
1062
|
+
}
|
|
1063
|
+
list() {
|
|
1064
|
+
const rejected = this.closedRejection();
|
|
1065
|
+
if (rejected) return rejected;
|
|
1066
|
+
return _embedpdf_engine_core_runtime.AbortablePromise.run(async (signal) => this.http.getJsonWithRefresh(async (s) => {
|
|
1067
|
+
const manifest = await this.manifest.get(s);
|
|
1068
|
+
return _embedpdf_engine_core_wire.wirePaths.layerSignatures(this.docId, this.layerName, manifest.docVersion);
|
|
1069
|
+
}, (raw) => _embedpdf_engine_core_wire.SignatureSnapshotSchema.parse(raw), async (s) => {
|
|
1070
|
+
await this.manifest.refresh(s);
|
|
1071
|
+
}, signal));
|
|
1072
|
+
}
|
|
1073
|
+
contents(field) {
|
|
1074
|
+
const rejected = this.closedRejection();
|
|
1075
|
+
if (rejected) return rejected;
|
|
1076
|
+
return _embedpdf_engine_core_runtime.AbortablePromise.run(async (signal) => {
|
|
1077
|
+
const manifest = await this.manifest.get(signal);
|
|
1078
|
+
const name = await this.fieldName(field, signal);
|
|
1079
|
+
return this.http.getBytes(_embedpdf_engine_core_wire.wirePaths.docVersionSignatureContents(this.docId, manifest.baseSha, name), signal);
|
|
1080
|
+
});
|
|
1081
|
+
}
|
|
1082
|
+
digest(field, algorithm) {
|
|
1083
|
+
const rejected = this.closedRejection();
|
|
1084
|
+
if (rejected) return rejected;
|
|
1085
|
+
return _embedpdf_engine_core_runtime.AbortablePromise.run(async (signal) => {
|
|
1086
|
+
const manifest = await this.manifest.get(signal);
|
|
1087
|
+
const name = await this.fieldName(field, signal);
|
|
1088
|
+
return this.http.getBytes(_embedpdf_engine_core_wire.wirePaths.docVersionSignatureDigest(this.docId, manifest.baseSha, name, algorithm), signal);
|
|
1089
|
+
});
|
|
1090
|
+
}
|
|
1091
|
+
revisionBytes(revisionIndex) {
|
|
1092
|
+
const rejected = this.closedRejection();
|
|
1093
|
+
if (rejected) return rejected;
|
|
1094
|
+
return _embedpdf_engine_core_runtime.AbortablePromise.run(async (signal) => {
|
|
1095
|
+
const manifest = await this.manifest.get(signal);
|
|
1096
|
+
return this.http.getBytes(_embedpdf_engine_core_wire.wirePaths.docVersionRevision(this.docId, manifest.baseSha, revisionIndex), signal);
|
|
1097
|
+
});
|
|
1098
|
+
}
|
|
1099
|
+
/**
|
|
1100
|
+
* `until: 'working-copy'` (or unset while the layer holds edits) judges
|
|
1101
|
+
* the layer's pending edits against the base at the layer URL; anything
|
|
1102
|
+
* else is history of the base version and resolves at the version URL.
|
|
1103
|
+
*/
|
|
1104
|
+
analyze(input) {
|
|
1105
|
+
const rejected = this.closedRejection();
|
|
1106
|
+
if (rejected) return rejected;
|
|
1107
|
+
return _embedpdf_engine_core_runtime.AbortablePromise.run(async (signal) => {
|
|
1108
|
+
const manifest = await this.manifest.get(signal);
|
|
1109
|
+
if (input.until === "working-copy" || input.until === void 0 && manifest.working) return this.http.getJsonWithRefresh(async (s) => {
|
|
1110
|
+
const current = await this.manifest.get(s);
|
|
1111
|
+
return _embedpdf_engine_core_wire.wirePaths.layerSignaturesAnalysis(this.docId, this.layerName, {
|
|
1112
|
+
docVersion: current.docVersion,
|
|
1113
|
+
since: input.since,
|
|
1114
|
+
...input.exploratoryLevel !== void 0 ? { exploratoryLevel: input.exploratoryLevel } : {},
|
|
1115
|
+
...input.detail !== void 0 ? { detail: input.detail } : {}
|
|
1116
|
+
});
|
|
1117
|
+
}, (raw) => _embedpdf_engine_core_wire.ChangeAnalysisSchema.parse(raw), async (s) => {
|
|
1118
|
+
await this.manifest.refresh(s);
|
|
1119
|
+
}, signal);
|
|
1120
|
+
return this.http.getJson(_embedpdf_engine_core_wire.wirePaths.docVersionAnalysis(this.docId, manifest.baseSha, {
|
|
1121
|
+
since: input.since,
|
|
1122
|
+
...typeof input.until === "object" ? { until: input.until.revisionIndex } : {},
|
|
1123
|
+
...input.exploratoryLevel !== void 0 ? { exploratoryLevel: input.exploratoryLevel } : {},
|
|
1124
|
+
...input.detail !== void 0 ? { detail: input.detail } : {}
|
|
1125
|
+
}), (raw) => _embedpdf_engine_core_wire.ChangeAnalysisSchema.parse(raw), signal);
|
|
1126
|
+
});
|
|
1127
|
+
}
|
|
1128
|
+
prepare(input) {
|
|
1129
|
+
const rejected = this.closedRejection();
|
|
1130
|
+
if (rejected) return rejected;
|
|
1131
|
+
return _embedpdf_engine_core_runtime.AbortablePromise.run(async (signal) => {
|
|
1132
|
+
const { appearance, ...rest } = input;
|
|
1133
|
+
const form = buildMutationForm({
|
|
1134
|
+
...rest,
|
|
1135
|
+
...appearance ? { appearance: {
|
|
1136
|
+
resource: "appearance",
|
|
1137
|
+
...appearance.pageIndex !== void 0 ? { pageIndex: appearance.pageIndex } : {}
|
|
1138
|
+
} } : {}
|
|
1139
|
+
}, appearance ? { appearance: {
|
|
1140
|
+
bytes: appearance.pdf.slice().buffer,
|
|
1141
|
+
mimeType: "application/pdf",
|
|
1142
|
+
name: "appearance.pdf"
|
|
1143
|
+
} } : {});
|
|
1144
|
+
const prepared = await this.http.postMultipartJson(_embedpdf_engine_core_wire.wirePaths.layerSignaturesPrepare(this.docId, this.layerName), form, (raw) => (0, _embedpdf_engine_core_wire.decodePrepared)(_embedpdf_engine_core_wire.SignaturePreparedWireSchema.parse(raw)), signal);
|
|
1145
|
+
await this.manifest.refresh(signal);
|
|
1146
|
+
this.publisher.publishLocal({
|
|
1147
|
+
type: "signature.prepared",
|
|
1148
|
+
signingId: prepared.signingId,
|
|
1149
|
+
field: input.field
|
|
1150
|
+
});
|
|
1151
|
+
return prepared;
|
|
1152
|
+
});
|
|
1153
|
+
}
|
|
1154
|
+
complete(input) {
|
|
1155
|
+
const rejected = this.closedRejection();
|
|
1156
|
+
if (rejected) return rejected;
|
|
1157
|
+
return _embedpdf_engine_core_runtime.AbortablePromise.run(async (signal) => {
|
|
1158
|
+
const result = await this.http.postJson(_embedpdf_engine_core_wire.wirePaths.layerSignatureComplete(this.docId, this.layerName, input.signingId), {
|
|
1159
|
+
cms: (0, _embedpdf_engine_core_wire.toBase64)(input.cms),
|
|
1160
|
+
expectedVersion: input.expectedVersion
|
|
1161
|
+
}, (raw) => _embedpdf_engine_core_wire.SignatureCompleteResultSchema.parse(raw), signal);
|
|
1162
|
+
await this.manifest.refresh(signal);
|
|
1163
|
+
if (result.status === "completed") {
|
|
1164
|
+
this.publisher.publishLocal({
|
|
1165
|
+
type: "signature.completed",
|
|
1166
|
+
signingId: input.signingId,
|
|
1167
|
+
...result
|
|
1168
|
+
});
|
|
1169
|
+
this.publisher.publishLocal({
|
|
1170
|
+
type: "document.versioned",
|
|
1171
|
+
version: result.version
|
|
1172
|
+
});
|
|
1173
|
+
}
|
|
1174
|
+
return result;
|
|
1175
|
+
});
|
|
1176
|
+
}
|
|
1177
|
+
abort(signingId) {
|
|
1178
|
+
const rejected = this.closedRejection();
|
|
1179
|
+
if (rejected) return rejected;
|
|
1180
|
+
return _embedpdf_engine_core_runtime.AbortablePromise.run(async (signal) => {
|
|
1181
|
+
const result = await this.http.deleteJson(_embedpdf_engine_core_wire.wirePaths.layerSignatureAbort(this.docId, this.layerName, signingId), (raw) => _embedpdf_engine_core_wire.SignatureAbortResultSchema.parse(raw), signal);
|
|
1182
|
+
if (result.status === "aborted") this.publisher.publishLocal({
|
|
1183
|
+
type: "signature.aborted",
|
|
1184
|
+
signingId
|
|
1185
|
+
});
|
|
1186
|
+
return result;
|
|
1187
|
+
});
|
|
1188
|
+
}
|
|
1189
|
+
/** Version routes address a field by its fully qualified name; an object-number ref is resolved through the snapshot. */
|
|
1190
|
+
async fieldName(field, signal) {
|
|
1191
|
+
if (field.kind === "fqn") return field.name;
|
|
1192
|
+
const match = (await this.http.getJsonWithRefresh(async (s) => {
|
|
1193
|
+
const manifest = await this.manifest.get(s);
|
|
1194
|
+
return _embedpdf_engine_core_wire.wirePaths.layerSignatures(this.docId, this.layerName, manifest.docVersion);
|
|
1195
|
+
}, (raw) => _embedpdf_engine_core_wire.SignatureSnapshotSchema.parse(raw), async (s) => {
|
|
1196
|
+
await this.manifest.refresh(s);
|
|
1197
|
+
}, signal)).signatures.find((s) => s.field.kind === "objectNumber" && s.field.fieldObjectNumber === field.fieldObjectNumber);
|
|
1198
|
+
if (!match) throw new _embedpdf_engine_core_runtime.EngineError(_embedpdf_engine_core_runtime.EngineErrorCode.NotFound, `no signature field #${field.fieldObjectNumber}`);
|
|
1199
|
+
return match.fieldName;
|
|
1200
|
+
}
|
|
1201
|
+
closedRejection() {
|
|
1202
|
+
if (!this.isClosed()) return null;
|
|
1203
|
+
return _embedpdf_engine_core_runtime.AbortablePromise.rejectReason(new _embedpdf_engine_core_runtime.EngineError(_embedpdf_engine_core_runtime.EngineErrorCode.DocNotOpen, `document ${this.docId} is closed`));
|
|
1204
|
+
}
|
|
1205
|
+
};
|
|
1206
|
+
//#endregion
|
|
1018
1207
|
//#region src/document/CloudMetadataService.ts
|
|
1019
1208
|
var CloudMetadataService = class {
|
|
1020
1209
|
constructor(http, docId, layerName, isClosed, manifest, publisher) {
|
|
@@ -1427,6 +1616,41 @@ var CloudPageTextService = class {
|
|
|
1427
1616
|
}
|
|
1428
1617
|
};
|
|
1429
1618
|
//#endregion
|
|
1619
|
+
//#region src/document/CloudPageMeasureService.ts
|
|
1620
|
+
var CloudPageMeasureService = class {
|
|
1621
|
+
constructor(http, docId, layerName, pon, isClosed, manifest, publisher) {
|
|
1622
|
+
this.http = http;
|
|
1623
|
+
this.docId = docId;
|
|
1624
|
+
this.layerName = layerName;
|
|
1625
|
+
this.pon = pon;
|
|
1626
|
+
this.isClosed = isClosed;
|
|
1627
|
+
this.manifest = manifest;
|
|
1628
|
+
this.publisher = publisher;
|
|
1629
|
+
}
|
|
1630
|
+
viewports() {
|
|
1631
|
+
return _embedpdf_engine_core_runtime.AbortablePromise.run(async (signal) => {
|
|
1632
|
+
this.check();
|
|
1633
|
+
return this.http.getJson(_embedpdf_engine_core_wire.wirePaths.layerPageViewports(this.docId, this.layerName, this.pon), (raw) => _embedpdf_engine_core_wire.PageMeasurementViewportSchema.array().parse(raw), signal);
|
|
1634
|
+
});
|
|
1635
|
+
}
|
|
1636
|
+
setScale(measure) {
|
|
1637
|
+
return _embedpdf_engine_core_runtime.AbortablePromise.run(async (signal) => {
|
|
1638
|
+
await Promise.resolve();
|
|
1639
|
+
signal.throwIfAborted();
|
|
1640
|
+
this.check();
|
|
1641
|
+
const result = await this.http.putJson(_embedpdf_engine_core_wire.wirePaths.layerPageScale(this.docId, this.layerName, this.pon), { measure }, (raw) => _embedpdf_engine_core_wire.PageScaleResultSchema.parse(raw), signal);
|
|
1642
|
+
this.manifest.apply(result.meta, []);
|
|
1643
|
+
this.publisher.publishLocal({
|
|
1644
|
+
type: "page.viewportsChanged",
|
|
1645
|
+
...result
|
|
1646
|
+
});
|
|
1647
|
+
});
|
|
1648
|
+
}
|
|
1649
|
+
check() {
|
|
1650
|
+
if (this.isClosed()) throw new _embedpdf_engine_core_runtime.EngineError(_embedpdf_engine_core_runtime.EngineErrorCode.DocNotOpen, `Document not open: ${this.docId}`);
|
|
1651
|
+
}
|
|
1652
|
+
};
|
|
1653
|
+
//#endregion
|
|
1430
1654
|
//#region src/document/CloudPageHandle.ts
|
|
1431
1655
|
var CloudPageHandle = class {
|
|
1432
1656
|
constructor(pageObjectNumber, pageIndex, http, docId, layerName, isClosed, manifest, publisher) {
|
|
@@ -1436,6 +1660,8 @@ var CloudPageHandle = class {
|
|
|
1436
1660
|
_defineProperty(this, "text", void 0);
|
|
1437
1661
|
_defineProperty(this, "geometry", void 0);
|
|
1438
1662
|
_defineProperty(this, "render", void 0);
|
|
1663
|
+
_defineProperty(this, "measure", void 0);
|
|
1664
|
+
this.measure = new CloudPageMeasureService(http, docId, layerName, pageObjectNumber, isClosed, manifest, publisher);
|
|
1439
1665
|
this.annotations = new CloudPageAnnotationsService(http, docId, layerName, pageObjectNumber, isClosed, manifest, publisher);
|
|
1440
1666
|
this.text = new CloudPageTextService(http, docId, layerName, pageObjectNumber, isClosed, manifest);
|
|
1441
1667
|
this.geometry = new CloudPageGeometryService(http, docId, layerName, pageObjectNumber, isClosed, manifest);
|
|
@@ -1468,6 +1694,11 @@ function auditRowToEvent(row, mySessionId) {
|
|
|
1468
1694
|
serverId: row.id
|
|
1469
1695
|
};
|
|
1470
1696
|
switch (row.kind) {
|
|
1697
|
+
case "measure.setScale": return {
|
|
1698
|
+
type: "page.viewportsChanged",
|
|
1699
|
+
origin,
|
|
1700
|
+
...row.payload
|
|
1701
|
+
};
|
|
1471
1702
|
case "annot.create": return {
|
|
1472
1703
|
type: "annotation.created",
|
|
1473
1704
|
pageObjectNumber: row.pageObjectNumber ?? row.affectedPages[0] ?? 0,
|
|
@@ -1562,7 +1793,8 @@ function auditRowToEvent(row, mySessionId) {
|
|
|
1562
1793
|
origin,
|
|
1563
1794
|
...row.payload
|
|
1564
1795
|
};
|
|
1565
|
-
case "form.updateField":
|
|
1796
|
+
case "form.updateField":
|
|
1797
|
+
case "form.setSignatureAppearance": return {
|
|
1566
1798
|
type: "form.fieldUpdated",
|
|
1567
1799
|
origin,
|
|
1568
1800
|
...row.payload
|
|
@@ -1702,6 +1934,7 @@ var CloudDocumentHandle = class {
|
|
|
1702
1934
|
_defineProperty(this, "annotations", void 0);
|
|
1703
1935
|
_defineProperty(this, "actions", void 0);
|
|
1704
1936
|
_defineProperty(this, "attachments", void 0);
|
|
1937
|
+
_defineProperty(this, "signatures", void 0);
|
|
1705
1938
|
_defineProperty(this, "forms", void 0);
|
|
1706
1939
|
_defineProperty(this, "search", void 0);
|
|
1707
1940
|
_defineProperty(this, "pages", void 0);
|
|
@@ -1771,6 +2004,7 @@ var CloudDocumentHandle = class {
|
|
|
1771
2004
|
this.annotations = new CloudDocumentAnnotationsService(http, id, layerName, () => this.closed, this.manifestAccessor);
|
|
1772
2005
|
this.actions = new CloudDocumentActionsService(http, id, layerName, () => this.closed, this.manifestAccessor);
|
|
1773
2006
|
this.attachments = new CloudDocumentAttachmentsService(http, id, layerName, () => this.closed, this.manifestAccessor, this.publisher);
|
|
2007
|
+
this.signatures = new CloudDocumentSignaturesService(http, id, layerName, () => this.closed, this.manifestAccessor, this.publisher);
|
|
1774
2008
|
this.forms = new CloudDocumentFormsService(http, id, layerName, () => this.closed, this.manifestAccessor, this.publisher);
|
|
1775
2009
|
this.search = new CloudDocumentSearchService(http, id, layerName, () => this.closed, this.manifestAccessor);
|
|
1776
2010
|
this.pages = new CloudDocumentPagesService(http, id, layerName, () => this.closed, this.manifestAccessor, this.publisher);
|
|
@@ -1873,6 +2107,8 @@ var CloudDocumentHandle = class {
|
|
|
1873
2107
|
...this.manifestCache,
|
|
1874
2108
|
docVersion: delta?.docVersion ?? this.manifestCache.docVersion,
|
|
1875
2109
|
...delta?.annotationsVersion !== void 0 ? { annotationsVersion: delta.annotationsVersion } : {},
|
|
2110
|
+
...delta?.layerVersion !== void 0 ? { layerVersion: delta.layerVersion } : {},
|
|
2111
|
+
...delta?.working !== void 0 ? { working: delta.working } : {},
|
|
1876
2112
|
pages: Array.from(byPageObjectNumber.values()).sort((a, b) => a.state.pageObjectNumber - b.state.pageObjectNumber)
|
|
1877
2113
|
};
|
|
1878
2114
|
}
|
|
@@ -2082,6 +2318,9 @@ var CloudDocumentHandle = class {
|
|
|
2082
2318
|
* whose hand caused the change. */
|
|
2083
2319
|
absorbRemoteEvent(event) {
|
|
2084
2320
|
switch (event.type) {
|
|
2321
|
+
case "page.viewportsChanged":
|
|
2322
|
+
this.absorbMutation(event.meta, []);
|
|
2323
|
+
return;
|
|
2085
2324
|
case "annotation.created":
|
|
2086
2325
|
case "annotation.updated":
|
|
2087
2326
|
case "annotation.deleted":
|
|
@@ -2498,6 +2737,9 @@ var HttpClient = class HttpClient {
|
|
|
2498
2737
|
const res = await this.requestJson(path, "POST", body, signal);
|
|
2499
2738
|
return await this.parseJsonResponse(res, parser);
|
|
2500
2739
|
}
|
|
2740
|
+
async putJson(path, body, parser, signal) {
|
|
2741
|
+
return this.parseJsonResponse(await this.requestJson(path, "PUT", body, signal), parser);
|
|
2742
|
+
}
|
|
2501
2743
|
/** POST a JSON body and return the raw binary response (pages.extract). */
|
|
2502
2744
|
async postJsonBytes(path, body, signal) {
|
|
2503
2745
|
const res = await this.requestJson(path, "POST", body, signal);
|