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

🛣️ Product ルート

Product ルートは Express ミドルウェアではなく SDK コンポーザーです。各機能がスキーマを提供し、詳細にはメソッド、パス、バリデーター順序、パイプライン、レスポンスステータスを記載します。

一覧

ルートメソッド/プロトコルパススキーマバリデーター成功ステータス
createProductRoutePOST / HTTP/productscreateProductSchemaisAuthenticated(), checkIdentityType(['admin'])200
findProductsRouteGET / HTTP/productsfindProductsSchemaなし200
createProductBatchRoutePOST / HTTP/products/batchcreateProductBatchSchemaisAuthenticated(), checkIdentityType(['admin'])200
updateProductBatchRoutePATCH / HTTP/products/batchupdateProductBatchSchemaisAuthenticated(), checkIdentityType(['admin'])200
deleteProductBatchRouteDELETE / HTTP/products/batchdeleteProductBatchSchemaisAuthenticated(), checkIdentityType(['admin'])204
getProductRouteGET / HTTP/products/:productIdgetProductSchemaなし200
updateProductRoutePATCH / HTTP/products/:productIdupdateProductSchemaisAuthenticated(), checkIdentityType(['admin'])200
deleteProductRouteDELETE / HTTP/products/:productIddeleteProductSchemaisAuthenticated(), checkIdentityType(['admin'])204
copyProductRoutePOST / HTTP/products/:productId/copycopyProductSchemaisAuthenticated(), checkIdentityType(['admin'])200
copyProductBatchRoutePOST / HTTP/products/batch/copycopyProductBatchSchemaisAuthenticated(), checkIdentityType(['admin'])200
getProductImageUploadUrlRouteGET / HTTP/products/:productId/image-upload-urlgetSignedImageUploadUrlSchemaisAuthenticated(), checkIdentityType(['admin'])200
createProductImageRoutePOST / HTTP/products/:productId/imagescreateProductImageSchemaisAuthenticated(), checkIdentityType(['admin'])201
deleteProductImageRouteDELETE / HTTP/products/:productId/images/:imageIddeleteProductImageSchemaisAuthenticated(), checkIdentityType(['admin'])204
createProductVariantRoutePOST / HTTP/products/:productId/variantscreateProductVariantSchemaisAuthenticated(), checkIdentityType(['admin'])201
getProductVariantRouteGET / HTTP/products/:productId/variants/:productVariantIdgetProductVariantSchemaisAuthenticated()200
updateProductVariantRoutePATCH / HTTP/products/:productId/variants/:productVariantIdupdateProductVariantSchemaisAuthenticated(), checkIdentityType(['admin'])200
deleteProductVariantRouteDELETE / HTTP/products/:productId/variants/:productVariantIddeleteProductVariantSchemaisAuthenticated(), checkIdentityType(['admin'])204
findProductVariantsRouteGET / HTTP/products/:productId/variantsfindProductVariantsSchemaなし200
createProductVariantBulkRoutePOST / HTTP/product/:productId/variants/bulkcreateProductVariantBulkSchemaisAuthenticated(), checkIdentityType(['admin'])201
updateProductVariantBulkRoutePATCH / HTTP/product/:productId/variants/bulkupdateProductVariantBulkSchemaisAuthenticated(), checkIdentityType(['admin'])200
deleteProductVariantBulkRoutePOST / HTTP/product/:productId/variants/bulk-deletedeleteProductVariantBulkSchemaisAuthenticated(), checkIdentityType(['admin'])204
findProductsByOrganizationIdRouteGET / HTTP/products/organizations/:organizationIdfindByOrganizationIdSchemaisAuthenticated(), hasOrgRole(['owner', 'admin', 'member'], ['params', 'requestParams', 'organizationId'])200
getProductLikersRouteGET / HTTP/products/:productId/likersgetProductLikersSchemaisAuthenticated(), checkIdentityType(['admin'])200

詳細

createProductRoute

実装

エンドポイント: POST /products

アクセス: 認証が必要です。バリデーターはソース順に実行されます: isAuthenticated(), checkIdentityType(['admin']).

リクエスト: createProductSchema は、付随する本文、パス、クエリの契約を定義します。

パイプライン: createProduct

成功: 最終の orThrow 成功マップは statusCode 記述子なしで通常のルートデータを返します。このコンポーザーは成功ステータスを設定しません。

失敗: ProductNotFoundBlockError404, FileStorageServiceError500. スキーマおよびバリデーターの失敗は、合成されたミドルウェアで処理されます。

完全なソースを表示
export const createProductRoute = withRoute({
handler: compose(
withLogging(createProduct),

flatMapAsync(
applyPayloadArgs(
getProductByIdBlock,
[
['context', 'db', 'products'],
['context', 'data', 'productId'],
],
'product'
)
),

flatMapAsync(
applyPayloadArgs(
normalizeProduct,
[['context', 'data', 'product']],
'normalizedProduct'
)
),

lift(
orThrow(
[
[ProductNotFoundBlockError, 404],
[FileStorageServiceError, 500],
],
[['context', 'data', 'normalizedProduct']]
)
)
),
method: 'POST',
path: '/products',
validators: [isAuthenticated(), checkIdentityType(['admin'])],
});

findProductsRoute

実装

エンドポイント: GET /products

アクセス: 公開です。ソースはルートバリデーターを提供しません。

