@tinycloud/sdk-services 3.2.6-beta.4 → 3.3.0-beta.11

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.
Files changed (45) hide show
  1. package/dist/{BaseService-1Ug6y7DC.d.cts → BaseService-Cc6Ueicm.d.cts} +1 -1
  2. package/dist/{BaseService-Bn07Vudy.d.ts → BaseService-DOdXd7sr.d.ts} +1 -1
  3. package/dist/encryption/index.cjs +8 -0
  4. package/dist/encryption/index.cjs.map +1 -1
  5. package/dist/encryption/index.d.cts +2 -2
  6. package/dist/encryption/index.d.ts +2 -2
  7. package/dist/encryption/index.js +8 -0
  8. package/dist/encryption/index.js.map +1 -1
  9. package/dist/index.cjs +345 -203
  10. package/dist/index.cjs.map +1 -1
  11. package/dist/index.d.cts +107 -7
  12. package/dist/index.d.ts +107 -7
  13. package/dist/index.js +344 -203
  14. package/dist/index.js.map +1 -1
  15. package/dist/internal/decrypt-transport-response-error.d.cts +1 -1
  16. package/dist/internal/decrypt-transport-response-error.d.ts +1 -1
  17. package/dist/kv/index.cjs +66 -21
  18. package/dist/kv/index.cjs.map +1 -1
  19. package/dist/kv/index.d.cts +4 -4
  20. package/dist/kv/index.d.ts +4 -4
  21. package/dist/kv/index.js +66 -21
  22. package/dist/kv/index.js.map +1 -1
  23. package/dist/kv/replication/grantPolicy.cjs +82 -0
  24. package/dist/kv/replication/grantPolicy.cjs.map +1 -0
  25. package/dist/kv/replication/grantPolicy.d.cts +19 -0
  26. package/dist/kv/replication/grantPolicy.d.ts +19 -0
  27. package/dist/kv/replication/grantPolicy.js +50 -0
  28. package/dist/kv/replication/grantPolicy.js.map +1 -0
  29. package/dist/kv/replication/index.cjs +571 -128
  30. package/dist/kv/replication/index.cjs.map +1 -1
  31. package/dist/kv/replication/index.d.cts +3 -3
  32. package/dist/kv/replication/index.d.ts +3 -3
  33. package/dist/kv/replication/index.js +571 -128
  34. package/dist/kv/replication/index.js.map +1 -1
  35. package/dist/{scope-BnyVPZ5E.d.ts → scope-B-m6cKH-.d.ts} +310 -7
  36. package/dist/{scope-CQ5kmHlt.d.cts → scope-B7oeKdLM.d.cts} +310 -7
  37. package/dist/sql/index.cjs +70 -36
  38. package/dist/sql/index.cjs.map +1 -1
  39. package/dist/sql/index.d.cts +2 -2
  40. package/dist/sql/index.d.ts +2 -2
  41. package/dist/sql/index.js +70 -36
  42. package/dist/sql/index.js.map +1 -1
  43. package/dist/{types-gmdUiorz.d.cts → types-BjH0ZtGy.d.cts} +6 -0
  44. package/dist/{types-gmdUiorz.d.ts → types-BjH0ZtGy.d.ts} +6 -0
  45. package/package.json +16 -2
