daiso 1.0.1 → 1.0.3
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.
- package/README.md +8 -0
- package/dist/cli.js +141 -19
- package/dist/cliHelp.js +133 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -41,9 +41,17 @@ CLI (npx):
|
|
|
41
41
|
|
|
42
42
|
```bash
|
|
43
43
|
npx daiso help
|
|
44
|
+
npx daiso help products
|
|
44
45
|
npx daiso url
|
|
45
46
|
npx daiso health
|
|
46
47
|
npx daiso claude
|
|
48
|
+
|
|
49
|
+
# AI 없이 직접 조회
|
|
50
|
+
npx daiso products 수납박스
|
|
51
|
+
npx daiso product 1034604
|
|
52
|
+
npx daiso stores 강남역
|
|
53
|
+
npx daiso inventory 1034604 --keyword 강남역
|
|
54
|
+
npx daiso get /api/cgv/movies --playDate 20260307 --theaterCode 0056
|
|
47
55
|
```
|
|
48
56
|
|
|
49
57
|
<br>
|
package/dist/cli.js
CHANGED
|
@@ -8,6 +8,7 @@ import { existsSync, readFileSync } from 'node:fs';
|
|
|
8
8
|
import path from 'node:path';
|
|
9
9
|
import { fileURLToPath } from 'node:url';
|
|
10
10
|
import { spawn } from 'node:child_process';
|
|
11
|
+
import { printCommandHelp, printHelp } from './cliHelp.js';
|
|
11
12
|
const DEFAULT_BASE_URL = 'https://mcp.aka.page';
|
|
12
13
|
const DEFAULT_MCP_URL = `${DEFAULT_BASE_URL}/mcp`;
|
|
13
14
|
function loadVersion() {
|
|
@@ -20,25 +21,6 @@ function loadVersion() {
|
|
|
20
21
|
const parsed = JSON.parse(raw);
|
|
21
22
|
return parsed.version ?? '0.0.0';
|
|
22
23
|
}
|
|
23
|
-
function printHelp(writeOut) {
|
|
24
|
-
writeOut('daiso CLI');
|
|
25
|
-
writeOut('');
|
|
26
|
-
writeOut('사용법:');
|
|
27
|
-
writeOut(' daiso <command> [options]');
|
|
28
|
-
writeOut('');
|
|
29
|
-
writeOut('명령어:');
|
|
30
|
-
writeOut(' help 도움말 출력');
|
|
31
|
-
writeOut(' version CLI 버전 출력');
|
|
32
|
-
writeOut(' url MCP 엔드포인트 URL 출력');
|
|
33
|
-
writeOut(' health 원격 서버 상태 확인');
|
|
34
|
-
writeOut(' claude Claude Code MCP 등록 명령 출력');
|
|
35
|
-
writeOut(' claude --exec Claude Code MCP 등록 명령 실행');
|
|
36
|
-
writeOut('');
|
|
37
|
-
writeOut('예시:');
|
|
38
|
-
writeOut(' npx daiso url');
|
|
39
|
-
writeOut(' npx daiso health');
|
|
40
|
-
writeOut(' npx daiso claude');
|
|
41
|
-
}
|
|
42
24
|
async function execCommand(command, args) {
|
|
43
25
|
return await new Promise((resolve, reject) => {
|
|
44
26
|
const child = spawn(command, args, {
|
|
@@ -67,6 +49,67 @@ function createDefaultDeps() {
|
|
|
67
49
|
runCommand: execCommand,
|
|
68
50
|
};
|
|
69
51
|
}
|
|
52
|
+
function parseCliArgs(args) {
|
|
53
|
+
const positionals = [];
|
|
54
|
+
const options = {};
|
|
55
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
56
|
+
const token = args[index];
|
|
57
|
+
if (!token.startsWith('--')) {
|
|
58
|
+
positionals.push(token);
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
const withoutPrefix = token.slice(2);
|
|
62
|
+
const equalIndex = withoutPrefix.indexOf('=');
|
|
63
|
+
if (equalIndex >= 0) {
|
|
64
|
+
const key = withoutPrefix.slice(0, equalIndex);
|
|
65
|
+
const value = withoutPrefix.slice(equalIndex + 1);
|
|
66
|
+
options[key] = value;
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
const key = withoutPrefix;
|
|
70
|
+
const nextValue = args[index + 1];
|
|
71
|
+
if (!nextValue || nextValue.startsWith('--')) {
|
|
72
|
+
options[key] = 'true';
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
options[key] = nextValue;
|
|
76
|
+
index += 1;
|
|
77
|
+
}
|
|
78
|
+
return { positionals, options };
|
|
79
|
+
}
|
|
80
|
+
function toUrl(pathOrUrl) {
|
|
81
|
+
if (pathOrUrl.startsWith('http://') || pathOrUrl.startsWith('https://')) {
|
|
82
|
+
return new URL(pathOrUrl);
|
|
83
|
+
}
|
|
84
|
+
const normalizedPath = pathOrUrl.startsWith('/') ? pathOrUrl : `/${pathOrUrl}`;
|
|
85
|
+
return new URL(normalizedPath, DEFAULT_BASE_URL);
|
|
86
|
+
}
|
|
87
|
+
function applyOptionsToQuery(url, options) {
|
|
88
|
+
for (const [key, value] of Object.entries(options)) {
|
|
89
|
+
url.searchParams.set(key, value);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
async function requestAndPrintJson(fetchImpl, writeOut, writeErr, url) {
|
|
93
|
+
try {
|
|
94
|
+
const response = await fetchImpl(url.toString());
|
|
95
|
+
if (!response.ok) {
|
|
96
|
+
const bodyText = await response.text();
|
|
97
|
+
writeErr(`요청 실패: HTTP ${response.status}`);
|
|
98
|
+
if (bodyText) {
|
|
99
|
+
writeErr(bodyText);
|
|
100
|
+
}
|
|
101
|
+
return 1;
|
|
102
|
+
}
|
|
103
|
+
const payload = (await response.json());
|
|
104
|
+
writeOut(JSON.stringify(payload, null, 2));
|
|
105
|
+
return 0;
|
|
106
|
+
}
|
|
107
|
+
catch (error) {
|
|
108
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
109
|
+
writeErr(`요청 중 오류 발생: ${message}`);
|
|
110
|
+
return 1;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
70
113
|
export async function runCli(argv, deps) {
|
|
71
114
|
const resolvedDeps = {
|
|
72
115
|
...createDefaultDeps(),
|
|
@@ -74,6 +117,10 @@ export async function runCli(argv, deps) {
|
|
|
74
117
|
};
|
|
75
118
|
const [command, ...options] = argv;
|
|
76
119
|
if (!command || command === 'help' || command === '--help' || command === '-h') {
|
|
120
|
+
const maybeCommand = options[0];
|
|
121
|
+
if (maybeCommand) {
|
|
122
|
+
return printCommandHelp(maybeCommand, resolvedDeps.writeOut, resolvedDeps.writeErr);
|
|
123
|
+
}
|
|
77
124
|
printHelp(resolvedDeps.writeOut);
|
|
78
125
|
return 0;
|
|
79
126
|
}
|
|
@@ -121,6 +168,81 @@ export async function runCli(argv, deps) {
|
|
|
121
168
|
resolvedDeps.writeOut(`claude ${cliArgs.join(' ')}`);
|
|
122
169
|
return 0;
|
|
123
170
|
}
|
|
171
|
+
if (command === 'get') {
|
|
172
|
+
const parsed = parseCliArgs(options);
|
|
173
|
+
if (parsed.options.help === 'true') {
|
|
174
|
+
return printCommandHelp('get', resolvedDeps.writeOut, resolvedDeps.writeErr);
|
|
175
|
+
}
|
|
176
|
+
const targetPath = parsed.positionals[0];
|
|
177
|
+
if (!targetPath) {
|
|
178
|
+
resolvedDeps.writeErr('get 명령은 경로가 필요합니다. 예: daiso get /api/daiso/products --q 수납박스');
|
|
179
|
+
return 1;
|
|
180
|
+
}
|
|
181
|
+
const targetUrl = toUrl(targetPath);
|
|
182
|
+
applyOptionsToQuery(targetUrl, parsed.options);
|
|
183
|
+
return await requestAndPrintJson(resolvedDeps.fetchImpl, resolvedDeps.writeOut, resolvedDeps.writeErr, targetUrl);
|
|
184
|
+
}
|
|
185
|
+
if (command === 'products') {
|
|
186
|
+
const parsed = parseCliArgs(options);
|
|
187
|
+
if (parsed.options.help === 'true') {
|
|
188
|
+
return printCommandHelp('products', resolvedDeps.writeOut, resolvedDeps.writeErr);
|
|
189
|
+
}
|
|
190
|
+
const query = parsed.positionals[0];
|
|
191
|
+
if (!query) {
|
|
192
|
+
resolvedDeps.writeErr('products 명령은 검색어가 필요합니다. 예: daiso products 수납박스');
|
|
193
|
+
return 1;
|
|
194
|
+
}
|
|
195
|
+
const targetUrl = toUrl('/api/daiso/products');
|
|
196
|
+
targetUrl.searchParams.set('q', query);
|
|
197
|
+
applyOptionsToQuery(targetUrl, parsed.options);
|
|
198
|
+
return await requestAndPrintJson(resolvedDeps.fetchImpl, resolvedDeps.writeOut, resolvedDeps.writeErr, targetUrl);
|
|
199
|
+
}
|
|
200
|
+
if (command === 'product') {
|
|
201
|
+
const parsed = parseCliArgs(options);
|
|
202
|
+
if (parsed.options.help === 'true') {
|
|
203
|
+
return printCommandHelp('product', resolvedDeps.writeOut, resolvedDeps.writeErr);
|
|
204
|
+
}
|
|
205
|
+
const productId = parsed.positionals[0];
|
|
206
|
+
if (!productId) {
|
|
207
|
+
resolvedDeps.writeErr('product 명령은 제품 ID가 필요합니다. 예: daiso product 1034604');
|
|
208
|
+
return 1;
|
|
209
|
+
}
|
|
210
|
+
const targetUrl = toUrl(`/api/daiso/products/${productId}`);
|
|
211
|
+
applyOptionsToQuery(targetUrl, parsed.options);
|
|
212
|
+
return await requestAndPrintJson(resolvedDeps.fetchImpl, resolvedDeps.writeOut, resolvedDeps.writeErr, targetUrl);
|
|
213
|
+
}
|
|
214
|
+
if (command === 'stores') {
|
|
215
|
+
const parsed = parseCliArgs(options);
|
|
216
|
+
if (parsed.options.help === 'true') {
|
|
217
|
+
return printCommandHelp('stores', resolvedDeps.writeOut, resolvedDeps.writeErr);
|
|
218
|
+
}
|
|
219
|
+
const keyword = parsed.positionals[0];
|
|
220
|
+
if (keyword) {
|
|
221
|
+
parsed.options.keyword = keyword;
|
|
222
|
+
}
|
|
223
|
+
if (!parsed.options.keyword && !parsed.options.sido) {
|
|
224
|
+
resolvedDeps.writeErr('stores 명령은 keyword 또는 --sido가 필요합니다. 예: daiso stores 강남역 / daiso stores --sido 서울');
|
|
225
|
+
return 1;
|
|
226
|
+
}
|
|
227
|
+
const targetUrl = toUrl('/api/daiso/stores');
|
|
228
|
+
applyOptionsToQuery(targetUrl, parsed.options);
|
|
229
|
+
return await requestAndPrintJson(resolvedDeps.fetchImpl, resolvedDeps.writeOut, resolvedDeps.writeErr, targetUrl);
|
|
230
|
+
}
|
|
231
|
+
if (command === 'inventory') {
|
|
232
|
+
const parsed = parseCliArgs(options);
|
|
233
|
+
if (parsed.options.help === 'true') {
|
|
234
|
+
return printCommandHelp('inventory', resolvedDeps.writeOut, resolvedDeps.writeErr);
|
|
235
|
+
}
|
|
236
|
+
const productId = parsed.positionals[0];
|
|
237
|
+
if (!productId) {
|
|
238
|
+
resolvedDeps.writeErr('inventory 명령은 제품 ID가 필요합니다. 예: daiso inventory 1034604 --keyword 강남역');
|
|
239
|
+
return 1;
|
|
240
|
+
}
|
|
241
|
+
const targetUrl = toUrl('/api/daiso/inventory');
|
|
242
|
+
targetUrl.searchParams.set('productId', productId);
|
|
243
|
+
applyOptionsToQuery(targetUrl, parsed.options);
|
|
244
|
+
return await requestAndPrintJson(resolvedDeps.fetchImpl, resolvedDeps.writeOut, resolvedDeps.writeErr, targetUrl);
|
|
245
|
+
}
|
|
124
246
|
resolvedDeps.writeErr(`알 수 없는 명령어: ${command}`);
|
|
125
247
|
resolvedDeps.writeErr('도움말: daiso help');
|
|
126
248
|
return 1;
|
package/dist/cliHelp.js
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI 도움말 정의
|
|
3
|
+
*/
|
|
4
|
+
export const COMMAND_LIST = [
|
|
5
|
+
'help',
|
|
6
|
+
'version',
|
|
7
|
+
'url',
|
|
8
|
+
'health',
|
|
9
|
+
'claude',
|
|
10
|
+
'get',
|
|
11
|
+
'products',
|
|
12
|
+
'product',
|
|
13
|
+
'stores',
|
|
14
|
+
'inventory',
|
|
15
|
+
];
|
|
16
|
+
const COMMAND_SUMMARY = {
|
|
17
|
+
help: '도움말 출력',
|
|
18
|
+
version: 'CLI 버전 출력',
|
|
19
|
+
url: 'MCP 엔드포인트 URL 출력',
|
|
20
|
+
health: '원격 서버 상태 확인',
|
|
21
|
+
claude: 'Claude Code MCP 등록 명령 출력/실행',
|
|
22
|
+
get: '임의 API 경로 GET 호출',
|
|
23
|
+
products: '다이소 제품 검색',
|
|
24
|
+
product: '다이소 제품 상세 조회',
|
|
25
|
+
stores: '다이소 매장 검색',
|
|
26
|
+
inventory: '다이소 재고 조회',
|
|
27
|
+
};
|
|
28
|
+
const COMMAND_DETAIL = {
|
|
29
|
+
help: [
|
|
30
|
+
'명령: help',
|
|
31
|
+
'설명: 전체 도움말 또는 특정 명령 상세 도움말을 출력합니다.',
|
|
32
|
+
'사용법: daiso help [command]',
|
|
33
|
+
'예시: daiso help products',
|
|
34
|
+
],
|
|
35
|
+
version: [
|
|
36
|
+
'명령: version',
|
|
37
|
+
'설명: 설치된 daiso CLI 버전을 출력합니다.',
|
|
38
|
+
'사용법: daiso version',
|
|
39
|
+
],
|
|
40
|
+
url: [
|
|
41
|
+
'명령: url',
|
|
42
|
+
'설명: MCP 엔드포인트 URL을 출력합니다.',
|
|
43
|
+
'사용법: daiso url',
|
|
44
|
+
'출력 예시: https://mcp.aka.page/mcp',
|
|
45
|
+
],
|
|
46
|
+
health: [
|
|
47
|
+
'명령: health',
|
|
48
|
+
'설명: 서버 /health API를 호출해 상태를 확인합니다.',
|
|
49
|
+
'사용법: daiso health',
|
|
50
|
+
'출력: status, endpoint, checkedAt(JSON)',
|
|
51
|
+
],
|
|
52
|
+
claude: [
|
|
53
|
+
'명령: claude',
|
|
54
|
+
'설명: Claude Code MCP 등록 명령을 출력하거나 실행합니다.',
|
|
55
|
+
'사용법: daiso claude [--exec]',
|
|
56
|
+
'옵션: --exec 실제 claude 명령 실행',
|
|
57
|
+
'예시: daiso claude --exec',
|
|
58
|
+
],
|
|
59
|
+
get: [
|
|
60
|
+
'명령: get',
|
|
61
|
+
'설명: 임의 API 경로를 GET으로 호출합니다.',
|
|
62
|
+
'사용법: daiso get <path|url> [--queryKey value ...]',
|
|
63
|
+
'필수: <path|url>',
|
|
64
|
+
'예시: daiso get /api/cgv/movies --playDate 20260307 --theaterCode 0056',
|
|
65
|
+
],
|
|
66
|
+
products: [
|
|
67
|
+
'명령: products',
|
|
68
|
+
'설명: 다이소 제품 검색 API를 호출합니다.',
|
|
69
|
+
'사용법: daiso products <query> [--page N] [--pageSize N]',
|
|
70
|
+
'필수: <query>',
|
|
71
|
+
'옵션: --page, --pageSize',
|
|
72
|
+
'예시: daiso products 수납박스 --page 1 --pageSize 30',
|
|
73
|
+
],
|
|
74
|
+
product: [
|
|
75
|
+
'명령: product',
|
|
76
|
+
'설명: 다이소 제품 상세 API를 호출합니다.',
|
|
77
|
+
'사용법: daiso product <productId>',
|
|
78
|
+
'필수: <productId>',
|
|
79
|
+
'예시: daiso product 1034604',
|
|
80
|
+
],
|
|
81
|
+
stores: [
|
|
82
|
+
'명령: stores',
|
|
83
|
+
'설명: 다이소 매장 검색 API를 호출합니다.',
|
|
84
|
+
'사용법: daiso stores [keyword] [--sido 값] [--gugun 값] [--dong 값] [--limit N]',
|
|
85
|
+
'필수: keyword 또는 --sido',
|
|
86
|
+
'옵션: --keyword, --sido, --gugun, --dong, --limit',
|
|
87
|
+
'예시: daiso stores 강남역',
|
|
88
|
+
'예시: daiso stores --sido 서울 --gugun 강남구',
|
|
89
|
+
],
|
|
90
|
+
inventory: [
|
|
91
|
+
'명령: inventory',
|
|
92
|
+
'설명: 다이소 재고 API를 호출합니다.',
|
|
93
|
+
'사용법: daiso inventory <productId> [--keyword 값] [--lat 값] [--lng 값] [--page N] [--pageSize N]',
|
|
94
|
+
'필수: <productId>',
|
|
95
|
+
'옵션: --keyword, --lat, --lng, --page, --pageSize',
|
|
96
|
+
'예시: daiso inventory 1034604 --keyword 강남역',
|
|
97
|
+
],
|
|
98
|
+
};
|
|
99
|
+
export function printHelp(writeOut) {
|
|
100
|
+
writeOut('daiso CLI');
|
|
101
|
+
writeOut('');
|
|
102
|
+
writeOut('사용법:');
|
|
103
|
+
writeOut(' daiso <command> [options]');
|
|
104
|
+
writeOut('');
|
|
105
|
+
writeOut('명령어:');
|
|
106
|
+
for (const command of COMMAND_LIST) {
|
|
107
|
+
writeOut(` ${command.padEnd(20, ' ')}${COMMAND_SUMMARY[command]}`);
|
|
108
|
+
}
|
|
109
|
+
writeOut('');
|
|
110
|
+
writeOut('예시:');
|
|
111
|
+
writeOut(' npx daiso url');
|
|
112
|
+
writeOut(' npx daiso health');
|
|
113
|
+
writeOut(' npx daiso claude');
|
|
114
|
+
writeOut(' npx daiso products 수납박스');
|
|
115
|
+
writeOut(' npx daiso stores 강남역');
|
|
116
|
+
writeOut(' npx daiso inventory 1034604 --keyword 강남역');
|
|
117
|
+
writeOut(' npx daiso get /api/cgv/movies --playDate 20260307 --theaterCode 0056');
|
|
118
|
+
writeOut('');
|
|
119
|
+
writeOut('상세 도움말:');
|
|
120
|
+
writeOut(' npx daiso help <command>');
|
|
121
|
+
}
|
|
122
|
+
export function printCommandHelp(command, writeOut, writeErr) {
|
|
123
|
+
if (!Object.hasOwn(COMMAND_DETAIL, command)) {
|
|
124
|
+
writeErr(`도움말을 찾을 수 없는 명령어: ${command}`);
|
|
125
|
+
writeErr('사용 가능한 명령어: help, version, url, health, claude, get, products, product, stores, inventory');
|
|
126
|
+
return 1;
|
|
127
|
+
}
|
|
128
|
+
const detail = COMMAND_DETAIL[command];
|
|
129
|
+
for (const line of detail) {
|
|
130
|
+
writeOut(line);
|
|
131
|
+
}
|
|
132
|
+
return 0;
|
|
133
|
+
}
|