From 3a6f50f0a46f20aa7100bd481d69cd7bde2107b8 Mon Sep 17 00:00:00 2001
From: hmmhmmhm
Date: Mon, 20 Oct 2025 00:10:40 +0900
Subject: [PATCH] refactor: convert build scripts from JavaScript to TypeScript
---
apps/browser/.gitignore | 3 +
apps/browser/package.json | 5 +-
.../before-sign.ts} | 44 +++++++++----
.../download-widevine.ts} | 29 ++++++---
.../evs-sign.js => scripts-src/evs-sign.ts} | 63 ++++++++++++-------
apps/browser/tsconfig.scripts.json | 17 +++++
6 files changed, 116 insertions(+), 45 deletions(-)
rename apps/browser/{scripts/before-sign.js => scripts-src/before-sign.ts} (67%)
mode change 100755 => 100644
rename apps/browser/{scripts/download-widevine.js => scripts-src/download-widevine.ts} (73%)
rename apps/browser/{scripts/evs-sign.js => scripts-src/evs-sign.ts} (84%)
create mode 100644 apps/browser/tsconfig.scripts.json
diff --git a/apps/browser/.gitignore b/apps/browser/.gitignore
index 634af8e..e7325e8 100644
--- a/apps/browser/.gitignore
+++ b/apps/browser/.gitignore
@@ -4,3 +4,6 @@ dist-renderer
release
*.log
.DS_Store
+
+# Compiled scripts (TypeScript sources in scripts-src/)
+scripts/*.js
diff --git a/apps/browser/package.json b/apps/browser/package.json
index c101902..669415f 100644
--- a/apps/browser/package.json
+++ b/apps/browser/package.json
@@ -4,9 +4,10 @@
"description": "A lightweight, elegant web browser for developers featuring an iPhone frame interface",
"main": "dist/main/index.js",
"scripts": {
- "dev": "npm run copy:assets && concurrently \"npm run build:main:watch\" \"npm run build:webview:watch\" \"npm run dev:renderer\" \"npm run start\"",
+ "dev": "npm run copy:assets && npm run build:scripts && concurrently \"npm run build:main:watch\" \"npm run build:webview:watch\" \"npm run dev:renderer\" \"npm run start\"",
"dev:renderer": "vite",
- "build": "npm run copy:assets && npm run build:main && npm run build:webview && npm run build:renderer",
+ "build": "npm run copy:assets && npm run build:scripts && npm run build:main && npm run build:webview && npm run build:renderer",
+ "build:scripts": "tsc --project tsconfig.scripts.json",
"build:main": "tsc",
"build:webview": "tsc --project tsconfig.webview.json",
"build:webview:watch": "tsc --project tsconfig.webview.json --watch",
diff --git a/apps/browser/scripts/before-sign.js b/apps/browser/scripts-src/before-sign.ts
old mode 100755
new mode 100644
similarity index 67%
rename from apps/browser/scripts/before-sign.js
rename to apps/browser/scripts-src/before-sign.ts
index fd52eb2..72fb9d5
--- a/apps/browser/scripts/before-sign.js
+++ b/apps/browser/scripts-src/before-sign.ts
@@ -5,15 +5,30 @@
* This runs BEFORE electron-builder's codesign
*/
-const { execSync } = require('child_process');
-const path = require('path');
-const os = require('os');
-const fs = require('fs');
+import { execSync } from 'child_process';
+import * as path from 'path';
+import * as os from 'os';
+import * as fs from 'fs';
+
+interface EVSConfig {
+ account_name?: string;
+ Auth?: {
+ AccountName?: string;
+ };
+ Account?: {
+ AccountName?: string;
+ };
+}
+
+interface BuildContext {
+ electronPlatformName: string;
+ appOutDir: string;
+}
/**
* Verify EVS environment
*/
-function verifyEnvironment() {
+function verifyEnvironment(): boolean {
const configPath = path.join(os.homedir(), '.config', 'evs', 'config.json');
if (!fs.existsSync(configPath)) {
@@ -22,14 +37,16 @@ function verifyEnvironment() {
}
try {
- const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
- const accountName = config.account_name || (config.Auth && config.Auth.AccountName) || (config.Account && config.Account.AccountName);
+ const configContent = fs.readFileSync(configPath, 'utf8');
+ const config: EVSConfig = JSON.parse(configContent);
+ const accountName = config.account_name || config.Auth?.AccountName || config.Account?.AccountName;
if (accountName) {
console.log('[EVS] ✓ EVS account configured:', accountName);
return true;
}
} catch (error) {
- console.error('[EVS] ✗ Failed to read EVS config:', error.message);
+ const errorMessage = error instanceof Error ? error.message : String(error);
+ console.error('[EVS] ✗ Failed to read EVS config:', errorMessage);
return false;
}
@@ -39,7 +56,7 @@ function verifyEnvironment() {
/**
* Sign with EVS VMP
*/
-function signWithEVS(appPath) {
+function signWithEVS(appPath: string): boolean {
console.log('[EVS] Signing with VMP before Apple codesign...');
console.log('[EVS] App path:', appPath);
@@ -54,7 +71,8 @@ function signWithEVS(appPath) {
console.log('[EVS] ✓ VMP signing completed successfully\n');
return true;
} catch (error) {
- console.error('[EVS] ✗ VMP signing failed:', error.message);
+ const errorMessage = error instanceof Error ? error.message : String(error);
+ console.error('[EVS] ✗ VMP signing failed:', errorMessage);
return false;
}
}
@@ -62,7 +80,7 @@ function signWithEVS(appPath) {
/**
* beforeSign hook for electron-builder
*/
-exports.default = async function(context) {
+export default async function(context: BuildContext): Promise {
const { electronPlatformName, appOutDir } = context;
console.log('\n[EVS] beforeSign hook triggered');
@@ -82,7 +100,7 @@ exports.default = async function(context) {
}
// Determine app path
- let appPath;
+ let appPath: string;
if (electronPlatformName === 'darwin') {
// Find .app bundle
const files = fs.readdirSync(appOutDir);
@@ -102,4 +120,4 @@ exports.default = async function(context) {
if (!success) {
console.warn('[EVS] ⚠ VMP signing failed, but continuing with Apple codesign...');
}
-};
+}
diff --git a/apps/browser/scripts/download-widevine.js b/apps/browser/scripts-src/download-widevine.ts
similarity index 73%
rename from apps/browser/scripts/download-widevine.js
rename to apps/browser/scripts-src/download-widevine.ts
index 378a6c9..0c37e5c 100644
--- a/apps/browser/scripts/download-widevine.js
+++ b/apps/browser/scripts-src/download-widevine.ts
@@ -7,29 +7,42 @@
* This script manually downloads the Widevine CDM component.
*/
-const { execSync } = require('child_process');
-const fs = require('fs');
-const path = require('path');
-const https = require('https');
+import * as path from 'path';
+
+interface PackageJson {
+ devDependencies: {
+ electron: string;
+ [key: string]: string;
+ };
+}
console.log('[Widevine] Starting Widevine CDM download...\n');
// Get Electron version
-const packageJson = require('../package.json');
-const electronVersion = packageJson.devDependencies.electron.match(/v?(\d+\.\d+\.\d+)/)[1];
+const packageJsonPath = path.join(__dirname, '..', 'package.json');
+const packageJson: PackageJson = require(packageJsonPath);
+const electronVersionMatch = packageJson.devDependencies.electron.match(/v?(\d+\.\d+\.\d+)/);
+
+if (!electronVersionMatch) {
+ console.error('[Widevine] ✗ Could not parse Electron version');
+ process.exit(1);
+}
+
+const electronVersion = electronVersionMatch[1];
console.log(`[Widevine] Electron version: ${electronVersion}`);
console.log(`[Widevine] Platform: ${process.platform}`);
console.log(`[Widevine] Arch: ${process.arch}\n`);
// Widevine CDM download URLs (from Chrome)
-const WIDEVINE_VERSIONS = {
+const WIDEVINE_VERSIONS: Record = {
'38.0.0': '4.10.2710.0',
'37.0.0': '4.10.2710.0',
'36.0.0': '4.10.2710.0'
};
-const widevineVersion = WIDEVINE_VERSIONS[electronVersion.split('.').slice(0, 2).join('.')] || '4.10.2710.0';
+const majorMinorVersion = electronVersion.split('.').slice(0, 2).join('.');
+const widevineVersion = WIDEVINE_VERSIONS[majorMinorVersion] || '4.10.2710.0';
console.log(`[Widevine] Widevine CDM version: ${widevineVersion}\n`);
diff --git a/apps/browser/scripts/evs-sign.js b/apps/browser/scripts-src/evs-sign.ts
similarity index 84%
rename from apps/browser/scripts/evs-sign.js
rename to apps/browser/scripts-src/evs-sign.ts
index a59d05d..b0cf755 100644
--- a/apps/browser/scripts/evs-sign.js
+++ b/apps/browser/scripts-src/evs-sign.ts
@@ -7,17 +7,32 @@
* 2. Signs the application with Widevine VMP signature after packaging
*/
-const { execSync, spawnSync } = require('child_process');
-const fs = require('fs');
-const path = require('path');
-const os = require('os');
+import { execSync, spawnSync, SpawnSyncReturns } from 'child_process';
+import * as fs from 'fs';
+import * as path from 'path';
+import * as os from 'os';
+
+interface EVSConfig {
+ account_name?: string;
+ Auth?: {
+ AccountName?: string;
+ };
+ Account?: {
+ AccountName?: string;
+ };
+}
+
+interface BuildContext {
+ electronPlatformName: string;
+ appOutDir: string;
+}
/**
* Check if Python 3 is available
*/
-function checkPython() {
+function checkPython(): boolean {
try {
- const result = spawnSync('python3', ['--version'], { encoding: 'utf8' });
+ const result: SpawnSyncReturns = spawnSync('python3', ['--version'], { encoding: 'utf8' });
if (result.status === 0) {
console.log('[EVS] Python 3 found:', result.stdout.trim());
return true;
@@ -32,9 +47,9 @@ function checkPython() {
/**
* Check if castlabs-evs is installed
*/
-function checkEvsInstalled() {
+function checkEvsInstalled(): boolean {
try {
- const result = spawnSync('python3', ['-m', 'pip', 'show', 'castlabs-evs'], { encoding: 'utf8' });
+ const result: SpawnSyncReturns = spawnSync('python3', ['-m', 'pip', 'show', 'castlabs-evs'], { encoding: 'utf8' });
if (result.status === 0 && result.stdout.includes('Name: castlabs-evs')) {
const versionMatch = result.stdout.match(/Version: ([\d.]+)/);
const version = versionMatch ? versionMatch[1] : 'unknown';
@@ -51,7 +66,7 @@ function checkEvsInstalled() {
/**
* Check if EVS account is configured
*/
-function checkEvsAccount() {
+function checkEvsAccount(): boolean {
const configPath = path.join(os.homedir(), '.config', 'evs', 'config.json');
if (!fs.existsSync(configPath)) {
@@ -60,15 +75,17 @@ function checkEvsAccount() {
}
try {
- const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
+ const configContent = fs.readFileSync(configPath, 'utf8');
+ const config: EVSConfig = JSON.parse(configContent);
// Check for both formats: account_name (old) and Auth.AccountName (new)
- const accountName = config.account_name || (config.Auth && config.Auth.AccountName) || (config.Account && config.Account.AccountName);
+ const accountName = config.account_name || config.Auth?.AccountName || config.Account?.AccountName;
if (accountName) {
console.log('[EVS] ✓ EVS account configured:', accountName);
return true;
}
} catch (error) {
- console.error('[EVS] ✗ Failed to read EVS config:', error.message);
+ const errorMessage = error instanceof Error ? error.message : String(error);
+ console.error('[EVS] ✗ Failed to read EVS config:', errorMessage);
return false;
}
@@ -79,7 +96,7 @@ function checkEvsAccount() {
/**
* Print setup instructions
*/
-function printSetupInstructions() {
+function printSetupInstructions(): void {
console.error('\n[EVS] Setup Instructions:');
console.error('[EVS] ==========================================');
console.error('[EVS] ');
@@ -101,7 +118,7 @@ function printSetupInstructions() {
/**
* Verify EVS environment setup
*/
-function verifyEnvironment() {
+function verifyEnvironment(): boolean {
console.log('\n[EVS] Verifying EVS environment...');
console.log('[EVS] ==========================================');
@@ -124,12 +141,12 @@ function verifyEnvironment() {
/**
* Copy Widevine CDM to app bundle
*/
-function copyWidevineCdm(appOutDir, electronPlatformName) {
+function copyWidevineCdm(appOutDir: string, electronPlatformName: string): boolean {
console.log('[Widevine] Copying Widevine CDM to app bundle...');
// Determine source path based on platform
- let widevineSrcPath;
- let widevineDestPath;
+ let widevineSrcPath: string | undefined;
+ let widevineDestPath: string;
if (electronPlatformName === 'darwin') {
// macOS: Check multiple possible locations
@@ -211,7 +228,8 @@ function copyWidevineCdm(appOutDir, electronPlatformName) {
return false;
}
} catch (error) {
- console.error('[Widevine] ✗ Failed to copy Widevine CDM:', error.message);
+ const errorMessage = error instanceof Error ? error.message : String(error);
+ console.error('[Widevine] ✗ Failed to copy Widevine CDM:', errorMessage);
return false;
}
} else if (electronPlatformName === 'win32') {
@@ -226,7 +244,7 @@ function copyWidevineCdm(appOutDir, electronPlatformName) {
/**
* Sign the application package
*/
-function signPackage(appOutDir, persistent = false) {
+function signPackage(appOutDir: string, persistent: boolean = false): boolean {
const persistentFlag = persistent ? '--persistent' : '';
const command = `python3 -m castlabs_evs.vmp sign-pkg ${persistentFlag} "${appOutDir}"`;
@@ -241,7 +259,8 @@ function signPackage(appOutDir, persistent = false) {
console.log('[EVS] VMP signing completed successfully\n');
return true;
} catch (error) {
- console.error('[EVS] VMP signing failed:', error.message);
+ const errorMessage = error instanceof Error ? error.message : String(error);
+ console.error('[EVS] VMP signing failed:', errorMessage);
return false;
}
}
@@ -249,7 +268,7 @@ function signPackage(appOutDir, persistent = false) {
/**
* Main electron-builder hook
*/
-exports.default = async function(context) {
+export default async function(context: BuildContext): Promise {
const { electronPlatformName, appOutDir } = context;
console.log('\n[EVS] Starting post-pack process...');
@@ -280,7 +299,7 @@ exports.default = async function(context) {
// castlabs v16+ uses Component Updater to automatically download and install CDM
// Manual bundling is not recommended and has legal implications
console.log('\n[EVS] Widevine CDM will be downloaded automatically by Component Updater on first run');
-};
+}
// Allow running this script directly for verification
if (require.main === module) {
diff --git a/apps/browser/tsconfig.scripts.json b/apps/browser/tsconfig.scripts.json
new file mode 100644
index 0000000..ea6618c
--- /dev/null
+++ b/apps/browser/tsconfig.scripts.json
@@ -0,0 +1,17 @@
+{
+ "extends": "./tsconfig.json",
+ "compilerOptions": {
+ "module": "CommonJS",
+ "target": "ES2020",
+ "moduleResolution": "node",
+ "outDir": "./scripts",
+ "rootDir": "./scripts-src",
+ "esModuleInterop": true,
+ "skipLibCheck": true,
+ "strict": true,
+ "resolveJsonModule": true,
+ "types": ["node"]
+ },
+ "include": ["scripts-src/**/*"],
+ "exclude": ["node_modules", "dist", "dist-renderer", "release"]
+}