@stream-io/node-sdk 0.4.18 → 0.4.20

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.js CHANGED
@@ -3,6 +3,7 @@
3
3
  var jwt = require('jsonwebtoken');
4
4
  var uuid = require('uuid');
5
5
  var crypto = require('crypto');
6
+ var undici = require('undici');
6
7
 
7
8
  function _interopNamespaceDefault(e) {
8
9
  var n = Object.create(null);
@@ -157,7 +158,7 @@ class BaseApi {
157
158
  Authorization: this.apiConfig.token,
158
159
  'stream-auth-type': 'jwt',
159
160
  'Content-Type': 'application/json',
160
- 'X-Stream-Client': 'stream-node-' + "0.4.18",
161
+ 'X-Stream-Client': 'stream-node-' + "0.4.20",
161
162
  'Accept-Encoding': 'gzip',
162
163
  'x-client-request-id': clientRequestId,
163
164
  };
@@ -168,6 +169,8 @@ class BaseApi {
168
169
  method,
169
170
  body: JSON.stringify(body),
170
171
  headers,
172
+ /** @ts-expect-error we get types from DOM here, but we should use node types */
173
+ dispatcher: this.dispatcher,
171
174
  });
172
175
  const responseHeaders = response.headers;
173
176
  const metadata = {
@@ -228,6 +231,7 @@ class BaseApi {
228
231
  }
229
232
  return newParams.join('&');
230
233
  };
234
+ this.dispatcher = this.apiConfig.agent;
231
235
  }
232
236
  }
233
237
 
@@ -531,6 +535,7 @@ decoders.ChannelStateResponse = (input) => {
531
535
  read: { type: 'ReadStateResponse', isSingle: false },
532
536
  watchers: { type: 'UserResponse', isSingle: false },
533
537
  channel: { type: 'ChannelResponse', isSingle: true },
538
+ draft: { type: 'DraftResponse', isSingle: true },
534
539
  membership: { type: 'ChannelMember', isSingle: true },
535
540
  push_preferences: { type: 'ChannelPushPreferences', isSingle: true },
536
541
  };
@@ -547,6 +552,7 @@ decoders.ChannelStateResponseFields = (input) => {
547
552
  read: { type: 'ReadStateResponse', isSingle: false },
548
553
  watchers: { type: 'UserResponse', isSingle: false },
549
554
  channel: { type: 'ChannelResponse', isSingle: true },
555
+ draft: { type: 'DraftResponse', isSingle: true },
550
556
  membership: { type: 'ChannelMember', isSingle: true },
551
557
  push_preferences: { type: 'ChannelPushPreferences', isSingle: true },
552
558
  };
@@ -673,6 +679,22 @@ decoders.DeviceResponse = (input) => {
673
679
  };
674
680
  return decode(typeMappings, input);
675
681
  };
