1pux-to-csv
Version:
Convert 1Password .1pux files to .csv
188 lines (187 loc) • 6.63 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.convert1PuxDataToCSV = exports.parseToRowData = exports.parse1PuxFile = void 0;
const jszip_1 = require("jszip");
const parse1PuxFile = async (fileContents) => {
try {
const zip = await (0, jszip_1.loadAsync)(fileContents);
const attributesContent = await zip
.file('export.attributes')
.async('string');
const attributes = JSON.parse(attributesContent);
const dataContent = await zip.file('export.data').async('string');
const data = JSON.parse(dataContent);
return {
attributes,
data,
};
}
catch (error) {
console.error('Failed to parse .1pux file');
throw error;
}
};
exports.parse1PuxFile = parse1PuxFile;
const escapeCSVValue = (value) => {
if (value === null || typeof value === 'undefined') {
return '';
}
if (typeof value !== 'string') {
return value.toString();
}
// Just return the value if there's no special character
if (!value.includes(',') &&
!value.includes(' ') &&
!value.includes('"') &&
!value.includes('\n')) {
return value;
}
return `"${value.replace(/"/g, '""').replace(/\n/g, ' ')}"`;
};
const parseFieldTypeToExtraFieldType = (field) => {
if (field.designation === 'username') {
return 'username';
}
else if (field.designation === 'password') {
return 'password';
}
else if (field.fieldType === 'E') {
return 'email';
}
else if (field.fieldType === 'U') {
return 'url';
}
return 'text';
};
const parseToRowData = (item, defaultTags) => {
const rowData = {
name: item.overview.title,
tags: [...(defaultTags || []), ...(item.overview.tags || [])].join(','),
url: item.overview.url || '',
username: '',
password: '',
notes: item.details.notesPlain || '',
extraFields: [],
};
// Skip documents
if (item.details.documentAttributes &&
item.details.loginFields.length === 0) {
return;
}
// Extract username, password, and some extraFields
item.details.loginFields.forEach((field) => {
if (field.designation === 'username') {
rowData.username = field.value;
}
else if (field.designation === 'password') {
rowData.password = field.value;
}
else if (field.fieldType === 'I' ||
field.fieldType === 'C' ||
field.id.includes(';opid=__') ||
field.value === '') {
// Skip these noisy form-fields
return;
}
else {
rowData.extraFields.push({
name: field.name || field.id,
value: field.value,
type: parseFieldTypeToExtraFieldType(field),
});
}
});
// Extract some more extraFields
item.details.sections.forEach((section) => {
section.fields.forEach((field) => {
let value = '';
let type = 'text';
if (Object.prototype.hasOwnProperty.call(field.value, 'concealed')) {
value = field.value.concealed || '';
}
else if (Object.prototype.hasOwnProperty.call(field.value, 'reference')) {
value = field.value.reference || '';
}
else if (Object.prototype.hasOwnProperty.call(field.value, 'string')) {
value = field.value.string || '';
}
else if (Object.prototype.hasOwnProperty.call(field.value, 'email')) {
value = field.value.email || '';
type = 'email';
}
else if (Object.prototype.hasOwnProperty.call(field.value, 'phone')) {
value = field.value.phone || '';
type = 'phone';
}
else if (Object.prototype.hasOwnProperty.call(field.value, 'url')) {
value = field.value.url || '';
type = 'url';
}
else if (Object.prototype.hasOwnProperty.call(field.value, 'totp')) {
value = field.value.totp || '';
type = 'totp';
}
else if (Object.prototype.hasOwnProperty.call(field.value, 'gender')) {
value = field.value.gender || '';
}
else if (Object.prototype.hasOwnProperty.call(field.value, 'creditCardType')) {
value = field.value.creditCardType || '';
}
else if (Object.prototype.hasOwnProperty.call(field.value, 'creditCardNumber')) {
value = field.value.creditCardNumber || '';
type = 'credit';
}
else if (Object.prototype.hasOwnProperty.call(field.value, 'monthYear')) {
value =
(field.value.monthYear && field.value.monthYear.toString()) || '';
type = 'month';
}
else if (Object.prototype.hasOwnProperty.call(field.value, 'date')) {
value = (field.value.date && field.value.date.toString()) || '';
type = 'date';
}
else {
// Default, so no data is lost when something new comes up
value = JSON.stringify(field.value);
}
rowData.extraFields.push({
name: field.title || field.id,
value,
type,
});
});
});
return rowData;
};
exports.parseToRowData = parseToRowData;
const convertDataToRow = (rowData) => {
const row = [
rowData.name,
rowData.tags,
rowData.url,
rowData.username,
rowData.password,
rowData.notes,
JSON.stringify(rowData.extraFields),
]
.map(escapeCSVValue)
.join(',');
return row;
};
const convert1PuxDataToCSV = async (onePuxData) => {
const rows = ['name,tags,url,username,password,notes,extraFields'];
onePuxData.accounts.forEach((account) => {
account.vaults.forEach((vault) => {
vault.items.forEach((item) => {
if (item.item && !item.item.trashed) {
const rowData = (0, exports.parseToRowData)(item.item, [vault.attrs.name]);
if (rowData) {
rows.push(convertDataToRow(rowData));
}
}
});
});
});
return rows.join('\n');
};
exports.convert1PuxDataToCSV = convert1PuxDataToCSV;