メインコンテンツまでスキップ
バージョン: 0.13.0 (Previous)

🛣️ チャットルート

チャットルートは Express ミドルウェアではなく、SDK のコンポーザーです。以下の一覧と詳細では、公開される HTTP および WebSocket エンドポイントの正確な契約を説明します。

一覧

ルートメソッド / プロトコルパススキーマバリデーター成功ステータス
createChatChannelRoutePOST / HTTP/channelscreateChatChannelSchemaisAuthenticated(), some( checkIdentityType(['admin']), isSelf(['params', 'requestBody', 'ownerId']) )201
findChatChannelsRouteGET / HTTP/channelsfindChatChannelsSchemaisAuthenticated(), some( checkIdentityType(['admin']), isSelf(['params', 'requestQuery', 'ownerId']) )200
getChatChannelRouteGET / HTTP/channels/:channelIdgetChatChannelSchemaisAuthenticated(), some( checkIdentityType(['admin']), ownsChannel(['params', 'requestParams', 'channelId']), hasSubscription(['params', 'requestParams', 'channelId']) )200
updateChatChannelRoutePATCH / HTTP/channels/:channelIdupdateChatChannelSchemaisAuthenticated(), some( checkIdentityType(['admin']), ownsChannel(['params', 'requestParams', 'channelId']) )200
deleteChatChannelRouteDELETE / HTTP/channels/:channelIddeleteChatChannelSchemaisAuthenticated(), some( checkIdentityType(['admin']), ownsChannel(['params', 'requestParams', 'channelId']) )204
getChannelMessagesRouteGET / HTTP/channels/:channelId/messagesgetChannelMessagesSchemaisAuthenticated(), channelExists(['params', 'requestParams', 'channelId']), hasSubscription(['params', 'requestParams', 'channelId'])200
getChatChannelIconUploadUrlRouteGET / HTTP/channels/:channelId/icon-upload-urlgetSignedImageUploadUrlSchemaisAuthenticated(), some( checkIdentityType(['admin']), ownsChannel(['params', 'requestParams', 'channelId']) )200
createChatMessageRoutePOST / HTTP/messagescreateChatMessageSchemaisAuthenticated(), isSelf(['params', 'requestBody', 'senderId']), hasSubscription(['params', 'requestBody', 'channelId'])201
findChatMessagesRouteGET / HTTP/messagesfindChatMessagesSchemaisAuthenticated(), some( checkIdentityType(['admin']), hasSubscription(['params', 'requestQuery', 'channelId']), isSelf(['params', 'requestQuery', 'senderId']) )200
getChatMessageRouteGET / HTTP/messages/:messageIdgetChatMessageSchemaisAuthenticated(), some( checkIdentityType(['admin']), ownsMessage(['params', 'requestParams', 'messageId']) )200
updateChatMessageRoutePATCH / HTTP/messages/:messageIdupdateChatMessageSchemaisAuthenticated(), ownsMessage(['params', 'requestParams', 'messageId'])200
deleteChatMessageRouteDELETE / HTTP/messages/:messageIddeleteChatMessageSchemaisAuthenticated(), some( checkIdentityType(['admin']), ownsMessage(['params', 'requestParams', 'messageId']) )204
getChatMessageAttachmentUploadUrlRouteGET / HTTP/messages/:messageId/attachment-upload-urlgetSignedFileUploadUrlSchemaisAuthenticated(), ownsMessage(['params', 'requestParams', 'messageId'])200
streamChatMessagesRouteWS / WebSocket/messages/listenstreamChatMessagesSchemaなしメッセージストリーム
createChatMessageAttachmentRoutePOST / HTTP/messages/:messageId/attachmentscreateChatMessageAttachmentSchemaisAuthenticated(), ownsMessage(['params', 'requestParams', 'messageId'])201
deleteChatMessageAttachmentRouteDELETE / HTTP/messages/:messageId/attachments/:attachmentIddeleteChatMessageAttachmentSchemaisAuthenticated(), some( checkIdentityType(['admin']), ownsMessage(['params', 'requestParams', 'messageId']) )204
createChatMessageTemplateRoutePOST / HTTP/message-templatescreateChatMessageTemplateSchemaisAuthenticated(), some( checkIdentityType(['admin']), hasOrgRole( ['owner', 'admin'], ['params', 'requestBody', 'organizationId'] ) )201
getChatMessageTemplateRouteGET / HTTP/message-templates/:messageTemplateIdgetChatMessageTemplateSchemaisAuthenticated(), some( checkIdentityType(['admin']), hasOrganizationAccessToMessageTemplate( ['owner', 'admin'], ['params', 'requestParams', 'messageTemplateId'] ) )200
updateChatMessageTemplateRoutePATCH / HTTP/message-templates/:messageTemplateIdupdateChatMessageTemplateSchemaisAuthenticated(), some( checkIdentityType(['admin']), hasOrganizationAccessToMessageTemplate( ['owner', 'admin'], ['params', 'requestParams', 'messageTemplateId'] ) )200
deleteChatMessageTemplateRouteDELETE / HTTP/message-templates/:messageTemplateIddeleteChatMessageTemplateSchemaisAuthenticated(), some( checkIdentityType(['admin']), hasOrganizationAccessToMessageTemplate( ['owner', 'admin'], ['params', 'requestParams', 'messageTemplateId'] ) )204
findChatMessageTemplatesRouteGET / HTTP/message-templatesfindChatMessageTemplatesSchemaisAuthenticated(), checkIdentityType(['admin'])200
findChatMessageTemplatesForOrganizationRouteGET / HTTP/organizations/:organizationId/message-templatesfindChatMessageTemplatesForOrganizationSchemaisAuthenticated(), hasOrgRole( ['owner', 'admin'], ['params', 'requestParams', 'organizationId'] )200
upsertChatChannelReadStateRoutePUT / HTTP/channels/:channelId/read-stateupsertChatChannelReadStateSchemaisAuthenticated(), channelExists(['params', 'requestParams', 'channelId']), hasSubscription(['params', 'requestParams', 'channelId']), isSelf(['params', 'requestBody', 'identityId'])204
createChatSubscriptionRoutePOST / HTTP/subscriptionscreateChatSubscriptionSchemaisAuthenticated(), some( checkIdentityType(['admin']), isSelf(['params', 'requestBody', 'subscribedId']) )201
findChatSubscriptionsRouteGET / HTTP/subscriptionsfindChatSubscriptionsSchemaisAuthenticated(), some( checkIdentityType(['admin']), hasSubscription(['params', 'requestQuery', 'channelId']), ownsChannel(['params', 'requestQuery', 'channelId']), isSelf(['params', 'requestQuery', 'subscribedId']) )200
getChatSubscriptionRouteGET / HTTP/subscriptions/:subscriptionIdgetChatSubscriptionSchemaisAuthenticated(), some( checkIdentityType(['admin']), ownsSubscription(['params', 'requestParams', 'subscriptionId']) )200
deleteChatSubscriptionRouteDELETE / HTTP/subscriptions/:subscriptionIddeleteChatSubscriptionSchemaisAuthenticated(), some( checkIdentityType(['admin']), ownsSubscription(['params', 'requestParams', 'subscriptionId']) )204

詳細

createChatChannelRoute

実装

エンドポイント: POST /channels