リクエスト: findProductsSchema は、付随する本文、パス、クエリの契約を定義します。

パイプライン: このルートは Product ブロックと共有ユーティリティを直接合成します。以下の完全なソースを参照してください。

成功: 最終の orThrow 成功マップは statusCode 記述子なしで通常のルートデータを返します。このコンポーザーは成功ステータスを設定しません。

失敗: ProductNotFoundBlockError404, FileStorageServiceError500, ProductBlockError500. スキーマおよびバリデーターの失敗は、合成されたミドルウェアで処理されます。

完全なソースを表示
export const findProductsRoute = withRoute({
handler: compose(
withPagination(
withLogging(
applyPayloadArgs(
findProducts,
[
['context', 'db', 'products'],
['params', 'requestQuery'],
],
'paginatedProducts'
)
)
),
flatMapAsync(
applyPayloadArgs(
normalizeImagesOfProducts,
[
['context', 'fileStorageDriver'],
['context', 'data', 'paginatedProducts', 'data'],
],
'productsWithNormalizedImages'
)
),
flatMapAsync(
applyPayloadArgs(
normalizeProducts,
[['context', 'data', 'productsWithNormalizedImages']],
'normalizedProducts'
)
),
flatMapAsync(
applyPayloadArgs(
applySpec({ data: nthArg(0), metadata: { pagination: nthArg(1) } }),
[
['context', 'data', 'normalizedProducts'],
['context', 'data', 'paginatedProducts', 'metadata'],
],
'normalizedProductsWithPagination'
)
),
lift(
orThrow(
[
[ProductNotFoundBlockError, 404],
[FileStorageServiceError, 500],
[ProductBlockError, 500],
],
[['context', 'data', 'normalizedProductsWithPagination']]
)
)
),
method: 'GET',
path: '/products',
validators: [],
});

createProductBatchRoute

実装

エンドポイント: POST /products/batch

アクセス: 認証が必要です。バリデーターはソース順に実行されます: isAuthenticated(), checkIdentityType(['admin']).

リクエスト: createProductBatchSchema は、付随する本文、パス、クエリの契約を定義します。

パイプライン: createProductBatchgetProductsByIds

成功: 最終の orThrow 成功マップは statusCode 記述子なしで通常のルートデータを返します。このコンポーザーは成功ステータスを設定しません。

失敗: ProductNotFoundBlockError404, FileStorageServiceError500. スキーマおよびバリデーターの失敗は、合成されたミドルウェアで処理されます。

完全なソースを表示
export const createProductBatchRoute = withRoute({
handler: compose(
withLogging(createProductBatch),
flatMapAsync(withLogging(getProductsByIds)),

flatMapAsync(
applyPayloadArgs(
normalizeProducts,
[['context', 'data', 'products']],
'normalizedProducts'
)
),

lift(
orThrow(
[
[ProductNotFoundBlockError, 404],
[FileStorageServiceError, 500],
],
[['context', 'data', 'normalizedProducts']]
)
)
),
method: 'POST',
path: '/products/batch',
validators: [isAuthenticated(), checkIdentityType(['admin'])],
});

updateProductBatchRoute

実装

エンドポイント: PATCH /products/batch

アクセス: 認証が必要です。バリデーターはソース順に実行されます: isAuthenticated(), checkIdentityType(['admin']).

リクエスト: updateProductBatchSchema は、付随する本文、パス、クエリの契約を定義します。

パイプライン: updateProductBatchgetProductsByIds

成功: 最終の orThrow 成功マップは statusCode 記述子なしで通常のルートデータを返します。このコンポーザーは成功ステータスを設定しません。

失敗: ProductNotFoundBlockError404, FileStorageServiceError500. スキーマおよびバリデーターの失敗は、合成されたミドルウェアで処理されます。

完全なソースを表示
export const updateProductBatchRoute = withRoute({
handler: compose(
withLogging(updateProductBatch),
flatMapAsync(withLogging(getProductsByIds)),

flatMapAsync(
applyPayloadArgs(
normalizeImagesOfProducts,
[
['context', 'fileStorageDriver'],
['context', 'data', 'products'],
],
'productsWithNormalizedImages'
)
),

flatMapAsync(
applyPayloadArgs(
normalizeProducts,
[['context', 'data', 'productsWithNormalizedImages']],
'normalizedProducts'
)
),

lift(
orThrow(
[
[ProductNotFoundBlockError, 404],
[FileStorageServiceError, 500],
],
[['context', 'data', 'normalizedProducts']]
)
)
),
method: 'PATCH',
path: '/products/batch',
validators: [isAuthenticated(), checkIdentityType(['admin'])],
});

deleteProductBatchRoute

実装

エンドポイント: DELETE /products/batch

アクセス: 認証が必要です。バリデーターはソース順に実行されます: isAuthenticated(), checkIdentityType(['admin']).

リクエスト: deleteProductBatchSchema は、付随する本文、パス、クエリの契約を定義します。

パイプライン: deleteProductBatchdeleteBatchProductsTerminator

成功: deleteBatchProductsTerminator による 204 レスポンス記述子。

失敗: ルート固有の orThrow エラー対応付けはありません。 スキーマおよびバリデーターの失敗は、合成されたミドルウェアで処理されます。

