servchan/tools/convert.js
jmcqueen c2e98d105e Initial commit: ServChan Webex bot for ServiceChannel work orders.
ServiceChannel webhook processor, proposal approval cards, attachment auto-post,
CollabSupport commands, and Docker deployment configuration.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-24 15:12:08 -04:00

97 lines
No EOL
3.3 KiB
JavaScript

import fs from 'fs';
import { Parser } from 'json2csv';
// Load the enriched JSON file
const jsonFile = 'enriched-meraki.csv.json'; // Your input JSON path
const data = JSON.parse(fs.readFileSync(jsonFile, 'utf8'));
// Flatten the nested objects for CSV-friendly structure
const flattenedData = data.map(item => {
const meraki = item.meraki || {}; // safe access
// Handle stickyMacList as comma-separated string (or empty string)
const stickyMacListStr = Array.isArray(meraki.stickyMacList) && meraki.stickyMacList.length > 0
? meraki.stickyMacList.join(', ')
: '';
return {
device_id: item.device_id || '',
device_friendly_name: item.device_friendly_name || '',
device_enrollment_user_name: item.device_enrollment_user_name || '',
_device_platform: item._device_platform || '',
device_os_version: item.device_os_version || '',
device_last_seen_utc: item.device_last_seen_utc || '',
device_enrollment_status: item.device_enrollment_status || '',
device_model_name: item.device_model_name || '',
_device_mac_address: item._device_mac_address || '',
device_mac_address: item.device_mac_address || '',
// Existing Meraki fields
meraki_deviceName: meraki.deviceName || '',
meraki_switchport: meraki.switchport || '',
meraki_vlan: meraki.vlan || '',
meraki_status: meraki.status || '',
meraki_connection: meraki.connection || '',
meraki_lastSeen: meraki.lastSeen || '',
meraki_ip: meraki.ip || '',
meraki_mac: meraki.mac || '',
// New Meraki port / Sticky MAC fields
meraki_portType: meraki.portType || 'N/A',
meraki_portEnabled: meraki.portEnabled != null
? (typeof meraki.portEnabled === 'boolean'
? (meraki.portEnabled ? 'Enabled' : 'Disabled')
: meraki.portEnabled) // handles 'Error' / 'N/A'
: 'N/A',
meraki_accessPolicyType: meraki.accessPolicyType || 'N/A',
meraki_stickyMacEnabled: meraki.stickyMacEnabled === true ? 'true' : 'false', // explicit string for CSV clarity
meraki_stickyMacList: stickyMacListStr,
meraki_stickyMacAllowListLimit: meraki.stickyMacAllowListLimit != null ? meraki.stickyMacAllowListLimit : '',
meraki_stickyMacCount: meraki.stickyMacCount != null ? meraki.stickyMacCount : '',
meraki_portError: meraki.portError || '' // only present if fetch failed
};
});
// Define all CSV column headers (order matters for output)
const fields = [
'device_id',
'device_friendly_name',
'device_enrollment_user_name',
'_device_platform',
'device_os_version',
'device_last_seen_utc',
'device_enrollment_status',
'device_model_name',
'_device_mac_address',
'device_mac_address',
'meraki_deviceName',
'meraki_switchport',
'meraki_vlan',
'meraki_status',
'meraki_connection',
'meraki_lastSeen',
'meraki_ip',
'meraki_mac',
// New fields
'meraki_portType',
'meraki_accessPolicyType',
'meraki_portEnabled', // ← NEW
'meraki_stickyMacEnabled',
'meraki_stickyMacList',
'meraki_stickyMacAllowListLimit',
'meraki_stickyMacCount',
'meraki_portError'
];
const opts = { fields };
const parser = new Parser(opts);
const csv = parser.parse(flattenedData);
// Save to output CSV
const csvFile = 'enriched-meraki-output.csv';
fs.writeFileSync(csvFile, csv);
console.log(`CSV file created: ${csvFile}`);
console.log(`Total rows processed: ${flattenedData.length}`);