アクセス: isAuthenticated()some(...)checkIdentityType(...)isSelf(...) は、ここに示したソース順で実行されます。正確な呼び出し: isAuthenticated(), some( checkIdentityType(['admin']), isSelf(['params', 'requestBody', 'ownerId']) ),.

リクエスト: createChatChannelSchemaapplication/json 本文を検証します: 必須: name および ownerId; 省略可能な null 許容アイコン。

パイプライン: createChatChannelgetChatChannelByIdcreateChatChannelTerminator.

成功: レスポンス記述子の data に正規化されたチャンネルを含む 201 を返します。

失敗: 認証および認可の失敗は、ハンドラーパイプラインの前にリンク先のバリデーターに従います。パイプラインの失敗は、リンク先のハンドラー/ブロック契約と共通エラーミドルウェアに従います。このルートは個別のインラインエラーマッピングを追加しません。

完全なソースを表示
export const createChatChannelRoute = withRoute({
handler: compose(
withLogging(createChatChannel),
flatMapAsync(withLogging(getChatChannelById)),
lift(withLogging(createChatChannelTerminator))
),
method: 'POST',
path: '/channels',
validators: [
isAuthenticated(),
some(
checkIdentityType(['admin']),
isSelf(['params', 'requestBody', 'ownerId'])
),
],
});

findChatChannelsRoute

実装

エンドポイント: GET /channels

アクセス: isAuthenticated()some(...)checkIdentityType(...)isSelf(...) は、ここに示したソース順で実行されます。正確な呼び出し: isAuthenticated(), some( checkIdentityType(['admin']), isSelf(['params', 'requestQuery', 'ownerId']) ),.

リクエスト: findChatChannelsSchema はクエリパラメータを検証します: 省略可能: name, ownerId, および共通ページネーションフィールド。

パイプライン: findChatChannelsnormalizeChatChannelsListTerminator.

成功: 正規化されたチャンネルとページネーションメタデータを含む 200 を返します。

失敗: 認証および認可の失敗は、ハンドラーパイプラインの前にリンク先のバリデーターに従います。パイプラインの失敗は、リンク先のハンドラー/ブロック契約と共通エラーミドルウェアに従います。このルートは個別のインラインエラーマッピングを追加しません。

完全なソースを表示
export const findChatChannelsRoute = withRoute({
handler: compose(
withPagination(withLogging(findChatChannels)),
lift(withLogging(normalizeChatChannelsListTerminator))
),
method: 'GET',
path: '/channels',
validators: [
isAuthenticated(),
some(
checkIdentityType(['admin']),
isSelf(['params', 'requestQuery', 'ownerId'])
),
],
});

getChatChannelRoute

実装

エンドポイント: GET /channels/:channelId

アクセス: isAuthenticated()some(...)checkIdentityType(...)ownsChannel(...)hasSubscription(...) は、ここに示したソース順で実行されます。正確な呼び出し: isAuthenticated(), some( checkIdentityType(['admin']), ownsChannel(['params', 'requestParams', 'channelId']), hasSubscription(['params', 'requestParams', 'channelId']) ),.

リクエスト: getChatChannelSchema はパスパラメータを検証します: 必須: channelId.

パイプライン: getChatChannelByIdnormalizeChatChannelTerminator.

成功: 正規化されたチャンネルを含む 200 を返します。

失敗: 認証および認可の失敗は、ハンドラーパイプラインの前にリンク先のバリデーターに従います。パイプラインの失敗は、リンク先のハンドラー/ブロック契約と共通エラーミドルウェアに従います。このルートは個別のインラインエラーマッピングを追加しません。

完全なソースを表示
export const getChatChannelRoute = withRoute({
handler: compose(
withLogging(getChatChannelById),
lift(withLogging(normalizeChatChannelTerminator))
),
method: 'GET',
path: '/channels/:channelId',
validators: [
isAuthenticated(),
some(
checkIdentityType(['admin']),
ownsChannel(['params', 'requestParams', 'channelId']),
hasSubscription(['params', 'requestParams', 'channelId'])
),
],
});

updateChatChannelRoute

実装

エンドポイント: PATCH /channels/:channelId

アクセス: isAuthenticated()some(...)checkIdentityType(...)ownsChannel(...) は、ここに示したソース順で実行されます。正確な呼び出し: isAuthenticated(), some( checkIdentityType(['admin']), ownsChannel(['params', 'requestParams', 'channelId']) ),.

リクエスト: updateChatChannelSchema はパスパラメータおよび application/json 本文を検証します: 必須: channelId; 本文では省略可能な name および null 許容の icon.

パイプライン: updateChatChannelgetChatChannelByIdnormalizeChatChannelTerminator.

成功: 更新済みで正規化されたチャンネルを含む 200 を返します。

失敗: 認証および認可の失敗は、ハンドラーパイプラインの前にリンク先のバリデーターに従います。パイプラインの失敗は、リンク先のハンドラー/ブロック契約と共通エラーミドルウェアに従います。このルートは個別のインラインエラーマッピングを追加しません。

完全なソースを表示
export const updateChatChannelRoute = withRoute({
handler: compose(
withLogging(updateChatChannel),
flatMapAsync(withLogging(getChatChannelById)),
lift(withLogging(normalizeChatChannelTerminator))
),
method: 'PATCH',
path: '/channels/:channelId',
validators: [
isAuthenticated(),
some(
checkIdentityType(['admin']),
ownsChannel(['params', 'requestParams', 'channelId'])
),
],
});

deleteChatChannelRoute

実装

エンドポイント: DELETE /channels/:channelId

アクセス: isAuthenticated()some(...)checkIdentityType(...)ownsChannel(...) は、ここに示したソース順で実行されます。正確な呼び出し: isAuthenticated(), some( checkIdentityType(['admin']), ownsChannel(['params', 'requestParams', 'channelId']) ),.

リクエスト: deleteChatChannelSchema はパスパラメータを検証します: 必須: channelId.

パイプライン: deleteChatChanneldeleteChatChannelTerminator.

成功: 空の 204 レスポンス。

失敗: 認証および認可の失敗は、ハンドラーパイプラインの前にリンク先のバリデーターに従います。パイプラインの失敗は、リンク先のハンドラー/ブロック契約と共通エラーミドルウェアに従います。このルートは個別のインラインエラーマッピングを追加しません。

完全なソースを表示
export const deleteChatChannelRoute = withRoute({
handler: compose(
withLogging(deleteChatChannel),
lift(withLogging(deleteChatChannelTerminator))
),
method: 'DELETE',
path: '/channels/:channelId',
validators: [
isAuthenticated(),
some(
checkIdentityType(['admin']),
ownsChannel(['params', 'requestParams', 'channelId'])
),
],
});

getChannelMessagesRoute

実装

エンドポイント: GET /channels/:channelId/messages

アクセス: isAuthenticated()hasSubscription(...)channelExists(...) は、ここに示したソース順で実行されます。正確な呼び出し: isAuthenticated(), channelExists(['params', 'requestParams', 'channelId']), hasSubscription(['params', 'requestParams', 'channelId']),.

リクエスト: getChannelMessagesSchema はパスおよびクエリパラメータを検証します: 必須: channelId および 省略可能な共通ページネーションフィールド。

パイプライン: getChannelMessagesByChannelId → ページネーション → normalizeChatMessages → レスポンスへの射影。