完全なソースを表示
export const deleteProductBatchRoute = withRoute({
handler: compose(
withLogging(deleteProductBatch),
lift(withLogging(deleteBatchProductsTerminator))
),
method: 'DELETE',
path: '/products/batch',
validators: [isAuthenticated(), checkIdentityType(['admin'])],
});

getProductRoute

実装

エンドポイント: GET /products/:productId

アクセス: 公開です。ソースはルートバリデーターを提供しません。

リクエスト: getProductSchema は、付随する本文、パス、クエリの契約を定義します。

パイプライン: このルートは Product ブロックと共有ユーティリティを直接合成します。以下の完全なソースを参照してください。

成功: 最終の orThrow 成功マップは statusCode 記述子なしで通常のルートデータを返します。このコンポーザーは成功ステータスを設定しません。

失敗: ProductNotFoundBlockError404, FileStorageServiceError500. スキーマおよびバリデーターの失敗は、合成されたミドルウェアで処理されます。

完全なソースを表示
export const getProductRoute = withRoute({
handler: compose(
applyPayloadArgs(
getProductByIdBlock,
[
['context', 'db', 'products'],
['params', 'requestParams', 'productId'],
],
'product'
),

flatMapAsync(
applyPayloadArgs(
normalizeImagesOfProduct,
[
['context', 'fileStorageDriver'],
['context', 'data', 'product'],
],
'productWithNormalizedImages'
)
),

flatMapAsync(
applyPayloadArgs(
normalizeProduct,
[['context', 'data', 'productWithNormalizedImages']],
'normalizedProduct'
)
),

lift(
orThrow(
[
[ProductNotFoundBlockError, 404],
[FileStorageServiceError, 500],
],
[['context', 'data', 'normalizedProduct']]
)
)
),
method: 'GET',
path: '/products/:productId',
validators: [],
});

updateProductRoute

実装

エンドポイント: PATCH /products/:productId

アクセス: 認証が必要です。バリデーターはソース順に実行されます: isAuthenticated(), checkIdentityType(['admin']).

リクエスト: updateProductSchema は、付随する本文、パス、クエリの契約を定義します。

パイプライン: updateProduct

成功: 最終の orThrow 成功マップは statusCode 記述子なしで通常のルートデータを返します。このコンポーザーは成功ステータスを設定しません。

失敗: ProductNotFoundBlockError404, FileStorageServiceError500. スキーマおよびバリデーターの失敗は、合成されたミドルウェアで処理されます。

完全なソースを表示
export const updateProductRoute = withRoute({
handler: compose(
withLogging(updateProduct),

flatMapAsync(
applyPayloadArgs(
getProductByIdBlock,
[
['context', 'db', 'products'],
['context', 'data', 'updateProductId'],
],
'product'
)
),

flatMapAsync(
applyPayloadArgs(
normalizeImagesOfProduct,
[
['context', 'fileStorageDriver'],
['context', 'data', 'product'],
],
'productWithNormalizedImages'
)
),

flatMapAsync(
applyPayloadArgs(
normalizeProduct,
[['context', 'data', 'productWithNormalizedImages']],
'normalizedProduct'
)
),

lift(
orThrow(
[
[ProductNotFoundBlockError, 404],
[FileStorageServiceError, 500],
],
[['context', 'data', 'normalizedProduct']]
)
)
),
method: 'PATCH',
path: '/products/:productId',
validators: [isAuthenticated(), checkIdentityType(['admin'])],
});

deleteProductRoute

実装

エンドポイント: DELETE /products/:productId

アクセス: 認証が必要です。バリデーターはソース順に実行されます: isAuthenticated(), checkIdentityType(['admin']).

リクエスト: deleteProductSchema は、付随する本文、パス、クエリの契約を定義します。

パイプライン: deleteProduct

成功: レスポンス本文なしの 204。ソースは [['undefined'], 204] に対応付けます。

失敗: ProductNotFoundBlockError404, FileStorageServiceError500. スキーマおよびバリデーターの失敗は、合成されたミドルウェアで処理されます。

完全なソースを表示
export const deleteProductRoute = withRoute({
handler: compose(
withLogging(
applyPayloadArgs(
deleteImagesOfProduct,
[
['context', 'fileStorageDriver'],
['context', 'db', 'products'],
['params', 'requestParams', 'productId'],
],
'wereProductImagesDeleted'
)
),
flatMapAsync(withLogging(deleteProduct)),
// TODO: when we delete a product, we should also delete all of its product variants
lift(
orThrow(
[
[ProductNotFoundBlockError, 404],
[FileStorageServiceError, 500],
],
[['undefined'], 204]
)
)
),
method: 'DELETE',
path: '/products/:productId',
validators: [isAuthenticated(), checkIdentityType(['admin'])],
});

copyProductRoute

実装

エンドポイント: POST /products/:productId/copy

アクセス: 認証が必要です。バリデーターはソース順に実行されます: isAuthenticated(), checkIdentityType(['admin']).

リクエスト: copyProductSchema は、付随する本文、パス、クエリの契約を定義します。

パイプライン: copyProduct

成功: レスポンス本文なしの 204。ソースは [['undefined'], 204] に対応付けます。

失敗: ProductNotFoundBlockError404, FileStorageServiceError500. スキーマおよびバリデーターの失敗は、合成されたミドルウェアで処理されます。

