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

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 (39) hide show
  1. package/dist/{BaseService-Cc6Ueicm.d.cts → BaseService-BhfKzKke.d.cts} +5 -1
  2. package/dist/{BaseService-DOdXd7sr.d.ts → BaseService-x4AFZiEa.d.ts} +5 -1
  3. package/dist/encryption/index.cjs +18 -5
  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 +18 -5
  8. package/dist/encryption/index.js.map +1 -1
  9. package/dist/index.cjs +911 -797
  10. package/dist/index.cjs.map +1 -1
  11. package/dist/index.d.cts +95 -11
  12. package/dist/index.d.ts +95 -11
  13. package/dist/index.js +911 -797
  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 +72 -80
  18. package/dist/kv/index.cjs.map +1 -1
  19. package/dist/kv/index.d.cts +4 -5
  20. package/dist/kv/index.d.ts +4 -5
  21. package/dist/kv/index.js +72 -80
  22. package/dist/kv/index.js.map +1 -1
  23. package/dist/kv/replication/index.cjs +6 -5
  24. package/dist/kv/replication/index.cjs.map +1 -1
  25. package/dist/kv/replication/index.d.cts +3 -3
  26. package/dist/kv/replication/index.d.ts +3 -3
  27. package/dist/kv/replication/index.js +6 -5
  28. package/dist/kv/replication/index.js.map +1 -1
  29. package/dist/{scope-B-m6cKH-.d.ts → scope-BHTkk5Yk.d.ts} +13 -2
  30. package/dist/{scope-B7oeKdLM.d.cts → scope-DMhalRFn.d.cts} +13 -2
  31. package/dist/sql/index.cjs +30 -16
  32. package/dist/sql/index.cjs.map +1 -1
  33. package/dist/sql/index.d.cts +2 -2
  34. package/dist/sql/index.d.ts +2 -2
  35. package/dist/sql/index.js +30 -16
  36. package/dist/sql/index.js.map +1 -1
  37. package/dist/{types-BjH0ZtGy.d.cts → types-eVS1Whuf.d.cts} +24 -4
  38. package/dist/{types-BjH0ZtGy.d.ts → types-eVS1Whuf.d.ts} +24 -4
  39. package/package.json +2 -2
