@tinycloud/operations 0.3.4-beta.1 → 0.3.4-beta.3

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.
@@ -1050,6 +1050,18 @@ function storageLimitReachedError(service, message, meta) {
1050
1050
  meta
1051
1051
  };
1052
1052
  }
1053
+ function parseStorageQuotaBytes(responseText) {
1054
+ const match = responseText.match(/Used:\s*(\d+)\s*bytes,\s*Limit:\s*(\d+)\s*bytes/i);
1055
+ if (!match) return void 0;
1056
+ return {
1057
+ usedBytes: parseInt(match[1], 10),
1058
+ limitBytes: parseInt(match[2], 10)
1059
+ };
1060
+ }
1061
+ function storageRejectionError(service, status, meta, responseText) {
1062
+ const quotaMeta = { ...meta, ...parseStorageQuotaBytes(responseText) };
1063
+ return status === 402 ? storageQuotaExceededError(service, STORAGE_FULL_MESSAGE, quotaMeta) : storageLimitReachedError(service, STORAGE_WRITE_TOO_LARGE_MESSAGE, quotaMeta);
1064
+ }
1053
1065
  function wrapError(service, error, defaultCode = ErrorCodes.NETWORK_ERROR) {
1054
1066
  if (error instanceof Error) {
1055
1067
  if (error.name === "AbortError") {
@@ -1179,6 +1191,9 @@ function serializeSqlValues(values) {
1179
1191
  (value) => value instanceof Uint8Array ? Array.from(value) : value
1180
1192
  );
1181
1193
  }
1194
+ function isMissingTableError(message) {
1195
+ return /no such table/i.test(message);
1196
+ }
1182
1197
  function migrationKey(namespace, id) {
1183
1198
  return `${encodeURIComponent(namespace)}:${encodeURIComponent(id)}`;
1184
1199
  }
@@ -1255,10 +1270,14 @@ async function responseError(service, message, response) {
1255
1270
  }
1256
1271
  } catch {
1257
1272
  }
1258
- return wrapError(
1273
+ const error = wrapError(
1259
1274
  service,
1260
1275
  new Error(`${message}: ${response.status} ${detail}`)
1261
1276
  );
1277
+ return {
1278
+ ...error,
1279
+ meta: { ...error.meta, status: response.status, statusText: response.statusText }
1280
+ };
1262
1281
  }
1263
1282
  function isAbortError(error) {
1264
1283
  return error instanceof DOMException && error.name === "AbortError";
@@ -1660,6 +1679,9 @@ function defaultVaultMessage(input) {
1660
1679
  return input.message ?? `Public key not found for ${input.did}`;
1661
1680
  case "STORAGE_ERROR":
1662
1681
  return input.message ?? input.cause.message;
1682
+ case "STORAGE_QUOTA_EXCEEDED":
1683
+ case "STORAGE_LIMIT_REACHED":
1684
+ return input.message;
1663
1685
  }
1664
1686
  }
1665
1687
  function vaultError(input) {
@@ -1670,6 +1692,15 @@ function vaultError(input) {
1670
1692
  };
1671
1693
  return { ok: false, error };
1672
1694
  }
1695
+ function kvWriteError(context, error) {
1696
+ if (error.code === ErrorCodes.STORAGE_QUOTA_EXCEEDED || error.code === ErrorCodes.STORAGE_LIMIT_REACHED) {
1697
+ return vaultError({ code: error.code, message: error.message, meta: error.meta });
1698
+ }
1699
+ return vaultError({
1700
+ code: "STORAGE_ERROR",
1701
+ cause: new Error(`${context}: ${error.message}`)
1702
+ });
1703
+ }
1673
1704
  function canonicalize(value) {
1674
1705
  if (value === void 0) {
1675
1706
  return "";
@@ -2428,7 +2459,7 @@ function encOk(data) {
2428
2459
  function encErr(error) {
2429
2460
  return { ok: false, error };
2430
2461
  }
2431
- var import_decrypt_transport_response_error, ErrorCodes, defaultRetryPolicy, TelemetryEvents, REDACTED, SAFE_NUMBER_FIELDS, SAFE_BOOLEAN_FIELDS, DEBUG_FLAG, MAX_EVENTS, TinyCloudDebugLogger, tinyCloudDebugLogger, ServiceErrorSchema, GenericResultSchema, KVResponseHeadersSchema, GenericKVResponseSchema, KVListResponseSchema, KVListResultSchema, ServiceRequestEventSchema, ServiceResponseEventSchema, ServiceErrorEventSchema, ServiceRetryEventSchema, TelemetrySpanEventSchema, RetryPolicySchema, ServiceSessionSchema, BaseService, PrefixedKVService, DEFAULT_SIGNED_READ_URL_EXPIRY_MS, KVAction, MAX_KV_BATCH_READ_ITEMS, KVService, SQLMigrations, DatabaseHandle, SQLAction, DDL_TOKENS, MIGRATIONS_TABLE, MIGRATIONS_SCHEMA, MIGRATIONS_META_NAMESPACE, MIGRATIONS_META_ID, SQLService, DuckDbDatabaseHandle, DuckDbAction, DuckDbService, AsyncQueue, HooksService, VaultVersionConfig, CURRENT_VAULT_VERSION, VaultHeaders, DB_NAME, DB_VERSION, STORE_NAME, WRAP_KEY_ID, DataVaultService, HEX, URN_PREFIX, NETWORK_NAME_RE, PKH_EIP155_DID_RE, NetworkIdError, DEFAULT_ENCRYPTION_ALG, ENVELOPE_VERSION, DEFAULT_KEY_VERSION, DECRYPT_FACT_TYPE, DECRYPT_RESULT_TYPE, EncryptionService;
2462
+ var import_decrypt_transport_response_error, ErrorCodes, defaultRetryPolicy, TelemetryEvents, REDACTED, SAFE_NUMBER_FIELDS, SAFE_BOOLEAN_FIELDS, DEBUG_FLAG, MAX_EVENTS, TinyCloudDebugLogger, tinyCloudDebugLogger, ServiceErrorSchema, GenericResultSchema, KVResponseHeadersSchema, GenericKVResponseSchema, KVListResponseSchema, KVListResultSchema, ServiceRequestEventSchema, ServiceResponseEventSchema, ServiceErrorEventSchema, ServiceRetryEventSchema, TelemetrySpanEventSchema, RetryPolicySchema, ServiceSessionSchema, STORAGE_FULL_MESSAGE, STORAGE_WRITE_TOO_LARGE_MESSAGE, BaseService, PrefixedKVService, DEFAULT_SIGNED_READ_URL_EXPIRY_MS, KVAction, MAX_KV_BATCH_READ_ITEMS, KVService, SQLMigrations, DatabaseHandle, SQLAction, DDL_TOKENS, MIGRATIONS_TABLE, MIGRATIONS_SCHEMA, MIGRATIONS_META_NAMESPACE, MIGRATIONS_META_ID, SQLService, DuckDbDatabaseHandle, DuckDbAction, DuckDbService, AsyncQueue, HooksService, VaultVersionConfig, CURRENT_VAULT_VERSION, VaultHeaders, DB_NAME, DB_VERSION, STORE_NAME, WRAP_KEY_ID, DataVaultService, HEX, URN_PREFIX, NETWORK_NAME_RE, PKH_EIP155_DID_RE, NetworkIdError, DEFAULT_ENCRYPTION_ALG, ENVELOPE_VERSION, DEFAULT_KEY_VERSION, DECRYPT_FACT_TYPE, DECRYPT_RESULT_TYPE, EncryptionService;
2432
2463
  var init_dist2 = __esm({
2433
2464
  "../sdk-services/dist/index.js"() {
2434
2465
  "use strict";
@@ -2710,6 +2741,8 @@ var init_dist2 = __esm({
2710
2741
  /** The session key JWK (required for invoke) */
2711
2742
  jwk: z.object({}).passthrough()
2712
2743
  });
2744
+ STORAGE_FULL_MESSAGE = "TinyCloud storage is full, so this change was not saved. Reading still works. Free up space or upgrade your plan to save again.";
2745
+ STORAGE_WRITE_TOO_LARGE_MESSAGE = "This change is larger than the TinyCloud storage you have left, so it was not saved. Reading still works. Free up space or upgrade your plan to save it.";
2713
2746
  BaseService = class {
2714
2747
  constructor() {
2715
2748
  this.abortController = new AbortController();
@@ -3058,47 +3091,21 @@ var init_dist2 = __esm({
3058
3091
  get config() {
3059
3092
  return this._config;
3060
3093
  }
3061
- // Parses "Used: X bytes, Limit: Y bytes" from tinycloud-node error responses
3062
- parseQuotaInfo(errorText) {
3063
- const match = errorText.match(
3064
- /Used:\s*(\d+)\s*bytes,\s*Limit:\s*(\d+)\s*bytes/i
3065
- );
3066
- if (match) {
3067
- return {
3068
- usedBytes: parseInt(match[1], 10),
3069
- limitBytes: parseInt(match[2], 10)
3070
- };
3071
- }
3072
- return void 0;
3073
- }
3074
3094
  handleQuotaErrorResponse(response, errorText, key) {
3075
- if (response.status === 402) {
3076
- const quotaInfo = this.parseQuotaInfo(errorText);
3077
- return err(
3078
- storageQuotaExceededError(
3079
- "kv",
3080
- `Storage quota exceeded for key "${key}": ${errorText}`,
3081
- {
3082
- status: response.status,
3083
- ...quotaInfo ? { usedBytes: quotaInfo.usedBytes, limitBytes: quotaInfo.limitBytes } : {}
3084
- }
3085
- )
3086
- );
3095
+ if (response.status !== 402 && response.status !== 413) {
3096
+ return void 0;
3087
3097
  }
3088
- if (response.status === 413) {
3089
- const quotaInfo = this.parseQuotaInfo(errorText);
3090
- return err(
3091
- storageLimitReachedError(
3092
- "kv",
3093
- `Storage limit reached for key "${key}": ${errorText}`,
3094
- {
3095
- status: response.status,
3096
- ...quotaInfo ? { usedBytes: quotaInfo.usedBytes, limitBytes: quotaInfo.limitBytes } : {}
3097
- }
3098
- )
3099
- );
3098
+ if (response.status === 413 && !parseStorageQuotaBytes(errorText)) {
3099
+ return void 0;
3100
3100
  }
3101
- return void 0;
3101
+ return err(
3102
+ storageRejectionError(
3103
+ "kv",
3104
+ response.status,
3105
+ { status: response.status, statusText: response.statusText, key },
3106
+ errorText
3107
+ )
3108
+ );
3102
3109
  }
3103
3110
  /**
3104
3111
  * Classify a KV 404 by reading the response body once.
@@ -3376,12 +3383,11 @@ var init_dist2 = __esm({
3376
3383
  if (!response.ok) {
3377
3384
  const errorText = await response.text();
3378
3385
  if (response.status === 401 || response.status === 403) {
3379
- const { resource, action: requiredAction } = parseAuthError(errorText);
3380
- return err(authUnauthorizedError("kv", errorText, {
3381
- status: response.status,
3382
- ...requiredAction && { requiredAction },
3383
- ...resource && { resource }
3384
- }));
3386
+ return this.authorizationFailure(
3387
+ `Failed to batch read ${keys.length} key(s)`,
3388
+ response,
3389
+ errorText
3390
+ );
3385
3391
  }
3386
3392
  if (response.status === 413) {
3387
3393
  return err(serviceError(
@@ -3480,23 +3486,39 @@ var init_dist2 = __esm({
3480
3486
  } catch {
3481
3487
  }
3482
3488
  if (response.status === 401 || response.status === 403) {
3483
- const { resource, action } = parseAuthError(errorText);
3484
- return err(authUnauthorizedError("kv", errorText, {
3485
- status: response.status,
3486
- ...action && { requiredAction: action },
3487
- ...resource && { resource }
3488
- }));
3489
+ return this.authorizationFailure(
3490
+ `Failed to create signed read URL for key ${JSON.stringify(key)}`,
3491
+ response,
3492
+ errorText
3493
+ );
3489
3494
  }
3490
3495
  const code = response.status === 400 ? ErrorCodes.INVALID_INPUT : ErrorCodes.NETWORK_ERROR;
3491
3496
  return err(
3492
3497
  serviceError(
3493
3498
  code,
3494
- `Failed to create signed read URL for key "${key}": ${response.status} - ${errorText}`,
3499
+ `Failed to create signed read URL for key ${JSON.stringify(key)}: ${response.status} - ${errorText}`,
3495
3500
  "kv",
3496
3501
  { meta: { status: response.status, statusText: response.statusText } }
3497
3502
  )
3498
3503
  );
3499
3504
  }
3505
+ /**
3506
+ * AUTH_UNAUTHORIZED for a 401/403 response. The message keeps the HTTP
3507
+ * status and the server text (`<context>: <status> - <text>`, the same
3508
+ * shape as every other KV failure) so callers that rethrow only the message
3509
+ * still see the status; `meta.status` carries it for typed callers.
3510
+ * Resource/ability hints are parsed from the raw body, never the message.
3511
+ */
3512
+ authorizationFailure(context, response, errorText, extraMeta = {}) {
3513
+ const { resource, action } = parseAuthError(errorText);
3514
+ const detail = errorText.trim().length > 0 ? errorText : response.statusText || "authorization failed";
3515
+ return err(authUnauthorizedError("kv", `${context}: ${response.status} - ${detail}`, {
3516
+ status: response.status,
3517
+ ...action && { requiredAction: action },
3518
+ ...resource && { resource },
3519
+ ...extraMeta
3520
+ }));
3521
+ }
3500
3522
  normalizeSignedReadUrlResponse(data) {
3501
3523
  if (!data || typeof data !== "object") {
3502
3524
  return void 0;
@@ -3539,14 +3561,13 @@ var init_dist2 = __esm({
3539
3561
  if (!response.ok) {
3540
3562
  if (response.status === 401 || response.status === 403) {
3541
3563
  const errorText2 = await response.text();
3542
- const { resource, action } = parseAuthError(errorText2);
3543
3564
  const permissionHint = parsePermissionHintFromErrorText(errorText2);
3544
- return err(authUnauthorizedError("kv", errorText2, {
3545
- status: response.status,
3546
- ...action && { requiredAction: action },
3547
- ...resource && { resource },
3548
- ...permissionHint === void 0 ? {} : { permissionHint }
3549
- }));
3565
+ return this.authorizationFailure(
3566
+ `Failed to get key ${JSON.stringify(key)}`,
3567
+ response,
3568
+ errorText2,
3569
+ permissionHint === void 0 ? {} : { permissionHint }
3570
+ );
3550
3571
  }
3551
3572
  if (response.status === 404) {
3552
3573
  return this.classifyNotFound(response, key);
@@ -3555,7 +3576,7 @@ var init_dist2 = __esm({
3555
3576
  if (response.status === 413) {
3556
3577
  return err(serviceError(
3557
3578
  ErrorCodes.KV_RESPONSE_TOO_LARGE,
3558
- `KV value at key "${key}" exceeds the requested response limit`,
3579
+ `KV value at key ${JSON.stringify(key)} exceeds the requested response limit`,
3559
3580
  "kv",
3560
3581
  { meta: { status: response.status, statusText: response.statusText } }
3561
3582
  ));
@@ -3563,7 +3584,7 @@ var init_dist2 = __esm({
3563
3584
  return err(
3564
3585
  serviceError(
3565
3586
  ErrorCodes.NETWORK_ERROR,
3566
- `Failed to get key "${key}": ${response.status} - ${errorText}`,
3587
+ `Failed to get key ${JSON.stringify(key)}: ${response.status} - ${errorText}`,
3567
3588
  "kv",
3568
3589
  { meta: { status: response.status, statusText: response.statusText } }
3569
3590
  )
@@ -3619,21 +3640,18 @@ var init_dist2 = __esm({
3619
3640
  }
3620
3641
  );
3621
3642
  if (response.status === 401 || response.status === 403) {
3622
- const errorText = await response.text();
3623
- const message = errorText.trim().length > 0 ? errorText : `Failed to put key "${key}": ${response.status} - ${response.statusText || "authorization failed"}`;
3624
- const { resource, action: requiredAction } = parseAuthError(errorText);
3625
- return err(authUnauthorizedError("kv", message, {
3626
- status: response.status,
3627
- ...requiredAction && { requiredAction },
3628
- ...resource && { resource }
3629
- }));
3643
+ return this.authorizationFailure(
3644
+ `Failed to put key ${JSON.stringify(key)}`,
3645
+ response,
3646
+ await response.text()
3647
+ );
3630
3648
  }
3631
3649
  if (!response.ok) {
3632
3650
  const errorText = await response.text();
3633
3651
  if (response.status === 412) {
3634
3652
  return err(serviceError(
3635
3653
  ErrorCodes.KV_PRECONDITION_FAILED,
3636
- `KV precondition failed for key "${key}"`,
3654
+ `KV precondition failed for key ${JSON.stringify(key)}`,
3637
3655
  "kv",
3638
3656
  { meta: { status: response.status, statusText: response.statusText } }
3639
3657
  ));
@@ -3641,7 +3659,7 @@ var init_dist2 = __esm({
3641
3659
  if (response.status === 503 && (options?.ifMatch !== void 0 || options?.ifNoneMatch !== void 0)) {
3642
3660
  return err(serviceError(
3643
3661
  ErrorCodes.KV_CONFLICT,
3644
- `Concurrent KV update conflicted for key "${key}"`,
3662
+ `Concurrent KV update conflicted for key ${JSON.stringify(key)}`,
3645
3663
  "kv",
3646
3664
  { meta: { status: response.status, statusText: response.statusText } }
3647
3665
  ));
@@ -3657,7 +3675,7 @@ var init_dist2 = __esm({
3657
3675
  return err(
3658
3676
  serviceError(
3659
3677
  ErrorCodes.KV_WRITE_FAILED,
3660
- `Failed to put key "${key}": ${response.status} - ${errorText}`,
3678
+ `Failed to put key ${JSON.stringify(key)}: ${response.status} - ${errorText}`,
3661
3679
  "kv",
3662
3680
  { meta: { status: response.status, statusText: response.statusText } }
3663
3681
  )
@@ -3751,12 +3769,11 @@ var init_dist2 = __esm({
3751
3769
  );
3752
3770
  }
3753
3771
  if (response.status === 401 || response.status === 403) {
3754
- const { resource, action } = parseAuthError(errorText);
3755
- return err(authUnauthorizedError("kv", errorText, {
3756
- status: response.status,
3757
- ...action && { requiredAction: action },
3758
- ...resource && { resource }
3759
- }));
3772
+ return this.authorizationFailure(
3773
+ `Failed to batch put ${items.length} key(s)`,
3774
+ response,
3775
+ errorText
3776
+ );
3760
3777
  }
3761
3778
  const quotaError = this.handleQuotaErrorResponse(
3762
3779
  response,
@@ -3877,13 +3894,11 @@ var init_dist2 = __esm({
3877
3894
  );
3878
3895
  if (!response.ok) {
3879
3896
  if (response.status === 401) {
3880
- const errorText2 = await response.text();
3881
- const { resource, action } = parseAuthError(errorText2);
3882
- return err(authUnauthorizedError("kv", errorText2, {
3883
- status: response.status,
3884
- ...action && { requiredAction: action },
3885
- ...resource && { resource }
3886
- }));
3897
+ return this.authorizationFailure(
3898
+ "Failed to list keys",
3899
+ response,
3900
+ await response.text()
3901
+ );
3887
3902
  }
3888
3903
  const errorText = await response.text();
3889
3904
  return err(
@@ -3932,13 +3947,11 @@ var init_dist2 = __esm({
3932
3947
  );
3933
3948
  if (!response.ok) {
3934
3949
  if (response.status === 401) {
3935
- const errorText2 = await response.text();
3936
- const { resource, action } = parseAuthError(errorText2);
3937
- return err(authUnauthorizedError("kv", errorText2, {
3938
- status: response.status,
3939
- ...action && { requiredAction: action },
3940
- ...resource && { resource }
3941
- }));
3950
+ return this.authorizationFailure(
3951
+ `Failed to delete key ${JSON.stringify(key)}`,
3952
+ response,
3953
+ await response.text()
3954
+ );
3942
3955
  }
3943
3956
  if (response.status === 404) {
3944
3957
  return this.classifyNotFound(response, key);
@@ -3947,7 +3960,7 @@ var init_dist2 = __esm({
3947
3960
  if (response.status === 412) {
3948
3961
  return err(serviceError(
3949
3962
  ErrorCodes.KV_PRECONDITION_FAILED,
3950
- `KV precondition failed for key "${key}"`,
3963
+ `KV precondition failed for key ${JSON.stringify(key)}`,
3951
3964
  "kv",
3952
3965
  { meta: { status: response.status, statusText: response.statusText } }
3953
3966
  ));
@@ -3955,7 +3968,7 @@ var init_dist2 = __esm({
3955
3968
  if (response.status === 503 && options?.ifMatch !== void 0) {
3956
3969
  return err(serviceError(
3957
3970
  ErrorCodes.KV_CONFLICT,
3958
- `Concurrent KV delete conflicted for key "${key}"`,
3971
+ `Concurrent KV delete conflicted for key ${JSON.stringify(key)}`,
3959
3972
  "kv",
3960
3973
  { meta: { status: response.status, statusText: response.statusText } }
3961
3974
  ));
@@ -3963,7 +3976,7 @@ var init_dist2 = __esm({
3963
3976
  return err(
3964
3977
  serviceError(
3965
3978
  ErrorCodes.NETWORK_ERROR,
3966
- `Failed to delete key "${key}": ${response.status} - ${errorText}`,
3979
+ `Failed to delete key ${JSON.stringify(key)}: ${response.status} - ${errorText}`,
3967
3980
  "kv",
3968
3981
  { meta: { status: response.status, statusText: response.statusText } }
3969
3982
  )
@@ -3996,13 +4009,11 @@ var init_dist2 = __esm({
3996
4009
  );
3997
4010
  if (!response.ok) {
3998
4011
  if (response.status === 401) {
3999
- const errorText2 = await response.text();
4000
- const { resource, action } = parseAuthError(errorText2);
4001
- return err(authUnauthorizedError("kv", errorText2, {
4002
- status: response.status,
4003
- ...action && { requiredAction: action },
4004
- ...resource && { resource }
4005
- }));
4012
+ return this.authorizationFailure(
4013
+ `Failed to get metadata for key ${JSON.stringify(key)}`,
4014
+ response,
4015
+ await response.text()
4016
+ );
4006
4017
  }
4007
4018
  if (response.status === 404) {
4008
4019
  return this.classifyNotFound(response, key);
@@ -4011,7 +4022,7 @@ var init_dist2 = __esm({
4011
4022
  return err(
4012
4023
  serviceError(
4013
4024
  ErrorCodes.NETWORK_ERROR,
4014
- `Failed to get metadata for key "${key}": ${response.status} - ${errorText}`,
4025
+ `Failed to get metadata for key ${JSON.stringify(key)}: ${response.status} - ${errorText}`,
4015
4026
  "kv",
4016
4027
  { meta: { status: response.status, statusText: response.statusText } }
4017
4028
  )
@@ -4383,21 +4394,24 @@ var init_dist2 = __esm({
4383
4394
  }
4384
4395
  async applyMigrationsOnDbUnlocked(dbName, options) {
4385
4396
  return this.withTelemetry("migrations.apply", dbName, async () => {
4386
- const created = await this.ensureMigrationsTable(dbName, options.signal);
4387
- if (!created.ok) return created;
4388
4397
  const listed = await this.queryOnDb(
4389
4398
  dbName,
4390
4399
  `SELECT id FROM ${MIGRATIONS_TABLE} WHERE namespace = ? ORDER BY applied_at, id`,
4391
4400
  [options.namespace],
4392
4401
  { signal: options.signal }
4393
4402
  );
4394
- if (!listed.ok) return listed;
4403
+ const tableMissing = !listed.ok && (listed.error.code === ErrorCodes.SQL_DATABASE_NOT_FOUND || isMissingTableError(listed.error.message));
4404
+ if (!listed.ok && !tableMissing) return listed;
4395
4405
  const appliedIds = new Set(
4396
- listed.data.rows.map((row) => rowValue(row, 0)).filter((id) => typeof id === "string")
4406
+ (listed.ok ? listed.data.rows : []).map((row) => rowValue(row, 0)).filter((id) => typeof id === "string")
4397
4407
  );
4398
4408
  const skipped = options.migrations.filter((migration) => appliedIds.has(migration.id)).map((migration) => migration.id);
4399
4409
  const pending = options.migrations.filter((migration) => !appliedIds.has(migration.id));
4400
4410
  const applied = [];
4411
+ if (pending.length > 0 && tableMissing) {
4412
+ const created = await this.ensureMigrationsTable(dbName, options.signal);
4413
+ if (!created.ok) return created;
4414
+ }
4401
4415
  for (const migration of pending) {
4402
4416
  const result = await this.applyOneMigration(dbName, options.namespace, migration, options.signal);
4403
4417
  if (!result.ok) return result;
@@ -4500,6 +4514,10 @@ var init_dist2 = __esm({
4500
4514
  }
4501
4515
  async handleErrorResponse(response, operation) {
4502
4516
  const errorText = await response.text();
4517
+ const meta = responseErrorMeta(response.status, response.statusText, errorText);
4518
+ if (response.status === 402) {
4519
+ return err(storageRejectionError("sql", 402, meta, errorText));
4520
+ }
4503
4521
  const errorBody = parseServiceErrorBody(errorText);
4504
4522
  const errorCode = this.mapHttpStatusToErrorCode(
4505
4523
  response.status,
@@ -4512,7 +4530,6 @@ var init_dist2 = __esm({
4512
4530
  errorText,
4513
4531
  errorBody
4514
4532
  );
4515
- const meta = responseErrorMeta(response.status, response.statusText, errorText);
4516
4533
  if (response.status === 401) {
4517
4534
  const { resource, action } = parseAuthError(errorText);
4518
4535
  if (action) meta.requiredAction = action;
@@ -4848,6 +4865,10 @@ var init_dist2 = __esm({
4848
4865
  }
4849
4866
  async handleErrorResponse(response, operation) {
4850
4867
  const errorText = await response.text();
4868
+ const meta = responseErrorMeta(response.status, response.statusText, errorText);
4869
+ if (response.status === 402) {
4870
+ return err(storageRejectionError("duckdb", 402, meta, errorText));
4871
+ }
4851
4872
  const errorBody = parseServiceErrorBody(errorText);
4852
4873
  const errorCode = this.mapHttpStatusToErrorCode(
4853
4874
  response.status,
@@ -4860,7 +4881,6 @@ var init_dist2 = __esm({
4860
4881
  errorText,
4861
4882
  errorBody
4862
4883
  );
4863
- const meta = responseErrorMeta(response.status, response.statusText, errorText);
4864
4884
  if (response.status === 401) {
4865
4885
  const { resource, action } = parseAuthError(errorText);
4866
4886
  if (action) meta.requiredAction = action;
@@ -5595,12 +5615,7 @@ var init_dist2 = __esm({
5595
5615
  JSON.stringify(envelopeResult.data)
5596
5616
  );
5597
5617
  if (!valuePutResult.ok) {
5598
- return vaultError({
5599
- code: "STORAGE_ERROR",
5600
- cause: new Error(
5601
- `Failed to store encrypted value: ${valuePutResult.error.message}`
5602
- )
5603
- });
5618
+ return kvWriteError("Failed to store encrypted value", valuePutResult.error);
5604
5619
  }
5605
5620
  return { ok: true, data: void 0 };
5606
5621
  } catch (error) {
@@ -5818,12 +5833,7 @@ var init_dist2 = __esm({
5818
5833
  keyPayload
5819
5834
  );
5820
5835
  if (!keyPutResult.ok) {
5821
- return vaultError({
5822
- code: "STORAGE_ERROR",
5823
- cause: new Error(
5824
- `Failed to store key blob: ${keyPutResult.error.message}`
5825
- )
5826
- });
5836
+ return kvWriteError("Failed to store key blob", keyPutResult.error);
5827
5837
  }
5828
5838
  const valuePayload = JSON.stringify({
5829
5839
  data: base64Encode(encrypted),
@@ -5834,12 +5844,7 @@ var init_dist2 = __esm({
5834
5844
  valuePayload
5835
5845
  );
5836
5846
  if (!valuePutResult.ok) {
5837
- return vaultError({
5838
- code: "STORAGE_ERROR",
5839
- cause: new Error(
5840
- `Failed to store encrypted value: ${valuePutResult.error.message}`
5841
- )
5842
- });
5847
+ return kvWriteError("Failed to store encrypted value", valuePutResult.error);
5843
5848
  }
5844
5849
  return ok(void 0);
5845
5850
  } catch (error) {
@@ -6170,12 +6175,7 @@ var init_dist2 = __esm({
6170
6175
  grantPayload
6171
6176
  );
6172
6177
  if (!grantPutResult.ok) {
6173
- return vaultError({
6174
- code: "STORAGE_ERROR",
6175
- cause: new Error(
6176
- `Failed to store grant: ${grantPutResult.error.message}`
6177
- )
6178
- });
6178
+ return kvWriteError("Failed to store grant", grantPutResult.error);
6179
6179
  }
6180
6180
  return ok(void 0);
6181
6181
  } catch (error) {
@@ -6520,12 +6520,7 @@ var init_dist2 = __esm({
6520
6520
  keyPayload
6521
6521
  );
6522
6522
  if (!keyPutResult.ok) {
6523
- return vaultError({
6524
- code: "STORAGE_ERROR",
6525
- cause: new Error(
6526
- `Failed to store rotated key blob: ${keyPutResult.error.message}`
6527
- )
6528
- });
6523
+ return kvWriteError("Failed to store rotated key blob", keyPutResult.error);
6529
6524
  }
6530
6525
  const valuePayload = JSON.stringify({
6531
6526
  data: base64Encode(encrypted),
@@ -6536,12 +6531,7 @@ var init_dist2 = __esm({
6536
6531
  valuePayload
6537
6532
  );
6538
6533
  if (!valuePutResult.ok) {
6539
- return vaultError({
6540
- code: "STORAGE_ERROR",
6541
- cause: new Error(
6542
- `Failed to store re-encrypted value: ${valuePutResult.error.message}`
6543
- )
6544
- });
6534
+ return kvWriteError("Failed to store re-encrypted value", valuePutResult.error);
6545
6535
  }
6546
6536
  for (const did of remainingGrantees) {
6547
6537
  const grantResult = await this.reencrypt(key, did);