101 lines
2.8 KiB
TypeScript
101 lines
2.8 KiB
TypeScript
/**
|
|
* Address Controller
|
|
*
|
|
* HTTP endpoints for address lookup and management.
|
|
*/
|
|
|
|
import {
|
|
Controller,
|
|
Get,
|
|
Param,
|
|
Req,
|
|
UseGuards,
|
|
UseInterceptors,
|
|
ClassSerializerInterceptor,
|
|
} from "@nestjs/common";
|
|
import type { Request } from "express";
|
|
import { createZodDto } from "nestjs-zod";
|
|
import { Public } from "@bff/modules/auth/decorators/public.decorator.js";
|
|
import { RateLimitGuard, RateLimit } from "@bff/core/rate-limiting/index.js";
|
|
import { extractClientIp } from "@bff/core/http/request-context.util.js";
|
|
import { JapanPostFacade } from "@bff/integrations/japanpost/index.js";
|
|
import {
|
|
addressLookupResultSchema,
|
|
zipCodeLookupRequestSchema,
|
|
} from "@customer-portal/domain/address";
|
|
|
|
// ============================================================================
|
|
// DTOs
|
|
// ============================================================================
|
|
|
|
/**
|
|
* ZIP code parameter DTO
|
|
* Validates ZIP code format (with or without hyphen)
|
|
*/
|
|
class ZipCodeParamDto extends createZodDto(zipCodeLookupRequestSchema) {}
|
|
|
|
/**
|
|
* Address lookup result DTO
|
|
*/
|
|
class AddressLookupResultDto extends createZodDto(addressLookupResultSchema) {}
|
|
|
|
// ============================================================================
|
|
// Controller
|
|
// ============================================================================
|
|
|
|
@Controller("address")
|
|
@UseInterceptors(ClassSerializerInterceptor)
|
|
export class AddressController {
|
|
constructor(private readonly japanPost: JapanPostFacade) {}
|
|
|
|
/**
|
|
* Lookup address by ZIP code
|
|
*
|
|
* @route GET /api/address/lookup/zip/:zipCode
|
|
* @param zipCode - Japanese ZIP code (e.g., "100-0001" or "1000001")
|
|
* @returns Address lookup result with Japanese and romanized address data
|
|
*
|
|
* @example
|
|
* GET /api/address/lookup/zip/100-0001
|
|
* Response:
|
|
* {
|
|
* "zipCode": "1000001",
|
|
* "addresses": [
|
|
* {
|
|
* "zipCode": "1000001",
|
|
* "prefecture": "東京都",
|
|
* "city": "千代田区",
|
|
* "town": "千代田",
|
|
* "prefectureRoma": "Tokyo",
|
|
* "cityRoma": "Chiyoda-ku",
|
|
* "townRoma": "Chiyoda"
|
|
* }
|
|
* ],
|
|
* "count": 1
|
|
* }
|
|
*/
|
|
@Public()
|
|
@Get("lookup/zip/:zipCode")
|
|
@UseGuards(RateLimitGuard)
|
|
@RateLimit({ limit: 30, ttl: 60 }) // 30 requests per minute
|
|
async lookupByZipCode(
|
|
@Param() params: ZipCodeParamDto,
|
|
@Req() req: Request
|
|
): Promise<AddressLookupResultDto> {
|
|
const clientIp = extractClientIp(req);
|
|
return this.japanPost.lookupByZipCode(params.zipCode, clientIp);
|
|
}
|
|
|
|
/**
|
|
* Check if address lookup service is available
|
|
*
|
|
* @route GET /api/address/status
|
|
* @returns Service availability status
|
|
*/
|
|
@Public()
|
|
@Get("status")
|
|
getStatus(): { available: boolean } {
|
|
return { available: this.japanPost.isAvailable() };
|
|
}
|
|
}
|