feat: Stage 2 TypeScript 타입 안전성 개선 - any 타입 83개 → 62개 대폭 감소
✨ 주요 개선사항: - any 타입 83개에서 62개로 21개 수정 (25% 감소) - 모든 ESLint 에러 11개 → 0개 완전 해결 - 타입 안전성 대폭 향상으로 런타임 오류 가능성 감소 🔧 수정된 파일들: • PWADebug.tsx - 사용하지 않는 import들에 _ prefix 추가 • categoryUtils.ts - 불필요한 any 캐스트 제거 • TransactionsHeader.tsx - BudgetData 인터페이스 정의 • storageUtils.ts - generic 타입과 unknown 타입 적용 • 각종 error handler들 - Error | {message?: string} 타입 적용 • test 파일들 - 적절한 mock 인터페이스 정의 • 유틸리티 파일들 - any → unknown 또는 적절한 타입으로 교체 🏆 성과: - 코드 품질 크게 향상 (280 → 80 문제로 71% 감소) - TypeScript 컴파일러의 타입 체크 효과성 증대 - 개발자 경험 개선 (IDE 자동완성, 타입 추론 등) 🧹 추가 정리: - ESLint no-console/no-alert 경고 해결 - Prettier 포맷팅 적용으로 코드 스타일 통일 🎯 다음 단계: 남은 62개 any 타입 계속 개선 예정 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
198
scripts/sync-versions.cjs
Executable file
198
scripts/sync-versions.cjs
Executable file
@@ -0,0 +1,198 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const { execSync } = require("child_process");
|
||||
|
||||
/**
|
||||
* 버전 동기화 스크립트
|
||||
* package.json의 버전을 Android build.gradle과 iOS Info.plist에 동기화합니다.
|
||||
*/
|
||||
|
||||
// package.json에서 버전 읽기
|
||||
const packageJsonPath = path.join(__dirname, "..", "package.json");
|
||||
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf8"));
|
||||
const version = packageJson.version;
|
||||
|
||||
// --check 플래그가 있으면 버전 검증만 수행
|
||||
const isCheckMode = process.argv.includes("--check");
|
||||
|
||||
if (isCheckMode) {
|
||||
console.log(`🔍 Checking version consistency for ${version}...`);
|
||||
} else {
|
||||
console.log(`🔄 Syncing version ${version} to mobile platforms...`);
|
||||
}
|
||||
|
||||
// 버전을 숫자로 변환 (예: "1.2.3" -> 10203)
|
||||
function versionToCode(version) {
|
||||
const parts = version.split(".").map(Number);
|
||||
return parts[0] * 10000 + parts[1] * 100 + parts[2];
|
||||
}
|
||||
|
||||
const versionCode = versionToCode(version);
|
||||
|
||||
// Android build.gradle 업데이트
|
||||
const androidBuildGradlePath = path.join(
|
||||
__dirname,
|
||||
"..",
|
||||
"android",
|
||||
"app",
|
||||
"build.gradle"
|
||||
);
|
||||
|
||||
if (fs.existsSync(androidBuildGradlePath)) {
|
||||
if (isCheckMode) {
|
||||
console.log("📱 Checking Android build.gradle versions...");
|
||||
const buildGradleContent = fs.readFileSync(androidBuildGradlePath, "utf8");
|
||||
|
||||
const versionCodeMatch = buildGradleContent.match(/versionCode\s+(\d+)/);
|
||||
const versionNameMatch = buildGradleContent.match(
|
||||
/versionName\s+"([^"]*)"/
|
||||
);
|
||||
|
||||
if (versionCodeMatch && versionNameMatch) {
|
||||
const currentVersionCode = parseInt(versionCodeMatch[1]);
|
||||
const currentVersionName = versionNameMatch[1];
|
||||
|
||||
if (
|
||||
currentVersionCode === versionCode &&
|
||||
currentVersionName === version
|
||||
) {
|
||||
console.log(
|
||||
`✅ Android versions are in sync: ${version} (${versionCode})`
|
||||
);
|
||||
} else {
|
||||
console.log(
|
||||
`❌ Android version mismatch: expected ${version} (${versionCode}), found ${currentVersionName} (${currentVersionCode})`
|
||||
);
|
||||
}
|
||||
} else {
|
||||
console.log("❌ Could not find version info in Android build.gradle");
|
||||
}
|
||||
} else {
|
||||
console.log("📱 Updating Android build.gradle...");
|
||||
|
||||
let buildGradleContent = fs.readFileSync(androidBuildGradlePath, "utf8");
|
||||
|
||||
// versionCode 업데이트
|
||||
buildGradleContent = buildGradleContent.replace(
|
||||
/versionCode\s+\d+/,
|
||||
`versionCode ${versionCode}`
|
||||
);
|
||||
|
||||
// versionName 업데이트
|
||||
buildGradleContent = buildGradleContent.replace(
|
||||
/versionName\s+"[^"]*"/,
|
||||
`versionName "${version}"`
|
||||
);
|
||||
|
||||
fs.writeFileSync(androidBuildGradlePath, buildGradleContent);
|
||||
console.log(`✅ Android version updated: ${version} (${versionCode})`);
|
||||
}
|
||||
} else {
|
||||
console.log("⚠️ Android build.gradle not found, skipping...");
|
||||
}
|
||||
|
||||
// iOS Info.plist 업데이트
|
||||
const iosInfoPlistPath = path.join(
|
||||
__dirname,
|
||||
"..",
|
||||
"ios",
|
||||
"App",
|
||||
"App",
|
||||
"Info.plist"
|
||||
);
|
||||
|
||||
if (fs.existsSync(iosInfoPlistPath)) {
|
||||
if (isCheckMode) {
|
||||
console.log("🍎 Checking iOS Info.plist versions...");
|
||||
|
||||
try {
|
||||
const currentVersion = execSync(
|
||||
`/usr/libexec/PlistBuddy -c "Print :CFBundleShortVersionString" "${iosInfoPlistPath}"`,
|
||||
{
|
||||
stdio: "pipe",
|
||||
}
|
||||
)
|
||||
.toString()
|
||||
.trim();
|
||||
|
||||
const currentBuildNumber = execSync(
|
||||
`/usr/libexec/PlistBuddy -c "Print :CFBundleVersion" "${iosInfoPlistPath}"`,
|
||||
{
|
||||
stdio: "pipe",
|
||||
}
|
||||
)
|
||||
.toString()
|
||||
.trim();
|
||||
|
||||
if (
|
||||
currentVersion === version &&
|
||||
parseInt(currentBuildNumber) === versionCode
|
||||
) {
|
||||
console.log(`✅ iOS versions are in sync: ${version} (${versionCode})`);
|
||||
} else {
|
||||
console.log(
|
||||
`❌ iOS version mismatch: expected ${version} (${versionCode}), found ${currentVersion} (${currentBuildNumber})`
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(
|
||||
"⚠️ Could not check iOS Info.plist (requires macOS), skipping..."
|
||||
);
|
||||
}
|
||||
} else {
|
||||
console.log("🍎 Updating iOS Info.plist...");
|
||||
|
||||
try {
|
||||
// CFBundleShortVersionString 업데이트 (앱 버전)
|
||||
execSync(
|
||||
`/usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString ${version}" "${iosInfoPlistPath}"`,
|
||||
{
|
||||
stdio: "pipe",
|
||||
}
|
||||
);
|
||||
|
||||
// CFBundleVersion 업데이트 (빌드 번호)
|
||||
execSync(
|
||||
`/usr/libexec/PlistBuddy -c "Set :CFBundleVersion ${versionCode}" "${iosInfoPlistPath}"`,
|
||||
{
|
||||
stdio: "pipe",
|
||||
}
|
||||
);
|
||||
|
||||
console.log(`✅ iOS version updated: ${version} (${versionCode})`);
|
||||
} catch (error) {
|
||||
console.log(
|
||||
"⚠️ Could not update iOS Info.plist (requires macOS), skipping..."
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
console.log("⚠️ iOS Info.plist not found, skipping...");
|
||||
}
|
||||
|
||||
// Capacitor config 업데이트 (선택사항)
|
||||
const capacitorConfigPath = path.join(__dirname, "..", "capacitor.config.ts");
|
||||
|
||||
if (fs.existsSync(capacitorConfigPath)) {
|
||||
console.log("⚡ Updating Capacitor config...");
|
||||
|
||||
let configContent = fs.readFileSync(capacitorConfigPath, "utf8");
|
||||
|
||||
// 버전 정보를 추가할 수 있지만, 현재는 스킵
|
||||
console.log("✅ Capacitor config checked");
|
||||
}
|
||||
|
||||
if (isCheckMode) {
|
||||
console.log("🎉 Version check completed!");
|
||||
} else {
|
||||
console.log("🎉 Version sync completed!");
|
||||
console.log(`📦 Version: ${version}`);
|
||||
console.log(`🔢 Build Code: ${versionCode}`);
|
||||
console.log("");
|
||||
console.log("Next steps:");
|
||||
console.log("1. Run: npm run mobile:sync");
|
||||
console.log("2. Build: npm run android:bundle (or ios:archive)");
|
||||
console.log("3. Test on devices");
|
||||
}
|
||||
Reference in New Issue
Block a user