@tinycloud/operations 0.1.0-beta.2 → 0.2.0-beta.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.
@@ -1,6 +1,6 @@
1
1
  import { PermissionEntry } from '@tinycloud/sdk-core';
2
2
  import { z } from 'zod';
3
- import { T as TinyCloudPosture, O as OperationOperatorType } from './contract-mCY8LFFI.cjs';
3
+ import { T as TinyCloudPosture, O as OperationOperatorType } from './contract-OnWT3OXa.cjs';
4
4
 
5
5
  /**
6
6
  * A capability in the canonical form persisted in a v1 request artifact.
@@ -1,6 +1,6 @@
1
1
  import { PermissionEntry } from '@tinycloud/sdk-core';
2
2
  import { z } from 'zod';
3
- import { T as TinyCloudPosture, O as OperationOperatorType } from './contract-mCY8LFFI.js';
3
+ import { T as TinyCloudPosture, O as OperationOperatorType } from './contract-OnWT3OXa.js';
4
4
 
5
5
  /**
6
6
  * A capability in the canonical form persisted in a v1 request artifact.
package/dist/artifacts.js CHANGED
@@ -711,6 +711,9 @@ var ErrorCodes = {
711
711
  // KV-specific errors
712
712
  KV_NOT_FOUND: "KV_NOT_FOUND",
713
713
  KV_WRITE_FAILED: "KV_WRITE_FAILED",
714
+ KV_PRECONDITION_FAILED: "KV_PRECONDITION_FAILED",
715
+ KV_CONFLICT: "KV_CONFLICT",
716
+ KV_RESPONSE_TOO_LARGE: "KV_RESPONSE_TOO_LARGE",
714
717
  // SQL-specific errors
715
718
  SQL_ERROR: "SQL_ERROR",
716
719
  SQL_PERMISSION_DENIED: "SQL_PERMISSION_DENIED",
@@ -1657,7 +1660,7 @@ var KVService = class extends BaseService {
1657
1660
  * @param signal - Optional abort signal
1658
1661
  * @returns Fetch response
1659
1662
  */