682
+ decoders.DraftPayloadResponse = (input) => {
683
+ const typeMappings = {
684
+ mentioned_users: { type: 'UserResponse', isSingle: false },
685
+ };
686
+ return decode(typeMappings, input);
687
+ };
688
+ decoders.DraftResponse = (input) => {
689
+ const typeMappings = {
690
+ created_at: { type: 'DatetimeType', isSingle: true },
691
+ message: { type: 'DraftPayloadResponse', isSingle: true },
692
+ channel: { type: 'ChannelResponse', isSingle: true },
693
+ parent_message: { type: 'MessageResponse', isSingle: true },
694
+ quoted_message: { type: 'MessageResponse', isSingle: true },
695
+ };
696
+ return decode(typeMappings, input);
697
+ };
676
698
  decoders.EgressRTMPResponse = (input) => {
677
699
  const typeMappings = {
678
700
  started_at: { type: 'DatetimeType', isSingle: true },
@@ -723,7 +745,7 @@ decoders.ExportUserResponse = (input) => {
723
745
  };
724
746
  return decode(typeMappings, input);
725
747
  };
726
- decoders.Flag2 = (input) => {
748
+ decoders.Flag = (input) => {
727
749
  const typeMappings = {
728
750
  created_at: { type: 'DatetimeType', isSingle: true },
729
751
  updated_at: { type: 'DatetimeType', isSingle: true },
@@ -731,14 +753,6 @@ decoders.Flag2 = (input) => {
731
753
  };
732
754
  return decode(typeMappings, input);
733
755
  };
734
- decoders.Flag2Response = (input) => {
735
- const typeMappings = {
736
- created_at: { type: 'DatetimeType', isSingle: true },
737
- updated_at: { type: 'DatetimeType', isSingle: true },
738
- user: { type: 'UserResponse', isSingle: true },
739
- };
740
- return decode(typeMappings, input);
741
- };
742
756
  decoders.FlagDetails = (input) => {
743
757
  const typeMappings = {
744
758
  automod: { type: 'AutomodDetails', isSingle: true },
@@ -758,6 +772,7 @@ decoders.FullUserResponse = (input) => {
758
772
  channel_mutes: { type: 'ChannelMute', isSingle: false },
759
773
  devices: { type: 'DeviceResponse', isSingle: false },
760
774
  mutes: { type: 'UserMuteResponse', isSingle: false },
775
+ ban_expires: { type: 'DatetimeType', isSingle: true },
761
776
  deactivated_at: { type: 'DatetimeType', isSingle: true },
762
777
  deleted_at: { type: 'DatetimeType', isSingle: true },
763
778
  last_active: { type: 'DatetimeType', isSingle: true },
@@ -797,12 +812,6 @@ decoders.GetCallTypeResponse = (input) => {
797
812
  };
798
813
  return decode(typeMappings, input);
799
814
  };
800
- decoders.GetCampaignResponse = (input) => {
801
- const typeMappings = {
802
- campaign: { type: 'CampaignResponse', isSingle: true },
803
- };
804
- return decode(typeMappings, input);
805
- };
806
815
  decoders.GetChannelTypeResponse = (input) => {
807
816
  const typeMappings = {
808
817
  created_at: { type: 'DatetimeType', isSingle: true },
@@ -824,6 +833,12 @@ decoders.GetConfigResponse = (input) => {
824
833
  };
825
834
  return decode(typeMappings, input);
826
835
  };
836
+ decoders.GetDraftResponse = (input) => {
837
+ const typeMappings = {
838
+ draft: { type: 'DraftResponse', isSingle: true },
839
+ };
840
+ return decode(typeMappings, input);
841
+ };
827
842
  decoders.GetImportResponse = (input) => {
828
843
  const typeMappings = {
829
844
  import_task: { type: 'ImportTask', isSingle: true },
@@ -887,14 +902,6 @@ decoders.GetThreadResponse = (input) => {
887
902
  };
888
903
  return decode(typeMappings, input);
889
904
  };
890
- decoders.GetUserModerationReportResponse = (input) => {
891
- const typeMappings = {
892
- user_blocks: { type: 'UserBlock', isSingle: false },
893
- user_mutes: { type: 'UserMute', isSingle: false },
894
- user: { type: 'UserResponse', isSingle: true },
895
- };
896
- return decode(typeMappings, input);
897
- };
898
905
  decoders.GoLiveResponse = (input) => {
899
906
  const typeMappings = {
900
907
  call: { type: 'CallResponse', isSingle: true },
@@ -1067,6 +1074,7 @@ decoders.MessageResponse = (input) => {
1067
1074
  pin_expires: { type: 'DatetimeType', isSingle: true },
1068
1075
  pinned_at: { type: 'DatetimeType', isSingle: true },
1069
1076
  thread_participants: { type: 'UserResponse', isSingle: false },
1077
+ draft: { type: 'DraftResponse', isSingle: true },
1070
1078
  pinned_by: { type: 'UserResponse', isSingle: true },
1071
1079
  poll: { type: 'PollResponseData', isSingle: true },
1072
1080
  quoted_message: { type: 'MessageResponse', isSingle: true },
@@ -1088,6 +1096,7 @@ decoders.MessageWithChannelResponse = (input) => {
1088
1096
  pin_expires: { type: 'DatetimeType', isSingle: true },
1089
1097
  pinned_at: { type: 'DatetimeType', isSingle: true },
1090
1098
  thread_participants: { type: 'UserResponse', isSingle: false },
1099
+ draft: { type: 'DraftResponse', isSingle: true },
1091
1100
  pinned_by: { type: 'UserResponse', isSingle: true },
1092
1101
  poll: { type: 'PollResponseData', isSingle: true },
1093
1102
  quoted_message: { type: 'MessageResponse', isSingle: true },
@@ -1095,13 +1104,6 @@ decoders.MessageWithChannelResponse = (input) => {
1095
1104
  };
1096
1105
  return decode(typeMappings, input);
1097
1106
  };
1098
- decoders.ModerationUsageStats = (input) => {
1099
- const typeMappings = {
1100
- reference_date: { type: 'DatetimeType', isSingle: true },
1101
- updated_at: { type: 'DatetimeType', isSingle: true },
1102
- };
1103
- return decode(typeMappings, input);
1104
- };
1105
1107
  decoders.MuteChannelResponse = (input) => {
1106
1108
  const typeMappings = {
1107
1109
  channel_mutes: { type: 'ChannelMute', isSingle: false },
@@ -1279,6 +1281,12 @@ decoders.QueryChannelsResponse = (input) => {
1279
1281
  };
1280
1282
  return decode(typeMappings, input);
1281
1283
  };
1284
+ decoders.QueryDraftsResponse = (input) => {
1285
+ const typeMappings = {
1286
+ drafts: { type: 'DraftResponse', isSingle: false },
1287
+ };
1288
+ return decode(typeMappings, input);
1289
+ };
1282
1290
  decoders.QueryFeedModerationTemplate = (input) => {
1283
1291
  const typeMappings = {
1284
1292
  created_at: { type: 'DatetimeType', isSingle: true },
@@ -1352,12 +1360,6 @@ decoders.QueryThreadsResponse = (input) => {
1352
1360
  };
1353
1361
  return decode(typeMappings, input);
1354
1362
  };
1355
- decoders.QueryUsageStatsResponse = (input) => {
1356
- const typeMappings = {
1357
- items: { type: 'ModerationUsageStats', isSingle: false },
1358
- };
1359
- return decode(typeMappings, input);
1360
- };
1361
1363
  decoders.QueryUsersResponse = (input) => {
1362
1364
  const typeMappings = {
1363
1365
  users: { type: 'FullUserResponse', isSingle: false },
@@ -1406,11 +1408,12 @@ decoders.ReviewQueueItem = (input) => {
1406
1408
  updated_at: { type: 'DatetimeType', isSingle: true },
1407
1409
  actions: { type: 'ActionLog', isSingle: false },
1408
1410
  bans: { type: 'Ban', isSingle: false },
1409
- flags: { type: 'Flag2', isSingle: false },
1411
+ flags: { type: 'Flag', isSingle: false },
1410
1412
  assigned_to: { type: 'User', isSingle: true },
1411
1413
  entity_creator: { type: 'EntityCreator', isSingle: true },
1412
1414
  feeds_v2_reaction: { type: 'Reaction', isSingle: true },
1413
1415
  message: { type: 'Message', isSingle: true },
1416
+ reaction: { type: 'Reaction', isSingle: true },
1414
1417
  };
1415
1418
  return decode(typeMappings, input);
1416
1419
  };
@@ -1420,13 +1423,13 @@ decoders.ReviewQueueItemResponse = (input) => {
1420
1423
  updated_at: { type: 'DatetimeType', isSingle: true },
1421
1424
  actions: { type: 'ActionLogResponse', isSingle: false },
1422
1425
  bans: { type: 'Ban', isSingle: false },
1423
- flags: { type: 'Flag2Response', isSingle: false },
1424
1426
  completed_at: { type: 'DatetimeType', isSingle: true },
1425
1427
  reviewed_at: { type: 'DatetimeType', isSingle: true },
1426
1428
  assigned_to: { type: 'UserResponse', isSingle: true },
1427
1429
  entity_creator: { type: 'EntityCreatorResponse', isSingle: true },
1428
1430
  feeds_v2_reaction: { type: 'Reaction', isSingle: true },
1429
1431
  message: { type: 'MessageResponse', isSingle: true },
1432
+ reaction: { type: 'Reaction', isSingle: true },
1430
1433
  };
1431
1434
  return decode(typeMappings, input);
1432
1435
  };
@@ -1457,6 +1460,7 @@ decoders.SearchResultMessage = (input) => {
1457
1460
  pinned_at: { type: 'DatetimeType', isSingle: true },
1458
1461
  thread_participants: { type: 'UserResponse', isSingle: false },
1459
1462
  channel: { type: 'ChannelResponse', isSingle: true },
1463
+ draft: { type: 'DraftResponse', isSingle: true },
1460
1464
  pinned_by: { type: 'UserResponse', isSingle: true },
1461
1465
  poll: { type: 'PollResponseData', isSingle: true },
1462
1466
  quoted_message: { type: 'MessageResponse', isSingle: true },
@@ -1499,12 +1503,6 @@ decoders.SendReactionResponse = (input) => {
1499
1503
  };
1500
1504
  return decode(typeMappings, input);
1501
1505
  };
1502
- decoders.StartCampaignResponse = (input) => {
1503
- const typeMappings = {
1504
- campaign: { type: 'CampaignResponse', isSingle: true },
1505
- };
1506
- return decode(typeMappings, input);
1507
- };
1508
1506
  decoders.StopLiveResponse = (input) => {
1509
1507
  const typeMappings = {
1510
1508
  call: { type: 'CallResponse', isSingle: true },
@@ -1551,6 +1549,7 @@ decoders.ThreadStateResponse = (input) => {
1551
1549
  thread_participants: { type: 'ThreadParticipant', isSingle: false },
1552
1550
  channel: { type: 'ChannelResponse', isSingle: true },
1553
1551
  created_by: { type: 'UserResponse', isSingle: true },
1552
+ draft: { type: 'DraftResponse', isSingle: true },
1554
1553
  parent_message: { type: 'MessageResponse', isSingle: true },
1555
1554
  };
1556
1555
  return decode(typeMappings, input);
@@ -1709,12 +1708,6 @@ decoders.User = (input) => {
1709
1708
  };
1710
1709
  return decode(typeMappings, input);
1711
1710
  };
1712
- decoders.UserBlock = (input) => {
1713
- const typeMappings = {
1714
- created_at: { type: 'DatetimeType', isSingle: true },
1715
- };
1716
- return decode(typeMappings, input);
1717
- };
1718
1711
  decoders.UserMute = (input) => {
1719
1712
  const typeMappings = {
1720
1713
  created_at: { type: 'DatetimeType', isSingle: true },
@@ -3102,6 +3095,7 @@ class ChatApi extends BaseApi {
3102
3095
  limit: request?.limit,
3103
3096
  next: request?.next,
3104
3097
  prev: request?.prev,
3098
+ user_limit: request?.user_limit,
3105
3099
  sort: request?.sort,
3106
3100
  filter: request?.filter,
3107
3101
  };
@@ -3110,10 +3104,15 @@ class ChatApi extends BaseApi {
3110
3104
  return { ...response.body, metadata: response.metadata };
3111
3105
  };
3112
3106
  this.getCampaign = async (request) => {
3107
+ const queryParams = {
3108
+ prev: request?.prev,
3109
+ next: request?.next,
3110
+ limit: request?.limit,
3111
+ };
3113
3112
  const pathParams = {
3114
3113
  id: request?.id,
3115
3114
  };
3116
- const response = await this.sendRequest('GET', '/api/v2/chat/campaigns/{id}', pathParams, undefined);
3115
+ const response = await this.sendRequest('GET', '/api/v2/chat/campaigns/{id}', pathParams, queryParams);
3117
3116
  decoders.GetCampaignResponse?.(response.body);
3118
3117
  return { ...response.body, metadata: response.metadata };
3119
3118
  };
@@ -3243,6 +3242,32 @@ class ChatApi extends BaseApi {
3243
3242
  decoders.UpdateChannelResponse?.(response.body);
3244
3243
  return { ...response.body, metadata: response.metadata };
3245
3244
  };
3245
+ this.deleteDraft = async (request) => {
3246
+ const queryParams = {
3247
+ parent_id: request?.parent_id,
3248
+ user_id: request?.user_id,
3249
+ };
3250
+ const pathParams = {
3251
+ type: request?.type,
3252
+ id: request?.id,
3253
+ };
3254
+ const response = await this.sendRequest('DELETE', '/api/v2/chat/channels/{type}/{id}/draft', pathParams, queryParams);
3255
+ decoders.Response?.(response.body);
3256
+ return { ...response.body, metadata: response.metadata };
3257
+ };
3258
+ this.getDraft = async (request) => {
3259
+ const queryParams = {
3260
+ parent_id: request?.parent_id,
3261
+ user_id: request?.user_id,
3262
+ };
3263
+ const pathParams = {
3264
+ type: request?.type,
3265
+ id: request?.id,
3266
+ };
3267
+ const response = await this.sendRequest('GET', '/api/v2/chat/channels/{type}/{id}/draft', pathParams, queryParams);
3268
+ decoders.GetDraftResponse?.(response.body);
3269
+ return { ...response.body, metadata: response.metadata };
3270
+ };
3246
3271
  this.sendEvent = async (request) => {
3247
3272
  const pathParams = {
3248
3273
  type: request?.type,
@@ -3581,6 +3606,20 @@ class ChatApi extends BaseApi {
3581
3606
  decoders.UpdateCommandResponse?.(response.body);
3582
3607
  return { ...response.body, metadata: response.metadata };
3583
3608
  };
3609
+ this.queryDrafts = async (request) => {
3610
+ const body = {
3611
+ limit: request?.limit,
3612
+ next: request?.next,
3613
+ prev: request?.prev,
3614
+ user_id: request?.user_id,
3615
+ sort: request?.sort,
3616
+ filter: request?.filter,
3617
+ user: request?.user,
3618
+ };
3619
+ const response = await this.sendRequest('POST', '/api/v2/chat/drafts/query', undefined, undefined, body);
3620
+ decoders.QueryDraftsResponse?.(response.body);
3621
+ return { ...response.body, metadata: response.metadata };
3622
+ };
3584
3623
  this.exportChannels = async (request) => {
3585
3624
  const body = {
3586
3625
  channels: request?.channels,
@@ -4197,6 +4236,22 @@ class ChannelApi {
4197
4236
  ...request,
4198
4237
  });
4199
4238
  };
4239
+ this.deleteDraft = (request) => {
4240
+ if (!this.id) {
4241
+ throw new Error(`Channel isn't yet created, call getOrCreateDistinctChannel() before this operation`);
4242
+ }
4243
+ return this.chatApi.deleteDraft({
4244
+ id: this.id,
4245
+ type: this.type,
4246
+ ...request,
4247
+ });
4248
+ };
4249
+ this.getDraft = (request) => {
4250
+ if (!this.id) {
4251
+ throw new Error(`Channel isn't yet created, call getOrCreateDistinctChannel() before this operation`);
4252
+ }
4253
+ return this.chatApi.getDraft({ id: this.id, type: this.type, ...request });
4254
+ };
4200
4255
  this.sendEvent = (request) => {
4201
4256
  if (!this.id) {
4202
4257
  throw new Error(`Channel isn't yet created, call getOrCreateDistinctChannel() before this operation`);
@@ -4382,15 +4437,6 @@ class StreamChatClient extends ChatApi {
4382
4437
  class ModerationApi extends BaseApi {
4383
4438
  constructor() {
4384
4439
  super(...arguments);
4385
- this.getModerationAnalytics = async (request) => {
4386
- const body = {
4387
- end_date: request?.end_date,
4388
- start_date: request?.start_date,
4389
- };
4390
- const response = await this.sendRequest('POST', '/api/v2/moderation/analytics', undefined, undefined, body);
4391
- decoders.GetModerationAnalyticsResponse?.(response.body);
4392
- return { ...response.body, metadata: response.metadata };
4393
- };
4394
4440
  this.ban = async (request) => {
4395
4441
  const body = {
4396
4442
  target_user_id: request?.target_user_id,
@@ -4544,11 +4590,6 @@ class ModerationApi extends BaseApi {
4544
4590
  decoders.QueryModerationLogsResponse?.(response.body);
4545
4591
  return { ...response.body, metadata: response.metadata };
4546
4592
  };
4547
- this.getModeratorStats = async () => {
4548
- const response = await this.sendRequest('GET', '/api/v2/moderation/moderator_stats', undefined, undefined);
4549
- decoders.ModeratorStatsResponse?.(response.body);
4550
- return { ...response.body, metadata: response.metadata };
4551
- };
4552
4593
  this.mute = async (request) => {
4553
4594
  const body = {
4554
4595
  target_ids: request?.target_ids,
@@ -4560,11 +4601,6 @@ class ModerationApi extends BaseApi {
4560
4601
  decoders.MuteResponse?.(response.body);
4561
4602
  return { ...response.body, metadata: response.metadata };
4562
4603
  };
4563
- this.getQueueStats = async () => {
4564
- const response = await this.sendRequest('GET', '/api/v2/moderation/queue_stats', undefined, undefined);
4565
- decoders.QueueStatsResponse?.(response.body);
4566
- return { ...response.body, metadata: response.metadata };
4567
- };
4568
4604
  this.queryReviewQueue = async (request) => {
4569
4605
  const body = {
4570
4606
  limit: request?.limit,
@@ -4634,31 +4670,6 @@ class ModerationApi extends BaseApi {
4634
4670
  decoders.UnmuteResponse?.(response.body);
4635
4671
  return { ...response.body, metadata: response.metadata };
4636
4672
  };
4637
- this.queryUsageStats = async (request) => {
4638
- const body = {
4639
- limit: request?.limit,
4640
- next: request?.next,
4641
- prev: request?.prev,
4642
- user_id: request?.user_id,
4643
- sort: request?.sort,
4644
- filter: request?.filter,
4645
- user: request?.user,
4646
- };
4647
- const response = await this.sendRequest('POST', '/api/v2/moderation/usage_stats', undefined, undefined, body);
4648
- decoders.QueryUsageStatsResponse?.(response.body);
4649
- return { ...response.body, metadata: response.metadata };
4650
- };
4651
- this.getUserReport = async (request) => {
4652
- const queryParams = {
4653
- user_id: request?.user_id,
4654
- create_user_if_not_exists: request?.create_user_if_not_exists,
4655
- include_user_mutes: request?.include_user_mutes,
4656
- include_user_blocks: request?.include_user_blocks,
4657
- };
4658
- const response = await this.sendRequest('GET', '/api/v2/moderation/user_report', undefined, queryParams);
4659
- decoders.GetUserModerationReportResponse?.(response.body);
4660
- return { ...response.body, metadata: response.metadata };
4661
- };
4662
4673
  }
4663
4674
  }
4664
4675
 
@@ -4675,9 +4686,15 @@ class StreamClient extends CommonApi {
4675
4686
  constructor(apiKey, secret, config) {
4676
4687
  const token = JWTServerToken(secret);
4677
4688
  const timeout = config?.timeout ?? StreamClient.DEFAULT_TIMEOUT;
4689
+ const agent = config?.agent ??
4690
+ new undici.Agent({
4691
+ connections: config?.maxConnections === undefined
4692
+ ? StreamClient.MAX_CONNECTIONS
4693
+ : config.maxConnections,
4694
+ });
4678
4695
  const chatBaseUrl = config?.basePath ?? 'https://chat.stream-io-api.com';
4679
4696
  const videoBaseUrl = config?.basePath ?? 'https://video.stream-io-api.com';
4680
- super({ apiKey, token, timeout, baseUrl: chatBaseUrl });
4697
+ super({ apiKey, token, timeout, baseUrl: chatBaseUrl, agent });
4681
4698
  this.apiKey = apiKey;
4682
4699
  this.secret = secret;
4683
4700
  this.config = config;
@@ -4778,22 +4795,26 @@ class StreamClient extends CommonApi {
4778
4795
  token,
4779
4796
  timeout,
4780
4797
  baseUrl: videoBaseUrl,
4798
+ agent,
4781
4799
  });
4782
4800
  this.chat = new StreamChatClient({
4783
4801
  apiKey,
4784
4802
  token,
4785
4803
  timeout,
4786
4804
  baseUrl: chatBaseUrl,
4805
+ agent,
4787
4806
  });
4788
4807
  this.moderation = new StreamModerationClient({
4789
4808
  apiKey,
4790
4809
  token,
4791
4810
  timeout,
4792
4811
  baseUrl: chatBaseUrl,
4812
+ agent,
4793
4813
  });
4794
4814
  }
4795
4815
  }
4796
4816
  StreamClient.DEFAULT_TIMEOUT = 3000;
4817
+ StreamClient.MAX_CONNECTIONS = 100;
4797
4818
 
4798
4819
  exports.ChannelOwnCapability = ChannelOwnCapability;
4799
4820
  exports.OwnCapability = OwnCapability;