ota-manager 1.0.14 → 1.0.15

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/lib/ota-build.cjs CHANGED
@@ -49,6 +49,44 @@ if (fs.existsSync(envPath)) {
49
49
  });
50
50
  }
51
51
 
52
+ function isBase64(str) {
53
+ if (!str) return false;
54
+ const clean = str.replace(/\s+/g, '');
55
+ if (clean.length === 0) return false;
56
+ const regex = /^[A-Za-z0-9+/=]+$/;
57
+ return regex.test(clean);
58
+ }
59
+
60
+ function getBase64OrFileContent(val) {
61
+ if (!val) return '';
62
+ try {
63
+ if (fs.existsSync(val)) {
64
+ const fileContent = fs.readFileSync(val);
65
+ const textContent = fileContent.toString('utf8').trim();
66
+
67
+ if (textContent.includes('=')) {
68
+ const match = textContent.match(/^\s*[\w.-]+\s*=\s*(.*)?\s*$/);
69
+ if (match && match[1]) {
70
+ const cleanVal = match[1].trim();
71
+ if (isBase64(cleanVal)) {
72
+ return cleanVal;
73
+ }
74
+ }
75
+ }
76
+
77
+ if (isBase64(textContent)) {
78
+ return textContent;
79
+ }
80
+
81
+ return fileContent.toString('base64');
82
+ }
83
+ } catch (e) {
84
+ console.warn(`⚠️ Warning: Error reading file at "${val}":`, e.message);
85
+ }
86
+ return val;
87
+ }
88
+
89
+
52
90
  const rawArgs = process.argv.slice(2).map(a => a.toLowerCase());
53
91
  const hasNv = rawArgs.includes('-nv') || rawArgs.includes('--nv') || rawArgs.includes('--no-version') || rawArgs.includes('nover') || rawArgs.includes('no-ver') || rawArgs.includes('-no') || rawArgs.includes('--no') || rawArgs.includes('no') || rawArgs.includes('-norev') || rawArgs.includes('--norev') || rawArgs.includes('norev');
54
92
 