成功: 正規化されたメッセージとページネーションメタデータを含む 200 を返します。

失敗: 認証および認可の失敗は、ハンドラーパイプラインの前にリンク先のバリデーターに従います。このルートは、ソースに示される次のマッピングを使用します: ChatChannelUnknownError500

完全なソースを表示
export const getChannelMessagesRoute = withRoute({
handler: compose(
withPagination(
withLogging(
applyPayloadArgs(
getChannelMessagesByChannelId,
[
['context', 'db', 'chatMessages'],
['params', 'requestParams', 'channelId'],
],
'paginatedMessages'
)
)
),
flatMapAsync(
applyPayloadArgs(
normalizeChatMessages,
[
['context', 'fileStorageDriver'],
['context', 'data', 'paginatedMessages', 'data'],
],
'normalizedMessages'
)
),
flatMapAsync(
applyPayloadArgs(
applySpec({ data: nthArg(0), metadata: { pagination: nthArg(1) } }),
[
['context', 'data', 'normalizedMessages'],
['context', 'data', 'paginatedMessages', 'metadata'],
],
'normalizedMessagesWithPagination'
)
),
lift(
orThrow(
[[ChatChannelUnknownError, 500]],
[['context', 'data', 'normalizedMessagesWithPagination'], 200]
)
)
),
method: 'GET',
path: '/channels/:channelId/messages',
validators: [
isAuthenticated(),
channelExists(['params', 'requestParams', 'channelId']),
hasSubscription(['params', 'requestParams', 'channelId']),
],
});

getChatChannelIconUploadUrlRoute

実装

エンドポイント: GET /channels/:channelId/icon-upload-url

アクセス: isAuthenticated()some(...)checkIdentityType(...)ownsChannel(...) は、ここに示したソース順で実行されます。正確な呼び出し: isAuthenticated(), some( checkIdentityType(['admin']), ownsChannel(['params', 'requestParams', 'channelId']) ),.

リクエスト: 共有の getSignedImageUploadUrlSchema はパス channelId と署名付き画像アップロードリクエストの契約を検証します。

パイプライン: generateChatChannelIconUploadUrlorThrow.

成功: { objectId, url } を含む 200 を返します。

失敗: 認証および認可の失敗は、ハンドラーパイプラインの前にリンク先のバリデーターに従います。このルートは、ソースに示される次のマッピングを使用します: FileStorageServiceError500, ChatChannelUnknownError500

完全なソースを表示
export const getChatChannelIconUploadUrlRoute = withRoute({
handler: compose(
withLogging(
applyPayloadArgs(
generateChatChannelIconUploadUrl,
[
['context', 'fileStorageDriver'],
['params', 'requestQuery', 'contentType'],
['params', 'requestQuery', 'contentLength'],
],
'iconUploadUrlResult'
)
),
lift(
orThrow(
[
[FileStorageServiceError, 500],
[ChatChannelUnknownError, 500],
],
[['context', 'data', 'iconUploadUrlResult'], 200]
)
)
),
method: 'GET',
path: '/channels/:channelId/icon-upload-url',
validators: [
isAuthenticated(),
some(
checkIdentityType(['admin']),
ownsChannel(['params', 'requestParams', 'channelId'])
),
],
});

createChatMessageRoute

実装

エンドポイント: POST /messages

アクセス: isAuthenticated()isSelf(...)hasSubscription(...) は、ここに示したソース順で実行されます。正確な呼び出し: isAuthenticated(), isSelf(['params', 'requestBody', 'senderId']), hasSubscription(['params', 'requestBody', 'channelId']),.

リクエスト: createChatMessageSchemaapplication/json 本文を検証します: 必須: content, senderId, および channelId。省略可能: title.

パイプライン: createChatMessagegetChatMessageByIdnormalizeChatMessageorThrow.

成功: 201正規化されたメッセージと署名付き添付ファイル URL を含む 201 を返します。

失敗: 認証および認可の失敗は、ハンドラーパイプラインの前にリンク先のバリデーターに従います。このルートは、ソースに示される次のマッピングを使用します: ChatMessageNotFoundBlockError404, FileStorageServiceError500, ChatMessageUnexpectedDBError500

完全なソースを表示
export const createChatMessageRoute = withRoute({
handler: compose(
withLogging(
applyPayloadArgs(
createChatMessage,
[
['context', 'db', 'chatMessages'],
['params', 'requestBody'],
],
'messageId'
)
),

flatMapAsync(
applyPayloadArgs(
getChatMessageByIdBlock,
[
['context', 'db', 'chatMessages'],
['context', 'data', 'messageId'],
],
'message'
)
),

flatMapAsync(
applyPayloadArgs(
normalizeChatMessage,
[
['context', 'fileStorageDriver'],
['context', 'data', 'message'],
],
'normalizedMessage'
)
),

lift(
orThrow(
[
[ChatMessageNotFoundBlockError, 404],
[FileStorageServiceError, 500],
[ChatMessageUnexpectedDBError, 500],
],
[['context', 'data', 'normalizedMessage'], 201]
)
)
),
method: 'POST',
path: '/messages',
validators: [
isAuthenticated(),
isSelf(['params', 'requestBody', 'senderId']),
hasSubscription(['params', 'requestBody', 'channelId']),
],
});

findChatMessagesRoute

実装

エンドポイント: GET /messages

アクセス: isAuthenticated()some(...)checkIdentityType(...)isSelf(...)hasSubscription(...) は、ここに示したソース順で実行されます。正確な呼び出し: isAuthenticated(), some( checkIdentityType(['admin']), hasSubscription(['params', 'requestQuery', 'channelId']), isSelf(['params', 'requestQuery', 'senderId']) ),.

リクエスト: findChatMessagesSchema はクエリパラメータを検証します: 必須: channelId; 省略可能なメッセージフィルターおよびページネーション。

パイプライン: findChatMessages.

成功: 正規化されたメッセージとページネーションメタデータを含む 200 を返します。

失敗: 認証および認可の失敗は、ハンドラーパイプラインの前にリンク先のバリデーターに従います。このルートは、ソースに示される次のマッピングを使用します: ChatMessageNotFoundBlockError404, FileStorageServiceError500, ChatMessageBlockError500

完全なソースを表示
export const findChatMessagesRoute = withRoute({
handler: compose(
withPagination(
withLogging(
applyPayloadArgs(
findChatMessages,
[
['context', 'db', 'chatMessages'],
['params', 'requestQuery'],
],
'paginatedMessages'
)
)
),
flatMapAsync(
applyPayloadArgs(
normalizeChatMessages,
[
['context', 'fileStorageDriver'],
['context', 'data', 'paginatedMessages', 'data'],
],
'normalizedMessages'
)
),
flatMapAsync(
applyPayloadArgs(
applySpec({ data: nthArg(0), metadata: { pagination: nthArg(1) } }),
[
['context', 'data', 'normalizedMessages'],
['context', 'data', 'paginatedMessages', 'metadata'],
],
'normalizedMessagesWithPagination'
)
),
lift(
orThrow(
[
[ChatMessageNotFoundBlockError, 404],
[FileStorageServiceError, 500],
[ChatMessageBlockError, 500],
],
[['context', 'data', 'normalizedMessagesWithPagination']]
)
)
),
method: 'GET',
path: '/messages',
validators: [
isAuthenticated(),
some(
checkIdentityType(['admin']),
hasSubscription(['params', 'requestQuery', 'channelId']),
isSelf(['params', 'requestQuery', 'senderId'])
),
],
});

