@clef-sh/client 0.1.2-beta.92

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/README.md ADDED
@@ -0,0 +1,58 @@
1
+ # @clef-sh/client
2
+
3
+ Lightweight SDK for consuming [Clef](https://clef.sh) secrets at runtime. Zero dependencies.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install @clef-sh/client
9
+ ```
10
+
11
+ ## App SDK
12
+
13
+ Read secrets from a `clef serve` endpoint (or Clef Cloud). Falls back to environment variables.
14
+
15
+ ```typescript
16
+ import { ClefClient } from "@clef-sh/client";
17
+
18
+ const secrets = new ClefClient();
19
+
20
+ const dbUrl = await secrets.get("DB_URL");
21
+ const all = await secrets.getAll();
22
+ const keyNames = await secrets.keys();
23
+ const isUp = await secrets.health();
24
+ ```
25
+
26
+ ### Configuration
27
+
28
+ | Option | Env var | Default | Description |
29
+ | ------------- | -------------------- | ----------------------- | --------------------------------------------- |
30
+ | `endpoint` | `CLEF_ENDPOINT` | `http://127.0.0.1:7779` | Serve endpoint URL |
31
+ | `token` | `CLEF_SERVICE_TOKEN` | — | Bearer token for authentication |
32
+ | `envFallback` | — | `true` | Fall back to `process.env` when key not found |
33
+ | `cacheTtlMs` | — | `0` | In-memory cache TTL (0 = no caching) |
34
+
35
+ ## Cloud KMS Provider
36
+
37
+ For `@clef-sh/runtime` integration — decrypts artifacts encrypted with Clef Cloud's managed KMS.
38
+
39
+ ```typescript
40
+ import { CloudKmsProvider } from "@clef-sh/client/kms";
41
+
42
+ const kms = new CloudKmsProvider({
43
+ endpoint: "https://api.clef.sh",
44
+ token: process.env.CLEF_SERVICE_TOKEN,
45
+ });
46
+ ```
47
+
48
+ The runtime uses this automatically when a packed artifact specifies the `cloud` KMS provider.
49
+
50
+ ## Documentation
51
+
52
+ - [Runtime Agent guide](https://docs.clef.sh/guide/agent)
53
+ - [Clef Cloud guide](https://docs.clef.sh/guide/cloud)
54
+ - [API reference](https://docs.clef.sh/api/)
55
+
56
+ ## License
57
+
58
+ MIT
package/dist/auth.d.ts ADDED
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Resolve a service token from an explicit value or CLEF_SERVICE_TOKEN env var.
3
+ */
4
+ export declare function resolveToken(explicit?: string): string;
5
+ /**
6
+ * Resolve the serve endpoint from an explicit value or CLEF_ENDPOINT env var.
7
+ */
8
+ export declare function resolveEndpoint(explicit?: string): string;
9
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,wBAAgB,YAAY,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAYtD;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAQzD"}
@@ -0,0 +1,28 @@
1
+ import { ClefClientOptions } from "./types";
2
+ /**
3
+ * Lightweight client for consuming Clef secrets from a serve endpoint.
4
+ *
5
+ * ```typescript
6
+ * const secrets = new ClefClient();
7
+ * const dbUrl = await secrets.get("DB_URL");
8
+ * ```
9
+ */
10
+ export declare class ClefClient {
11
+ private readonly endpoint;
12
+ private readonly token;
13
+ private readonly envFallback;
14
+ private readonly cacheTtlMs;
15
+ private readonly fetchFn;
16
+ private cache;
17
+ constructor(options?: ClefClientOptions);
18
+ /** Get a single secret by key. Falls back to env var if configured. */
19
+ get(key: string): Promise<string | undefined>;
20
+ /** Get all secrets as a key-value map. */
21
+ getAll(): Promise<Record<string, string>>;
22
+ /** List available key names. */
23
+ keys(): Promise<string[]>;
24
+ /** Check if the serve endpoint is reachable. */
25
+ health(): Promise<boolean>;
26
+ private fetchSecrets;
27
+ }
28
+ //# sourceMappingURL=clef-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clef-client.d.ts","sourceRoot":"","sources":["../src/clef-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAS5C;;;;;;;GAOG;AACH,qBAAa,UAAU;IACrB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAU;IACtC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA0B;IAClD,OAAO,CAAC,KAAK,CAA2B;gBAE5B,OAAO,CAAC,EAAE,iBAAiB;IAQvC,uEAAuE;IACjE,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAYnD,0CAA0C;IACpC,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAI/C,gCAAgC;IAC1B,IAAI,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAK/B,gDAAgD;IAC1C,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC;YASlB,YAAY;CAqB3B"}
@@ -0,0 +1,21 @@
1
+ import { CloudKmsProviderOptions } from "./types";
2
+ /**
3
+ * Clef Cloud KMS provider.
4
+ *
5
+ * Implements the KmsProvider interface (structurally — no import needed)
6
+ * for use with @clef-sh/runtime's createKmsProvider factory.
7
+ *
8
+ * Only `unwrap()` is supported. Encryption (wrap) is handled by the
9
+ * keyservice sidecar during `clef pack`.
10
+ */
11
+ export declare class CloudKmsProvider {
12
+ private readonly endpoint;
13
+ private readonly token;
14
+ constructor(options: CloudKmsProviderOptions);
15
+ wrap(_keyId: string, _plaintext: Buffer): Promise<{
16
+ wrappedKey: Buffer;
17
+ algorithm: string;
18
+ }>;
19
+ unwrap(keyId: string, wrappedKey: Buffer, _algorithm: string): Promise<Buffer>;
20
+ }
21
+ //# sourceMappingURL=cloud-kms-provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cloud-kms-provider.d.ts","sourceRoot":"","sources":["../src/cloud-kms-provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAmB,MAAM,SAAS,CAAC;AAInE;;;;;;;;GAQG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;gBAEnB,OAAO,EAAE,uBAAuB;IAKtC,IAAI,CACR,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IAM/C,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAcrF"}
package/dist/http.d.ts ADDED
@@ -0,0 +1,14 @@
1
+ interface RequestOptions {
2
+ method: "GET" | "POST";
3
+ path: string;
4
+ body?: unknown;
5
+ token: string;
6
+ fetchFn: typeof globalThis.fetch;
7
+ }
8
+ /**
9
+ * Make an authenticated HTTP request to a Clef endpoint.
10
+ * Handles the { data, success, message } envelope and retries once on 5xx.
11
+ */
12
+ export declare function request<T>(baseUrl: string, opts: RequestOptions): Promise<T>;
13
+ export {};
14
+ //# sourceMappingURL=http.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AAEA,UAAU,cAAc;IACtB,MAAM,EAAE,KAAK,GAAG,MAAM,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;CAClC;AAED;;;GAGG;AACH,wBAAsB,OAAO,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,CAAC,CAAC,CAgElF"}
@@ -0,0 +1,4 @@
1
+ export { ClefClient } from "./clef-client";
2
+ export { ClefClientError } from "./types";
3
+ export type { ClefClientOptions } from "./types";
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,4 @@
1
+ export { ClefClient } from "./clef-client";
2
+ export { ClefClientError } from "./types";
3
+ export type { ClefClientOptions } from "./types";
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC1C,YAAY,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,177 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ ClefClient: () => ClefClient,
24
+ ClefClientError: () => ClefClientError
25
+ });
26
+ module.exports = __toCommonJS(index_exports);
27
+
28
+ // src/types.ts
29
+ var ClefClientError = class extends Error {
30
+ constructor(message, statusCode, fix) {
31
+ super(message);
32
+ this.statusCode = statusCode;
33
+ this.fix = fix;
34
+ this.name = "ClefClientError";
35
+ }
36
+ statusCode;
37
+ fix;
38
+ };
39
+
40
+ // src/auth.ts
41
+ function resolveToken(explicit) {
42
+ if (explicit) return explicit;
43
+ if (typeof process !== "undefined" && process.env?.CLEF_SERVICE_TOKEN) {
44
+ return process.env.CLEF_SERVICE_TOKEN;
45
+ }
46
+ throw new ClefClientError(
47
+ "No service token configured",
48
+ void 0,
49
+ "Set CLEF_SERVICE_TOKEN or pass token in options."
50
+ );
51
+ }
52
+ function resolveEndpoint(explicit) {
53
+ if (explicit) return explicit;
54
+ if (typeof process !== "undefined" && process.env?.CLEF_ENDPOINT) {
55
+ return process.env.CLEF_ENDPOINT;
56
+ }
57
+ return "http://127.0.0.1:7779";
58
+ }
59
+
60
+ // src/http.ts
61
+ async function request(baseUrl, opts) {
62
+ const url = `${baseUrl}${opts.path}`;
63
+ const headers = {
64
+ Authorization: `Bearer ${opts.token}`,
65
+ Accept: "application/json"
66
+ };
67
+ if (opts.body !== void 0) {
68
+ headers["Content-Type"] = "application/json";
69
+ }
70
+ const init = {
71
+ method: opts.method,
72
+ headers,
73
+ body: opts.body !== void 0 ? JSON.stringify(opts.body) : void 0
74
+ };
75
+ let response;
76
+ try {
77
+ response = await opts.fetchFn(url, init);
78
+ } catch (err) {
79
+ try {
80
+ response = await opts.fetchFn(url, init);
81
+ } catch {
82
+ throw new ClefClientError(
83
+ `Connection failed: ${err.message}`,
84
+ void 0,
85
+ "Is the endpoint reachable? Check your CLEF_ENDPOINT setting."
86
+ );
87
+ }
88
+ }
89
+ if (response.status >= 500) {
90
+ response = await opts.fetchFn(url, init);
91
+ }
92
+ if (response.status === 401) {
93
+ throw new ClefClientError("Authentication failed", 401, "Check your CLEF_SERVICE_TOKEN.");
94
+ }
95
+ if (response.status === 503) {
96
+ throw new ClefClientError("Secrets expired or not loaded", 503, "Check the agent logs.");
97
+ }
98
+ if (!response.ok) {
99
+ const text = await response.text().catch(() => "");
100
+ throw new ClefClientError(
101
+ `HTTP ${response.status}: ${text || response.statusText}`,
102
+ response.status
103
+ );
104
+ }
105
+ const json = await response.json();
106
+ if (json && typeof json === "object" && "success" in json) {
107
+ if (!json.success) {
108
+ throw new ClefClientError(json.message || "Request failed", response.status);
109
+ }
110
+ return json.data;
111
+ }
112
+ return json;
113
+ }
114
+
115
+ // src/clef-client.ts
116
+ var ClefClient = class {
117
+ endpoint;
118
+ token;
119
+ envFallback;
120
+ cacheTtlMs;
121
+ fetchFn;
122
+ cache = null;
123
+ constructor(options) {
124
+ this.endpoint = resolveEndpoint(options?.endpoint);
125
+ this.token = resolveToken(options?.token);
126
+ this.envFallback = options?.envFallback ?? true;
127
+ this.cacheTtlMs = options?.cacheTtlMs ?? 0;
128
+ this.fetchFn = options?.fetch ?? globalThis.fetch;
129
+ }
130
+ /** Get a single secret by key. Falls back to env var if configured. */
131
+ async get(key) {
132
+ const all = await this.fetchSecrets();
133
+ const value = all[key];
134
+ if (value !== void 0) return value;
135
+ if (this.envFallback && typeof process !== "undefined") {
136
+ return process.env[key];
137
+ }
138
+ return void 0;
139
+ }
140
+ /** Get all secrets as a key-value map. */
141
+ async getAll() {
142
+ return this.fetchSecrets();
143
+ }
144
+ /** List available key names. */
145
+ async keys() {
146
+ const all = await this.fetchSecrets();
147
+ return Object.keys(all);
148
+ }
149
+ /** Check if the serve endpoint is reachable. */
150
+ async health() {
151
+ try {
152
+ const response = await this.fetchFn(`${this.endpoint}/v1/health`);
153
+ return response.ok;
154
+ } catch {
155
+ return false;
156
+ }
157
+ }
158
+ async fetchSecrets() {
159
+ if (this.cacheTtlMs > 0 && this.cache) {
160
+ const age = Date.now() - this.cache.fetchedAt;
161
+ if (age < this.cacheTtlMs) {
162
+ return this.cache.secrets;
163
+ }
164
+ }
165
+ const secrets = await request(this.endpoint, {
166
+ method: "GET",
167
+ path: "/v1/secrets",
168
+ token: this.token,
169
+ fetchFn: this.fetchFn
170
+ });
171
+ if (this.cacheTtlMs > 0) {
172
+ this.cache = { secrets, fetchedAt: Date.now() };
173
+ }
174
+ return secrets;
175
+ }
176
+ };
177
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/index.ts", "../src/types.ts", "../src/auth.ts", "../src/http.ts", "../src/clef-client.ts"],
4
+ "sourcesContent": ["export { ClefClient } from \"./clef-client\";\nexport { ClefClientError } from \"./types\";\nexport type { ClefClientOptions } from \"./types\";\n", "/** Configuration for the ClefClient app SDK. */\nexport interface ClefClientOptions {\n /** Base URL of the clef serve endpoint. Default: http://127.0.0.1:7779 */\n endpoint?: string;\n /** Bearer token for authentication. Falls back to CLEF_SERVICE_TOKEN env var. */\n token?: string;\n /** Fall back to process.env when a key is not found. Default: true */\n envFallback?: boolean;\n /** In-memory cache TTL in milliseconds. 0 = no caching. Default: 0 */\n cacheTtlMs?: number;\n /** Custom fetch implementation (for testing or edge runtimes). */\n fetch?: typeof globalThis.fetch;\n}\n\n/** Configuration for the Cloud KMS provider. */\nexport interface CloudKmsProviderOptions {\n /** Clef Cloud API endpoint. Falls back to CLEF_ENDPOINT env var. */\n endpoint: string;\n /** Bearer token for Cloud API auth. Falls back to CLEF_SERVICE_TOKEN env var. */\n token?: string;\n}\n\n/** Error thrown by ClefClient and CloudKmsProvider. */\nexport class ClefClientError extends Error {\n constructor(\n message: string,\n public readonly statusCode?: number,\n public readonly fix?: string,\n ) {\n super(message);\n this.name = \"ClefClientError\";\n }\n}\n", "import { ClefClientError } from \"./types\";\n\n/**\n * Resolve a service token from an explicit value or CLEF_SERVICE_TOKEN env var.\n */\nexport function resolveToken(explicit?: string): string {\n if (explicit) return explicit;\n\n if (typeof process !== \"undefined\" && process.env?.CLEF_SERVICE_TOKEN) {\n return process.env.CLEF_SERVICE_TOKEN;\n }\n\n throw new ClefClientError(\n \"No service token configured\",\n undefined,\n \"Set CLEF_SERVICE_TOKEN or pass token in options.\",\n );\n}\n\n/**\n * Resolve the serve endpoint from an explicit value or CLEF_ENDPOINT env var.\n */\nexport function resolveEndpoint(explicit?: string): string {\n if (explicit) return explicit;\n\n if (typeof process !== \"undefined\" && process.env?.CLEF_ENDPOINT) {\n return process.env.CLEF_ENDPOINT;\n }\n\n return \"http://127.0.0.1:7779\";\n}\n", "import { ClefClientError } from \"./types\";\n\ninterface RequestOptions {\n method: \"GET\" | \"POST\";\n path: string;\n body?: unknown;\n token: string;\n fetchFn: typeof globalThis.fetch;\n}\n\n/**\n * Make an authenticated HTTP request to a Clef endpoint.\n * Handles the { data, success, message } envelope and retries once on 5xx.\n */\nexport async function request<T>(baseUrl: string, opts: RequestOptions): Promise<T> {\n const url = `${baseUrl}${opts.path}`;\n const headers: Record<string, string> = {\n Authorization: `Bearer ${opts.token}`,\n Accept: \"application/json\",\n };\n if (opts.body !== undefined) {\n headers[\"Content-Type\"] = \"application/json\";\n }\n\n const init: RequestInit = {\n method: opts.method,\n headers,\n body: opts.body !== undefined ? JSON.stringify(opts.body) : undefined,\n };\n\n let response: Response;\n try {\n response = await opts.fetchFn(url, init);\n } catch (err) {\n // Retry once on network error\n try {\n response = await opts.fetchFn(url, init);\n } catch {\n throw new ClefClientError(\n `Connection failed: ${(err as Error).message}`,\n undefined,\n \"Is the endpoint reachable? Check your CLEF_ENDPOINT setting.\",\n );\n }\n }\n\n // Retry once on 5xx\n if (response.status >= 500) {\n response = await opts.fetchFn(url, init);\n }\n\n if (response.status === 401) {\n throw new ClefClientError(\"Authentication failed\", 401, \"Check your CLEF_SERVICE_TOKEN.\");\n }\n\n if (response.status === 503) {\n throw new ClefClientError(\"Secrets expired or not loaded\", 503, \"Check the agent logs.\");\n }\n\n if (!response.ok) {\n const text = await response.text().catch(() => \"\");\n throw new ClefClientError(\n `HTTP ${response.status}: ${text || response.statusText}`,\n response.status,\n );\n }\n\n const json = await response.json();\n\n // Unwrap { data, success, message } envelope if present\n if (json && typeof json === \"object\" && \"success\" in json) {\n if (!json.success) {\n throw new ClefClientError(json.message || \"Request failed\", response.status);\n }\n return json.data as T;\n }\n\n return json as T;\n}\n", "import { ClefClientOptions } from \"./types\";\nimport { resolveToken, resolveEndpoint } from \"./auth\";\nimport { request } from \"./http\";\n\ninterface CacheEntry {\n secrets: Record<string, string>;\n fetchedAt: number;\n}\n\n/**\n * Lightweight client for consuming Clef secrets from a serve endpoint.\n *\n * ```typescript\n * const secrets = new ClefClient();\n * const dbUrl = await secrets.get(\"DB_URL\");\n * ```\n */\nexport class ClefClient {\n private readonly endpoint: string;\n private readonly token: string;\n private readonly envFallback: boolean;\n private readonly cacheTtlMs: number;\n private readonly fetchFn: typeof globalThis.fetch;\n private cache: CacheEntry | null = null;\n\n constructor(options?: ClefClientOptions) {\n this.endpoint = resolveEndpoint(options?.endpoint);\n this.token = resolveToken(options?.token);\n this.envFallback = options?.envFallback ?? true;\n this.cacheTtlMs = options?.cacheTtlMs ?? 0;\n this.fetchFn = options?.fetch ?? globalThis.fetch;\n }\n\n /** Get a single secret by key. Falls back to env var if configured. */\n async get(key: string): Promise<string | undefined> {\n const all = await this.fetchSecrets();\n const value = all[key];\n if (value !== undefined) return value;\n\n if (this.envFallback && typeof process !== \"undefined\") {\n return process.env[key];\n }\n\n return undefined;\n }\n\n /** Get all secrets as a key-value map. */\n async getAll(): Promise<Record<string, string>> {\n return this.fetchSecrets();\n }\n\n /** List available key names. */\n async keys(): Promise<string[]> {\n const all = await this.fetchSecrets();\n return Object.keys(all);\n }\n\n /** Check if the serve endpoint is reachable. */\n async health(): Promise<boolean> {\n try {\n const response = await this.fetchFn(`${this.endpoint}/v1/health`);\n return response.ok;\n } catch {\n return false;\n }\n }\n\n private async fetchSecrets(): Promise<Record<string, string>> {\n if (this.cacheTtlMs > 0 && this.cache) {\n const age = Date.now() - this.cache.fetchedAt;\n if (age < this.cacheTtlMs) {\n return this.cache.secrets;\n }\n }\n\n const secrets = await request<Record<string, string>>(this.endpoint, {\n method: \"GET\",\n path: \"/v1/secrets\",\n token: this.token,\n fetchFn: this.fetchFn,\n });\n\n if (this.cacheTtlMs > 0) {\n this.cache = { secrets, fetchedAt: Date.now() };\n }\n\n return secrets;\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
package/dist/index.mjs ADDED
@@ -0,0 +1,154 @@
1
+ // src/types.ts
2
+ var ClefClientError = class extends Error {
3
+ constructor(message, statusCode, fix) {
4
+ super(message);
5
+ this.statusCode = statusCode;
6
+ this.fix = fix;
7
+ this.name = "ClefClientError";
8
+ }
9
+ statusCode;
10
+ fix;
11
+ };
12
+
13
+ // src/auth.ts
14
+ function resolveToken(explicit) {
15
+ if (explicit) return explicit;
16
+ if (typeof process !== "undefined" && process.env?.CLEF_SERVICE_TOKEN) {
17
+ return process.env.CLEF_SERVICE_TOKEN;
18
+ }
19
+ throw new ClefClientError(
20
+ "No service token configured",
21
+ void 0,
22
+ "Set CLEF_SERVICE_TOKEN or pass token in options."
23
+ );
24
+ }
25
+ function resolveEndpoint(explicit) {
26
+ if (explicit) return explicit;
27
+ if (typeof process !== "undefined" && process.env?.CLEF_ENDPOINT) {
28
+ return process.env.CLEF_ENDPOINT;
29
+ }
30
+ return "http://127.0.0.1:7779";
31
+ }
32
+
33
+ // src/http.ts
34
+ async function request(baseUrl, opts) {
35
+ const url = `${baseUrl}${opts.path}`;
36
+ const headers = {
37
+ Authorization: `Bearer ${opts.token}`,
38
+ Accept: "application/json"
39
+ };
40
+ if (opts.body !== void 0) {
41
+ headers["Content-Type"] = "application/json";
42
+ }
43
+ const init = {
44
+ method: opts.method,
45
+ headers,
46
+ body: opts.body !== void 0 ? JSON.stringify(opts.body) : void 0
47
+ };
48
+ let response;
49
+ try {
50
+ response = await opts.fetchFn(url, init);
51
+ } catch (err) {
52
+ try {
53
+ response = await opts.fetchFn(url, init);
54
+ } catch {
55
+ throw new ClefClientError(
56
+ `Connection failed: ${err.message}`,
57
+ void 0,
58
+ "Is the endpoint reachable? Check your CLEF_ENDPOINT setting."
59
+ );
60
+ }
61
+ }
62
+ if (response.status >= 500) {
63
+ response = await opts.fetchFn(url, init);
64
+ }
65
+ if (response.status === 401) {
66
+ throw new ClefClientError("Authentication failed", 401, "Check your CLEF_SERVICE_TOKEN.");
67
+ }
68
+ if (response.status === 503) {
69
+ throw new ClefClientError("Secrets expired or not loaded", 503, "Check the agent logs.");
70
+ }
71
+ if (!response.ok) {
72
+ const text = await response.text().catch(() => "");
73
+ throw new ClefClientError(
74
+ `HTTP ${response.status}: ${text || response.statusText}`,
75
+ response.status
76
+ );
77
+ }
78
+ const json = await response.json();
79
+ if (json && typeof json === "object" && "success" in json) {
80
+ if (!json.success) {
81
+ throw new ClefClientError(json.message || "Request failed", response.status);
82
+ }
83
+ return json.data;
84
+ }
85
+ return json;
86
+ }
87
+
88
+ // src/clef-client.ts
89
+ var ClefClient = class {
90
+ endpoint;
91
+ token;
92
+ envFallback;
93
+ cacheTtlMs;
94
+ fetchFn;
95
+ cache = null;
96
+ constructor(options) {
97
+ this.endpoint = resolveEndpoint(options?.endpoint);
98
+ this.token = resolveToken(options?.token);
99
+ this.envFallback = options?.envFallback ?? true;
100
+ this.cacheTtlMs = options?.cacheTtlMs ?? 0;
101
+ this.fetchFn = options?.fetch ?? globalThis.fetch;
102
+ }
103
+ /** Get a single secret by key. Falls back to env var if configured. */
104
+ async get(key) {
105
+ const all = await this.fetchSecrets();
106
+ const value = all[key];
107
+ if (value !== void 0) return value;
108
+ if (this.envFallback && typeof process !== "undefined") {
109
+ return process.env[key];
110
+ }
111
+ return void 0;
112
+ }
113
+ /** Get all secrets as a key-value map. */
114
+ async getAll() {
115
+ return this.fetchSecrets();
116
+ }
117
+ /** List available key names. */
118
+ async keys() {
119
+ const all = await this.fetchSecrets();
120
+ return Object.keys(all);
121
+ }
122
+ /** Check if the serve endpoint is reachable. */
123
+ async health() {
124
+ try {
125
+ const response = await this.fetchFn(`${this.endpoint}/v1/health`);
126
+ return response.ok;
127
+ } catch {
128
+ return false;
129
+ }
130
+ }
131
+ async fetchSecrets() {
132
+ if (this.cacheTtlMs > 0 && this.cache) {
133
+ const age = Date.now() - this.cache.fetchedAt;
134
+ if (age < this.cacheTtlMs) {
135
+ return this.cache.secrets;
136
+ }
137
+ }
138
+ const secrets = await request(this.endpoint, {
139
+ method: "GET",
140
+ path: "/v1/secrets",
141
+ token: this.token,
142
+ fetchFn: this.fetchFn
143
+ });
144
+ if (this.cacheTtlMs > 0) {
145
+ this.cache = { secrets, fetchedAt: Date.now() };
146
+ }
147
+ return secrets;
148
+ }
149
+ };
150
+ export {
151
+ ClefClient,
152
+ ClefClientError
153
+ };
154
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/types.ts", "../src/auth.ts", "../src/http.ts", "../src/clef-client.ts"],
4
+ "sourcesContent": ["/** Configuration for the ClefClient app SDK. */\nexport interface ClefClientOptions {\n /** Base URL of the clef serve endpoint. Default: http://127.0.0.1:7779 */\n endpoint?: string;\n /** Bearer token for authentication. Falls back to CLEF_SERVICE_TOKEN env var. */\n token?: string;\n /** Fall back to process.env when a key is not found. Default: true */\n envFallback?: boolean;\n /** In-memory cache TTL in milliseconds. 0 = no caching. Default: 0 */\n cacheTtlMs?: number;\n /** Custom fetch implementation (for testing or edge runtimes). */\n fetch?: typeof globalThis.fetch;\n}\n\n/** Configuration for the Cloud KMS provider. */\nexport interface CloudKmsProviderOptions {\n /** Clef Cloud API endpoint. Falls back to CLEF_ENDPOINT env var. */\n endpoint: string;\n /** Bearer token for Cloud API auth. Falls back to CLEF_SERVICE_TOKEN env var. */\n token?: string;\n}\n\n/** Error thrown by ClefClient and CloudKmsProvider. */\nexport class ClefClientError extends Error {\n constructor(\n message: string,\n public readonly statusCode?: number,\n public readonly fix?: string,\n ) {\n super(message);\n this.name = \"ClefClientError\";\n }\n}\n", "import { ClefClientError } from \"./types\";\n\n/**\n * Resolve a service token from an explicit value or CLEF_SERVICE_TOKEN env var.\n */\nexport function resolveToken(explicit?: string): string {\n if (explicit) return explicit;\n\n if (typeof process !== \"undefined\" && process.env?.CLEF_SERVICE_TOKEN) {\n return process.env.CLEF_SERVICE_TOKEN;\n }\n\n throw new ClefClientError(\n \"No service token configured\",\n undefined,\n \"Set CLEF_SERVICE_TOKEN or pass token in options.\",\n );\n}\n\n/**\n * Resolve the serve endpoint from an explicit value or CLEF_ENDPOINT env var.\n */\nexport function resolveEndpoint(explicit?: string): string {\n if (explicit) return explicit;\n\n if (typeof process !== \"undefined\" && process.env?.CLEF_ENDPOINT) {\n return process.env.CLEF_ENDPOINT;\n }\n\n return \"http://127.0.0.1:7779\";\n}\n", "import { ClefClientError } from \"./types\";\n\ninterface RequestOptions {\n method: \"GET\" | \"POST\";\n path: string;\n body?: unknown;\n token: string;\n fetchFn: typeof globalThis.fetch;\n}\n\n/**\n * Make an authenticated HTTP request to a Clef endpoint.\n * Handles the { data, success, message } envelope and retries once on 5xx.\n */\nexport async function request<T>(baseUrl: string, opts: RequestOptions): Promise<T> {\n const url = `${baseUrl}${opts.path}`;\n const headers: Record<string, string> = {\n Authorization: `Bearer ${opts.token}`,\n Accept: \"application/json\",\n };\n if (opts.body !== undefined) {\n headers[\"Content-Type\"] = \"application/json\";\n }\n\n const init: RequestInit = {\n method: opts.method,\n headers,\n body: opts.body !== undefined ? JSON.stringify(opts.body) : undefined,\n };\n\n let response: Response;\n try {\n response = await opts.fetchFn(url, init);\n } catch (err) {\n // Retry once on network error\n try {\n response = await opts.fetchFn(url, init);\n } catch {\n throw new ClefClientError(\n `Connection failed: ${(err as Error).message}`,\n undefined,\n \"Is the endpoint reachable? Check your CLEF_ENDPOINT setting.\",\n );\n }\n }\n\n // Retry once on 5xx\n if (response.status >= 500) {\n response = await opts.fetchFn(url, init);\n }\n\n if (response.status === 401) {\n throw new ClefClientError(\"Authentication failed\", 401, \"Check your CLEF_SERVICE_TOKEN.\");\n }\n\n if (response.status === 503) {\n throw new ClefClientError(\"Secrets expired or not loaded\", 503, \"Check the agent logs.\");\n }\n\n if (!response.ok) {\n const text = await response.text().catch(() => \"\");\n throw new ClefClientError(\n `HTTP ${response.status}: ${text || response.statusText}`,\n response.status,\n );\n }\n\n const json = await response.json();\n\n // Unwrap { data, success, message } envelope if present\n if (json && typeof json === \"object\" && \"success\" in json) {\n if (!json.success) {\n throw new ClefClientError(json.message || \"Request failed\", response.status);\n }\n return json.data as T;\n }\n\n return json as T;\n}\n", "import { ClefClientOptions } from \"./types\";\nimport { resolveToken, resolveEndpoint } from \"./auth\";\nimport { request } from \"./http\";\n\ninterface CacheEntry {\n secrets: Record<string, string>;\n fetchedAt: number;\n}\n\n/**\n * Lightweight client for consuming Clef secrets from a serve endpoint.\n *\n * ```typescript\n * const secrets = new ClefClient();\n * const dbUrl = await secrets.get(\"DB_URL\");\n * ```\n */\nexport class ClefClient {\n private readonly endpoint: string;\n private readonly token: string;\n private readonly envFallback: boolean;\n private readonly cacheTtlMs: number;\n private readonly fetchFn: typeof globalThis.fetch;\n private cache: CacheEntry | null = null;\n\n constructor(options?: ClefClientOptions) {\n this.endpoint = resolveEndpoint(options?.endpoint);\n this.token = resolveToken(options?.token);\n this.envFallback = options?.envFallback ?? true;\n this.cacheTtlMs = options?.cacheTtlMs ?? 0;\n this.fetchFn = options?.fetch ?? globalThis.fetch;\n }\n\n /** Get a single secret by key. Falls back to env var if configured. */\n async get(key: string): Promise<string | undefined> {\n const all = await this.fetchSecrets();\n const value = all[key];\n if (value !== undefined) return value;\n\n if (this.envFallback && typeof process !== \"undefined\") {\n return process.env[key];\n }\n\n return undefined;\n }\n\n /** Get all secrets as a key-value map. */\n async getAll(): Promise<Record<string, string>> {\n return this.fetchSecrets();\n }\n\n /** List available key names. */\n async keys(): Promise<string[]> {\n const all = await this.fetchSecrets();\n return Object.keys(all);\n }\n\n /** Check if the serve endpoint is reachable. */\n async health(): Promise<boolean> {\n try {\n const response = await this.fetchFn(`${this.endpoint}/v1/health`);\n return response.ok;\n } catch {\n return false;\n }\n }\n\n private async fetchSecrets(): Promise<Record<string, string>> {\n if (this.cacheTtlMs > 0 && this.cache) {\n const age = Date.now() - this.cache.fetchedAt;\n if (age < this.cacheTtlMs) {\n return this.cache.secrets;\n }\n }\n\n const secrets = await request<Record<string, string>>(this.endpoint, {\n method: \"GET\",\n path: \"/v1/secrets\",\n token: this.token,\n fetchFn: this.fetchFn,\n });\n\n if (this.cacheTtlMs > 0) {\n this.cache = { secrets, fetchedAt: Date.now() };\n }\n\n return secrets;\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
package/dist/kms.d.mts ADDED
@@ -0,0 +1,4 @@
1
+ export { CloudKmsProvider } from "./cloud-kms-provider";
2
+ export { ClefClientError } from "./types";
3
+ export type { CloudKmsProviderOptions } from "./types";
4
+ //# sourceMappingURL=kms.d.ts.map
package/dist/kms.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ export { CloudKmsProvider } from "./cloud-kms-provider";
2
+ export { ClefClientError } from "./types";
3
+ export type { CloudKmsProviderOptions } from "./types";
4
+ //# sourceMappingURL=kms.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kms.d.ts","sourceRoot":"","sources":["../src/kms.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC1C,YAAY,EAAE,uBAAuB,EAAE,MAAM,SAAS,CAAC"}
package/dist/kms.js ADDED
@@ -0,0 +1,140 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/kms.ts
21
+ var kms_exports = {};
22
+ __export(kms_exports, {
23
+ ClefClientError: () => ClefClientError,
24
+ CloudKmsProvider: () => CloudKmsProvider
25
+ });
26
+ module.exports = __toCommonJS(kms_exports);
27
+
28
+ // src/types.ts
29
+ var ClefClientError = class extends Error {
30
+ constructor(message, statusCode, fix) {
31
+ super(message);
32
+ this.statusCode = statusCode;
33
+ this.fix = fix;
34
+ this.name = "ClefClientError";
35
+ }
36
+ statusCode;
37
+ fix;
38
+ };
39
+
40
+ // src/auth.ts
41
+ function resolveToken(explicit) {
42
+ if (explicit) return explicit;
43
+ if (typeof process !== "undefined" && process.env?.CLEF_SERVICE_TOKEN) {
44
+ return process.env.CLEF_SERVICE_TOKEN;
45
+ }
46
+ throw new ClefClientError(
47
+ "No service token configured",
48
+ void 0,
49
+ "Set CLEF_SERVICE_TOKEN or pass token in options."
50
+ );
51
+ }
52
+
53
+ // src/http.ts
54
+ async function request(baseUrl, opts) {
55
+ const url = `${baseUrl}${opts.path}`;
56
+ const headers = {
57
+ Authorization: `Bearer ${opts.token}`,
58
+ Accept: "application/json"
59
+ };
60
+ if (opts.body !== void 0) {
61
+ headers["Content-Type"] = "application/json";
62
+ }
63
+ const init = {
64
+ method: opts.method,
65
+ headers,
66
+ body: opts.body !== void 0 ? JSON.stringify(opts.body) : void 0
67
+ };
68
+ let response;
69
+ try {
70
+ response = await opts.fetchFn(url, init);
71
+ } catch (err) {
72
+ try {
73
+ response = await opts.fetchFn(url, init);
74
+ } catch {
75
+ throw new ClefClientError(
76
+ `Connection failed: ${err.message}`,
77
+ void 0,
78
+ "Is the endpoint reachable? Check your CLEF_ENDPOINT setting."
79
+ );
80
+ }
81
+ }
82
+ if (response.status >= 500) {
83
+ response = await opts.fetchFn(url, init);
84
+ }
85
+ if (response.status === 401) {
86
+ throw new ClefClientError("Authentication failed", 401, "Check your CLEF_SERVICE_TOKEN.");
87
+ }
88
+ if (response.status === 503) {
89
+ throw new ClefClientError("Secrets expired or not loaded", 503, "Check the agent logs.");
90
+ }
91
+ if (!response.ok) {
92
+ const text = await response.text().catch(() => "");
93
+ throw new ClefClientError(
94
+ `HTTP ${response.status}: ${text || response.statusText}`,
95
+ response.status
96
+ );
97
+ }
98
+ const json = await response.json();
99
+ if (json && typeof json === "object" && "success" in json) {
100
+ if (!json.success) {
101
+ throw new ClefClientError(json.message || "Request failed", response.status);
102
+ }
103
+ return json.data;
104
+ }
105
+ return json;
106
+ }
107
+
108
+ // src/cloud-kms-provider.ts
109
+ var CloudKmsProvider = class {
110
+ endpoint;
111
+ token;
112
+ constructor(options) {
113
+ this.endpoint = options.endpoint;
114
+ this.token = resolveToken(options.token);
115
+ }
116
+ async wrap(_keyId, _plaintext) {
117
+ throw new ClefClientError(
118
+ "CloudKmsProvider.wrap() is not supported. Use the keyservice sidecar for encryption."
119
+ );
120
+ }
121
+ async unwrap(keyId, wrappedKey, _algorithm) {
122
+ const result = await request(this.endpoint, {
123
+ method: "POST",
124
+ path: "/api/v1/cloud/kms/decrypt",
125
+ body: {
126
+ keyArn: keyId,
127
+ ciphertext: wrappedKey.toString("base64")
128
+ },
129
+ token: this.token,
130
+ fetchFn: globalThis.fetch
131
+ });
132
+ return Buffer.from(result.plaintext, "base64");
133
+ }
134
+ };
135
+ // Annotate the CommonJS export names for ESM import in node:
136
+ 0 && (module.exports = {
137
+ ClefClientError,
138
+ CloudKmsProvider
139
+ });
140
+ //# sourceMappingURL=kms.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/kms.ts", "../src/types.ts", "../src/auth.ts", "../src/http.ts", "../src/cloud-kms-provider.ts"],
4
+ "sourcesContent": ["export { CloudKmsProvider } from \"./cloud-kms-provider\";\nexport { ClefClientError } from \"./types\";\nexport type { CloudKmsProviderOptions } from \"./types\";\n", "/** Configuration for the ClefClient app SDK. */\nexport interface ClefClientOptions {\n /** Base URL of the clef serve endpoint. Default: http://127.0.0.1:7779 */\n endpoint?: string;\n /** Bearer token for authentication. Falls back to CLEF_SERVICE_TOKEN env var. */\n token?: string;\n /** Fall back to process.env when a key is not found. Default: true */\n envFallback?: boolean;\n /** In-memory cache TTL in milliseconds. 0 = no caching. Default: 0 */\n cacheTtlMs?: number;\n /** Custom fetch implementation (for testing or edge runtimes). */\n fetch?: typeof globalThis.fetch;\n}\n\n/** Configuration for the Cloud KMS provider. */\nexport interface CloudKmsProviderOptions {\n /** Clef Cloud API endpoint. Falls back to CLEF_ENDPOINT env var. */\n endpoint: string;\n /** Bearer token for Cloud API auth. Falls back to CLEF_SERVICE_TOKEN env var. */\n token?: string;\n}\n\n/** Error thrown by ClefClient and CloudKmsProvider. */\nexport class ClefClientError extends Error {\n constructor(\n message: string,\n public readonly statusCode?: number,\n public readonly fix?: string,\n ) {\n super(message);\n this.name = \"ClefClientError\";\n }\n}\n", "import { ClefClientError } from \"./types\";\n\n/**\n * Resolve a service token from an explicit value or CLEF_SERVICE_TOKEN env var.\n */\nexport function resolveToken(explicit?: string): string {\n if (explicit) return explicit;\n\n if (typeof process !== \"undefined\" && process.env?.CLEF_SERVICE_TOKEN) {\n return process.env.CLEF_SERVICE_TOKEN;\n }\n\n throw new ClefClientError(\n \"No service token configured\",\n undefined,\n \"Set CLEF_SERVICE_TOKEN or pass token in options.\",\n );\n}\n\n/**\n * Resolve the serve endpoint from an explicit value or CLEF_ENDPOINT env var.\n */\nexport function resolveEndpoint(explicit?: string): string {\n if (explicit) return explicit;\n\n if (typeof process !== \"undefined\" && process.env?.CLEF_ENDPOINT) {\n return process.env.CLEF_ENDPOINT;\n }\n\n return \"http://127.0.0.1:7779\";\n}\n", "import { ClefClientError } from \"./types\";\n\ninterface RequestOptions {\n method: \"GET\" | \"POST\";\n path: string;\n body?: unknown;\n token: string;\n fetchFn: typeof globalThis.fetch;\n}\n\n/**\n * Make an authenticated HTTP request to a Clef endpoint.\n * Handles the { data, success, message } envelope and retries once on 5xx.\n */\nexport async function request<T>(baseUrl: string, opts: RequestOptions): Promise<T> {\n const url = `${baseUrl}${opts.path}`;\n const headers: Record<string, string> = {\n Authorization: `Bearer ${opts.token}`,\n Accept: \"application/json\",\n };\n if (opts.body !== undefined) {\n headers[\"Content-Type\"] = \"application/json\";\n }\n\n const init: RequestInit = {\n method: opts.method,\n headers,\n body: opts.body !== undefined ? JSON.stringify(opts.body) : undefined,\n };\n\n let response: Response;\n try {\n response = await opts.fetchFn(url, init);\n } catch (err) {\n // Retry once on network error\n try {\n response = await opts.fetchFn(url, init);\n } catch {\n throw new ClefClientError(\n `Connection failed: ${(err as Error).message}`,\n undefined,\n \"Is the endpoint reachable? Check your CLEF_ENDPOINT setting.\",\n );\n }\n }\n\n // Retry once on 5xx\n if (response.status >= 500) {\n response = await opts.fetchFn(url, init);\n }\n\n if (response.status === 401) {\n throw new ClefClientError(\"Authentication failed\", 401, \"Check your CLEF_SERVICE_TOKEN.\");\n }\n\n if (response.status === 503) {\n throw new ClefClientError(\"Secrets expired or not loaded\", 503, \"Check the agent logs.\");\n }\n\n if (!response.ok) {\n const text = await response.text().catch(() => \"\");\n throw new ClefClientError(\n `HTTP ${response.status}: ${text || response.statusText}`,\n response.status,\n );\n }\n\n const json = await response.json();\n\n // Unwrap { data, success, message } envelope if present\n if (json && typeof json === \"object\" && \"success\" in json) {\n if (!json.success) {\n throw new ClefClientError(json.message || \"Request failed\", response.status);\n }\n return json.data as T;\n }\n\n return json as T;\n}\n", "import { CloudKmsProviderOptions, ClefClientError } from \"./types\";\nimport { resolveToken } from \"./auth\";\nimport { request } from \"./http\";\n\n/**\n * Clef Cloud KMS provider.\n *\n * Implements the KmsProvider interface (structurally \u2014 no import needed)\n * for use with @clef-sh/runtime's createKmsProvider factory.\n *\n * Only `unwrap()` is supported. Encryption (wrap) is handled by the\n * keyservice sidecar during `clef pack`.\n */\nexport class CloudKmsProvider {\n private readonly endpoint: string;\n private readonly token: string;\n\n constructor(options: CloudKmsProviderOptions) {\n this.endpoint = options.endpoint;\n this.token = resolveToken(options.token);\n }\n\n async wrap(\n _keyId: string,\n _plaintext: Buffer,\n ): Promise<{ wrappedKey: Buffer; algorithm: string }> {\n throw new ClefClientError(\n \"CloudKmsProvider.wrap() is not supported. Use the keyservice sidecar for encryption.\",\n );\n }\n\n async unwrap(keyId: string, wrappedKey: Buffer, _algorithm: string): Promise<Buffer> {\n const result = await request<{ plaintext: string }>(this.endpoint, {\n method: \"POST\",\n path: \"/api/v1/cloud/kms/decrypt\",\n body: {\n keyArn: keyId,\n ciphertext: wrappedKey.toString(\"base64\"),\n },\n token: this.token,\n fetchFn: globalThis.fetch,\n });\n\n return Buffer.from(result.plaintext, \"base64\");\n }\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACuBO,IAAM,kBAAN,cAA8B,MAAM;AAAA,EACzC,YACE,SACgB,YACA,KAChB;AACA,UAAM,OAAO;AAHG;AACA;AAGhB,SAAK,OAAO;AAAA,EACd;AAAA,EALkB;AAAA,EACA;AAKpB;;;AC3BO,SAAS,aAAa,UAA2B;AACtD,MAAI,SAAU,QAAO;AAErB,MAAI,OAAO,YAAY,eAAe,QAAQ,KAAK,oBAAoB;AACrE,WAAO,QAAQ,IAAI;AAAA,EACrB;AAEA,QAAM,IAAI;AAAA,IACR;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;ACHA,eAAsB,QAAW,SAAiB,MAAkC;AAClF,QAAM,MAAM,GAAG,OAAO,GAAG,KAAK,IAAI;AAClC,QAAM,UAAkC;AAAA,IACtC,eAAe,UAAU,KAAK,KAAK;AAAA,IACnC,QAAQ;AAAA,EACV;AACA,MAAI,KAAK,SAAS,QAAW;AAC3B,YAAQ,cAAc,IAAI;AAAA,EAC5B;AAEA,QAAM,OAAoB;AAAA,IACxB,QAAQ,KAAK;AAAA,IACb;AAAA,IACA,MAAM,KAAK,SAAS,SAAY,KAAK,UAAU,KAAK,IAAI,IAAI;AAAA,EAC9D;AAEA,MAAI;AACJ,MAAI;AACF,eAAW,MAAM,KAAK,QAAQ,KAAK,IAAI;AAAA,EACzC,SAAS,KAAK;AAEZ,QAAI;AACF,iBAAW,MAAM,KAAK,QAAQ,KAAK,IAAI;AAAA,IACzC,QAAQ;AACN,YAAM,IAAI;AAAA,QACR,sBAAuB,IAAc,OAAO;AAAA,QAC5C;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAGA,MAAI,SAAS,UAAU,KAAK;AAC1B,eAAW,MAAM,KAAK,QAAQ,KAAK,IAAI;AAAA,EACzC;AAEA,MAAI,SAAS,WAAW,KAAK;AAC3B,UAAM,IAAI,gBAAgB,yBAAyB,KAAK,gCAAgC;AAAA,EAC1F;AAEA,MAAI,SAAS,WAAW,KAAK;AAC3B,UAAM,IAAI,gBAAgB,iCAAiC,KAAK,uBAAuB;AAAA,EACzF;AAEA,MAAI,CAAC,SAAS,IAAI;AAChB,UAAM,OAAO,MAAM,SAAS,KAAK,EAAE,MAAM,MAAM,EAAE;AACjD,UAAM,IAAI;AAAA,MACR,QAAQ,SAAS,MAAM,KAAK,QAAQ,SAAS,UAAU;AAAA,MACvD,SAAS;AAAA,IACX;AAAA,EACF;AAEA,QAAM,OAAO,MAAM,SAAS,KAAK;AAGjC,MAAI,QAAQ,OAAO,SAAS,YAAY,aAAa,MAAM;AACzD,QAAI,CAAC,KAAK,SAAS;AACjB,YAAM,IAAI,gBAAgB,KAAK,WAAW,kBAAkB,SAAS,MAAM;AAAA,IAC7E;AACA,WAAO,KAAK;AAAA,EACd;AAEA,SAAO;AACT;;;ACjEO,IAAM,mBAAN,MAAuB;AAAA,EACX;AAAA,EACA;AAAA,EAEjB,YAAY,SAAkC;AAC5C,SAAK,WAAW,QAAQ;AACxB,SAAK,QAAQ,aAAa,QAAQ,KAAK;AAAA,EACzC;AAAA,EAEA,MAAM,KACJ,QACA,YACoD;AACpD,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,OAAO,OAAe,YAAoB,YAAqC;AACnF,UAAM,SAAS,MAAM,QAA+B,KAAK,UAAU;AAAA,MACjE,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,MAAM;AAAA,QACJ,QAAQ;AAAA,QACR,YAAY,WAAW,SAAS,QAAQ;AAAA,MAC1C;AAAA,MACA,OAAO,KAAK;AAAA,MACZ,SAAS,WAAW;AAAA,IACtB,CAAC;AAED,WAAO,OAAO,KAAK,OAAO,WAAW,QAAQ;AAAA,EAC/C;AACF;",
6
+ "names": []
7
+ }
package/dist/kms.mjs ADDED
@@ -0,0 +1,112 @@
1
+ // src/types.ts
2
+ var ClefClientError = class extends Error {
3
+ constructor(message, statusCode, fix) {
4
+ super(message);
5
+ this.statusCode = statusCode;
6
+ this.fix = fix;
7
+ this.name = "ClefClientError";
8
+ }
9
+ statusCode;
10
+ fix;
11
+ };
12
+
13
+ // src/auth.ts
14
+ function resolveToken(explicit) {
15
+ if (explicit) return explicit;
16
+ if (typeof process !== "undefined" && process.env?.CLEF_SERVICE_TOKEN) {
17
+ return process.env.CLEF_SERVICE_TOKEN;
18
+ }
19
+ throw new ClefClientError(
20
+ "No service token configured",
21
+ void 0,
22
+ "Set CLEF_SERVICE_TOKEN or pass token in options."
23
+ );
24
+ }
25
+
26
+ // src/http.ts
27
+ async function request(baseUrl, opts) {
28
+ const url = `${baseUrl}${opts.path}`;
29
+ const headers = {
30
+ Authorization: `Bearer ${opts.token}`,
31
+ Accept: "application/json"
32
+ };
33
+ if (opts.body !== void 0) {
34
+ headers["Content-Type"] = "application/json";
35
+ }
36
+ const init = {
37
+ method: opts.method,
38
+ headers,
39
+ body: opts.body !== void 0 ? JSON.stringify(opts.body) : void 0
40
+ };
41
+ let response;
42
+ try {
43
+ response = await opts.fetchFn(url, init);
44
+ } catch (err) {
45
+ try {
46
+ response = await opts.fetchFn(url, init);
47
+ } catch {
48
+ throw new ClefClientError(
49
+ `Connection failed: ${err.message}`,
50
+ void 0,
51
+ "Is the endpoint reachable? Check your CLEF_ENDPOINT setting."
52
+ );
53
+ }
54
+ }
55
+ if (response.status >= 500) {
56
+ response = await opts.fetchFn(url, init);
57
+ }
58
+ if (response.status === 401) {
59
+ throw new ClefClientError("Authentication failed", 401, "Check your CLEF_SERVICE_TOKEN.");
60
+ }
61
+ if (response.status === 503) {
62
+ throw new ClefClientError("Secrets expired or not loaded", 503, "Check the agent logs.");
63
+ }
64
+ if (!response.ok) {
65
+ const text = await response.text().catch(() => "");
66
+ throw new ClefClientError(
67
+ `HTTP ${response.status}: ${text || response.statusText}`,
68
+ response.status
69
+ );
70
+ }
71
+ const json = await response.json();
72
+ if (json && typeof json === "object" && "success" in json) {
73
+ if (!json.success) {
74
+ throw new ClefClientError(json.message || "Request failed", response.status);
75
+ }
76
+ return json.data;
77
+ }
78
+ return json;
79
+ }
80
+
81
+ // src/cloud-kms-provider.ts
82
+ var CloudKmsProvider = class {
83
+ endpoint;
84
+ token;
85
+ constructor(options) {
86
+ this.endpoint = options.endpoint;
87
+ this.token = resolveToken(options.token);
88
+ }
89
+ async wrap(_keyId, _plaintext) {
90
+ throw new ClefClientError(
91
+ "CloudKmsProvider.wrap() is not supported. Use the keyservice sidecar for encryption."
92
+ );
93
+ }
94
+ async unwrap(keyId, wrappedKey, _algorithm) {
95
+ const result = await request(this.endpoint, {
96
+ method: "POST",
97
+ path: "/api/v1/cloud/kms/decrypt",
98
+ body: {
99
+ keyArn: keyId,
100
+ ciphertext: wrappedKey.toString("base64")
101
+ },
102
+ token: this.token,
103
+ fetchFn: globalThis.fetch
104
+ });
105
+ return Buffer.from(result.plaintext, "base64");
106
+ }
107
+ };
108
+ export {
109
+ ClefClientError,
110
+ CloudKmsProvider
111
+ };
112
+ //# sourceMappingURL=kms.mjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/types.ts", "../src/auth.ts", "../src/http.ts", "../src/cloud-kms-provider.ts"],
4
+ "sourcesContent": ["/** Configuration for the ClefClient app SDK. */\nexport interface ClefClientOptions {\n /** Base URL of the clef serve endpoint. Default: http://127.0.0.1:7779 */\n endpoint?: string;\n /** Bearer token for authentication. Falls back to CLEF_SERVICE_TOKEN env var. */\n token?: string;\n /** Fall back to process.env when a key is not found. Default: true */\n envFallback?: boolean;\n /** In-memory cache TTL in milliseconds. 0 = no caching. Default: 0 */\n cacheTtlMs?: number;\n /** Custom fetch implementation (for testing or edge runtimes). */\n fetch?: typeof globalThis.fetch;\n}\n\n/** Configuration for the Cloud KMS provider. */\nexport interface CloudKmsProviderOptions {\n /** Clef Cloud API endpoint. Falls back to CLEF_ENDPOINT env var. */\n endpoint: string;\n /** Bearer token for Cloud API auth. Falls back to CLEF_SERVICE_TOKEN env var. */\n token?: string;\n}\n\n/** Error thrown by ClefClient and CloudKmsProvider. */\nexport class ClefClientError extends Error {\n constructor(\n message: string,\n public readonly statusCode?: number,\n public readonly fix?: string,\n ) {\n super(message);\n this.name = \"ClefClientError\";\n }\n}\n", "import { ClefClientError } from \"./types\";\n\n/**\n * Resolve a service token from an explicit value or CLEF_SERVICE_TOKEN env var.\n */\nexport function resolveToken(explicit?: string): string {\n if (explicit) return explicit;\n\n if (typeof process !== \"undefined\" && process.env?.CLEF_SERVICE_TOKEN) {\n return process.env.CLEF_SERVICE_TOKEN;\n }\n\n throw new ClefClientError(\n \"No service token configured\",\n undefined,\n \"Set CLEF_SERVICE_TOKEN or pass token in options.\",\n );\n}\n\n/**\n * Resolve the serve endpoint from an explicit value or CLEF_ENDPOINT env var.\n */\nexport function resolveEndpoint(explicit?: string): string {\n if (explicit) return explicit;\n\n if (typeof process !== \"undefined\" && process.env?.CLEF_ENDPOINT) {\n return process.env.CLEF_ENDPOINT;\n }\n\n return \"http://127.0.0.1:7779\";\n}\n", "import { ClefClientError } from \"./types\";\n\ninterface RequestOptions {\n method: \"GET\" | \"POST\";\n path: string;\n body?: unknown;\n token: string;\n fetchFn: typeof globalThis.fetch;\n}\n\n/**\n * Make an authenticated HTTP request to a Clef endpoint.\n * Handles the { data, success, message } envelope and retries once on 5xx.\n */\nexport async function request<T>(baseUrl: string, opts: RequestOptions): Promise<T> {\n const url = `${baseUrl}${opts.path}`;\n const headers: Record<string, string> = {\n Authorization: `Bearer ${opts.token}`,\n Accept: \"application/json\",\n };\n if (opts.body !== undefined) {\n headers[\"Content-Type\"] = \"application/json\";\n }\n\n const init: RequestInit = {\n method: opts.method,\n headers,\n body: opts.body !== undefined ? JSON.stringify(opts.body) : undefined,\n };\n\n let response: Response;\n try {\n response = await opts.fetchFn(url, init);\n } catch (err) {\n // Retry once on network error\n try {\n response = await opts.fetchFn(url, init);\n } catch {\n throw new ClefClientError(\n `Connection failed: ${(err as Error).message}`,\n undefined,\n \"Is the endpoint reachable? Check your CLEF_ENDPOINT setting.\",\n );\n }\n }\n\n // Retry once on 5xx\n if (response.status >= 500) {\n response = await opts.fetchFn(url, init);\n }\n\n if (response.status === 401) {\n throw new ClefClientError(\"Authentication failed\", 401, \"Check your CLEF_SERVICE_TOKEN.\");\n }\n\n if (response.status === 503) {\n throw new ClefClientError(\"Secrets expired or not loaded\", 503, \"Check the agent logs.\");\n }\n\n if (!response.ok) {\n const text = await response.text().catch(() => \"\");\n throw new ClefClientError(\n `HTTP ${response.status}: ${text || response.statusText}`,\n response.status,\n );\n }\n\n const json = await response.json();\n\n // Unwrap { data, success, message } envelope if present\n if (json && typeof json === \"object\" && \"success\" in json) {\n if (!json.success) {\n throw new ClefClientError(json.message || \"Request failed\", response.status);\n }\n return json.data as T;\n }\n\n return json as T;\n}\n", "import { CloudKmsProviderOptions, ClefClientError } from \"./types\";\nimport { resolveToken } from \"./auth\";\nimport { request } from \"./http\";\n\n/**\n * Clef Cloud KMS provider.\n *\n * Implements the KmsProvider interface (structurally \u2014 no import needed)\n * for use with @clef-sh/runtime's createKmsProvider factory.\n *\n * Only `unwrap()` is supported. Encryption (wrap) is handled by the\n * keyservice sidecar during `clef pack`.\n */\nexport class CloudKmsProvider {\n private readonly endpoint: string;\n private readonly token: string;\n\n constructor(options: CloudKmsProviderOptions) {\n this.endpoint = options.endpoint;\n this.token = resolveToken(options.token);\n }\n\n async wrap(\n _keyId: string,\n _plaintext: Buffer,\n ): Promise<{ wrappedKey: Buffer; algorithm: string }> {\n throw new ClefClientError(\n \"CloudKmsProvider.wrap() is not supported. Use the keyservice sidecar for encryption.\",\n );\n }\n\n async unwrap(keyId: string, wrappedKey: Buffer, _algorithm: string): Promise<Buffer> {\n const result = await request<{ plaintext: string }>(this.endpoint, {\n method: \"POST\",\n path: \"/api/v1/cloud/kms/decrypt\",\n body: {\n keyArn: keyId,\n ciphertext: wrappedKey.toString(\"base64\"),\n },\n token: this.token,\n fetchFn: globalThis.fetch,\n });\n\n return Buffer.from(result.plaintext, \"base64\");\n }\n}\n"],
5
+ "mappings": ";AAuBO,IAAM,kBAAN,cAA8B,MAAM;AAAA,EACzC,YACE,SACgB,YACA,KAChB;AACA,UAAM,OAAO;AAHG;AACA;AAGhB,SAAK,OAAO;AAAA,EACd;AAAA,EALkB;AAAA,EACA;AAKpB;;;AC3BO,SAAS,aAAa,UAA2B;AACtD,MAAI,SAAU,QAAO;AAErB,MAAI,OAAO,YAAY,eAAe,QAAQ,KAAK,oBAAoB;AACrE,WAAO,QAAQ,IAAI;AAAA,EACrB;AAEA,QAAM,IAAI;AAAA,IACR;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;ACHA,eAAsB,QAAW,SAAiB,MAAkC;AAClF,QAAM,MAAM,GAAG,OAAO,GAAG,KAAK,IAAI;AAClC,QAAM,UAAkC;AAAA,IACtC,eAAe,UAAU,KAAK,KAAK;AAAA,IACnC,QAAQ;AAAA,EACV;AACA,MAAI,KAAK,SAAS,QAAW;AAC3B,YAAQ,cAAc,IAAI;AAAA,EAC5B;AAEA,QAAM,OAAoB;AAAA,IACxB,QAAQ,KAAK;AAAA,IACb;AAAA,IACA,MAAM,KAAK,SAAS,SAAY,KAAK,UAAU,KAAK,IAAI,IAAI;AAAA,EAC9D;AAEA,MAAI;AACJ,MAAI;AACF,eAAW,MAAM,KAAK,QAAQ,KAAK,IAAI;AAAA,EACzC,SAAS,KAAK;AAEZ,QAAI;AACF,iBAAW,MAAM,KAAK,QAAQ,KAAK,IAAI;AAAA,IACzC,QAAQ;AACN,YAAM,IAAI;AAAA,QACR,sBAAuB,IAAc,OAAO;AAAA,QAC5C;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAGA,MAAI,SAAS,UAAU,KAAK;AAC1B,eAAW,MAAM,KAAK,QAAQ,KAAK,IAAI;AAAA,EACzC;AAEA,MAAI,SAAS,WAAW,KAAK;AAC3B,UAAM,IAAI,gBAAgB,yBAAyB,KAAK,gCAAgC;AAAA,EAC1F;AAEA,MAAI,SAAS,WAAW,KAAK;AAC3B,UAAM,IAAI,gBAAgB,iCAAiC,KAAK,uBAAuB;AAAA,EACzF;AAEA,MAAI,CAAC,SAAS,IAAI;AAChB,UAAM,OAAO,MAAM,SAAS,KAAK,EAAE,MAAM,MAAM,EAAE;AACjD,UAAM,IAAI;AAAA,MACR,QAAQ,SAAS,MAAM,KAAK,QAAQ,SAAS,UAAU;AAAA,MACvD,SAAS;AAAA,IACX;AAAA,EACF;AAEA,QAAM,OAAO,MAAM,SAAS,KAAK;AAGjC,MAAI,QAAQ,OAAO,SAAS,YAAY,aAAa,MAAM;AACzD,QAAI,CAAC,KAAK,SAAS;AACjB,YAAM,IAAI,gBAAgB,KAAK,WAAW,kBAAkB,SAAS,MAAM;AAAA,IAC7E;AACA,WAAO,KAAK;AAAA,EACd;AAEA,SAAO;AACT;;;ACjEO,IAAM,mBAAN,MAAuB;AAAA,EACX;AAAA,EACA;AAAA,EAEjB,YAAY,SAAkC;AAC5C,SAAK,WAAW,QAAQ;AACxB,SAAK,QAAQ,aAAa,QAAQ,KAAK;AAAA,EACzC;AAAA,EAEA,MAAM,KACJ,QACA,YACoD;AACpD,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,OAAO,OAAe,YAAoB,YAAqC;AACnF,UAAM,SAAS,MAAM,QAA+B,KAAK,UAAU;AAAA,MACjE,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,MAAM;AAAA,QACJ,QAAQ;AAAA,QACR,YAAY,WAAW,SAAS,QAAQ;AAAA,MAC1C;AAAA,MACA,OAAO,KAAK;AAAA,MACZ,SAAS,WAAW;AAAA,IACtB,CAAC;AAED,WAAO,OAAO,KAAK,OAAO,WAAW,QAAQ;AAAA,EAC/C;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,27 @@
1
+ /** Configuration for the ClefClient app SDK. */
2
+ export interface ClefClientOptions {
3
+ /** Base URL of the clef serve endpoint. Default: http://127.0.0.1:7779 */
4
+ endpoint?: string;
5
+ /** Bearer token for authentication. Falls back to CLEF_SERVICE_TOKEN env var. */
6
+ token?: string;
7
+ /** Fall back to process.env when a key is not found. Default: true */
8
+ envFallback?: boolean;
9
+ /** In-memory cache TTL in milliseconds. 0 = no caching. Default: 0 */
10
+ cacheTtlMs?: number;
11
+ /** Custom fetch implementation (for testing or edge runtimes). */
12
+ fetch?: typeof globalThis.fetch;
13
+ }
14
+ /** Configuration for the Cloud KMS provider. */
15
+ export interface CloudKmsProviderOptions {
16
+ /** Clef Cloud API endpoint. Falls back to CLEF_ENDPOINT env var. */
17
+ endpoint: string;
18
+ /** Bearer token for Cloud API auth. Falls back to CLEF_SERVICE_TOKEN env var. */
19
+ token?: string;
20
+ }
21
+ /** Error thrown by ClefClient and CloudKmsProvider. */
22
+ export declare class ClefClientError extends Error {
23
+ readonly statusCode?: number | undefined;
24
+ readonly fix?: string | undefined;
25
+ constructor(message: string, statusCode?: number | undefined, fix?: string | undefined);
26
+ }
27
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,gDAAgD;AAChD,MAAM,WAAW,iBAAiB;IAChC,0EAA0E;IAC1E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iFAAiF;IACjF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,sEAAsE;IACtE,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,sEAAsE;IACtE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,kEAAkE;IAClE,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;CACjC;AAED,gDAAgD;AAChD,MAAM,WAAW,uBAAuB;IACtC,oEAAoE;IACpE,QAAQ,EAAE,MAAM,CAAC;IACjB,iFAAiF;IACjF,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,uDAAuD;AACvD,qBAAa,eAAgB,SAAQ,KAAK;aAGtB,UAAU,CAAC,EAAE,MAAM;aACnB,GAAG,CAAC,EAAE,MAAM;gBAF5B,OAAO,EAAE,MAAM,EACC,UAAU,CAAC,EAAE,MAAM,YAAA,EACnB,GAAG,CAAC,EAAE,MAAM,YAAA;CAK/B"}
package/package.json ADDED
@@ -0,0 +1,64 @@
1
+ {
2
+ "name": "@clef-sh/client",
3
+ "version": "0.1.2-beta.92",
4
+ "description": "Lightweight SDK for consuming Clef secrets — Cloud KMS provider and app client",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "https://github.com/clef-sh/clef",
8
+ "directory": "packages/client"
9
+ },
10
+ "main": "dist/index.js",
11
+ "module": "dist/index.mjs",
12
+ "types": "dist/index.d.ts",
13
+ "exports": {
14
+ ".": {
15
+ "import": {
16
+ "types": "./dist/index.d.mts",
17
+ "default": "./dist/index.mjs"
18
+ },
19
+ "require": {
20
+ "types": "./dist/index.d.ts",
21
+ "default": "./dist/index.js"
22
+ }
23
+ },
24
+ "./kms": {
25
+ "import": {
26
+ "types": "./dist/kms.d.mts",
27
+ "default": "./dist/kms.mjs"
28
+ },
29
+ "require": {
30
+ "types": "./dist/kms.d.ts",
31
+ "default": "./dist/kms.js"
32
+ }
33
+ },
34
+ "./package.json": "./package.json"
35
+ },
36
+ "typesVersions": {
37
+ "*": {
38
+ "kms": [
39
+ "dist/kms.d.ts"
40
+ ]
41
+ }
42
+ },
43
+ "files": [
44
+ "dist"
45
+ ],
46
+ "scripts": {
47
+ "build": "tsc --noEmit && node scripts/build.mjs",
48
+ "test": "jest",
49
+ "test:coverage": "jest --coverage"
50
+ },
51
+ "devDependencies": {
52
+ "@types/jest": "^29.5.0",
53
+ "@types/node": "^20.11.0",
54
+ "esbuild": "^0.27.4",
55
+ "jest": "^29.7.0",
56
+ "ts-jest": "^29.1.0",
57
+ "typescript": "^5.9.3"
58
+ },
59
+ "publishConfig": {
60
+ "access": "public",
61
+ "provenance": true
62
+ },
63
+ "license": "MIT"
64
+ }