完全なソースを表示
export const copyProductRoute = withRoute({
handler: compose(
withLogging(copyProduct),

flatMapAsync(
applyPayloadArgs(
getProductByIdBlock,
[
['context', 'db', 'products'],
['context', 'data', 'productId'],
],
'product'
)
),

flatMapAsync(
applyPayloadArgs(
normalizeImagesOfProduct,
[
['context', 'fileStorageDriver'],
['context', 'data', 'product'],
],
'productWithNormalizedImages'
)
),

flatMapAsync(
applyPayloadArgs(
normalizeProduct,
[['context', 'data', 'productWithNormalizedImages']],
'normalizedProduct'
)
),

lift(
orThrow(
[
[ProductNotFoundBlockError, 404],
[FileStorageServiceError, 500],
],
[['context', 'data', 'normalizedProduct']]
)
)
),
method: 'POST',
path: '/products/:productId/copy',
validators: [isAuthenticated(), checkIdentityType(['admin'])],
});

copyProductBatchRoute

実装

エンドポイント: POST /products/batch/copy

アクセス: 認証が必要です。バリデーターはソース順に実行されます: isAuthenticated(), checkIdentityType(['admin']).

リクエスト: copyProductBatchSchema は、付随する本文、パス、クエリの契約を定義します。

パイプライン: copyProductBatchgetProductsByIds

成功: レスポンス本文なしの 204。ソースは [['undefined'], 204] に対応付けます。

失敗: ProductNotFoundBlockError404, FileStorageServiceError500. スキーマおよびバリデーターの失敗は、合成されたミドルウェアで処理されます。

完全なソースを表示
export const copyProductBatchRoute = withRoute({
handler: compose(
withLogging(copyProductBatch),
flatMapAsync(withLogging(getProductsByIds)),

flatMapAsync(
applyPayloadArgs(
normalizeImagesOfProducts,
[
['context', 'fileStorageDriver'],
['context', 'data', 'products'],
],
'productsWithNormalizedImages'
)
),

flatMapAsync(
applyPayloadArgs(
normalizeProducts,
[['context', 'data', 'productsWithNormalizedImages']],
'normalizedProducts'
)
),

lift(
orThrow(
[
[ProductNotFoundBlockError, 404],
[FileStorageServiceError, 500],
],
[['context', 'data', 'normalizedProducts']]
)
)
),
method: 'POST',
path: '/products/batch/copy',
validators: [isAuthenticated(), checkIdentityType(['admin'])],
});

getProductImageUploadUrlRoute

実装

エンドポイント: GET /products/:productId/image-upload-url

アクセス: 認証が必要です。バリデーターはソース順に実行されます: isAuthenticated(), checkIdentityType(['admin']).

リクエスト: getSignedImageUploadUrlSchema は、付随する本文、パス、クエリの契約を定義します。

パイプライン: このルートは Product ブロックと共有ユーティリティを直接合成します。以下の完全なソースを参照してください。

成功: 最終の orThrow 呼び出しによる 200

失敗: FileStorageServiceError500, ProductBlockError500. スキーマおよびバリデーターの失敗は、合成されたミドルウェアで処理されます。

完全なソースを表示
export const getProductImageUploadUrlRoute = withRoute({
handler: compose(
withLogging(
applyPayloadArgs(
generateProductImageUploadUrl,
[
['context', 'fileStorageDriver'],
['params', 'requestQuery', 'contentType'],
['params', 'requestQuery', 'contentLength'],
],
'imageUploadUrlResult'
)
),
lift(
orThrow(
[
[FileStorageServiceError, 500],
[ProductBlockError, 500],
],
[['context', 'data', 'imageUploadUrlResult'], 200]
)
)
),
method: 'GET',
path: '/products/:productId/image-upload-url',
validators: [isAuthenticated(), checkIdentityType(['admin'])],
});

createProductImageRoute

実装

エンドポイント: POST /products/:productId/images

アクセス: 認証が必要です。バリデーターはソース順に実行されます: isAuthenticated(), checkIdentityType(['admin']).

リクエスト: createProductImageSchema は、付随する本文、パス、クエリの契約を定義します。

パイプライン: このルートは Product ブロックと共有ユーティリティを直接合成します。以下の完全なソースを参照してください。

成功: 最終の orThrow 呼び出しによる 201

失敗: ProductNotFoundBlockError404, ProductImageNotFoundBlockError404, ProductUnexpectedDBError500. スキーマおよびバリデーターの失敗は、合成されたミドルウェアで処理されます。

完全なソースを表示
export const createProductImageRoute = withRoute({
handler: compose(
withLogging(
applyPayloadArgs(
createProductImage,
[
['context', 'db', 'products'],
['params', 'requestParams', 'productId'],
['params', 'requestBody'],
],
'productImageId'
)
),

flatMapAsync(
withLogging(
applyPayloadArgs(
getProductImageById,
[
['context', 'db', 'products'],
['params', 'requestParams', 'productId'],
['context', 'data', 'productImageId'],
],
'productImage'
)
)
),

flatMapAsync(
applyPayloadArgs(
normalizeProductImage,
[
['context', 'fileStorageDriver'],
['context', 'data', 'productImage'],
],
'normalizedProductImage'
)
),

lift(
orThrow(
[
[ProductNotFoundBlockError, 404],
[ProductImageNotFoundBlockError, 404],
[ProductUnexpectedDBError, 500],
],
[['context', 'data', 'normalizedProductImage'], 201]
)
)
),
method: 'POST',
path: '/products/:productId/images',
validators: [isAuthenticated(), checkIdentityType(['admin'])],
});

