@symbo.ls/sdk 2.34.32 → 2.34.33

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.
@@ -50331,6 +50331,160 @@ var IntegrationService = class extends BaseService {
50331
50331
  }
50332
50332
  };
50333
50333
 
50334
+ // src/services/FeatureFlagService.js
50335
+ function normalizeKeysParam(keys2) {
50336
+ if (!keys2) {
50337
+ return null;
50338
+ }
50339
+ if (Array.isArray(keys2)) {
50340
+ const flattened = keys2.flatMap((k3) => String(k3).split(","));
50341
+ const cleaned2 = flattened.map((s3) => s3.trim()).filter(Boolean);
50342
+ return cleaned2.length ? cleaned2.join(",") : null;
50343
+ }
50344
+ const cleaned = String(keys2).split(",").map((s3) => s3.trim()).filter(Boolean);
50345
+ return cleaned.length ? cleaned.join(",") : null;
50346
+ }
50347
+ var FeatureFlagService = class extends BaseService {
50348
+ // ==================== USER FEATURE FLAGS (optional auth) ====================
50349
+ /**
50350
+ * Evaluate feature flags for the current user (or anonymous).
50351
+ * @param {Object} [params]
50352
+ * @param {string[]|string} [params.keys] Optional subset of keys (array or comma-separated string)
50353
+ * @returns {Promise<{flags: Record<string, {enabled: boolean, variant: string|null, payload: any}>}>}
50354
+ */
50355
+ async getFeatureFlags(params2 = {}) {
50356
+ this._requireReady("getFeatureFlags");
50357
+ const { keys: keys2 } = params2 || {};
50358
+ const queryParams = new URLSearchParams();
50359
+ const keysParam = normalizeKeysParam(keys2);
50360
+ if (keysParam) {
50361
+ queryParams.append("keys", keysParam);
50362
+ }
50363
+ const queryString = queryParams.toString();
50364
+ const url2 = `/feature-flags${queryString ? `?${queryString}` : ""}`;
50365
+ try {
50366
+ const response = await this._request(url2, {
50367
+ method: "GET",
50368
+ methodName: "getFeatureFlags"
50369
+ });
50370
+ if (response.success) {
50371
+ return response.data;
50372
+ }
50373
+ throw new Error(response.message);
50374
+ } catch (error) {
50375
+ throw new Error(`Failed to get feature flags: ${error.message}`, { cause: error });
50376
+ }
50377
+ }
50378
+ /**
50379
+ * Evaluate a single feature flag for the current user (or anonymous).
50380
+ */
50381
+ async getFeatureFlag(key) {
50382
+ this._requireReady("getFeatureFlag");
50383
+ if (!key) {
50384
+ throw new Error("Feature flag key is required");
50385
+ }
50386
+ try {
50387
+ const response = await this._request(`/feature-flags/${encodeURIComponent(String(key))}`, {
50388
+ method: "GET",
50389
+ methodName: "getFeatureFlag"
50390
+ });
50391
+ if (response.success) {
50392
+ return response.data;
50393
+ }
50394
+ throw new Error(response.message);
50395
+ } catch (error) {
50396
+ throw new Error(`Failed to get feature flag: ${error.message}`, { cause: error });
50397
+ }
50398
+ }
50399
+ // ==================== ADMIN FEATURE FLAGS (admin only) ====================
50400
+ async getAdminFeatureFlags(params2 = {}) {
50401
+ this._requireReady("getAdminFeatureFlags");
50402
+ const { includeArchived = true } = params2 || {};
50403
+ const queryParams = new URLSearchParams();
50404
+ if (includeArchived === false) {
50405
+ queryParams.append("includeArchived", "false");
50406
+ }
50407
+ const queryString = queryParams.toString();
50408
+ const url2 = `/admin/feature-flags${queryString ? `?${queryString}` : ""}`;
50409
+ try {
50410
+ const response = await this._request(url2, {
50411
+ method: "GET",
50412
+ methodName: "getAdminFeatureFlags"
50413
+ });
50414
+ if (response.success) {
50415
+ return response.data;
50416
+ }
50417
+ throw new Error(response.message);
50418
+ } catch (error) {
50419
+ throw new Error(`Failed to get admin feature flags: ${error.message}`, {
50420
+ cause: error
50421
+ });
50422
+ }
50423
+ }
50424
+ async createFeatureFlag(flagData) {
50425
+ this._requireReady("createFeatureFlag");
50426
+ if (!flagData || typeof flagData !== "object") {
50427
+ throw new Error("Feature flag data is required");
50428
+ }
50429
+ if (!flagData.key) {
50430
+ throw new Error("Feature flag key is required");
50431
+ }
50432
+ try {
50433
+ const response = await this._request("/admin/feature-flags", {
50434
+ method: "POST",
50435
+ body: JSON.stringify(flagData),
50436
+ methodName: "createFeatureFlag"
50437
+ });
50438
+ if (response.success) {
50439
+ return response.data;
50440
+ }
50441
+ throw new Error(response.message);
50442
+ } catch (error) {
50443
+ throw new Error(`Failed to create feature flag: ${error.message}`, { cause: error });
50444
+ }
50445
+ }
50446
+ async updateFeatureFlag(id2, patch) {
50447
+ this._requireReady("updateFeatureFlag");
50448
+ if (!id2) {
50449
+ throw new Error("Feature flag id is required");
50450
+ }
50451
+ if (!patch || typeof patch !== "object") {
50452
+ throw new Error("Feature flag patch is required");
50453
+ }
50454
+ try {
50455
+ const response = await this._request(`/admin/feature-flags/${encodeURIComponent(String(id2))}`, {
50456
+ method: "PATCH",
50457
+ body: JSON.stringify(patch),
50458
+ methodName: "updateFeatureFlag"
50459
+ });
50460
+ if (response.success) {
50461
+ return response.data;
50462
+ }
50463
+ throw new Error(response.message);
50464
+ } catch (error) {
50465
+ throw new Error(`Failed to update feature flag: ${error.message}`, { cause: error });
50466
+ }
50467
+ }
50468
+ async archiveFeatureFlag(id2) {
50469
+ this._requireReady("archiveFeatureFlag");
50470
+ if (!id2) {
50471
+ throw new Error("Feature flag id is required");
50472
+ }
50473
+ try {
50474
+ const response = await this._request(`/admin/feature-flags/${encodeURIComponent(String(id2))}`, {
50475
+ method: "DELETE",
50476
+ methodName: "archiveFeatureFlag"
50477
+ });
50478
+ if (response.success) {
50479
+ return response.data;
50480
+ }
50481
+ throw new Error(response.message);
50482
+ } catch (error) {
50483
+ throw new Error(`Failed to archive feature flag: ${error.message}`, { cause: error });
50484
+ }
50485
+ }
50486
+ };
50487
+
50334
50488
  // src/services/index.js
