@wireapp/api-client 27.84.0 → 27.86.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.
Files changed (32) hide show
  1. package/lib/APIClient.js +1 -1
  2. package/lib/asset/AssetAPI.d.ts +17 -17
  3. package/lib/asset/AssetAPI.d.ts.map +1 -1
  4. package/lib/asset/AssetAPI.js +15 -113
  5. package/lib/asset/AssetAPI.schema.d.ts +27 -0
  6. package/lib/asset/AssetAPI.schema.d.ts.map +1 -0
  7. package/lib/asset/{AssetUploadData.js → AssetAPI.schema.js} +16 -0
  8. package/lib/asset/index.d.ts +1 -1
  9. package/lib/asset/index.d.ts.map +1 -1
  10. package/lib/asset/index.js +0 -1
  11. package/lib/services/ServicesAPI.d.ts +6 -1
  12. package/lib/services/ServicesAPI.d.ts.map +1 -1
  13. package/lib/team/feature/FeatureAPI.d.ts +13 -31
  14. package/lib/team/feature/FeatureAPI.d.ts.map +1 -1
  15. package/lib/team/feature/FeatureAPI.js +71 -84
  16. package/lib/team/feature/FeatureList.schema.d.ts +2186 -0
  17. package/lib/team/feature/FeatureList.schema.d.ts.map +1 -0
  18. package/lib/team/feature/FeatureList.schema.js +168 -0
  19. package/lib/team/feature/FeatureList.types.d.ts +108 -0
  20. package/lib/team/feature/FeatureList.types.d.ts.map +1 -0
  21. package/lib/team/feature/{FeatureList.js → FeatureList.types.js} +41 -4
  22. package/lib/team/feature/index.d.ts +2 -2
  23. package/lib/team/feature/index.d.ts.map +1 -1
  24. package/lib/team/feature/index.js +2 -2
  25. package/package.json +2 -2
  26. package/lib/asset/AssetUploadData.d.ts +0 -8
  27. package/lib/asset/AssetUploadData.d.ts.map +0 -1
  28. package/lib/team/feature/Feature.d.ts +0 -96
  29. package/lib/team/feature/Feature.d.ts.map +0 -1
  30. package/lib/team/feature/Feature.js +0 -47
  31. package/lib/team/feature/FeatureList.d.ts +0 -55
  32. package/lib/team/feature/FeatureList.d.ts.map +0 -1
@@ -18,63 +18,60 @@
18
18
  *
19
19
  */
20
20
  Object.defineProperty(exports, "__esModule", { value: true });
21
- exports.FeatureAPI = void 0;
21
+ exports.FeatureAPI = exports.isBackendError = void 0;
22
+ const commons_1 = require("@wireapp/commons");
22
23
  const FeatureError_1 = require("./FeatureError");
24
+ const FeatureList_schema_1 = require("./FeatureList.schema");
23
25
  const http_1 = require("../../http");
24
26
  const _1 = require(".");