deleteProductImageRoute

実装

エンドポイント: DELETE /products/:productId/images/:imageId

アクセス: 認証が必要です。バリデーターはソース順に実行されます: isAuthenticated(), checkIdentityType(['admin']).

リクエスト: deleteProductImageSchema は、付随する本文、パス、クエリの契約を定義します。

パイプライン: このルートは Product ブロックと共有ユーティリティを直接合成します。以下の完全なソースを参照してください。

成功: 最終の orThrow 呼び出しによる 204

失敗: ProductNotFoundBlockError404, ProductImageNotFoundBlockError404, ProductUnexpectedDBError500, FileStorageServiceError500. スキーマおよびバリデーターの失敗は、合成されたミドルウェアで処理されます。

完全なソースを表示
export const deleteProductImageRoute = withRoute({
handler: compose(
withLogging(
applyPayloadArgs(
deleteProductImage,
[
['context', 'fileStorageDriver'],
['context', 'db', 'products'],
['params', 'requestParams', 'productId'],
['params', 'requestParams', 'imageId'],
],
'productImageDeleted'
)
),

lift(
orThrow(
[
[ProductNotFoundBlockError, 404],
[ProductImageNotFoundBlockError, 404],
[ProductUnexpectedDBError, 500],
[FileStorageServiceError, 500],
],
[['context', 'data', 'productImageDeleted'], 204]
)
)
),
method: 'DELETE',
path: '/products/:productId/images/:imageId',
validators: [isAuthenticated(), checkIdentityType(['admin'])],
});

createProductVariantRoute

実装

エンドポイント: POST /products/:productId/variants

アクセス: 認証が必要です。バリデーターはソース順に実行されます: isAuthenticated(), checkIdentityType(['admin']).

リクエスト: createProductVariantSchema は、付随する本文、パス、クエリの契約を定義します。

パイプライン: このルートは Product ブロックと共有ユーティリティを直接合成します。以下の完全なソースを参照してください。

成功: 最終の orThrow 呼び出しによる 201

失敗: ProductVariantDbError500, ProductVariantNotFoundError404. スキーマおよびバリデーターの失敗は、合成されたミドルウェアで処理されます。

完全なソースを表示
export const createProductVariantRoute = withRoute({
handler: compose(
withLogging(
applyPayloadArgs(
createProductVariant,
[
['context', 'db', 'productVariants'],
['params', 'requestBody'],
['params', 'requestParams', 'productId'],
],
'productVariantId'
)
),
flatMapAsync(
withLogging(
applyPayloadArgs(
getProductVariantById,
[
['context', 'db', 'productVariants'],
['context', 'data', 'productVariantId'],
],
'rawProductVariant'
)
)
),
flatMapAsync(
withLogging(
applyPayloadArgs(
normalizeRawDocument,
[['context', 'data', 'rawProductVariant']],
'normalizedBody'
)
)
),
lift(
withLogging(
orThrow(
[
[ProductVariantDbError, 500],
[ProductVariantNotFoundError, 404],
],
[['context', 'data', 'normalizedBody'], 201]
)
)
)
),
method: 'POST',
path: '/products/:productId/variants',
// TODO: go back and add validator to check if logged in identity is ['admin', 'owner'] of the organization of the product of the product variant
// TODO: there is also a validator that checks if the logged in identity's email is verified
validators: [isAuthenticated(), checkIdentityType(['admin'])],
});

getProductVariantRoute

実装

エンドポイント: GET /products/:productId/variants/:productVariantId

アクセス: 認証が必要です。バリデーターはソース順に実行されます: isAuthenticated().

リクエスト: getProductVariantSchema は、付随する本文、パス、クエリの契約を定義します。

パイプライン: このルートは Product ブロックと共有ユーティリティを直接合成します。以下の完全なソースを参照してください。

成功: 最終の orThrow 呼び出しによる 200

失敗: ProductVariantDbError500, ProductVariantNotFoundError404. スキーマおよびバリデーターの失敗は、合成されたミドルウェアで処理されます。

完全なソースを表示
export const getProductVariantRoute = withRoute({
handler: compose(
withLogging(
applyPayloadArgs(
getProductVariantById,
[
['context', 'db', 'productVariants'],
['params', 'requestParams', 'productVariantId'],
['params', 'requestParams', 'productId'],
],
'rawProductVariant'
)
),
flatMapAsync(
withLogging(
applyPayloadArgs(
normalizeRawDocument,
[['context', 'data', 'rawProductVariant']],
'normalizedBody'
)
)
),
lift(
withLogging(
orThrow(
[
[ProductVariantDbError, 500],
[ProductVariantNotFoundError, 404],
],
[['context', 'data', 'normalizedBody'], 200]
)
)
)
),
method: 'GET',
path: '/products/:productId/variants/:productVariantId',
validators: [isAuthenticated()],
});

updateProductVariantRoute

実装

エンドポイント: PATCH /products/:productId/variants/:productVariantId

アクセス: 認証が必要です。バリデーターはソース順に実行されます: isAuthenticated(), checkIdentityType(['admin']).

