@tinycloud/sdk-services 3.2.6-beta.2 → 3.3.0-beta.7

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 (65) hide show
  1. package/dist/{BaseService-4wwJq1Gn.d.cts → BaseService-Cc6Ueicm.d.cts} +1 -1
  2. package/dist/{BaseService-BGr2slUz.d.ts → BaseService-DOdXd7sr.d.ts} +1 -1
  3. package/dist/encryption/index.cjs +10 -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 +10 -0
  8. package/dist/encryption/index.js.map +1 -1
  9. package/dist/index.cjs +109 -64
  10. package/dist/index.cjs.map +1 -1
  11. package/dist/index.d.cts +38 -12
  12. package/dist/index.d.ts +38 -12
  13. package/dist/index.js +108 -64
  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 +68 -21
  18. package/dist/kv/index.cjs.map +1 -1
  19. package/dist/kv/index.d.cts +7 -4
  20. package/dist/kv/index.d.ts +7 -4
  21. package/dist/kv/index.js +68 -21
  22. package/dist/kv/index.js.map +1 -1
  23. package/dist/kv/replication/contractConstants.cjs +115 -0
  24. package/dist/kv/replication/contractConstants.cjs.map +1 -0
  25. package/dist/kv/replication/contractConstants.d.cts +77 -0
  26. package/dist/kv/replication/contractConstants.d.ts +77 -0
  27. package/dist/kv/replication/contractConstants.js +75 -0
  28. package/dist/kv/replication/contractConstants.js.map +1 -0
  29. package/dist/kv/replication/grantPolicy.cjs +82 -0
  30. package/dist/kv/replication/grantPolicy.cjs.map +1 -0
  31. package/dist/kv/replication/grantPolicy.d.cts +19 -0
  32. package/dist/kv/replication/grantPolicy.d.ts +19 -0
  33. package/dist/kv/replication/grantPolicy.js +50 -0
  34. package/dist/kv/replication/grantPolicy.js.map +1 -0
  35. package/dist/kv/replication/grantPolicyConstants.cjs +42 -0
  36. package/dist/kv/replication/grantPolicyConstants.cjs.map +1 -0
  37. package/dist/kv/replication/grantPolicyConstants.d.cts +10 -0
  38. package/dist/kv/replication/grantPolicyConstants.d.ts +10 -0
  39. package/dist/kv/replication/grantPolicyConstants.js +14 -0
  40. package/dist/kv/replication/grantPolicyConstants.js.map +1 -0
  41. package/dist/kv/replication/grantPolicyTypes.cjs +19 -0
  42. package/dist/kv/replication/grantPolicyTypes.cjs.map +1 -0
  43. package/dist/kv/replication/grantPolicyTypes.d.cts +87 -0
  44. package/dist/kv/replication/grantPolicyTypes.d.ts +87 -0
  45. package/dist/kv/replication/grantPolicyTypes.js +1 -0
  46. package/dist/kv/replication/grantPolicyTypes.js.map +1 -0
  47. package/dist/kv/replication/index.cjs +575 -131
  48. package/dist/kv/replication/index.cjs.map +1 -1
  49. package/dist/kv/replication/index.d.cts +6 -3
  50. package/dist/kv/replication/index.d.ts +6 -3
  51. package/dist/kv/replication/index.js +575 -131
  52. package/dist/kv/replication/index.js.map +1 -1
  53. package/dist/scope-B-m6cKH-.d.ts +1962 -0
  54. package/dist/scope-B7oeKdLM.d.cts +1962 -0
  55. package/dist/sql/index.cjs +72 -36
  56. package/dist/sql/index.cjs.map +1 -1
  57. package/dist/sql/index.d.cts +2 -2
  58. package/dist/sql/index.d.ts +2 -2
  59. package/dist/sql/index.js +72 -36
  60. package/dist/sql/index.js.map +1 -1
  61. package/dist/{types-D-9A3Sut.d.cts → types-BjH0ZtGy.d.cts} +8 -0
  62. package/dist/{types-D-9A3Sut.d.ts → types-BjH0ZtGy.d.ts} +8 -0
  63. package/package.json +55 -2
  64. package/dist/scope-CoKKmMiI.d.ts +0 -957
  65. package/dist/scope-D7wmjbMH.d.cts +0 -957
@@ -1,4 +1,4 @@
1
- import { P as PermissionHint } from '../types-D-9A3Sut.cjs';
1
+ import { P as PermissionHint } from '../types-BjH0ZtGy.cjs';
2
2
 
3
3
  /** A reachable node returned an HTTP failure for a decrypt request. */
