@thi.ng/csv 2.4.5 → 2.5.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/CHANGELOG.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Change Log
2
2
 
3
- - **Last updated**: 2025-07-30T22:32:35Z
3
+ - **Last updated**: 2025-08-06T11:29:19Z
4
4
  - **Generator**: [thi.ng/monopub](https://thi.ng/monopub)
5
5
 
6
6
  All notable changes to this project will be documented in this file.
@@ -11,6 +11,15 @@ See [Conventional Commits](https://conventionalcommits.org/) for commit guidelin
11
11
  **Note:** Unlisted _patch_ versions only involve non-code or otherwise excluded changes
12
12
  and/or version bumps of transitive dependencies.
13
13
 
14
+ ## [2.5.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/csv@2.5.0) (2025-08-06)
15
+
16
+ #### 🚀 Features
17
+
18
+ - add support for column default values ([e105548](https://github.com/thi-ng/umbrella/commit/e105548))
19
+ - update `ColumnSpec`
20
+ - update `parseCSV()` to support & validate column specs w/ default values
21
+ - add tests
22
+
14
23
  ## [2.4.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/csv@2.4.0) (2025-07-12)
15
24
 
16
25
  #### 🚀 Features
package/README.md CHANGED
@@ -87,12 +87,13 @@ For Node.js REPL:
87
87
  const csv = await import("@thi.ng/csv");
88
88
  ```
89
89
 
90
- Package sizes (brotli'd, pre-treeshake): ESM: 1.56 KB
90
+ Package sizes (brotli'd, pre-treeshake): ESM: 1.71 KB
91
91
 
92
92
  ## Dependencies
93
93
 
94
94
  - [@thi.ng/api](https://github.com/thi-ng/umbrella/tree/develop/packages/api)
95
95
  - [@thi.ng/checks](https://github.com/thi-ng/umbrella/tree/develop/packages/checks)
96
+ - [@thi.ng/errors](https://github.com/thi-ng/umbrella/tree/develop/packages/errors)
96
97
  - [@thi.ng/strings](https://github.com/thi-ng/umbrella/tree/develop/packages/strings)
97
98
  - [@thi.ng/transducers](https://github.com/thi-ng/umbrella/tree/develop/packages/transducers)
98
99
 
package/api.d.ts CHANGED
@@ -16,7 +16,9 @@ export type CSVRecord = Record<string, any>;
16
16
  export type CellTransform = Fn2<string, any, any>;
17
17
  export interface ColumnSpec {
18
18
  /**
19
- * Rename column to given name in result objects.
19
+ * Rename column to given name in result objects. MUST be given if
20
+ * {@link ColumnSpec.default} is defined and column specs are provided to
21
+ * {@link parseCSV} as array (rather than as object).
20
22
  */
21
23
  alias?: string;
22
24
  /**
@@ -25,6 +27,13 @@ export interface ColumnSpec {
25
27
  * actual value for the cell.
26
28
  */
27
29
  tx?: CellTransform;
30
+ /**
31
+ * Default value to use if column is missing.
32
+ *
33
+ * @remarks
34
+ * Also see note about {@link ColumnSpec.alias}.
35
+ */
36
+ default?: any;
28
37
  }
29
38
  export type ColumnSpecs = Record<string, ColumnSpec>;
30
39
  export interface CommonCSVOpts {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thi.ng/csv",
3
- "version": "2.4.5",
3
+ "version": "2.5.0",
4
4
  "description": "Customizable, transducer-based CSV parser/object mapper and transformer",
5
5
  "type": "module",
6
6
  "module": "./index.js",
@@ -39,15 +39,16 @@
39
39
  "tool:tangle": "../../node_modules/.bin/tangle src/**/*.ts"
40
40
  },
41
41
  "dependencies": {
42
- "@thi.ng/api": "^8.11.33",
43
- "@thi.ng/checks": "^3.7.13",
44
- "@thi.ng/strings": "^3.9.19",
45
- "@thi.ng/transducers": "^9.6.4"
42
+ "@thi.ng/api": "^8.12.1",
43
+ "@thi.ng/checks": "^3.7.15",
44
+ "@thi.ng/errors": "^2.5.41",
45
+ "@thi.ng/strings": "^3.9.21",
46
+ "@thi.ng/transducers": "^9.6.6"
46
47
  },
47
48
  "devDependencies": {
48
49
  "esbuild": "^0.25.8",
49
- "typedoc": "^0.28.7",
50
- "typescript": "^5.8.3"
50
+ "typedoc": "^0.28.9",
51
+ "typescript": "^5.9.2"
51
52
  },
52
53
  "keywords": [
53
54
  "csv",
@@ -87,5 +88,5 @@
87
88
  "thi.ng": {
88
89
  "year": 2014
89
90
  },
90
- "gitHead": "1df8a3a9061257ea73ccf1ab9cdf63c81a9f519f\n"
91
+ "gitHead": "c31170bdfc63c127350968b05341c0955b2b9d5f\n"
91
92
  }
package/parse.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { isArray } from "@thi.ng/checks/is-array";
2
2
  import { isFunction } from "@thi.ng/checks/is-function";
3
3
  import { isIterable } from "@thi.ng/checks/is-iterable";
4
+ import { illegalArgs } from "@thi.ng/errors/illegal-arguments";
4
5
  import { ESCAPES } from "@thi.ng/strings/escape";
5
6
  import { split } from "@thi.ng/strings/split";
6
7
  import { compR } from "@thi.ng/transducers/compr";
@@ -28,12 +29,16 @@ function parseCSV(opts, src) {
28
29
  const reduce = rfn[2];
29
30
  let index;
30
31
  let revIndex;
32
+ let defaults;
31
33
  let first = true;
32
34
  let isQuoted = false;
33
35
  let record = [];
34
36
  const init = (header2) => {
35
- cols && (index = __initIndex(header2, cols));
36
- all && (revIndex = __initRevIndex(header2));
37
+ if (cols) {
38
+ index = __initIndex(header2, cols);
39
+ defaults = __initDefaults(cols);
40
+ }
41
+ if (all) revIndex = __initRevIndex(header2);
37
42
  first = false;
38
43
  };
39
44
  const collectAll = (row) => record.reduce(
@@ -49,6 +54,10 @@ function parseCSV(opts, src) {
49
54
  }
50
55
  return acc;
51
56
  }, row);
57
+ const collectDefaults = (row) => defaults.reduce((acc, { alias, default: val }) => {
58
+ if (acc[alias] === void 0) acc[alias] = val;
59
+ return acc;
60
+ }, row);
52
61
  header && init(header);
53
62
  return compR(rfn, (acc, line) => {
54
63
  if ((!line.length || line.startsWith(comment)) && !isQuoted)
@@ -65,6 +74,7 @@ function parseCSV(opts, src) {
65
74
  const row = {};
66
75
  all && collectAll(row);
67
76
  index && collectIndexed(row);
77
+ defaults && collectDefaults(row);
68
78
  record = [];
69
79
  return reduce(acc, row);
70
80
  } else {
@@ -185,6 +195,25 @@ const __initIndex = (line, cols) => isArray(cols) ? cols.reduce((acc, spec, i) =
185
195
  {}
186
196
  );
187
197
  const __initRevIndex = (line) => line.reduce((acc, x, i) => (acc[i] = x, acc), {});
198
+ const __initDefaults = (cols) => {
199
+ const defaults = isArray(cols) ? cols.filter((c) => {
200
+ if (!c || c.default == void 0) return false;
201
+ if (!c.alias)
202
+ illegalArgs(
203
+ `missing column alias for default: ${c.default}`
204
+ );
205
+ return true;
206
+ }) : Object.entries(cols).reduce((acc, [k, v]) => {
207
+ if (v.default !== void 0) {
208
+ acc.push({
209
+ alias: v.alias ?? k,
210
+ default: v.default
211
+ });
212
+ }
213
+ return acc;
214
+ }, []);
215
+ return defaults.length ? defaults : void 0;
216
+ };
188
217
  export {
189
218
  parseCSV,
190
219
  parseCSVFromString,