getChatMessageRoute

実装

エンドポイント: GET /messages/:messageId

アクセス: isAuthenticated()some(...)checkIdentityType(...)ownsMessage(...) は、ここに示したソース順で実行されます。正確な呼び出し: isAuthenticated(), some( checkIdentityType(['admin']), ownsMessage(['params', 'requestParams', 'messageId']) ),.

リクエスト: getChatMessageSchema はパスパラメータを検証します: 必須: messageId.

パイプライン: getChatMessageByIdnormalizeChatMessageorThrow.

成功: 正規化されたメッセージを含む 200 を返します。

失敗: 認証および認可の失敗は、ハンドラーパイプラインの前にリンク先のバリデーターに従います。このルートは、ソースに示される次のマッピングを使用します: ChatMessageNotFoundBlockError404, FileStorageServiceError500, ChatMessageBlockError500

完全なソースを表示
export const getChatMessageRoute = withRoute({
handler: compose(
applyPayloadArgs(
getChatMessageByIdBlock,
[
['context', 'db', 'chatMessages'],
['params', 'requestParams', 'messageId'],
],
'message'
),

flatMapAsync(
applyPayloadArgs(
normalizeChatMessage,
[
['context', 'fileStorageDriver'],
['context', 'data', 'message'],
],
'normalizedMessage'
)
),

lift(
orThrow(
[
[ChatMessageNotFoundBlockError, 404],
[FileStorageServiceError, 500],
[ChatMessageBlockError, 500],
],
[['context', 'data', 'normalizedMessage']]
)
)
),
method: 'GET',
path: '/messages/:messageId',
validators: [
isAuthenticated(),
some(
checkIdentityType(['admin']),
ownsMessage(['params', 'requestParams', 'messageId'])
),
],
});

updateChatMessageRoute

実装

エンドポイント: PATCH /messages/:messageId

アクセス: isAuthenticated()ownsMessage(...) は、ここに示したソース順で実行されます。正確な呼び出し: isAuthenticated(), ownsMessage(['params', 'requestParams', 'messageId']),.

リクエスト: updateChatMessageSchema はパスパラメータおよび application/json 本文を検証します: 必須: messageId。省略可能: content, senderId, および title.

パイプライン: updateChatMessagegetChatMessageById.

成功: 更新済みで正規化されたメッセージを含む 200 を返します。

失敗: 認証および認可の失敗は、ハンドラーパイプラインの前にリンク先のバリデーターに従います。このルートは、ソースに示される次のマッピングを使用します: ChatMessageNotFoundBlockError404, FileStorageServiceError500, ChatMessageBlockError500

完全なソースを表示
export const updateChatMessageRoute = withRoute({
handler: compose(
withLogging(updateChatMessage),
flatMapAsync(withLogging(getChatMessageById)),

flatMapAsync(
applyPayloadArgs(
normalizeChatMessage,
[
['context', 'fileStorageDriver'],
['context', 'data', 'chatMessage'],
],
'normalizedMessage'
)
),

lift(
orThrow(
[
[ChatMessageNotFoundBlockError, 404],
[FileStorageServiceError, 500],
[ChatMessageBlockError, 500],
],
[['context', 'data', 'normalizedMessage'], 200]
)
)
),
method: 'PATCH',
path: '/messages/:messageId',
validators: [
isAuthenticated(),
ownsMessage(['params', 'requestParams', 'messageId']),
],
});

deleteChatMessageRoute

実装

エンドポイント: DELETE /messages/:messageId

アクセス: isAuthenticated()some(...)checkIdentityType(...)ownsMessage(...) は、ここに示したソース順で実行されます。正確な呼び出し: isAuthenticated(), some( checkIdentityType(['admin']), ownsMessage(['params', 'requestParams', 'messageId']) ),.

リクエスト: deleteChatMessageSchema はパスパラメータを検証します: 必須: messageId.

パイプライン: deleteChatMessagedeleteChatMessageTerminator.

成功: 空の 204 レスポンス。

失敗: 認証および認可の失敗は、ハンドラーパイプラインの前にリンク先のバリデーターに従います。パイプラインの失敗は、リンク先のハンドラー/ブロック契約と共通エラーミドルウェアに従います。このルートは個別のインラインエラーマッピングを追加しません。

完全なソースを表示
export const deleteChatMessageRoute = withRoute({
handler: compose(
withLogging(deleteChatMessage),
lift(withLogging(deleteChatMessageTerminator))
),
method: 'DELETE',
path: '/messages/:messageId',
validators: [
isAuthenticated(),
some(
checkIdentityType(['admin']),
ownsMessage(['params', 'requestParams', 'messageId'])
),
],
});

getChatMessageAttachmentUploadUrlRoute

実装

エンドポイント: GET /messages/:messageId/attachment-upload-url

アクセス: isAuthenticated()ownsMessage(...) は、ここに示したソース順で実行されます。正確な呼び出し: isAuthenticated(), ownsMessage(['params', 'requestParams', 'messageId']),.

リクエスト: 共有の getSignedFileUploadUrlSchema はパス messageId と署名付きファイルアップロードリクエストの契約を検証します。

パイプライン: generateChatMessageAttachmentUploadUrlorThrow.

成功: { objectId, url } を含む 200 を返します。

失敗: 認証および認可の失敗は、ハンドラーパイプラインの前にリンク先のバリデーターに従います。このルートは、ソースに示される次のマッピングを使用します: FileStorageServiceError500, ChatMessageBlockError500

完全なソースを表示
export const getChatMessageAttachmentUploadUrlRoute = withRoute({
handler: compose(
withLogging(
applyPayloadArgs(
generateChatMessageAttachmentUploadUrl,
[
['context', 'fileStorageDriver'],
['params', 'requestQuery', 'contentType'],
['params', 'requestQuery', 'contentLength'],
],
'attachmentUploadUrlResult'
)
),
lift(
orThrow(
[
[FileStorageServiceError, 500],
[ChatMessageBlockError, 500],
],
[['context', 'data', 'attachmentUploadUrlResult'], 200]
)
)
),
method: 'GET',
path: '/messages/:messageId/attachment-upload-url',
validators: [
isAuthenticated(),
ownsMessage(['params', 'requestParams', 'messageId']),
],
});

streamChatMessagesRoute

実装

エンドポイント: ws /messages/listen

アクセス: 有効なバリデーターはありません。ソースでは isAuthenticated() および hasSubscription(...) がコメントアウトされているため、現在の WebSocket エンドポイントでは Bearer/cookie 認証またはチャンネルメンバーシップは強制されません。

リクエスト: streamChatMessagesSchema はクエリパラメータを検証します: 必須: channelId.

パイプライン: streamChatMessagesnormalizeChatMessageStreamorThrow により WebSocket Subject を生成します。

成功: 正規化された挿入メッセージを発行し、各値を JSON としてシリアライズする WebSocket Subject。

失敗: アクセスバリデーターは実行されません。パイプラインのマッピングは ChatMessageBadRequestError400, ChatMessageUnknownError500 です。Subject/データベースの失敗によって WebSocket ストリームが終了することもあります。

