daiso 1.2.7 → 1.2.9

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 (70) hide show
  1. package/README.md +17 -17
  2. package/dist/api/actionsProxy.js +0 -10
  3. package/dist/api/cgvHandlers.js +4 -3
  4. package/dist/api/configStatus.js +7 -2
  5. package/dist/api/gs25Handlers.js +4 -3
  6. package/dist/api/handlers.js +11 -7
  7. package/dist/api/healthCheckDefinitions.js +0 -9
  8. package/dist/api/healthChecks.js +0 -1
  9. package/dist/api/lottecinemaHandlers.js +4 -3
  10. package/dist/api/lottemartHandlers.js +5 -142
  11. package/dist/api/megaboxHandlers.js +4 -3
  12. package/dist/api/opinetHandlers.js +2 -1
  13. package/dist/api/routes/cgvRoutes.js +3 -3
  14. package/dist/api/routes/cuRoutes.js +2 -2
  15. package/dist/api/routes/gs25Routes.js +3 -3
  16. package/dist/api/routes/lottecinemaRoutes.js +3 -3
  17. package/dist/api/routes/lottemartRoutes.js +4 -16
  18. package/dist/api/routes/megaboxRoutes.js +3 -3
  19. package/dist/api/routes/opinetRoutes.js +4 -4
  20. package/dist/cli.js +5 -5
  21. package/dist/cliHelp.js +0 -3
  22. package/dist/cliHelpDefinitions.js +2 -19
  23. package/dist/index.js +10 -11
  24. package/dist/middleware/dailyRateLimit.js +0 -1
  25. package/dist/pages/openapiFullSpec.js +0 -2
  26. package/dist/pages/openapiSpecActionParameters.js +4 -4
  27. package/dist/pages/openapiSpecComponents.js +0 -2
  28. package/dist/pages/openapiSpecPathsMegabox.js +1 -1
  29. package/dist/pages/promptReferenceText.js +0 -5
  30. package/dist/pages/promptRetailCinemaText.js +0 -26
  31. package/dist/services/cgv/index.js +3 -6
  32. package/dist/services/cgv/location.js +38 -125
  33. package/dist/services/cgv/tools/findTheaters.js +5 -4
  34. package/dist/services/cgv/tools/getTimetable.js +5 -4
  35. package/dist/services/cgv/tools/searchMovies.js +5 -4
  36. package/dist/services/cu/client.js +3 -35
  37. package/dist/services/cu/index.js +1 -0
  38. package/dist/services/cu/tools/checkInventory.js +3 -1
  39. package/dist/services/gs25/client.js +3 -33
  40. package/dist/services/gs25/index.js +2 -2
  41. package/dist/services/gs25/tools/checkInventory.js +3 -1
  42. package/dist/services/gs25/tools/findNearbyStores.js +3 -1
  43. package/dist/services/lottecinema/index.js +3 -6
  44. package/dist/services/lottecinema/location.js +13 -100
  45. package/dist/services/lottecinema/tools/findNearbyTheaters.js +7 -6
  46. package/dist/services/lottecinema/tools/getRemainingSeats.js +5 -4
  47. package/dist/services/lottecinema/tools/listNowShowing.js +5 -4
  48. package/dist/services/lottemart/client.js +5 -32
  49. package/dist/services/lottemart/geocode.js +3 -46
  50. package/dist/services/megabox/index.js +9 -8
  51. package/dist/services/megabox/location.js +19 -84
  52. package/dist/services/megabox/tools/findNearbyTheaters.js +7 -7
  53. package/dist/services/megabox/tools/getRemainingSeats.js +5 -5
  54. package/dist/services/megabox/tools/listNowShowing.js +5 -5
  55. package/dist/services/oliveyoung/tools/checkInventory.js +5 -5
  56. package/dist/services/oliveyoung/tools/findNearbyStores.js +3 -3
  57. package/dist/services/oliveyoung/tools/searchProducts.js +3 -3
  58. package/dist/services/oliveyoung/transport.js +49 -33
  59. package/dist/services/opinet/client.js +1 -1
  60. package/dist/services/opinet/index.js +1 -1
  61. package/dist/services/opinet/location.js +5 -56
  62. package/dist/services/opinet/tools.js +2 -2
  63. package/dist/utils/geocode.js +155 -0
  64. package/dist/utils/http.js +2 -2
  65. package/dist/utils/relayQuota.js +4 -2
  66. package/openapi.json +4 -183
  67. package/openapi.yaml +4 -131
  68. package/package.json +1 -2
  69. package/dist/pages/openapiSpecComponentsLotteMart.js +0 -85
  70. package/dist/pages/openapiSpecPathsLotteMart.js +0 -157