@@ -1,7 +1,7 @@
1
- import { B as BaseService } from '../BaseService-1Ug6y7DC.cjs';
2
- import { R as Result, I as IService } from '../types-gmdUiorz.cjs';
3
- import { au as KVGetOptions, az as KVResponse, an as KVBatchReadResponse, ay as KVPutOptions, ak as KVBatchPutItem, al as KVBatchPutOptions, am as KVBatchPutResponse, aw as KVListOptions, ax as KVListResponse, aq as KVChangesOptions, ar as KVChangesResponse, at as KVDeleteOptions, av as KVHeadOptions, as as KVCreateSignedReadUrlOptions, aC as KVSignedReadUrlResponse, aB as KVServiceConfig, c as KVReadThrough } from '../scope-CQ5kmHlt.cjs';
4
- export { A as AuthorityRefusal, C as CLEAR_PENDING_WARNING, ah as DEFAULT_SIGNED_READ_URL_EXPIRY_MS, ai as KVAction, aj as KVActionType, ao as KVChange, ap as KVChangesAuthority, b as KVListPage, d as KVReplicaHandle, e as KVReplicaSpec, f as KVReplicaStorage, a as KVReplicationController, K as KVReplicationDeps, aA as KVResponseHeaders, L as LocalGetResult, g as LocalListResult, h as LocalReadMeta, i as LocalReplicaStatus, j as LocalSyncResult, k as PendingWriteRecord, l as PendingWriteState, P as PendingWriteStore, m as PinnedKey, n as PurgeTarget, q as ReplicaAuthorityState, w as ReplicaCoverage, B as ReplicaDevice, M as ReplicaGatedHandle, Q as ReplicaGrantInfo, T as ReplicaInspectedStatus, a3 as ReplicaState, a4 as ReplicaStatusEntry, a5 as ReplicationAuthority, a6 as ReplicationControl, a7 as ReplicationEvent, R as ReplicationIdentity, a8 as ReplicationOptions, a9 as ReplicationPurgeReport, aa as ReplicationReason, ab as ReplicationScheduler, ac as ResolvedReplicationOptions, ae as canonicalReplicationIdentity, af as replicationIdentityKey, ag as requiresSecretsOptIn } from '../scope-CQ5kmHlt.cjs';
1
+ import { B as BaseService } from '../BaseService-Cc6Ueicm.cjs';
2
+ import { R as Result, I as IService } from '../types-BjH0ZtGy.cjs';
3
+ import { aD as KVGetOptions, aI as KVResponse, aw as KVBatchReadResponse, aH as KVPutOptions, at as KVBatchPutItem, au as KVBatchPutOptions, av as KVBatchPutResponse, aF as KVListOptions, aG as KVListResponse, az as KVChangesOptions, aA as KVChangesResponse, aC as KVDeleteOptions, aE as KVHeadOptions, aB as KVCreateSignedReadUrlOptions, aL as KVSignedReadUrlResponse, aK as KVServiceConfig, c as KVReadThrough } from '../scope-B7oeKdLM.cjs';
4
+ export { A as AuthorityRefusal, C as CLEAR_PENDING_WARNING, aq as DEFAULT_SIGNED_READ_URL_EXPIRY_MS, ar as KVAction, as as KVActionType, ax as KVChange, ay as KVChangesAuthority, b as KVListPage, d as KVReplicaHandle, e as KVReplicaSpec, f as KVReplicaStorage, a as KVReplicationController, K as KVReplicationDeps, aJ as KVResponseHeaders, L as LocalGetResult, g as LocalListResult, h as LocalReadMeta, i as LocalReplicaStatus, j as LocalSyncResult, k as PendingWriteRecord, l as PendingWriteState, P as PendingWriteStore, m as PinnedKey, w as PurgeTarget, z as ReplicaAuthorityState, H as ReplicaCoverage, N as ReplicaDevice, X as ReplicaGatedHandle, _ as ReplicaGrantInfo, a0 as ReplicaInspectedStatus, ac as ReplicaState, ad as ReplicaStatusEntry, ae as ReplicationAuthority, af as ReplicationControl, ag as ReplicationEvent, R as ReplicationIdentity, ah as ReplicationOptions, ai as ReplicationPurgeReport, aj as ReplicationReason, ak as ReplicationScheduler, al as ResolvedReplicationOptions, an as canonicalReplicationIdentity, ao as replicationIdentityKey, ap as requiresSecretsOptIn } from '../scope-B7oeKdLM.cjs';
5
5
  export { kvPrefixCovers } from './replication/prefix.cjs';
6
6
  import './replication/contractConstants.cjs';
7
7
  import './replication/grantPolicyConstants.cjs';