完全なソースを表示
export const streamChatMessagesRoute = withRoute({
handler: compose(
withLogging(
applyPayloadArgs(
streamChatMessages,
[
['context', 'db', 'chatMessages'],
['params', 'requestQuery', 'channelId'],
],
'streamSubject'
)
),
flatMapAsync(
withLogging(
applyPayloadArgs(
normalizeChatMessageStream,
[
['context', 'fileStorageDriver'],
['context', 'data', 'streamSubject'],
],
'normalizedStreamSubject'
)
)
),
lift(
withLogging(
orThrow(
[
[ChatMessageBadRequestError, 400],
[ChatMessageUnknownError, 500],
],
[['context', 'data', 'normalizedStreamSubject']]
)
)
)
),
path: '/messages/listen',
protocol: 'ws',
validators: [
// @TODO: Websockets have different IP address format than the regular HTTP requests. So once that is fixed, we can uncomment this.
// isAuthenticated(),
// hasSubscription(['params', 'requestQuery', 'channelId']),
],
});

createChatMessageAttachmentRoute

実装

エンドポイント: POST /messages/:messageId/attachments

アクセス: isAuthenticated()ownsMessage(...) は、ここに示したソース順で実行されます。正確な呼び出し: isAuthenticated(), ownsMessage(['params', 'requestParams', 'messageId']),.

リクエスト: createChatMessageAttachmentSchemaapplication/json 本文を検証します: 必須: UUID の objectId および 文字列の type.

パイプライン: createChatMessageAttachmentgetChatMessageAttachmentByIdnormalizeChatMessageAttachmentorThrow.

成功: 正規化された添付ファイル { type, url } を含む 201 を返します。

失敗: 認証および認可の失敗は、ハンドラーパイプラインの前にリンク先のバリデーターに従います。このルートは、ソースに示される次のマッピングを使用します: ChatMessageNotFoundBlockError404, ChatMessageAttachmentNotFoundBlockError404, ChatMessageUnexpectedDBError500

完全なソースを表示
export const createChatMessageAttachmentRoute = withRoute({
handler: compose(
withLogging(
applyPayloadArgs(
createChatMessageAttachment,
[
['context', 'db', 'chatMessages'],
['params', 'requestParams', 'messageId'],
['params', 'requestBody'],
],
'messageAttachmentId'
)
),

flatMapAsync(
withLogging(
applyPayloadArgs(
getChatMessageAttachmentById,
[
['context', 'db', 'chatMessages'],
['params', 'requestParams', 'messageId'],
['context', 'data', 'messageAttachmentId'],
],
'messageAttachment'
)
)
),

flatMapAsync(
withLogging(
applyPayloadArgs(
normalizeChatMessageAttachment,
[
['context', 'fileStorageDriver'],
['context', 'data', 'messageAttachment'],
],
'normalizedMessageAttachment'
)
)
),

lift(
orThrow(
[
[ChatMessageNotFoundBlockError, 404],
[ChatMessageAttachmentNotFoundBlockError, 404],
[ChatMessageUnexpectedDBError, 500],
],
[['context', 'data', 'normalizedMessageAttachment'], 201]
)
)
),
method: 'POST',
path: '/messages/:messageId/attachments',
validators: [
isAuthenticated(),
ownsMessage(['params', 'requestParams', 'messageId']),
],
});

deleteChatMessageAttachmentRoute

実装

エンドポイント: DELETE /messages/:messageId/attachments/:attachmentId

アクセス: isAuthenticated()some(...)checkIdentityType(...)ownsMessage(...) は、ここに示したソース順で実行されます。正確な呼び出し: isAuthenticated(), some( checkIdentityType(['admin']), ownsMessage(['params', 'requestParams', 'messageId']) ),.

リクエスト: deleteChatMessageAttachmentSchema はパスパラメータを検証します: 必須: messageId および attachmentId.

パイプライン: deleteChatMessageAttachmentorThrow.

成功: メタデータおよび保存済みファイルを削除した後、空の 204 レスポンスを返します。

失敗: 認証および認可の失敗は、ハンドラーパイプラインの前にリンク先のバリデーターに従います。このルートは、ソースに示される次のマッピングを使用します: ChatMessageNotFoundBlockError404, ChatMessageAttachmentNotFoundBlockError404, ChatMessageUnexpectedDBError500, ChatMessageBlockError500, FileStorageServiceError500

完全なソースを表示
export const deleteChatMessageAttachmentRoute = withRoute({
handler: compose(
withLogging(
applyPayloadArgs(
deleteChatMessageAttachment,
[
['context', 'fileStorageDriver'],
['context', 'db', 'chatMessages'],
['params', 'requestParams', 'messageId'],
['params', 'requestParams', 'attachmentId'],
],
'messageAttachmentDeleted'
)
),

lift(
orThrow(
[
[ChatMessageNotFoundBlockError, 404],
[ChatMessageAttachmentNotFoundBlockError, 404],
[ChatMessageUnexpectedDBError, 500],
[ChatMessageBlockError, 500],
[FileStorageServiceError, 500],
],
[['context', 'data', 'messageAttachmentDeleted'], 204]
)
)
),
method: 'DELETE',
path: '/messages/:messageId/attachments/:attachmentId',
validators: [
isAuthenticated(),
some(
checkIdentityType(['admin']),
ownsMessage(['params', 'requestParams', 'messageId'])
),
],
});

createChatMessageTemplateRoute

実装

エンドポイント: POST /message-templates

アクセス: isAuthenticated()some(...)checkIdentityType(...)hasOrgRole(...) は、ここに示したソース順で実行されます。正確な呼び出し: isAuthenticated(), some( checkIdentityType(['admin']), hasOrgRole( ['owner', 'admin'], ['params', 'requestBody', 'organizationId'] ) ),.

リクエスト: createChatMessageTemplateSchemaapplication/json 本文を検証します: 必須: content および title。省略可能: organizationId.

パイプライン: createChatMessageTemplategetChatMessageTemplateByIdorThrow.

成功: MongoDB の _id を除外した作成済みテンプレートを含む 201 を返します。

失敗: 認証および認可の失敗は、ハンドラーパイプラインの前にリンク先のバリデーターに従います。このルートは、ソースに示される次のマッピングを使用します: ChatMessageTemplateNotFoundError404, ChatMessageTemplateInternalError500, ChatMessageTemplateDbError500

完全なソースを表示
export const createChatMessageTemplateRoute = withRoute({
handler: compose(
withLogging(
applyPayloadArgs(
createChatMessageTemplate,
[
['context', 'db', 'chatMessageTemplates'],
['params', 'requestBody'],
],
'messageTemplateId'
)
),
flatMapAsync(
applyPayloadArgs(
getChatMessageTemplateById,
[
['context', 'db', 'chatMessageTemplates'],
['context', 'data', 'messageTemplateId'],
],
'messageTemplate'
)
),
lift(
withLogging(
orThrow(
[
[ChatMessageTemplateNotFoundError, 404],
[ChatMessageTemplateInternalError, 500],
[ChatMessageTemplateDbError, 500],
],
[['context', 'data', 'messageTemplate'], 201]
)
)
)
),
method: 'POST',
path: '/message-templates',
validators: [
isAuthenticated(),
some(
checkIdentityType(['admin']),
hasOrgRole(
['owner', 'admin'],
['params', 'requestBody', 'organizationId']
)
),
],
});

