@haddowg/json-api-client 1.3.0 → 1.4.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/README.md +6 -0
- package/dist/ajv.d.cts +1 -1
- package/dist/ajv.d.mts +1 -1
- package/dist/index.cjs +199 -28
- package/dist/index.d.cts +2 -2
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +199 -29
- package/dist/index.mjs.map +1 -1
- package/dist/{validate-CJPivkqT.d.cts → validate-CQv5lmqO.d.cts} +218 -21
- package/dist/validate-CQv5lmqO.d.cts.map +1 -0
- package/dist/{validate-CJPivkqT.d.mts → validate-CQv5lmqO.d.mts} +218 -21
- package/dist/validate-CQv5lmqO.d.mts.map +1 -0
- package/package.json +1 -1
- package/dist/validate-CJPivkqT.d.cts.map +0 -1
- package/dist/validate-CJPivkqT.d.mts.map +0 -1
package/dist/index.mjs
CHANGED
|
@@ -539,18 +539,37 @@ const ATOMIC_MEDIA_TYPE = mediaType({ ext: [ATOMIC_EXT] });
|
|
|
539
539
|
//#region src/request.ts
|
|
540
540
|
const isAbsolute = (path) => /^https?:\/\//i.test(path);
|
|
541
541
|
const RELATIVE_ORIGIN = "http://relative.invalid";
|
|
542
|
-
/**
|
|
542
|
+
/**
|
|
543
|
+
* Resolve a server link against `baseUrl` per RFC 3986 and check where it lands. A link on the
|
|
544
|
+
* base's origin is followed; a relative base (e.g. `/api`) takes the page's origin in a browser and
|
|
545
|
+
* otherwise only accepts a link that keeps the host. Anything that isn't plain http(s) is refused.
|
|
546
|
+
*/
|
|
543
547
|
function resolveLink(link, baseUrl) {
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
+
let normalised = link.replace(/[\t\n\r]/g, "");
|
|
549
|
+
let start = 0;
|
|
550
|
+
while (start < normalised.length && normalised.charCodeAt(start) <= 32) start++;
|
|
551
|
+
normalised = normalised.slice(start);
|
|
552
|
+
const scheme = /^([a-z][a-z0-9+.-]*):/i.exec(normalised)?.[1]?.toLowerCase();
|
|
553
|
+
if (scheme !== void 0 && scheme !== "http" && scheme !== "https") throw new Error(`Refusing to follow link "${link}": only http(s) links are followed`);
|
|
554
|
+
const relativeBase = !isAbsolute(baseUrl);
|
|
555
|
+
const page = globalThis.location?.href;
|
|
556
|
+
const base = new URL(baseUrl, relativeBase ? typeof page === "string" ? page : RELATIVE_ORIGIN : void 0);
|
|
557
|
+
const resolved = new URL(link, base);
|
|
558
|
+
const sameOrigin = resolved.origin === base.origin && (scheme === void 0 || /^https?:\/\//i.test(normalised));
|
|
559
|
+
if (!sameOrigin) return {
|
|
560
|
+
url: resolved.href,
|
|
561
|
+
sameOrigin
|
|
562
|
+
};
|
|
563
|
+
return {
|
|
564
|
+
url: relativeBase ? resolved.pathname + resolved.search + resolved.hash : resolved.href,
|
|
565
|
+
sameOrigin
|
|
566
|
+
};
|
|
548
567
|
}
|
|
549
568
|
const append = (parts, key, value) => {
|
|
550
569
|
if (value === void 0 || value === null || value === "") return;
|
|
551
570
|
parts.push(`${key}=${encodeURIComponent(String(value))}`);
|
|
552
571
|
};
|
|
553
|
-
const isPlainObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
572
|
+
const isPlainObject$1 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
554
573
|
/**
|
|
555
574
|
* Append a filter value under its (already-bracketed) key. A plain object is a STRUCTURED filter
|
|
556
575
|
* value — a `Range`/`DateRange` deepObject (`{ min, max }`) — and recurses into nested bracketed
|
|
@@ -559,7 +578,7 @@ const isPlainObject = (value) => typeof value === "object" && value !== null &&
|
|
|
559
578
|
* wire as `filter[k]=[object Object]` and be silently ignored by the server (D23).
|
|
560
579
|
*/
|
|
561
580
|
const appendFilterValue = (parts, key, value) => {
|
|
562
|
-
if (isPlainObject(value)) {
|
|
581
|
+
if (isPlainObject$1(value)) {
|
|
563
582
|
for (const [subKey, subValue] of Object.entries(value)) appendFilterValue(parts, `${key}[${subKey}]`, subValue);
|
|
564
583
|
return;
|
|
565
584
|
}
|
|
@@ -582,14 +601,37 @@ function serializeQuery(query) {
|
|
|
582
601
|
return parts.join("&");
|
|
583
602
|
}
|
|
584
603
|
/**
|
|
585
|
-
* Execute a request: build the URL (a server link resolved against `baseUrl
|
|
586
|
-
* verbatim, else `baseUrl + path`), apply content negotiation and any async per-request headers,
|
|
604
|
+
* Execute a request: build the URL (a server link resolved against `baseUrl` and held to its
|
|
605
|
+
* origin, an absolute path verbatim, else `baseUrl + path`), apply content negotiation and any async per-request headers,
|
|
587
606
|
* then drive the transport. A 2xx with a body parses to a {@link Document}; an empty /
|
|
588
607
|
* 204 body resolves to `undefined`. A non-2xx throws a {@link JsonApiError} carrying the
|
|
589
608
|
* parsed error objects (tolerating a non-JSON error body with an empty list).
|
|
590
609
|
*/
|
|
591
610
|
async function execute(ctx, req) {
|
|
592
|
-
|
|
611
|
+
return parseDocument((await send(ctx, req)).body);
|
|
612
|
+
}
|
|
613
|
+
async function executeRaw(ctx, req, as) {
|
|
614
|
+
const res = await send(ctx, req, as === "text" ? void 0 : as);
|
|
615
|
+
if (as === "text") return res.body === "" ? void 0 : res.body;
|
|
616
|
+
if (res.status === 204) return;
|
|
617
|
+
if (res.binary === void 0) throw new Error("The transport returned no binary body for a request that asked for one; a custom transport must read the response as binary when the request sets responseType.");
|
|
618
|
+
return res.binary;
|
|
619
|
+
}
|
|
620
|
+
/**
|
|
621
|
+
* Build the URL (a server link resolved against `baseUrl` and held to its origin, an absolute
|
|
622
|
+
* path verbatim, else `baseUrl + path`), apply content negotiation and any async per-request
|
|
623
|
+
* headers, then drive the transport. A non-2xx throws a {@link JsonApiError} carrying the parsed
|
|
624
|
+
* error objects (tolerating a non-JSON error body with an empty list).
|
|
625
|
+
*/
|
|
626
|
+
async function send(ctx, req, responseType) {
|
|
627
|
+
let url;
|
|
628
|
+
let sendHeaders = true;
|
|
629
|
+
if (req.link) {
|
|
630
|
+
const link = resolveLink(req.path, ctx.baseUrl);
|
|
631
|
+
if (!link.sameOrigin && ctx.allowCrossOriginLinks !== true) throw new Error(`Refusing to follow link "${req.path}": it leaves the base URL's origin (set allowCrossOriginLinks to follow it without the configured headers)`);
|
|
632
|
+
url = link.url;
|
|
633
|
+
sendHeaders = link.sameOrigin;
|
|
634
|
+
} else url = isAbsolute(req.path) ? req.path : ctx.baseUrl + req.path;
|
|
593
635
|
if (req.query) {
|
|
594
636
|
const qs = serializeQuery(req.query);
|
|
595
637
|
if (qs) url += (url.includes("?") ? "&" : "?") + qs;
|
|
@@ -605,15 +647,23 @@ async function execute(ctx, req) {
|
|
|
605
647
|
headers
|
|
606
648
|
};
|
|
607
649
|
if (req.signal !== void 0) transportReq.signal = req.signal;
|
|
608
|
-
if (
|
|
609
|
-
|
|
610
|
-
|
|
650
|
+
if (responseType !== void 0) transportReq.responseType = responseType;
|
|
651
|
+
if (req.body !== void 0 || req.method.toUpperCase() === "POST") {
|
|
652
|
+
const contentType = req.contentType === void 0 ? negotiated : req.contentType;
|
|
653
|
+
if (contentType !== null) headers["Content-Type"] = contentType;
|
|
611
654
|
}
|
|
612
|
-
if (
|
|
655
|
+
if (typeof req.body === "string" && req.raw) transportReq.body = req.body;
|
|
656
|
+
else if (req.raw && isRawBody(req.body)) transportReq.rawBody = req.body;
|
|
657
|
+
else if (req.body !== void 0) transportReq.body = JSON.stringify(req.body);
|
|
658
|
+
if (ctx.headers && sendHeaders) mergeHeaders(headers, await ctx.headers());
|
|
613
659
|
const res = await ctx.transport(transportReq);
|
|
614
|
-
if (res.status >= 200 && res.status < 300) return
|
|
660
|
+
if (res.status >= 200 && res.status < 300) return res;
|
|
615
661
|
throw new JsonApiError(res.status, parseErrors(res.body));
|
|
616
662
|
}
|
|
663
|
+
/** Whether a raw body goes to the transport as is rather than through `JSON.stringify`. */
|
|
664
|
+
function isRawBody(body) {
|
|
665
|
+
return typeof Blob !== "undefined" && body instanceof Blob || body instanceof ArrayBuffer || ArrayBuffer.isView(body) || typeof FormData !== "undefined" && body instanceof FormData || typeof URLSearchParams !== "undefined" && body instanceof URLSearchParams;
|
|
666
|
+
}
|
|
617
667
|
/**
|
|
618
668
|
* Merge a `HeadersInit` (object / tuple array / `Headers`) into the outgoing map,
|
|
619
669
|
* preserving the caller's casing (unlike the WHATWG `Headers`, which lowercases). The
|
|
@@ -1001,13 +1051,23 @@ const fetchTransport = async (req) => {
|
|
|
1001
1051
|
method: req.method,
|
|
1002
1052
|
headers: req.headers
|
|
1003
1053
|
};
|
|
1004
|
-
if (req.
|
|
1054
|
+
if (req.rawBody !== void 0) init.body = req.rawBody;
|
|
1055
|
+
else if (req.body !== void 0) init.body = req.body;
|
|
1005
1056
|
if (req.signal !== void 0) init.signal = req.signal;
|
|
1006
1057
|
const res = await fetch(req.url, init);
|
|
1007
1058
|
const headers = {};
|
|
1008
1059
|
res.headers.forEach((value, key) => {
|
|
1009
1060
|
headers[key] = value;
|
|
1010
1061
|
});
|
|
1062
|
+
if (req.responseType !== void 0 && res.ok) {
|
|
1063
|
+
const binary = req.responseType === "blob" ? await res.blob() : await res.arrayBuffer();
|
|
1064
|
+
return {
|
|
1065
|
+
status: res.status,
|
|
1066
|
+
headers,
|
|
1067
|
+
body: "",
|
|
1068
|
+
binary
|
|
1069
|
+
};
|
|
1070
|
+
}
|
|
1011
1071
|
return {
|
|
1012
1072
|
status: res.status,
|
|
1013
1073
|
headers,
|
|
@@ -1118,36 +1178,145 @@ async function runWrite(ctx, spec) {
|
|
|
1118
1178
|
* - `raw` — the caller's payload, sent with the action's declared media type (e.g.
|
|
1119
1179
|
* `application/octet-stream`), falling back to a wildcard when the spec declared none.
|
|
1120
1180
|
*
|
|
1181
|
+
* An action listing several request media types (`inputMedia`) sends the one the caller picks
|
|
1182
|
+
* with `options.contentType`, or JSON:API when listed, else the first.
|
|
1183
|
+
*
|
|
1121
1184
|
* The response is shaped by the action's `output`: `document` materialises into the resource /
|
|
1122
1185
|
* collection view, `meta` returns the document's top-level `meta`, `none` resolves `undefined` (a
|
|
1123
|
-
* `204` / no body).
|
|
1186
|
+
* `204` / no body). An action declaring `rawOutput` answers in the media type the caller picks
|
|
1187
|
+
* with `options.accept`: JSON:API as above, or a `string`, a `Blob` or `ArrayBuffer`, or parsed
|
|
1188
|
+
* JSON by the media type's kind.
|
|
1124
1189
|
*/
|
|
1125
|
-
async function runAction(ctx, action, vars, input) {
|
|
1190
|
+
async function runAction(ctx, action, vars, input, options = {}) {
|
|
1126
1191
|
const req = {
|
|
1127
1192
|
method: action.method ?? "POST",
|
|
1128
1193
|
path: fill(action.path, vars)
|
|
1129
1194
|
};
|
|
1195
|
+
if (options.signal !== void 0) req.signal = options.signal;
|
|
1130
1196
|
let remap;
|
|
1131
|
-
|
|
1197
|
+
const media = requestMedia(action, options.contentType);
|
|
1198
|
+
if (media !== void 0 && media.kind !== "document") {
|
|
1199
|
+
req.body = encodeFields(media.mediaType, media.kind, input);
|
|
1200
|
+
req.raw = true;
|
|
1201
|
+
req.contentType = sentContentType(media.mediaType, media.kind, req.body);
|
|
1202
|
+
} else if (action.input === "document") if (action.inputType !== void 0) {
|
|
1132
1203
|
const inputType = action.inputType;
|
|
1133
1204
|
req.body = toDocument(ctx.descriptor, inputType, input ?? {});
|
|
1134
1205
|
remap = (error) => withRemappedPaths(error, ctx.descriptor, inputType);
|
|
1135
1206
|
} else req.body = input;
|
|
1136
1207
|
else if (action.input === "raw") {
|
|
1137
|
-
req.body = input;
|
|
1138
|
-
req.contentType = action.contentType ?? "*/*";
|
|
1208
|
+
req.body = encodeFields(action.contentType ?? "*/*", void 0, input);
|
|
1209
|
+
req.contentType = sentContentType(action.contentType ?? "*/*", void 0, req.body);
|
|
1139
1210
|
req.raw = true;
|
|
1140
1211
|
}
|
|
1141
|
-
|
|
1212
|
+
const raw = responseMedia(action, options.accept);
|
|
1142
1213
|
try {
|
|
1143
|
-
|
|
1214
|
+
if (raw !== void 0) {
|
|
1215
|
+
req.accept = raw.mediaType;
|
|
1216
|
+
if (raw.kind === "binary") return await executeRaw(ctx.request, req, options.responseType === "arrayBuffer" ? "arraybuffer" : "blob");
|
|
1217
|
+
const text = await executeRaw(ctx.request, req, "text");
|
|
1218
|
+
return raw.kind === "json" && text !== void 0 ? JSON.parse(text) : text;
|
|
1219
|
+
}
|
|
1220
|
+
const doc = await execute(ctx.request, req);
|
|
1221
|
+
if (action.output === "none" || doc === void 0) return;
|
|
1222
|
+
if (action.output === "meta") return doc.meta;
|
|
1223
|
+
return materialise(doc, ctx.materialise);
|
|
1144
1224
|
} catch (error) {
|
|
1145
1225
|
if (remap !== void 0 && error instanceof JsonApiError) throw remap(error);
|
|
1146
1226
|
throw error;
|
|
1147
1227
|
}
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1228
|
+
}
|
|
1229
|
+
/**
|
|
1230
|
+
* The request media type an action with several (`inputMedia`) sends: the caller's pick, matched
|
|
1231
|
+
* exactly or through a declared wildcard such as `image/*`, else JSON:API when listed, else the
|
|
1232
|
+
* first. `undefined` for an action with a single request media type.
|
|
1233
|
+
*/
|
|
1234
|
+
function requestMedia(action, picked) {
|
|
1235
|
+
const listed = action.inputMedia;
|
|
1236
|
+
if (listed === void 0 || listed.length === 0) {
|
|
1237
|
+
if (picked !== void 0) throw new Error(`This action declares no request media types to choose "${picked}" from.`);
|
|
1238
|
+
return;
|
|
1239
|
+
}
|
|
1240
|
+
if (picked === void 0) {
|
|
1241
|
+
const media = listed.find((entry) => entry.mediaType === "application/vnd.api+json") ?? listed[0];
|
|
1242
|
+
return {
|
|
1243
|
+
mediaType: media.mediaType,
|
|
1244
|
+
kind: media.kind
|
|
1245
|
+
};
|
|
1246
|
+
}
|
|
1247
|
+
const essence = picked.split(";")[0].trim().toLowerCase();
|
|
1248
|
+
const match = listed.find((entry) => entry.mediaType === essence) ?? listed.find((entry) => entry.mediaType === `${essence.split("/")[0]}/*`) ?? listed.find((entry) => entry.mediaType === "*/*");
|
|
1249
|
+
if (match === void 0) throw new Error(`This action does not accept "${picked}"; it accepts ${listed.map((entry) => entry.mediaType).join(", ")}.`);
|
|
1250
|
+
return {
|
|
1251
|
+
mediaType: picked,
|
|
1252
|
+
kind: match.kind
|
|
1253
|
+
};
|
|
1254
|
+
}
|
|
1255
|
+
/**
|
|
1256
|
+
* A multipart or URL-encoded body given as a plain object of fields, encoded into a `FormData` or
|
|
1257
|
+
* `URLSearchParams`. Any other body, a ready `FormData` included, is sent as it is.
|
|
1258
|
+
*/
|
|
1259
|
+
function encodeFields(mediaType, kind, body) {
|
|
1260
|
+
const multipart = kind === "multipart" || mediaType.startsWith("multipart/");
|
|
1261
|
+
if (!multipart && !(kind === "form" || mediaType === "application/x-www-form-urlencoded") || !isPlainObject(body)) return body;
|
|
1262
|
+
return multipart ? toFormData(body) : toSearchParams(body);
|
|
1263
|
+
}
|
|
1264
|
+
/** Whether a body is a plain object of fields rather than a ready payload. */
|
|
1265
|
+
function isPlainObject(value) {
|
|
1266
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
|
|
1267
|
+
const proto = Object.getPrototypeOf(value);
|
|
1268
|
+
return proto === Object.prototype || proto === null;
|
|
1269
|
+
}
|
|
1270
|
+
/**
|
|
1271
|
+
* The entries a field contributes: nothing for `null` or `undefined`, one `name[]` entry per item
|
|
1272
|
+
* for an array (the bracket suffix is how PHP servers read a repeated field as a list), else one
|
|
1273
|
+
* `name` entry.
|
|
1274
|
+
*/
|
|
1275
|
+
function fieldEntries(name, value) {
|
|
1276
|
+
if (value === null || value === void 0) return [];
|
|
1277
|
+
if (Array.isArray(value)) return value.filter((item) => item !== null && item !== void 0).map((item) => [`${name}[]`, item]);
|
|
1278
|
+
return [[name, value]];
|
|
1279
|
+
}
|
|
1280
|
+
/** A field's text value: booleans as `true` or `false`, everything else through `String`. */
|
|
1281
|
+
function fieldText(value) {
|
|
1282
|
+
return typeof value === "boolean" ? value ? "true" : "false" : String(value);
|
|
1283
|
+
}
|
|
1284
|
+
/** A multipart body from fields. A `File` keeps its name; a bare `Blob` is named after its field. */
|
|
1285
|
+
function toFormData(fields) {
|
|
1286
|
+
const data = new FormData();
|
|
1287
|
+
for (const [field, value] of Object.entries(fields)) for (const [name, item] of fieldEntries(field, value)) if (typeof Blob !== "undefined" && item instanceof Blob) {
|
|
1288
|
+
const fileName = typeof File !== "undefined" && item instanceof File && item.name !== "" ? item.name : field;
|
|
1289
|
+
data.append(name, item, fileName);
|
|
1290
|
+
} else data.append(name, fieldText(item));
|
|
1291
|
+
return data;
|
|
1292
|
+
}
|
|
1293
|
+
/** A URL-encoded body from fields. */
|
|
1294
|
+
function toSearchParams(fields) {
|
|
1295
|
+
const params = new URLSearchParams();
|
|
1296
|
+
for (const [field, value] of Object.entries(fields)) for (const [name, item] of fieldEntries(field, value)) params.append(name, fieldText(item));
|
|
1297
|
+
return params;
|
|
1298
|
+
}
|
|
1299
|
+
/**
|
|
1300
|
+
* The `Content-Type` for a non-JSON:API body. A multipart `FormData` body gets none, so the
|
|
1301
|
+
* transport writes the boundary. A wildcard media type takes a `Blob` body's own type.
|
|
1302
|
+
*/
|
|
1303
|
+
function sentContentType(mediaType, kind, body) {
|
|
1304
|
+
if ((kind === "multipart" || mediaType.startsWith("multipart/")) && typeof FormData !== "undefined" && body instanceof FormData) return null;
|
|
1305
|
+
if (mediaType.includes("*") && typeof Blob !== "undefined" && body instanceof Blob) return body.type === "" ? mediaType : body.type;
|
|
1306
|
+
return mediaType;
|
|
1307
|
+
}
|
|
1308
|
+
/**
|
|
1309
|
+
* The non-JSON:API media type an action is asked to answer in: the caller's `accept` when it isn't
|
|
1310
|
+
* JSON:API, else, with no `accept`, the first raw media type of an action that answers in no
|
|
1311
|
+
* JSON:API document. `undefined` means a JSON:API response.
|
|
1312
|
+
*/
|
|
1313
|
+
function responseMedia(action, accept) {
|
|
1314
|
+
const raw = action.rawOutput ?? [];
|
|
1315
|
+
if (accept === void 0) return action.output === "none" ? raw[0] : void 0;
|
|
1316
|
+
if (accept === "application/vnd.api+json") return;
|
|
1317
|
+
const media = raw.find((entry) => entry.mediaType === accept);
|
|
1318
|
+
if (media === void 0) throw new Error(`This action does not answer in "${accept}"; it answers in ${[...action.output === "none" ? [] : [JSON_API_MEDIA_TYPE], ...raw.map((entry) => entry.mediaType)].join(", ")}.`);
|
|
1319
|
+
return media;
|
|
1151
1320
|
}
|
|
1152
1321
|
/**
|
|
1153
1322
|
* Build the typed `.actions` accessor at one scope: a plain object exposing exactly the
|
|
@@ -1159,7 +1328,7 @@ async function runAction(ctx, action, vars, input) {
|
|
|
1159
1328
|
function actionsAccessor(ctx, type, scope, vars) {
|
|
1160
1329
|
const actions = ctx.descriptor[type]?.actions ?? {};
|
|
1161
1330
|
const out = {};
|
|
1162
|
-
for (const [name, action] of Object.entries(actions)) if (action.scope === scope) out[name] = (
|
|
1331
|
+
for (const [name, action] of Object.entries(actions)) if (action.scope === scope) out[name] = (...args) => action.input === "none" ? runAction(ctx, action, vars, void 0, args[0]) : runAction(ctx, action, vars, args[0], args[1]);
|
|
1163
1332
|
return out;
|
|
1164
1333
|
}
|
|
1165
1334
|
/**
|
|
@@ -1279,7 +1448,8 @@ function createClient(descriptor, options) {
|
|
|
1279
1448
|
const request = {
|
|
1280
1449
|
baseUrl: options.baseUrl,
|
|
1281
1450
|
transport: options.transport ?? fetchTransport,
|
|
1282
|
-
...options.headers !== void 0 ? { headers: options.headers } : {}
|
|
1451
|
+
...options.headers !== void 0 ? { headers: options.headers } : {},
|
|
1452
|
+
...options.allowCrossOriginLinks !== void 0 ? { allowCrossOriginLinks: options.allowCrossOriginLinks } : {}
|
|
1283
1453
|
};
|
|
1284
1454
|
const validator = resolveValidator(options.validate);
|
|
1285
1455
|
const ctx = {
|
|
@@ -1322,6 +1492,6 @@ function createClient(descriptor, options) {
|
|
|
1322
1492
|
});
|
|
1323
1493
|
}
|
|
1324
1494
|
//#endregion
|
|
1325
|
-
export { ATOMIC_EXT, ATOMIC_MEDIA_TYPE, CANONICAL_PAGE_KEYS, HANDLE_RESERVED, JSON_API_MEDIA_TYPE, JsonApiError, StructuralGuardError, assertJsonApiDocument, createClient, execute, fetchTransport, hasErrorCode, materialise, mediaType, relatedPaginator, relatedPaginatorKind, remapPointer, remapRelationshipPointer, resolvePaginator, resolveValidator, runAtomic, serializeQuery, toDocument, toRelationshipDocument, validateDocument, withRemappedAtomicPaths, withRemappedPaths, withRemappedRelationshipPaths };
|
|
1495
|
+
export { ATOMIC_EXT, ATOMIC_MEDIA_TYPE, CANONICAL_PAGE_KEYS, HANDLE_RESERVED, JSON_API_MEDIA_TYPE, JsonApiError, StructuralGuardError, assertJsonApiDocument, createClient, execute, executeRaw, fetchTransport, hasErrorCode, materialise, mediaType, relatedPaginator, relatedPaginatorKind, remapPointer, remapRelationshipPointer, resolvePaginator, resolveValidator, runAtomic, serializeQuery, toDocument, toRelationshipDocument, validateDocument, withRemappedAtomicPaths, withRemappedPaths, withRemappedRelationshipPaths };
|
|
1326
1496
|
|
|
1327
1497
|
//# sourceMappingURL=index.mjs.map
|