Package Exports
- sakti-parser-fa
- sakti-parser-fa/browser
- sakti-parser-fa/core
- sakti-parser-fa/node
Readme
Sakti Parser FA
Universal TypeScript library untuk mem-parsing file Excel Laporan Ketersediaan Dana (FA) dari sistem Sakti Kementerian Keuangan RI. Bekerja di browser dan Node.js.
โจ Fitur Utama
- ๐ Universal - Bekerja di browser dan server
- ๐๏ธ Parsing Hierarki - Struktur anggaran 11 level sesuai Sakti
- ๐ Multi Format - Object, JSON, dan CSV output
- โ Validasi Data - Otomatis cleaning dan validasi
- ๐ Type Safety - Full TypeScript support
- ๐ฎ๐ฉ Bahasa Indonesia - Parsing tanggal dan format lokal
- โก Performance - Optimized untuk file besar
๐ฆ Instalasi
npm install sakti-parser-fa๐ Quick Start
Browser (React.js)
import React, { useState } from 'react';
import { SaktiParser } from 'sakti-parser-fa/browser';
function ExcelUploader() {
const [result, setResult] = useState(null);
const [loading, setLoading] = useState(false);
const handleFileUpload = async (event: React.ChangeEvent<HTMLInputElement>) => {
const file = event.target.files?.[0];
if (!file) return;
setLoading(true);
try {
const parser = new SaktiParser({
outputFormat: 'object'
});
const parseResult = await parser.parseStructuredData(file);
setResult(parseResult);
} catch (error) {
console.error('Error parsing file:', error);
} finally {
setLoading(false);
}
};
return (
<div>
<input
type="file"
accept=".xlsx"
onChange={handleFileUpload}
disabled={loading}
/>
{loading && <p>Processing...</p>}
{result && (
<div>
<h3>๐ Metadata</h3>
<p>Judul: {result.metadata.judul}</p>
<p>Periode: {result.metadata.periode_text}</p>
<p>Kementerian: {result.metadata.kementerian_nama}</p>
<h3>๐ Data</h3>
<p>Total items: {result.data.length}</p>
{/* Show first 5 items */}
{result.data.slice(0, 5).map((item, index) => (
<div key={index} style={{ marginLeft: item._level * 20 }}>
<strong>Level {item._level}:</strong> {item.uraian}
<br />
<small>Budget: Rp {item.pagu.toLocaleString('id-ID')}</small>
</div>
))}
</div>
)}
</div>
);
}
export default ExcelUploader;Server (Express.js)
import express from 'express';
import multer from 'multer';
import { SaktiParser } from 'sakti-parser-fa/node';
const app = express();
const upload = multer({ dest: 'uploads/' });
// Parse Excel file endpoint
app.post('/api/parse-excel', upload.single('excelFile'), async (req, res) => {
try {
if (!req.file) {
return res.status(400).json({ error: 'No file uploaded' });
}
const parser = new SaktiParser({
outputFormat: 'json'
});
// Parse the uploaded file
const result = await parser.parseStructuredData(req.file.path);
// Return parsed data
res.json({
success: true,
metadata: result.metadata,
dataCount: result.data.length,
data: result.data
});
} catch (error) {
console.error('Parsing error:', error);
res.status(500).json({
error: 'Failed to parse Excel file',
message: error.message
});
}
});
// Get summary endpoint
app.post('/api/parse-summary', upload.single('excelFile'), async (req, res) => {
try {
const parser = new SaktiParser();
const result = await parser.parseStructuredData(req.file.path);
// Calculate summary
const summary = {
metadata: result.metadata,
totalItems: result.data.length,
totalBudget: result.data
.filter(item => item._level === 11)
.reduce((sum, item) => sum + item.pagu, 0),
levelBreakdown: {}
};
// Count items by level
result.data.forEach(item => {
summary.levelBreakdown[item._level] =
(summary.levelBreakdown[item._level] || 0) + 1;
});
res.json(summary);
} catch (error) {
res.status(500).json({ error: error.message });
}
});
app.listen(3000, () => {
console.log('Server running on port 3000');
});๐ Data Structure
Input: Excel FA File
File Excel dengan struktur:
- Baris 1: Judul laporan
- Baris 3: Periode (contoh: "Periode Juli 2025")
- Baris 4-6: Metadata kementerian, unit, satuan kerja
- Baris 10+: Data anggaran hierarki (11 level)
Output: Structured Data
interface ParseResult {
metadata: {
judul: string;
periode_text: string;
periode_bulan: number; // 1-12
periode_tahun: number; // 2025
kementerian_kode: string; // "145"
kementerian_nama: string; // "KEMENTERIAN KEUANGAN"
unit_kode: string; // "06"
unit_nama: string; // "SEKRETARIAT JENDERAL"
satuan_kerja_kode: string; // "123456"
satuan_kerja_nama: string; // "BIRO KEUANGAN"
};
data: Array<{
_level: number; // 1-11 (hierarchy level)
_parent: string; // Parent mata anggaran
mata_anggaran: string; // Full budget code
kode: string; // Item code
uraian: string; // Description
pagu: number; // Budget amount (Rupiah)
pagu_terkunci: number; // Locked budget
realisasi_sebelum: number; // Previous realization
realisasi_periode: number; // Current period realization
realisasi_kumulatif: number; // Total realization
realisasi_persen: number; // Realization percentage (0.0-1.0)
sisa_anggaran: number; // Remaining budget
}>;
}๐ง Configuration Options
const parser = new SaktiParser({
// Output format
outputFormat: 'object' | 'json' | 'csv',
// CSV options
csvOptions: {
delimiter: ';', // Column separator
header: true, // Include header row
quoted: true // Quote all fields
},
// JSON options
jsonOptions: {
flat: true // Flat array vs nested object
}
});๐ก Advanced Usage
Universal Parser (Auto-detect Environment)
import { UniversalSaktiParser } from 'sakti-parser-fa';
const parser = new UniversalSaktiParser();
// Works in Node.js
const result1 = await parser.parse('./file.xlsx');
// Works in browser
const result2 = await parser.parse(fileObject);
// Works everywhere
const result3 = await parser.parse(worksheetData);Multiple Output Formats
// Get different formats
const objectResult = await parser.parseAndFormat(input); // Default: object
const jsonResult = await parser.parseAndFormat(input, { outputFormat: 'json' });
const csvResult = await parser.parseAndFormat(input, { outputFormat: 'csv' });Custom CSV Export
const parser = new SaktiParser({
outputFormat: 'csv',
csvOptions: {
delimiter: ';',
header: true,
quoted: true
}
});
const result = await parser.parseAndFormat('file.xlsx');
// result.content.data contains CSV string๐ Bundle Sizes
- Core: 36KB (pure parsing logic)
- Browser: 43KB (includes File handling)
- Node.js: 42KB (includes file reading)
- Universal: 41KB (auto-detection)
All bundles are gzipped and include TypeScript definitions.
๐ Browser Support
- Modern Browsers: Chrome 80+, Firefox 75+, Safari 13+, Edge 80+
- Mobile: iOS Safari 13+, Chrome Android 80+
- Bundle: ES2020 modules with tree-shaking support
๐ Examples
- Basic Usage - Simple file parsing
- Formatting Options - Different output formats
- Browser Demo - Complete web application
- React Component - React.js integration
- Express Server - Node.js API server
๐งช Testing
npm test # Run all tests
npm run test:coverage # Run with coverage
npm run test:watch # Watch modeTest Coverage: 85%+ with 88 test cases across all platforms.
๐ Links
๐ License
MIT License - see LICENSE file.
๐ท๏ธ Keywords
sakti kementerian-keuangan anggaran excel-parser typescript universal browser nodejs indonesia government budget hierarchical-data
Dibuat dengan โค๏ธ untuk komunitas developer Indonesia
๐ Documentation โข ๐ก Examples โข ๐ Issues โข ๐ฌ Discussions