getChatMessageTemplateRoute

実装

エンドポイント: GET /message-templates/:messageTemplateId

アクセス: isAuthenticated()some(...)checkIdentityType(...)hasOrganizationAccessToMessageTemplate(...) は、ここに示したソース順で実行されます。正確な呼び出し: isAuthenticated(), some( checkIdentityType(['admin']), hasOrganizationAccessToMessageTemplate( ['owner', 'admin'], ['params', 'requestParams', 'messageTemplateId'] ) ),.

リクエスト: getChatMessageTemplateSchema はパスパラメータを検証します: 必須: messageTemplateId.

パイプライン: getChatMessageTemplateByIdorThrow.

成功: MongoDB の _id を除外したテンプレートを含む 200 を返します。

失敗: 認証および認可の失敗は、ハンドラーパイプラインの前にリンク先のバリデーターに従います。このルートは、ソースに示される次のマッピングを使用します: ChatMessageTemplateNotFoundError404, ChatMessageTemplateUnauthorizedError403, ChatMessageTemplateInternalError500, ChatMessageTemplateDbError500

完全なソースを表示
export const getChatMessageTemplateRoute = withRoute({
handler: compose(
withLogging(
applyPayloadArgs(
getChatMessageTemplateById,
[
['context', 'db', 'chatMessageTemplates'],
['params', 'requestParams', 'messageTemplateId'],
],
'messageTemplate'
)
),
lift(
withLogging(
orThrow(
[
[ChatMessageTemplateNotFoundError, 404],
[ChatMessageTemplateUnauthorizedError, 403],
[ChatMessageTemplateInternalError, 500],
[ChatMessageTemplateDbError, 500],
],
[['context', 'data', 'messageTemplate']]
)
)
)
),
method: 'GET',
path: '/message-templates/:messageTemplateId',
validators: [
isAuthenticated(),
some(
checkIdentityType(['admin']),
hasOrganizationAccessToMessageTemplate(
['owner', 'admin'],
['params', 'requestParams', 'messageTemplateId']
)
),
],
});

updateChatMessageTemplateRoute

実装

エンドポイント: PATCH /message-templates/:messageTemplateId

アクセス: isAuthenticated()some(...)checkIdentityType(...)hasOrganizationAccessToMessageTemplate(...) は、ここに示したソース順で実行されます。正確な呼び出し: isAuthenticated(), some( checkIdentityType(['admin']), hasOrganizationAccessToMessageTemplate( ['owner', 'admin'], ['params', 'requestParams', 'messageTemplateId'] ) ),.

リクエスト: updateChatMessageTemplateSchema はパスパラメータおよび application/json 本文を検証します: 必須: テンプレート ID。省略可能: content および title.

パイプライン: updateChatMessageTemplategetChatMessageTemplateByIdorThrow.

成功: MongoDB の _id を除外した更新済みテンプレートを含む 200 を返します。

失敗: 認証および認可の失敗は、ハンドラーパイプラインの前にリンク先のバリデーターに従います。このルートは、ソースに示される次のマッピングを使用します: ChatMessageTemplateNotFoundError404, ChatMessageTemplateUnauthorizedError403, ChatMessageTemplateInternalError500, ChatMessageTemplateDbError500

完全なソースを表示
export const updateChatMessageTemplateRoute = withRoute({
handler: compose(
withLogging(
applyPayloadArgs(
updateChatMessageTemplate,
[
['context', 'db', 'chatMessageTemplates'],
['params', 'requestParams', 'messageTemplateId'],
['params', 'requestBody'],
],
'hasUpdatedMessageTemplate'
)
),
flatMapAsync(
withLogging(
applyPayloadArgs(
getChatMessageTemplateById,
[
['context', 'db', 'chatMessageTemplates'],
['params', 'requestParams', 'messageTemplateId'],
],
'messageTemplate'
)
)
),
lift(
withLogging(
orThrow(
[
[ChatMessageTemplateNotFoundError, 404],
[ChatMessageTemplateUnauthorizedError, 403],
[ChatMessageTemplateInternalError, 500],
[ChatMessageTemplateDbError, 500],
],
[['context', 'data', 'messageTemplate'], 200]
)
)
)
),
method: 'PATCH',
path: '/message-templates/:messageTemplateId',
validators: [
isAuthenticated(),
some(
checkIdentityType(['admin']),
hasOrganizationAccessToMessageTemplate(
['owner', 'admin'],
['params', 'requestParams', 'messageTemplateId']
)
),
],
});

deleteChatMessageTemplateRoute

実装

エンドポイント: DELETE /message-templates/:messageTemplateId

アクセス: isAuthenticated()some(...)checkIdentityType(...)hasOrganizationAccessToMessageTemplate(...) は、ここに示したソース順で実行されます。正確な呼び出し: isAuthenticated(), some( checkIdentityType(['admin']), hasOrganizationAccessToMessageTemplate( ['owner', 'admin'], ['params', 'requestParams', 'messageTemplateId'] ) ),.

リクエスト: deleteChatMessageTemplateSchema はパスパラメータを検証します: 必須: messageTemplateId.

パイプライン: deleteChatMessageTemplateorThrow.

成功: 空の 204 レスポンス。

失敗: 認証および認可の失敗は、ハンドラーパイプラインの前にリンク先のバリデーターに従います。このルートは、ソースに示される次のマッピングを使用します: ChatMessageTemplateNotFoundError404, ChatMessageTemplateUnauthorizedError403, ChatMessageTemplateInternalError500, ChatMessageTemplateDbError500

完全なソースを表示
export const deleteChatMessageTemplateRoute = withRoute({
handler: compose(
withLogging(
applyPayloadArgs(
deleteChatMessageTemplate,
[
['context', 'db', 'chatMessageTemplates'],
['params', 'requestParams', 'messageTemplateId'],
],
'hasDeletedMessageTemplate'
)
),
lift(
withLogging(
orThrow(
[
[ChatMessageTemplateNotFoundError, 404],
[ChatMessageTemplateUnauthorizedError, 403],
[ChatMessageTemplateInternalError, 500],
[ChatMessageTemplateDbError, 500],
],
[[''], 204]
)
)
)
),
method: 'DELETE',
path: '/message-templates/:messageTemplateId',
validators: [
isAuthenticated(),
some(
checkIdentityType(['admin']),
hasOrganizationAccessToMessageTemplate(
['owner', 'admin'],
['params', 'requestParams', 'messageTemplateId']
)
),
],
});

findChatMessageTemplatesRoute

実装

エンドポイント: GET /message-templates

アクセス: isAuthenticated()checkIdentityType(...) は、ここに示したソース順で実行されます。正確な呼び出し: isAuthenticated(), checkIdentityType(['admin']).

リクエスト: findChatMessageTemplatesSchema はクエリパラメータを検証します: 共通のページネーションフィールドのみ。

パイプライン: findChatMessageTemplates → ページネーション → 共通の normalizeDocumentsorThrow.

成功: 正規化されたテンプレートとページネーションメタデータを含む 200 を返します。

失敗: 認証および認可の失敗は、ハンドラーパイプラインの前にリンク先のバリデーターに従います。このルートは、ソースに示される次のマッピングを使用します: ChatMessageTemplateNotFoundError404, ChatMessageTemplateUnauthorizedError403, ChatMessageTemplateInternalError500, ChatMessageTemplateDbError500

