@smplkit/sdk 1.8.4 → 1.9.0

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.js CHANGED
@@ -16614,7 +16614,7 @@ var require_pino = __commonJS({
16614
16614
  });
16615
16615
 
16616
16616
  // src/client.ts
16617
- import createClient4 from "openapi-fetch";
16617
+ import createClient5 from "openapi-fetch";
16618
16618
 
16619
16619
  // src/config/client.ts
16620
16620
  import createClient from "openapi-fetch";
@@ -17846,7 +17846,7 @@ var FlagsClient = class {
17846
17846
  /** Management API — CRUD operations on Flag models. */
17847
17847
  management;
17848
17848
  /** @internal */
17849
- constructor(apiKey, ensureWs, timeout, flagsBaseUrl, appBaseUrl) {
17849
+ constructor(apiKey, ensureWs, timeout, flagsBaseUrl, appBaseUrl, contextBuffer) {
17850
17850
  this._apiKey = apiKey;
17851
17851
  this._ensureWs = ensureWs;
17852
17852
  const resolvedBaseUrl = flagsBaseUrl ?? FLAGS_BASE_URL;
@@ -17883,6 +17883,9 @@ var FlagsClient = class {
17883
17883
  },
17884
17884
  fetch: fetchWithTimeout
17885
17885
  });
17886
+ if (contextBuffer !== void 0) {
17887
+ this._contextBuffer = contextBuffer;
17888
+ }
17886
17889
  this.management = new FlagsManagement(this);
17887
17890
  }
17888
17891
  // ------------------------------------------------------------------
@@ -18257,25 +18260,6 @@ var FlagsClient = class {
18257
18260
  }
18258
18261
  }
18259
18262
  // ------------------------------------------------------------------
18260
- // Runtime: context registration
18261
- // ------------------------------------------------------------------
18262
- /**
18263
- * Register context(s) with the server.
18264
- *
18265
- * Accepts a single Context or an array. Works before `initialize()` is called.
18266
- */
18267
- register(context) {
18268
- if (Array.isArray(context)) {
18269
- this._contextBuffer.observe(context);
18270
- } else {
18271
- this._contextBuffer.observe([context]);
18272
- }
18273
- }
18274
- /** Flush pending context registrations to the server. */
18275
- async flushContexts() {
18276
- await this._flushContexts();
18277
- }
18278
- // ------------------------------------------------------------------
18279
18263
  // Runtime: Tier 1 evaluate
18280
18264
  // ------------------------------------------------------------------
18281
18265
  /**
@@ -18844,6 +18828,16 @@ var LoggingManagement = class {
18844
18828
  async deleteGroup(id) {
18845
18829
  return this._client._mgDeleteGroup(id);
18846
18830
  }
18831
+ /**
18832
+ * Bulk-register explicit logger sources with the logging service.
18833
+ *
18834
+ * Unlike `start()`, which auto-discovers loggers from the current
18835
+ * process, this method accepts explicit `service` and `environment`
18836
+ * overrides — useful for sample-data seeding and test fixtures.
18837
+ */
18838
+ async registerSources(sources) {
18839
+ return this._client._mgRegisterSources(sources);
18840
+ }
18847
18841
  };
