@smplkit/sdk 1.0.1 → 1.1.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 +0 -1
- package/dist/chunk-PZD5PSQY.js +317 -0
- package/dist/chunk-PZD5PSQY.js.map +1 -0
- package/dist/index.cjs +713 -202
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +298 -87
- package/dist/index.d.ts +298 -87
- package/dist/index.js +372 -202
- package/dist/index.js.map +1 -1
- package/dist/runtime-CCRTBKED.js +7 -0
- package/dist/runtime-CCRTBKED.js.map +1 -0
- package/package.json +6 -1
package/dist/index.js
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ConfigRuntime
|
|
3
|
+
} from "./chunk-PZD5PSQY.js";
|
|
4
|
+
|
|
5
|
+
// src/config/client.ts
|
|
6
|
+
import createClient from "openapi-fetch";
|
|
7
|
+
|
|
1
8
|
// src/errors.ts
|
|
2
9
|
var SmplError = class extends Error {
|
|
3
10
|
/** The HTTP status code, if the error originated from an HTTP response. */
|
|
@@ -48,276 +55,439 @@ var SmplValidationError = class extends SmplError {
|
|
|
48
55
|
}
|
|
49
56
|
};
|
|
50
57
|
|
|
51
|
-
// src/config/
|
|
52
|
-
var
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
58
|
+
// src/config/types.ts
|
|
59
|
+
var Config = class {
|
|
60
|
+
/** UUID of the config. */
|
|
61
|
+
id;
|
|
62
|
+
/** Human-readable key (e.g. `"user_service"`). */
|
|
63
|
+
key;
|
|
64
|
+
/** Display name. */
|
|
65
|
+
name;
|
|
66
|
+
/** Optional description. */
|
|
67
|
+
description;
|
|
68
|
+
/** Parent config UUID, or null if this is a root config. */
|
|
69
|
+
parent;
|
|
70
|
+
/** Base key-value pairs. */
|
|
71
|
+
values;
|
|
72
|
+
/**
|
|
73
|
+
* Per-environment overrides.
|
|
74
|
+
* Stored as `{ env_name: { values: { key: value } } }` to match the
|
|
75
|
+
* server's format.
|
|
76
|
+
*/
|
|
77
|
+
environments;
|
|
78
|
+
/** When the config was created, or null if unavailable. */
|
|
79
|
+
createdAt;
|
|
80
|
+
/** When the config was last updated, or null if unavailable. */
|
|
81
|
+
updatedAt;
|
|
82
|
+
/**
|
|
83
|
+
* Internal reference to the parent client.
|
|
84
|
+
* @internal
|
|
85
|
+
*/
|
|
86
|
+
_client;
|
|
56
87
|
/** @internal */
|
|
57
|
-
constructor(
|
|
58
|
-
this.
|
|
88
|
+
constructor(client, fields) {
|
|
89
|
+
this._client = client;
|
|
90
|
+
this.id = fields.id;
|
|
91
|
+
this.key = fields.key;
|
|
92
|
+
this.name = fields.name;
|
|
93
|
+
this.description = fields.description;
|
|
94
|
+
this.parent = fields.parent;
|
|
95
|
+
this.values = fields.values;
|
|
96
|
+
this.environments = fields.environments;
|
|
97
|
+
this.createdAt = fields.createdAt;
|
|
98
|
+
this.updatedAt = fields.updatedAt;
|
|
59
99
|
}
|
|
60
100
|
/**
|
|
61
|
-
*
|
|
101
|
+
* Update this config's attributes on the server.
|
|
62
102
|
*
|
|
63
|
-
*
|
|
103
|
+
* Builds the request from current attribute values, overriding with any
|
|
104
|
+
* provided options. Updates local attributes in place on success.
|
|
64
105
|
*
|
|
65
|
-
* @param options -
|
|
66
|
-
* @
|
|
67
|
-
* @
|
|
68
|
-
* @
|
|
106
|
+
* @param options.name - New display name.
|
|
107
|
+
* @param options.description - New description (pass empty string to clear).
|
|
108
|
+
* @param options.values - New base values (replaces entirely).
|
|
109
|
+
* @param options.environments - New environments dict (replaces entirely).
|
|
69
110
|
*/
|
|
70
|
-
async
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
111
|
+
async update(options) {
|
|
112
|
+
const updated = await this._client._updateConfig({
|
|
113
|
+
configId: this.id,
|
|
114
|
+
name: options.name ?? this.name,
|
|
115
|
+
key: this.key,
|
|
116
|
+
description: options.description !== void 0 ? options.description : this.description,
|
|
117
|
+
parent: this.parent,
|
|
118
|
+
values: options.values ?? this.values,
|
|
119
|
+
environments: options.environments ?? this.environments
|
|
120
|
+
});
|
|
121
|
+
this.name = updated.name;
|
|
122
|
+
this.description = updated.description;
|
|
123
|
+
this.values = updated.values;
|
|
124
|
+
this.environments = updated.environments;
|
|
125
|
+
this.updatedAt = updated.updatedAt;
|
|
79
126
|
}
|
|
80
127
|
/**
|
|
81
|
-
*
|
|
128
|
+
* Replace base or environment-specific values.
|
|
129
|
+
*
|
|
130
|
+
* When `environment` is provided, replaces that environment's `values`
|
|
131
|
+
* sub-dict (other environments are preserved). When omitted, replaces
|
|
132
|
+
* the base `values`.
|
|
82
133
|
*
|
|
83
|
-
* @
|
|
134
|
+
* @param values - The complete set of values to set.
|
|
135
|
+
* @param environment - Target environment, or omit for base values.
|
|
84
136
|
*/
|
|
85
|
-
async
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
137
|
+
async setValues(values, environment) {
|
|
138
|
+
let newValues;
|
|
139
|
+
let newEnvs;
|
|
140
|
+
if (environment === void 0) {
|
|
141
|
+
newValues = values;
|
|
142
|
+
newEnvs = this.environments;
|
|
143
|
+
} else {
|
|
144
|
+
newValues = this.values;
|
|
145
|
+
const existingEntry = typeof this.environments[environment] === "object" && this.environments[environment] !== null ? { ...this.environments[environment] } : {};
|
|
146
|
+
existingEntry.values = values;
|
|
147
|
+
newEnvs = { ...this.environments, [environment]: existingEntry };
|
|
148
|
+
}
|
|
149
|
+
const updated = await this._client._updateConfig({
|
|
150
|
+
configId: this.id,
|
|
151
|
+
name: this.name,
|
|
152
|
+
key: this.key,
|
|
153
|
+
description: this.description,
|
|
154
|
+
parent: this.parent,
|
|
155
|
+
values: newValues,
|
|
156
|
+
environments: newEnvs
|
|
157
|
+
});
|
|
158
|
+
this.values = updated.values;
|
|
159
|
+
this.environments = updated.environments;
|
|
160
|
+
this.updatedAt = updated.updatedAt;
|
|
89
161
|
}
|
|
90
162
|
/**
|
|
91
|
-
*
|
|
163
|
+
* Set a single key within base or environment-specific values.
|
|
92
164
|
*
|
|
93
|
-
*
|
|
94
|
-
*
|
|
95
|
-
* @
|
|
165
|
+
* Merges the key into existing values rather than replacing all values.
|
|
166
|
+
*
|
|
167
|
+
* @param key - The config key to set.
|
|
168
|
+
* @param value - The value to assign.
|
|
169
|
+
* @param environment - Target environment, or omit for base values.
|
|
96
170
|
*/
|
|
97
|
-
async
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
171
|
+
async setValue(key, value, environment) {
|
|
172
|
+
if (environment === void 0) {
|
|
173
|
+
const merged = { ...this.values, [key]: value };
|
|
174
|
+
await this.setValues(merged);
|
|
175
|
+
} else {
|
|
176
|
+
const envEntry = typeof this.environments[environment] === "object" && this.environments[environment] !== null ? this.environments[environment] : {};
|
|
177
|
+
const existing = {
|
|
178
|
+
...typeof envEntry.values === "object" && envEntry.values !== null ? envEntry.values : {}
|
|
179
|
+
};
|
|
180
|
+
existing[key] = value;
|
|
181
|
+
await this.setValues(existing, environment);
|
|
102
182
|
}
|
|
103
|
-
return this.resourceToModel(response.data);
|
|
104
183
|
}
|
|
105
184
|
/**
|
|
106
|
-
*
|
|
185
|
+
* Connect to this config for runtime value resolution.
|
|
107
186
|
*
|
|
108
|
-
*
|
|
109
|
-
*
|
|
110
|
-
* @
|
|
187
|
+
* Eagerly fetches this config and its full parent chain, resolves values
|
|
188
|
+
* for the given environment via deep merge, and returns a
|
|
189
|
+
* {@link ConfigRuntime} with a fully populated local cache.
|
|
190
|
+
*
|
|
191
|
+
* A background WebSocket connection is started for real-time updates.
|
|
192
|
+
* If the WebSocket fails to connect, the runtime operates in cache-only
|
|
193
|
+
* mode and reconnects automatically.
|
|
194
|
+
*
|
|
195
|
+
* Supports both `await` and `await using` (TypeScript 5.2+)::
|
|
196
|
+
*
|
|
197
|
+
* ```typescript
|
|
198
|
+
* // Simple await
|
|
199
|
+
* const runtime = await config.connect("production");
|
|
200
|
+
* try { ... } finally { await runtime.close(); }
|
|
201
|
+
*
|
|
202
|
+
* // await using (auto-close)
|
|
203
|
+
* await using runtime = await config.connect("production");
|
|
204
|
+
* ```
|
|
205
|
+
*
|
|
206
|
+
* @param environment - The environment to resolve for (e.g. `"production"`).
|
|
207
|
+
* @param options.timeout - Milliseconds to wait for the initial fetch.
|
|
111
208
|
*/
|
|
112
|
-
async
|
|
113
|
-
await
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
const response = await this.transport.get(CONFIGS_PATH, { "filter[key]": key });
|
|
126
|
-
const resources = response.data;
|
|
127
|
-
if (!resources || resources.length === 0) {
|
|
128
|
-
throw new SmplNotFoundError(`Config with key '${key}' not found`);
|
|
129
|
-
}
|
|
130
|
-
return this.resourceToModel(resources[0]);
|
|
209
|
+
async connect(environment, options) {
|
|
210
|
+
const { ConfigRuntime: ConfigRuntime2 } = await import("./runtime-CCRTBKED.js");
|
|
211
|
+
const timeout = options?.timeout ?? 3e4;
|
|
212
|
+
const chain = await this._buildChain(timeout);
|
|
213
|
+
return new ConfigRuntime2({
|
|
214
|
+
configKey: this.key,
|
|
215
|
+
configId: this.id,
|
|
216
|
+
environment,
|
|
217
|
+
chain,
|
|
218
|
+
apiKey: this._client._apiKey,
|
|
219
|
+
baseUrl: this._client._baseUrl,
|
|
220
|
+
fetchChain: () => this._buildChain(timeout)
|
|
221
|
+
});
|
|
131
222
|
}
|
|
132
223
|
/**
|
|
133
|
-
*
|
|
224
|
+
* Walk the parent chain and return config data objects, child-to-root.
|
|
134
225
|
* @internal
|
|
135
226
|
*/
|
|
136
|
-
|
|
137
|
-
const
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
227
|
+
async _buildChain(_timeout) {
|
|
228
|
+
const chain = [{ id: this.id, values: this.values, environments: this.environments }];
|
|
229
|
+
let parentId = this.parent;
|
|
230
|
+
while (parentId !== null) {
|
|
231
|
+
const parentConfig = await this._client.get({ id: parentId });
|
|
232
|
+
chain.push({
|
|
233
|
+
id: parentConfig.id,
|
|
234
|
+
values: parentConfig.values,
|
|
235
|
+
environments: parentConfig.environments
|
|
236
|
+
});
|
|
237
|
+
parentId = parentConfig.parent;
|
|
238
|
+
}
|
|
239
|
+
return chain;
|
|
149
240
|
}
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
const attributes = {
|
|
153
|
-
name: options.name
|
|
154
|
-
};
|
|
155
|
-
if (options.key !== void 0) attributes.key = options.key;
|
|
156
|
-
if (options.description !== void 0) attributes.description = options.description;
|
|
157
|
-
if (options.parent !== void 0) attributes.parent = options.parent;
|
|
158
|
-
if (options.values !== void 0) attributes.values = options.values;
|
|
159
|
-
return {
|
|
160
|
-
data: {
|
|
161
|
-
type: "config",
|
|
162
|
-
attributes
|
|
163
|
-
}
|
|
164
|
-
};
|
|
241
|
+
toString() {
|
|
242
|
+
return `Config(id=${this.id}, key=${this.key}, name=${this.name})`;
|
|
165
243
|
}
|
|
166
244
|
};
|
|
167
245
|
|
|
168
|
-
// src/
|
|
169
|
-
|
|
170
|
-
|
|
246
|
+
// src/config/client.ts
|
|
247
|
+
var BASE_URL = "https://config.smplkit.com";
|
|
248
|
+
function resourceToConfig(resource, client) {
|
|
249
|
+
const attrs = resource.attributes;
|
|
250
|
+
return new Config(client, {
|
|
251
|
+
id: resource.id ?? "",
|
|
252
|
+
key: attrs.key ?? "",
|
|
253
|
+
name: attrs.name,
|
|
254
|
+
description: attrs.description ?? null,
|
|
255
|
+
parent: attrs.parent ?? null,
|
|
256
|
+
values: attrs.values ?? {},
|
|
257
|
+
environments: attrs.environments ?? {},
|
|
258
|
+
createdAt: attrs.created_at ? new Date(attrs.created_at) : null,
|
|
259
|
+
updatedAt: attrs.updated_at ? new Date(attrs.updated_at) : null
|
|
260
|
+
});
|
|
171
261
|
}
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
262
|
+
async function checkError(response, context) {
|
|
263
|
+
const body = await response.text().catch(() => "");
|
|
264
|
+
switch (response.status) {
|
|
265
|
+
case 404:
|
|
266
|
+
throw new SmplNotFoundError(body || context, 404, body);
|
|
267
|
+
case 409:
|
|
268
|
+
throw new SmplConflictError(body || context, 409, body);
|
|
269
|
+
case 422:
|
|
270
|
+
throw new SmplValidationError(body || context, 422, body);
|
|
271
|
+
default:
|
|
272
|
+
throw new SmplError(`HTTP ${response.status}: ${body}`, response.status, body);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
function wrapFetchError(err) {
|
|
276
|
+
if (err instanceof SmplNotFoundError || err instanceof SmplConflictError || err instanceof SmplValidationError || err instanceof SmplError) {
|
|
277
|
+
throw err;
|
|
278
|
+
}
|
|
279
|
+
if (err instanceof TypeError) {
|
|
280
|
+
throw new SmplConnectionError(`Network error: ${err.message}`);
|
|
281
|
+
}
|
|
282
|
+
throw new SmplConnectionError(
|
|
283
|
+
`Request failed: ${err instanceof Error ? err.message : String(err)}`
|
|
284
|
+
);
|
|
285
|
+
}
|
|
286
|
+
function buildRequestBody(options) {
|
|
287
|
+
const attrs = {
|
|
288
|
+
name: options.name
|
|
289
|
+
};
|
|
290
|
+
if (options.key !== void 0) attrs.key = options.key;
|
|
291
|
+
if (options.description !== void 0) attrs.description = options.description;
|
|
292
|
+
if (options.parent !== void 0) attrs.parent = options.parent;
|
|
293
|
+
if (options.values !== void 0)
|
|
294
|
+
attrs.values = options.values;
|
|
295
|
+
if (options.environments !== void 0)
|
|
296
|
+
attrs.environments = options.environments;
|
|
297
|
+
return {
|
|
298
|
+
data: {
|
|
299
|
+
id: options.id ?? null,
|
|
300
|
+
type: "config",
|
|
301
|
+
attributes: attrs
|
|
302
|
+
}
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
var ConfigClient = class {
|
|
306
|
+
/** @internal — used by Config instances for reconnecting and WebSocket auth. */
|
|
307
|
+
_apiKey;
|
|
308
|
+
/** @internal */
|
|
309
|
+
_baseUrl = BASE_URL;
|
|
310
|
+
/** @internal */
|
|
311
|
+
_http;
|
|
312
|
+
/** @internal */
|
|
313
|
+
constructor(apiKey, timeout) {
|
|
314
|
+
this._apiKey = apiKey;
|
|
315
|
+
const ms = timeout ?? 3e4;
|
|
316
|
+
this._http = createClient({
|
|
317
|
+
baseUrl: BASE_URL,
|
|
318
|
+
headers: {
|
|
319
|
+
Authorization: `Bearer ${apiKey}`,
|
|
320
|
+
Accept: "application/json"
|
|
321
|
+
},
|
|
322
|
+
// openapi-fetch custom fetch receives a pre-built Request object
|
|
323
|
+
fetch: async (request) => {
|
|
324
|
+
const controller = new AbortController();
|
|
325
|
+
const timer = setTimeout(() => controller.abort(), ms);
|
|
326
|
+
try {
|
|
327
|
+
return await fetch(new Request(request, { signal: controller.signal }));
|
|
328
|
+
} catch (err) {
|
|
329
|
+
if (err instanceof DOMException && err.name === "AbortError") {
|
|
330
|
+
throw new SmplTimeoutError(`Request timed out after ${ms}ms`);
|
|
331
|
+
}
|
|
332
|
+
throw err;
|
|
333
|
+
} finally {
|
|
334
|
+
clearTimeout(timer);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
});
|
|
184
338
|
}
|
|
185
339
|
/**
|
|
186
|
-
*
|
|
340
|
+
* Fetch a single config by key or UUID.
|
|
341
|
+
*
|
|
342
|
+
* Exactly one of `key` or `id` must be provided.
|
|
187
343
|
*
|
|
188
|
-
* @
|
|
189
|
-
* @param params - Optional query parameters.
|
|
190
|
-
* @returns Parsed JSON response body.
|
|
344
|
+
* @throws {SmplNotFoundError} If no matching config exists.
|
|
191
345
|
*/
|
|
192
|
-
async get(
|
|
193
|
-
|
|
346
|
+
async get(options) {
|
|
347
|
+
const { key, id } = options;
|
|
348
|
+
if (key === void 0 === (id === void 0)) {
|
|
349
|
+
throw new Error("Exactly one of 'key' or 'id' must be provided.");
|
|
350
|
+
}
|
|
351
|
+
return id !== void 0 ? this._getById(id) : this._getByKey(key);
|
|
194
352
|
}
|
|
195
353
|
/**
|
|
196
|
-
*
|
|
197
|
-
*
|
|
198
|
-
* @param path - URL path relative to `baseUrl`.
|
|
199
|
-
* @param body - JSON-serializable request body.
|
|
200
|
-
* @returns Parsed JSON response body.
|
|
354
|
+
* List all configs for the account.
|
|
201
355
|
*/
|
|
202
|
-
async
|
|
203
|
-
|
|
356
|
+
async list() {
|
|
357
|
+
let data;
|
|
358
|
+
try {
|
|
359
|
+
const result = await this._http.GET("/api/v1/configs", {});
|
|
360
|
+
if (result.error !== void 0) await checkError(result.response, "Failed to list configs");
|
|
361
|
+
data = result.data;
|
|
362
|
+
} catch (err) {
|
|
363
|
+
wrapFetchError(err);
|
|
364
|
+
}
|
|
365
|
+
if (!data) return [];
|
|
366
|
+
return data.data.map((r) => resourceToConfig(r, this));
|
|
204
367
|
}
|
|
205
368
|
/**
|
|
206
|
-
*
|
|
369
|
+
* Create a new config.
|
|
207
370
|
*
|
|
208
|
-
* @
|
|
209
|
-
* @param body - JSON-serializable request body.
|
|
210
|
-
* @returns Parsed JSON response body.
|
|
371
|
+
* @throws {SmplValidationError} If the server rejects the request.
|
|
211
372
|
*/
|
|
212
|
-
async
|
|
213
|
-
|
|
373
|
+
async create(options) {
|
|
374
|
+
const body = buildRequestBody({
|
|
375
|
+
name: options.name,
|
|
376
|
+
key: options.key,
|
|
377
|
+
description: options.description,
|
|
378
|
+
parent: options.parent,
|
|
379
|
+
values: options.values
|
|
380
|
+
});
|
|
381
|
+
let data;
|
|
382
|
+
try {
|
|
383
|
+
const result = await this._http.POST("/api/v1/configs", { body });
|
|
384
|
+
if (result.error !== void 0) await checkError(result.response, "Failed to create config");
|
|
385
|
+
data = result.data;
|
|
386
|
+
} catch (err) {
|
|
387
|
+
wrapFetchError(err);
|
|
388
|
+
}
|
|
389
|
+
if (!data || !data.data) throw new SmplValidationError("Failed to create config");
|
|
390
|
+
return resourceToConfig(data.data, this);
|
|
214
391
|
}
|
|
215
392
|
/**
|
|
216
|
-
*
|
|
393
|
+
* Delete a config by UUID.
|
|
217
394
|
*
|
|
218
|
-
* @
|
|
219
|
-
* @
|
|
395
|
+
* @throws {SmplNotFoundError} If the config does not exist.
|
|
396
|
+
* @throws {SmplConflictError} If the config has child configs.
|
|
220
397
|
*/
|
|
221
|
-
async delete(
|
|
222
|
-
|
|
398
|
+
async delete(configId) {
|
|
399
|
+
try {
|
|
400
|
+
const result = await this._http.DELETE("/api/v1/configs/{id}", {
|
|
401
|
+
params: { path: { id: configId } }
|
|
402
|
+
});
|
|
403
|
+
if (result.error !== void 0 && result.response.status !== 204)
|
|
404
|
+
await checkError(result.response, `Failed to delete config ${configId}`);
|
|
405
|
+
} catch (err) {
|
|
406
|
+
wrapFetchError(err);
|
|
407
|
+
}
|
|
223
408
|
}
|
|
224
409
|
/**
|
|
225
|
-
*
|
|
410
|
+
* Internal: PUT a full config update and return the updated model.
|
|
411
|
+
*
|
|
412
|
+
* Called by {@link Config} instance methods.
|
|
413
|
+
* @internal
|
|
226
414
|
*/
|
|
227
|
-
async
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
if (body !== void 0) {
|
|
239
|
-
headers["Content-Type"] = "application/vnd.api+json";
|
|
240
|
-
}
|
|
241
|
-
const controller = new AbortController();
|
|
242
|
-
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
243
|
-
let response;
|
|
415
|
+
async _updateConfig(payload) {
|
|
416
|
+
const body = buildRequestBody({
|
|
417
|
+
id: payload.configId,
|
|
418
|
+
name: payload.name,
|
|
419
|
+
key: payload.key,
|
|
420
|
+
description: payload.description,
|
|
421
|
+
parent: payload.parent,
|
|
422
|
+
values: payload.values,
|
|
423
|
+
environments: payload.environments
|
|
424
|
+
});
|
|
425
|
+
let data;
|
|
244
426
|
try {
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
body: body !== void 0 ? JSON.stringify(body) : void 0,
|
|
249
|
-
signal: controller.signal
|
|
427
|
+
const result = await this._http.PUT("/api/v1/configs/{id}", {
|
|
428
|
+
params: { path: { id: payload.configId } },
|
|
429
|
+
body
|
|
250
430
|
});
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
if (error instanceof TypeError) {
|
|
257
|
-
throw new SmplConnectionError(`Network error: ${error.message}`);
|
|
258
|
-
}
|
|
259
|
-
throw new SmplConnectionError(
|
|
260
|
-
`Request failed: ${error instanceof Error ? error.message : String(error)}`
|
|
261
|
-
);
|
|
262
|
-
} finally {
|
|
263
|
-
clearTimeout(timeoutId);
|
|
264
|
-
}
|
|
265
|
-
if (response.status === 204) {
|
|
266
|
-
return {};
|
|
267
|
-
}
|
|
268
|
-
const responseText = await response.text();
|
|
269
|
-
if (!response.ok) {
|
|
270
|
-
this.throwForStatus(response.status, responseText);
|
|
431
|
+
if (result.error !== void 0)
|
|
432
|
+
await checkError(result.response, `Failed to update config ${payload.configId}`);
|
|
433
|
+
data = result.data;
|
|
434
|
+
} catch (err) {
|
|
435
|
+
wrapFetchError(err);
|
|
271
436
|
}
|
|
437
|
+
if (!data || !data.data)
|
|
438
|
+
throw new SmplValidationError(`Failed to update config ${payload.configId}`);
|
|
439
|
+
return resourceToConfig(data.data, this);
|
|
440
|
+
}
|
|
441
|
+
// ---- Private helpers ----
|
|
442
|
+
async _getById(configId) {
|
|
443
|
+
let data;
|
|
272
444
|
try {
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
445
|
+
const result = await this._http.GET("/api/v1/configs/{id}", {
|
|
446
|
+
params: { path: { id: configId } }
|
|
447
|
+
});
|
|
448
|
+
if (result.error !== void 0)
|
|
449
|
+
await checkError(result.response, `Config ${configId} not found`);
|
|
450
|
+
data = result.data;
|
|
451
|
+
} catch (err) {
|
|
452
|
+
wrapFetchError(err);
|
|
276
453
|
}
|
|
454
|
+
if (!data || !data.data) throw new SmplNotFoundError(`Config ${configId} not found`);
|
|
455
|
+
return resourceToConfig(data.data, this);
|
|
277
456
|
}
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
case 422:
|
|
293
|
-
throw new SmplValidationError(body, 422, body);
|
|
294
|
-
default:
|
|
295
|
-
throw new SmplError(`HTTP ${status}: ${body}`, status, body);
|
|
457
|
+
async _getByKey(key) {
|
|
458
|
+
let data;
|
|
459
|
+
try {
|
|
460
|
+
const result = await this._http.GET("/api/v1/configs", {
|
|
461
|
+
params: { query: { "filter[key]": key } }
|
|
462
|
+
});
|
|
463
|
+
if (result.error !== void 0)
|
|
464
|
+
await checkError(result.response, `Config with key '${key}' not found`);
|
|
465
|
+
data = result.data;
|
|
466
|
+
} catch (err) {
|
|
467
|
+
wrapFetchError(err);
|
|
468
|
+
}
|
|
469
|
+
if (!data || !data.data || data.data.length === 0) {
|
|
470
|
+
throw new SmplNotFoundError(`Config with key '${key}' not found`);
|
|
296
471
|
}
|
|
472
|
+
return resourceToConfig(data.data[0], this);
|
|
297
473
|
}
|
|
298
474
|
};
|
|
299
475
|
|
|
300
476
|
// src/client.ts
|
|
301
|
-
var DEFAULT_BASE_URL = "https://config.smplkit.com";
|
|
302
477
|
var SmplkitClient = class {
|
|
303
478
|
/** Client for config management-plane operations. */
|
|
304
479
|
config;
|
|
305
|
-
/** @internal */
|
|
306
|
-
transport;
|
|
307
480
|
constructor(options) {
|
|
308
481
|
if (!options.apiKey) {
|
|
309
482
|
throw new Error("apiKey is required");
|
|
310
483
|
}
|
|
311
|
-
this.
|
|
312
|
-
apiKey: options.apiKey,
|
|
313
|
-
baseUrl: options.baseUrl ?? DEFAULT_BASE_URL,
|
|
314
|
-
timeout: options.timeout
|
|
315
|
-
});
|
|
316
|
-
this.config = new ConfigClient(this.transport);
|
|
484
|
+
this.config = new ConfigClient(options.apiKey, options.timeout);
|
|
317
485
|
}
|
|
318
486
|
};
|
|
319
487
|
export {
|
|
488
|
+
Config,
|
|
320
489
|
ConfigClient,
|
|
490
|
+
ConfigRuntime,
|
|
321
491
|
SmplConflictError,
|
|
322
492
|
SmplConnectionError,
|
|
323
493
|
SmplError,
|