完全なソースを表示
export const findChatMessageTemplatesRoute = withRoute({
handler: compose(
withPagination(
withLogging(
applyPayloadArgs(
findChatMessageTemplates,
[
['context', 'db', 'chatMessageTemplates'],
['params', 'requestQuery'],
],
'messageTemplates'
)
)
),
flatMapAsync(
withLogging(
applyPayloadArgs(
normalizeDocuments,
[['context', 'data', 'messageTemplates', 'data']],
'normalizedMessageTemplates'
)
)
),
flatMapAsync(
applyPayloadArgs(
applySpec({ data: nthArg(0), metadata: { pagination: nthArg(1) } }),
[
['context', 'data', 'normalizedMessageTemplates'],
['context', 'data', 'messageTemplates', 'metadata'],
],
'normalizedBody'
)
),
lift(
withLogging(
orThrow(
[
[ChatMessageTemplateNotFoundError, 404],
[ChatMessageTemplateUnauthorizedError, 403],
[ChatMessageTemplateInternalError, 500],
[ChatMessageTemplateDbError, 500],
],
[['context', 'data', 'normalizedBody']]
)
)
)
),
method: 'GET',
path: '/message-templates',
validators: [isAuthenticated(), checkIdentityType(['admin'])],
});

findChatMessageTemplatesForOrganizationRoute

実装

エンドポイント: GET /organizations/:organizationId/message-templates

アクセス: isAuthenticated()hasOrgRole(...) は、ここに示したソース順で実行されます。正確な呼び出し: isAuthenticated(), hasOrgRole( ['owner', 'admin'], ['params', 'requestParams', 'organizationId'] ),.

リクエスト: findChatMessageTemplatesForOrganizationSchema はパスおよびクエリパラメータを検証します: 必須: organizationId および共通ページネーションフィールド。

パイプライン: buildFilterToGetChatMessageTemplatesByOrganizationIdfindChatMessageTemplates → ページネーション → 共通の normalizeDocumentsorThrow.

成功: パスで指定された組織の正規化済みテンプレートとページネーションメタデータを含む 200 を返します。

失敗: 認証および認可の失敗は、ハンドラーパイプラインの前にリンク先のバリデーターに従います。このルートは、ソースに示される次のマッピングを使用します: ChatMessageTemplateNotFoundError404, ChatMessageTemplateUnauthorizedError403, ChatMessageTemplateInternalError500, ChatMessageTemplateDbError500

完全なソースを表示
export const findChatMessageTemplatesForOrganizationRoute = withRoute({
handler: compose(
withLogging(
applyPayloadArgs(
buildFilterToGetChatMessageTemplatesByOrganizationId,
[['params', 'requestParams', 'organizationId']],
'filter'
)
),
flatMapAsync(
withPagination(
withLogging(
applyPayloadArgs(
findChatMessageTemplates,
[
['context', 'db', 'chatMessageTemplates'],
['context', 'data', 'filter'],
],
'messageTemplates'
)
)
)
),
flatMapAsync(
withLogging(
applyPayloadArgs(
normalizeDocuments,
[['context', 'data', 'messageTemplates', 'data']],
'normalizedMessageTemplates'
)
)
),
flatMapAsync(
applyPayloadArgs(
applySpec({ data: nthArg(0), metadata: { pagination: nthArg(1) } }),
[
['context', 'data', 'normalizedMessageTemplates'],
['context', 'data', 'messageTemplates', 'metadata'],
],
'normalizedBody'
)
),
lift(
withLogging(
orThrow(
[
[ChatMessageTemplateNotFoundError, 404],
[ChatMessageTemplateUnauthorizedError, 403],
[ChatMessageTemplateInternalError, 500],
[ChatMessageTemplateDbError, 500],
],
[['context', 'data', 'normalizedBody']]
)
)
)
),
method: 'GET',
path: '/organizations/:organizationId/message-templates',
validators: [
isAuthenticated(),
hasOrgRole(
['owner', 'admin'],
['params', 'requestParams', 'organizationId']
),
],
});

upsertChatChannelReadStateRoute

実装

エンドポイント: PUT /channels/:channelId/read-state

アクセス: isAuthenticated()isSelf(...)hasSubscription(...)channelExists(...) は、ここに示したソース順で実行されます。正確な呼び出し: isAuthenticated(), channelExists(['params', 'requestParams', 'channelId']), hasSubscription(['params', 'requestParams', 'channelId']), isSelf(['params', 'requestBody', 'identityId']),.

リクエスト: upsertChatChannelReadStateSchema はパスパラメータおよび application/json 本文を検証します: 必須: channelId, identityId, および lastReadMessageId.

パイプライン: findChatMessages.

成功: 空の 204 レスポンス既読状態を作成または更新した後、空の 204 レスポンスを返します。

失敗: 認証および認可の失敗は、ハンドラーパイプラインの前にリンク先のバリデーターに従います。このルートは、ソースに示される次のマッピングを使用します: ChatChannelReadStateNotFoundError404, ChatChannelReadStateDatabaseError500, ChatChannelReadStateUnknownError500

完全なソースを表示
export const upsertChatChannelReadStateRoute = withRoute({
handler: compose(
// Find the existing chat channel read state by channel and identity
compose(
withLogging(
applyPayloadArgs(
buildChatChannelReadStateQuery,
[
['params', 'requestParams', 'channelId'],
['params', 'requestBody', 'identityId'],
],
'chatChannelReadStateQuery'
)
),
flatMapAsync(
withLogging(
applyPayloadArgs(
findChatChannelReadStates,
[
['context', 'db', 'chatChannelReadStates'],
['context', 'data', 'chatChannelReadStateQuery'],
],
'findChatChannelReadStatesResult'
)
)
),
flatMapAsync(
withLogging(
applyPayloadArgs(
head,
[['context', 'data', 'findChatChannelReadStatesResult']],
'chatChannelReadState'
)
)
)
),
// Find the last read message by message id, channel id, and identity id
compose(
flatMapAsync(
withLogging(
applyPayloadArgs(
buildLastReadMessageQuery,
[
['params', 'requestBody', 'lastReadMessageId'],
['params', 'requestParams', 'channelId'],
['params', 'requestBody', 'identityId'],
],
'lastReadMessageQuery'
)
)
),
flatMapAsync(
withLogging(
applyPayloadArgs(
findChatMessages,
[
['context', 'db', 'chatMessages'],
['context', 'data', 'lastReadMessageQuery'],
],
'findChatMessagesResult'
)
)
),
flatMapAsync(
withLogging(
applyPayloadArgs(
head,
[['context', 'data', 'findChatMessagesResult']],
'lastReadMessage'
)
)
)
),
flatMapAsync(
ifElse(
match(hasValue, ['context', 'data', 'chatChannelReadState']),
// Update the existing chat channel read state
compose(
withLogging(
applyPayloadArgs(
buildUpdateChatChannelReadStatePayload,
[['context', 'data', 'lastReadMessage']],
'updateChatChannelReadStatePayload'
)
),
flatMapAsync(
withLogging(
applyPayloadArgs(
updateChatChannelReadState,
[
['context', 'db', 'chatChannelReadStates'],
['context', 'data', 'chatChannelReadState', 'id'],
['context', 'data', 'updateChatChannelReadStatePayload'],
],
'upsertChatChannelReadStateResult'
)
)
)
),
// Create a new chat channel read state
compose(
withLogging(
applyPayloadArgs(
buildCreateChatChannelReadStatePayload,
[
['params', 'requestParams', 'channelId'],
['params', 'requestBody', 'identityId'],
['context', 'data', 'lastReadMessage'],
],
'createChatChannelReadStatePayload'
)
),
flatMapAsync(
withLogging(
applyPayloadArgs(
createChatChannelReadState,
[
['context', 'db', 'chatChannelReadStates'],
['context', 'data', 'createChatChannelReadStatePayload'],
],
'upsertChatChannelReadStateResult'
)
)
)
)
)
),
lift(
withLogging(
orThrow(
[
[ChatChannelReadStateNotFoundError, 404],
[ChatChannelReadStateDatabaseError, 500],
[ChatChannelReadStateUnknownError, 500],
],
[['context', 'data', 'upsertChatChannelReadStateResult'], 204]
)
)
)
),
method: 'PUT',
path: '/channels/:channelId/read-state',
validators: [
isAuthenticated(),
channelExists(['params', 'requestParams', 'channelId']),
hasSubscription(['params', 'requestParams', 'channelId']),
isSelf(['params', 'requestBody', 'identityId']),
],
});

