foreslash 0.3.8 → 0.3.9

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/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # Change Log
2
2
 
3
+ ## Version 0.3.9 - 2026-01-31
4
+
5
+ Added functions to generate CSV strings
6
+
7
+ - Feat 🥥 Function(s) added: `arrayToCSV` `objectListToCSV` `csvToArray` `csvToObjectList`
8
+ - Feat 🥥 Function(s) change: Refactor `getGlobalThis` to avoid `ReferenceError` in some case
9
+ - Other fixes and improvements
10
+
11
+ 添加了生成 CSV 字符串的函数
12
+
13
+ - 功能 🥥 添加函数: `arrayToCSV` `objectListToCSV` `csvToArray` `csvToObjectList`
14
+ - 功能 🥥 变更函数: 重写 `getGlobalThis` 避免部分环境下调用出现 `ReferenceError`
15
+ - 其他修复与优化
16
+
3
17
  ## Version 0.3.8 - 2026-01-25
4
18
 
5
19
  - Feat 🥥 Function(s) added: `constantCase`
package/README.EN.md CHANGED
@@ -3,6 +3,9 @@
3
3
  <div align="center">
4
4
  <p align="center">
5
5
  <img src="https://img.shields.io/github/languages/top/Moushudyx/foreslash" alt="GitHub top lang" />
6
+ <a href="https://codecov.io/gh/moushudyx/foreslash">
7
+ <img src="https://codecov.io/gh/moushudyx/foreslash/graph/badge.svg" alt="codecov" />
8
+ </a>
6
9
  <img src="https://img.shields.io/badge/license-Mulan_PSL_v2-blue" alt="GitHub license" />
7
10
  <img src="https://img.shields.io/npm/v/foreslash" alt="NPM Version" />
8
11
  <img src="https://img.shields.io/npm/dm/foreslash" alt="NPM Downloads" />
package/README.md CHANGED
@@ -3,6 +3,9 @@
3
3
  <div align="center">
4
4
  <p align="center">
5
5
  <img src="https://img.shields.io/github/languages/top/Moushudyx/foreslash" alt="GitHub top lang" />
6
+ <a href="https://codecov.io/gh/moushudyx/foreslash">
7
+ <img src="https://codecov.io/gh/moushudyx/foreslash/graph/badge.svg" alt="codecov" />
8
+ </a>
6
9
  <a href="https://github.com/moushudyx/foreslash/blob/master/LICENSE">
7
10
  <img src="https://img.shields.io/badge/license-Mulan_PSL_v2-blue" alt="GitHub license" />
8
11
  </a>
package/lib/index.cmn.cjs CHANGED
@@ -157,13 +157,40 @@ function getTag(value) {
157
157
  return object2String.call(value).slice(8, -1);
158
158
  }
159
159
 