1660
- async invokeOperation(path, action, body, signal) {
1663
+ async invokeOperation(path, action, body, signal, extraHeaders) {
1661
1664
  const session = this.context.session;
1662
1665
  const headers = this.context.invoke(
1663
1666
  session,
@@ -1665,9 +1668,10 @@ var KVService = class extends BaseService {
1665
1668
  path,
1666
1669
  action
1667
1670
  );
1671
+ const requestHeaders = Array.isArray(headers) ? [...headers, ...Object.entries(extraHeaders ?? {})] : { ...headers, ...extraHeaders };
1668
1672
  return this.context.fetch(`${this.host}/invoke`, {
1669
1673
  method: "POST",
1670
- headers,
1674
+ headers: requestHeaders,
1671
1675
  body,
1672
1676
  signal: this.combineSignals(signal)
1673
1677
  });
@@ -1849,13 +1853,21 @@ var KVService = class extends BaseService {
1849
1853
  if (!this.requireAuth()) {
1850
1854
  return err(authRequiredError("kv"));
1851
1855
  }
1856
+ if (options?.maxResponseBytes !== void 0 && (!Number.isSafeInteger(options.maxResponseBytes) || options.maxResponseBytes <= 0)) {
1857
+ return err(serviceError(
1858
+ ErrorCodes.INVALID_INPUT,
1859
+ "KV maxResponseBytes must be a positive safe integer",
1860
+ "kv"
1861
+ ));
1862
+ }
1852
1863
  const path = this.getFullPath(key, options?.prefix);
1853
1864
  try {
1854
1865
  const response = await this.invokeOperation(
1855
1866
  path,
1856
1867
  KVAction.GET,
1857
1868
  void 0,
1858
- options?.signal
1869
+ options?.signal,
1870
+ options?.maxResponseBytes === void 0 ? void 0 : { "x-tinycloud-max-response-bytes": String(options.maxResponseBytes) }
1859
1871
  );
1860
1872
  if (!response.ok) {
1861
1873
  if (response.status === 401 || response.status === 403) {
@@ -1873,6 +1885,14 @@ var KVService = class extends BaseService {
1873
1885
  return this.classifyNotFound(response, key);
1874
1886
  }
1875
1887
  const errorText = await response.text();
1888
+ if (response.status === 413) {
1889
+ return err(serviceError(
1890
+ ErrorCodes.KV_RESPONSE_TOO_LARGE,
1891
+ `KV value at key "${key}" exceeds the requested response limit`,
1892
+ "kv",
1893
+ { meta: { status: response.status, statusText: response.statusText } }
1894
+ ));
1895
+ }
1876
1896
  return err(
1877
1897
  serviceError(
1878
1898
  ErrorCodes.NETWORK_ERROR,
@@ -1904,6 +1924,13 @@ var KVService = class extends BaseService {
1904
1924
  if (!this.requireAuth()) {
1905
1925
  return err(authRequiredError("kv"));
1906
1926
  }
1927
+ if (options?.ifMatch !== void 0 && options.ifNoneMatch !== void 0) {
1928
+ return err(serviceError(
1929
+ ErrorCodes.INVALID_INPUT,
1930
+ "KV put cannot combine ifMatch and ifNoneMatch",
1931
+ "kv"
1932
+ ));
1933
+ }
1907
1934
  const path = this.getFullPath(key, options?.prefix);
1908
1935
  const body = this.serializePutValue(value, options?.contentType);
1909
1936
  try {
@@ -1911,7 +1938,11 @@ var KVService = class extends BaseService {
1911
1938
  path,
1912
1939
  KVAction.PUT,
1913
1940
  body,
1914
- options?.signal
1941
+ options?.signal,
1942
+ {
1943
+ ...options?.ifMatch === void 0 ? {} : { "if-match": options.ifMatch },
1944
+ ...options?.ifNoneMatch === void 0 ? {} : { "if-none-match": options.ifNoneMatch }
1945
+ }
1915
1946
  );
1916
1947
  if (!response.ok) {
1917
1948
  if (response.status === 401) {
@@ -1924,6 +1955,22 @@ var KVService = class extends BaseService {
1924
1955
  }));
1925
1956
  }
1926
1957
  const errorText = await response.text();
1958
+ if (response.status === 412) {
1959
+ return err(serviceError(
1960
+ ErrorCodes.KV_PRECONDITION_FAILED,
1961
+ `KV precondition failed for key "${key}"`,
1962
+ "kv",
1963
+ { meta: { status: response.status, statusText: response.statusText } }
1964
+ ));
1965
+ }
1966
+ if (response.status === 503 && (options?.ifMatch !== void 0 || options?.ifNoneMatch !== void 0)) {
1967
+ return err(serviceError(
1968
+ ErrorCodes.KV_CONFLICT,
1969
+ `Concurrent KV update conflicted for key "${key}"`,
1970
+ "kv",
1971
+ { meta: { status: response.status, statusText: response.statusText } }
1972
+ ));
1973
+ }
1927
1974
  const quotaError = this.handleQuotaErrorResponse(
1928
1975
  response,
1929
1976
  errorText,
@@ -2059,6 +2106,13 @@ var KVService = class extends BaseService {
2059
2106
  if (!this.requireAuth()) {
2060
2107
  return err(authRequiredError("kv"));
2061
2108
  }
2109
+ if (options?.limit !== void 0 && (!Number.isInteger(options.limit) || options.limit < 1 || options.limit > 1e3)) {
2110
+ return err(serviceError(
2111
+ ErrorCodes.INVALID_INPUT,
2112
+ "KV list limit must be an integer from 1 through 1000",
2113
+ "kv"
2114
+ ));
2115
+ }
2062
2116
  let listPath = options?.prefix ?? this._config.prefix ?? "";
2063
2117
  if (options?.path) {
2064
2118
  listPath = listPath ? `${listPath}/${options.path}` : options.path;
@@ -2068,7 +2122,8 @@ var KVService = class extends BaseService {
2068
2122
  listPath,
2069
2123
  KVAction.LIST,
2070
2124
  void 0,
2071
- options?.signal
2125
+ options?.signal,
2126
+ options?.limit === void 0 ? void 0 : { "x-tinycloud-limit": String(options.limit) }
2072
2127
  );
2073
2128
  if (!response.ok) {
2074
2129
  if (response.status === 401) {
@@ -2098,7 +2153,10 @@ var KVService = class extends BaseService {
2098
2153
  (key) => key.startsWith(prefixWithSlash) ? key.slice(prefixWithSlash.length) : key
2099
2154
  );
2100
2155
  }
2101
- return ok({ keys });
2156
+ return ok({
2157
+ keys,
2158
+ ...response.headers.get("x-tinycloud-truncated") === null ? {} : { truncated: response.headers.get("x-tinycloud-truncated") === "true" }
2159
+ });
2102
2160
  } catch (error) {
2103
2161
  return err(wrapError("kv", error));
2104
2162
  }
@@ -2118,7 +2176,8 @@ var KVService = class extends BaseService {
2118
2176
  path,
2119
2177
  KVAction.DELETE,
2120
2178
  void 0,
2121
- options?.signal
2179
+ options?.signal,
2180
+ options?.ifMatch === void 0 ? void 0 : { "if-match": options.ifMatch }
2122
2181
  );
2123
2182
  if (!response.ok) {
2124
2183
  if (response.status === 401) {
@@ -2134,6 +2193,22 @@ var KVService = class extends BaseService {
2134
2193
  return this.classifyNotFound(response, key);
2135
2194
  }
2136
2195
  const errorText = await response.text();
2196
+ if (response.status === 412) {
2197
+ return err(serviceError(
2198
+ ErrorCodes.KV_PRECONDITION_FAILED,
2199
+ `KV precondition failed for key "${key}"`,
2200
+ "kv",
2201
+ { meta: { status: response.status, statusText: response.statusText } }
2202
+ ));
2203
+ }
2204
+ if (response.status === 503 && options?.ifMatch !== void 0) {
2205
+ return err(serviceError(
2206
+ ErrorCodes.KV_CONFLICT,
2207
+ `Concurrent KV delete conflicted for key "${key}"`,
2208
+ "kv",
2209
+ { meta: { status: response.status, statusText: response.statusText } }
2210
+ ));
2211
+ }
2137
2212
  return err(
2138
2213
  serviceError(
2139
2214
  ErrorCodes.NETWORK_ERROR,
@@ -2143,7 +2218,10 @@ var KVService = class extends BaseService {
2143
2218
  )
2144
2219
  );
2145
2220
  }
2146
- return ok(void 0);
2221
+ return ok({
2222
+ data: void 0,
2223
+ headers: this.createResponseHeaders(response.headers)
2224
+ });
2147
2225
  } catch (error) {
2148
2226
  return err(wrapError("kv", error));
2149
2227
  }
@@ -2449,10 +2527,17 @@ var SQLService = class extends BaseService {
2449
2527
  return err(authRequiredError("sql"));
2450
2528
  }
2451
2529
  try {
2530
+ const body = {
2531
+ action: "query",
2532
+ sql,
2533
+ params: serializeSqlValues(params ?? [])
2534
+ };
2535
+ if (options?.maxRows !== void 0) body.maxRows = options.maxRows;
2536
+ if (options?.maxBytes !== void 0) body.maxBytes = options.maxBytes;
2452
2537
  const response = await this.invokeSQL(
2453
2538
  dbName,
2454
2539
  this.actionForSql(sql, SQLAction.READ),
2455
- { action: "query", sql, params: params ?? [] },
2540
+ body,
2456
2541
  options?.signal
2457
2542
  );
2458
2543
  if (!response.ok) {
@@ -2474,7 +2559,7 @@ var SQLService = class extends BaseService {
2474
2559
  const body = {
2475
2560
  action: "execute",
2476
2561
  sql,
2477
- params: params ?? []
2562
+ params: serializeSqlValues(params ?? [])
2478
2563
  };
2479
2564
  if (options?.schema) {
2480
2565
  body.schema = options.schema;
@@ -2799,6 +2884,11 @@ function validateMigrationOptions(options) {
2799
2884
  }
2800
2885
  return null;
2801
2886
  }
2887
+ function serializeSqlValues(values) {
2888
+ return values.map(
2889
+ (value) => value instanceof Uint8Array ? Array.from(value) : value
2890
+ );
2891
+ }
2802
2892
  function migrationKey(namespace, id) {
2803
2893
  return `${encodeURIComponent(namespace)}:${encodeURIComponent(id)}`;
2804
2894
  }