@@ -261,13 +299,22 @@ async function buildIos() {
261
299
  console.log('🚀 Triggering GitHub Action...');
262
300
  try {
263
301
  const payload = { ref: branch };
264
- if (activeWorkflowId === 'ios-build.yml') {
265
- payload.inputs = {
266
- channel: process.env.PUBLIC_APP_CHANNEL || 'training',
267
- api_url: process.env.PUBLIC_API_URL || '',
268
- github_ota_pat: process.env.PUBLIC_GITHUB_OTA_PAT || '',
269
- ota_update_url: process.env.PUBLIC_OTA_UPDATE_URL || ''
270
- };
302
+ payload.inputs = {
303
+ channel: process.env.PUBLIC_APP_CHANNEL || 'training',
304
+ api_url: process.env.PUBLIC_API_URL || '',
305
+ github_ota_pat: process.env.PUBLIC_GITHUB_OTA_PAT || '',
306
+ ota_update_url: process.env.PUBLIC_OTA_UPDATE_URL || ''
307
+ };
308
+ if (activeWorkflowId === 'ios-release.yml') {
309
+ const certVal = process.env.APPLE_BUILD_CERTIFICATE_BASE64 || '';
310
+ const provVal = process.env.APPLE_BUILD_PROVISION_PROFILE_BASE64 || '';
311
+ const apiKeyVal = process.env.APP_STORE_CONNECT_API_KEY_BASE64 || '';
312
+
313
+ payload.inputs.apple_build_certificate_base64 = getBase64OrFileContent(certVal);
314
+ payload.inputs.apple_build_provision_profile_base64 = getBase64OrFileContent(provVal);
315
+ payload.inputs.app_store_connect_api_key_base64 = getBase64OrFileContent(apiKeyVal);
316
+ payload.inputs.app_store_connect_api_key_id = process.env.APP_STORE_CONNECT_API_KEY_ID || '';
317
+ payload.inputs.app_store_connect_api_issuer = process.env.APP_STORE_CONNECT_API_ISSUER || '';
271
318
  }
272
319
  await githubApi(`/repos/${REPO}/actions/workflows/${activeWorkflowId}/dispatches`, 'POST', payload);
273
320
  console.log('✅ Trigger Success! Waiting for run to start...');
@@ -114,7 +114,8 @@ async function runSecurityAudit() {
114
114
 
115
115
  if (content.includes('"version"')) {
116
116
  const data = JSON.parse(content);
117
- console.log(`✅ Read Successful! Current Remote Version: v${data.version}`);
117
+ const remoteVer = data.version || data[channel]?.version || (data.live?.version || data.training?.version);
118
+ console.log(`✅ Read Successful! Current Remote Version: v${remoteVer}`);
118
119
  } else {
119
120
  console.log(`❌ Raw Response: ${content.substring(0, 100)}...`);
120
121
  throw new Error("Invalid content");
@@ -4,7 +4,7 @@ const path = require('path');
4
4
  const distDir = path.join(process.cwd(), 'dist');
5
5
  const filesToVerify = ['splash.html', 'index.html', 'home.html'];
6
6
 
7
- console.log('🔍 MEMULAI VERIFIKASI OTA ZIP (Pre-Flight Check)...\n');
7
+ console.log('🔍 STARTING OTA ZIP VERIFICATION (Pre-Flight Check)...\n');
8
8
 
9
9
  if (!fs.existsSync(distDir)) {
10
10
  console.log(`❌ Error: dist/ directory not found in ${process.cwd()}`);
@@ -16,70 +16,70 @@ let totalErrors = 0;
16
16
  filesToVerify.forEach(filename => {
17
17
  const filePath = path.join(distDir, filename);
18
18
  if (!fs.existsSync(filePath)) {
19
- console.log(`⚠️ WARNING: File utama ${filename} tidak ditemukan di dist/`);
19
+ console.log(`⚠️ WARNING: Main file ${filename} not found in dist/`);
20
20
  return;
21
21
  }
22
22
 
23
- console.log(`📄 Memeriksa: ${filename}`);
23
+ console.log(`📄 Verifying: ${filename}`);
24
24
  const content = fs.readFileSync(filePath, 'utf8');
25
25
 
26
- // Regex untuk mencari src="..." atau href="..."
26
+ // Regex to search for src="..." or href="..."
27
27
  const regex = /(?:src|href)=["']([^"']+)["']/g;
28
28
  let match;
29
29
 
30
30
  while ((match = regex.exec(content)) !== null) {
31
31
  const assetPath = match[1];
32
32
 
33
- // Abaikan link eksternal atau base64
33
+ // Ignore external links or base64
34
34
  if (assetPath.startsWith('http') || assetPath.startsWith('data:')) continue;
35
35
 
36
36
  let hasError = false;
37
37
 
38
- // CEK 1: Garis Miring Ilegal khusus untuk folder assets
38
+ // CHECK 1: Illegal slashes specifically for assets folder
39
39
  if (assetPath.startsWith('/assets') || assetPath.startsWith('.//')) {
40
- console.log(` ❌ ERROR JALUR: Ditemukan path ilegal -> "${assetPath}"`);
40
+ console.log(` ❌ PATH ERROR: Illegal path found -> "${assetPath}"`);
41
41
  hasError = true;
42
42
  totalErrors++;
43
43
  }
44
44
 
45
- // Abaikan validasi file fisik untuk navigasi HTML atau anchor SVG
45
+ // Ignore physical file validation for HTML navigation or SVG anchors
46
46
  if (assetPath.endsWith('.html') || assetPath.startsWith('#')) continue;
47
47
 
48
- // CEK 2: Apakah filenya benar-benar ada secara fisik?
49
- // Karena path kita harusnya relatif (misal: assets/file.css),
50
- // kita gabungkan dengan root folder dist/
48
+ // CHECK 2: Does the file physically exist?
49
+ // Since our paths must be relative (e.g., assets/file.css),
50
+ // we join them with the root dist/ folder
51
51
  const physicalPath = path.join(distDir, assetPath);
52
52
  if (!fs.existsSync(physicalPath)) {
53
- console.log(` ❌ ERROR FILE HILANG: File tidak ditemukan di -> "${assetPath}"`);
53
+ console.log(` ❌ MISSING FILE ERROR: File not found at -> "${assetPath}"`);
54
54
  hasError = true;
55
55
  totalErrors++;
56
56
  }
57
57
  }
58
- console.log(` ✅ ${filename} selesai diperiksa.`);
58
+ console.log(` ✅ ${filename} verification complete.`);
59
59
  });
60
60
 
61
- // Verifikasi isi folder dist/assets/
61
+ // Verify contents of dist/assets/ folder
62
62
  const assetsDir = path.join(distDir, 'assets');
63
63
  if (fs.existsSync(assetsDir)) {
64
- console.log('\n📁 Memeriksa file JS di folder dist/assets/...');
64
+ console.log('\n📁 Verifying JS files in dist/assets/...');
65
65
  const jsFiles = fs.readdirSync(assetsDir).filter(f => f.endsWith('.js'));
66
66
 
67
67
  jsFiles.forEach(f => {
68
68
  const content = fs.readFileSync(path.join(assetsDir, f), 'utf8');
69
69
  if (content.includes('return"/"+e') || content.includes('return "/" + e')) {
70
- console.log(` ❌ ERROR VITE PRELOAD: Ditemukan path absolut di file JS -> "${f}"`);
70
+ console.log(` ❌ VITE PRELOAD ERROR: Absolute dynamic path found in JS file -> "${f}"`);
71
71
  totalErrors++;
72
72
  }
73
73
  });
74
- console.log(' ✅ Verifikasi file JS di dist/assets/ selesai.');
74
+ console.log(' ✅ JS file verification in dist/assets/ complete.');
75
75
  }
76
76
 
77
77
  console.log('\n------------------------------------');
78
78
  if (totalErrors === 0) {
79
- console.log('🎉 VERIFIKASI SUKSES! Semua path relatif murni dan file fisik terdeteksi.');
80
- console.log('Bungkusan OTA ini 100% AMAN untuk dikirim.\n');
79
+ console.log('🎉 VERIFICATION SUCCESS! All paths are purely relative and physical files detected.');
80
+ console.log('This OTA bundle is 100% SAFE to deploy.\n');
81
81
  } else {
82
- console.log(`💥 VERIFIKASI GAGAL! Ditemukan ${totalErrors} error pada struktur path atau file.`);
83
- console.log('💡 WAJIB PERBAIKI sebelum mengirim OTA untuk menghindari blank screen di HP user!\n');
82
+ console.log(`💥 VERIFICATION FAILED! Found ${totalErrors} error(s) in path structure or files.`);
83
+ console.log('💡 MUST FIX before deploying OTA to avoid blank screens on users\' devices!\n');
84
84
  process.exit(1);
85
85
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ota-manager",
3
- "version": "1.0.14",
3
+ "version": "1.0.15",
4
4
  "description": "Multi-provider OTA update manager for Astro and static web projects.",
5
5
  "type": "module",
6
6
  "main": "index.js",