4
4
  declare class DecryptTransportResponseError extends Error {
@@ -1,4 +1,4 @@
1
- import { P as PermissionHint } from '../types-D-9A3Sut.js';
1
+ import { P as PermissionHint } from '../types-BjH0ZtGy.js';
2
2
 
3
3
  /** A reachable node returned an HTTP failure for a decrypt request. */
4
4
  declare class DecryptTransportResponseError extends Error {
package/dist/kv/index.cjs CHANGED
@@ -48,6 +48,14 @@ var ErrorCodes = {
48
48
  ABORTED: "ABORTED",
49
49
  INVALID_INPUT: "INVALID_INPUT",
50
50
  PERMISSION_DENIED: "PERMISSION_DENIED",
51
+ // Node retry signals (tinycloud-node #347). `meta.retryable` says whether a
52
+ // retry is safe; `meta.retryAfterMs` carries the node's Retry-After.
53
+ /** HTTP 503 `sql_busy:<stage>` / `unavailable_retryable`: nothing was applied; retry after `meta.retryAfterMs`. */
54
+ NODE_BUSY: "NODE_BUSY",
55
+ /** HTTP 503 `request_timeout`: the node's deadline passed before any write began; nothing was applied. */
56
+ REQUEST_TIMEOUT: "REQUEST_TIMEOUT",
57
+ /** HTTP 500 `outcome_unknown`: a write may have been applied; read back before retrying a non-idempotent operation. */
58
+ OUTCOME_UNKNOWN: "OUTCOME_UNKNOWN",
51
59
  // KV-specific errors
52
60
  KV_NOT_FOUND: "KV_NOT_FOUND",
53
61
  KV_WRITE_FAILED: "KV_WRITE_FAILED",
@@ -102,6 +110,8 @@ var TelemetryEvents = {
102
110
  REPLICATION_SYNC: "replication.sync",
103
111
  REPLICATION_STATE: "replication.state",
104
112
  REPLICATION_DIVERGENCE: "replication.divergence",
113
+ REPLICATION_GRANT: "replication.grant",
114
+ REPLICATION_LIFECYCLE: "replication.lifecycle",
105
115
  /** Emitted once, on the first write rejected because storage is full. */
106
116
  STORAGE_FULL: "storage.full"
107
117
  };
@@ -121,6 +131,20 @@ function serviceError(code, message, service, options) {
121
131
  };
122
132
  }
123
133
 
134
+ // src/responseErrors.ts
135
+ function responseErrorMeta(status, statusText, errorText) {
136
+ const meta = { status, statusText };
137
+ const snippet = compactMessage(errorText);
138
+ if (snippet) {
139
+ meta.responseSnippet = snippet.slice(0, 300);
140
+ }
141
+ return meta;
142
+ }
143
+ function compactMessage(message) {
144
+ const compact = message.replace(/\s+/g, " ").trim();
145
+ return compact.length > 500 ? `${compact.slice(0, 500)}...` : compact;
146
+ }
147
+
124
148
  // src/errors.ts
125
149
  var import_bootstrap = require("@tinycloud/bootstrap");
126
150
 
@@ -214,6 +238,30 @@ function authRequiredError(service) {
214
238
  service
215
239
  };
216
240
  }
241
+ function nodeRetryError(service, message, response, errorText) {
242
+ const body = errorText.trim();
243
+ const [, token, stage] = /^([a-z_]+)(?::\s*([a-z_]+):)?/.exec(body) ?? [];
244
+ let code;
245
+ if (response.status === 503 && (token === "sql_busy" || token === "unavailable_retryable")) {
246
+ code = ErrorCodes.NODE_BUSY;
247
+ } else if (response.status === 503 && token === "request_timeout") {
248
+ code = ErrorCodes.REQUEST_TIMEOUT;
249
+ } else if (response.status === 500 && token === "outcome_unknown") {
250
+ code = ErrorCodes.OUTCOME_UNKNOWN;
251
+ } else {
252
+ return void 0;
253
+ }
254
+ const retryable = code !== ErrorCodes.OUTCOME_UNKNOWN;
255
+ const retryAfter = response.headers.get("retry-after")?.trim();
256
+ return serviceError(code, message, service, {
257
+ meta: {
258
+ ...responseErrorMeta(response.status, response.statusText, errorText),
259
+ retryable,
260
+ ...token === "sql_busy" && stage ? { stage } : {},
261
+ ...retryable && retryAfter && /^\d{1,9}$/.test(retryAfter) ? { retryAfterMs: Number(retryAfter) * 1e3 } : {}
262
+ }
263
+ });
264
+ }
217
265
  var RequestTimeoutError = class extends Error {
218
266
  constructor(timeoutMs) {
219
267
  super(`Request timed out after ${timeoutMs}ms.`);
@@ -1532,9 +1580,12 @@ var KVService = class extends BaseService {
1532
1580
  { meta: { status: response.status, statusText: response.statusText } }
1533
1581
  ));
1534
1582
  }
1583
+ const message = `Failed to get key ${JSON.stringify(key)}: ${response.status} - ${errorText}`;
1584
+ const retryError = nodeRetryError("kv", message, response, errorText);
1585
+ if (retryError) return err(retryError);
1535
1586
  return err(serviceError(
1536
1587
  ErrorCodes.NETWORK_ERROR,
1537
- `Failed to get key ${JSON.stringify(key)}: ${response.status} - ${errorText}`,
1588
+ message,
1538
1589
  "kv",
1539
1590
  { meta: { status: response.status, statusText: response.statusText } }
1540
1591
  ));
@@ -1616,19 +1667,14 @@ var KVService = class extends BaseService {
1616
1667
  { meta: { status: response.status, statusText: response.statusText } }
1617
1668
  ));