@@ -1,7 +1,7 @@
1
- import { B as BaseService } from '../BaseService-Bn07Vudy.js';
2
- import { R as Result, I as IService } from '../types-gmdUiorz.js';
3
- import { au as KVGetOptions, az as KVResponse, an as KVBatchReadResponse, ay as KVPutOptions, ak as KVBatchPutItem, al as KVBatchPutOptions, am as KVBatchPutResponse, aw as KVListOptions, ax as KVListResponse, aq as KVChangesOptions, ar as KVChangesResponse, at as KVDeleteOptions, av as KVHeadOptions, as as KVCreateSignedReadUrlOptions, aC as KVSignedReadUrlResponse, aB as KVServiceConfig, c as KVReadThrough } from '../scope-BnyVPZ5E.js';
4
- export { A as AuthorityRefusal, C as CLEAR_PENDING_WARNING, ah as DEFAULT_SIGNED_READ_URL_EXPIRY_MS, ai as KVAction, aj as KVActionType, ao as KVChange, ap as KVChangesAuthority, b as KVListPage, d as KVReplicaHandle, e as KVReplicaSpec, f as KVReplicaStorage, a as KVReplicationController, K as KVReplicationDeps, aA as KVResponseHeaders, L as LocalGetResult, g as LocalListResult, h as LocalReadMeta, i as LocalReplicaStatus, j as LocalSyncResult, k as PendingWriteRecord, l as PendingWriteState, P as PendingWriteStore, m as PinnedKey, n as PurgeTarget, q as ReplicaAuthorityState, w as ReplicaCoverage, B as ReplicaDevice, M as ReplicaGatedHandle, Q as ReplicaGrantInfo, T as ReplicaInspectedStatus, a3 as ReplicaState, a4 as ReplicaStatusEntry, a5 as ReplicationAuthority, a6 as ReplicationControl, a7 as ReplicationEvent, R as ReplicationIdentity, a8 as ReplicationOptions, a9 as ReplicationPurgeReport, aa as ReplicationReason, ab as ReplicationScheduler, ac as ResolvedReplicationOptions, ae as canonicalReplicationIdentity, af as replicationIdentityKey, ag as requiresSecretsOptIn } from '../scope-BnyVPZ5E.js';
1
+ import { B as BaseService } from '../BaseService-DOdXd7sr.js';
2
+ import { R as Result, I as IService } from '../types-BjH0ZtGy.js';
3
+ import { aD as KVGetOptions, aI as KVResponse, aw as KVBatchReadResponse, aH as KVPutOptions, at as KVBatchPutItem, au as KVBatchPutOptions, av as KVBatchPutResponse, aF as KVListOptions, aG as KVListResponse, az as KVChangesOptions, aA as KVChangesResponse, aC as KVDeleteOptions, aE as KVHeadOptions, aB as KVCreateSignedReadUrlOptions, aL as KVSignedReadUrlResponse, aK as KVServiceConfig, c as KVReadThrough } from '../scope-B-m6cKH-.js';
4
+ export { A as AuthorityRefusal, C as CLEAR_PENDING_WARNING, aq as DEFAULT_SIGNED_READ_URL_EXPIRY_MS, ar as KVAction, as as KVActionType, ax as KVChange, ay as KVChangesAuthority, b as KVListPage, d as KVReplicaHandle, e as KVReplicaSpec, f as KVReplicaStorage, a as KVReplicationController, K as KVReplicationDeps, aJ as KVResponseHeaders, L as LocalGetResult, g as LocalListResult, h as LocalReadMeta, i as LocalReplicaStatus, j as LocalSyncResult, k as PendingWriteRecord, l as PendingWriteState, P as PendingWriteStore, m as PinnedKey, w as PurgeTarget, z as ReplicaAuthorityState, H as ReplicaCoverage, N as ReplicaDevice, X as ReplicaGatedHandle, _ as ReplicaGrantInfo, a0 as ReplicaInspectedStatus, ac as ReplicaState, ad as ReplicaStatusEntry, ae as ReplicationAuthority, af as ReplicationControl, ag as ReplicationEvent, R as ReplicationIdentity, ah as ReplicationOptions, ai as ReplicationPurgeReport, aj as ReplicationReason, ak as ReplicationScheduler, al as ResolvedReplicationOptions, an as canonicalReplicationIdentity, ao as replicationIdentityKey, ap as requiresSecretsOptIn } from '../scope-B-m6cKH-.js';
5
5
  export { kvPrefixCovers } from './replication/prefix.js';
6
6
  import './replication/contractConstants.js';
7
7
  import './replication/grantPolicyConstants.js';
