@tinycloud/sdk-services 2.1.0 → 2.2.0-beta.10

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
@@ -37,8 +37,10 @@ __export(index_exports, {
37
37
  KVService: () => KVService,
38
38
  PrefixedKVService: () => PrefixedKVService,
39
39
  RetryPolicySchema: () => RetryPolicySchema,
40
+ SECRET_NAME_RE: () => SECRET_NAME_RE,
40
41
  SQLAction: () => SQLAction,
41
42
  SQLService: () => SQLService,
43
+ SecretsService: () => SecretsService,
42
44
  ServiceContext: () => ServiceContext,
43
45
  ServiceErrorEventSchema: () => ServiceErrorEventSchema,
44
46
  ServiceErrorSchema: () => ServiceErrorSchema,
@@ -54,6 +56,7 @@ __export(index_exports, {
54
56
  authExpiredError: () => authExpiredError,
55
57
  authRequiredError: () => authRequiredError,
56
58
  authUnauthorizedError: () => authUnauthorizedError,
59
+ canonicalizeSecretScope: () => canonicalizeSecretScope,
57
60
  createKVResponseSchema: () => createKVResponseSchema,
58
61
  createResultSchema: () => createResultSchema,
59
62
  createVaultCrypto: () => createVaultCrypto,
@@ -65,6 +68,7 @@ __export(index_exports, {
65
68
  ok: () => ok,
66
69
  parseAuthError: () => parseAuthError,
67
70
  permissionDeniedError: () => permissionDeniedError,
71
+ resolveSecretPath: () => resolveSecretPath,
68
72
  serviceError: () => serviceError,
69
73
  storageLimitReachedError: () => storageLimitReachedError,
70
74
  storageQuotaExceededError: () => storageQuotaExceededError,
@@ -3844,6 +3848,127 @@ function createVaultCrypto(wasm) {
3844
3848
  sha256: (data) => wasm.vault_sha256(data)
3845
3849
  };
3846
3850
  }
3851
+
3852
+ // src/secrets/paths.ts
3853
+ var SECRET_NAME_RE = /^[A-Z][A-Z0-9_]*$/;
3854
+ var SECRET_PREFIX = "secrets/";
3855
+ var SCOPED_SECRET_PREFIX = "secrets/scoped/";
3856
+ var RESERVED_SECRET_SCOPES = /* @__PURE__ */ new Set(["default", "global"]);
3857
+ function canonicalizeSecretScope(scope) {
3858
+ if (scope === void 0) {
3859
+ return void 0;
3860
+ }
3861
+ const trimmed = scope.trim();
3862
+ if (trimmed === "") {
3863
+ throw new Error("Secret scope must be non-empty; omit scope for global secrets.");
3864
+ }
3865
+ const canonical = trimmed.toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
3866
+ if (canonical === "") {
3867
+ throw new Error("Secret scope must contain at least one letter or number.");
3868
+ }
3869
+ if (RESERVED_SECRET_SCOPES.has(canonical)) {
3870
+ throw new Error(
3871
+ `Secret scope ${JSON.stringify(scope)} is reserved; omit scope for global secrets.`
3872
+ );
3873
+ }
3874
+ return canonical;
3875
+ }
3876
+ function resolveSecretPath(name, options = {}) {
3877
+ const normalizedName = name.trim();
3878
+ if (!SECRET_NAME_RE.test(normalizedName)) {
3879
+ throw new Error(
3880
+ `Invalid secret name ${JSON.stringify(name)}. Secret names must match ${SECRET_NAME_RE.source}.`
3881
+ );
3882
+ }
3883
+ const scope = canonicalizeSecretScope(options.scope);
3884
+ const vaultKey = scope === void 0 ? `${SECRET_PREFIX}${normalizedName}` : `${SCOPED_SECRET_PREFIX}${scope}/${normalizedName}`;
3885
+ return {
3886
+ name: normalizedName,
3887
+ ...scope !== void 0 ? { scope } : {},
3888
+ vaultKey,
3889
+ permissionPaths: {
3890
+ keys: `keys/${vaultKey}`,
3891
+ vault: `vault/${vaultKey}`
3892
+ }
3893
+ };
3894
+ }
3895
+
3896
+ // src/secrets/SecretsService.ts
3897
+ function invalidSecretInput(message) {
3898
+ return err({
3899
+ code: ErrorCodes.INVALID_INPUT,
3900
+ service: "secrets",
3901
+ message
3902
+ });
3903
+ }
3904
+ function resolveSecretPathResult(name, options) {
3905
+ try {
3906
+ return resolveSecretPath(name, options);
3907
+ } catch (error) {
3908
+ return invalidSecretInput(error instanceof Error ? error.message : String(error));
3909
+ }
3910
+ }
3911
+ var SecretsService = class {
3912
+ constructor(vault) {
3913
+ this.getVault = typeof vault === "function" ? vault : () => vault;
3914
+ }
3915
+ get vault() {
3916
+ return this.getVault();
3917
+ }
3918
+ get isUnlocked() {
3919
+ return this.vault.isUnlocked;
3920
+ }
3921
+ unlock(signer) {
3922
+ return this.vault.unlock(signer);
3923
+ }
3924
+ lock() {
3925
+ this.vault.lock();
3926
+ }
3927
+ async get(name, options) {
3928
+ const secretPath = resolveSecretPathResult(name, options);
3929
+ if ("ok" in secretPath) return secretPath;
3930
+ const result = await this.vault.get(secretPath.vaultKey);
3931
+ if (!result.ok) {
3932
+ return result;
3933
+ }
3934
+ return { ok: true, data: result.data.value.value };
3935
+ }
3936
+ async put(name, value, options) {
3937
+ const secretPath = resolveSecretPathResult(name, options);
3938
+ if ("ok" in secretPath) return secretPath;
3939
+ const now = (/* @__PURE__ */ new Date()).toISOString();
3940
+ return this.vault.put(secretPath.vaultKey, {
3941
+ value,
3942
+ createdAt: now,
3943
+ updatedAt: now
3944
+ });
3945
+ }
3946
+ async delete(name, options) {
3947
+ const secretPath = resolveSecretPathResult(name, options);
3948
+ if ("ok" in secretPath) return secretPath;
3949
+ return this.vault.delete(secretPath.vaultKey);
3950
+ }
3951
+ async list(options) {
3952
+ let prefix;
3953
+ try {
3954
+ const scope = canonicalizeSecretScope(options?.scope);
3955
+ prefix = scope === void 0 ? "secrets/" : `secrets/scoped/${scope}/`;
3956
+ } catch (error) {
3957
+ return invalidSecretInput(error instanceof Error ? error.message : String(error));
3958
+ }
3959
+ const result = await this.vault.list({
3960
+ prefix,
3961
+ removePrefix: true
3962
+ });
3963
+ if (!result.ok) {
3964
+ return result;
3965
+ }
3966
+ return {
3967
+ ok: true,
3968
+ data: result.data.filter((name) => SECRET_NAME_RE.test(name))
3969
+ };
3970
+ }
3971
+ };
3847
3972
  // Annotate the CommonJS export names for ESM import in node:
3848
3973
  0 && (module.exports = {
3849
3974
  BaseService,
@@ -3863,8 +3988,10 @@ function createVaultCrypto(wasm) {
3863
3988
  KVService,
3864
3989
  PrefixedKVService,
3865
3990
  RetryPolicySchema,
3991
+ SECRET_NAME_RE,
3866
3992
  SQLAction,
3867
3993
  SQLService,
3994
+ SecretsService,
3868
3995
  ServiceContext,
3869
3996
  ServiceErrorEventSchema,
3870
3997
  ServiceErrorSchema,
@@ -3880,6 +4007,7 @@ function createVaultCrypto(wasm) {
3880
4007
  authExpiredError,
3881
4008
  authRequiredError,
3882
4009
  authUnauthorizedError,
4010
+ canonicalizeSecretScope,
3883
4011
  createKVResponseSchema,
3884
4012
  createResultSchema,
3885
4013
  createVaultCrypto,
@@ -3891,6 +4019,7 @@ function createVaultCrypto(wasm) {
3891
4019
  ok,
3892
4020
  parseAuthError,
3893
4021
  permissionDeniedError,
4022
+ resolveSecretPath,
3894
4023
  serviceError,
3895
4024
  storageLimitReachedError,
3896
4025
  storageQuotaExceededError,