@smplkit/sdk 1.5.6 → 1.5.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +165 -38
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +165 -38
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -17579,6 +17579,8 @@ var APP_BASE_URL = "https://app.smplkit.com";
|
|
|
17579
17579
|
var CACHE_MAX_SIZE = 1e4;
|
|
17580
17580
|
var CONTEXT_REGISTRATION_LRU_SIZE = 1e4;
|
|
17581
17581
|
var CONTEXT_BATCH_FLUSH_SIZE = 100;
|
|
17582
|
+
var FLAG_REGISTRATION_FLUSH_SIZE = 50;
|
|
17583
|
+
var FLAG_REGISTRATION_FLUSH_INTERVAL_MS = 3e4;
|
|
17582
17584
|
async function checkError2(response, _context) {
|
|
17583
17585
|
const body = await response.text().catch(() => "");
|
|
17584
17586
|
throwForStatus(response.status, body);
|
|
@@ -17728,6 +17730,30 @@ var ContextRegistrationBuffer = class {
|
|
|
17728
17730
|
return this._pending.length;
|
|
17729
17731
|
}
|
|
17730
17732
|
};
|
|
17733
|
+
var FlagRegistrationBuffer = class {
|
|
17734
|
+
_seen = /* @__PURE__ */ new Set();
|
|
17735
|
+
_pending = [];
|
|
17736
|
+
add(id, type, defaultValue, service, environment) {
|
|
17737
|
+
if (!this._seen.has(id)) {
|
|
17738
|
+
this._seen.add(id);
|
|
17739
|
+
this._pending.push({
|
|
17740
|
+
id,
|
|
17741
|
+
type,
|
|
17742
|
+
default: defaultValue,
|
|
17743
|
+
service: service ?? void 0,
|
|
17744
|
+
environment: environment ?? void 0
|
|
17745
|
+
});
|
|
17746
|
+
}
|
|
17747
|
+
}
|
|
17748
|
+
drain() {
|
|
17749
|
+
const batch = this._pending;
|
|
17750
|
+
this._pending = [];
|
|
17751
|
+
return batch;
|
|
17752
|
+
}
|
|
17753
|
+
get pendingCount() {
|
|
17754
|
+
return this._pending.length;
|
|
17755
|
+
}
|
|
17756
|
+
};
|
|
17731
17757
|
var FlagsManagement = class {
|
|
17732
17758
|
constructor(_client) {
|
|
17733
17759
|
this._client = _client;
|
|
@@ -17777,6 +17803,8 @@ var FlagsClient = class {
|
|
|
17777
17803
|
_cache = new ResolutionCache();
|
|
17778
17804
|
_contextProvider = null;
|
|
17779
17805
|
_contextBuffer = new ContextRegistrationBuffer();
|
|
17806
|
+
_flagBuffer = new FlagRegistrationBuffer();
|
|
17807
|
+
_flagFlushTimer = null;
|
|
17780
17808
|
_handles = {};
|
|
17781
17809
|
_globalListeners = [];
|
|
17782
17810
|
_keyListeners = /* @__PURE__ */ new Map();
|
|
@@ -18004,6 +18032,16 @@ var FlagsClient = class {
|
|
|
18004
18032
|
updatedAt: null
|
|
18005
18033
|
});
|
|
18006
18034
|
this._handles[id] = handle;
|
|
18035
|
+
this._flagBuffer.add(
|
|
18036
|
+
id,
|
|
18037
|
+
"BOOLEAN",
|
|
18038
|
+
defaultValue,
|
|
18039
|
+
this._parent?._service ?? null,
|
|
18040
|
+
this._parent?._environment ?? null
|
|
18041
|
+
);
|
|
18042
|
+
if (this._flagBuffer.pendingCount >= FLAG_REGISTRATION_FLUSH_SIZE) {
|
|
18043
|
+
void this._flushFlags();
|
|
18044
|
+
}
|
|
18007
18045
|
return handle;
|
|
18008
18046
|
}
|
|
18009
18047
|
/** Declare a string flag handle for runtime evaluation. */
|
|
@@ -18020,6 +18058,16 @@ var FlagsClient = class {
|
|
|
18020
18058
|
updatedAt: null
|
|
18021
18059
|
});
|
|
18022
18060
|
this._handles[id] = handle;
|
|
18061
|
+
this._flagBuffer.add(
|
|
18062
|
+
id,
|
|
18063
|
+
"STRING",
|
|
18064
|
+
defaultValue,
|
|
18065
|
+
this._parent?._service ?? null,
|
|
18066
|
+
this._parent?._environment ?? null
|
|
18067
|
+
);
|
|
18068
|
+
if (this._flagBuffer.pendingCount >= FLAG_REGISTRATION_FLUSH_SIZE) {
|
|
18069
|
+
void this._flushFlags();
|
|
18070
|
+
}
|
|
18023
18071
|
return handle;
|
|
18024
18072
|
}
|
|
18025
18073
|
/** Declare a numeric flag handle for runtime evaluation. */
|
|
@@ -18036,6 +18084,16 @@ var FlagsClient = class {
|
|
|
18036
18084
|
updatedAt: null
|
|
18037
18085
|
});
|
|
18038
18086
|
this._handles[id] = handle;
|
|
18087
|
+
this._flagBuffer.add(
|
|
18088
|
+
id,
|
|
18089
|
+
"NUMERIC",
|
|
18090
|
+
defaultValue,
|
|
18091
|
+
this._parent?._service ?? null,
|
|
18092
|
+
this._parent?._environment ?? null
|
|
18093
|
+
);
|
|
18094
|
+
if (this._flagBuffer.pendingCount >= FLAG_REGISTRATION_FLUSH_SIZE) {
|
|
18095
|
+
void this._flushFlags();
|
|
18096
|
+
}
|
|
18039
18097
|
return handle;
|
|
18040
18098
|
}
|
|
18041
18099
|
/** Declare a JSON flag handle for runtime evaluation. */
|
|
@@ -18052,6 +18110,16 @@ var FlagsClient = class {
|
|
|
18052
18110
|
updatedAt: null
|
|
18053
18111
|
});
|
|
18054
18112
|
this._handles[id] = handle;
|
|
18113
|
+
this._flagBuffer.add(
|
|
18114
|
+
id,
|
|
18115
|
+
"JSON",
|
|
18116
|
+
defaultValue,
|
|
18117
|
+
this._parent?._service ?? null,
|
|
18118
|
+
this._parent?._environment ?? null
|
|
18119
|
+
);
|
|
18120
|
+
if (this._flagBuffer.pendingCount >= FLAG_REGISTRATION_FLUSH_SIZE) {
|
|
18121
|
+
void this._flushFlags();
|
|
18122
|
+
}
|
|
18055
18123
|
return handle;
|
|
18056
18124
|
}
|
|
18057
18125
|
// ------------------------------------------------------------------
|
|
@@ -18085,12 +18153,16 @@ var FlagsClient = class {
|
|
|
18085
18153
|
if (this._initialized) return;
|
|
18086
18154
|
debug("lifecycle", "FlagsClient.initialize() called");
|
|
18087
18155
|
this._environment = this._parent?._environment ?? null;
|
|
18156
|
+
await this._flushFlags();
|
|
18088
18157
|
await this._fetchAllFlags();
|
|
18089
18158
|
this._initialized = true;
|
|
18090
18159
|
this._cache.clear();
|
|
18091
18160
|
this._wsManager = this._ensureWs();
|
|
18092
18161
|
this._wsManager.on("flag_changed", this._handleFlagChanged);
|
|
18093
18162
|
this._wsManager.on("flag_deleted", this._handleFlagDeleted);
|
|
18163
|
+
this._flagFlushTimer = setInterval(() => {
|
|
18164
|
+
void this._flushFlags();
|
|
18165
|
+
}, FLAG_REGISTRATION_FLUSH_INTERVAL_MS);
|
|
18094
18166
|
}
|
|
18095
18167
|
/** Disconnect the flags runtime and release resources. */
|
|
18096
18168
|
async disconnect() {
|
|
@@ -18099,6 +18171,10 @@ var FlagsClient = class {
|
|
|
18099
18171
|
this._wsManager.off("flag_deleted", this._handleFlagDeleted);
|
|
18100
18172
|
this._wsManager = null;
|
|
18101
18173
|
}
|
|
18174
|
+
if (this._flagFlushTimer !== null) {
|
|
18175
|
+
clearInterval(this._flagFlushTimer);
|
|
18176
|
+
this._flagFlushTimer = null;
|
|
18177
|
+
}
|
|
18102
18178
|
await this._flushContexts();
|
|
18103
18179
|
this._flagStore = {};
|
|
18104
18180
|
this._cache.clear();
|
|
@@ -18250,12 +18326,16 @@ var FlagsClient = class {
|
|
|
18250
18326
|
/** @internal — called by SmplClient constructor / lazy init. */
|
|
18251
18327
|
async _connectInternal(environment) {
|
|
18252
18328
|
this._environment = environment;
|
|
18329
|
+
await this._flushFlags();
|
|
18253
18330
|
await this._fetchAllFlags();
|
|
18254
18331
|
this._initialized = true;
|
|
18255
18332
|
this._cache.clear();
|
|
18256
18333
|
this._wsManager = this._ensureWs();
|
|
18257
18334
|
this._wsManager.on("flag_changed", this._handleFlagChanged);
|
|
18258
18335
|
this._wsManager.on("flag_deleted", this._handleFlagDeleted);
|
|
18336
|
+
this._flagFlushTimer = setInterval(() => {
|
|
18337
|
+
void this._flushFlags();
|
|
18338
|
+
}, FLAG_REGISTRATION_FLUSH_INTERVAL_MS);
|
|
18259
18339
|
}
|
|
18260
18340
|
// ------------------------------------------------------------------
|
|
18261
18341
|
// Internal: event handlers (called by SharedWebSocket)
|
|
@@ -18331,6 +18411,23 @@ var FlagsClient = class {
|
|
|
18331
18411
|
}
|
|
18332
18412
|
}
|
|
18333
18413
|
// ------------------------------------------------------------------
|
|
18414
|
+
// Internal: flag registration flush
|
|
18415
|
+
// ------------------------------------------------------------------
|
|
18416
|
+
async _flushFlags() {
|
|
18417
|
+
const batch = this._flagBuffer.drain();
|
|
18418
|
+
if (batch.length === 0) return;
|
|
18419
|
+
debug("registration", `flushing ${batch.length} flag(s) to bulk-register endpoint`);
|
|
18420
|
+
try {
|
|
18421
|
+
await this._http.POST("/api/v1/flags/bulk", {
|
|
18422
|
+
body: { flags: batch }
|
|
18423
|
+
});
|
|
18424
|
+
} catch (err) {
|
|
18425
|
+
console.warn(
|
|
18426
|
+
`[smplkit] Failed to bulk-register flags: ${err instanceof Error ? err.message : String(err)}`
|
|
18427
|
+
);
|
|
18428
|
+
}
|
|
18429
|
+
}
|
|
18430
|
+
// ------------------------------------------------------------------
|
|
18334
18431
|
// Internal: context flush
|
|
18335
18432
|
// ------------------------------------------------------------------
|
|
18336
18433
|
async _flushContexts() {
|
|
@@ -18554,6 +18651,26 @@ var LogGroup = class {
|
|
|
18554
18651
|
|
|
18555
18652
|
// src/logging/client.ts
|
|
18556
18653
|
var LOGGING_BASE_URL = "https://logging.smplkit.com";
|
|
18654
|
+
var LoggerRegistrationBuffer = class {
|
|
18655
|
+
_seen = /* @__PURE__ */ new Set();
|
|
18656
|
+
_pending = [];
|
|
18657
|
+
add(id, level, resolvedLevel, service, environment) {
|
|
18658
|
+
if (this._seen.has(id)) return;
|
|
18659
|
+
this._seen.add(id);
|
|
18660
|
+
const item = { id, level, resolved_level: resolvedLevel };
|
|
18661
|
+
if (service) item.service = service;
|
|
18662
|
+
if (environment) item.environment = environment;
|
|
18663
|
+
this._pending.push(item);
|
|
18664
|
+
}
|
|
18665
|
+
drain() {
|
|
18666
|
+
const batch = this._pending;
|
|
18667
|
+
this._pending = [];
|
|
18668
|
+
return batch;
|
|
18669
|
+
}
|
|
18670
|
+
get pendingCount() {
|
|
18671
|
+
return this._pending.length;
|
|
18672
|
+
}
|
|
18673
|
+
};
|
|
18557
18674
|
async function checkError3(response, _context) {
|
|
18558
18675
|
const body = await response.text().catch(() => "");
|
|
18559
18676
|
throwForStatus(response.status, body);
|
|
@@ -18624,6 +18741,8 @@ var LoggingClient = class {
|
|
|
18624
18741
|
_keyListeners = /* @__PURE__ */ new Map();
|
|
18625
18742
|
_adapters = [];
|
|
18626
18743
|
_explicitAdapters = false;
|
|
18744
|
+
_loggerBuffer = new LoggerRegistrationBuffer();
|
|
18745
|
+
_loggerFlushTimer = null;
|
|
18627
18746
|
/** @internal */
|
|
18628
18747
|
constructor(apiKey, ensureWs, timeout) {
|
|
18629
18748
|
this._apiKey = apiKey;
|
|
@@ -18869,15 +18988,20 @@ var LoggingClient = class {
|
|
|
18869
18988
|
if (!this._explicitAdapters) {
|
|
18870
18989
|
this._adapters = this._autoLoadAdapters();
|
|
18871
18990
|
}
|
|
18872
|
-
const
|
|
18991
|
+
const service = this._parent?._service ?? null;
|
|
18992
|
+
const environment = this._parent?._environment ?? null;
|
|
18993
|
+
let discoveredCount = 0;
|
|
18873
18994
|
for (const adapter of this._adapters) {
|
|
18874
18995
|
try {
|
|
18875
18996
|
const loggers = adapter.discover();
|
|
18876
|
-
|
|
18997
|
+
for (const { name, level } of loggers) {
|
|
18998
|
+
this._loggerBuffer.add(name, level, level, service, environment);
|
|
18999
|
+
discoveredCount++;
|
|
19000
|
+
}
|
|
18877
19001
|
} catch {
|
|
18878
19002
|
}
|
|
18879
19003
|
}
|
|
18880
|
-
debug("discovery", `discovered ${
|
|
19004
|
+
debug("discovery", `discovered ${discoveredCount} logger(s) from adapters`);
|
|
18881
19005
|
for (const adapter of this._adapters) {
|
|
18882
19006
|
try {
|
|
18883
19007
|
adapter.installHook((name, level) => {
|
|
@@ -18887,39 +19011,13 @@ var LoggingClient = class {
|
|
|
18887
19011
|
} catch {
|
|
18888
19012
|
}
|
|
18889
19013
|
}
|
|
18890
|
-
if (
|
|
19014
|
+
if (discoveredCount > 0) {
|
|
18891
19015
|
const metrics = this._parent?._metrics;
|
|
18892
19016
|
if (metrics) {
|
|
18893
|
-
metrics.record("logging.loggers_discovered",
|
|
18894
|
-
}
|
|
18895
|
-
}
|
|
18896
|
-
if (discovered.length > 0) {
|
|
18897
|
-
const service = this._parent?._service ?? null;
|
|
18898
|
-
const environment = this._parent?._environment ?? null;
|
|
18899
|
-
const loggers = discovered.map(
|
|
18900
|
-
({ name, level }) => ({
|
|
18901
|
-
id: name,
|
|
18902
|
-
// For Winston/Pino there is no inherited-null distinction — both fields carry the same value.
|
|
18903
|
-
level,
|
|
18904
|
-
resolved_level: level,
|
|
18905
|
-
service: service ?? void 0,
|
|
18906
|
-
environment: environment ?? void 0
|
|
18907
|
-
})
|
|
18908
|
-
);
|
|
18909
|
-
debug("registration", `flushing ${loggers.length} logger(s) to bulk-register endpoint`);
|
|
18910
|
-
try {
|
|
18911
|
-
const result = await this._http.POST("/api/v1/loggers/bulk", {
|
|
18912
|
-
body: { loggers }
|
|
18913
|
-
});
|
|
18914
|
-
if (result.error !== void 0)
|
|
18915
|
-
await checkError3(result.response, "Failed to bulk-register loggers");
|
|
18916
|
-
debug("registration", `bulk-register complete (${loggers.length} logger(s))`);
|
|
18917
|
-
} catch (err) {
|
|
18918
|
-
console.warn(
|
|
18919
|
-
`[smplkit] Failed to bulk-register loggers: ${err instanceof Error ? err.message : String(err)}`
|
|
18920
|
-
);
|
|
19017
|
+
metrics.record("logging.loggers_discovered", discoveredCount, "loggers");
|
|
18921
19018
|
}
|
|
18922
19019
|
}
|
|
19020
|
+
await this._flushLoggerBuffer();
|
|
18923
19021
|
debug("resolution", `starting resolution pass (trigger: start())`);
|
|
18924
19022
|
try {
|
|
18925
19023
|
const [serverLoggers, serverGroups] = await Promise.all([
|
|
@@ -18938,6 +19036,9 @@ var LoggingClient = class {
|
|
|
18938
19036
|
this._wsManager.on("logger_deleted", this._handleLoggerChanged);
|
|
18939
19037
|
this._wsManager.on("group_changed", this._handleGroupChanged);
|
|
18940
19038
|
this._wsManager.on("group_deleted", this._handleGroupChanged);
|
|
19039
|
+
this._loggerFlushTimer = setInterval(() => {
|
|
19040
|
+
void this._flushLoggerBuffer();
|
|
19041
|
+
}, 3e4);
|
|
18941
19042
|
this._started = true;
|
|
18942
19043
|
}
|
|
18943
19044
|
// ------------------------------------------------------------------
|
|
@@ -18969,6 +19070,10 @@ var LoggingClient = class {
|
|
|
18969
19070
|
/** @internal */
|
|
18970
19071
|
_close() {
|
|
18971
19072
|
debug("lifecycle", "LoggingClient._close() called");
|
|
19073
|
+
if (this._loggerFlushTimer !== null) {
|
|
19074
|
+
clearInterval(this._loggerFlushTimer);
|
|
19075
|
+
this._loggerFlushTimer = null;
|
|
19076
|
+
}
|
|
18972
19077
|
for (const adapter of this._adapters) {
|
|
18973
19078
|
try {
|
|
18974
19079
|
adapter.uninstallHook();
|
|
@@ -19037,12 +19142,34 @@ var LoggingClient = class {
|
|
|
19037
19142
|
}
|
|
19038
19143
|
}
|
|
19039
19144
|
/** Called by adapter hooks when a new logger is created in the framework. */
|
|
19040
|
-
_onAdapterNewLogger(
|
|
19041
|
-
debug("discovery", `new logger intercepted at runtime: ${
|
|
19042
|
-
const
|
|
19043
|
-
|
|
19044
|
-
|
|
19045
|
-
|
|
19145
|
+
_onAdapterNewLogger(name, level) {
|
|
19146
|
+
debug("discovery", `new logger intercepted at runtime: ${name}`);
|
|
19147
|
+
const service = this._parent?._service ?? null;
|
|
19148
|
+
const environment = this._parent?._environment ?? null;
|
|
19149
|
+
this._loggerBuffer.add(name, level, level, service, environment);
|
|
19150
|
+
if (this._loggerBuffer.pendingCount >= 50) {
|
|
19151
|
+
void this._flushLoggerBuffer();
|
|
19152
|
+
}
|
|
19153
|
+
}
|
|
19154
|
+
/** Flush buffered loggers to the bulk-register endpoint. */
|
|
19155
|
+
async _flushLoggerBuffer() {
|
|
19156
|
+
const batch = this._loggerBuffer.drain();
|
|
19157
|
+
if (batch.length === 0) return;
|
|
19158
|
+
debug("registration", `flushing ${batch.length} logger(s) to bulk-register endpoint`);
|
|
19159
|
+
try {
|
|
19160
|
+
const result = await this._http.POST("/api/v1/loggers/bulk", {
|
|
19161
|
+
body: { loggers: batch }
|
|
19162
|
+
});
|
|
19163
|
+
if (result.error !== void 0) {
|
|
19164
|
+
console.warn("[smplkit] Logger bulk registration failed");
|
|
19165
|
+
} else {
|
|
19166
|
+
debug("registration", `bulk-register complete (${batch.length} logger(s))`);
|
|
19167
|
+
}
|
|
19168
|
+
} catch (err) {
|
|
19169
|
+
console.warn(
|
|
19170
|
+
`[smplkit] Logger bulk registration failed: ${err instanceof Error ? err.message : String(err)}`
|
|
19171
|
+
);
|
|
19172
|
+
}
|
|
19046
19173
|
}
|
|
19047
19174
|
// ------------------------------------------------------------------
|
|
19048
19175
|
// Internal: WebSocket handler
|