package/dist/kv/index.js CHANGED
@@ -14,6 +14,14 @@ var ErrorCodes = {
14
14
  ABORTED: "ABORTED",
15
15
  INVALID_INPUT: "INVALID_INPUT",
16
16
  PERMISSION_DENIED: "PERMISSION_DENIED",
17
+ // Node retry signals (tinycloud-node #347). `meta.retryable` says whether a
18
+ // retry is safe; `meta.retryAfterMs` carries the node's Retry-After.
19
+ /** HTTP 503 `sql_busy:<stage>` / `unavailable_retryable`: nothing was applied; retry after `meta.retryAfterMs`. */
20
+ NODE_BUSY: "NODE_BUSY",
21
+ /** HTTP 503 `request_timeout`: the node's deadline passed before any write began; nothing was applied. */
22
+ REQUEST_TIMEOUT: "REQUEST_TIMEOUT",
23
+ /** HTTP 500 `outcome_unknown`: a write may have been applied; read back before retrying a non-idempotent operation. */
24
+ OUTCOME_UNKNOWN: "OUTCOME_UNKNOWN",
17
25
  // KV-specific errors
18
26
  KV_NOT_FOUND: "KV_NOT_FOUND",
19
27
  KV_WRITE_FAILED: "KV_WRITE_FAILED",
@@ -89,6 +97,20 @@ function serviceError(code, message, service, options) {
89
97
  };
90
98
  }
91
99
 
100
+ // src/responseErrors.ts
101
+ function responseErrorMeta(status, statusText, errorText) {
102
+ const meta = { status, statusText };
103
+ const snippet = compactMessage(errorText);
104
+ if (snippet) {
105
+ meta.responseSnippet = snippet.slice(0, 300);
106
+ }
107
+ return meta;
108
+ }
109
+ function compactMessage(message) {
110
+ const compact = message.replace(/\s+/g, " ").trim();
111
+ return compact.length > 500 ? `${compact.slice(0, 500)}...` : compact;
112
+ }
113
+
92
114
  // src/errors.ts
93
115
  import { CAPABILITY_REGISTRY } from "@tinycloud/bootstrap";
94
116
 
@@ -182,6 +204,30 @@ function authRequiredError(service) {
182
204
  service
183
205
  };
184
206
  }
207
+ function nodeRetryError(service, message, response, errorText) {
208
+ const body = errorText.trim();
209
+ const [, token, stage] = /^([a-z_]+)(?::\s*([a-z_]+):)?/.exec(body) ?? [];
210
+ let code;
211
+ if (response.status === 503 && (token === "sql_busy" || token === "unavailable_retryable")) {
212
+ code = ErrorCodes.NODE_BUSY;
213
+ } else if (response.status === 503 && token === "request_timeout") {
214
+ code = ErrorCodes.REQUEST_TIMEOUT;
215
+ } else if (response.status === 500 && token === "outcome_unknown") {
216
+ code = ErrorCodes.OUTCOME_UNKNOWN;
217
+ } else {
218
+ return void 0;
219
+ }
220
+ const retryable = code !== ErrorCodes.OUTCOME_UNKNOWN;
221
+ const retryAfter = response.headers.get("retry-after")?.trim();
222
+ return serviceError(code, message, service, {
223
+ meta: {
224
+ ...responseErrorMeta(response.status, response.statusText, errorText),
225
+ retryable,
226
+ ...token === "sql_busy" && stage ? { stage } : {},
227
+ ...retryable && retryAfter && /^\d{1,9}$/.test(retryAfter) ? { retryAfterMs: Number(retryAfter) * 1e3 } : {}
228
+ }
229
+ });
230
+ }
185
231
  var RequestTimeoutError = class extends Error {
186
232
  constructor(timeoutMs) {
187
233
  super(`Request timed out after ${timeoutMs}ms.`);
@@ -1500,9 +1546,12 @@ var KVService = class extends BaseService {
1500
1546
  { meta: { status: response.status, statusText: response.statusText } }
1501
1547
  ));
1502
1548
  }
1549
+ const message = `Failed to get key ${JSON.stringify(key)}: ${response.status} - ${errorText}`;
1550
+ const retryError = nodeRetryError("kv", message, response, errorText);
1551
+ if (retryError) return err(retryError);
1503
1552
  return err(serviceError(
1504
1553
  ErrorCodes.NETWORK_ERROR,
1505
- `Failed to get key ${JSON.stringify(key)}: ${response.status} - ${errorText}`,
1554
+ message,
1506
1555
  "kv",
1507
1556
  { meta: { status: response.status, statusText: response.statusText } }
1508
1557
  ));
