%PDF- <> %âãÏÓ endobj 2 0 obj <> endobj 3 0 obj <>/ExtGState<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/Annots[ 28 0 R 29 0 R] /MediaBox[ 0 0 595.5 842.25] /Contents 4 0 R/Group<>/Tabs/S>> endobj ºaâÚÎΞ-ÌE1ÍØÄ÷{òò2ÿ ÛÖ^ÔÀá TÎ{¦?§®¥kuµùÕ5sLOšuY>endobj 2 0 obj<>endobj 2 0 obj<>endobj 2 0 obj<>endobj 2 0 obj<> endobj 2 0 obj<>endobj 2 0 obj<>es 3 0 R>> endobj 2 0 obj<> ox[ 0.000000 0.000000 609.600000 935.600000]/Fi endobj 3 0 obj<> endobj 7 1 obj<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI]>>/Subtype/Form>> stream
/**
* build-deploy.js — Susun folder `_deploy/` siap-upload ke hosting (mis. InfinityFree).
*
* Dijalankan via: npm run build:deploy
* (npm script sudah menjalankan `npm run build:css` lebih dulu agar app.css minified & segar.)
*
* Prinsip: WHITELIST — hanya menyalin berkas yang benar-benar dibutuhkan server.
* Semua artefak dev/build (node_modules, resources, .git, config build, installer, dll.)
* TIDAK ikut. Server tidak perlu Node.
*/
'use strict';
const fs = require('fs');
const path = require('path');
const ROOT = path.join(__dirname, '..');
const OUT = path.join(ROOT, '_deploy');
// Berkas .php di root yang TIDAK ikut (installer sekali pakai).
const ROOT_PHP_EXCLUDE = new Set(['install.php', 'install_.php']);
// Folder yang disalin utuh (beserta isinya).
const COPY_DIRS = ['admin', 'config', 'includes', 'partials', 'lang', 'assets', 'uploads', 'database'];
// Berkas tambahan di root (non-.php) yang ikut.
const COPY_ROOT_FILES = ['.htaccess'];
// Path relatif (di dalam folder yang disalin) yang DIKECUALIKAN.
const EXCLUDE_REL = new Set(
[
'assets/video-mateng_.mp4', // backup video asli, tidak dipakai situs
].map((p) => p.split('/').join(path.sep))
);
// Nama folder yang selalu dilewati (jaga-jaga bila tersisip di suatu tempat).
const ALWAYS_SKIP = new Set(['node_modules', '.git', '_deploy']);
/**
* Filter untuk fs.cpSync: kembalikan false untuk melewati berkas/folder.
*
* CATATAN (Windows): fs.cpSync memberikan `src` dalam bentuk extended-length
* path berawalan `\\?\` (mis. \\?\C:\...\assets\video.mp4). Tanpa dinormalkan,
* path.relative() menghasilkan path yang tidak pernah cocok dengan EXCLUDE_REL
* sehingga exclude gagal DIAM-DIAM. Karena itu prefix dibuang lebih dulu.
*/
function keep(src) {
const clean = String(src).replace(/^\\\\\?\\/, '');
const base = path.basename(clean);
if (ALWAYS_SKIP.has(base)) return false;
const rel = path.relative(ROOT, clean);
if (EXCLUDE_REL.has(rel)) return false;
return true;
}
/** Hitung jumlah berkas & total ukuran (byte) secara rekursif. */
function stats(dir) {
let files = 0;
let bytes = 0;
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
const full = path.join(dir, entry.name);
if (entry.isDirectory()) {
const s = stats(full);
files += s.files;
bytes += s.bytes;
} else {
files += 1;
bytes += fs.statSync(full).size;
}
}
return { files, bytes };
}
function humanMB(bytes) {
return (bytes / (1024 * 1024)).toFixed(1) + ' MB';
}
function main() {
// 1) Bersihkan folder lama.
fs.rmSync(OUT, { recursive: true, force: true });
fs.mkdirSync(OUT, { recursive: true });
// 2) Salin berkas .php di root (kecuali installer).
let phpCount = 0;
for (const name of fs.readdirSync(ROOT)) {
if (!name.toLowerCase().endsWith('.php')) continue;
if (ROOT_PHP_EXCLUDE.has(name)) continue;
fs.copyFileSync(path.join(ROOT, name), path.join(OUT, name));
phpCount++;
}
// 3) Salin berkas root tambahan (.htaccess).
for (const name of COPY_ROOT_FILES) {
const src = path.join(ROOT, name);
if (fs.existsSync(src)) fs.copyFileSync(src, path.join(OUT, name));
}
// 4) Salin folder-folder (whitelist) dengan filter exclude.
for (const dir of COPY_DIRS) {
const src = path.join(ROOT, dir);
if (!fs.existsSync(src)) {
console.warn(' ! folder tidak ditemukan, dilewati: ' + dir);
continue;
}
fs.cpSync(src, path.join(OUT, dir), { recursive: true, filter: keep });
}
// 5) Ringkasan + pengingat.
const s = stats(OUT);
const cssPath = path.join(OUT, 'assets', 'css', 'app.css');
const cssKB = fs.existsSync(cssPath) ? Math.round(fs.statSync(cssPath).size / 1024) : 0;
console.log('');
console.log(' ✅ _deploy/ siap — ' + s.files + ' berkas, ' + humanMB(s.bytes));
console.log(' berkas .php root : ' + phpCount);
console.log(' app.css minified : ' + cssKB + ' KB');
console.log(' lokasi : ' + OUT);
console.log('');
console.log(' Langkah berikutnya (lihat CLAUDE.md → Deploy ke hosting):');
console.log(' 1) Upload SEMUA ISI _deploy/ ke htdocs/ (bukan folder _deploy-nya).');
console.log(' 2) Edit config/database.php dgn kredensial hosting.');
console.log(' 3) Impor database/ppid_mateng.sql via phpMyAdmin (install baru).');
console.log(' 4) Set PHP 8.1+ ; opsional APP_ENV=production di config/config.php.');
console.log(' ⚠ Saat UPDATE: jangan timpa uploads/ & config/database.php di server.');
console.log('');
}
main();