50335
50489
  var createService = (ServiceClass, config) => new ServiceClass(config);
50336
50490
  var createAuthService = (config) => createService(AuthService, config);
@@ -50349,12 +50503,14 @@ var createTrackingService = (config) => createService(TrackingService, config);
50349
50503
  var createWaitlistService = (config) => createService(WaitlistService, config);
50350
50504
  var createMetricsService = (config) => createService(MetricsService, config);
50351
50505
  var createIntegrationService = (config) => createService(IntegrationService, config);
50506
+ var createFeatureFlagService = (config) => createService(FeatureFlagService, config);
50352
50507
  export {
50353
50508
  AdminService,
50354
50509
  AuthService,
50355
50510
  BranchService,
50356
50511
  CollabService,
50357
50512
  DnsService,
50513
+ FeatureFlagService,
50358
50514
  FileService,
50359
50515
  IntegrationService,
50360
50516
  MetricsService,
@@ -50371,6 +50527,7 @@ export {
50371
50527
  createBranchService,
50372
50528
  createCollabService,
50373
50529
  createDnsService,
50530
+ createFeatureFlagService,
50374
50531
  createFileService,
50375
50532
  createIntegrationService,
50376
50533
  createMetricsService,
@@ -298,7 +298,14 @@ var SERVICE_METHODS = {
298
298
  listGitHubConnectors: "integration",
299
299
  createGitHubConnector: "integration",
300
300
  updateGitHubConnector: "integration",
301
- deleteGitHubConnector: "integration"
301
+ deleteGitHubConnector: "integration",
302
+ // Feature flag methods (system-level + experiments)
303
+ getFeatureFlags: "featureFlag",
304
+ getFeatureFlag: "featureFlag",
305
+ getAdminFeatureFlags: "featureFlag",
306
+ createFeatureFlag: "featureFlag",
307
+ updateFeatureFlag: "featureFlag",
308
+ archiveFeatureFlag: "featureFlag"
302
309
  };
303
310
  export {
304
311
  SERVICE_METHODS
@@ -14,7 +14,8 @@ import {
14
14
  createTrackingService,
15
15
  createWaitlistService,
16
16
  createMetricsService,
17
- createIntegrationService
17
+ createIntegrationService,
18
+ createFeatureFlagService
18
19
  } from "./services/index.js";
19
20
  import { SERVICE_METHODS } from "./utils/services.js";
20
21
  import environment from "./config/environment.js";
@@ -155,6 +156,13 @@ class SDK {
155
156
  context: this._context,
156
157
  options: this._options
157
158
  })
159
+ ),
160
+ this._initService(
161
+ "featureFlag",
162
+ createFeatureFlagService({
163
+ context: this._context,
164
+ options: this._options
165
+ })
158
166
  )
159
167
  ]);
