@amityco/ts-sdk 7.26.1-db34ef5c.0 → 7.26.1-e618fbd1.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 (59) hide show
  1. package/dist/@types/core/events.d.ts +2 -0
  2. package/dist/@types/core/events.d.ts.map +1 -1
  3. package/dist/@types/core/permissions.d.ts +1 -0
  4. package/dist/@types/core/permissions.d.ts.map +1 -1
  5. package/dist/@types/domains/channel.d.ts +5 -0
  6. package/dist/@types/domains/channel.d.ts.map +1 -1
  7. package/dist/@types/domains/client.d.ts +7 -0
  8. package/dist/@types/domains/client.d.ts.map +1 -1
  9. package/dist/@types/domains/pinnedMessage.d.ts +43 -0
  10. package/dist/@types/domains/pinnedMessage.d.ts.map +1 -0
  11. package/dist/@types/index.d.ts +1 -0
  12. package/dist/@types/index.d.ts.map +1 -1
  13. package/dist/channelRepository/events/index.d.ts +2 -0
  14. package/dist/channelRepository/events/index.d.ts.map +1 -1
  15. package/dist/channelRepository/events/onChannelMessagePinned.d.ts +24 -0
  16. package/dist/channelRepository/events/onChannelMessagePinned.d.ts.map +1 -0
  17. package/dist/channelRepository/events/onChannelMessageUnpinned.d.ts +21 -0
  18. package/dist/channelRepository/events/onChannelMessageUnpinned.d.ts.map +1 -0
  19. package/dist/channelRepository/events/onChannelPinnedMessageDeleted.d.ts +12 -0
  20. package/dist/channelRepository/events/onChannelPinnedMessageDeleted.d.ts.map +1 -0
  21. package/dist/channelRepository/events/tests/onChannelMessagePinned.test.d.ts +2 -0
  22. package/dist/channelRepository/events/tests/onChannelMessagePinned.test.d.ts.map +1 -0
  23. package/dist/channelRepository/observers/getChannel.d.ts.map +1 -1
  24. package/dist/channelRepository/utils/index.d.ts +1 -0
  25. package/dist/channelRepository/utils/index.d.ts.map +1 -1
  26. package/dist/channelRepository/utils/tests/pinnedMessage.test.d.ts +2 -0
  27. package/dist/channelRepository/utils/tests/pinnedMessage.test.d.ts.map +1 -0
  28. package/dist/channelRepository/utils/updatePinnedMessageCache.d.ts +24 -0
  29. package/dist/channelRepository/utils/updatePinnedMessageCache.d.ts.map +1 -0
  30. package/dist/client/api/loginWithAccessToken.d.ts.map +1 -1
  31. package/dist/client/api/resumeSession.d.ts.map +1 -1
  32. package/dist/client/api/tests/validateAccessToken.test.d.ts +2 -0
  33. package/dist/client/api/tests/validateAccessToken.test.d.ts.map +1 -0
  34. package/dist/client/api/validateAccessToken.d.ts +1 -1
  35. package/dist/client/api/validateAccessToken.d.ts.map +1 -1
  36. package/dist/core/events.d.ts +3 -3
  37. package/dist/core/events.d.ts.map +1 -1
  38. package/dist/index.cjs.js +396 -107
  39. package/dist/index.esm.js +396 -107
  40. package/dist/index.umd.js +2 -2
  41. package/dist/messagePreview/utils/getChannelMessagePreviewWithUser.d.ts +1 -0
  42. package/dist/messagePreview/utils/getChannelMessagePreviewWithUser.d.ts.map +1 -1
  43. package/dist/messageRepository/api/index.d.ts +2 -0
  44. package/dist/messageRepository/api/index.d.ts.map +1 -1
  45. package/dist/messageRepository/api/pinMessage.d.ts +29 -0
  46. package/dist/messageRepository/api/pinMessage.d.ts.map +1 -0
  47. package/dist/messageRepository/api/tests/pinMessage.test.d.ts +2 -0
  48. package/dist/messageRepository/api/tests/pinMessage.test.d.ts.map +1 -0
  49. package/dist/messageRepository/api/tests/unpinMessage.test.d.ts +2 -0
  50. package/dist/messageRepository/api/tests/unpinMessage.test.d.ts.map +1 -0
  51. package/dist/messageRepository/api/unpinMessage.d.ts +28 -0
  52. package/dist/messageRepository/api/unpinMessage.d.ts.map +1 -0
  53. package/dist/messageRepository/utils/refreshChannelPermissionsForMessage.d.ts +13 -0
  54. package/dist/messageRepository/utils/refreshChannelPermissionsForMessage.d.ts.map +1 -0
  55. package/dist/utils/tests/dummy/index.d.ts +1 -0
  56. package/dist/utils/tests/dummy/index.d.ts.map +1 -1
  57. package/dist/utils/tests/dummy/pinnedMessage.d.ts +2 -0
  58. package/dist/utils/tests/dummy/pinnedMessage.d.ts.map +1 -0
  59. package/package.json +1 -1
package/dist/index.cjs.js CHANGED
@@ -3842,6 +3842,53 @@ const prepareChannelPayload = async (rawPayload, options = { isMessagePreviewUpd
3842
3842
  channelUsers });
3843
3843
  };
3844
3844
 
