@tinycloud/sdk-services 3.1.0 → 3.2.0-beta.2

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.
package/dist/index.cjs CHANGED
@@ -47,11 +47,13 @@ __export(src_exports, {
47
47
  KVListResultSchema: () => KVListResultSchema,
48
48
  KVResponseHeadersSchema: () => KVResponseHeadersSchema,
49
49
  KVService: () => KVService,
50
+ MAX_SECRET_SCOPE_LENGTH: () => MAX_SECRET_SCOPE_LENGTH,
50
51
  NETWORK_NAME_PATTERN: () => NETWORK_NAME_PATTERN,
51
52
  NetworkIdError: () => NetworkIdError,
52
53
  PrefixedKVService: () => PrefixedKVService,
53
54
  RetryPolicySchema: () => RetryPolicySchema,
54
55
  SECRET_NAME_RE: () => SECRET_NAME_RE,
56
+ SECRET_SCOPE_RE: () => SECRET_SCOPE_RE,
55
57
  SQLAction: () => SQLAction,
56
58
  SQLMigrations: () => SQLMigrations,
57
59
  SQLService: () => SQLService,
@@ -65,6 +67,7 @@ __export(src_exports, {
65
67
  ServiceResponseEventSchema: () => ServiceResponseEventSchema,
66
68
  ServiceRetryEventSchema: () => ServiceRetryEventSchema,
67
69
  ServiceSessionSchema: () => ServiceSessionSchema,
70
+ TC832_RESERVED_SCOPES: () => TC832_RESERVED_SCOPES,
68
71
  TelemetryEvents: () => TelemetryEvents,
69
72
  TelemetrySpanEventSchema: () => TelemetrySpanEventSchema,
70
73
  TinyCloudDebugLogger: () => TinyCloudDebugLogger,
@@ -72,6 +75,7 @@ __export(src_exports, {
72
75
  VaultHeaders: () => VaultHeaders,
73
76
  VaultPublicSpaceKVActions: () => VaultPublicSpaceKVActions,
74
77
  abortedError: () => abortedError,
78
+ appSecretScope: () => appSecretScope,
75
79
  authExpiredError: () => authExpiredError,
76
80
  authRequiredError: () => authRequiredError,
77
81
  authUnauthorizedError: () => authUnauthorizedError,
@@ -2449,7 +2453,7 @@ var KVService = class extends BaseService {
2449
2453
  );
2450
2454
  }
2451
2455
  if (response.status === 404) {
2452
- return this.classifyNotFound(response, key);
2456
+ return await this.classifyNotFound(response, key);
2453
2457
  }
2454
2458
  const errorText = await response.text();
2455
2459
  if (response.status === 413) {
@@ -3018,7 +3022,7 @@ var KVService = class extends BaseService {
3018
3022
  );
3019
3023
  }
3020
3024
  if (response.status === 404) {
3021
- return this.classifyNotFound(response, key);
3025
+ return await this.classifyNotFound(response, key);
3022
3026
  }
3023
3027
  const errorText = await response.text();
3024
3028
  if (response.status === 412) {
@@ -3085,7 +3089,7 @@ var KVService = class extends BaseService {
3085
3089
  );
3086
3090
  }
3087
3091
  if (response.status === 404) {
3088
- return this.classifyNotFound(response, key);
3092
+ return await this.classifyNotFound(response, key);
3089
3093
  }
3090
3094
  const errorText = await response.text();
3091
3095
  return err(
@@ -3151,7 +3155,7 @@ var KVService = class extends BaseService {
3151
3155
  signal: request.signal
3152
3156
  });
3153
3157
  if (!response.ok) {
3154
- return this.createSignedReadUrlError(response, key, path);
3158
+ return await this.createSignedReadUrlError(response, key, path);
3155
3159
  }
3156
3160
  const signedUrl = this.normalizeSignedReadUrlResponse(
3157
3161
  await response.json()
@@ -5442,6 +5446,12 @@ function defaultVaultMessage(input) {
5442
5446
  return input.message ?? `Public key not found for ${input.did}`;
5443
5447
  case "STORAGE_ERROR":
5444
5448
  return input.message ?? input.cause.message;
5449
+ case "ALREADY_EXISTS":
5450
+ return input.message ?? `A value already exists at ${input.key}`;
5451
+ case "AUTH_UNAUTHORIZED":
5452
+ return input.message;
5453
+ case "PERMISSION_DENIED":
5454
+ return input.message;
5445
5455
  case "STORAGE_QUOTA_EXCEEDED":
5446
5456
  case "STORAGE_LIMIT_REACHED":
5447
5457
  return input.message;
@@ -5455,13 +5465,33 @@ function vaultError(input) {
5455
5465
  };
5456
5466
  return { ok: false, error };
5457
5467
  }
5468
+ function typedKvCause(error) {
5469
+ return Object.assign(new Error(error.message), {
5470
+ name: "ServiceError",
5471
+ code: error.code,
5472
+ service: error.service,
5473
+ ...error.meta !== void 0 ? { meta: error.meta } : {},
5474
+ ...error.cause !== void 0 ? { cause: error.cause } : {}
5475
+ });
5476
+ }
5458
5477
  function kvWriteError(context, error) {
5459
5478
  if (error.code === ErrorCodes.STORAGE_QUOTA_EXCEEDED || error.code === ErrorCodes.STORAGE_LIMIT_REACHED) {
5460
5479
  return vaultError({ code: error.code, message: error.message, meta: error.meta });
5461
5480
  }
5481
+ const message = `${context}: ${error.message}`;
5482
+ if (error.code === ErrorCodes.AUTH_UNAUTHORIZED) {
5483
+ const code = authorizationVerdictOf(error) === "unauthenticated" ? "AUTH_UNAUTHORIZED" : "PERMISSION_DENIED";
5484
+ return vaultError({
5485
+ code,
5486
+ message,
5487
+ ...error.meta !== void 0 ? { meta: error.meta } : {},
5488
+ cause: typedKvCause(error)
5489
+ });
5490
+ }
5462
5491
  return vaultError({
5463
5492
  code: "STORAGE_ERROR",
5464
- cause: new Error(`${context}: ${error.message}`)
5493
+ cause: new Error(message, { cause: typedKvCause(error) }),
5494
+ ...error.meta !== void 0 ? { meta: error.meta } : {}
5465
5495
  });
5466
5496
  }
5467
5497
  var DataVaultService = class extends BaseService {
@@ -5741,11 +5771,18 @@ var DataVaultService = class extends BaseService {
5741
5771
  cause: new Error(envelopeResult.error.message)
5742
5772
  });
5743
5773
  }
5744
- const valuePutResult = await this.tc.kv.put(
5745
- `vault/${key}`,
5746
- JSON.stringify(envelopeResult.data)
5747
- );
5774
+ const valuePath = `vault/${key}`;
5775
+ const valueBody = JSON.stringify(envelopeResult.data);
5776
+ const valuePutResult = options?.ifNoneMatch !== void 0 ? await this.tc.kv.put(valuePath, valueBody, { ifNoneMatch: options.ifNoneMatch }) : await this.tc.kv.put(valuePath, valueBody);
5748
5777
  if (!valuePutResult.ok) {
5778
+ if (options?.ifNoneMatch !== void 0 && valuePutResult.error.code === ErrorCodes.KV_PRECONDITION_FAILED) {
5779
+ return vaultError({
5780
+ code: "ALREADY_EXISTS",
5781
+ key,
5782
+ ...valuePutResult.error.meta !== void 0 ? { meta: valuePutResult.error.meta } : {},
5783
+ cause: typedKvCause(valuePutResult.error)
5784
+ });
5785
+ }
5749
5786
  return kvWriteError("Failed to store encrypted value", valuePutResult.error);
5750
5787
  }
5751
5788
  return { ok: true, data: void 0 };
@@ -5913,6 +5950,14 @@ var DataVaultService = class extends BaseService {
5913
5950
  if (this.usesNetworkEncryption) {
5914
5951
  return this.putNetworkEncrypted(key, value, options);
5915
5952
  }
5953
+ if (options?.ifNoneMatch !== void 0) {
5954
+ return vaultError({
5955
+ code: "STORAGE_ERROR",
5956
+ cause: new Error(
5957
+ "ifNoneMatch is only supported by network-encrypted vaults"
5958
+ )
5959
+ });
5960
+ }
5916
5961
  if (!this._isUnlocked || !this.masterKey) {
5917
5962
  return vaultError({
5918
5963
  code: "VAULT_LOCKED",
@@ -6724,6 +6769,35 @@ var SECRET_NAME_RE = /^[A-Z][A-Z0-9_]*$/;
6724
6769
  var SECRET_PREFIX = "secrets/";
6725
6770
  var SCOPED_SECRET_PREFIX = "secrets/scoped/";
6726
6771
  var RESERVED_SECRET_SCOPES = /* @__PURE__ */ new Set(["default", "global"]);
6772
+ var SECRET_SCOPE_RE = /^[a-z0-9]+(-[a-z0-9]+)*$/;
6773
+ var MAX_SECRET_SCOPE_LENGTH = 64;
6774
+ var TC832_RESERVED_SCOPES = Object.freeze([
6775
+ "default",
6776
+ "global",
6777
+ "scoped"
6778
+ ]);
6779
+ function appSecretScope(appId) {
6780
+ if (appId.trim() === "") {
6781
+ throw new Error("App id must be non-empty to derive a secret scope.");
6782
+ }
6783
+ const scope = appId.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
6784
+ if (scope === "") {
6785
+ throw new Error(
6786
+ `App id ${JSON.stringify(appId)} must contain at least one letter or number.`
6787
+ );
6788
+ }
6789
+ if (scope.length > MAX_SECRET_SCOPE_LENGTH) {
6790
+ throw new Error(
6791
+ `App id ${JSON.stringify(appId)} yields a secret scope longer than ${MAX_SECRET_SCOPE_LENGTH} characters.`
6792
+ );
6793
+ }
6794
+ if (TC832_RESERVED_SCOPES.includes(scope)) {
6795
+ throw new Error(
6796
+ `App id ${JSON.stringify(appId)} yields the reserved secret scope ${JSON.stringify(scope)}.`
6797
+ );
6798
+ }
6799
+ return scope;
6800
+ }
6727
6801
  function canonicalizeSecretScope(scope) {
6728
6802
  if (scope === void 0) {
6729
6803
  return void 0;
@@ -6836,11 +6910,12 @@ var SecretsService = class {
6836
6910
  const secretPath = resolveSecretPathResult(name, options);
6837
6911
  if ("ok" in secretPath) return secretPath;
6838
6912
  const now = (/* @__PURE__ */ new Date()).toISOString();
6839
- return this.vault.put(secretPath.vaultKey, {
6913
+ const payload = {
6840
6914
  value,
6841
6915
  createdAt: now,
6842
6916
  updatedAt: now
6843
- });
6917
+ };
6918
+ return options?.ifAbsent === true ? this.vault.put(secretPath.vaultKey, payload, { ifNoneMatch: "*" }) : this.vault.put(secretPath.vaultKey, payload);
6844
6919
  }
6845
6920
  async delete(name, options) {
6846
6921
  const secretPath = resolveSecretPathResult(name, options);
@@ -7896,11 +7971,13 @@ var import_decrypt_transport_response_error3 = require("@tinycloud/sdk-services/
7896
7971
  KVListResultSchema,
7897
7972
  KVResponseHeadersSchema,
7898
7973
  KVService,
7974
+ MAX_SECRET_SCOPE_LENGTH,
7899
7975
  NETWORK_NAME_PATTERN,
7900
7976
  NetworkIdError,
7901
7977
  PrefixedKVService,
7902
7978
  RetryPolicySchema,
7903
7979
  SECRET_NAME_RE,
7980
+ SECRET_SCOPE_RE,
7904
7981
  SQLAction,
7905
7982
  SQLMigrations,
7906
7983
  SQLService,
@@ -7914,6 +7991,7 @@ var import_decrypt_transport_response_error3 = require("@tinycloud/sdk-services/
7914
7991
  ServiceResponseEventSchema,
7915
7992
  ServiceRetryEventSchema,
7916
7993
  ServiceSessionSchema,
7994
+ TC832_RESERVED_SCOPES,
7917
7995
  TelemetryEvents,
7918
7996
  TelemetrySpanEventSchema,
7919
7997
  TinyCloudDebugLogger,
@@ -7921,6 +7999,7 @@ var import_decrypt_transport_response_error3 = require("@tinycloud/sdk-services/
7921
7999
  VaultHeaders,
7922
8000
  VaultPublicSpaceKVActions,
7923
8001
  abortedError,
8002
+ appSecretScope,
7924
8003
  authExpiredError,
7925
8004
  authRequiredError,
7926
8005
  authUnauthorizedError,