160
168
  return this;
@@ -286,7 +294,8 @@ import {
286
294
  createTrackingService as createTrackingService2,
287
295
  createWaitlistService as createWaitlistService2,
288
296
  createMetricsService as createMetricsService2,
289
- createIntegrationService as createIntegrationService2
297
+ createIntegrationService as createIntegrationService2,
298
+ createFeatureFlagService as createFeatureFlagService2
290
299
  } from "./services/index.js";
291
300
  import { default as default2 } from "./config/environment.js";
292
301
  export {
@@ -296,6 +305,7 @@ export {
296
305
  createBranchService2 as createBranchService,
297
306
  createCollabService2 as createCollabService,
298
307
  createDnsService2 as createDnsService,
308
+ createFeatureFlagService2 as createFeatureFlagService,
299
309
  createFileService2 as createFileService,
300
310
  createIntegrationService2 as createIntegrationService,
301
311
  createMetricsService2 as createMetricsService,
@@ -0,0 +1,156 @@
1
+ import { BaseService } from "./BaseService.js";
2
+ function normalizeKeysParam(keys) {
3
+ if (!keys) {
4
+ return null;
5
+ }
6
+ if (Array.isArray(keys)) {
7
+ const flattened = keys.flatMap((k) => String(k).split(","));
8
+ const cleaned2 = flattened.map((s) => s.trim()).filter(Boolean);
9
+ return cleaned2.length ? cleaned2.join(",") : null;
10
+ }
11
+ const cleaned = String(keys).split(",").map((s) => s.trim()).filter(Boolean);
12
+ return cleaned.length ? cleaned.join(",") : null;
13
+ }
14
+ class FeatureFlagService extends BaseService {
15
+ // ==================== USER FEATURE FLAGS (optional auth) ====================
16
+ /**
17
+ * Evaluate feature flags for the current user (or anonymous).
18
+ * @param {Object} [params]
19
+ * @param {string[]|string} [params.keys] Optional subset of keys (array or comma-separated string)
20
+ * @returns {Promise<{flags: Record<string, {enabled: boolean, variant: string|null, payload: any}>}>}
21
+ */
22
+ async getFeatureFlags(params = {}) {
23
+ this._requireReady("getFeatureFlags");
24
+ const { keys } = params || {};
25
+ const queryParams = new URLSearchParams();
26
+ const keysParam = normalizeKeysParam(keys);
27
+ if (keysParam) {
28
+ queryParams.append("keys", keysParam);
29
+ }
30
+ const queryString = queryParams.toString();
31
+ const url = `/feature-flags${queryString ? `?${queryString}` : ""}`;
32
+ try {
33
+ const response = await this._request(url, {
34
+ method: "GET",
35
+ methodName: "getFeatureFlags"
36
+ });
37
+ if (response.success) {
38
+ return response.data;
39
+ }
40
+ throw new Error(response.message);
41
+ } catch (error) {
42
+ throw new Error(`Failed to get feature flags: ${error.message}`, { cause: error });
43
+ }
44
+ }
45
+ /**
46
+ * Evaluate a single feature flag for the current user (or anonymous).
47
+ */
48
+ async getFeatureFlag(key) {
49
+ this._requireReady("getFeatureFlag");
50
+ if (!key) {
51
+ throw new Error("Feature flag key is required");
52
+ }
53
+ try {
54
+ const response = await this._request(`/feature-flags/${encodeURIComponent(String(key))}`, {
55
+ method: "GET",
56
+ methodName: "getFeatureFlag"
57
+ });
58
+ if (response.success) {
59
+ return response.data;
60
+ }
61
+ throw new Error(response.message);
62
+ } catch (error) {
63
+ throw new Error(`Failed to get feature flag: ${error.message}`, { cause: error });
64
+ }
65
+ }
66
+ // ==================== ADMIN FEATURE FLAGS (admin only) ====================
67
+ async getAdminFeatureFlags(params = {}) {
68
+ this._requireReady("getAdminFeatureFlags");
69
+ const { includeArchived = true } = params || {};
70
+ const queryParams = new URLSearchParams();
71
+ if (includeArchived === false) {
72
+ queryParams.append("includeArchived", "false");
73
+ }
74
+ const queryString = queryParams.toString();
75
+ const url = `/admin/feature-flags${queryString ? `?${queryString}` : ""}`;
76
+ try {
77
+ const response = await this._request(url, {
78
+ method: "GET",
79
+ methodName: "getAdminFeatureFlags"
80
+ });
81
+ if (response.success) {
82
+ return response.data;
83
+ }
84
+ throw new Error(response.message);
85
+ } catch (error) {
86
+ throw new Error(`Failed to get admin feature flags: ${error.message}`, {
87
+ cause: error
88
+ });
89
+ }
90
+ }
91
+ async createFeatureFlag(flagData) {
92
+ this._requireReady("createFeatureFlag");
93
+ if (!flagData || typeof flagData !== "object") {
94
+ throw new Error("Feature flag data is required");
95
+ }
96
+ if (!flagData.key) {
97
+ throw new Error("Feature flag key is required");
98
+ }
99
+ try {
100
+ const response = await this._request("/admin/feature-flags", {
101
+ method: "POST",
102
+ body: JSON.stringify(flagData),
103
+ methodName: "createFeatureFlag"
104
+ });
105
+ if (response.success) {
106
+ return response.data;
107
+ }
108
+ throw new Error(response.message);
109
+ } catch (error) {
110
+ throw new Error(`Failed to create feature flag: ${error.message}`, { cause: error });
111
+ }
112
+ }
113
+ async updateFeatureFlag(id, patch) {
114
+ this._requireReady("updateFeatureFlag");
115
+ if (!id) {
116
+ throw new Error("Feature flag id is required");
117
+ }
118
+ if (!patch || typeof patch !== "object") {
119
+ throw new Error("Feature flag patch is required");
120
+ }
121
+ try {
122
+ const response = await this._request(`/admin/feature-flags/${encodeURIComponent(String(id))}`, {
123
+ method: "PATCH",
124
+ body: JSON.stringify(patch),
125
+ methodName: "updateFeatureFlag"
126
+ });
127
+ if (response.success) {
128
+ return response.data;
129
+ }
130
+ throw new Error(response.message);
131
+ } catch (error) {
132
+ throw new Error(`Failed to update feature flag: ${error.message}`, { cause: error });
133
+ }
134
+ }
135
+ async archiveFeatureFlag(id) {
136
+ this._requireReady("archiveFeatureFlag");
137
+ if (!id) {
138
+ throw new Error("Feature flag id is required");
139
+ }
140
+ try {
141
+ const response = await this._request(`/admin/feature-flags/${encodeURIComponent(String(id))}`, {
142
+ method: "DELETE",
143
+ methodName: "archiveFeatureFlag"
144
+ });
145
+ if (response.success) {
146
+ return response.data;
147
+ }
148
+ throw new Error(response.message);
149
+ } catch (error) {
150
+ throw new Error(`Failed to archive feature flag: ${error.message}`, { cause: error });
151
+ }
152
+ }
153
+ }
154
+ export {
155
+ FeatureFlagService
156
+ };
@@ -14,6 +14,7 @@ import { TrackingService } from "./TrackingService.js";
14
14
  import { WaitlistService } from "./WaitlistService.js";
15
15
  import { MetricsService } from "./MetricsService.js";
16
16
  import { IntegrationService } from "./IntegrationService.js";
17
+ import { FeatureFlagService } from "./FeatureFlagService.js";
17
18
  const createService = (ServiceClass, config) => new ServiceClass(config);
18
19
  const createAuthService = (config) => createService(AuthService, config);
19
20
  const createCollabService = (config) => createService(CollabService, config);
@@ -31,12 +32,14 @@ const createTrackingService = (config) => createService(TrackingService, config)
31
32
  const createWaitlistService = (config) => createService(WaitlistService, config);
32
33
  const createMetricsService = (config) => createService(MetricsService, config);
33
34
  const createIntegrationService = (config) => createService(IntegrationService, config);
35
+ const createFeatureFlagService = (config) => createService(FeatureFlagService, config);
34
36
  export {
35
37
  AdminService,
36
38
  AuthService,
37
39
  BranchService,
38
40
  CollabService,
39
41
  DnsService,
42
+ FeatureFlagService,
40
43
  FileService,
41
44
  IntegrationService,
42
45
  MetricsService,
@@ -53,6 +56,7 @@ export {
53
56
  createBranchService,
54
57
  createCollabService,
55
58
  createDnsService,
59
+ createFeatureFlagService,
56
60
  createFileService,
57
61
  createIntegrationService,
58
62
  createMetricsService,
@@ -297,7 +297,14 @@ const SERVICE_METHODS = {
297
297
  listGitHubConnectors: "integration",
298
298
  createGitHubConnector: "integration",
299
299
  updateGitHubConnector: "integration",
300
- deleteGitHubConnector: "integration"
300
+ deleteGitHubConnector: "integration",
301
+ // Feature flag methods (system-level + experiments)
302
+ getFeatureFlags: "featureFlag",
303
+ getFeatureFlag: "featureFlag",
304
+ getAdminFeatureFlags: "featureFlag",
305
+ createFeatureFlag: "featureFlag",
306
+ updateFeatureFlag: "featureFlag",
307
+ archiveFeatureFlag: "featureFlag"
301
308
  };
302
309
  export {
303
310
  SERVICE_METHODS
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@symbo.ls/sdk",
3
- "version": "2.34.32",
3
+ "version": "2.34.33",
4
4
  "type": "module",
5
5
  "main": "dist/esm/index.js",
6
6
  "module": "dist/esm/index.js",
@@ -47,12 +47,12 @@
47
47
  "test:unit-all": "cross-env NODE_ENV=$NODE_ENV npx tape src/services/tests/**/*.test.js | tap-spec"
48
48
  },
49
49
  "dependencies": {
50
- "@domql/element": "^2.34.32",
51
- "@domql/utils": "^2.34.32",
50
+ "@domql/element": "^2.34.33",
51
+ "@domql/utils": "^2.34.33",
52
52
  "@grafana/faro-web-sdk": "^1.19.0",
53
53
  "@grafana/faro-web-tracing": "^1.19.0",
54
- "@symbo.ls/router": "^2.34.32",
55
- "@symbo.ls/socket": "^2.34.32",
54
+ "@symbo.ls/router": "^2.34.33",
55
+ "@symbo.ls/socket": "^2.34.33",
56
56
  "acorn": "^8.14.0",
57
57
  "acorn-walk": "^8.3.4",
58
58
  "dexie": "^4.0.11",
@@ -75,5 +75,5 @@
75
75
  "tap-spec": "^5.0.0",
76
76
  "tape": "^5.9.0"
77
77
  },
78
- "gitHead": "99bd991fb87c092bcfd045ad358c15064a8b8c30"
78
+ "gitHead": "a7ecaaa2792aea530bf0b4cef625904c63a0272a"
79
79
  }
package/src/index.js CHANGED
@@ -14,7 +14,8 @@ import {
14
14
  createTrackingService,
15
15
  createWaitlistService,
16
16
  createMetricsService,
17
- createIntegrationService
17
+ createIntegrationService,
18
+ createFeatureFlagService
18
19
  } from './services/index.js'
19
20
 
20
21
  import { SERVICE_METHODS } from './utils/services.js'
@@ -169,6 +170,13 @@ export class SDK {
169
170
  context: this._context,
170
171
  options: this._options
171
172
  })
173
+ ),
174
+ this._initService(
175
+ 'featureFlag',
176
+ createFeatureFlagService({
177
+ context: this._context,
178
+ options: this._options
179
+ })
172
180
  )
173
181
  ])