@@ -1584,19 +1633,14 @@ var KVService = class extends BaseService {
1584
1633
  { meta: { status: response.status, statusText: response.statusText } }
1585
1634
  ));
1586
1635
  }
1587
- if (response.status === 503 && (options?.ifMatch !== void 0 || options?.ifNoneMatch !== void 0)) {
1588
- return err(serviceError(
1589
- ErrorCodes.KV_CONFLICT,
1590
- `Concurrent KV update conflicted for key ${JSON.stringify(key)}`,
1591
- "kv",
1592
- { meta: { status: response.status, statusText: response.statusText } }
1593
- ));
1594
- }
1636
+ const message = `Failed to put key ${JSON.stringify(key)}: ${response.status} - ${errorText}`;
1637
+ const retryError = nodeRetryError("kv", message, response, errorText);
1638
+ if (retryError) return err(retryError);
1595
1639
  const quotaError = this.handleQuotaErrorResponse(response, errorText, key);
1596
1640
  if (quotaError) return quotaError;
1597
1641
  return err(serviceError(
1598
1642
  ErrorCodes.KV_WRITE_FAILED,
1599
- `Failed to put key ${JSON.stringify(key)}: ${response.status} - ${errorText}`,
1643
+ message,
1600
1644
  "kv",
1601
1645
  { meta: { status: response.status, statusText: response.statusText } }
1602
1646
  ));
@@ -1896,9 +1940,12 @@ var KVService = class extends BaseService {
1896
1940
  );
1897
1941
  }
1898
1942
  const errorText = await response.text();
1943
+ const message = `Failed to list keys: ${response.status} - ${errorText}`;
1944
+ const retryError = nodeRetryError("kv", message, response, errorText);
1945
+ if (retryError) return err(retryError);
1899
1946
  return err(serviceError(
1900
1947
  ErrorCodes.NETWORK_ERROR,
1901
- `Failed to list keys: ${response.status} - ${errorText}`,
1948
+ message,
1902
1949
  "kv",
1903
1950
  { meta: { status: response.status, statusText: response.statusText } }
1904
1951
  ));
@@ -2149,17 +2196,12 @@ var KVService = class extends BaseService {
2149
2196
  { meta: { status: response.status, statusText: response.statusText } }
2150
2197
  ));
2151
2198
  }
2152
- if (response.status === 503 && options?.ifMatch !== void 0) {
2153
- return err(serviceError(
2154
- ErrorCodes.KV_CONFLICT,
2155
- `Concurrent KV delete conflicted for key ${JSON.stringify(key)}`,
2156
- "kv",
2157
- { meta: { status: response.status, statusText: response.statusText } }
2158
- ));
2159
- }
2199
+ const message = `Failed to delete key ${JSON.stringify(key)}: ${response.status} - ${errorText}`;
2200
+ const retryError = nodeRetryError("kv", message, response, errorText);
2201
+ if (retryError) return err(retryError);
2160
2202
  return err(serviceError(
2161
2203
  ErrorCodes.NETWORK_ERROR,
2162
- `Failed to delete key ${JSON.stringify(key)}: ${response.status} - ${errorText}`,
2204
+ message,
2163
2205
  "kv",
2164
2206
  { meta: { status: response.status, statusText: response.statusText } }
2165
2207
  ));
@@ -2200,10 +2242,13 @@ var KVService = class extends BaseService {
2200
2242
  return await this.classifyNotFound(response, key);
2201
2243
  }
2202
2244
  const errorText = await response.text();
2245
+ const message = `Failed to get metadata for key ${JSON.stringify(key)}: ${response.status} - ${errorText}`;
2246
+ const retryError = nodeRetryError("kv", message, response, errorText);
2247
+ if (retryError) return err(retryError);
2203
2248
  return err(
2204
2249
  serviceError(
2205
2250
  ErrorCodes.NETWORK_ERROR,
2206
- `Failed to get metadata for key ${JSON.stringify(key)}: ${response.status} - ${errorText}`,
2251
+ message,
2207
2252
  "kv",
2208
2253
  { meta: { status: response.status, statusText: response.statusText } }
2209
2254
  )