@smplkit/sdk 1.3.12 → 1.3.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -46,36 +46,19 @@ declare class SharedWebSocket {
46
46
  }
47
47
 
48
48
  /**
49
- * Config resource — management-plane model.
50
- *
51
- * Instances are returned by {@link ConfigClient} methods and provide
52
- * management-plane operations (`update`, `setValues`, `setValue`).
53
- * Prescriptive value access is via `client.config.getValue()` after
54
- * `client.connect()`.
55
- */
56
- /**
57
- * Internal type used by {@link ConfigClient}. Not part of the public API.
58
- * @internal
49
+ * Config resource — active-record model with save() pattern.
59
50
  */
60
- interface ConfigUpdatePayload {
61
- configId: string;
62
- name: string;
63
- key: string | null;
64
- description: string | null;
65
- parent: string | null;
66
- items: Record<string, unknown>;
67
- environments: Record<string, unknown>;
68
- }
51
+
69
52
  /**
70
- * A configuration resource fetched from the smplkit Config service.
53
+ * A configuration resource managed by the smplkit platform.
71
54
  *
72
- * Instances are returned by {@link ConfigClient} methods and provide
73
- * management-plane operations (update, setValues, setValue).
55
+ * Management: mutate properties directly and call `save()` to persist.
56
+ * POST if `id` is null (new), PUT if `id` is set (update).
74
57
  */
