@smplkit/sdk 3.0.21 → 3.0.23

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 CHANGED
@@ -16796,19 +16796,20 @@ var AuditEventBuffer = class {
16796
16796
 
16797
16797
  // src/audit/client.ts
16798
16798
  var JSONAPI_CONTENT_TYPE = "application/vnd.api+json";
16799
- function _attributesFromInput(input) {
16799
+ function _eventBodyFromInput(input) {
16800
16800
  const attrs = {
16801
16801
  action: input.action,
16802
16802
  resource_type: input.resourceType,
16803
- resource_id: input.resourceId
16803
+ resource_id: input.resourceId,
16804
+ do_not_forward: input.doNotForward ?? false
16804
16805
  };
16805
16806
  if (input.occurredAt !== void 0) {
16806
- const ts = input.occurredAt instanceof Date ? input.occurredAt.toISOString() : input.occurredAt;
16807
- attrs.occurred_at = ts;
16807
+ attrs.occurred_at = input.occurredAt instanceof Date ? input.occurredAt.toISOString() : input.occurredAt;
16808
16808
  }
16809
- if (input.data !== void 0) attrs.data = input.data;
16810
- if (input.doNotForward) attrs.do_not_forward = true;
16811
- return attrs;
16809
+ if (input.data !== void 0) {
16810
+ attrs.data = input.data;
16811
+ }
16812
+ return { data: { id: "", type: "event", attributes: attrs } };
16812
16813
  }
16813
16814
  function _eventFromResource(resource) {
16814
16815
  const attrs = resource.attributes;
@@ -16857,9 +16858,13 @@ function _forwarderAttributes(input) {
16857
16858
  enabled: input.enabled ?? true,
16858
16859
  http: _httpToWire(input.http)
16859
16860
  };
16860
- if (input.filter !== void 0) attrs.filter = input.filter;
16861
+ if (input.filter !== void 0) {
16862
+ attrs.filter = input.filter;
16863
+ }
16861
16864
  if (input.transform !== void 0) attrs.transform = input.transform;
16862
- if (input.data !== void 0) attrs.data = input.data;
16865
+ if (input.data !== void 0) {
16866
+ attrs.data = input.data;
16867
+ }
16863
16868
  return attrs;
16864
16869
  }
16865
16870
  function _forwarderFromResource(resource) {
@@ -16923,9 +16928,6 @@ var EventsClient = class {
16923
16928
  const headerInit = {};
16924
16929
  if (item.idempotencyKey !== null) headerInit["Idempotency-Key"] = item.idempotencyKey;
16925
16930
  const result = await this._http.POST("/api/v1/events", {
16926
- // Casting through unknown because the generated body type is
16927
- // EventResponse with id required, while the wrapper builds an
16928
- // unsaved-resource body without an id (server assigns).
16929
16931
  body: item.body,
16930
16932
  headers: headerInit
16931
16933
  });
@@ -16945,10 +16947,7 @@ var EventsClient = class {
16945
16947
  * failures, so a misuse will silently disappear from the queue).
16946
16948
  */
16947
16949
  record(input) {
16948
- const body = {
16949
- data: { id: "", type: "event", attributes: _attributesFromInput(input) }
16950
- };
16951
- this._buffer.enqueue(body, input.idempotencyKey ?? null);
16950
+ this._buffer.enqueue(_eventBodyFromInput(input), input.idempotencyKey ?? null);
16952
16951
  }
16953
16952
  async list(params = {}) {
16954
16953
  const query = {};
@@ -17078,10 +17077,10 @@ var ForwardersClient = class {
17078
17077
  deliveries;
17079
17078
  actions;
17080
17079
  async create(input) {
17081
- const body = { data: { id: "", type: "forwarder", attributes: _forwarderAttributes(input) } };
17082
- const result = await this._http.POST("/api/v1/forwarders", {
17083
- body
17084
- });
17080
+ const body = {
17081
+ data: { id: "", type: "forwarder", attributes: _forwarderAttributes(input) }
17082
+ };
17083
+ const result = await this._http.POST("/api/v1/forwarders", { body });
17085
17084
  if (!result.response.ok || result.data === void 0) {
17086
17085
  throw new Error(
17087
17086
  `audit create forwarder failed: ${result.response.status} ${result.response.statusText}`
@@ -19200,6 +19199,15 @@ var FlagRegistrationBuffer = class {
19200
19199
  environment: decl.environment ?? void 0
19201
19200
  });
19202
19201
  }
19202
+ /** Non-destructive snapshot — items remain in the buffer until committed. */
19203
+ peek() {
19204
+ return [...this._pending];
19205
+ }
19206
+ /** Remove successfully-sent items by id. Called after a successful POST. */
19207
+ commit(ids) {
19208
+ this._pending = this._pending.filter((item) => !ids.has(item.id));
19209
+ }
19210
+ /** Destructively clear the buffer. For teardown / test use only. */
19203
19211
  drain() {
19204
19212
  const batch = this._pending;
19205
19213
  this._pending = [];
@@ -19341,10 +19349,13 @@ var ManagementFlagsClient = class {
19341
19349
  }
19342
19350
  /** Send any pending flag declarations to the server. */
19343
19351
  async flush() {
19344
- const batch = this._buffer.drain();
19352
+ const batch = this._buffer.peek();
19345
19353
  if (batch.length === 0) return;
19346
19354
  try {
19347
- await this._http.POST("/api/v1/flags/bulk", { body: { flags: batch } });
19355
+ const result = await this._http.POST("/api/v1/flags/bulk", { body: { flags: batch } });
19356
+ if (result.response.ok) {
19357
+ this._buffer.commit(new Set(batch.map((b) => b.id)));
19358
+ }
19348
19359
  } catch {
19349
19360
  }
19350
19361
  }
@@ -20893,6 +20904,15 @@ var FlagRegistrationBuffer2 = class {
20893
20904
  });
20894
20905
  }
20895
20906
  }
20907
+ /** Non-destructive snapshot — items remain in the buffer until committed. */
20908
+ peek() {
20909
+ return [...this._pending];
20910
+ }
20911
+ /** Remove successfully-sent items by id. Called after a successful POST. */
20912
+ commit(ids) {
20913
+ this._pending = this._pending.filter((item) => !ids.has(item.id));
20914
+ }
20915
+ /** Destructively clear the buffer. For teardown / test use only. */
20896
20916
  drain() {
20897
20917
  const batch = this._pending;
20898
20918
  this._pending = [];
@@ -20921,6 +20941,10 @@ var FlagsClient = class {
20921
20941
  _flagBuffer = new FlagRegistrationBuffer2();
20922
20942
  _flagFlushTimer = null;
20923
20943
  _handles = {};
20944
+ // Backoff-retry state for initialize() / _connectInternal()
20945
+ _initBackoffMs = 1e3;
20946
+ _initRetryTimer = null;
20947
+ _wsSubscribed = false;
20924
20948
  _globalListeners = [];
20925
20949
  _keyListeners = /* @__PURE__ */ new Map();
20926
20950
  // Shared WebSocket (set during initialize)
@@ -20998,7 +21022,14 @@ var FlagsClient = class {
20998
21022
  this._parent?._environment ?? null
20999
21023
  );
21000
21024
  if (this._flagBuffer.pendingCount >= FLAG_REGISTRATION_FLUSH_SIZE2) {
21001
- void this._flushFlags();
21025
+ void this._flushFlags().catch((err) => {
21026
+ const msg = err instanceof Error ? err.message : String(err);
21027
+ console.warn(`[smplkit] Failed to bulk-register flags: ${msg}`);
21028
+ debug(
21029
+ "registration",
21030
+ `flag bulk-register error: ${err instanceof Error ? err.stack ?? msg : msg}`
21031
+ );
21032
+ });
21002
21033
  }
21003
21034
  return handle;
21004
21035
  }
@@ -21024,7 +21055,14 @@ var FlagsClient = class {
21024
21055
  this._parent?._environment ?? null
21025
21056
  );
21026
21057
  if (this._flagBuffer.pendingCount >= FLAG_REGISTRATION_FLUSH_SIZE2) {
21027
- void this._flushFlags();
21058
+ void this._flushFlags().catch((err) => {
21059
+ const msg = err instanceof Error ? err.message : String(err);
21060
+ console.warn(`[smplkit] Failed to bulk-register flags: ${msg}`);
21061
+ debug(
21062
+ "registration",
21063
+ `flag bulk-register error: ${err instanceof Error ? err.stack ?? msg : msg}`
21064
+ );
21065
+ });
21028
21066
  }
21029
21067
  return handle;
21030
21068
  }
@@ -21050,7 +21088,14 @@ var FlagsClient = class {
21050
21088
  this._parent?._environment ?? null
21051
21089
  );
21052
21090
  if (this._flagBuffer.pendingCount >= FLAG_REGISTRATION_FLUSH_SIZE2) {
21053
- void this._flushFlags();
21091
+ void this._flushFlags().catch((err) => {
21092
+ const msg = err instanceof Error ? err.message : String(err);
21093
+ console.warn(`[smplkit] Failed to bulk-register flags: ${msg}`);
21094
+ debug(
21095
+ "registration",
21096
+ `flag bulk-register error: ${err instanceof Error ? err.stack ?? msg : msg}`
21097
+ );
21098
+ });
21054
21099
  }
21055
21100
  return handle;
21056
21101
  }
@@ -21076,7 +21121,14 @@ var FlagsClient = class {
21076
21121
  this._parent?._environment ?? null
21077
21122
  );
21078
21123
  if (this._flagBuffer.pendingCount >= FLAG_REGISTRATION_FLUSH_SIZE2) {
21079
- void this._flushFlags();
21124
+ void this._flushFlags().catch((err) => {
21125
+ const msg = err instanceof Error ? err.message : String(err);
21126
+ console.warn(`[smplkit] Failed to bulk-register flags: ${msg}`);
21127
+ debug(
21128
+ "registration",
21129
+ `flag bulk-register error: ${err instanceof Error ? err.stack ?? msg : msg}`
21130
+ );
21131
+ });
21080
21132
  }
21081
21133
  return handle;
21082
21134
  }
@@ -21111,19 +21163,51 @@ var FlagsClient = class {
21111
21163
  if (this._initialized) return;
21112
21164
  debug("lifecycle", "FlagsClient.initialize() called");
21113
21165
  this._environment = this._parent?._environment ?? null;
21114
- await this._flushFlags();
21115
- await this._fetchAllFlags();
21166
+ try {
21167
+ await this._flushFlags();
21168
+ await this._fetchAllFlags();
21169
+ } catch (err) {
21170
+ const msg = err instanceof Error ? err.message : String(err);
21171
+ console.warn(`[smplkit] FlagsClient initialization failed (will retry): ${msg}`);
21172
+ if (this._initRetryTimer !== null) {
21173
+ clearTimeout(this._initRetryTimer);
21174
+ this._initRetryTimer = null;
21175
+ }
21176
+ const delay = this._initBackoffMs;
21177
+ this._initBackoffMs = Math.min(this._initBackoffMs * 2, 6e4);
21178
+ this._initRetryTimer = setTimeout(() => {
21179
+ this._initRetryTimer = null;
21180
+ void this.initialize();
21181
+ }, delay);
21182
+ if (typeof this._initRetryTimer === "object" && "unref" in this._initRetryTimer) {
21183
+ this._initRetryTimer.unref();
21184
+ }
21185
+ return;
21186
+ }
21187
+ this._initBackoffMs = 1e3;
21116
21188
  this._initialized = true;
21117
21189
  this._cache.clear();
21118
- this._wsManager = this._ensureWs();
21119
- this._wsManager.on("flag_changed", this._handleFlagChanged);
21120
- this._wsManager.on("flag_deleted", this._handleFlagDeleted);
21121
- this._wsManager.on("flags_changed", this._handleFlagsChanged);
21122
- this._flagFlushTimer = setInterval(() => {
21123
- void this._flushFlags();
21124
- }, FLAG_REGISTRATION_FLUSH_INTERVAL_MS);
21125
- if (typeof this._flagFlushTimer === "object" && "unref" in this._flagFlushTimer) {
21126
- this._flagFlushTimer.unref();
21190
+ if (!this._wsSubscribed) {
21191
+ this._wsManager = this._ensureWs();
21192
+ this._wsManager.on("flag_changed", this._handleFlagChanged);
21193
+ this._wsManager.on("flag_deleted", this._handleFlagDeleted);
21194
+ this._wsManager.on("flags_changed", this._handleFlagsChanged);
21195
+ this._wsSubscribed = true;
21196
+ }
21197
+ if (this._flagFlushTimer === null) {
21198
+ this._flagFlushTimer = setInterval(() => {
21199
+ void this._flushFlags().catch((err) => {
21200
+ const msg = err instanceof Error ? err.message : String(err);
21201
+ console.warn(`[smplkit] Failed to bulk-register flags: ${msg}`);
21202
+ debug(
21203
+ "registration",
21204
+ `flag bulk-register error: ${err instanceof Error ? err.stack ?? msg : msg}`
21205
+ );
21206
+ });
21207
+ }, FLAG_REGISTRATION_FLUSH_INTERVAL_MS);
21208
+ if (typeof this._flagFlushTimer === "object" && "unref" in this._flagFlushTimer) {
21209
+ this._flagFlushTimer.unref();
21210
+ }
21127
21211
  }
21128
21212
  }
21129
21213
  /**
@@ -21133,6 +21217,10 @@ var FlagsClient = class {
21133
21217
  * @internal
21134
21218
  */
21135
21219
  _close() {
21220
+ if (this._initRetryTimer !== null) {
21221
+ clearTimeout(this._initRetryTimer);
21222
+ this._initRetryTimer = null;
21223
+ }
21136
21224
  if (this._flagFlushTimer !== null) {
21137
21225
  clearInterval(this._flagFlushTimer);
21138
21226
  this._flagFlushTimer = null;
@@ -21145,10 +21233,16 @@ var FlagsClient = class {
21145
21233
  }
21146
21234
  this._cache.clear();
21147
21235
  this._initialized = false;
21236
+ this._wsSubscribed = false;
21237
+ this._initBackoffMs = 1e3;
21148
21238
  this._environment = null;
21149
21239
  }
21150
21240
  /** Disconnect the flags runtime and release resources. */
21151
21241
  async disconnect() {
21242
+ if (this._initRetryTimer !== null) {
21243
+ clearTimeout(this._initRetryTimer);
21244
+ this._initRetryTimer = null;
21245
+ }
21152
21246
  if (this._wsManager !== null) {
21153
21247
  this._wsManager.off("flag_changed", this._handleFlagChanged);
21154
21248
  this._wsManager.off("flag_deleted", this._handleFlagDeleted);
@@ -21163,6 +21257,8 @@ var FlagsClient = class {
21163
21257
  this._flagStore = {};
21164
21258
  this._cache.clear();
21165
21259
  this._initialized = false;
21260
+ this._wsSubscribed = false;
21261
+ this._initBackoffMs = 1e3;
21166
21262
  this._environment = null;
21167
21263
  }
21168
21264
  /** Refresh all flag definitions from the server. */
@@ -21291,19 +21387,51 @@ var FlagsClient = class {
21291
21387
  /** @internal — called by SmplClient constructor / lazy init. */
21292
21388
  async _connectInternal(environment) {
21293
21389
  this._environment = environment;
21294
- await this._flushFlags();
21295
- await this._fetchAllFlags();
21390
+ try {
21391
+ await this._flushFlags();
21392
+ await this._fetchAllFlags();
21393
+ } catch (err) {
21394
+ const msg = err instanceof Error ? err.message : String(err);
21395
+ console.warn(`[smplkit] FlagsClient initialization failed (will retry): ${msg}`);
21396
+ if (this._initRetryTimer !== null) {
21397
+ clearTimeout(this._initRetryTimer);
21398
+ this._initRetryTimer = null;
21399
+ }
21400
+ const delay = this._initBackoffMs;
21401
+ this._initBackoffMs = Math.min(this._initBackoffMs * 2, 6e4);
21402
+ this._initRetryTimer = setTimeout(() => {
21403
+ this._initRetryTimer = null;
21404
+ void this._connectInternal(environment);
21405
+ }, delay);
21406
+ if (typeof this._initRetryTimer === "object" && "unref" in this._initRetryTimer) {
21407
+ this._initRetryTimer.unref();
21408
+ }
21409
+ return;
21410
+ }
21411
+ this._initBackoffMs = 1e3;
21296
21412
  this._initialized = true;
21297
21413
  this._cache.clear();
21298
- this._wsManager = this._ensureWs();
21299
- this._wsManager.on("flag_changed", this._handleFlagChanged);
21300
- this._wsManager.on("flag_deleted", this._handleFlagDeleted);
21301
- this._wsManager.on("flags_changed", this._handleFlagsChanged);
21302
- this._flagFlushTimer = setInterval(() => {
21303
- void this._flushFlags();
21304
- }, FLAG_REGISTRATION_FLUSH_INTERVAL_MS);
21305
- if (typeof this._flagFlushTimer === "object" && "unref" in this._flagFlushTimer) {
21306
- this._flagFlushTimer.unref();
21414
+ if (!this._wsSubscribed) {
21415
+ this._wsManager = this._ensureWs();
21416
+ this._wsManager.on("flag_changed", this._handleFlagChanged);
21417
+ this._wsManager.on("flag_deleted", this._handleFlagDeleted);
21418
+ this._wsManager.on("flags_changed", this._handleFlagsChanged);
21419
+ this._wsSubscribed = true;
21420
+ }
21421
+ if (this._flagFlushTimer === null) {
21422
+ this._flagFlushTimer = setInterval(() => {
21423
+ void this._flushFlags().catch((err) => {
21424
+ const msg = err instanceof Error ? err.message : String(err);
21425
+ console.warn(`[smplkit] Failed to bulk-register flags: ${msg}`);
21426
+ debug(
21427
+ "registration",
21428
+ `flag bulk-register error: ${err instanceof Error ? err.stack ?? msg : msg}`
21429
+ );
21430
+ });
21431
+ }, FLAG_REGISTRATION_FLUSH_INTERVAL_MS);
21432
+ if (typeof this._flagFlushTimer === "object" && "unref" in this._flagFlushTimer) {
21433
+ this._flagFlushTimer.unref();
21434
+ }
21307
21435
  }
21308
21436
  }
21309
21437
  // ------------------------------------------------------------------
@@ -21462,21 +21590,16 @@ var FlagsClient = class {
21462
21590
  // Internal: flag registration flush
21463
21591
  // ------------------------------------------------------------------
21464
21592
  async _flushFlags() {
21465
- const batch = this._flagBuffer.drain();
21593
+ const batch = this._flagBuffer.peek();
21466
21594
  if (batch.length === 0) return;
21467
21595
  debug("registration", `flushing ${batch.length} flag(s) to bulk-register endpoint`);
21468
- try {
21469
- await this._http.POST("/api/v1/flags/bulk", {
21470
- body: { flags: batch }
21471
- });
21472
- } catch (err) {
21473
- const msg = err instanceof Error ? err.message : String(err);
21474
- console.warn(`[smplkit] Failed to bulk-register flags: ${msg}`);
21475
- debug(
21476
- "registration",
21477
- `flag bulk-register error: ${err instanceof Error ? err.stack ?? msg : msg}`
21478
- );
21596
+ const result = await this._http.POST("/api/v1/flags/bulk", {
21597
+ body: { flags: batch }
21598
+ });
21599
+ if (!result.response.ok) {
21600
+ throw new Error(`HTTP ${result.response.status}`);
21479
21601
  }
21602
+ this._flagBuffer.commit(new Set(batch.map((b) => b.id)));
21480
21603
  }
21481
21604
  // ------------------------------------------------------------------
21482
21605
  // Internal: context flush