リクエスト: updateProductVariantSchema は、付随する本文、パス、クエリの契約を定義します。

パイプライン: このルートは Product ブロックと共有ユーティリティを直接合成します。以下の完全なソースを参照してください。

成功: 最終の orThrow 呼び出しによる 200

失敗: ProductVariantDbError500, ProductVariantNotFoundError404. スキーマおよびバリデーターの失敗は、合成されたミドルウェアで処理されます。

完全なソースを表示
export const updateProductVariantRoute = withRoute({
handler: compose(
withLogging(
applyPayloadArgs(
updateProductVariant,
[
['context', 'db', 'productVariants'],
['params', 'requestBody'],
['params', 'requestParams', 'productVariantId'],
],
'hasUpdatedProductVariant'
)
),
flatMapAsync(
withLogging(
applyPayloadArgs(
getProductVariantById,
[
['context', 'db', 'productVariants'],
['params', 'requestParams', 'productVariantId'],
],
'rawProductVariant'
)
)
),
flatMapAsync(
withLogging(
applyPayloadArgs(
normalizeRawDocument,
[['context', 'data', 'rawProductVariant']],
'normalizedBody'
)
)
),
lift(
withLogging(
orThrow(
[
[ProductVariantDbError, 500],
[ProductVariantNotFoundError, 404],
],
[['context', 'data', 'normalizedBody'], 200]
)
)
)
),
method: 'PATCH',
path: '/products/:productId/variants/:productVariantId',
// TODO: go back and add validator to check if logged in identity is ['admin', 'owner'] of the organization of the product of the product variant
// TODO: there is also a validator that checks if the logged in identity's email is verified
validators: [isAuthenticated(), checkIdentityType(['admin'])],
});

deleteProductVariantRoute

実装

エンドポイント: DELETE /products/:productId/variants/:productVariantId

アクセス: 認証が必要です。バリデーターはソース順に実行されます: isAuthenticated(), checkIdentityType(['admin']).

リクエスト: deleteProductVariantSchema は、付随する本文、パス、クエリの契約を定義します。

パイプライン: このルートは Product ブロックと共有ユーティリティを直接合成します。以下の完全なソースを参照してください。

成功: 最終の orThrow 呼び出しによる 204

失敗: ProductVariantDbError500. スキーマおよびバリデーターの失敗は、合成されたミドルウェアで処理されます。

完全なソースを表示
export const deleteProductVariantRoute = withRoute({
handler: compose(
withLogging(
applyPayloadArgs(
deleteProductVariant,
[
['context', 'db', 'productVariants'],
['params', 'requestParams', 'productVariantId'],
],
'hasDeletedProductVariant'
)
),
flatMapAsync(
withLogging(applyPayloadArgs(normalizeEmptyBody, [], 'normalizedBody'))
),
lift(
withLogging(
orThrow(
[[ProductVariantDbError, 500]],
[['context', 'data', 'normalizedBody'], 204]
)
)
)
),
method: 'DELETE',
path: '/products/:productId/variants/:productVariantId',
// TODO: go back and add validator to check if logged in identity is ['admin', 'owner'] of the organization of the product of the product variant
// TODO: there is also a validator that checks if the logged in identity's email is verified
validators: [isAuthenticated(), checkIdentityType(['admin'])],
});

findProductVariantsRoute

実装

エンドポイント: GET /products/:productId/variants

アクセス: 公開です。ソースはルートバリデーターを提供しません。

リクエスト: findProductVariantsSchema は、付随する本文、パス、クエリの契約を定義します。

パイプライン: このルートは Product ブロックと共有ユーティリティを直接合成します。以下の完全なソースを参照してください。

成功: 最終の orThrow 呼び出しによる 200

失敗: ProductVariantDbError500. スキーマおよびバリデーターの失敗は、合成されたミドルウェアで処理されます。

完全なソースを表示
export const findProductVariantsRoute = withRoute({
handler: compose(
withLogging(
applyPayloadArgs(
buildFilterToGetProductVariantsByProductId,
[['params', 'requestParams', 'productId']],
'filter'
)
),
flatMapAsync(
withPagination(
withLogging(
applyPayloadArgs(
findProductVariants,
[
['context', 'db', 'productVariants'],
['context', 'data', 'filter'],
],
'rawProductVariants'
)
)
)
),
flatMapAsync(
withLogging(
applyPayloadArgs(
normalizeDocuments,
[['context', 'data', 'rawProductVariants', 'data']],
'normalizedProductVariants'
)
)
),
flatMapAsync(
applyPayloadArgs(
applySpec({ data: nthArg(0), metadata: { pagination: nthArg(1) } }),
[
['context', 'data', 'normalizedProductVariants'],
['context', 'data', 'rawProductVariants', 'metadata'],
],
'normalizedBody'
)
),
lift(
withLogging(
orThrow(
[[ProductVariantDbError, 500]],
[['context', 'data', 'normalizedBody'], 200]
)
)
)
),
method: 'GET',
path: '/products/:productId/variants',
validators: [
// TODO: add validator to check productId in request params is a product that actually exists
],
});

createProductVariantBulkRoute

実装

エンドポイント: POST /product/:productId/variants/bulk

アクセス: 認証が必要です。バリデーターはソース順に実行されます: isAuthenticated(), checkIdentityType(['admin']).