createChatSubscriptionRoute

実装

エンドポイント: POST /subscriptions

アクセス: isAuthenticated()some(...)checkIdentityType(...)isSelf(...) は、ここに示したソース順で実行されます。正確な呼び出し: isAuthenticated(), some( checkIdentityType(['admin']), isSelf(['params', 'requestBody', 'subscribedId']) ),.

リクエスト: createChatSubscriptionSchemaapplication/json 本文を検証します: 必須: channelId および subscribedId; その他のサブスクリプションフィールドは省略可能です。

パイプライン: createChatSubscriptiongetChatSubscriptionByIdcreateChatSubscriptionTerminator.

成功: レスポンス記述子の data に作成済みサブスクリプションを含む 201 を返します。

失敗: 認証および認可の失敗は、ハンドラーパイプラインの前にリンク先のバリデーターに従います。パイプラインの失敗は、リンク先のハンドラー/ブロック契約と共通エラーミドルウェアに従います。このルートは個別のインラインエラーマッピングを追加しません。

完全なソースを表示
export const createChatSubscriptionRoute = withRoute({
handler: compose(
// TODO: need to check if the user is already subscribed to the channel
withLogging(createChatSubscription),
flatMapAsync(withLogging(getChatSubscriptionById)),
lift(withLogging(createChatSubscriptionTerminator))
),
method: 'POST',
path: '/subscriptions',
validators: [
isAuthenticated(),
some(
checkIdentityType(['admin']),
isSelf(['params', 'requestBody', 'subscribedId'])
),
],
});

findChatSubscriptionsRoute

実装

エンドポイント: GET /subscriptions

アクセス: isAuthenticated()some(...)checkIdentityType(...)isSelf(...)ownsChannel(...)hasSubscription(...) は、ここに示したソース順で実行されます。正確な呼び出し: isAuthenticated(), some( checkIdentityType(['admin']), hasSubscription(['params', 'requestQuery', 'channelId']), ownsChannel(['params', 'requestQuery', 'channelId']), isSelf(['params', 'requestQuery', 'subscribedId']) ),.

リクエスト: findChatSubscriptionsSchema はクエリパラメータを検証します: 省略可能: subscription filters および共通ページネーションフィールド。

パイプライン: findChatSubscriptionsnormalizeChatSubscriptionsListTerminator.

成功: 200正規化されたサブスクリプションとページネーションメタデータを含む 200 を返します。

失敗: 認証および認可の失敗は、ハンドラーパイプラインの前にリンク先のバリデーターに従います。パイプラインの失敗は、リンク先のハンドラー/ブロック契約と共通エラーミドルウェアに従います。このルートは個別のインラインエラーマッピングを追加しません。

完全なソースを表示
export const findChatSubscriptionsRoute = withRoute({
handler: compose(
withPagination(withLogging(findChatSubscriptions)),
lift(withLogging(normalizeChatSubscriptionsListTerminator))
),
method: 'GET',
path: '/subscriptions',
validators: [
isAuthenticated(),
some(
checkIdentityType(['admin']),
hasSubscription(['params', 'requestQuery', 'channelId']),
ownsChannel(['params', 'requestQuery', 'channelId']),
isSelf(['params', 'requestQuery', 'subscribedId'])
),
],
});

getChatSubscriptionRoute

実装

エンドポイント: GET /subscriptions/:subscriptionId

アクセス: isAuthenticated()some(...)checkIdentityType(...)ownsSubscription(...) は、ここに示したソース順で実行されます。正確な呼び出し: isAuthenticated(), some( checkIdentityType(['admin']), ownsSubscription(['params', 'requestParams', 'subscriptionId']) ),.

リクエスト: getChatSubscriptionSchema はパスパラメータを検証します: 必須: subscriptionId.

パイプライン: getChatSubscriptionByIdnormalizeChatSubscriptionTerminator.

成功: MongoDB の _id を除外したサブスクリプションを含む 200 を返します。

失敗: 認証および認可の失敗は、ハンドラーパイプラインの前にリンク先のバリデーターに従います。パイプラインの失敗は、リンク先のハンドラー/ブロック契約と共通エラーミドルウェアに従います。このルートは個別のインラインエラーマッピングを追加しません。

完全なソースを表示
export const getChatSubscriptionRoute = withRoute({
handler: compose(
withLogging(getChatSubscriptionById),
lift(withLogging(normalizeChatSubscriptionTerminator))
),
method: 'GET',
path: '/subscriptions/:subscriptionId',
validators: [
isAuthenticated(),
some(
checkIdentityType(['admin']),
ownsSubscription(['params', 'requestParams', 'subscriptionId'])
),
],
});

deleteChatSubscriptionRoute

実装

エンドポイント: DELETE /subscriptions/:subscriptionId

アクセス: isAuthenticated()some(...)checkIdentityType(...)ownsSubscription(...) は、ここに示したソース順で実行されます。正確な呼び出し: isAuthenticated(), some( checkIdentityType(['admin']), ownsSubscription(['params', 'requestParams', 'subscriptionId']) ),.

リクエスト: deleteChatSubscriptionSchema はパスパラメータを検証します: 必須: subscriptionId.

パイプライン: deleteChatSubscriptiondeleteChatSubscriptionTerminator.

成功: 空の 204 レスポンス。

失敗: 認証および認可の失敗は、ハンドラーパイプラインの前にリンク先のバリデーターに従います。パイプラインの失敗は、リンク先のハンドラー/ブロック契約と共通エラーミドルウェアに従います。このルートは個別のインラインエラーマッピングを追加しません。

完全なソースを表示
export const deleteChatSubscriptionRoute = withRoute({
handler: compose(
withLogging(deleteChatSubscription),
lift(withLogging(deleteChatSubscriptionTerminator))
),
method: 'DELETE',
path: '/subscriptions/:subscriptionId',
validators: [
isAuthenticated(),
some(
checkIdentityType(['admin']),
ownsSubscription(['params', 'requestParams', 'subscriptionId'])
),
],
});