3845
+ const channelCacheKey = (channel) => [
3846
+ 'channel',
3847
+ 'get',
3848
+ getResolver('channel')(channel),
3849
+ ];
3850
+ /**
3851
+ * Find a cached channel by any of its ids (internal, public, or `channelId`).
3852
+ *
3853
+ * The channel cache is keyed by the channel internal id (see `idResolvers.channel`), but
3854
+ * realtime payloads reference channels by different ids: pin events carry the **public**
3855
+ * id, messages carry `channelId`. Try the cheap direct lookup first, then scan.
3856
+ */
3857
+ const findCachedChannelByAnyId = (id) => {
3858
+ var _a, _b, _c;
3859
+ if (!id)
3860
+ return undefined;
3861
+ const direct = (_a = pullFromCache(['channel', 'get', id])) === null || _a === void 0 ? void 0 : _a.data;
3862
+ if (direct)
3863
+ return direct;
3864
+ return (_c = (_b = queryCache(['channel', 'get'])) === null || _b === void 0 ? void 0 : _b.find(({ data }) => data.channelInternalId === id || data.channelPublicId === id || data.channelId === id)) === null || _c === void 0 ? void 0 : _c.data;
3865
+ };
3866
+ /**
3867
+ * Resolve the cached channel a `channel.messagePinned` / `channel.messageUnpinned` event
3868
+ * refers to. `data.channelId` is the channel public id; a pinned message body (present on
3869
+ * `messagePinned` only) also carries the internal id, which is the direct cache key.
3870
+ */
3871
+ const findCachedChannelForPin = (payload) => {
3872
+ var _a, _b;
3873
+ return (_b = findCachedChannelByAnyId((_a = payload.pinnedMessage) === null || _a === void 0 ? void 0 : _a.channelId)) !== null && _b !== void 0 ? _b : findCachedChannelByAnyId(payload.channelId);
3874
+ };
3875
+ /**
3876
+ * Write a new pin snapshot (or `null` to clear) on a cached channel and ingest any
3877
+ * users delivered with it (the pin author and the message author), so the banner can
3878
+ * render a byline without a second fetch.
3879
+ *
3880
+ * Every `messagePinned` payload is a full snapshot — "this is the pin now" — so the last
3881
+ * one received always wins; there is no merging with the previous pin.
3882
+ */
3883
+ const updatePinnedMessageCache = (channel, pinnedMessage, users) => {
3884
+ if (users && users.length > 0) {
3885
+ ingestInCache({ users: users.map(convertRawUserToInternalUser) });
3886
+ }
3887
+ const updated = Object.assign(Object.assign({}, channel), { pinnedMessage });
3888
+ pushToCache(channelCacheKey(channel), updated);
3889
+ return updated;
3890
+ };
3891
+
3845
3892
  /**
3846
3893
  * ```js
3847
3894
  * import { getSubChannelMarkers } from '@amityco/ts-sdk'
@@ -4123,55 +4170,55 @@ function isEqual(x, y) {
4123
4170
  }));
4124
4171
  }
4125
4172
 
4126
- const callbacks$c = [];
4127
- let mainDisposer$b = null;
4128
- const dispose$c = (cb) => {
4129
- const index = callbacks$c.indexOf(cb);
4173
+ const callbacks$e = [];
4174
+ let mainDisposer$d = null;
4175
+ const dispose$e = (cb) => {
4176
+ const index = callbacks$e.indexOf(cb);
4130
4177
  if (index > -1) {
4131
- callbacks$c.splice(index, 1);
4178
+ callbacks$e.splice(index, 1);
4132
4179
  }
4133
- if (callbacks$c.length === 0) {
4134
- mainDisposer$b === null || mainDisposer$b === void 0 ? void 0 : mainDisposer$b();
4180
+ if (callbacks$e.length === 0) {
4181
+ mainDisposer$d === null || mainDisposer$d === void 0 ? void 0 : mainDisposer$d();
4135
4182
  }
4136
4183
  };
4137
4184
  const onChannelCreated = (callback) => {
4138
- if (callbacks$c.length === 0) {
4185
+ if (callbacks$e.length === 0) {
4139
4186
  const client = getActiveClient();
4140
4187
  const filter = async (payload) => {
4141
4188
  const data = await prepareChannelPayload(payload);
4142
4189
  ingestInCache(data);
4143
- callbacks$c.forEach(cb => cb(data.channels[0]));
4190
+ callbacks$e.forEach(cb => cb(data.channels[0]));
4144
4191
  };
4145
- mainDisposer$b = createEventSubscriber(client, 'onChannelCreated', 'channel.created', filter);
4192
+ mainDisposer$d = createEventSubscriber(client, 'onChannelCreated', 'channel.created', filter);
4146
4193
  }
4147
- callbacks$c.push(callback);
4148
- return () => dispose$c(callback);
4194
+ callbacks$e.push(callback);
4195
+ return () => dispose$e(callback);
4149
4196
  };
4150
4197
 
4151
- const callbacks$b = [];
4198
+ const callbacks$d = [];
4152
4199
  const mainDisposers = [];
4153
- const dispose$b = (cb) => {
4154
- const index = callbacks$b.indexOf(cb);
4200
+ const dispose$d = (cb) => {
4201
+ const index = callbacks$d.indexOf(cb);
4155
4202
  if (index > -1) {
4156
- callbacks$b.splice(index, 1);
4203
+ callbacks$d.splice(index, 1);
4157
4204
  }
4158
- if (callbacks$b.length === 0) {
4205
+ if (callbacks$d.length === 0) {
4159
4206
  mainDisposers.forEach(fn => fn());
4160
4207
  }
4161
4208
  };
4162
4209
  const onChannelUpdated = (callback) => {
4163
4210
  const client = getActiveClient();
4164
- if (callbacks$b.length === 0) {
4211
+ if (callbacks$d.length === 0) {
4165
4212
  const filter = async (payload) => {
4166
4213
  const data = await prepareChannelPayload(payload);
4167
4214
  ingestInCache(data);
4168
- callbacks$b.forEach(cb => cb(data.channels[0]));
4215
+ callbacks$d.forEach(cb => cb(data.channels[0]));
4169
4216
  };
4170
4217
  mainDisposers.push(createEventSubscriber(client, 'onChannelUpdated', 'channel.updated', filter));
4171
- mainDisposers.push(createEventSubscriber(client, 'onChannelUpdated', 'local.channel.updated', payload => callbacks$b.forEach(cb => cb(payload.channels[0]))));
4218
+ mainDisposers.push(createEventSubscriber(client, 'onChannelUpdated', 'local.channel.updated', payload => callbacks$d.forEach(cb => cb(payload.channels[0]))));
4172
4219
  }
4173
- callbacks$b.push(callback);
4174
- return () => dispose$b(callback);
4220
+ callbacks$d.push(callback);
4221
+ return () => dispose$d(callback);
4175
4222
  };
4176
4223
 
4177
4224
  const addFlagIsDeletedSubChannelUnreadByChannelId = (channelId) => {
@@ -4194,19 +4241,19 @@ const deleteChannelUnreadByChannelId = (channelId) => {
4194
4241
  }
4195
4242
  };
4196
4243
 
4197
- const callbacks$a = [];
4198
- let mainDisposer$a = null;
4199
- const dispose$a = (cb) => {
4200
- const index = callbacks$a.indexOf(cb);
4244
+ const callbacks$c = [];
4245
+ let mainDisposer$c = null;
4246
+ const dispose$c = (cb) => {
4247
+ const index = callbacks$c.indexOf(cb);
4201
4248
  if (index > -1) {
4202
- callbacks$a.splice(index, 1);
4249
+ callbacks$c.splice(index, 1);
4203
4250
  }
4204
- if (callbacks$a.length === 0) {
4205
- mainDisposer$a === null || mainDisposer$a === void 0 ? void 0 : mainDisposer$a();
4251
+ if (callbacks$c.length === 0) {
4252
+ mainDisposer$c === null || mainDisposer$c === void 0 ? void 0 : mainDisposer$c();
4206
4253
  }
4207
4254
  };
4208
4255
  const onChannelDeleted = (callback) => {
4209
- if (callbacks$a.length === 0) {
4256
+ if (callbacks$c.length === 0) {
4210
4257
  const client = getActiveClient();
4211
4258
  const filter = async (payload) => {
4212
4259
  const data = await prepareChannelPayload(payload);
@@ -4226,53 +4273,53 @@ const onChannelDeleted = (callback) => {
4226
4273
  }
4227
4274
  });
4228
4275
  ingestInCache(data);
4229
- callbacks$a.forEach(cb => cb(data.channels[0]));
4276
+ callbacks$c.forEach(cb => cb(data.channels[0]));
4230
4277
  };
4231
- mainDisposer$a = createEventSubscriber(client, 'onChannelDeleted', 'channel.deleted', filter);
4278
+ mainDisposer$c = createEventSubscriber(client, 'onChannelDeleted', 'channel.deleted', filter);
4232
4279
  }
4233
- callbacks$a.push(callback);
4234
- return () => dispose$a(callback);
4280
+ callbacks$c.push(callback);
4281
+ return () => dispose$c(callback);
4235
4282
  };
4236
4283
 
4237
- const callbacks$9 = [];
4238
- let mainDisposer$9 = null;
4239
- const dispose$9 = (cb) => {
4240
- const index = callbacks$9.indexOf(cb);
4284
+ const callbacks$b = [];
4285
+ let mainDisposer$b = null;
4286
+ const dispose$b = (cb) => {
4287
+ const index = callbacks$b.indexOf(cb);
4241
4288
  if (index > -1) {
4242
- callbacks$9.splice(index, 1);
4289
+ callbacks$b.splice(index, 1);
4243
4290
  }
4244
- if (callbacks$9.length === 0) {
4245
- mainDisposer$9 === null || mainDisposer$9 === void 0 ? void 0 : mainDisposer$9();
4291
+ if (callbacks$b.length === 0) {
4292
+ mainDisposer$b === null || mainDisposer$b === void 0 ? void 0 : mainDisposer$b();
4246
4293
  }
4247
4294
  };
4248
4295
  const onChannelJoined = (callback) => {
4249
- if (callbacks$9.length === 0) {
4296
+ if (callbacks$b.length === 0) {
4250
4297
  const client = getActiveClient();
4251
4298
  const filter = async (payload) => {
4252
4299
  const preparedPayload = await prepareChannelPayload(payload);
4253
4300
  const { channels, channelUsers } = preparedPayload;
4254
4301
  ingestInCache(preparedPayload);
4255
- callbacks$9.forEach(cb => cb(channels[0], channelUsers[0]));
4302
+ callbacks$b.forEach(cb => cb(channels[0], channelUsers[0]));
4256
4303
  };
4257
- mainDisposer$9 = createEventSubscriber(client, 'onChannelJoined', 'channel.joined', filter);
4304
+ mainDisposer$b = createEventSubscriber(client, 'onChannelJoined', 'channel.joined', filter);
4258
4305
  }
4259
- callbacks$9.push(callback);
4260
- return () => dispose$9(callback);
4306
+ callbacks$b.push(callback);
4307
+ return () => dispose$b(callback);
4261
4308
  };
4262
4309
 
4263
- const callbacks$8 = [];
4264
- let mainDisposer$8 = null;
4265
- const dispose$8 = (cb) => {
4266
- const index = callbacks$8.indexOf(cb);
4310
+ const callbacks$a = [];
4311
+ let mainDisposer$a = null;
4312
+ const dispose$a = (cb) => {
4313
+ const index = callbacks$a.indexOf(cb);
4267
4314
  if (index > -1) {
4268
- callbacks$8.splice(index, 1);
4315
+ callbacks$a.splice(index, 1);
4269
4316
  }
4270
- if (callbacks$8.length === 0) {
4271
- mainDisposer$8 === null || mainDisposer$8 === void 0 ? void 0 : mainDisposer$8();
4317
+ if (callbacks$a.length === 0) {
4318
+ mainDisposer$a === null || mainDisposer$a === void 0 ? void 0 : mainDisposer$a();
4272
4319
  }
4273
4320
  };
4274
4321
  const onChannelLeft = (callback) => {
4275
- if (callbacks$8.length === 0) {
4322
+ if (callbacks$a.length === 0) {
4276
4323
  const client = getActiveClient();
4277
4324
  const filter = async (payload) => {
4278
4325
  const { userId } = getActiveClient();
@@ -4296,27 +4343,27 @@ const onChannelLeft = (callback) => {
4296
4343
  }
4297
4344
  const { channels, channelUsers } = preparedPayload;
4298
4345
  ingestInCache(preparedPayload);
4299
- callbacks$8.forEach(cb => cb(channels[0], channelUsers[0]));
4346
+ callbacks$a.forEach(cb => cb(channels[0], channelUsers[0]));
4300
4347
  };
4301
- mainDisposer$8 = createEventSubscriber(client, 'onChannelLeft', 'channel.left', filter);
4348
+ mainDisposer$a = createEventSubscriber(client, 'onChannelLeft', 'channel.left', filter);
4302
4349
  }
4303
- callbacks$8.push(callback);
4304
- return () => dispose$8(callback);
4350
+ callbacks$a.push(callback);
4351
+ return () => dispose$a(callback);
4305
4352
  };
4306
4353
 
4307
- const callbacks$7 = [];
4308
- let mainDisposer$7 = null;
4309
- const dispose$7 = (cb) => {
4310
- const index = callbacks$7.indexOf(cb);
4354
+ const callbacks$9 = [];
4355
+ let mainDisposer$9 = null;
4356
+ const dispose$9 = (cb) => {
4357
+ const index = callbacks$9.indexOf(cb);
4311
4358
  if (index > -1) {
4312
- callbacks$7.splice(index, 1);
4359
+ callbacks$9.splice(index, 1);
4313
4360
  }
4314
- if (callbacks$7.length === 0) {
4315
- mainDisposer$7 === null || mainDisposer$7 === void 0 ? void 0 : mainDisposer$7();
4361
+ if (callbacks$9.length === 0) {
4362
+ mainDisposer$9 === null || mainDisposer$9 === void 0 ? void 0 : mainDisposer$9();
4316
4363
  }
4317
4364
  };
4318
4365
  const onChannelSetMuted = (callback) => {
4319
- if (callbacks$7.length === 0) {
4366
+ if (callbacks$9.length === 0) {
4320
4367
  const client = getActiveClient();
4321
4368
  const filter = async (payload) => {
4322
4369
  var _a;
@@ -4331,14 +4378,114 @@ const onChannelSetMuted = (callback) => {
4331
4378
  payload.channelId,
4332
4379
  ])) === null || _a === void 0 ? void 0 : _a.data;
4333
4380
  if (channel) {
4334
- callbacks$7.forEach(cb => cb(channel));
4381
+ callbacks$9.forEach(cb => cb(channel));
4335
4382
  }
4336
4383
  };
4337
- mainDisposer$7 = createEventSubscriber(client, 'onChannelMute', 'channel.setMuted', filter);
4384
+ mainDisposer$9 = createEventSubscriber(client, 'onChannelMute', 'channel.setMuted', filter);
4385
+ }
4386
+ callbacks$9.push(callback);
4387
+ return () => dispose$9(callback);
4388
+ };
4389
+
4390
+ const callbacks$8 = [];
4391
+ let mainDisposer$8 = null;
4392
+ const dispose$8 = (cb) => {
4393
+ const index = callbacks$8.indexOf(cb);
4394
+ if (index > -1) {
4395
+ callbacks$8.splice(index, 1);
4396
+ }
4397
+ if (callbacks$8.length === 0) {
4398
+ mainDisposer$8 === null || mainDisposer$8 === void 0 ? void 0 : mainDisposer$8();
4399
+ }
4400
+ };
4401
+ /* begin_public_function
4402
+ id: channel.event.message_pinned
4403
+ */
4404
+ /**
4405
+ * ```js
4406
+ * import { onChannelMessagePinned } from '@amityco/ts-sdk'
4407
+ * const dispose = onChannelMessagePinned(channel => {
4408
+ * // channel.pinnedMessage is the new pin
4409
+ * })
4410
+ * ```
4411
+ *
4412
+ * Fired when a message is pinned in a channel (the `channel.messagePinned` realtime
4413
+ * event). Pinning a different message while one is already pinned emits a single
4414
+ * `messagePinned` carrying the replacement — treat every payload as a full snapshot.
4415
+ *
4416
+ * The updated channel is written to cache before the callback runs, so
4417
+ * `ChannelRepository.getChannel` observers see `channel.pinnedMessage` change.
4418
+ *
4419
+ * @param callback The function to call when the event was fired
4420
+ * @returns an {@link Amity.Unsubscriber} function to run when willing to stop listening
4421
+ *
4422
+ * @category Channel Events
4423
+ */
4424
+ const onChannelMessagePinned = (callback) => {
4425
+ if (callbacks$8.length === 0) {
4426
+ const client = getActiveClient();
4427
+ const filter = (payload) => {
4428
+ var _a;
4429
+ const channel = findCachedChannelForPin(payload);
4430
+ if (!channel)
4431
+ return;
4432
+ const updated = updatePinnedMessageCache(channel, (_a = payload.pinnedMessage) !== null && _a !== void 0 ? _a : null, payload.users);
4433
+ callbacks$8.forEach(cb => cb(updated));
4434
+ };
4435
+ mainDisposer$8 = createEventSubscriber(client, 'onChannelMessagePinned', 'channel.messagePinned', filter);
4436
+ }
4437
+ callbacks$8.push(callback);
4438
+ return () => dispose$8(callback);
4439
+ };
4440
+ /* end_public_function */
4441
+
4442
+ const callbacks$7 = [];
4443
+ let mainDisposer$7 = null;
4444
+ const dispose$7 = (cb) => {
4445
+ const index = callbacks$7.indexOf(cb);
4446
+ if (index > -1) {
4447
+ callbacks$7.splice(index, 1);
4448
+ }
4449
+ if (callbacks$7.length === 0) {
4450
+ mainDisposer$7 === null || mainDisposer$7 === void 0 ? void 0 : mainDisposer$7();
4451
+ }
4452
+ };
4453
+ /* begin_public_function
4454
+ id: channel.event.message_unpinned
4455
+ */
4456
+ /**
4457
+ * ```js
4458
+ * import { onChannelMessageUnpinned } from '@amityco/ts-sdk'
4459
+ * const dispose = onChannelMessageUnpinned(channel => {
4460
+ * // channel.pinnedMessage is now null
4461
+ * })
4462
+ * ```
4463
+ *
4464
+ * Fired when a channel's pinned message is removed (the `channel.messageUnpinned`
4465
+ * realtime event) — either by an explicit unpin or automatically by the server when the
4466
+ * pinned message is deleted or its author is banned from the channel / globally.
4467
+ *
4468
+ * @param callback The function to call when the event was fired
4469
+ * @returns an {@link Amity.Unsubscriber} function to run when willing to stop listening
4470
+ *
4471
+ * @category Channel Events
4472
+ */
4473
+ const onChannelMessageUnpinned = (callback) => {
4474
+ if (callbacks$7.length === 0) {
4475
+ const client = getActiveClient();
4476
+ const filter = (payload) => {
4477
+ const channel = findCachedChannelForPin(payload);
4478
+ if (!channel)
4479
+ return;
4480
+ const updated = updatePinnedMessageCache(channel, null);
4481
+ callbacks$7.forEach(cb => cb(updated));
4482
+ };
4483
+ mainDisposer$7 = createEventSubscriber(client, 'onChannelMessageUnpinned', 'channel.messageUnpinned', filter);
4338
4484
  }
4339
4485
  callbacks$7.push(callback);
4340
4486
  return () => dispose$7(callback);
4341
4487
  };
