@relyio/sdk 0.3.0 → 0.5.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.
@@ -734,6 +734,111 @@ function fillPath(template, params) {
734
734
  return filled;
735
735
  }
736
736
  __name(fillPath, "fillPath");
737
+ var DECLARED_PATHS = {
738
+ "/health": true,
739
+ "/health/cache": true,
740
+ "/health/live": true,
741
+ "/health/ready": true,
742
+ "/internal/media/claim": true,
743
+ "/internal/media/file-complete": true,
744
+ "/internal/media/progress": true,
745
+ "/internal/media/resolve": true,
746
+ "/internal/usage/cycle": true,
747
+ "/internal/usage/ingest": true,
748
+ "/v1/{contentType}": true,
749
+ "/v1/{contentType}/{id}": true,
750
+ "/v1/{contentType}/{id}/children": true,
751
+ "/v1/{contentType}/{id}/file": true,
752
+ "/v1/{contentType}/{id}/file/confirm": true,
753
+ "/v1/{contentType}/{id}/file/multipart/abort": true,
754
+ "/v1/{contentType}/{id}/file/multipart/complete": true,
755
+ "/v1/{contentType}/{id}/file/multipart/create": true,
756
+ "/v1/{contentType}/{id}/file/multipart/list-parts": true,
757
+ "/v1/{contentType}/{id}/file/multipart/sign-part": true,
758
+ "/v1/{contentType}/{id}/file/presign": true,
759
+ "/v1/{contentType}/{id}/file/url": true,
760
+ "/v1/{contentType}/{id}/versions": true,
761
+ "/v1/{contentType}/{id}/versions/{versionNumber}": true,
762
+ "/v1/{contentType}/{id}/versions/{versionNumber}/restore": true,
763
+ "/v1/batch": true,
764
+ "/v1/changes": true,
765
+ "/v1/meta/content-types": true,
766
+ "/v1/meta/info": true,
767
+ "/v1/meta/locales": true,
768
+ "/v1/meta/schema": true,
769
+ "/v1/meta/schema/{contentType}": true,
770
+ "/v1/meta/schema/{contentType}/fields": true,
771
+ "/v1/project": true,
772
+ "/v1/query": true,
773
+ "/v1/search": true,
774
+ "/v1/search/autocomplete": true,
775
+ "/v1/search/similar": true,
776
+ "/v1/settings": true,
777
+ "/v1/settings/{groupId}": true,
778
+ "/v1/settings/{groupId}/defaults": true,
779
+ "/v1/settings/{groupId}/reset": true,
780
+ "/v1/settings/{groupId}/versions": true,
781
+ "/v1/settings/{groupId}/versions/{versionNumber}": true,
782
+ "/v1/singletons/{key}": true,
783
+ "/v1/singletons/{key}/exists": true,
784
+ "/v1/singletons/{key}/versions": true,
785
+ "/v1/singletons/{key}/versions/{versionNumber}": true
786
+ };
787
+ function compile(path) {
788
+ const segments = path.split("/").slice(1).map((part) => {
789
+ const param = /^\{(\w+)\}$/.exec(part);
790
+ return param?.[1] === void 0 ? { kind: "static", value: part } : { kind: "param", name: param[1] };
791
+ });
792
+ return { path, segments };
793
+ }
794
+ __name(compile, "compile");
795
+ function byRouterPrecedence(a, b) {
796
+ const shared = Math.min(a.segments.length, b.segments.length);
797
+ for (let index = 0; index < shared; index += 1) {
798
+ const left = a.segments[index]?.kind;
799
+ const right = b.segments[index]?.kind;
800
+ if (left !== right) return left === "static" ? -1 : 1;
801
+ }
802
+ return 0;
803
+ }
804
+ __name(byRouterPrecedence, "byRouterPrecedence");
805
+ var COMPILED_ROUTES = Object.keys(DECLARED_PATHS).map(compile).sort(byRouterPrecedence);
806
+ function matchRoute(url, options = {}) {
807
+ const parsed = new URL(url, "http://relative.invalid");
808
+ let pathname = parsed.pathname;
809
+ if (options.baseUrl !== void 0) {
810
+ const prefix = new URL(options.baseUrl, "http://relative.invalid").pathname.replace(/\/+$/, "");
811
+ if (prefix !== "") {
812
+ if (pathname !== prefix && !pathname.startsWith(`${prefix}/`)) return null;
813
+ pathname = pathname.slice(prefix.length);
814
+ }
815
+ }
816
+ const parts = pathname.split("/").slice(1);
817
+ for (const route of COMPILED_ROUTES) {
818
+ if (route.segments.length !== parts.length) continue;
819
+ const params = {};
820
+ const matched = route.segments.every((segment, index) => {
821
+ const part = parts[index];
822
+ if (part === void 0) return false;
823
+ if (segment.kind === "static") return segment.value === part;
824
+ if (part === "") return false;
825
+ params[segment.name] = decodeURIComponent(part);
826
+ return true;
827
+ });
828
+ if (matched) return { path: route.path, params, query: readQuery(parsed.searchParams) };
829
+ }
830
+ return null;
831
+ }
832
+ __name(matchRoute, "matchRoute");
833
+ function readQuery(searchParams) {
834
+ const query = {};
835
+ for (const key of new Set(searchParams.keys())) {
836
+ const values = searchParams.getAll(key);
837
+ query[key] = values.length === 1 && values[0] !== void 0 ? values[0] : values;
838
+ }
839
+ return query;
840
+ }
841
+ __name(readQuery, "readQuery");
737
842
 