リクエスト: createProductVariantBulkSchema は、付随する本文、パス、クエリの契約を定義します。

パイプライン: このルートは Product ブロックと共有ユーティリティを直接合成します。以下の完全なソースを参照してください。

成功: 最終の orThrow 呼び出しによる 201

失敗: ProductVariantDbError500. スキーマおよびバリデーターの失敗は、合成されたミドルウェアで処理されます。

完全なソースを表示
export const createProductVariantBulkRoute = withRoute({
handler: compose(
withLogging(
applyPayloadArgs(
createProductVariantBulk,
[
['context', 'db', 'productVariants'],
['params', 'requestBody'],
['params', 'requestParams', 'productId'],
],
'productVariantIds'
)
),
flatMapAsync(
withLogging(
applyPayloadArgs(
buildFilterToGetProductVariantsByIds,
[['context', 'data', 'productVariantIds']],
'filter'
)
)
),
flatMapAsync(
withLogging(
applyPayloadArgs(
findProductVariants,
[
['context', 'db', 'productVariants'],
['context', 'data', 'filter'],
],
'rawProductVariants'
)
)
),
flatMapAsync(
withLogging(
applyPayloadArgs(
normalizeDocuments,
[['context', 'data', 'rawProductVariants']],
'normalizedBody'
)
)
),
lift(
withLogging(
orThrow(
[[ProductVariantDbError, 500]],
[['context', 'data', 'normalizedBody'], 201]
)
)
)
),
method: 'POST',
path: '/product/:productId/variants/bulk',
// TODO: go back and add validator to check if logged in identity is ['admin', 'owner'] of the organization of the product (of the product variant) for each item in the bulk
// TODO: there is also a validator that checks if the logged in identity's email is verified
validators: [isAuthenticated(), checkIdentityType(['admin'])],
});

updateProductVariantBulkRoute

実装

エンドポイント: PATCH /product/:productId/variants/bulk

アクセス: 認証が必要です。バリデーターはソース順に実行されます: isAuthenticated(), checkIdentityType(['admin']).

リクエスト: updateProductVariantBulkSchema は、付随する本文、パス、クエリの契約を定義します。

パイプライン: このルートは Product ブロックと共有ユーティリティを直接合成します。以下の完全なソースを参照してください。

成功: 最終の orThrow 呼び出しによる 200

失敗: ProductVariantDbError500, ProductVariantNotFoundError404. スキーマおよびバリデーターの失敗は、合成されたミドルウェアで処理されます。

完全なソースを表示
export const updateProductVariantBulkRoute = withRoute({
handler: compose(
withLogging(
applyPayloadArgs(
updateProductVariantBulk,
[
['context', 'db', 'productVariants'],
['params', 'requestBody', 'ids'],
['params', 'requestBody', 'data'],
],
'hasUpdatedProductVariants'
)
),
flatMapAsync(
withLogging(
applyPayloadArgs(
buildFilterToGetProductVariantsByIds,
[['params', 'requestBody', 'ids']],
'filter'
)
)
),
flatMapAsync(
withLogging(
applyPayloadArgs(
findProductVariants,
[
['context', 'db', 'productVariants'],
['context', 'data', 'filter'],
],
'rawProductVariants'
)
)
),
flatMapAsync(
withLogging(
applyPayloadArgs(
normalizeDocuments,
[['context', 'data', 'rawProductVariants']],
'normalizedBody'
)
)
),
lift(
withLogging(
orThrow(
[
[ProductVariantDbError, 500],
[ProductVariantNotFoundError, 404],
],
[['context', 'data', 'normalizedBody'], 200]
)
)
)
),
method: 'PATCH',
path: '/product/:productId/variants/bulk',
// TODO: add check for if each product variant exists
// TODO: there is also a validator that checks if the logged in identity's email is verified
validators: [
isAuthenticated(),
// TODO: go back and add validator to check if logged in identity is ['admin', 'owner'] of the organization of the product of the product variant for each item in bulk
checkIdentityType(['admin']),
],
});

deleteProductVariantBulkRoute

実装

エンドポイント: POST /product/:productId/variants/bulk-delete

アクセス: 認証が必要です。バリデーターはソース順に実行されます: isAuthenticated(), checkIdentityType(['admin']).

リクエスト: deleteProductVariantBulkSchema は、付随する本文、パス、クエリの契約を定義します。

パイプライン: このルートは Product ブロックと共有ユーティリティを直接合成します。以下の完全なソースを参照してください。

成功: 最終の orThrow 呼び出しによる 204

失敗: ProductVariantDbError500. スキーマおよびバリデーターの失敗は、合成されたミドルウェアで処理されます。

完全なソースを表示
export const deleteProductVariantBulkRoute = withRoute({
handler: compose(
withLogging(
applyPayloadArgs(
deleteProductVariantBulk,
[
['context', 'db', 'productVariants'],
['params', 'requestBody'],
],
'hasDeletedProductVariants'
)
),
flatMapAsync(
withLogging(applyPayloadArgs(normalizeEmptyBody, [], 'normalizedBody'))
),
lift(
withLogging(
orThrow(
[[ProductVariantDbError, 500]],
[['context', 'data', 'normalizedBody'], 204]
)
)
)
),
method: 'POST',
path: '/product/:productId/variants/bulk-delete',
// TODO: add check for if each product variant exists
// TODO: there is also a validator that checks if the logged in identity's email is verified
validators: [
isAuthenticated(),
// TODO: go back and add validator to check if logged in identity is ['admin', 'owner'] of the organization of the product of the product variant for each item in the bulk
checkIdentityType(['admin']),
],
});

