Skip to content

Commit 9d8992d

Browse files
authored
feat: middleware handler API improvement (#1523)
1 parent 3aab325 commit 9d8992d

40 files changed

Lines changed: 2430 additions & 2258 deletions

src/messageComposer/configuration/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ export type AttachmentManagerConfig = {
3434
maxNumberOfFilesPerMessage: number;
3535
/**
3636
* Array of one or more file types, or unique file type specifiers (https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Attributes/accept#unique_file_type_specifiers),
37-
* describing which file types to allow to select when uploading files.
37+
* describing which file types are allowed to be selected when uploading files.
3838
*/
3939
acceptedFiles: string[];
4040
// todo: refactor this. We want a pipeline where it would be possible to customize the preparation, upload, and post-upload steps.

src/messageComposer/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,4 @@ export * from './middleware';
99
export * from './pollComposer';
1010
export * from './textComposer';
1111
export * from './types';
12+
export type { CustomTextComposerSuggestion } from './types.custom';

src/messageComposer/linkPreviewsManager.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ export interface ILinkPreviewsManager {
1818
}
1919

2020
export enum LinkPreviewStatus {
21-
/** Link preview has been dismissed using MessageInputContextValue.dismissLinkPreview **/
21+
/** Link preview has been dismissed using **/
2222
DISMISSED = 'dismissed',
2323
/** Link preview could not be loaded, the enrichment request has failed. **/
2424
FAILED = 'failed',

src/messageComposer/messageComposer.ts

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -563,8 +563,9 @@ export class MessageComposer {
563563
compose = async (): Promise<MessageComposerMiddlewareValue['state'] | undefined> => {
564564
const created_at = this.editedMessage?.created_at ?? new Date();
565565
const text = '';
566-
const result = await this.compositionMiddlewareExecutor.execute('compose', {
567-
state: {
566+
const result = await this.compositionMiddlewareExecutor.execute({
567+
eventName: 'compose',
568+
initialValue: {
568569
message: {
569570
id: this.id,
570571
parent_id: this.threadId ?? undefined,
@@ -594,14 +595,12 @@ export class MessageComposer {
594595
};
595596

596597
composeDraft = async () => {
597-
const { state, status } = await this.draftCompositionMiddlewareExecutor.execute(
598-
'compose',
599-
{
600-
state: {
601-
draft: { id: this.id, parent_id: this.threadId ?? undefined, text: '' },
602-
},
598+
const { state, status } = await this.draftCompositionMiddlewareExecutor.execute({
599+
eventName: 'compose',
600+
initialValue: {
601+
draft: { id: this.id, parent_id: this.threadId ?? undefined, text: '' },
603602
},
604-
);
603+
});
605604
if (status === 'discard') return;
606605
return state;
607606
};

src/messageComposer/middleware/messageComposer/MessageComposerMiddlewareExecutor.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import {
2222
import { createCompositionDataCleanupMiddleware } from './cleanData';
2323
import type {
2424
MessageComposerMiddlewareExecutorOptions,
25-
MessageComposerMiddlewareValueState,
25+
MessageComposerMiddlewareState,
2626
MessageDraftComposerMiddlewareExecutorOptions,
2727
MessageDraftComposerMiddlewareValueState,
2828
} from './types';
@@ -31,7 +31,10 @@ import {
3131
createDraftCustomDataCompositionMiddleware,
3232
} from './customData';
3333

34-
export class MessageComposerMiddlewareExecutor extends MiddlewareExecutor<MessageComposerMiddlewareValueState> {
34+
export class MessageComposerMiddlewareExecutor extends MiddlewareExecutor<
35+
MessageComposerMiddlewareState,
36+
'compose'
37+
> {
3538
constructor({ composer }: MessageComposerMiddlewareExecutorOptions) {
3639
super();
3740
// todo: document how to add custom data to a composed message using middleware
@@ -48,7 +51,10 @@ export class MessageComposerMiddlewareExecutor extends MiddlewareExecutor<Messag
4851
}
4952
}
5053

51-
export class MessageDraftComposerMiddlewareExecutor extends MiddlewareExecutor<MessageDraftComposerMiddlewareValueState> {
54+
export class MessageDraftComposerMiddlewareExecutor extends MiddlewareExecutor<
55+
MessageDraftComposerMiddlewareValueState,
56+
'compose'
57+
> {
5258
constructor({ composer }: MessageDraftComposerMiddlewareExecutorOptions) {
5359
super();
5460
// todo: document how to add custom data to a composed message using middleware

src/messageComposer/middleware/messageComposer/attachments.ts

Lines changed: 56 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@ import type { Attachment } from '../../../types';
33
import type { MessageComposer } from '../../messageComposer';
44
import type { LocalAttachment } from '../../types';
55
import type {
6-
MessageComposerMiddlewareValueState,
6+
MessageComposerMiddlewareState,
7+
MessageCompositionMiddleware,
78
MessageDraftComposerMiddlewareValueState,
9+
MessageDraftCompositionMiddleware,
810
} from './types';
911

1012
const localAttachmentToAttachment = (localAttachment: LocalAttachment) => {
@@ -13,77 +15,80 @@ const localAttachmentToAttachment = (localAttachment: LocalAttachment) => {
1315
return attachment as Attachment;
1416
};
1517

16-
export const createAttachmentsCompositionMiddleware = (composer: MessageComposer) => ({
18+
export const createAttachmentsCompositionMiddleware = (
19+
composer: MessageComposer,
20+
): MessageCompositionMiddleware => ({
1721
id: 'stream-io/message-composer-middleware/attachments',
18-
compose: ({
19-
input,
20-
nextHandler,
21-
}: MiddlewareHandlerParams<MessageComposerMiddlewareValueState>) => {
22-
const { attachmentManager } = composer;
23-
if (!attachmentManager) return nextHandler(input);
22+
handlers: {
23+
compose: ({
24+
state,
25+
next,
26+
discard,
27+
forward,
28+
}: MiddlewareHandlerParams<MessageComposerMiddlewareState>) => {
29+
const { attachmentManager } = composer;
30+
if (!attachmentManager) return forward();
2431

25-
if (attachmentManager.uploadsInProgressCount > 0) {
26-
composer.client.notifications.addWarning({
27-
message: 'Wait until all attachments have uploaded',
28-
origin: {
29-
emitter: 'MessageComposer',
30-
context: { composer },
31-
},
32-
});
33-
return nextHandler({ ...input, status: 'discard' });
34-
}
32+
if (attachmentManager.uploadsInProgressCount > 0) {
33+
composer.client.notifications.addWarning({
34+
message: 'Wait until all attachments have uploaded',
35+
origin: {
36+
emitter: 'MessageComposer',
37+
context: { composer },
38+
},
39+
});
40+
return discard();
41+
}
3542

36-
const attachments = (input.state.message.attachments ?? []).concat(
37-
attachmentManager.successfulUploads.map(localAttachmentToAttachment),
38-
);
43+
const attachments = (state.message.attachments ?? []).concat(
44+
attachmentManager.successfulUploads.map(localAttachmentToAttachment),
45+
);
3946

40-
// prevent introducing attachments array into the payload sent to the server
41-
if (!attachments.length) return nextHandler(input);
47+
// prevent introducing attachments array into the payload sent to the server
48+
if (!attachments.length) return forward();
4249

43-
return nextHandler({
44-
...input,
45-
state: {
46-
...input.state,
50+
return next({
51+
...state,
4752
localMessage: {
48-
...input.state.localMessage,
53+
...state.localMessage,
4954
attachments,
5055
},
5156
message: {
52-
...input.state.message,
57+
...state.message,
5358
attachments,
5459
},
55-
},
56-
});
60+
});
61+
},
5762
},
5863
});
5964

6065
export const createDraftAttachmentsCompositionMiddleware = (
6166
composer: MessageComposer,
62-
) => ({
67+
): MessageDraftCompositionMiddleware => ({
6368
id: 'stream-io/message-composer-middleware/draft-attachments',
64-
compose: ({
65-
input,
66-
nextHandler,
67-
}: MiddlewareHandlerParams<MessageDraftComposerMiddlewareValueState>) => {
68-
const { attachmentManager } = composer;
69-
if (!attachmentManager) return nextHandler(input);
69+
handlers: {
70+
compose: ({
71+
state,
72+
next,
73+
forward,
74+
}: MiddlewareHandlerParams<MessageDraftComposerMiddlewareValueState>) => {
75+
const { attachmentManager } = composer;
76+
if (!attachmentManager) return forward();
7077

71-
const successfulUploads = attachmentManager.successfulUploads;
72-
const attachments = successfulUploads.length
73-
? (input.state.draft.attachments ?? []).concat(
74-
successfulUploads.map(localAttachmentToAttachment),
75-
)
76-
: undefined;
78+
const successfulUploads = attachmentManager.successfulUploads;
79+
const attachments = successfulUploads.length
80+
? (state.draft.attachments ?? []).concat(
81+
successfulUploads.map(localAttachmentToAttachment),
82+
)
83+
: undefined;
7784

78-
return nextHandler({
79-
...input,
80-
state: {
81-
...input.state,
85+
return next({
86+
...state,
8287
draft: {
83-
...input.state.draft,
88+
...state.draft,
8489
attachments,
8590
},
86-
},
87-
});
91+
});
92+
},
8893
},
8994
});
Lines changed: 27 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,46 @@
11
import type { MiddlewareHandlerParams } from '../../../middleware';
22
import { formatMessage, toUpdatedMessagePayload } from '../../../utils';
33
import type { MessageComposer } from '../../messageComposer';
4-
import type { MessageComposerMiddlewareValueState } from './types';
4+
import type {
5+
MessageComposerMiddlewareState,
6+
MessageCompositionMiddleware,
7+
} from './types';
58

6-
export const createCompositionDataCleanupMiddleware = (composer: MessageComposer) => ({
9+
export const createCompositionDataCleanupMiddleware = (
10+
composer: MessageComposer,
11+
): MessageCompositionMiddleware => ({
712
id: 'stream-io/message-composer-middleware/data-cleanup',
8-
compose: ({
9-
input,
10-
nextHandler,
11-
}: MiddlewareHandlerParams<MessageComposerMiddlewareValueState>) => {
12-
const common = {
13-
type: composer.editedMessage?.type ?? 'regular',
14-
};
13+
handlers: {
14+
compose: ({
15+
state,
16+
next,
17+
}: MiddlewareHandlerParams<MessageComposerMiddlewareState>) => {
18+
const common = {
19+
type: composer.editedMessage?.type ?? 'regular',
20+
};
1521

16-
const editedMessagePayloadToBeSent = composer.editedMessage
17-
? toUpdatedMessagePayload(composer.editedMessage)
18-
: undefined;
22+
const editedMessagePayloadToBeSent = composer.editedMessage
23+
? toUpdatedMessagePayload(composer.editedMessage)
24+
: undefined;
1925

20-
return nextHandler({
21-
...input,
22-
state: {
23-
...input.state,
26+
return next({
27+
...state,
2428
localMessage: formatMessage({
2529
...composer.editedMessage,
26-
...input.state.localMessage,
30+
...state.localMessage,
2731
...common,
2832
user: composer.client.user,
2933
}),
3034
message: {
3135
...editedMessagePayloadToBeSent,
32-
...input.state.message,
36+
...state.message,
3337
...common,
3438
},
3539
sendOptions:
36-
composer.editedMessage && input.state.sendOptions?.skip_enrich_url
37-
? { skip_enrich_url: input.state.sendOptions?.skip_enrich_url }
38-
: input.state.sendOptions,
39-
},
40-
});
40+
composer.editedMessage && state.sendOptions?.skip_enrich_url
41+
? { skip_enrich_url: state.sendOptions?.skip_enrich_url }
42+
: state.sendOptions,
43+
});
44+
},
4145
},
4246
});

0 commit comments

Comments
 (0)