27
+ const isBackendError = (error) => {
28
+ return error instanceof Error && 'label' in error && typeof error.label === 'string';
29
+ };
30
+ exports.isBackendError = isBackendError;
25
31
  class FeatureAPI {
26
32
  client;
33
+ logger;
27
34
  constructor(client) {
28
35
  this.client = client;
29
- }
30
- static URL = {
31
- APPLOCK: 'appLock',
32
- ALLOWED_GLOBAL_OPERATIONS: 'allowedGlobalOperations',
33
- AUDIT_LOG: 'assetAuditLog',
34
- CALLING_CONFERENCE: 'conferenceCalling',
35
- CALLING_VIDEO: 'videoCalling',
36
- CONSUMABLE_NOTIFICATIONS: 'consumableNotifications',
37
- SELF_DELETING_MESSAGES: 'selfDeletingMessages',
38
- DIGITAL_SIGNATURES: 'digitalSignatures',
39
- DOMAIN_REGISTRATION: 'domainRegistration',
40
- DL_PATH: 'enforceFileDownloadLocation',
41
- CELLS: 'cells',
42
- CHANNELS: 'channels',
43
- CONVERSATION_GUEST_LINKS: 'conversationGuestLinks',
44
- FEATURE_CONFIGS: '/feature-configs',
45
- FEATURES: 'features',
46
- FILE_SHARING: 'fileSharing',
47
- LEGAL_HOLD: 'legalhold',
48
- SND_FACTOR_PASSWORD: 'sndFactorPasswordChallenge',
49
- SSO: 'sso',
50
- MLS: 'mls',
51
- MLSE2EID: 'mlsE2EId',
52
- MLS_MIGRATION: 'mlsMigration',
53
- TEAMS: '/teams',
54
- };
55
- async getAllFeatures() {
56
- const config = {
57
- method: 'get',
58
- url: FeatureAPI.URL.FEATURE_CONFIGS,
59
- };
60
- const response = await this.client.sendJSON(config);
61
- return response.data;
36
+ this.logger = commons_1.LogFactory.getLogger('@wireapp/api-client/FeatureAPI');
62
37
  }
63
38
  /**
64
- * @deprecated Use `getAllFeatures()` instead. It is teamId agnostic.
39
+ * Retrieves all feature flags for the current user/team.
40
+ *
41
+ * This endpoint is backwards and forwards compatible across Wire backend API versions:
42
+ * - Validates response structure using Zod but never throws validation errors
43
+ * - Logs validation errors for debugging/monitoring purposes
44
+ * - Returns original API response even if validation fails
45
+ * - Works with older backends (missing features) and newer backends (unknown features)
65
46
  */
66
- async getAllTeamFeatures(teamId) {
47
+ async getAllFeatures() {
67
48
  const config = {
68
49
  method: 'get',
69
- url: `${FeatureAPI.URL.TEAMS}/${teamId}/${FeatureAPI.URL.FEATURES}`,
50
+ url: '/feature-configs',
70
51
  };
71
52
  const response = await this.client.sendJSON(config);
53
+ // Validate response schema without throwing errors (backwards/forwards compatibility)
54
+ const validationResult = FeatureList_schema_1.allFeaturesResponseSchema.safeParse(response.data);
55
+ if (!validationResult.success) {
56
+ const validationErrorDetails = validationResult.error.format();
57
+ this.logger.error('Feature flags response failed schema validation. ' +
58
+ 'This may indicate an API version mismatch between client and backend. ' +
59
+ 'The response will still be returned to maintain compatibility.', {
60
+ validationErrors: validationErrorDetails,
61
+ receivedResponse: response.data,
62
+ });
63
+ }
64
+ // Always return the original response data to ensure compatibility
65
+ // across different backend API versions. This allows consumers to mutate
66
+ // the response if needed (e.g., wire-webapp's TeamRepository).
67
+ // Once all consumers are updated to not mutate the response, we can
68
+ // return validationResult.data instead for immutability benefits.
72
69
  return response.data;
73
70
  }
74
71
  async getLegalholdFeature(teamId) {
75
72
  const config = {
76
73
  method: 'get',
77
- url: `${FeatureAPI.URL.TEAMS}/${teamId}/${FeatureAPI.URL.FEATURES}/${FeatureAPI.URL.LEGAL_HOLD}`,
74
+ url: `/teams/${teamId}/features/legalhold`,
78
75
  };
79
76
  const response = await this.client.sendJSON(config);
80
77
  return response.data;
@@ -82,7 +79,7 @@ class FeatureAPI {
82
79
  async getConversationGuestLinkFeature(teamId) {
83
80
  const config = {
84
81
  method: 'get',
85
- url: `${FeatureAPI.URL.TEAMS}/${teamId}/${FeatureAPI.URL.FEATURES}/${FeatureAPI.URL.CONVERSATION_GUEST_LINKS}`,
82
+ url: `/teams/${teamId}/features/conversation_guest_links`,
86
83
  };
87
84
  const response = await this.client.sendJSON(config);
88
85
  return response.data;
@@ -91,17 +88,15 @@ class FeatureAPI {
91
88
  const config = {
92
89
  data: conversationGuestLinkFeature,
93
90
  method: 'put',
94
- url: `${FeatureAPI.URL.TEAMS}/${teamId}/${FeatureAPI.URL.FEATURES}/${FeatureAPI.URL.CONVERSATION_GUEST_LINKS}`,
91
+ url: `/teams/${teamId}/features/conversation_guest_links`,
95
92
  };
96
93
  try {
97
94
  const response = await this.client.sendJSON(config);
98
95
  return response.data;
99
96
  }
100
97
  catch (error) {
101
- switch (error.label) {
102
- case http_1.BackendErrorLabel.FEATURE_LOCKED: {
103
- throw new _1.FeatureLockedError(error.message);
104
- }
98
+ if ((0, exports.isBackendError)(error) && error.label === http_1.BackendErrorLabel.FEATURE_LOCKED) {
99
+ throw new _1.FeatureLockedError(error.message);
105
100
  }
106
101
  throw error;
107
102
  }
@@ -109,7 +104,7 @@ class FeatureAPI {
109
104
  async getConferenceCallingFeature(teamId) {
110
105
  const config = {
111
106
  method: 'get',
112
- url: `${FeatureAPI.URL.TEAMS}/${teamId}/${FeatureAPI.URL.FEATURES}/${FeatureAPI.URL.CALLING_CONFERENCE}`,
107
+ url: `/teams/${teamId}/features/conferenceCalling`,
113
108
  };
114
109
  const response = await this.client.sendJSON(config);
115
110
  return response.data;
@@ -118,17 +113,15 @@ class FeatureAPI {
118
113
  const config = {
119
114
  data: conferenceCallingFeature,
120
115
  method: 'put',
121
- url: `${FeatureAPI.URL.TEAMS}/${teamId}/${FeatureAPI.URL.FEATURES}/${FeatureAPI.URL.CALLING_CONFERENCE}`,
116
+ url: `/teams/${teamId}/features/conferenceCalling`,
122
117
  };
123
118
  try {
124
119
  const response = await this.client.sendJSON(config);
125
120
  return response.data;
126
121
  }
127
122
  catch (error) {
128
- switch (error.label) {
129
- case http_1.BackendErrorLabel.FEATURE_LOCKED: {
130
- throw new _1.FeatureLockedError(error.message);
131
- }
123
+ if ((0, exports.isBackendError)(error) && error.label === http_1.BackendErrorLabel.FEATURE_LOCKED) {
124
+ throw new _1.FeatureLockedError(error.message);
132
125
  }
133
126
  throw error;
134
127
  }
@@ -139,7 +132,7 @@ class FeatureAPI {
139
132
  async getVideoCallingFeature(teamId) {
140
133
  const config = {
141
134
  method: 'get',
142
- url: `${FeatureAPI.URL.TEAMS}/${teamId}/${FeatureAPI.URL.FEATURES}/${FeatureAPI.URL.CALLING_VIDEO}`,
135
+ url: `/teams/${teamId}/features/callingVideo`,
143
136
  };
144
137
  const response = await this.client.sendJSON(config);
145
138
  return response.data;
@@ -151,17 +144,15 @@ class FeatureAPI {
151
144
  const config = {
152
145
  data: videoCallingFeature,
153
146
  method: 'put',
154
- url: `${FeatureAPI.URL.TEAMS}/${teamId}/${FeatureAPI.URL.FEATURES}/${FeatureAPI.URL.CALLING_VIDEO}`,
147
+ url: `/teams/${teamId}/features/callingVideo`,
155
148
  };
156
149
  try {
157
150
  const response = await this.client.sendJSON(config);
158
151
  return response.data;
159
152
  }
160
153
  catch (error) {
161
- switch (error.label) {
162
- case http_1.BackendErrorLabel.FEATURE_LOCKED: {
163
- throw new _1.FeatureLockedError(error.message);
164
- }
154
+ if ((0, exports.isBackendError)(error) && error.label === http_1.BackendErrorLabel.FEATURE_LOCKED) {
155
+ throw new _1.FeatureLockedError(error.message);
165
156
  }
166
157
  throw error;
167
158
  }
@@ -169,7 +160,7 @@ class FeatureAPI {
169
160
  async getSelfDeletingMessagesFeature(teamId) {
170
161
  const config = {
171
162
  method: 'get',
172
- url: `${FeatureAPI.URL.TEAMS}/${teamId}/${FeatureAPI.URL.FEATURES}/${FeatureAPI.URL.SELF_DELETING_MESSAGES}`,
163
+ url: `/teams/${teamId}/features/selfDeletingMessages`,
173
164
  };
174
165
  const response = await this.client.sendJSON(config);
175
166
  return response.data;
@@ -178,17 +169,15 @@ class FeatureAPI {
178
169
  const config = {
179
170
  data: selfDeleteingMessagesFeature,
180
171
  method: 'put',
181
- url: `${FeatureAPI.URL.TEAMS}/${teamId}/${FeatureAPI.URL.FEATURES}/${FeatureAPI.URL.SELF_DELETING_MESSAGES}`,
172
+ url: `/teams/${teamId}/features/selfDeletingMessages`,
182
173
  };
183
174
  try {
184
175
  const response = await this.client.sendJSON(config);
185
176
  return response.data;
186
177
  }
187
178
  catch (error) {
188
- switch (error.label) {
189
- case http_1.BackendErrorLabel.FEATURE_LOCKED: {
190
- throw new _1.FeatureLockedError(error.message);
191
- }
179
+ if ((0, exports.isBackendError)(error) && error.label === http_1.BackendErrorLabel.FEATURE_LOCKED) {
180
+ throw new _1.FeatureLockedError(error.message);
192
181
  }
193
182
  throw error;
194
183
  }
@@ -196,7 +185,7 @@ class FeatureAPI {
196
185
  async getFileSharingFeature(teamId) {
197
186
  const config = {
198
187
  method: 'get',
199
- url: `${FeatureAPI.URL.TEAMS}/${teamId}/${FeatureAPI.URL.FEATURES}/${FeatureAPI.URL.FILE_SHARING}`,
188
+ url: `/teams/${teamId}/features/fileSharing`,
200
189
  };
201
190
  const response = await this.client.sendJSON(config);
202
191
  return response.data;
@@ -205,17 +194,15 @@ class FeatureAPI {
205
194
  const config = {
206
195
  data: fileSharingFeature,
207
196
  method: 'put',
208
- url: `${FeatureAPI.URL.TEAMS}/${teamId}/${FeatureAPI.URL.FEATURES}/${FeatureAPI.URL.FILE_SHARING}`,
197
+ url: `/teams/${teamId}/features/fileSharing`,
209
198
  };
210
199
  try {
211
200
  const response = await this.client.sendJSON(config);
212
201
  return response.data;
213
202
  }
214
203
  catch (error) {
215
- switch (error.label) {
216
- case http_1.BackendErrorLabel.FEATURE_LOCKED: {
217
- throw new _1.FeatureLockedError(error.message);
218
- }
204
+ if ((0, exports.isBackendError)(error) && error.label === http_1.BackendErrorLabel.FEATURE_LOCKED) {
205
+ throw new _1.FeatureLockedError(error.message);
219
206
  }
220
207
  throw error;
221
208
  }
@@ -223,7 +210,7 @@ class FeatureAPI {
223
210
  async getSndFactorPasswordFeature(teamId) {
224
211
  const config = {
225
212
  method: 'get',
226
- url: `${FeatureAPI.URL.TEAMS}/${teamId}/${FeatureAPI.URL.FEATURES}/${FeatureAPI.URL.SND_FACTOR_PASSWORD}`,
213
+ url: `/teams/${teamId}/features/sndFactorPasswordChallenge`,
227
214
  };
228
215
  const response = await this.client.sendJSON(config);
229
216
  return response.data;
@@ -231,7 +218,7 @@ class FeatureAPI {
231
218
  async getSSOFeature(teamId) {
232
219
  const config = {
233
220
  method: 'get',
234
- url: `${FeatureAPI.URL.TEAMS}/${teamId}/${FeatureAPI.URL.FEATURES}/${FeatureAPI.URL.SSO}`,
221
+ url: `/teams/${teamId}/features/sso`,
235
222
  };
236
223
  const response = await this.client.sendJSON(config);
237
224
  return response.data;
@@ -239,7 +226,7 @@ class FeatureAPI {
239
226
  async getMLSFeature(teamId) {
240
227
  const config = {
241
228
  method: 'get',
242
- url: `${FeatureAPI.URL.TEAMS}/${teamId}/${FeatureAPI.URL.FEATURES}/${FeatureAPI.URL.MLS}`,
229
+ url: `/teams/${teamId}/features/mls`,
243
230
  };
244
231
  const response = await this.client.sendJSON(config);
245
232
  return response.data;
@@ -248,7 +235,7 @@ class FeatureAPI {
248
235
  const config = {
249
236
  data: mlsFeature,
250
237
  method: 'put',
251
- url: `${FeatureAPI.URL.TEAMS}/${teamId}/${FeatureAPI.URL.FEATURES}/${FeatureAPI.URL.MLS}`,
238
+ url: `/teams/${teamId}/features/mls`,
252
239
  };
253
240
  const response = await this.client.sendJSON(config);
254
241
  return response.data;
@@ -257,7 +244,7 @@ class FeatureAPI {
257
244
  const config = {
258
245
  data: mlsFeature,
259
246
  method: 'put',
260
- url: `${FeatureAPI.URL.TEAMS}/${teamId}/${FeatureAPI.URL.FEATURES}/${FeatureAPI.URL.MLSE2EID}`,
247
+ url: `/teams/${teamId}/features/mlsE2EId`,
261
248
  };
262
249
  const response = await this.client.sendJSON(config);
263
250
  return response.data;
@@ -266,7 +253,7 @@ class FeatureAPI {
266
253
  const config = {
267
254
  data: mlsMigrationFeature,
268
255
  method: 'put',
269
- url: `${FeatureAPI.URL.TEAMS}/${teamId}/${FeatureAPI.URL.FEATURES}/${FeatureAPI.URL.MLS_MIGRATION}`,
256
+ url: `/teams/${teamId}/features/mlsMigration`,
270
257
  };
271
258
  const response = await this.client.sendJSON(config);
272
259
  return response.data;
@@ -274,7 +261,7 @@ class FeatureAPI {
274
261
  async getDigitalSignatureFeature(teamId) {
275
262
  const config = {
276
263
  method: 'get',
277
- url: `${FeatureAPI.URL.TEAMS}/${teamId}/${FeatureAPI.URL.FEATURES}/${FeatureAPI.URL.DIGITAL_SIGNATURES}`,
264
+ url: `/teams/${teamId}/features/digitalSignatures`,
278
265
  };
279
266
  const response = await this.client.sendJSON(config);
280
267
  return response.data;
@@ -283,7 +270,7 @@ class FeatureAPI {
283
270
  async getDomainRegistrationFeature(teamId) {
284
271
  const config = {
285
272
  method: 'get',
286
- url: `${FeatureAPI.URL.TEAMS}/${teamId}/${FeatureAPI.URL.FEATURES}/${FeatureAPI.URL.DOMAIN_REGISTRATION}`,
273
+ url: `/teams/${teamId}/features/domainRegistration`,
287
274
  };
288
275
  const response = await this.client.sendJSON(config);
289
276
  return response.data;
@@ -291,7 +278,7 @@ class FeatureAPI {
291
278
  async getAppLockFeature(teamId) {
292
279
  const config = {
293
280
  method: 'get',
294
- url: `${FeatureAPI.URL.TEAMS}/${teamId}/${FeatureAPI.URL.FEATURES}/${FeatureAPI.URL.APPLOCK}`,
281
+ url: `/teams/${teamId}/features/appLock`,
295
282
  };
296
283
  const response = await this.client.sendJSON(config);
297
284
  return response.data;
@@ -299,7 +286,7 @@ class FeatureAPI {
299
286
  async getAllowedGlobalOperationsFeature(teamId) {
300
287
  const config = {
301
288
  method: 'get',
302
- url: `${FeatureAPI.URL.TEAMS}/${teamId}/${FeatureAPI.URL.FEATURES}/${FeatureAPI.URL.ALLOWED_GLOBAL_OPERATIONS}`,
289
+ url: `/teams/${teamId}/features/allowedGlobalOperations`,
303
290
  };
304
291
  const response = await this.client.sendJSON(config);
305
292
  return response.data;
@@ -307,7 +294,7 @@ class FeatureAPI {
307
294
  async getConsumableNotificationsFeature(teamId) {
308
295
  const config = {
309
296
  method: 'get',
310
- url: `${FeatureAPI.URL.TEAMS}/${teamId}/${FeatureAPI.URL.FEATURES}/${FeatureAPI.URL.CONSUMABLE_NOTIFICATIONS}`,
297
+ url: `/teams/${teamId}/features/consumableNotifications`,
311
298
  };
312
299
  const response = await this.client.sendJSON(config);
313
300
  return response.data;
@@ -316,7 +303,7 @@ class FeatureAPI {
316
303
  const config = {
317
304
  data: appLockFeature,
318
305
  method: 'put',
319
- url: `${FeatureAPI.URL.TEAMS}/${teamId}/${FeatureAPI.URL.FEATURES}/${FeatureAPI.URL.APPLOCK}`,
306
+ url: `/teams/${teamId}/features/appLock`,
320
307
  };
321
308
  try {
322
309
  const response = await this.client.sendJSON(config);
@@ -338,7 +325,7 @@ class FeatureAPI {
338
325
  const config = {
339
326
  data: dlPathFeature,
340
327
  method: 'put',
341
- url: `${FeatureAPI.URL.TEAMS}/${teamId}/${FeatureAPI.URL.FEATURES}/${FeatureAPI.URL.DL_PATH}`,
328
+ url: `/teams/${teamId}/features/enforceFileDownloadLocation`,
342
329
  };
343
330
  const response = await this.client.sendJSON(config);
344
331
  return response.data;
@@ -347,7 +334,7 @@ class FeatureAPI {
347
334
  const config = {
348
335
  data: channelFeature,
349
336
  method: 'put',
350
- url: `${FeatureAPI.URL.TEAMS}/${teamId}/${FeatureAPI.URL.FEATURES}/${FeatureAPI.URL.CHANNELS}`,
337
+ url: `/teams/${teamId}/features/channels`,
351
338
  };
352
339
  const response = await this.client.sendJSON(config);
353
340
  return response.data;
@@ -355,7 +342,7 @@ class FeatureAPI {
355
342
  async getCellsFeature(teamId) {
356
343
  const config = {
357
344
  method: 'get',
358
- url: `${FeatureAPI.URL.TEAMS}/${teamId}/${FeatureAPI.URL.FEATURES}/${FeatureAPI.URL.CELLS}`,
345
+ url: `/teams/${teamId}/features/cells`,
359
346
  };
360
347
  const response = await this.client.sendJSON(config);
361
348
  return response.data;
@@ -363,7 +350,7 @@ class FeatureAPI {
363
350
  async getAssetAuditLog(teamId) {
364
351
  const config = {
365
352
  method: 'get',
366
- url: `${FeatureAPI.URL.TEAMS}/${teamId}/${FeatureAPI.URL.FEATURES}/${FeatureAPI.URL.AUDIT_LOG}`,
353
+ url: `/teams/${teamId}/features/assetAuditLog`,
367
354
  };
368
355
  const response = await this.client.sendJSON(config);
369
356
  return response.data;