@@ -0,0 +1,155 @@
1
+ import { fetchJson } from './http.js';
2
+ import { searchNaverLocalPlaces } from '../services/places/client.js';
3
+ function validKakaoDocument(value) {
4
+ if (!value || typeof value !== 'object')
5
+ return false;
6
+ const document = value;
7
+ return ['place_name', 'address_name', 'road_address_name'].every((field) => document[field] === undefined || typeof document[field] === 'string');
8
+ }
9
+ export function readGeocodeEnvironment() {
10
+ const env = typeof process === 'undefined' ? {} : process.env;
11
+ return {
12
+ kakaoRestApiKey: env.KAKAO_REST_API_KEY,
13
+ naverClientId: env.NAVER_CLIENT_ID,
14
+ naverClientSecret: env.NAVER_CLIENT_SECRET,
15
+ };
16
+ }
17
+ export function geocodeBindings(bindings) {
18
+ return {
19
+ kakaoRestApiKey: bindings?.KAKAO_REST_API_KEY,
20
+ naverClientId: bindings?.NAVER_CLIENT_ID,
21
+ naverClientSecret: bindings?.NAVER_CLIENT_SECRET,
22
+ };
23
+ }
24
+ export function validKoreanCoordinates(latitude, longitude) {
25
+ return (Number.isFinite(latitude) &&
26
+ Number.isFinite(longitude) &&
27
+ latitude >= 33 &&
28
+ latitude <= 39 &&
29
+ longitude >= 124 &&
30
+ longitude <= 132);
31
+ }
32
+ const normalize = (value) => value
33
+ .replace(/특별자치시|특별자치도|특별시|광역시/gu, '')
34
+ .replace(/경기도/gu, '경기')
35
+ .replace(/충청북도/gu, '충북')
36
+ .replace(/충청남도/gu, '충남')
37
+ .replace(/전라북도|전북특별자치도/gu, '전북')
38
+ .replace(/전라남도/gu, '전남')
39
+ .replace(/경상북도/gu, '경북')
40
+ .replace(/경상남도/gu, '경남')
41
+ .replace(/강원도/gu, '강원')
42
+ .replace(/제주도/gu, '제주')
43
+ .replace(/[^0-9a-z가-힣]/giu, '')
44
+ .toLowerCase();
45
+ function matches(query, value) {
46
+ const tokens = query
47
+ .replace(/^대한민국\s*/u, '')
48
+ .match(/[0-9]+(?:-[0-9]+)?|[a-z가-힣]+/giu)
49
+ ?.map((token) => (/^\d/u.test(token) ? token : normalize(token))) || [];
50
+ const normalized = normalize(value);
51
+ return (tokens.length > 0 &&
52
+ tokens.every((token) => /^\d+(?:-\d+)?$/u.test(token)
53
+ ? value.match(/\d+(?:-\d+)?/gu)?.includes(token)
54
+ : token.endsWith('역')
55
+ ? new RegExp(`${token}(?:[0-9]+호선|$|[^가-힣])`, 'u').test(value)
56
+ : normalized.includes(token)));
57
+ }
58
+ function matchesAddress(query, address) {
59
+ // 주소 검색은 숫자 존재뿐 아니라 도로 번호와 건물 번호의 순서도 검증합니다.
60
+ return (matches(query, address) &&
61
+ query.match(/\d+(?:-\d+)?/gu).join(',') === address.match(/\d+(?:-\d+)?/gu).join(','));
62
+ }
63
+ export async function searchKakaoPlaces(query, options, coordinates) {
64
+ const key = (options.kakaoRestApiKey ?? readGeocodeEnvironment().kakaoRestApiKey)?.trim();
65
+ if (!key)
66
+ return [];
67
+ const endpoint = new URL('https://dapi.kakao.com/v2/local/search/keyword.json');
68
+ endpoint.searchParams.set('query', query);
69
+ endpoint.searchParams.set('size', '15');
70
+ if (coordinates) {
71
+ endpoint.searchParams.set('x', String(coordinates.longitude));
72
+ endpoint.searchParams.set('y', String(coordinates.latitude));
73
+ endpoint.searchParams.set('radius', '20000');
74
+ endpoint.searchParams.set('sort', 'distance');
75
+ }
76
+ const body = await fetchJson(endpoint.toString(), {
77
+ fetchImpl: options.fetchImpl,
78
+ headers: { Authorization: `KakaoAK ${key}` },
79
+ timeout: options.timeout ?? options.timeoutMs ?? 10000,
80
+ });
81
+ return Array.isArray(body.documents) ? body.documents.filter(validKakaoDocument) : [];
82
+ }
83
+ export async function geocodeLocation(query, input = {}) {
84
+ const keyword = query.trim();
85
+ if (!keyword)
86
+ return null;
87
+ const env = readGeocodeEnvironment();
88
+ const options = {
89
+ ...input,
90
+ kakaoRestApiKey: input.kakaoRestApiKey ?? env.kakaoRestApiKey,
91
+ naverClientId: input.naverClientId ?? env.naverClientId,
92
+ naverClientSecret: input.naverClientSecret ?? env.naverClientSecret,
93
+ };
94
+ const isAddress = /(?:로|길|동|읍|면|리)\s*\d/u.test(keyword);
95
+ let documents = [];
96
+ if (options.kakaoRestApiKey?.trim()) {
97
+ try {
98
+ if (isAddress) {
99
+ const endpoint = new URL('https://dapi.kakao.com/v2/local/search/address.json');
100
+ endpoint.searchParams.set('query', keyword);
101
+ const body = await fetchJson(endpoint.toString(), {
102
+ fetchImpl: options.fetchImpl,
103
+ headers: { Authorization: `KakaoAK ${options.kakaoRestApiKey.trim()}` },
104
+ timeout: options.timeout ?? options.timeoutMs ?? 10000,
105
+ });
106
+ documents = Array.isArray(body.documents) ? body.documents.filter(validKakaoDocument) : [];
107
+ }
108
+ else
109
+ documents = await searchKakaoPlaces(keyword, options);
110
+ }
111
+ catch {
112
+ // 장소명은 네이버 지역 검색으로 보완하고 주소는 잘못된 장소로 대체하지 않습니다.
113
+ }
114
+ }
115
+ for (const document of documents) {
116
+ if (!isAddress && !document.place_name?.trim())
117
+ continue;
118
+ const latitude = Number(document.y);
119
+ const longitude = Number(document.x);
120
+ if (!validKoreanCoordinates(latitude, longitude) ||
121
+ !(isAddress
122
+ ? matchesAddress(keyword, document.address_name || '') ||
123
+ matchesAddress(keyword, document.road_address_name || '')
124
+ : matches(keyword, `${document.place_name} ${document.address_name || ''} ${document.road_address_name || ''}`)))
125
+ continue;
126
+ return {
127
+ latitude,
128
+ longitude,
129
+ formattedAddress: document.road_address_name || document.address_name || null,
130
+ };
131
+ }
132
+ if (!isAddress && options.naverClientId && options.naverClientSecret) {
133
+ try {
134
+ const result = await searchNaverLocalPlaces({
135
+ ...options,
136
+ keyword,
137
+ timeoutMs: options.timeout ?? options.timeoutMs,
138
+ });
139
+ const place = result.places.find((item) => item.latitude !== null &&
140
+ item.longitude !== null &&
141
+ validKoreanCoordinates(item.latitude, item.longitude) &&
142
+ matches(keyword, `${item.name} ${item.address} ${item.roadAddress}`));
143
+ if (place)
144
+ return {
145
+ latitude: place.latitude,
146
+ longitude: place.longitude,
147
+ formattedAddress: place.roadAddress || place.address || null,
148
+ };
149
+ }
150
+ catch {
151
+ return null;
152
+ }
153
+ }
154
+ return null;
155
+ }
@@ -67,7 +67,7 @@ function parseRetryAfterDelayMs(response) {
67
67
  return null;
68
68
  }