@@ -1,4 +1,4 @@
1
- import { P as PermissionHint } from '../types-BjH0ZtGy.cjs';
1
+ import { P as PermissionHint } from '../types-eVS1Whuf.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-BjH0ZtGy.js';
1
+ import { P as PermissionHint } from '../types-eVS1Whuf.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
@@ -50,7 +50,7 @@ var ErrorCodes = {
50
50
  PERMISSION_DENIED: "PERMISSION_DENIED",
51
51
  // Node retry signals (tinycloud-node #347). `meta.retryable` says whether a
52
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`. */
53
+ /** HTTP 503 `sql_busy:<stage>` / `unavailable_retryable`/`read_audit_busy`: nothing was applied; retry after `meta.retryAfterMs`. */
54
54
  NODE_BUSY: "NODE_BUSY",
55
55
  /** HTTP 503 `request_timeout`: the node's deadline passed before any write began; nothing was applied. */
56
56
  REQUEST_TIMEOUT: "REQUEST_TIMEOUT",
@@ -91,11 +91,12 @@ var ErrorCodes = {
91
91
  DUCKDB_READONLY_VIOLATION: "DUCKDB_READONLY_VIOLATION"
92
92
  };
93
93
  var defaultRetryPolicy = {
94
- maxAttempts: 3,
94
+ maxAttempts: 4,
95
95
  backoff: "exponential",
96
- baseDelayMs: 1e3,
97
- maxDelayMs: 1e4,
98
- retryableErrors: [ErrorCodes.NETWORK_ERROR, ErrorCodes.TIMEOUT]
96
+ baseDelayMs: 250,
97
+ maxDelayMs: 4e3,
98
+ retryableErrors: [ErrorCodes.NODE_BUSY, ErrorCodes.REQUEST_TIMEOUT],
99
+ maxTotalMs: 12e3
99
100
  };
100
101
  var TelemetryEvents = {
101
102
  SPAN: "telemetry.span",
@@ -242,7 +243,7 @@ function nodeRetryError(service, message, response, errorText) {
242
243
  const body = errorText.trim();
243
244
  const [, token, stage] = /^([a-z_]+)(?::\s*([a-z_]+):)?/.exec(body) ?? [];
244
245
  let code;
245
- if (response.status === 503 && (token === "sql_busy" || token === "unavailable_retryable")) {
246
+ if (response.status === 503 && (token === "sql_busy" || token === "unavailable_retryable" || token === "read_audit_busy")) {
246
247
  code = ErrorCodes.NODE_BUSY;
247
248
  } else if (response.status === 503 && token === "request_timeout") {
248
249
  code = ErrorCodes.REQUEST_TIMEOUT;
@@ -673,6 +674,18 @@ var BaseService = class {
673
674
  }
674
675
  return controller.signal;
675
676
  }
677
+ /** POST a signed invocation with retry; `mint` re-signs per attempt, `init.headers` add to the signed ones. */
678
+ invokeWithRetry(url, mint, { headers: extra, ...init } = {}) {
679
+ const build = () => {
680
+ const signed = mint();
681
+ return {
682
+ method: "POST",
683
+ ...init,
684
+ headers: Array.isArray(signed) ? [...signed, ...Object.entries(extra ?? {})] : { ...signed, ...extra }
685
+ };
686
+ };
687
+ return this.context.invokeWithRetry ? this.context.invokeWithRetry(url, build) : this.context.fetch(url, build());
688
+ }
676
689
  /**
677
690
  * Create the abort signal for one request, bounded by the request timeout.
678
691
  *
@@ -1040,15 +1053,6 @@ var KVService = class extends BaseService {
1040
1053
  get host() {
1041
1054
  return this.context.hosts[0];
1042
1055
  }
1043
- withJsonContentType(headers) {
1044
- if (Array.isArray(headers)) {
1045
- return [...headers, ["content-type", "application/json"]];
1046
- }
1047
- return {
1048
- ...headers,
1049
- "content-type": "application/json"
1050
- };
1051
- }
1052
1056
  /**
1053
1057
  * Execute an invoke operation.
1054
1058
  *
@@ -1059,20 +1063,11 @@ var KVService = class extends BaseService {
1059
1063
  * @returns Fetch response
1060
1064
  */
1061
1065
  async invokeOperation(path, action, body, signal, extraHeaders) {
1062
- const session = this.context.session;
1063
- const headers = this.context.invoke(
1064
- session,
1065
- "kv",
1066
- path,
1067
- action
1066
+ return this.invokeWithRetry(
1067
+ `${this.host}/invoke`,
1068
+ () => this.context.invoke(this.context.session, "kv", path, action),
1069
+ { headers: extraHeaders, body, signal }
1068
1070
  );
1069
- const requestHeaders = Array.isArray(headers) ? [...headers, ...Object.entries(extraHeaders ?? {})] : { ...headers, ...extraHeaders };
1070
- return this.context.fetch(`${this.host}/invoke`, {
1071
- method: "POST",
1072
- headers: requestHeaders,
1073
- body,
1074
- signal
1075
- });
1076
1071
  }
1077
1072
  /**
1078
1073
  * Serialize a single put value into a fetch body.
@@ -1278,28 +1273,28 @@ var KVService = class extends BaseService {
1278
1273
  }
1279
1274
  const request = this.createRequestSignal(options?.signal, options?.timeout);
1280
1275
  try {
1281
- const session = this.context.session;
1282
- const invocationHeaders = this.context.invokeAny(
1283
- session,
1284
- paths.map((path) => ({
1285
- spaceId: session.spaceId,
1286
- service: "kv",
1287
- path,
1288
- action
1289
- }))
1290
- );
1291
1276
  const limitHeaders = {};
1292
1277
  if (getOptions?.maxResponseBytes !== void 0) {
1293
1278
  limitHeaders["x-tinycloud-max-response-bytes"] = String(
1294
1279
  getOptions.maxResponseBytes
1295
1280
  );
1296
1281
  }
1297
- const headers = Array.isArray(invocationHeaders) ? [...invocationHeaders, ...Object.entries(limitHeaders)] : { ...invocationHeaders, ...limitHeaders };
1298
- const response = await this.context.fetch(`${this.host}/invoke`, {
1299
- method: "POST",
1300
- headers,
1301
- signal: request.signal
1302
- });
1282
+ const response = await this.invokeWithRetry(
1283
+ `${this.host}/invoke`,
1284
+ () => {
1285
+ const session = this.context.session;
1286
+ return this.context.invokeAny(
1287
+ session,
1288
+ paths.map((path) => ({
1289
+ spaceId: session.spaceId,
1290
+ service: "kv",
1291
+ path,
1292
+ action
1293
+ }))
1294
+ );
1295
+ },
1296
+ { headers: limitHeaders, signal: request.signal }
1297
+ );
1303
1298
  if (!response.ok) {
1304
1299
  const errorText = response.status === 401 || response.status === 403 ? await this.readAuthorizationText(response) : await response.text();
1305
1300
  if (response.status === 401 || response.status === 403) {
@@ -1345,10 +1340,10 @@ var KVService = class extends BaseService {
1345
1340
  result: err(serviceError(item.error.code, item.error.message, "kv"))
1346
1341
  };
1347
1342
  }
1348
- const headers2 = item.headers;
1343
+ const headers = item.headers;
1349
1344
  const data = action === KVAction.HEAD ? void 0 : this.parseBatchValue(
1350
1345
  item.dataBase64,
1351
- headers2,
1346
+ headers,
1352
1347
  getOptions?.raw,
1353
1348
  getOptions?.binary
1354
1349
  );
@@ -1356,7 +1351,7 @@ var KVService = class extends BaseService {
1356
1351
  key: keys[index],
1357
1352
  result: ok({
1358
1353
  data,
1359
- headers: this.createBatchResponseHeaders(headers2)
1354
+ headers: this.createBatchResponseHeaders(headers)
1360
1355
  })
1361
1356
  };
1362
1357
  });
@@ -1591,7 +1586,7 @@ var KVService = class extends BaseService {
1591
1586
  ));
1592
1587
  }
1593
1588
  const data = await this.parseResponse(response, options?.raw, options?.binary);
1594
- return ok({ data, headers: this.createResponseHeaders(response.headers) });
1589
+ return ok({ data, headers: this.createResponseHeaders(response.headers), ...response.retry && { retry: response.retry } });
1595
1590
  }
1596
1591
  async batchGet(keys, options) {
1597
1592
  return this.withTelemetry(
@@ -1681,7 +1676,8 @@ var KVService = class extends BaseService {
1681
1676
  }
1682
1677
  return ok({
1683
1678
  data: void 0,
1684
- headers: this.createResponseHeaders(response.headers)
1679
+ headers: this.createResponseHeaders(response.headers),
1680
+ ...response.retry && { retry: response.retry }
1685
1681
  });
1686
1682
  }
1687
1683
  /**
@@ -1754,25 +1750,23 @@ var KVService = class extends BaseService {
1754
1750
  entries?.[index]?.body ?? this.serializeBatchPutValue(items[index])
1755
1751
  );
1756
1752
  }
1757
- const headers = this.context.invokeAny(
1758
- session,
1759
- paths.map((path) => ({
1760
- spaceId: session.spaceId,
1761
- service: "kv",
1762
- path,
1763
- action: KVAction.PUT
1764
- }))
1753
+ const response = await this.invokeWithRetry(
1754
+ `${this.host}/invoke`,
1755
+ () => {
1756
+ const headers = this.context.invokeAny(
1757
+ session,
1758
+ paths.map((path) => ({
1759
+ spaceId: session.spaceId,
1760
+ service: "kv",
1761
+ path,
1762
+ action: KVAction.PUT
1763
+ }))
1764
+ );
1765
+ requestMayHaveDispatched = true;
1766
+ return headers;
1767
+ },
1768
+ { body, signal }
1765
1769
  );
1766
- const url = `${this.host}/invoke`;
1767
- const init = {
1768
- method: "POST",
1769
- headers,
1770
- body,
1771
- signal
1772
- };
1773
- const fetchFn = this.context.fetch;
1774
- requestMayHaveDispatched = true;
1775
- const response = await fetchFn(url, init);
1776
1770
  if (!response.ok) {
1777
1771
  let errorText;
1778
1772
  try {
@@ -2242,7 +2236,8 @@ var KVService = class extends BaseService {
2242
2236
  }
2243
2237
  return ok({
2244
2238
  data: void 0,
2245
- headers: this.createResponseHeaders(response.headers)
2239
+ headers: this.createResponseHeaders(response.headers),
2240
+ ...response.retry && { retry: response.retry }
2246
2241
  });
2247
2242
  }
2248
2243
  /**
@@ -2316,12 +2311,6 @@ var KVService = class extends BaseService {
2316
2311
  }
2317
2312
  const path = this.getFullPath(key, options?.prefix);
2318
2313
  const session = this.context.session;
2319
- const headers = this.context.invoke(
2320
- session,
2321
- "kv",
2322
- path,
2323
- KVAction.GET
2324
- );
2325
2314
  const body = {
2326
2315
  space: session.spaceId,
2327
2316
  path,
@@ -2335,12 +2324,15 @@ var KVService = class extends BaseService {
2335
2324
  }
2336
2325
  const request = this.createRequestSignal(options?.signal, options?.timeout);
2337
2326
  try {
2338
- const response = await this.context.fetch(`${this.host}/signed/kv`, {
2339
- method: "POST",
2340
- headers: this.withJsonContentType(headers),
2341
- body: JSON.stringify(body),
2342
- signal: request.signal
2343
- });
2327
+ const response = await this.invokeWithRetry(
2328
+ `${this.host}/signed/kv`,
2329
+ () => this.context.invoke(session, "kv", path, KVAction.GET),
2330
+ {
2331
+ headers: { "content-type": "application/json" },
2332
+ body: JSON.stringify(body),
2333
+ signal: request.signal
2334
+ }
2335
+ );
2344
2336
  if (!response.ok) {
2345
2337
  return await this.createSignedReadUrlError(response, key, path);
2346
2338
  }