Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions apps/browser/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,6 @@ dist-renderer
release
*.log
.DS_Store

# Compiled scripts (TypeScript sources in scripts-src/)
scripts/*.js
5 changes: 3 additions & 2 deletions apps/browser/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
44 changes: 31 additions & 13 deletions apps/browser/scripts/before-sign.js → apps/browser/scripts-src/before-sign.ts
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {
Expand All @@ -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;
}

Expand All @@ -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);

Expand All @@ -54,15 +71,16 @@ 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;
}
}

/**
* beforeSign hook for electron-builder
*/
exports.default = async function(context) {
export default async function(context: BuildContext): Promise<void> {
const { electronPlatformName, appOutDir } = context;

console.log('\n[EVS] beforeSign hook triggered');
Expand All @@ -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);
Expand All @@ -102,4 +120,4 @@ exports.default = async function(context) {
if (!success) {
console.warn('[EVS] ⚠ VMP signing failed, but continuing with Apple codesign...');
}
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -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<string, string> = {
'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`);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<string> = spawnSync('python3', ['--version'], { encoding: 'utf8' });
if (result.status === 0) {
console.log('[EVS] Python 3 found:', result.stdout.trim());
return true;
Expand All @@ -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<string> = 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';
Expand All @@ -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)) {
Expand All @@ -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;
}

Expand All @@ -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] ');
Expand All @@ -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] ==========================================');

Expand All @@ -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
Expand Down Expand Up @@ -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') {
Expand All @@ -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}"`;

Expand All @@ -241,15 +259,16 @@ 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;
}
}

/**
* Main electron-builder hook
*/
exports.default = async function(context) {
export default async function(context: BuildContext): Promise<void> {
const { electronPlatformName, appOutDir } = context;

console.log('\n[EVS] Starting post-pack process...');
Expand Down Expand Up @@ -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) {
Expand Down
17 changes: 17 additions & 0 deletions apps/browser/tsconfig.scripts.json
Original file line number Diff line number Diff line change
@@ -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"]
}