daiso 1.0.4 → 1.0.6

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 (166) hide show
  1. package/README.md +249 -533
  2. package/dist/api/actionsProxy.js +82 -0
  3. package/dist/api/cgvHandlers.js +103 -16
  4. package/dist/api/configStatus.js +19 -0
  5. package/dist/api/daisoHandlers.js +127 -0
  6. package/dist/api/emart24Handlers.js +176 -0
  7. package/dist/api/gs25Handlers.js +267 -0
  8. package/dist/api/handlers.js +209 -104
  9. package/dist/api/healthChecks.js +504 -0
  10. package/dist/api/lottecinemaHandlers.js +155 -0
  11. package/dist/api/lottemartHandlers.js +144 -0
  12. package/dist/api/megaboxHandlers.js +81 -50
  13. package/dist/api/response.js +2 -0
  14. package/dist/api/routes/cuRoutes.js +17 -0
  15. package/dist/api/routes/daisoRoutes.js +6 -1
  16. package/dist/api/routes/emart24Routes.js +22 -0
  17. package/dist/api/routes/gs25Routes.js +22 -0
  18. package/dist/api/routes/healthRoutes.js +61 -0
  19. package/dist/api/routes/lottecinemaRoutes.js +22 -0
  20. package/dist/api/routes/lottemartRoutes.js +18 -0
  21. package/dist/api/routes/oliveyoungRoutes.js +6 -1
  22. package/dist/api/routes/sevenelevenRoutes.js +32 -0
  23. package/dist/api/sevenelevenHandlers.js +200 -0
  24. package/dist/bin.js +0 -0
  25. package/dist/cli/args.js +75 -0
  26. package/dist/cli/commandOptions.js +38 -0
  27. package/dist/cli/commands/convenience.js +293 -0
  28. package/dist/cli/commands/daiso.js +112 -0
  29. package/dist/cli/constants.js +5 -0
  30. package/dist/cli/deps.js +48 -0
  31. package/dist/cli/http.js +156 -0
  32. package/dist/cli/interactiveFetch.js +31 -0
  33. package/dist/cli/interactiveItemSearch.js +261 -0
  34. package/dist/cli/interactivePrompt.js +50 -0
  35. package/dist/cli/interactiveTypes.js +4 -0
  36. package/dist/cli/types.js +4 -0
  37. package/dist/cli.js +87 -196
  38. package/dist/cliHelp.js +212 -1
  39. package/dist/cliInteractive.js +243 -0
  40. package/dist/cliPicker.js +57 -0
  41. package/dist/cliRenderer.js +90 -3
  42. package/dist/core/errors.js +66 -0
  43. package/dist/core/registry.js +227 -3
  44. package/dist/index.js +149 -9
  45. package/dist/pages/openapi.js +2 -1
  46. package/dist/pages/openapiFullSpec.js +58 -0
  47. package/dist/pages/openapiResponse.js +28 -0
  48. package/dist/pages/openapiSpec.js +2 -41
  49. package/dist/pages/openapiSpecActions.js +109 -0
  50. package/dist/pages/openapiSpecComponents.js +30 -391
  51. package/dist/pages/openapiSpecComponentsCgv.js +24 -0
  52. package/dist/pages/openapiSpecComponentsCu.js +112 -0
  53. package/dist/pages/openapiSpecComponentsDaisoOliveyoung.js +342 -0
  54. package/dist/pages/openapiSpecComponentsEmart24.js +141 -0
  55. package/dist/pages/openapiSpecComponentsGs25.js +109 -0
  56. package/dist/pages/openapiSpecComponentsLotteMart.js +85 -0
  57. package/dist/pages/openapiSpecComponentsLottecinema.js +163 -0
  58. package/dist/pages/openapiSpecComponentsMegabox.js +144 -0
  59. package/dist/pages/openapiSpecComponentsSeveneleven.js +82 -0
  60. package/dist/pages/openapiSpecPathsCgv.js +66 -3
  61. package/dist/pages/openapiSpecPathsCu.js +145 -0
  62. package/dist/pages/openapiSpecPathsDaiso.js +302 -0
  63. package/dist/pages/openapiSpecPathsDaisoOliveyoung.js +4 -376
  64. package/dist/pages/openapiSpecPathsEmart24.js +223 -0
  65. package/dist/pages/openapiSpecPathsGs25.js +166 -0
  66. package/dist/pages/openapiSpecPathsLotteMart.js +149 -0
  67. package/dist/pages/openapiSpecPathsLottecinema.js +212 -0
  68. package/dist/pages/openapiSpecPathsMegabox.js +52 -3
  69. package/dist/pages/openapiSpecPathsOliveyoung.js +266 -0
  70. package/dist/pages/openapiSpecPathsSeveneleven.js +234 -0
  71. package/dist/pages/prompt.js +8 -402
  72. package/dist/pages/promptCoreText.js +278 -0
  73. package/dist/pages/promptReferenceText.js +137 -0
  74. package/dist/pages/promptRetailCinemaText.js +274 -0
  75. package/dist/services/cgv/client.js +6 -1
  76. package/dist/services/cgv/index.js +3 -3
  77. package/dist/services/cgv/location.js +235 -0
  78. package/dist/services/cgv/tools/findTheaters.js +30 -5
  79. package/dist/services/cgv/tools/getTimetable.js +42 -14
  80. package/dist/services/cgv/tools/searchMovies.js +40 -12
  81. package/dist/services/cgv/transport.js +0 -3
  82. package/dist/services/cu/api.js +11 -0
  83. package/dist/services/cu/client.js +297 -0
  84. package/dist/services/cu/index.js +21 -0
  85. package/dist/services/cu/tools/checkInventory.js +123 -0
  86. package/dist/services/cu/tools/findNearbyStores.js +49 -0
  87. package/dist/services/cu/types.js +4 -0
  88. package/dist/services/daiso/api.js +22 -2
  89. package/dist/services/daiso/client.js +67 -0
  90. package/dist/services/daiso/index.js +4 -0
  91. package/dist/services/daiso/product.js +17 -0
  92. package/dist/services/daiso/tools/checkInventory.js +80 -43
  93. package/dist/services/daiso/tools/findInventoryByName.js +222 -0
  94. package/dist/services/daiso/tools/findStores.js +17 -7
  95. package/dist/services/daiso/tools/getDisplayLocation.js +75 -0
  96. package/dist/services/emart24/api.js +11 -0
  97. package/dist/services/emart24/client.js +182 -0
  98. package/dist/services/emart24/index.js +22 -0
  99. package/dist/services/emart24/inventoryLookup.js +134 -0
  100. package/dist/services/emart24/tools/checkInventory.js +54 -0
  101. package/dist/services/emart24/tools/findNearbyStores.js +72 -0
  102. package/dist/services/emart24/tools/searchProducts.js +73 -0
  103. package/dist/services/emart24/types.js +4 -0
  104. package/dist/services/gs25/api.js +9 -0
  105. package/dist/services/gs25/client.js +208 -0
  106. package/dist/services/gs25/index.js +22 -0
  107. package/dist/services/gs25/storeUtils.js +168 -0
  108. package/dist/services/gs25/tools/checkInventory.js +163 -0
  109. package/dist/services/gs25/tools/findNearbyStores.js +103 -0
  110. package/dist/services/gs25/tools/searchProducts.js +57 -0
  111. package/dist/services/gs25/types.js +4 -0
  112. package/dist/services/lottecinema/api.js +12 -0
  113. package/dist/services/lottecinema/client.js +161 -0
  114. package/dist/services/lottecinema/index.js +30 -0
  115. package/dist/services/lottecinema/location.js +191 -0
  116. package/dist/services/lottecinema/tools/findNearbyTheaters.js +47 -0
  117. package/dist/services/lottecinema/tools/getRemainingSeats.js +85 -0
  118. package/dist/services/lottecinema/tools/listNowShowing.js +79 -0
  119. package/dist/services/lottecinema/types.js +4 -0
  120. package/dist/services/lottemart/api.js +31 -0
  121. package/dist/services/lottemart/client.js +254 -0
  122. package/dist/services/lottemart/clientTypes.js +4 -0
  123. package/dist/services/lottemart/config.js +4 -0
  124. package/dist/services/lottemart/debug.js +92 -0
  125. package/dist/services/lottemart/geocode.js +49 -0
  126. package/dist/services/lottemart/index.js +30 -0
  127. package/dist/services/lottemart/keyword.js +29 -0
  128. package/dist/services/lottemart/parser.js +185 -0
  129. package/dist/services/lottemart/session.js +331 -0
  130. package/dist/services/lottemart/storeSearch.js +52 -0
  131. package/dist/services/lottemart/tools/findNearbyStores.js +67 -0
  132. package/dist/services/lottemart/tools/searchProducts.js +69 -0
  133. package/dist/services/lottemart/types.js +4 -0
  134. package/dist/services/lottemart/zetta.js +105 -0
  135. package/dist/services/megabox/location.js +219 -0
  136. package/dist/services/megabox/tools/findNearbyTheaters.js +13 -44
  137. package/dist/services/megabox/tools/getRemainingSeats.js +31 -3
  138. package/dist/services/megabox/tools/listNowShowing.js +31 -3
  139. package/dist/services/oliveyoung/api.js +2 -0
  140. package/dist/services/oliveyoung/client.js +225 -13
  141. package/dist/services/oliveyoung/index.js +3 -1
  142. package/dist/services/oliveyoung/tools/checkInventory.js +21 -5
  143. package/dist/services/oliveyoung/tools/searchProducts.js +57 -0
  144. package/dist/services/seveneleven/api.js +15 -0
  145. package/dist/services/seveneleven/client.js +286 -0
  146. package/dist/services/seveneleven/index.js +30 -0
  147. package/dist/services/seveneleven/inventory.js +302 -0
  148. package/dist/services/seveneleven/productKeyword.js +141 -0
  149. package/dist/services/seveneleven/tools/checkInventory.js +82 -0
  150. package/dist/services/seveneleven/tools/getCatalogSnapshot.js +55 -0
  151. package/dist/services/seveneleven/tools/getSearchPopwords.js +41 -0
  152. package/dist/services/seveneleven/tools/searchProducts.js +67 -0
  153. package/dist/services/seveneleven/tools/searchStores.js +45 -0
  154. package/dist/services/seveneleven/types.js +4 -0
  155. package/dist/utils/cliInteractiveHelpers.js +63 -0
  156. package/dist/utils/daisoKeyword.js +30 -0
  157. package/dist/utils/http.js +98 -12
  158. package/dist/utils/zyte.js +47 -26
  159. package/openapi.json +1979 -736
  160. package/openapi.yaml +1428 -541
  161. package/package.json +49 -18
  162. package/dist/tools/checkInventory.js +0 -98
  163. package/dist/tools/findStores.js +0 -125
  164. package/dist/tools/getPriceInfo.js +0 -77
  165. package/dist/tools/searchProducts.js +0 -61
  166. package/dist/types/index.js +0 -4