738
843
  // src/http/retry-policy.ts
739
844
  var IDEMPOTENT_METHODS = /* @__PURE__ */ new Set([
@@ -881,6 +986,7 @@ var _HttpClient = class _HttpClient {
881
986
  return response;
882
987
  } catch (error) {
883
988
  const failure = error;
989
+ if (config.signal?.aborted === true) throw failure;
884
990
  this.log("warn", "Request failed", {
885
991
  error: error instanceof Error ? error.message : "Unknown error",
886
992
  attempt,
@@ -889,7 +995,7 @@ var _HttpClient = class _HttpClient {
889
995
  if (this.retryPolicy.shouldRetry(attempt, failure, mergedConfig)) {
890
996
  const delay = this.retryPolicy.delayFor(attempt, failure);
891
997
  this.log("debug", "Retrying request", { attempt, delay });
892
- await this.sleep(delay);
998
+ await this.sleep(delay, config.signal);
893
999
  continue;
894
1000
  }
895
1001
  const sdkError = ErrorMapper.mapGenericError(failure, {
@@ -988,20 +1094,41 @@ var _HttpClient = class _HttpClient {
988
1094
  getBaseUrl() {
989
1095
  return this.baseUrl;
990
1096
  }
1097
+ /**
1098
+ * One attempt.
1099
+ *
1100
+ * The caller's `signal` and the timeout both end it, through one controller.
1101
+ * The incumbent handed `fetch` the caller's signal **instead of** its own, so a
1102
+ * request that passed a signal had no timeout at all — and a caller abort then
1103
+ * surfaced as `Request timed out`. `timedOut` is what tells the two apart: a
1104
+ * timeout is a `TimeoutError`, a caller abort is the platform's `AbortError`,
1105
+ * rethrown as it came.
1106
+ */
991
1107
  async makeRequest(url, config) {
1108
+ const caller = config.signal;
1109
+ if (caller?.aborted === true) {
1110
+ throw new DOMException("The request was aborted before it was sent", "AbortError");
1111
+ }
992
1112
  const controller = new AbortController();
993
- const timeoutId = setTimeout(() => controller.abort(), config.timeout ?? this.timeout);
1113
+ let timedOut = false;
1114
+ const timeoutId = setTimeout(() => {
1115
+ timedOut = true;
1116
+ controller.abort();
1117
+ }, config.timeout ?? this.timeout);
1118
+ const onCallerAbort = /* @__PURE__ */ __name(() => controller.abort(), "onCallerAbort");
1119
+ caller?.addEventListener("abort", onCallerAbort, { once: true });
994
1120
  try {
995
1121
  const filteredHeaders = this.filterHeadersForBrowser(config.headers ?? {});
996
1122
  const requestInit = {
997
1123
  method: config.method,
998
1124
  headers: filteredHeaders,
999
1125
  body: this.prepareRequestBody(config),
1000
- signal: config.signal ?? controller.signal,
1126
+ signal: controller.signal,
1001
1127
  // Include credentials for CORS requests if in browser and configured
1002
1128
  ...typeof window !== "undefined" && this.config.browser.includeCredentials != null && { credentials: "include" }
1003
1129
  };
1004
- const response = await fetch(url, requestInit);
1130
+ const send = this.config.fetch ?? globalThis.fetch;
1131
+ const response = await send(url, requestInit);
1005
1132
  clearTimeout(timeoutId);
1006
1133
  const responseBody = await this.parseResponse(response);
1007
1134
  if (!response.ok) {
@@ -1032,6 +1159,7 @@ var _HttpClient = class _HttpClient {
1032
1159
  throw error;
1033
1160
  }
1034
1161
  if (error instanceof DOMException && error.name === "AbortError") {
1162
+ if (!timedOut && isAborted(caller)) throw error;
1035
1163
  throw new TimeoutError(
1036
1164
  `Request timed out after ${config.timeout ?? this.timeout}ms`,
1037
1165
  config.timeout ?? this.timeout
@@ -1063,6 +1191,8 @@ var _HttpClient = class _HttpClient {
1063
1191
  throw corsError;
1064
1192
  }
1065
1193
  throw error;
1194
+ } finally {
1195
+ caller?.removeEventListener("abort", onCallerAbort);
1066
1196
  }
1067
1197
  }
1068
1198
  /**
@@ -1151,8 +1281,21 @@ var _HttpClient = class _HttpClient {
1151
1281
  });
1152
1282
  return obj;
1153
1283
  }
1154
- sleep(ms) {
1155
- return new Promise((resolve) => setTimeout(resolve, ms));
1284
+ /** A backoff the caller's abort cuts short; the next attempt then refuses to send. */
1285
+ sleep(ms, signal) {
1286
+ return new Promise((resolve) => {
1287
+ if (isAborted(signal)) {
1288
+ resolve();
1289
+ return;
1290
+ }
1291
+ const done = /* @__PURE__ */ __name(() => {
1292
+ clearTimeout(timer);
1293
+ signal?.removeEventListener("abort", done);
1294
+ resolve();
1295
+ }, "done");
1296
+ const timer = setTimeout(done, ms);
1297
+ signal?.addEventListener("abort", done, { once: true });
1298
+ });
1156
1299
  }
1157
1300
  log(level, message, data) {
1158
1301
  if (!this.debug) return;
@@ -1165,6 +1308,10 @@ var _HttpClient = class _HttpClient {
1165
1308
  };
1166
1309
  __name(_HttpClient, "HttpClient");
1167
1310
  var HttpClient = _HttpClient;
1311
+ function isAborted(signal) {
1312
+ return signal?.aborted === true;
1313
+ }
1314
+ __name(isAborted, "isAborted");
1168
1315
 
1169
1316
  // src/content/query-builder.ts
1170
1317
  var _ContentQueryBuilder = class _ContentQueryBuilder {
@@ -3932,7 +4079,108 @@ var _AdhocQueryClient = class _AdhocQueryClient {
3932
4079
  __name(_AdhocQueryClient, "AdhocQueryClient");
3933
4080
  var AdhocQueryClient = _AdhocQueryClient;
3934
4081
 
4082
+ // src/changes/changes.ts
4083
+ var CHANGES_POLL_TIMEOUT_MS = 25e3 + 5e3;
4084
+ var _ChangesExpiredError = class _ChangesExpiredError extends ResourceExpiredError {
4085
+ /** The base class's signature, so `withContext` can rebuild one. */
4086
+ constructor(message, statusCode = 410, cause, context) {
4087
+ super(message, statusCode, cause, context);
4088
+ __publicField(this, "reason");
4089
+ this.name = "ChangesExpiredError";
4090
+ this.reason = expiredReasonOf(message);
4091
+ }
4092
+ static of(expired) {
4093
+ return new _ChangesExpiredError(expired.message, expired.statusCode, expired, expired.context);
4094
+ }
4095
+ };
4096
+ __name(_ChangesExpiredError, "ChangesExpiredError");
4097
+ var ChangesExpiredError = _ChangesExpiredError;
4098
+ function expiredReasonOf(message) {
4099
+ if (message.includes("(retention)")) return "retention";
4100
+ if (message.includes("(dataset-replaced)")) return "dataset-replaced";
4101
+ return "unknown";
4102
+ }
4103
+ __name(expiredReasonOf, "expiredReasonOf");
4104
+ async function* pollChanges(http, options = {}) {
4105
+ const { signal } = options;
4106
+ let since = options.since;
4107
+ let resynced;
4108
+ for (; ; ) {
4109
+ if (aborted(signal)) return;
4110
+ let response;
4111
+ try {
4112
+ response = await pollOnce(http, since, options);
4113
+ } catch (error) {
4114
+ if (aborted(signal)) return;
4115
+ if (!(error instanceof ResourceExpiredError) || since === void 0) throw error;
4116
+ const expired = ChangesExpiredError.of(error);
4117
+ const onExpired = options.onExpired ?? "throw";
4118
+ if (onExpired === "throw") throw expired;
4119
+ since = void 0;
4120
+ resynced = typeof onExpired === "function" ? expired : void 0;
4121
+ continue;
4122
+ }
4123
+ const { data, page } = response.body;
4124
+ if (page.nextCursor === null) {
4125
+ throw new Error("GET /v1/changes answered without page.nextCursor");
4126
+ }
4127
+ since = page.nextCursor;
4128
+ if (resynced !== void 0 && typeof options.onExpired === "function") {
4129
+ const expired = resynced;
4130
+ resynced = void 0;
4131
+ await options.onExpired(expired);
4132
+ if (aborted(signal)) return;
4133
+ }
4134
+ for (const change of data) {
4135
+ yield change;
4136
+ if (aborted(signal)) return;
4137
+ }
4138
+ if (data.length === 0) {
4139
+ const wait = parseRetryAfterMs(headerValue(response.headers, "Retry-After"), Date.now());
4140
+ if (wait !== void 0 && wait > 0) await sleep(wait, signal);
4141
+ }
4142
+ }
4143
+ }
4144
+ __name(pollChanges, "pollChanges");
4145
+ async function pollOnce(http, since, options) {
4146
+ const query = {};
4147
+ if (since !== void 0) query.since = since;
4148
+ if (options.types !== void 0) query.types = options.types.join(",");
4149
+ if (options.ids !== void 0) query.ids = options.ids.join(",");
4150
+ if (options.limit !== void 0) query.limit = options.limit;
4151
+ return http.send("/v1/changes", "get", {
4152
+ query,
4153
+ timeout: CHANGES_POLL_TIMEOUT_MS,
4154
+ ...options.signal === void 0 ? {} : { signal: options.signal }
4155
+ });
4156
+ }
4157
+ __name(pollOnce, "pollOnce");
4158
+ function sleep(ms, signal) {
4159
+ return new Promise((resolve) => {
4160
+ if (aborted(signal)) {
4161
+ resolve();
4162
+ return;
4163
+ }
4164
+ const done = /* @__PURE__ */ __name(() => {
4165
+ clearTimeout(timer);
4166
+ signal?.removeEventListener("abort", done);
4167
+ resolve();
4168
+ }, "done");
4169
+ const timer = setTimeout(done, ms);
4170
+ signal?.addEventListener("abort", done, { once: true });
4171
+ });
4172
+ }
4173
+ __name(sleep, "sleep");
4174
+ function aborted(signal) {
4175
+ return signal?.aborted === true;
4176
+ }
4177
+ __name(aborted, "aborted");
4178
+
3935
4179
  // src/config/dev-detection.ts
4180
+ function sandboxStateOf(resolution) {
4181
+ return resolution.state === "active" ? resolution.sandbox : resolution;
4182
+ }
4183
+ __name(sandboxStateOf, "sandboxStateOf");
3936
4184
  function getProcess() {
3937
4185
  return typeof process !== "undefined" ? process : void 0;
3938
4186
  }
@@ -3956,11 +4204,14 @@ function resolveFromEnv(proc, now) {
3956
4204
  case "active":
3957
4205
  return {
3958
4206
  state: "active",
3959
- override: {
3960
- dataset: verdict.credentials.dataset,
3961
- apiKey: verdict.credentials.apiKey,
4207
+ sandbox: {
4208
+ state: "active",
4209
+ datasetId: verdict.credentials.dataset,
4210
+ branchId: null,
4211
+ expiresAt: verdict.expiresAt,
3962
4212
  source: "env"
3963
- }
4213
+ },
4214
+ apiKey: verdict.credentials.apiKey
3964
4215
  };
3965
4216
  case "expired":
3966
4217
  return { state: "expired", expiredAt: verdict.expiredAt };
@@ -3991,11 +4242,14 @@ function resolveFromFile(proc, now) {
3991
4242
  case "active":
3992
4243
  return {
3993
4244
  state: "active",
3994
- override: {
3995
- dataset: verdict.context.datasetId,
3996
- apiKey: verdict.context.previewApiKey,
4245
+ sandbox: {
4246
+ state: "active",
4247
+ datasetId: verdict.context.datasetId,
4248
+ branchId: verdict.context.branchId,
4249
+ expiresAt: verdict.context.expiresAt,
3997
4250
  source: "file"
3998
- }
4251
+ },
4252
+ apiKey: verdict.context.previewApiKey
3999
4253
  };
4000
4254
  case "expired":
4001
4255
  return { state: "expired", expiredAt: verdict.expiredAt };
@@ -4076,7 +4330,7 @@ function validateConfig(config) {
4076
4330
  }
4077
4331
  __name(validateConfig, "validateConfig");
4078
4332
  var devOverrideNotified = false;
4079
- function mergeConfig(userConfig) {
4333
+ function resolveConfig(userConfig) {
4080
4334
  validateConfig(userConfig);
4081
4335
  const merged = {
4082
4336
  ...DEFAULT_CONFIG,
@@ -4104,12 +4358,12 @@ function mergeConfig(userConfig) {
4104
4358
  };
4105
4359
  const dev = resolveDevOverride(userConfig.dev);
4106
4360
  if (dev.state === "active") {
4107
- merged.apiKey = dev.override.apiKey;
4108
- merged.dataset = dev.override.dataset;
4361
+ merged.apiKey = dev.apiKey;
4362
+ merged.dataset = dev.sandbox.datasetId;
4109
4363
  if (!devOverrideNotified) {
4110
4364
  devOverrideNotified = true;
4111
4365
  console.info(
4112
- `[RelyIO] Sandbox dev mode active (${dev.override.source}) \u2014 targeting dataset "${dev.override.dataset}" with a scoped preview key.`
4366
+ `[RelyIO] Sandbox dev mode active (${dev.sandbox.source}) \u2014 targeting dataset "${dev.sandbox.datasetId}" with a scoped preview key.`
4113
4367
  );
4114
4368
  }
4115
4369
  } else if (dev.state === "expired" && !devOverrideNotified) {
@@ -4123,9 +4377,9 @@ function mergeConfig(userConfig) {
4123
4377
  `[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.`
4124
4378
  );
4125
4379
  }
4126
- return merged;
4380
+ return { config: merged, sandbox: sandboxStateOf(dev) };
4127
4381
  }
4128
- __name(mergeConfig, "mergeConfig");
4382
+ __name(resolveConfig, "resolveConfig");
4129
4383
 
4130
4384
  // src/client/create-client.ts
4131
4385
  var API_VERSION_SEGMENT = "v1";
@@ -4133,13 +4387,16 @@ var _TypedRelyIOClient = class _TypedRelyIOClient {
4133
4387
  constructor(config) {
4134
4388
  __publicField(this, "httpClient");
4135
4389
  __publicField(this, "config");
4390
+ __publicField(this, "_sandbox");
4136
4391
  __publicField(this, "_search");
4137
4392
  __publicField(this, "_batch");
4138
4393
  __publicField(this, "_adhocQuery");
4139
4394
  __publicField(this, "_schema");
4140
4395
  const { schema, ...clientConfig } = config;
4141
4396
  this._schema = schema;
4142
- this.config = mergeConfig(clientConfig);
4397
+ const resolved = resolveConfig(clientConfig);
4398
+ this.config = resolved.config;
4399
+ this._sandbox = resolved.sandbox;
4143
4400
  this.httpClient = new HttpClient(this.config);
4144
4401
  this._search = new SearchClient(this.httpClient);
4145
4402
  this._batch = new BatchClient(this.httpClient);
@@ -4154,6 +4411,23 @@ var _TypedRelyIOClient = class _TypedRelyIOClient {
4154
4411
  get schema() {
4155
4412
  return this._schema;
4156
4413
  }
4414
+ /**
4415
+ * The `relyio dev` sandbox this client resolved at construction, as the preview toolbar displays
4416
+ * it (`sdk-surfaces-spec.md` decision 22).
4417
+ *
4418
+ * Plain, JSON-serializable data and no key, so a server component can hand it to a client
4419
+ * component as a prop — the browser cannot read the handshake itself, so a client created there
4420
+ * reports `absent`. See {@link SandboxState} for what each state means.
4421
+ *
4422
+ * @example
4423
+ * ```tsx
4424
+ * // app/layout.tsx — a server component handing the state to a client component
4425
+ * <SandboxBadge sandbox={relyio.sandbox} />
4426
+ * ```
4427
+ */
4428
+ get sandbox() {
4429
+ return this._sandbox;
4430
+ }
4157
4431
  /**
4158
4432
  * Get the ad-hoc query client
4159
4433
  */
@@ -4302,6 +4576,37 @@ var _TypedRelyIOClient = class _TypedRelyIOClient {
4302
4576
  return this._batch.create();
4303
4577
  }
4304
4578
  // ============================================================================
4579
+ // CHANGES FEED
4580
+ // ============================================================================
4581
+ /**
4582
+ * Follow the dataset's changes feed: each write this key can see, as ids, in
4583
+ * order, long-polled from `GET /v1/changes`.
4584
+ *
4585
+ * Lazy — nothing is requested until the first `next()`. It runs until
4586
+ * `signal` aborts, which ends the `for await` cleanly rather than throwing.
4587
+ * A change names what changed; refetch it through the ordinary read path
4588
+ * (`INV-SS-CHANGE-IS-IDS`).
4589
+ *
4590
+ * @example
4591
+ * ```typescript
4592
+ * const controller = new AbortController()
4593
+ * for await (const change of relyio.changes({ since: cursor, types: ['post'], signal: controller.signal })) {
4594
+ * // { entryId, contentType, locale, kind, cursor }
4595
+ * }
4596
+ * ```
4597
+ *
4598
+ * @example Resync when the cursor has expired
4599
+ * ```typescript
4600
+ * for await (const change of relyio.changes({
4601
+ * since: cursor,
4602
+ * onExpired: async () => invalidateEverything(),
4603
+ * })) { … }
4604
+ * ```
4605
+ */
4606
+ changes(options = {}) {
4607
+ return pollChanges(this.httpClient, options);
4608
+ }
4609
+ // ============================================================================
4305
4610
  // QUERY OPERATIONS
4306
4611
  // ============================================================================
4307
4612
  /**
@@ -4346,6 +4651,23 @@ var _TypedRelyIOClient = class _TypedRelyIOClient {
4346
4651
  const payload = readPayload(response.body);
4347
4652
  return Array.isArray(payload) ? payload : [payload];
4348
4653
  }
4654
+ /**
4655
+ * Describe the project this key resolves to — `GET /v1/project`.
4656
+ *
4657
+ * `dataset` is the one this client's requests select (`dataset`, a sandbox from the `relyio dev`
4658
+ * handshake, or the key's default), which is not always the project's default, so a Studio link
4659
+ * built from `studioUrl` should carry it as `?dataset=`. `studioUrl` is `null` — a value, not an
4660
+ * error — when the service has no Dashboard address configured.
4661
+ *
4662
+ * @example
4663
+ * ```typescript
4664
+ * const { studioUrl, dataset } = await relyio.project()
4665
+ * if (studioUrl !== null) window.open(`${studioUrl}?dataset=${dataset.id}`)
4666
+ * ```
4667
+ */
4668
+ async project() {
4669
+ return this.httpClient.fetchPayload("/v1/project", "get", {});
4670
+ }
4349
4671
  /**
4350
4672
  * Get schema information from the API
4351
4673
  */
@@ -4392,7 +4714,9 @@ var _TypedRelyIOClient = class _TypedRelyIOClient {
4392
4714
  * Update the configuration and reinitialize all clients
4393
4715
  */
4394
4716
  updateConfig(newConfig) {
4395
- this.config = mergeConfig({ ...this.config, ...newConfig });
4717
+ const resolved = resolveConfig({ ...this.config, ...newConfig });
4718
+ this.config = resolved.config;
4719
+ this._sandbox = resolved.sandbox;
4396
4720
  this.httpClient = new HttpClient(this.config);
4397
4721
  this._search = new SearchClient(this.httpClient);
4398
4722
  this._batch = new BatchClient(this.httpClient);
@@ -4489,6 +4813,6 @@ function createClient(config) {
4489
4813
  }
4490
4814
  __name(createClient, "createClient");
4491
4815
 
4492
- export { AdhocQueryBuilder, AdhocQueryClient, AssetClient, AssetFileBuilder, AssetUploadBuilder, AuthenticationError, AuthorizationError, AutocompleteBuilder, BaseValidationError, BatchBuilder, BatchClient, ConnectionError, ContentByIdBuilder, ContentClient, ContentQueryBuilder, ErrorMapper, FileUploadError, FileValidationError, HttpClient, InvalidApiKeyError, InvalidFieldTypeError, InvalidPayloadError, MethodNotAllowedError, MissingApiKeyError, NetworkError, PayloadTooLargeError, PlanFeatureUnavailableError, RateLimitError, ReadOnlyKeyError, RequiredFieldError, ResourceConflictError, ResourceExpiredError, ResourceNotFoundError, SDKError, SchemaValidationError, SearchBuilder, SearchClient, ServerError, ServiceIndeterminateError, SettingsClient, SimilarBuilder, SingletonClient, TimeoutError, TransactionRolledBackError, TypedRelyIOClient, UnknownContractError, UsageQuotaExceededError, ValidationError, createClient, entityTagOf, isAssetEntry, isResourceNotFound, validateFile };
4493
- //# sourceMappingURL=chunk-QIZOBT5F.js.map
4494
- //# sourceMappingURL=chunk-QIZOBT5F.js.map
4816
+ export { AdhocQueryBuilder, AdhocQueryClient, AssetClient, AssetFileBuilder, AssetUploadBuilder, AuthenticationError, AuthorizationError, AutocompleteBuilder, BaseValidationError, BatchBuilder, BatchClient, ChangesExpiredError, ConnectionError, ContentByIdBuilder, ContentClient, ContentQueryBuilder, ErrorMapper, FileUploadError, FileValidationError, HttpClient, InvalidApiKeyError, InvalidFieldTypeError, InvalidPayloadError, MethodNotAllowedError, MissingApiKeyError, NetworkError, PayloadTooLargeError, PlanFeatureUnavailableError, RateLimitError, ReadOnlyKeyError, RequiredFieldError, ResourceConflictError, ResourceExpiredError, ResourceNotFoundError, SDKError, SchemaValidationError, SearchBuilder, SearchClient, ServerError, ServiceIndeterminateError, SettingsClient, SimilarBuilder, SingletonClient, TimeoutError, TransactionRolledBackError, TypedRelyIOClient, UnknownContractError, UsageQuotaExceededError, ValidationError, createClient, entityTagOf, isAssetEntry, isResourceNotFound, matchRoute, validateFile };
4817
+ //# sourceMappingURL=chunk-5AZUUV5B.js.map
4818
+ //# sourceMappingURL=chunk-5AZUUV5B.js.map