findProductsByOrganizationIdRoute

実装

エンドポイント: GET /products/organizations/:organizationId

アクセス: 認証が必要です。バリデーターはソース順に実行されます: isAuthenticated(), hasOrgRole(...).

リクエスト: findByOrganizationIdSchema は、付随する本文、パス、クエリの契約を定義します。

パイプライン: このルートは Product ブロックと共有ユーティリティを直接合成します。以下の完全なソースを参照してください。

成功: 最終の orThrow 成功マップは statusCode 記述子なしで通常のルートデータを返します。このコンポーザーは成功ステータスを設定しません。

失敗: ProductUnexpectedDBError500, FileStorageServiceError500. スキーマおよびバリデーターの失敗は、合成されたミドルウェアで処理されます。

完全なソースを表示
export const findProductsByOrganizationIdRoute = withRoute({
handler: compose(
withLogging(
applyPayloadArgs(
buildOrganizationIdFilter,
[['params', 'requestParams', 'organizationId']],
'filter'
)
),
flatMapAsync(
withLogging(
applyPayloadArgs(buildWithoutMongoIdFindOptions, [], 'options')
)
),
flatMapAsync(
withPagination(
withLogging(
applyPayloadArgs(
findProductResources,
[
['context', 'db', 'products'],
['context', 'data', 'filter'],
['context', 'data', 'options'],
],
'paginatedProducts'
)
)
)
),
flatMapAsync(
applyPayloadArgs(
normalizeImagesOfProducts,
[
['context', 'fileStorageDriver'],
['context', 'data', 'paginatedProducts', 'data'],
],
'productsWithNormalizedImages'
)
),
flatMapAsync(
applyPayloadArgs(
normalizeProducts,
[['context', 'data', 'productsWithNormalizedImages']],
'normalizedProducts'
)
),
flatMapAsync(
applyPayloadArgs(
applySpec({ data: nthArg(0), metadata: { pagination: nthArg(1) } }),
[
['context', 'data', 'normalizedProducts'],
['context', 'data', 'paginatedProducts', 'metadata'],
],
'normalizedBody'
)
),
lift(
orThrow(
[
[ProductUnexpectedDBError, 500],
[FileStorageServiceError, 500],
],
[['context', 'data', 'normalizedBody']]
)
)
),
method: 'GET',
path: '/products/organizations/:organizationId',
validators: [
isAuthenticated(),
hasOrgRole(
['owner', 'admin', 'member'],
['params', 'requestParams', 'organizationId']
),
],
});

getProductLikersRoute

実装

エンドポイント: GET /products/:productId/likers

アクセス: 認証が必要です。バリデーターはソース順に実行されます: isAuthenticated(), checkIdentityType(['admin']).

リクエスト: getProductLikersSchema は、付随する本文、パス、クエリの契約を定義します。

パイプライン: このルートは Product ブロックと共有ユーティリティを直接合成します。以下の完全なソースを参照してください。

成功: 最終の orThrow 呼び出しによる 200

失敗: ProductNotFoundBlockError404, ProductUnexpectedDBError500, ProfileDbBlockError500, AvatarBlockError500. スキーマおよびバリデーターの失敗は、合成されたミドルウェアで処理されます。

完全なソースを表示
export const getProductLikersRoute = withRoute({
handler: compose(
withLogging(
applyPayloadArgs(
getProductByIdBlock,
[
['context', 'db', 'products'],
['params', 'requestParams', 'productId'],
],
'product'
)
),

flatMapAsync(
withLogging(
applyPayloadArgs(
buildProductLikersByLikeProductIdQuery,
[['params', 'requestParams', 'productId']],
'filter'
)
)
),
flatMapAsync(
withLogging(
applyPayloadArgs(buildWithoutMongoIdFindOptions, [], 'options')
)
),
flatMapAsync(
withPagination(
withLogging(
applyPayloadArgs(
findProfiles,
[
['context', 'db', 'profiles'],
['context', 'data', 'filter'],
['context', 'data', 'options'],
],
'paginatedLikers'
)
)
)
),
flatMapAsync(
withLogging(
applyPayloadArgs(
normalizeFollowers,
[
['context', 'fileStorageDriver'],
['context', 'data', 'paginatedLikers', 'data'],
],
'normalizedLikers'
)
)
),

flatMapAsync(
applyPayloadArgs(
applySpec({ data: nthArg(0), metadata: { pagination: nthArg(1) } }),
[
['context', 'data', 'normalizedLikers'],
['context', 'data', 'paginatedLikers', 'metadata'],
],
'normalizedBody'
)
),
lift(
orThrow(
[
[ProductNotFoundBlockError, 404],
[ProductUnexpectedDBError, 500],
[ProfileDbBlockError, 500],
[AvatarBlockError, 500],
],
[['context', 'data', 'normalizedBody'], 200]
)
)
),
method: 'GET',
path: '/products/:productId/likers',
validators: [isAuthenticated(), checkIdentityType(['admin'])],
});