@@ -0,0 +1,109 @@
1
+ /**
2
+ * OpenAI Actions용 축약 OpenAPI 스펙
3
+ */
4
+ import { ACTION_QUERY_ACTIONS } from '../api/actionsProxy.js';
5
+ import { OPENAPI_COMPONENTS } from './openapiSpecComponents.js';
6
+ const ACTION_QUERY_PARAMETERS = [
7
+ {
8
+ name: 'action',
9
+ in: 'query',
10
+ required: true,
11
+ description: '실행할 액션 이름입니다. 사용 가능한 값은 enum 목록을 참고하세요.',
12
+ schema: {
13
+ type: 'string',
14
+ enum: ACTION_QUERY_ACTIONS,
15
+ },
16
+ },
17
+ { name: 'q', in: 'query', required: false, description: '다이소 제품 검색어', schema: { type: 'string' } },
18
+ { name: 'query', in: 'query', required: false, description: '세븐일레븐 상품 검색어', schema: { type: 'string' } },
19
+ { name: 'itemCode', in: 'query', required: false, description: 'GS25 상품 코드', schema: { type: 'string' } },
20
+ { name: 'productId', in: 'query', required: false, description: '제품 ID 또는 상세 조회용 path 파라미터. 상품명만 알면 먼저 daisoSearchProducts 또는 /api/daiso/products로 productId를 확인하세요.', schema: { type: 'string' } },
21
+ { name: 'keyword', in: 'query', required: false, description: '공통 키워드 파라미터', schema: { type: 'string' } },
22
+ { name: 'sido', in: 'query', required: false, description: '다이소 시/도', schema: { type: 'string' } },
23
+ { name: 'gugun', in: 'query', required: false, description: '다이소 구/군', schema: { type: 'string' } },
24
+ { name: 'dong', in: 'query', required: false, description: '다이소 동', schema: { type: 'string' } },
25
+ { name: 'area', in: 'query', required: false, description: '롯데마트 지역', schema: { type: 'string' } },
26
+ { name: 'area1', in: 'query', required: false, description: '이마트24 1차 지역', schema: { type: 'string' } },
27
+ { name: 'area2', in: 'query', required: false, description: '이마트24 2차 지역', schema: { type: 'string' } },
28
+ { name: 'areaCode', in: 'query', required: false, description: '메가박스 지역 코드', schema: { type: 'string' } },
29
+ { name: 'brandVariant', in: 'query', required: false, description: '롯데마트 브랜드 변형', schema: { type: 'string' } },
30
+ { name: 'lat', in: 'query', required: false, description: '위도', schema: { type: 'number', format: 'float' } },
31
+ { name: 'lng', in: 'query', required: false, description: '경도', schema: { type: 'number', format: 'float' } },
32
+ { name: 'page', in: 'query', required: false, description: '페이지 번호', schema: { type: 'integer' } },
33
+ { name: 'pageIdx', in: 'query', required: false, description: '올리브영 페이지 번호', schema: { type: 'integer' } },
34
+ { name: 'pageLimit', in: 'query', required: false, description: '롯데마트 추가 페이지 수', schema: { type: 'integer' } },
35
+ { name: 'pageSize', in: 'query', required: false, description: '페이지 크기', schema: { type: 'integer' } },
36
+ { name: 'size', in: 'query', required: false, description: '페이지 크기 또는 검색 크기', schema: { type: 'integer' } },
37
+ { name: 'offset', in: 'query', required: false, description: 'CU 검색 오프셋', schema: { type: 'integer' } },
38
+ { name: 'limit', in: 'query', required: false, description: '최대 결과 수', schema: { type: 'integer' } },
39
+ { name: 'storeLimit', in: 'query', required: false, description: '매장 결과 제한 수', schema: { type: 'integer' } },
40
+ { name: 'storeCode', in: 'query', required: false, description: '매장 코드. 다이소 진열 위치는 /api/daiso/inventory 응답의 storeInventory.stores[].storeCode에서 확인하세요.', schema: { type: 'string' } },
41
+ { name: 'storeName', in: 'query', required: false, description: '매장명. 롯데마트 상품 조회에서 storeCode가 없을 때 사용하며, 모르면 먼저 lottemartFindNearbyStores 또는 /api/lottemart/stores로 확인하세요.', schema: { type: 'string' } },
42
+ { name: 'storeKeyword', in: 'query', required: false, description: '매장 키워드', schema: { type: 'string' } },
43
+ { name: 'playDate', in: 'query', required: false, description: '상영일(YYYYMMDD)', schema: { type: 'string' } },
44
+ { name: 'regionCode', in: 'query', required: false, description: 'CGV 지역 코드', schema: { type: 'string' } },
45
+ { name: 'theaterCode', in: 'query', required: false, description: 'CGV 극장 코드', schema: { type: 'string' } },
46
+ { name: 'theaterId', in: 'query', required: false, description: '메가박스/롯데시네마 지점 ID', schema: { type: 'string' } },
47
+ { name: 'movieCode', in: 'query', required: false, description: 'CGV 영화 코드', schema: { type: 'string' } },
48
+ { name: 'movieId', in: 'query', required: false, description: '메가박스/롯데시네마 영화 ID', schema: { type: 'string' } },
49
+ { name: 'pluCd', in: 'query', required: false, description: '이마트24 상품 PLU 코드', schema: { type: 'string' } },
50
+ { name: 'bizNoArr', in: 'query', required: false, description: '이마트24 사업자번호 목록', schema: { type: 'string' } },
51
+ { name: 'label', in: 'query', required: false, description: '세븐일레븐 인기 검색어 라벨', schema: { type: 'string' } },
52
+ { name: 'sort', in: 'query', required: false, description: '정렬 기준', schema: { type: 'string' } },
53
+ { name: 'searchSort', in: 'query', required: false, description: 'CU 검색 정렬 기준', schema: { type: 'string' } },
54
+ { name: 'service24h', in: 'query', required: false, description: '이마트24 24시간 필터', schema: { type: 'boolean' } },
55
+ { name: 'includeSoldOut', in: 'query', required: false, description: '올리브영 품절 포함 여부', schema: { type: 'boolean' } },
56
+ { name: 'includeIssues', in: 'query', required: false, description: '세븐일레븐 이달의 행사지 포함 여부', schema: { type: 'boolean' } },
57
+ { name: 'includeExhibition', in: 'query', required: false, description: '세븐일레븐 전시상품 포함 여부', schema: { type: 'boolean' } },
58
+ { name: 'timeoutMs', in: 'query', required: false, description: '세븐일레븐 inventory 타임아웃', schema: { type: 'integer' } },
59
+ ];
60
+ export function generateOpenApiSpec(baseUrl) {
61
+ return {
62
+ openapi: '3.1.0',
63
+ info: {
64
+ title: '다이소 MCP API (OpenAI Actions용)',
65
+ description: `OpenAI 챗봇의 OpenAPI import 개수 제한을 피하기 위해 모든 GET API를 단일 facade 엔드포인트로 집약한 스펙입니다.
66
+
67
+ 실제 런타임은 기존 /api/{service}/... 엔드포인트로 위임하며, 이 스펙은 OpenAI Actions 등록 전용으로 사용합니다.
68
+
69
+ 브랜드명이 요청 앞부분에 나오면 뒤의 상품/재고 요청까지 같은 브랜드로 해석해야 합니다. 예: "안산 중앙역 주변 다이소 찾아주시고 핫식스 재고 찾아주세요"는 다이소 기준 조회를 먼저 수행하고, 결과가 없을 때만 다른 브랜드를 제안합니다.
70
+
71
+ 전체 개별 엔드포인트 스펙이 필요하면 /openapi-full.json 또는 /openapi-full.yaml 을 사용하세요.`,
72
+ version: '1.0.0',
73
+ contact: {
74
+ name: 'GitHub Repository',
75
+ url: 'https://github.com/hmmhmmhm/daiso-mcp',
76
+ },
77
+ },
78
+ servers: [{ url: baseUrl, description: 'Production Server' }],
79
+ paths: {
80
+ '/api/actions/query': {
81
+ get: {
82
+ operationId: 'queryAction',
83
+ summary: '공통 GET 액션 실행',
84
+ description: 'action 값에 따라 기존 GET API 엔드포인트로 프록시합니다. OpenAI Actions 등록 시 이 단일 엔드포인트를 사용하세요.',
85
+ parameters: ACTION_QUERY_PARAMETERS,
86
+ responses: {
87
+ '200': {
88
+ description: '프록시 호출 성공',
89
+ content: {
90
+ 'application/json': {
91
+ schema: { $ref: '#/components/schemas/ActionQueryResponse' },
92
+ },
93
+ },
94
+ },
95
+ '400': {
96
+ description: '잘못된 요청',
97
+ content: {
98
+ 'application/json': {
99
+ schema: { $ref: '#/components/schemas/ErrorResponse' },
100
+ },
101
+ },
102
+ },
103
+ },
104
+ },
105
+ },
106
+ },
107
+ components: OPENAPI_COMPONENTS,
108
+ };
109
+ }
@@ -2,416 +2,55 @@
2
2
  * OpenAPI 컴포넌트 스키마 정의