18848
18842
  var LoggingClient = class {
18849
18843
  /** @internal */
@@ -19022,6 +19016,26 @@ var LoggingClient = class {
19022
19016
  return data.data.map((r) => this._groupToModel(r));
19023
19017
  }
19024
19018
  /** @internal */
19019
+ async _mgRegisterSources(sources) {
19020
+ if (sources.length === 0) return;
19021
+ const loggers = sources.map((src) => ({
19022
+ id: src.name,
19023
+ level: src.level ?? void 0,
19024
+ resolved_level: src.resolvedLevel,
19025
+ service: src.service,
19026
+ environment: src.environment
19027
+ }));
19028
+ try {
19029
+ const result = await this._http.POST("/api/v1/loggers/bulk", {
19030
+ body: { loggers }
19031
+ });
19032
+ if (result.error !== void 0)
19033
+ await checkError3(result.response, "Failed to register sources");
19034
+ } catch (err) {
19035
+ wrapFetchError3(err);
19036
+ }
19037
+ }
19038
+ /** @internal */
19025
19039
  async _mgDeleteGroup(id) {
19026
19040
  const group = await this.management.getGroup(id);
19027
19041
  try {
@@ -19549,10 +19563,11 @@ var LoggingClient = class {
19549
19563
  // ------------------------------------------------------------------
19550
19564
  _loggerToModel(resource) {
19551
19565
  const attrs = resource.attributes;
19566
+ const rawLevel = attrs.level ?? null;
19552
19567
  return new Logger(this, {
19553
19568
  id: resource.id ?? null,
19554
19569
  name: attrs.name,
19555
- level: attrs.level ?? null,
19570
+ level: rawLevel,
19556
19571
  group: attrs.group ?? null,
19557
19572
  managed: attrs.managed ?? false,
19558
19573
  sources: [],
@@ -19563,11 +19578,12 @@ var LoggingClient = class {
19563
19578
  }
19564
19579
  _groupToModel(resource) {
19565
19580
  const attrs = resource.attributes;
19581
+ const rawLevel = attrs.level ?? null;
19566
19582
  return new LogGroup(this, {
19567
19583
  id: resource.id ?? null,
19568
19584
  key: attrs.key ?? null,
19569
19585
  name: attrs.name,
19570
- level: attrs.level ?? null,
19586
+ level: rawLevel,
19571
19587
  group: attrs.parent_id ?? null,
19572
19588
  environments: attrs.environments ?? {},
19573
19589
  createdAt: attrs.created_at ?? null,
@@ -19576,6 +19592,666 @@ var LoggingClient = class {
19576
19592
  }
19577
19593
  };
19578
19594
 
19595
+ // src/management/client.ts
19596
+ import createClient4 from "openapi-fetch";
19597
+
19598
+ // src/management/types.ts
19599
+ var EnvironmentClassification = /* @__PURE__ */ ((EnvironmentClassification2) => {
19600
+ EnvironmentClassification2["STANDARD"] = "STANDARD";
19601
+ EnvironmentClassification2["AD_HOC"] = "AD_HOC";
19602
+ return EnvironmentClassification2;
19603
+ })(EnvironmentClassification || {});
19604
+
19605
+ // src/management/models.ts
19606
+ var Environment = class {
19607
+ /** Unique slug identifier (e.g. `"production"`). */
19608
+ id;
19609
+ /** Human-readable display name. */
19610
+ name;
19611
+ /** Hex color code, or null. */
19612
+ color;
19613
+ /** Whether this is a STANDARD or AD_HOC environment. */
19614
+ classification;
19615
+ /** When the environment was created. */
19616
+ createdAt;
19617
+ /** When the environment was last updated. */
19618
+ updatedAt;
19619
+ /** @internal */
19620
+ _client;
19621
+ /** @internal */
19622
+ constructor(client, fields) {
19623
+ this._client = client;
19624
+ this.id = fields.id;
19625
+ this.name = fields.name;
19626
+ this.color = fields.color;
19627
+ this.classification = fields.classification;
19628
+ this.createdAt = fields.createdAt;
19629
+ this.updatedAt = fields.updatedAt;
19630
+ }
19631
+ /** Persist this environment to the server (creates if new, updates if existing). */
19632
+ async save() {
19633
+ if (this._client === null) {
19634
+ throw new Error("Environment was constructed without a client; cannot save");
19635
+ }
19636
+ if (this.createdAt === null) {
19637
+ const saved = await this._client._create(this);
19638
+ this._apply(saved);
19639
+ } else {
19640
+ const saved = await this._client._update(this);
19641
+ this._apply(saved);
19642
+ }
19643
+ }
19644
+ /** @internal */
19645
+ _apply(other) {
19646
+ this.id = other.id;
19647
+ this.name = other.name;
19648
+ this.color = other.color;
19649
+ this.classification = other.classification;
19650
+ this.createdAt = other.createdAt;
19651
+ this.updatedAt = other.updatedAt;
19652
+ }
19653
+ toString() {
19654
+ return `Environment(id=${this.id}, name=${this.name}, classification=${this.classification})`;
19655
+ }
19656
+ };
19657
+ var ContextType = class {
19658
+ /** Unique slug identifier (e.g. `"user"`). */
19659
+ id;
19660
+ /** Human-readable display name. */
19661
+ name;
19662
+ /** Known attribute keys with metadata objects. */
19663
+ attributes;
19664
+ /** When the context type was created. */
19665
+ createdAt;
19666
+ /** When the context type was last updated. */
19667
+ updatedAt;
19668
+ /** @internal */
19669
+ _client;
19670
+ /** @internal */
19671
+ constructor(client, fields) {
19672
+ this._client = client;
19673
+ this.id = fields.id;
19674
+ this.name = fields.name;
19675
+ this.attributes = { ...fields.attributes };
19676
+ this.createdAt = fields.createdAt;
19677
+ this.updatedAt = fields.updatedAt;
19678
+ }
19679
+ /** Add a known-attribute slot. Local; call `save()` to persist. */
19680
+ addAttribute(name, metadata = {}) {
19681
+ this.attributes = { ...this.attributes, [name]: metadata };
19682
+ }
19683
+ /** Remove a known-attribute slot. Local; call `save()` to persist. */
19684
+ removeAttribute(name) {
19685
+ const attrs = { ...this.attributes };
19686
+ delete attrs[name];
19687
+ this.attributes = attrs;
19688
+ }
19689
+ /** Replace a known-attribute slot's metadata. Local; call `save()` to persist. */
19690
+ updateAttribute(name, metadata) {
19691
+ this.attributes = { ...this.attributes, [name]: metadata };
19692
+ }
19693
+ /** Persist this context type to the server (creates if new, updates if existing). */
19694
+ async save() {
19695
+ if (this._client === null) {
19696
+ throw new Error("ContextType was constructed without a client; cannot save");
19697
+ }
19698
+ if (this.createdAt === null) {
19699
+ const saved = await this._client._create(this);
19700
+ this._apply(saved);
19701
+ } else {
19702
+ const saved = await this._client._update(this);
19703
+ this._apply(saved);
19704
+ }
19705
+ }
19706
+ /** @internal */
19707
+ _apply(other) {
19708
+ this.id = other.id;
19709
+ this.name = other.name;
19710
+ this.attributes = { ...other.attributes };
19711
+ this.createdAt = other.createdAt;
19712
+ this.updatedAt = other.updatedAt;
19713
+ }
19714
+ toString() {
19715
+ return `ContextType(id=${this.id}, name=${this.name})`;
19716
+ }
19717
+ };
19718
+ var ContextEntity = class {
19719
+ /** Context type key (e.g. `"user"`). */
19720
+ type;
19721
+ /** Entity key (e.g. `"user-123"`). */
19722
+ key;
19723
+ /** Human-readable display name, or null. */
19724
+ name;
19725
+ /** Observed attributes. */
19726
+ attributes;
19727
+ /** When the context was created. */
19728
+ createdAt;
19729
+ /** When the context was last updated. */
19730
+ updatedAt;
19731
+ /** @internal */
19732
+ constructor(fields) {
19733
+ this.type = fields.type;
19734
+ this.key = fields.key;
19735
+ this.name = fields.name;
19736
+ this.attributes = { ...fields.attributes };
19737
+ this.createdAt = fields.createdAt;
19738
+ this.updatedAt = fields.updatedAt;
19739
+ }
19740
+ /** Composite `"type:key"` identifier. */
19741
+ get id() {
19742
+ return `${this.type}:${this.key}`;
19743
+ }
19744
+ toString() {
19745
+ return `ContextEntity(type=${this.type}, key=${this.key})`;
19746
+ }
19747
+ };
19748
+ var AccountSettings = class {
19749
+ /** @internal */
19750
+ _data;
19751
+ /** @internal */
19752
+ _client;
19753
+ /** @internal */
19754
+ constructor(client, data) {
19755
+ this._client = client;
19756
+ this._data = { ...data };
19757
+ }
19758
+ /** The full settings dict. Direct mutations are reflected in `save()`. */
19759
+ get raw() {
19760
+ return this._data;
19761
+ }
19762
+ set raw(value) {
19763
+ this._data = { ...value };
19764
+ }
19765
+ /** Canonical ordering of STANDARD environments. Empty array if unset. */
19766
+ get environmentOrder() {
19767
+ const val = this._data["environment_order"];
19768
+ return Array.isArray(val) ? [...val] : [];
19769
+ }
19770
+ set environmentOrder(value) {
19771
+ this._data["environment_order"] = [...value];
19772
+ }
19773
+ /** Persist the settings to the server. */
19774
+ async save() {
19775
+ if (this._client === null) {
19776
+ throw new Error("AccountSettings was constructed without a client; cannot save");
19777
+ }
19778
+ const saved = await this._client._save(this._data);
19779
+ this._apply(saved);
19780
+ }
19781
+ /** @internal */
19782
+ _apply(other) {
19783
+ this._data = { ...other._data };
19784
+ }
19785
+ /** @internal — expose raw data for _save(). */
19786
+ get _rawData() {
19787
+ return this._data;
19788
+ }
19789
+ toString() {
19790
+ return `AccountSettings(${JSON.stringify(this._data)})`;
19791
+ }
19792
+ };
19793
+
19794
+ // src/management/client.ts
19795
+ function splitContextId(idOrType, key) {
19796
+ if (key === void 0) {
19797
+ if (!idOrType.includes(":")) {
19798
+ throw new Error(
19799
+ `context id must be 'type:key' (got ${JSON.stringify(idOrType)}); alternatively pass type and key as separate args`
19800
+ );
19801
+ }
19802
+ const colonIdx = idOrType.indexOf(":");
19803
+ return [idOrType.slice(0, colonIdx), idOrType.slice(colonIdx + 1)];
19804
+ }
19805
+ return [idOrType, key];
19806
+ }
19807
+ async function checkError4(response, _context) {
19808
+ const body = await response.text().catch(() => "");
19809
+ throwForStatus(response.status, body);
19810
+ }
19811
+ function wrapFetchError4(err) {
19812
+ if (err instanceof SmplError) {
19813
+ throw err;
19814
+ }
19815
+ if (err instanceof TypeError) {
19816
+ throw new SmplConnectionError(`Network error: ${err.message}`);
19817
+ }
19818
+ throw new SmplConnectionError(
19819
+ `Request failed: ${err instanceof Error ? err.message : String(err)}`
19820
+ );
19821
+ }
19822
+ function envFromResource(resource, client) {
19823
+ const attrs = resource.attributes ?? {};
19824
+ return new Environment(client, {
19825
+ id: resource.id ?? null,
19826
+ name: attrs.name ?? "",
19827
+ color: attrs.color ?? null,
19828
+ classification: attrs.classification === "AD_HOC" ? "AD_HOC" /* AD_HOC */ : "STANDARD" /* STANDARD */,
19829
+ createdAt: attrs.created_at ?? null,
19830
+ updatedAt: attrs.updated_at ?? null
19831
+ });
19832
+ }
19833
+ function ctFromResource(resource, client) {
19834
+ const attrs = resource.attributes ?? {};
19835
+ const rawMeta = attrs.attributes;
19836
+ const attributeMetadata = {};
19837
+ if (rawMeta && typeof rawMeta === "object") {
19838
+ for (const [k, v] of Object.entries(rawMeta)) {
19839
+ attributeMetadata[k] = typeof v === "object" && v !== null ? v : {};
19840
+ }
19841
+ }
19842
+ return new ContextType(client, {
19843
+ id: resource.id ?? null,
19844
+ name: attrs.name ?? "",
19845
+ attributes: attributeMetadata,
19846
+ createdAt: attrs.created_at ?? null,
19847
+ updatedAt: attrs.updated_at ?? null
19848
+ });
19849
+ }
19850
+ function ctxEntityFromResource(resource) {
19851
+ const compositeId = resource.id ?? "";
19852
+ const colonIdx = compositeId.indexOf(":");
19853
+ const ctxType = colonIdx >= 0 ? compositeId.slice(0, colonIdx) : compositeId;
19854
+ const ctxKey = colonIdx >= 0 ? compositeId.slice(colonIdx + 1) : "";
19855
+ const attrs = resource.attributes ?? {};
19856
+ const rawAttrs = attrs.attributes;
19857
+ const attrDict = rawAttrs && typeof rawAttrs === "object" ? { ...rawAttrs } : {};
19858
+ return new ContextEntity({
19859
+ type: ctxType,
19860
+ key: ctxKey,
19861
+ name: attrs.name ?? null,
19862
+ attributes: attrDict,
19863
+ createdAt: attrs.created_at ?? null,
19864
+ updatedAt: attrs.updated_at ?? null
19865
+ });
19866
+ }
19867
+ var EnvironmentsClient = class {
19868
+ /** @internal */
19869
+ constructor(_http) {
19870
+ this._http = _http;
19871
+ }
19872
+ /**
19873
+ * Return an unsaved `Environment`. Call `.save()` to persist.
19874
+ */
19875
+ new(id, options) {
19876
+ return new Environment(this, {
19877
+ id,
19878
+ name: options.name,
19879
+ color: options.color ?? null,
19880
+ classification: options.classification ?? "STANDARD" /* STANDARD */,
19881
+ createdAt: null,
19882
+ updatedAt: null
19883
+ });
19884
+ }
19885
+ /** List all environments. */
19886
+ async list() {
19887
+ let data;
19888
+ try {
19889
+ const result = await this._http.GET("/api/v1/environments", {});
19890
+ if (!result.response.ok) await checkError4(result.response, "Failed to list environments");
19891
+ data = result.data;
19892
+ } catch (err) {
19893
+ wrapFetchError4(err);
19894
+ }
19895
+ const items = data?.data ?? [];
19896
+ return items.map((r) => envFromResource(r, this));
19897
+ }
19898
+ /** Fetch an environment by id. */
19899
+ async get(id) {
19900
+ let data;
19901
+ try {
19902
+ const result = await this._http.GET("/api/v1/environments/{id}", {
19903
+ params: { path: { id } }
19904
+ });
19905
+ if (!result.response.ok) await checkError4(result.response, `Environment '${id}' not found`);
19906
+ data = result.data;
19907
+ } catch (err) {
19908
+ wrapFetchError4(err);
19909
+ }
19910
+ if (!data?.data) throw new SmplNotFoundError(`Environment with id '${id}' not found`);
19911
+ return envFromResource(data.data, this);
19912
+ }
19913
+ /** Delete an environment by id. */
19914
+ async delete(id) {
19915
+ try {
19916
+ const result = await this._http.DELETE("/api/v1/environments/{id}", {
19917
+ params: { path: { id } }
19918
+ });
19919
+ if (!result.response.ok && result.response.status !== 204)
19920
+ await checkError4(result.response, `Failed to delete environment '${id}'`);
19921
+ } catch (err) {
19922
+ wrapFetchError4(err);
19923
+ }
19924
+ }
19925
+ /** @internal — called by Environment.save() for new resources. */
19926
+ async _create(env) {
19927
+ const body = {
19928
+ data: {
19929
+ id: env.id,
19930
+ type: "environment",
19931
+ attributes: {
19932
+ name: env.name,
19933
+ color: env.color,
19934
+ classification: env.classification
19935
+ }
19936
+ }
19937
+ };
19938
+ let data;
19939
+ try {
19940
+ const result = await this._http.POST("/api/v1/environments", { body });
19941
+ if (!result.response.ok) await checkError4(result.response, "Failed to create environment");
19942
+ data = result.data;
19943
+ } catch (err) {
19944
+ wrapFetchError4(err);
19945
+ }
19946
+ if (!data?.data) throw new SmplValidationError("Failed to create environment");
19947
+ return envFromResource(data.data, this);
19948
+ }
19949
+ /** @internal — called by Environment.save() for existing resources. */
19950
+ async _update(env) {
19951
+ if (!env.id) throw new Error("Cannot update an Environment with no id");
19952
+ const body = {
19953
+ data: {
19954
+ id: env.id,
19955
+ type: "environment",
19956
+ attributes: {
19957
+ name: env.name,
19958
+ color: env.color,
19959
+ classification: env.classification
19960
+ }
19961
+ }
19962
+ };
19963
+ let data;
19964
+ try {
19965
+ const result = await this._http.PUT("/api/v1/environments/{id}", {
19966
+ params: { path: { id: env.id } },
19967
+ body
19968
+ });
19969
+ if (!result.response.ok)
19970
+ await checkError4(result.response, `Failed to update environment ${env.id}`);
19971
+ data = result.data;
19972
+ } catch (err) {
19973
+ wrapFetchError4(err);
19974
+ }
19975
+ if (!data?.data) throw new SmplValidationError(`Failed to update environment ${env.id}`);
19976
+ return envFromResource(data.data, this);
19977
+ }
19978
+ };
19979
+ var ContextTypesClient = class {
19980
+ /** @internal */
19981
+ constructor(_http) {
19982
+ this._http = _http;
19983
+ }
19984
+ /**
19985
+ * Return an unsaved `ContextType`. Call `.save()` to persist.
19986
+ */
19987
+ new(id, options = {}) {
19988
+ return new ContextType(this, {
19989
+ id,
19990
+ name: options.name ?? id,
19991
+ attributes: options.attributes ?? {},
19992
+ createdAt: null,
19993
+ updatedAt: null
19994
+ });
19995
+ }
19996
+ /** List all context types. */
19997
+ async list() {
19998
+ let data;
19999
+ try {
20000
+ const result = await this._http.GET("/api/v1/context_types", {});
20001
+ if (!result.response.ok) await checkError4(result.response, "Failed to list context types");
20002
+ data = result.data;
20003
+ } catch (err) {
20004
+ wrapFetchError4(err);
20005
+ }
20006
+ const items = data?.data ?? [];
20007
+ return items.map((r) => ctFromResource(r, this));
20008
+ }
20009
+ /** Fetch a context type by id. */
20010
+ async get(id) {
20011
+ let data;
20012
+ try {
20013
+ const result = await this._http.GET("/api/v1/context_types/{id}", {
20014
+ params: { path: { id } }
20015
+ });
20016
+ if (!result.response.ok) await checkError4(result.response, `ContextType '${id}' not found`);
20017
+ data = result.data;
20018
+ } catch (err) {
20019
+ wrapFetchError4(err);
20020
+ }
20021
+ if (!data?.data) throw new SmplNotFoundError(`ContextType with id '${id}' not found`);
20022
+ return ctFromResource(data.data, this);
20023
+ }
20024
+ /** Delete a context type by id. */
20025
+ async delete(id) {
20026
+ try {
20027
+ const result = await this._http.DELETE("/api/v1/context_types/{id}", {
20028
+ params: { path: { id } }
20029
+ });
20030
+ if (!result.response.ok && result.response.status !== 204)
20031
+ await checkError4(result.response, `Failed to delete context type '${id}'`);
20032
+ } catch (err) {
20033
+ wrapFetchError4(err);
20034
+ }
20035
+ }
20036
+ /** @internal — called by ContextType.save() for new resources. */
20037
+ async _create(ct) {
20038
+ const body = {
20039
+ data: {
20040
+ id: ct.id,
20041
+ type: "context_type",
20042
+ attributes: {
20043
+ id: ct.id,
20044
+ name: ct.name,
20045
+ attributes: ct.attributes
20046
+ }
20047
+ }
20048
+ };
20049
+ let data;
20050
+ try {
20051
+ const result = await this._http.POST("/api/v1/context_types", { body });
20052
+ if (!result.response.ok) await checkError4(result.response, "Failed to create context type");
20053
+ data = result.data;
20054
+ } catch (err) {
20055
+ wrapFetchError4(err);
20056
+ }
20057
+ if (!data?.data) throw new SmplValidationError("Failed to create context type");
20058
+ return ctFromResource(data.data, this);
20059
+ }
20060
+ /** @internal — called by ContextType.save() for existing resources. */
20061
+ async _update(ct) {
20062
+ if (!ct.id) throw new Error("Cannot update a ContextType with no id");
20063
+ const body = {
20064
+ data: {
20065
+ id: ct.id,
20066
+ type: "context_type",
20067
+ attributes: {
20068
+ id: ct.id,
20069
+ name: ct.name,
20070
+ attributes: ct.attributes
20071
+ }
20072
+ }
20073
+ };
20074
+ let data;
20075
+ try {
20076
+ const result = await this._http.PUT("/api/v1/context_types/{id}", {
20077
+ params: { path: { id: ct.id } },
20078
+ body
20079
+ });
20080
+ if (!result.response.ok)
20081
+ await checkError4(result.response, `Failed to update context type ${ct.id}`);
20082
+ data = result.data;
20083
+ } catch (err) {
20084
+ wrapFetchError4(err);
20085
+ }
20086
+ if (!data?.data) throw new SmplValidationError(`Failed to update context type ${ct.id}`);
20087
+ return ctFromResource(data.data, this);
20088
+ }
20089
+ };
20090
+ var ContextsClient = class {
20091
+ /** @internal */
20092
+ constructor(_http, _buffer) {
20093
+ this._http = _http;
20094
+ this._buffer = _buffer;
20095
+ }
20096
+ /**
20097
+ * Buffer context(s) for registration; optionally flush immediately.
20098
+ *
20099
+ * When `flush` is false (default), contexts are queued for the SDK's
20100
+ * background flush — right for high-frequency observation from a live
20101
+ * request handler. When `flush` is true the call awaits the round-trip
20102
+ * — right for IaC scripts.
20103
+ */
20104
+ async register(items, options = {}) {
20105
+ const batch = Array.isArray(items) ? items : [items];
20106
+ this._buffer.observe(batch);
20107
+ if (options.flush) {
20108
+ await this.flush();
20109
+ }
20110
+ }
20111
+ /** Send any pending context observations to the server. */
20112
+ async flush() {
20113
+ const batch = this._buffer.drain();
20114
+ if (batch.length === 0) return;
20115
+ try {
20116
+ const result = await this._http.POST("/api/v1/contexts/bulk", {
20117
+ body: {
20118
+ contexts: batch.map((ctx) => ({
20119
+ type: ctx.type,
20120
+ key: ctx.key,
20121
+ attributes: ctx.attributes
20122
+ }))
20123
+ }
20124
+ });
20125
+ if (!result.response.ok) await checkError4(result.response, "Failed to flush contexts");
20126
+ } catch (err) {
20127
+ wrapFetchError4(err);
20128
+ }
20129
+ }
20130
+ /** List all contexts of a given type. */
20131
+ async list(type) {
20132
+ let data;
20133
+ try {
20134
+ const result = await this._http.GET("/api/v1/contexts", {
20135
+ params: { query: { "filter[context_type]": type } }
20136
+ });
20137
+ if (!result.response.ok) await checkError4(result.response, "Failed to list contexts");
20138
+ data = result.data;
20139
+ } catch (err) {
20140
+ wrapFetchError4(err);
20141
+ }
20142
+ const items = data?.data ?? [];
20143
+ return items.map(ctxEntityFromResource);
20144
+ }
20145
+ /** Fetch a context by composite id (`"type:key"`) or by separate type and key. */
20146
+ async get(idOrType, key) {
20147
+ const [ctxType, ctxKey] = splitContextId(idOrType, key);
20148
+ const composite = `${ctxType}:${ctxKey}`;
20149
+ let data;
20150
+ try {
20151
+ const result = await this._http.GET("/api/v1/contexts/{id}", {
20152
+ params: { path: { id: composite } }
20153
+ });
20154
+ if (!result.response.ok)
20155
+ await checkError4(result.response, `Context '${composite}' not found`);
20156
+ data = result.data;
20157
+ } catch (err) {
20158
+ wrapFetchError4(err);
20159
+ }
20160
+ if (!data?.data) throw new SmplNotFoundError(`Context with id '${composite}' not found`);
20161
+ return ctxEntityFromResource(data.data);
20162
+ }
20163
+ /** Delete a context by composite id (`"type:key"`) or by separate type and key. */
20164
+ async delete(idOrType, key) {
20165
+ const [ctxType, ctxKey] = splitContextId(idOrType, key);
20166
+ const composite = `${ctxType}:${ctxKey}`;
20167
+ try {
20168
+ const result = await this._http.DELETE("/api/v1/contexts/{id}", {
20169
+ params: { path: { id: composite } }
20170
+ });
20171
+ if (!result.response.ok && result.response.status !== 204)
20172
+ await checkError4(result.response, `Failed to delete context '${composite}'`);
20173
+ } catch (err) {
20174
+ wrapFetchError4(err);
20175
+ }
20176
+ }
20177
+ };
20178
+ var AccountSettingsClient = class {
20179
+ /** @internal */
20180
+ constructor(_appBaseUrl, apiKey) {
20181
+ this._appBaseUrl = _appBaseUrl;
20182
+ this._headers = {
20183
+ Authorization: `Bearer ${apiKey}`,
20184
+ "Content-Type": "application/json",
20185
+ Accept: "application/json"
20186
+ };
20187
+ }
20188
+ _headers;
20189
+ /** Fetch the current account settings. */
20190
+ async get() {
20191
+ const url = `${this._appBaseUrl}/api/v1/accounts/current/settings`;
20192
+ let resp;
20193
+ try {
20194
+ resp = await fetch(url, { headers: this._headers });
20195
+ } catch (err) {
20196
+ throw new SmplConnectionError(
20197
+ `Network error: ${err instanceof Error ? err.message : String(err)}`
20198
+ );
20199
+ }
20200
+ if (!resp.ok) {
20201
+ const body = await resp.text().catch(() => "");
20202
+ throwForStatus(resp.status, body);
20203
+ }
20204
+ const data = await resp.json();
20205
+ return new AccountSettings(this, data ?? {});
20206
+ }
20207
+ /** @internal — called by AccountSettings.save(). */
20208
+ async _save(data) {
20209
+ const url = `${this._appBaseUrl}/api/v1/accounts/current/settings`;
20210
+ let resp;
20211
+ try {
20212
+ resp = await fetch(url, {
20213
+ method: "PUT",
20214
+ headers: this._headers,
20215
+ body: JSON.stringify(data)
20216
+ });
20217
+ } catch (err) {
20218
+ throw new SmplConnectionError(
20219
+ `Network error: ${err instanceof Error ? err.message : String(err)}`
20220
+ );
20221
+ }
20222
+ if (!resp.ok) {
20223
+ const body = await resp.text().catch(() => "");
20224
+ throwForStatus(resp.status, body);
20225
+ }
20226
+ const saved = await resp.json();
20227
+ return new AccountSettings(this, saved ?? {});
20228
+ }
20229
+ };
20230
+ var ManagementClient = class {
20231
+ /** CRUD for environments. */
20232
+ environments;
20233
+ /** Registration, list, get, and delete for context instances. */
20234
+ contexts;
20235
+ /** CRUD for context types (entity schemas). */
20236
+ context_types;
20237
+ /** Get/save for account-level settings. */
20238
+ account_settings;
20239
+ /** @internal */
20240
+ constructor(options) {
20241
+ const http = createClient4({
20242
+ baseUrl: options.appBaseUrl,
20243
+ headers: {
20244
+ Authorization: `Bearer ${options.apiKey}`,
20245
+ Accept: "application/json"
20246
+ }
20247
+ });
20248
+ this.environments = new EnvironmentsClient(http);
20249
+ this.contexts = new ContextsClient(http, options.buffer);
20250
+ this.context_types = new ContextTypesClient(http);
20251
+ this.account_settings = new AccountSettingsClient(options.appBaseUrl, options.apiKey);
20252
+ }
20253
+ };
20254
+
19579
20255
  // src/ws.ts
19580
20256
  import WebSocket from "ws";
19581
20257
  var BACKOFF_MS = [1e3, 2e3, 4e3, 8e3, 16e3, 32e3, 6e4];
@@ -20013,6 +20689,8 @@ var SmplClient = class {
20013
20689
  flags;
20014
20690
  /** Client for logging management and runtime. */
20015
20691
  logging;
20692
+ /** Client for app-plane management (environments, contexts, context types, account settings). */
20693
+ management;
20016
20694
  _wsManager = null;
20017
20695
  _apiKey;
20018
20696
  /** @internal */
@@ -20043,7 +20721,7 @@ var SmplClient = class {
20043
20721
  "lifecycle",
20044
20722
  `SmplClient created (api_key=${maskedKey}, environment=${cfg.environment}, service=${cfg.service})`
20045
20723
  );
20046
- this._appHttp = createClient4({
20724
+ this._appHttp = createClient5({
20047
20725
  baseUrl: appBaseUrl,
20048
20726
  headers: {
20049
20727
  Authorization: `Bearer ${cfg.apiKey}`,
@@ -20058,13 +20736,15 @@ var SmplClient = class {
20058
20736
  appBaseUrl
20059
20737
  });
20060
20738
  }
20739
+ const sharedContextBuffer = new ContextRegistrationBuffer();
20061
20740
  this.config = new ConfigClient(cfg.apiKey, this._timeout, configBaseUrl);
20062
20741
  this.flags = new FlagsClient(
20063
20742
  cfg.apiKey,
20064
20743
  () => this._ensureWs(),
20065
20744
  this._timeout,
20066
20745
  flagsBaseUrl,
20067
- appBaseUrl
20746
+ appBaseUrl,
20747
+ sharedContextBuffer
20068
20748
  );
20069
20749
  this.logging = new LoggingClient(
20070
20750
  cfg.apiKey,
@@ -20072,6 +20752,11 @@ var SmplClient = class {
20072
20752
  this._timeout,
20073
20753
  loggingBaseUrl
20074
20754
  );
20755
+ this.management = new ManagementClient({
20756
+ appBaseUrl,
20757
+ apiKey: cfg.apiKey,
20758
+ buffer: sharedContextBuffer
20759
+ });
20075
20760
  this.config._getSharedWs = () => this._ensureWs();
20076
20761
  this.flags._parent = this;
20077
20762
  this.config._parent = this;
@@ -20197,6 +20882,25 @@ var LogLevel = /* @__PURE__ */ ((LogLevel2) => {
20197
20882
  LogLevel2["SILENT"] = "SILENT";
20198
20883
  return LogLevel2;
20199
20884
  })(LogLevel || {});
20885
+ var LoggerSource = class {
20886
+ /** Logger name (e.g. `"sqlalchemy.engine"`). */
20887
+ name;
20888
+ /** Service name this source belongs to. */
20889
+ service;
20890
+ /** Environment name this source belongs to. */
20891
+ environment;
20892
+ /** Effective log level for this source. */
20893
+ resolvedLevel;
20894
+ /** Explicit (configured) log level, if different from `resolvedLevel`. */
20895
+ level;
20896
+ constructor(name, options) {
20897
+ this.name = name;
20898
+ this.service = options.service;
20899
+ this.environment = options.environment;
20900
+ this.resolvedLevel = options.resolved_level;
20901
+ this.level = options.level ?? null;
20902
+ }
20903
+ };
20200
20904
 
20201
20905
  // src/logging/adapters/winston.ts
20202
20906
  var SMPLKIT_TO_WINSTON = {
@@ -20422,11 +21126,20 @@ var PinoAdapter = class {
20422
21126
  }
20423
21127
  };
20424
21128
  export {
21129
+ AccountSettings,
21130
+ AccountSettingsClient,
20425
21131
  BooleanFlag,
20426
21132
  Config,
20427
21133
  ConfigClient,
20428
21134
  ConfigManagement,
20429
21135
  Context,
21136
+ ContextEntity,
21137
+ ContextType,
21138
+ ContextTypesClient,
21139
+ ContextsClient,
21140
+ Environment,
21141
+ EnvironmentClassification,
21142
+ EnvironmentsClient,
20430
21143
  Flag,
20431
21144
  FlagChangeEvent,
20432
21145
  FlagStats,
@@ -20437,8 +21150,10 @@ export {
20437
21150
  LogGroup,
20438
21151
  LogLevel,
20439
21152
  Logger,
21153
+ LoggerSource,
20440
21154
  LoggingClient,
20441
21155
  LoggingManagement,
21156
+ ManagementClient,
20442
21157
  NumberFlag,
20443
21158
  PinoAdapter,
20444
21159
  Rule,