160
- function getGlobalThis() {
161
- if (typeof self !== 'undefined')
162
- return self;
163
- if (typeof window !== 'undefined')
164
- return window;
165
- if (typeof global !== 'undefined')
166
- return global;
160
+ const getGlobalThis = (function () {
161
+ let globalThisCache = null;
162
+ return function () {
163
+ if (globalThisCache)
164
+ return globalThisCache;
165
+ globalThisCache = _getGlobalThis();
166
+ return globalThisCache;
167
+ };
168
+ })();
169
+ function _getGlobalThis() {
170
+ try {
171
+ if (typeof self !== 'undefined')
172
+ return self;
173
+ }
174
+ catch (_a) {
175
+ }
176
+ try {
177
+ if (typeof window !== 'undefined')
178
+ return window;
179
+ }
180
+ catch (_b) {
181
+ }
182
+ try {
183
+ if (typeof global !== 'undefined')
184
+ return global;
185
+ }
186
+ catch (_c) {
187
+ }
188
+ try {
189
+ if (typeof globalThis !== 'undefined')
190
+ return globalThis;
191
+ }
192
+ catch (_d) {
193
+ }
167
194
  return Function('return this')();
168
195
  }
169
196
 
@@ -1519,6 +1546,160 @@ function acceptableFileType(fileType, accept) {
1519
1546
  return false;
1520
1547
  }
1521
1548
 
1549
+ function normalizeOptions$2(options) {
1550
+ var _a, _b, _c, _d;
1551
+ if (typeof options === 'string') {
1552
+ return { delimiter: options, bom: false, newline: '\n', quoteAll: false };
1553
+ }
1554
+ return {
1555
+ delimiter: (_a = options === null || options === void 0 ? void 0 : options.delimiter) !== null && _a !== void 0 ? _a : ',',
1556
+ bom: (_b = options === null || options === void 0 ? void 0 : options.bom) !== null && _b !== void 0 ? _b : false,
1557
+ newline: (_c = options === null || options === void 0 ? void 0 : options.newline) !== null && _c !== void 0 ? _c : '\n',
1558
+ quoteAll: (_d = options === null || options === void 0 ? void 0 : options.quoteAll) !== null && _d !== void 0 ? _d : false,
1559
+ };
1560
+ }
1561
+ function arrayToCSV(data, options) {
1562
+ const { delimiter, bom, newline, quoteAll } = normalizeOptions$2(options);
1563
+ const content = data
1564
+ .map((row) => row
1565
+ .map((item) => {
1566
+ const str = String(item);
1567
+ if (quoteAll) {
1568
+ return `"${str.replace(/"/g, '""')}"`;
1569
+ }
1570
+ if (typeof item === 'string' && (item.includes(delimiter) || item.includes('"') || item.includes('\n'))) {
1571
+ return `"${str.replace(/"/g, '""')}"`;
1572
+ }
1573
+ return str;
1574
+ })
1575
+ .join(delimiter))
1576
+ .join(newline);
1577
+ return bom ? `\uFEFF${content}` : content;
1578
+ }
1579
+
1580
+ function normalizeOptions$1(options) {
1581
+ var _a, _b;
1582
+ if (typeof options === 'string') {
1583
+ return { delimiter: options, skipEmptyLines: true };
1584
+ }
1585
+ return {
1586
+ delimiter: (_a = options === null || options === void 0 ? void 0 : options.delimiter) !== null && _a !== void 0 ? _a : ',',
1587
+ skipEmptyLines: (_b = options === null || options === void 0 ? void 0 : options.skipEmptyLines) !== null && _b !== void 0 ? _b : true,
1588
+ };
1589
+ }
1590
+ function csvToArray(csv, options) {
1591
+ if (!csv)
1592
+ return [];
1593
+ const { delimiter, skipEmptyLines } = normalizeOptions$1(options);
1594
+ const text = csv.charCodeAt(0) === 0xfeff ? csv.slice(1) : csv;
1595
+ const rows = [];
1596
+ let row = [];
1597
+ let field = '';
1598
+ let inQuotes = false;
1599
+ for (let i = 0; i < text.length; i++) {
1600
+ const char = text[i];
1601
+ if (inQuotes) {
1602
+ if (char === '"') {
1603
+ if (text[i + 1] === '"') {
1604
+ field += '"';
1605
+ i++;
1606
+ }
1607
+ else {
1608
+ inQuotes = false;
1609
+ }
1610
+ }
1611
+ else {
1612
+ field += char;
1613
+ }
1614
+ continue;
1615
+ }
1616
+ if (char === '"') {
1617
+ inQuotes = true;
1618
+ continue;
1619
+ }
1620
+ if (char === delimiter) {
1621
+ row.push(field);
1622
+ field = '';
1623
+ continue;
1624
+ }
1625
+ if (char === '\r') {
1626
+ if (text[i + 1] === '\n')
1627
+ i++;
1628
+ row.push(field);
1629
+ field = '';
1630
+ if (!(skipEmptyLines && row.length === 1 && row[0] === '')) {
1631
+ rows.push(row);
1632
+ }
1633
+ row = [];
1634
+ continue;
1635
+ }
1636
+ if (char === '\n') {
1637
+ row.push(field);
1638
+ field = '';
1639
+ if (!(skipEmptyLines && row.length === 1 && row[0] === '')) {
1640
+ rows.push(row);
1641
+ }
1642
+ row = [];
1643
+ continue;
1644
+ }
1645
+ field += char;
1646
+ }
1647
+ row.push(field);
1648
+ if (!(skipEmptyLines && row.length === 1 && row[0] === '')) {
1649
+ rows.push(row);
1650
+ }
1651
+ return rows;
1652
+ }
1653
+
1654
+ function normalizeOptions(options) {
1655
+ var _a, _b, _c, _d, _e, _f;
1656
+ if (typeof options === 'string') {
1657
+ return {
1658
+ delimiter: options,
1659
+ skipEmptyLines: true,
1660
+ includeUnknown: false,
1661
+ emptyValue: '',
1662
+ emptyNumberValue: NaN,
1663
+ numberFields: [],
1664
+ };
1665
+ }
1666
+ return {
1667
+ delimiter: (_a = options === null || options === void 0 ? void 0 : options.delimiter) !== null && _a !== void 0 ? _a : ',',
1668
+ skipEmptyLines: (_b = options === null || options === void 0 ? void 0 : options.skipEmptyLines) !== null && _b !== void 0 ? _b : true,
1669
+ includeUnknown: (_c = options === null || options === void 0 ? void 0 : options.includeUnknown) !== null && _c !== void 0 ? _c : false,
1670
+ emptyValue: (_d = options === null || options === void 0 ? void 0 : options.emptyValue) !== null && _d !== void 0 ? _d : '',
1671
+ emptyNumberValue: (_e = options === null || options === void 0 ? void 0 : options.emptyNumberValue) !== null && _e !== void 0 ? _e : NaN,
1672
+ numberFields: (_f = options === null || options === void 0 ? void 0 : options.numberFields) !== null && _f !== void 0 ? _f : [],
1673
+ };
1674
+ }
1675
+ function csvToObjectList(csv, fields, options) {
1676
+ const normalized = normalizeOptions(options);
1677
+ const rows = csvToArray(csv, normalized);
1678
+ if (!rows.length)
1679
+ return [];
1680
+ const [headers, ...data] = rows;
1681
+ const fieldMap = new Map(fields.map(([key, value]) => [value, key]));
1682
+ const numberFields = new Set(normalized.numberFields);
1683
+ const { includeUnknown, emptyValue, emptyNumberValue } = normalized;
1684
+ const fieldKeys = headers.map(header => { var _a; return (_a = fieldMap.get(header)) !== null && _a !== void 0 ? _a : (includeUnknown ? header : undefined); });
1685
+ return data.map((row) => {
1686
+ const record = {};
1687
+ for (let i = 0; i < headers.length; i++) {
1688
+ const fieldKey = fieldKeys[i];
1689
+ if (!fieldKey)
1690
+ continue;
1691
+ const isNumberField = numberFields.has(fieldKey);
1692
+ const raw = row[i];
1693
+ let value = isNil(raw) || raw === '' ? (isNumberField ? emptyNumberValue : emptyValue) : raw;
1694
+ if (isNumberField && typeof value === 'string' && value.trim() !== '') {
1695
+ value = Number(value);
1696
+ }
1697
+ record[fieldKey] = value;
1698
+ }
1699
+ return record;
1700
+ });
1701
+ }
1702
+
1522
1703
  function getAcceptableExtByMIME(mime) {
1523
1704
  if (!mime || !isString(mime))
1524
1705
  return [];
@@ -1533,6 +1714,20 @@ function getAcceptableMIMEByExt(ext) {
1533
1714
  return _getAcceptableMIMEByExt(e);
1534
1715
  }
1535
1716
 
1717
+ function objectListToCSV(objList, fields, options) {
1718
+ var _a;
1719
+ const data = [];
1720
+ data.push(fields.map((f) => f[1]));
1721
+ for (const obj of objList) {
1722
+ const row = [];
1723
+ for (const field of fields) {
1724
+ row.push((_a = obj[field[0]]) !== null && _a !== void 0 ? _a : '');
1725
+ }
1726
+ data.push(row);
1727
+ }
1728
+ return arrayToCSV(data, options);
1729
+ }
1730
+
1536
1731
  function randomInt(min, max) {
1537
1732
  return Math.floor(Math.random() * (max - min + 1)) + min;
1538
1733
  }
@@ -2764,6 +2959,7 @@ exports.$$Empty = $$Empty;
2764
2959
  exports._ = _;
2765
2960
  exports.acceptableFileName = acceptableFileName;
2766
2961
  exports.acceptableFileType = acceptableFileType;
2962
+ exports.arrayToCSV = arrayToCSV;
2767
2963
  exports.base64ToBlob = base64ToBlob;
2768
2964
  exports.blobToBase64 = blobToBase64;
2769
2965
  exports.camelCase = camelCase;
@@ -2780,6 +2976,8 @@ exports.chunk = chunk;
2780
2976
  exports.clamp = clamp;
2781
2977
  exports.compose = compose;
2782
2978
  exports.constantCase = constantCase;
2979
+ exports.csvToArray = csvToArray;
2980
+ exports.csvToObjectList = csvToObjectList;
2783
2981
  exports.curry = _curryMore;
2784
2982
  exports.dataUrlToBlob = dataUrlToBlob;
2785
2983
  exports.debounce = debounce;
@@ -2857,6 +3055,7 @@ exports.lerp = lerp;
2857
3055
  exports.memo = memo;
2858
3056
  exports.noop = noop;
2859
3057
  exports.not = not;
3058
+ exports.objectListToCSV = objectListToCSV;
2860
3059
  exports.omit = omit;
2861
3060
  exports.parallel = parallel;
2862
3061
  exports.pascalCase = pascalCase;
package/lib/index.d.ts CHANGED
@@ -1382,6 +1382,97 @@ declare function acceptableFileName(fileName: string, accept: string): boolean;
1382
1382
  */
1383
1383
  declare function acceptableFileType(fileType: string, accept: string): boolean;
1384
1384
 
1385
+ /** CSV 字符串选项 */
1386
+ interface CSVStringifyOptions {
1387
+ delimiter?: string;
1388
+ bom?: boolean;
1389
+ newline?: '\n' | '\r\n';
1390
+ quoteAll?: boolean;
1391
+ }
1392
+ /**
1393
+ * 将二维数组转换为 CSV 格式的字符串
1394
+ * @param data 二维数组
1395
+ * @param options 配置项, 可设置分隔符、BOM、换行符、引号策略\
1396
+ * 直接传入字符串时表示分隔符\
1397
+ * `delimiter` 分隔符, 默认为 `,`\
1398
+ * `bom` 是否在开头添加 BOM, 默认为 `false`\
1399
+ * `newline` 换行符, 可选值为 `\n` 或 `\r\n`, 默认为 `\n`\
1400
+ * `quoteAll` 是否对所有字段加引号, 默认为 `false`, 仅在必要时加引号
1401
+ * @returns CSV 格式的字符串
1402
+ * @example
1403
+ * ```js
1404
+ * arrayToCSV([['姓名', '年龄'], ['张三', 16], ['李四', 25]])
1405
+ * // 返回:
1406
+ * // 姓名,年龄
1407
+ * // 张三,16
1408
+ * // 李四,25
1409
+ * ```
1410
+ * @version 0.3.9
1411
+ */
1412
+ declare function arrayToCSV(data: any[][], options?: string | CSVStringifyOptions): string;
1413
+
1414
+ /**
1415
+ * CSV 解析选项
1416
+ */
1417
+ interface CSVParseOptions {
1418
+ delimiter?: string;
1419
+ skipEmptyLines?: boolean;
1420
+ }
1421
+ /**
1422
+ * 将 CSV 字符串解析为二维数组
1423
+ * @param csv CSV 字符串
1424
+ * @param options 配置项, 可设置分隔符与是否跳过空行
1425
+ * @returns 二维数组
1426
+ * @example
1427
+ * ```js
1428
+ * csvToArray('姓名,年龄\n张三,16\n李四,25')
1429
+ * // 返回:
1430
+ * // [['姓名', '年龄'], ['张三', '16'], ['李四', '25']]
1431
+ * ```
1432
+ * @version 0.3.9
1433
+ */
1434
+ declare function csvToArray(csv: string, options?: string | CSVParseOptions): string[][];
1435
+
1436
+ /**
1437
+ * CSV 对象解析选项
1438
+ */
1439
+ interface CSVObjectParseOptions extends CSVParseOptions {
1440
+ includeUnknown?: boolean;
1441
+ emptyValue?: unknown;
1442
+ emptyNumberValue?: number;
1443
+ numberFields?: string[];
1444
+ }
1445
+ /**
1446
+ * 将 CSV 字符串解析为对象列表
1447
+ * @param csv CSV 字符串
1448
+ * @param fields 字段映射数组, 每一项为 `[对象字段名, CSV 列名]`
1449
+ * @param options 配置项, 可设置分隔符、空行处理、空值默认值、数字字段等
1450
+ * @returns 对象列表
1451
+ * @example
1452
+ * ```js
1453
+ * const csv = '姓名,年龄\n张三,16\n李四,25'
1454
+ * const fields = [['name', '姓名'], ['age', '年龄']]
1455
+ * csvToObjectList(csv, fields)
1456
+ * // 返回:
1457
+ * // [{ name: '张三', age: '16' }, { name: '李四', age: '25' }]
1458
+ * ```
1459
+ * @version 0.3.9
1460
+ */
1461
+ declare function csvToObjectList(csv: string, fields: [string, string][], options?: string | (CSVObjectParseOptions & {
1462
+ emptyValue?: string;
1463
+ numberFields?: undefined;
1464
+ })): Record<string, string>[];
1465
+ declare function csvToObjectList(csv: string, fields: [string, string][], options?: string | (CSVObjectParseOptions & {
1466
+ numberFields?: undefined;
1467
+ })): Record<string, string | unknown>[];
1468
+ declare function csvToObjectList(csv: string, fields: [string, string][], options: string | (CSVObjectParseOptions & {
1469
+ emptyValue?: string;
1470
+ numberFields: string[];
1471
+ })): Record<string, string | number>[];
1472
+ declare function csvToObjectList(csv: string, fields: [string, string][], options: string | (CSVObjectParseOptions & {
1473
+ numberFields: string[];
1474
+ })): Record<string, string | number | unknown>[];
1475
+
1385
1476
  /**
1386
1477
  * 根据 MIME 类型获取所有匹配的文件拓展名,需要注意 `.C` 与 `.c` 的区别
1387
1478
  * - `text/x-c++src` 对应 `.C`
@@ -1418,6 +1509,33 @@ declare function getAcceptableExtByMIME(mime: string): string[];
1418
1509
  */
1419
1510
  declare function getAcceptableMIMEByExt(ext: string): string[];
1420
1511
 
1512
+ /**
1513
+ * 根据对象列表生成 CSV 字符串
1514
+ * @param objList 对象列表
1515
+ * @param fields 字段映射数组, 每一项为 `[对象字段名, CSV 列名]`
1516
+ * @param options 配置项, 可设置分隔符、BOM、换行符、引号策略
1517
+ * @returns CSV 格式的字符串
1518
+ * @example
1519
+ * ```js
1520
+ * const objList = [
1521
+ * { name: '张三', age: 16, city: '上海' },
1522
+ * { name: '李四', age: 25, city: '新加坡' }
1523
+ * ]
1524
+ * const fields = [
1525
+ * ['name', '姓名'],
1526
+ * ['age', '年龄'],
1527
+ * ['city', '城市']
1528
+ * ]
1529
+ * objectListToCSV(objList, fields)
1530
+ * // 返回:
1531
+ * // 姓名,年龄,城市
1532
+ * // 张三,16,上海
1533
+ * // 李四,25,新加坡
1534
+ * ```
1535
+ * @version 0.3.9
1536
+ */
1537
+ declare function objectListToCSV(objList: Record<string, any>[], fields: [string, string][], options?: string | CSVStringifyOptions): string;
1538
+
1421
1539
  /**
1422
1540
  * 从给定的数组中返回随机一个元素
1423
1541
  * @param arr 可以是数组或类数组对象
@@ -1973,7 +2091,7 @@ declare function getTag(value: unknown): string;
1973
2091
  * 获取全局对象,浏览器环境返回 `self` 或 `window`, Node.js 环境返回 `global`
1974
2092
  * @returns 全局对象
1975
2093
  */
1976
- declare function getGlobalThis(): typeof globalThis;
2094
+ declare const getGlobalThis: () => typeof globalThis;
1977
2095
 
1978
2096
  // compose
1979
2097
  type ComposeFuncList1<CompArgs extends any[], CompResult> = [(...args: CompArgs) => CompResult]
@@ -2657,5 +2775,5 @@ declare function throttle<T extends any[]>(fn: (...args: T) => any, delay: numbe
2657
2775
  reset: () => void;
2658
2776
  };
2659
2777
 
2660
- export { $$Empty, _, acceptableFileName, acceptableFileType, base64ToBlob, blobToBase64, camelCase, capitalize, cartesianProduct, caseCamel, caseConvert, caseKebab, casePascal, caseSnake, castArray, chinaNumerals, chunk, clamp, compose, constantCase, _curryMore as curry, dataUrlToBlob, debounce, decimalNotation, decodeBase64, dedent, deepClone, deepMerge, defer, deprecate, encodeBase64, fastClone, format, getAcceptableExtByMIME, getAcceptableMIMEByExt, getGlobalThis, getInitP, getTag, indent, isArray, isArrayBuffer, isArrayLike, isBigInt, isBigInt64Array, isBigUint64Array, isBlob, isBoolean, isBuffer, isDataView, isDate, isEmpty, isEven, isFile, isFloat32Array, isFloat64Array, isFormData, isFunction, isInt16Array, isInt32Array, isInt8Array, isInteger, isIterable, isMap, isMergeEmptyPlaceholder, isNil, isNull, isNumber, isObject, isOdd, isPlaceholder, isPlainObject, isPrimitive, isPromise, isPromiseLike, isRegExp, isSet, isString, isSymbol, isTypedArray, isUint16Array, isUint32Array, isUint8Array, isUint8ClampedArray, isUndefined, isWeakMap, isWeakSet, isWrapperBigInt, isWrapperBoolean, isWrapperNumber, isWrapperObject, isWrapperString, isWrapperSymbol, kebabCase, lerp, memo, noop, not, omit, parallel, pascalCase, pass, passWith, pick, pipe, randomBase32String, randomChoice, randomDistribution, randomHexString, randomInt, randomIntFloor, randomString, range, remove, retry, romanNumerals, round, roundBank, roundBase, roundCeil, roundFloor, scientificNotation, shuffle, sleep, snakeCase, splitWords, throttle, titleCase, transferNumberToSupUniCode, tryit, ulid, uncapitalize, uuidNil, uuidV4, uuidV7, withResolvers };
2661
- export type { BaseMargeType, CastArray, Chunked, CloneOptions, CustomCloner, IsNegative, IsPositive, IsZero, MergeOption, MergeStrategy, MergeStrategyFunction, MergeType, MergeTypeStrategy, Not, RangeOptions, SourceMergeType, Stringify, TargetMergeType, TypedArray };
2778
+ export { $$Empty, _, acceptableFileName, acceptableFileType, arrayToCSV, base64ToBlob, blobToBase64, camelCase, capitalize, cartesianProduct, caseCamel, caseConvert, caseKebab, casePascal, caseSnake, castArray, chinaNumerals, chunk, clamp, compose, constantCase, csvToArray, csvToObjectList, _curryMore as curry, dataUrlToBlob, debounce, decimalNotation, decodeBase64, dedent, deepClone, deepMerge, defer, deprecate, encodeBase64, fastClone, format, getAcceptableExtByMIME, getAcceptableMIMEByExt, getGlobalThis, getInitP, getTag, indent, isArray, isArrayBuffer, isArrayLike, isBigInt, isBigInt64Array, isBigUint64Array, isBlob, isBoolean, isBuffer, isDataView, isDate, isEmpty, isEven, isFile, isFloat32Array, isFloat64Array, isFormData, isFunction, isInt16Array, isInt32Array, isInt8Array, isInteger, isIterable, isMap, isMergeEmptyPlaceholder, isNil, isNull, isNumber, isObject, isOdd, isPlaceholder, isPlainObject, isPrimitive, isPromise, isPromiseLike, isRegExp, isSet, isString, isSymbol, isTypedArray, isUint16Array, isUint32Array, isUint8Array, isUint8ClampedArray, isUndefined, isWeakMap, isWeakSet, isWrapperBigInt, isWrapperBoolean, isWrapperNumber, isWrapperObject, isWrapperString, isWrapperSymbol, kebabCase, lerp, memo, noop, not, objectListToCSV, omit, parallel, pascalCase, pass, passWith, pick, pipe, randomBase32String, randomChoice, randomDistribution, randomHexString, randomInt, randomIntFloor, randomString, range, remove, retry, romanNumerals, round, roundBank, roundBase, roundCeil, roundFloor, scientificNotation, shuffle, sleep, snakeCase, splitWords, throttle, titleCase, transferNumberToSupUniCode, tryit, ulid, uncapitalize, uuidNil, uuidV4, uuidV7, withResolvers };
2779
+ export type { BaseMargeType, CSVObjectParseOptions, CSVParseOptions, CSVStringifyOptions, CastArray, Chunked, CloneOptions, CustomCloner, IsNegative, IsPositive, IsZero, MergeOption, MergeStrategy, MergeStrategyFunction, MergeType, MergeTypeStrategy, Not, RangeOptions, SourceMergeType, Stringify, TargetMergeType, TypedArray };
package/lib/index.mjs CHANGED
@@ -155,13 +155,40 @@ function getTag(value) {
155
155
  return object2String.call(value).slice(8, -1);
156
156
  }
157
157
 
158
- function getGlobalThis() {
159
- if (typeof self !== 'undefined')
160
- return self;
161
- if (typeof window !== 'undefined')
162
- return window;
163
- if (typeof global !== 'undefined')
164
- return global;
158
+ const getGlobalThis = (function () {
159
+ let globalThisCache = null;
160
+ return function () {
161
+ if (globalThisCache)
162
+ return globalThisCache;
163
+ globalThisCache = _getGlobalThis();
164
+ return globalThisCache;
165
+ };
166
+ })();
167
+ function _getGlobalThis() {
168
+ try {
169
+ if (typeof self !== 'undefined')
170
+ return self;
171
+ }
172
+ catch (_a) {
173
+ }
174
+ try {
175
+ if (typeof window !== 'undefined')
176
+ return window;
177
+ }
178
+ catch (_b) {
179
+ }
180
+ try {
181
+ if (typeof global !== 'undefined')
182
+ return global;
183
+ }
184
+ catch (_c) {
185
+ }
186
+ try {
187
+ if (typeof globalThis !== 'undefined')
188
+ return globalThis;
189
+ }
190
+ catch (_d) {
191
+ }
165
192
  return Function('return this')();
166
193
  }
167
194
 
@@ -1517,6 +1544,160 @@ function acceptableFileType(fileType, accept) {
1517
1544
  return false;
1518
1545
  }
1519
1546
 
1547
+ function normalizeOptions$2(options) {
1548
+ var _a, _b, _c, _d;
1549
+ if (typeof options === 'string') {
1550
+ return { delimiter: options, bom: false, newline: '\n', quoteAll: false };
1551
+ }
1552
+ return {
1553
+ delimiter: (_a = options === null || options === void 0 ? void 0 : options.delimiter) !== null && _a !== void 0 ? _a : ',',
1554
+ bom: (_b = options === null || options === void 0 ? void 0 : options.bom) !== null && _b !== void 0 ? _b : false,
1555
+ newline: (_c = options === null || options === void 0 ? void 0 : options.newline) !== null && _c !== void 0 ? _c : '\n',
1556
+ quoteAll: (_d = options === null || options === void 0 ? void 0 : options.quoteAll) !== null && _d !== void 0 ? _d : false,
1557
+ };
1558
+ }
1559
+ function arrayToCSV(data, options) {
1560
+ const { delimiter, bom, newline, quoteAll } = normalizeOptions$2(options);
1561
+ const content = data
1562
+ .map((row) => row
1563
+ .map((item) => {
1564
+ const str = String(item);
1565
+ if (quoteAll) {
1566
+ return `"${str.replace(/"/g, '""')}"`;
1567
+ }
1568
+ if (typeof item === 'string' && (item.includes(delimiter) || item.includes('"') || item.includes('\n'))) {
1569
+ return `"${str.replace(/"/g, '""')}"`;
1570
+ }
1571
+ return str;
1572
+ })
1573
+ .join(delimiter))
1574
+ .join(newline);
1575
+ return bom ? `\uFEFF${content}` : content;
1576
+ }
1577
+
1578
+ function normalizeOptions$1(options) {
1579
+ var _a, _b;
1580
+ if (typeof options === 'string') {
1581
+ return { delimiter: options, skipEmptyLines: true };
1582
+ }
1583
+ return {
1584
+ delimiter: (_a = options === null || options === void 0 ? void 0 : options.delimiter) !== null && _a !== void 0 ? _a : ',',
1585
+ skipEmptyLines: (_b = options === null || options === void 0 ? void 0 : options.skipEmptyLines) !== null && _b !== void 0 ? _b : true,
1586
+ };
1587
+ }
1588
+ function csvToArray(csv, options) {
1589
+ if (!csv)
1590
+ return [];
1591
+ const { delimiter, skipEmptyLines } = normalizeOptions$1(options);
1592
+ const text = csv.charCodeAt(0) === 0xfeff ? csv.slice(1) : csv;
1593
+ const rows = [];
1594
+ let row = [];
1595
+ let field = '';
1596
+ let inQuotes = false;
1597
+ for (let i = 0; i < text.length; i++) {
1598
+ const char = text[i];
1599
+ if (inQuotes) {
1600
+ if (char === '"') {
1601
+ if (text[i + 1] === '"') {
1602
+ field += '"';
1603
+ i++;
1604
+ }
1605
+ else {
1606
+ inQuotes = false;
1607
+ }
1608
+ }
1609
+ else {
1610
+ field += char;
1611
+ }
1612
+ continue;
1613
+ }
1614
+ if (char === '"') {
1615
+ inQuotes = true;
1616
+ continue;
1617
+ }
1618
+ if (char === delimiter) {
1619
+ row.push(field);
1620
+ field = '';
1621
+ continue;
1622
+ }
1623
+ if (char === '\r') {
1624
+ if (text[i + 1] === '\n')
1625
+ i++;
1626
+ row.push(field);
1627
+ field = '';
1628
+ if (!(skipEmptyLines && row.length === 1 && row[0] === '')) {
1629
+ rows.push(row);
1630
+ }
1631
+ row = [];
1632
+ continue;
1633
+ }
1634
+ if (char === '\n') {
1635
+ row.push(field);
1636
+ field = '';
1637
+ if (!(skipEmptyLines && row.length === 1 && row[0] === '')) {
1638
+ rows.push(row);
1639
+ }
1640
+ row = [];
1641
+ continue;
1642
+ }
1643
+ field += char;
1644
+ }
1645
+ row.push(field);
1646
+ if (!(skipEmptyLines && row.length === 1 && row[0] === '')) {
1647
+ rows.push(row);
1648
+ }
1649
+ return rows;
1650
+ }
1651
+
1652
+ function normalizeOptions(options) {
1653
+ var _a, _b, _c, _d, _e, _f;
1654
+ if (typeof options === 'string') {
1655
+ return {
1656
+ delimiter: options,
1657
+ skipEmptyLines: true,
1658
+ includeUnknown: false,
1659
+ emptyValue: '',
1660
+ emptyNumberValue: NaN,
1661
+ numberFields: [],
1662
+ };
1663
+ }
1664
+ return {
1665
+ delimiter: (_a = options === null || options === void 0 ? void 0 : options.delimiter) !== null && _a !== void 0 ? _a : ',',
1666
+ skipEmptyLines: (_b = options === null || options === void 0 ? void 0 : options.skipEmptyLines) !== null && _b !== void 0 ? _b : true,
1667
+ includeUnknown: (_c = options === null || options === void 0 ? void 0 : options.includeUnknown) !== null && _c !== void 0 ? _c : false,
1668
+ emptyValue: (_d = options === null || options === void 0 ? void 0 : options.emptyValue) !== null && _d !== void 0 ? _d : '',
1669
+ emptyNumberValue: (_e = options === null || options === void 0 ? void 0 : options.emptyNumberValue) !== null && _e !== void 0 ? _e : NaN,
1670
+ numberFields: (_f = options === null || options === void 0 ? void 0 : options.numberFields) !== null && _f !== void 0 ? _f : [],
1671
+ };
1672
+ }
1673
+ function csvToObjectList(csv, fields, options) {
1674
+ const normalized = normalizeOptions(options);
1675
+ const rows = csvToArray(csv, normalized);
1676
+ if (!rows.length)
1677
+ return [];
1678
+ const [headers, ...data] = rows;
1679
+ const fieldMap = new Map(fields.map(([key, value]) => [value, key]));
1680
+ const numberFields = new Set(normalized.numberFields);
1681
+ const { includeUnknown, emptyValue, emptyNumberValue } = normalized;
1682
+ const fieldKeys = headers.map(header => { var _a; return (_a = fieldMap.get(header)) !== null && _a !== void 0 ? _a : (includeUnknown ? header : undefined); });
1683
+ return data.map((row) => {
1684
+ const record = {};
1685
+ for (let i = 0; i < headers.length; i++) {
1686
+ const fieldKey = fieldKeys[i];
1687
+ if (!fieldKey)
1688
+ continue;
1689
+ const isNumberField = numberFields.has(fieldKey);
1690
+ const raw = row[i];
1691
+ let value = isNil(raw) || raw === '' ? (isNumberField ? emptyNumberValue : emptyValue) : raw;
1692
+ if (isNumberField && typeof value === 'string' && value.trim() !== '') {
1693
+ value = Number(value);
1694
+ }
1695
+ record[fieldKey] = value;
1696
+ }
1697
+ return record;
1698
+ });
1699
+ }
1700
+
1520
1701
  function getAcceptableExtByMIME(mime) {
1521
1702
  if (!mime || !isString(mime))
1522
1703
  return [];
@@ -1531,6 +1712,20 @@ function getAcceptableMIMEByExt(ext) {
1531
1712
  return _getAcceptableMIMEByExt(e);
1532
1713
  }
1533
1714
 
1715
+ function objectListToCSV(objList, fields, options) {
1716
+ var _a;
1717
+ const data = [];
1718
+ data.push(fields.map((f) => f[1]));
1719
+ for (const obj of objList) {
1720
+ const row = [];
1721
+ for (const field of fields) {
1722
+ row.push((_a = obj[field[0]]) !== null && _a !== void 0 ? _a : '');
1723
+ }
1724
+ data.push(row);
1725
+ }
1726
+ return arrayToCSV(data, options);
1727
+ }
1728
+
1534
1729
  function randomInt(min, max) {
1535
1730
  return Math.floor(Math.random() * (max - min + 1)) + min;
1536
1731
  }
@@ -2758,4 +2953,4 @@ function throttle(fn, delay, options) {
2758
2953
  return _throttle(fn, delay, Object.assign({ trailing: false, leading: true }, options));
2759
2954
  }
2760
2955
 
2761
- export { $$Empty, _, acceptableFileName, acceptableFileType, base64ToBlob, blobToBase64, camelCase, capitalize, cartesianProduct, caseCamel, caseConvert, caseKebab, casePascal, caseSnake, castArray, chinaNumerals, chunk, clamp, compose, constantCase, _curryMore as curry, dataUrlToBlob, debounce, decimalNotation, decodeBase64, dedent, deepClone, deepMerge, defer, deprecate, encodeBase64, fastClone, format, getAcceptableExtByMIME, getAcceptableMIMEByExt, getGlobalThis, getInitP, getTag, indent, isArray, isArrayBuffer, isArrayLike, isBigInt, isBigInt64Array, isBigUint64Array, isBlob, isBoolean, isBuffer, isDataView, isDate, isEmpty, isEven, isFile, isFloat32Array, isFloat64Array, isFormData, isFunction, isInt16Array, isInt32Array, isInt8Array, isInteger, isIterable, isMap, isMergeEmptyPlaceholder, isNil, isNull, isNumber, isObject, isOdd, isPlaceholder, isPlainObject, isPrimitive, isPromise, isPromiseLike, isRegExp, isSet, isString, isSymbol, isTypedArray, isUint16Array, isUint32Array, isUint8Array, isUint8ClampedArray, isUndefined, isWeakMap, isWeakSet, isWrapperBigInt, isWrapperBoolean, isWrapperNumber, isWrapperObject, isWrapperString, isWrapperSymbol, kebabCase, lerp, memo, noop, not, omit, parallel, pascalCase, pass, passWith, pick, pipe, randomBase32String, randomChoice, randomDistribution, randomHexString, randomInt, randomIntFloor, randomString, range, remove, retry, romanNumerals, round, roundBank, roundBase, roundCeil, roundFloor, scientificNotation, shuffle, sleep, snakeCase, splitWords, throttle, titleCase, transferNumberToSupUniCode, tryit, ulid, uncapitalize, uuidNil, uuidV4, uuidV7, withResolvers };
2956
+ export { $$Empty, _, acceptableFileName, acceptableFileType, arrayToCSV, base64ToBlob, blobToBase64, camelCase, capitalize, cartesianProduct, caseCamel, caseConvert, caseKebab, casePascal, caseSnake, castArray, chinaNumerals, chunk, clamp, compose, constantCase, csvToArray, csvToObjectList, _curryMore as curry, dataUrlToBlob, debounce, decimalNotation, decodeBase64, dedent, deepClone, deepMerge, defer, deprecate, encodeBase64, fastClone, format, getAcceptableExtByMIME, getAcceptableMIMEByExt, getGlobalThis, getInitP, getTag, indent, isArray, isArrayBuffer, isArrayLike, isBigInt, isBigInt64Array, isBigUint64Array, isBlob, isBoolean, isBuffer, isDataView, isDate, isEmpty, isEven, isFile, isFloat32Array, isFloat64Array, isFormData, isFunction, isInt16Array, isInt32Array, isInt8Array, isInteger, isIterable, isMap, isMergeEmptyPlaceholder, isNil, isNull, isNumber, isObject, isOdd, isPlaceholder, isPlainObject, isPrimitive, isPromise, isPromiseLike, isRegExp, isSet, isString, isSymbol, isTypedArray, isUint16Array, isUint32Array, isUint8Array, isUint8ClampedArray, isUndefined, isWeakMap, isWeakSet, isWrapperBigInt, isWrapperBoolean, isWrapperNumber, isWrapperObject, isWrapperString, isWrapperSymbol, kebabCase, lerp, memo, noop, not, objectListToCSV, omit, parallel, pascalCase, pass, passWith, pick, pipe, randomBase32String, randomChoice, randomDistribution, randomHexString, randomInt, randomIntFloor, randomString, range, remove, retry, romanNumerals, round, roundBank, roundBase, roundCeil, roundFloor, scientificNotation, shuffle, sleep, snakeCase, splitWords, throttle, titleCase, transferNumberToSupUniCode, tryit, ulid, uncapitalize, uuidNil, uuidV4, uuidV7, withResolvers };
package/lib/index.umd.js CHANGED
@@ -161,13 +161,40 @@ See the Mulan PSL v2 for more details.
161
161
  return object2String.call(value).slice(8, -1);
162
162
  }
163
163
 
164
- function getGlobalThis() {
165
- if (typeof self !== 'undefined')
166
- return self;
167
- if (typeof window !== 'undefined')
168
- return window;
169
- if (typeof global !== 'undefined')
170
- return global;
164
+ const getGlobalThis = (function () {
165
+ let globalThisCache = null;
166
+ return function () {
167
+ if (globalThisCache)
168
+ return globalThisCache;
169
+ globalThisCache = _getGlobalThis();
170
+ return globalThisCache;
171
+ };
172
+ })();
173
+ function _getGlobalThis() {
174
+ try {
175
+ if (typeof self !== 'undefined')
176
+ return self;
177
+ }
178
+ catch (_a) {
179
+ }
180
+ try {
181
+ if (typeof window !== 'undefined')
182
+ return window;
183
+ }
184
+ catch (_b) {
185
+ }
186
+ try {
187
+ if (typeof global !== 'undefined')
188
+ return global;
189
+ }
190
+ catch (_c) {
191
+ }
192
+ try {
193
+ if (typeof globalThis !== 'undefined')
194
+ return globalThis;
195
+ }
196
+ catch (_d) {
197
+ }
171
198
  return Function('return this')();
172
199
  }
173
200
 
@@ -1523,6 +1550,160 @@ See the Mulan PSL v2 for more details.
1523
1550
  return false;
1524
1551
  }
1525
1552
 
1553
+ function normalizeOptions$2(options) {
1554
+ var _a, _b, _c, _d;
1555
+ if (typeof options === 'string') {
1556
+ return { delimiter: options, bom: false, newline: '\n', quoteAll: false };
1557
+ }
1558
+ return {
1559
+ delimiter: (_a = options === null || options === void 0 ? void 0 : options.delimiter) !== null && _a !== void 0 ? _a : ',',
1560
+ bom: (_b = options === null || options === void 0 ? void 0 : options.bom) !== null && _b !== void 0 ? _b : false,
1561
+ newline: (_c = options === null || options === void 0 ? void 0 : options.newline) !== null && _c !== void 0 ? _c : '\n',
1562
+ quoteAll: (_d = options === null || options === void 0 ? void 0 : options.quoteAll) !== null && _d !== void 0 ? _d : false,
1563
+ };
1564
+ }
1565
+ function arrayToCSV(data, options) {
1566
+ const { delimiter, bom, newline, quoteAll } = normalizeOptions$2(options);
1567
+ const content = data
1568
+ .map((row) => row
1569
+ .map((item) => {
1570
+ const str = String(item);
1571
+ if (quoteAll) {
1572
+ return `"${str.replace(/"/g, '""')}"`;
1573
+ }
1574
+ if (typeof item === 'string' && (item.includes(delimiter) || item.includes('"') || item.includes('\n'))) {
1575
+ return `"${str.replace(/"/g, '""')}"`;
1576
+ }
1577
+ return str;
1578
+ })
1579
+ .join(delimiter))
1580
+ .join(newline);
1581
+ return bom ? `\uFEFF${content}` : content;
1582
+ }
1583
+
1584
+ function normalizeOptions$1(options) {
1585
+ var _a, _b;
1586
+ if (typeof options === 'string') {
1587
+ return { delimiter: options, skipEmptyLines: true };
1588
+ }
1589
+ return {
1590
+ delimiter: (_a = options === null || options === void 0 ? void 0 : options.delimiter) !== null && _a !== void 0 ? _a : ',',
1591
+ skipEmptyLines: (_b = options === null || options === void 0 ? void 0 : options.skipEmptyLines) !== null && _b !== void 0 ? _b : true,
1592
+ };
1593
+ }
1594
+ function csvToArray(csv, options) {
1595
+ if (!csv)
1596
+ return [];
1597
+ const { delimiter, skipEmptyLines } = normalizeOptions$1(options);
1598
+ const text = csv.charCodeAt(0) === 0xfeff ? csv.slice(1) : csv;
1599
+ const rows = [];
1600
+ let row = [];
1601
+ let field = '';
1602
+ let inQuotes = false;
1603
+ for (let i = 0; i < text.length; i++) {
1604
+ const char = text[i];
1605
+ if (inQuotes) {
1606
+ if (char === '"') {
1607
+ if (text[i + 1] === '"') {
1608
+ field += '"';
1609
+ i++;
1610
+ }
1611
+ else {
1612
+ inQuotes = false;
1613
+ }
1614
+ }
1615
+ else {
1616
+ field += char;
1617
+ }
1618
+ continue;
1619
+ }
1620
+ if (char === '"') {
1621
+ inQuotes = true;
1622
+ continue;
1623
+ }
1624
+ if (char === delimiter) {
1625
+ row.push(field);
1626
+ field = '';
1627
+ continue;
1628
+ }
1629
+ if (char === '\r') {
1630
+ if (text[i + 1] === '\n')
1631
+ i++;
1632
+ row.push(field);
1633
+ field = '';
1634
+ if (!(skipEmptyLines && row.length === 1 && row[0] === '')) {
1635
+ rows.push(row);
1636
+ }
1637
+ row = [];
1638
+ continue;
1639
+ }
1640
+ if (char === '\n') {
1641
+ row.push(field);
1642
+ field = '';
1643
+ if (!(skipEmptyLines && row.length === 1 && row[0] === '')) {
1644
+ rows.push(row);
1645
+ }
1646
+ row = [];
1647
+ continue;
1648
+ }
1649
+ field += char;
1650
+ }
1651
+ row.push(field);
1652
+ if (!(skipEmptyLines && row.length === 1 && row[0] === '')) {
1653
+ rows.push(row);
1654
+ }
1655
+ return rows;
1656
+ }
1657
+
1658
+ function normalizeOptions(options) {
1659
+ var _a, _b, _c, _d, _e, _f;
1660
+ if (typeof options === 'string') {
1661
+ return {
1662
+ delimiter: options,
1663
+ skipEmptyLines: true,
1664
+ includeUnknown: false,
1665
+ emptyValue: '',
1666
+ emptyNumberValue: NaN,
1667
+ numberFields: [],
1668
+ };
1669
+ }
1670
+ return {
1671
+ delimiter: (_a = options === null || options === void 0 ? void 0 : options.delimiter) !== null && _a !== void 0 ? _a : ',',
1672
+ skipEmptyLines: (_b = options === null || options === void 0 ? void 0 : options.skipEmptyLines) !== null && _b !== void 0 ? _b : true,
1673
+ includeUnknown: (_c = options === null || options === void 0 ? void 0 : options.includeUnknown) !== null && _c !== void 0 ? _c : false,
1674
+ emptyValue: (_d = options === null || options === void 0 ? void 0 : options.emptyValue) !== null && _d !== void 0 ? _d : '',
1675
+ emptyNumberValue: (_e = options === null || options === void 0 ? void 0 : options.emptyNumberValue) !== null && _e !== void 0 ? _e : NaN,
1676
+ numberFields: (_f = options === null || options === void 0 ? void 0 : options.numberFields) !== null && _f !== void 0 ? _f : [],
1677
+ };
1678
+ }
1679
+ function csvToObjectList(csv, fields, options) {
1680
+ const normalized = normalizeOptions(options);
1681
+ const rows = csvToArray(csv, normalized);
1682
+ if (!rows.length)
1683
+ return [];
1684
+ const [headers, ...data] = rows;
1685
+ const fieldMap = new Map(fields.map(([key, value]) => [value, key]));
1686
+ const numberFields = new Set(normalized.numberFields);
1687
+ const { includeUnknown, emptyValue, emptyNumberValue } = normalized;
1688
+ const fieldKeys = headers.map(header => { var _a; return (_a = fieldMap.get(header)) !== null && _a !== void 0 ? _a : (includeUnknown ? header : undefined); });
1689
+ return data.map((row) => {
1690
+ const record = {};
1691
+ for (let i = 0; i < headers.length; i++) {
1692
+ const fieldKey = fieldKeys[i];
1693
+ if (!fieldKey)
1694
+ continue;
1695
+ const isNumberField = numberFields.has(fieldKey);
1696
+ const raw = row[i];
1697
+ let value = isNil(raw) || raw === '' ? (isNumberField ? emptyNumberValue : emptyValue) : raw;
1698
+ if (isNumberField && typeof value === 'string' && value.trim() !== '') {
1699
+ value = Number(value);
1700
+ }
1701
+ record[fieldKey] = value;
1702
+ }
1703
+ return record;
1704
+ });
1705
+ }
1706
+
1526
1707
  function getAcceptableExtByMIME(mime) {
1527
1708
  if (!mime || !isString(mime))
1528
1709
  return [];
@@ -1537,6 +1718,20 @@ See the Mulan PSL v2 for more details.
1537
1718
  return _getAcceptableMIMEByExt(e);
1538
1719
  }
1539
1720
 
1721
+ function objectListToCSV(objList, fields, options) {
1722
+ var _a;
1723
+ const data = [];
1724
+ data.push(fields.map((f) => f[1]));
1725
+ for (const obj of objList) {
1726
+ const row = [];
1727
+ for (const field of fields) {
1728
+ row.push((_a = obj[field[0]]) !== null && _a !== void 0 ? _a : '');
1729
+ }
1730
+ data.push(row);
1731
+ }
1732
+ return arrayToCSV(data, options);
1733
+ }
1734
+
1540
1735
  function randomInt(min, max) {
1541
1736
  return Math.floor(Math.random() * (max - min + 1)) + min;
1542
1737
  }
@@ -2768,6 +2963,7 @@ See the Mulan PSL v2 for more details.
2768
2963
  exports._ = _;
2769
2964
  exports.acceptableFileName = acceptableFileName;
2770
2965
  exports.acceptableFileType = acceptableFileType;
2966
+ exports.arrayToCSV = arrayToCSV;
2771
2967
  exports.base64ToBlob = base64ToBlob;
2772
2968
  exports.blobToBase64 = blobToBase64;
2773
2969
  exports.camelCase = camelCase;
@@ -2784,6 +2980,8 @@ See the Mulan PSL v2 for more details.
2784
2980
  exports.clamp = clamp;
2785
2981
  exports.compose = compose;
2786
2982
  exports.constantCase = constantCase;
2983
+ exports.csvToArray = csvToArray;
2984
+ exports.csvToObjectList = csvToObjectList;
2787
2985
  exports.curry = _curryMore;
2788
2986
  exports.dataUrlToBlob = dataUrlToBlob;
2789
2987
  exports.debounce = debounce;
@@ -2861,6 +3059,7 @@ See the Mulan PSL v2 for more details.
2861
3059
  exports.memo = memo;
2862
3060
  exports.noop = noop;
2863
3061
  exports.not = not;
3062
+ exports.objectListToCSV = objectListToCSV;
2864
3063
  exports.omit = omit;
2865
3064
  exports.parallel = parallel;
2866
3065
  exports.pascalCase = pascalCase;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "foreslash",
3
- "version": "0.3.8",
3
+ "version": "0.3.9",
4
4
  "description": "Foreslash is a Javascript utilities lib which contains plenty of practical functions.",
5
5
  "author": "moushu",
6
6
  "license": "Mulan PSL v2",