@tinycloud/sdk-services 3.2.6-beta.4 → 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 (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 +94 -57
  10. package/dist/index.cjs.map +1 -1
  11. package/dist/index.d.cts +29 -6
  12. package/dist/index.d.ts +29 -6
  13. package/dist/index.js +93 -57
  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
package/dist/sql/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,42 @@ function serviceError(code, message, service, options) {
89
97
  };
90
98
  }
91
99
 
100
+ // src/responseErrors.ts
101
+ function parseServiceErrorBody(errorText) {
102
+ try {
103
+ return JSON.parse(errorText);
104
+ } catch {
105
+ return {};
106
+ }
107
+ }
108
+ function formatServiceResponseError(serviceLabel, operation, status, errorText, parsed) {
109
+ if (parsed.message) {
110
+ return compactMessage(parsed.message);
111
+ }
112
+ if (looksLikeHtml(errorText)) {
113
+ if (status === 524 || /524\s*[:-]/i.test(errorText) || /a timeout occurred/i.test(errorText)) {
114
+ return `${serviceLabel} ${operation} failed: upstream request timed out. Please retry.`;
115
+ }
116
+ return `${serviceLabel} ${operation} failed: upstream service returned an HTML error page (${status}).`;
117
+ }
118
+ return `${serviceLabel} ${operation} failed: ${status} - ${compactMessage(errorText)}`;
119
+ }
120
+ function responseErrorMeta(status, statusText, errorText) {
121
+ const meta = { status, statusText };
122
+ const snippet = compactMessage(errorText);
123
+ if (snippet) {
124
+ meta.responseSnippet = snippet.slice(0, 300);
125
+ }
126
+ return meta;
127
+ }
128
+ function looksLikeHtml(text) {
129
+ return /<!doctype html/i.test(text) || /<html[\s>]/i.test(text);
130
+ }
131
+ function compactMessage(message) {
132
+ const compact = message.replace(/\s+/g, " ").trim();
133
+ return compact.length > 500 ? `${compact.slice(0, 500)}...` : compact;
134
+ }
135
+
92
136
  // src/errors.ts
93
137
  import { CAPABILITY_REGISTRY } from "@tinycloud/bootstrap";
94
138
  function authRequiredError(service) {
@@ -98,6 +142,30 @@ function authRequiredError(service) {
98
142
  service
99
143
  };
100
144
  }
145
+ function nodeRetryError(service, message, response, errorText) {
146
+ const body = errorText.trim();
147
+ const [, token, stage] = /^([a-z_]+)(?::\s*([a-z_]+):)?/.exec(body) ?? [];
148
+ let code;
149
+ if (response.status === 503 && (token === "sql_busy" || token === "unavailable_retryable")) {
150
+ code = ErrorCodes.NODE_BUSY;
151
+ } else if (response.status === 503 && token === "request_timeout") {
152
+ code = ErrorCodes.REQUEST_TIMEOUT;
153
+ } else if (response.status === 500 && token === "outcome_unknown") {
154
+ code = ErrorCodes.OUTCOME_UNKNOWN;
155
+ } else {
156
+ return void 0;
157
+ }
158
+ const retryable = code !== ErrorCodes.OUTCOME_UNKNOWN;
159
+ const retryAfter = response.headers.get("retry-after")?.trim();
160
+ return serviceError(code, message, service, {
161
+ meta: {
162
+ ...responseErrorMeta(response.status, response.statusText, errorText),
163
+ retryable,
164
+ ...token === "sql_busy" && stage ? { stage } : {},
165
+ ...retryable && retryAfter && /^\d{1,9}$/.test(retryAfter) ? { retryAfterMs: Number(retryAfter) * 1e3 } : {}
166
+ }
167
+ });
168
+ }
101
169
  var RequestTimeoutError = class extends Error {
102
170
  constructor(timeoutMs) {
103
171
  super(`Request timed out after ${timeoutMs}ms.`);
@@ -505,42 +573,6 @@ var BaseService = class {
505
573
  }
506
574
  };
507
575
 
508
- // src/responseErrors.ts
509
- function parseServiceErrorBody(errorText) {
510
- try {
511
- return JSON.parse(errorText);
512
- } catch {
513
- return {};
514
- }
515
- }
516
- function formatServiceResponseError(serviceLabel, operation, status, errorText, parsed) {
517
- if (parsed.message) {
518
- return compactMessage(parsed.message);
519
- }
520
- if (looksLikeHtml(errorText)) {
521
- if (status === 524 || /524\s*[:-]/i.test(errorText) || /a timeout occurred/i.test(errorText)) {
522
- return `${serviceLabel} ${operation} failed: upstream request timed out. Please retry.`;
523
- }
524
- return `${serviceLabel} ${operation} failed: upstream service returned an HTML error page (${status}).`;
525
- }
526
- return `${serviceLabel} ${operation} failed: ${status} - ${compactMessage(errorText)}`;
527
- }
528
- function responseErrorMeta(status, statusText, errorText) {
529
- const meta = { status, statusText };
530
- const snippet = compactMessage(errorText);
531
- if (snippet) {
532
- meta.responseSnippet = snippet.slice(0, 300);
533
- }
534
- return meta;
535
- }
536
- function looksLikeHtml(text) {
537
- return /<!doctype html/i.test(text) || /<html[\s>]/i.test(text);
538
- }
539
- function compactMessage(message) {
540
- const compact = message.replace(/\s+/g, " ").trim();
541
- return compact.length > 500 ? `${compact.slice(0, 500)}...` : compact;
542
- }
543
-
544
576
  // src/sql/SQLMigrations.ts
545
577
  var SQLMigrations = class {
546
578
  constructor(service, dbName) {
@@ -956,6 +988,8 @@ var SQLService = class extends BaseService {
956
988
  if (response.status === 413 && parseStorageRejection(errorText)) {
957
989
  return err(storageRejectionError("sql", 413, meta, errorText));
958
990
  }
991
+ const retryError = nodeRetryError("sql", `SQL ${operation} failed: ${response.status} - ${errorText}`, response, errorText);
992
+ if (retryError) return err(retryError);
959
993
  const errorBody = parseServiceErrorBody(errorText);
960
994
  const errorCode = this.mapHttpStatusToErrorCode(
961
995
  response.status,