@relyio/sdk 0.6.0 → 0.7.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/CHANGELOG.md +370 -0
- package/dist/.tsbuildinfo +1 -1
- package/dist/{chunk-DY2XT7OF.cjs → chunk-72UK5U7T.cjs} +70 -60
- package/dist/{chunk-7ABNXVWL.js → chunk-GYHAVYND.js} +777 -399
- package/dist/{chunk-I3ESNANB.js → chunk-H6IBQSMM.js} +2 -2
- package/dist/{chunk-HT6NFRM2.cjs → chunk-TZL374LS.cjs} +2 -2
- package/dist/{chunk-GCMQUM6N.cjs → chunk-VH2DE7HZ.cjs} +776 -402
- package/dist/{chunk-XJVY2CLY.js → chunk-YEJUMW4X.js} +70 -60
- package/dist/client/index.cjs +4 -3
- package/dist/client/index.d.cts +4 -4
- package/dist/client/index.d.ts +4 -4
- package/dist/client/index.js +2 -1
- package/dist/{index-d1Kz1e19.d.cts → define-content-type-DiVpbwNs.d.cts} +1615 -684
- package/dist/{index-yPbhZc6q.d.ts → define-content-type-DiVpbwNs.d.ts} +1615 -684
- package/dist/{define-schema-1kr2HIzN.d.cts → define-schema-C-5an28C.d.ts} +189 -85
- package/dist/{define-schema-ChvAzY8H.d.ts → define-schema-D7MButVt.d.cts} +189 -85
- package/dist/{index-XqoGUaAY.d.ts → index-1G97sNA8.d.ts} +489 -267
- package/dist/index-BOQIHnsh.d.ts +818 -0
- package/dist/index-DbsTUw3Q.d.cts +818 -0
- package/dist/{index-Df1VsfJR.d.cts → index-M0X45k7J.d.cts} +489 -267
- package/dist/index.cjs +98 -114
- package/dist/index.d.cts +31 -31
- package/dist/index.d.ts +31 -31
- package/dist/index.js +8 -8
- package/dist/schema/index.cjs +35 -35
- package/dist/schema/index.d.cts +13 -11
- package/dist/schema/index.d.ts +13 -11
- package/dist/schema/index.js +1 -1
- package/dist/types/index.d.cts +2 -2
- package/dist/types/index.d.ts +2 -2
- package/dist/utils/index.cjs +19 -19
- package/dist/utils/index.d.cts +10 -1
- package/dist/utils/index.d.ts +10 -1
- package/dist/utils/index.js +1 -1
- package/package.json +4 -3
- package/dist/define-content-type-CDB3kyeA.d.cts +0 -1173
- package/dist/define-content-type-CDB3kyeA.d.ts +0 -1173
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { parseDevEnv, DEV_CONTEXT_DIR, DEV_CONTEXT_FILENAME, parseDevContextFile } from './chunk-BBUB7C2Z.js';
|
|
2
|
+
import { isBrowser } from './chunk-H6IBQSMM.js';
|
|
2
3
|
import { __name, __publicField } from './chunk-XQ4QHWZE.js';
|
|
3
4
|
|
|
4
5
|
/* RelyIO SDK - Built with ❤️ by the RelyIO Team */
|
|
@@ -230,18 +231,6 @@ __name(_UnknownContractError, "UnknownContractError");
|
|
|
230
231
|
var UnknownContractError = _UnknownContractError;
|
|
231
232
|
|
|
232
233
|
// src/errors/auth-errors.ts
|
|
233
|
-
var _AuthenticationError = class _AuthenticationError extends SDKError {
|
|
234
|
-
constructor(message = "Authentication failed", statusCode = 401, cause, context) {
|
|
235
|
-
super(message, statusCode, cause, context);
|
|
236
|
-
__publicField(this, "code", "AUTHENTICATION_ERROR");
|
|
237
|
-
__publicField(this, "retryable", false);
|
|
238
|
-
}
|
|
239
|
-
getUserMessage() {
|
|
240
|
-
return "Authentication failed. Please check your API key and try again.";
|
|
241
|
-
}
|
|
242
|
-
};
|
|
243
|
-
__name(_AuthenticationError, "AuthenticationError");
|
|
244
|
-
var AuthenticationError = _AuthenticationError;
|
|
245
234
|
var _AuthorizationError = class _AuthorizationError extends SDKError {
|
|
246
235
|
constructor(message = "Authorization failed", statusCode = 403, cause, context) {
|
|
247
236
|
super(message, statusCode, cause, context);
|
|
@@ -420,58 +409,6 @@ var _InvalidPayloadError = class _InvalidPayloadError extends BaseValidationErro
|
|
|
420
409
|
};
|
|
421
410
|
__name(_InvalidPayloadError, "InvalidPayloadError");
|
|
422
411
|
var InvalidPayloadError = _InvalidPayloadError;
|
|
423
|
-
var _SchemaValidationError = class _SchemaValidationError extends BaseValidationError {
|
|
424
|
-
constructor(message = "Schema validation failed", violations = [], cause) {
|
|
425
|
-
super(message, violations, 400, cause);
|
|
426
|
-
__publicField(this, "code", "SCHEMA_VALIDATION_ERROR");
|
|
427
|
-
}
|
|
428
|
-
getUserMessage() {
|
|
429
|
-
return "The data does not match the expected schema. Please check your content structure.";
|
|
430
|
-
}
|
|
431
|
-
};
|
|
432
|
-
__name(_SchemaValidationError, "SchemaValidationError");
|
|
433
|
-
var SchemaValidationError = _SchemaValidationError;
|
|
434
|
-
var _RequiredFieldError = class _RequiredFieldError extends BaseValidationError {
|
|
435
|
-
constructor(fieldName, message, cause) {
|
|
436
|
-
const violation = {
|
|
437
|
-
field: fieldName,
|
|
438
|
-
message: message ?? `Field "${fieldName}" is required`,
|
|
439
|
-
code: "REQUIRED"
|
|
440
|
-
};
|
|
441
|
-
super(`Required field "${fieldName}" is missing`, [violation], 400, cause);
|
|
442
|
-
__publicField(this, "code", "REQUIRED_FIELD_ERROR");
|
|
443
|
-
}
|
|
444
|
-
getUserMessage() {
|
|
445
|
-
const violation = this.violations[0];
|
|
446
|
-
const fieldName = violation?.field;
|
|
447
|
-
return `The field "${fieldName}" is required and cannot be empty.`;
|
|
448
|
-
}
|
|
449
|
-
};
|
|
450
|
-
__name(_RequiredFieldError, "RequiredFieldError");
|
|
451
|
-
var RequiredFieldError = _RequiredFieldError;
|
|
452
|
-
var _InvalidFieldTypeError = class _InvalidFieldTypeError extends BaseValidationError {
|
|
453
|
-
constructor(fieldName, expectedType, actualType, value, cause) {
|
|
454
|
-
const violation = {
|
|
455
|
-
field: fieldName,
|
|
456
|
-
message: `Expected ${expectedType}, got ${actualType}`,
|
|
457
|
-
code: "INVALID_TYPE",
|
|
458
|
-
value
|
|
459
|
-
};
|
|
460
|
-
super(
|
|
461
|
-
`Invalid type for field "${fieldName}": expected ${expectedType}, got ${actualType}`,
|
|
462
|
-
[violation],
|
|
463
|
-
400,
|
|
464
|
-
cause
|
|
465
|
-
);
|
|
466
|
-
__publicField(this, "code", "INVALID_FIELD_TYPE");
|
|
467
|
-
}
|
|
468
|
-
getUserMessage() {
|
|
469
|
-
const violation = this.violations[0];
|
|
470
|
-
return `The field "${violation?.field}" has an invalid type. ${violation?.message}.`;
|
|
471
|
-
}
|
|
472
|
-
};
|
|
473
|
-
__name(_InvalidFieldTypeError, "InvalidFieldTypeError");
|
|
474
|
-
var InvalidFieldTypeError = _InvalidFieldTypeError;
|
|
475
412
|
|
|
476
413
|
// ../../platform/api-contract/dist/index.js
|
|
477
414
|
var HEADER_RETRY_AFTER = { name: "Retry-After" };
|
|
@@ -871,6 +808,20 @@ function isAborted(signal) {
|
|
|
871
808
|
}
|
|
872
809
|
__name(isAborted, "isAborted");
|
|
873
810
|
|
|
811
|
+
// src/http/request-timeout.ts
|
|
812
|
+
var MAX_TIMER_DELAY_MS = 2147483647;
|
|
813
|
+
function isTimerDelay(value) {
|
|
814
|
+
return typeof value === "number" && value >= 1 && value <= MAX_TIMER_DELAY_MS;
|
|
815
|
+
}
|
|
816
|
+
__name(isTimerDelay, "isTimerDelay");
|
|
817
|
+
function assertRequestTimeout(timeout) {
|
|
818
|
+
if (isTimerDelay(timeout)) return;
|
|
819
|
+
throw new Error(
|
|
820
|
+
`timeout must be a number of milliseconds from 1 to ${MAX_TIMER_DELAY_MS} \u2014 a timer given 0, NaN, Infinity or more fires at once and ends every request \u2014 and got ${String(timeout)}`
|
|
821
|
+
);
|
|
822
|
+
}
|
|
823
|
+
__name(assertRequestTimeout, "assertRequestTimeout");
|
|
824
|
+
|
|
874
825
|
// src/errors/instructed-delay.ts
|
|
875
826
|
function serviceInstructedDelayMs(error, nowMs) {
|
|
876
827
|
if (error instanceof ServiceIndeterminateError) {
|
|
@@ -924,43 +875,31 @@ var DefaultRetryPolicy = _DefaultRetryPolicy;
|
|
|
924
875
|
// src/http/http-client.ts
|
|
925
876
|
var _HttpClient = class _HttpClient {
|
|
926
877
|
constructor(config) {
|
|
927
|
-
|
|
928
|
-
__publicField(this, "
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
}
|
|
948
|
-
if (typeof window === "undefined") {
|
|
949
|
-
const globalWithVersion = globalThis;
|
|
950
|
-
this.defaultHeaders["User-Agent"] = `RelyIO-SDK/${globalWithVersion.__VERSION__ ?? "0.0.0"}`;
|
|
951
|
-
}
|
|
952
|
-
this.retryPolicy = new DefaultRetryPolicy({
|
|
953
|
-
maxAttempts: config.retryAttempts,
|
|
954
|
-
baseDelay: 1e3,
|
|
955
|
-
maxDelay: 1e4,
|
|
956
|
-
backoffFactor: 2,
|
|
957
|
-
jitter: true
|
|
958
|
-
});
|
|
878
|
+
/** What every request reads off the configuration, derived by {@link configure} and nowhere else. */
|
|
879
|
+
__publicField(this, "connection");
|
|
880
|
+
this.connection = connectionFor(config);
|
|
881
|
+
this.announce();
|
|
882
|
+
}
|
|
883
|
+
/**
|
|
884
|
+
* Run on `config` from now on: every later request — whoever holds this client — is sent to its
|
|
885
|
+
* `baseUrl`, with its headers, key and dataset, its timeout and retries, through its `fetch`, and
|
|
886
|
+
* logged by its `debug` options.
|
|
887
|
+
*
|
|
888
|
+
* The client's own `updateConfig()` calls this rather than building a second client, so a
|
|
889
|
+
* `content()` or other sub-client taken before the update sends through the update too. Anything
|
|
890
|
+
* set on this client since it was last configured — `setDefaultHeaders()`, `setBaseUrl()` — is
|
|
891
|
+
* replaced by what `config` says.
|
|
892
|
+
*/
|
|
893
|
+
configure(config) {
|
|
894
|
+
this.connection = connectionFor(config);
|
|
895
|
+
this.announce();
|
|
896
|
+
}
|
|
897
|
+
announce() {
|
|
959
898
|
this.log("debug", "HttpClient initialized", {
|
|
960
|
-
baseUrl: this.baseUrl,
|
|
961
|
-
timeout: this.timeout,
|
|
962
|
-
retryAttempts: config.retryAttempts,
|
|
963
|
-
environment:
|
|
899
|
+
baseUrl: this.connection.baseUrl,
|
|
900
|
+
timeout: this.connection.timeout,
|
|
901
|
+
retryAttempts: this.connection.config.retryAttempts,
|
|
902
|
+
environment: isBrowser() ? "browser" : "node"
|
|
964
903
|
});
|
|
965
904
|
}
|
|
966
905
|
/**
|
|
@@ -997,19 +936,24 @@ var _HttpClient = class _HttpClient {
|
|
|
997
936
|
*
|
|
998
937
|
* The loop always makes one attempt. The incumbent's `while (attempt <
|
|
999
938
|
* maxAttempts)` made none at `retryAttempts: 0` — a value the config validator
|
|
1000
|
-
*
|
|
939
|
+
* then accepted, and now refuses — and then dereferenced an unassigned
|
|
940
|
+
* `lastError`. `retryAttempts` is the most attempts, the first included; an
|
|
941
|
+
* `HttpClient` constructed directly is not validated, so the first attempt
|
|
942
|
+
* stays unconditional.
|
|
1001
943
|
*
|
|
1002
944
|
* A request that would carry no `X-API-Key` makes none: it rejects with
|
|
1003
945
|
* `MissingApiKeyError` before `fetch` is called, is not retried, and names
|
|
1004
946
|
* `apiKey`. This is where a client built without a key learns it — the
|
|
1005
947
|
* constructor accepts one so that a module-scope client can be evaluated by a
|
|
1006
|
-
* build that holds no key (REL-1120)
|
|
948
|
+
* build that holds no key (REL-1120) — and so does one whose `setApiKey` was
|
|
949
|
+
* given none.
|
|
1007
950
|
*/
|
|
1008
951
|
async request(config) {
|
|
952
|
+
if (config.timeout !== void 0) assertRequestTimeout(config.timeout);
|
|
1009
953
|
const mergedConfig = this.mergeRequestConfig(config);
|
|
1010
954
|
if (presentKey(headerValue(mergedConfig.headers, API_KEY_HEADER)) === void 0) {
|
|
1011
955
|
throw new MissingApiKeyError(
|
|
1012
|
-
"`apiKey` is missing: this client
|
|
956
|
+
"`apiKey` is missing: this client holds no API key, so the request was not sent. Pass `apiKey` to createClient \u2014 the documented setup reads it from RELYIO_API_KEY.",
|
|
1013
957
|
{ url: mergedConfig.url, method: mergedConfig.method, sent: false }
|
|
1014
958
|
);
|
|
1015
959
|
}
|
|
@@ -1019,7 +963,7 @@ var _HttpClient = class _HttpClient {
|
|
|
1019
963
|
// Show the final URL with query params
|
|
1020
964
|
});
|
|
1021
965
|
if (config.method === "DELETE" && mergedConfig.headers) {
|
|
1022
|
-
|
|
966
|
+
mergedConfig.headers = layerHeaders(mergedConfig.headers, { "Content-Type": null });
|
|
1023
967
|
}
|
|
1024
968
|
for (let attempt = 1; ; attempt++) {
|
|
1025
969
|
try {
|
|
@@ -1038,8 +982,8 @@ var _HttpClient = class _HttpClient {
|
|
|
1038
982
|
attempt,
|
|
1039
983
|
url: mergedConfig.url
|
|
1040
984
|
});
|
|
1041
|
-
if (this.retryPolicy.shouldRetry(attempt, failure, mergedConfig)) {
|
|
1042
|
-
const delay = this.retryPolicy.delayFor(attempt, failure);
|
|
985
|
+
if (this.connection.retryPolicy.shouldRetry(attempt, failure, mergedConfig)) {
|
|
986
|
+
const delay = this.connection.retryPolicy.delayFor(attempt, failure);
|
|
1043
987
|
this.log("debug", "Retrying request", { attempt, delay });
|
|
1044
988
|
await sleep(delay, config.signal);
|
|
1045
989
|
continue;
|
|
@@ -1111,34 +1055,60 @@ var _HttpClient = class _HttpClient {
|
|
|
1111
1055
|
});
|
|
1112
1056
|
}
|
|
1113
1057
|
/**
|
|
1114
|
-
*
|
|
1058
|
+
* Add headers to every later request, each replacing any header of the same name — the name
|
|
1059
|
+
* matched without regard to case — until the client is next configured.
|
|
1115
1060
|
*/
|
|
1116
1061
|
setDefaultHeaders(headers) {
|
|
1117
|
-
this.
|
|
1062
|
+
this.connection = {
|
|
1063
|
+
...this.connection,
|
|
1064
|
+
defaultHeaders: layerHeaders(this.connection.defaultHeaders, headers)
|
|
1065
|
+
};
|
|
1118
1066
|
}
|
|
1119
1067
|
/**
|
|
1120
|
-
*
|
|
1068
|
+
* Replace the key every later request sends as `X-API-Key`, and the `apiKey` the configuration
|
|
1069
|
+
* reports.
|
|
1070
|
+
*
|
|
1071
|
+
* The key is read the way construction reads it (`presentKey`): an absent, empty or blank key is
|
|
1072
|
+
* no key, so the header is dropped and the next request is refused with `MissingApiKeyError`
|
|
1073
|
+
* before anything is sent. A key header of any other spelling — one given in `headers` — goes
|
|
1074
|
+
* too, from the headers sent and from the headers the configuration reports, so the old key is
|
|
1075
|
+
* never sent beside the new one.
|
|
1076
|
+
*
|
|
1077
|
+
* The configuration is the one the owning `TypedRelyIOClient` holds (it hands its own to the
|
|
1078
|
+
* constructor), so its `getConfig().apiKey` — what a surface reads to decide a key's kind — is the
|
|
1079
|
+
* key sent from here on.
|
|
1080
|
+
*
|
|
1081
|
+
* This replaced `setAuthToken`, which added `Authorization: Bearer` beside an `X-API-Key` it
|
|
1082
|
+
* never touched: the API reads `X-API-Key` first, so the old key was the one used (REL-1385).
|
|
1121
1083
|
*/
|
|
1122
|
-
|
|
1123
|
-
|
|
1084
|
+
setApiKey(apiKey) {
|
|
1085
|
+
const { config } = this.connection;
|
|
1086
|
+
config.apiKey = apiKey;
|
|
1087
|
+
config.headers = layerHeaders(config.headers, { [API_KEY_HEADER]: null });
|
|
1088
|
+
this.connection = {
|
|
1089
|
+
...this.connection,
|
|
1090
|
+
defaultHeaders: layerHeaders(this.connection.defaultHeaders, {
|
|
1091
|
+
[API_KEY_HEADER]: presentKey(apiKey) ?? null
|
|
1092
|
+
})
|
|
1093
|
+
};
|
|
1124
1094
|
}
|
|
1125
1095
|
/**
|
|
1126
1096
|
* Get current default headers
|
|
1127
1097
|
*/
|
|
1128
1098
|
getDefaultHeaders() {
|
|
1129
|
-
return { ...this.defaultHeaders };
|
|
1099
|
+
return { ...this.connection.defaultHeaders };
|
|
1130
1100
|
}
|
|
1131
1101
|
/**
|
|
1132
1102
|
* Update base URL
|
|
1133
1103
|
*/
|
|
1134
1104
|
setBaseUrl(baseUrl) {
|
|
1135
|
-
this.
|
|
1105
|
+
this.connection = { ...this.connection, baseUrl };
|
|
1136
1106
|
}
|
|
1137
1107
|
/**
|
|
1138
1108
|
* Get current base URL
|
|
1139
1109
|
*/
|
|
1140
1110
|
getBaseUrl() {
|
|
1141
|
-
return this.baseUrl;
|
|
1111
|
+
return this.connection.baseUrl;
|
|
1142
1112
|
}
|
|
1143
1113
|
/**
|
|
1144
1114
|
* One attempt.
|
|
@@ -1160,7 +1130,7 @@ var _HttpClient = class _HttpClient {
|
|
|
1160
1130
|
const timeoutId = setTimeout(() => {
|
|
1161
1131
|
timedOut = true;
|
|
1162
1132
|
controller.abort();
|
|
1163
|
-
}, config.timeout ?? this.timeout);
|
|
1133
|
+
}, config.timeout ?? this.connection.timeout);
|
|
1164
1134
|
const onCallerAbort = /* @__PURE__ */ __name(() => controller.abort(), "onCallerAbort");
|
|
1165
1135
|
caller?.addEventListener("abort", onCallerAbort, { once: true });
|
|
1166
1136
|
try {
|
|
@@ -1170,14 +1140,15 @@ var _HttpClient = class _HttpClient {
|
|
|
1170
1140
|
headers: filteredHeaders,
|
|
1171
1141
|
body: this.prepareRequestBody(config),
|
|
1172
1142
|
signal: controller.signal,
|
|
1173
|
-
// Only
|
|
1174
|
-
// govern, so the field is left off and the
|
|
1175
|
-
//
|
|
1176
|
-
|
|
1177
|
-
|
|
1143
|
+
// Only in a browser — a `window` with a `document` (`isBrowser()`). A server or edge
|
|
1144
|
+
// runtime has no cookie jar for the mode to govern, so the field is left off and the
|
|
1145
|
+
// runtime's default stands; that includes Deno 1.x, whose global is a `window` with no
|
|
1146
|
+
// `document`. A Web Worker gets that default too: it has cookies but no `window`.
|
|
1147
|
+
...isBrowser() && {
|
|
1148
|
+
credentials: credentialsModeFor(this.connection.config.browser.includeCredentials)
|
|
1178
1149
|
}
|
|
1179
1150
|
};
|
|
1180
|
-
const send = this.config.fetch ?? globalThis.fetch;
|
|
1151
|
+
const send = this.connection.config.fetch ?? globalThis.fetch;
|
|
1181
1152
|
const response = await send(url, requestInit);
|
|
1182
1153
|
clearTimeout(timeoutId);
|
|
1183
1154
|
const responseBody = await this.parseResponse(response);
|
|
@@ -1210,10 +1181,8 @@ var _HttpClient = class _HttpClient {
|
|
|
1210
1181
|
}
|
|
1211
1182
|
if (error instanceof DOMException && error.name === "AbortError") {
|
|
1212
1183
|
if (!timedOut && isAborted(caller)) throw error;
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
config.timeout ?? this.timeout
|
|
1216
|
-
);
|
|
1184
|
+
const timeout = config.timeout ?? this.connection.timeout;
|
|
1185
|
+
throw new TimeoutError(`Request timed out after ${timeout}ms`, timeout);
|
|
1217
1186
|
}
|
|
1218
1187
|
if (error instanceof TypeError && error.message.includes("CORS")) {
|
|
1219
1188
|
const corsError = new NetworkError(
|
|
@@ -1227,9 +1196,10 @@ var _HttpClient = class _HttpClient {
|
|
|
1227
1196
|
suggestion: "Check if the API server allows requests from your domain and has proper CORS headers configured."
|
|
1228
1197
|
}
|
|
1229
1198
|
);
|
|
1230
|
-
|
|
1199
|
+
const { onCorsError } = this.connection.config.browser;
|
|
1200
|
+
if (isBrowser() && onCorsError) {
|
|
1231
1201
|
try {
|
|
1232
|
-
|
|
1202
|
+
onCorsError(corsError, {
|
|
1233
1203
|
url: config.url,
|
|
1234
1204
|
method: config.method,
|
|
1235
1205
|
originalError: error
|
|
@@ -1246,20 +1216,20 @@ var _HttpClient = class _HttpClient {
|
|
|
1246
1216
|
}
|
|
1247
1217
|
}
|
|
1248
1218
|
/**
|
|
1249
|
-
*
|
|
1219
|
+
* The headers without those a browser controls itself, when this is a browser; unchanged when it
|
|
1220
|
+
* is not.
|
|
1221
|
+
*
|
|
1222
|
+
* A name is matched without regard to case (RFC 9110 §5.1), because a browser refuses `Origin`
|
|
1223
|
+
* whatever case a page spells it in. This matched only the all-lowercase and all-uppercase
|
|
1224
|
+
* spellings, so `Origin` and `User-Agent` — how people write them — reached `fetch` (REL-1409).
|
|
1250
1225
|
*/
|
|
1251
1226
|
filterHeadersForBrowser(headers) {
|
|
1252
|
-
if (
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
delete filteredHeaders[header.toUpperCase()];
|
|
1259
|
-
});
|
|
1260
|
-
return filteredHeaders;
|
|
1261
|
-
}
|
|
1262
|
-
return headers;
|
|
1227
|
+
if (!isBrowser()) return headers;
|
|
1228
|
+
return Object.fromEntries(
|
|
1229
|
+
Object.entries(headers).filter(
|
|
1230
|
+
([name]) => !BROWSER_CONTROLLED_HEADERS.has(name.toLowerCase())
|
|
1231
|
+
)
|
|
1232
|
+
);
|
|
1263
1233
|
}
|
|
1264
1234
|
/**
|
|
1265
1235
|
* Prepare request body based on content type and environment
|
|
@@ -1295,7 +1265,7 @@ var _HttpClient = class _HttpClient {
|
|
|
1295
1265
|
if (url.startsWith("http://") || url.startsWith("https://")) {
|
|
1296
1266
|
return url;
|
|
1297
1267
|
}
|
|
1298
|
-
return `${this.baseUrl}${url.startsWith("/") ? "" : "/"}${url}`;
|
|
1268
|
+
return `${this.connection.baseUrl}${url.startsWith("/") ? "" : "/"}${url}`;
|
|
1299
1269
|
}
|
|
1300
1270
|
mergeRequestConfig(config) {
|
|
1301
1271
|
const url = this.resolveUrl(config.url);
|
|
@@ -1304,11 +1274,11 @@ var _HttpClient = class _HttpClient {
|
|
|
1304
1274
|
return {
|
|
1305
1275
|
...config,
|
|
1306
1276
|
url: finalUrl,
|
|
1307
|
-
headers:
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
timeout: config.timeout ?? this.timeout
|
|
1277
|
+
// The request's own headers replace the client's of the same name, whatever the case: a
|
|
1278
|
+
// per-request `x-relyio-dataset` sent beside the client's `X-RelyIO-Dataset` is one header
|
|
1279
|
+
// `Headers` joins into `main, staging`.
|
|
1280
|
+
headers: layerHeaders(this.connection.defaultHeaders, config.headers),
|
|
1281
|
+
timeout: config.timeout ?? this.connection.timeout
|
|
1312
1282
|
};
|
|
1313
1283
|
}
|
|
1314
1284
|
buildQueryString(params) {
|
|
@@ -1332,9 +1302,10 @@ var _HttpClient = class _HttpClient {
|
|
|
1332
1302
|
return obj;
|
|
1333
1303
|
}
|
|
1334
1304
|
log(level, message, data) {
|
|
1335
|
-
|
|
1336
|
-
if (
|
|
1337
|
-
|
|
1305
|
+
const { debug } = this.connection.config;
|
|
1306
|
+
if (!debug.enabled) return;
|
|
1307
|
+
if (debug.logger != null) {
|
|
1308
|
+
debug.logger(level, message, data);
|
|
1338
1309
|
} else {
|
|
1339
1310
|
console.log(`[RelyIO SDK ${level.toUpperCase()}] ${message}`, data ?? "");
|
|
1340
1311
|
}
|
|
@@ -1343,29 +1314,104 @@ var _HttpClient = class _HttpClient {
|
|
|
1343
1314
|
__name(_HttpClient, "HttpClient");
|
|
1344
1315
|
var HttpClient = _HttpClient;
|
|
1345
1316
|
var API_KEY_HEADER = "X-API-Key";
|
|
1317
|
+
var DATASET_HEADER = "X-RelyIO-Dataset";
|
|
1318
|
+
var BROWSER_CONTROLLED_HEADERS = /* @__PURE__ */ new Set([
|
|
1319
|
+
"user-agent",
|
|
1320
|
+
"referer",
|
|
1321
|
+
"origin",
|
|
1322
|
+
"host",
|
|
1323
|
+
"connection",
|
|
1324
|
+
"upgrade"
|
|
1325
|
+
]);
|
|
1326
|
+
function connectionFor(config) {
|
|
1327
|
+
const globalWithVersion = globalThis;
|
|
1328
|
+
const defaultHeaders = layerHeaders(
|
|
1329
|
+
layerHeaders({ "Content-Type": "application/json" }, config.headers),
|
|
1330
|
+
{
|
|
1331
|
+
[API_KEY_HEADER]: presentKey(config.apiKey),
|
|
1332
|
+
[DATASET_HEADER]: config.dataset,
|
|
1333
|
+
// Only outside a browser, which controls this header. "A browser" is the core's one
|
|
1334
|
+
// definition, `isBrowser()` — every environment question in this file asks it.
|
|
1335
|
+
"User-Agent": isBrowser() ? void 0 : `RelyIO-SDK/${globalWithVersion.__VERSION__ ?? "0.0.0"}`
|
|
1336
|
+
}
|
|
1337
|
+
);
|
|
1338
|
+
return {
|
|
1339
|
+
config,
|
|
1340
|
+
baseUrl: config.baseUrl,
|
|
1341
|
+
defaultHeaders,
|
|
1342
|
+
timeout: config.timeout,
|
|
1343
|
+
// The policy, not a predicate over `(error, attempt)`: whether a request may be sent again is a
|
|
1344
|
+
// property of the **route** as much as of the refusal, and a callback that never sees the
|
|
1345
|
+
// request cannot express that.
|
|
1346
|
+
retryPolicy: new DefaultRetryPolicy({
|
|
1347
|
+
maxAttempts: config.retryAttempts,
|
|
1348
|
+
baseDelay: 1e3,
|
|
1349
|
+
maxDelay: 1e4,
|
|
1350
|
+
backoffFactor: 2,
|
|
1351
|
+
jitter: true
|
|
1352
|
+
})
|
|
1353
|
+
};
|
|
1354
|
+
}
|
|
1355
|
+
__name(connectionFor, "connectionFor");
|
|
1356
|
+
function layerHeaders(base, over) {
|
|
1357
|
+
const layered = { ...base };
|
|
1358
|
+
for (const [name, value] of Object.entries(over ?? {})) {
|
|
1359
|
+
if (value === void 0) continue;
|
|
1360
|
+
const lower = name.toLowerCase();
|
|
1361
|
+
for (const existing of Object.keys(layered)) {
|
|
1362
|
+
if (existing.toLowerCase() === lower) delete layered[existing];
|
|
1363
|
+
}
|
|
1364
|
+
if (value !== null) layered[name] = value;
|
|
1365
|
+
}
|
|
1366
|
+
return layered;
|
|
1367
|
+
}
|
|
1368
|
+
__name(layerHeaders, "layerHeaders");
|
|
1346
1369
|
function presentKey(value) {
|
|
1347
1370
|
return typeof value === "string" && value.trim() !== "" ? value : void 0;
|
|
1348
1371
|
}
|
|
1349
1372
|
__name(presentKey, "presentKey");
|
|
1350
1373
|
function credentialsModeFor(includeCredentials) {
|
|
1351
|
-
|
|
1352
|
-
case false: {
|
|
1353
|
-
return "same-origin";
|
|
1354
|
-
}
|
|
1355
|
-
case true:
|
|
1356
|
-
case void 0: {
|
|
1357
|
-
return "include";
|
|
1358
|
-
}
|
|
1359
|
-
}
|
|
1374
|
+
return includeCredentials ? "include" : "same-origin";
|
|
1360
1375
|
}
|
|
1361
1376
|
__name(credentialsModeFor, "credentialsModeFor");
|
|
1362
1377
|
|
|
1378
|
+
// src/content/client-locale.ts
|
|
1379
|
+
function callLocale(named, clientLocale) {
|
|
1380
|
+
if (named !== void 0) return named;
|
|
1381
|
+
return clientLocale === void 0 || clientLocale === "" ? void 0 : clientLocale;
|
|
1382
|
+
}
|
|
1383
|
+
__name(callLocale, "callLocale");
|
|
1384
|
+
function readClientLocale(locale) {
|
|
1385
|
+
return typeof locale === "function" ? locale : () => locale;
|
|
1386
|
+
}
|
|
1387
|
+
__name(readClientLocale, "readClientLocale");
|
|
1388
|
+
|
|
1363
1389
|
// src/content/query-builder.ts
|
|
1390
|
+
function namesMetadata(key) {
|
|
1391
|
+
return key === "_metadata" || key.startsWith("_metadata.");
|
|
1392
|
+
}
|
|
1393
|
+
__name(namesMetadata, "namesMetadata");
|
|
1394
|
+
function refuseMetadataConditions(conditions) {
|
|
1395
|
+
const named = Object.keys(conditions).filter(namesMetadata);
|
|
1396
|
+
if (named.length === 0) return;
|
|
1397
|
+
throw new ValidationError(
|
|
1398
|
+
`A condition cannot name ${named.join(", ")}: the API filters on the fields the content type declares, and reports _metadata beside them. Filter on a field, and read _metadata from the result.`,
|
|
1399
|
+
named.map((field) => ({
|
|
1400
|
+
field,
|
|
1401
|
+
code: "METADATA_CONDITION",
|
|
1402
|
+
message: `${field} is not a field the API can filter on`
|
|
1403
|
+
}))
|
|
1404
|
+
);
|
|
1405
|
+
}
|
|
1406
|
+
__name(refuseMetadataConditions, "refuseMetadataConditions");
|
|
1364
1407
|
var _ContentQueryBuilder = class _ContentQueryBuilder {
|
|
1365
|
-
|
|
1408
|
+
/**
|
|
1409
|
+
* @param locale - The client's locale (`withLocale()`, `updateConfig({ locale })`), sent when the
|
|
1410
|
+
* query names none: the function `TypedRelyIOClient` hands over, or a locale fixed for it
|
|
1411
|
+
*/
|
|
1412
|
+
constructor(httpClient, contentType, locale) {
|
|
1366
1413
|
this.httpClient = httpClient;
|
|
1367
1414
|
this.contentType = contentType;
|
|
1368
|
-
this.defaultLocale = defaultLocale;
|
|
1369
1415
|
__publicField(this, "queryOptions", {});
|
|
1370
1416
|
__publicField(this, "localeValue");
|
|
1371
1417
|
__publicField(this, "localesArray");
|
|
@@ -1375,6 +1421,9 @@ var _ContentQueryBuilder = class _ContentQueryBuilder {
|
|
|
1375
1421
|
__publicField(this, "pageNumber");
|
|
1376
1422
|
__publicField(this, "pageSizeValue");
|
|
1377
1423
|
__publicField(this, "requestHeaders");
|
|
1424
|
+
/** The client's locale, asked when the query is sent rather than copied when it was built. */
|
|
1425
|
+
__publicField(this, "clientLocale");
|
|
1426
|
+
this.clientLocale = readClientLocale(locale);
|
|
1378
1427
|
}
|
|
1379
1428
|
/**
|
|
1380
1429
|
* Headers this query adds to the client's own, e.g. `X-RelyIO-Dataset` to list another dataset
|
|
@@ -1386,9 +1435,11 @@ var _ContentQueryBuilder = class _ContentQueryBuilder {
|
|
|
1386
1435
|
return this;
|
|
1387
1436
|
}
|
|
1388
1437
|
/**
|
|
1389
|
-
* Add where conditions to the query
|
|
1438
|
+
* Add where conditions to the query: conditions on the fields the content type declares. A
|
|
1439
|
+
* condition on `_metadata` is refused here, before anything is sent (`refuseMetadataConditions`).
|
|
1390
1440
|
*/
|
|
1391
1441
|
where(conditions) {
|
|
1442
|
+
refuseMetadataConditions(conditions);
|
|
1392
1443
|
this.queryOptions.where = {
|
|
1393
1444
|
...this.queryOptions.where,
|
|
1394
1445
|
...conditions
|
|
@@ -1645,7 +1696,11 @@ var _ContentQueryBuilder = class _ContentQueryBuilder {
|
|
|
1645
1696
|
* Clone the query builder
|
|
1646
1697
|
*/
|
|
1647
1698
|
clone() {
|
|
1648
|
-
const cloned = new _ContentQueryBuilder(
|
|
1699
|
+
const cloned = new _ContentQueryBuilder(
|
|
1700
|
+
this.httpClient,
|
|
1701
|
+
this.contentType,
|
|
1702
|
+
this.clientLocale
|
|
1703
|
+
);
|
|
1649
1704
|
cloned.queryOptions = JSON.parse(JSON.stringify(this.queryOptions));
|
|
1650
1705
|
cloned.localeValue = this.localeValue;
|
|
1651
1706
|
cloned.localesArray = this.localesArray ? [...this.localesArray] : void 0;
|
|
@@ -1720,14 +1775,15 @@ var _ContentQueryBuilder = class _ContentQueryBuilder {
|
|
|
1720
1775
|
if (this.queryOptions.cursor !== void 0) {
|
|
1721
1776
|
params.cursor = this.queryOptions.cursor;
|
|
1722
1777
|
}
|
|
1778
|
+
const clientLocale = this.clientLocale();
|
|
1723
1779
|
if (this.localeValue != null && this.localeValue !== "") {
|
|
1724
1780
|
params.locale = this.localeValue;
|
|
1725
1781
|
} else if (this.fetchAllLocales) {
|
|
1726
1782
|
params.locale = "*";
|
|
1727
1783
|
} else if (this.localesArray && this.localesArray.length > 0) {
|
|
1728
1784
|
params.locales = this.localesArray.join(",");
|
|
1729
|
-
} else if (
|
|
1730
|
-
params.locale =
|
|
1785
|
+
} else if (clientLocale != null && clientLocale !== "") {
|
|
1786
|
+
params.locale = clientLocale;
|
|
1731
1787
|
}
|
|
1732
1788
|
if (this.pageNumber !== void 0) {
|
|
1733
1789
|
params.page = this.pageNumber;
|
|
@@ -1751,17 +1807,23 @@ var _ContentQueryBuilder = class _ContentQueryBuilder {
|
|
|
1751
1807
|
__name(_ContentQueryBuilder, "ContentQueryBuilder");
|
|
1752
1808
|
var ContentQueryBuilder = _ContentQueryBuilder;
|
|
1753
1809
|
var _ContentByIdBuilder = class _ContentByIdBuilder {
|
|
1754
|
-
|
|
1810
|
+
/**
|
|
1811
|
+
* @param locale - The client's locale (`withLocale()`, `updateConfig({ locale })`), sent when the
|
|
1812
|
+
* read names none: the function `TypedRelyIOClient` hands over, or a locale fixed for it
|
|
1813
|
+
*/
|
|
1814
|
+
constructor(httpClient, contentType, id, locale) {
|
|
1755
1815
|
this.httpClient = httpClient;
|
|
1756
1816
|
this.contentType = contentType;
|
|
1757
1817
|
this.id = id;
|
|
1758
|
-
this.defaultLocale = defaultLocale;
|
|
1759
1818
|
__publicField(this, "includeRelations");
|
|
1760
1819
|
__publicField(this, "localeValue");
|
|
1761
1820
|
__publicField(this, "localesArray");
|
|
1762
1821
|
__publicField(this, "fetchAllLocales", false);
|
|
1763
1822
|
__publicField(this, "childrenOptions");
|
|
1764
1823
|
__publicField(this, "requestHeaders");
|
|
1824
|
+
/** The client's locale, asked when the read is sent rather than copied when it was built. */
|
|
1825
|
+
__publicField(this, "clientLocale");
|
|
1826
|
+
this.clientLocale = readClientLocale(locale);
|
|
1765
1827
|
}
|
|
1766
1828
|
/**
|
|
1767
1829
|
* Include related content in the response
|
|
@@ -1831,14 +1893,15 @@ var _ContentByIdBuilder = class _ContentByIdBuilder {
|
|
|
1831
1893
|
if (this.includeRelations != null) {
|
|
1832
1894
|
params.include = this.includeRelations.join(",");
|
|
1833
1895
|
}
|
|
1896
|
+
const clientLocale = this.clientLocale();
|
|
1834
1897
|
if (this.localeValue != null && this.localeValue !== "") {
|
|
1835
1898
|
params.locale = this.localeValue;
|
|
1836
1899
|
} else if (this.fetchAllLocales) {
|
|
1837
1900
|
params.locale = "*";
|
|
1838
1901
|
} else if (this.localesArray && this.localesArray.length > 0) {
|
|
1839
1902
|
params.locales = this.localesArray.join(",");
|
|
1840
|
-
} else if (
|
|
1841
|
-
params.locale =
|
|
1903
|
+
} else if (clientLocale != null && clientLocale !== "") {
|
|
1904
|
+
params.locale = clientLocale;
|
|
1842
1905
|
}
|
|
1843
1906
|
if (this.childrenOptions != null) {
|
|
1844
1907
|
if (this.childrenOptions.contentTypes) {
|
|
@@ -1903,22 +1966,28 @@ __name(entityTagOf, "entityTagOf");
|
|
|
1903
1966
|
|
|
1904
1967
|
// src/content/content-client.ts
|
|
1905
1968
|
var _ContentClient = class _ContentClient {
|
|
1906
|
-
|
|
1969
|
+
/**
|
|
1970
|
+
* @param locale - The client's locale: the function `TypedRelyIOClient` hands over, asked on
|
|
1971
|
+
* every call, or a locale fixed for this client
|
|
1972
|
+
*/
|
|
1973
|
+
constructor(httpClient, contentType, locale) {
|
|
1907
1974
|
this.httpClient = httpClient;
|
|
1908
1975
|
this.contentType = contentType;
|
|
1909
|
-
this.
|
|
1976
|
+
/** The client's locale, asked on every call rather than copied when this client was taken. */
|
|
1977
|
+
__publicField(this, "clientLocale");
|
|
1978
|
+
this.clientLocale = readClientLocale(locale);
|
|
1910
1979
|
}
|
|
1911
1980
|
/**
|
|
1912
1981
|
* Create a new query builder for this content type
|
|
1913
1982
|
*/
|
|
1914
1983
|
query() {
|
|
1915
|
-
return new ContentQueryBuilder(this.httpClient, this.contentType, this.
|
|
1984
|
+
return new ContentQueryBuilder(this.httpClient, this.contentType, this.clientLocale);
|
|
1916
1985
|
}
|
|
1917
1986
|
/**
|
|
1918
1987
|
* Find content by ID with fluent options
|
|
1919
1988
|
*/
|
|
1920
1989
|
findById(id) {
|
|
1921
|
-
return new ContentByIdBuilder(this.httpClient, this.contentType, id, this.
|
|
1990
|
+
return new ContentByIdBuilder(this.httpClient, this.contentType, id, this.clientLocale);
|
|
1922
1991
|
}
|
|
1923
1992
|
/**
|
|
1924
1993
|
* Fetch all content items
|
|
@@ -2002,7 +2071,7 @@ var _ContentClient = class _ContentClient {
|
|
|
2002
2071
|
async fetchOneWithTag(id, options) {
|
|
2003
2072
|
const query = {};
|
|
2004
2073
|
if (options?.include != null) query.include = options.include.join(",");
|
|
2005
|
-
const locale = options?.locale ?? this.
|
|
2074
|
+
const locale = options?.locale ?? this.clientLocale();
|
|
2006
2075
|
if (locale != null && locale !== "") query.locale = locale;
|
|
2007
2076
|
const response = await this.httpClient.send(
|
|
2008
2077
|
"/v1/{contentType}/{id}",
|
|
@@ -2032,16 +2101,17 @@ var _ContentClient = class _ContentClient {
|
|
|
2032
2101
|
* @param options - Create options (slug, locale, parentId, sortOrder), and `headers` this one
|
|
2033
2102
|
* request adds — e.g. `{ 'X-RelyIO-Dataset': 'staging' }` to write a dataset other than the
|
|
2034
2103
|
* client's. They are sent, never put in the body; `idempotencyKey` still wins over an
|
|
2035
|
-
* `Idempotency-Key` among them.
|
|
2104
|
+
* `Idempotency-Key` among them. `locale` defaults to the client's own (`withLocale()`).
|
|
2036
2105
|
*/
|
|
2037
2106
|
async create(data, options) {
|
|
2038
|
-
const { idempotencyKey, headers, ...body } = options ?? {};
|
|
2107
|
+
const { idempotencyKey, headers, locale, ...body } = options ?? {};
|
|
2108
|
+
const sent = callLocale(locale, this.clientLocale());
|
|
2039
2109
|
return this.httpClient.fetchPayload(
|
|
2040
2110
|
"/v1/{contentType}",
|
|
2041
2111
|
"post",
|
|
2042
2112
|
{
|
|
2043
2113
|
path: { contentType: this.contentType },
|
|
2044
|
-
body: { content: data, ...body },
|
|
2114
|
+
body: { content: data, ...body, ...sent === void 0 ? {} : { locale: sent } },
|
|
2045
2115
|
headers: requestHeaders(headers, writeHeaders({ idempotencyKey }))
|
|
2046
2116
|
}
|
|
2047
2117
|
);
|
|
@@ -2052,16 +2122,18 @@ var _ContentClient = class _ContentClient {
|
|
|
2052
2122
|
* @param data - Fields to update
|
|
2053
2123
|
* @param options - Update options (slug, locale, parentId, sortOrder), and `headers` this one
|
|
2054
2124
|
* request adds, as for {@link create}. `ifMatch` and `idempotencyKey` win over the same
|
|
2055
|
-
* header among them.
|
|
2125
|
+
* header among them. `locale` defaults to the client's own, the locale whose entity tag
|
|
2126
|
+
* {@link fetchOneWithTag} reads, so the tag it hands back is checked against the same locale.
|
|
2056
2127
|
*/
|
|
2057
2128
|
async update(id, data, options) {
|
|
2058
|
-
const { idempotencyKey, ifMatch, headers, ...body } = options ?? {};
|
|
2129
|
+
const { idempotencyKey, ifMatch, headers, locale, ...body } = options ?? {};
|
|
2130
|
+
const sent = callLocale(locale, this.clientLocale());
|
|
2059
2131
|
return this.httpClient.fetchPayload(
|
|
2060
2132
|
"/v1/{contentType}/{id}",
|
|
2061
2133
|
"patch",
|
|
2062
2134
|
{
|
|
2063
2135
|
path: { contentType: this.contentType, id },
|
|
2064
|
-
body: { content: data, ...body },
|
|
2136
|
+
body: { content: data, ...body, ...sent === void 0 ? {} : { locale: sent } },
|
|
2065
2137
|
headers: requestHeaders(headers, writeHeaders({ idempotencyKey, ifMatch }))
|
|
2066
2138
|
}
|
|
2067
2139
|
);
|
|
@@ -2093,32 +2165,35 @@ var _ContentClient = class _ContentClient {
|
|
|
2093
2165
|
* Get version history for one locale of an entry.
|
|
2094
2166
|
*
|
|
2095
2167
|
* Versions are numbered per locale, so this is one locale's timeline: `locale` defaults to the
|
|
2096
|
-
* schema default
|
|
2097
|
-
* rather than another locale's rows. Every row names the
|
|
2168
|
+
* client's own (`withLocale()`), else the schema default; no fallback is applied, and a locale
|
|
2169
|
+
* with no history returns an empty array rather than another locale's rows. Every row names the
|
|
2170
|
+
* locale it belongs to.
|
|
2098
2171
|
*/
|
|
2099
2172
|
async versions(id, options) {
|
|
2173
|
+
const locale = callLocale(options?.locale, this.clientLocale());
|
|
2100
2174
|
return this.httpClient.fetchPayload("/v1/{contentType}/{id}/versions", "get", {
|
|
2101
2175
|
path: { contentType: this.contentType, id },
|
|
2102
2176
|
query: {
|
|
2103
2177
|
limit: options?.limit ?? 10,
|
|
2104
|
-
...
|
|
2178
|
+
...locale === void 0 ? {} : { locale }
|
|
2105
2179
|
}
|
|
2106
2180
|
});
|
|
2107
2181
|
}
|
|
2108
2182
|
/**
|
|
2109
2183
|
* Get a specific version of an entry.
|
|
2110
2184
|
*
|
|
2111
|
-
* `locale` defaults to the
|
|
2112
|
-
* different content in each one.
|
|
2185
|
+
* `locale` defaults to the client's own (`withLocale()`), else the schema default. Version
|
|
2186
|
+
* numbers are per locale, so version 2 is different content in each one.
|
|
2113
2187
|
*/
|
|
2114
2188
|
async version(id, versionNumber, options) {
|
|
2189
|
+
const locale = callLocale(options?.locale, this.clientLocale());
|
|
2115
2190
|
return this.httpClient.fetchPayload("/v1/{contentType}/{id}/versions/{versionNumber}", "get", {
|
|
2116
2191
|
path: {
|
|
2117
2192
|
contentType: this.contentType,
|
|
2118
2193
|
id,
|
|
2119
2194
|
versionNumber: String(versionNumber)
|
|
2120
2195
|
},
|
|
2121
|
-
query:
|
|
2196
|
+
query: locale === void 0 ? void 0 : { locale }
|
|
2122
2197
|
});
|
|
2123
2198
|
}
|
|
2124
2199
|
/**
|
|
@@ -2157,7 +2232,7 @@ var _ContentClient = class _ContentClient {
|
|
|
2157
2232
|
if (options?.include != null) {
|
|
2158
2233
|
params.include = options.include.join(",");
|
|
2159
2234
|
}
|
|
2160
|
-
const locale = options?.locale ?? this.
|
|
2235
|
+
const locale = options?.locale ?? this.clientLocale();
|
|
2161
2236
|
if (locale != null && locale !== "") {
|
|
2162
2237
|
params.locale = locale;
|
|
2163
2238
|
}
|
|
@@ -2177,19 +2252,20 @@ var _ContentClient = class _ContentClient {
|
|
|
2177
2252
|
* Create a new ContentClient for a different content type
|
|
2178
2253
|
*/
|
|
2179
2254
|
ofType(contentType) {
|
|
2180
|
-
return new _ContentClient(this.httpClient, contentType, this.
|
|
2255
|
+
return new _ContentClient(this.httpClient, contentType, this.clientLocale);
|
|
2181
2256
|
}
|
|
2182
2257
|
/**
|
|
2183
|
-
* Create a new ContentClient with a different default locale
|
|
2258
|
+
* Create a new ContentClient with a different default locale, fixed: an update of the client's
|
|
2259
|
+
* locale (`updateConfig({ locale })`) does not reach it
|
|
2184
2260
|
*/
|
|
2185
2261
|
withLocale(locale) {
|
|
2186
2262
|
return new _ContentClient(this.httpClient, this.contentType, locale);
|
|
2187
2263
|
}
|
|
2188
2264
|
/**
|
|
2189
|
-
* Get the
|
|
2265
|
+
* Get the default locale as it is now: the client's, or the one `withLocale()` fixed
|
|
2190
2266
|
*/
|
|
2191
2267
|
getDefaultLocale() {
|
|
2192
|
-
return this.
|
|
2268
|
+
return this.clientLocale();
|
|
2193
2269
|
}
|
|
2194
2270
|
};
|
|
2195
2271
|
__name(_ContentClient, "ContentClient");
|
|
@@ -2198,7 +2274,7 @@ var ContentClient = _ContentClient;
|
|
|
2198
2274
|
// src/errors/file-errors.ts
|
|
2199
2275
|
var _FileUploadError = class _FileUploadError extends SDKError {
|
|
2200
2276
|
constructor(code, message, options = {}) {
|
|
2201
|
-
super(message, options.statusCode, options.cause, { fileErrorCode: code });
|
|
2277
|
+
super(message, options.statusCode, options.cause, { ...options.context, fileErrorCode: code });
|
|
2202
2278
|
__publicField(this, "code");
|
|
2203
2279
|
__publicField(this, "retryable");
|
|
2204
2280
|
this.code = code;
|
|
@@ -2245,11 +2321,52 @@ function validateFile(file, constraints = {}) {
|
|
|
2245
2321
|
}
|
|
2246
2322
|
__name(validateFile, "validateFile");
|
|
2247
2323
|
|
|
2324
|
+
// src/errors/file-error-codes.ts
|
|
2325
|
+
var FILE_ERROR_CODES = [
|
|
2326
|
+
"UPLOAD_TOO_LARGE",
|
|
2327
|
+
"UNSUPPORTED_MIME",
|
|
2328
|
+
"DIMENSION_OUT_OF_RANGE",
|
|
2329
|
+
"ASPECT_RATIO",
|
|
2330
|
+
"CORRUPT_FILE",
|
|
2331
|
+
"UNSUPPORTED_CODEC",
|
|
2332
|
+
"IMAGES_LIMIT_EXCEEDED",
|
|
2333
|
+
"STREAM_ENCODE_FAILED",
|
|
2334
|
+
"SCAN_INFECTED",
|
|
2335
|
+
"INTERNAL"
|
|
2336
|
+
];
|
|
2337
|
+
|
|
2248
2338
|
// src/content/asset-client.ts
|
|
2339
|
+
function assertWaitOptions(options) {
|
|
2340
|
+
const { timeoutMs, pollIntervalMs } = options;
|
|
2341
|
+
if (timeoutMs !== void 0 && !(typeof timeoutMs === "number" && timeoutMs >= 0 && timeoutMs <= MAX_TIMER_DELAY_MS)) {
|
|
2342
|
+
throw new Error(
|
|
2343
|
+
`timeoutMs must be a number of milliseconds from 0 to ${MAX_TIMER_DELAY_MS}, and got ${String(timeoutMs)}`
|
|
2344
|
+
);
|
|
2345
|
+
}
|
|
2346
|
+
if (pollIntervalMs !== void 0 && !isTimerDelay(pollIntervalMs)) {
|
|
2347
|
+
throw new Error(
|
|
2348
|
+
`pollIntervalMs must be a number of milliseconds from 1 to ${MAX_TIMER_DELAY_MS} \u2014 a timer given 0, NaN, Infinity or more fires at once \u2014 and got ${String(pollIntervalMs)}`
|
|
2349
|
+
);
|
|
2350
|
+
}
|
|
2351
|
+
}
|
|
2352
|
+
__name(assertWaitOptions, "assertWaitOptions");
|
|
2249
2353
|
function hasText(value) {
|
|
2250
2354
|
return value != null && value !== "";
|
|
2251
2355
|
}
|
|
2252
2356
|
__name(hasText, "hasText");
|
|
2357
|
+
function processingFailure(subject, stored) {
|
|
2358
|
+
const storedCode = stored?.code;
|
|
2359
|
+
const code = FILE_ERROR_CODES.find((known) => known === storedCode) ?? "PROCESSING_FAILED";
|
|
2360
|
+
return new FileUploadError(
|
|
2361
|
+
code,
|
|
2362
|
+
`Asset ${subject}: ${stored?.message ?? "File processing failed"}`,
|
|
2363
|
+
{
|
|
2364
|
+
retriable: stored?.retriable === true,
|
|
2365
|
+
context: { processingError: stored }
|
|
2366
|
+
}
|
|
2367
|
+
);
|
|
2368
|
+
}
|
|
2369
|
+
__name(processingFailure, "processingFailure");
|
|
2253
2370
|
async function computeSha256Hex(blob) {
|
|
2254
2371
|
try {
|
|
2255
2372
|
const subtle = globalThis.crypto?.subtle;
|
|
@@ -2265,11 +2382,17 @@ async function computeSha256Hex(blob) {
|
|
|
2265
2382
|
}
|
|
2266
2383
|
__name(computeSha256Hex, "computeSha256Hex");
|
|
2267
2384
|
var _AssetFileBuilder = class _AssetFileBuilder {
|
|
2268
|
-
|
|
2385
|
+
/**
|
|
2386
|
+
* @param locale - The client's locale, sent when a call names none: the function
|
|
2387
|
+
* `TypedRelyIOClient` hands over, or a locale fixed for this builder
|
|
2388
|
+
*/
|
|
2389
|
+
constructor(httpClient, assetType, entryUid, locale) {
|
|
2269
2390
|
this.httpClient = httpClient;
|
|
2270
2391
|
this.assetType = assetType;
|
|
2271
2392
|
this.entryUid = entryUid;
|
|
2272
|
-
this.
|
|
2393
|
+
/** The client's locale, asked on every call rather than copied when this builder was taken. */
|
|
2394
|
+
__publicField(this, "clientLocale");
|
|
2395
|
+
this.clientLocale = readClientLocale(locale);
|
|
2273
2396
|
}
|
|
2274
2397
|
/**
|
|
2275
2398
|
* The path parameters every `/file/*` route on this builder takes.
|
|
@@ -2282,7 +2405,16 @@ var _AssetFileBuilder = class _AssetFileBuilder {
|
|
|
2282
2405
|
return { contentType: this.assetType, id: this.entryUid };
|
|
2283
2406
|
}
|
|
2284
2407
|
withLocale(locale) {
|
|
2285
|
-
return locale ?? this.
|
|
2408
|
+
return locale ?? this.clientLocale();
|
|
2409
|
+
}
|
|
2410
|
+
/**
|
|
2411
|
+
* The `locale` body field of a multipart call: the session's, else the client's. The API finds
|
|
2412
|
+
* the binding by it, so a session a `withLocale()` client opened must name the same locale on
|
|
2413
|
+
* every later call or its `objectKey` is refused as another binding's.
|
|
2414
|
+
*/
|
|
2415
|
+
localeField(locale) {
|
|
2416
|
+
const sent = this.withLocale(locale);
|
|
2417
|
+
return hasText(sent) ? { locale: sent } : {};
|
|
2286
2418
|
}
|
|
2287
2419
|
/**
|
|
2288
2420
|
* Issue a single upload target — an R2 presigned PUT (image/file) or a
|
|
@@ -2341,7 +2473,7 @@ var _AssetFileBuilder = class _AssetFileBuilder {
|
|
|
2341
2473
|
uploadId: target.uploadId,
|
|
2342
2474
|
objectKey: target.objectKey,
|
|
2343
2475
|
partNumber: target.partNumber,
|
|
2344
|
-
...
|
|
2476
|
+
...this.localeField(target.locale)
|
|
2345
2477
|
}
|
|
2346
2478
|
});
|
|
2347
2479
|
}
|
|
@@ -2352,7 +2484,7 @@ var _AssetFileBuilder = class _AssetFileBuilder {
|
|
|
2352
2484
|
body: {
|
|
2353
2485
|
uploadId: target.uploadId,
|
|
2354
2486
|
objectKey: target.objectKey,
|
|
2355
|
-
...
|
|
2487
|
+
...this.localeField(target.locale)
|
|
2356
2488
|
}
|
|
2357
2489
|
});
|
|
2358
2490
|
return payload.parts;
|
|
@@ -2365,7 +2497,7 @@ var _AssetFileBuilder = class _AssetFileBuilder {
|
|
|
2365
2497
|
uploadId: target.uploadId,
|
|
2366
2498
|
objectKey: target.objectKey,
|
|
2367
2499
|
parts: target.parts.map((p) => ({ partNumber: p.partNumber, etag: p.etag })),
|
|
2368
|
-
...
|
|
2500
|
+
...this.localeField(target.locale)
|
|
2369
2501
|
}
|
|
2370
2502
|
});
|
|
2371
2503
|
}
|
|
@@ -2376,7 +2508,7 @@ var _AssetFileBuilder = class _AssetFileBuilder {
|
|
|
2376
2508
|
body: {
|
|
2377
2509
|
uploadId: target.uploadId,
|
|
2378
2510
|
objectKey: target.objectKey,
|
|
2379
|
-
...
|
|
2511
|
+
...this.localeField(target.locale)
|
|
2380
2512
|
}
|
|
2381
2513
|
});
|
|
2382
2514
|
}
|
|
@@ -2396,6 +2528,25 @@ var _AssetFileBuilder = class _AssetFileBuilder {
|
|
|
2396
2528
|
{ path: this.target, query: params }
|
|
2397
2529
|
);
|
|
2398
2530
|
}
|
|
2531
|
+
/**
|
|
2532
|
+
* Read where this file's upload got to — `status`, and the processing stage, progress and error
|
|
2533
|
+
* the pipeline recorded — whatever the asset entry is published in.
|
|
2534
|
+
*
|
|
2535
|
+
* An asset is a draft until its file is ready, and stays one when its file fails, so a key that
|
|
2536
|
+
* reads published content finds no entry for an upload in flight or one that failed. This read
|
|
2537
|
+
* answers for the binding itself. It takes the capability the upload calls take, so a read-only
|
|
2538
|
+
* key is refused with `ReadOnlyKeyError`, and it never returns the entry's fields.
|
|
2539
|
+
*/
|
|
2540
|
+
async status(options = {}) {
|
|
2541
|
+
const params = {};
|
|
2542
|
+
const locale = this.withLocale(options.locale);
|
|
2543
|
+
if (hasText(locale)) params.locale = locale;
|
|
2544
|
+
return this.httpClient.fetchPayload(
|
|
2545
|
+
"/v1/{contentType}/{id}/file",
|
|
2546
|
+
"get",
|
|
2547
|
+
{ path: this.target, query: params }
|
|
2548
|
+
);
|
|
2549
|
+
}
|
|
2399
2550
|
/**
|
|
2400
2551
|
* Update the binding's delivery visibility (token-based; no byte relocation —
|
|
2401
2552
|
* a downgrade purges the gateway cache). Returns the refreshed asset entry.
|
|
@@ -2434,14 +2585,31 @@ var _AssetFileBuilder = class _AssetFileBuilder {
|
|
|
2434
2585
|
});
|
|
2435
2586
|
}
|
|
2436
2587
|
/**
|
|
2437
|
-
* Poll the asset entry until its file binding reaches `ready
|
|
2438
|
-
*
|
|
2588
|
+
* Poll the asset entry until its file binding reaches `ready`, and resolve with the ready entry.
|
|
2589
|
+
*
|
|
2590
|
+
* Each poll reads the entry through the key's lens. When that finds nothing — a key that reads
|
|
2591
|
+
* published content, and an asset that is a draft until its file is ready and stays one when it
|
|
2592
|
+
* fails — the poll reads the binding itself ({@link status}), so a failed upload rejects as one
|
|
2593
|
+
* rather than running out the limit (REL-1481).
|
|
2594
|
+
*
|
|
2595
|
+
* @throws {FileUploadError} When processing failed. `code` is the processing code the service
|
|
2596
|
+
* stored — `UNSUPPORTED_CODEC`, `CORRUPT_FILE` and so on — or `PROCESSING_FAILED` where it
|
|
2597
|
+
* stored none this SDK knows; `context.processingError` holds what it stored, and `retryable`
|
|
2598
|
+
* is its `retriable` hint.
|
|
2599
|
+
* @throws {TimeoutError} When `timeoutMs` passes first. The file may still become ready; the
|
|
2600
|
+
* error's `context.timeout` is the limit and `context.fileStatus` the status last seen. A file
|
|
2601
|
+
* that is `ready` in an asset the key's lens never shows — created with `publish: false`, or
|
|
2602
|
+
* awaiting a workflow — ends here too, and the message says so.
|
|
2603
|
+
* @throws {ReadOnlyKeyError} When the key's lens does not show the asset and the key may not read
|
|
2604
|
+
* its binding either: nothing it can read would ever report the file.
|
|
2439
2605
|
*/
|
|
2440
2606
|
async waitUntilReady(options = {}) {
|
|
2607
|
+
assertWaitOptions(options);
|
|
2441
2608
|
const timeoutMs = options.timeoutMs ?? 6e4;
|
|
2442
2609
|
const pollIntervalMs = options.pollIntervalMs ?? 1500;
|
|
2443
2610
|
const locale = this.withLocale(options.locale);
|
|
2444
2611
|
const deadline = Date.now() + timeoutMs;
|
|
2612
|
+
const subject = `${this.assetType}/${this.entryUid}`;
|
|
2445
2613
|
for (; ; ) {
|
|
2446
2614
|
const builder = new ContentByIdBuilder(
|
|
2447
2615
|
this.httpClient,
|
|
@@ -2451,15 +2619,24 @@ var _AssetFileBuilder = class _AssetFileBuilder {
|
|
|
2451
2619
|
);
|
|
2452
2620
|
if (hasText(locale)) builder.locale(locale);
|
|
2453
2621
|
const entry = await builder.execute();
|
|
2454
|
-
|
|
2455
|
-
if (entry
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
throw
|
|
2622
|
+
let status;
|
|
2623
|
+
if (entry === null) {
|
|
2624
|
+
const binding = await this.status({ ...hasText(locale) ? { locale } : {} });
|
|
2625
|
+
status = binding.status;
|
|
2626
|
+
if (status === "failed") throw processingFailure(subject, binding.processing?.error);
|
|
2627
|
+
} else {
|
|
2628
|
+
status = entry.file?.status;
|
|
2629
|
+
if (status === "ready") return entry;
|
|
2630
|
+
if (status === "failed") throw processingFailure(subject, entry.file?.processing?.error);
|
|
2459
2631
|
}
|
|
2460
2632
|
if (Date.now() >= deadline) {
|
|
2461
|
-
|
|
2462
|
-
|
|
2633
|
+
const unseen = entry === null && status === "ready" ? "; the file is ready and this key's lens does not show the asset \u2014 it is not published" : "";
|
|
2634
|
+
throw new TimeoutError(
|
|
2635
|
+
`Timed out after ${timeoutMs}ms waiting for ${subject} (status: ${status ?? "unknown"})${unseen}`,
|
|
2636
|
+
timeoutMs,
|
|
2637
|
+
void 0,
|
|
2638
|
+
void 0,
|
|
2639
|
+
{ fileStatus: status }
|
|
2463
2640
|
);
|
|
2464
2641
|
}
|
|
2465
2642
|
await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
|
|
@@ -2469,11 +2646,14 @@ var _AssetFileBuilder = class _AssetFileBuilder {
|
|
|
2469
2646
|
__name(_AssetFileBuilder, "AssetFileBuilder");
|
|
2470
2647
|
var AssetFileBuilder = _AssetFileBuilder;
|
|
2471
2648
|
var _AssetUploadBuilder = class _AssetUploadBuilder {
|
|
2472
|
-
|
|
2649
|
+
/**
|
|
2650
|
+
* @param locale - The client's locale, the upload's when `.locale()` names none: the function
|
|
2651
|
+
* `TypedRelyIOClient` hands over, or a locale fixed for this upload
|
|
2652
|
+
*/
|
|
2653
|
+
constructor(httpClient, assetType, file, locale) {
|
|
2473
2654
|
this.httpClient = httpClient;
|
|
2474
2655
|
this.assetType = assetType;
|
|
2475
2656
|
this.file = file;
|
|
2476
|
-
this.defaultLocale = defaultLocale;
|
|
2477
2657
|
__publicField(this, "_fileName");
|
|
2478
2658
|
__publicField(this, "_visibility");
|
|
2479
2659
|
__publicField(this, "_locale");
|
|
@@ -2485,6 +2665,9 @@ var _AssetUploadBuilder = class _AssetUploadBuilder {
|
|
|
2485
2665
|
__publicField(this, "_onProgress");
|
|
2486
2666
|
__publicField(this, "_validate");
|
|
2487
2667
|
__publicField(this, "_maxPartRetries", 3);
|
|
2668
|
+
/** The client's locale, read once when the upload starts. */
|
|
2669
|
+
__publicField(this, "clientLocale");
|
|
2670
|
+
this.clientLocale = readClientLocale(locale);
|
|
2488
2671
|
}
|
|
2489
2672
|
/** Subscribe to client → storage upload progress (single PUT + multipart). */
|
|
2490
2673
|
onProgress(callback) {
|
|
@@ -2534,8 +2717,14 @@ var _AssetUploadBuilder = class _AssetUploadBuilder {
|
|
|
2534
2717
|
this._slug = slug;
|
|
2535
2718
|
return this;
|
|
2536
2719
|
}
|
|
2537
|
-
/**
|
|
2720
|
+
/**
|
|
2721
|
+
* Wait until the file binding becomes `ready` before resolving.
|
|
2722
|
+
*
|
|
2723
|
+
* @throws {Error} When `timeoutMs` or `pollIntervalMs` is one the wait cannot honour — refused
|
|
2724
|
+
* here, before anything is uploaded, rather than after the bytes are in.
|
|
2725
|
+
*/
|
|
2538
2726
|
waitForReady(options = true) {
|
|
2727
|
+
if (typeof options === "object") assertWaitOptions(options);
|
|
2539
2728
|
if (options === false) {
|
|
2540
2729
|
this._waitForReady = false;
|
|
2541
2730
|
} else {
|
|
@@ -2550,7 +2739,8 @@ var _AssetUploadBuilder = class _AssetUploadBuilder {
|
|
|
2550
2739
|
if (!fileName) {
|
|
2551
2740
|
throw new Error('A file name is required: pass a File, or call .filename("name.ext")');
|
|
2552
2741
|
}
|
|
2553
|
-
const
|
|
2742
|
+
const clientLocale = this.clientLocale();
|
|
2743
|
+
const locale = this._locale ?? clientLocale;
|
|
2554
2744
|
if (this._validate) {
|
|
2555
2745
|
const violations = validateFile(this.file, this._validate);
|
|
2556
2746
|
if (violations.length > 0) {
|
|
@@ -2561,7 +2751,7 @@ var _AssetUploadBuilder = class _AssetUploadBuilder {
|
|
|
2561
2751
|
}
|
|
2562
2752
|
}
|
|
2563
2753
|
const hash = await computeSha256Hex(this.file);
|
|
2564
|
-
const client = new AssetClient(this.httpClient, this.assetType,
|
|
2754
|
+
const client = new AssetClient(this.httpClient, this.assetType, clientLocale);
|
|
2565
2755
|
const created = await client.create(this._content, {
|
|
2566
2756
|
...hasText(this._slug) ? { slug: this._slug } : {},
|
|
2567
2757
|
...hasText(locale) ? { locale } : {},
|
|
@@ -2712,17 +2902,26 @@ var _AssetUploadBuilder = class _AssetUploadBuilder {
|
|
|
2712
2902
|
__name(_AssetUploadBuilder, "AssetUploadBuilder");
|
|
2713
2903
|
var AssetUploadBuilder = _AssetUploadBuilder;
|
|
2714
2904
|
var _AssetClient = class _AssetClient {
|
|
2715
|
-
|
|
2905
|
+
/**
|
|
2906
|
+
* @param locale - The client's locale: the function `TypedRelyIOClient` hands over, asked on
|
|
2907
|
+
* every call, or a locale fixed for this client
|
|
2908
|
+
*/
|
|
2909
|
+
constructor(httpClient, assetType, locale) {
|
|
2716
2910
|
this.httpClient = httpClient;
|
|
2717
2911
|
this.assetType = assetType;
|
|
2718
|
-
this.
|
|
2912
|
+
/** The client's locale, asked on every call rather than copied when this client was taken. */
|
|
2913
|
+
__publicField(this, "clientLocale");
|
|
2914
|
+
this.clientLocale = readClientLocale(locale);
|
|
2719
2915
|
}
|
|
2720
|
-
/**
|
|
2916
|
+
/**
|
|
2917
|
+
* Create a query builder for this asset type. It resolves asset reads; its conditions name the
|
|
2918
|
+
* asset type's fields, which the `file` and `urls` blocks are not.
|
|
2919
|
+
*/
|
|
2721
2920
|
query() {
|
|
2722
2921
|
return new ContentQueryBuilder(
|
|
2723
2922
|
this.httpClient,
|
|
2724
2923
|
this.assetType,
|
|
2725
|
-
this.
|
|
2924
|
+
this.clientLocale
|
|
2726
2925
|
);
|
|
2727
2926
|
}
|
|
2728
2927
|
/** Find an asset entry by id (or slug) with fluent options. */
|
|
@@ -2731,7 +2930,7 @@ var _AssetClient = class _AssetClient {
|
|
|
2731
2930
|
this.httpClient,
|
|
2732
2931
|
this.assetType,
|
|
2733
2932
|
id,
|
|
2734
|
-
this.
|
|
2933
|
+
this.clientLocale
|
|
2735
2934
|
);
|
|
2736
2935
|
}
|
|
2737
2936
|
/** Fetch a single asset entry by id (or slug), or `null` if not found. */
|
|
@@ -2752,28 +2951,34 @@ var _AssetClient = class _AssetClient {
|
|
|
2752
2951
|
* Create a new asset entry as a draft. The binary is uploaded separately via
|
|
2753
2952
|
* `file(uid)` (or use the high-level `upload()` helper), and the entry
|
|
2754
2953
|
* auto-publishes when its file becomes ready (unless `publish: false`).
|
|
2954
|
+
* `locale` defaults to the client's own (`withLocale()`).
|
|
2755
2955
|
*/
|
|
2756
2956
|
async create(data, options) {
|
|
2757
|
-
const { idempotencyKey, ...rest } = options ?? {};
|
|
2957
|
+
const { idempotencyKey, locale, ...rest } = options ?? {};
|
|
2958
|
+
const sent = callLocale(locale, this.clientLocale());
|
|
2758
2959
|
return this.httpClient.fetchPayload(
|
|
2759
2960
|
"/v1/{contentType}",
|
|
2760
2961
|
"post",
|
|
2761
2962
|
{
|
|
2762
2963
|
path: { contentType: this.assetType },
|
|
2763
|
-
body: { content: data, ...rest },
|
|
2964
|
+
body: { content: data, ...rest, ...sent === void 0 ? {} : { locale: sent } },
|
|
2764
2965
|
headers: writeHeaders({ idempotencyKey })
|
|
2765
2966
|
}
|
|
2766
2967
|
);
|
|
2767
2968
|
}
|
|
2768
|
-
/**
|
|
2969
|
+
/**
|
|
2970
|
+
* Update an asset entry's metadata fields (and/or slug). `locale` defaults to the client's own
|
|
2971
|
+
* (`withLocale()`).
|
|
2972
|
+
*/
|
|
2769
2973
|
async update(id, data, options) {
|
|
2770
|
-
const { idempotencyKey, ifMatch, ...rest } = options ?? {};
|
|
2974
|
+
const { idempotencyKey, ifMatch, locale, ...rest } = options ?? {};
|
|
2975
|
+
const sent = callLocale(locale, this.clientLocale());
|
|
2771
2976
|
return this.httpClient.fetchPayload(
|
|
2772
2977
|
"/v1/{contentType}/{id}",
|
|
2773
2978
|
"patch",
|
|
2774
2979
|
{
|
|
2775
2980
|
path: { contentType: this.assetType, id },
|
|
2776
|
-
body: { content: data, ...rest },
|
|
2981
|
+
body: { content: data, ...rest, ...sent === void 0 ? {} : { locale: sent } },
|
|
2777
2982
|
headers: writeHeaders({ idempotencyKey, ifMatch })
|
|
2778
2983
|
}
|
|
2779
2984
|
);
|
|
@@ -2787,21 +2992,24 @@ var _AssetClient = class _AssetClient {
|
|
|
2787
2992
|
}
|
|
2788
2993
|
/** Get the file sub-resource builder for a specific asset entry. */
|
|
2789
2994
|
file(entryUid) {
|
|
2790
|
-
return new AssetFileBuilder(this.httpClient, this.assetType, entryUid, this.
|
|
2995
|
+
return new AssetFileBuilder(this.httpClient, this.assetType, entryUid, this.clientLocale);
|
|
2791
2996
|
}
|
|
2792
2997
|
/** Start a high-level upload (create → presign → PUT → confirm). */
|
|
2793
2998
|
upload(file) {
|
|
2794
|
-
return new AssetUploadBuilder(this.httpClient, this.assetType, file, this.
|
|
2999
|
+
return new AssetUploadBuilder(this.httpClient, this.assetType, file, this.clientLocale);
|
|
2795
3000
|
}
|
|
2796
3001
|
/** Get the asset type id. */
|
|
2797
3002
|
getAssetType() {
|
|
2798
3003
|
return this.assetType;
|
|
2799
3004
|
}
|
|
2800
|
-
/** Get the
|
|
3005
|
+
/** Get the default locale as it is now: the client's, or the one `withLocale()` fixed. */
|
|
2801
3006
|
getDefaultLocale() {
|
|
2802
|
-
return this.
|
|
3007
|
+
return this.clientLocale();
|
|
2803
3008
|
}
|
|
2804
|
-
/**
|
|
3009
|
+
/**
|
|
3010
|
+
* Create a new AssetClient for this type with a different default locale, fixed: an update of the
|
|
3011
|
+
* client's locale (`updateConfig({ locale })`) does not reach it.
|
|
3012
|
+
*/
|
|
2805
3013
|
withLocale(locale) {
|
|
2806
3014
|
return new _AssetClient(this.httpClient, this.assetType, locale);
|
|
2807
3015
|
}
|
|
@@ -2817,12 +3025,18 @@ __name(isAssetEntry, "isAssetEntry");
|
|
|
2817
3025
|
|
|
2818
3026
|
// src/content/singleton-client.ts
|
|
2819
3027
|
var _SingletonClient = class _SingletonClient {
|
|
2820
|
-
|
|
3028
|
+
/**
|
|
3029
|
+
* @param locale - The client's locale: the function `TypedRelyIOClient` hands over, asked on
|
|
3030
|
+
* every call, or a locale fixed for this client
|
|
3031
|
+
*/
|
|
3032
|
+
constructor(httpClient, singletonKey, locale) {
|
|
2821
3033
|
this.httpClient = httpClient;
|
|
2822
3034
|
this.singletonKey = singletonKey;
|
|
2823
|
-
this.defaultLocale = defaultLocale;
|
|
2824
3035
|
__publicField(this, "includeFields");
|
|
2825
3036
|
__publicField(this, "localeValue");
|
|
3037
|
+
/** The client's locale, asked on every call rather than copied when this client was taken. */
|
|
3038
|
+
__publicField(this, "clientLocale");
|
|
3039
|
+
this.clientLocale = readClientLocale(locale);
|
|
2826
3040
|
}
|
|
2827
3041
|
/**
|
|
2828
3042
|
* Include reference fields in the response
|
|
@@ -2862,7 +3076,7 @@ var _SingletonClient = class _SingletonClient {
|
|
|
2862
3076
|
async fetchWithTag(options) {
|
|
2863
3077
|
const query = {};
|
|
2864
3078
|
const includeValue = options?.include ?? this.includeFields;
|
|
2865
|
-
const localeValueFinal = options?.locale ?? this.localeValue ?? this.
|
|
3079
|
+
const localeValueFinal = options?.locale ?? this.localeValue ?? this.clientLocale();
|
|
2866
3080
|
if (includeValue) query.include = includeValue.join(",");
|
|
2867
3081
|
if (localeValueFinal != null && localeValueFinal !== "") query.locale = localeValueFinal;
|
|
2868
3082
|
const response = await this.httpClient.send(
|
|
@@ -2876,11 +3090,12 @@ var _SingletonClient = class _SingletonClient {
|
|
|
2876
3090
|
* Update singleton content. The API auto-publishes on PATCH — there is no
|
|
2877
3091
|
* separate publish route; calling `update()` writes and publishes.
|
|
2878
3092
|
* @param data - The content fields to update
|
|
2879
|
-
* @param locale - Optional locale for localized content (overrides fluent locale
|
|
3093
|
+
* @param locale - Optional locale for localized content (overrides the fluent locale, which
|
|
3094
|
+
* overrides the client's own)
|
|
2880
3095
|
* @param options - `If-Match` / `Idempotency-Key`, both declared on this route
|
|
2881
3096
|
*/
|
|
2882
3097
|
async update(data, locale, options) {
|
|
2883
|
-
const finalLocale =
|
|
3098
|
+
const finalLocale = this.localeOf(locale);
|
|
2884
3099
|
return this.httpClient.fetchPayload(
|
|
2885
3100
|
"/v1/singletons/{key}",
|
|
2886
3101
|
"patch",
|
|
@@ -2909,15 +3124,17 @@ var _SingletonClient = class _SingletonClient {
|
|
|
2909
3124
|
* Get version history for one locale of the singleton.
|
|
2910
3125
|
*
|
|
2911
3126
|
* Versions are numbered per locale, so this is one locale's timeline: `locale` defaults to the
|
|
2912
|
-
*
|
|
2913
|
-
*
|
|
3127
|
+
* fluent `.locale()`, then the client's own (`withLocale()`), then the schema default; no
|
|
3128
|
+
* fallback is applied, and a locale with no history returns an empty array rather than another
|
|
3129
|
+
* locale's rows. Every row names the locale it belongs to.
|
|
2914
3130
|
*/
|
|
2915
3131
|
async versions(options) {
|
|
3132
|
+
const locale = this.localeOf(options?.locale);
|
|
2916
3133
|
const payload = await this.httpClient.fetchPayload("/v1/singletons/{key}/versions", "get", {
|
|
2917
3134
|
path: { key: this.singletonKey },
|
|
2918
3135
|
query: {
|
|
2919
3136
|
limit: options?.limit ?? 10,
|
|
2920
|
-
...
|
|
3137
|
+
...locale === void 0 ? {} : { locale }
|
|
2921
3138
|
}
|
|
2922
3139
|
});
|
|
2923
3140
|
return payload.versions;
|
|
@@ -2925,20 +3142,25 @@ var _SingletonClient = class _SingletonClient {
|
|
|
2925
3142
|
/**
|
|
2926
3143
|
* Get a specific version of the singleton.
|
|
2927
3144
|
*
|
|
2928
|
-
* `locale` defaults to the
|
|
2929
|
-
* different content in each one.
|
|
3145
|
+
* `locale` defaults to the fluent `.locale()`, then the client's own (`withLocale()`), then the
|
|
3146
|
+
* schema default. Version numbers are per locale, so version 2 is different content in each one.
|
|
2930
3147
|
*/
|
|
2931
3148
|
async version(versionNumber, options) {
|
|
3149
|
+
const locale = this.localeOf(options?.locale);
|
|
2932
3150
|
try {
|
|
2933
3151
|
return await this.httpClient.fetchPayload("/v1/singletons/{key}/versions/{versionNumber}", "get", {
|
|
2934
3152
|
path: { key: this.singletonKey, versionNumber: String(versionNumber) },
|
|
2935
|
-
query:
|
|
3153
|
+
query: locale === void 0 ? void 0 : { locale }
|
|
2936
3154
|
});
|
|
2937
3155
|
} catch (error) {
|
|
2938
3156
|
if (isResourceNotFound(error)) return null;
|
|
2939
3157
|
throw error;
|
|
2940
3158
|
}
|
|
2941
3159
|
}
|
|
3160
|
+
/** The locale a write or history read sends: the call's, the fluent one, else the client's. */
|
|
3161
|
+
localeOf(named) {
|
|
3162
|
+
return callLocale(named ?? this.localeValue, this.clientLocale());
|
|
3163
|
+
}
|
|
2942
3164
|
/**
|
|
2943
3165
|
* Get the singleton key
|
|
2944
3166
|
*/
|
|
@@ -2959,12 +3181,18 @@ var SingletonClient = _SingletonClient;
|
|
|
2959
3181
|
|
|
2960
3182
|
// src/content/settings-client.ts
|
|
2961
3183
|
var _SettingsClient = class _SettingsClient {
|
|
2962
|
-
|
|
3184
|
+
/**
|
|
3185
|
+
* @param locale - The client's locale: the function `TypedRelyIOClient` hands over, asked on
|
|
3186
|
+
* every call, or a locale fixed for this client
|
|
3187
|
+
*/
|
|
3188
|
+
constructor(httpClient, groupId, locale) {
|
|
2963
3189
|
this.httpClient = httpClient;
|
|
2964
3190
|
this.groupId = groupId;
|
|
2965
|
-
this.defaultLocale = defaultLocale;
|
|
2966
3191
|
__publicField(this, "includeFields");
|
|
2967
3192
|
__publicField(this, "localeValue");
|
|
3193
|
+
/** The client's locale, asked on every call rather than copied when this client was taken. */
|
|
3194
|
+
__publicField(this, "clientLocale");
|
|
3195
|
+
this.clientLocale = readClientLocale(locale);
|
|
2968
3196
|
}
|
|
2969
3197
|
/**
|
|
2970
3198
|
* Include reference fields in the response
|
|
@@ -2996,12 +3224,20 @@ var _SettingsClient = class _SettingsClient {
|
|
|
2996
3224
|
}
|
|
2997
3225
|
/**
|
|
2998
3226
|
* Update settings group
|
|
3227
|
+
*
|
|
3228
|
+
* The fields travel as `content` beside an optional `locale`, the body the route validates
|
|
3229
|
+
* (`UpdateSettingsDto`); any other top-level key is refused `REQUEST_INVALID`.
|
|
3230
|
+
*
|
|
2999
3231
|
* @param settings - The settings fields to update
|
|
3000
|
-
* @param locale - Optional locale for localized settings (overrides fluent locale
|
|
3232
|
+
* @param locale - Optional locale for localized settings (overrides the fluent locale, which
|
|
3233
|
+
* overrides the client's own)
|
|
3001
3234
|
*/
|
|
3002
3235
|
async update(settings, locale, options) {
|
|
3003
|
-
const finalLocale =
|
|
3004
|
-
const body =
|
|
3236
|
+
const finalLocale = this.localeOf(locale);
|
|
3237
|
+
const body = {
|
|
3238
|
+
content: settings,
|
|
3239
|
+
...finalLocale != null && finalLocale !== "" ? { locale: finalLocale } : {}
|
|
3240
|
+
};
|
|
3005
3241
|
return this.httpClient.fetchPayload(
|
|
3006
3242
|
"/v1/settings/{groupId}",
|
|
3007
3243
|
"patch",
|
|
@@ -3016,7 +3252,7 @@ var _SettingsClient = class _SettingsClient {
|
|
|
3016
3252
|
async fetchWithTag(options) {
|
|
3017
3253
|
const query = {};
|
|
3018
3254
|
const includeValue = options?.include ?? this.includeFields;
|
|
3019
|
-
const localeValueFinal = options?.locale ?? this.localeValue ?? this.
|
|
3255
|
+
const localeValueFinal = options?.locale ?? this.localeValue ?? this.clientLocale();
|
|
3020
3256
|
if (includeValue) query.include = includeValue.join(",");
|
|
3021
3257
|
if (localeValueFinal != null && localeValueFinal !== "") query.locale = localeValueFinal;
|
|
3022
3258
|
const response = await this.httpClient.send(
|
|
@@ -3028,16 +3264,20 @@ var _SettingsClient = class _SettingsClient {
|
|
|
3028
3264
|
}
|
|
3029
3265
|
/**
|
|
3030
3266
|
* Reset settings to default values
|
|
3031
|
-
*
|
|
3267
|
+
*
|
|
3268
|
+
* The route reads its locale from `?locale=` and takes no body, so that is where it is sent.
|
|
3269
|
+
*
|
|
3270
|
+
* @param locale - Optional locale for localized settings (overrides the fluent locale, which
|
|
3271
|
+
* overrides the client's own)
|
|
3032
3272
|
*/
|
|
3033
3273
|
async reset(locale, options) {
|
|
3034
|
-
const finalLocale =
|
|
3274
|
+
const finalLocale = this.localeOf(locale);
|
|
3035
3275
|
return this.httpClient.fetchPayload(
|
|
3036
3276
|
"/v1/settings/{groupId}/reset",
|
|
3037
3277
|
"post",
|
|
3038
3278
|
{
|
|
3039
3279
|
path: { groupId: this.groupId },
|
|
3040
|
-
|
|
3280
|
+
query: finalLocale != null && finalLocale !== "" ? { locale: finalLocale } : void 0,
|
|
3041
3281
|
headers: writeHeaders(options)
|
|
3042
3282
|
}
|
|
3043
3283
|
);
|
|
@@ -3068,15 +3308,17 @@ var _SettingsClient = class _SettingsClient {
|
|
|
3068
3308
|
* Get version history for one locale of the settings group.
|
|
3069
3309
|
*
|
|
3070
3310
|
* Versions are numbered per locale, so this is one locale's timeline: `locale` defaults to the
|
|
3071
|
-
*
|
|
3072
|
-
*
|
|
3311
|
+
* fluent `.locale()`, then the client's own (`withLocale()`), then the schema default; no
|
|
3312
|
+
* fallback is applied, and a locale with no history returns an empty array rather than another
|
|
3313
|
+
* locale's rows. Every row names the locale it belongs to.
|
|
3073
3314
|
*/
|
|
3074
3315
|
async versions(options) {
|
|
3316
|
+
const locale = this.localeOf(options?.locale);
|
|
3075
3317
|
const payload = await this.httpClient.fetchPayload("/v1/settings/{groupId}/versions", "get", {
|
|
3076
3318
|
path: { groupId: this.groupId },
|
|
3077
3319
|
query: {
|
|
3078
3320
|
limit: options?.limit ?? 10,
|
|
3079
|
-
...
|
|
3321
|
+
...locale === void 0 ? {} : { locale }
|
|
3080
3322
|
}
|
|
3081
3323
|
});
|
|
3082
3324
|
return payload.versions;
|
|
@@ -3084,20 +3326,25 @@ var _SettingsClient = class _SettingsClient {
|
|
|
3084
3326
|
/**
|
|
3085
3327
|
* Get a specific version of the settings.
|
|
3086
3328
|
*
|
|
3087
|
-
* `locale` defaults to the
|
|
3088
|
-
* different content in each one.
|
|
3329
|
+
* `locale` defaults to the fluent `.locale()`, then the client's own (`withLocale()`), then the
|
|
3330
|
+
* schema default. Version numbers are per locale, so version 2 is different content in each one.
|
|
3089
3331
|
*/
|
|
3090
3332
|
async version(versionNumber, options) {
|
|
3333
|
+
const locale = this.localeOf(options?.locale);
|
|
3091
3334
|
try {
|
|
3092
3335
|
return await this.httpClient.fetchPayload("/v1/settings/{groupId}/versions/{versionNumber}", "get", {
|
|
3093
3336
|
path: { groupId: this.groupId, versionNumber: String(versionNumber) },
|
|
3094
|
-
query:
|
|
3337
|
+
query: locale === void 0 ? void 0 : { locale }
|
|
3095
3338
|
});
|
|
3096
3339
|
} catch (error) {
|
|
3097
3340
|
if (isResourceNotFound(error)) return null;
|
|
3098
3341
|
throw error;
|
|
3099
3342
|
}
|
|
3100
3343
|
}
|
|
3344
|
+
/** The locale a write or history read sends: the call's, the fluent one, else the client's. */
|
|
3345
|
+
localeOf(named) {
|
|
3346
|
+
return callLocale(named ?? this.localeValue, this.clientLocale());
|
|
3347
|
+
}
|
|
3101
3348
|
/**
|
|
3102
3349
|
* Get the settings group ID
|
|
3103
3350
|
*/
|
|
@@ -3119,15 +3366,18 @@ var SettingsClient = _SettingsClient;
|
|
|
3119
3366
|
// src/search/search-client.ts
|
|
3120
3367
|
var _SearchBuilder = class _SearchBuilder {
|
|
3121
3368
|
/**
|
|
3122
|
-
* @param
|
|
3369
|
+
* @param locale - The client's locale (`withLocale()`, `updateConfig({ locale })`), sent when
|
|
3370
|
+
* `.locale()` names none: the function `TypedRelyIOClient` hands over, or a locale fixed for it
|
|
3123
3371
|
*/
|
|
3124
|
-
constructor(httpClient, query,
|
|
3372
|
+
constructor(httpClient, query, locale) {
|
|
3125
3373
|
this.httpClient = httpClient;
|
|
3126
|
-
this.defaultLocale = defaultLocale;
|
|
3127
3374
|
__publicField(this, "query");
|
|
3128
3375
|
__publicField(this, "searchOptions", {});
|
|
3129
3376
|
__publicField(this, "requestHeaders");
|
|
3377
|
+
/** The client's locale, asked when the query is sent rather than copied when it was built. */
|
|
3378
|
+
__publicField(this, "clientLocale");
|
|
3130
3379
|
this.query = query;
|
|
3380
|
+
this.clientLocale = readClientLocale(locale);
|
|
3131
3381
|
}
|
|
3132
3382
|
/**
|
|
3133
3383
|
* Headers this search adds to the client's own, e.g. `X-RelyIO-Dataset` to search another
|
|
@@ -3158,10 +3408,12 @@ var _SearchBuilder = class _SearchBuilder {
|
|
|
3158
3408
|
return this;
|
|
3159
3409
|
}
|
|
3160
3410
|
/**
|
|
3161
|
-
* Add filter conditions
|
|
3411
|
+
* Add filter conditions, on the fields the content types declare. A condition on `_metadata` is
|
|
3412
|
+
* refused here, before anything is sent.
|
|
3162
3413
|
* @param conditions - Filter conditions
|
|
3163
3414
|
*/
|
|
3164
3415
|
where(conditions) {
|
|
3416
|
+
refuseMetadataConditions(conditions);
|
|
3165
3417
|
this.searchOptions.where = {
|
|
3166
3418
|
...this.searchOptions.where,
|
|
3167
3419
|
...conditions
|
|
@@ -3269,7 +3521,7 @@ var _SearchBuilder = class _SearchBuilder {
|
|
|
3269
3521
|
if (this.searchOptions.explain === true) {
|
|
3270
3522
|
body.explain = true;
|
|
3271
3523
|
}
|
|
3272
|
-
const locale = this.searchOptions.locale ?? this.
|
|
3524
|
+
const locale = this.searchOptions.locale ?? this.clientLocale();
|
|
3273
3525
|
if (locale != null && locale !== "") {
|
|
3274
3526
|
body.locale = locale;
|
|
3275
3527
|
}
|
|
@@ -3297,14 +3549,17 @@ __name(_SearchBuilder, "SearchBuilder");
|
|
|
3297
3549
|
var SearchBuilder = _SearchBuilder;
|
|
3298
3550
|
var _AutocompleteBuilder = class _AutocompleteBuilder {
|
|
3299
3551
|
/**
|
|
3300
|
-
* @param
|
|
3552
|
+
* @param locale - The client's locale (`withLocale()`, `updateConfig({ locale })`), sent when
|
|
3553
|
+
* `.locale()` names none: the function `TypedRelyIOClient` hands over, or a locale fixed for it
|
|
3301
3554
|
*/
|
|
3302
|
-
constructor(httpClient, query,
|
|
3555
|
+
constructor(httpClient, query, locale) {
|
|
3303
3556
|
this.httpClient = httpClient;
|
|
3304
|
-
this.defaultLocale = defaultLocale;
|
|
3305
3557
|
__publicField(this, "query");
|
|
3306
3558
|
__publicField(this, "autocompleteOptions", {});
|
|
3559
|
+
/** The client's locale, asked when the query is sent rather than copied when it was built. */
|
|
3560
|
+
__publicField(this, "clientLocale");
|
|
3307
3561
|
this.query = query;
|
|
3562
|
+
this.clientLocale = readClientLocale(locale);
|
|
3308
3563
|
}
|
|
3309
3564
|
/**
|
|
3310
3565
|
* Autocomplete within a content type
|
|
@@ -3330,10 +3585,12 @@ var _AutocompleteBuilder = class _AutocompleteBuilder {
|
|
|
3330
3585
|
return this;
|
|
3331
3586
|
}
|
|
3332
3587
|
/**
|
|
3333
|
-
* Add filter conditions
|
|
3588
|
+
* Add filter conditions, on the fields the content types declare. A condition on `_metadata` is
|
|
3589
|
+
* refused here, before anything is sent.
|
|
3334
3590
|
* @param conditions - Filter conditions
|
|
3335
3591
|
*/
|
|
3336
3592
|
where(conditions) {
|
|
3593
|
+
refuseMetadataConditions(conditions);
|
|
3337
3594
|
this.autocompleteOptions.where = {
|
|
3338
3595
|
...this.autocompleteOptions.where,
|
|
3339
3596
|
...conditions
|
|
@@ -3380,7 +3637,7 @@ var _AutocompleteBuilder = class _AutocompleteBuilder {
|
|
|
3380
3637
|
if (this.autocompleteOptions.limit !== void 0) {
|
|
3381
3638
|
body.limit = this.autocompleteOptions.limit;
|
|
3382
3639
|
}
|
|
3383
|
-
const locale = this.autocompleteOptions.locale ?? this.
|
|
3640
|
+
const locale = this.autocompleteOptions.locale ?? this.clientLocale();
|
|
3384
3641
|
if (locale != null && locale !== "") {
|
|
3385
3642
|
body.locale = locale;
|
|
3386
3643
|
}
|
|
@@ -3398,15 +3655,18 @@ __name(_AutocompleteBuilder, "AutocompleteBuilder");
|
|
|
3398
3655
|
var AutocompleteBuilder = _AutocompleteBuilder;
|
|
3399
3656
|
var _SimilarBuilder = class _SimilarBuilder {
|
|
3400
3657
|
/**
|
|
3401
|
-
* @param
|
|
3658
|
+
* @param locale - The client's locale (`withLocale()`, `updateConfig({ locale })`), sent when
|
|
3659
|
+
* `.locale()` names none: the function `TypedRelyIOClient` hands over, or a locale fixed for it
|
|
3402
3660
|
*/
|
|
3403
|
-
constructor(httpClient, sourceId,
|
|
3661
|
+
constructor(httpClient, sourceId, locale) {
|
|
3404
3662
|
this.httpClient = httpClient;
|
|
3405
|
-
this.defaultLocale = defaultLocale;
|
|
3406
3663
|
__publicField(this, "sourceId");
|
|
3407
3664
|
__publicField(this, "similarOptions", {});
|
|
3408
3665
|
__publicField(this, "requestHeaders");
|
|
3666
|
+
/** The client's locale, asked when the read is sent rather than copied when it was built. */
|
|
3667
|
+
__publicField(this, "clientLocale");
|
|
3409
3668
|
this.sourceId = sourceId;
|
|
3669
|
+
this.clientLocale = readClientLocale(locale);
|
|
3410
3670
|
}
|
|
3411
3671
|
/**
|
|
3412
3672
|
* Headers this read adds to the client's own, e.g. `X-RelyIO-Dataset` to read another dataset
|
|
@@ -3434,17 +3694,12 @@ var _SimilarBuilder = class _SimilarBuilder {
|
|
|
3434
3694
|
this.similarOptions.contentType = void 0;
|
|
3435
3695
|
return this;
|
|
3436
3696
|
}
|
|
3437
|
-
|
|
3438
|
-
*
|
|
3439
|
-
*
|
|
3697
|
+
/*
|
|
3698
|
+
* No `where()` (REL-1452). Similar ranks from the source entry's stored vector, and the vector
|
|
3699
|
+
* index can pre-filter by content type and locale only — never by an entry field. The API used to
|
|
3700
|
+
* accept `where` here and apply nothing; it now refuses the property, so the builder does not
|
|
3701
|
+
* offer a filter that cannot be honoured. Narrow with `.in()`, `.across()` and `.locale()`.
|
|
3440
3702
|
*/
|
|
3441
|
-
where(conditions) {
|
|
3442
|
-
this.similarOptions.where = {
|
|
3443
|
-
...this.similarOptions.where,
|
|
3444
|
-
...conditions
|
|
3445
|
-
};
|
|
3446
|
-
return this;
|
|
3447
|
-
}
|
|
3448
3703
|
/**
|
|
3449
3704
|
* Limit number of results
|
|
3450
3705
|
* @param count - Maximum results
|
|
@@ -3478,13 +3733,10 @@ var _SimilarBuilder = class _SimilarBuilder {
|
|
|
3478
3733
|
if (contentTypes != null) {
|
|
3479
3734
|
body.contentTypes = contentTypes;
|
|
3480
3735
|
}
|
|
3481
|
-
if (this.similarOptions.where && Object.keys(this.similarOptions.where).length > 0) {
|
|
3482
|
-
body.where = this.similarOptions.where;
|
|
3483
|
-
}
|
|
3484
3736
|
if (this.similarOptions.limit !== void 0) {
|
|
3485
3737
|
body.limit = this.similarOptions.limit;
|
|
3486
3738
|
}
|
|
3487
|
-
const locale = this.similarOptions.locale ?? this.
|
|
3739
|
+
const locale = this.similarOptions.locale ?? this.clientLocale();
|
|
3488
3740
|
if (locale != null && locale !== "") {
|
|
3489
3741
|
body.locale = locale;
|
|
3490
3742
|
}
|
|
@@ -3512,41 +3764,36 @@ __name(_SimilarBuilder, "SimilarBuilder");
|
|
|
3512
3764
|
var SimilarBuilder = _SimilarBuilder;
|
|
3513
3765
|
var _SearchClient = class _SearchClient {
|
|
3514
3766
|
/**
|
|
3515
|
-
* @param
|
|
3516
|
-
* the query names none, as `content()`'s reads do
|
|
3767
|
+
* @param locale - The client's locale (`withLocale()`, `updateConfig({ locale })`): every builder
|
|
3768
|
+
* here sends it when the query names none, as `content()`'s reads do — the function
|
|
3769
|
+
* `TypedRelyIOClient` hands over, or a locale fixed for this client
|
|
3517
3770
|
*/
|
|
3518
|
-
constructor(httpClient,
|
|
3771
|
+
constructor(httpClient, locale) {
|
|
3519
3772
|
this.httpClient = httpClient;
|
|
3520
|
-
|
|
3773
|
+
/** The client's locale, handed to every builder here to ask when it sends. */
|
|
3774
|
+
__publicField(this, "clientLocale");
|
|
3775
|
+
this.clientLocale = readClientLocale(locale);
|
|
3521
3776
|
}
|
|
3522
3777
|
/**
|
|
3523
3778
|
* Start a search query
|
|
3524
3779
|
* @param query - Search query string
|
|
3525
3780
|
*/
|
|
3526
3781
|
search(query) {
|
|
3527
|
-
return new SearchBuilder(this.httpClient, query, this.
|
|
3782
|
+
return new SearchBuilder(this.httpClient, query, this.clientLocale);
|
|
3528
3783
|
}
|
|
3529
3784
|
/**
|
|
3530
3785
|
* Start an autocomplete query
|
|
3531
3786
|
* @param query - Partial query to autocomplete
|
|
3532
3787
|
*/
|
|
3533
3788
|
autocomplete(query) {
|
|
3534
|
-
return new AutocompleteBuilder(this.httpClient, query, this.
|
|
3789
|
+
return new AutocompleteBuilder(this.httpClient, query, this.clientLocale);
|
|
3535
3790
|
}
|
|
3536
3791
|
/**
|
|
3537
3792
|
* Find content similar to a given entry
|
|
3538
3793
|
* @param sourceId - Entry ID to find similar content for
|
|
3539
3794
|
*/
|
|
3540
3795
|
similar(sourceId) {
|
|
3541
|
-
return new SimilarBuilder(this.httpClient, sourceId, this.
|
|
3542
|
-
}
|
|
3543
|
-
/**
|
|
3544
|
-
* Quick search helper - searches all content types
|
|
3545
|
-
* @param query - Search query
|
|
3546
|
-
* @param limit - Max results (default 20)
|
|
3547
|
-
*/
|
|
3548
|
-
async global(query, limit = 20) {
|
|
3549
|
-
return this.search(query).across("*").limit(limit).execute();
|
|
3796
|
+
return new SimilarBuilder(this.httpClient, sourceId, this.clientLocale);
|
|
3550
3797
|
}
|
|
3551
3798
|
};
|
|
3552
3799
|
__name(_SearchClient, "SearchClient");
|
|
@@ -3554,7 +3801,12 @@ var SearchClient = _SearchClient;
|
|
|
3554
3801
|
|
|
3555
3802
|
// src/batch/batch-client.ts
|
|
3556
3803
|
var _BatchBuilder = class _BatchBuilder {
|
|
3557
|
-
|
|
3804
|
+
/**
|
|
3805
|
+
* @param locale - The client's locale (`withLocale()`, `updateConfig({ locale })`), each
|
|
3806
|
+
* operation's when it names none: the function `TypedRelyIOClient` hands over, or a locale fixed
|
|
3807
|
+
* for this batch
|
|
3808
|
+
*/
|
|
3809
|
+
constructor(httpClient, locale) {
|
|
3558
3810
|
this.httpClient = httpClient;
|
|
3559
3811
|
__publicField(this, "operations", []);
|
|
3560
3812
|
__publicField(this, "defaultOptions", {
|
|
@@ -3564,6 +3816,17 @@ var _BatchBuilder = class _BatchBuilder {
|
|
|
3564
3816
|
continueOnError: true
|
|
3565
3817
|
});
|
|
3566
3818
|
__publicField(this, "requestHeaders");
|
|
3819
|
+
/** The client's locale, asked as each operation is added rather than copied when this was built. */
|
|
3820
|
+
__publicField(this, "clientLocale");
|
|
3821
|
+
this.clientLocale = readClientLocale(locale);
|
|
3822
|
+
}
|
|
3823
|
+
/**
|
|
3824
|
+
* An operation's body with its locale: the one it names, else the client's as it is when the
|
|
3825
|
+
* operation is added.
|
|
3826
|
+
*/
|
|
3827
|
+
localized(data) {
|
|
3828
|
+
const locale = callLocale(data.locale, this.clientLocale());
|
|
3829
|
+
return locale === void 0 ? data : { ...data, locale };
|
|
3567
3830
|
}
|
|
3568
3831
|
// ==========================================================================
|
|
3569
3832
|
// ENTRY OPERATIONS
|
|
@@ -3579,7 +3842,7 @@ var _BatchBuilder = class _BatchBuilder {
|
|
|
3579
3842
|
id,
|
|
3580
3843
|
method: "POST",
|
|
3581
3844
|
path: `/${contentType}`,
|
|
3582
|
-
body: data
|
|
3845
|
+
body: this.localized(data)
|
|
3583
3846
|
});
|
|
3584
3847
|
return this;
|
|
3585
3848
|
}
|
|
@@ -3599,7 +3862,7 @@ var _BatchBuilder = class _BatchBuilder {
|
|
|
3599
3862
|
id,
|
|
3600
3863
|
method: "PATCH",
|
|
3601
3864
|
path: `/${contentType}/${entryId}`,
|
|
3602
|
-
body: data
|
|
3865
|
+
body: this.localized(data)
|
|
3603
3866
|
});
|
|
3604
3867
|
return this;
|
|
3605
3868
|
}
|
|
@@ -3619,7 +3882,7 @@ var _BatchBuilder = class _BatchBuilder {
|
|
|
3619
3882
|
id,
|
|
3620
3883
|
method: "PUT",
|
|
3621
3884
|
path: `/${contentType}/${entryId}`,
|
|
3622
|
-
body: data
|
|
3885
|
+
body: this.localized(data)
|
|
3623
3886
|
});
|
|
3624
3887
|
return this;
|
|
3625
3888
|
}
|
|
@@ -3651,7 +3914,7 @@ var _BatchBuilder = class _BatchBuilder {
|
|
|
3651
3914
|
id,
|
|
3652
3915
|
method: "PATCH",
|
|
3653
3916
|
path: `/_singletons/${singletonKey}`,
|
|
3654
|
-
body: data
|
|
3917
|
+
body: this.localized(data)
|
|
3655
3918
|
});
|
|
3656
3919
|
return this;
|
|
3657
3920
|
}
|
|
@@ -3666,7 +3929,7 @@ var _BatchBuilder = class _BatchBuilder {
|
|
|
3666
3929
|
id,
|
|
3667
3930
|
method: "POST",
|
|
3668
3931
|
path: `/_singletons/${singletonKey}`,
|
|
3669
|
-
body: data
|
|
3932
|
+
body: this.localized(data)
|
|
3670
3933
|
});
|
|
3671
3934
|
return this;
|
|
3672
3935
|
}
|
|
@@ -3674,7 +3937,8 @@ var _BatchBuilder = class _BatchBuilder {
|
|
|
3674
3937
|
// RAW OPERATIONS
|
|
3675
3938
|
// ==========================================================================
|
|
3676
3939
|
/**
|
|
3677
|
-
* Add a raw operation (for advanced use cases)
|
|
3940
|
+
* Add a raw operation (for advanced use cases). It is sent exactly as written: the client's
|
|
3941
|
+
* locale is not added to it.
|
|
3678
3942
|
* @param operation - The operation to add
|
|
3679
3943
|
*/
|
|
3680
3944
|
raw(operation) {
|
|
@@ -3800,7 +4064,7 @@ var _BatchBuilder = class _BatchBuilder {
|
|
|
3800
4064
|
* Clone the builder
|
|
3801
4065
|
*/
|
|
3802
4066
|
clone() {
|
|
3803
|
-
const cloned = new _BatchBuilder(this.httpClient);
|
|
4067
|
+
const cloned = new _BatchBuilder(this.httpClient, this.clientLocale);
|
|
3804
4068
|
cloned.operations = [...this.operations];
|
|
3805
4069
|
cloned.defaultOptions = { ...this.defaultOptions };
|
|
3806
4070
|
cloned.requestHeaders = this.requestHeaders === void 0 ? void 0 : { ...this.requestHeaders };
|
|
@@ -3853,14 +4117,21 @@ var _BatchBuilder = class _BatchBuilder {
|
|
|
3853
4117
|
__name(_BatchBuilder, "BatchBuilder");
|
|
3854
4118
|
var BatchBuilder = _BatchBuilder;
|
|
3855
4119
|
var _BatchClient = class _BatchClient {
|
|
3856
|
-
|
|
4120
|
+
/**
|
|
4121
|
+
* @param locale - The client's locale: the function `TypedRelyIOClient` hands over, or a locale
|
|
4122
|
+
* fixed for this client
|
|
4123
|
+
*/
|
|
4124
|
+
constructor(httpClient, locale) {
|
|
3857
4125
|
this.httpClient = httpClient;
|
|
4126
|
+
/** The client's locale, handed to every batch this builds to ask as operations are added. */
|
|
4127
|
+
__publicField(this, "clientLocale");
|
|
4128
|
+
this.clientLocale = readClientLocale(locale);
|
|
3858
4129
|
}
|
|
3859
4130
|
/**
|
|
3860
|
-
* Create a new batch builder
|
|
4131
|
+
* Create a new batch builder, whose operations default to this client's locale
|
|
3861
4132
|
*/
|
|
3862
4133
|
create() {
|
|
3863
|
-
return new BatchBuilder(this.httpClient);
|
|
4134
|
+
return new BatchBuilder(this.httpClient, this.clientLocale);
|
|
3864
4135
|
}
|
|
3865
4136
|
/**
|
|
3866
4137
|
* Quick bulk create entries
|
|
@@ -3911,15 +4182,18 @@ function withClientLocale(parameters, clientLocale) {
|
|
|
3911
4182
|
__name(withClientLocale, "withClientLocale");
|
|
3912
4183
|
var _AdhocQueryBuilder = class _AdhocQueryBuilder {
|
|
3913
4184
|
/**
|
|
3914
|
-
* @param
|
|
3915
|
-
* when `.param('locale', …)` binds none
|
|
4185
|
+
* @param locale - The client's locale (`withLocale()`, `updateConfig({ locale })`), sent as the
|
|
4186
|
+
* `locale` parameter when `.param('locale', …)` binds none: the function `TypedRelyIOClient`
|
|
4187
|
+
* hands over, or a locale fixed for this builder
|
|
3916
4188
|
*/
|
|
3917
|
-
constructor(httpClient,
|
|
4189
|
+
constructor(httpClient, locale) {
|
|
3918
4190
|
this.httpClient = httpClient;
|
|
3919
|
-
this.defaultLocale = defaultLocale;
|
|
3920
4191
|
__publicField(this, "queryDef", {});
|
|
3921
4192
|
__publicField(this, "parameters", {});
|
|
3922
4193
|
__publicField(this, "options", {});
|
|
4194
|
+
/** The client's locale, asked when the query is sent rather than copied when it was built. */
|
|
4195
|
+
__publicField(this, "clientLocale");
|
|
4196
|
+
this.clientLocale = readClientLocale(locale);
|
|
3923
4197
|
}
|
|
3924
4198
|
// ==========================================================================
|
|
3925
4199
|
// QUERY BLOCKS
|
|
@@ -3964,14 +4238,6 @@ var _AdhocQueryBuilder = class _AdhocQueryBuilder {
|
|
|
3964
4238
|
this.queryDef.search = config;
|
|
3965
4239
|
return this;
|
|
3966
4240
|
}
|
|
3967
|
-
/**
|
|
3968
|
-
* Add similar block
|
|
3969
|
-
* @param config - Similar configuration
|
|
3970
|
-
*/
|
|
3971
|
-
similar(config) {
|
|
3972
|
-
this.queryDef.similar = config;
|
|
3973
|
-
return this;
|
|
3974
|
-
}
|
|
3975
4241
|
// ==========================================================================
|
|
3976
4242
|
// FETCH MODIFIERS
|
|
3977
4243
|
// ==========================================================================
|
|
@@ -4148,15 +4414,15 @@ var _AdhocQueryBuilder = class _AdhocQueryBuilder {
|
|
|
4148
4414
|
* Execute the query
|
|
4149
4415
|
*/
|
|
4150
4416
|
async execute() {
|
|
4151
|
-
if (!this.queryDef.fetch && !this.queryDef.aggregate && !this.queryDef.search
|
|
4417
|
+
if (!this.queryDef.fetch && !this.queryDef.aggregate && !this.queryDef.search) {
|
|
4152
4418
|
throw new Error(
|
|
4153
|
-
"Query must have at least one of: fetch, aggregate
|
|
4419
|
+
"Query must have at least one of: fetch, aggregate or search. Use .from(), .aggregate() or .search()"
|
|
4154
4420
|
);
|
|
4155
4421
|
}
|
|
4156
4422
|
const body = {
|
|
4157
4423
|
query: this.queryDef
|
|
4158
4424
|
};
|
|
4159
|
-
const parameters = withClientLocale(this.parameters, this.
|
|
4425
|
+
const parameters = withClientLocale(this.parameters, this.clientLocale());
|
|
4160
4426
|
if (parameters !== void 0 && Object.keys(parameters).length > 0) {
|
|
4161
4427
|
body.parameters = parameters;
|
|
4162
4428
|
}
|
|
@@ -4189,7 +4455,7 @@ var _AdhocQueryBuilder = class _AdhocQueryBuilder {
|
|
|
4189
4455
|
* Clone the builder
|
|
4190
4456
|
*/
|
|
4191
4457
|
clone() {
|
|
4192
|
-
const cloned = new _AdhocQueryBuilder(this.httpClient, this.
|
|
4458
|
+
const cloned = new _AdhocQueryBuilder(this.httpClient, this.clientLocale);
|
|
4193
4459
|
cloned.queryDef = JSON.parse(JSON.stringify(this.queryDef));
|
|
4194
4460
|
cloned.parameters = { ...this.parameters };
|
|
4195
4461
|
cloned.options = { ...this.options };
|
|
@@ -4200,18 +4466,21 @@ __name(_AdhocQueryBuilder, "AdhocQueryBuilder");
|
|
|
4200
4466
|
var AdhocQueryBuilder = _AdhocQueryBuilder;
|
|
4201
4467
|
var _AdhocQueryClient = class _AdhocQueryClient {
|
|
4202
4468
|
/**
|
|
4203
|
-
* @param
|
|
4204
|
-
* every query that binds none
|
|
4469
|
+
* @param locale - The client's locale (`withLocale()`, `updateConfig({ locale })`), sent as the
|
|
4470
|
+
* `locale` parameter of every query that binds none: the function `TypedRelyIOClient` hands
|
|
4471
|
+
* over, or a locale fixed for this client
|
|
4205
4472
|
*/
|
|
4206
|
-
constructor(httpClient,
|
|
4473
|
+
constructor(httpClient, locale) {
|
|
4207
4474
|
this.httpClient = httpClient;
|
|
4208
|
-
this.
|
|
4475
|
+
/** The client's locale, asked on every query rather than copied when this client was taken. */
|
|
4476
|
+
__publicField(this, "clientLocale");
|
|
4477
|
+
this.clientLocale = readClientLocale(locale);
|
|
4209
4478
|
}
|
|
4210
4479
|
/**
|
|
4211
4480
|
* Create a new query builder
|
|
4212
4481
|
*/
|
|
4213
4482
|
build() {
|
|
4214
|
-
return new AdhocQueryBuilder(this.httpClient, this.
|
|
4483
|
+
return new AdhocQueryBuilder(this.httpClient, this.clientLocale);
|
|
4215
4484
|
}
|
|
4216
4485
|
/**
|
|
4217
4486
|
* Execute a query definition directly
|
|
@@ -4226,7 +4495,7 @@ var _AdhocQueryClient = class _AdhocQueryClient {
|
|
|
4226
4495
|
const body = {
|
|
4227
4496
|
query: definition
|
|
4228
4497
|
};
|
|
4229
|
-
const sent = withClientLocale(parameters, this.
|
|
4498
|
+
const sent = withClientLocale(parameters, this.clientLocale());
|
|
4230
4499
|
if (sent !== void 0 && Object.keys(sent).length > 0) {
|
|
4231
4500
|
body.parameters = sent;
|
|
4232
4501
|
}
|
|
@@ -4475,7 +4744,7 @@ var DEFAULT_CONFIG = {
|
|
|
4475
4744
|
environment: "production",
|
|
4476
4745
|
headers: {},
|
|
4477
4746
|
browser: {
|
|
4478
|
-
includeCredentials:
|
|
4747
|
+
includeCredentials: false,
|
|
4479
4748
|
useRelativeUrls: false
|
|
4480
4749
|
},
|
|
4481
4750
|
cache: {
|
|
@@ -4507,45 +4776,42 @@ function validateConfig(config) {
|
|
|
4507
4776
|
if (config.baseUrl != null && typeof config.baseUrl !== "string") {
|
|
4508
4777
|
throw new Error("Base URL must be a string");
|
|
4509
4778
|
}
|
|
4510
|
-
if (config.timeout != null
|
|
4511
|
-
|
|
4512
|
-
|
|
4513
|
-
|
|
4514
|
-
|
|
4779
|
+
if (config.timeout != null) assertRequestTimeout(config.timeout);
|
|
4780
|
+
if (config.retryAttempts != null && !(Number.isInteger(config.retryAttempts) && config.retryAttempts >= 1)) {
|
|
4781
|
+
throw new Error(
|
|
4782
|
+
`retryAttempts must be a whole number of at least 1 \u2014 the most attempts one request makes, the first included, so 1 turns retrying off \u2014 and got ${String(config.retryAttempts)}`
|
|
4783
|
+
);
|
|
4515
4784
|
}
|
|
4516
4785
|
}
|
|
4517
4786
|
__name(validateConfig, "validateConfig");
|
|
4518
4787
|
var devOverrideNotified = false;
|
|
4519
4788
|
function resolveConfig(userConfig) {
|
|
4520
4789
|
validateConfig(userConfig);
|
|
4521
|
-
|
|
4522
|
-
|
|
4523
|
-
|
|
4524
|
-
|
|
4525
|
-
|
|
4526
|
-
|
|
4527
|
-
|
|
4528
|
-
|
|
4529
|
-
|
|
4530
|
-
|
|
4531
|
-
|
|
4532
|
-
|
|
4533
|
-
|
|
4534
|
-
|
|
4535
|
-
|
|
4536
|
-
|
|
4537
|
-
|
|
4538
|
-
|
|
4539
|
-
|
|
4540
|
-
|
|
4541
|
-
|
|
4542
|
-
|
|
4543
|
-
|
|
4544
|
-
|
|
4545
|
-
const dev = resolveDevOverride(userConfig.dev);
|
|
4790
|
+
return withHandshake(withDefaults(DEFAULT_CONFIG, userConfig, DEFAULT_CONFIG));
|
|
4791
|
+
}
|
|
4792
|
+
__name(resolveConfig, "resolveConfig");
|
|
4793
|
+
function resolveConfigUpdate(configured, update) {
|
|
4794
|
+
validateConfig(update);
|
|
4795
|
+
const base = update.apiKey === void 0 ? configured : withoutKeyHeader(configured);
|
|
4796
|
+
return withHandshake(withDefaults(base, update, DEFAULT_CONFIG));
|
|
4797
|
+
}
|
|
4798
|
+
__name(resolveConfigUpdate, "resolveConfigUpdate");
|
|
4799
|
+
function withConfiguredKey(configured, apiKey) {
|
|
4800
|
+
return { ...withoutKeyHeader(configured), apiKey };
|
|
4801
|
+
}
|
|
4802
|
+
__name(withConfiguredKey, "withConfiguredKey");
|
|
4803
|
+
function withoutKeyHeader(configured) {
|
|
4804
|
+
return { ...configured, headers: layerHeaders(configured.headers, { [API_KEY_HEADER]: null }) };
|
|
4805
|
+
}
|
|
4806
|
+
__name(withoutKeyHeader, "withoutKeyHeader");
|
|
4807
|
+
function withHandshake(configured) {
|
|
4808
|
+
const dev = resolveDevOverride(configured.dev);
|
|
4809
|
+
const merged = withDefaults(
|
|
4810
|
+
configured,
|
|
4811
|
+
dev.state === "active" ? { apiKey: dev.apiKey, dataset: dev.sandbox.datasetId } : {},
|
|
4812
|
+
DEFAULT_CONFIG
|
|
4813
|
+
);
|
|
4546
4814
|
if (dev.state === "active") {
|
|
4547
|
-
merged.apiKey = dev.apiKey;
|
|
4548
|
-
merged.dataset = dev.sandbox.datasetId;
|
|
4549
4815
|
if (!devOverrideNotified) {
|
|
4550
4816
|
devOverrideNotified = true;
|
|
4551
4817
|
console.info(
|
|
@@ -4563,30 +4829,67 @@ function resolveConfig(userConfig) {
|
|
|
4563
4829
|
`[RelyIO] Your .relyio/dev.json could not be read (${dev.reason}) \u2014 ignoring it and using the configured dataset "${merged.dataset}". Run \`relyio dev\` to rewrite it.`
|
|
4564
4830
|
);
|
|
4565
4831
|
}
|
|
4566
|
-
return { config: merged, sandbox: sandboxStateOf(dev) };
|
|
4832
|
+
return { config: merged, sandbox: sandboxStateOf(dev), configured };
|
|
4567
4833
|
}
|
|
4568
|
-
__name(
|
|
4834
|
+
__name(withHandshake, "withHandshake");
|
|
4835
|
+
function withDefaults(base, given, defaults) {
|
|
4836
|
+
const merged = new Map(Object.entries(base));
|
|
4837
|
+
const givenValues = new Map(Object.entries(given ?? {}));
|
|
4838
|
+
const defaultValues = new Map(Object.entries(defaults));
|
|
4839
|
+
for (const key of /* @__PURE__ */ new Set([...merged.keys(), ...givenValues.keys()])) {
|
|
4840
|
+
const fallback = merged.get(key);
|
|
4841
|
+
const value = givenValues.get(key);
|
|
4842
|
+
const givenBag = isOptionBag(value) ? value : void 0;
|
|
4843
|
+
if (isOptionBag(fallback) && key === "headers") {
|
|
4844
|
+
merged.set(key, layerHeaders(fallback, givenBag));
|
|
4845
|
+
} else if (isOptionBag(fallback)) {
|
|
4846
|
+
const defaultBag = defaultValues.get(key);
|
|
4847
|
+
merged.set(key, withDefaults(fallback, givenBag, isOptionBag(defaultBag) ? defaultBag : {}));
|
|
4848
|
+
} else if (value === null) {
|
|
4849
|
+
if (defaultValues.has(key)) merged.set(key, defaultValues.get(key));
|
|
4850
|
+
else merged.delete(key);
|
|
4851
|
+
} else if (value !== void 0) {
|
|
4852
|
+
merged.set(key, value);
|
|
4853
|
+
}
|
|
4854
|
+
}
|
|
4855
|
+
return Object.fromEntries(merged);
|
|
4856
|
+
}
|
|
4857
|
+
__name(withDefaults, "withDefaults");
|
|
4858
|
+
function isOptionBag(value) {
|
|
4859
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
4860
|
+
}
|
|
4861
|
+
__name(isOptionBag, "isOptionBag");
|
|
4569
4862
|
|
|
4570
4863
|
// src/client/create-client.ts
|
|
4571
4864
|
var API_VERSION_SEGMENT = "v1";
|
|
4572
4865
|
var _TypedRelyIOClient = class _TypedRelyIOClient {
|
|
4573
4866
|
constructor(config) {
|
|
4867
|
+
/**
|
|
4868
|
+
* The one HTTP client every sub-client sends through. `updateConfig()` and `setApiKey()` change it
|
|
4869
|
+
* in place rather than replacing it, so a sub-client taken before either sends through the change.
|
|
4870
|
+
*/
|
|
4574
4871
|
__publicField(this, "httpClient");
|
|
4575
4872
|
__publicField(this, "config");
|
|
4873
|
+
/**
|
|
4874
|
+
* The configuration as `createClient()`, `setApiKey()` and `updateConfig()` gave it, before the
|
|
4875
|
+
* `relyio dev` handshake: what the next update is laid over, and what `withLocale()` starts from.
|
|
4876
|
+
*/
|
|
4877
|
+
__publicField(this, "configured");
|
|
4576
4878
|
__publicField(this, "_sandbox");
|
|
4577
|
-
__publicField(this, "_search");
|
|
4578
|
-
__publicField(this, "_batch");
|
|
4579
|
-
__publicField(this, "_adhocQuery");
|
|
4580
4879
|
__publicField(this, "_schema");
|
|
4880
|
+
/**
|
|
4881
|
+
* The client's locale as it is when a call is made. Every sub-client and builder is handed this
|
|
4882
|
+
* rather than a copy of the locale, so one taken before `updateConfig({ locale })` sends the new
|
|
4883
|
+
* locale, or none after `locale: null` (REL-1453).
|
|
4884
|
+
*/
|
|
4885
|
+
__publicField(this, "currentLocale", /* @__PURE__ */ __name(() => this.config.locale, "currentLocale"));
|
|
4581
4886
|
const { schema, ...clientConfig } = config;
|
|
4582
4887
|
this._schema = schema;
|
|
4583
4888
|
const resolved = resolveConfig(clientConfig);
|
|
4584
4889
|
this.config = resolved.config;
|
|
4890
|
+
this.configured = resolved.configured;
|
|
4585
4891
|
this._sandbox = resolved.sandbox;
|
|
4586
4892
|
this.httpClient = new HttpClient(this.config);
|
|
4587
|
-
this._search = new SearchClient(this.httpClient, this.config.locale);
|
|
4588
|
-
this._batch = new BatchClient(this.httpClient);
|
|
4589
|
-
this._adhocQuery = new AdhocQueryClient(this.httpClient, this.config.locale);
|
|
4590
4893
|
}
|
|
4591
4894
|
// ============================================================================
|
|
4592
4895
|
// CORE CLIENTS
|
|
@@ -4615,10 +4918,10 @@ var _TypedRelyIOClient = class _TypedRelyIOClient {
|
|
|
4615
4918
|
return this._sandbox;
|
|
4616
4919
|
}
|
|
4617
4920
|
/**
|
|
4618
|
-
* Get the ad-hoc query client
|
|
4921
|
+
* Get the ad-hoc query client. Every query it sends is in the client's locale as it is then.
|
|
4619
4922
|
*/
|
|
4620
4923
|
get query() {
|
|
4621
|
-
return this.
|
|
4924
|
+
return new AdhocQueryClient(this.httpClient, this.currentLocale);
|
|
4622
4925
|
}
|
|
4623
4926
|
// ============================================================================
|
|
4624
4927
|
// CONTENT OPERATIONS
|
|
@@ -4638,7 +4941,7 @@ var _TypedRelyIOClient = class _TypedRelyIOClient {
|
|
|
4638
4941
|
* ```
|
|
4639
4942
|
*/
|
|
4640
4943
|
content(contentType) {
|
|
4641
|
-
return new ContentClient(this.httpClient, contentType, this.
|
|
4944
|
+
return new ContentClient(this.httpClient, contentType, this.currentLocale);
|
|
4642
4945
|
}
|
|
4643
4946
|
/**
|
|
4644
4947
|
* Get an asset client for a specific asset type.
|
|
@@ -4659,7 +4962,7 @@ var _TypedRelyIOClient = class _TypedRelyIOClient {
|
|
|
4659
4962
|
* ```
|
|
4660
4963
|
*/
|
|
4661
4964
|
asset(assetType) {
|
|
4662
|
-
return new AssetClient(this.httpClient, assetType, this.
|
|
4965
|
+
return new AssetClient(this.httpClient, assetType, this.currentLocale);
|
|
4663
4966
|
}
|
|
4664
4967
|
/**
|
|
4665
4968
|
* Get a singleton client for a specific singleton key
|
|
@@ -4674,7 +4977,7 @@ var _TypedRelyIOClient = class _TypedRelyIOClient {
|
|
|
4674
4977
|
* ```
|
|
4675
4978
|
*/
|
|
4676
4979
|
singleton(key) {
|
|
4677
|
-
return new SingletonClient(this.httpClient, key, this.
|
|
4980
|
+
return new SingletonClient(this.httpClient, key, this.currentLocale);
|
|
4678
4981
|
}
|
|
4679
4982
|
/**
|
|
4680
4983
|
* Get a settings client for a specific settings group
|
|
@@ -4688,7 +4991,7 @@ var _TypedRelyIOClient = class _TypedRelyIOClient {
|
|
|
4688
4991
|
* ```
|
|
4689
4992
|
*/
|
|
4690
4993
|
settings(groupId) {
|
|
4691
|
-
return new SettingsClient(this.httpClient, groupId, this.
|
|
4994
|
+
return new SettingsClient(this.httpClient, groupId, this.currentLocale);
|
|
4692
4995
|
}
|
|
4693
4996
|
// ============================================================================
|
|
4694
4997
|
// SEARCH OPERATIONS
|
|
@@ -4710,7 +5013,7 @@ var _TypedRelyIOClient = class _TypedRelyIOClient {
|
|
|
4710
5013
|
* ```
|
|
4711
5014
|
*/
|
|
4712
5015
|
search(query) {
|
|
4713
|
-
return this.
|
|
5016
|
+
return this.searchClient().search(query);
|
|
4714
5017
|
}
|
|
4715
5018
|
/**
|
|
4716
5019
|
* Start an autocomplete query for search suggestions
|
|
@@ -4726,7 +5029,7 @@ var _TypedRelyIOClient = class _TypedRelyIOClient {
|
|
|
4726
5029
|
* ```
|
|
4727
5030
|
*/
|
|
4728
5031
|
autocomplete(query) {
|
|
4729
|
-
return this.
|
|
5032
|
+
return this.searchClient().autocomplete(query);
|
|
4730
5033
|
}
|
|
4731
5034
|
/**
|
|
4732
5035
|
* Find content similar to a given entry using vector search
|
|
@@ -4741,13 +5044,17 @@ var _TypedRelyIOClient = class _TypedRelyIOClient {
|
|
|
4741
5044
|
* ```
|
|
4742
5045
|
*/
|
|
4743
5046
|
similar(sourceId) {
|
|
4744
|
-
return this.
|
|
5047
|
+
return this.searchClient().similar(sourceId);
|
|
4745
5048
|
}
|
|
4746
5049
|
// ============================================================================
|
|
4747
5050
|
// BATCH OPERATIONS
|
|
4748
5051
|
// ============================================================================
|
|
4749
5052
|
/**
|
|
4750
|
-
* Start a batch operation for bulk create/update/delete
|
|
5053
|
+
* Start a batch operation for bulk create/update/delete.
|
|
5054
|
+
*
|
|
5055
|
+
* By default each operation lands or fails on its own. `atomic: true` makes the batch one
|
|
5056
|
+
* transaction, which the API accepts only when every operation is the same kind of write and none
|
|
5057
|
+
* writes a singleton that does not exist yet.
|
|
4751
5058
|
*
|
|
4752
5059
|
* @example
|
|
4753
5060
|
* ```typescript
|
|
@@ -4756,13 +5063,23 @@ var _TypedRelyIOClient = class _TypedRelyIOClient {
|
|
|
4756
5063
|
* .update('product', 'entry_abc', { content: { price: 899 } })
|
|
4757
5064
|
* .delete('product', 'entry_xyz')
|
|
4758
5065
|
* .upsertSingleton('homepage', { content: { hero: 'Welcome!' } })
|
|
4759
|
-
* .execute(
|
|
5066
|
+
* .execute()
|
|
4760
5067
|
*
|
|
4761
5068
|
* console.log(result.summary.succeeded)
|
|
5069
|
+
*
|
|
5070
|
+
* // All or nothing: one kind of write
|
|
5071
|
+
* await relyio.batch()
|
|
5072
|
+
* .update('product', 'entry_abc', { content: { price: 899 } })
|
|
5073
|
+
* .update('product', 'entry_def', { content: { price: 799 } })
|
|
5074
|
+
* .execute({ atomic: true })
|
|
4762
5075
|
* ```
|
|
4763
5076
|
*/
|
|
4764
5077
|
batch() {
|
|
4765
|
-
return this.
|
|
5078
|
+
return new BatchClient(this.httpClient, this.currentLocale).create();
|
|
5079
|
+
}
|
|
5080
|
+
/** The search client, whose builders send the client's locale as it is when each one is sent. */
|
|
5081
|
+
searchClient() {
|
|
5082
|
+
return new SearchClient(this.httpClient, this.currentLocale);
|
|
4766
5083
|
}
|
|
4767
5084
|
// ============================================================================
|
|
4768
5085
|
// CHANGES FEED
|
|
@@ -4836,7 +5153,7 @@ var _TypedRelyIOClient = class _TypedRelyIOClient {
|
|
|
4836
5153
|
* ```
|
|
4837
5154
|
*/
|
|
4838
5155
|
adhoc() {
|
|
4839
|
-
return this.
|
|
5156
|
+
return this.query.build();
|
|
4840
5157
|
}
|
|
4841
5158
|
/**
|
|
4842
5159
|
* Execute a predefined query by name (from schema)
|
|
@@ -4921,16 +5238,53 @@ var _TypedRelyIOClient = class _TypedRelyIOClient {
|
|
|
4921
5238
|
}
|
|
4922
5239
|
}
|
|
4923
5240
|
/**
|
|
4924
|
-
*
|
|
5241
|
+
* Change some of the client's options and keep the rest.
|
|
5242
|
+
*
|
|
5243
|
+
* What you pass is laid over the configuration the client holds, field by field:
|
|
5244
|
+
*
|
|
5245
|
+
* - an option you name replaces the value the client holds;
|
|
5246
|
+
* - an option left out, or given as `undefined`, keeps the value the client holds;
|
|
5247
|
+
* - an option with no default given as `null` is cleared — `locale`, `dataset`, `apiKey`, `dev`,
|
|
5248
|
+
* `fetch`, `browser.onCorsError`, `realtime.wsUrl`, `debug.logger` — so the client runs as though
|
|
5249
|
+
* it had never been given one. An option with a default takes no `null`;
|
|
5250
|
+
* - a bag of options you name — `browser`, `cache`, `realtime`, `debug` — keeps every field of it
|
|
5251
|
+
* you do not name, so `updateConfig({ browser: { includeCredentials: true } })` keeps a
|
|
5252
|
+
* configured `onCorsError`;
|
|
5253
|
+
* - `headers` is laid over the headers the client sends, a name matched without regard to case: a
|
|
5254
|
+
* header you name is added or replaces every spelling of it, every other one is still sent, and a
|
|
5255
|
+
* header given as `null` is no longer sent;
|
|
5256
|
+
* - naming `apiKey` — a key, or `null` — replaces every key the client holds, one given in
|
|
5257
|
+
* `headers` included.
|
|
5258
|
+
*
|
|
5259
|
+
* The configuration it is laid over is what `createClient()`, `setApiKey()` and earlier updates
|
|
5260
|
+
* gave the client. The `relyio dev` handshake is read again, as `createClient()` reads it: while a
|
|
5261
|
+
* sandbox is active its key and dataset are sent over the configured ones, and once it has gone
|
|
5262
|
+
* the configured ones are.
|
|
5263
|
+
*
|
|
5264
|
+
* The client's one HTTP client is changed in place, so every request from now on is sent as the
|
|
5265
|
+
* update says — including one from a `content()`, `asset()`, `singleton()` or `settings()`
|
|
5266
|
+
* sub-client, a `query` client, or a builder such as `search()` or `batch()`, taken before the
|
|
5267
|
+
* call. The locale reaches them too: each reads the client's locale when it sends, so a new
|
|
5268
|
+
* `locale` is the default of its next request and `locale: null` leaves that request with none. A
|
|
5269
|
+
* locale the call names, and a sub-client's own `withLocale()`, still win over it. A client made
|
|
5270
|
+
* by `withLocale()` is a client of its own: an update of this one does not reach it.
|
|
5271
|
+
*
|
|
5272
|
+
* @example
|
|
5273
|
+
* ```typescript
|
|
5274
|
+
* const relyio = createClient({ apiKey, headers: { 'X-Tenant': 'acme' }, browser: { onCorsError } })
|
|
5275
|
+
*
|
|
5276
|
+
* relyio.updateConfig({ headers: { 'X-Trace': traceId } }) // X-Tenant is still sent
|
|
5277
|
+
* relyio.updateConfig({ browser: { includeCredentials: true } }) // onCorsError is kept
|
|
5278
|
+
* relyio.updateConfig({ headers: { 'X-Tenant': null } }) // X-Tenant is no longer sent
|
|
5279
|
+
* relyio.updateConfig({ locale: null }) // reads name no locale of the client's
|
|
5280
|
+
* ```
|
|
4925
5281
|
*/
|
|
4926
|
-
updateConfig(
|
|
4927
|
-
const resolved =
|
|
5282
|
+
updateConfig(update) {
|
|
5283
|
+
const resolved = resolveConfigUpdate(this.configured, update);
|
|
4928
5284
|
this.config = resolved.config;
|
|
5285
|
+
this.configured = resolved.configured;
|
|
4929
5286
|
this._sandbox = resolved.sandbox;
|
|
4930
|
-
this.httpClient
|
|
4931
|
-
this._search = new SearchClient(this.httpClient, this.config.locale);
|
|
4932
|
-
this._batch = new BatchClient(this.httpClient);
|
|
4933
|
-
this._adhocQuery = new AdhocQueryClient(this.httpClient, this.config.locale);
|
|
5287
|
+
this.httpClient.configure(this.config);
|
|
4934
5288
|
}
|
|
4935
5289
|
/**
|
|
4936
5290
|
* Get the current configuration
|
|
@@ -4939,11 +5293,31 @@ var _TypedRelyIOClient = class _TypedRelyIOClient {
|
|
|
4939
5293
|
return { ...this.config };
|
|
4940
5294
|
}
|
|
4941
5295
|
/**
|
|
4942
|
-
*
|
|
5296
|
+
* Replace the API key every later request sends as `X-API-Key`.
|
|
5297
|
+
*
|
|
5298
|
+
* It reaches every request this client makes from now on, including those of a `content()`,
|
|
5299
|
+
* `asset()` or other sub-client taken before the call, and `getConfig().apiKey` reports it. A key
|
|
5300
|
+
* given in `headers`, under any spelling, is replaced with it and does not come back on a later
|
|
5301
|
+
* `updateConfig()`. A client already derived with `withLocale()` is a client of its own and keeps
|
|
5302
|
+
* its key.
|
|
5303
|
+
*
|
|
5304
|
+
* An empty or blank key is no key, as it is when passed to `createClient`: the next request
|
|
5305
|
+
* rejects with `MissingApiKeyError` and nothing is sent.
|
|
5306
|
+
*
|
|
5307
|
+
* Under an active `relyio dev` sandbox the sandbox's scoped key stands, as it does over the key
|
|
5308
|
+
* passed to `createClient` — replacing the configured key does not retarget the client at the
|
|
5309
|
+
* sandbox's dataset with a key the sandbox did not issue.
|
|
5310
|
+
*
|
|
5311
|
+
* @example
|
|
5312
|
+
* ```typescript
|
|
5313
|
+
* const relyio = createClient({ apiKey: process.env.RELYIO_API_KEY! })
|
|
5314
|
+
* relyio.setApiKey(rotatedKey) // the next read sends `X-API-Key: <rotatedKey>`
|
|
5315
|
+
* ```
|
|
4943
5316
|
*/
|
|
4944
5317
|
setApiKey(apiKey) {
|
|
4945
|
-
this.
|
|
4946
|
-
this.
|
|
5318
|
+
this.configured = withConfiguredKey(this.configured, apiKey);
|
|
5319
|
+
if (this._sandbox.state === "active") return;
|
|
5320
|
+
this.httpClient.setApiKey(apiKey);
|
|
4947
5321
|
}
|
|
4948
5322
|
/**
|
|
4949
5323
|
* Get the HTTP client instance (for advanced usage)
|
|
@@ -4957,9 +5331,12 @@ var _TypedRelyIOClient = class _TypedRelyIOClient {
|
|
|
4957
5331
|
/**
|
|
4958
5332
|
* Create a locale-scoped client
|
|
4959
5333
|
*
|
|
4960
|
-
* Every
|
|
4961
|
-
* `
|
|
4962
|
-
*
|
|
5334
|
+
* Every call the returned client builds is in this locale unless the call names one of its own,
|
|
5335
|
+
* which wins: every read — `content()`, `asset()`, `singleton()`, `settings()`, `search()`,
|
|
5336
|
+
* `similar()`, `autocomplete()`, `executeQuery()` and the ad-hoc queries — and every write and
|
|
5337
|
+
* version-history read — `create()` and `update()`, the singleton and settings writes, the asset
|
|
5338
|
+
* file writes, `versions()` and `version()`, and each operation `batch()` builds. `restore()`
|
|
5339
|
+
* always names its locale; a delete, and a `batch().raw()` operation, carry none of the client's.
|
|
4963
5340
|
*
|
|
4964
5341
|
* Type-safe when schema is provided: autocompletes valid locale codes!
|
|
4965
5342
|
*
|
|
@@ -4967,10 +5344,11 @@ var _TypedRelyIOClient = class _TypedRelyIOClient {
|
|
|
4967
5344
|
* ```typescript
|
|
4968
5345
|
* const spanish = relyio.withLocale('es-ES') // ← Autocompletes with schema!
|
|
4969
5346
|
*
|
|
4970
|
-
* // Reads use Spanish
|
|
5347
|
+
* // Reads and writes use Spanish
|
|
4971
5348
|
* const products = await spanish.content('product').query().execute()
|
|
4972
5349
|
* const homepage = await spanish.singleton('homepage').fetch()
|
|
4973
5350
|
* const results = await spanish.search('zapatos').execute()
|
|
5351
|
+
* await spanish.content('product').update(id, { title: 'Zapatos' })
|
|
4974
5352
|
*
|
|
4975
5353
|
* // Original client unchanged
|
|
4976
5354
|
* const englishProducts = await relyio.content('product').query().execute()
|
|
@@ -4978,7 +5356,7 @@ var _TypedRelyIOClient = class _TypedRelyIOClient {
|
|
|
4978
5356
|
*/
|
|
4979
5357
|
withLocale(locale) {
|
|
4980
5358
|
const newConfig = {
|
|
4981
|
-
...this.
|
|
5359
|
+
...this.configured,
|
|
4982
5360
|
locale,
|
|
4983
5361
|
schema: this._schema
|
|
4984
5362
|
};
|
|
@@ -5027,6 +5405,6 @@ function createClient(config) {
|
|
|
5027
5405
|
}
|
|
5028
5406
|
__name(createClient, "createClient");
|
|
5029
5407
|
|
|
5030
|
-
export { AdhocQueryBuilder, AdhocQueryClient, AssetClient, AssetFileBuilder, AssetUploadBuilder,
|
|
5031
|
-
//# sourceMappingURL=chunk-
|
|
5032
|
-
//# sourceMappingURL=chunk-
|
|
5408
|
+
export { AdhocQueryBuilder, AdhocQueryClient, AssetClient, AssetFileBuilder, AssetUploadBuilder, AuthorizationError, AutocompleteBuilder, BaseValidationError, BatchBuilder, BatchClient, ChangesExpiredError, ConnectionError, ContentByIdBuilder, ContentClient, ContentQueryBuilder, ErrorMapper, FileUploadError, FileValidationError, HttpClient, InvalidApiKeyError, InvalidPayloadError, MethodNotAllowedError, MissingApiKeyError, NetworkError, PayloadTooLargeError, PlanFeatureUnavailableError, RateLimitError, ReadOnlyKeyError, ResourceConflictError, ResourceExpiredError, ResourceNotFoundError, SDKError, SearchBuilder, SearchClient, ServerError, ServiceIndeterminateError, SettingsClient, SimilarBuilder, SingletonClient, TimeoutError, TransactionRolledBackError, TypedRelyIOClient, UnknownContractError, UsageQuotaExceededError, ValidationError, createClient, entityTagOf, isAborted, isAssetEntry, isResourceNotFound, matchRoute, serviceInstructedDelayMs, sleep, validateFile };
|
|
5409
|
+
//# sourceMappingURL=chunk-GYHAVYND.js.map
|
|
5410
|
+
//# sourceMappingURL=chunk-GYHAVYND.js.map
|