174
182
 
@@ -335,7 +343,8 @@ export {
335
343
  createTrackingService,
336
344
  createWaitlistService,
337
345
  createMetricsService,
338
- createIntegrationService
346
+ createIntegrationService,
347
+ createFeatureFlagService
339
348
  } from './services/index.js'
340
349
 
341
350
  // Export environment configuration
@@ -0,0 +1,174 @@
1
+ import { BaseService } from './BaseService.js'
2
+
3
+ function normalizeKeysParam (keys) {
4
+ if (!keys) { return null }
5
+ if (Array.isArray(keys)) {
6
+ const flattened = keys.flatMap(k => String(k).split(','))
7
+ const cleaned = flattened.map(s => s.trim()).filter(Boolean)
8
+ return cleaned.length ? cleaned.join(',') : null
9
+ }
10
+ const cleaned = String(keys)
11
+ .split(',')
12
+ .map(s => s.trim())
13
+ .filter(Boolean)
14
+ return cleaned.length ? cleaned.join(',') : null
15
+ }
16
+
17
+ export class FeatureFlagService extends BaseService {
18
+ // ==================== USER FEATURE FLAGS (optional auth) ====================
19
+
20
+ /**
21
+ * Evaluate feature flags for the current user (or anonymous).
22
+ * @param {Object} [params]
23
+ * @param {string[]|string} [params.keys] Optional subset of keys (array or comma-separated string)
24
+ * @returns {Promise<{flags: Record<string, {enabled: boolean, variant: string|null, payload: any}>}>}
25
+ */
26
+ async getFeatureFlags (params = {}) {
27
+ this._requireReady('getFeatureFlags')
28
+ const { keys } = params || {}
29
+
30
+ const queryParams = new URLSearchParams()
31
+ const keysParam = normalizeKeysParam(keys)
32
+ if (keysParam) {
33
+ queryParams.append('keys', keysParam)
34
+ }
35
+
36
+ const queryString = queryParams.toString()
37
+ const url = `/feature-flags${queryString ? `?${queryString}` : ''}`
38
+
39
+ try {
40
+ const response = await this._request(url, {
41
+ method: 'GET',
42
+ methodName: 'getFeatureFlags'
43
+ })
44
+ if (response.success) {
45
+ return response.data
46
+ }
47
+ throw new Error(response.message)
48
+ } catch (error) {
49
+ throw new Error(`Failed to get feature flags: ${error.message}`, { cause: error })
50
+ }
51
+ }
52
+
53
+ /**
54
+ * Evaluate a single feature flag for the current user (or anonymous).
55
+ */
56
+ async getFeatureFlag (key) {
57
+ this._requireReady('getFeatureFlag')
58
+ if (!key) {
59
+ throw new Error('Feature flag key is required')
60
+ }
61
+
62
+ try {
63
+ const response = await this._request(`/feature-flags/${encodeURIComponent(String(key))}`, {
64
+ method: 'GET',
65
+ methodName: 'getFeatureFlag'
66
+ })
67
+ if (response.success) {
68
+ return response.data
69
+ }
70
+ throw new Error(response.message)
71
+ } catch (error) {
72
+ throw new Error(`Failed to get feature flag: ${error.message}`, { cause: error })
73
+ }
74
+ }
75
+
76
+ // ==================== ADMIN FEATURE FLAGS (admin only) ====================
77
+
78
+ async getAdminFeatureFlags (params = {}) {
79
+ this._requireReady('getAdminFeatureFlags')
80
+ const { includeArchived = true } = params || {}
81
+
82
+ const queryParams = new URLSearchParams()
83
+ if (includeArchived === false) {
84
+ queryParams.append('includeArchived', 'false')
85
+ }
86
+
87
+ const queryString = queryParams.toString()
88
+ const url = `/admin/feature-flags${queryString ? `?${queryString}` : ''}`
89
+
90
+ try {
91
+ const response = await this._request(url, {
92
+ method: 'GET',
93
+ methodName: 'getAdminFeatureFlags'
94
+ })
95
+ if (response.success) {
96
+ return response.data
97
+ }
98
+ throw new Error(response.message)
99
+ } catch (error) {
100
+ throw new Error(`Failed to get admin feature flags: ${error.message}`, {
101
+ cause: error
102
+ })
103
+ }
104
+ }
105
+
106
+ async createFeatureFlag (flagData) {
107
+ this._requireReady('createFeatureFlag')
108
+ if (!flagData || typeof flagData !== 'object') {
109
+ throw new Error('Feature flag data is required')
110
+ }
111
+ if (!flagData.key) {
112
+ throw new Error('Feature flag key is required')
113
+ }
114
+
115
+ try {
116
+ const response = await this._request('/admin/feature-flags', {
117
+ method: 'POST',
118
+ body: JSON.stringify(flagData),
119
+ methodName: 'createFeatureFlag'
120
+ })
121
+ if (response.success) {
122
+ return response.data
123
+ }
124
+ throw new Error(response.message)
125
+ } catch (error) {
126
+ throw new Error(`Failed to create feature flag: ${error.message}`, { cause: error })
127
+ }
128
+ }
129
+
130
+ async updateFeatureFlag (id, patch) {
131
+ this._requireReady('updateFeatureFlag')
132
+ if (!id) {
133
+ throw new Error('Feature flag id is required')
134
+ }
135
+ if (!patch || typeof patch !== 'object') {
136
+ throw new Error('Feature flag patch is required')
137
+ }
138
+
139
+ try {
140
+ const response = await this._request(`/admin/feature-flags/${encodeURIComponent(String(id))}`, {
141
+ method: 'PATCH',
142
+ body: JSON.stringify(patch),
143
+ methodName: 'updateFeatureFlag'
144
+ })
145
+ if (response.success) {
146
+ return response.data
147
+ }
148
+ throw new Error(response.message)
149
+ } catch (error) {
150
+ throw new Error(`Failed to update feature flag: ${error.message}`, { cause: error })
151
+ }
152
+ }
153
+
154
+ async archiveFeatureFlag (id) {
155
+ this._requireReady('archiveFeatureFlag')
156
+ if (!id) {
157
+ throw new Error('Feature flag id is required')
158
+ }
159
+
160
+ try {
161
+ const response = await this._request(`/admin/feature-flags/${encodeURIComponent(String(id))}`, {
162
+ method: 'DELETE',
163
+ methodName: 'archiveFeatureFlag'
164
+ })
165
+ if (response.success) {
166
+ return response.data
167
+ }
168
+ throw new Error(response.message)
169
+ } catch (error) {
170
+ throw new Error(`Failed to archive feature flag: ${error.message}`, { cause: error })
171
+ }
172
+ }
173
+ }
174
+