vcf-to-json-converter 1.0.1 → 1.0.2
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/LICENSE +21 -21
- package/README.md +457 -457
- package/index.d.ts +32 -32
- package/index.js +252 -252
- package/package.json +5 -4
package/index.d.ts
CHANGED
|
@@ -1,32 +1,32 @@
|
|
|
1
|
-
export interface Phone {
|
|
2
|
-
value: string;
|
|
3
|
-
type: string;
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
export interface Email {
|
|
7
|
-
value: string;
|
|
8
|
-
type: string;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export interface Contact {
|
|
12
|
-
fullName: string;
|
|
13
|
-
firstName: string;
|
|
14
|
-
lastName: string;
|
|
15
|
-
phones: Phone[];
|
|
16
|
-
emails: Email[];
|
|
17
|
-
organization: string;
|
|
18
|
-
title: string;
|
|
19
|
-
note: string;
|
|
20
|
-
photo: string;
|
|
21
|
-
url: string;
|
|
22
|
-
raw: any;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export declare function vcfToJson(vcfText: string): Contact[];
|
|
26
|
-
export declare function vcfToJsonFromFile(filePath: string): Contact[];
|
|
27
|
-
export declare function saveJsonToFile(
|
|
28
|
-
jsonData: Contact[],
|
|
29
|
-
outputPath: string,
|
|
30
|
-
prettyPrint?: boolean
|
|
31
|
-
): void;
|
|
32
|
-
export declare function cli(): void;
|
|
1
|
+
export interface Phone {
|
|
2
|
+
value: string;
|
|
3
|
+
type: string;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
export interface Email {
|
|
7
|
+
value: string;
|
|
8
|
+
type: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface Contact {
|
|
12
|
+
fullName: string;
|
|
13
|
+
firstName: string;
|
|
14
|
+
lastName: string;
|
|
15
|
+
phones: Phone[];
|
|
16
|
+
emails: Email[];
|
|
17
|
+
organization: string;
|
|
18
|
+
title: string;
|
|
19
|
+
note: string;
|
|
20
|
+
photo: string;
|
|
21
|
+
url: string;
|
|
22
|
+
raw: any;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export declare function vcfToJson(vcfText: string): Contact[];
|
|
26
|
+
export declare function vcfToJsonFromFile(filePath: string): Contact[];
|
|
27
|
+
export declare function saveJsonToFile(
|
|
28
|
+
jsonData: Contact[],
|
|
29
|
+
outputPath: string,
|
|
30
|
+
prettyPrint?: boolean
|
|
31
|
+
): void;
|
|
32
|
+
export declare function cli(): void;
|
package/index.js
CHANGED
|
@@ -1,252 +1,252 @@
|
|
|
1
|
-
const fs = require("fs");
|
|
2
|
-
const path = require("path");
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Manual VCF parser that properly extracts contact information
|
|
6
|
-
* @param {string} vcfText - The VCF content as string
|
|
7
|
-
* @returns {Array} Array of contact objects
|
|
8
|
-
*/
|
|
9
|
-
function parseVCF(vcfText) {
|
|
10
|
-
const contacts = [];
|
|
11
|
-
|
|
12
|
-
// Split by BEGIN:VCARD to handle multiple contacts
|
|
13
|
-
const vCards = vcfText.split("BEGIN:VCARD").filter((card) => card.trim());
|
|
14
|
-
|
|
15
|
-
for (const vCard of vCards) {
|
|
16
|
-
const lines = vCard.split(/\r?\n/).filter((line) => line.trim());
|
|
17
|
-
|
|
18
|
-
const contact = {
|
|
19
|
-
fullName: "",
|
|
20
|
-
firstName: "",
|
|
21
|
-
lastName: "",
|
|
22
|
-
phones: [],
|
|
23
|
-
emails: [],
|
|
24
|
-
organization: "",
|
|
25
|
-
title: "",
|
|
26
|
-
note: "",
|
|
27
|
-
photo: "",
|
|
28
|
-
url: "",
|
|
29
|
-
raw: vCard, // Store original vCard text
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
for (const line of lines) {
|
|
33
|
-
// Parse FN (Formatted Name) - supports UTF-8/Hindi
|
|
34
|
-
if (line.startsWith("FN:")) {
|
|
35
|
-
contact.fullName = line.substring(3).trim();
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
// Parse N (Name) for first and last name
|
|
39
|
-
if (line.startsWith("N:")) {
|
|
40
|
-
const nameParts = line.substring(2).split(";");
|
|
41
|
-
// Format: Last;First;Middle;Prefix;Suffix
|
|
42
|
-
contact.lastName = (nameParts[0] || "").trim();
|
|
43
|
-
contact.firstName = (nameParts[1] || "").trim();
|
|
44
|
-
|
|
45
|
-
// If fullName is empty, construct it from first and last name
|
|
46
|
-
if (!contact.fullName) {
|
|
47
|
-
contact.fullName = `${contact.firstName} ${contact.lastName}`.trim();
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// Parse TEL (Phone)
|
|
52
|
-
if (line.startsWith("TEL")) {
|
|
53
|
-
const phoneMatch = line.match(/:([\d\s\-+()]+)/);
|
|
54
|
-
if (phoneMatch) {
|
|
55
|
-
// Extract phone type from the TEL line
|
|
56
|
-
let phoneType = "unknown";
|
|
57
|
-
if (line.includes("CELL")) phoneType = "mobile";
|
|
58
|
-
else if (line.includes("HOME")) phoneType = "home";
|
|
59
|
-
else if (line.includes("WORK")) phoneType = "work";
|
|
60
|
-
else if (line.includes("VOICE")) phoneType = "voice";
|
|
61
|
-
else if (line.includes("PREF")) phoneType = "primary";
|
|
62
|
-
|
|
63
|
-
contact.phones.push({
|
|
64
|
-
value: phoneMatch[1].trim(),
|
|
65
|
-
type: phoneType,
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
// Parse EMAIL
|
|
71
|
-
if (line.startsWith("EMAIL")) {
|
|
72
|
-
const emailMatch = line.match(/:(.+)/);
|
|
73
|
-
if (emailMatch) {
|
|
74
|
-
// Extract email type from the EMAIL line
|
|
75
|
-
let emailType = "unknown";
|
|
76
|
-
if (line.includes("HOME")) emailType = "home";
|
|
77
|
-
else if (line.includes("WORK")) emailType = "work";
|
|
78
|
-
else if (line.includes("PREF")) emailType = "primary";
|
|
79
|
-
|
|
80
|
-
contact.emails.push({
|
|
81
|
-
value: emailMatch[1].trim(),
|
|
82
|
-
type: emailType,
|
|
83
|
-
});
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
// Parse ORG (Organization)
|
|
88
|
-
if (line.startsWith("ORG:")) {
|
|
89
|
-
contact.organization = line.substring(4).trim();
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
// Parse TITLE
|
|
93
|
-
if (line.startsWith("TITLE:")) {
|
|
94
|
-
contact.title = line.substring(6).trim();
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
// Parse NOTE
|
|
98
|
-
if (line.startsWith("NOTE:")) {
|
|
99
|
-
contact.note = line.substring(5).trim();
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
// Parse URL
|
|
103
|
-
if (line.startsWith("URL:")) {
|
|
104
|
-
contact.url = line.substring(4).trim();
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
// Parse PHOTO (basic support)
|
|
108
|
-
if (line.startsWith("PHOTO:")) {
|
|
109
|
-
contact.photo = line.substring(6).trim();
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
// Only add contact if it has meaningful data
|
|
114
|
-
if (
|
|
115
|
-
contact.fullName ||
|
|
116
|
-
contact.firstName ||
|
|
117
|
-
contact.lastName ||
|
|
118
|
-
contact.phones.length > 0
|
|
119
|
-
) {
|
|
120
|
-
contacts.push(contact);
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
return contacts;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
/**
|
|
128
|
-
* Convert VCF text content to JSON
|
|
129
|
-
* @param {string} vcfText - The VCF content as string
|
|
130
|
-
* @returns {Array} Array of contact objects
|
|
131
|
-
*/
|
|
132
|
-
function vcfToJson(vcfText) {
|
|
133
|
-
if (!vcfText || typeof vcfText !== "string") {
|
|
134
|
-
throw new Error("Invalid VCF content. Expected non-empty string.");
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
try {
|
|
138
|
-
return parseVCF(vcfText);
|
|
139
|
-
} catch (error) {
|
|
140
|
-
throw new Error(`Failed to parse VCF content: ${error.message}`);
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
/**
|
|
145
|
-
* Convert VCF file to JSON
|
|
146
|
-
* @param {string} filePath - Path to the VCF file
|
|
147
|
-
* @returns {Array} Array of contact objects
|
|
148
|
-
*/
|
|
149
|
-
function vcfToJsonFromFile(filePath) {
|
|
150
|
-
if (!filePath || typeof filePath !== "string") {
|
|
151
|
-
throw new Error("File path is required and must be a string.");
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
try {
|
|
155
|
-
if (!fs.existsSync(filePath)) {
|
|
156
|
-
throw new Error(`File not found: ${filePath}`);
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
const vcfText = fs.readFileSync(filePath, "utf8");
|
|
160
|
-
return vcfToJson(vcfText);
|
|
161
|
-
} catch (error) {
|
|
162
|
-
if (error.code === "ENOENT") {
|
|
163
|
-
throw new Error(`File not found: ${filePath}`);
|
|
164
|
-
}
|
|
165
|
-
if (error.code === "EACCES") {
|
|
166
|
-
throw new Error(`Permission denied: ${filePath}`);
|
|
167
|
-
}
|
|
168
|
-
throw error;
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
/**
|
|
173
|
-
* Save JSON data to file
|
|
174
|
-
* @param {Array} jsonData - The JSON data to save
|
|
175
|
-
* @param {string} outputPath - Path to save the JSON file
|
|
176
|
-
* @param {boolean} prettyPrint - Whether to format JSON with indentation
|
|
177
|
-
*/
|
|
178
|
-
function saveJsonToFile(jsonData, outputPath, prettyPrint = true) {
|
|
179
|
-
if (!outputPath || typeof outputPath !== "string") {
|
|
180
|
-
throw new Error("Output path is required and must be a string.");
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
try {
|
|
184
|
-
const jsonString = prettyPrint
|
|
185
|
-
? JSON.stringify(jsonData, null, 2)
|
|
186
|
-
: JSON.stringify(jsonData);
|
|
187
|
-
|
|
188
|
-
fs.writeFileSync(outputPath, jsonString, "utf8");
|
|
189
|
-
} catch (error) {
|
|
190
|
-
throw new Error(`Failed to save JSON file: ${error.message}`);
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
/**
|
|
195
|
-
* CLI function to convert VCF to JSON
|
|
196
|
-
*/
|
|
197
|
-
function cli() {
|
|
198
|
-
const args = process.argv.slice(2);
|
|
199
|
-
|
|
200
|
-
if (args.length === 0 || args.includes("--help") || args.includes("-h")) {
|
|
201
|
-
console.log(`
|
|
202
|
-
VCF to JSON Converter
|
|
203
|
-
|
|
204
|
-
Usage:
|
|
205
|
-
vcf-to-json <input.vcf> [output.json] [options]
|
|
206
|
-
|
|
207
|
-
Options:
|
|
208
|
-
--compact, -c Output compact JSON (no formatting)
|
|
209
|
-
--help, -h Show this help message
|
|
210
|
-
|
|
211
|
-
Examples:
|
|
212
|
-
vcf-to-json contacts.vcf
|
|
213
|
-
vcf-to-json contacts.vcf output.json
|
|
214
|
-
vcf-to-json contacts.vcf output.json --compact
|
|
215
|
-
`);
|
|
216
|
-
return;
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
const inputFile = args[0];
|
|
220
|
-
const outputFile = args[1] || inputFile.replace(/\.vcf$/i, ".json");
|
|
221
|
-
const compact = args.includes("--compact") || args.includes("-c");
|
|
222
|
-
|
|
223
|
-
try {
|
|
224
|
-
console.log(`Converting ${inputFile} to JSON...`);
|
|
225
|
-
const jsonData = vcfToJsonFromFile(inputFile);
|
|
226
|
-
|
|
227
|
-
if (args[1]) {
|
|
228
|
-
saveJsonToFile(jsonData, outputFile, !compact);
|
|
229
|
-
console.log(
|
|
230
|
-
`✅ Converted ${jsonData.length} contacts and saved to ${outputFile}`
|
|
231
|
-
);
|
|
232
|
-
} else {
|
|
233
|
-
console.log(JSON.stringify(jsonData, null, compact ? 0 : 2));
|
|
234
|
-
}
|
|
235
|
-
} catch (error) {
|
|
236
|
-
console.error(`❌ Error: ${error.message}`);
|
|
237
|
-
process.exit(1);
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
// Export functions
|
|
242
|
-
module.exports = {
|
|
243
|
-
vcfToJson,
|
|
244
|
-
vcfToJsonFromFile,
|
|
245
|
-
saveJsonToFile,
|
|
246
|
-
cli,
|
|
247
|
-
};
|
|
248
|
-
|
|
249
|
-
// If this file is run directly, execute CLI
|
|
250
|
-
if (require.main === module) {
|
|
251
|
-
cli();
|
|
252
|
-
}
|
|
1
|
+
const fs = require("fs");
|
|
2
|
+
const path = require("path");
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Manual VCF parser that properly extracts contact information
|
|
6
|
+
* @param {string} vcfText - The VCF content as string
|
|
7
|
+
* @returns {Array} Array of contact objects
|
|
8
|
+
*/
|
|
9
|
+
function parseVCF(vcfText) {
|
|
10
|
+
const contacts = [];
|
|
11
|
+
|
|
12
|
+
// Split by BEGIN:VCARD to handle multiple contacts
|
|
13
|
+
const vCards = vcfText.split("BEGIN:VCARD").filter((card) => card.trim());
|
|
14
|
+
|
|
15
|
+
for (const vCard of vCards) {
|
|
16
|
+
const lines = vCard.split(/\r?\n/).filter((line) => line.trim());
|
|
17
|
+
|
|
18
|
+
const contact = {
|
|
19
|
+
fullName: "",
|
|
20
|
+
firstName: "",
|
|
21
|
+
lastName: "",
|
|
22
|
+
phones: [],
|
|
23
|
+
emails: [],
|
|
24
|
+
organization: "",
|
|
25
|
+
title: "",
|
|
26
|
+
note: "",
|
|
27
|
+
photo: "",
|
|
28
|
+
url: "",
|
|
29
|
+
raw: vCard, // Store original vCard text
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
for (const line of lines) {
|
|
33
|
+
// Parse FN (Formatted Name) - supports UTF-8/Hindi
|
|
34
|
+
if (line.startsWith("FN:")) {
|
|
35
|
+
contact.fullName = line.substring(3).trim();
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Parse N (Name) for first and last name
|
|
39
|
+
if (line.startsWith("N:")) {
|
|
40
|
+
const nameParts = line.substring(2).split(";");
|
|
41
|
+
// Format: Last;First;Middle;Prefix;Suffix
|
|
42
|
+
contact.lastName = (nameParts[0] || "").trim();
|
|
43
|
+
contact.firstName = (nameParts[1] || "").trim();
|
|
44
|
+
|
|
45
|
+
// If fullName is empty, construct it from first and last name
|
|
46
|
+
if (!contact.fullName) {
|
|
47
|
+
contact.fullName = `${contact.firstName} ${contact.lastName}`.trim();
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Parse TEL (Phone)
|
|
52
|
+
if (line.startsWith("TEL")) {
|
|
53
|
+
const phoneMatch = line.match(/:([\d\s\-+()]+)/);
|
|
54
|
+
if (phoneMatch) {
|
|
55
|
+
// Extract phone type from the TEL line
|
|
56
|
+
let phoneType = "unknown";
|
|
57
|
+
if (line.includes("CELL")) phoneType = "mobile";
|
|
58
|
+
else if (line.includes("HOME")) phoneType = "home";
|
|
59
|
+
else if (line.includes("WORK")) phoneType = "work";
|
|
60
|
+
else if (line.includes("VOICE")) phoneType = "voice";
|
|
61
|
+
else if (line.includes("PREF")) phoneType = "primary";
|
|
62
|
+
|
|
63
|
+
contact.phones.push({
|
|
64
|
+
value: phoneMatch[1].trim(),
|
|
65
|
+
type: phoneType,
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Parse EMAIL
|
|
71
|
+
if (line.startsWith("EMAIL")) {
|
|
72
|
+
const emailMatch = line.match(/:(.+)/);
|
|
73
|
+
if (emailMatch) {
|
|
74
|
+
// Extract email type from the EMAIL line
|
|
75
|
+
let emailType = "unknown";
|
|
76
|
+
if (line.includes("HOME")) emailType = "home";
|
|
77
|
+
else if (line.includes("WORK")) emailType = "work";
|
|
78
|
+
else if (line.includes("PREF")) emailType = "primary";
|
|
79
|
+
|
|
80
|
+
contact.emails.push({
|
|
81
|
+
value: emailMatch[1].trim(),
|
|
82
|
+
type: emailType,
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Parse ORG (Organization)
|
|
88
|
+
if (line.startsWith("ORG:")) {
|
|
89
|
+
contact.organization = line.substring(4).trim();
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Parse TITLE
|
|
93
|
+
if (line.startsWith("TITLE:")) {
|
|
94
|
+
contact.title = line.substring(6).trim();
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Parse NOTE
|
|
98
|
+
if (line.startsWith("NOTE:")) {
|
|
99
|
+
contact.note = line.substring(5).trim();
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Parse URL
|
|
103
|
+
if (line.startsWith("URL:")) {
|
|
104
|
+
contact.url = line.substring(4).trim();
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Parse PHOTO (basic support)
|
|
108
|
+
if (line.startsWith("PHOTO:")) {
|
|
109
|
+
contact.photo = line.substring(6).trim();
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Only add contact if it has meaningful data
|
|
114
|
+
if (
|
|
115
|
+
contact.fullName ||
|
|
116
|
+
contact.firstName ||
|
|
117
|
+
contact.lastName ||
|
|
118
|
+
contact.phones.length > 0
|
|
119
|
+
) {
|
|
120
|
+
contacts.push(contact);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return contacts;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Convert VCF text content to JSON
|
|
129
|
+
* @param {string} vcfText - The VCF content as string
|
|
130
|
+
* @returns {Array} Array of contact objects
|
|
131
|
+
*/
|
|
132
|
+
function vcfToJson(vcfText) {
|
|
133
|
+
if (!vcfText || typeof vcfText !== "string") {
|
|
134
|
+
throw new Error("Invalid VCF content. Expected non-empty string.");
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
try {
|
|
138
|
+
return parseVCF(vcfText);
|
|
139
|
+
} catch (error) {
|
|
140
|
+
throw new Error(`Failed to parse VCF content: ${error.message}`);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Convert VCF file to JSON
|
|
146
|
+
* @param {string} filePath - Path to the VCF file
|
|
147
|
+
* @returns {Array} Array of contact objects
|
|
148
|
+
*/
|
|
149
|
+
function vcfToJsonFromFile(filePath) {
|
|
150
|
+
if (!filePath || typeof filePath !== "string") {
|
|
151
|
+
throw new Error("File path is required and must be a string.");
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
try {
|
|
155
|
+
if (!fs.existsSync(filePath)) {
|
|
156
|
+
throw new Error(`File not found: ${filePath}`);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const vcfText = fs.readFileSync(filePath, "utf8");
|
|
160
|
+
return vcfToJson(vcfText);
|
|
161
|
+
} catch (error) {
|
|
162
|
+
if (error.code === "ENOENT") {
|
|
163
|
+
throw new Error(`File not found: ${filePath}`);
|
|
164
|
+
}
|
|
165
|
+
if (error.code === "EACCES") {
|
|
166
|
+
throw new Error(`Permission denied: ${filePath}`);
|
|
167
|
+
}
|
|
168
|
+
throw error;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Save JSON data to file
|
|
174
|
+
* @param {Array} jsonData - The JSON data to save
|
|
175
|
+
* @param {string} outputPath - Path to save the JSON file
|
|
176
|
+
* @param {boolean} prettyPrint - Whether to format JSON with indentation
|
|
177
|
+
*/
|
|
178
|
+
function saveJsonToFile(jsonData, outputPath, prettyPrint = true) {
|
|
179
|
+
if (!outputPath || typeof outputPath !== "string") {
|
|
180
|
+
throw new Error("Output path is required and must be a string.");
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
try {
|
|
184
|
+
const jsonString = prettyPrint
|
|
185
|
+
? JSON.stringify(jsonData, null, 2)
|
|
186
|
+
: JSON.stringify(jsonData);
|
|
187
|
+
|
|
188
|
+
fs.writeFileSync(outputPath, jsonString, "utf8");
|
|
189
|
+
} catch (error) {
|
|
190
|
+
throw new Error(`Failed to save JSON file: ${error.message}`);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* CLI function to convert VCF to JSON
|
|
196
|
+
*/
|
|
197
|
+
function cli() {
|
|
198
|
+
const args = process.argv.slice(2);
|
|
199
|
+
|
|
200
|
+
if (args.length === 0 || args.includes("--help") || args.includes("-h")) {
|
|
201
|
+
console.log(`
|
|
202
|
+
VCF to JSON Converter
|
|
203
|
+
|
|
204
|
+
Usage:
|
|
205
|
+
vcf-to-json <input.vcf> [output.json] [options]
|
|
206
|
+
|
|
207
|
+
Options:
|
|
208
|
+
--compact, -c Output compact JSON (no formatting)
|
|
209
|
+
--help, -h Show this help message
|
|
210
|
+
|
|
211
|
+
Examples:
|
|
212
|
+
vcf-to-json contacts.vcf
|
|
213
|
+
vcf-to-json contacts.vcf output.json
|
|
214
|
+
vcf-to-json contacts.vcf output.json --compact
|
|
215
|
+
`);
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
const inputFile = args[0];
|
|
220
|
+
const outputFile = args[1] || inputFile.replace(/\.vcf$/i, ".json");
|
|
221
|
+
const compact = args.includes("--compact") || args.includes("-c");
|
|
222
|
+
|
|
223
|
+
try {
|
|
224
|
+
console.log(`Converting ${inputFile} to JSON...`);
|
|
225
|
+
const jsonData = vcfToJsonFromFile(inputFile);
|
|
226
|
+
|
|
227
|
+
if (args[1]) {
|
|
228
|
+
saveJsonToFile(jsonData, outputFile, !compact);
|
|
229
|
+
console.log(
|
|
230
|
+
`✅ Converted ${jsonData.length} contacts and saved to ${outputFile}`
|
|
231
|
+
);
|
|
232
|
+
} else {
|
|
233
|
+
console.log(JSON.stringify(jsonData, null, compact ? 0 : 2));
|
|
234
|
+
}
|
|
235
|
+
} catch (error) {
|
|
236
|
+
console.error(`❌ Error: ${error.message}`);
|
|
237
|
+
process.exit(1);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// Export functions
|
|
242
|
+
module.exports = {
|
|
243
|
+
vcfToJson,
|
|
244
|
+
vcfToJsonFromFile,
|
|
245
|
+
saveJsonToFile,
|
|
246
|
+
cli,
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
// If this file is run directly, execute CLI
|
|
250
|
+
if (require.main === module) {
|
|
251
|
+
cli();
|
|
252
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vcf-to-json-converter",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "A lightweight Node.js library to convert VCF (vCard) files to JSON format with CLI support",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Shubhanshu Rao",
|
|
@@ -8,12 +8,13 @@
|
|
|
8
8
|
"main": "index.js",
|
|
9
9
|
"types": "index.d.ts",
|
|
10
10
|
"bin": {
|
|
11
|
-
"vcf-to-json": "
|
|
11
|
+
"vcf-to-json": "index.js"
|
|
12
12
|
},
|
|
13
13
|
"scripts": {
|
|
14
14
|
"start": "node index.js",
|
|
15
15
|
"test": "node test.js",
|
|
16
|
-
"demo": "node index.js contacts.vcf"
|
|
16
|
+
"demo": "node index.js contacts.vcf",
|
|
17
|
+
"build": "node index.js"
|
|
17
18
|
},
|
|
18
19
|
"keywords": [
|
|
19
20
|
"vcf",
|
|
@@ -26,7 +27,7 @@
|
|
|
26
27
|
],
|
|
27
28
|
"repository": {
|
|
28
29
|
"type": "git",
|
|
29
|
-
"url": "https://github.com/shubhanshurav/vcf-to-json.git"
|
|
30
|
+
"url": "git+https://github.com/shubhanshurav/vcf-to-json.git"
|
|
30
31
|
},
|
|
31
32
|
"bugs": {
|
|
32
33
|
"url": "https://github.com/shubhanshurav/vcf-to-json.git/issues"
|