4488
+ /* end_public_function */
4342
4489
 
4343
4490
  const callbacks$6 = [];
4344
4491
  let mainDisposer$6 = null;
@@ -7734,19 +7881,21 @@ const renewal = () => {
7734
7881
 
7735
7882
  const validateAccessToken = async ({ token, userId }) => {
7736
7883
  const client = getActiveClient();
7737
- // Validate token using sessions API
7738
- await client.http.get('/api/v3/sessions', {
7884
+ // Verify the token and hydrate the caller in a single call.
7885
+ const { data } = await client.http.get('/api/v4/sessions', {
7739
7886
  headers: {
7740
7887
  Authorization: `Bearer ${token.accessToken}`,
7741
7888
  },
7742
7889
  });
7743
- // Get user details
7744
- const { data: { users }, } = await client.http.get(`/api/v3/users/${userId}`, {
7745
- headers: {
7746
- Authorization: `Bearer ${token.accessToken}`,
7747
- },
7748
- });
7749
- const user = users.find((u) => u.userId === userId);
7890
+ const { users, files, userType } = data;
7891
+ const [user] = users;
7892
+ if (userId && (user === null || user === void 0 ? void 0 : user.userId) && userId !== user.userId) {
7893
+ client.log('client/api/validateAccessToken', {
7894
+ message: 'session userId does not match the token userId; using the server value',
7895
+ tokenUserId: userId,
7896
+ sessionUserId: user.userId,
7897
+ });
7898
+ }
7750
7899
  client.http.defaults.headers.common.Authorization = `Bearer ${token.accessToken}`;
7751
7900
  client.http.defaults.metadata = {
7752
7901
  tokenExpiry: token.expiresAt,
@@ -7760,6 +7909,8 @@ const validateAccessToken = async ({ token, userId }) => {
7760
7909
  isUserDeleted: false,
7761
7910
  };
7762
7911
  client.token = token;
7912
+ ingestInCache(prepareUserPayload({ users, files }));
7913
+ setCurrentUserType(userType);
7763
7914
  return user;
7764
7915
  };
7765
7916
 
@@ -7842,14 +7993,6 @@ const loginWithAccessToken = async (accessToken) => {
7842
7993
  setSessionState("notLoggedIn" /* Amity.SessionStates.NOT_LOGGED_IN */);
7843
7994
  throw new ASCError(`User ${userId} has not been found`, 800000 /* Amity.ClientError.UNKNOWN_ERROR */, "error" /* Amity.ErrorLevel.ERROR */);
7844
7995
  }
7845
- if (user.isDeleted) {
7846
- setSessionState("notLoggedIn" /* Amity.SessionStates.NOT_LOGGED_IN */);
7847
- throw new ASCError(`User ${userId} has been deleted`, 800000 /* Amity.ClientError.UNKNOWN_ERROR */, "error" /* Amity.ErrorLevel.ERROR */);
7848
- }
7849
- if (user.isGlobalBanned) {
7850
- setSessionState("notLoggedIn" /* Amity.SessionStates.NOT_LOGGED_IN */);
7851
- throw new ASCError(`User ${userId} is globally banned`, 800000 /* Amity.ClientError.UNKNOWN_ERROR */, "error" /* Amity.ErrorLevel.ERROR */);
7852
- }
7853
7996
  // Set userId and login method flag
7854
7997
  client.userId = user.userId;
7855
7998
  // Set login method flag to 'accessToken' in platform-specific login session
@@ -8648,21 +8791,13 @@ const resumeSession = async (params, sessionHandler, config) => {
8648
8791
  if (user == null) {
8649
8792
  throw new ASCError(`${params.userId} has not been found`, 800000 /* Amity.ClientError.UNKNOWN_ERROR */, "error" /* Amity.ErrorLevel.ERROR */);
8650
8793
  }
8651
- if (user.isDeleted) {
8652
- terminateClient("userDeleted" /* Amity.TokenTerminationReason.USER_DELETED */);
8653
- return false;
8654
- }
8655
- if (user.isGlobalBanned) {
8656
- terminateClient("globalBan" /* Amity.TokenTerminationReason.GLOBAL_BAN */);
8657
- return false;
8658
- }
8659
8794
  client.userId = user.userId;
8660
8795
  client.sessionHandler = sessionHandler;
8661
8796
  /*
8662
8797
  * Cannot push to subscriptions as watcher needs to continue working even if
8663
8798
  * token expires
8664
8799
  */
8665
- unsubWatcher = client.accessTokenExpiryWatcher(sessionHandler);
8800
+ unsubWatcher = client.accessTokenExpiryWatcher();
8666
8801
  setActiveUser(user);
8667
8802
  }
8668
8803
  catch (error) {
@@ -18256,20 +18391,20 @@ const getArchivedChannelIds = async () => {
18256
18391
 
18257
18392
  /**
18258
18393
  * ```js
18259
- * import { onMessageUpdated } from '@amityco/ts-sdk'
18260
- * const dispose = onMessageUpdated(message => {
18394
+ * import { onMessageDeleted } from '@amityco/ts-sdk'
18395
+ * const dispose = onMessageDeleted(message => {
18261
18396
  * // ...
18262
18397
  * })
18263
18398
  * ```
18264
18399
  *
18265
- * Fired when an {@link Amity.Message} has been updated
18400
+ * Fired when an {@link Amity.Message} was deleted
18266
18401
  *
18267
18402
  * @param callback The function to call when the event was fired
18268
18403
  * @returns an {@link Amity.Unsubscriber} function to stop listening
18269
18404
  *
18270
18405
  * @category Message Events
18271
18406
  */
18272
- const onMessageUpdated = (callback) => {
18407
+ const onMessageDeleted = (callback) => {
18273
18408
  const client = getActiveClient();
18274
18409
  const filter = async (rawPayload) => {
18275
18410
  const payload = await prepareMessagePayload(rawPayload);
@@ -18277,30 +18412,48 @@ const onMessageUpdated = (callback) => {
18277
18412
  callback(payload.messages[0]);
18278
18413
  };
18279
18414
  const disposers = [
18280
- createEventSubscriber(client, 'onMessageUpdated', 'message.updated', filter),
18281
- createEventSubscriber(client, 'onMessageUpdated', 'local.message.updated', payload => callback(payload.messages[0])),
18415
+ createEventSubscriber(client, 'message/onMessageDeleted', 'message.deleted', filter),
18416
+ createEventSubscriber(client, 'message/onMessageDeleted', 'local.message.deleted', payload => callback(payload.messages[0])),
18282
18417
  ];
18283
18418
  return () => {
18284
18419
  disposers.forEach(fn => fn());
18285
18420
  };
18286
18421
  };
18287
18422
 
18423
+ /**
18424
+ * Defensive clear of `channel.pinnedMessage` when the pinned message itself is deleted.
18425
+ *
18426
+ * The server also emits `channel.messageUnpinned` in this case, but realtime events are
18427
+ * fire-and-forget and their order is not guaranteed. Clearing on `message.deleted`
18428
+ * (MQTT or local) makes the banner disappear even if the unpin event is lost; the
18429
+ * server's own `messageUnpinned` then becomes a no-op.
18430
+ *
18431
+ * Internal — wired into the `getChannel` live object; not exported publicly.
18432
+ */
18433
+ const onChannelPinnedMessageDeleted = (callback) => onMessageDeleted(message => {
18434
+ var _a;
18435
+ const channel = findCachedChannelByAnyId(message.channelId);
18436
+ if (!channel || ((_a = channel.pinnedMessage) === null || _a === void 0 ? void 0 : _a.messageId) !== message.messageId)
18437
+ return;
18438
+ callback(updatePinnedMessageCache(channel, null));
18439
+ });
18440
+
18288
18441
  /**
18289
18442
  * ```js
18290
- * import { onMessageDeleted } from '@amityco/ts-sdk'
18291
- * const dispose = onMessageDeleted(message => {
18443
+ * import { onMessageUpdated } from '@amityco/ts-sdk'
18444
+ * const dispose = onMessageUpdated(message => {
18292
18445
  * // ...
18293
18446
  * })
18294
18447
  * ```
18295
18448
  *
18296
- * Fired when an {@link Amity.Message} was deleted
18449
+ * Fired when an {@link Amity.Message} has been updated
18297
18450
  *
18298
18451
  * @param callback The function to call when the event was fired
18299
18452
  * @returns an {@link Amity.Unsubscriber} function to stop listening
18300
18453
  *
18301
18454
  * @category Message Events
18302
18455
  */
18303
- const onMessageDeleted = (callback) => {
18456
+ const onMessageUpdated = (callback) => {
18304
18457
  const client = getActiveClient();
18305
18458
  const filter = async (rawPayload) => {
18306
18459
  const payload = await prepareMessagePayload(rawPayload);
@@ -18308,8 +18461,8 @@ const onMessageDeleted = (callback) => {
18308
18461
  callback(payload.messages[0]);
18309
18462
  };
18310
18463
  const disposers = [
18311
- createEventSubscriber(client, 'message/onMessageDeleted', 'message.deleted', filter),
18312
- createEventSubscriber(client, 'message/onMessageDeleted', 'local.message.deleted', payload => callback(payload.messages[0])),
18464
+ createEventSubscriber(client, 'onMessageUpdated', 'message.updated', filter),
18465
+ createEventSubscriber(client, 'onMessageUpdated', 'local.message.updated', payload => callback(payload.messages[0])),
18313
18466
  ];
18314
18467
  return () => {
18315
18468
  disposers.forEach(fn => fn());
@@ -18890,6 +19043,132 @@ softDeleteMessage.optimistically = (messageId) => {
18890
19043
  };
18891
19044
  /* end_public_function */
18892
19045
 
19046
+ /**
19047
+ * Fire-and-forget refresh of `channelUsers[...].permissions` for the channel a
19048
+ * message belongs to. Used by `pinMessage` / `unpinMessage` on `403` so the next
19049
+ * `hasPermission(PIN_MESSAGE).channel(channelId)` reflects a revoked role
19050
+ * ([`pinMessage` REQ-010](../../@types/../..) / [`unpinMessage` REQ-008](../../@types/../..)).
19051
+ *
19052
+ * The API only receives a `messageId`, so the channel is resolved through the
19053
+ * local cache: first the message row, then any cached channel whose current pin
19054
+ * is that message. When nothing matches the refresh is skipped — the next
19055
+ * channel read picks up the fresh permissions anyway.
19056
+ */
19057
+ const refreshChannelPermissionsForMessage = (messageId) => {
19058
+ var _a, _b, _c;
19059
+ const cachedMessage = (_a = getMessage$1.locally(messageId)) === null || _a === void 0 ? void 0 : _a.data;
19060
+ let channelId = cachedMessage === null || cachedMessage === void 0 ? void 0 : cachedMessage.channelId;
19061
+ if (!channelId) {
19062
+ channelId = (_c = (_b = queryCache(['channel', 'get'])) === null || _b === void 0 ? void 0 : _b.find(({ data }) => { var _a; return ((_a = data.pinnedMessage) === null || _a === void 0 ? void 0 : _a.messageId) === messageId; })) === null || _c === void 0 ? void 0 : _c.data.channelId;
19063
+ }
19064
+ if (!channelId)
19065
+ return;
19066
+ getChannel$1(channelId).catch(() => {
19067
+ /* silent per spec; UIKit renders no error toast */
19068
+ });
19069
+ };
19070
+
19071
+ /* begin_public_function
19072
+ id: message.pin
19073
+ */
19074
+ /**
19075
+ * ```js
19076
+ * import { MessageRepository } from '@amityco/ts-sdk'
19077
+ * const channel = await MessageRepository.pinMessage(messageId)
19078
+ * console.log(channel.pinnedMessage)
19079
+ * ```
19080
+ *
19081
+ * Pins a {@link Amity.Message} in its livestream (`live`) channel. A channel holds at
19082
+ * most one pinned message: pinning a different message replaces the current pin in a
19083
+ * single step — no unpin is needed first. Pinning the message that is already pinned is
19084
+ * rejected by the server (400).
19085
+ *
19086
+ * The caller must hold the `PIN_MESSAGE` permission in the channel (or be an admin with
19087
+ * `ModerateChannel`). The server also rejects pinning a deleted message, a message whose
19088
+ * author is banned from the channel or globally banned, and pinning in any channel type
19089
+ * other than `live`. On any error the pin state is left unchanged.
19090
+ *
19091
+ * The response is the affected channel; it is ingested into cache and fires
19092
+ * `local.channel.updated`, so `ChannelRepository.getChannel` observers update without
19093
+ * waiting for the `channel.messagePinned` realtime event.
19094
+ *
19095
+ * @param messageId the **internal** ID of the {@link Amity.Message} to pin
19096
+ * @returns the updated {@link Amity.Channel}, with `pinnedMessage` set
19097
+ *
19098
+ * @category Message API
19099
+ * @async
19100
+ */
19101
+ const pinMessage = async (messageId) => {
19102
+ const client = getActiveClient();
19103
+ client.log('message/pinMessage', messageId);
19104
+ let payload;
19105
+ try {
19106
+ ({ data: payload } = await client.http.post(`/api/v5/messages/${encodeURIComponent(messageId)}/pin`));
19107
+ }
19108
+ catch (error) {
19109
+ if ((error === null || error === void 0 ? void 0 : error.code) === 400301 /* Amity.ServerError.PERMISSION_DENIED */) {
19110
+ refreshChannelPermissionsForMessage(messageId);
19111
+ }
19112
+ throw error;
19113
+ }
19114
+ const data = await prepareChannelPayload(payload);
19115
+ if (client.cache)
19116
+ ingestInCache(data);
19117
+ fireEvent('local.channel.updated', data);
19118
+ return constructChannelObject(data.channels[0]);
19119
+ };
19120
+ /* end_public_function */
19121
+
19122
+ /* begin_public_function
19123
+ id: message.unpin
19124
+ */
19125
+ /**
19126
+ * ```js
19127
+ * import { MessageRepository } from '@amityco/ts-sdk'
19128
+ * const channel = await MessageRepository.unpinMessage(messageId)
19129
+ * console.log(channel.pinnedMessage) // null
19130
+ * ```
19131
+ *
19132
+ * Removes the pin from a {@link Amity.Message}. `messageId` must be the message that is
19133
+ * **currently** pinned in its channel; otherwise the server answers 400 — this is
19134
+ * deliberate, so a stale client cannot clear a pin that someone else has since replaced.
19135
+ * On that error, re-read the channel (or rely on the `channel.messagePinned` event) to
19136
+ * get the current pin.
19137
+ *
19138
+ * The caller must hold the `PIN_MESSAGE` permission in the channel (or be an admin with
19139
+ * `ModerateChannel`). Unpinning is allowed regardless of channel type and stream state.
19140
+ *
19141
+ * The response is the affected channel; it is ingested into cache and fires
19142
+ * `local.channel.updated`, so `ChannelRepository.getChannel` observers update without
19143
+ * waiting for the `channel.messageUnpinned` realtime event.
19144
+ *
19145
+ * @param messageId the **internal** ID of the currently pinned {@link Amity.Message}
19146
+ * @returns the updated {@link Amity.Channel}, with `pinnedMessage` cleared
19147
+ *
19148
+ * @category Message API
19149
+ * @async
19150
+ */
19151
+ const unpinMessage = async (messageId) => {
19152
+ const client = getActiveClient();
19153
+ client.log('message/unpinMessage', messageId);
19154
+ let payload;
19155
+ try {
19156
+ ({ data: payload } = await client.http.delete(`/api/v5/messages/${encodeURIComponent(messageId)}/pin`));
19157
+ }
19158
+ catch (error) {
19159
+ if ((error === null || error === void 0 ? void 0 : error.code) === 400301 /* Amity.ServerError.PERMISSION_DENIED */) {
19160
+ refreshChannelPermissionsForMessage(messageId);
19161
+ }
19162
+ throw error;
19163
+ }
19164
+ const data = await prepareChannelPayload(payload);
19165
+ if (client.cache)
19166
+ ingestInCache(data);
19167
+ fireEvent('local.channel.updated', data);
19168
+ return constructChannelObject(data.channels[0]);
19169
+ };
19170
+ /* end_public_function */
19171
+
18893
19172
  /**
18894
19173
  * ```js
18895
19174
  * import { MessageRepository } from '@amityco/ts-sdk'
@@ -19793,6 +20072,8 @@ var index$n = /*#__PURE__*/Object.freeze({
19793
20072
  editMessage: editMessage,
19794
20073
  deleteMessage: deleteMessage,
19795
20074
  softDeleteMessage: softDeleteMessage,
20075
+ pinMessage: pinMessage,
20076
+ unpinMessage: unpinMessage,
19796
20077
  markAsDelivered: markAsDelivered,
19797
20078
  getReadUsers: getReadUsers,
19798
20079
  getDeliveredUsers: getDeliveredUsers,
@@ -20430,6 +20711,9 @@ const getChannel = (channelId, callback) => {
20430
20711
  onChannelMemberBanned,
20431
20712
  onChannelMemberUnbanned,
20432
20713
  onChannelSetMuted,
20714
+ onChannelMessagePinned,
20715
+ onChannelMessageUnpinned,
20716
+ onChannelPinnedMessageDeleted,
20433
20717
  convertEventPayload(onChannelMarkerFetched, 'entityId', 'channel'),
20434
20718
  convertEventPayload(onChannelMarkerUpdated, 'entityId', 'channel'),
20435
20719
  convertEventPayload((callback) => {
@@ -22526,6 +22810,8 @@ var index$j = /*#__PURE__*/Object.freeze({
22526
22810
  onChannelJoined: onChannelJoined,
22527
22811
  onChannelLeft: onChannelLeft,
22528
22812
  onChannelSetMuted: onChannelSetMuted,
22813
+ onChannelMessagePinned: onChannelMessagePinned,
22814
+ onChannelMessageUnpinned: onChannelMessageUnpinned,
22529
22815
  onChannelMemberAdded: onChannelMemberAdded,
22530
22816
  onChannelMemberRemoved: onChannelMemberRemoved,
22531
22817
  onChannelMemberBanned: onChannelMemberBanned,
@@ -22543,7 +22829,10 @@ var index$j = /*#__PURE__*/Object.freeze({
22543
22829
  isUnreadCountSupport: isUnreadCountSupport,
22544
22830
  convertFromRaw: convertFromRaw,
22545
22831
  preUpdateChannelCache: preUpdateChannelCache,
22546
- prepareChannelPayload: prepareChannelPayload
22832
+ prepareChannelPayload: prepareChannelPayload,
22833
+ findCachedChannelByAnyId: findCachedChannelByAnyId,
22834
+ findCachedChannelForPin: findCachedChannelForPin,
22835
+ updatePinnedMessageCache: updatePinnedMessageCache
22547
22836
  });
22548
22837
 
22549
22838
  const saveCommunityUsers = (communities, communityUsers) => {