@crowsgear/escl-protocol-scanner 0.1.0

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.
@@ -0,0 +1,185 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Python 의존성 확인 및 설치 스크립트
5
+ * - 시스템에 Python 3 설치 여부 확인
6
+ * - 필요한 패키지(zeroconf, pillow) 설치 여부 확인
7
+ * - 대화형 설치 프롬프트
8
+ *
9
+ * 사용자는 PYTHON_PATH 환경변수로 어느 Python을 사용할지 결정
10
+ */
11
+
12
+ const fs = require('fs');
13
+ const path = require('path');
14
+ const { execSync, spawnSync } = require('child_process');
15
+ const readline = require('readline');
16
+
17
+ const REQUIRED_PACKAGES = ['zeroconf', 'pillow'];
18
+ const PACKAGE_JSON_PATH = path.join(__dirname, '..', 'package.json');
19
+ const PROJECT_ROOT = path.dirname(path.dirname(PACKAGE_JSON_PATH));
20
+
21
+ // 색상 코드
22
+ const colors = {
23
+ reset: '\x1b[0m',
24
+ bright: '\x1b[1m',
25
+ red: '\x1b[31m',
26
+ green: '\x1b[32m',
27
+ yellow: '\x1b[33m',
28
+ blue: '\x1b[34m',
29
+ cyan: '\x1b[36m',
30
+ };
31
+
32
+ const log = {
33
+ info: (msg) => console.log(`${colors.blue}ℹ️ ${msg}${colors.reset}`),
34
+ success: (msg) => console.log(`${colors.green}✅ ${msg}${colors.reset}`),
35
+ warn: (msg) => console.log(`${colors.yellow}⚠️ ${msg}${colors.reset}`),
36
+ error: (msg) => console.log(`${colors.red}❌ ${msg}${colors.reset}`),
37
+ header: (msg) => console.log(`\n${colors.bright}${colors.cyan}${msg}${colors.reset}\n`),
38
+ };
39
+
40
+ /**
41
+ * 시스템 Python 경로 찾기
42
+ */
43
+ function findPythonPath() {
44
+ // PYTHON_PATH 환경변수가 설정되어 있으면 사용
45
+ if (process.env.PYTHON_PATH) {
46
+ log.success(`PYTHON_PATH 환경변수 사용: ${process.env.PYTHON_PATH}`);
47
+ return process.env.PYTHON_PATH;
48
+ }
49
+
50
+ // 아니면 시스템 python3 사용
51
+ try {
52
+ const pythonPath = execSync('which python3', { encoding: 'utf-8' }).trim();
53
+ log.info(`시스템 Python 사용: ${pythonPath}`);
54
+ return pythonPath;
55
+ } catch (error) {
56
+ log.error('python3를 찾을 수 없습니다. Python 3을 설치하세요.');
57
+ process.exit(1);
58
+ }
59
+ }
60
+
61
+ /**
62
+ * 패키지 설치 여부 확인
63
+ */
64
+ function checkPackageInstalled(pythonPath, packageName) {
65
+ try {
66
+ execSync(`${pythonPath} -c "import ${packageName}"`, {
67
+ stdio: 'pipe',
68
+ encoding: 'utf-8',
69
+ });
70
+ return true;
71
+ } catch (error) {
72
+ return false;
73
+ }
74
+ }
75
+
76
+ /**
77
+ * 설치된 패키지 확인
78
+ */
79
+ function checkInstalledPackages(pythonPath) {
80
+ const missing = [];
81
+
82
+ for (const pkg of REQUIRED_PACKAGES) {
83
+ const installed = checkPackageInstalled(pythonPath, pkg);
84
+
85
+ if (installed) {
86
+ log.success(`${pkg} 설치됨`);
87
+ } else {
88
+ log.warn(`${pkg} 미설치`);
89
+ missing.push(pkg);
90
+ }
91
+ }
92
+
93
+ return missing;
94
+ }
95
+
96
+ /**
97
+ * 사용자 입력 프롬프트
98
+ */
99
+ function prompt(question) {
100
+ return new Promise((resolve) => {
101
+ const rl = readline.createInterface({
102
+ input: process.stdin,
103
+ output: process.stdout,
104
+ });
105
+
106
+ rl.question(question, (answer) => {
107
+ rl.close();
108
+ resolve(answer.toLowerCase());
109
+ });
110
+ });
111
+ }
112
+
113
+ /**
114
+ * 패키지 설치
115
+ */
116
+ async function installPackages(pythonPath, packages) {
117
+ log.header(`Python 패키지 설치`);
118
+
119
+ const installCmd = `${pythonPath} -m pip install ${packages.join(' ')}`;
120
+
121
+ console.log(`설치 명령어: ${colors.cyan}${installCmd}${colors.reset}\n`);
122
+
123
+ const answer = await prompt(
124
+ `${colors.bright}패키지를 설치하시겠습니까? (y/n): ${colors.reset}`
125
+ );
126
+
127
+ if (answer === 'y' || answer === 'yes') {
128
+ try {
129
+ log.info('설치 중...');
130
+ execSync(installCmd, { stdio: 'inherit' });
131
+ log.success('패키지 설치 완료');
132
+ return true;
133
+ } catch (error) {
134
+ log.error(`설치 실패: ${error.message}`);
135
+ return false;
136
+ }
137
+ } else {
138
+ log.warn('사용자가 설치를 거부했습니다.');
139
+ log.info(`수동 설치 명령어: ${colors.cyan}${installCmd}${colors.reset}`);
140
+ return false;
141
+ }
142
+ }
143
+
144
+ /**
145
+ * 메인 함수
146
+ */
147
+ async function main() {
148
+ log.header('eSCL Protocol Scanner - Python 의존성 확인');
149
+
150
+ // Python 경로 결정
151
+ const pythonPath = findPythonPath();
152
+
153
+ // 패키지 확인
154
+ log.header('필수 패키지 확인');
155
+ const missing = checkInstalledPackages(pythonPath);
156
+
157
+ if (missing.length === 0) {
158
+ log.success('모든 필수 패키지가 설치되어 있습니다.');
159
+ console.log();
160
+ process.exit(0);
161
+ }
162
+
163
+ // 설치 필요
164
+ log.header('필수 패키지 설치 필요');
165
+ log.warn(`다음 패키지가 필요합니다: ${missing.join(', ')}`);
166
+
167
+ const installed = await installPackages(pythonPath, missing);
168
+
169
+ if (!installed) {
170
+ log.error('필수 패키지 없이는 eSCL 스캐너를 사용할 수 없습니다.');
171
+ console.log(
172
+ `\n${colors.bright}수동 설치 방법:${colors.reset}`
173
+ );
174
+
175
+ console.log(`${colors.cyan}${pythonPath} -m pip install ${missing.join(' ')}${colors.reset}`);
176
+ console.log();
177
+ process.exit(1);
178
+ }
179
+ }
180
+
181
+ // 실행
182
+ main().catch((error) => {
183
+ log.error(`예기치 않은 오류: ${error.message}`);
184
+ process.exit(1);
185
+ });