1618
1669
  }
1619
- if (response.status === 503 && (options?.ifMatch !== void 0 || options?.ifNoneMatch !== void 0)) {
1620
- return err(serviceError(
1621
- ErrorCodes.KV_CONFLICT,
1622
- `Concurrent KV update conflicted for key ${JSON.stringify(key)}`,
1623
- "kv",
1624
- { meta: { status: response.status, statusText: response.statusText } }
1625
- ));
1626
- }
1670
+ const message = `Failed to put key ${JSON.stringify(key)}: ${response.status} - ${errorText}`;
1671
+ const retryError = nodeRetryError("kv", message, response, errorText);
1672
+ if (retryError) return err(retryError);
1627
1673
  const quotaError = this.handleQuotaErrorResponse(response, errorText, key);
1628
1674
  if (quotaError) return quotaError;
1629
1675
  return err(serviceError(
1630
1676
  ErrorCodes.KV_WRITE_FAILED,
1631
- `Failed to put key ${JSON.stringify(key)}: ${response.status} - ${errorText}`,
1677
+ message,
1632
1678
  "kv",
1633
1679
  { meta: { status: response.status, statusText: response.statusText } }
1634
1680
  ));
@@ -1928,9 +1974,12 @@ var KVService = class extends BaseService {
1928
1974
  );
1929
1975
  }
1930
1976
  const errorText = await response.text();
1977
+ const message = `Failed to list keys: ${response.status} - ${errorText}`;
1978
+ const retryError = nodeRetryError("kv", message, response, errorText);
1979
+ if (retryError) return err(retryError);
1931
1980
  return err(serviceError(
1932
1981
  ErrorCodes.NETWORK_ERROR,
1933
- `Failed to list keys: ${response.status} - ${errorText}`,
1982
+ message,
1934
1983
  "kv",
1935
1984
  { meta: { status: response.status, statusText: response.statusText } }
1936
1985
  ));
@@ -2181,17 +2230,12 @@ var KVService = class extends BaseService {
2181
2230
  { meta: { status: response.status, statusText: response.statusText } }
2182
2231
  ));
2183
2232
  }
2184
- if (response.status === 503 && options?.ifMatch !== void 0) {
2185
- return err(serviceError(
2186
- ErrorCodes.KV_CONFLICT,
2187
- `Concurrent KV delete conflicted for key ${JSON.stringify(key)}`,
2188
- "kv",
2189
- { meta: { status: response.status, statusText: response.statusText } }
2190
- ));
2191
- }
2233
+ const message = `Failed to delete key ${JSON.stringify(key)}: ${response.status} - ${errorText}`;
2234
+ const retryError = nodeRetryError("kv", message, response, errorText);
2235
+ if (retryError) return err(retryError);
2192
2236
  return err(serviceError(
2193
2237
  ErrorCodes.NETWORK_ERROR,
2194
- `Failed to delete key ${JSON.stringify(key)}: ${response.status} - ${errorText}`,
2238
+ message,
2195
2239
  "kv",
2196
2240
  { meta: { status: response.status, statusText: response.statusText } }
2197
2241
  ));
@@ -2232,10 +2276,13 @@ var KVService = class extends BaseService {
2232
2276
  return await this.classifyNotFound(response, key);
2233
2277
  }
2234
2278
  const errorText = await response.text();
2279
+ const message = `Failed to get metadata for key ${JSON.stringify(key)}: ${response.status} - ${errorText}`;
2280
+ const retryError = nodeRetryError("kv", message, response, errorText);
2281
+ if (retryError) return err(retryError);
2235
2282
  return err(
2236
2283
  serviceError(
2237
2284
  ErrorCodes.NETWORK_ERROR,
2238
- `Failed to get metadata for key ${JSON.stringify(key)}: ${response.status} - ${errorText}`,
2285
+ message,
2239
2286
  "kv",
2240
2287
  { meta: { status: response.status, statusText: response.statusText } }
2241
2288
  )