69
69
  async function requestWithTimeout(url, options, readResponse) {
70
- const { timeout = 10000, retries = 0, retryDelayMs = 250, retryStatusCodes = DEFAULT_RETRY_STATUS_CODES, retryUnsafeMethods = false, retryMethods = DEFAULT_RETRY_METHODS, onRetry, expectedStatus: _expectedStatus, ...restOptions } = options;
70
+ const { timeout = 10000, fetchImpl = fetch, retries = 0, retryDelayMs = 250, retryStatusCodes = DEFAULT_RETRY_STATUS_CODES, retryUnsafeMethods = false, retryMethods = DEFAULT_RETRY_METHODS, onRetry, expectedStatus: _expectedStatus, ...restOptions } = options;
71
71
  const maxAttempts = Math.max(1, Math.trunc(retries) + 1);
72
72
  const method = normalizeMethod(restOptions.method);
73
73
  const retryAllowed = canRetryMethod(method, retryMethods, retryUnsafeMethods);
@@ -77,7 +77,7 @@ async function requestWithTimeout(url, options, readResponse) {
77
77
  const started = Date.now();
78
78
  let responseStatus;
79
79
  try {
80
- const response = await fetch(url, {
80
+ const response = await fetchImpl(url, {
81
81
  ...restOptions,
82
82
  signal: controller.signal,
83
83
  });
@@ -3,7 +3,9 @@ export function parseRelayQuota(status, headers) {
3
3
  return undefined;
4
4
  const reason = headers.get('x-relay-quota-reason');
5
5
  const retry = headers.get('retry-after') || '';
6
- if (reason !== 'minute' && reason !== 'daily' && reason !== 'consumer')
6
+ if (reason !== 'minute' && reason !== 'daily' && reason !== 'consumer' && reason !== 'consumer-busy')
7
+ return undefined;
8
+ if (reason === 'consumer-busy' && retry !== '1')
7
9
  return undefined;
8
10
  if (!/^[1-9][0-9]{0,4}$/.test(retry) || Number(retry) > 86400)
9
11
  return undefined;
@@ -27,7 +29,7 @@ export function createRelayCooldown(now = () => Date.now(), maxEntries = 1024) {
27
29
  },
28
30
  set(scope, consumer, quota) {
29
31
  prune();
30
- const key = quota.quotaReason === 'consumer' ? `${scope}:${consumer}` : scope;
32
+ const key = (quota.quotaReason === 'consumer' || quota.quotaReason === 'consumer-busy') ? `${scope}:${consumer}` : scope;
31
33
  if (!entries.has(key) && entries.size >= maxEntries)
32
34
  return;
33
35
  const until = now() + quota.retryAfter * 1000;
package/openapi.json CHANGED
@@ -91,8 +91,6 @@
91
91
  "emart24FindStores",
92
92
  "emart24SearchProducts",
93
93
  "emart24CheckInventory",
94
- "lottemartFindStores",
95
- "lottemartSearchProducts",
96
94
  "gs25FindStores",
97
95
  "gs25SearchProducts",
98
96
  "gs25CheckInventory",
@@ -300,7 +298,7 @@
300
298
  "name": "area",
301
299
  "in": "query",
302
300
  "required": false,
303
- "description": "롯데마트 지역",
301
+ "description": "지역",
304
302
  "schema": {
305
303
  "type": "string"
306
304
  }
@@ -336,7 +334,7 @@
336
334
  "name": "brandVariant",
337
335
  "in": "query",
338
336
  "required": false,
339
- "description": "롯데마트 브랜드 변형",
337
+ "description": "브랜드 변형",
340
338
  "schema": {
341
339
  "type": "string"
342
340
  }
@@ -383,7 +381,7 @@
383
381
  "name": "pageLimit",
384
382
  "in": "query",
385
383
  "required": false,
386
- "description": "롯데마트 추가 페이지 수",
384
+ "description": "추가 페이지 수",
387
385
  "schema": {
388
386
  "type": "integer"
389
387
  }
@@ -446,7 +444,7 @@
446
444
  "name": "storeName",
447
445
  "in": "query",
448
446
  "required": false,
449
- "description": "매장명. 롯데마트 상품 조회에서 storeCode가 없을 때 사용하며, 모르면 먼저 lottemartFindNearbyStores 또는 /api/lottemart/stores로 확인하세요.",
447
+ "description": "매장명",
450
448
  "schema": {
451
449
  "type": "string"
452
450
  }
@@ -2084,183 +2082,6 @@
2084
2082
  }
2085
2083
  }
2086
2084
  },
2087
- "LotteMartStore": {
2088
- "type": "object",
2089
- "properties": {
2090
- "area": {
2091
- "type": "string",
2092
- "example": "서울"
2093
- },
2094
- "storeCode": {
2095
- "type": "string",
2096
- "example": "2301"
2097
- },
2098
- "storeName": {
2099
- "type": "string",
2100
- "example": "강변점"
2101
- },
2102
- "brandVariant": {
2103
- "type": "string",
2104
- "example": "lottemart"
2105
- },
2106
- "address": {
2107
- "type": "string",
2108
- "example": "서울 광진구 광나루로 56길 85 테크노마트 B2"
2109
- },
2110
- "phone": {
2111
- "type": "string",
2112
- "example": "02-3424-2502"
2113
- },
2114
- "openTime": {
2115
- "type": "string",
2116
- "example": "10:00~23:00"
2117
- },
2118
- "closedDays": {
2119
- "type": "string",
2120
- "example": "03/08(일), 03/22(일)"
2121
- },
2122
- "parkingType": {
2123
- "type": "string",
2124
- "example": "유료"
2125
- },
2126
- "parkingDetails": {
2127
- "type": "string",
2128
- "example": "최초 무료주차 : 1시간"
2129
- },
2130
- "detailUrl": {
2131
- "type": "string",
2132
- "example": "/mobiledowa/market/detail_shop.asp?werks=2301"
2133
- },
2134
- "latitude": {
2135
- "type": "number",
2136
- "format": "float",
2137
- "example": 37.5354
2138
- },
2139
- "longitude": {
2140
- "type": "number",
2141
- "format": "float",
2142
- "example": 127.0958
2143
- },
2144
- "distanceM": {
2145
- "type": "number",
2146
- "nullable": true,
2147
- "example": 530
2148
- }
2149
- }
2150
- },
2151
- "LotteMartProduct": {
2152
- "type": "object",
2153
- "properties": {
2154
- "area": {
2155
- "type": "string",
2156
- "example": "서울"
2157
- },
2158
- "storeCode": {
2159
- "type": "string",
2160
- "example": "2301"
2161
- },
2162
- "storeName": {
2163
- "type": "string",
2164
- "example": "강변점"
2165
- },
2166
- "keyword": {
2167
- "type": "string",
2168
- "example": "콜라"
2169
- },
2170
- "productName": {
2171
- "type": "string",
2172
- "example": "코카콜라"
2173
- },
2174
- "barcode": {
2175
- "type": "string",
2176
- "example": "8801094011307"
2177
- },
2178
- "spec": {
2179
- "type": "string",
2180
- "example": "1.2L"
2181
- },
2182
- "manufacturer": {
2183
- "type": "string",
2184
- "example": "코카콜라음료 주식회사"
2185
- },
2186
- "price": {
2187
- "type": "integer",
2188
- "example": 2980
2189
- },
2190
- "stockQuantity": {
2191
- "type": "integer",
2192
- "example": 20
2193
- }
2194
- }
2195
- },
2196
- "LotteMartStoreSearchResponse": {
2197
- "type": "object",
2198
- "properties": {
2199
- "success": {
2200
- "type": "boolean",
2201
- "example": true
2202
- },
2203
- "data": {
2204
- "type": "object",
2205
- "properties": {
2206
- "stores": {
2207
- "type": "array",
2208
- "items": {
2209
- "$ref": "#/components/schemas/LotteMartStore"
2210
- }
2211
- }
2212
- }
2213
- },
2214
- "meta": {
2215
- "type": "object",
2216
- "properties": {
2217
- "total": {
2218
- "type": "integer"
2219
- },
2220
- "page": {
2221
- "type": "integer"
2222
- },
2223
- "pageSize": {
2224
- "type": "integer"
2225
- }
2226
- }
2227
- }
2228
- }
2229
- },
2230
- "LotteMartProductSearchResponse": {
2231
- "type": "object",
2232
- "properties": {
2233
- "success": {
2234
- "type": "boolean",
2235
- "example": true
2236
- },
2237
- "data": {
2238
- "type": "object",
2239
- "properties": {
2240
- "products": {
2241
- "type": "array",
2242
- "items": {
2243
- "$ref": "#/components/schemas/LotteMartProduct"
2244
- }
2245
- }
2246
- }
2247
- },
2248
- "meta": {
2249
- "type": "object",
2250
- "properties": {
2251
- "total": {
2252
- "type": "integer"
2253
- },
2254
- "page": {
2255
- "type": "integer"
2256
- },
2257
- "pageSize": {
2258
- "type": "integer"
2259
- }
2260
- }
2261
- }
2262
- }
2263
- },
2264
2085
  "Gs25Store": {
2265
2086
  "type": "object",
2266
2087
  "properties": {
package/openapi.yaml CHANGED
@@ -77,8 +77,6 @@ paths:
77
77
  - emart24FindStores
78
78
  - emart24SearchProducts
79
79
  - emart24CheckInventory
80
- - lottemartFindStores
81
- - lottemartSearchProducts
82
80
  - gs25FindStores
83
81
  - gs25SearchProducts
84
82
  - gs25CheckInventory
@@ -222,7 +220,7 @@ paths:
222
220
  - name: area
223
221
  in: query
224
222
  required: false
225
- description: 롯데마트 지역
223
+ description: 지역
226
224
  schema:
227
225
  type: string
228
226
  - name: area1
@@ -246,7 +244,7 @@ paths:
246
244
  - name: brandVariant
247
245
  in: query
248
246
  required: false
249
- description: 롯데마트 브랜드 변형
247
+ description: 브랜드 변형
250
248
  schema:
251
249
  type: string
252
250
  - name: lat
@@ -278,7 +276,7 @@ paths:
278
276
  - name: pageLimit
279
277
  in: query
280
278
  required: false
281
- description: 롯데마트 추가 페이지 수
279
+ description: 추가 페이지 수
282
280
  schema:
283
281
  type: integer
284
282
  - name: pageSize
@@ -320,7 +318,7 @@ paths:
320
318
  - name: storeName
321
319
  in: query
322
320
  required: false
323
- description: 매장명. 롯데마트 상품 조회에서 storeCode가 없을 때 사용하며, 모르면 먼저 lottemartFindNearbyStores 또는 /api/lottemart/stores로 확인하세요.
321
+ description: 매장명
324
322
  schema:
325
323
  type: string
326
324
  - name: storeKeyword
@@ -1460,131 +1458,6 @@ components:
1460
1458
  type: number
1461
1459
  nullable: true
1462
1460
  example: 120
1463
- LotteMartStore:
1464
- type: object
1465
- properties:
1466
- area:
1467
- type: string
1468
- example: 서울
1469
- storeCode:
1470
- type: string
1471
- example: 2301
1472
- storeName:
1473
- type: string
1474
- example: 강변점
1475
- brandVariant:
1476
- type: string
1477
- example: lottemart
1478
- address:
1479
- type: string
1480
- example: 서울 광진구 광나루로 56길 85 테크노마트 B2
1481
- phone:
1482
- type: string
1483
- example: 02-3424-2502
1484
- openTime:
1485
- type: string
1486
- example: "10:00~23:00"
1487
- closedDays:
1488
- type: string
1489
- example: 03/08(일), 03/22(일)
1490
- parkingType:
1491
- type: string
1492
- example: 유료
1493
- parkingDetails:
1494
- type: string
1495
- example: "최초 무료주차 : 1시간"
1496
- detailUrl:
1497
- type: string
1498
- example: /mobiledowa/market/detail_shop.asp?werks=2301
1499
- latitude:
1500
- type: number
1501
- format: float
1502
- example: 37.5354
1503
- longitude:
1504
- type: number
1505
- format: float
1506
- example: 127.0958
1507
- distanceM:
1508
- type: number
1509
- nullable: true
1510
- example: 530
1511
- LotteMartProduct:
1512
- type: object
1513
- properties:
1514
- area:
1515
- type: string
1516
- example: 서울
1517
- storeCode:
1518
- type: string
1519
- example: 2301
1520
- storeName:
1521
- type: string
1522
- example: 강변점
1523
- keyword:
1524
- type: string
1525
- example: 콜라
1526
- productName:
1527
- type: string
1528
- example: 코카콜라
1529
- barcode:
1530
- type: string
1531
- example: 8801094011307
1532
- spec:
1533
- type: string
1534
- example: 1.2L
1535
- manufacturer:
1536
- type: string
1537
- example: 코카콜라음료 주식회사
1538
- price:
1539
- type: integer
1540
- example: 2980
1541
- stockQuantity:
1542
- type: integer
1543
- example: 20
1544
- LotteMartStoreSearchResponse:
1545
- type: object
1546
- properties:
1547
- success:
1548
- type: boolean
1549
- example: true
1550
- data:
1551
- type: object
1552
- properties:
1553
- stores:
1554
- type: array
1555
- items:
1556
- $ref: "#/components/schemas/LotteMartStore"
1557
- meta:
1558
- type: object
1559
- properties:
1560
- total:
1561
- type: integer
1562
- page:
1563
- type: integer
1564
- pageSize:
1565
- type: integer
1566
- LotteMartProductSearchResponse:
1567
- type: object
1568
- properties:
1569
- success:
1570
- type: boolean
1571
- example: true
1572
- data:
1573
- type: object
1574
- properties:
1575
- products:
1576
- type: array
1577
- items:
1578
- $ref: "#/components/schemas/LotteMartProduct"
1579
- meta:
1580
- type: object
1581
- properties:
1582
- total:
1583
- type: integer
1584
- page:
1585
- type: integer
1586
- pageSize:
1587
- type: integer
1588
1461
  Gs25Store:
1589
1462
  type: object
1590
1463
  properties:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "daiso",
3
- "version": "1.2.7",
3
+ "version": "1.2.9",
4
4
  "description": "Korean retail and cinema MCP server, CLI, and Codex Skill for Daiso, convenience stores, marts, Olive Young, and theaters",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -59,7 +59,6 @@
59
59
  "cu",
60
60
  "seveneleven",
61
61
  "emart24",
62
- "lottemart",
63
62
  "cgv",
64
63
  "megabox",
65
64
  "lottecinema",