@tinycloud/sdk-services 3.0.0 → 3.1.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -1075,6 +1075,24 @@ declare function parseAuthError(responseText: string): {
1075
1075
  * Create a service error for unauthorized action (missing capability).
1076
1076
  */
1077
1077
  declare function authUnauthorizedError(service: string, message: string, meta?: Record<string, unknown>): ServiceError;
1078
+ /**
1079
+ * Authorization verdict read from an error's structure, never its message:
1080
+ * - `"unauthenticated"`: HTTP 401 — the session is missing or stale.
1081
+ * - `"forbidden"`: HTTP 403, or `AUTH_UNAUTHORIZED` without a status — the
1082
+ * session is valid but lacks the capability.
1083
+ * - `"other"`: a non-authorization HTTP error status (4xx/5xx).
1084
+ */
1085
+ type AuthorizationVerdict = "unauthenticated" | "forbidden" | "other";
1086
+ /**
1087
+ * Classify an error from its typed HTTP error status (`status`, `statusCode`,
1088
+ * or `meta.status`, 4xx/5xx only) and `AUTH_UNAUTHORIZED` code, following the
1089
+ * `cause` chain outer-first (at most {@link MAX_CAUSE_DEPTH} links, cycles
1090
+ * stop the walk) so wrappers that rethrow with `cause` keep the verdict. The
1091
+ * outermost error status decides, so an outer 5xx keeps its retry budget even
1092
+ * over an inner 401. Returns `undefined` for untyped errors; only then may
1093
+ * callers fall back to message heuristics.
1094
+ */
1095
+ declare function authorizationVerdictOf(error: unknown): AuthorizationVerdict | undefined;
1078
1096
  /**
1079
1097
  * Create a service error for storage quota exceeded (402 Payment Required).
1080
1098
  */
@@ -2245,4 +2263,4 @@ declare class SecretsService implements ISecretsService {
2245
2263
  listAll(): Promise<Result<SecretCatalogEntry[], SecretsError>>;
2246
2264
  }
2247
2265
 
2248
- export { BaseService, type BaseServiceOptions, type ColumnInfo, type DataVaultConfig, DataVaultService, DecryptCapabilityProof, DuckDbAction, type DuckDbActionType, type DuckDbBatchOptions, type BatchResponse as DuckDbBatchResponse, DuckDbDatabaseHandle, type DuckDbExecuteOptions, type ExecuteResponse as DuckDbExecuteResponse, type DuckDbOptions, type DuckDbQueryOptions, type QueryResponse as DuckDbQueryResponse, DuckDbService, type DuckDbServiceConfig, type DuckDbStatement, type DuckDbValue, EventHandler, FetchFunction, GenericKVResponseSchema, type GenericKVResponseType, GenericResultSchema, type HookEvent, type HookServiceName, type HookStreamEvent, type HookSubscription, type HookWebhookListOptions, type HookWebhookRecord, type HookWebhookRegistration, type HookWebhookScope, type HookWebhookUnregisterOptions, HooksService, type HooksServiceConfig, type IDataVaultService, type IDuckDbDatabaseHandle, type IDuckDbService, IEncryptionService, type IHooksService, IKVService, type ISecretsService, IService, IServiceContext, InvokeAnyFunction, InvokeFunction, KVListResponseSchema, type KVListResponseType, KVListResultSchema, type KVListResultType, KVResponseHeadersSchema, type KVResponseHeadersType, type ParsedSecretCatalogKey, PermissionHint, type QuotaConfig, type QuotaStatus, type ResolvedSecretPath, Result, RetryPolicy, RetryPolicySchema, type RetryPolicyType, SECRET_NAME_RE, type SchemaInfo, type SecretCatalogEntry, type SecretPayload, type SecretScopeOptions, type SecretsError, SecretsService, type ServiceConstructor, ServiceContext, type ServiceContextConfig, ServiceError, ServiceErrorEventSchema, type ServiceErrorEventType, ServiceErrorSchema, type ServiceErrorType, type ServiceRegistration, ServiceRequestEventSchema, type ServiceRequestEventType, ServiceResponseEventSchema, type ServiceResponseEventType, ServiceRetryEventSchema, type ServiceRetryEventType, ServiceSession, ServiceSessionSchema, type ServiceSessionType, StorageQuotaInfo, type SubscribeOptions, type TableInfo, TelemetryConfig, TelemetrySpanEventSchema, type TelemetrySpanEventType, type TinyCloudDebugEnableOptions, type TinyCloudDebugEvent, type TinyCloudDebugLevel, TinyCloudDebugLogger, type TinyCloudDebugTimer, TinyCloudQuota, type ValidationError, type VaultCrypto, type VaultEntry, type VaultError, type VaultGetOptions, type VaultGrantOptions, VaultHeaders, type VaultListOptions, type VaultListPage, type VaultNetworkReadResult, VaultPublicSpaceKVActions, type VaultPutOptions, type ViewInfo, type WasmVaultFunctions, abortedError, authExpiredError, authRequiredError, authUnauthorizedError, canonicalizeSecretScope, clearTinyCloudDebugLogs, createKVResponseSchema, createResultSchema, createVaultCrypto, disableTinyCloudDebug, enableTinyCloudDebug, errorResult, getTinyCloudDebugLogs, installTinyCloudDebugGlobals, networkError, notFoundError, parseAuthError, parsePermissionHint, parsePermissionHintFromErrorText, parseSecretCatalogKey, permissionDeniedError, resolveSecretListPrefix, resolveSecretPath, storageLimitReachedError, storageQuotaExceededError, timeoutError, tinyCloudDebugLogger, validateKVListResponse, validateKVResponseHeaders, validateRetryPolicy, validateServiceError, validateServiceRequestEvent, validateServiceResponseEvent, validateServiceSession, validateTelemetrySpanEvent, wrapError };
2266
+ export { type AuthorizationVerdict, BaseService, type BaseServiceOptions, type ColumnInfo, type DataVaultConfig, DataVaultService, DecryptCapabilityProof, DuckDbAction, type DuckDbActionType, type DuckDbBatchOptions, type BatchResponse as DuckDbBatchResponse, DuckDbDatabaseHandle, type DuckDbExecuteOptions, type ExecuteResponse as DuckDbExecuteResponse, type DuckDbOptions, type DuckDbQueryOptions, type QueryResponse as DuckDbQueryResponse, DuckDbService, type DuckDbServiceConfig, type DuckDbStatement, type DuckDbValue, EventHandler, FetchFunction, GenericKVResponseSchema, type GenericKVResponseType, GenericResultSchema, type HookEvent, type HookServiceName, type HookStreamEvent, type HookSubscription, type HookWebhookListOptions, type HookWebhookRecord, type HookWebhookRegistration, type HookWebhookScope, type HookWebhookUnregisterOptions, HooksService, type HooksServiceConfig, type IDataVaultService, type IDuckDbDatabaseHandle, type IDuckDbService, IEncryptionService, type IHooksService, IKVService, type ISecretsService, IService, IServiceContext, InvokeAnyFunction, InvokeFunction, KVListResponseSchema, type KVListResponseType, KVListResultSchema, type KVListResultType, KVResponseHeadersSchema, type KVResponseHeadersType, type ParsedSecretCatalogKey, PermissionHint, type QuotaConfig, type QuotaStatus, type ResolvedSecretPath, Result, RetryPolicy, RetryPolicySchema, type RetryPolicyType, SECRET_NAME_RE, type SchemaInfo, type SecretCatalogEntry, type SecretPayload, type SecretScopeOptions, type SecretsError, SecretsService, type ServiceConstructor, ServiceContext, type ServiceContextConfig, ServiceError, ServiceErrorEventSchema, type ServiceErrorEventType, ServiceErrorSchema, type ServiceErrorType, type ServiceRegistration, ServiceRequestEventSchema, type ServiceRequestEventType, ServiceResponseEventSchema, type ServiceResponseEventType, ServiceRetryEventSchema, type ServiceRetryEventType, ServiceSession, ServiceSessionSchema, type ServiceSessionType, StorageQuotaInfo, type SubscribeOptions, type TableInfo, TelemetryConfig, TelemetrySpanEventSchema, type TelemetrySpanEventType, type TinyCloudDebugEnableOptions, type TinyCloudDebugEvent, type TinyCloudDebugLevel, TinyCloudDebugLogger, type TinyCloudDebugTimer, TinyCloudQuota, type ValidationError, type VaultCrypto, type VaultEntry, type VaultError, type VaultGetOptions, type VaultGrantOptions, VaultHeaders, type VaultListOptions, type VaultListPage, type VaultNetworkReadResult, VaultPublicSpaceKVActions, type VaultPutOptions, type ViewInfo, type WasmVaultFunctions, abortedError, authExpiredError, authRequiredError, authUnauthorizedError, authorizationVerdictOf, canonicalizeSecretScope, clearTinyCloudDebugLogs, createKVResponseSchema, createResultSchema, createVaultCrypto, disableTinyCloudDebug, enableTinyCloudDebug, errorResult, getTinyCloudDebugLogs, installTinyCloudDebugGlobals, networkError, notFoundError, parseAuthError, parsePermissionHint, parsePermissionHintFromErrorText, parseSecretCatalogKey, permissionDeniedError, resolveSecretListPrefix, resolveSecretPath, storageLimitReachedError, storageQuotaExceededError, timeoutError, tinyCloudDebugLogger, validateKVListResponse, validateKVResponseHeaders, validateRetryPolicy, validateServiceError, validateServiceRequestEvent, validateServiceResponseEvent, validateServiceSession, validateTelemetrySpanEvent, wrapError };
package/dist/index.d.ts CHANGED
@@ -1075,6 +1075,24 @@ declare function parseAuthError(responseText: string): {
1075
1075
  * Create a service error for unauthorized action (missing capability).
1076
1076
  */
1077
1077
  declare function authUnauthorizedError(service: string, message: string, meta?: Record<string, unknown>): ServiceError;
1078
+ /**
1079
+ * Authorization verdict read from an error's structure, never its message:
1080
+ * - `"unauthenticated"`: HTTP 401 — the session is missing or stale.
1081
+ * - `"forbidden"`: HTTP 403, or `AUTH_UNAUTHORIZED` without a status — the
1082
+ * session is valid but lacks the capability.
1083
+ * - `"other"`: a non-authorization HTTP error status (4xx/5xx).
1084
+ */
1085
+ type AuthorizationVerdict = "unauthenticated" | "forbidden" | "other";
1086
+ /**
1087
+ * Classify an error from its typed HTTP error status (`status`, `statusCode`,
1088
+ * or `meta.status`, 4xx/5xx only) and `AUTH_UNAUTHORIZED` code, following the
1089
+ * `cause` chain outer-first (at most {@link MAX_CAUSE_DEPTH} links, cycles
1090
+ * stop the walk) so wrappers that rethrow with `cause` keep the verdict. The
1091
+ * outermost error status decides, so an outer 5xx keeps its retry budget even
1092
+ * over an inner 401. Returns `undefined` for untyped errors; only then may
1093
+ * callers fall back to message heuristics.
1094
+ */
1095
+ declare function authorizationVerdictOf(error: unknown): AuthorizationVerdict | undefined;
1078
1096
  /**
1079
1097
  * Create a service error for storage quota exceeded (402 Payment Required).
1080
1098
  */
@@ -2245,4 +2263,4 @@ declare class SecretsService implements ISecretsService {
2245
2263
  listAll(): Promise<Result<SecretCatalogEntry[], SecretsError>>;
2246
2264
  }
2247
2265
 
2248
- export { BaseService, type BaseServiceOptions, type ColumnInfo, type DataVaultConfig, DataVaultService, DecryptCapabilityProof, DuckDbAction, type DuckDbActionType, type DuckDbBatchOptions, type BatchResponse as DuckDbBatchResponse, DuckDbDatabaseHandle, type DuckDbExecuteOptions, type ExecuteResponse as DuckDbExecuteResponse, type DuckDbOptions, type DuckDbQueryOptions, type QueryResponse as DuckDbQueryResponse, DuckDbService, type DuckDbServiceConfig, type DuckDbStatement, type DuckDbValue, EventHandler, FetchFunction, GenericKVResponseSchema, type GenericKVResponseType, GenericResultSchema, type HookEvent, type HookServiceName, type HookStreamEvent, type HookSubscription, type HookWebhookListOptions, type HookWebhookRecord, type HookWebhookRegistration, type HookWebhookScope, type HookWebhookUnregisterOptions, HooksService, type HooksServiceConfig, type IDataVaultService, type IDuckDbDatabaseHandle, type IDuckDbService, IEncryptionService, type IHooksService, IKVService, type ISecretsService, IService, IServiceContext, InvokeAnyFunction, InvokeFunction, KVListResponseSchema, type KVListResponseType, KVListResultSchema, type KVListResultType, KVResponseHeadersSchema, type KVResponseHeadersType, type ParsedSecretCatalogKey, PermissionHint, type QuotaConfig, type QuotaStatus, type ResolvedSecretPath, Result, RetryPolicy, RetryPolicySchema, type RetryPolicyType, SECRET_NAME_RE, type SchemaInfo, type SecretCatalogEntry, type SecretPayload, type SecretScopeOptions, type SecretsError, SecretsService, type ServiceConstructor, ServiceContext, type ServiceContextConfig, ServiceError, ServiceErrorEventSchema, type ServiceErrorEventType, ServiceErrorSchema, type ServiceErrorType, type ServiceRegistration, ServiceRequestEventSchema, type ServiceRequestEventType, ServiceResponseEventSchema, type ServiceResponseEventType, ServiceRetryEventSchema, type ServiceRetryEventType, ServiceSession, ServiceSessionSchema, type ServiceSessionType, StorageQuotaInfo, type SubscribeOptions, type TableInfo, TelemetryConfig, TelemetrySpanEventSchema, type TelemetrySpanEventType, type TinyCloudDebugEnableOptions, type TinyCloudDebugEvent, type TinyCloudDebugLevel, TinyCloudDebugLogger, type TinyCloudDebugTimer, TinyCloudQuota, type ValidationError, type VaultCrypto, type VaultEntry, type VaultError, type VaultGetOptions, type VaultGrantOptions, VaultHeaders, type VaultListOptions, type VaultListPage, type VaultNetworkReadResult, VaultPublicSpaceKVActions, type VaultPutOptions, type ViewInfo, type WasmVaultFunctions, abortedError, authExpiredError, authRequiredError, authUnauthorizedError, canonicalizeSecretScope, clearTinyCloudDebugLogs, createKVResponseSchema, createResultSchema, createVaultCrypto, disableTinyCloudDebug, enableTinyCloudDebug, errorResult, getTinyCloudDebugLogs, installTinyCloudDebugGlobals, networkError, notFoundError, parseAuthError, parsePermissionHint, parsePermissionHintFromErrorText, parseSecretCatalogKey, permissionDeniedError, resolveSecretListPrefix, resolveSecretPath, storageLimitReachedError, storageQuotaExceededError, timeoutError, tinyCloudDebugLogger, validateKVListResponse, validateKVResponseHeaders, validateRetryPolicy, validateServiceError, validateServiceRequestEvent, validateServiceResponseEvent, validateServiceSession, validateTelemetrySpanEvent, wrapError };
2266
+ export { type AuthorizationVerdict, BaseService, type BaseServiceOptions, type ColumnInfo, type DataVaultConfig, DataVaultService, DecryptCapabilityProof, DuckDbAction, type DuckDbActionType, type DuckDbBatchOptions, type BatchResponse as DuckDbBatchResponse, DuckDbDatabaseHandle, type DuckDbExecuteOptions, type ExecuteResponse as DuckDbExecuteResponse, type DuckDbOptions, type DuckDbQueryOptions, type QueryResponse as DuckDbQueryResponse, DuckDbService, type DuckDbServiceConfig, type DuckDbStatement, type DuckDbValue, EventHandler, FetchFunction, GenericKVResponseSchema, type GenericKVResponseType, GenericResultSchema, type HookEvent, type HookServiceName, type HookStreamEvent, type HookSubscription, type HookWebhookListOptions, type HookWebhookRecord, type HookWebhookRegistration, type HookWebhookScope, type HookWebhookUnregisterOptions, HooksService, type HooksServiceConfig, type IDataVaultService, type IDuckDbDatabaseHandle, type IDuckDbService, IEncryptionService, type IHooksService, IKVService, type ISecretsService, IService, IServiceContext, InvokeAnyFunction, InvokeFunction, KVListResponseSchema, type KVListResponseType, KVListResultSchema, type KVListResultType, KVResponseHeadersSchema, type KVResponseHeadersType, type ParsedSecretCatalogKey, PermissionHint, type QuotaConfig, type QuotaStatus, type ResolvedSecretPath, Result, RetryPolicy, RetryPolicySchema, type RetryPolicyType, SECRET_NAME_RE, type SchemaInfo, type SecretCatalogEntry, type SecretPayload, type SecretScopeOptions, type SecretsError, SecretsService, type ServiceConstructor, ServiceContext, type ServiceContextConfig, ServiceError, ServiceErrorEventSchema, type ServiceErrorEventType, ServiceErrorSchema, type ServiceErrorType, type ServiceRegistration, ServiceRequestEventSchema, type ServiceRequestEventType, ServiceResponseEventSchema, type ServiceResponseEventType, ServiceRetryEventSchema, type ServiceRetryEventType, ServiceSession, ServiceSessionSchema, type ServiceSessionType, StorageQuotaInfo, type SubscribeOptions, type TableInfo, TelemetryConfig, TelemetrySpanEventSchema, type TelemetrySpanEventType, type TinyCloudDebugEnableOptions, type TinyCloudDebugEvent, type TinyCloudDebugLevel, TinyCloudDebugLogger, type TinyCloudDebugTimer, TinyCloudQuota, type ValidationError, type VaultCrypto, type VaultEntry, type VaultError, type VaultGetOptions, type VaultGrantOptions, VaultHeaders, type VaultListOptions, type VaultListPage, type VaultNetworkReadResult, VaultPublicSpaceKVActions, type VaultPutOptions, type ViewInfo, type WasmVaultFunctions, abortedError, authExpiredError, authRequiredError, authUnauthorizedError, authorizationVerdictOf, canonicalizeSecretScope, clearTinyCloudDebugLogs, createKVResponseSchema, createResultSchema, createVaultCrypto, disableTinyCloudDebug, enableTinyCloudDebug, errorResult, getTinyCloudDebugLogs, installTinyCloudDebugGlobals, networkError, notFoundError, parseAuthError, parsePermissionHint, parsePermissionHintFromErrorText, parseSecretCatalogKey, permissionDeniedError, resolveSecretListPrefix, resolveSecretPath, storageLimitReachedError, storageQuotaExceededError, timeoutError, tinyCloudDebugLogger, validateKVListResponse, validateKVResponseHeaders, validateRetryPolicy, validateServiceError, validateServiceRequestEvent, validateServiceResponseEvent, validateServiceSession, validateTelemetrySpanEvent, wrapError };
package/dist/index.js CHANGED
@@ -993,6 +993,37 @@ function parseAuthError(responseText) {
993
993
  function authUnauthorizedError(service, message, meta) {
994
994
  return serviceError(ErrorCodes.AUTH_UNAUTHORIZED, message, service, { meta });
995
995
  }
996
+ var MAX_CAUSE_DEPTH = 8;
997
+ function errorStatusOf(node) {
998
+ const meta = node.meta;
999
+ const candidates = [
1000
+ node.status,
1001
+ node.statusCode,
1002
+ typeof meta === "object" && meta !== null ? meta.status : void 0
1003
+ ];
1004
+ for (const candidate of candidates) {
1005
+ if (typeof candidate === "number" && Number.isInteger(candidate) && candidate >= 400 && candidate <= 599) {
1006
+ return candidate;
1007
+ }
1008
+ }
1009
+ return void 0;
1010
+ }
1011
+ function authorizationVerdictOf(error) {
1012
+ const seen = /* @__PURE__ */ new Set();
1013
+ let sawUnauthorizedCode = false;
1014
+ let node = error;
1015
+ for (let depth = 0; depth < MAX_CAUSE_DEPTH && typeof node === "object" && node !== null && !seen.has(node); depth += 1) {
1016
+ seen.add(node);
1017
+ const record = node;
1018
+ const status = errorStatusOf(record);
1019
+ if (status === 401) return "unauthenticated";
1020
+ if (status === 403) return "forbidden";
1021
+ if (status !== void 0) return "other";
1022
+ if (record.code === ErrorCodes.AUTH_UNAUTHORIZED) sawUnauthorizedCode = true;
1023
+ node = record.cause;
1024
+ }
1025
+ return sawUnauthorizedCode ? "forbidden" : void 0;
1026
+ }
996
1027
  function storageQuotaExceededError(service, message, meta) {
997
1028
  return {
998
1029
  code: ErrorCodes.STORAGE_QUOTA_EXCEEDED,
@@ -1421,7 +1452,7 @@ var KVService = class extends BaseService {
1421
1452
  return err(
1422
1453
  storageQuotaExceededError(
1423
1454
  "kv",
1424
- `Storage quota exceeded for key "${key}": ${errorText}`,
1455
+ `Storage quota exceeded for key ${JSON.stringify(key)}: ${errorText}`,
1425
1456
  {
1426
1457
  status: response.status,
1427
1458
  ...quotaInfo ? { usedBytes: quotaInfo.usedBytes, limitBytes: quotaInfo.limitBytes } : {}
@@ -1434,7 +1465,7 @@ var KVService = class extends BaseService {
1434
1465
  return err(
1435
1466
  storageLimitReachedError(
1436
1467
  "kv",
1437
- `Storage limit reached for key "${key}": ${errorText}`,
1468
+ `Storage limit reached for key ${JSON.stringify(key)}: ${errorText}`,
1438
1469
  {
1439
1470
  status: response.status,
1440
1471
  ...quotaInfo ? { usedBytes: quotaInfo.usedBytes, limitBytes: quotaInfo.limitBytes } : {}
@@ -1720,12 +1751,11 @@ var KVService = class extends BaseService {
1720
1751
  if (!response.ok) {
1721
1752
  const errorText = await response.text();
1722
1753
  if (response.status === 401 || response.status === 403) {
1723
- const { resource, action: requiredAction } = parseAuthError(errorText);
1724
- return err(authUnauthorizedError("kv", errorText, {
1725
- status: response.status,
1726
- ...requiredAction && { requiredAction },
1727
- ...resource && { resource }
1728
- }));
1754
+ return this.authorizationFailure(
1755
+ `Failed to batch read ${keys.length} key(s)`,
1756
+ response,
1757
+ errorText
1758
+ );
1729
1759
  }
1730
1760
  if (response.status === 413) {
1731
1761
  return err(serviceError(
@@ -1824,23 +1854,39 @@ var KVService = class extends BaseService {
1824
1854
  } catch {
1825
1855
  }
1826
1856
  if (response.status === 401 || response.status === 403) {
1827
- const { resource, action } = parseAuthError(errorText);
1828
- return err(authUnauthorizedError("kv", errorText, {
1829
- status: response.status,
1830
- ...action && { requiredAction: action },
1831
- ...resource && { resource }
1832
- }));
1857
+ return this.authorizationFailure(
1858
+ `Failed to create signed read URL for key ${JSON.stringify(key)}`,
1859
+ response,
1860
+ errorText
1861
+ );
1833
1862
  }
1834
1863
  const code = response.status === 400 ? ErrorCodes.INVALID_INPUT : ErrorCodes.NETWORK_ERROR;
1835
1864
  return err(
1836
1865
  serviceError(
1837
1866
  code,
1838
- `Failed to create signed read URL for key "${key}": ${response.status} - ${errorText}`,
1867
+ `Failed to create signed read URL for key ${JSON.stringify(key)}: ${response.status} - ${errorText}`,
1839
1868
  "kv",
1840
1869
  { meta: { status: response.status, statusText: response.statusText } }
1841
1870
  )
1842
1871
  );
1843
1872
  }
1873
+ /**
1874
+ * AUTH_UNAUTHORIZED for a 401/403 response. The message keeps the HTTP
1875
+ * status and the server text (`<context>: <status> - <text>`, the same
1876
+ * shape as every other KV failure) so callers that rethrow only the message
1877
+ * still see the status; `meta.status` carries it for typed callers.
1878
+ * Resource/ability hints are parsed from the raw body, never the message.
1879
+ */
1880
+ authorizationFailure(context, response, errorText, extraMeta = {}) {
1881
+ const { resource, action } = parseAuthError(errorText);
1882
+ const detail = errorText.trim().length > 0 ? errorText : response.statusText || "authorization failed";
1883
+ return err(authUnauthorizedError("kv", `${context}: ${response.status} - ${detail}`, {
1884
+ status: response.status,
1885
+ ...action && { requiredAction: action },
1886
+ ...resource && { resource },
1887
+ ...extraMeta
1888
+ }));
1889
+ }
1844
1890
  normalizeSignedReadUrlResponse(data) {
1845
1891
  if (!data || typeof data !== "object") {
1846
1892
  return void 0;
@@ -1883,14 +1929,13 @@ var KVService = class extends BaseService {
1883
1929
  if (!response.ok) {
1884
1930
  if (response.status === 401 || response.status === 403) {
1885
1931
  const errorText2 = await response.text();
1886
- const { resource, action } = parseAuthError(errorText2);
1887
1932
  const permissionHint = parsePermissionHintFromErrorText(errorText2);
1888
- return err(authUnauthorizedError("kv", errorText2, {
1889
- status: response.status,
1890
- ...action && { requiredAction: action },
1891
- ...resource && { resource },
1892
- ...permissionHint === void 0 ? {} : { permissionHint }
1893
- }));
1933
+ return this.authorizationFailure(
1934
+ `Failed to get key ${JSON.stringify(key)}`,
1935
+ response,
1936
+ errorText2,
1937
+ permissionHint === void 0 ? {} : { permissionHint }
1938
+ );
1894
1939
  }
1895
1940
  if (response.status === 404) {
1896
1941
  return this.classifyNotFound(response, key);
@@ -1899,7 +1944,7 @@ var KVService = class extends BaseService {
1899
1944
  if (response.status === 413) {
1900
1945
  return err(serviceError(
1901
1946
  ErrorCodes.KV_RESPONSE_TOO_LARGE,
1902
- `KV value at key "${key}" exceeds the requested response limit`,
1947
+ `KV value at key ${JSON.stringify(key)} exceeds the requested response limit`,
1903
1948
  "kv",
1904
1949
  { meta: { status: response.status, statusText: response.statusText } }
1905
1950
  ));
@@ -1907,7 +1952,7 @@ var KVService = class extends BaseService {
1907
1952
  return err(
1908
1953
  serviceError(
1909
1954
  ErrorCodes.NETWORK_ERROR,
1910
- `Failed to get key "${key}": ${response.status} - ${errorText}`,
1955
+ `Failed to get key ${JSON.stringify(key)}: ${response.status} - ${errorText}`,
1911
1956
  "kv",
1912
1957
  { meta: { status: response.status, statusText: response.statusText } }
1913
1958
  )
@@ -1963,21 +2008,18 @@ var KVService = class extends BaseService {
1963
2008
  }
1964
2009
  );
1965
2010
  if (response.status === 401 || response.status === 403) {
1966
- const errorText = await response.text();
1967
- const message = errorText.trim().length > 0 ? errorText : `Failed to put key "${key}": ${response.status} - ${response.statusText || "authorization failed"}`;
1968
- const { resource, action: requiredAction } = parseAuthError(errorText);
1969
- return err(authUnauthorizedError("kv", message, {
1970
- status: response.status,
1971
- ...requiredAction && { requiredAction },
1972
- ...resource && { resource }
1973
- }));
2011
+ return this.authorizationFailure(
2012
+ `Failed to put key ${JSON.stringify(key)}`,
2013
+ response,
2014
+ await response.text()
2015
+ );
1974
2016
  }
1975
2017
  if (!response.ok) {
1976
2018
  const errorText = await response.text();
1977
2019
  if (response.status === 412) {
1978
2020
  return err(serviceError(
1979
2021
  ErrorCodes.KV_PRECONDITION_FAILED,
1980
- `KV precondition failed for key "${key}"`,
2022
+ `KV precondition failed for key ${JSON.stringify(key)}`,
1981
2023
  "kv",
1982
2024
  { meta: { status: response.status, statusText: response.statusText } }
1983
2025
  ));
@@ -1985,7 +2027,7 @@ var KVService = class extends BaseService {
1985
2027
  if (response.status === 503 && (options?.ifMatch !== void 0 || options?.ifNoneMatch !== void 0)) {
1986
2028
  return err(serviceError(
1987
2029
  ErrorCodes.KV_CONFLICT,
1988
- `Concurrent KV update conflicted for key "${key}"`,
2030
+ `Concurrent KV update conflicted for key ${JSON.stringify(key)}`,
1989
2031
  "kv",
1990
2032
  { meta: { status: response.status, statusText: response.statusText } }
1991
2033
  ));
@@ -2001,7 +2043,7 @@ var KVService = class extends BaseService {
2001
2043
  return err(
2002
2044
  serviceError(
2003
2045
  ErrorCodes.KV_WRITE_FAILED,
2004
- `Failed to put key "${key}": ${response.status} - ${errorText}`,
2046
+ `Failed to put key ${JSON.stringify(key)}: ${response.status} - ${errorText}`,
2005
2047
  "kv",
2006
2048
  { meta: { status: response.status, statusText: response.statusText } }
2007
2049
  )
@@ -2095,12 +2137,11 @@ var KVService = class extends BaseService {
2095
2137
  );
2096
2138
  }
2097
2139
  if (response.status === 401 || response.status === 403) {
2098
- const { resource, action } = parseAuthError(errorText);
2099
- return err(authUnauthorizedError("kv", errorText, {
2100
- status: response.status,
2101
- ...action && { requiredAction: action },
2102
- ...resource && { resource }
2103
- }));
2140
+ return this.authorizationFailure(
2141
+ `Failed to batch put ${items.length} key(s)`,
2142
+ response,
2143
+ errorText
2144
+ );
2104
2145
  }
2105
2146
  const quotaError = this.handleQuotaErrorResponse(
2106
2147
  response,
@@ -2221,13 +2262,11 @@ var KVService = class extends BaseService {
2221
2262
  );
2222
2263
  if (!response.ok) {
2223
2264
  if (response.status === 401) {
2224
- const errorText2 = await response.text();
2225
- const { resource, action } = parseAuthError(errorText2);
2226
- return err(authUnauthorizedError("kv", errorText2, {
2227
- status: response.status,
2228
- ...action && { requiredAction: action },
2229
- ...resource && { resource }
2230
- }));
2265
+ return this.authorizationFailure(
2266
+ "Failed to list keys",
2267
+ response,
2268
+ await response.text()
2269
+ );
2231
2270
  }
2232
2271
  const errorText = await response.text();
2233
2272
  return err(
@@ -2276,13 +2315,11 @@ var KVService = class extends BaseService {
2276
2315
  );
2277
2316
  if (!response.ok) {
2278
2317
  if (response.status === 401) {
2279
- const errorText2 = await response.text();
2280
- const { resource, action } = parseAuthError(errorText2);
2281
- return err(authUnauthorizedError("kv", errorText2, {
2282
- status: response.status,
2283
- ...action && { requiredAction: action },
2284
- ...resource && { resource }
2285
- }));
2318
+ return this.authorizationFailure(
2319
+ `Failed to delete key ${JSON.stringify(key)}`,
2320
+ response,
2321
+ await response.text()
2322
+ );
2286
2323
  }
2287
2324
  if (response.status === 404) {
2288
2325
  return this.classifyNotFound(response, key);
@@ -2291,7 +2328,7 @@ var KVService = class extends BaseService {
2291
2328
  if (response.status === 412) {
2292
2329
  return err(serviceError(
2293
2330
  ErrorCodes.KV_PRECONDITION_FAILED,
2294
- `KV precondition failed for key "${key}"`,
2331
+ `KV precondition failed for key ${JSON.stringify(key)}`,
2295
2332
  "kv",
2296
2333
  { meta: { status: response.status, statusText: response.statusText } }
2297
2334
  ));
@@ -2299,7 +2336,7 @@ var KVService = class extends BaseService {
2299
2336
  if (response.status === 503 && options?.ifMatch !== void 0) {
2300
2337
  return err(serviceError(
2301
2338
  ErrorCodes.KV_CONFLICT,
2302
- `Concurrent KV delete conflicted for key "${key}"`,
2339
+ `Concurrent KV delete conflicted for key ${JSON.stringify(key)}`,
2303
2340
  "kv",
2304
2341
  { meta: { status: response.status, statusText: response.statusText } }
2305
2342
  ));
@@ -2307,7 +2344,7 @@ var KVService = class extends BaseService {
2307
2344
  return err(
2308
2345
  serviceError(
2309
2346
  ErrorCodes.NETWORK_ERROR,
2310
- `Failed to delete key "${key}": ${response.status} - ${errorText}`,
2347
+ `Failed to delete key ${JSON.stringify(key)}: ${response.status} - ${errorText}`,
2311
2348
  "kv",
2312
2349
  { meta: { status: response.status, statusText: response.statusText } }
2313
2350
  )
@@ -2340,13 +2377,11 @@ var KVService = class extends BaseService {
2340
2377
  );
2341
2378
  if (!response.ok) {
2342
2379
  if (response.status === 401) {
2343
- const errorText2 = await response.text();
2344
- const { resource, action } = parseAuthError(errorText2);
2345
- return err(authUnauthorizedError("kv", errorText2, {
2346
- status: response.status,
2347
- ...action && { requiredAction: action },
2348
- ...resource && { resource }
2349
- }));
2380
+ return this.authorizationFailure(
2381
+ `Failed to get metadata for key ${JSON.stringify(key)}`,
2382
+ response,
2383
+ await response.text()
2384
+ );
2350
2385
  }
2351
2386
  if (response.status === 404) {
2352
2387
  return this.classifyNotFound(response, key);
@@ -2355,7 +2390,7 @@ var KVService = class extends BaseService {
2355
2390
  return err(
2356
2391
  serviceError(
2357
2392
  ErrorCodes.NETWORK_ERROR,
2358
- `Failed to get metadata for key "${key}": ${response.status} - ${errorText}`,
2393
+ `Failed to get metadata for key ${JSON.stringify(key)}: ${response.status} - ${errorText}`,
2359
2394
  "kv",
2360
2395
  { meta: { status: response.status, statusText: response.statusText } }
2361
2396
  )
@@ -3837,10 +3872,14 @@ async function responseError(service, message, response) {
3837
3872
  }
3838
3873
  } catch {
3839
3874
  }
3840
- return wrapError(
3875
+ const error = wrapError(
3841
3876
  service,
3842
3877
  new Error(`${message}: ${response.status} ${detail}`)
3843
3878
  );
3879
+ return {
3880
+ ...error,
3881
+ meta: { ...error.meta, status: response.status, statusText: response.statusText }
3882
+ };
3844
3883
  }
3845
3884
  function isAbortError(error) {
3846
3885
  return error instanceof DOMException && error.name === "AbortError";
@@ -6891,6 +6930,7 @@ export {
6891
6930
  authExpiredError,
6892
6931
  authRequiredError,
6893
6932
  authUnauthorizedError,
6933
+ authorizationVerdictOf,
6894
6934
  base64Decode2 as base64Decode,
6895
6935
  base64Encode2 as base64Encode,
6896
6936
  buildCanonicalDecryptRequest,