75
58
  declare class Config {
76
- /** UUID of the config. */
77
- id: string;
78
- /** Human-readable key (e.g. `"user_service"`). */
59
+ /** UUID of the config, or `null` if unsaved. */
60
+ id: string | null;
61
+ /** Human-readable key (e.g. `"user-service"`). */
79
62
  key: string;
80
63
  /** Display name. */
81
64
  name: string;
@@ -92,102 +75,75 @@ declare class Config {
92
75
  */
93
76
  environments: Record<string, unknown>;
94
77
  /** When the config was created, or null if unavailable. */
95
- createdAt: Date | null;
78
+ createdAt: string | null;
96
79
  /** When the config was last updated, or null if unavailable. */
97
- updatedAt: Date | null;
98
- /**
99
- * Internal reference to the parent client.
100
- * @internal
101
- */
102
- private readonly _client;
80
+ updatedAt: string | null;
103
81
  /** @internal */
104
- constructor(client: {
105
- _updateConfig(payload: ConfigUpdatePayload): Promise<Config>;
106
- get(options: {
107
- id: string;
108
- }): Promise<Config>;
109
- readonly _apiKey: string;
110
- readonly _baseUrl: string;
111
- _getSharedWs?: () => SharedWebSocket;
112
- }, fields: {
113
- id: string;
82
+ readonly _client: ConfigClient;
83
+ /** @internal */
84
+ constructor(client: ConfigClient, fields: {
85
+ id: string | null;
114
86
  key: string;
115
87
  name: string;
116
88
  description: string | null;
117
89
  parent: string | null;
118
90
  items: Record<string, unknown>;
119
91
  environments: Record<string, unknown>;
120
- createdAt: Date | null;
121
- updatedAt: Date | null;
92
+ createdAt: string | null;
93
+ updatedAt: string | null;
122
94
  });
123
95
  /**
124
- * Update this config's attributes on the server.
125
- *
126
- * Builds the request from current attribute values, overriding with any
127
- * provided options. Updates local attributes in place on success.
128
- *
129
- * @param options.name - New display name.
130
- * @param options.description - New description (pass empty string to clear).
131
- * @param options.items - New base values (replaces entirely).
132
- * @param options.environments - New environments dict (replaces entirely).
133
- */
134
- update(options: {
135
- name?: string;
136
- description?: string;
137
- items?: Record<string, unknown>;
138
- environments?: Record<string, unknown>;
139
- }): Promise<void>;
140
- /**
141
- * Replace base or environment-specific values.
142
- *
143
- * When `environment` is provided, replaces that environment's `values`
144
- * sub-dict (other environments are preserved). When omitted, replaces
145
- * the base `items`.
146
- *
147
- * @param values - The complete set of values to set.
148
- * @param environment - Target environment, or omit for base values.
149
- */
150
- setValues(values: Record<string, unknown>, environment?: string): Promise<void>;
151
- /**
152
- * Set a single key within base or environment-specific values.
153
- *
154
- * Merges the key into existing values rather than replacing all values.
96
+ * Persist this config to the server.
155
97
  *
156
- * @param key - The config key to set.
157
- * @param value - The value to assign.
158
- * @param environment - Target environment, or omit for base values.
98
+ * POST if `id` is null (new config), PUT if `id` is set (update).
99
+ * Updates this instance in-place with the server response.
159
100
  */
160
- setValue(key: string, value: unknown, environment?: string): Promise<void>;
101
+ save(): Promise<void>;
161
102
  /**
162
103
  * Walk the parent chain and return config data objects, child-to-root.
163
104
  * @internal
164
105
  */
165
- _buildChain(_timeout?: unknown): Promise<Array<{
106
+ _buildChain(): Promise<Array<{
166
107
  id: string;
167
108
  items: Record<string, unknown>;
168
109
  environments: Record<string, unknown>;
169
110
  }>>;
111
+ /** @internal — copy all fields from another Config instance. */
112
+ _apply(other: Config): void;
170
113
  toString(): string;
171
114
  }
172
- /** Options for creating a new config. */
173
- interface CreateConfigOptions {
174
- /** Display name for the config. */
175
- name: string;
176
- /** Human-readable key. Auto-generated by the server if omitted. */
177
- key?: string;
178
- /** Optional description. */
179
- description?: string;
180
- /** Parent config UUID. Defaults to the account's `common` config if omitted. */
181
- parent?: string;
182
- /** Initial base values. */
183
- items?: Record<string, unknown>;
184
- }
185
- /** Options for fetching a single config. Exactly one of `key` or `id` must be provided. */
186
- interface GetConfigOptions {
187
- /** Fetch by human-readable key. */
188
- key?: string;
189
- /** Fetch by UUID. */
190
- id?: string;
115
+
116
+ /**
117
+ * LiveConfigProxy ES6 Proxy-based live configuration access.
118
+ *
119
+ * Property reads are delegated to the latest resolved values in the
120
+ * ConfigClient cache. When the cache updates via WebSocket, subsequent
121
+ * reads automatically reflect the new values.
122
+ */
123
+
124
+ /**
125
+ * A live proxy that auto-updates when the underlying config changes.
126
+ *
127
+ * Access properties directly — each read re-resolves from the cache.
128
+ *
129
+ * @example
130
+ * ```typescript
131
+ * const proxy = await client.config.subscribe("user-service");
132
+ * console.log(proxy.timeout); // reads from live cache
133
+ * // ... later, after a WebSocket update ...
134
+ * console.log(proxy.timeout); // reads the updated value
135
+ * ```
136
+ */
137
+ declare class LiveConfigProxy<T = Record<string, unknown>> {
138
+ /** @internal */
139
+ private readonly _client;
140
+ /** @internal */
141
+ private readonly _key;
142
+ /** @internal */
143
+ private readonly _model?;
144
+ constructor(client: ConfigClient, key: string, model?: new (data: any) => T);
145
+ /** @internal */
146
+ _currentValues(): Record<string, unknown>;
191
147
  }
192
148
 
193
149
  /** Describes a single config value change detected on refresh. */
@@ -204,15 +160,12 @@ interface ConfigChangeEvent {
204
160
  source: "websocket" | "manual";
205
161
  }
206
162
  /**
207
- * Client for the smplkit Config API (management plane).
208
- *
209
- * All methods are async and return `Promise<T>`. Network and server
210
- * errors are mapped to typed SDK exceptions.
163
+ * Client for the smplkit Config API management plane + runtime.
211
164
  *
212
165
  * Obtained via `SmplClient.config`.
213
166
  */
214
167
  declare class ConfigClient {
215
- /** @internal — used by Config instances for reconnecting and WebSocket auth. */
168
+ /** @internal */
216
169
  readonly _apiKey: string;
217
170
  /** @internal */
218
171
  readonly _baseUrl: string;
@@ -226,205 +179,287 @@ declare class ConfigClient {
226
179
  readonly _service: string | null;
227
180
  } | null;
228
181
  private _configCache;
229
- private _connected;
182
+ private _initialized;
230
183
  private _listeners;
231
184
  /** @internal */
232
185
  constructor(apiKey: string, timeout?: number);
233
- /**
234
- * Fetch a single config by key or UUID.
235
- *
236
- * Exactly one of `key` or `id` must be provided.
237
- *
238
- * @throws {SmplNotFoundError} If no matching config exists.
239
- */
240
- get(options: GetConfigOptions): Promise<Config>;
241
- /**
242
- * List all configs for the account.
243
- */
186
+ /** Create an unsaved config. Call `.save()` to persist. */
187
+ new(key: string, options?: {
188
+ name?: string;
189
+ description?: string;
190
+ parent?: string;
191
+ }): Config;
192
+ /** Fetch a config by key. */
193
+ get(key: string): Promise<Config>;
194
+ /** List all configs. */
244
195
  list(): Promise<Config[]>;
196
+ /** Delete a config by key. */
197
+ delete(key: string): Promise<void>;
198
+ /** @internal — POST a new config. */
199
+ _createConfig(config: Config): Promise<Config>;
200
+ /** @internal — PUT a config update. */
201
+ _updateConfig(config: Config): Promise<Config>;
202
+ /** @internal — fetch a config by UUID. */
203
+ _getById(configId: string): Promise<Config>;
245
204
  /**
246
- * Create a new config.
247
- *
248
- * @throws {SmplValidationError} If the server rejects the request.
249
- */
250
- create(options: CreateConfigOptions): Promise<Config>;
251
- /**
252
- * Delete a config by UUID.
253
- *
254
- * @throws {SmplNotFoundError} If the config does not exist.
255
- * @throws {SmplConflictError} If the config has child configs.
256
- */
257
- delete(configId: string): Promise<void>;
258
- /**
259
- * Fetch all configs, resolve values for the environment, and cache.
260
- * @internal — called by SmplClient.connect().
261
- */
262
- _connectInternal(environment: string): Promise<void>;
263
- /**
264
- * Read a resolved config value (prescriptive access).
265
- *
266
- * Requires {@link SmplClient.connect} to have been called.
267
- *
268
- * @param configKey - The config key to look up.
269
- * @param itemKey - Optional specific item key. If omitted, returns all values.
270
- * @param defaultValue - Default value if the key is missing.
205
+ * Resolve a config's values for the current environment.
271
206
  *
272
- * @throws {SmplNotConnectedError} If connect() has not been called.
273
- */
274
- getValue(configKey: string, itemKey?: string, defaultValue?: unknown): unknown;
275
- /**
276
- * Return a config value as a string, or `defaultValue` if absent or not a string.
207
+ * Returns a flat dict of resolved key-value pairs, walking the
208
+ * parent chain and applying environment overrides.
277
209
  *
278
- * @throws {SmplNotConnectedError} If connect() has not been called.
210
+ * Optionally pass a model class to map the resolved values.
279
211
  */
280
- getString(configKey: string, itemKey: string, defaultValue?: string | null): string | null;
212
+ resolve<T = Record<string, unknown>>(key: string, model?: new (data: any) => T): Promise<T>;
281
213
  /**
282
- * Return a config value as a number, or `defaultValue` if absent or not a number.
214
+ * Subscribe to a config's values returns a live proxy that
215
+ * auto-updates when the underlying config changes.
283
216
  *
284
- * @throws {SmplNotConnectedError} If connect() has not been called.
217
+ * Optionally pass a model class to map the resolved values.
285
218
  */
286
- getInt(configKey: string, itemKey: string, defaultValue?: number | null): number | null;
219
+ subscribe<T = Record<string, unknown>>(key: string, model?: new (data: any) => T): Promise<LiveConfigProxy<T>>;
287
220
  /**
288
- * Return a config value as a boolean, or `defaultValue` if absent or not a boolean.
221
+ * Register a change listener.
289
222
  *
290
- * @throws {SmplNotConnectedError} If connect() has not been called.
223
+ * - `onChange(callback)` fires for any config change (global).
224
+ * - `onChange(configKey, callback)` — fires for changes to a specific config.
225
+ * - `onChange(configKey, itemKey, callback)` — fires for a specific item.
291
226
  */
292
- getBool(configKey: string, itemKey: string, defaultValue?: boolean | null): boolean | null;
227
+ onChange(callbackOrConfigKey: string | ((event: ConfigChangeEvent) => void), callbackOrItemKey?: string | ((event: ConfigChangeEvent) => void), callback?: (event: ConfigChangeEvent) => void): void;
293
228
  /**
294
229
  * Re-fetch all configs, re-resolve values, and update the cache.
295
- *
296
- * Fires change listeners for any values that differ from the previous cache.
297
- *
298
- * @throws {SmplNotConnectedError} If connect() has not been called.
230
+ * Fires change listeners for any values that differ.
299
231
  */
300
232
  refresh(): Promise<void>;
301
- /**
302
- * Register a listener that fires when a config value changes (on refresh).
303
- *
304
- * @param callback - Called with a {@link ConfigChangeEvent} on each change.
305
- * @param options.configKey - If provided, only fire for changes to this config.
306
- * @param options.itemKey - If provided, only fire for changes to this item key.
307
- */
308
- onChange(callback: (event: ConfigChangeEvent) => void, options?: {
309
- configKey?: string;
310
- itemKey?: string;
311
- }): void;
233
+ /** @internal */
234
+ private _ensureInitialized;
235
+ /** @internal — called by SmplClient for backward compat. */
236
+ _connectInternal(environment: string): Promise<void>;
237
+ /** @internal get resolved config from cache. Used by LiveConfigProxy. */
238
+ _getCachedConfig(key: string): Record<string, unknown> | undefined;
239
+ private _handleConfigChanged;
312
240
  /** @internal */
313
241
  private _diffAndFire;
314
- /**
315
- * Internal: PUT a full config update and return the updated model.
316
- *
317
- * Called by {@link Config} instance methods.
318
- * @internal
319
- */
320
- _updateConfig(payload: ConfigUpdatePayload): Promise<Config>;
321
- private _getById;
322
242
  private _getByKey;
323
243
  }
324
244
 
325
- /**
326
- * Flag and ContextType resource models returned by the management API.
327
- */
328
-
329
- /**
330
- * A flag resource returned by {@link FlagsClient} management methods.
331
- *
332
- * Provides `update()` for partial updates and `addRule()` for
333
- * conveniently appending a rule to an environment.
334
- */
335
- declare class Flag {
336
- /** UUID of the flag. */
337
- id: string;
338
- /** Unique key within the account. */
339
- key: string;
340
- /** Human-readable display name. */
341
- name: string;
342
- /** Value type: BOOLEAN, STRING, NUMERIC, or JSON. */
343
- type: string;
344
- /** Flag-level default value. */
345
- default: unknown;
346
- /** Closed set of possible values. */
347
- values: Array<{
348
- name: string;
349
- value: unknown;
350
- }>;
351
- /** Optional description. */
352
- description: string | null;
353
- /** Per-environment configuration. */
354
- environments: Record<string, any>;
355
- /** When the flag was created. */
356
- createdAt: string | null;
357
- /** When the flag was last updated. */
358
- updatedAt: string | null;
359
- /** @internal */
360
- private readonly _client;
361
- /** @internal */
362
- constructor(client: FlagsClient, fields: {
363
- id: string;
364
- key: string;
365
- name: string;
366
- type: string;
367
- default: unknown;
368
- values: Array<{
245
+ interface components {
246
+ schemas: {
247
+ /**
248
+ * Flag
249
+ * @example {
250
+ * "created_at": "2026-03-27T10:00:00Z",
251
+ * "default": false,
252
+ * "description": "Enable dark mode for the application UI",
253
+ * "environments": {
254
+ * "production": {
255
+ * "default": false,
256
+ * "enabled": true,
257
+ * "rules": [
258
+ * {
259
+ * "description": "Beta users get dark mode",
260
+ * "logic": {
261
+ * "attribute": "beta",
262
+ * "op": "eq",
263
+ * "value": true
264
+ * },
265
+ * "value": true
266
+ * }
267
+ * ]
268
+ * },
269
+ * "staging": {
270
+ * "default": true,
271
+ * "enabled": true,
272
+ * "rules": []
273
+ * }
274
+ * },
275
+ * "key": "dark_mode",
276
+ * "name": "Dark Mode",
277
+ * "type": "BOOLEAN",
278
+ * "updated_at": "2026-03-27T10:00:00Z",
279
+ * "values": [
280
+ * {
281
+ * "name": "on",
282
+ * "value": true
283
+ * },
284
+ * {
285
+ * "name": "off",
286
+ * "value": false
287
+ * }
288
+ * ]
289
+ * }
290
+ */
291
+ Flag: {
292
+ /**
293
+ * Key
294
+ * @description Unique key within account
295
+ */
296
+ key: string;
297
+ /**
298
+ * Name
299
+ * @description Human-readable display name
300
+ */
369
301
  name: string;
302
+ /**
303
+ * Description
304
+ * @default
305
+ */
306
+ description: string;
307
+ /**
308
+ * Type
309
+ * @description Value type: STRING, BOOLEAN, NUMERIC, or JSON
310
+ */
311
+ type: string;
312
+ /**
313
+ * Default
314
+ * @description Default value; must reference a value in the values array
315
+ */
316
+ default: unknown;
317
+ /**
318
+ * Values
319
+ * @description Closed set of possible values
320
+ */
321
+ values: components["schemas"]["FlagValue"][];
322
+ /** Environments */
323
+ environments?: {
324
+ [key: string]: components["schemas"]["FlagEnvironment"];
325
+ };
326
+ /** Created At */
327
+ readonly created_at?: string | null;
328
+ /** Updated At */
329
+ readonly updated_at?: string | null;
330
+ };
331
+ /** FlagEnvironment */
332
+ FlagEnvironment: {
333
+ /**
334
+ * Enabled
335
+ * @default false
336
+ */
337
+ enabled: boolean;
338
+ /** Default */
339
+ default?: unknown | null;
340
+ /** Rules */
341
+ rules?: components["schemas"]["FlagRule"][];
342
+ };
343
+ /** FlagListResponse */
344
+ FlagListResponse: {
345
+ /** Data */
346
+ data: components["schemas"]["FlagResource"][];
347
+ };
348
+ /**
349
+ * FlagResource
350
+ * @example {
351
+ * "attributes": {
352
+ * "created_at": "2026-03-27T10:00:00Z",
353
+ * "default": false,
354
+ * "description": "Enable dark mode for the application UI",
355
+ * "environments": {
356
+ * "production": {
357
+ * "default": false,
358
+ * "enabled": true,
359
+ * "rules": [
360
+ * {
361
+ * "description": "Beta users get dark mode",
362
+ * "logic": {
363
+ * "attribute": "beta",
364
+ * "op": "eq",
365
+ * "value": true
366
+ * },
367
+ * "value": true
368
+ * }
369
+ * ]
370
+ * }
371
+ * },
372
+ * "key": "dark_mode",
373
+ * "name": "Dark Mode",
374
+ * "type": "BOOLEAN",
375
+ * "updated_at": "2026-03-27T10:00:00Z",
376
+ * "values": [
377
+ * {
378
+ * "name": "on",
379
+ * "value": true
380
+ * },
381
+ * {
382
+ * "name": "off",
383
+ * "value": false
384
+ * }
385
+ * ]
386
+ * },
387
+ * "id": "550e8400-e29b-41d4-a716-446655440000",
388
+ * "type": "flag"
389
+ * }
390
+ */
391
+ FlagResource: {
392
+ /** Id */
393
+ id?: string | null;
394
+ /**
395
+ * Type
396
+ * @constant
397
+ */
398
+ type: "flag";
399
+ attributes: components["schemas"]["Flag"];
400
+ };
401
+ /** FlagResponse */
402
+ FlagResponse: {
403
+ data: components["schemas"]["FlagResource"];
404
+ };
405
+ /** FlagRule */
406
+ FlagRule: {
407
+ /** Description */
408
+ description?: string | null;
409
+ /** Logic */
410
+ logic: {
411
+ [key: string]: unknown;
412
+ };
413
+ /** Value */
370
414
  value: unknown;
371
- }>;
372
- description: string | null;
373
- environments: Record<string, any>;
374
- createdAt: string | null;
375
- updatedAt: string | null;
376
- });
377
- /**
378
- * Update this flag's attributes on the server.
379
- *
380
- * Only provided fields are changed; others retain their current values.
381
- */
382
- update(options: {
383
- environments?: Record<string, any>;
384
- values?: Array<{
415
+ };
416
+ /** FlagValue */
417
+ FlagValue: {
418
+ /** Name */
385
419
  name: string;
420
+ /** Value */
386
421
  value: unknown;
387
- }>;
388
- default?: unknown;
389
- description?: string;
390
- name?: string;
391
- }): Promise<void>;
392
- /**
393
- * Add a rule to a specific environment.
394
- *
395
- * The built rule must include an `environment` key (set via
396
- * `Rule(...).environment("env_key")`). Re-fetches current state
397
- * first to avoid stale data.
398
- */
399
- addRule(builtRule: Record<string, any>): Promise<void>;
400
- /** @internal */
401
- _apply(other: Flag): void;
402
- toString(): string;
403
- }
404
- /** A context type resource returned by management API methods. */
405
- declare class ContextType {
406
- /** UUID. */
407
- id: string;
408
- /** Unique key within the account. */
409
- key: string;
410
- /** Human-readable display name. */
411
- name: string;
412
- /** Known attributes. */
413
- attributes: Record<string, any>;
414
- constructor(fields: {
415
- id: string;
416
- key: string;
417
- name: string;
418
- attributes: Record<string, any>;
419
- });
420
- toString(): string;
422
+ };
423
+ /** HTTPValidationError */
424
+ HTTPValidationError: {
425
+ /** Detail */
426
+ detail?: components["schemas"]["ValidationError"][];
427
+ };
428
+ /** Resource[Flag] */
429
+ Resource_Flag_: {
430
+ /** Id */
431
+ id?: string | null;
432
+ /**
433
+ * Type
434
+ * @default
435
+ */
436
+ type: string;
437
+ attributes: components["schemas"]["Flag"];
438
+ };
439
+ /** Response[Flag] */
440
+ Response_Flag_: {
441
+ data: components["schemas"]["Resource_Flag_"];
442
+ };
443
+ /** ValidationError */
444
+ ValidationError: {
445
+ /** Location */
446
+ loc: (string | number)[];
447
+ /** Message */
448
+ msg: string;
449
+ /** Error Type */
450
+ type: string;
451
+ };
452
+ };
453
+ responses: never;
454
+ parameters: never;
455
+ requestBodies: never;
456
+ headers: never;
457
+ pathItems: never;
421
458
  }
422
459
 
423
460
  /**
424
- * Public types for the Flags SDK: FlagType, Context, Rule.
461
+ * Public types for the Flags SDK: Context, Rule.
425
462
  */
426
- /** The value type of a flag. */
427
- type FlagType = "BOOLEAN" | "STRING" | "NUMERIC" | "JSON";
428
463
  /**
429
464
  * A typed evaluation context entity.
430
465
  *
@@ -480,65 +515,141 @@ declare class Rule {
480
515
  }
481
516
 
482
517
  /**
483
- * FlagsClient — management + prescriptive runtime for Smpl Flags.
518
+ * Unified Flag hierarchy — management model + runtime handle.
484
519
  *
485
- * Uses the generated OpenAPI types (`src/generated/flags.d.ts`) via
486
- * `openapi-fetch` for all flag HTTP calls. Context type management and
487
- * context registration use the generated app service types
488
- * (`src/generated/app.d.ts`) via a separate `openapi-fetch` client.
520
+ * A single {@link Flag} class replaces the old separate Flag + FlagHandle
521
+ * classes. Typed subclasses ({@link BooleanFlag}, {@link StringFlag},
522
+ * {@link NumberFlag}, {@link JsonFlag}) override `get()` for type safety.
489
523
  */
490
524
 
491
- /** Describes a flag definition change. */
492
- declare class FlagChangeEvent {
493
- readonly key: string;
494
- readonly source: string;
495
- constructor(key: string, source: string);
496
- }
497
- /** Cache statistics for the flags runtime. */
498
- declare class FlagStats {
499
- readonly cacheHits: number;
500
- readonly cacheMisses: number;
501
- constructor(cacheHits: number, cacheMisses: number);
502
- }
503
- /** @internal */
504
- declare class FlagHandleBase {
505
- /** @internal */ readonly _namespace: FlagsClient;
506
- /** @internal */ readonly _key: string;
507
- /** @internal */ readonly _default: any;
508
- /** @internal */ _listeners: Array<(event: FlagChangeEvent) => void>;
509
- constructor(namespace: FlagsClient, key: string, defaultValue: any);
510
- get key(): string;
511
- get default(): any;
525
+ /**
526
+ * A flag resource that doubles as a runtime handle.
527
+ *
528
+ * Management: call `save()` to persist (POST if new, PUT if existing).
529
+ * Runtime: call `get()` for local JSON Logic evaluation.
530
+ */
531
+ declare class Flag {
532
+ /** UUID of the flag, or `null` if unsaved. */
533
+ id: string | null;
534
+ /** Unique key within the account. */
535
+ key: string;
536
+ /** Human-readable display name. */
537
+ name: string;
538
+ /** Value type: BOOLEAN, STRING, NUMERIC, or JSON. */
539
+ type: string;
540
+ /** Flag-level default value. */
541
+ default: unknown;
542
+ /** Closed set of possible values. */
543
+ values: Array<{
544
+ name: string;
545
+ value: unknown;
546
+ }>;
547
+ /** Optional description. */
548
+ description: string | null;
549
+ /** Per-environment configuration. */
550
+ environments: Record<string, any>;
551
+ /** When the flag was created. */
552
+ createdAt: string | null;
553
+ /** When the flag was last updated. */
554
+ updatedAt: string | null;
555
+ /** @internal */
556
+ readonly _client: FlagsClient;
557
+ /** @internal */
558
+ constructor(client: FlagsClient, fields: {
559
+ id: string | null;
560
+ key: string;
561
+ name: string;
562
+ type: string;
563
+ default: unknown;
564
+ values: Array<{
565
+ name: string;
566
+ value: unknown;
567
+ }>;
568
+ description: string | null;
569
+ environments: Record<string, any>;
570
+ createdAt: string | null;
571
+ updatedAt: string | null;
572
+ });
573
+ /**
574
+ * Persist this flag to the server.
575
+ *
576
+ * POST if `id` is null (new flag), PUT if `id` is set (update).
577
+ * Updates this instance in-place with the server response.
578
+ */
579
+ save(): Promise<void>;
580
+ /**
581
+ * Add a rule to a specific environment (sync local mutation).
582
+ *
583
+ * The built rule must include an `environment` key (set via
584
+ * `Rule(...).environment("env_key")`). No HTTP call is made.
585
+ *
586
+ * @returns `this` for chaining.
587
+ */
588
+ addRule(builtRule: Record<string, any>): Flag;
589
+ /** Enable or disable a flag in a specific environment (sync local mutation). */
590
+ setEnvironmentEnabled(envKey: string, enabled: boolean): void;
591
+ /** Set the default value for a specific environment (sync local mutation). */
592
+ setEnvironmentDefault(envKey: string, defaultValue: unknown): void;
593
+ /** Clear all rules for a specific environment (sync local mutation). */
594
+ clearRules(envKey: string): void;
595
+ /**
596
+ * Evaluate the flag locally (sync, no HTTP).
597
+ *
598
+ * Requires `initialize()` to have been called.
599
+ */
512
600
  get(options?: {
513
601
  context?: Context[];
514
- }): any;
515
- /** Register a flag-specific change listener. Works as a decorator. */
516
- onChange(callback: (event: FlagChangeEvent) => void): (event: FlagChangeEvent) => void;
602
+ }): unknown;
603
+ /** @internal copy all fields from another Flag instance. */
604
+ _apply(other: Flag): void;
605
+ toString(): string;
517
606
  }
518
- /** Typed handle for a boolean flag. */
519
- declare class BoolFlagHandle extends FlagHandleBase {
607
+ /** Typed flag that returns `boolean` from `get()`. */
608
+ declare class BooleanFlag extends Flag {
520
609
  get(options?: {
521
610
  context?: Context[];
522
611
  }): boolean;
523
612
  }
524
- /** Typed handle for a string flag. */
525
- declare class StringFlagHandle extends FlagHandleBase {
613
+ /** Typed flag that returns `string` from `get()`. */
614
+ declare class StringFlag extends Flag {
526
615
  get(options?: {
527
616
  context?: Context[];
528
617
  }): string;
529
618
  }
530
- /** Typed handle for a numeric flag. */
531
- declare class NumberFlagHandle extends FlagHandleBase {
619
+ /** Typed flag that returns `number` from `get()`. */
620
+ declare class NumberFlag extends Flag {
532
621
  get(options?: {
533
622
  context?: Context[];
534
623
  }): number;
535
624
  }
536
- /** Typed handle for a JSON flag. */
537
- declare class JsonFlagHandle extends FlagHandleBase {
625
+ /** Typed flag that returns `Record<string, any>` from `get()`. */
626
+ declare class JsonFlag extends Flag {
538
627
  get(options?: {
539
628
  context?: Context[];
540
629
  }): Record<string, any>;
541
630
  }
631
+
632
+ /**
633
+ * FlagsClient — management + prescriptive runtime for Smpl Flags.
634
+ *
635
+ * Uses the generated OpenAPI types (`src/generated/flags.d.ts`) via
636
+ * `openapi-fetch` for all flag HTTP calls. Context registration uses
637
+ * the generated app service types (`src/generated/app.d.ts`).
638
+ */
639
+
640
+ type FlagResource = components["schemas"]["FlagResource"];
641
+ /** Describes a flag definition change. */
642
+ declare class FlagChangeEvent {
643
+ readonly key: string;
644
+ readonly source: string;
645
+ constructor(key: string, source: string);
646
+ }
647
+ /** Cache statistics for the flags runtime. */
648
+ declare class FlagStats {
649
+ readonly cacheHits: number;
650
+ readonly cacheMisses: number;
651
+ constructor(cacheHits: number, cacheMisses: number);
652
+ }
542
653
  /**
543
654
  * Client for the smplkit Flags API — management plane + prescriptive runtime.
544
655
  *
@@ -555,12 +666,13 @@ declare class FlagsClient {
555
666
  private readonly _appHttp;
556
667
  private _environment;
557
668
  private _flagStore;
558
- private _connected;
669
+ private _initialized;
559
670
  private _cache;
560
671
  private _contextProvider;
561
672
  private _contextBuffer;
562
673
  private _handles;
563
674
  private _globalListeners;
675
+ private _keyListeners;
564
676
  private _wsManager;
565
677
  private readonly _ensureWs;
566
678
  /** @internal — set by SmplClient after construction. */
@@ -570,92 +682,77 @@ declare class FlagsClient {
570
682
  } | null;
571
683
  /** @internal */
572
684
  constructor(apiKey: string, ensureWs: () => SharedWebSocket, timeout?: number);
573
- /** Create a flag. */
574
- create(key: string, options: {
575
- name: string;
576
- type: FlagType;
577
- default: unknown;
685
+ /** Create an unsaved boolean flag. Call `.save()` to persist. */
686
+ newBooleanFlag(key: string, options: {
687
+ default: boolean;
688
+ name?: string;
689
+ description?: string;
690
+ }): BooleanFlag;
691
+ /** Create an unsaved string flag. Call `.save()` to persist. */
692
+ newStringFlag(key: string, options: {
693
+ default: string;
694
+ name?: string;
578
695
  description?: string;
579
696
  values?: Array<{
580
697
  name: string;
581
698
  value: unknown;
582
699
  }>;
583
- }): Promise<Flag>;
584
- /** Fetch a flag by UUID. */
585
- get(flagId: string): Promise<Flag>;
586
- /** List all flags. */
587
- list(): Promise<Flag[]>;
588
- /** Delete a flag by UUID. */
589
- delete(flagId: string): Promise<void>;
590
- /**
591
- * Internal: PUT a full flag update.
592
- * Called by {@link Flag} instance methods.
593
- * @internal
594
- */
595
- _updateFlag(options: {
596
- flag: Flag;
597
- environments?: Record<string, any>;
700
+ }): StringFlag;
701
+ /** Create an unsaved number flag. Call `.save()` to persist. */
702
+ newNumberFlag(key: string, options: {
703
+ default: number;
704
+ name?: string;
705
+ description?: string;
598
706
  values?: Array<{
599
707
  name: string;
600
708
  value: unknown;
601
709
  }>;
602
- default?: unknown;
603
- description?: string;
710
+ }): NumberFlag;
711
+ /** Create an unsaved JSON flag. Call `.save()` to persist. */
712
+ newJsonFlag(key: string, options: {
713
+ default: Record<string, any>;
604
714
  name?: string;
605
- }): Promise<Flag>;
606
- /** Create a context type. */
607
- createContextType(key: string, options: {
608
- name: string;
609
- }): Promise<ContextType>;
610
- /** Update a context type (merge attributes). */
611
- updateContextType(ctId: string, options: {
612
- key: string;
613
- name: string;
614
- attributes: Record<string, any>;
615
- }): Promise<ContextType>;
616
- /** List all context types. */
617
- listContextTypes(): Promise<ContextType[]>;
618
- /** Delete a context type. */
619
- deleteContextType(ctId: string): Promise<void>;
620
- /** List context instances filtered by context type key. */
621
- listContexts(options: {
622
- contextTypeKey: string;
623
- }): Promise<any[]>;
624
- /** Declare a boolean flag handle. */
625
- boolFlag(key: string, defaultValue: boolean): BoolFlagHandle;
626
- /** Declare a string flag handle. */
627
- stringFlag(key: string, defaultValue: string): StringFlagHandle;
628
- /** Declare a numeric flag handle. */
629
- numberFlag(key: string, defaultValue: number): NumberFlagHandle;
630
- /** Declare a JSON flag handle. */
631
- jsonFlag(key: string, defaultValue: Record<string, any>): JsonFlagHandle;
715
+ description?: string;
716
+ values?: Array<{
717
+ name: string;
718
+ value: unknown;
719
+ }>;
720
+ }): JsonFlag;
721
+ /** Fetch a flag by key. */
722
+ get(key: string): Promise<Flag>;
723
+ /** List all flags. */
724
+ list(): Promise<Flag[]>;
725
+ /** Delete a flag by key. */
726
+ delete(key: string): Promise<void>;
727
+ /** @internal — POST a new flag. */
728
+ _createFlag(flag: Flag): Promise<Flag>;
729
+ /** @internal — PUT a flag update. */
730
+ _updateFlag(flag: Flag): Promise<Flag>;
731
+ /** Declare a boolean flag handle for runtime evaluation. */
732
+ booleanFlag(key: string, defaultValue: boolean): BooleanFlag;
733
+ /** Declare a string flag handle for runtime evaluation. */
734
+ stringFlag(key: string, defaultValue: string): StringFlag;
735
+ /** Declare a numeric flag handle for runtime evaluation. */
736
+ numberFlag(key: string, defaultValue: number): NumberFlag;
737
+ /** Declare a JSON flag handle for runtime evaluation. */
738
+ jsonFlag(key: string, defaultValue: Record<string, any>): JsonFlag;
632
739
  /**
633
740
  * Register a context provider function.
634
741
  *
635
- * Called on every `handle.get()` to supply the current evaluation
636
- * context. Can also be used as a decorator:
637
- *
638
- * ```typescript
639
- * client.flags.setContextProvider(() => [
640
- * new Context("user", userId, { plan: userPlan }),
641
- * ]);
642
- * ```
742
+ * Called on every `handle.get()` to supply the current evaluation context.
643
743
  */
644
744
  setContextProvider(fn: () => Context[]): void;
645
745
  /**
646
746
  * Register a context provider — decorator-style alias.
647
- *
648
- * ```typescript
649
- * const provider = client.flags.contextProvider(() => [...]);
650
- * ```
651
747
  */
652
748
  contextProvider(fn: () => Context[]): () => Context[];
653
749
  /**
654
- * Connect to an environment: fetch flag definitions, register on
655
- * shared WebSocket, enable local evaluation.
656
- * @internalcalled by SmplClient.connect().
750
+ * Initialize the flags runtime: fetch definitions and wire WebSocket.
751
+ *
752
+ * Idempotentsafe to call multiple times. Must be called (and awaited)
753
+ * before using `.get()` on flag handles.
657
754
  */
658
- _connectInternal(environment: string): Promise<void>;
755
+ initialize(): Promise<void>;
659
756
  /** Disconnect: unregister from WebSocket, flush contexts, clear state. */
660
757
  disconnect(): Promise<void>;
661
758
  /** Re-fetch all flag definitions and clear cache. */
@@ -664,29 +761,24 @@ declare class FlagsClient {
664
761
  connectionStatus(): string;
665
762
  /** Return cache statistics. */
666
763
  stats(): FlagStats;
667
- /** Register a global change listener that fires for any flag change. */
668
- onChangeAny(callback: (event: FlagChangeEvent) => void): (event: FlagChangeEvent) => void;
669
764
  /**
670
- * Register a global change listener — decorator-style alias.
765
+ * Register a change listener.
671
766
  *
672
- * ```typescript
673
- * const listener = client.flags.onChange((event) => { ... });
674
- * ```
767
+ * - `onChange(callback)` — fires for any flag change (global).
768
+ * - `onChange(key, callback)` fires only for the specified flag key.
675
769
  */
676
- onChange(callback: (event: FlagChangeEvent) => void): (event: FlagChangeEvent) => void;
770
+ onChange(callbackOrKey: string | ((event: FlagChangeEvent) => void), callback?: (event: FlagChangeEvent) => void): void;
677
771
  /**
678
772
  * Explicitly register context(s) for background batch registration.
679
773
  *
680
774
  * Accepts a single Context or an array. Fire-and-forget — never
681
- * blocks. Works before `connect()` is called.
775
+ * blocks. Works before `initialize()` is called.
682
776
  */
683
777
  register(context: Context | Context[]): void;
684
778
  /** Flush pending context registrations to the server. */
685
779
  flushContexts(): Promise<void>;
686
780
  /**
687
781
  * Tier 1 explicit evaluation — stateless, no provider or cache.
688
- *
689
- * Useful for scripts, one-off jobs, and infrastructure code.
690
782
  */
691
783
  evaluate(key: string, options: {
692
784
  environment: string;
@@ -694,6 +786,8 @@ declare class FlagsClient {
694
786
  }): Promise<any>;
695
787
  /** @internal */
696
788
  _evaluateHandle(key: string, defaultValue: any, context: Context[] | null): any;
789
+ /** @internal — called by SmplClient constructor / lazy init. */
790
+ _connectInternal(environment: string): Promise<void>;
697
791
  private _handleFlagChanged;
698
792
  private _handleFlagDeleted;
699
793
  private _fetchAllFlags;
@@ -701,16 +795,243 @@ declare class FlagsClient {
701
795
  private _fireChangeListeners;
702
796
  private _fireChangeListenersAll;
703
797
  private _flushContexts;
704
- private _resourceToModel;
798
+ /** @internal */
799
+ _resourceToModel(resource: FlagResource): Flag;
705
800
  private _resourceToPlainDict;
706
- private _parseContextType;
801
+ }
802
+
803
+ /**
804
+ * Public types for the Logging SDK.
805
+ */
806
+ /** Log level values matching the smplkit platform. */
807
+ declare enum LogLevel {
808
+ TRACE = "TRACE",
809
+ DEBUG = "DEBUG",
810
+ INFO = "INFO",
811
+ WARN = "WARN",
812
+ ERROR = "ERROR",
813
+ FATAL = "FATAL",
814
+ SILENT = "SILENT"
815
+ }
816
+ /** Describes a logger configuration change. */
817
+ interface LoggerChangeEvent {
818
+ /** The logger key that changed. */
819
+ key: string;
820
+ /** The new effective log level, or null if removed. */
821
+ level: LogLevel | null;
822
+ /** How the change was delivered. */
823
+ source: string;
824
+ }
825
+
826
+ /**
827
+ * Logger and LogGroup active-record models for the Logging SDK.
828
+ */
829
+
830
+ /**
831
+ * A logger resource managed by the smplkit platform.
832
+ *
833
+ * Management: mutate properties and call `save()` to persist.
834
+ * Convenience methods (`setLevel`, `setEnvironmentLevel`, etc.) are
835
+ * sync local mutations — no HTTP until `save()`.
836
+ */
837
+ declare class Logger {
838
+ /** UUID of the logger, or `null` if unsaved. */
839
+ id: string | null;
840
+ /** Unique key (dot-separated hierarchy). */
841
+ key: string;
842
+ /** Human-readable display name. */
843
+ name: string;
844
+ /** Base log level, or null if inherited. */
845
+ level: string | null;
846
+ /** UUID of the parent log group, or null. */
847
+ group: string | null;
848
+ /** Whether this logger is managed by the platform. */
849
+ managed: boolean;
850
+ /** Observed sources (services that report this logger). */
851
+ sources: Array<Record<string, any>>;
852
+ /** Per-environment level overrides. */
853
+ environments: Record<string, any>;
854
+ /** When the logger was created. */
855
+ createdAt: string | null;
856
+ /** When the logger was last updated. */
857
+ updatedAt: string | null;
858
+ /** @internal */
859
+ readonly _client: LoggingClient;
860
+ /** @internal */
861
+ constructor(client: LoggingClient, fields: {
862
+ id: string | null;
863
+ key: string;
864
+ name: string;
865
+ level: string | null;
866
+ group: string | null;
867
+ managed: boolean;
868
+ sources: Array<Record<string, any>>;
869
+ environments: Record<string, any>;
870
+ createdAt: string | null;
871
+ updatedAt: string | null;
872
+ });
873
+ /**
874
+ * Persist this logger to the server.
875
+ *
876
+ * POST if `id` is null (new), PUT if `id` is set (update).
877
+ */
878
+ save(): Promise<void>;
879
+ /** Set the base log level (sync local mutation). */
880
+ setLevel(level: LogLevel): void;
881
+ /** Clear the base log level (sync local mutation). */
882
+ clearLevel(): void;
883
+ /** Set an environment-specific log level (sync local mutation). */
884
+ setEnvironmentLevel(env: string, level: LogLevel): void;
885
+ /** Clear an environment-specific log level (sync local mutation). */
886
+ clearEnvironmentLevel(env: string): void;
887
+ /** Clear all environment-specific log levels (sync local mutation). */
888
+ clearAllEnvironmentLevels(): void;
889
+ /** @internal — copy all fields from another Logger instance. */
890
+ _apply(other: Logger): void;
891
+ toString(): string;
892
+ }
893
+ /**
894
+ * A log group resource for organizing loggers.
895
+ *
896
+ * Management: mutate properties and call `save()` to persist.
897
+ */
898
+ declare class LogGroup {
899
+ /** UUID of the log group, or `null` if unsaved. */
900
+ id: string | null;
901
+ /** Unique key. */
902
+ key: string;
903
+ /** Human-readable display name. */
904
+ name: string;
905
+ /** Base log level, or null if inherited. */
906
+ level: string | null;
907
+ /** UUID of the parent log group, or null. */
908
+ group: string | null;
909
+ /** Per-environment level overrides. */
910
+ environments: Record<string, any>;
911
+ /** When the log group was created. */
912
+ createdAt: string | null;
913
+ /** When the log group was last updated. */
914
+ updatedAt: string | null;
915
+ /** @internal */
916
+ readonly _client: LoggingClient;
917
+ /** @internal */
918
+ constructor(client: LoggingClient, fields: {
919
+ id: string | null;
920
+ key: string;
921
+ name: string;
922
+ level: string | null;
923
+ group: string | null;
924
+ environments: Record<string, any>;
925
+ createdAt: string | null;
926
+ updatedAt: string | null;
927
+ });
928
+ /**
929
+ * Persist this log group to the server.
930
+ *
931
+ * POST if `id` is null (new), PUT if `id` is set (update).
932
+ */
933
+ save(): Promise<void>;
934
+ /** Set the base log level (sync local mutation). */
935
+ setLevel(level: LogLevel): void;
936
+ /** Clear the base log level (sync local mutation). */
937
+ clearLevel(): void;
938
+ /** Set an environment-specific log level (sync local mutation). */
939
+ setEnvironmentLevel(env: string, level: LogLevel): void;
940
+ /** Clear an environment-specific log level (sync local mutation). */
941
+ clearEnvironmentLevel(env: string): void;
942
+ /** Clear all environment-specific log levels (sync local mutation). */
943
+ clearAllEnvironmentLevels(): void;
944
+ /** @internal — copy all fields from another LogGroup instance. */
945
+ _apply(other: LogGroup): void;
946
+ toString(): string;
947
+ }
948
+
949
+ /**
950
+ * LoggingClient — management plane + scaffolded runtime for Smpl Logging.
951
+ *
952
+ * Uses the generated OpenAPI types (`src/generated/logging.d.ts`) via
953
+ * `openapi-fetch` for all HTTP calls.
954
+ */
955
+
956
+ /**
957
+ * Client for the smplkit Logging API — management plane + scaffolded runtime.
958
+ *
959
+ * Obtained via `SmplClient.logging`.
960
+ */
961
+ declare class LoggingClient {
962
+ /** @internal */
963
+ readonly _apiKey: string;
964
+ /** @internal */
965
+ readonly _baseUrl: string;
966
+ /** @internal */
967
+ private readonly _http;
968
+ /** @internal — set by SmplClient after construction. */
969
+ _parent: {
970
+ readonly _environment: string;
971
+ readonly _service: string | null;
972
+ } | null;
973
+ private readonly _ensureWs;
974
+ private _wsManager;
975
+ private _started;
976
+ private _globalListeners;
977
+ private _keyListeners;
978
+ /** @internal */
979
+ constructor(apiKey: string, ensureWs: () => SharedWebSocket, timeout?: number);
980
+ /** Create an unsaved logger. Call `.save()` to persist. */
981
+ new(key: string, options?: {
982
+ name?: string;
983
+ managed?: boolean;
984
+ }): Logger;
985
+ /** Fetch a logger by key. */
986
+ get(key: string): Promise<Logger>;
987
+ /** List all loggers. */
988
+ list(): Promise<Logger[]>;
989
+ /** Delete a logger by key. */
990
+ delete(key: string): Promise<void>;
991
+ /** Create an unsaved log group. Call `.save()` to persist. */
992
+ newGroup(key: string, options?: {
993
+ name?: string;
994
+ group?: string;
995
+ }): LogGroup;
996
+ /** Fetch a log group by key. */
997
+ getGroup(key: string): Promise<LogGroup>;
998
+ /** List all log groups. */
999
+ listGroups(): Promise<LogGroup[]>;
1000
+ /** Delete a log group by key. */
1001
+ deleteGroup(key: string): Promise<void>;
1002
+ /** @internal — POST or PUT a logger. */
1003
+ _saveLogger(logger: Logger): Promise<Logger>;
1004
+ /** @internal — POST or PUT a log group. */
1005
+ _saveLogGroup(group: LogGroup): Promise<LogGroup>;
1006
+ /**
1007
+ * Start the logging runtime.
1008
+ *
1009
+ * Fetches existing loggers/groups and wires WebSocket listeners for
1010
+ * live updates. Idempotent — safe to call multiple times.
1011
+ *
1012
+ * Note: Node.js auto-discovery (equivalent to Python's logging module
1013
+ * monkey-patching) is deferred. Management methods work without start().
1014
+ */
1015
+ start(): Promise<void>;
1016
+ /**
1017
+ * Register a change listener.
1018
+ *
1019
+ * - `onChange(callback)` — fires for any logger change (global).
1020
+ * - `onChange(key, callback)` — fires only for the specified logger key.
1021
+ */
1022
+ onChange(callbackOrKey: string | ((event: LoggerChangeEvent) => void), callback?: (event: LoggerChangeEvent) => void): void;
1023
+ /** @internal */
1024
+ _close(): void;
1025
+ private _handleLoggerChanged;
1026
+ private _loggerToModel;
1027
+ private _groupToModel;
707
1028
  }
708
1029
 
709
1030
  /**
710
1031
  * Top-level SDK client — SmplClient.
711
1032
  *
712
1033
  * The main entry point for the smplkit TypeScript SDK. Provides access
713
- * to sub-clients for each API domain (config, flags, logging, etc.).
1034
+ * to sub-clients for each API domain (config, flags, logging).
714
1035
  */
715
1036
 
716
1037
  /** Configuration options for the {@link SmplClient}. */
@@ -745,34 +1066,37 @@ interface SmplClientOptions {
745
1066
  * ```typescript
746
1067
  * import { SmplClient } from "@smplkit/sdk";
747
1068
  *
748
- * const client = new SmplClient({ apiKey: "sk_api_...", environment: "production" });
749
- * await client.connect();
1069
+ * const client = new SmplClient({
1070
+ * apiKey: "sk_api_...",
1071
+ * environment: "production",
1072
+ * service: "my-service",
1073
+ * });
1074
+ *
1075
+ * // Flags runtime
1076
+ * await client.flags.initialize();
1077
+ * const flag = client.flags.booleanFlag("checkout-v2", false);
1078
+ * console.log(flag.get());
1079
+ *
1080
+ * // Config runtime
1081
+ * const values = await client.config.resolve("user-service");
750
1082
  * ```
751
1083
  */
752
1084
  declare class SmplClient {
753
- /** Client for config management-plane operations. */
1085
+ /** Client for config management and runtime. */
754
1086
  readonly config: ConfigClient;
755
- /** Client for flags management and runtime operations. */
1087
+ /** Client for flags management and runtime. */
756
1088
  readonly flags: FlagsClient;
1089
+ /** Client for logging management and runtime. */
1090
+ readonly logging: LoggingClient;
757
1091
  private _wsManager;
758
1092
  private readonly _apiKey;
759
1093
  /** @internal */
760
1094
  readonly _environment: string;
761
1095
  /** @internal */
762
1096
  readonly _service: string;
763
- private _connected;
764
1097
  private readonly _timeout;
765
1098
  private readonly _appHttp;
766
1099
  constructor(options?: SmplClientOptions);
767
- /**
768
- * Connect to the smplkit platform.
769
- *
770
- * Fetches initial flag and config data, opens the shared WebSocket,
771
- * and registers the service as a context instance (if provided).
772
- *
773
- * This method is idempotent — calling it multiple times is safe.
774
- */
775
- connect(): Promise<void>;
776
1100
  /** @internal */
777
1101
  private _registerServiceContext;
778
1102
  /** Lazily create and start the shared WebSocket. @internal */
@@ -822,13 +1146,9 @@ declare class SmplNotFoundError extends SmplError {
822
1146
  declare class SmplConflictError extends SmplError {
823
1147
  constructor(message: string, statusCode?: number, responseBody?: string, errors?: ApiErrorObject[]);
824
1148
  }
825
- /** Raised when a method requiring connect() is called before connecting. */
826
- declare class SmplNotConnectedError extends SmplError {
827
- constructor(message: string);
828
- }
829
1149
  /** Raised when the server rejects a request due to validation errors (HTTP 422). */
830
1150
  declare class SmplValidationError extends SmplError {
831
1151
  constructor(message: string, statusCode?: number, responseBody?: string, errors?: ApiErrorObject[]);
832
1152
  }
833
1153
 
834
- export { type ApiErrorObject, BoolFlagHandle, Config, type ConfigChangeEvent, ConfigClient, Context, ContextType, type CreateConfigOptions, Flag, FlagChangeEvent, FlagStats, type FlagType, FlagsClient, type GetConfigOptions, JsonFlagHandle, NumberFlagHandle, Rule, SharedWebSocket, SmplClient, type SmplClientOptions, SmplConflictError, SmplConnectionError, SmplError, SmplNotConnectedError, SmplNotFoundError, SmplTimeoutError, SmplValidationError, StringFlagHandle };
1154
+ export { type ApiErrorObject, BooleanFlag, Config, type ConfigChangeEvent, ConfigClient, Context, Flag, FlagChangeEvent, FlagStats, FlagsClient, JsonFlag, LiveConfigProxy, LogGroup, LogLevel, Logger, type LoggerChangeEvent, LoggingClient, NumberFlag, Rule, SharedWebSocket, SmplClient, type SmplClientOptions, SmplConflictError, SmplConnectionError, SmplError, SmplNotFoundError, SmplTimeoutError, SmplValidationError, StringFlag };