Skip to content

Commit

Permalink
.
Browse files Browse the repository at this point in the history
  • Loading branch information
catamphetamine committed May 1, 2024
1 parent 9a65a67 commit b2d18cd
Show file tree
Hide file tree
Showing 26 changed files with 7,889 additions and 1,574 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
5.8.0 / 01.05.2024
==================

* Added new parameters to replace the old `includeNullValues: true` parameter: `schemaPropertyValueEmptyCellValue`, `schemaPropertyValueForMissingColumn`, `getEmptyObjectValue`. Now `includeNullValues: true` could be replaced with the following combination of parameters:
* `schemaPropertyValueForMissingColumn: null`
* `schemaPropertyValueForEmptyCell: null`
* `getEmptyObjectValue = (object, { path? }) => null`
* Added `schemaPropertyShouldSkipRequiredValidationForMissingColumn: () => boolean` parameter. It is `() => false` by default.
* Added `getEmptyArrayValue: (array, { path }) => any` parameter. It is `() => null` by default.

5.5.0 / 14.09.2022
==================

Expand Down
64 changes: 45 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,22 @@ Each property of a JSON object should be described by an "entry" in the `schema`
* Custom type:
* A function that receives a cell value and returns a parsed value. If the value is invalid, it should throw an error with the error message set to the error code.

Sidenote: When converting cell values to object properties, by default, it skips all `null` values (skips all empty cells). That's for simplicity. In some edge cases though, it may be required to keep all `null` values for all the empty cells. For example, that's the case when updating data in an SQL database from an XLSX spreadsheet using Sequelize ORM library that requires a property to explicitly be `null` in order to clear it during an `UPDATE` operation. To keep all `null` values, pass `includeNullValues: true` option when calling `readXlsxFile()`.
#### Note on missing columns or empty cells

When converting cell values to object properties, by default, it skips any missing columns or empty cells, which means that property values for such cells will be `undefined`. To be more specific, first it interprets any missing columns as if those columns existed but had empty cells, and then it interprets all empty cells as `undefined`s in the output objects.

In some cases thought that default behavior is not appropriate.

For example, spreadsheet data might be used to update an SQL database using Sequelize ORM library, and Sequelize completely ignores any `undefined` values. In order for Sequelize to set a certain field value to `NULL` in the database, it must be passed as `null` rather than `undefined`.

So for Sequelize use case, property values for any missing columns should stay `undefined` but property values for any empty cells should be `null`. That could be achieved by passing two parameters to `read-excel-file`: `schemaPropertyValueForMissingColumn: undefined` and `schemaPropertyValueForEmptyCell: null`.

An additional option that could be passed in that case would be `schemaPropertyShouldSkipRequiredValidationForMissingColumn: (column, { object }) => true`: it would skip `required` validation for columns that're missing from the spreadsheet.

There's also a legacy parameter `includeNullValues: true` that could be replaced with the following combination of parameters:
* `schemaPropertyValueForMissingColumn: null`
* `schemaPropertyValueForEmptyCell: null`
* `getEmptyObjectValue = () => null`

#### `errors`

Expand Down Expand Up @@ -238,7 +253,35 @@ readXlsxFile(file, { schema }).then(({ rows, errors }) => {
})
```

#### Tips and Features
#### Separate use

The function for converting input data rows to JSON objects using a schema is exported independently as `read-excel-file/map`, if anyone's interested.

```js
import convertToJson from "read-excel-file/map"