3
3
  */
4
4
  import { OPENAPI_CGV_COMPONENT_SCHEMAS } from './openapiSpecComponentsCgv.js';
5
+ import { OPENAPI_CU_COMPONENT_SCHEMAS } from './openapiSpecComponentsCu.js';
6
+ import { OPENAPI_DAISO_OLIVEYOUNG_COMPONENT_SCHEMAS } from './openapiSpecComponentsDaisoOliveyoung.js';
7
+ import { OPENAPI_EMART24_COMPONENT_SCHEMAS } from './openapiSpecComponentsEmart24.js';
8
+ import { OPENAPI_GS25_COMPONENT_SCHEMAS } from './openapiSpecComponentsGs25.js';
9
+ import { OPENAPI_LOTTECINEMA_COMPONENT_SCHEMAS } from './openapiSpecComponentsLottecinema.js';
10
+ import { OPENAPI_LOTTEMART_COMPONENT_SCHEMAS } from './openapiSpecComponentsLotteMart.js';
11
+ import { OPENAPI_MEGABOX_COMPONENT_SCHEMAS } from './openapiSpecComponentsMegabox.js';
12
+ import { OPENAPI_SEVENELEVEN_COMPONENT_SCHEMAS } from './openapiSpecComponentsSeveneleven.js';
5
13
  export const OPENAPI_COMPONENTS = {
6
14
  schemas: {
7
- Product: {
8
- type: 'object',
9
- description: '제품 정보',
10
- properties: {
11
- id: { type: 'string', description: '제품 ID', example: '1234567890' },
12
- name: { type: 'string', description: '제품명', example: 'PP 수납박스 대형' },
13
- price: { type: 'integer', description: '가격 (원)', example: 5000 },
14
- imageUrl: {
15
- type: 'string',
16
- description: '제품 이미지 URL',
17
- example: 'https://img.daisomall.co.kr/...',
18
- },
19
- soldOut: { type: 'boolean', description: '품절 여부', example: false },
20
- isNew: { type: 'boolean', description: '신상품 여부', example: false },
21
- pickupAvailable: { type: 'boolean', description: '매장 픽업 가능 여부', example: true },
22
- },
23
- },
24
- ProductDetail: {
25
- type: 'object',
26
- description: '제품 상세 정보',
27
- properties: {
28
- id: { type: 'string', description: '제품 ID' },
29
- name: { type: 'string', description: '제품명' },
30
- price: { type: 'integer', description: '가격 (원)' },
31
- currency: { type: 'string', description: '통화', example: 'KRW' },
32
- imageUrl: { type: 'string', description: '제품 이미지 URL' },
33
- brand: { type: 'string', description: '브랜드명' },
34
- soldOut: { type: 'boolean', description: '품절 여부' },
35
- isNew: { type: 'boolean', description: '신상품 여부' },
36
- },
37
- },
38
- Store: {
39
- type: 'object',
40
- description: '매장 정보',
41
- properties: {
42
- name: { type: 'string', description: '매장명', example: '다이소 강남역점' },
43
- phone: { type: 'string', description: '전화번호', example: '02-1234-5678' },
44
- address: {
45
- type: 'string',
46
- description: '주소',
47
- example: '서울특별시 강남구 강남대로 123',
48
- },
49
- lat: { type: 'number', format: 'float', description: '위도', example: 37.4979 },
50
- lng: { type: 'number', format: 'float', description: '경도', example: 127.0276 },
51
- openTime: { type: 'string', description: '영업 시작 시간', example: '10:00' },
52
- closeTime: { type: 'string', description: '영업 종료 시간', example: '22:00' },
53
- options: {
54
- type: 'object',
55
- description: '매장 옵션',
56
- properties: {
57
- parking: { type: 'boolean', description: '주차 가능 여부' },
58
- pickup: { type: 'boolean', description: '픽업 가능 여부' },
59
- taxFree: { type: 'boolean', description: '면세 가능 여부' },
60
- },
61
- },
62
- },
63
- },
64
- StoreInventory: {
65
- type: 'object',
66
- description: '매장 재고 정보',
67
- properties: {
68
- storeCode: { type: 'string', description: '매장 코드', example: 'ST001' },
69
- storeName: { type: 'string', description: '매장명', example: '다이소 강남역점' },
70
- address: { type: 'string', description: '주소' },
71
- distance: { type: 'string', description: '거리', example: '0.5km' },
72
- quantity: { type: 'integer', description: '재고 수량', example: 12 },
73
- options: {
74
- type: 'object',
75
- properties: {
76
- parking: { type: 'boolean' },
77
- pickup: { type: 'boolean' },
78
- },
79
- },
80
- },
81
- },
82
- ProductSearchResponse: {
83
- type: 'object',
84
- properties: {
85
- success: { type: 'boolean', example: true },
86
- data: {
87
- type: 'object',
88
- properties: {
89
- products: { type: 'array', items: { $ref: '#/components/schemas/Product' } },
90
- },
91
- },
92
- meta: {
93
- type: 'object',
94
- properties: {
95
- total: { type: 'integer', description: '전체 결과 수' },
96
- page: { type: 'integer', description: '현재 페이지' },
97
- pageSize: { type: 'integer', description: '페이지당 결과 수' },
98
- },
99
- },
100
- },
101
- },
102
- ProductDetailResponse: {
103
- type: 'object',
104
- properties: {
105
- success: { type: 'boolean', example: true },
106
- data: { $ref: '#/components/schemas/ProductDetail' },
107
- },
108
- },
109
- StoreSearchResponse: {
110
- type: 'object',
111
- properties: {
112
- success: { type: 'boolean', example: true },
113
- data: {
114
- type: 'object',
115
- properties: {
116
- stores: { type: 'array', items: { $ref: '#/components/schemas/Store' } },
117
- },
118
- },
119
- meta: {
120
- type: 'object',
121
- properties: { total: { type: 'integer', description: '전체 결과 수' } },
122
- },
123
- },
124
- },
125
- InventoryResponse: {
126
- type: 'object',
127
- properties: {
128
- success: { type: 'boolean', example: true },
129
- data: {
130
- type: 'object',
131
- properties: {
132
- productId: { type: 'string', description: '제품 ID' },
133
- location: {
134
- type: 'object',
135
- properties: {
136
- latitude: { type: 'number', format: 'float' },
137
- longitude: { type: 'number', format: 'float' },
138
- },
139
- },
140
- onlineStock: { type: 'integer', description: '온라인 재고 수량', example: 150 },
141
- storeInventory: {
142
- type: 'object',
143
- properties: {
144
- totalStores: { type: 'integer', description: '전체 매장 수' },
145
- inStockCount: { type: 'integer', description: '재고 있는 매장 수' },
146
- stores: {
147
- type: 'array',
148
- items: { $ref: '#/components/schemas/StoreInventory' },
149
- },
150
- },
151
- },
152
- },
153
- },
154
- meta: {
155
- type: 'object',
156
- properties: {
157
- total: { type: 'integer' },
158
- page: { type: 'integer' },
159
- pageSize: { type: 'integer' },
160
- },
161
- },
162
- },
163
- },
164
- OliveyoungStore: {
165
- type: 'object',
166
- description: '올리브영 매장 정보',
167
- properties: {
168
- storeCode: { type: 'string', example: 'D176' },
169
- storeName: { type: 'string', example: '올리브영 명동 타운' },
170
- address: { type: 'string', example: '서울특별시 중구 명동길 53' },
171
- latitude: { type: 'number', format: 'float', example: 37.56409158 },
172
- longitude: { type: 'number', format: 'float', example: 126.9851771 },
173
- pickupYn: { type: 'boolean', example: false },
174
- o2oRemainQuantity: { type: 'integer', example: 0 },
175
- },
176
- },
177
- OliveyoungProduct: {
178
- type: 'object',
179
- description: '올리브영 상품 재고 정보',
180
- properties: {
181
- goodsNumber: { type: 'string', example: 'A000000200614' },
182
- goodsName: { type: 'string', example: '달바 퍼플 톤업 선크림 듀오 기획' },
183
- priceToPay: { type: 'integer', example: 32130 },
184
- originalPrice: { type: 'integer', example: 51000 },
185
- discountRate: { type: 'integer', example: 37 },
186
- o2oStockFlag: { type: 'boolean', example: true },
187
- o2oRemainQuantity: { type: 'integer', example: 0 },
188
- },
189
- },
190
- OliveyoungStoreSearchResponse: {
191
- type: 'object',
192
- properties: {
193
- success: { type: 'boolean', example: true },
194
- data: {
195
- type: 'object',
196
- properties: {
197
- stores: {
198
- type: 'array',
199
- items: { $ref: '#/components/schemas/OliveyoungStore' },
200
- },
201
- },
202
- },
203
- meta: {
204
- type: 'object',
205
- properties: {
206
- total: { type: 'integer' },
207
- page: { type: 'integer' },
208
- pageSize: { type: 'integer' },
209
- },
210
- },
211
- },
212
- },
213
- OliveyoungInventoryResponse: {
214
- type: 'object',
215
- properties: {
216
- success: { type: 'boolean', example: true },
217
- data: {
218
- type: 'object',
219
- properties: {
220
- keyword: { type: 'string', example: '선크림' },
221
- location: {
222
- type: 'object',
223
- properties: {
224
- latitude: { type: 'number', format: 'float' },
225
- longitude: { type: 'number', format: 'float' },
226
- },
227
- },
228
- nearbyStores: {
229
- type: 'object',
230
- properties: {
231
- totalCount: { type: 'integer' },
232
- stores: {
233
- type: 'array',
234
- items: { $ref: '#/components/schemas/OliveyoungStore' },
235
- },
236
- },
237
- },
238
- inventory: {
239
- type: 'object',
240
- properties: {
241
- totalCount: { type: 'integer' },
242
- nextPage: { type: 'boolean' },
243
- products: {
244
- type: 'array',
245
- items: { $ref: '#/components/schemas/OliveyoungProduct' },
246
- },
247
- },
248
- },
249
- },
250
- },
251
- meta: {
252
- type: 'object',
253
- properties: {
254
- total: { type: 'integer' },
255
- page: { type: 'integer' },
256
- pageSize: { type: 'integer' },
257
- },
258
- },
259
- },
260
- },
261
- MegaboxTheater: {
262
- type: 'object',
263
- properties: {
264
- theaterId: { type: 'string', example: '1372' },
265
- theaterName: { type: 'string', example: '강남' },
266
- address: { type: 'string', example: '서울특별시 강남구 강남대로 438' },
267
- latitude: { type: 'number', format: 'float', example: 37.4982 },
268
- longitude: { type: 'number', format: 'float', example: 127.0264 },
269
- distanceKm: { type: 'number', format: 'float', example: 0.5 },
270
- },
271
- },
272
- MegaboxShowtime: {
273
- type: 'object',
274
- properties: {
275
- scheduleId: { type: 'string', example: '2603041372011' },
276
- movieId: { type: 'string', example: '25104500' },
277
- movieName: { type: 'string', example: '미키 17' },
278
- theaterId: { type: 'string', example: '1372' },
279
- theaterName: { type: 'string', example: '강남' },
280
- playDate: { type: 'string', example: '20260304' },
281
- startTime: { type: 'string', example: '09:30' },
282
- endTime: { type: 'string', example: '11:20' },
283
- totalSeats: { type: 'integer', example: 120 },
284
- remainingSeats: { type: 'integer', example: 42 },
285
- },
286
- },
287
- MegaboxTheaterSearchResponse: {
288
- type: 'object',
289
- properties: {
290
- success: { type: 'boolean', example: true },
291
- data: {
292
- type: 'object',
293
- properties: {
294
- location: {
295
- type: 'object',
296
- properties: {
297
- latitude: { type: 'number', format: 'float' },
298
- longitude: { type: 'number', format: 'float' },
299
- },
300
- },
301
- playDate: { type: 'string' },
302
- areaCode: { type: 'string' },
303
- theaters: {
304
- type: 'array',
305
- items: { $ref: '#/components/schemas/MegaboxTheater' },
306
- },
307
- },
308
- },
309
- meta: {
310
- type: 'object',
311
- properties: {
312
- total: { type: 'integer' },
313
- pageSize: { type: 'integer' },
314
- },
315
- },
316
- },
317
- },
318
- MegaboxMovieListResponse: {
15
+ ...OPENAPI_DAISO_OLIVEYOUNG_COMPONENT_SCHEMAS,
16
+ ...OPENAPI_MEGABOX_COMPONENT_SCHEMAS,
17
+ ...OPENAPI_CU_COMPONENT_SCHEMAS,
18
+ ...OPENAPI_EMART24_COMPONENT_SCHEMAS,
19
+ ...OPENAPI_LOTTEMART_COMPONENT_SCHEMAS,
20
+ ...OPENAPI_GS25_COMPONENT_SCHEMAS,
21
+ ...OPENAPI_SEVENELEVEN_COMPONENT_SCHEMAS,
22
+ ...OPENAPI_LOTTECINEMA_COMPONENT_SCHEMAS,
23
+ ...OPENAPI_CGV_COMPONENT_SCHEMAS,
24
+ ErrorResponse: {
319
25
  type: 'object',
320
26
  properties: {
321
- success: { type: 'boolean', example: true },
322
- data: {
27
+ success: { type: 'boolean', example: false },
28
+ error: {
323
29
  type: 'object',
324
30
  properties: {
325
- playDate: { type: 'string' },
326
- filters: {
327
- type: 'object',
328
- properties: {
329
- theaterId: { type: 'string', nullable: true },
330
- movieId: { type: 'string', nullable: true },
331
- areaCode: { type: 'string' },
332
- },
333
- },
334
- theaters: {
335
- type: 'array',
336
- items: {
337
- type: 'object',
338
- properties: {
339
- theaterId: { type: 'string' },
340
- theaterName: { type: 'string' },
341
- },
342
- },
343
- },
344
- movies: {
345
- type: 'array',
346
- items: {
347
- type: 'object',
348
- properties: {
349
- movieId: { type: 'string' },
350
- movieName: { type: 'string' },
351
- movieStatus: { type: 'string' },
352
- },
353
- },
354
- },
355
- showtimes: {
356
- type: 'array',
357
- items: { $ref: '#/components/schemas/MegaboxShowtime' },
31
+ code: { type: 'string', description: '에러 코드', example: 'MISSING_QUERY' },
32
+ message: {
33
+ type: 'string',
34
+ description: '에러 메시지',
35
+ example: '검색어(q)를 입력해주세요.',
358
36
  },
359
37
  },
360
38
  },
361
- meta: {
362
- type: 'object',
363
- properties: {
364
- total: { type: 'integer' },
365
- },
366
- },
367
39
  },
368
40
  },
369
- MegaboxSeatListResponse: {
41
+ ActionQueryResponse: {
370
42
  type: 'object',
371
43
  properties: {
372
44
  success: { type: 'boolean', example: true },
373
45
  data: {
374
46
  type: 'object',
375
- properties: {
376
- playDate: { type: 'string' },
377
- filters: {
378
- type: 'object',
379
- properties: {
380
- theaterId: { type: 'string', nullable: true },
381
- movieId: { type: 'string', nullable: true },
382
- areaCode: { type: 'string' },
383
- },
384
- },
385
- seats: {
386
- type: 'array',
387
- items: { $ref: '#/components/schemas/MegaboxShowtime' },
388
- },
389
- },
47
+ additionalProperties: true,
48
+ description: '대상 엔드포인트가 반환한 data 객체',
390
49
  },
391
50
  meta: {
392
51
  type: 'object',
393
- properties: {
394
- total: { type: 'integer' },
395
- pageSize: { type: 'integer' },
396
- },
397
- },
398
- },
399
- },
400
- ...OPENAPI_CGV_COMPONENT_SCHEMAS,
401
- ErrorResponse: {
402
- type: 'object',
403
- properties: {
404
- success: { type: 'boolean', example: false },
405
- error: {
406
- type: 'object',
407
- properties: {
408
- code: { type: 'string', description: '에러 코드', example: 'MISSING_QUERY' },
409
- message: {
410
- type: 'string',
411
- description: '에러 메시지',
412
- example: '검색어(q)를 입력해주세요.',
413
- },
414
- },
52
+ additionalProperties: true,
53
+ description: '대상 엔드포인트가 반환한 meta 객체',
415
54
  },
416
55
  },
417
56
  },
@@ -8,6 +8,10 @@ export const OPENAPI_CGV_COMPONENT_SCHEMAS = {
8
8
  theaterCode: { type: 'string', example: '0056' },
9
9
  theaterName: { type: 'string', example: 'CGV강남' },
10
10
  regionCode: { type: 'string', example: '01' },
11
+ latitude: { type: 'number', nullable: true, example: 37.5016 },
12
+ longitude: { type: 'number', nullable: true, example: 127.0264 },
13
+ distanceKm: { type: 'number', nullable: true, example: 0.8 },
14
+ address: { type: 'string', nullable: true, example: '서울특별시 강남구 강남대로 438' },
11
15
  },
12
16
  },
13
17
  CgvMovie: {
@@ -45,8 +49,16 @@ export const OPENAPI_CGV_COMPONENT_SCHEMAS = {
45
49
  type: 'object',
46
50
  properties: {
47
51
  regionCode: { type: 'string', nullable: true },
52
+ keyword: { type: 'string', nullable: true },
53
+ latitude: { type: 'number', nullable: true },
54
+ longitude: { type: 'number', nullable: true },
48
55
  },
49
56
  },
57
+ keyword: { type: 'string', nullable: true },
58
+ latitude: { type: 'number', nullable: true },
59
+ longitude: { type: 'number', nullable: true },
60
+ geocodeUsed: { type: 'boolean' },
61
+ formattedAddress: { type: 'string', nullable: true },
50
62
  theaters: {
51
63
  type: 'array',
52
64
  items: { $ref: '#/components/schemas/CgvTheater' },
@@ -74,8 +86,14 @@ export const OPENAPI_CGV_COMPONENT_SCHEMAS = {
74
86
  type: 'object',
75
87
  properties: {
76
88
  theaterCode: { type: 'string', nullable: true },
89
+ keyword: { type: 'string', nullable: true },
90
+ latitude: { type: 'number', nullable: true },
91
+ longitude: { type: 'number', nullable: true },
77
92
  },
78
93
  },
94
+ resolvedTheater: {
95
+ anyOf: [{ $ref: '#/components/schemas/CgvTheater' }, { type: 'null' }],
96
+ },
79
97
  movies: {
80
98
  type: 'array',
81
99
  items: { $ref: '#/components/schemas/CgvMovie' },
@@ -103,8 +121,14 @@ export const OPENAPI_CGV_COMPONENT_SCHEMAS = {
103
121
  properties: {
104
122
  theaterCode: { type: 'string', nullable: true },
105
123
  movieCode: { type: 'string', nullable: true },
124
+ keyword: { type: 'string', nullable: true },
125
+ latitude: { type: 'number', nullable: true },
126
+ longitude: { type: 'number', nullable: true },
106
127
  },
107
128
  },
129
+ resolvedTheater: {
130
+ anyOf: [{ $ref: '#/components/schemas/CgvTheater' }, { type: 'null' }],
131
+ },
108
132
  timetable: {
109
133
  type: 'array',
110
134
  items: { $ref: '#/components/schemas/CgvTimetable' },