@relyio/sdk 0.5.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 +540 -0
- package/dist/.tsbuildinfo +1 -1
- package/dist/{chunk-HAQELDZN.cjs → chunk-72UK5U7T.cjs} +70 -60
- package/dist/{chunk-5AZUUV5B.js → chunk-GYHAVYND.js} +1086 -494
- package/dist/{chunk-I3ESNANB.js → chunk-H6IBQSMM.js} +2 -2
- package/dist/{chunk-HT6NFRM2.cjs → chunk-TZL374LS.cjs} +2 -2
- package/dist/{chunk-CIRT6TVT.cjs → chunk-VH2DE7HZ.cjs} +1088 -497
- package/dist/{chunk-XY5KFEFY.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-C5mRBb6t.d.cts → define-content-type-DiVpbwNs.d.cts} +1629 -665
- package/dist/{index-mXUx2H99.d.ts → define-content-type-DiVpbwNs.d.ts} +1629 -665
- package/dist/{define-schema-DzYXk4HL.d.ts → define-schema-C-5an28C.d.ts} +211 -429
- package/dist/{define-schema-2xbHgtK-.d.cts → define-schema-D7MButVt.d.cts} +211 -429
- package/dist/{index-Dzo-upNS.d.ts → index-1G97sNA8.d.ts} +677 -296
- package/dist/index-BOQIHnsh.d.ts +818 -0
- package/dist/index-DbsTUw3Q.d.cts +818 -0
- package/dist/{index-BozPz4n1.d.cts → index-M0X45k7J.d.cts} +677 -296
- package/dist/index.cjs +180 -103
- package/dist/index.d.cts +307 -32
- package/dist/index.d.ts +307 -32
- package/dist/index.js +95 -8
- package/dist/schema/index.cjs +35 -35
- package/dist/schema/index.d.cts +21 -15
- package/dist/schema/index.d.ts +21 -15
- 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-CBfnTWSS.d.cts +0 -716
- package/dist/define-content-type-CBfnTWSS.d.ts +0 -716
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var chunkLSRPMNPT_cjs = require('./chunk-LSRPMNPT.cjs');
|
|
4
|
+
var chunkTZL374LS_cjs = require('./chunk-TZL374LS.cjs');
|
|
4
5
|
var chunkMWMSFIWN_cjs = require('./chunk-MWMSFIWN.cjs');
|
|
5
6
|
|
|
6
7
|
/* RelyIO SDK - Built with ❤️ by the RelyIO Team */
|
|
@@ -71,44 +72,6 @@ var _SDKError = class _SDKError extends Error {
|
|
|
71
72
|
chunkMWMSFIWN_cjs.__name(_SDKError, "SDKError");
|
|
72
73
|
var SDKError = _SDKError;
|
|
73
74
|
|
|
74
|
-
// src/errors/auth-errors.ts
|
|
75
|
-
var _AuthenticationError = class _AuthenticationError extends SDKError {
|
|
76
|
-
constructor(message = "Authentication failed", statusCode = 401, cause, context) {
|
|
77
|
-
super(message, statusCode, cause, context);
|
|
78
|
-
chunkMWMSFIWN_cjs.__publicField(this, "code", "AUTHENTICATION_ERROR");
|
|
79
|
-
chunkMWMSFIWN_cjs.__publicField(this, "retryable", false);
|
|
80
|
-
}
|
|
81
|
-
getUserMessage() {
|
|
82
|
-
return "Authentication failed. Please check your API key and try again.";
|
|
83
|
-
}
|
|
84
|
-
};
|
|
85
|
-
chunkMWMSFIWN_cjs.__name(_AuthenticationError, "AuthenticationError");
|
|
86
|
-
var AuthenticationError = _AuthenticationError;
|
|
87
|
-
var _AuthorizationError = class _AuthorizationError extends SDKError {
|
|
88
|
-
constructor(message = "Authorization failed", statusCode = 403, cause, context) {
|
|
89
|
-
super(message, statusCode, cause, context);
|
|
90
|
-
chunkMWMSFIWN_cjs.__publicField(this, "code", "AUTHORIZATION_ERROR");
|
|
91
|
-
chunkMWMSFIWN_cjs.__publicField(this, "retryable", false);
|
|
92
|
-
}
|
|
93
|
-
getUserMessage() {
|
|
94
|
-
return "You do not have permission to access this resource.";
|
|
95
|
-
}
|
|
96
|
-
};
|
|
97
|
-
chunkMWMSFIWN_cjs.__name(_AuthorizationError, "AuthorizationError");
|
|
98
|
-
var AuthorizationError = _AuthorizationError;
|
|
99
|
-
var _InvalidApiKeyError = class _InvalidApiKeyError extends SDKError {
|
|
100
|
-
constructor(message = "Invalid API key", cause, context) {
|
|
101
|
-
super(message, 401, cause, context);
|
|
102
|
-
chunkMWMSFIWN_cjs.__publicField(this, "code", "INVALID_API_KEY");
|
|
103
|
-
chunkMWMSFIWN_cjs.__publicField(this, "retryable", false);
|
|
104
|
-
}
|
|
105
|
-
getUserMessage() {
|
|
106
|
-
return "Invalid API key. Please check your API key and try again.";
|
|
107
|
-
}
|
|
108
|
-
};
|
|
109
|
-
chunkMWMSFIWN_cjs.__name(_InvalidApiKeyError, "InvalidApiKeyError");
|
|
110
|
-
var InvalidApiKeyError = _InvalidApiKeyError;
|
|
111
|
-
|
|
112
75
|
// src/errors/contract-errors.ts
|
|
113
76
|
var _MissingApiKeyError = class _MissingApiKeyError extends SDKError {
|
|
114
77
|
constructor(message = "No API key was sent", context) {
|
|
@@ -269,6 +232,32 @@ var _UnknownContractError = class _UnknownContractError extends SDKError {
|
|
|
269
232
|
chunkMWMSFIWN_cjs.__name(_UnknownContractError, "UnknownContractError");
|
|
270
233
|
var UnknownContractError = _UnknownContractError;
|
|
271
234
|
|
|
235
|
+
// src/errors/auth-errors.ts
|
|
236
|
+
var _AuthorizationError = class _AuthorizationError extends SDKError {
|
|
237
|
+
constructor(message = "Authorization failed", statusCode = 403, cause, context) {
|
|
238
|
+
super(message, statusCode, cause, context);
|
|
239
|
+
chunkMWMSFIWN_cjs.__publicField(this, "code", "AUTHORIZATION_ERROR");
|
|
240
|
+
chunkMWMSFIWN_cjs.__publicField(this, "retryable", false);
|
|
241
|
+
}
|
|
242
|
+
getUserMessage() {
|
|
243
|
+
return "You do not have permission to access this resource.";
|
|
244
|
+
}
|
|
245
|
+
};
|
|
246
|
+
chunkMWMSFIWN_cjs.__name(_AuthorizationError, "AuthorizationError");
|
|
247
|
+
var AuthorizationError = _AuthorizationError;
|
|
248
|
+
var _InvalidApiKeyError = class _InvalidApiKeyError extends SDKError {
|
|
249
|
+
constructor(message = "Invalid API key", cause, context) {
|
|
250
|
+
super(message, 401, cause, context);
|
|
251
|
+
chunkMWMSFIWN_cjs.__publicField(this, "code", "INVALID_API_KEY");
|
|
252
|
+
chunkMWMSFIWN_cjs.__publicField(this, "retryable", false);
|
|
253
|
+
}
|
|
254
|
+
getUserMessage() {
|
|
255
|
+
return "Invalid API key. Please check your API key and try again.";
|
|
256
|
+
}
|
|
257
|
+
};
|
|
258
|
+
chunkMWMSFIWN_cjs.__name(_InvalidApiKeyError, "InvalidApiKeyError");
|
|
259
|
+
var InvalidApiKeyError = _InvalidApiKeyError;
|
|
260
|
+
|
|
272
261
|
// src/errors/content-errors.ts
|
|
273
262
|
var _ResourceNotFoundError = class _ResourceNotFoundError extends SDKError {
|
|
274
263
|
constructor(message = "Resource not found", statusCode = 404, cause, context) {
|
|
@@ -330,8 +319,12 @@ var _NetworkError = class _NetworkError extends SDKError {
|
|
|
330
319
|
chunkMWMSFIWN_cjs.__name(_NetworkError, "NetworkError");
|
|
331
320
|
var NetworkError = _NetworkError;
|
|
332
321
|
var _TimeoutError = class _TimeoutError extends SDKError {
|
|
333
|
-
|
|
334
|
-
|
|
322
|
+
/**
|
|
323
|
+
* @param context - Carried beside `timeout`. The mapper passes a `REQUEST_TIMEOUT` refusal's body
|
|
324
|
+
* as `context.response`, as it does for every other contract code.
|
|
325
|
+
*/
|
|
326
|
+
constructor(message = "Request timed out", timeout, statusCode, cause, context) {
|
|
327
|
+
super(message, statusCode, cause, { ...context, timeout });
|
|
335
328
|
chunkMWMSFIWN_cjs.__publicField(this, "code", "TIMEOUT_ERROR");
|
|
336
329
|
chunkMWMSFIWN_cjs.__publicField(this, "retryable", true);
|
|
337
330
|
}
|
|
@@ -357,8 +350,13 @@ var ConnectionError = _ConnectionError;
|
|
|
357
350
|
|
|
358
351
|
// src/errors/validation-errors.ts
|
|
359
352
|
var _BaseValidationError = class _BaseValidationError extends SDKError {
|
|
360
|
-
|
|
361
|
-
|
|
353
|
+
/**
|
|
354
|
+
* @param context - Carried beside `violations`. The mapper passes the refusal body as
|
|
355
|
+
* `context.response`, as it does for every other contract code, so a consumer that hands the
|
|
356
|
+
* service's own words on can read them here too.
|
|
357
|
+
*/
|
|
358
|
+
constructor(message = "Validation failed", violations = [], statusCode = 400, cause, context) {
|
|
359
|
+
super(message, statusCode, cause, { ...context, violations });
|
|
362
360
|
chunkMWMSFIWN_cjs.__publicField(this, "retryable", false);
|
|
363
361
|
chunkMWMSFIWN_cjs.__publicField(this, "violations");
|
|
364
362
|
this.violations = violations;
|
|
@@ -403,8 +401,8 @@ var _ValidationError = class _ValidationError extends BaseValidationError {
|
|
|
403
401
|
chunkMWMSFIWN_cjs.__name(_ValidationError, "ValidationError");
|
|
404
402
|
var ValidationError = _ValidationError;
|
|
405
403
|
var _InvalidPayloadError = class _InvalidPayloadError extends BaseValidationError {
|
|
406
|
-
constructor(message = "Invalid payload", violations = [], cause) {
|
|
407
|
-
super(message, violations, 400, cause);
|
|
404
|
+
constructor(message = "Invalid payload", violations = [], cause, context) {
|
|
405
|
+
super(message, violations, 400, cause, context);
|
|
408
406
|
chunkMWMSFIWN_cjs.__publicField(this, "code", "INVALID_PAYLOAD");
|
|
409
407
|
}
|
|
410
408
|
getUserMessage() {
|
|
@@ -413,58 +411,6 @@ var _InvalidPayloadError = class _InvalidPayloadError extends BaseValidationErro
|
|
|
413
411
|
};
|
|
414
412
|
chunkMWMSFIWN_cjs.__name(_InvalidPayloadError, "InvalidPayloadError");
|
|
415
413
|
var InvalidPayloadError = _InvalidPayloadError;
|
|
416
|
-
var _SchemaValidationError = class _SchemaValidationError extends BaseValidationError {
|
|
417
|
-
constructor(message = "Schema validation failed", violations = [], cause) {
|
|
418
|
-
super(message, violations, 400, cause);
|
|
419
|
-
chunkMWMSFIWN_cjs.__publicField(this, "code", "SCHEMA_VALIDATION_ERROR");
|
|
420
|
-
}
|
|
421
|
-
getUserMessage() {
|
|
422
|
-
return "The data does not match the expected schema. Please check your content structure.";
|
|
423
|
-
}
|
|
424
|
-
};
|
|
425
|
-
chunkMWMSFIWN_cjs.__name(_SchemaValidationError, "SchemaValidationError");
|
|
426
|
-
var SchemaValidationError = _SchemaValidationError;
|
|
427
|
-
var _RequiredFieldError = class _RequiredFieldError extends BaseValidationError {
|
|
428
|
-
constructor(fieldName, message, cause) {
|
|
429
|
-
const violation = {
|
|
430
|
-
field: fieldName,
|
|
431
|
-
message: message ?? `Field "${fieldName}" is required`,
|
|
432
|
-
code: "REQUIRED"
|
|
433
|
-
};
|
|
434
|
-
super(`Required field "${fieldName}" is missing`, [violation], 400, cause);
|
|
435
|
-
chunkMWMSFIWN_cjs.__publicField(this, "code", "REQUIRED_FIELD_ERROR");
|
|
436
|
-
}
|
|
437
|
-
getUserMessage() {
|
|
438
|
-
const violation = this.violations[0];
|
|
439
|
-
const fieldName = violation?.field;
|
|
440
|
-
return `The field "${fieldName}" is required and cannot be empty.`;
|
|
441
|
-
}
|
|
442
|
-
};
|
|
443
|
-
chunkMWMSFIWN_cjs.__name(_RequiredFieldError, "RequiredFieldError");
|
|
444
|
-
var RequiredFieldError = _RequiredFieldError;
|
|
445
|
-
var _InvalidFieldTypeError = class _InvalidFieldTypeError extends BaseValidationError {
|
|
446
|
-
constructor(fieldName, expectedType, actualType, value, cause) {
|
|
447
|
-
const violation = {
|
|
448
|
-
field: fieldName,
|
|
449
|
-
message: `Expected ${expectedType}, got ${actualType}`,
|
|
450
|
-
code: "INVALID_TYPE",
|
|
451
|
-
value
|
|
452
|
-
};
|
|
453
|
-
super(
|
|
454
|
-
`Invalid type for field "${fieldName}": expected ${expectedType}, got ${actualType}`,
|
|
455
|
-
[violation],
|
|
456
|
-
400,
|
|
457
|
-
cause
|
|
458
|
-
);
|
|
459
|
-
chunkMWMSFIWN_cjs.__publicField(this, "code", "INVALID_FIELD_TYPE");
|
|
460
|
-
}
|
|
461
|
-
getUserMessage() {
|
|
462
|
-
const violation = this.violations[0];
|
|
463
|
-
return `The field "${violation?.field}" has an invalid type. ${violation?.message}.`;
|
|
464
|
-
}
|
|
465
|
-
};
|
|
466
|
-
chunkMWMSFIWN_cjs.__name(_InvalidFieldTypeError, "InvalidFieldTypeError");
|
|
467
|
-
var InvalidFieldTypeError = _InvalidFieldTypeError;
|
|
468
414
|
|
|
469
415
|
// ../../platform/api-contract/dist/index.js
|
|
470
416
|
var HEADER_RETRY_AFTER = { name: "Retry-After" };
|
|
@@ -593,10 +539,10 @@ var _ErrorMapper = class _ErrorMapper {
|
|
|
593
539
|
);
|
|
594
540
|
}
|
|
595
541
|
case "REQUEST_INVALID": {
|
|
596
|
-
return new InvalidPayloadError(message, violationsOf(refusal));
|
|
542
|
+
return new InvalidPayloadError(message, violationsOf(refusal), void 0, context);
|
|
597
543
|
}
|
|
598
544
|
case "CONTENT_INVALID": {
|
|
599
|
-
return new ValidationError(message, violationsOf(refusal), 400);
|
|
545
|
+
return new ValidationError(message, violationsOf(refusal), 400, void 0, context);
|
|
600
546
|
}
|
|
601
547
|
case "METHOD_NOT_ALLOWED": {
|
|
602
548
|
return new MethodNotAllowedError(message, context);
|
|
@@ -619,7 +565,7 @@ var _ErrorMapper = class _ErrorMapper {
|
|
|
619
565
|
return new ResourceExpiredError(message, 410, void 0, context);
|
|
620
566
|
}
|
|
621
567
|
case "REQUEST_TIMEOUT": {
|
|
622
|
-
return new TimeoutError(message, void 0, void 0,
|
|
568
|
+
return new TimeoutError(message, void 0, status, void 0, context);
|
|
623
569
|
}
|
|
624
570
|
case "PAYLOAD_TOO_LARGE": {
|
|
625
571
|
return new PayloadTooLargeError(message, detailNumber(refusal, "limitBytes"), context);
|
|
@@ -842,20 +788,43 @@ function readQuery(searchParams) {
|
|
|
842
788
|
}
|
|
843
789
|
chunkMWMSFIWN_cjs.__name(readQuery, "readQuery");
|
|
844
790
|
|
|
845
|
-
// src/http/
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
791
|
+
// src/http/abortable-sleep.ts
|
|
792
|
+
function sleep(ms, signal) {
|
|
793
|
+
return new Promise((resolve) => {
|
|
794
|
+
if (isAborted(signal)) {
|
|
795
|
+
resolve();
|
|
796
|
+
return;
|
|
797
|
+
}
|
|
798
|
+
const done = /* @__PURE__ */ chunkMWMSFIWN_cjs.__name(() => {
|
|
799
|
+
clearTimeout(timer);
|
|
800
|
+
signal?.removeEventListener("abort", done);
|
|
801
|
+
resolve();
|
|
802
|
+
}, "done");
|
|
803
|
+
const timer = setTimeout(done, ms);
|
|
804
|
+
signal?.addEventListener("abort", done, { once: true });
|
|
805
|
+
});
|
|
857
806
|
}
|
|
858
|
-
chunkMWMSFIWN_cjs.__name(
|
|
807
|
+
chunkMWMSFIWN_cjs.__name(sleep, "sleep");
|
|
808
|
+
function isAborted(signal) {
|
|
809
|
+
return signal?.aborted === true;
|
|
810
|
+
}
|
|
811
|
+
chunkMWMSFIWN_cjs.__name(isAborted, "isAborted");
|
|
812
|
+
|
|
813
|
+
// src/http/request-timeout.ts
|
|
814
|
+
var MAX_TIMER_DELAY_MS = 2147483647;
|
|
815
|
+
function isTimerDelay(value) {
|
|
816
|
+
return typeof value === "number" && value >= 1 && value <= MAX_TIMER_DELAY_MS;
|
|
817
|
+
}
|
|
818
|
+
chunkMWMSFIWN_cjs.__name(isTimerDelay, "isTimerDelay");
|
|
819
|
+
function assertRequestTimeout(timeout) {
|
|
820
|
+
if (isTimerDelay(timeout)) return;
|
|
821
|
+
throw new Error(
|
|
822
|
+
`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)}`
|
|
823
|
+
);
|
|
824
|
+
}
|
|
825
|
+
chunkMWMSFIWN_cjs.__name(assertRequestTimeout, "assertRequestTimeout");
|
|
826
|
+
|
|
827
|
+
// src/errors/instructed-delay.ts
|
|
859
828
|
function serviceInstructedDelayMs(error, nowMs) {
|
|
860
829
|
if (error instanceof ServiceIndeterminateError) {
|
|
861
830
|
return error.retryAfterMs;
|
|
@@ -869,6 +838,21 @@ function serviceInstructedDelayMs(error, nowMs) {
|
|
|
869
838
|
return wait > 0 ? wait : void 0;
|
|
870
839
|
}
|
|
871
840
|
chunkMWMSFIWN_cjs.__name(serviceInstructedDelayMs, "serviceInstructedDelayMs");
|
|
841
|
+
|
|
842
|
+
// src/http/retry-policy.ts
|
|
843
|
+
var IDEMPOTENT_METHODS = /* @__PURE__ */ new Set([
|
|
844
|
+
"GET",
|
|
845
|
+
"HEAD",
|
|
846
|
+
"OPTIONS",
|
|
847
|
+
"PUT",
|
|
848
|
+
"DELETE",
|
|
849
|
+
"TRACE"
|
|
850
|
+
]);
|
|
851
|
+
function isReplaySafe(request) {
|
|
852
|
+
if (IDEMPOTENT_METHODS.has(request.method.toUpperCase())) return true;
|
|
853
|
+
return headerValue(request.headers, HEADER_IDEMPOTENCY_KEY.name) !== void 0;
|
|
854
|
+
}
|
|
855
|
+
chunkMWMSFIWN_cjs.__name(isReplaySafe, "isReplaySafe");
|
|
872
856
|
var _DefaultRetryPolicy = class _DefaultRetryPolicy {
|
|
873
857
|
constructor(config) {
|
|
874
858
|
chunkMWMSFIWN_cjs.__publicField(this, "config");
|
|
@@ -893,42 +877,31 @@ var DefaultRetryPolicy = _DefaultRetryPolicy;
|
|
|
893
877
|
// src/http/http-client.ts
|
|
894
878
|
var _HttpClient = class _HttpClient {
|
|
895
879
|
constructor(config) {
|
|
896
|
-
|
|
897
|
-
chunkMWMSFIWN_cjs.__publicField(this, "
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
if (typeof window === "undefined") {
|
|
917
|
-
const globalWithVersion = globalThis;
|
|
918
|
-
this.defaultHeaders["User-Agent"] = `RelyIO-SDK/${globalWithVersion.__VERSION__ ?? "0.0.0"}`;
|
|
919
|
-
}
|
|
920
|
-
this.retryPolicy = new DefaultRetryPolicy({
|
|
921
|
-
maxAttempts: config.retryAttempts,
|
|
922
|
-
baseDelay: 1e3,
|
|
923
|
-
maxDelay: 1e4,
|
|
924
|
-
backoffFactor: 2,
|
|
925
|
-
jitter: true
|
|
926
|
-
});
|
|
880
|
+
/** What every request reads off the configuration, derived by {@link configure} and nowhere else. */
|
|
881
|
+
chunkMWMSFIWN_cjs.__publicField(this, "connection");
|
|
882
|
+
this.connection = connectionFor(config);
|
|
883
|
+
this.announce();
|
|
884
|
+
}
|
|
885
|
+
/**
|
|
886
|
+
* Run on `config` from now on: every later request — whoever holds this client — is sent to its
|
|
887
|
+
* `baseUrl`, with its headers, key and dataset, its timeout and retries, through its `fetch`, and
|
|
888
|
+
* logged by its `debug` options.
|
|
889
|
+
*
|
|
890
|
+
* The client's own `updateConfig()` calls this rather than building a second client, so a
|
|
891
|
+
* `content()` or other sub-client taken before the update sends through the update too. Anything
|
|
892
|
+
* set on this client since it was last configured — `setDefaultHeaders()`, `setBaseUrl()` — is
|
|
893
|
+
* replaced by what `config` says.
|
|
894
|
+
*/
|
|
895
|
+
configure(config) {
|
|
896
|
+
this.connection = connectionFor(config);
|
|
897
|
+
this.announce();
|
|
898
|
+
}
|
|
899
|
+
announce() {
|
|
927
900
|
this.log("debug", "HttpClient initialized", {
|
|
928
|
-
baseUrl: this.baseUrl,
|
|
929
|
-
timeout: this.timeout,
|
|
930
|
-
retryAttempts: config.retryAttempts,
|
|
931
|
-
environment:
|
|
901
|
+
baseUrl: this.connection.baseUrl,
|
|
902
|
+
timeout: this.connection.timeout,
|
|
903
|
+
retryAttempts: this.connection.config.retryAttempts,
|
|
904
|
+
environment: chunkTZL374LS_cjs.isBrowser() ? "browser" : "node"
|
|
932
905
|
});
|
|
933
906
|
}
|
|
934
907
|
/**
|
|
@@ -965,17 +938,34 @@ var _HttpClient = class _HttpClient {
|
|
|
965
938
|
*
|
|
966
939
|
* The loop always makes one attempt. The incumbent's `while (attempt <
|
|
967
940
|
* maxAttempts)` made none at `retryAttempts: 0` — a value the config validator
|
|
968
|
-
*
|
|
941
|
+
* then accepted, and now refuses — and then dereferenced an unassigned
|
|
942
|
+
* `lastError`. `retryAttempts` is the most attempts, the first included; an
|
|
943
|
+
* `HttpClient` constructed directly is not validated, so the first attempt
|
|
944
|
+
* stays unconditional.
|
|
945
|
+
*
|
|
946
|
+
* A request that would carry no `X-API-Key` makes none: it rejects with
|
|
947
|
+
* `MissingApiKeyError` before `fetch` is called, is not retried, and names
|
|
948
|
+
* `apiKey`. This is where a client built without a key learns it — the
|
|
949
|
+
* constructor accepts one so that a module-scope client can be evaluated by a
|
|
950
|
+
* build that holds no key (REL-1120) — and so does one whose `setApiKey` was
|
|
951
|
+
* given none.
|
|
969
952
|
*/
|
|
970
953
|
async request(config) {
|
|
954
|
+
if (config.timeout !== void 0) assertRequestTimeout(config.timeout);
|
|
971
955
|
const mergedConfig = this.mergeRequestConfig(config);
|
|
956
|
+
if (presentKey(headerValue(mergedConfig.headers, API_KEY_HEADER)) === void 0) {
|
|
957
|
+
throw new MissingApiKeyError(
|
|
958
|
+
"`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.",
|
|
959
|
+
{ url: mergedConfig.url, method: mergedConfig.method, sent: false }
|
|
960
|
+
);
|
|
961
|
+
}
|
|
972
962
|
this.log("debug", "Making request", {
|
|
973
963
|
method: mergedConfig.method,
|
|
974
964
|
url: mergedConfig.url
|
|
975
965
|
// Show the final URL with query params
|
|
976
966
|
});
|
|
977
967
|
if (config.method === "DELETE" && mergedConfig.headers) {
|
|
978
|
-
|
|
968
|
+
mergedConfig.headers = layerHeaders(mergedConfig.headers, { "Content-Type": null });
|
|
979
969
|
}
|
|
980
970
|
for (let attempt = 1; ; attempt++) {
|
|
981
971
|
try {
|
|
@@ -994,10 +984,10 @@ var _HttpClient = class _HttpClient {
|
|
|
994
984
|
attempt,
|
|
995
985
|
url: mergedConfig.url
|
|
996
986
|
});
|
|
997
|
-
if (this.retryPolicy.shouldRetry(attempt, failure, mergedConfig)) {
|
|
998
|
-
const delay = this.retryPolicy.delayFor(attempt, failure);
|
|
987
|
+
if (this.connection.retryPolicy.shouldRetry(attempt, failure, mergedConfig)) {
|
|
988
|
+
const delay = this.connection.retryPolicy.delayFor(attempt, failure);
|
|
999
989
|
this.log("debug", "Retrying request", { attempt, delay });
|
|
1000
|
-
await
|
|
990
|
+
await sleep(delay, config.signal);
|
|
1001
991
|
continue;
|
|
1002
992
|
}
|
|
1003
993
|
const sdkError = ErrorMapper.mapGenericError(failure, {
|
|
@@ -1067,34 +1057,60 @@ var _HttpClient = class _HttpClient {
|
|
|
1067
1057
|
});
|
|
1068
1058
|
}
|
|
1069
1059
|
/**
|
|
1070
|
-
*
|
|
1060
|
+
* Add headers to every later request, each replacing any header of the same name — the name
|
|
1061
|
+
* matched without regard to case — until the client is next configured.
|
|
1071
1062
|
*/
|
|
1072
1063
|
setDefaultHeaders(headers) {
|
|
1073
|
-
this.
|
|
1064
|
+
this.connection = {
|
|
1065
|
+
...this.connection,
|
|
1066
|
+
defaultHeaders: layerHeaders(this.connection.defaultHeaders, headers)
|
|
1067
|
+
};
|
|
1074
1068
|
}
|
|
1075
1069
|
/**
|
|
1076
|
-
*
|
|
1070
|
+
* Replace the key every later request sends as `X-API-Key`, and the `apiKey` the configuration
|
|
1071
|
+
* reports.
|
|
1072
|
+
*
|
|
1073
|
+
* The key is read the way construction reads it (`presentKey`): an absent, empty or blank key is
|
|
1074
|
+
* no key, so the header is dropped and the next request is refused with `MissingApiKeyError`
|
|
1075
|
+
* before anything is sent. A key header of any other spelling — one given in `headers` — goes
|
|
1076
|
+
* too, from the headers sent and from the headers the configuration reports, so the old key is
|
|
1077
|
+
* never sent beside the new one.
|
|
1078
|
+
*
|
|
1079
|
+
* The configuration is the one the owning `TypedRelyIOClient` holds (it hands its own to the
|
|
1080
|
+
* constructor), so its `getConfig().apiKey` — what a surface reads to decide a key's kind — is the
|
|
1081
|
+
* key sent from here on.
|
|
1082
|
+
*
|
|
1083
|
+
* This replaced `setAuthToken`, which added `Authorization: Bearer` beside an `X-API-Key` it
|
|
1084
|
+
* never touched: the API reads `X-API-Key` first, so the old key was the one used (REL-1385).
|
|
1077
1085
|
*/
|
|
1078
|
-
|
|
1079
|
-
|
|
1086
|
+
setApiKey(apiKey) {
|
|
1087
|
+
const { config } = this.connection;
|
|
1088
|
+
config.apiKey = apiKey;
|
|
1089
|
+
config.headers = layerHeaders(config.headers, { [API_KEY_HEADER]: null });
|
|
1090
|
+
this.connection = {
|
|
1091
|
+
...this.connection,
|
|
1092
|
+
defaultHeaders: layerHeaders(this.connection.defaultHeaders, {
|
|
1093
|
+
[API_KEY_HEADER]: presentKey(apiKey) ?? null
|
|
1094
|
+
})
|
|
1095
|
+
};
|
|
1080
1096
|
}
|
|
1081
1097
|
/**
|
|
1082
1098
|
* Get current default headers
|
|
1083
1099
|
*/
|
|
1084
1100
|
getDefaultHeaders() {
|
|
1085
|
-
return { ...this.defaultHeaders };
|
|
1101
|
+
return { ...this.connection.defaultHeaders };
|
|
1086
1102
|
}
|
|
1087
1103
|
/**
|
|
1088
1104
|
* Update base URL
|
|
1089
1105
|
*/
|
|
1090
1106
|
setBaseUrl(baseUrl) {
|
|
1091
|
-
this.
|
|
1107
|
+
this.connection = { ...this.connection, baseUrl };
|
|
1092
1108
|
}
|
|
1093
1109
|
/**
|
|
1094
1110
|
* Get current base URL
|
|
1095
1111
|
*/
|
|
1096
1112
|
getBaseUrl() {
|
|
1097
|
-
return this.baseUrl;
|
|
1113
|
+
return this.connection.baseUrl;
|
|
1098
1114
|
}
|
|
1099
1115
|
/**
|
|
1100
1116
|
* One attempt.
|
|
@@ -1116,7 +1132,7 @@ var _HttpClient = class _HttpClient {
|
|
|
1116
1132
|
const timeoutId = setTimeout(() => {
|
|
1117
1133
|
timedOut = true;
|
|
1118
1134
|
controller.abort();
|
|
1119
|
-
}, config.timeout ?? this.timeout);
|
|
1135
|
+
}, config.timeout ?? this.connection.timeout);
|
|
1120
1136
|
const onCallerAbort = /* @__PURE__ */ chunkMWMSFIWN_cjs.__name(() => controller.abort(), "onCallerAbort");
|
|
1121
1137
|
caller?.addEventListener("abort", onCallerAbort, { once: true });
|
|
1122
1138
|
try {
|
|
@@ -1126,10 +1142,15 @@ var _HttpClient = class _HttpClient {
|
|
|
1126
1142
|
headers: filteredHeaders,
|
|
1127
1143
|
body: this.prepareRequestBody(config),
|
|
1128
1144
|
signal: controller.signal,
|
|
1129
|
-
//
|
|
1130
|
-
|
|
1145
|
+
// Only in a browser — a `window` with a `document` (`isBrowser()`). A server or edge
|
|
1146
|
+
// runtime has no cookie jar for the mode to govern, so the field is left off and the
|
|
1147
|
+
// runtime's default stands; that includes Deno 1.x, whose global is a `window` with no
|
|
1148
|
+
// `document`. A Web Worker gets that default too: it has cookies but no `window`.
|
|
1149
|
+
...chunkTZL374LS_cjs.isBrowser() && {
|
|
1150
|
+
credentials: credentialsModeFor(this.connection.config.browser.includeCredentials)
|
|
1151
|
+
}
|
|
1131
1152
|
};
|
|
1132
|
-
const send = this.config.fetch ?? globalThis.fetch;
|
|
1153
|
+
const send = this.connection.config.fetch ?? globalThis.fetch;
|
|
1133
1154
|
const response = await send(url, requestInit);
|
|
1134
1155
|
clearTimeout(timeoutId);
|
|
1135
1156
|
const responseBody = await this.parseResponse(response);
|
|
@@ -1162,10 +1183,8 @@ var _HttpClient = class _HttpClient {
|
|
|
1162
1183
|
}
|
|
1163
1184
|
if (error instanceof DOMException && error.name === "AbortError") {
|
|
1164
1185
|
if (!timedOut && isAborted(caller)) throw error;
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
config.timeout ?? this.timeout
|
|
1168
|
-
);
|
|
1186
|
+
const timeout = config.timeout ?? this.connection.timeout;
|
|
1187
|
+
throw new TimeoutError(`Request timed out after ${timeout}ms`, timeout);
|
|
1169
1188
|
}
|
|
1170
1189
|
if (error instanceof TypeError && error.message.includes("CORS")) {
|
|
1171
1190
|
const corsError = new NetworkError(
|
|
@@ -1179,9 +1198,10 @@ var _HttpClient = class _HttpClient {
|
|
|
1179
1198
|
suggestion: "Check if the API server allows requests from your domain and has proper CORS headers configured."
|
|
1180
1199
|
}
|
|
1181
1200
|
);
|
|
1182
|
-
|
|
1201
|
+
const { onCorsError } = this.connection.config.browser;
|
|
1202
|
+
if (chunkTZL374LS_cjs.isBrowser() && onCorsError) {
|
|
1183
1203
|
try {
|
|
1184
|
-
|
|
1204
|
+
onCorsError(corsError, {
|
|
1185
1205
|
url: config.url,
|
|
1186
1206
|
method: config.method,
|
|
1187
1207
|
originalError: error
|
|
@@ -1198,20 +1218,20 @@ var _HttpClient = class _HttpClient {
|
|
|
1198
1218
|
}
|
|
1199
1219
|
}
|
|
1200
1220
|
/**
|
|
1201
|
-
*
|
|
1221
|
+
* The headers without those a browser controls itself, when this is a browser; unchanged when it
|
|
1222
|
+
* is not.
|
|
1223
|
+
*
|
|
1224
|
+
* A name is matched without regard to case (RFC 9110 §5.1), because a browser refuses `Origin`
|
|
1225
|
+
* whatever case a page spells it in. This matched only the all-lowercase and all-uppercase
|
|
1226
|
+
* spellings, so `Origin` and `User-Agent` — how people write them — reached `fetch` (REL-1409).
|
|
1202
1227
|
*/
|
|
1203
1228
|
filterHeadersForBrowser(headers) {
|
|
1204
|
-
if (
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
delete filteredHeaders[header.toUpperCase()];
|
|
1211
|
-
});
|
|
1212
|
-
return filteredHeaders;
|
|
1213
|
-
}
|
|
1214
|
-
return headers;
|
|
1229
|
+
if (!chunkTZL374LS_cjs.isBrowser()) return headers;
|
|
1230
|
+
return Object.fromEntries(
|
|
1231
|
+
Object.entries(headers).filter(
|
|
1232
|
+
([name]) => !BROWSER_CONTROLLED_HEADERS.has(name.toLowerCase())
|
|
1233
|
+
)
|
|
1234
|
+
);
|
|
1215
1235
|
}
|
|
1216
1236
|
/**
|
|
1217
1237
|
* Prepare request body based on content type and environment
|
|
@@ -1247,7 +1267,7 @@ var _HttpClient = class _HttpClient {
|
|
|
1247
1267
|
if (url.startsWith("http://") || url.startsWith("https://")) {
|
|
1248
1268
|
return url;
|
|
1249
1269
|
}
|
|
1250
|
-
return `${this.baseUrl}${url.startsWith("/") ? "" : "/"}${url}`;
|
|
1270
|
+
return `${this.connection.baseUrl}${url.startsWith("/") ? "" : "/"}${url}`;
|
|
1251
1271
|
}
|
|
1252
1272
|
mergeRequestConfig(config) {
|
|
1253
1273
|
const url = this.resolveUrl(config.url);
|
|
@@ -1256,11 +1276,11 @@ var _HttpClient = class _HttpClient {
|
|
|
1256
1276
|
return {
|
|
1257
1277
|
...config,
|
|
1258
1278
|
url: finalUrl,
|
|
1259
|
-
headers:
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
timeout: config.timeout ?? this.timeout
|
|
1279
|
+
// The request's own headers replace the client's of the same name, whatever the case: a
|
|
1280
|
+
// per-request `x-relyio-dataset` sent beside the client's `X-RelyIO-Dataset` is one header
|
|
1281
|
+
// `Headers` joins into `main, staging`.
|
|
1282
|
+
headers: layerHeaders(this.connection.defaultHeaders, config.headers),
|
|
1283
|
+
timeout: config.timeout ?? this.connection.timeout
|
|
1264
1284
|
};
|
|
1265
1285
|
}
|
|
1266
1286
|
buildQueryString(params) {
|
|
@@ -1283,26 +1303,11 @@ var _HttpClient = class _HttpClient {
|
|
|
1283
1303
|
});
|
|
1284
1304
|
return obj;
|
|
1285
1305
|
}
|
|
1286
|
-
/** A backoff the caller's abort cuts short; the next attempt then refuses to send. */
|
|
1287
|
-
sleep(ms, signal) {
|
|
1288
|
-
return new Promise((resolve) => {
|
|
1289
|
-
if (isAborted(signal)) {
|
|
1290
|
-
resolve();
|
|
1291
|
-
return;
|
|
1292
|
-
}
|
|
1293
|
-
const done = /* @__PURE__ */ chunkMWMSFIWN_cjs.__name(() => {
|
|
1294
|
-
clearTimeout(timer);
|
|
1295
|
-
signal?.removeEventListener("abort", done);
|
|
1296
|
-
resolve();
|
|
1297
|
-
}, "done");
|
|
1298
|
-
const timer = setTimeout(done, ms);
|
|
1299
|
-
signal?.addEventListener("abort", done, { once: true });
|
|
1300
|
-
});
|
|
1301
|
-
}
|
|
1302
1306
|
log(level, message, data) {
|
|
1303
|
-
|
|
1304
|
-
if (
|
|
1305
|
-
|
|
1307
|
+
const { debug } = this.connection.config;
|
|
1308
|
+
if (!debug.enabled) return;
|
|
1309
|
+
if (debug.logger != null) {
|
|
1310
|
+
debug.logger(level, message, data);
|
|
1306
1311
|
} else {
|
|
1307
1312
|
console.log(`[RelyIO SDK ${level.toUpperCase()}] ${message}`, data ?? "");
|
|
1308
1313
|
}
|
|
@@ -1310,17 +1315,105 @@ var _HttpClient = class _HttpClient {
|
|
|
1310
1315
|
};
|
|
1311
1316
|
chunkMWMSFIWN_cjs.__name(_HttpClient, "HttpClient");
|
|
1312
1317
|
var HttpClient = _HttpClient;
|
|
1313
|
-
|
|
1314
|
-
|
|
1318
|
+
var API_KEY_HEADER = "X-API-Key";
|
|
1319
|
+
var DATASET_HEADER = "X-RelyIO-Dataset";
|
|
1320
|
+
var BROWSER_CONTROLLED_HEADERS = /* @__PURE__ */ new Set([
|
|
1321
|
+
"user-agent",
|
|
1322
|
+
"referer",
|
|
1323
|
+
"origin",
|
|
1324
|
+
"host",
|
|
1325
|
+
"connection",
|
|
1326
|
+
"upgrade"
|
|
1327
|
+
]);
|
|
1328
|
+
function connectionFor(config) {
|
|
1329
|
+
const globalWithVersion = globalThis;
|
|
1330
|
+
const defaultHeaders = layerHeaders(
|
|
1331
|
+
layerHeaders({ "Content-Type": "application/json" }, config.headers),
|
|
1332
|
+
{
|
|
1333
|
+
[API_KEY_HEADER]: presentKey(config.apiKey),
|
|
1334
|
+
[DATASET_HEADER]: config.dataset,
|
|
1335
|
+
// Only outside a browser, which controls this header. "A browser" is the core's one
|
|
1336
|
+
// definition, `isBrowser()` — every environment question in this file asks it.
|
|
1337
|
+
"User-Agent": chunkTZL374LS_cjs.isBrowser() ? void 0 : `RelyIO-SDK/${globalWithVersion.__VERSION__ ?? "0.0.0"}`
|
|
1338
|
+
}
|
|
1339
|
+
);
|
|
1340
|
+
return {
|
|
1341
|
+
config,
|
|
1342
|
+
baseUrl: config.baseUrl,
|
|
1343
|
+
defaultHeaders,
|
|
1344
|
+
timeout: config.timeout,
|
|
1345
|
+
// The policy, not a predicate over `(error, attempt)`: whether a request may be sent again is a
|
|
1346
|
+
// property of the **route** as much as of the refusal, and a callback that never sees the
|
|
1347
|
+
// request cannot express that.
|
|
1348
|
+
retryPolicy: new DefaultRetryPolicy({
|
|
1349
|
+
maxAttempts: config.retryAttempts,
|
|
1350
|
+
baseDelay: 1e3,
|
|
1351
|
+
maxDelay: 1e4,
|
|
1352
|
+
backoffFactor: 2,
|
|
1353
|
+
jitter: true
|
|
1354
|
+
})
|
|
1355
|
+
};
|
|
1315
1356
|
}
|
|
1316
|
-
chunkMWMSFIWN_cjs.__name(
|
|
1357
|
+
chunkMWMSFIWN_cjs.__name(connectionFor, "connectionFor");
|
|
1358
|
+
function layerHeaders(base, over) {
|
|
1359
|
+
const layered = { ...base };
|
|
1360
|
+
for (const [name, value] of Object.entries(over ?? {})) {
|
|
1361
|
+
if (value === void 0) continue;
|
|
1362
|
+
const lower = name.toLowerCase();
|
|
1363
|
+
for (const existing of Object.keys(layered)) {
|
|
1364
|
+
if (existing.toLowerCase() === lower) delete layered[existing];
|
|
1365
|
+
}
|
|
1366
|
+
if (value !== null) layered[name] = value;
|
|
1367
|
+
}
|
|
1368
|
+
return layered;
|
|
1369
|
+
}
|
|
1370
|
+
chunkMWMSFIWN_cjs.__name(layerHeaders, "layerHeaders");
|
|
1371
|
+
function presentKey(value) {
|
|
1372
|
+
return typeof value === "string" && value.trim() !== "" ? value : void 0;
|
|
1373
|
+
}
|
|
1374
|
+
chunkMWMSFIWN_cjs.__name(presentKey, "presentKey");
|
|
1375
|
+
function credentialsModeFor(includeCredentials) {
|
|
1376
|
+
return includeCredentials ? "include" : "same-origin";
|
|
1377
|
+
}
|
|
1378
|
+
chunkMWMSFIWN_cjs.__name(credentialsModeFor, "credentialsModeFor");
|
|
1379
|
+
|
|
1380
|
+
// src/content/client-locale.ts
|
|
1381
|
+
function callLocale(named, clientLocale) {
|
|
1382
|
+
if (named !== void 0) return named;
|
|
1383
|
+
return clientLocale === void 0 || clientLocale === "" ? void 0 : clientLocale;
|
|
1384
|
+
}
|
|
1385
|
+
chunkMWMSFIWN_cjs.__name(callLocale, "callLocale");
|
|
1386
|
+
function readClientLocale(locale) {
|
|
1387
|
+
return typeof locale === "function" ? locale : () => locale;
|
|
1388
|
+
}
|
|
1389
|
+
chunkMWMSFIWN_cjs.__name(readClientLocale, "readClientLocale");
|
|
1317
1390
|
|
|
1318
1391
|
// src/content/query-builder.ts
|
|
1392
|
+
function namesMetadata(key) {
|
|
1393
|
+
return key === "_metadata" || key.startsWith("_metadata.");
|
|
1394
|
+
}
|
|
1395
|
+
chunkMWMSFIWN_cjs.__name(namesMetadata, "namesMetadata");
|
|
1396
|
+
function refuseMetadataConditions(conditions) {
|
|
1397
|
+
const named = Object.keys(conditions).filter(namesMetadata);
|
|
1398
|
+
if (named.length === 0) return;
|
|
1399
|
+
throw new ValidationError(
|
|
1400
|
+
`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.`,
|
|
1401
|
+
named.map((field) => ({
|
|
1402
|
+
field,
|
|
1403
|
+
code: "METADATA_CONDITION",
|
|
1404
|
+
message: `${field} is not a field the API can filter on`
|
|
1405
|
+
}))
|
|
1406
|
+
);
|
|
1407
|
+
}
|
|
1408
|
+
chunkMWMSFIWN_cjs.__name(refuseMetadataConditions, "refuseMetadataConditions");
|
|
1319
1409
|
var _ContentQueryBuilder = class _ContentQueryBuilder {
|
|
1320
|
-
|
|
1410
|
+
/**
|
|
1411
|
+
* @param locale - The client's locale (`withLocale()`, `updateConfig({ locale })`), sent when the
|
|
1412
|
+
* query names none: the function `TypedRelyIOClient` hands over, or a locale fixed for it
|
|
1413
|
+
*/
|
|
1414
|
+
constructor(httpClient, contentType, locale) {
|
|
1321
1415
|
this.httpClient = httpClient;
|
|
1322
1416
|
this.contentType = contentType;
|
|
1323
|
-
this.defaultLocale = defaultLocale;
|
|
1324
1417
|
chunkMWMSFIWN_cjs.__publicField(this, "queryOptions", {});
|
|
1325
1418
|
chunkMWMSFIWN_cjs.__publicField(this, "localeValue");
|
|
1326
1419
|
chunkMWMSFIWN_cjs.__publicField(this, "localesArray");
|
|
@@ -1329,11 +1422,26 @@ var _ContentQueryBuilder = class _ContentQueryBuilder {
|
|
|
1329
1422
|
chunkMWMSFIWN_cjs.__publicField(this, "childrenOptions");
|
|
1330
1423
|
chunkMWMSFIWN_cjs.__publicField(this, "pageNumber");
|
|
1331
1424
|
chunkMWMSFIWN_cjs.__publicField(this, "pageSizeValue");
|
|
1425
|
+
chunkMWMSFIWN_cjs.__publicField(this, "requestHeaders");
|
|
1426
|
+
/** The client's locale, asked when the query is sent rather than copied when it was built. */
|
|
1427
|
+
chunkMWMSFIWN_cjs.__publicField(this, "clientLocale");
|
|
1428
|
+
this.clientLocale = readClientLocale(locale);
|
|
1429
|
+
}
|
|
1430
|
+
/**
|
|
1431
|
+
* Headers this query adds to the client's own, e.g. `X-RelyIO-Dataset` to list another dataset
|
|
1432
|
+
* the key can see. A name the client already sends is replaced for this query only; the client
|
|
1433
|
+
* is not changed.
|
|
1434
|
+
*/
|
|
1435
|
+
headers(headers) {
|
|
1436
|
+
this.requestHeaders = headers;
|
|
1437
|
+
return this;
|
|
1332
1438
|
}
|
|
1333
1439
|
/**
|
|
1334
|
-
* Add where conditions to the query
|
|
1440
|
+
* Add where conditions to the query: conditions on the fields the content type declares. A
|
|
1441
|
+
* condition on `_metadata` is refused here, before anything is sent (`refuseMetadataConditions`).
|
|
1335
1442
|
*/
|
|
1336
1443
|
where(conditions) {
|
|
1444
|
+
refuseMetadataConditions(conditions);
|
|
1337
1445
|
this.queryOptions.where = {
|
|
1338
1446
|
...this.queryOptions.where,
|
|
1339
1447
|
...conditions
|
|
@@ -1526,7 +1634,11 @@ var _ContentQueryBuilder = class _ContentQueryBuilder {
|
|
|
1526
1634
|
const response = await this.httpClient.send(
|
|
1527
1635
|
"/v1/{contentType}",
|
|
1528
1636
|
"get",
|
|
1529
|
-
{
|
|
1637
|
+
{
|
|
1638
|
+
path: { contentType: this.contentType },
|
|
1639
|
+
query: this.buildQueryParams(),
|
|
1640
|
+
headers: this.requestHeaders
|
|
1641
|
+
}
|
|
1530
1642
|
);
|
|
1531
1643
|
return response.body;
|
|
1532
1644
|
}
|
|
@@ -1586,7 +1698,11 @@ var _ContentQueryBuilder = class _ContentQueryBuilder {
|
|
|
1586
1698
|
* Clone the query builder
|
|
1587
1699
|
*/
|
|
1588
1700
|
clone() {
|
|
1589
|
-
const cloned = new _ContentQueryBuilder(
|
|
1701
|
+
const cloned = new _ContentQueryBuilder(
|
|
1702
|
+
this.httpClient,
|
|
1703
|
+
this.contentType,
|
|
1704
|
+
this.clientLocale
|
|
1705
|
+
);
|
|
1590
1706
|
cloned.queryOptions = JSON.parse(JSON.stringify(this.queryOptions));
|
|
1591
1707
|
cloned.localeValue = this.localeValue;
|
|
1592
1708
|
cloned.localesArray = this.localesArray ? [...this.localesArray] : void 0;
|
|
@@ -1594,6 +1710,7 @@ var _ContentQueryBuilder = class _ContentQueryBuilder {
|
|
|
1594
1710
|
cloned.fieldsProjection = this.fieldsProjection ? [...this.fieldsProjection] : void 0;
|
|
1595
1711
|
cloned.pageNumber = this.pageNumber;
|
|
1596
1712
|
cloned.pageSizeValue = this.pageSizeValue;
|
|
1713
|
+
cloned.requestHeaders = this.requestHeaders ? { ...this.requestHeaders } : void 0;
|
|
1597
1714
|
return cloned;
|
|
1598
1715
|
}
|
|
1599
1716
|
/**
|
|
@@ -1660,14 +1777,15 @@ var _ContentQueryBuilder = class _ContentQueryBuilder {
|
|
|
1660
1777
|
if (this.queryOptions.cursor !== void 0) {
|
|
1661
1778
|
params.cursor = this.queryOptions.cursor;
|
|
1662
1779
|
}
|
|
1780
|
+
const clientLocale = this.clientLocale();
|
|
1663
1781
|
if (this.localeValue != null && this.localeValue !== "") {
|
|
1664
1782
|
params.locale = this.localeValue;
|
|
1665
1783
|
} else if (this.fetchAllLocales) {
|
|
1666
1784
|
params.locale = "*";
|
|
1667
1785
|
} else if (this.localesArray && this.localesArray.length > 0) {
|
|
1668
1786
|
params.locales = this.localesArray.join(",");
|
|
1669
|
-
} else if (
|
|
1670
|
-
params.locale =
|
|
1787
|
+
} else if (clientLocale != null && clientLocale !== "") {
|
|
1788
|
+
params.locale = clientLocale;
|
|
1671
1789
|
}
|
|
1672
1790
|
if (this.pageNumber !== void 0) {
|
|
1673
1791
|
params.page = this.pageNumber;
|
|
@@ -1691,16 +1809,23 @@ var _ContentQueryBuilder = class _ContentQueryBuilder {
|
|
|
1691
1809
|
chunkMWMSFIWN_cjs.__name(_ContentQueryBuilder, "ContentQueryBuilder");
|
|
1692
1810
|
var ContentQueryBuilder = _ContentQueryBuilder;
|
|
1693
1811
|
var _ContentByIdBuilder = class _ContentByIdBuilder {
|
|
1694
|
-
|
|
1812
|
+
/**
|
|
1813
|
+
* @param locale - The client's locale (`withLocale()`, `updateConfig({ locale })`), sent when the
|
|
1814
|
+
* read names none: the function `TypedRelyIOClient` hands over, or a locale fixed for it
|
|
1815
|
+
*/
|
|
1816
|
+
constructor(httpClient, contentType, id, locale) {
|
|
1695
1817
|
this.httpClient = httpClient;
|
|
1696
1818
|
this.contentType = contentType;
|
|
1697
1819
|
this.id = id;
|
|
1698
|
-
this.defaultLocale = defaultLocale;
|
|
1699
1820
|
chunkMWMSFIWN_cjs.__publicField(this, "includeRelations");
|
|
1700
1821
|
chunkMWMSFIWN_cjs.__publicField(this, "localeValue");
|
|
1701
1822
|
chunkMWMSFIWN_cjs.__publicField(this, "localesArray");
|
|
1702
1823
|
chunkMWMSFIWN_cjs.__publicField(this, "fetchAllLocales", false);
|
|
1703
1824
|
chunkMWMSFIWN_cjs.__publicField(this, "childrenOptions");
|
|
1825
|
+
chunkMWMSFIWN_cjs.__publicField(this, "requestHeaders");
|
|
1826
|
+
/** The client's locale, asked when the read is sent rather than copied when it was built. */
|
|
1827
|
+
chunkMWMSFIWN_cjs.__publicField(this, "clientLocale");
|
|
1828
|
+
this.clientLocale = readClientLocale(locale);
|
|
1704
1829
|
}
|
|
1705
1830
|
/**
|
|
1706
1831
|
* Include related content in the response
|
|
@@ -1731,6 +1856,15 @@ var _ContentByIdBuilder = class _ContentByIdBuilder {
|
|
|
1731
1856
|
this.fetchAllLocales = false;
|
|
1732
1857
|
return this;
|
|
1733
1858
|
}
|
|
1859
|
+
/**
|
|
1860
|
+
* Headers this one read adds to the client's own, e.g. `X-RelyIO-Dataset` to read another dataset
|
|
1861
|
+
* the key can see. A name the client already sends is replaced for this request only; the client
|
|
1862
|
+
* is not changed.
|
|
1863
|
+
*/
|
|
1864
|
+
headers(headers) {
|
|
1865
|
+
this.requestHeaders = headers;
|
|
1866
|
+
return this;
|
|
1867
|
+
}
|
|
1734
1868
|
/**
|
|
1735
1869
|
* Fetch content in all available locales
|
|
1736
1870
|
* Returns default locale at top level, others in _metadata.localizations
|
|
@@ -1761,14 +1895,15 @@ var _ContentByIdBuilder = class _ContentByIdBuilder {
|
|
|
1761
1895
|
if (this.includeRelations != null) {
|
|
1762
1896
|
params.include = this.includeRelations.join(",");
|
|
1763
1897
|
}
|
|
1898
|
+
const clientLocale = this.clientLocale();
|
|
1764
1899
|
if (this.localeValue != null && this.localeValue !== "") {
|
|
1765
1900
|
params.locale = this.localeValue;
|
|
1766
1901
|
} else if (this.fetchAllLocales) {
|
|
1767
1902
|
params.locale = "*";
|
|
1768
1903
|
} else if (this.localesArray && this.localesArray.length > 0) {
|
|
1769
1904
|
params.locales = this.localesArray.join(",");
|
|
1770
|
-
} else if (
|
|
1771
|
-
params.locale =
|
|
1905
|
+
} else if (clientLocale != null && clientLocale !== "") {
|
|
1906
|
+
params.locale = clientLocale;
|
|
1772
1907
|
}
|
|
1773
1908
|
if (this.childrenOptions != null) {
|
|
1774
1909
|
if (this.childrenOptions.contentTypes) {
|
|
@@ -1784,7 +1919,11 @@ var _ContentByIdBuilder = class _ContentByIdBuilder {
|
|
|
1784
1919
|
return await this.httpClient.fetchPayload(
|
|
1785
1920
|
"/v1/{contentType}/{id}",
|
|
1786
1921
|
"get",
|
|
1787
|
-
{
|
|
1922
|
+
{
|
|
1923
|
+
path: { contentType: this.contentType, id: this.id },
|
|
1924
|
+
query: params,
|
|
1925
|
+
headers: this.requestHeaders
|
|
1926
|
+
}
|
|
1788
1927
|
);
|
|
1789
1928
|
} catch (error) {
|
|
1790
1929
|
if (isResourceNotFound(error)) return null;
|
|
@@ -1814,6 +1953,14 @@ function writeHeaders(options) {
|
|
|
1814
1953
|
return Object.keys(headers).length > 0 ? headers : void 0;
|
|
1815
1954
|
}
|
|
1816
1955
|
chunkMWMSFIWN_cjs.__name(writeHeaders, "writeHeaders");
|
|
1956
|
+
function requestHeaders(headers, typed) {
|
|
1957
|
+
if (headers === void 0) return typed;
|
|
1958
|
+
if (typed === void 0) return headers;
|
|
1959
|
+
const typedNames = new Set(Object.keys(typed).map((name) => name.toLowerCase()));
|
|
1960
|
+
const own = Object.entries(headers).filter(([name]) => !typedNames.has(name.toLowerCase()));
|
|
1961
|
+
return { ...Object.fromEntries(own), ...typed };
|
|
1962
|
+
}
|
|
1963
|
+
chunkMWMSFIWN_cjs.__name(requestHeaders, "requestHeaders");
|
|
1817
1964
|
function entityTagOf(response) {
|
|
1818
1965
|
return headerValue(response.headers, HEADER_ENTITY_TAG.name);
|
|
1819
1966
|
}
|
|
@@ -1821,22 +1968,28 @@ chunkMWMSFIWN_cjs.__name(entityTagOf, "entityTagOf");
|
|
|
1821
1968
|
|
|
1822
1969
|
// src/content/content-client.ts
|
|
1823
1970
|
var _ContentClient = class _ContentClient {
|
|
1824
|
-
|
|
1971
|
+
/**
|
|
1972
|
+
* @param locale - The client's locale: the function `TypedRelyIOClient` hands over, asked on
|
|
1973
|
+
* every call, or a locale fixed for this client
|
|
1974
|
+
*/
|
|
1975
|
+
constructor(httpClient, contentType, locale) {
|
|
1825
1976
|
this.httpClient = httpClient;
|
|
1826
1977
|
this.contentType = contentType;
|
|
1827
|
-
this.
|
|
1978
|
+
/** The client's locale, asked on every call rather than copied when this client was taken. */
|
|
1979
|
+
chunkMWMSFIWN_cjs.__publicField(this, "clientLocale");
|
|
1980
|
+
this.clientLocale = readClientLocale(locale);
|
|
1828
1981
|
}
|
|
1829
1982
|
/**
|
|
1830
1983
|
* Create a new query builder for this content type
|
|
1831
1984
|
*/
|
|
1832
1985
|
query() {
|
|
1833
|
-
return new ContentQueryBuilder(this.httpClient, this.contentType, this.
|
|
1986
|
+
return new ContentQueryBuilder(this.httpClient, this.contentType, this.clientLocale);
|
|
1834
1987
|
}
|
|
1835
1988
|
/**
|
|
1836
1989
|
* Find content by ID with fluent options
|
|
1837
1990
|
*/
|
|
1838
1991
|
findById(id) {
|
|
1839
|
-
return new ContentByIdBuilder(this.httpClient, this.contentType, id, this.
|
|
1992
|
+
return new ContentByIdBuilder(this.httpClient, this.contentType, id, this.clientLocale);
|
|
1840
1993
|
}
|
|
1841
1994
|
/**
|
|
1842
1995
|
* Fetch all content items
|
|
@@ -1883,7 +2036,8 @@ var _ContentClient = class _ContentClient {
|
|
|
1883
2036
|
/**
|
|
1884
2037
|
* Fetch a single content item by ID
|
|
1885
2038
|
* @param id - Entry ID or slug
|
|
1886
|
-
* @param options - Fetch options (include, locale
|
|
2039
|
+
* @param options - Fetch options (include, locale, and `headers` this one request adds — e.g.
|
|
2040
|
+
* `{ 'X-RelyIO-Dataset': 'staging' }` to read a dataset other than the client's)
|
|
1887
2041
|
*/
|
|
1888
2042
|
async fetchOne(id, options) {
|
|
1889
2043
|
const builder = this.findById(id);
|
|
@@ -1893,6 +2047,9 @@ var _ContentClient = class _ContentClient {
|
|
|
1893
2047
|
if (options?.locale != null && options.locale !== "") {
|
|
1894
2048
|
builder.locale(options.locale);
|
|
1895
2049
|
}
|
|
2050
|
+
if (options?.headers != null) {
|
|
2051
|
+
builder.headers(options.headers);
|
|
2052
|
+
}
|
|
1896
2053
|
return builder.execute();
|
|
1897
2054
|
}
|
|
1898
2055
|
/**
|
|
@@ -1907,16 +2064,21 @@ var _ContentClient = class _ContentClient {
|
|
|
1907
2064
|
* `entityTag` is `undefined` when the response came from the cache: a cached
|
|
1908
2065
|
* body cannot know the current version, and an absent tag beats a stale one
|
|
1909
2066
|
* that would refuse the next write.
|
|
2067
|
+
*
|
|
2068
|
+
* Unlike {@link fetchOne}, a missing entry is not `null`: the service's
|
|
2069
|
+
* `RESOURCE_NOT_FOUND` is thrown as it arrived, with the `kind` that says
|
|
2070
|
+
* whether the entry, the content type or the schema was missing. `headers`
|
|
2071
|
+
* are the ones this read adds, as for `fetchOne`.
|
|
1910
2072
|
*/
|
|
1911
2073
|
async fetchOneWithTag(id, options) {
|
|
1912
2074
|
const query = {};
|
|
1913
2075
|
if (options?.include != null) query.include = options.include.join(",");
|
|
1914
|
-
const locale = options?.locale ?? this.
|
|
2076
|
+
const locale = options?.locale ?? this.clientLocale();
|
|
1915
2077
|
if (locale != null && locale !== "") query.locale = locale;
|
|
1916
2078
|
const response = await this.httpClient.send(
|
|
1917
2079
|
"/v1/{contentType}/{id}",
|
|
1918
2080
|
"get",
|
|
1919
|
-
{ path: { contentType: this.contentType, id }, query }
|
|
2081
|
+
{ path: { contentType: this.contentType, id }, query, headers: options?.headers }
|
|
1920
2082
|
);
|
|
1921
2083
|
return { entry: readPayload(response.body), entityTag: entityTagOf(response) };
|
|
1922
2084
|
}
|
|
@@ -1938,17 +2100,21 @@ var _ContentClient = class _ContentClient {
|
|
|
1938
2100
|
/**
|
|
1939
2101
|
* Create a new content item
|
|
1940
2102
|
* @param data - Content data
|
|
1941
|
-
* @param options - Create options (slug, locale, parentId, sortOrder)
|
|
2103
|
+
* @param options - Create options (slug, locale, parentId, sortOrder), and `headers` this one
|
|
2104
|
+
* request adds — e.g. `{ 'X-RelyIO-Dataset': 'staging' }` to write a dataset other than the
|
|
2105
|
+
* client's. They are sent, never put in the body; `idempotencyKey` still wins over an
|
|
2106
|
+
* `Idempotency-Key` among them. `locale` defaults to the client's own (`withLocale()`).
|
|
1942
2107
|
*/
|
|
1943
2108
|
async create(data, options) {
|
|
1944
|
-
const { idempotencyKey, ...body } = options ?? {};
|
|
2109
|
+
const { idempotencyKey, headers, locale, ...body } = options ?? {};
|
|
2110
|
+
const sent = callLocale(locale, this.clientLocale());
|
|
1945
2111
|
return this.httpClient.fetchPayload(
|
|
1946
2112
|
"/v1/{contentType}",
|
|
1947
2113
|
"post",
|
|
1948
2114
|
{
|
|
1949
2115
|
path: { contentType: this.contentType },
|
|
1950
|
-
body: { content: data, ...body },
|
|
1951
|
-
headers: writeHeaders({ idempotencyKey })
|
|
2116
|
+
body: { content: data, ...body, ...sent === void 0 ? {} : { locale: sent } },
|
|
2117
|
+
headers: requestHeaders(headers, writeHeaders({ idempotencyKey }))
|
|
1952
2118
|
}
|
|
1953
2119
|
);
|
|
1954
2120
|
}
|
|
@@ -1956,17 +2122,21 @@ var _ContentClient = class _ContentClient {
|
|
|
1956
2122
|
* Update a content item by ID (partial update)
|
|
1957
2123
|
* @param id - Entry ID
|
|
1958
2124
|
* @param data - Fields to update
|
|
1959
|
-
* @param options - Update options (slug, locale, parentId, sortOrder)
|
|
2125
|
+
* @param options - Update options (slug, locale, parentId, sortOrder), and `headers` this one
|
|
2126
|
+
* request adds, as for {@link create}. `ifMatch` and `idempotencyKey` win over the same
|
|
2127
|
+
* header among them. `locale` defaults to the client's own, the locale whose entity tag
|
|
2128
|
+
* {@link fetchOneWithTag} reads, so the tag it hands back is checked against the same locale.
|
|
1960
2129
|
*/
|
|
1961
2130
|
async update(id, data, options) {
|
|
1962
|
-
const { idempotencyKey, ifMatch, ...body } = options ?? {};
|
|
2131
|
+
const { idempotencyKey, ifMatch, headers, locale, ...body } = options ?? {};
|
|
2132
|
+
const sent = callLocale(locale, this.clientLocale());
|
|
1963
2133
|
return this.httpClient.fetchPayload(
|
|
1964
2134
|
"/v1/{contentType}/{id}",
|
|
1965
2135
|
"patch",
|
|
1966
2136
|
{
|
|
1967
2137
|
path: { contentType: this.contentType, id },
|
|
1968
|
-
body: { content: data, ...body },
|
|
1969
|
-
headers: writeHeaders({ idempotencyKey, ifMatch })
|
|
2138
|
+
body: { content: data, ...body, ...sent === void 0 ? {} : { locale: sent } },
|
|
2139
|
+
headers: requestHeaders(headers, writeHeaders({ idempotencyKey, ifMatch }))
|
|
1970
2140
|
}
|
|
1971
2141
|
);
|
|
1972
2142
|
}
|
|
@@ -1997,32 +2167,35 @@ var _ContentClient = class _ContentClient {
|
|
|
1997
2167
|
* Get version history for one locale of an entry.
|
|
1998
2168
|
*
|
|
1999
2169
|
* Versions are numbered per locale, so this is one locale's timeline: `locale` defaults to the
|
|
2000
|
-
* schema default
|
|
2001
|
-
* rather than another locale's rows. Every row names the
|
|
2170
|
+
* client's own (`withLocale()`), else the schema default; no fallback is applied, and a locale
|
|
2171
|
+
* with no history returns an empty array rather than another locale's rows. Every row names the
|
|
2172
|
+
* locale it belongs to.
|
|
2002
2173
|
*/
|
|
2003
2174
|
async versions(id, options) {
|
|
2175
|
+
const locale = callLocale(options?.locale, this.clientLocale());
|
|
2004
2176
|
return this.httpClient.fetchPayload("/v1/{contentType}/{id}/versions", "get", {
|
|
2005
2177
|
path: { contentType: this.contentType, id },
|
|
2006
2178
|
query: {
|
|
2007
2179
|
limit: options?.limit ?? 10,
|
|
2008
|
-
...
|
|
2180
|
+
...locale === void 0 ? {} : { locale }
|
|
2009
2181
|
}
|
|
2010
2182
|
});
|
|
2011
2183
|
}
|
|
2012
2184
|
/**
|
|
2013
2185
|
* Get a specific version of an entry.
|
|
2014
2186
|
*
|
|
2015
|
-
* `locale` defaults to the
|
|
2016
|
-
* different content in each one.
|
|
2187
|
+
* `locale` defaults to the client's own (`withLocale()`), else the schema default. Version
|
|
2188
|
+
* numbers are per locale, so version 2 is different content in each one.
|
|
2017
2189
|
*/
|
|
2018
2190
|
async version(id, versionNumber, options) {
|
|
2191
|
+
const locale = callLocale(options?.locale, this.clientLocale());
|
|
2019
2192
|
return this.httpClient.fetchPayload("/v1/{contentType}/{id}/versions/{versionNumber}", "get", {
|
|
2020
2193
|
path: {
|
|
2021
2194
|
contentType: this.contentType,
|
|
2022
2195
|
id,
|
|
2023
2196
|
versionNumber: String(versionNumber)
|
|
2024
2197
|
},
|
|
2025
|
-
query:
|
|
2198
|
+
query: locale === void 0 ? void 0 : { locale }
|
|
2026
2199
|
});
|
|
2027
2200
|
}
|
|
2028
2201
|
/**
|
|
@@ -2061,8 +2234,9 @@ var _ContentClient = class _ContentClient {
|
|
|
2061
2234
|
if (options?.include != null) {
|
|
2062
2235
|
params.include = options.include.join(",");
|
|
2063
2236
|
}
|
|
2064
|
-
|
|
2065
|
-
|
|
2237
|
+
const locale = options?.locale ?? this.clientLocale();
|
|
2238
|
+
if (locale != null && locale !== "") {
|
|
2239
|
+
params.locale = locale;
|
|
2066
2240
|
}
|
|
2067
2241
|
return this.httpClient.fetchPayload(
|
|
2068
2242
|
"/v1/{contentType}/{id}/children",
|
|
@@ -2080,19 +2254,20 @@ var _ContentClient = class _ContentClient {
|
|
|
2080
2254
|
* Create a new ContentClient for a different content type
|
|
2081
2255
|
*/
|
|
2082
2256
|
ofType(contentType) {
|
|
2083
|
-
return new _ContentClient(this.httpClient, contentType, this.
|
|
2257
|
+
return new _ContentClient(this.httpClient, contentType, this.clientLocale);
|
|
2084
2258
|
}
|
|
2085
2259
|
/**
|
|
2086
|
-
* Create a new ContentClient with a different default locale
|
|
2260
|
+
* Create a new ContentClient with a different default locale, fixed: an update of the client's
|
|
2261
|
+
* locale (`updateConfig({ locale })`) does not reach it
|
|
2087
2262
|
*/
|
|
2088
2263
|
withLocale(locale) {
|
|
2089
2264
|
return new _ContentClient(this.httpClient, this.contentType, locale);
|
|
2090
2265
|
}
|
|
2091
2266
|
/**
|
|
2092
|
-
* Get the
|
|
2267
|
+
* Get the default locale as it is now: the client's, or the one `withLocale()` fixed
|
|
2093
2268
|
*/
|
|
2094
2269
|
getDefaultLocale() {
|
|
2095
|
-
return this.
|
|
2270
|
+
return this.clientLocale();
|
|
2096
2271
|
}
|
|
2097
2272
|
};
|
|
2098
2273
|
chunkMWMSFIWN_cjs.__name(_ContentClient, "ContentClient");
|
|
@@ -2101,7 +2276,7 @@ var ContentClient = _ContentClient;
|
|
|
2101
2276
|
// src/errors/file-errors.ts
|
|
2102
2277
|
var _FileUploadError = class _FileUploadError extends SDKError {
|
|
2103
2278
|
constructor(code, message, options = {}) {
|
|
2104
|
-
super(message, options.statusCode, options.cause, { fileErrorCode: code });
|
|
2279
|
+
super(message, options.statusCode, options.cause, { ...options.context, fileErrorCode: code });
|
|
2105
2280
|
chunkMWMSFIWN_cjs.__publicField(this, "code");
|
|
2106
2281
|
chunkMWMSFIWN_cjs.__publicField(this, "retryable");
|
|
2107
2282
|
this.code = code;
|
|
@@ -2148,11 +2323,52 @@ function validateFile(file, constraints = {}) {
|
|
|
2148
2323
|
}
|
|
2149
2324
|
chunkMWMSFIWN_cjs.__name(validateFile, "validateFile");
|
|
2150
2325
|
|
|
2326
|
+
// src/errors/file-error-codes.ts
|
|
2327
|
+
var FILE_ERROR_CODES = [
|
|
2328
|
+
"UPLOAD_TOO_LARGE",
|
|
2329
|
+
"UNSUPPORTED_MIME",
|
|
2330
|
+
"DIMENSION_OUT_OF_RANGE",
|
|
2331
|
+
"ASPECT_RATIO",
|
|
2332
|
+
"CORRUPT_FILE",
|
|
2333
|
+
"UNSUPPORTED_CODEC",
|
|
2334
|
+
"IMAGES_LIMIT_EXCEEDED",
|
|
2335
|
+
"STREAM_ENCODE_FAILED",
|
|
2336
|
+
"SCAN_INFECTED",
|
|
2337
|
+
"INTERNAL"
|
|
2338
|
+
];
|
|
2339
|
+
|
|
2151
2340
|
// src/content/asset-client.ts
|
|
2341
|
+
function assertWaitOptions(options) {
|
|
2342
|
+
const { timeoutMs, pollIntervalMs } = options;
|
|
2343
|
+
if (timeoutMs !== void 0 && !(typeof timeoutMs === "number" && timeoutMs >= 0 && timeoutMs <= MAX_TIMER_DELAY_MS)) {
|
|
2344
|
+
throw new Error(
|
|
2345
|
+
`timeoutMs must be a number of milliseconds from 0 to ${MAX_TIMER_DELAY_MS}, and got ${String(timeoutMs)}`
|
|
2346
|
+
);
|
|
2347
|
+
}
|
|
2348
|
+
if (pollIntervalMs !== void 0 && !isTimerDelay(pollIntervalMs)) {
|
|
2349
|
+
throw new Error(
|
|
2350
|
+
`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)}`
|
|
2351
|
+
);
|
|
2352
|
+
}
|
|
2353
|
+
}
|
|
2354
|
+
chunkMWMSFIWN_cjs.__name(assertWaitOptions, "assertWaitOptions");
|
|
2152
2355
|
function hasText(value) {
|
|
2153
2356
|
return value != null && value !== "";
|
|
2154
2357
|
}
|
|
2155
2358
|
chunkMWMSFIWN_cjs.__name(hasText, "hasText");
|
|
2359
|
+
function processingFailure(subject, stored) {
|
|
2360
|
+
const storedCode = stored?.code;
|
|
2361
|
+
const code = FILE_ERROR_CODES.find((known) => known === storedCode) ?? "PROCESSING_FAILED";
|
|
2362
|
+
return new FileUploadError(
|
|
2363
|
+
code,
|
|
2364
|
+
`Asset ${subject}: ${stored?.message ?? "File processing failed"}`,
|
|
2365
|
+
{
|
|
2366
|
+
retriable: stored?.retriable === true,
|
|
2367
|
+
context: { processingError: stored }
|
|
2368
|
+
}
|
|
2369
|
+
);
|
|
2370
|
+
}
|
|
2371
|
+
chunkMWMSFIWN_cjs.__name(processingFailure, "processingFailure");
|
|
2156
2372
|
async function computeSha256Hex(blob) {
|
|
2157
2373
|
try {
|
|
2158
2374
|
const subtle = globalThis.crypto?.subtle;
|
|
@@ -2168,11 +2384,17 @@ async function computeSha256Hex(blob) {
|
|
|
2168
2384
|
}
|
|
2169
2385
|
chunkMWMSFIWN_cjs.__name(computeSha256Hex, "computeSha256Hex");
|
|
2170
2386
|
var _AssetFileBuilder = class _AssetFileBuilder {
|
|
2171
|
-
|
|
2387
|
+
/**
|
|
2388
|
+
* @param locale - The client's locale, sent when a call names none: the function
|
|
2389
|
+
* `TypedRelyIOClient` hands over, or a locale fixed for this builder
|
|
2390
|
+
*/
|
|
2391
|
+
constructor(httpClient, assetType, entryUid, locale) {
|
|
2172
2392
|
this.httpClient = httpClient;
|
|
2173
2393
|
this.assetType = assetType;
|
|
2174
2394
|
this.entryUid = entryUid;
|
|
2175
|
-
this.
|
|
2395
|
+
/** The client's locale, asked on every call rather than copied when this builder was taken. */
|
|
2396
|
+
chunkMWMSFIWN_cjs.__publicField(this, "clientLocale");
|
|
2397
|
+
this.clientLocale = readClientLocale(locale);
|
|
2176
2398
|
}
|
|
2177
2399
|
/**
|
|
2178
2400
|
* The path parameters every `/file/*` route on this builder takes.
|
|
@@ -2185,7 +2407,16 @@ var _AssetFileBuilder = class _AssetFileBuilder {
|
|
|
2185
2407
|
return { contentType: this.assetType, id: this.entryUid };
|
|
2186
2408
|
}
|
|
2187
2409
|
withLocale(locale) {
|
|
2188
|
-
return locale ?? this.
|
|
2410
|
+
return locale ?? this.clientLocale();
|
|
2411
|
+
}
|
|
2412
|
+
/**
|
|
2413
|
+
* The `locale` body field of a multipart call: the session's, else the client's. The API finds
|
|
2414
|
+
* the binding by it, so a session a `withLocale()` client opened must name the same locale on
|
|
2415
|
+
* every later call or its `objectKey` is refused as another binding's.
|
|
2416
|
+
*/
|
|
2417
|
+
localeField(locale) {
|
|
2418
|
+
const sent = this.withLocale(locale);
|
|
2419
|
+
return hasText(sent) ? { locale: sent } : {};
|
|
2189
2420
|
}
|
|
2190
2421
|
/**
|
|
2191
2422
|
* Issue a single upload target — an R2 presigned PUT (image/file) or a
|
|
@@ -2244,7 +2475,7 @@ var _AssetFileBuilder = class _AssetFileBuilder {
|
|
|
2244
2475
|
uploadId: target.uploadId,
|
|
2245
2476
|
objectKey: target.objectKey,
|
|
2246
2477
|
partNumber: target.partNumber,
|
|
2247
|
-
...
|
|
2478
|
+
...this.localeField(target.locale)
|
|
2248
2479
|
}
|
|
2249
2480
|
});
|
|
2250
2481
|
}
|
|
@@ -2255,7 +2486,7 @@ var _AssetFileBuilder = class _AssetFileBuilder {
|
|
|
2255
2486
|
body: {
|
|
2256
2487
|
uploadId: target.uploadId,
|
|
2257
2488
|
objectKey: target.objectKey,
|
|
2258
|
-
...
|
|
2489
|
+
...this.localeField(target.locale)
|
|
2259
2490
|
}
|
|
2260
2491
|
});
|
|
2261
2492
|
return payload.parts;
|
|
@@ -2268,7 +2499,7 @@ var _AssetFileBuilder = class _AssetFileBuilder {
|
|
|
2268
2499
|
uploadId: target.uploadId,
|
|
2269
2500
|
objectKey: target.objectKey,
|
|
2270
2501
|
parts: target.parts.map((p) => ({ partNumber: p.partNumber, etag: p.etag })),
|
|
2271
|
-
...
|
|
2502
|
+
...this.localeField(target.locale)
|
|
2272
2503
|
}
|
|
2273
2504
|
});
|
|
2274
2505
|
}
|
|
@@ -2279,7 +2510,7 @@ var _AssetFileBuilder = class _AssetFileBuilder {
|
|
|
2279
2510
|
body: {
|
|
2280
2511
|
uploadId: target.uploadId,
|
|
2281
2512
|
objectKey: target.objectKey,
|
|
2282
|
-
...
|
|
2513
|
+
...this.localeField(target.locale)
|
|
2283
2514
|
}
|
|
2284
2515
|
});
|
|
2285
2516
|
}
|
|
@@ -2299,6 +2530,25 @@ var _AssetFileBuilder = class _AssetFileBuilder {
|
|
|
2299
2530
|
{ path: this.target, query: params }
|
|
2300
2531
|
);
|
|
2301
2532
|
}
|
|
2533
|
+
/**
|
|
2534
|
+
* Read where this file's upload got to — `status`, and the processing stage, progress and error
|
|
2535
|
+
* the pipeline recorded — whatever the asset entry is published in.
|
|
2536
|
+
*
|
|
2537
|
+
* An asset is a draft until its file is ready, and stays one when its file fails, so a key that
|
|
2538
|
+
* reads published content finds no entry for an upload in flight or one that failed. This read
|
|
2539
|
+
* answers for the binding itself. It takes the capability the upload calls take, so a read-only
|
|
2540
|
+
* key is refused with `ReadOnlyKeyError`, and it never returns the entry's fields.
|
|
2541
|
+
*/
|
|
2542
|
+
async status(options = {}) {
|
|
2543
|
+
const params = {};
|
|
2544
|
+
const locale = this.withLocale(options.locale);
|
|
2545
|
+
if (hasText(locale)) params.locale = locale;
|
|
2546
|
+
return this.httpClient.fetchPayload(
|
|
2547
|
+
"/v1/{contentType}/{id}/file",
|
|
2548
|
+
"get",
|
|
2549
|
+
{ path: this.target, query: params }
|
|
2550
|
+
);
|
|
2551
|
+
}
|
|
2302
2552
|
/**
|
|
2303
2553
|
* Update the binding's delivery visibility (token-based; no byte relocation —
|
|
2304
2554
|
* a downgrade purges the gateway cache). Returns the refreshed asset entry.
|
|
@@ -2337,14 +2587,31 @@ var _AssetFileBuilder = class _AssetFileBuilder {
|
|
|
2337
2587
|
});
|
|
2338
2588
|
}
|
|
2339
2589
|
/**
|
|
2340
|
-
* Poll the asset entry until its file binding reaches `ready
|
|
2341
|
-
*
|
|
2590
|
+
* Poll the asset entry until its file binding reaches `ready`, and resolve with the ready entry.
|
|
2591
|
+
*
|
|
2592
|
+
* Each poll reads the entry through the key's lens. When that finds nothing — a key that reads
|
|
2593
|
+
* published content, and an asset that is a draft until its file is ready and stays one when it
|
|
2594
|
+
* fails — the poll reads the binding itself ({@link status}), so a failed upload rejects as one
|
|
2595
|
+
* rather than running out the limit (REL-1481).
|
|
2596
|
+
*
|
|
2597
|
+
* @throws {FileUploadError} When processing failed. `code` is the processing code the service
|
|
2598
|
+
* stored — `UNSUPPORTED_CODEC`, `CORRUPT_FILE` and so on — or `PROCESSING_FAILED` where it
|
|
2599
|
+
* stored none this SDK knows; `context.processingError` holds what it stored, and `retryable`
|
|
2600
|
+
* is its `retriable` hint.
|
|
2601
|
+
* @throws {TimeoutError} When `timeoutMs` passes first. The file may still become ready; the
|
|
2602
|
+
* error's `context.timeout` is the limit and `context.fileStatus` the status last seen. A file
|
|
2603
|
+
* that is `ready` in an asset the key's lens never shows — created with `publish: false`, or
|
|
2604
|
+
* awaiting a workflow — ends here too, and the message says so.
|
|
2605
|
+
* @throws {ReadOnlyKeyError} When the key's lens does not show the asset and the key may not read
|
|
2606
|
+
* its binding either: nothing it can read would ever report the file.
|
|
2342
2607
|
*/
|
|
2343
2608
|
async waitUntilReady(options = {}) {
|
|
2609
|
+
assertWaitOptions(options);
|
|
2344
2610
|
const timeoutMs = options.timeoutMs ?? 6e4;
|
|
2345
2611
|
const pollIntervalMs = options.pollIntervalMs ?? 1500;
|
|
2346
2612
|
const locale = this.withLocale(options.locale);
|
|
2347
2613
|
const deadline = Date.now() + timeoutMs;
|
|
2614
|
+
const subject = `${this.assetType}/${this.entryUid}`;
|
|
2348
2615
|
for (; ; ) {
|
|
2349
2616
|
const builder = new ContentByIdBuilder(
|
|
2350
2617
|
this.httpClient,
|
|
@@ -2354,15 +2621,24 @@ var _AssetFileBuilder = class _AssetFileBuilder {
|
|
|
2354
2621
|
);
|
|
2355
2622
|
if (hasText(locale)) builder.locale(locale);
|
|
2356
2623
|
const entry = await builder.execute();
|
|
2357
|
-
|
|
2358
|
-
if (entry
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
throw
|
|
2624
|
+
let status;
|
|
2625
|
+
if (entry === null) {
|
|
2626
|
+
const binding = await this.status({ ...hasText(locale) ? { locale } : {} });
|
|
2627
|
+
status = binding.status;
|
|
2628
|
+
if (status === "failed") throw processingFailure(subject, binding.processing?.error);
|
|
2629
|
+
} else {
|
|
2630
|
+
status = entry.file?.status;
|
|
2631
|
+
if (status === "ready") return entry;
|
|
2632
|
+
if (status === "failed") throw processingFailure(subject, entry.file?.processing?.error);
|
|
2362
2633
|
}
|
|
2363
2634
|
if (Date.now() >= deadline) {
|
|
2364
|
-
|
|
2365
|
-
|
|
2635
|
+
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" : "";
|
|
2636
|
+
throw new TimeoutError(
|
|
2637
|
+
`Timed out after ${timeoutMs}ms waiting for ${subject} (status: ${status ?? "unknown"})${unseen}`,
|
|
2638
|
+
timeoutMs,
|
|
2639
|
+
void 0,
|
|
2640
|
+
void 0,
|
|
2641
|
+
{ fileStatus: status }
|
|
2366
2642
|
);
|
|
2367
2643
|
}
|
|
2368
2644
|
await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
|
|
@@ -2372,11 +2648,14 @@ var _AssetFileBuilder = class _AssetFileBuilder {
|
|
|
2372
2648
|
chunkMWMSFIWN_cjs.__name(_AssetFileBuilder, "AssetFileBuilder");
|
|
2373
2649
|
var AssetFileBuilder = _AssetFileBuilder;
|
|
2374
2650
|
var _AssetUploadBuilder = class _AssetUploadBuilder {
|
|
2375
|
-
|
|
2651
|
+
/**
|
|
2652
|
+
* @param locale - The client's locale, the upload's when `.locale()` names none: the function
|
|
2653
|
+
* `TypedRelyIOClient` hands over, or a locale fixed for this upload
|
|
2654
|
+
*/
|
|
2655
|
+
constructor(httpClient, assetType, file, locale) {
|
|
2376
2656
|
this.httpClient = httpClient;
|
|
2377
2657
|
this.assetType = assetType;
|
|
2378
2658
|
this.file = file;
|
|
2379
|
-
this.defaultLocale = defaultLocale;
|
|
2380
2659
|
chunkMWMSFIWN_cjs.__publicField(this, "_fileName");
|
|
2381
2660
|
chunkMWMSFIWN_cjs.__publicField(this, "_visibility");
|
|
2382
2661
|
chunkMWMSFIWN_cjs.__publicField(this, "_locale");
|
|
@@ -2388,6 +2667,9 @@ var _AssetUploadBuilder = class _AssetUploadBuilder {
|
|
|
2388
2667
|
chunkMWMSFIWN_cjs.__publicField(this, "_onProgress");
|
|
2389
2668
|
chunkMWMSFIWN_cjs.__publicField(this, "_validate");
|
|
2390
2669
|
chunkMWMSFIWN_cjs.__publicField(this, "_maxPartRetries", 3);
|
|
2670
|
+
/** The client's locale, read once when the upload starts. */
|
|
2671
|
+
chunkMWMSFIWN_cjs.__publicField(this, "clientLocale");
|
|
2672
|
+
this.clientLocale = readClientLocale(locale);
|
|
2391
2673
|
}
|
|
2392
2674
|
/** Subscribe to client → storage upload progress (single PUT + multipart). */
|
|
2393
2675
|
onProgress(callback) {
|
|
@@ -2437,8 +2719,14 @@ var _AssetUploadBuilder = class _AssetUploadBuilder {
|
|
|
2437
2719
|
this._slug = slug;
|
|
2438
2720
|
return this;
|
|
2439
2721
|
}
|
|
2440
|
-
/**
|
|
2722
|
+
/**
|
|
2723
|
+
* Wait until the file binding becomes `ready` before resolving.
|
|
2724
|
+
*
|
|
2725
|
+
* @throws {Error} When `timeoutMs` or `pollIntervalMs` is one the wait cannot honour — refused
|
|
2726
|
+
* here, before anything is uploaded, rather than after the bytes are in.
|
|
2727
|
+
*/
|
|
2441
2728
|
waitForReady(options = true) {
|
|
2729
|
+
if (typeof options === "object") assertWaitOptions(options);
|
|
2442
2730
|
if (options === false) {
|
|
2443
2731
|
this._waitForReady = false;
|
|
2444
2732
|
} else {
|
|
@@ -2453,7 +2741,8 @@ var _AssetUploadBuilder = class _AssetUploadBuilder {
|
|
|
2453
2741
|
if (!fileName) {
|
|
2454
2742
|
throw new Error('A file name is required: pass a File, or call .filename("name.ext")');
|
|
2455
2743
|
}
|
|
2456
|
-
const
|
|
2744
|
+
const clientLocale = this.clientLocale();
|
|
2745
|
+
const locale = this._locale ?? clientLocale;
|
|
2457
2746
|
if (this._validate) {
|
|
2458
2747
|
const violations = validateFile(this.file, this._validate);
|
|
2459
2748
|
if (violations.length > 0) {
|
|
@@ -2464,7 +2753,7 @@ var _AssetUploadBuilder = class _AssetUploadBuilder {
|
|
|
2464
2753
|
}
|
|
2465
2754
|
}
|
|
2466
2755
|
const hash = await computeSha256Hex(this.file);
|
|
2467
|
-
const client = new AssetClient(this.httpClient, this.assetType,
|
|
2756
|
+
const client = new AssetClient(this.httpClient, this.assetType, clientLocale);
|
|
2468
2757
|
const created = await client.create(this._content, {
|
|
2469
2758
|
...hasText(this._slug) ? { slug: this._slug } : {},
|
|
2470
2759
|
...hasText(locale) ? { locale } : {},
|
|
@@ -2615,17 +2904,26 @@ var _AssetUploadBuilder = class _AssetUploadBuilder {
|
|
|
2615
2904
|
chunkMWMSFIWN_cjs.__name(_AssetUploadBuilder, "AssetUploadBuilder");
|
|
2616
2905
|
var AssetUploadBuilder = _AssetUploadBuilder;
|
|
2617
2906
|
var _AssetClient = class _AssetClient {
|
|
2618
|
-
|
|
2907
|
+
/**
|
|
2908
|
+
* @param locale - The client's locale: the function `TypedRelyIOClient` hands over, asked on
|
|
2909
|
+
* every call, or a locale fixed for this client
|
|
2910
|
+
*/
|
|
2911
|
+
constructor(httpClient, assetType, locale) {
|
|
2619
2912
|
this.httpClient = httpClient;
|
|
2620
2913
|
this.assetType = assetType;
|
|
2621
|
-
this.
|
|
2914
|
+
/** The client's locale, asked on every call rather than copied when this client was taken. */
|
|
2915
|
+
chunkMWMSFIWN_cjs.__publicField(this, "clientLocale");
|
|
2916
|
+
this.clientLocale = readClientLocale(locale);
|
|
2622
2917
|
}
|
|
2623
|
-
/**
|
|
2918
|
+
/**
|
|
2919
|
+
* Create a query builder for this asset type. It resolves asset reads; its conditions name the
|
|
2920
|
+
* asset type's fields, which the `file` and `urls` blocks are not.
|
|
2921
|
+
*/
|
|
2624
2922
|
query() {
|
|
2625
2923
|
return new ContentQueryBuilder(
|
|
2626
2924
|
this.httpClient,
|
|
2627
2925
|
this.assetType,
|
|
2628
|
-
this.
|
|
2926
|
+
this.clientLocale
|
|
2629
2927
|
);
|
|
2630
2928
|
}
|
|
2631
2929
|
/** Find an asset entry by id (or slug) with fluent options. */
|
|
@@ -2634,7 +2932,7 @@ var _AssetClient = class _AssetClient {
|
|
|
2634
2932
|
this.httpClient,
|
|
2635
2933
|
this.assetType,
|
|
2636
2934
|
id,
|
|
2637
|
-
this.
|
|
2935
|
+
this.clientLocale
|
|
2638
2936
|
);
|
|
2639
2937
|
}
|
|
2640
2938
|
/** Fetch a single asset entry by id (or slug), or `null` if not found. */
|
|
@@ -2655,28 +2953,34 @@ var _AssetClient = class _AssetClient {
|
|
|
2655
2953
|
* Create a new asset entry as a draft. The binary is uploaded separately via
|
|
2656
2954
|
* `file(uid)` (or use the high-level `upload()` helper), and the entry
|
|
2657
2955
|
* auto-publishes when its file becomes ready (unless `publish: false`).
|
|
2956
|
+
* `locale` defaults to the client's own (`withLocale()`).
|
|
2658
2957
|
*/
|
|
2659
2958
|
async create(data, options) {
|
|
2660
|
-
const { idempotencyKey, ...rest } = options ?? {};
|
|
2959
|
+
const { idempotencyKey, locale, ...rest } = options ?? {};
|
|
2960
|
+
const sent = callLocale(locale, this.clientLocale());
|
|
2661
2961
|
return this.httpClient.fetchPayload(
|
|
2662
2962
|
"/v1/{contentType}",
|
|
2663
2963
|
"post",
|
|
2664
2964
|
{
|
|
2665
2965
|
path: { contentType: this.assetType },
|
|
2666
|
-
body: { content: data, ...rest },
|
|
2966
|
+
body: { content: data, ...rest, ...sent === void 0 ? {} : { locale: sent } },
|
|
2667
2967
|
headers: writeHeaders({ idempotencyKey })
|
|
2668
2968
|
}
|
|
2669
2969
|
);
|
|
2670
2970
|
}
|
|
2671
|
-
/**
|
|
2971
|
+
/**
|
|
2972
|
+
* Update an asset entry's metadata fields (and/or slug). `locale` defaults to the client's own
|
|
2973
|
+
* (`withLocale()`).
|
|
2974
|
+
*/
|
|
2672
2975
|
async update(id, data, options) {
|
|
2673
|
-
const { idempotencyKey, ifMatch, ...rest } = options ?? {};
|
|
2976
|
+
const { idempotencyKey, ifMatch, locale, ...rest } = options ?? {};
|
|
2977
|
+
const sent = callLocale(locale, this.clientLocale());
|
|
2674
2978
|
return this.httpClient.fetchPayload(
|
|
2675
2979
|
"/v1/{contentType}/{id}",
|
|
2676
2980
|
"patch",
|
|
2677
2981
|
{
|
|
2678
2982
|
path: { contentType: this.assetType, id },
|
|
2679
|
-
body: { content: data, ...rest },
|
|
2983
|
+
body: { content: data, ...rest, ...sent === void 0 ? {} : { locale: sent } },
|
|
2680
2984
|
headers: writeHeaders({ idempotencyKey, ifMatch })
|
|
2681
2985
|
}
|
|
2682
2986
|
);
|
|
@@ -2690,21 +2994,24 @@ var _AssetClient = class _AssetClient {
|
|
|
2690
2994
|
}
|
|
2691
2995
|
/** Get the file sub-resource builder for a specific asset entry. */
|
|
2692
2996
|
file(entryUid) {
|
|
2693
|
-
return new AssetFileBuilder(this.httpClient, this.assetType, entryUid, this.
|
|
2997
|
+
return new AssetFileBuilder(this.httpClient, this.assetType, entryUid, this.clientLocale);
|
|
2694
2998
|
}
|
|
2695
2999
|
/** Start a high-level upload (create → presign → PUT → confirm). */
|
|
2696
3000
|
upload(file) {
|
|
2697
|
-
return new AssetUploadBuilder(this.httpClient, this.assetType, file, this.
|
|
3001
|
+
return new AssetUploadBuilder(this.httpClient, this.assetType, file, this.clientLocale);
|
|
2698
3002
|
}
|
|
2699
3003
|
/** Get the asset type id. */
|
|
2700
3004
|
getAssetType() {
|
|
2701
3005
|
return this.assetType;
|
|
2702
3006
|
}
|
|
2703
|
-
/** Get the
|
|
3007
|
+
/** Get the default locale as it is now: the client's, or the one `withLocale()` fixed. */
|
|
2704
3008
|
getDefaultLocale() {
|
|
2705
|
-
return this.
|
|
3009
|
+
return this.clientLocale();
|
|
2706
3010
|
}
|
|
2707
|
-
/**
|
|
3011
|
+
/**
|
|
3012
|
+
* Create a new AssetClient for this type with a different default locale, fixed: an update of the
|
|
3013
|
+
* client's locale (`updateConfig({ locale })`) does not reach it.
|
|
3014
|
+
*/
|
|
2708
3015
|
withLocale(locale) {
|
|
2709
3016
|
return new _AssetClient(this.httpClient, this.assetType, locale);
|
|
2710
3017
|
}
|
|
@@ -2720,11 +3027,18 @@ chunkMWMSFIWN_cjs.__name(isAssetEntry, "isAssetEntry");
|
|
|
2720
3027
|
|
|
2721
3028
|
// src/content/singleton-client.ts
|
|
2722
3029
|
var _SingletonClient = class _SingletonClient {
|
|
2723
|
-
|
|
3030
|
+
/**
|
|
3031
|
+
* @param locale - The client's locale: the function `TypedRelyIOClient` hands over, asked on
|
|
3032
|
+
* every call, or a locale fixed for this client
|
|
3033
|
+
*/
|
|
3034
|
+
constructor(httpClient, singletonKey, locale) {
|
|
2724
3035
|
this.httpClient = httpClient;
|
|
2725
3036
|
this.singletonKey = singletonKey;
|
|
2726
3037
|
chunkMWMSFIWN_cjs.__publicField(this, "includeFields");
|
|
2727
3038
|
chunkMWMSFIWN_cjs.__publicField(this, "localeValue");
|
|
3039
|
+
/** The client's locale, asked on every call rather than copied when this client was taken. */
|
|
3040
|
+
chunkMWMSFIWN_cjs.__publicField(this, "clientLocale");
|
|
3041
|
+
this.clientLocale = readClientLocale(locale);
|
|
2728
3042
|
}
|
|
2729
3043
|
/**
|
|
2730
3044
|
* Include reference fields in the response
|
|
@@ -2747,11 +3061,6 @@ var _SingletonClient = class _SingletonClient {
|
|
|
2747
3061
|
* @param options - Optional fetch options (alternative to fluent methods)
|
|
2748
3062
|
*/
|
|
2749
3063
|
async fetch(options) {
|
|
2750
|
-
const includeValue = options?.include ?? this.includeFields;
|
|
2751
|
-
options?.locale ?? this.localeValue;
|
|
2752
|
-
if (includeValue) {
|
|
2753
|
-
includeValue.join(",");
|
|
2754
|
-
}
|
|
2755
3064
|
try {
|
|
2756
3065
|
return (await this.fetchWithTag(options)).content;
|
|
2757
3066
|
} catch (error) {
|
|
@@ -2769,7 +3078,7 @@ var _SingletonClient = class _SingletonClient {
|
|
|
2769
3078
|
async fetchWithTag(options) {
|
|
2770
3079
|
const query = {};
|
|
2771
3080
|
const includeValue = options?.include ?? this.includeFields;
|
|
2772
|
-
const localeValueFinal = options?.locale ?? this.localeValue;
|
|
3081
|
+
const localeValueFinal = options?.locale ?? this.localeValue ?? this.clientLocale();
|
|
2773
3082
|
if (includeValue) query.include = includeValue.join(",");
|
|
2774
3083
|
if (localeValueFinal != null && localeValueFinal !== "") query.locale = localeValueFinal;
|
|
2775
3084
|
const response = await this.httpClient.send(
|
|
@@ -2783,11 +3092,12 @@ var _SingletonClient = class _SingletonClient {
|
|
|
2783
3092
|
* Update singleton content. The API auto-publishes on PATCH — there is no
|
|
2784
3093
|
* separate publish route; calling `update()` writes and publishes.
|
|
2785
3094
|
* @param data - The content fields to update
|
|
2786
|
-
* @param locale - Optional locale for localized content (overrides fluent locale
|
|
3095
|
+
* @param locale - Optional locale for localized content (overrides the fluent locale, which
|
|
3096
|
+
* overrides the client's own)
|
|
2787
3097
|
* @param options - `If-Match` / `Idempotency-Key`, both declared on this route
|
|
2788
3098
|
*/
|
|
2789
3099
|
async update(data, locale, options) {
|
|
2790
|
-
const finalLocale =
|
|
3100
|
+
const finalLocale = this.localeOf(locale);
|
|
2791
3101
|
return this.httpClient.fetchPayload(
|
|
2792
3102
|
"/v1/singletons/{key}",
|
|
2793
3103
|
"patch",
|
|
@@ -2816,15 +3126,17 @@ var _SingletonClient = class _SingletonClient {
|
|
|
2816
3126
|
* Get version history for one locale of the singleton.
|
|
2817
3127
|
*
|
|
2818
3128
|
* Versions are numbered per locale, so this is one locale's timeline: `locale` defaults to the
|
|
2819
|
-
*
|
|
2820
|
-
*
|
|
3129
|
+
* fluent `.locale()`, then the client's own (`withLocale()`), then the schema default; no
|
|
3130
|
+
* fallback is applied, and a locale with no history returns an empty array rather than another
|
|
3131
|
+
* locale's rows. Every row names the locale it belongs to.
|
|
2821
3132
|
*/
|
|
2822
3133
|
async versions(options) {
|
|
3134
|
+
const locale = this.localeOf(options?.locale);
|
|
2823
3135
|
const payload = await this.httpClient.fetchPayload("/v1/singletons/{key}/versions", "get", {
|
|
2824
3136
|
path: { key: this.singletonKey },
|
|
2825
3137
|
query: {
|
|
2826
3138
|
limit: options?.limit ?? 10,
|
|
2827
|
-
...
|
|
3139
|
+
...locale === void 0 ? {} : { locale }
|
|
2828
3140
|
}
|
|
2829
3141
|
});
|
|
2830
3142
|
return payload.versions;
|
|
@@ -2832,20 +3144,25 @@ var _SingletonClient = class _SingletonClient {
|
|
|
2832
3144
|
/**
|
|
2833
3145
|
* Get a specific version of the singleton.
|
|
2834
3146
|
*
|
|
2835
|
-
* `locale` defaults to the
|
|
2836
|
-
* different content in each one.
|
|
3147
|
+
* `locale` defaults to the fluent `.locale()`, then the client's own (`withLocale()`), then the
|
|
3148
|
+
* schema default. Version numbers are per locale, so version 2 is different content in each one.
|
|
2837
3149
|
*/
|
|
2838
3150
|
async version(versionNumber, options) {
|
|
3151
|
+
const locale = this.localeOf(options?.locale);
|
|
2839
3152
|
try {
|
|
2840
3153
|
return await this.httpClient.fetchPayload("/v1/singletons/{key}/versions/{versionNumber}", "get", {
|
|
2841
3154
|
path: { key: this.singletonKey, versionNumber: String(versionNumber) },
|
|
2842
|
-
query:
|
|
3155
|
+
query: locale === void 0 ? void 0 : { locale }
|
|
2843
3156
|
});
|
|
2844
3157
|
} catch (error) {
|
|
2845
3158
|
if (isResourceNotFound(error)) return null;
|
|
2846
3159
|
throw error;
|
|
2847
3160
|
}
|
|
2848
3161
|
}
|
|
3162
|
+
/** The locale a write or history read sends: the call's, the fluent one, else the client's. */
|
|
3163
|
+
localeOf(named) {
|
|
3164
|
+
return callLocale(named ?? this.localeValue, this.clientLocale());
|
|
3165
|
+
}
|
|
2849
3166
|
/**
|
|
2850
3167
|
* Get the singleton key
|
|
2851
3168
|
*/
|
|
@@ -2866,11 +3183,18 @@ var SingletonClient = _SingletonClient;
|
|
|
2866
3183
|
|
|
2867
3184
|
// src/content/settings-client.ts
|
|
2868
3185
|
var _SettingsClient = class _SettingsClient {
|
|
2869
|
-
|
|
3186
|
+
/**
|
|
3187
|
+
* @param locale - The client's locale: the function `TypedRelyIOClient` hands over, asked on
|
|
3188
|
+
* every call, or a locale fixed for this client
|
|
3189
|
+
*/
|
|
3190
|
+
constructor(httpClient, groupId, locale) {
|
|
2870
3191
|
this.httpClient = httpClient;
|
|
2871
3192
|
this.groupId = groupId;
|
|
2872
3193
|
chunkMWMSFIWN_cjs.__publicField(this, "includeFields");
|
|
2873
3194
|
chunkMWMSFIWN_cjs.__publicField(this, "localeValue");
|
|
3195
|
+
/** The client's locale, asked on every call rather than copied when this client was taken. */
|
|
3196
|
+
chunkMWMSFIWN_cjs.__publicField(this, "clientLocale");
|
|
3197
|
+
this.clientLocale = readClientLocale(locale);
|
|
2874
3198
|
}
|
|
2875
3199
|
/**
|
|
2876
3200
|
* Include reference fields in the response
|
|
@@ -2893,11 +3217,6 @@ var _SettingsClient = class _SettingsClient {
|
|
|
2893
3217
|
* @param options - Optional fetch options (alternative to fluent methods)
|
|
2894
3218
|
*/
|
|
2895
3219
|
async fetch(options) {
|
|
2896
|
-
const includeValue = options?.include ?? this.includeFields;
|
|
2897
|
-
options?.locale ?? this.localeValue;
|
|
2898
|
-
if (includeValue) {
|
|
2899
|
-
includeValue.join(",");
|
|
2900
|
-
}
|
|
2901
3220
|
try {
|
|
2902
3221
|
return (await this.fetchWithTag(options)).settings;
|
|
2903
3222
|
} catch (error) {
|
|
@@ -2907,12 +3226,20 @@ var _SettingsClient = class _SettingsClient {
|
|
|
2907
3226
|
}
|
|
2908
3227
|
/**
|
|
2909
3228
|
* Update settings group
|
|
3229
|
+
*
|
|
3230
|
+
* The fields travel as `content` beside an optional `locale`, the body the route validates
|
|
3231
|
+
* (`UpdateSettingsDto`); any other top-level key is refused `REQUEST_INVALID`.
|
|
3232
|
+
*
|
|
2910
3233
|
* @param settings - The settings fields to update
|
|
2911
|
-
* @param locale - Optional locale for localized settings (overrides fluent locale
|
|
3234
|
+
* @param locale - Optional locale for localized settings (overrides the fluent locale, which
|
|
3235
|
+
* overrides the client's own)
|
|
2912
3236
|
*/
|
|
2913
3237
|
async update(settings, locale, options) {
|
|
2914
|
-
const finalLocale =
|
|
2915
|
-
const body =
|
|
3238
|
+
const finalLocale = this.localeOf(locale);
|
|
3239
|
+
const body = {
|
|
3240
|
+
content: settings,
|
|
3241
|
+
...finalLocale != null && finalLocale !== "" ? { locale: finalLocale } : {}
|
|
3242
|
+
};
|
|
2916
3243
|
return this.httpClient.fetchPayload(
|
|
2917
3244
|
"/v1/settings/{groupId}",
|
|
2918
3245
|
"patch",
|
|
@@ -2927,7 +3254,7 @@ var _SettingsClient = class _SettingsClient {
|
|
|
2927
3254
|
async fetchWithTag(options) {
|
|
2928
3255
|
const query = {};
|
|
2929
3256
|
const includeValue = options?.include ?? this.includeFields;
|
|
2930
|
-
const localeValueFinal = options?.locale ?? this.localeValue;
|
|
3257
|
+
const localeValueFinal = options?.locale ?? this.localeValue ?? this.clientLocale();
|
|
2931
3258
|
if (includeValue) query.include = includeValue.join(",");
|
|
2932
3259
|
if (localeValueFinal != null && localeValueFinal !== "") query.locale = localeValueFinal;
|
|
2933
3260
|
const response = await this.httpClient.send(
|
|
@@ -2939,16 +3266,20 @@ var _SettingsClient = class _SettingsClient {
|
|
|
2939
3266
|
}
|
|
2940
3267
|
/**
|
|
2941
3268
|
* Reset settings to default values
|
|
2942
|
-
*
|
|
3269
|
+
*
|
|
3270
|
+
* The route reads its locale from `?locale=` and takes no body, so that is where it is sent.
|
|
3271
|
+
*
|
|
3272
|
+
* @param locale - Optional locale for localized settings (overrides the fluent locale, which
|
|
3273
|
+
* overrides the client's own)
|
|
2943
3274
|
*/
|
|
2944
3275
|
async reset(locale, options) {
|
|
2945
|
-
const finalLocale =
|
|
3276
|
+
const finalLocale = this.localeOf(locale);
|
|
2946
3277
|
return this.httpClient.fetchPayload(
|
|
2947
3278
|
"/v1/settings/{groupId}/reset",
|
|
2948
3279
|
"post",
|
|
2949
3280
|
{
|
|
2950
3281
|
path: { groupId: this.groupId },
|
|
2951
|
-
|
|
3282
|
+
query: finalLocale != null && finalLocale !== "" ? { locale: finalLocale } : void 0,
|
|
2952
3283
|
headers: writeHeaders(options)
|
|
2953
3284
|
}
|
|
2954
3285
|
);
|
|
@@ -2979,15 +3310,17 @@ var _SettingsClient = class _SettingsClient {
|
|
|
2979
3310
|
* Get version history for one locale of the settings group.
|
|
2980
3311
|
*
|
|
2981
3312
|
* Versions are numbered per locale, so this is one locale's timeline: `locale` defaults to the
|
|
2982
|
-
*
|
|
2983
|
-
*
|
|
3313
|
+
* fluent `.locale()`, then the client's own (`withLocale()`), then the schema default; no
|
|
3314
|
+
* fallback is applied, and a locale with no history returns an empty array rather than another
|
|
3315
|
+
* locale's rows. Every row names the locale it belongs to.
|
|
2984
3316
|
*/
|
|
2985
3317
|
async versions(options) {
|
|
3318
|
+
const locale = this.localeOf(options?.locale);
|
|
2986
3319
|
const payload = await this.httpClient.fetchPayload("/v1/settings/{groupId}/versions", "get", {
|
|
2987
3320
|
path: { groupId: this.groupId },
|
|
2988
3321
|
query: {
|
|
2989
3322
|
limit: options?.limit ?? 10,
|
|
2990
|
-
...
|
|
3323
|
+
...locale === void 0 ? {} : { locale }
|
|
2991
3324
|
}
|
|
2992
3325
|
});
|
|
2993
3326
|
return payload.versions;
|
|
@@ -2995,20 +3328,25 @@ var _SettingsClient = class _SettingsClient {
|
|
|
2995
3328
|
/**
|
|
2996
3329
|
* Get a specific version of the settings.
|
|
2997
3330
|
*
|
|
2998
|
-
* `locale` defaults to the
|
|
2999
|
-
* different content in each one.
|
|
3331
|
+
* `locale` defaults to the fluent `.locale()`, then the client's own (`withLocale()`), then the
|
|
3332
|
+
* schema default. Version numbers are per locale, so version 2 is different content in each one.
|
|
3000
3333
|
*/
|
|
3001
3334
|
async version(versionNumber, options) {
|
|
3335
|
+
const locale = this.localeOf(options?.locale);
|
|
3002
3336
|
try {
|
|
3003
3337
|
return await this.httpClient.fetchPayload("/v1/settings/{groupId}/versions/{versionNumber}", "get", {
|
|
3004
3338
|
path: { groupId: this.groupId, versionNumber: String(versionNumber) },
|
|
3005
|
-
query:
|
|
3339
|
+
query: locale === void 0 ? void 0 : { locale }
|
|
3006
3340
|
});
|
|
3007
3341
|
} catch (error) {
|
|
3008
3342
|
if (isResourceNotFound(error)) return null;
|
|
3009
3343
|
throw error;
|
|
3010
3344
|
}
|
|
3011
3345
|
}
|
|
3346
|
+
/** The locale a write or history read sends: the call's, the fluent one, else the client's. */
|
|
3347
|
+
localeOf(named) {
|
|
3348
|
+
return callLocale(named ?? this.localeValue, this.clientLocale());
|
|
3349
|
+
}
|
|
3012
3350
|
/**
|
|
3013
3351
|
* Get the settings group ID
|
|
3014
3352
|
*/
|
|
@@ -3029,14 +3367,31 @@ var SettingsClient = _SettingsClient;
|
|
|
3029
3367
|
|
|
3030
3368
|
// src/search/search-client.ts
|
|
3031
3369
|
var _SearchBuilder = class _SearchBuilder {
|
|
3032
|
-
|
|
3370
|
+
/**
|
|
3371
|
+
* @param locale - The client's locale (`withLocale()`, `updateConfig({ locale })`), sent when
|
|
3372
|
+
* `.locale()` names none: the function `TypedRelyIOClient` hands over, or a locale fixed for it
|
|
3373
|
+
*/
|
|
3374
|
+
constructor(httpClient, query, locale) {
|
|
3033
3375
|
this.httpClient = httpClient;
|
|
3034
3376
|
chunkMWMSFIWN_cjs.__publicField(this, "query");
|
|
3035
3377
|
chunkMWMSFIWN_cjs.__publicField(this, "searchOptions", {});
|
|
3378
|
+
chunkMWMSFIWN_cjs.__publicField(this, "requestHeaders");
|
|
3379
|
+
/** The client's locale, asked when the query is sent rather than copied when it was built. */
|
|
3380
|
+
chunkMWMSFIWN_cjs.__publicField(this, "clientLocale");
|
|
3036
3381
|
this.query = query;
|
|
3382
|
+
this.clientLocale = readClientLocale(locale);
|
|
3037
3383
|
}
|
|
3038
3384
|
/**
|
|
3039
|
-
*
|
|
3385
|
+
* Headers this search adds to the client's own, e.g. `X-RelyIO-Dataset` to search another
|
|
3386
|
+
* dataset the key can see. A name the client already sends is replaced for this search only.
|
|
3387
|
+
*/
|
|
3388
|
+
headers(headers) {
|
|
3389
|
+
this.requestHeaders = headers;
|
|
3390
|
+
return this;
|
|
3391
|
+
}
|
|
3392
|
+
/**
|
|
3393
|
+
* Search within a single content type. Where a schema types the client, the name is one of its
|
|
3394
|
+
* content types and the results are that type's entries.
|
|
3040
3395
|
* @param contentType - Content type to search in
|
|
3041
3396
|
*/
|
|
3042
3397
|
in(contentType) {
|
|
@@ -3045,7 +3400,8 @@ var _SearchBuilder = class _SearchBuilder {
|
|
|
3045
3400
|
return this;
|
|
3046
3401
|
}
|
|
3047
3402
|
/**
|
|
3048
|
-
* Search across multiple content types
|
|
3403
|
+
* Search across multiple content types. Where a schema types the client, the names are its content
|
|
3404
|
+
* types and the results are a union of their entries — every type's, for `'*'`.
|
|
3049
3405
|
* @param contentTypes - Array of content types or '*' for all
|
|
3050
3406
|
*/
|
|
3051
3407
|
across(contentTypes) {
|
|
@@ -3054,10 +3410,12 @@ var _SearchBuilder = class _SearchBuilder {
|
|
|
3054
3410
|
return this;
|
|
3055
3411
|
}
|
|
3056
3412
|
/**
|
|
3057
|
-
* Add filter conditions
|
|
3413
|
+
* Add filter conditions, on the fields the content types declare. A condition on `_metadata` is
|
|
3414
|
+
* refused here, before anything is sent.
|
|
3058
3415
|
* @param conditions - Filter conditions
|
|
3059
3416
|
*/
|
|
3060
3417
|
where(conditions) {
|
|
3418
|
+
refuseMetadataConditions(conditions);
|
|
3061
3419
|
this.searchOptions.where = {
|
|
3062
3420
|
...this.searchOptions.where,
|
|
3063
3421
|
...conditions
|
|
@@ -3080,6 +3438,16 @@ var _SearchBuilder = class _SearchBuilder {
|
|
|
3080
3438
|
this.searchOptions.fields = projection;
|
|
3081
3439
|
return this;
|
|
3082
3440
|
}
|
|
3441
|
+
/**
|
|
3442
|
+
* Order the results by a field instead of by relevance. Called again, it adds a tie-breaker.
|
|
3443
|
+
* `_score` names relevance itself.
|
|
3444
|
+
* @param field - Field path to sort by (e.g. `updatedAt`, `pricing.basePrice`)
|
|
3445
|
+
* @param direction - `asc` or `desc` (the route's default is `desc`)
|
|
3446
|
+
*/
|
|
3447
|
+
sort(field, direction = "desc") {
|
|
3448
|
+
this.searchOptions.sort = [...this.searchOptions.sort ?? [], { field, direction }];
|
|
3449
|
+
return this;
|
|
3450
|
+
}
|
|
3083
3451
|
/**
|
|
3084
3452
|
* Limit number of results
|
|
3085
3453
|
* @param count - Maximum results
|
|
@@ -3140,6 +3508,9 @@ var _SearchBuilder = class _SearchBuilder {
|
|
|
3140
3508
|
if (this.searchOptions.fields) {
|
|
3141
3509
|
body.fields = this.searchOptions.fields;
|
|
3142
3510
|
}
|
|
3511
|
+
if (this.searchOptions.sort) {
|
|
3512
|
+
body.sort = this.searchOptions.sort;
|
|
3513
|
+
}
|
|
3143
3514
|
if (this.searchOptions.limit !== void 0) {
|
|
3144
3515
|
body.limit = this.searchOptions.limit;
|
|
3145
3516
|
}
|
|
@@ -3152,13 +3523,14 @@ var _SearchBuilder = class _SearchBuilder {
|
|
|
3152
3523
|
if (this.searchOptions.explain === true) {
|
|
3153
3524
|
body.explain = true;
|
|
3154
3525
|
}
|
|
3155
|
-
|
|
3156
|
-
|
|
3526
|
+
const locale = this.searchOptions.locale ?? this.clientLocale();
|
|
3527
|
+
if (locale != null && locale !== "") {
|
|
3528
|
+
body.locale = locale;
|
|
3157
3529
|
}
|
|
3158
3530
|
const response = await this.httpClient.send(
|
|
3159
3531
|
"/v1/search",
|
|
3160
3532
|
"post",
|
|
3161
|
-
{ body }
|
|
3533
|
+
{ body, headers: this.requestHeaders }
|
|
3162
3534
|
);
|
|
3163
3535
|
return response.body;
|
|
3164
3536
|
}
|
|
@@ -3178,11 +3550,18 @@ var _SearchBuilder = class _SearchBuilder {
|
|
|
3178
3550
|
chunkMWMSFIWN_cjs.__name(_SearchBuilder, "SearchBuilder");
|
|
3179
3551
|
var SearchBuilder = _SearchBuilder;
|
|
3180
3552
|
var _AutocompleteBuilder = class _AutocompleteBuilder {
|
|
3181
|
-
|
|
3553
|
+
/**
|
|
3554
|
+
* @param locale - The client's locale (`withLocale()`, `updateConfig({ locale })`), sent when
|
|
3555
|
+
* `.locale()` names none: the function `TypedRelyIOClient` hands over, or a locale fixed for it
|
|
3556
|
+
*/
|
|
3557
|
+
constructor(httpClient, query, locale) {
|
|
3182
3558
|
this.httpClient = httpClient;
|
|
3183
3559
|
chunkMWMSFIWN_cjs.__publicField(this, "query");
|
|
3184
3560
|
chunkMWMSFIWN_cjs.__publicField(this, "autocompleteOptions", {});
|
|
3561
|
+
/** The client's locale, asked when the query is sent rather than copied when it was built. */
|
|
3562
|
+
chunkMWMSFIWN_cjs.__publicField(this, "clientLocale");
|
|
3185
3563
|
this.query = query;
|
|
3564
|
+
this.clientLocale = readClientLocale(locale);
|
|
3186
3565
|
}
|
|
3187
3566
|
/**
|
|
3188
3567
|
* Autocomplete within a content type
|
|
@@ -3208,10 +3587,12 @@ var _AutocompleteBuilder = class _AutocompleteBuilder {
|
|
|
3208
3587
|
return this;
|
|
3209
3588
|
}
|
|
3210
3589
|
/**
|
|
3211
|
-
* Add filter conditions
|
|
3590
|
+
* Add filter conditions, on the fields the content types declare. A condition on `_metadata` is
|
|
3591
|
+
* refused here, before anything is sent.
|
|
3212
3592
|
* @param conditions - Filter conditions
|
|
3213
3593
|
*/
|
|
3214
3594
|
where(conditions) {
|
|
3595
|
+
refuseMetadataConditions(conditions);
|
|
3215
3596
|
this.autocompleteOptions.where = {
|
|
3216
3597
|
...this.autocompleteOptions.where,
|
|
3217
3598
|
...conditions
|
|
@@ -3258,8 +3639,9 @@ var _AutocompleteBuilder = class _AutocompleteBuilder {
|
|
|
3258
3639
|
if (this.autocompleteOptions.limit !== void 0) {
|
|
3259
3640
|
body.limit = this.autocompleteOptions.limit;
|
|
3260
3641
|
}
|
|
3261
|
-
|
|
3262
|
-
|
|
3642
|
+
const locale = this.autocompleteOptions.locale ?? this.clientLocale();
|
|
3643
|
+
if (locale != null && locale !== "") {
|
|
3644
|
+
body.locale = locale;
|
|
3263
3645
|
}
|
|
3264
3646
|
const response = await this.httpClient.send("/v1/search/autocomplete", "post", { body });
|
|
3265
3647
|
return response.body;
|
|
@@ -3274,11 +3656,27 @@ var _AutocompleteBuilder = class _AutocompleteBuilder {
|
|
|
3274
3656
|
chunkMWMSFIWN_cjs.__name(_AutocompleteBuilder, "AutocompleteBuilder");
|
|
3275
3657
|
var AutocompleteBuilder = _AutocompleteBuilder;
|
|
3276
3658
|
var _SimilarBuilder = class _SimilarBuilder {
|
|
3277
|
-
|
|
3659
|
+
/**
|
|
3660
|
+
* @param locale - The client's locale (`withLocale()`, `updateConfig({ locale })`), sent when
|
|
3661
|
+
* `.locale()` names none: the function `TypedRelyIOClient` hands over, or a locale fixed for it
|
|
3662
|
+
*/
|
|
3663
|
+
constructor(httpClient, sourceId, locale) {
|
|
3278
3664
|
this.httpClient = httpClient;
|
|
3279
3665
|
chunkMWMSFIWN_cjs.__publicField(this, "sourceId");
|
|
3280
3666
|
chunkMWMSFIWN_cjs.__publicField(this, "similarOptions", {});
|
|
3667
|
+
chunkMWMSFIWN_cjs.__publicField(this, "requestHeaders");
|
|
3668
|
+
/** The client's locale, asked when the read is sent rather than copied when it was built. */
|
|
3669
|
+
chunkMWMSFIWN_cjs.__publicField(this, "clientLocale");
|
|
3281
3670
|
this.sourceId = sourceId;
|
|
3671
|
+
this.clientLocale = readClientLocale(locale);
|
|
3672
|
+
}
|
|
3673
|
+
/**
|
|
3674
|
+
* Headers this read adds to the client's own, e.g. `X-RelyIO-Dataset` to read another dataset
|
|
3675
|
+
* the key can see. A name the client already sends is replaced for this read only.
|
|
3676
|
+
*/
|
|
3677
|
+
headers(headers) {
|
|
3678
|
+
this.requestHeaders = headers;
|
|
3679
|
+
return this;
|
|
3282
3680
|
}
|
|
3283
3681
|
/**
|
|
3284
3682
|
* Find similar content within a content type
|
|
@@ -3286,19 +3684,24 @@ var _SimilarBuilder = class _SimilarBuilder {
|
|
|
3286
3684
|
*/
|
|
3287
3685
|
in(contentType) {
|
|
3288
3686
|
this.similarOptions.contentType = contentType;
|
|
3687
|
+
this.similarOptions.contentTypes = void 0;
|
|
3289
3688
|
return this;
|
|
3290
3689
|
}
|
|
3291
3690
|
/**
|
|
3292
|
-
*
|
|
3293
|
-
* @param
|
|
3691
|
+
* Find similar content across several content types, or `'*'` for every type
|
|
3692
|
+
* @param contentTypes - Array of content types or '*' for all
|
|
3294
3693
|
*/
|
|
3295
|
-
|
|
3296
|
-
this.similarOptions.
|
|
3297
|
-
|
|
3298
|
-
...conditions
|
|
3299
|
-
};
|
|
3694
|
+
across(contentTypes) {
|
|
3695
|
+
this.similarOptions.contentTypes = contentTypes;
|
|
3696
|
+
this.similarOptions.contentType = void 0;
|
|
3300
3697
|
return this;
|
|
3301
3698
|
}
|
|
3699
|
+
/*
|
|
3700
|
+
* No `where()` (REL-1452). Similar ranks from the source entry's stored vector, and the vector
|
|
3701
|
+
* index can pre-filter by content type and locale only — never by an entry field. The API used to
|
|
3702
|
+
* accept `where` here and apply nothing; it now refuses the property, so the builder does not
|
|
3703
|
+
* offer a filter that cannot be honoured. Narrow with `.in()`, `.across()` and `.locale()`.
|
|
3704
|
+
*/
|
|
3302
3705
|
/**
|
|
3303
3706
|
* Limit number of results
|
|
3304
3707
|
* @param count - Maximum results
|
|
@@ -3319,26 +3722,30 @@ var _SimilarBuilder = class _SimilarBuilder {
|
|
|
3319
3722
|
* Execute the similar query
|
|
3320
3723
|
*/
|
|
3321
3724
|
async execute() {
|
|
3322
|
-
|
|
3323
|
-
|
|
3725
|
+
const { contentType, contentTypes } = this.similarOptions;
|
|
3726
|
+
if ((contentType == null || contentType === "") && contentTypes == null) {
|
|
3727
|
+
throw new Error(
|
|
3728
|
+
'Content type is required for similar search. Use .in("contentType") or .across("*")'
|
|
3729
|
+
);
|
|
3324
3730
|
}
|
|
3325
|
-
const body = {
|
|
3326
|
-
|
|
3327
|
-
contentType
|
|
3328
|
-
}
|
|
3329
|
-
if (
|
|
3330
|
-
body.
|
|
3731
|
+
const body = { source: this.sourceId };
|
|
3732
|
+
if (contentType != null && contentType !== "") {
|
|
3733
|
+
body.contentType = contentType;
|
|
3734
|
+
}
|
|
3735
|
+
if (contentTypes != null) {
|
|
3736
|
+
body.contentTypes = contentTypes;
|
|
3331
3737
|
}
|
|
3332
3738
|
if (this.similarOptions.limit !== void 0) {
|
|
3333
3739
|
body.limit = this.similarOptions.limit;
|
|
3334
3740
|
}
|
|
3335
|
-
|
|
3336
|
-
|
|
3741
|
+
const locale = this.similarOptions.locale ?? this.clientLocale();
|
|
3742
|
+
if (locale != null && locale !== "") {
|
|
3743
|
+
body.locale = locale;
|
|
3337
3744
|
}
|
|
3338
3745
|
const response = await this.httpClient.send(
|
|
3339
3746
|
"/v1/search/similar",
|
|
3340
3747
|
"post",
|
|
3341
|
-
{ body }
|
|
3748
|
+
{ body, headers: this.requestHeaders }
|
|
3342
3749
|
);
|
|
3343
3750
|
return response.body;
|
|
3344
3751
|
}
|
|
@@ -3358,37 +3765,37 @@ var _SimilarBuilder = class _SimilarBuilder {
|
|
|
3358
3765
|
chunkMWMSFIWN_cjs.__name(_SimilarBuilder, "SimilarBuilder");
|
|
3359
3766
|
var SimilarBuilder = _SimilarBuilder;
|
|
3360
3767
|
var _SearchClient = class _SearchClient {
|
|
3361
|
-
|
|
3768
|
+
/**
|
|
3769
|
+
* @param locale - The client's locale (`withLocale()`, `updateConfig({ locale })`): every builder
|
|
3770
|
+
* here sends it when the query names none, as `content()`'s reads do — the function
|
|
3771
|
+
* `TypedRelyIOClient` hands over, or a locale fixed for this client
|
|
3772
|
+
*/
|
|
3773
|
+
constructor(httpClient, locale) {
|
|
3362
3774
|
this.httpClient = httpClient;
|
|
3775
|
+
/** The client's locale, handed to every builder here to ask when it sends. */
|
|
3776
|
+
chunkMWMSFIWN_cjs.__publicField(this, "clientLocale");
|
|
3777
|
+
this.clientLocale = readClientLocale(locale);
|
|
3363
3778
|
}
|
|
3364
3779
|
/**
|
|
3365
3780
|
* Start a search query
|
|
3366
3781
|
* @param query - Search query string
|
|
3367
3782
|
*/
|
|
3368
3783
|
search(query) {
|
|
3369
|
-
return new SearchBuilder(this.httpClient, query);
|
|
3784
|
+
return new SearchBuilder(this.httpClient, query, this.clientLocale);
|
|
3370
3785
|
}
|
|
3371
3786
|
/**
|
|
3372
3787
|
* Start an autocomplete query
|
|
3373
3788
|
* @param query - Partial query to autocomplete
|
|
3374
3789
|
*/
|
|
3375
3790
|
autocomplete(query) {
|
|
3376
|
-
return new AutocompleteBuilder(this.httpClient, query);
|
|
3791
|
+
return new AutocompleteBuilder(this.httpClient, query, this.clientLocale);
|
|
3377
3792
|
}
|
|
3378
3793
|
/**
|
|
3379
3794
|
* Find content similar to a given entry
|
|
3380
3795
|
* @param sourceId - Entry ID to find similar content for
|
|
3381
3796
|
*/
|
|
3382
3797
|
similar(sourceId) {
|
|
3383
|
-
return new SimilarBuilder(this.httpClient, sourceId);
|
|
3384
|
-
}
|
|
3385
|
-
/**
|
|
3386
|
-
* Quick search helper - searches all content types
|
|
3387
|
-
* @param query - Search query
|
|
3388
|
-
* @param limit - Max results (default 20)
|
|
3389
|
-
*/
|
|
3390
|
-
async global(query, limit = 20) {
|
|
3391
|
-
return this.search(query).across("*").limit(limit).execute();
|
|
3798
|
+
return new SimilarBuilder(this.httpClient, sourceId, this.clientLocale);
|
|
3392
3799
|
}
|
|
3393
3800
|
};
|
|
3394
3801
|
chunkMWMSFIWN_cjs.__name(_SearchClient, "SearchClient");
|
|
@@ -3396,7 +3803,12 @@ var SearchClient = _SearchClient;
|
|
|
3396
3803
|
|
|
3397
3804
|
// src/batch/batch-client.ts
|
|
3398
3805
|
var _BatchBuilder = class _BatchBuilder {
|
|
3399
|
-
|
|
3806
|
+
/**
|
|
3807
|
+
* @param locale - The client's locale (`withLocale()`, `updateConfig({ locale })`), each
|
|
3808
|
+
* operation's when it names none: the function `TypedRelyIOClient` hands over, or a locale fixed
|
|
3809
|
+
* for this batch
|
|
3810
|
+
*/
|
|
3811
|
+
constructor(httpClient, locale) {
|
|
3400
3812
|
this.httpClient = httpClient;
|
|
3401
3813
|
chunkMWMSFIWN_cjs.__publicField(this, "operations", []);
|
|
3402
3814
|
chunkMWMSFIWN_cjs.__publicField(this, "defaultOptions", {
|
|
@@ -3405,6 +3817,18 @@ var _BatchBuilder = class _BatchBuilder {
|
|
|
3405
3817
|
returnData: true,
|
|
3406
3818
|
continueOnError: true
|
|
3407
3819
|
});
|
|
3820
|
+
chunkMWMSFIWN_cjs.__publicField(this, "requestHeaders");
|
|
3821
|
+
/** The client's locale, asked as each operation is added rather than copied when this was built. */
|
|
3822
|
+
chunkMWMSFIWN_cjs.__publicField(this, "clientLocale");
|
|
3823
|
+
this.clientLocale = readClientLocale(locale);
|
|
3824
|
+
}
|
|
3825
|
+
/**
|
|
3826
|
+
* An operation's body with its locale: the one it names, else the client's as it is when the
|
|
3827
|
+
* operation is added.
|
|
3828
|
+
*/
|
|
3829
|
+
localized(data) {
|
|
3830
|
+
const locale = callLocale(data.locale, this.clientLocale());
|
|
3831
|
+
return locale === void 0 ? data : { ...data, locale };
|
|
3408
3832
|
}
|
|
3409
3833
|
// ==========================================================================
|
|
3410
3834
|
// ENTRY OPERATIONS
|
|
@@ -3420,7 +3844,7 @@ var _BatchBuilder = class _BatchBuilder {
|
|
|
3420
3844
|
id,
|
|
3421
3845
|
method: "POST",
|
|
3422
3846
|
path: `/${contentType}`,
|
|
3423
|
-
body: data
|
|
3847
|
+
body: this.localized(data)
|
|
3424
3848
|
});
|
|
3425
3849
|
return this;
|
|
3426
3850
|
}
|
|
@@ -3440,7 +3864,7 @@ var _BatchBuilder = class _BatchBuilder {
|
|
|
3440
3864
|
id,
|
|
3441
3865
|
method: "PATCH",
|
|
3442
3866
|
path: `/${contentType}/${entryId}`,
|
|
3443
|
-
body: data
|
|
3867
|
+
body: this.localized(data)
|
|
3444
3868
|
});
|
|
3445
3869
|
return this;
|
|
3446
3870
|
}
|
|
@@ -3460,7 +3884,7 @@ var _BatchBuilder = class _BatchBuilder {
|
|
|
3460
3884
|
id,
|
|
3461
3885
|
method: "PUT",
|
|
3462
3886
|
path: `/${contentType}/${entryId}`,
|
|
3463
|
-
body: data
|
|
3887
|
+
body: this.localized(data)
|
|
3464
3888
|
});
|
|
3465
3889
|
return this;
|
|
3466
3890
|
}
|
|
@@ -3492,7 +3916,7 @@ var _BatchBuilder = class _BatchBuilder {
|
|
|
3492
3916
|
id,
|
|
3493
3917
|
method: "PATCH",
|
|
3494
3918
|
path: `/_singletons/${singletonKey}`,
|
|
3495
|
-
body: data
|
|
3919
|
+
body: this.localized(data)
|
|
3496
3920
|
});
|
|
3497
3921
|
return this;
|
|
3498
3922
|
}
|
|
@@ -3507,7 +3931,7 @@ var _BatchBuilder = class _BatchBuilder {
|
|
|
3507
3931
|
id,
|
|
3508
3932
|
method: "POST",
|
|
3509
3933
|
path: `/_singletons/${singletonKey}`,
|
|
3510
|
-
body: data
|
|
3934
|
+
body: this.localized(data)
|
|
3511
3935
|
});
|
|
3512
3936
|
return this;
|
|
3513
3937
|
}
|
|
@@ -3515,7 +3939,8 @@ var _BatchBuilder = class _BatchBuilder {
|
|
|
3515
3939
|
// RAW OPERATIONS
|
|
3516
3940
|
// ==========================================================================
|
|
3517
3941
|
/**
|
|
3518
|
-
* Add a raw operation (for advanced use cases)
|
|
3942
|
+
* Add a raw operation (for advanced use cases). It is sent exactly as written: the client's
|
|
3943
|
+
* locale is not added to it.
|
|
3519
3944
|
* @param operation - The operation to add
|
|
3520
3945
|
*/
|
|
3521
3946
|
raw(operation) {
|
|
@@ -3606,6 +4031,15 @@ var _BatchBuilder = class _BatchBuilder {
|
|
|
3606
4031
|
this.defaultOptions.continueOnError = false;
|
|
3607
4032
|
return this;
|
|
3608
4033
|
}
|
|
4034
|
+
/**
|
|
4035
|
+
* Headers the batch request adds — e.g. `{ 'X-RelyIO-Dataset': 'staging' }` to write a dataset
|
|
4036
|
+
* other than the client's. They replace the client's own header of the same name for this
|
|
4037
|
+
* request alone, and apply to every operation in it: a batch is one request.
|
|
4038
|
+
*/
|
|
4039
|
+
headers(headers) {
|
|
4040
|
+
this.requestHeaders = { ...this.requestHeaders, ...headers };
|
|
4041
|
+
return this;
|
|
4042
|
+
}
|
|
3609
4043
|
// ==========================================================================
|
|
3610
4044
|
// EXECUTION
|
|
3611
4045
|
// ==========================================================================
|
|
@@ -3632,9 +4066,10 @@ var _BatchBuilder = class _BatchBuilder {
|
|
|
3632
4066
|
* Clone the builder
|
|
3633
4067
|
*/
|
|
3634
4068
|
clone() {
|
|
3635
|
-
const cloned = new _BatchBuilder(this.httpClient);
|
|
4069
|
+
const cloned = new _BatchBuilder(this.httpClient, this.clientLocale);
|
|
3636
4070
|
cloned.operations = [...this.operations];
|
|
3637
4071
|
cloned.defaultOptions = { ...this.defaultOptions };
|
|
4072
|
+
cloned.requestHeaders = this.requestHeaders === void 0 ? void 0 : { ...this.requestHeaders };
|
|
3638
4073
|
return cloned;
|
|
3639
4074
|
}
|
|
3640
4075
|
/**
|
|
@@ -3652,7 +4087,8 @@ var _BatchBuilder = class _BatchBuilder {
|
|
|
3652
4087
|
}
|
|
3653
4088
|
const finalOptions = { ...this.defaultOptions, ...options };
|
|
3654
4089
|
return this.httpClient.fetchPayload("/v1/batch", "post", {
|
|
3655
|
-
body: { operations: this.operations, options: finalOptions }
|
|
4090
|
+
body: { operations: this.operations, options: finalOptions },
|
|
4091
|
+
headers: this.requestHeaders
|
|
3656
4092
|
});
|
|
3657
4093
|
}
|
|
3658
4094
|
/**
|
|
@@ -3683,14 +4119,21 @@ var _BatchBuilder = class _BatchBuilder {
|
|
|
3683
4119
|
chunkMWMSFIWN_cjs.__name(_BatchBuilder, "BatchBuilder");
|
|
3684
4120
|
var BatchBuilder = _BatchBuilder;
|
|
3685
4121
|
var _BatchClient = class _BatchClient {
|
|
3686
|
-
|
|
4122
|
+
/**
|
|
4123
|
+
* @param locale - The client's locale: the function `TypedRelyIOClient` hands over, or a locale
|
|
4124
|
+
* fixed for this client
|
|
4125
|
+
*/
|
|
4126
|
+
constructor(httpClient, locale) {
|
|
3687
4127
|
this.httpClient = httpClient;
|
|
4128
|
+
/** The client's locale, handed to every batch this builds to ask as operations are added. */
|
|
4129
|
+
chunkMWMSFIWN_cjs.__publicField(this, "clientLocale");
|
|
4130
|
+
this.clientLocale = readClientLocale(locale);
|
|
3688
4131
|
}
|
|
3689
4132
|
/**
|
|
3690
|
-
* Create a new batch builder
|
|
4133
|
+
* Create a new batch builder, whose operations default to this client's locale
|
|
3691
4134
|
*/
|
|
3692
4135
|
create() {
|
|
3693
|
-
return new BatchBuilder(this.httpClient);
|
|
4136
|
+
return new BatchBuilder(this.httpClient, this.clientLocale);
|
|
3694
4137
|
}
|
|
3695
4138
|
/**
|
|
3696
4139
|
* Quick bulk create entries
|
|
@@ -3732,12 +4175,27 @@ chunkMWMSFIWN_cjs.__name(_BatchClient, "BatchClient");
|
|
|
3732
4175
|
var BatchClient = _BatchClient;
|
|
3733
4176
|
|
|
3734
4177
|
// src/queries/adhoc-query-client.ts
|
|
4178
|
+
function withClientLocale(parameters, clientLocale) {
|
|
4179
|
+
if (clientLocale === void 0 || clientLocale === "" || parameters?.locale != null) {
|
|
4180
|
+
return parameters;
|
|
4181
|
+
}
|
|
4182
|
+
return { ...parameters, locale: clientLocale };
|
|
4183
|
+
}
|
|
4184
|
+
chunkMWMSFIWN_cjs.__name(withClientLocale, "withClientLocale");
|
|
3735
4185
|
var _AdhocQueryBuilder = class _AdhocQueryBuilder {
|
|
3736
|
-
|
|
4186
|
+
/**
|
|
4187
|
+
* @param locale - The client's locale (`withLocale()`, `updateConfig({ locale })`), sent as the
|
|
4188
|
+
* `locale` parameter when `.param('locale', …)` binds none: the function `TypedRelyIOClient`
|
|
4189
|
+
* hands over, or a locale fixed for this builder
|
|
4190
|
+
*/
|
|
4191
|
+
constructor(httpClient, locale) {
|
|
3737
4192
|
this.httpClient = httpClient;
|
|
3738
4193
|
chunkMWMSFIWN_cjs.__publicField(this, "queryDef", {});
|
|
3739
4194
|
chunkMWMSFIWN_cjs.__publicField(this, "parameters", {});
|
|
3740
4195
|
chunkMWMSFIWN_cjs.__publicField(this, "options", {});
|
|
4196
|
+
/** The client's locale, asked when the query is sent rather than copied when it was built. */
|
|
4197
|
+
chunkMWMSFIWN_cjs.__publicField(this, "clientLocale");
|
|
4198
|
+
this.clientLocale = readClientLocale(locale);
|
|
3741
4199
|
}
|
|
3742
4200
|
// ==========================================================================
|
|
3743
4201
|
// QUERY BLOCKS
|
|
@@ -3782,14 +4240,6 @@ var _AdhocQueryBuilder = class _AdhocQueryBuilder {
|
|
|
3782
4240
|
this.queryDef.search = config;
|
|
3783
4241
|
return this;
|
|
3784
4242
|
}
|
|
3785
|
-
/**
|
|
3786
|
-
* Add similar block
|
|
3787
|
-
* @param config - Similar configuration
|
|
3788
|
-
*/
|
|
3789
|
-
similar(config) {
|
|
3790
|
-
this.queryDef.similar = config;
|
|
3791
|
-
return this;
|
|
3792
|
-
}
|
|
3793
4243
|
// ==========================================================================
|
|
3794
4244
|
// FETCH MODIFIERS
|
|
3795
4245
|
// ==========================================================================
|
|
@@ -3966,16 +4416,17 @@ var _AdhocQueryBuilder = class _AdhocQueryBuilder {
|
|
|
3966
4416
|
* Execute the query
|
|
3967
4417
|
*/
|
|
3968
4418
|
async execute() {
|
|
3969
|
-
if (!this.queryDef.fetch && !this.queryDef.aggregate && !this.queryDef.search
|
|
4419
|
+
if (!this.queryDef.fetch && !this.queryDef.aggregate && !this.queryDef.search) {
|
|
3970
4420
|
throw new Error(
|
|
3971
|
-
"Query must have at least one of: fetch, aggregate
|
|
4421
|
+
"Query must have at least one of: fetch, aggregate or search. Use .from(), .aggregate() or .search()"
|
|
3972
4422
|
);
|
|
3973
4423
|
}
|
|
3974
4424
|
const body = {
|
|
3975
4425
|
query: this.queryDef
|
|
3976
4426
|
};
|
|
3977
|
-
|
|
3978
|
-
|
|
4427
|
+
const parameters = withClientLocale(this.parameters, this.clientLocale());
|
|
4428
|
+
if (parameters !== void 0 && Object.keys(parameters).length > 0) {
|
|
4429
|
+
body.parameters = parameters;
|
|
3979
4430
|
}
|
|
3980
4431
|
if (Object.keys(this.options).length > 0) {
|
|
3981
4432
|
body.options = this.options;
|
|
@@ -4006,7 +4457,7 @@ var _AdhocQueryBuilder = class _AdhocQueryBuilder {
|
|
|
4006
4457
|
* Clone the builder
|
|
4007
4458
|
*/
|
|
4008
4459
|
clone() {
|
|
4009
|
-
const cloned = new _AdhocQueryBuilder(this.httpClient);
|
|
4460
|
+
const cloned = new _AdhocQueryBuilder(this.httpClient, this.clientLocale);
|
|
4010
4461
|
cloned.queryDef = JSON.parse(JSON.stringify(this.queryDef));
|
|
4011
4462
|
cloned.parameters = { ...this.parameters };
|
|
4012
4463
|
cloned.options = { ...this.options };
|
|
@@ -4016,27 +4467,39 @@ var _AdhocQueryBuilder = class _AdhocQueryBuilder {
|
|
|
4016
4467
|
chunkMWMSFIWN_cjs.__name(_AdhocQueryBuilder, "AdhocQueryBuilder");
|
|
4017
4468
|
var AdhocQueryBuilder = _AdhocQueryBuilder;
|
|
4018
4469
|
var _AdhocQueryClient = class _AdhocQueryClient {
|
|
4019
|
-
|
|
4470
|
+
/**
|
|
4471
|
+
* @param locale - The client's locale (`withLocale()`, `updateConfig({ locale })`), sent as the
|
|
4472
|
+
* `locale` parameter of every query that binds none: the function `TypedRelyIOClient` hands
|
|
4473
|
+
* over, or a locale fixed for this client
|
|
4474
|
+
*/
|
|
4475
|
+
constructor(httpClient, locale) {
|
|
4020
4476
|
this.httpClient = httpClient;
|
|
4477
|
+
/** The client's locale, asked on every query rather than copied when this client was taken. */
|
|
4478
|
+
chunkMWMSFIWN_cjs.__publicField(this, "clientLocale");
|
|
4479
|
+
this.clientLocale = readClientLocale(locale);
|
|
4021
4480
|
}
|
|
4022
4481
|
/**
|
|
4023
4482
|
* Create a new query builder
|
|
4024
4483
|
*/
|
|
4025
4484
|
build() {
|
|
4026
|
-
return new AdhocQueryBuilder(this.httpClient);
|
|
4485
|
+
return new AdhocQueryBuilder(this.httpClient, this.clientLocale);
|
|
4027
4486
|
}
|
|
4028
4487
|
/**
|
|
4029
4488
|
* Execute a query definition directly
|
|
4030
4489
|
* @param definition - Query definition
|
|
4031
4490
|
* @param parameters - Parameter values
|
|
4032
4491
|
* @param options - Execution options
|
|
4492
|
+
* @param request - `headers` this one request adds to the client's own, e.g. `X-RelyIO-Dataset`
|
|
4493
|
+
* to query another dataset the key can see. A name the client already sends is replaced for
|
|
4494
|
+
* this request only.
|
|
4033
4495
|
*/
|
|
4034
|
-
async execute(definition, parameters, options) {
|
|
4496
|
+
async execute(definition, parameters, options, request) {
|
|
4035
4497
|
const body = {
|
|
4036
4498
|
query: definition
|
|
4037
4499
|
};
|
|
4038
|
-
|
|
4039
|
-
|
|
4500
|
+
const sent = withClientLocale(parameters, this.clientLocale());
|
|
4501
|
+
if (sent !== void 0 && Object.keys(sent).length > 0) {
|
|
4502
|
+
body.parameters = sent;
|
|
4040
4503
|
}
|
|
4041
4504
|
if (options && Object.keys(options).length > 0) {
|
|
4042
4505
|
body.options = options;
|
|
@@ -4044,7 +4507,7 @@ var _AdhocQueryClient = class _AdhocQueryClient {
|
|
|
4044
4507
|
return this.httpClient.fetchPayload(
|
|
4045
4508
|
"/v1/query",
|
|
4046
4509
|
"post",
|
|
4047
|
-
{ body }
|
|
4510
|
+
{ body, headers: request?.headers }
|
|
4048
4511
|
);
|
|
4049
4512
|
}
|
|
4050
4513
|
/**
|
|
@@ -4108,12 +4571,12 @@ async function* pollChanges(http, options = {}) {
|
|
|
4108
4571
|
let since = options.since;
|
|
4109
4572
|
let resynced;
|
|
4110
4573
|
for (; ; ) {
|
|
4111
|
-
if (
|
|
4574
|
+
if (isAborted(signal)) return;
|
|
4112
4575
|
let response;
|
|
4113
4576
|
try {
|
|
4114
4577
|
response = await pollOnce(http, since, options);
|
|
4115
4578
|
} catch (error) {
|
|
4116
|
-
if (
|
|
4579
|
+
if (isAborted(signal)) return;
|
|
4117
4580
|
if (!(error instanceof ResourceExpiredError) || since === void 0) throw error;
|
|
4118
4581
|
const expired = ChangesExpiredError.of(error);
|
|
4119
4582
|
const onExpired = options.onExpired ?? "throw";
|
|
@@ -4131,11 +4594,11 @@ async function* pollChanges(http, options = {}) {
|
|
|
4131
4594
|
const expired = resynced;
|
|
4132
4595
|
resynced = void 0;
|
|
4133
4596
|
await options.onExpired(expired);
|
|
4134
|
-
if (
|
|
4597
|
+
if (isAborted(signal)) return;
|
|
4135
4598
|
}
|
|
4136
4599
|
for (const change of data) {
|
|
4137
4600
|
yield change;
|
|
4138
|
-
if (
|
|
4601
|
+
if (isAborted(signal)) return;
|
|
4139
4602
|
}
|
|
4140
4603
|
if (data.length === 0) {
|
|
4141
4604
|
const wait = parseRetryAfterMs(headerValue(response.headers, "Retry-After"), Date.now());
|
|
@@ -4144,6 +4607,21 @@ async function* pollChanges(http, options = {}) {
|
|
|
4144
4607
|
}
|
|
4145
4608
|
}
|
|
4146
4609
|
chunkMWMSFIWN_cjs.__name(pollChanges, "pollChanges");
|
|
4610
|
+
async function readChangesHead(http, options = {}) {
|
|
4611
|
+
const response = await http.send("/v1/changes", "get", {
|
|
4612
|
+
query: {},
|
|
4613
|
+
...options.signal === void 0 ? {} : { signal: options.signal }
|
|
4614
|
+
});
|
|
4615
|
+
const { data, page } = response.body;
|
|
4616
|
+
if (page.nextCursor === null) {
|
|
4617
|
+
throw new Error("GET /v1/changes answered without page.nextCursor");
|
|
4618
|
+
}
|
|
4619
|
+
if (data.length > 0) {
|
|
4620
|
+
throw new Error("GET /v1/changes without since answered changes; a head carries none");
|
|
4621
|
+
}
|
|
4622
|
+
return page.nextCursor;
|
|
4623
|
+
}
|
|
4624
|
+
chunkMWMSFIWN_cjs.__name(readChangesHead, "readChangesHead");
|
|
4147
4625
|
async function pollOnce(http, since, options) {
|
|
4148
4626
|
const query = {};
|
|
4149
4627
|
if (since !== void 0) query.since = since;
|
|
@@ -4157,26 +4635,6 @@ async function pollOnce(http, since, options) {
|
|
|
4157
4635
|
});
|
|
4158
4636
|
}
|
|
4159
4637
|
chunkMWMSFIWN_cjs.__name(pollOnce, "pollOnce");
|
|
4160
|
-
function sleep(ms, signal) {
|
|
4161
|
-
return new Promise((resolve) => {
|
|
4162
|
-
if (aborted(signal)) {
|
|
4163
|
-
resolve();
|
|
4164
|
-
return;
|
|
4165
|
-
}
|
|
4166
|
-
const done = /* @__PURE__ */ chunkMWMSFIWN_cjs.__name(() => {
|
|
4167
|
-
clearTimeout(timer);
|
|
4168
|
-
signal?.removeEventListener("abort", done);
|
|
4169
|
-
resolve();
|
|
4170
|
-
}, "done");
|
|
4171
|
-
const timer = setTimeout(done, ms);
|
|
4172
|
-
signal?.addEventListener("abort", done, { once: true });
|
|
4173
|
-
});
|
|
4174
|
-
}
|
|
4175
|
-
chunkMWMSFIWN_cjs.__name(sleep, "sleep");
|
|
4176
|
-
function aborted(signal) {
|
|
4177
|
-
return signal?.aborted === true;
|
|
4178
|
-
}
|
|
4179
|
-
chunkMWMSFIWN_cjs.__name(aborted, "aborted");
|
|
4180
4638
|
|
|
4181
4639
|
// src/config/dev-detection.ts
|
|
4182
4640
|
function sandboxStateOf(resolution) {
|
|
@@ -4288,7 +4746,7 @@ var DEFAULT_CONFIG = {
|
|
|
4288
4746
|
environment: "production",
|
|
4289
4747
|
headers: {},
|
|
4290
4748
|
browser: {
|
|
4291
|
-
includeCredentials:
|
|
4749
|
+
includeCredentials: false,
|
|
4292
4750
|
useRelativeUrls: false
|
|
4293
4751
|
},
|
|
4294
4752
|
cache: {
|
|
@@ -4314,54 +4772,48 @@ var DEFAULT_CONFIG = {
|
|
|
4314
4772
|
}
|
|
4315
4773
|
};
|
|
4316
4774
|
function validateConfig(config) {
|
|
4317
|
-
if (
|
|
4318
|
-
throw new Error("API key is required");
|
|
4319
|
-
}
|
|
4320
|
-
if (typeof config.apiKey !== "string") {
|
|
4775
|
+
if (config.apiKey != null && typeof config.apiKey !== "string") {
|
|
4321
4776
|
throw new Error("API key must be a string");
|
|
4322
4777
|
}
|
|
4323
4778
|
if (config.baseUrl != null && typeof config.baseUrl !== "string") {
|
|
4324
4779
|
throw new Error("Base URL must be a string");
|
|
4325
4780
|
}
|
|
4326
|
-
if (config.timeout != null
|
|
4327
|
-
|
|
4328
|
-
|
|
4329
|
-
|
|
4330
|
-
|
|
4781
|
+
if (config.timeout != null) assertRequestTimeout(config.timeout);
|
|
4782
|
+
if (config.retryAttempts != null && !(Number.isInteger(config.retryAttempts) && config.retryAttempts >= 1)) {
|
|
4783
|
+
throw new Error(
|
|
4784
|
+
`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)}`
|
|
4785
|
+
);
|
|
4331
4786
|
}
|
|
4332
4787
|
}
|
|
4333
4788
|
chunkMWMSFIWN_cjs.__name(validateConfig, "validateConfig");
|
|
4334
4789
|
var devOverrideNotified = false;
|
|
4335
4790
|
function resolveConfig(userConfig) {
|
|
4336
4791
|
validateConfig(userConfig);
|
|
4337
|
-
|
|
4338
|
-
|
|
4339
|
-
|
|
4340
|
-
|
|
4341
|
-
|
|
4342
|
-
|
|
4343
|
-
|
|
4344
|
-
|
|
4345
|
-
|
|
4346
|
-
|
|
4347
|
-
|
|
4348
|
-
|
|
4349
|
-
|
|
4350
|
-
|
|
4351
|
-
|
|
4352
|
-
|
|
4353
|
-
|
|
4354
|
-
|
|
4355
|
-
|
|
4356
|
-
|
|
4357
|
-
|
|
4358
|
-
|
|
4359
|
-
|
|
4360
|
-
|
|
4361
|
-
const dev = resolveDevOverride(userConfig.dev);
|
|
4792
|
+
return withHandshake(withDefaults(DEFAULT_CONFIG, userConfig, DEFAULT_CONFIG));
|
|
4793
|
+
}
|
|
4794
|
+
chunkMWMSFIWN_cjs.__name(resolveConfig, "resolveConfig");
|
|
4795
|
+
function resolveConfigUpdate(configured, update) {
|
|
4796
|
+
validateConfig(update);
|
|
4797
|
+
const base = update.apiKey === void 0 ? configured : withoutKeyHeader(configured);
|
|
4798
|
+
return withHandshake(withDefaults(base, update, DEFAULT_CONFIG));
|
|
4799
|
+
}
|
|
4800
|
+
chunkMWMSFIWN_cjs.__name(resolveConfigUpdate, "resolveConfigUpdate");
|
|
4801
|
+
function withConfiguredKey(configured, apiKey) {
|
|
4802
|
+
return { ...withoutKeyHeader(configured), apiKey };
|
|
4803
|
+
}
|
|
4804
|
+
chunkMWMSFIWN_cjs.__name(withConfiguredKey, "withConfiguredKey");
|
|
4805
|
+
function withoutKeyHeader(configured) {
|
|
4806
|
+
return { ...configured, headers: layerHeaders(configured.headers, { [API_KEY_HEADER]: null }) };
|
|
4807
|
+
}
|
|
4808
|
+
chunkMWMSFIWN_cjs.__name(withoutKeyHeader, "withoutKeyHeader");
|
|
4809
|
+
function withHandshake(configured) {
|
|
4810
|
+
const dev = resolveDevOverride(configured.dev);
|
|
4811
|
+
const merged = withDefaults(
|
|
4812
|
+
configured,
|
|
4813
|
+
dev.state === "active" ? { apiKey: dev.apiKey, dataset: dev.sandbox.datasetId } : {},
|
|
4814
|
+
DEFAULT_CONFIG
|
|
4815
|
+
);
|
|
4362
4816
|
if (dev.state === "active") {
|
|
4363
|
-
merged.apiKey = dev.apiKey;
|
|
4364
|
-
merged.dataset = dev.sandbox.datasetId;
|
|
4365
4817
|
if (!devOverrideNotified) {
|
|
4366
4818
|
devOverrideNotified = true;
|
|
4367
4819
|
console.info(
|
|
@@ -4379,30 +4831,67 @@ function resolveConfig(userConfig) {
|
|
|
4379
4831
|
`[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.`
|
|
4380
4832
|
);
|
|
4381
4833
|
}
|
|
4382
|
-
return { config: merged, sandbox: sandboxStateOf(dev) };
|
|
4834
|
+
return { config: merged, sandbox: sandboxStateOf(dev), configured };
|
|
4383
4835
|
}
|
|
4384
|
-
chunkMWMSFIWN_cjs.__name(
|
|
4836
|
+
chunkMWMSFIWN_cjs.__name(withHandshake, "withHandshake");
|
|
4837
|
+
function withDefaults(base, given, defaults) {
|
|
4838
|
+
const merged = new Map(Object.entries(base));
|
|
4839
|
+
const givenValues = new Map(Object.entries(given ?? {}));
|
|
4840
|
+
const defaultValues = new Map(Object.entries(defaults));
|
|
4841
|
+
for (const key of /* @__PURE__ */ new Set([...merged.keys(), ...givenValues.keys()])) {
|
|
4842
|
+
const fallback = merged.get(key);
|
|
4843
|
+
const value = givenValues.get(key);
|
|
4844
|
+
const givenBag = isOptionBag(value) ? value : void 0;
|
|
4845
|
+
if (isOptionBag(fallback) && key === "headers") {
|
|
4846
|
+
merged.set(key, layerHeaders(fallback, givenBag));
|
|
4847
|
+
} else if (isOptionBag(fallback)) {
|
|
4848
|
+
const defaultBag = defaultValues.get(key);
|
|
4849
|
+
merged.set(key, withDefaults(fallback, givenBag, isOptionBag(defaultBag) ? defaultBag : {}));
|
|
4850
|
+
} else if (value === null) {
|
|
4851
|
+
if (defaultValues.has(key)) merged.set(key, defaultValues.get(key));
|
|
4852
|
+
else merged.delete(key);
|
|
4853
|
+
} else if (value !== void 0) {
|
|
4854
|
+
merged.set(key, value);
|
|
4855
|
+
}
|
|
4856
|
+
}
|
|
4857
|
+
return Object.fromEntries(merged);
|
|
4858
|
+
}
|
|
4859
|
+
chunkMWMSFIWN_cjs.__name(withDefaults, "withDefaults");
|
|
4860
|
+
function isOptionBag(value) {
|
|
4861
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
4862
|
+
}
|
|
4863
|
+
chunkMWMSFIWN_cjs.__name(isOptionBag, "isOptionBag");
|
|
4385
4864
|
|
|
4386
4865
|
// src/client/create-client.ts
|
|
4387
4866
|
var API_VERSION_SEGMENT = "v1";
|
|
4388
4867
|
var _TypedRelyIOClient = class _TypedRelyIOClient {
|
|
4389
4868
|
constructor(config) {
|
|
4869
|
+
/**
|
|
4870
|
+
* The one HTTP client every sub-client sends through. `updateConfig()` and `setApiKey()` change it
|
|
4871
|
+
* in place rather than replacing it, so a sub-client taken before either sends through the change.
|
|
4872
|
+
*/
|
|
4390
4873
|
chunkMWMSFIWN_cjs.__publicField(this, "httpClient");
|
|
4391
4874
|
chunkMWMSFIWN_cjs.__publicField(this, "config");
|
|
4875
|
+
/**
|
|
4876
|
+
* The configuration as `createClient()`, `setApiKey()` and `updateConfig()` gave it, before the
|
|
4877
|
+
* `relyio dev` handshake: what the next update is laid over, and what `withLocale()` starts from.
|
|
4878
|
+
*/
|
|
4879
|
+
chunkMWMSFIWN_cjs.__publicField(this, "configured");
|
|
4392
4880
|
chunkMWMSFIWN_cjs.__publicField(this, "_sandbox");
|
|
4393
|
-
chunkMWMSFIWN_cjs.__publicField(this, "_search");
|
|
4394
|
-
chunkMWMSFIWN_cjs.__publicField(this, "_batch");
|
|
4395
|
-
chunkMWMSFIWN_cjs.__publicField(this, "_adhocQuery");
|
|
4396
4881
|
chunkMWMSFIWN_cjs.__publicField(this, "_schema");
|
|
4882
|
+
/**
|
|
4883
|
+
* The client's locale as it is when a call is made. Every sub-client and builder is handed this
|
|
4884
|
+
* rather than a copy of the locale, so one taken before `updateConfig({ locale })` sends the new
|
|
4885
|
+
* locale, or none after `locale: null` (REL-1453).
|
|
4886
|
+
*/
|
|
4887
|
+
chunkMWMSFIWN_cjs.__publicField(this, "currentLocale", /* @__PURE__ */ chunkMWMSFIWN_cjs.__name(() => this.config.locale, "currentLocale"));
|
|
4397
4888
|
const { schema, ...clientConfig } = config;
|
|
4398
4889
|
this._schema = schema;
|
|
4399
4890
|
const resolved = resolveConfig(clientConfig);
|
|
4400
4891
|
this.config = resolved.config;
|
|
4892
|
+
this.configured = resolved.configured;
|
|
4401
4893
|
this._sandbox = resolved.sandbox;
|
|
4402
4894
|
this.httpClient = new HttpClient(this.config);
|
|
4403
|
-
this._search = new SearchClient(this.httpClient);
|
|
4404
|
-
this._batch = new BatchClient(this.httpClient);
|
|
4405
|
-
this._adhocQuery = new AdhocQueryClient(this.httpClient);
|
|
4406
4895
|
}
|
|
4407
4896
|
// ============================================================================
|
|
4408
4897
|
// CORE CLIENTS
|
|
@@ -4431,10 +4920,10 @@ var _TypedRelyIOClient = class _TypedRelyIOClient {
|
|
|
4431
4920
|
return this._sandbox;
|
|
4432
4921
|
}
|
|
4433
4922
|
/**
|
|
4434
|
-
* Get the ad-hoc query client
|
|
4923
|
+
* Get the ad-hoc query client. Every query it sends is in the client's locale as it is then.
|
|
4435
4924
|
*/
|
|
4436
4925
|
get query() {
|
|
4437
|
-
return this.
|
|
4926
|
+
return new AdhocQueryClient(this.httpClient, this.currentLocale);
|
|
4438
4927
|
}
|
|
4439
4928
|
// ============================================================================
|
|
4440
4929
|
// CONTENT OPERATIONS
|
|
@@ -4454,7 +4943,7 @@ var _TypedRelyIOClient = class _TypedRelyIOClient {
|
|
|
4454
4943
|
* ```
|
|
4455
4944
|
*/
|
|
4456
4945
|
content(contentType) {
|
|
4457
|
-
return new ContentClient(this.httpClient, contentType, this.
|
|
4946
|
+
return new ContentClient(this.httpClient, contentType, this.currentLocale);
|
|
4458
4947
|
}
|
|
4459
4948
|
/**
|
|
4460
4949
|
* Get an asset client for a specific asset type.
|
|
@@ -4475,7 +4964,7 @@ var _TypedRelyIOClient = class _TypedRelyIOClient {
|
|
|
4475
4964
|
* ```
|
|
4476
4965
|
*/
|
|
4477
4966
|
asset(assetType) {
|
|
4478
|
-
return new AssetClient(this.httpClient, assetType, this.
|
|
4967
|
+
return new AssetClient(this.httpClient, assetType, this.currentLocale);
|
|
4479
4968
|
}
|
|
4480
4969
|
/**
|
|
4481
4970
|
* Get a singleton client for a specific singleton key
|
|
@@ -4490,7 +4979,7 @@ var _TypedRelyIOClient = class _TypedRelyIOClient {
|
|
|
4490
4979
|
* ```
|
|
4491
4980
|
*/
|
|
4492
4981
|
singleton(key) {
|
|
4493
|
-
return new SingletonClient(this.httpClient, key);
|
|
4982
|
+
return new SingletonClient(this.httpClient, key, this.currentLocale);
|
|
4494
4983
|
}
|
|
4495
4984
|
/**
|
|
4496
4985
|
* Get a settings client for a specific settings group
|
|
@@ -4504,13 +4993,16 @@ var _TypedRelyIOClient = class _TypedRelyIOClient {
|
|
|
4504
4993
|
* ```
|
|
4505
4994
|
*/
|
|
4506
4995
|
settings(groupId) {
|
|
4507
|
-
return new SettingsClient(this.httpClient, groupId);
|
|
4996
|
+
return new SettingsClient(this.httpClient, groupId, this.currentLocale);
|
|
4508
4997
|
}
|
|
4509
4998
|
// ============================================================================
|
|
4510
4999
|
// SEARCH OPERATIONS
|
|
4511
5000
|
// ============================================================================
|
|
4512
5001
|
/**
|
|
4513
|
-
* Start a search query with full-text, semantic, or hybrid search
|
|
5002
|
+
* Start a search query with full-text, semantic, or hybrid search.
|
|
5003
|
+
*
|
|
5004
|
+
* Where a schema types the client, the results are its entries — every content type's until
|
|
5005
|
+
* `in()` or `across()` narrows them (`INV-SS-TYPES-INFERRED`).
|
|
4514
5006
|
*
|
|
4515
5007
|
* @example
|
|
4516
5008
|
* ```typescript
|
|
@@ -4523,7 +5015,7 @@ var _TypedRelyIOClient = class _TypedRelyIOClient {
|
|
|
4523
5015
|
* ```
|
|
4524
5016
|
*/
|
|
4525
5017
|
search(query) {
|
|
4526
|
-
return this.
|
|
5018
|
+
return this.searchClient().search(query);
|
|
4527
5019
|
}
|
|
4528
5020
|
/**
|
|
4529
5021
|
* Start an autocomplete query for search suggestions
|
|
@@ -4539,7 +5031,7 @@ var _TypedRelyIOClient = class _TypedRelyIOClient {
|
|
|
4539
5031
|
* ```
|
|
4540
5032
|
*/
|
|
4541
5033
|
autocomplete(query) {
|
|
4542
|
-
return this.
|
|
5034
|
+
return this.searchClient().autocomplete(query);
|
|
4543
5035
|
}
|
|
4544
5036
|
/**
|
|
4545
5037
|
* Find content similar to a given entry using vector search
|
|
@@ -4554,13 +5046,17 @@ var _TypedRelyIOClient = class _TypedRelyIOClient {
|
|
|
4554
5046
|
* ```
|
|
4555
5047
|
*/
|
|
4556
5048
|
similar(sourceId) {
|
|
4557
|
-
return this.
|
|
5049
|
+
return this.searchClient().similar(sourceId);
|
|
4558
5050
|
}
|
|
4559
5051
|
// ============================================================================
|
|
4560
5052
|
// BATCH OPERATIONS
|
|
4561
5053
|
// ============================================================================
|
|
4562
5054
|
/**
|
|
4563
|
-
* Start a batch operation for bulk create/update/delete
|
|
5055
|
+
* Start a batch operation for bulk create/update/delete.
|
|
5056
|
+
*
|
|
5057
|
+
* By default each operation lands or fails on its own. `atomic: true` makes the batch one
|
|
5058
|
+
* transaction, which the API accepts only when every operation is the same kind of write and none
|
|
5059
|
+
* writes a singleton that does not exist yet.
|
|
4564
5060
|
*
|
|
4565
5061
|
* @example
|
|
4566
5062
|
* ```typescript
|
|
@@ -4569,13 +5065,23 @@ var _TypedRelyIOClient = class _TypedRelyIOClient {
|
|
|
4569
5065
|
* .update('product', 'entry_abc', { content: { price: 899 } })
|
|
4570
5066
|
* .delete('product', 'entry_xyz')
|
|
4571
5067
|
* .upsertSingleton('homepage', { content: { hero: 'Welcome!' } })
|
|
4572
|
-
* .execute(
|
|
5068
|
+
* .execute()
|
|
4573
5069
|
*
|
|
4574
5070
|
* console.log(result.summary.succeeded)
|
|
5071
|
+
*
|
|
5072
|
+
* // All or nothing: one kind of write
|
|
5073
|
+
* await relyio.batch()
|
|
5074
|
+
* .update('product', 'entry_abc', { content: { price: 899 } })
|
|
5075
|
+
* .update('product', 'entry_def', { content: { price: 799 } })
|
|
5076
|
+
* .execute({ atomic: true })
|
|
4575
5077
|
* ```
|
|
4576
5078
|
*/
|
|
4577
5079
|
batch() {
|
|
4578
|
-
return this.
|
|
5080
|
+
return new BatchClient(this.httpClient, this.currentLocale).create();
|
|
5081
|
+
}
|
|
5082
|
+
/** The search client, whose builders send the client's locale as it is when each one is sent. */
|
|
5083
|
+
searchClient() {
|
|
5084
|
+
return new SearchClient(this.httpClient, this.currentLocale);
|
|
4579
5085
|
}
|
|
4580
5086
|
// ============================================================================
|
|
4581
5087
|
// CHANGES FEED
|
|
@@ -4608,6 +5114,25 @@ var _TypedRelyIOClient = class _TypedRelyIOClient {
|
|
|
4608
5114
|
changes(options = {}) {
|
|
4609
5115
|
return pollChanges(this.httpClient, options);
|
|
4610
5116
|
}
|
|
5117
|
+
/**
|
|
5118
|
+
* The dataset's current position in the changes feed, as a cursor to start
|
|
5119
|
+
* `changes({ since })` or `followChanges(…, { since })` from. One
|
|
5120
|
+
* `GET /v1/changes` without a cursor: answered at once, holding nothing.
|
|
5121
|
+
*
|
|
5122
|
+
* Take it **before** you read what you will follow. A write your read did not
|
|
5123
|
+
* see is then after the position and replayed; opening the feed afterwards
|
|
5124
|
+
* without a `since` starts after it and misses it.
|
|
5125
|
+
*
|
|
5126
|
+
* @example
|
|
5127
|
+
* ```typescript
|
|
5128
|
+
* const since = await relyio.changesHead()
|
|
5129
|
+
* const post = await relyio.content('post').findById(id).execute()
|
|
5130
|
+
* for await (const change of relyio.changes({ since, ids: [id] })) { … }
|
|
5131
|
+
* ```
|
|
5132
|
+
*/
|
|
5133
|
+
changesHead(options = {}) {
|
|
5134
|
+
return readChangesHead(this.httpClient, options);
|
|
5135
|
+
}
|
|
4611
5136
|
// ============================================================================
|
|
4612
5137
|
// QUERY OPERATIONS
|
|
4613
5138
|
// ============================================================================
|
|
@@ -4630,7 +5155,7 @@ var _TypedRelyIOClient = class _TypedRelyIOClient {
|
|
|
4630
5155
|
* ```
|
|
4631
5156
|
*/
|
|
4632
5157
|
adhoc() {
|
|
4633
|
-
return this.
|
|
5158
|
+
return this.query.build();
|
|
4634
5159
|
}
|
|
4635
5160
|
/**
|
|
4636
5161
|
* Execute a predefined query by name (from schema)
|
|
@@ -4645,10 +5170,12 @@ var _TypedRelyIOClient = class _TypedRelyIOClient {
|
|
|
4645
5170
|
* ```
|
|
4646
5171
|
*/
|
|
4647
5172
|
async executeQuery(queryName, params) {
|
|
5173
|
+
const clientLocale = this.config.locale;
|
|
5174
|
+
const namesLocale = params?.locale != null || params?.locales != null;
|
|
4648
5175
|
const response = await this.httpClient.request({
|
|
4649
5176
|
method: "GET",
|
|
4650
5177
|
url: `/${API_VERSION_SEGMENT}/${String(queryName)}`,
|
|
4651
|
-
params: params ?? {}
|
|
5178
|
+
params: namesLocale || clientLocale === void 0 || clientLocale === "" ? params ?? {} : { ...params, locale: clientLocale }
|
|
4652
5179
|
});
|
|
4653
5180
|
const payload = readPayload(response.body);
|
|
4654
5181
|
return Array.isArray(payload) ? payload : [payload];
|
|
@@ -4713,16 +5240,53 @@ var _TypedRelyIOClient = class _TypedRelyIOClient {
|
|
|
4713
5240
|
}
|
|
4714
5241
|
}
|
|
4715
5242
|
/**
|
|
4716
|
-
*
|
|
5243
|
+
* Change some of the client's options and keep the rest.
|
|
5244
|
+
*
|
|
5245
|
+
* What you pass is laid over the configuration the client holds, field by field:
|
|
5246
|
+
*
|
|
5247
|
+
* - an option you name replaces the value the client holds;
|
|
5248
|
+
* - an option left out, or given as `undefined`, keeps the value the client holds;
|
|
5249
|
+
* - an option with no default given as `null` is cleared — `locale`, `dataset`, `apiKey`, `dev`,
|
|
5250
|
+
* `fetch`, `browser.onCorsError`, `realtime.wsUrl`, `debug.logger` — so the client runs as though
|
|
5251
|
+
* it had never been given one. An option with a default takes no `null`;
|
|
5252
|
+
* - a bag of options you name — `browser`, `cache`, `realtime`, `debug` — keeps every field of it
|
|
5253
|
+
* you do not name, so `updateConfig({ browser: { includeCredentials: true } })` keeps a
|
|
5254
|
+
* configured `onCorsError`;
|
|
5255
|
+
* - `headers` is laid over the headers the client sends, a name matched without regard to case: a
|
|
5256
|
+
* header you name is added or replaces every spelling of it, every other one is still sent, and a
|
|
5257
|
+
* header given as `null` is no longer sent;
|
|
5258
|
+
* - naming `apiKey` — a key, or `null` — replaces every key the client holds, one given in
|
|
5259
|
+
* `headers` included.
|
|
5260
|
+
*
|
|
5261
|
+
* The configuration it is laid over is what `createClient()`, `setApiKey()` and earlier updates
|
|
5262
|
+
* gave the client. The `relyio dev` handshake is read again, as `createClient()` reads it: while a
|
|
5263
|
+
* sandbox is active its key and dataset are sent over the configured ones, and once it has gone
|
|
5264
|
+
* the configured ones are.
|
|
5265
|
+
*
|
|
5266
|
+
* The client's one HTTP client is changed in place, so every request from now on is sent as the
|
|
5267
|
+
* update says — including one from a `content()`, `asset()`, `singleton()` or `settings()`
|
|
5268
|
+
* sub-client, a `query` client, or a builder such as `search()` or `batch()`, taken before the
|
|
5269
|
+
* call. The locale reaches them too: each reads the client's locale when it sends, so a new
|
|
5270
|
+
* `locale` is the default of its next request and `locale: null` leaves that request with none. A
|
|
5271
|
+
* locale the call names, and a sub-client's own `withLocale()`, still win over it. A client made
|
|
5272
|
+
* by `withLocale()` is a client of its own: an update of this one does not reach it.
|
|
5273
|
+
*
|
|
5274
|
+
* @example
|
|
5275
|
+
* ```typescript
|
|
5276
|
+
* const relyio = createClient({ apiKey, headers: { 'X-Tenant': 'acme' }, browser: { onCorsError } })
|
|
5277
|
+
*
|
|
5278
|
+
* relyio.updateConfig({ headers: { 'X-Trace': traceId } }) // X-Tenant is still sent
|
|
5279
|
+
* relyio.updateConfig({ browser: { includeCredentials: true } }) // onCorsError is kept
|
|
5280
|
+
* relyio.updateConfig({ headers: { 'X-Tenant': null } }) // X-Tenant is no longer sent
|
|
5281
|
+
* relyio.updateConfig({ locale: null }) // reads name no locale of the client's
|
|
5282
|
+
* ```
|
|
4717
5283
|
*/
|
|
4718
|
-
updateConfig(
|
|
4719
|
-
const resolved =
|
|
5284
|
+
updateConfig(update) {
|
|
5285
|
+
const resolved = resolveConfigUpdate(this.configured, update);
|
|
4720
5286
|
this.config = resolved.config;
|
|
5287
|
+
this.configured = resolved.configured;
|
|
4721
5288
|
this._sandbox = resolved.sandbox;
|
|
4722
|
-
this.httpClient
|
|
4723
|
-
this._search = new SearchClient(this.httpClient);
|
|
4724
|
-
this._batch = new BatchClient(this.httpClient);
|
|
4725
|
-
this._adhocQuery = new AdhocQueryClient(this.httpClient);
|
|
5289
|
+
this.httpClient.configure(this.config);
|
|
4726
5290
|
}
|
|
4727
5291
|
/**
|
|
4728
5292
|
* Get the current configuration
|
|
@@ -4731,11 +5295,31 @@ var _TypedRelyIOClient = class _TypedRelyIOClient {
|
|
|
4731
5295
|
return { ...this.config };
|
|
4732
5296
|
}
|
|
4733
5297
|
/**
|
|
4734
|
-
*
|
|
5298
|
+
* Replace the API key every later request sends as `X-API-Key`.
|
|
5299
|
+
*
|
|
5300
|
+
* It reaches every request this client makes from now on, including those of a `content()`,
|
|
5301
|
+
* `asset()` or other sub-client taken before the call, and `getConfig().apiKey` reports it. A key
|
|
5302
|
+
* given in `headers`, under any spelling, is replaced with it and does not come back on a later
|
|
5303
|
+
* `updateConfig()`. A client already derived with `withLocale()` is a client of its own and keeps
|
|
5304
|
+
* its key.
|
|
5305
|
+
*
|
|
5306
|
+
* An empty or blank key is no key, as it is when passed to `createClient`: the next request
|
|
5307
|
+
* rejects with `MissingApiKeyError` and nothing is sent.
|
|
5308
|
+
*
|
|
5309
|
+
* Under an active `relyio dev` sandbox the sandbox's scoped key stands, as it does over the key
|
|
5310
|
+
* passed to `createClient` — replacing the configured key does not retarget the client at the
|
|
5311
|
+
* sandbox's dataset with a key the sandbox did not issue.
|
|
5312
|
+
*
|
|
5313
|
+
* @example
|
|
5314
|
+
* ```typescript
|
|
5315
|
+
* const relyio = createClient({ apiKey: process.env.RELYIO_API_KEY! })
|
|
5316
|
+
* relyio.setApiKey(rotatedKey) // the next read sends `X-API-Key: <rotatedKey>`
|
|
5317
|
+
* ```
|
|
4735
5318
|
*/
|
|
4736
5319
|
setApiKey(apiKey) {
|
|
4737
|
-
this.
|
|
4738
|
-
this.
|
|
5320
|
+
this.configured = withConfiguredKey(this.configured, apiKey);
|
|
5321
|
+
if (this._sandbox.state === "active") return;
|
|
5322
|
+
this.httpClient.setApiKey(apiKey);
|
|
4739
5323
|
}
|
|
4740
5324
|
/**
|
|
4741
5325
|
* Get the HTTP client instance (for advanced usage)
|
|
@@ -4748,7 +5332,13 @@ var _TypedRelyIOClient = class _TypedRelyIOClient {
|
|
|
4748
5332
|
// ============================================================================
|
|
4749
5333
|
/**
|
|
4750
5334
|
* Create a locale-scoped client
|
|
4751
|
-
*
|
|
5335
|
+
*
|
|
5336
|
+
* Every call the returned client builds is in this locale unless the call names one of its own,
|
|
5337
|
+
* which wins: every read — `content()`, `asset()`, `singleton()`, `settings()`, `search()`,
|
|
5338
|
+
* `similar()`, `autocomplete()`, `executeQuery()` and the ad-hoc queries — and every write and
|
|
5339
|
+
* version-history read — `create()` and `update()`, the singleton and settings writes, the asset
|
|
5340
|
+
* file writes, `versions()` and `version()`, and each operation `batch()` builds. `restore()`
|
|
5341
|
+
* always names its locale; a delete, and a `batch().raw()` operation, carry none of the client's.
|
|
4752
5342
|
*
|
|
4753
5343
|
* Type-safe when schema is provided: autocompletes valid locale codes!
|
|
4754
5344
|
*
|
|
@@ -4756,9 +5346,11 @@ var _TypedRelyIOClient = class _TypedRelyIOClient {
|
|
|
4756
5346
|
* ```typescript
|
|
4757
5347
|
* const spanish = relyio.withLocale('es-ES') // ← Autocompletes with schema!
|
|
4758
5348
|
*
|
|
4759
|
-
* //
|
|
5349
|
+
* // Reads and writes use Spanish
|
|
4760
5350
|
* const products = await spanish.content('product').query().execute()
|
|
4761
5351
|
* const homepage = await spanish.singleton('homepage').fetch()
|
|
5352
|
+
* const results = await spanish.search('zapatos').execute()
|
|
5353
|
+
* await spanish.content('product').update(id, { title: 'Zapatos' })
|
|
4762
5354
|
*
|
|
4763
5355
|
* // Original client unchanged
|
|
4764
5356
|
* const englishProducts = await relyio.content('product').query().execute()
|
|
@@ -4766,7 +5358,7 @@ var _TypedRelyIOClient = class _TypedRelyIOClient {
|
|
|
4766
5358
|
*/
|
|
4767
5359
|
withLocale(locale) {
|
|
4768
5360
|
const newConfig = {
|
|
4769
|
-
...this.
|
|
5361
|
+
...this.configured,
|
|
4770
5362
|
locale,
|
|
4771
5363
|
schema: this._schema
|
|
4772
5364
|
};
|
|
@@ -4820,7 +5412,6 @@ exports.AdhocQueryClient = AdhocQueryClient;
|
|
|
4820
5412
|
exports.AssetClient = AssetClient;
|
|
4821
5413
|
exports.AssetFileBuilder = AssetFileBuilder;
|
|
4822
5414
|
exports.AssetUploadBuilder = AssetUploadBuilder;
|
|
4823
|
-
exports.AuthenticationError = AuthenticationError;
|
|
4824
5415
|
exports.AuthorizationError = AuthorizationError;
|
|
4825
5416
|
exports.AutocompleteBuilder = AutocompleteBuilder;
|
|
4826
5417
|
exports.BaseValidationError = BaseValidationError;
|
|
@@ -4836,7 +5427,6 @@ exports.FileUploadError = FileUploadError;
|
|
|
4836
5427
|
exports.FileValidationError = FileValidationError;
|
|
4837
5428
|
exports.HttpClient = HttpClient;
|
|
4838
5429
|
exports.InvalidApiKeyError = InvalidApiKeyError;
|
|
4839
|
-
exports.InvalidFieldTypeError = InvalidFieldTypeError;
|
|
4840
5430
|
exports.InvalidPayloadError = InvalidPayloadError;
|
|
4841
5431
|
exports.MethodNotAllowedError = MethodNotAllowedError;
|
|
4842
5432
|
exports.MissingApiKeyError = MissingApiKeyError;
|
|
@@ -4845,12 +5435,10 @@ exports.PayloadTooLargeError = PayloadTooLargeError;
|
|
|
4845
5435
|
exports.PlanFeatureUnavailableError = PlanFeatureUnavailableError;
|
|
4846
5436
|
exports.RateLimitError = RateLimitError;
|
|
4847
5437
|
exports.ReadOnlyKeyError = ReadOnlyKeyError;
|
|
4848
|
-
exports.RequiredFieldError = RequiredFieldError;
|
|
4849
5438
|
exports.ResourceConflictError = ResourceConflictError;
|
|
4850
5439
|
exports.ResourceExpiredError = ResourceExpiredError;
|
|
4851
5440
|
exports.ResourceNotFoundError = ResourceNotFoundError;
|
|
4852
5441
|
exports.SDKError = SDKError;
|
|
4853
|
-
exports.SchemaValidationError = SchemaValidationError;
|
|
4854
5442
|
exports.SearchBuilder = SearchBuilder;
|
|
4855
5443
|
exports.SearchClient = SearchClient;
|
|
4856
5444
|
exports.ServerError = ServerError;
|
|
@@ -4866,9 +5454,12 @@ exports.UsageQuotaExceededError = UsageQuotaExceededError;
|
|
|
4866
5454
|
exports.ValidationError = ValidationError;
|
|
4867
5455
|
exports.createClient = createClient;
|
|
4868
5456
|
exports.entityTagOf = entityTagOf;
|
|
5457
|
+
exports.isAborted = isAborted;
|
|
4869
5458
|
exports.isAssetEntry = isAssetEntry;
|
|
4870
5459
|
exports.isResourceNotFound = isResourceNotFound;
|
|
4871
5460
|
exports.matchRoute = matchRoute;
|
|
5461
|
+
exports.serviceInstructedDelayMs = serviceInstructedDelayMs;
|
|
5462
|
+
exports.sleep = sleep;
|
|
4872
5463
|
exports.validateFile = validateFile;
|
|
4873
|
-
//# sourceMappingURL=chunk-
|
|
4874
|
-
//# sourceMappingURL=chunk-
|
|
5464
|
+
//# sourceMappingURL=chunk-VH2DE7HZ.cjs.map
|
|
5465
|
+
//# sourceMappingURL=chunk-VH2DE7HZ.cjs.map
|