@smplkit/sdk 1.0.0 → 1.0.1
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 +3 -3
- package/dist/{index.mjs → index.cjs} +37 -3
- package/dist/index.cjs.map +1 -0
- package/dist/{index.d.mts → index.d.cts} +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -36
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
- package/dist/index.mjs.map +0 -1
package/README.md
CHANGED
|
@@ -5,13 +5,13 @@ Official TypeScript SDK for the [smplkit](https://docs.smplkit.com) platform.
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
npm install smplkit
|
|
8
|
+
npm install @smplkit/sdk
|
|
9
9
|
```
|
|
10
10
|
|
|
11
11
|
## Quick Start
|
|
12
12
|
|
|
13
13
|
```typescript
|
|
14
|
-
import { SmplkitClient } from "smplkit";
|
|
14
|
+
import { SmplkitClient } from "@smplkit/sdk";
|
|
15
15
|
|
|
16
16
|
const client = new SmplkitClient({ apiKey: "sk_api_..." });
|
|
17
17
|
|
|
@@ -56,7 +56,7 @@ import {
|
|
|
56
56
|
SmplValidationError,
|
|
57
57
|
SmplConnectionError,
|
|
58
58
|
SmplTimeoutError,
|
|
59
|
-
} from "smplkit";
|
|
59
|
+
} from "@smplkit/sdk";
|
|
60
60
|
|
|
61
61
|
try {
|
|
62
62
|
const config = await client.config.get({ key: "nonexistent" });
|
|
@@ -1,3 +1,36 @@
|
|
|
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
|
+
ConfigClient: () => ConfigClient,
|
|
24
|
+
SmplConflictError: () => SmplConflictError,
|
|
25
|
+
SmplConnectionError: () => SmplConnectionError,
|
|
26
|
+
SmplError: () => SmplError,
|
|
27
|
+
SmplNotFoundError: () => SmplNotFoundError,
|
|
28
|
+
SmplTimeoutError: () => SmplTimeoutError,
|
|
29
|
+
SmplValidationError: () => SmplValidationError,
|
|
30
|
+
SmplkitClient: () => SmplkitClient
|
|
31
|
+
});
|
|
32
|
+
module.exports = __toCommonJS(index_exports);
|
|
33
|
+
|
|
1
34
|
// src/errors.ts
|
|
2
35
|
var SmplError = class extends Error {
|
|
3
36
|
/** The HTTP status code, if the error originated from an HTTP response. */
|
|
@@ -316,7 +349,8 @@ var SmplkitClient = class {
|
|
|
316
349
|
this.config = new ConfigClient(this.transport);
|
|
317
350
|
}
|
|
318
351
|
};
|
|
319
|
-
export
|
|
352
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
353
|
+
0 && (module.exports = {
|
|
320
354
|
ConfigClient,
|
|
321
355
|
SmplConflictError,
|
|
322
356
|
SmplConnectionError,
|
|
@@ -325,5 +359,5 @@ export {
|
|
|
325
359
|
SmplTimeoutError,
|
|
326
360
|
SmplValidationError,
|
|
327
361
|
SmplkitClient
|
|
328
|
-
};
|
|
329
|
-
//# sourceMappingURL=index.
|
|
362
|
+
});
|
|
363
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/config/client.ts","../src/auth.ts","../src/transport.ts","../src/client.ts"],"sourcesContent":["/**\n * smplkit — Official TypeScript SDK for the smplkit platform.\n *\n * @packageDocumentation\n */\n\n// Main client\nexport { SmplkitClient } from \"./client.js\";\nexport type { SmplkitClientOptions } from \"./client.js\";\n\n// Config types\nexport { ConfigClient } from \"./config/client.js\";\nexport type { Config, CreateConfigOptions, GetConfigOptions } from \"./config/types.js\";\n\n// Error hierarchy\nexport {\n SmplError,\n SmplConnectionError,\n SmplTimeoutError,\n SmplNotFoundError,\n SmplConflictError,\n SmplValidationError,\n} from \"./errors.js\";\n","/**\n * Structured SDK error types.\n *\n * All smplkit errors extend {@link SmplError}, allowing callers to catch\n * the base class for generic handling or specific subclasses for\n * fine-grained control.\n */\n\n/** Base exception for all smplkit SDK errors. */\nexport class SmplError extends Error {\n /** The HTTP status code, if the error originated from an HTTP response. */\n public readonly statusCode?: number;\n\n /** The raw response body, if available. */\n public readonly responseBody?: string;\n\n constructor(message: string, statusCode?: number, responseBody?: string) {\n super(message);\n this.name = \"SmplError\";\n this.statusCode = statusCode;\n this.responseBody = responseBody;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Raised when a network request fails (e.g., DNS resolution, connection refused). */\nexport class SmplConnectionError extends SmplError {\n constructor(message: string, statusCode?: number, responseBody?: string) {\n super(message, statusCode, responseBody);\n this.name = \"SmplConnectionError\";\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Raised when an operation exceeds its timeout. */\nexport class SmplTimeoutError extends SmplError {\n constructor(message: string, statusCode?: number, responseBody?: string) {\n super(message, statusCode, responseBody);\n this.name = \"SmplTimeoutError\";\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Raised when a requested resource does not exist (HTTP 404). */\nexport class SmplNotFoundError extends SmplError {\n constructor(message: string, statusCode?: number, responseBody?: string) {\n super(message, statusCode ?? 404, responseBody);\n this.name = \"SmplNotFoundError\";\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Raised when an operation conflicts with current state (HTTP 409). */\nexport class SmplConflictError extends SmplError {\n constructor(message: string, statusCode?: number, responseBody?: string) {\n super(message, statusCode ?? 409, responseBody);\n this.name = \"SmplConflictError\";\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Raised when the server rejects a request due to validation errors (HTTP 422). */\nexport class SmplValidationError extends SmplError {\n constructor(message: string, statusCode?: number, responseBody?: string) {\n super(message, statusCode ?? 422, responseBody);\n this.name = \"SmplValidationError\";\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n","/**\n * ConfigClient — management-plane operations for configs.\n *\n * Provides CRUD operations on config resources. Obtained via\n * `SmplkitClient.config`.\n */\n\nimport { SmplNotFoundError, SmplValidationError } from \"../errors.js\";\nimport type { Transport } from \"../transport.js\";\nimport type { Config, CreateConfigOptions, GetConfigOptions } from \"./types.js\";\n\nconst CONFIGS_PATH = \"/api/v1/configs\";\n\n/**\n * JSON:API resource shape as returned by the Config API.\n * @internal\n */\ninterface JsonApiResource {\n id: string;\n type: string;\n attributes: {\n name: string;\n key: string;\n description: string | null;\n parent: string | null;\n values: Record<string, unknown> | null;\n environments: Record<string, Record<string, unknown>> | null;\n created_at: string | null;\n updated_at: string | null;\n };\n}\n\n/**\n * Client for the smplkit Config API.\n *\n * All methods are async and return `Promise<T>`. Network and server\n * errors are mapped to typed SDK exceptions.\n */\nexport class ConfigClient {\n /** @internal */\n private readonly transport: Transport;\n\n /** @internal */\n constructor(transport: Transport) {\n this.transport = transport;\n }\n\n /**\n * Fetch a single config by key or UUID.\n *\n * Exactly one of `key` or `id` must be provided.\n *\n * @param options - Lookup options.\n * @returns The matching config.\n * @throws {SmplNotFoundError} If no matching config exists.\n * @throws {Error} If neither or both of `key` and `id` are provided.\n */\n async get(options: GetConfigOptions): Promise<Config> {\n const { key, id } = options;\n\n if ((key === undefined) === (id === undefined)) {\n throw new Error(\"Exactly one of 'key' or 'id' must be provided.\");\n }\n\n if (id !== undefined) {\n return this.getById(id);\n }\n\n return this.getByKey(key!);\n }\n\n /**\n * List all configs for the account.\n *\n * @returns An array of config objects.\n */\n async list(): Promise<Config[]> {\n const response = await this.transport.get(CONFIGS_PATH);\n const resources = response.data as JsonApiResource[];\n return resources.map((r) => this.resourceToModel(r));\n }\n\n /**\n * Create a new config.\n *\n * @param options - Config creation options.\n * @returns The created config.\n * @throws {SmplValidationError} If the server rejects the request.\n */\n async create(options: CreateConfigOptions): Promise<Config> {\n const body = this.buildRequestBody(options);\n const response = await this.transport.post(CONFIGS_PATH, body);\n\n if (!response.data) {\n throw new SmplValidationError(\"Failed to create config\");\n }\n\n return this.resourceToModel(response.data as JsonApiResource);\n }\n\n /**\n * Delete a config by UUID.\n *\n * @param configId - The UUID of the config to delete.\n * @throws {SmplNotFoundError} If the config does not exist.\n * @throws {SmplConflictError} If the config has children.\n */\n async delete(configId: string): Promise<void> {\n await this.transport.delete(`${CONFIGS_PATH}/${configId}`);\n }\n\n /** Fetch a config by UUID. */\n private async getById(configId: string): Promise<Config> {\n const response = await this.transport.get(`${CONFIGS_PATH}/${configId}`);\n\n if (!response.data) {\n throw new SmplNotFoundError(`Config ${configId} not found`);\n }\n\n return this.resourceToModel(response.data as JsonApiResource);\n }\n\n /** Fetch a config by key using the list endpoint with a filter. */\n private async getByKey(key: string): Promise<Config> {\n const response = await this.transport.get(CONFIGS_PATH, { \"filter[key]\": key });\n const resources = response.data as JsonApiResource[];\n\n if (!resources || resources.length === 0) {\n throw new SmplNotFoundError(`Config with key '${key}' not found`);\n }\n\n return this.resourceToModel(resources[0]);\n }\n\n /**\n * Convert a JSON:API resource to a Config domain model.\n * @internal\n */\n private resourceToModel(resource: JsonApiResource): Config {\n const attrs = resource.attributes;\n return {\n id: resource.id,\n key: attrs.key ?? \"\",\n name: attrs.name,\n description: attrs.description ?? null,\n parent: attrs.parent ?? null,\n values: attrs.values ?? {},\n environments: attrs.environments ?? {},\n createdAt: attrs.created_at ? new Date(attrs.created_at) : null,\n updatedAt: attrs.updated_at ? new Date(attrs.updated_at) : null,\n };\n }\n\n /** Build a JSON:API request body for create operations. */\n private buildRequestBody(options: CreateConfigOptions): Record<string, unknown> {\n const attributes: Record<string, unknown> = {\n name: options.name,\n };\n\n if (options.key !== undefined) attributes.key = options.key;\n if (options.description !== undefined) attributes.description = options.description;\n if (options.parent !== undefined) attributes.parent = options.parent;\n if (options.values !== undefined) attributes.values = options.values;\n\n return {\n data: {\n type: \"config\",\n attributes,\n },\n };\n }\n}\n","/**\n * Authentication handling for API key auth.\n *\n * @internal This module is not part of the public API.\n */\n\n/**\n * Build the Authorization header value for Bearer token auth.\n *\n * @param apiKey - The API key to use for authentication.\n * @returns The header value string in the form `Bearer {apiKey}`.\n */\nexport function buildAuthHeader(apiKey: string): string {\n return `Bearer ${apiKey}`;\n}\n","/**\n * Internal HTTP client wrapper.\n *\n * Uses native `fetch` with `AbortController` for timeouts. Maps network\n * errors and HTTP status codes to typed SDK exceptions.\n *\n * @internal This module is not part of the public API.\n */\n\nimport { buildAuthHeader } from \"./auth.js\";\nimport {\n SmplConnectionError,\n SmplConflictError,\n SmplError,\n SmplNotFoundError,\n SmplTimeoutError,\n SmplValidationError,\n} from \"./errors.js\";\n\nconst SDK_VERSION = \"0.0.0\";\nconst DEFAULT_TIMEOUT_MS = 30_000;\n\n/** Options for constructing a {@link Transport} instance. */\nexport interface TransportOptions {\n /** The API key used for Bearer token authentication. */\n apiKey: string;\n\n /** Base URL for all API requests. Must not have a trailing slash. */\n baseUrl: string;\n\n /** Request timeout in milliseconds. Defaults to 30 000. */\n timeout?: number;\n}\n\n/** Parsed JSON response from the API. */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype JsonBody = Record<string, any>;\n\n/**\n * Low-level HTTP transport that handles auth, timeouts, and error mapping.\n *\n * @internal\n */\nexport class Transport {\n private readonly apiKey: string;\n private readonly baseUrl: string;\n private readonly timeout: number;\n\n constructor(options: TransportOptions) {\n this.apiKey = options.apiKey;\n this.baseUrl = options.baseUrl.replace(/\\/+$/, \"\");\n this.timeout = options.timeout ?? DEFAULT_TIMEOUT_MS;\n }\n\n /**\n * Send a GET request.\n *\n * @param path - URL path relative to `baseUrl` (e.g. `/api/v1/configs`).\n * @param params - Optional query parameters.\n * @returns Parsed JSON response body.\n */\n async get(path: string, params?: Record<string, string>): Promise<JsonBody> {\n return this.request(\"GET\", path, undefined, params);\n }\n\n /**\n * Send a POST request with a JSON body.\n *\n * @param path - URL path relative to `baseUrl`.\n * @param body - JSON-serializable request body.\n * @returns Parsed JSON response body.\n */\n async post(path: string, body: JsonBody): Promise<JsonBody> {\n return this.request(\"POST\", path, body);\n }\n\n /**\n * Send a PUT request with a JSON body.\n *\n * @param path - URL path relative to `baseUrl`.\n * @param body - JSON-serializable request body.\n * @returns Parsed JSON response body.\n */\n async put(path: string, body: JsonBody): Promise<JsonBody> {\n return this.request(\"PUT\", path, body);\n }\n\n /**\n * Send a DELETE request.\n *\n * @param path - URL path relative to `baseUrl`.\n * @returns Parsed JSON response body (empty object for 204 responses).\n */\n async delete(path: string): Promise<JsonBody> {\n return this.request(\"DELETE\", path);\n }\n\n /**\n * Core request method. Handles headers, timeouts, and error mapping.\n */\n private async request(\n method: string,\n path: string,\n body?: JsonBody,\n params?: Record<string, string>,\n ): Promise<JsonBody> {\n let url = `${this.baseUrl}${path}`;\n\n if (params) {\n const searchParams = new URLSearchParams(params);\n url += `?${searchParams.toString()}`;\n }\n\n const headers: Record<string, string> = {\n Authorization: buildAuthHeader(this.apiKey),\n \"User-Agent\": `smplkit-typescript-sdk/${SDK_VERSION}`,\n Accept: \"application/vnd.api+json\",\n };\n\n if (body !== undefined) {\n headers[\"Content-Type\"] = \"application/vnd.api+json\";\n }\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n let response: Response;\n try {\n response = await fetch(url, {\n method,\n headers,\n body: body !== undefined ? JSON.stringify(body) : undefined,\n signal: controller.signal,\n });\n } catch (error: unknown) {\n clearTimeout(timeoutId);\n if (error instanceof DOMException && error.name === \"AbortError\") {\n throw new SmplTimeoutError(`Request timed out after ${this.timeout}ms`);\n }\n if (error instanceof TypeError) {\n throw new SmplConnectionError(`Network error: ${error.message}`);\n }\n throw new SmplConnectionError(\n `Request failed: ${error instanceof Error ? error.message : String(error)}`,\n );\n } finally {\n clearTimeout(timeoutId);\n }\n\n // 204 No Content — return empty object\n if (response.status === 204) {\n return {};\n }\n\n const responseText = await response.text();\n\n if (!response.ok) {\n this.throwForStatus(response.status, responseText);\n }\n\n try {\n return JSON.parse(responseText) as JsonBody;\n } catch {\n throw new SmplError(`Invalid JSON response: ${responseText}`, response.status, responseText);\n }\n }\n\n /**\n * Map HTTP error status codes to typed SDK exceptions.\n *\n * @throws {SmplNotFoundError} On 404.\n * @throws {SmplConflictError} On 409.\n * @throws {SmplValidationError} On 422.\n * @throws {SmplError} On any other non-2xx status.\n */\n private throwForStatus(status: number, body: string): never {\n switch (status) {\n case 404:\n throw new SmplNotFoundError(body, 404, body);\n case 409:\n throw new SmplConflictError(body, 409, body);\n case 422:\n throw new SmplValidationError(body, 422, body);\n default:\n throw new SmplError(`HTTP ${status}: ${body}`, status, body);\n }\n }\n}\n","/**\n * Top-level SDK client — SmplkitClient.\n *\n * The main entry point for the smplkit TypeScript SDK. Provides access\n * to sub-clients for each API domain (config, flags, logging, etc.).\n */\n\nimport { ConfigClient } from \"./config/client.js\";\nimport { Transport } from \"./transport.js\";\n\nconst DEFAULT_BASE_URL = \"https://config.smplkit.com\";\n\n/** Configuration options for the {@link SmplkitClient}. */\nexport interface SmplkitClientOptions {\n /** API key for authenticating with the smplkit platform. */\n apiKey: string;\n\n /**\n * Base URL for all API requests.\n * @default \"https://config.smplkit.com\"\n */\n baseUrl?: string;\n\n /**\n * Request timeout in milliseconds.\n * @default 30000\n */\n timeout?: number;\n}\n\n/**\n * Entry point for the smplkit TypeScript SDK.\n *\n * @example\n * ```typescript\n * import { SmplkitClient } from \"@smplkit/sdk\";\n *\n * const client = new SmplkitClient({ apiKey: \"sk_api_...\" });\n * const cfg = await client.config.get({ key: \"common\" });\n * ```\n */\nexport class SmplkitClient {\n /** Client for config management-plane operations. */\n readonly config: ConfigClient;\n\n /** @internal */\n private readonly transport: Transport;\n\n constructor(options: SmplkitClientOptions) {\n if (!options.apiKey) {\n throw new Error(\"apiKey is required\");\n }\n\n this.transport = new Transport({\n apiKey: options.apiKey,\n baseUrl: options.baseUrl ?? DEFAULT_BASE_URL,\n timeout: options.timeout,\n });\n\n this.config = new ConfigClient(this.transport);\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -212,7 +212,7 @@ interface SmplkitClientOptions {
|
|
|
212
212
|
*
|
|
213
213
|
* @example
|
|
214
214
|
* ```typescript
|
|
215
|
-
* import { SmplkitClient } from "smplkit";
|
|
215
|
+
* import { SmplkitClient } from "@smplkit/sdk";
|
|
216
216
|
*
|
|
217
217
|
* const client = new SmplkitClient({ apiKey: "sk_api_..." });
|
|
218
218
|
* const cfg = await client.config.get({ key: "common" });
|
package/dist/index.d.ts
CHANGED
|
@@ -212,7 +212,7 @@ interface SmplkitClientOptions {
|
|
|
212
212
|
*
|
|
213
213
|
* @example
|
|
214
214
|
* ```typescript
|
|
215
|
-
* import { SmplkitClient } from "smplkit";
|
|
215
|
+
* import { SmplkitClient } from "@smplkit/sdk";
|
|
216
216
|
*
|
|
217
217
|
* const client = new SmplkitClient({ apiKey: "sk_api_..." });
|
|
218
218
|
* const cfg = await client.config.get({ key: "common" });
|
package/dist/index.js
CHANGED
|
@@ -1,36 +1,3 @@
|
|
|
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
|
-
ConfigClient: () => ConfigClient,
|
|
24
|
-
SmplConflictError: () => SmplConflictError,
|
|
25
|
-
SmplConnectionError: () => SmplConnectionError,
|
|
26
|
-
SmplError: () => SmplError,
|
|
27
|
-
SmplNotFoundError: () => SmplNotFoundError,
|
|
28
|
-
SmplTimeoutError: () => SmplTimeoutError,
|
|
29
|
-
SmplValidationError: () => SmplValidationError,
|
|
30
|
-
SmplkitClient: () => SmplkitClient
|
|
31
|
-
});
|
|
32
|
-
module.exports = __toCommonJS(index_exports);
|
|
33
|
-
|
|
34
1
|
// src/errors.ts
|
|
35
2
|
var SmplError = class extends Error {
|
|
36
3
|
/** The HTTP status code, if the error originated from an HTTP response. */
|
|
@@ -349,8 +316,7 @@ var SmplkitClient = class {
|
|
|
349
316
|
this.config = new ConfigClient(this.transport);
|
|
350
317
|
}
|
|
351
318
|
};
|
|
352
|
-
|
|
353
|
-
0 && (module.exports = {
|
|
319
|
+
export {
|
|
354
320
|
ConfigClient,
|
|
355
321
|
SmplConflictError,
|
|
356
322
|
SmplConnectionError,
|
|
@@ -359,5 +325,5 @@ var SmplkitClient = class {
|
|
|
359
325
|
SmplTimeoutError,
|
|
360
326
|
SmplValidationError,
|
|
361
327
|
SmplkitClient
|
|
362
|
-
}
|
|
328
|
+
};
|
|
363
329
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/config/client.ts","../src/auth.ts","../src/transport.ts","../src/client.ts"],"sourcesContent":["/**\n * smplkit — Official TypeScript SDK for the smplkit platform.\n *\n * @packageDocumentation\n */\n\n// Main client\nexport { SmplkitClient } from \"./client.js\";\nexport type { SmplkitClientOptions } from \"./client.js\";\n\n// Config types\nexport { ConfigClient } from \"./config/client.js\";\nexport type { Config, CreateConfigOptions, GetConfigOptions } from \"./config/types.js\";\n\n// Error hierarchy\nexport {\n SmplError,\n SmplConnectionError,\n SmplTimeoutError,\n SmplNotFoundError,\n SmplConflictError,\n SmplValidationError,\n} from \"./errors.js\";\n","/**\n * Structured SDK error types.\n *\n * All smplkit errors extend {@link SmplError}, allowing callers to catch\n * the base class for generic handling or specific subclasses for\n * fine-grained control.\n */\n\n/** Base exception for all smplkit SDK errors. */\nexport class SmplError extends Error {\n /** The HTTP status code, if the error originated from an HTTP response. */\n public readonly statusCode?: number;\n\n /** The raw response body, if available. */\n public readonly responseBody?: string;\n\n constructor(message: string, statusCode?: number, responseBody?: string) {\n super(message);\n this.name = \"SmplError\";\n this.statusCode = statusCode;\n this.responseBody = responseBody;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Raised when a network request fails (e.g., DNS resolution, connection refused). */\nexport class SmplConnectionError extends SmplError {\n constructor(message: string, statusCode?: number, responseBody?: string) {\n super(message, statusCode, responseBody);\n this.name = \"SmplConnectionError\";\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Raised when an operation exceeds its timeout. */\nexport class SmplTimeoutError extends SmplError {\n constructor(message: string, statusCode?: number, responseBody?: string) {\n super(message, statusCode, responseBody);\n this.name = \"SmplTimeoutError\";\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Raised when a requested resource does not exist (HTTP 404). */\nexport class SmplNotFoundError extends SmplError {\n constructor(message: string, statusCode?: number, responseBody?: string) {\n super(message, statusCode ?? 404, responseBody);\n this.name = \"SmplNotFoundError\";\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Raised when an operation conflicts with current state (HTTP 409). */\nexport class SmplConflictError extends SmplError {\n constructor(message: string, statusCode?: number, responseBody?: string) {\n super(message, statusCode ?? 409, responseBody);\n this.name = \"SmplConflictError\";\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Raised when the server rejects a request due to validation errors (HTTP 422). */\nexport class SmplValidationError extends SmplError {\n constructor(message: string, statusCode?: number, responseBody?: string) {\n super(message, statusCode ?? 422, responseBody);\n this.name = \"SmplValidationError\";\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n","/**\n * ConfigClient — management-plane operations for configs.\n *\n * Provides CRUD operations on config resources. Obtained via\n * `SmplkitClient.config`.\n */\n\nimport { SmplNotFoundError, SmplValidationError } from \"../errors.js\";\nimport type { Transport } from \"../transport.js\";\nimport type { Config, CreateConfigOptions, GetConfigOptions } from \"./types.js\";\n\nconst CONFIGS_PATH = \"/api/v1/configs\";\n\n/**\n * JSON:API resource shape as returned by the Config API.\n * @internal\n */\ninterface JsonApiResource {\n id: string;\n type: string;\n attributes: {\n name: string;\n key: string;\n description: string | null;\n parent: string | null;\n values: Record<string, unknown> | null;\n environments: Record<string, Record<string, unknown>> | null;\n created_at: string | null;\n updated_at: string | null;\n };\n}\n\n/**\n * Client for the smplkit Config API.\n *\n * All methods are async and return `Promise<T>`. Network and server\n * errors are mapped to typed SDK exceptions.\n */\nexport class ConfigClient {\n /** @internal */\n private readonly transport: Transport;\n\n /** @internal */\n constructor(transport: Transport) {\n this.transport = transport;\n }\n\n /**\n * Fetch a single config by key or UUID.\n *\n * Exactly one of `key` or `id` must be provided.\n *\n * @param options - Lookup options.\n * @returns The matching config.\n * @throws {SmplNotFoundError} If no matching config exists.\n * @throws {Error} If neither or both of `key` and `id` are provided.\n */\n async get(options: GetConfigOptions): Promise<Config> {\n const { key, id } = options;\n\n if ((key === undefined) === (id === undefined)) {\n throw new Error(\"Exactly one of 'key' or 'id' must be provided.\");\n }\n\n if (id !== undefined) {\n return this.getById(id);\n }\n\n return this.getByKey(key!);\n }\n\n /**\n * List all configs for the account.\n *\n * @returns An array of config objects.\n */\n async list(): Promise<Config[]> {\n const response = await this.transport.get(CONFIGS_PATH);\n const resources = response.data as JsonApiResource[];\n return resources.map((r) => this.resourceToModel(r));\n }\n\n /**\n * Create a new config.\n *\n * @param options - Config creation options.\n * @returns The created config.\n * @throws {SmplValidationError} If the server rejects the request.\n */\n async create(options: CreateConfigOptions): Promise<Config> {\n const body = this.buildRequestBody(options);\n const response = await this.transport.post(CONFIGS_PATH, body);\n\n if (!response.data) {\n throw new SmplValidationError(\"Failed to create config\");\n }\n\n return this.resourceToModel(response.data as JsonApiResource);\n }\n\n /**\n * Delete a config by UUID.\n *\n * @param configId - The UUID of the config to delete.\n * @throws {SmplNotFoundError} If the config does not exist.\n * @throws {SmplConflictError} If the config has children.\n */\n async delete(configId: string): Promise<void> {\n await this.transport.delete(`${CONFIGS_PATH}/${configId}`);\n }\n\n /** Fetch a config by UUID. */\n private async getById(configId: string): Promise<Config> {\n const response = await this.transport.get(`${CONFIGS_PATH}/${configId}`);\n\n if (!response.data) {\n throw new SmplNotFoundError(`Config ${configId} not found`);\n }\n\n return this.resourceToModel(response.data as JsonApiResource);\n }\n\n /** Fetch a config by key using the list endpoint with a filter. */\n private async getByKey(key: string): Promise<Config> {\n const response = await this.transport.get(CONFIGS_PATH, { \"filter[key]\": key });\n const resources = response.data as JsonApiResource[];\n\n if (!resources || resources.length === 0) {\n throw new SmplNotFoundError(`Config with key '${key}' not found`);\n }\n\n return this.resourceToModel(resources[0]);\n }\n\n /**\n * Convert a JSON:API resource to a Config domain model.\n * @internal\n */\n private resourceToModel(resource: JsonApiResource): Config {\n const attrs = resource.attributes;\n return {\n id: resource.id,\n key: attrs.key ?? \"\",\n name: attrs.name,\n description: attrs.description ?? null,\n parent: attrs.parent ?? null,\n values: attrs.values ?? {},\n environments: attrs.environments ?? {},\n createdAt: attrs.created_at ? new Date(attrs.created_at) : null,\n updatedAt: attrs.updated_at ? new Date(attrs.updated_at) : null,\n };\n }\n\n /** Build a JSON:API request body for create operations. */\n private buildRequestBody(options: CreateConfigOptions): Record<string, unknown> {\n const attributes: Record<string, unknown> = {\n name: options.name,\n };\n\n if (options.key !== undefined) attributes.key = options.key;\n if (options.description !== undefined) attributes.description = options.description;\n if (options.parent !== undefined) attributes.parent = options.parent;\n if (options.values !== undefined) attributes.values = options.values;\n\n return {\n data: {\n type: \"config\",\n attributes,\n },\n };\n }\n}\n","/**\n * Authentication handling for API key auth.\n *\n * @internal This module is not part of the public API.\n */\n\n/**\n * Build the Authorization header value for Bearer token auth.\n *\n * @param apiKey - The API key to use for authentication.\n * @returns The header value string in the form `Bearer {apiKey}`.\n */\nexport function buildAuthHeader(apiKey: string): string {\n return `Bearer ${apiKey}`;\n}\n","/**\n * Internal HTTP client wrapper.\n *\n * Uses native `fetch` with `AbortController` for timeouts. Maps network\n * errors and HTTP status codes to typed SDK exceptions.\n *\n * @internal This module is not part of the public API.\n */\n\nimport { buildAuthHeader } from \"./auth.js\";\nimport {\n SmplConnectionError,\n SmplConflictError,\n SmplError,\n SmplNotFoundError,\n SmplTimeoutError,\n SmplValidationError,\n} from \"./errors.js\";\n\nconst SDK_VERSION = \"0.0.0\";\nconst DEFAULT_TIMEOUT_MS = 30_000;\n\n/** Options for constructing a {@link Transport} instance. */\nexport interface TransportOptions {\n /** The API key used for Bearer token authentication. */\n apiKey: string;\n\n /** Base URL for all API requests. Must not have a trailing slash. */\n baseUrl: string;\n\n /** Request timeout in milliseconds. Defaults to 30 000. */\n timeout?: number;\n}\n\n/** Parsed JSON response from the API. */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype JsonBody = Record<string, any>;\n\n/**\n * Low-level HTTP transport that handles auth, timeouts, and error mapping.\n *\n * @internal\n */\nexport class Transport {\n private readonly apiKey: string;\n private readonly baseUrl: string;\n private readonly timeout: number;\n\n constructor(options: TransportOptions) {\n this.apiKey = options.apiKey;\n this.baseUrl = options.baseUrl.replace(/\\/+$/, \"\");\n this.timeout = options.timeout ?? DEFAULT_TIMEOUT_MS;\n }\n\n /**\n * Send a GET request.\n *\n * @param path - URL path relative to `baseUrl` (e.g. `/api/v1/configs`).\n * @param params - Optional query parameters.\n * @returns Parsed JSON response body.\n */\n async get(path: string, params?: Record<string, string>): Promise<JsonBody> {\n return this.request(\"GET\", path, undefined, params);\n }\n\n /**\n * Send a POST request with a JSON body.\n *\n * @param path - URL path relative to `baseUrl`.\n * @param body - JSON-serializable request body.\n * @returns Parsed JSON response body.\n */\n async post(path: string, body: JsonBody): Promise<JsonBody> {\n return this.request(\"POST\", path, body);\n }\n\n /**\n * Send a PUT request with a JSON body.\n *\n * @param path - URL path relative to `baseUrl`.\n * @param body - JSON-serializable request body.\n * @returns Parsed JSON response body.\n */\n async put(path: string, body: JsonBody): Promise<JsonBody> {\n return this.request(\"PUT\", path, body);\n }\n\n /**\n * Send a DELETE request.\n *\n * @param path - URL path relative to `baseUrl`.\n * @returns Parsed JSON response body (empty object for 204 responses).\n */\n async delete(path: string): Promise<JsonBody> {\n return this.request(\"DELETE\", path);\n }\n\n /**\n * Core request method. Handles headers, timeouts, and error mapping.\n */\n private async request(\n method: string,\n path: string,\n body?: JsonBody,\n params?: Record<string, string>,\n ): Promise<JsonBody> {\n let url = `${this.baseUrl}${path}`;\n\n if (params) {\n const searchParams = new URLSearchParams(params);\n url += `?${searchParams.toString()}`;\n }\n\n const headers: Record<string, string> = {\n Authorization: buildAuthHeader(this.apiKey),\n \"User-Agent\": `smplkit-typescript-sdk/${SDK_VERSION}`,\n Accept: \"application/vnd.api+json\",\n };\n\n if (body !== undefined) {\n headers[\"Content-Type\"] = \"application/vnd.api+json\";\n }\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n let response: Response;\n try {\n response = await fetch(url, {\n method,\n headers,\n body: body !== undefined ? JSON.stringify(body) : undefined,\n signal: controller.signal,\n });\n } catch (error: unknown) {\n clearTimeout(timeoutId);\n if (error instanceof DOMException && error.name === \"AbortError\") {\n throw new SmplTimeoutError(`Request timed out after ${this.timeout}ms`);\n }\n if (error instanceof TypeError) {\n throw new SmplConnectionError(`Network error: ${error.message}`);\n }\n throw new SmplConnectionError(\n `Request failed: ${error instanceof Error ? error.message : String(error)}`,\n );\n } finally {\n clearTimeout(timeoutId);\n }\n\n // 204 No Content — return empty object\n if (response.status === 204) {\n return {};\n }\n\n const responseText = await response.text();\n\n if (!response.ok) {\n this.throwForStatus(response.status, responseText);\n }\n\n try {\n return JSON.parse(responseText) as JsonBody;\n } catch {\n throw new SmplError(`Invalid JSON response: ${responseText}`, response.status, responseText);\n }\n }\n\n /**\n * Map HTTP error status codes to typed SDK exceptions.\n *\n * @throws {SmplNotFoundError} On 404.\n * @throws {SmplConflictError} On 409.\n * @throws {SmplValidationError} On 422.\n * @throws {SmplError} On any other non-2xx status.\n */\n private throwForStatus(status: number, body: string): never {\n switch (status) {\n case 404:\n throw new SmplNotFoundError(body, 404, body);\n case 409:\n throw new SmplConflictError(body, 409, body);\n case 422:\n throw new SmplValidationError(body, 422, body);\n default:\n throw new SmplError(`HTTP ${status}: ${body}`, status, body);\n }\n }\n}\n","/**\n * Top-level SDK client — SmplkitClient.\n *\n * The main entry point for the smplkit TypeScript SDK. Provides access\n * to sub-clients for each API domain (config, flags, logging, etc.).\n */\n\nimport { ConfigClient } from \"./config/client.js\";\nimport { Transport } from \"./transport.js\";\n\nconst DEFAULT_BASE_URL = \"https://config.smplkit.com\";\n\n/** Configuration options for the {@link SmplkitClient}. */\nexport interface SmplkitClientOptions {\n /** API key for authenticating with the smplkit platform. */\n apiKey: string;\n\n /**\n * Base URL for all API requests.\n * @default \"https://config.smplkit.com\"\n */\n baseUrl?: string;\n\n /**\n * Request timeout in milliseconds.\n * @default 30000\n */\n timeout?: number;\n}\n\n/**\n * Entry point for the smplkit TypeScript SDK.\n *\n * @example\n * ```typescript\n * import { SmplkitClient } from \"smplkit\";\n *\n * const client = new SmplkitClient({ apiKey: \"sk_api_...\" });\n * const cfg = await client.config.get({ key: \"common\" });\n * ```\n */\nexport class SmplkitClient {\n /** Client for config management-plane operations. */\n readonly config: ConfigClient;\n\n /** @internal */\n private readonly transport: Transport;\n\n constructor(options: SmplkitClientOptions) {\n if (!options.apiKey) {\n throw new Error(\"apiKey is required\");\n }\n\n this.transport = new Transport({\n apiKey: options.apiKey,\n baseUrl: options.baseUrl ?? DEFAULT_BASE_URL,\n timeout: options.timeout,\n });\n\n this.config = new ConfigClient(this.transport);\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/errors.ts","../src/config/client.ts","../src/auth.ts","../src/transport.ts","../src/client.ts"],"sourcesContent":["/**\n * Structured SDK error types.\n *\n * All smplkit errors extend {@link SmplError}, allowing callers to catch\n * the base class for generic handling or specific subclasses for\n * fine-grained control.\n */\n\n/** Base exception for all smplkit SDK errors. */\nexport class SmplError extends Error {\n /** The HTTP status code, if the error originated from an HTTP response. */\n public readonly statusCode?: number;\n\n /** The raw response body, if available. */\n public readonly responseBody?: string;\n\n constructor(message: string, statusCode?: number, responseBody?: string) {\n super(message);\n this.name = \"SmplError\";\n this.statusCode = statusCode;\n this.responseBody = responseBody;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Raised when a network request fails (e.g., DNS resolution, connection refused). */\nexport class SmplConnectionError extends SmplError {\n constructor(message: string, statusCode?: number, responseBody?: string) {\n super(message, statusCode, responseBody);\n this.name = \"SmplConnectionError\";\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Raised when an operation exceeds its timeout. */\nexport class SmplTimeoutError extends SmplError {\n constructor(message: string, statusCode?: number, responseBody?: string) {\n super(message, statusCode, responseBody);\n this.name = \"SmplTimeoutError\";\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Raised when a requested resource does not exist (HTTP 404). */\nexport class SmplNotFoundError extends SmplError {\n constructor(message: string, statusCode?: number, responseBody?: string) {\n super(message, statusCode ?? 404, responseBody);\n this.name = \"SmplNotFoundError\";\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Raised when an operation conflicts with current state (HTTP 409). */\nexport class SmplConflictError extends SmplError {\n constructor(message: string, statusCode?: number, responseBody?: string) {\n super(message, statusCode ?? 409, responseBody);\n this.name = \"SmplConflictError\";\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Raised when the server rejects a request due to validation errors (HTTP 422). */\nexport class SmplValidationError extends SmplError {\n constructor(message: string, statusCode?: number, responseBody?: string) {\n super(message, statusCode ?? 422, responseBody);\n this.name = \"SmplValidationError\";\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n","/**\n * ConfigClient — management-plane operations for configs.\n *\n * Provides CRUD operations on config resources. Obtained via\n * `SmplkitClient.config`.\n */\n\nimport { SmplNotFoundError, SmplValidationError } from \"../errors.js\";\nimport type { Transport } from \"../transport.js\";\nimport type { Config, CreateConfigOptions, GetConfigOptions } from \"./types.js\";\n\nconst CONFIGS_PATH = \"/api/v1/configs\";\n\n/**\n * JSON:API resource shape as returned by the Config API.\n * @internal\n */\ninterface JsonApiResource {\n id: string;\n type: string;\n attributes: {\n name: string;\n key: string;\n description: string | null;\n parent: string | null;\n values: Record<string, unknown> | null;\n environments: Record<string, Record<string, unknown>> | null;\n created_at: string | null;\n updated_at: string | null;\n };\n}\n\n/**\n * Client for the smplkit Config API.\n *\n * All methods are async and return `Promise<T>`. Network and server\n * errors are mapped to typed SDK exceptions.\n */\nexport class ConfigClient {\n /** @internal */\n private readonly transport: Transport;\n\n /** @internal */\n constructor(transport: Transport) {\n this.transport = transport;\n }\n\n /**\n * Fetch a single config by key or UUID.\n *\n * Exactly one of `key` or `id` must be provided.\n *\n * @param options - Lookup options.\n * @returns The matching config.\n * @throws {SmplNotFoundError} If no matching config exists.\n * @throws {Error} If neither or both of `key` and `id` are provided.\n */\n async get(options: GetConfigOptions): Promise<Config> {\n const { key, id } = options;\n\n if ((key === undefined) === (id === undefined)) {\n throw new Error(\"Exactly one of 'key' or 'id' must be provided.\");\n }\n\n if (id !== undefined) {\n return this.getById(id);\n }\n\n return this.getByKey(key!);\n }\n\n /**\n * List all configs for the account.\n *\n * @returns An array of config objects.\n */\n async list(): Promise<Config[]> {\n const response = await this.transport.get(CONFIGS_PATH);\n const resources = response.data as JsonApiResource[];\n return resources.map((r) => this.resourceToModel(r));\n }\n\n /**\n * Create a new config.\n *\n * @param options - Config creation options.\n * @returns The created config.\n * @throws {SmplValidationError} If the server rejects the request.\n */\n async create(options: CreateConfigOptions): Promise<Config> {\n const body = this.buildRequestBody(options);\n const response = await this.transport.post(CONFIGS_PATH, body);\n\n if (!response.data) {\n throw new SmplValidationError(\"Failed to create config\");\n }\n\n return this.resourceToModel(response.data as JsonApiResource);\n }\n\n /**\n * Delete a config by UUID.\n *\n * @param configId - The UUID of the config to delete.\n * @throws {SmplNotFoundError} If the config does not exist.\n * @throws {SmplConflictError} If the config has children.\n */\n async delete(configId: string): Promise<void> {\n await this.transport.delete(`${CONFIGS_PATH}/${configId}`);\n }\n\n /** Fetch a config by UUID. */\n private async getById(configId: string): Promise<Config> {\n const response = await this.transport.get(`${CONFIGS_PATH}/${configId}`);\n\n if (!response.data) {\n throw new SmplNotFoundError(`Config ${configId} not found`);\n }\n\n return this.resourceToModel(response.data as JsonApiResource);\n }\n\n /** Fetch a config by key using the list endpoint with a filter. */\n private async getByKey(key: string): Promise<Config> {\n const response = await this.transport.get(CONFIGS_PATH, { \"filter[key]\": key });\n const resources = response.data as JsonApiResource[];\n\n if (!resources || resources.length === 0) {\n throw new SmplNotFoundError(`Config with key '${key}' not found`);\n }\n\n return this.resourceToModel(resources[0]);\n }\n\n /**\n * Convert a JSON:API resource to a Config domain model.\n * @internal\n */\n private resourceToModel(resource: JsonApiResource): Config {\n const attrs = resource.attributes;\n return {\n id: resource.id,\n key: attrs.key ?? \"\",\n name: attrs.name,\n description: attrs.description ?? null,\n parent: attrs.parent ?? null,\n values: attrs.values ?? {},\n environments: attrs.environments ?? {},\n createdAt: attrs.created_at ? new Date(attrs.created_at) : null,\n updatedAt: attrs.updated_at ? new Date(attrs.updated_at) : null,\n };\n }\n\n /** Build a JSON:API request body for create operations. */\n private buildRequestBody(options: CreateConfigOptions): Record<string, unknown> {\n const attributes: Record<string, unknown> = {\n name: options.name,\n };\n\n if (options.key !== undefined) attributes.key = options.key;\n if (options.description !== undefined) attributes.description = options.description;\n if (options.parent !== undefined) attributes.parent = options.parent;\n if (options.values !== undefined) attributes.values = options.values;\n\n return {\n data: {\n type: \"config\",\n attributes,\n },\n };\n }\n}\n","/**\n * Authentication handling for API key auth.\n *\n * @internal This module is not part of the public API.\n */\n\n/**\n * Build the Authorization header value for Bearer token auth.\n *\n * @param apiKey - The API key to use for authentication.\n * @returns The header value string in the form `Bearer {apiKey}`.\n */\nexport function buildAuthHeader(apiKey: string): string {\n return `Bearer ${apiKey}`;\n}\n","/**\n * Internal HTTP client wrapper.\n *\n * Uses native `fetch` with `AbortController` for timeouts. Maps network\n * errors and HTTP status codes to typed SDK exceptions.\n *\n * @internal This module is not part of the public API.\n */\n\nimport { buildAuthHeader } from \"./auth.js\";\nimport {\n SmplConnectionError,\n SmplConflictError,\n SmplError,\n SmplNotFoundError,\n SmplTimeoutError,\n SmplValidationError,\n} from \"./errors.js\";\n\nconst SDK_VERSION = \"0.0.0\";\nconst DEFAULT_TIMEOUT_MS = 30_000;\n\n/** Options for constructing a {@link Transport} instance. */\nexport interface TransportOptions {\n /** The API key used for Bearer token authentication. */\n apiKey: string;\n\n /** Base URL for all API requests. Must not have a trailing slash. */\n baseUrl: string;\n\n /** Request timeout in milliseconds. Defaults to 30 000. */\n timeout?: number;\n}\n\n/** Parsed JSON response from the API. */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype JsonBody = Record<string, any>;\n\n/**\n * Low-level HTTP transport that handles auth, timeouts, and error mapping.\n *\n * @internal\n */\nexport class Transport {\n private readonly apiKey: string;\n private readonly baseUrl: string;\n private readonly timeout: number;\n\n constructor(options: TransportOptions) {\n this.apiKey = options.apiKey;\n this.baseUrl = options.baseUrl.replace(/\\/+$/, \"\");\n this.timeout = options.timeout ?? DEFAULT_TIMEOUT_MS;\n }\n\n /**\n * Send a GET request.\n *\n * @param path - URL path relative to `baseUrl` (e.g. `/api/v1/configs`).\n * @param params - Optional query parameters.\n * @returns Parsed JSON response body.\n */\n async get(path: string, params?: Record<string, string>): Promise<JsonBody> {\n return this.request(\"GET\", path, undefined, params);\n }\n\n /**\n * Send a POST request with a JSON body.\n *\n * @param path - URL path relative to `baseUrl`.\n * @param body - JSON-serializable request body.\n * @returns Parsed JSON response body.\n */\n async post(path: string, body: JsonBody): Promise<JsonBody> {\n return this.request(\"POST\", path, body);\n }\n\n /**\n * Send a PUT request with a JSON body.\n *\n * @param path - URL path relative to `baseUrl`.\n * @param body - JSON-serializable request body.\n * @returns Parsed JSON response body.\n */\n async put(path: string, body: JsonBody): Promise<JsonBody> {\n return this.request(\"PUT\", path, body);\n }\n\n /**\n * Send a DELETE request.\n *\n * @param path - URL path relative to `baseUrl`.\n * @returns Parsed JSON response body (empty object for 204 responses).\n */\n async delete(path: string): Promise<JsonBody> {\n return this.request(\"DELETE\", path);\n }\n\n /**\n * Core request method. Handles headers, timeouts, and error mapping.\n */\n private async request(\n method: string,\n path: string,\n body?: JsonBody,\n params?: Record<string, string>,\n ): Promise<JsonBody> {\n let url = `${this.baseUrl}${path}`;\n\n if (params) {\n const searchParams = new URLSearchParams(params);\n url += `?${searchParams.toString()}`;\n }\n\n const headers: Record<string, string> = {\n Authorization: buildAuthHeader(this.apiKey),\n \"User-Agent\": `smplkit-typescript-sdk/${SDK_VERSION}`,\n Accept: \"application/vnd.api+json\",\n };\n\n if (body !== undefined) {\n headers[\"Content-Type\"] = \"application/vnd.api+json\";\n }\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n let response: Response;\n try {\n response = await fetch(url, {\n method,\n headers,\n body: body !== undefined ? JSON.stringify(body) : undefined,\n signal: controller.signal,\n });\n } catch (error: unknown) {\n clearTimeout(timeoutId);\n if (error instanceof DOMException && error.name === \"AbortError\") {\n throw new SmplTimeoutError(`Request timed out after ${this.timeout}ms`);\n }\n if (error instanceof TypeError) {\n throw new SmplConnectionError(`Network error: ${error.message}`);\n }\n throw new SmplConnectionError(\n `Request failed: ${error instanceof Error ? error.message : String(error)}`,\n );\n } finally {\n clearTimeout(timeoutId);\n }\n\n // 204 No Content — return empty object\n if (response.status === 204) {\n return {};\n }\n\n const responseText = await response.text();\n\n if (!response.ok) {\n this.throwForStatus(response.status, responseText);\n }\n\n try {\n return JSON.parse(responseText) as JsonBody;\n } catch {\n throw new SmplError(`Invalid JSON response: ${responseText}`, response.status, responseText);\n }\n }\n\n /**\n * Map HTTP error status codes to typed SDK exceptions.\n *\n * @throws {SmplNotFoundError} On 404.\n * @throws {SmplConflictError} On 409.\n * @throws {SmplValidationError} On 422.\n * @throws {SmplError} On any other non-2xx status.\n */\n private throwForStatus(status: number, body: string): never {\n switch (status) {\n case 404:\n throw new SmplNotFoundError(body, 404, body);\n case 409:\n throw new SmplConflictError(body, 409, body);\n case 422:\n throw new SmplValidationError(body, 422, body);\n default:\n throw new SmplError(`HTTP ${status}: ${body}`, status, body);\n }\n }\n}\n","/**\n * Top-level SDK client — SmplkitClient.\n *\n * The main entry point for the smplkit TypeScript SDK. Provides access\n * to sub-clients for each API domain (config, flags, logging, etc.).\n */\n\nimport { ConfigClient } from \"./config/client.js\";\nimport { Transport } from \"./transport.js\";\n\nconst DEFAULT_BASE_URL = \"https://config.smplkit.com\";\n\n/** Configuration options for the {@link SmplkitClient}. */\nexport interface SmplkitClientOptions {\n /** API key for authenticating with the smplkit platform. */\n apiKey: string;\n\n /**\n * Base URL for all API requests.\n * @default \"https://config.smplkit.com\"\n */\n baseUrl?: string;\n\n /**\n * Request timeout in milliseconds.\n * @default 30000\n */\n timeout?: number;\n}\n\n/**\n * Entry point for the smplkit TypeScript SDK.\n *\n * @example\n * ```typescript\n * import { SmplkitClient } from \"@smplkit/sdk\";\n *\n * const client = new SmplkitClient({ apiKey: \"sk_api_...\" });\n * const cfg = await client.config.get({ key: \"common\" });\n * ```\n */\nexport class SmplkitClient {\n /** Client for config management-plane operations. */\n readonly config: ConfigClient;\n\n /** @internal */\n private readonly transport: Transport;\n\n constructor(options: SmplkitClientOptions) {\n if (!options.apiKey) {\n throw new Error(\"apiKey is required\");\n }\n\n this.transport = new Transport({\n apiKey: options.apiKey,\n baseUrl: options.baseUrl ?? DEFAULT_BASE_URL,\n timeout: options.timeout,\n });\n\n this.config = new ConfigClient(this.transport);\n }\n}\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
package/dist/index.mjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/errors.ts","../src/config/client.ts","../src/auth.ts","../src/transport.ts","../src/client.ts"],"sourcesContent":["/**\n * Structured SDK error types.\n *\n * All smplkit errors extend {@link SmplError}, allowing callers to catch\n * the base class for generic handling or specific subclasses for\n * fine-grained control.\n */\n\n/** Base exception for all smplkit SDK errors. */\nexport class SmplError extends Error {\n /** The HTTP status code, if the error originated from an HTTP response. */\n public readonly statusCode?: number;\n\n /** The raw response body, if available. */\n public readonly responseBody?: string;\n\n constructor(message: string, statusCode?: number, responseBody?: string) {\n super(message);\n this.name = \"SmplError\";\n this.statusCode = statusCode;\n this.responseBody = responseBody;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Raised when a network request fails (e.g., DNS resolution, connection refused). */\nexport class SmplConnectionError extends SmplError {\n constructor(message: string, statusCode?: number, responseBody?: string) {\n super(message, statusCode, responseBody);\n this.name = \"SmplConnectionError\";\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Raised when an operation exceeds its timeout. */\nexport class SmplTimeoutError extends SmplError {\n constructor(message: string, statusCode?: number, responseBody?: string) {\n super(message, statusCode, responseBody);\n this.name = \"SmplTimeoutError\";\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Raised when a requested resource does not exist (HTTP 404). */\nexport class SmplNotFoundError extends SmplError {\n constructor(message: string, statusCode?: number, responseBody?: string) {\n super(message, statusCode ?? 404, responseBody);\n this.name = \"SmplNotFoundError\";\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Raised when an operation conflicts with current state (HTTP 409). */\nexport class SmplConflictError extends SmplError {\n constructor(message: string, statusCode?: number, responseBody?: string) {\n super(message, statusCode ?? 409, responseBody);\n this.name = \"SmplConflictError\";\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Raised when the server rejects a request due to validation errors (HTTP 422). */\nexport class SmplValidationError extends SmplError {\n constructor(message: string, statusCode?: number, responseBody?: string) {\n super(message, statusCode ?? 422, responseBody);\n this.name = \"SmplValidationError\";\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n","/**\n * ConfigClient — management-plane operations for configs.\n *\n * Provides CRUD operations on config resources. Obtained via\n * `SmplkitClient.config`.\n */\n\nimport { SmplNotFoundError, SmplValidationError } from \"../errors.js\";\nimport type { Transport } from \"../transport.js\";\nimport type { Config, CreateConfigOptions, GetConfigOptions } from \"./types.js\";\n\nconst CONFIGS_PATH = \"/api/v1/configs\";\n\n/**\n * JSON:API resource shape as returned by the Config API.\n * @internal\n */\ninterface JsonApiResource {\n id: string;\n type: string;\n attributes: {\n name: string;\n key: string;\n description: string | null;\n parent: string | null;\n values: Record<string, unknown> | null;\n environments: Record<string, Record<string, unknown>> | null;\n created_at: string | null;\n updated_at: string | null;\n };\n}\n\n/**\n * Client for the smplkit Config API.\n *\n * All methods are async and return `Promise<T>`. Network and server\n * errors are mapped to typed SDK exceptions.\n */\nexport class ConfigClient {\n /** @internal */\n private readonly transport: Transport;\n\n /** @internal */\n constructor(transport: Transport) {\n this.transport = transport;\n }\n\n /**\n * Fetch a single config by key or UUID.\n *\n * Exactly one of `key` or `id` must be provided.\n *\n * @param options - Lookup options.\n * @returns The matching config.\n * @throws {SmplNotFoundError} If no matching config exists.\n * @throws {Error} If neither or both of `key` and `id` are provided.\n */\n async get(options: GetConfigOptions): Promise<Config> {\n const { key, id } = options;\n\n if ((key === undefined) === (id === undefined)) {\n throw new Error(\"Exactly one of 'key' or 'id' must be provided.\");\n }\n\n if (id !== undefined) {\n return this.getById(id);\n }\n\n return this.getByKey(key!);\n }\n\n /**\n * List all configs for the account.\n *\n * @returns An array of config objects.\n */\n async list(): Promise<Config[]> {\n const response = await this.transport.get(CONFIGS_PATH);\n const resources = response.data as JsonApiResource[];\n return resources.map((r) => this.resourceToModel(r));\n }\n\n /**\n * Create a new config.\n *\n * @param options - Config creation options.\n * @returns The created config.\n * @throws {SmplValidationError} If the server rejects the request.\n */\n async create(options: CreateConfigOptions): Promise<Config> {\n const body = this.buildRequestBody(options);\n const response = await this.transport.post(CONFIGS_PATH, body);\n\n if (!response.data) {\n throw new SmplValidationError(\"Failed to create config\");\n }\n\n return this.resourceToModel(response.data as JsonApiResource);\n }\n\n /**\n * Delete a config by UUID.\n *\n * @param configId - The UUID of the config to delete.\n * @throws {SmplNotFoundError} If the config does not exist.\n * @throws {SmplConflictError} If the config has children.\n */\n async delete(configId: string): Promise<void> {\n await this.transport.delete(`${CONFIGS_PATH}/${configId}`);\n }\n\n /** Fetch a config by UUID. */\n private async getById(configId: string): Promise<Config> {\n const response = await this.transport.get(`${CONFIGS_PATH}/${configId}`);\n\n if (!response.data) {\n throw new SmplNotFoundError(`Config ${configId} not found`);\n }\n\n return this.resourceToModel(response.data as JsonApiResource);\n }\n\n /** Fetch a config by key using the list endpoint with a filter. */\n private async getByKey(key: string): Promise<Config> {\n const response = await this.transport.get(CONFIGS_PATH, { \"filter[key]\": key });\n const resources = response.data as JsonApiResource[];\n\n if (!resources || resources.length === 0) {\n throw new SmplNotFoundError(`Config with key '${key}' not found`);\n }\n\n return this.resourceToModel(resources[0]);\n }\n\n /**\n * Convert a JSON:API resource to a Config domain model.\n * @internal\n */\n private resourceToModel(resource: JsonApiResource): Config {\n const attrs = resource.attributes;\n return {\n id: resource.id,\n key: attrs.key ?? \"\",\n name: attrs.name,\n description: attrs.description ?? null,\n parent: attrs.parent ?? null,\n values: attrs.values ?? {},\n environments: attrs.environments ?? {},\n createdAt: attrs.created_at ? new Date(attrs.created_at) : null,\n updatedAt: attrs.updated_at ? new Date(attrs.updated_at) : null,\n };\n }\n\n /** Build a JSON:API request body for create operations. */\n private buildRequestBody(options: CreateConfigOptions): Record<string, unknown> {\n const attributes: Record<string, unknown> = {\n name: options.name,\n };\n\n if (options.key !== undefined) attributes.key = options.key;\n if (options.description !== undefined) attributes.description = options.description;\n if (options.parent !== undefined) attributes.parent = options.parent;\n if (options.values !== undefined) attributes.values = options.values;\n\n return {\n data: {\n type: \"config\",\n attributes,\n },\n };\n }\n}\n","/**\n * Authentication handling for API key auth.\n *\n * @internal This module is not part of the public API.\n */\n\n/**\n * Build the Authorization header value for Bearer token auth.\n *\n * @param apiKey - The API key to use for authentication.\n * @returns The header value string in the form `Bearer {apiKey}`.\n */\nexport function buildAuthHeader(apiKey: string): string {\n return `Bearer ${apiKey}`;\n}\n","/**\n * Internal HTTP client wrapper.\n *\n * Uses native `fetch` with `AbortController` for timeouts. Maps network\n * errors and HTTP status codes to typed SDK exceptions.\n *\n * @internal This module is not part of the public API.\n */\n\nimport { buildAuthHeader } from \"./auth.js\";\nimport {\n SmplConnectionError,\n SmplConflictError,\n SmplError,\n SmplNotFoundError,\n SmplTimeoutError,\n SmplValidationError,\n} from \"./errors.js\";\n\nconst SDK_VERSION = \"0.0.0\";\nconst DEFAULT_TIMEOUT_MS = 30_000;\n\n/** Options for constructing a {@link Transport} instance. */\nexport interface TransportOptions {\n /** The API key used for Bearer token authentication. */\n apiKey: string;\n\n /** Base URL for all API requests. Must not have a trailing slash. */\n baseUrl: string;\n\n /** Request timeout in milliseconds. Defaults to 30 000. */\n timeout?: number;\n}\n\n/** Parsed JSON response from the API. */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype JsonBody = Record<string, any>;\n\n/**\n * Low-level HTTP transport that handles auth, timeouts, and error mapping.\n *\n * @internal\n */\nexport class Transport {\n private readonly apiKey: string;\n private readonly baseUrl: string;\n private readonly timeout: number;\n\n constructor(options: TransportOptions) {\n this.apiKey = options.apiKey;\n this.baseUrl = options.baseUrl.replace(/\\/+$/, \"\");\n this.timeout = options.timeout ?? DEFAULT_TIMEOUT_MS;\n }\n\n /**\n * Send a GET request.\n *\n * @param path - URL path relative to `baseUrl` (e.g. `/api/v1/configs`).\n * @param params - Optional query parameters.\n * @returns Parsed JSON response body.\n */\n async get(path: string, params?: Record<string, string>): Promise<JsonBody> {\n return this.request(\"GET\", path, undefined, params);\n }\n\n /**\n * Send a POST request with a JSON body.\n *\n * @param path - URL path relative to `baseUrl`.\n * @param body - JSON-serializable request body.\n * @returns Parsed JSON response body.\n */\n async post(path: string, body: JsonBody): Promise<JsonBody> {\n return this.request(\"POST\", path, body);\n }\n\n /**\n * Send a PUT request with a JSON body.\n *\n * @param path - URL path relative to `baseUrl`.\n * @param body - JSON-serializable request body.\n * @returns Parsed JSON response body.\n */\n async put(path: string, body: JsonBody): Promise<JsonBody> {\n return this.request(\"PUT\", path, body);\n }\n\n /**\n * Send a DELETE request.\n *\n * @param path - URL path relative to `baseUrl`.\n * @returns Parsed JSON response body (empty object for 204 responses).\n */\n async delete(path: string): Promise<JsonBody> {\n return this.request(\"DELETE\", path);\n }\n\n /**\n * Core request method. Handles headers, timeouts, and error mapping.\n */\n private async request(\n method: string,\n path: string,\n body?: JsonBody,\n params?: Record<string, string>,\n ): Promise<JsonBody> {\n let url = `${this.baseUrl}${path}`;\n\n if (params) {\n const searchParams = new URLSearchParams(params);\n url += `?${searchParams.toString()}`;\n }\n\n const headers: Record<string, string> = {\n Authorization: buildAuthHeader(this.apiKey),\n \"User-Agent\": `smplkit-typescript-sdk/${SDK_VERSION}`,\n Accept: \"application/vnd.api+json\",\n };\n\n if (body !== undefined) {\n headers[\"Content-Type\"] = \"application/vnd.api+json\";\n }\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n let response: Response;\n try {\n response = await fetch(url, {\n method,\n headers,\n body: body !== undefined ? JSON.stringify(body) : undefined,\n signal: controller.signal,\n });\n } catch (error: unknown) {\n clearTimeout(timeoutId);\n if (error instanceof DOMException && error.name === \"AbortError\") {\n throw new SmplTimeoutError(`Request timed out after ${this.timeout}ms`);\n }\n if (error instanceof TypeError) {\n throw new SmplConnectionError(`Network error: ${error.message}`);\n }\n throw new SmplConnectionError(\n `Request failed: ${error instanceof Error ? error.message : String(error)}`,\n );\n } finally {\n clearTimeout(timeoutId);\n }\n\n // 204 No Content — return empty object\n if (response.status === 204) {\n return {};\n }\n\n const responseText = await response.text();\n\n if (!response.ok) {\n this.throwForStatus(response.status, responseText);\n }\n\n try {\n return JSON.parse(responseText) as JsonBody;\n } catch {\n throw new SmplError(`Invalid JSON response: ${responseText}`, response.status, responseText);\n }\n }\n\n /**\n * Map HTTP error status codes to typed SDK exceptions.\n *\n * @throws {SmplNotFoundError} On 404.\n * @throws {SmplConflictError} On 409.\n * @throws {SmplValidationError} On 422.\n * @throws {SmplError} On any other non-2xx status.\n */\n private throwForStatus(status: number, body: string): never {\n switch (status) {\n case 404:\n throw new SmplNotFoundError(body, 404, body);\n case 409:\n throw new SmplConflictError(body, 409, body);\n case 422:\n throw new SmplValidationError(body, 422, body);\n default:\n throw new SmplError(`HTTP ${status}: ${body}`, status, body);\n }\n }\n}\n","/**\n * Top-level SDK client — SmplkitClient.\n *\n * The main entry point for the smplkit TypeScript SDK. Provides access\n * to sub-clients for each API domain (config, flags, logging, etc.).\n */\n\nimport { ConfigClient } from \"./config/client.js\";\nimport { Transport } from \"./transport.js\";\n\nconst DEFAULT_BASE_URL = \"https://config.smplkit.com\";\n\n/** Configuration options for the {@link SmplkitClient}. */\nexport interface SmplkitClientOptions {\n /** API key for authenticating with the smplkit platform. */\n apiKey: string;\n\n /**\n * Base URL for all API requests.\n * @default \"https://config.smplkit.com\"\n */\n baseUrl?: string;\n\n /**\n * Request timeout in milliseconds.\n * @default 30000\n */\n timeout?: number;\n}\n\n/**\n * Entry point for the smplkit TypeScript SDK.\n *\n * @example\n * ```typescript\n * import { SmplkitClient } from \"smplkit\";\n *\n * const client = new SmplkitClient({ apiKey: \"sk_api_...\" });\n * const cfg = await client.config.get({ key: \"common\" });\n * ```\n */\nexport class SmplkitClient {\n /** Client for config management-plane operations. */\n readonly config: ConfigClient;\n\n /** @internal */\n private readonly transport: Transport;\n\n constructor(options: SmplkitClientOptions) {\n if (!options.apiKey) {\n throw new Error(\"apiKey is required\");\n }\n\n this.transport = new Transport({\n apiKey: options.apiKey,\n baseUrl: options.baseUrl ?? DEFAULT_BASE_URL,\n timeout: options.timeout,\n });\n\n this.config = new ConfigClient(this.transport);\n }\n}\n"],"mappings":"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","names":[]}
|