@alwatr/json2csv 1.0.4 โ 2.0.0
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/dist/main.js +6 -0
- package/dist/main.js.map +10 -0
- package/package.json +19 -21
- package/src/main.ts +92 -0
- package/CHANGELOG.md +0 -38
- package/dist/main.cjs +0 -4
- package/dist/main.cjs.map +0 -7
- package/dist/main.mjs +0 -4
- package/dist/main.mjs.map +0 -7
package/dist/main.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/* ๐ฆ @alwatr/json2csv v2.0.0 */
|
|
2
|
+
function Y(q,F=",",J=!0,K){if(!Array.isArray(q)||q.length===0||typeof q[0]!=="object"||q[0]===null)return"";let M=new RegExp(`[${F}\\n"]`),N=/"/g,P=Object.keys(q[0]),W=P.length,T=[];if(J){let B="";for(let A=0;A<W;A++){if(A>0)B+=F;B+=U(P[A],M,N)}T.push(B)}for(let B of q){if(typeof B!=="object"||B===null||Array.isArray(B))continue;let A="";for(let G=0;G<W;G++){if(G>0)A+=F;let X=P[G],E=B[X];if(K&&E!==void 0)E=K(X,E);if(E===null||E===void 0);else if(typeof E==="object")A+=U(JSON.stringify(E,K),M,N);else A+=U(String(E),M,N)}T.push(A)}return T.join(`
|
|
3
|
+
`)}function U(q,F,J){if(q==="")return q;if(F.test(q))return`"${q.replace(J,'""')}"`;return q}export{Y as jsonToCsv};
|
|
4
|
+
|
|
5
|
+
//# debugId=E7F9F781DA15CF3A64756E2164756E21
|
|
6
|
+
//# sourceMappingURL=main.js.map
|
package/dist/main.js.map
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/main.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"import type {} from '@alwatr/type-helper';\n\n/**\n * Converts a JSON array of objects to a CSV string.\n *\n * @param jsonData - The Array of JSON objects to convert.\n * @param delimiter - The delimiter character to use (default: ',').\n * @param includeHeaders - Whether to include the header row (default: true).\n * @param replacer - A function that handles value replacement, similar to `JSON.stringify`.\n * @returns The CSV string.\n *\n * @example\n * ```ts\n * const data = [{name: 'Ali', age: 30}, {name: 'John', age: 25}];\n * const csv = jsonToCsv(data);\n * // \"name,age\\nAli,30\\nJohn,25\"\n * ```\n */\nexport function jsonToCsv(\n jsonData?: DictionaryOpt<unknown>[],\n delimiter = ',',\n includeHeaders = true,\n replacer?: (key: string, value: unknown) => JsonValue,\n): string {\n if (!Array.isArray(jsonData) || jsonData.length === 0 || typeof jsonData[0] !== 'object' || jsonData[0] === null) {\n return '';\n }\n\n const delimiterRegex = new RegExp(`[${delimiter}\\\\n\"]`);\n const doubleQuoteRegex = /\"/g;\n\n // 1. Extract Headers (Keys)\n const headers = Object.keys(jsonData[0]);\n const headersLen = headers.length;\n\n // 2. Create CSV\n const csvRows: string[] = [];\n\n if (includeHeaders) {\n let headerRow = '';\n for (let i = 0; i < headersLen; i++) {\n if (i > 0) headerRow += delimiter;\n headerRow += escapeCsvValue(headers[i], delimiterRegex, doubleQuoteRegex);\n }\n csvRows.push(headerRow);\n }\n\n // 3. Iterate through Data and Create CSV Rows\n for (const row of jsonData) {\n if (typeof row !== 'object' || row === null || Array.isArray(row)) {\n // Skip non-object rows\n continue;\n }\n\n let rowStr = '';\n for (let i = 0; i < headersLen; i++) {\n if (i > 0) rowStr += delimiter;\n\n const header = headers[i];\n let cellValue = (row as DictionaryOpt<JsonValue>)[header];\n\n if (replacer && cellValue !== undefined) {\n cellValue = replacer(header, cellValue);\n }\n\n if (cellValue === null || cellValue === undefined) {\n // skip empty value\n }\n else if (typeof cellValue === 'object') {\n rowStr += escapeCsvValue(JSON.stringify(cellValue, replacer), delimiterRegex, doubleQuoteRegex);\n }\n else {\n rowStr += escapeCsvValue(String(cellValue), delimiterRegex, doubleQuoteRegex);\n }\n }\n csvRows.push(rowStr);\n }\n\n return csvRows.join('\\n');\n}\n\n// Optimized helper function\nfunction escapeCsvValue(value: string, delimiterRegex: RegExp, doubleQuoteRegex: RegExp): string {\n if (value === '') return value;\n\n // Only replace if necessary\n if (delimiterRegex.test(value)) {\n return `\"${value.replace(doubleQuoteRegex, '\"\"')}\"`;\n }\n\n return value;\n}\n"
|
|
6
|
+
],
|
|
7
|
+
"mappings": ";AAkBO,SAAS,CAAS,CACvB,EACA,EAAY,IACZ,EAAiB,GACjB,EACQ,CACR,GAAI,CAAC,MAAM,QAAQ,CAAQ,GAAK,EAAS,SAAW,GAAK,OAAO,EAAS,KAAO,UAAY,EAAS,KAAO,KAC1G,MAAO,GAGT,IAAM,EAAiB,IAAI,OAAO,IAAI,QAAgB,EAChD,EAAmB,KAGnB,EAAU,OAAO,KAAK,EAAS,EAAE,EACjC,EAAa,EAAQ,OAGrB,EAAoB,CAAC,EAE3B,GAAI,EAAgB,CAClB,IAAI,EAAY,GAChB,QAAS,EAAI,EAAG,EAAI,EAAY,IAAK,CACnC,GAAI,EAAI,EAAG,GAAa,EACxB,GAAa,EAAe,EAAQ,GAAI,EAAgB,CAAgB,EAE1E,EAAQ,KAAK,CAAS,EAIxB,QAAW,KAAO,EAAU,CAC1B,GAAI,OAAO,IAAQ,UAAY,IAAQ,MAAQ,MAAM,QAAQ,CAAG,EAE9D,SAGF,IAAI,EAAS,GACb,QAAS,EAAI,EAAG,EAAI,EAAY,IAAK,CACnC,GAAI,EAAI,EAAG,GAAU,EAErB,IAAM,EAAS,EAAQ,GACnB,EAAa,EAAiC,GAElD,GAAI,GAAY,IAAc,OAC5B,EAAY,EAAS,EAAQ,CAAS,EAGxC,GAAI,IAAc,MAAQ,IAAc,OAAW,CAG9C,QAAI,OAAO,IAAc,SAC5B,GAAU,EAAe,KAAK,UAAU,EAAW,CAAQ,EAAG,EAAgB,CAAgB,EAG9F,QAAU,EAAe,OAAO,CAAS,EAAG,EAAgB,CAAgB,EAGhF,EAAQ,KAAK,CAAM,EAGrB,OAAO,EAAQ,KAAK;AAAA,CAAI,EAI1B,SAAS,CAAc,CAAC,EAAe,EAAwB,EAAkC,CAC/F,GAAI,IAAU,GAAI,OAAO,EAGzB,GAAI,EAAe,KAAK,CAAK,EAC3B,MAAO,IAAI,EAAM,QAAQ,EAAkB,IAAI,KAGjD,OAAO",
|
|
8
|
+
"debugId": "E7F9F781DA15CF3A64756E2164756E21",
|
|
9
|
+
"names": []
|
|
10
|
+
}
|
package/package.json
CHANGED
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alwatr/json2csv",
|
|
3
3
|
"description": "A tiny, efficient, and cross-platform JSON to CSV converter.",
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "2.0.0",
|
|
5
5
|
"author": "S. Ali Mihandoost <ali.mihandoost@gmail.com>",
|
|
6
6
|
"bugs": "https://github.com/Alwatr/nanolib/issues",
|
|
7
7
|
"devDependencies": {
|
|
8
|
-
"@alwatr/nano-build": "
|
|
9
|
-
"@alwatr/prettier-config": "
|
|
10
|
-
"@alwatr/tsconfig-base": "
|
|
11
|
-
"@alwatr/type-helper": "
|
|
8
|
+
"@alwatr/nano-build": "7.0.0",
|
|
9
|
+
"@alwatr/prettier-config": "7.0.0",
|
|
10
|
+
"@alwatr/tsconfig-base": "7.0.0",
|
|
11
|
+
"@alwatr/type-helper": "8.0.0",
|
|
12
12
|
"typescript": "^5.9.3"
|
|
13
13
|
},
|
|
14
14
|
"exports": {
|
|
15
15
|
".": {
|
|
16
16
|
"types": "./dist/main.d.ts",
|
|
17
|
-
"
|
|
18
|
-
"require": "./dist/main.cjs"
|
|
17
|
+
"default": "./dist/main.js"
|
|
19
18
|
}
|
|
20
19
|
},
|
|
21
20
|
"files": [
|
|
22
|
-
"**/*.{js,mjs,cjs,map,d.ts,html,
|
|
21
|
+
"**/*.{js,mjs,cjs,ts,map,d.ts,html,LEGAL.txt}",
|
|
22
|
+
"README.md",
|
|
23
23
|
"LICENSE",
|
|
24
24
|
"!demo/**/*",
|
|
25
25
|
"!**/*.test.js"
|
|
@@ -44,8 +44,6 @@
|
|
|
44
44
|
"zero-dependency"
|
|
45
45
|
],
|
|
46
46
|
"license": "MPL-2.0",
|
|
47
|
-
"main": "./dist/main.cjs",
|
|
48
|
-
"module": "./dist/main.mjs",
|
|
49
47
|
"prettier": "@alwatr/prettier-config",
|
|
50
48
|
"publishConfig": {
|
|
51
49
|
"access": "public"
|
|
@@ -56,21 +54,21 @@
|
|
|
56
54
|
"directory": "packages/json2csv"
|
|
57
55
|
},
|
|
58
56
|
"scripts": {
|
|
59
|
-
"b": "
|
|
60
|
-
"build": "
|
|
61
|
-
"build:es": "nano-build --preset=module",
|
|
57
|
+
"b": "bun run build",
|
|
58
|
+
"build": "bun run build:ts && bun run build:es",
|
|
59
|
+
"build:es": "nano-build --preset=module src/main.ts",
|
|
62
60
|
"build:ts": "tsc --build",
|
|
63
|
-
"c": "
|
|
64
|
-
"cb": "
|
|
61
|
+
"c": "bun run clean",
|
|
62
|
+
"cb": "bun run clean && bun run build",
|
|
65
63
|
"clean": "rm -rfv dist *.tsbuildinfo",
|
|
66
|
-
"d": "
|
|
67
|
-
"w": "
|
|
68
|
-
"watch": "
|
|
69
|
-
"watch:es": "
|
|
70
|
-
"watch:ts": "
|
|
64
|
+
"d": "bun run build:es && bun",
|
|
65
|
+
"w": "bun run watch",
|
|
66
|
+
"watch": "bun run watch:ts & bun run watch:es",
|
|
67
|
+
"watch:es": "bun run build:es --watch",
|
|
68
|
+
"watch:ts": "bun run build:ts --watch --preserveWatchOutput"
|
|
71
69
|
},
|
|
72
70
|
"sideEffects": false,
|
|
73
71
|
"type": "module",
|
|
74
72
|
"types": "./dist/main.d.ts",
|
|
75
|
-
"gitHead": "
|
|
73
|
+
"gitHead": "056102a1c8a563bbae8a290b6830450f467322a3"
|
|
76
74
|
}
|
package/src/main.ts
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import type {} from '@alwatr/type-helper';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Converts a JSON array of objects to a CSV string.
|
|
5
|
+
*
|
|
6
|
+
* @param jsonData - The Array of JSON objects to convert.
|
|
7
|
+
* @param delimiter - The delimiter character to use (default: ',').
|
|
8
|
+
* @param includeHeaders - Whether to include the header row (default: true).
|
|
9
|
+
* @param replacer - A function that handles value replacement, similar to `JSON.stringify`.
|
|
10
|
+
* @returns The CSV string.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```ts
|
|
14
|
+
* const data = [{name: 'Ali', age: 30}, {name: 'John', age: 25}];
|
|
15
|
+
* const csv = jsonToCsv(data);
|
|
16
|
+
* // "name,age\nAli,30\nJohn,25"
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
export function jsonToCsv(
|
|
20
|
+
jsonData?: DictionaryOpt<unknown>[],
|
|
21
|
+
delimiter = ',',
|
|
22
|
+
includeHeaders = true,
|
|
23
|
+
replacer?: (key: string, value: unknown) => JsonValue,
|
|
24
|
+
): string {
|
|
25
|
+
if (!Array.isArray(jsonData) || jsonData.length === 0 || typeof jsonData[0] !== 'object' || jsonData[0] === null) {
|
|
26
|
+
return '';
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const delimiterRegex = new RegExp(`[${delimiter}\\n"]`);
|
|
30
|
+
const doubleQuoteRegex = /"/g;
|
|
31
|
+
|
|
32
|
+
// 1. Extract Headers (Keys)
|
|
33
|
+
const headers = Object.keys(jsonData[0]);
|
|
34
|
+
const headersLen = headers.length;
|
|
35
|
+
|
|
36
|
+
// 2. Create CSV
|
|
37
|
+
const csvRows: string[] = [];
|
|
38
|
+
|
|
39
|
+
if (includeHeaders) {
|
|
40
|
+
let headerRow = '';
|
|
41
|
+
for (let i = 0; i < headersLen; i++) {
|
|
42
|
+
if (i > 0) headerRow += delimiter;
|
|
43
|
+
headerRow += escapeCsvValue(headers[i], delimiterRegex, doubleQuoteRegex);
|
|
44
|
+
}
|
|
45
|
+
csvRows.push(headerRow);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// 3. Iterate through Data and Create CSV Rows
|
|
49
|
+
for (const row of jsonData) {
|
|
50
|
+
if (typeof row !== 'object' || row === null || Array.isArray(row)) {
|
|
51
|
+
// Skip non-object rows
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
let rowStr = '';
|
|
56
|
+
for (let i = 0; i < headersLen; i++) {
|
|
57
|
+
if (i > 0) rowStr += delimiter;
|
|
58
|
+
|
|
59
|
+
const header = headers[i];
|
|
60
|
+
let cellValue = (row as DictionaryOpt<JsonValue>)[header];
|
|
61
|
+
|
|
62
|
+
if (replacer && cellValue !== undefined) {
|
|
63
|
+
cellValue = replacer(header, cellValue);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (cellValue === null || cellValue === undefined) {
|
|
67
|
+
// skip empty value
|
|
68
|
+
}
|
|
69
|
+
else if (typeof cellValue === 'object') {
|
|
70
|
+
rowStr += escapeCsvValue(JSON.stringify(cellValue, replacer), delimiterRegex, doubleQuoteRegex);
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
rowStr += escapeCsvValue(String(cellValue), delimiterRegex, doubleQuoteRegex);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
csvRows.push(rowStr);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return csvRows.join('\n');
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Optimized helper function
|
|
83
|
+
function escapeCsvValue(value: string, delimiterRegex: RegExp, doubleQuoteRegex: RegExp): string {
|
|
84
|
+
if (value === '') return value;
|
|
85
|
+
|
|
86
|
+
// Only replace if necessary
|
|
87
|
+
if (delimiterRegex.test(value)) {
|
|
88
|
+
return `"${value.replace(doubleQuoteRegex, '""')}"`;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return value;
|
|
92
|
+
}
|
package/CHANGELOG.md
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
# Change Log
|
|
2
|
-
|
|
3
|
-
All notable changes to this project will be documented in this file.
|
|
4
|
-
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
|
-
|
|
6
|
-
## [1.0.4](https://github.com/Alwatr/nanolib/compare/@alwatr/json2csv@1.0.3...@alwatr/json2csv@1.0.4) (2026-02-18)
|
|
7
|
-
|
|
8
|
-
### ๐งน Miscellaneous Chores
|
|
9
|
-
|
|
10
|
-
* update keywords in package.json files for better categorization ([cf0ddb6](https://github.com/Alwatr/nanolib/commit/cf0ddb66eab7e2a87158279e455d71c495b30834))
|
|
11
|
-
|
|
12
|
-
## [1.0.3](https://github.com/Alwatr/nanolib/compare/@alwatr/json2csv@1.0.2...@alwatr/json2csv@1.0.3) (2025-12-23)
|
|
13
|
-
|
|
14
|
-
**Note:** Version bump only for package @alwatr/json2csv
|
|
15
|
-
|
|
16
|
-
## [1.0.2](https://github.com/Alwatr/nanolib/compare/@alwatr/json2csv@1.0.1...@alwatr/json2csv@1.0.2) (2025-12-13)
|
|
17
|
-
|
|
18
|
-
**Note:** Version bump only for package @alwatr/json2csv
|
|
19
|
-
|
|
20
|
-
## [1.0.1](https://github.com/Alwatr/nanolib/compare/@alwatr/json2csv@1.0.0...@alwatr/json2csv@1.0.1) (2025-12-10)
|
|
21
|
-
|
|
22
|
-
**Note:** Version bump only for package @alwatr/json2csv
|
|
23
|
-
|
|
24
|
-
## 1.0.0 (2025-12-10)
|
|
25
|
-
|
|
26
|
-
### โจ Features
|
|
27
|
-
|
|
28
|
-
* add new json2csv package with its configuration, license, and main source file. ([ed2db6f](https://github.com/Alwatr/nanolib/commit/ed2db6f53eb85ff8408a0cb651b7a2e848d11c25))
|
|
29
|
-
* enhance json2csv function with configurable delimiter, header inclusion, and value replacer, alongside expanded tests and documentation. ([a78f11b](https://github.com/Alwatr/nanolib/commit/a78f11b7a68c601662fc437956d02bc056224a5f))
|
|
30
|
-
|
|
31
|
-
### ๐ Bug Fixes
|
|
32
|
-
|
|
33
|
-
* Ensure the first `json2csv` array element is a non-null object. ([0db4115](https://github.com/Alwatr/nanolib/commit/0db4115a8bc35a4e2542fedf9ac389a85e504f7c))
|
|
34
|
-
* Skip non-object rows in JSON data instead of attempting to convert them to a single CSV cell. ([1415724](https://github.com/Alwatr/nanolib/commit/14157242eaf0a2ae004e5aa3c6f27111411c9e68))
|
|
35
|
-
|
|
36
|
-
### โก Performance Improvements
|
|
37
|
-
|
|
38
|
-
* optimize CSV generation with direct string concatenation, improved `escapeCsvValue` logic, and updated replacer type. ([ac2a562](https://github.com/Alwatr/nanolib/commit/ac2a562f55b3e8b3aa614ae5ec8fa680b09e83c6))
|
package/dist/main.cjs
DELETED
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
/** ๐ฆ @alwatr/json2csv v1.0.4 */
|
|
2
|
-
__dev_mode__: console.debug("๐ฆ @alwatr/json2csv v1.0.4");
|
|
3
|
-
"use strict";var __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __getOwnPropNames=Object.getOwnPropertyNames;var __hasOwnProp=Object.prototype.hasOwnProperty;var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:true})};var __copyProps=(to,from,except,desc)=>{if(from&&typeof from==="object"||typeof from==="function"){for(let key of __getOwnPropNames(from))if(!__hasOwnProp.call(to,key)&&key!==except)__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable})}return to};var __toCommonJS=mod=>__copyProps(__defProp({},"__esModule",{value:true}),mod);var main_exports={};__export(main_exports,{jsonToCsv:()=>jsonToCsv});module.exports=__toCommonJS(main_exports);function jsonToCsv(jsonData,delimiter=",",includeHeaders=true,replacer){if(!Array.isArray(jsonData)||jsonData.length===0||typeof jsonData[0]!=="object"||jsonData[0]===null){return""}const delimiterRegex=new RegExp(`[${delimiter}\\n"]`);const doubleQuoteRegex=/"/g;const headers=Object.keys(jsonData[0]);const headersLen=headers.length;const csvRows=[];if(includeHeaders){let headerRow="";for(let i=0;i<headersLen;i++){if(i>0)headerRow+=delimiter;headerRow+=escapeCsvValue(headers[i],delimiterRegex,doubleQuoteRegex)}csvRows.push(headerRow)}for(const row of jsonData){if(typeof row!=="object"||row===null||Array.isArray(row)){continue}let rowStr="";for(let i=0;i<headersLen;i++){if(i>0)rowStr+=delimiter;const header=headers[i];let cellValue=row[header];if(replacer&&cellValue!==void 0){cellValue=replacer(header,cellValue)}if(cellValue===null||cellValue===void 0){}else if(typeof cellValue==="object"){rowStr+=escapeCsvValue(JSON.stringify(cellValue,replacer),delimiterRegex,doubleQuoteRegex)}else{rowStr+=escapeCsvValue(String(cellValue),delimiterRegex,doubleQuoteRegex)}}csvRows.push(rowStr)}return csvRows.join("\n")}function escapeCsvValue(value,delimiterRegex,doubleQuoteRegex){if(value==="")return value;if(delimiterRegex.test(value)){return`"${value.replace(doubleQuoteRegex,'""')}"`}return value}0&&(module.exports={jsonToCsv});
|
|
4
|
-
//# sourceMappingURL=main.cjs.map
|
package/dist/main.cjs.map
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../src/main.ts"],
|
|
4
|
-
"sourcesContent": ["import type {} from '@alwatr/type-helper';\n\n/**\n * Converts a JSON array of objects to a CSV string.\n *\n * @param jsonData - The Array of JSON objects to convert.\n * @param delimiter - The delimiter character to use (default: ',').\n * @param includeHeaders - Whether to include the header row (default: true).\n * @param replacer - A function that handles value replacement, similar to `JSON.stringify`.\n * @returns The CSV string.\n *\n * @example\n * ```ts\n * const data = [{name: 'Ali', age: 30}, {name: 'John', age: 25}];\n * const csv = jsonToCsv(data);\n * // \"name,age\\nAli,30\\nJohn,25\"\n * ```\n */\nexport function jsonToCsv(\n jsonData?: DictionaryOpt<unknown>[],\n delimiter = ',',\n includeHeaders = true,\n replacer?: (key: string, value: unknown) => JsonValue,\n): string {\n if (!Array.isArray(jsonData) || jsonData.length === 0 || typeof jsonData[0] !== 'object' || jsonData[0] === null) {\n return '';\n }\n\n const delimiterRegex = new RegExp(`[${delimiter}\\\\n\"]`);\n const doubleQuoteRegex = /\"/g;\n\n // 1. Extract Headers (Keys)\n const headers = Object.keys(jsonData[0]);\n const headersLen = headers.length;\n\n // 2. Create CSV\n const csvRows: string[] = [];\n\n if (includeHeaders) {\n let headerRow = '';\n for (let i = 0; i < headersLen; i++) {\n if (i > 0) headerRow += delimiter;\n headerRow += escapeCsvValue(headers[i], delimiterRegex, doubleQuoteRegex);\n }\n csvRows.push(headerRow);\n }\n\n // 3. Iterate through Data and Create CSV Rows\n for (const row of jsonData) {\n if (typeof row !== 'object' || row === null || Array.isArray(row)) {\n // Skip non-object rows\n continue;\n }\n\n let rowStr = '';\n for (let i = 0; i < headersLen; i++) {\n if (i > 0) rowStr += delimiter;\n\n const header = headers[i];\n let cellValue = (row as DictionaryOpt<JsonValue>)[header];\n\n if (replacer && cellValue !== undefined) {\n cellValue = replacer(header, cellValue);\n }\n\n if (cellValue === null || cellValue === undefined) {\n // skip empty value\n }\n else if (typeof cellValue === 'object') {\n rowStr += escapeCsvValue(JSON.stringify(cellValue, replacer), delimiterRegex, doubleQuoteRegex);\n }\n else {\n rowStr += escapeCsvValue(String(cellValue), delimiterRegex, doubleQuoteRegex);\n }\n }\n csvRows.push(rowStr);\n }\n\n return csvRows.join('\\n');\n}\n\n// Optimized helper function\nfunction escapeCsvValue(value: string, delimiterRegex: RegExp, doubleQuoteRegex: RegExp): string {\n if (value === '') return value;\n\n // Only replace if necessary\n if (delimiterRegex.test(value)) {\n return `\"${value.replace(doubleQuoteRegex, '\"\"')}\"`;\n }\n\n return value;\n}\n"],
|
|
5
|
-
"mappings": ";;qqBAAA,+GAkBO,SAAS,UACd,SACA,UAAY,IACZ,eAAiB,KACjB,SACQ,CACR,GAAI,CAAC,MAAM,QAAQ,QAAQ,GAAK,SAAS,SAAW,GAAK,OAAO,SAAS,CAAC,IAAM,UAAY,SAAS,CAAC,IAAM,KAAM,CAChH,MAAO,EACT,CAEA,MAAM,eAAiB,IAAI,OAAO,IAAI,SAAS,OAAO,EACtD,MAAM,iBAAmB,KAGzB,MAAM,QAAU,OAAO,KAAK,SAAS,CAAC,CAAC,EACvC,MAAM,WAAa,QAAQ,OAG3B,MAAM,QAAoB,CAAC,EAE3B,GAAI,eAAgB,CAClB,IAAI,UAAY,GAChB,QAAS,EAAI,EAAG,EAAI,WAAY,IAAK,CACnC,GAAI,EAAI,EAAG,WAAa,UACxB,WAAa,eAAe,QAAQ,CAAC,EAAG,eAAgB,gBAAgB,CAC1E,CACA,QAAQ,KAAK,SAAS,CACxB,CAGA,UAAW,OAAO,SAAU,CAC1B,GAAI,OAAO,MAAQ,UAAY,MAAQ,MAAQ,MAAM,QAAQ,GAAG,EAAG,CAEjE,QACF,CAEA,IAAI,OAAS,GACb,QAAS,EAAI,EAAG,EAAI,WAAY,IAAK,CACnC,GAAI,EAAI,EAAG,QAAU,UAErB,MAAM,OAAS,QAAQ,CAAC,EACxB,IAAI,UAAa,IAAiC,MAAM,EAExD,GAAI,UAAY,YAAc,OAAW,CACvC,UAAY,SAAS,OAAQ,SAAS,CACxC,CAEA,GAAI,YAAc,MAAQ,YAAc,OAAW,CAEnD,SACS,OAAO,YAAc,SAAU,CACtC,QAAU,eAAe,KAAK,UAAU,UAAW,QAAQ,EAAG,eAAgB,gBAAgB,CAChG,KACK,CACH,QAAU,eAAe,OAAO,SAAS,EAAG,eAAgB,gBAAgB,CAC9E,CACF,CACA,QAAQ,KAAK,MAAM,CACrB,CAEA,OAAO,QAAQ,KAAK,IAAI,CAC1B,CAGA,SAAS,eAAe,MAAe,eAAwB,iBAAkC,CAC/F,GAAI,QAAU,GAAI,OAAO,MAGzB,GAAI,eAAe,KAAK,KAAK,EAAG,CAC9B,MAAO,IAAI,MAAM,QAAQ,iBAAkB,IAAI,CAAC,GAClD,CAEA,OAAO,KACT",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
package/dist/main.mjs
DELETED
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
/** ๐ฆ @alwatr/json2csv v1.0.4 */
|
|
2
|
-
__dev_mode__: console.debug("๐ฆ @alwatr/json2csv v1.0.4");
|
|
3
|
-
function jsonToCsv(jsonData,delimiter=",",includeHeaders=true,replacer){if(!Array.isArray(jsonData)||jsonData.length===0||typeof jsonData[0]!=="object"||jsonData[0]===null){return""}const delimiterRegex=new RegExp(`[${delimiter}\\n"]`);const doubleQuoteRegex=/"/g;const headers=Object.keys(jsonData[0]);const headersLen=headers.length;const csvRows=[];if(includeHeaders){let headerRow="";for(let i=0;i<headersLen;i++){if(i>0)headerRow+=delimiter;headerRow+=escapeCsvValue(headers[i],delimiterRegex,doubleQuoteRegex)}csvRows.push(headerRow)}for(const row of jsonData){if(typeof row!=="object"||row===null||Array.isArray(row)){continue}let rowStr="";for(let i=0;i<headersLen;i++){if(i>0)rowStr+=delimiter;const header=headers[i];let cellValue=row[header];if(replacer&&cellValue!==void 0){cellValue=replacer(header,cellValue)}if(cellValue===null||cellValue===void 0){}else if(typeof cellValue==="object"){rowStr+=escapeCsvValue(JSON.stringify(cellValue,replacer),delimiterRegex,doubleQuoteRegex)}else{rowStr+=escapeCsvValue(String(cellValue),delimiterRegex,doubleQuoteRegex)}}csvRows.push(rowStr)}return csvRows.join("\n")}function escapeCsvValue(value,delimiterRegex,doubleQuoteRegex){if(value==="")return value;if(delimiterRegex.test(value)){return`"${value.replace(doubleQuoteRegex,'""')}"`}return value}export{jsonToCsv};
|
|
4
|
-
//# sourceMappingURL=main.mjs.map
|
package/dist/main.mjs.map
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../src/main.ts"],
|
|
4
|
-
"sourcesContent": ["import type {} from '@alwatr/type-helper';\n\n/**\n * Converts a JSON array of objects to a CSV string.\n *\n * @param jsonData - The Array of JSON objects to convert.\n * @param delimiter - The delimiter character to use (default: ',').\n * @param includeHeaders - Whether to include the header row (default: true).\n * @param replacer - A function that handles value replacement, similar to `JSON.stringify`.\n * @returns The CSV string.\n *\n * @example\n * ```ts\n * const data = [{name: 'Ali', age: 30}, {name: 'John', age: 25}];\n * const csv = jsonToCsv(data);\n * // \"name,age\\nAli,30\\nJohn,25\"\n * ```\n */\nexport function jsonToCsv(\n jsonData?: DictionaryOpt<unknown>[],\n delimiter = ',',\n includeHeaders = true,\n replacer?: (key: string, value: unknown) => JsonValue,\n): string {\n if (!Array.isArray(jsonData) || jsonData.length === 0 || typeof jsonData[0] !== 'object' || jsonData[0] === null) {\n return '';\n }\n\n const delimiterRegex = new RegExp(`[${delimiter}\\\\n\"]`);\n const doubleQuoteRegex = /\"/g;\n\n // 1. Extract Headers (Keys)\n const headers = Object.keys(jsonData[0]);\n const headersLen = headers.length;\n\n // 2. Create CSV\n const csvRows: string[] = [];\n\n if (includeHeaders) {\n let headerRow = '';\n for (let i = 0; i < headersLen; i++) {\n if (i > 0) headerRow += delimiter;\n headerRow += escapeCsvValue(headers[i], delimiterRegex, doubleQuoteRegex);\n }\n csvRows.push(headerRow);\n }\n\n // 3. Iterate through Data and Create CSV Rows\n for (const row of jsonData) {\n if (typeof row !== 'object' || row === null || Array.isArray(row)) {\n // Skip non-object rows\n continue;\n }\n\n let rowStr = '';\n for (let i = 0; i < headersLen; i++) {\n if (i > 0) rowStr += delimiter;\n\n const header = headers[i];\n let cellValue = (row as DictionaryOpt<JsonValue>)[header];\n\n if (replacer && cellValue !== undefined) {\n cellValue = replacer(header, cellValue);\n }\n\n if (cellValue === null || cellValue === undefined) {\n // skip empty value\n }\n else if (typeof cellValue === 'object') {\n rowStr += escapeCsvValue(JSON.stringify(cellValue, replacer), delimiterRegex, doubleQuoteRegex);\n }\n else {\n rowStr += escapeCsvValue(String(cellValue), delimiterRegex, doubleQuoteRegex);\n }\n }\n csvRows.push(rowStr);\n }\n\n return csvRows.join('\\n');\n}\n\n// Optimized helper function\nfunction escapeCsvValue(value: string, delimiterRegex: RegExp, doubleQuoteRegex: RegExp): string {\n if (value === '') return value;\n\n // Only replace if necessary\n if (delimiterRegex.test(value)) {\n return `\"${value.replace(doubleQuoteRegex, '\"\"')}\"`;\n }\n\n return value;\n}\n"],
|
|
5
|
-
"mappings": ";;AAkBO,SAAS,UACd,SACA,UAAY,IACZ,eAAiB,KACjB,SACQ,CACR,GAAI,CAAC,MAAM,QAAQ,QAAQ,GAAK,SAAS,SAAW,GAAK,OAAO,SAAS,CAAC,IAAM,UAAY,SAAS,CAAC,IAAM,KAAM,CAChH,MAAO,EACT,CAEA,MAAM,eAAiB,IAAI,OAAO,IAAI,SAAS,OAAO,EACtD,MAAM,iBAAmB,KAGzB,MAAM,QAAU,OAAO,KAAK,SAAS,CAAC,CAAC,EACvC,MAAM,WAAa,QAAQ,OAG3B,MAAM,QAAoB,CAAC,EAE3B,GAAI,eAAgB,CAClB,IAAI,UAAY,GAChB,QAAS,EAAI,EAAG,EAAI,WAAY,IAAK,CACnC,GAAI,EAAI,EAAG,WAAa,UACxB,WAAa,eAAe,QAAQ,CAAC,EAAG,eAAgB,gBAAgB,CAC1E,CACA,QAAQ,KAAK,SAAS,CACxB,CAGA,UAAW,OAAO,SAAU,CAC1B,GAAI,OAAO,MAAQ,UAAY,MAAQ,MAAQ,MAAM,QAAQ,GAAG,EAAG,CAEjE,QACF,CAEA,IAAI,OAAS,GACb,QAAS,EAAI,EAAG,EAAI,WAAY,IAAK,CACnC,GAAI,EAAI,EAAG,QAAU,UAErB,MAAM,OAAS,QAAQ,CAAC,EACxB,IAAI,UAAa,IAAiC,MAAM,EAExD,GAAI,UAAY,YAAc,OAAW,CACvC,UAAY,SAAS,OAAQ,SAAS,CACxC,CAEA,GAAI,YAAc,MAAQ,YAAc,OAAW,CAEnD,SACS,OAAO,YAAc,SAAU,CACtC,QAAU,eAAe,KAAK,UAAU,UAAW,QAAQ,EAAG,eAAgB,gBAAgB,CAChG,KACK,CACH,QAAU,eAAe,OAAO,SAAS,EAAG,eAAgB,gBAAgB,CAC9E,CACF,CACA,QAAQ,KAAK,MAAM,CACrB,CAEA,OAAO,QAAQ,KAAK,IAAI,CAC1B,CAGA,SAAS,eAAe,MAAe,eAAwB,iBAAkC,CAC/F,GAAI,QAAU,GAAI,OAAO,MAGzB,GAAI,eAAe,KAAK,KAAK,EAAG,CAC9B,MAAO,IAAI,MAAM,QAAQ,iBAAkB,IAAI,CAAC,GAClD,CAEA,OAAO,KACT",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|