const { rows, errors } = convertToJson(data, schema, options)
```

Maps a list of rows — `data` — into a list of objects — `rows` — using a `schema` as a mapping specification.

* `data` — An array of rows, each row being an array of cells. The first row should be the list of column headers and the rest of the rows should be the data.
* `schema` — A "to JSON" convertion schema (see above).
* `options` — (optional) Schema conversion parameters of `read-excel-file`:
* `schemaPropertyValueForMissingColumn` — By default, when some of the `schema` columns are missing in the input `data`, those properties are set to `undefined` in the output objects. Pass `schemaPropertyValueForMissingColumn: null` to set such "missing column" properties to `null` in the output objects.
* `schemaPropertyValueForNullCellValue` — By default, when it encounters a `null` value in a cell in input `data`, it sets it to `undefined` in the output object. Pass `schemaPropertyValueForNullCellValue: null` to make it set such values as `null`s in output objects.
* `schemaPropertyValueForUndefinedCellValue` — By default, when it encounters an `undefined` value in a cell in input `data`, it it sets it to `undefined` in the output object. Pass `schemaPropertyValueForUndefinedCellValue: null` to make it set such values as `null`s in output objects.
* `schemaPropertyShouldSkipRequiredValidationForMissingColumn: (column: string, { object }) => boolean` — By default, it does apply `required` validation to `schema` properties for which columns are missing in the input `data`. One could pass a custom `schemaPropertyShouldSkipRequiredValidationForMissingColumn(column, { object })` to disable `required` validation for missing columns in some or all cases.
* `getEmptyObjectValue(object, { path? })` — By default, it returns `null` for an "empty" resulting object. One could override that value using `getEmptyObjectValue(object, { path })` parameter. The value applies to both top-level object and any nested sub-objects in case of a nested schema, hence the additional (optional) `path?: string` parameter.
* `getEmptyArrayValue(array, { path })` — By default, it returns `null` for an "empty" array value. One could override that value using `getEmptyArrayValue(array, { path })` parameter.

Returns a list of "mapped objects".

When parsing a schema property value, in case of an error, the value of that property is gonna be `undefined`.

When a "mapped object" is empty, i.e. when all property values of it are `null` or `undefined`, it is returned as `null` rather than an object.

#### Schema: Tips and Features

<!-- If no `type` is specified then the cell value is returned "as is": as a string, number, date or boolean. -->

Expand Down Expand Up @@ -303,22 +346,6 @@ readXlsxFile(file, {
```
</details>

<details>
<summary>
The <strong>function for converting data to JSON objects using a schema</strong> is exported from this library too, if anyone wants it.
</summary>

#####

```js
import convertToJson from "read-excel-file/schema"

// `data` is an array of rows, each row being an array of cells.
// `schema` is a "to JSON" convertion schema (see above).
const { rows, errors } = convertToJson(data, schema)
```
</details>

<details>
<summary>A <strong>React component for displaying errors</strong> that occured during schema parsing/validation.</summary>

Expand Down Expand Up @@ -516,4 +543,3 @@ On March 9th, 2020, GitHub, Inc. silently [banned](https://medium.com/@catamphet
## License

[MIT](LICENSE)

2 changes: 2 additions & 0 deletions map/index.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
exports = module.exports = require('../commonjs/read/schema/convertToJson.js').default
exports['default'] = require('../commonjs/read/schema/convertToJson.js').default
7 changes: 7 additions & 0 deletions map/index.cjs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// This file is deprecated.
// It's the same as `index.cjs`, just with an added `*.js` extension.
// It fixes the issue when some software doesn't see files with `*.cjs` file extensions
// when used as the `main` property value in `package.json`.

exports = module.exports = require('../commonjs/read/schema/convertToJson.js').default
exports['default'] = require('../commonjs/read/schema/convertToJson.js').default
11 changes: 11 additions & 0 deletions map/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import {
Row,
Schema,
MappingParameters
} from '../types.d.js';

export {
MappingParameters
} from '../types.d.js'

export default function map(data: Row[], schema: Schema, options?: MappingParameters): object[];
1 change: 1 addition & 0 deletions map/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as default } from '../modules/read/schema/convertToJson.js'
17 changes: 17 additions & 0 deletions map/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"private": true,
"name": "read-excel-file/schema",
"version": "1.0.0",
"main": "index.cjs",
"module": "index.js",
"types": "./index.d.ts",
"type": "module",
"exports": {
".": {
"types": "./index.d.ts",
"import": "./index.js",
"require": "./index.cjs"
}
},
"sideEffects": false
}
Loading

0 comments on commit b2d18cd

Please sign in to comment.