@ellipticltd/aml-utils 0.16.27 → 0.16.29
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/README.md +11 -43
- package/lib/errors/errors.js +19 -30
- package/lib/errors/errors.js.map +1 -0
- package/{dist → lib}/file-parser/errors.js +1 -1
- package/lib/file-parser/errors.js.map +1 -0
- package/{dist → lib}/file-parser/file-parser.d.ts +2 -4
- package/lib/file-parser/file-parser.js +59 -0
- package/lib/file-parser/file-parser.js.map +1 -0
- package/{dist/structured-file-parser → lib/file-parser}/parse-row.js +2 -1
- package/lib/file-parser/parse-row.js.map +1 -0
- package/{dist/file-parser/sanitzeRows.d.ts → lib/file-parser/sanitizeRows.d.ts} +3 -1
- package/lib/file-parser/sanitizeRows.js +15 -0
- package/lib/file-parser/sanitizeRows.js.map +1 -0
- package/lib/formatting/formatting.js +11 -12
- package/lib/formatting/formatting.js.map +1 -0
- package/{dist → lib}/index.d.ts +1 -1
- package/lib/index.js +21 -0
- package/lib/index.js.map +1 -0
- package/lib/middleware/middleware.js +14 -17
- package/lib/middleware/middleware.js.map +1 -0
- package/lib/orm-helpers/ormHelpers.js +12 -13
- package/lib/orm-helpers/ormHelpers.js.map +1 -0
- package/{dist → lib}/structured-file-parser/errors.js +1 -0
- package/lib/structured-file-parser/errors.js.map +1 -0
- package/{dist/file-parser → lib/structured-file-parser}/parse-row.js +2 -1
- package/lib/structured-file-parser/parse-row.js.map +1 -0
- package/{dist → lib}/structured-file-parser/sanitize-rows.js +3 -4
- package/lib/structured-file-parser/sanitize-rows.js.map +1 -0
- package/{dist → lib}/structured-file-parser/structured-file-parser.d.ts +2 -2
- package/lib/structured-file-parser/structured-file-parser.js +95 -0
- package/lib/structured-file-parser/structured-file-parser.js.map +1 -0
- package/{dist → lib}/types/types.d.ts +0 -6
- package/lib/types/types.js +191 -203
- package/lib/types/types.js.map +1 -0
- package/{dist → lib}/validations/validations.d.ts +133 -82
- package/lib/validations/validations.js +673 -458
- package/lib/validations/validations.js.map +1 -0
- package/package.json +7 -61
- package/.circleci/config.yml +0 -87
- package/.claude/settings.local.json +0 -7
- package/.eslintrc +0 -45
- package/.huskyrc +0 -5
- package/.mocharc.json +0 -3
- package/.nvmrc +0 -1
- package/.nycrc.json +0 -11
- package/.releaserc.json +0 -18
- package/.snyk +0 -12
- package/codecov.yml +0 -29
- package/commitlint.config.js +0 -1
- package/dist/errors/errors.js +0 -42
- package/dist/errors/errors.spec.d.ts +0 -1
- package/dist/errors/errors.spec.js +0 -23
- package/dist/file-parser/__tests/file-parser.spec.d.ts +0 -1
- package/dist/file-parser/__tests/file-parser.spec.js +0 -109
- package/dist/file-parser/__tests/parse-row.spec.d.ts +0 -1
- package/dist/file-parser/__tests/parse-row.spec.js +0 -29
- package/dist/file-parser/__tests/sanitize-rows.spec.d.ts +0 -1
- package/dist/file-parser/__tests/sanitize-rows.spec.js +0 -78
- package/dist/file-parser/file-parser.js +0 -55
- package/dist/file-parser/sanitzeRows.js +0 -18
- package/dist/formatting/formatting.js +0 -17
- package/dist/formatting/formatting.spec.d.ts +0 -1
- package/dist/formatting/formatting.spec.js +0 -37
- package/dist/index.js +0 -22
- package/dist/middleware/middleware.js +0 -22
- package/dist/orm-helpers/ormHelpers.js +0 -17
- package/dist/orm-helpers/ormHelpers.spec.d.ts +0 -1
- package/dist/orm-helpers/ormHelpers.spec.js +0 -38
- package/dist/structured-file-parser/structured-file-parser.js +0 -98
- package/dist/types/types.js +0 -203
- package/dist/validations/validations.js +0 -470
- package/dist/validations/validations.spec.d.ts +0 -1
- package/dist/validations/validations.spec.js +0 -463
- package/lib/errors/errors.spec.js +0 -37
- package/lib/file-parser/__tests/file-parser.spec.js +0 -107
- package/lib/file-parser/__tests/parse-row.spec.js +0 -35
- package/lib/file-parser/__tests/sanitize-rows.spec.js +0 -88
- package/lib/file-parser/errors.ts +0 -7
- package/lib/file-parser/file-parser.ts +0 -84
- package/lib/file-parser/parse-row.ts +0 -52
- package/lib/file-parser/sanitzeRows.ts +0 -32
- package/lib/formatting/formatting.spec.js +0 -45
- package/lib/index.ts +0 -19
- package/lib/orm-helpers/ormHelpers.spec.js +0 -41
- package/lib/structured-file-parser/errors.ts +0 -25
- package/lib/structured-file-parser/parse-row.ts +0 -52
- package/lib/structured-file-parser/sanitize-rows.ts +0 -24
- package/lib/structured-file-parser/structured-file-parser.ts +0 -155
- package/lib/validations/validations.spec.js +0 -603
- package/tsconfig.json +0 -26
- /package/{dist → lib}/errors/errors.d.ts +0 -0
- /package/{dist → lib}/file-parser/errors.d.ts +0 -0
- /package/{dist → lib}/file-parser/parse-row.d.ts +0 -0
- /package/{dist → lib}/formatting/formatting.d.ts +0 -0
- /package/{dist → lib}/middleware/middleware.d.ts +0 -0
- /package/{dist → lib}/orm-helpers/ormHelpers.d.ts +0 -0
- /package/{dist → lib}/structured-file-parser/errors.d.ts +0 -0
- /package/{dist → lib}/structured-file-parser/parse-row.d.ts +0 -0
- /package/{dist → lib}/structured-file-parser/sanitize-rows.d.ts +0 -0
package/README.md
CHANGED
|
@@ -1,51 +1,19 @@
|
|
|
1
|
-
#
|
|
1
|
+
# aml-utils
|
|
2
2
|
|
|
3
|
-
This
|
|
3
|
+
This lib contains some utility functions which originally lived in aml-utils repo.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
- Formatting functions (sql escaping)
|
|
7
|
-
- Validator functions, also used by swagger node middleware. E.g. Bitcoin and Ethereum addresses validators
|
|
8
|
-
- Express middlewares to validate params types
|
|
9
|
-
- An async CSV file parser
|
|
5
|
+
## Running unit tests
|
|
10
6
|
|
|
7
|
+
Run `npx nx test aml-utils` to execute the unit tests via [Jest](https://jestjs.io).
|
|
11
8
|
|
|
12
|
-
|
|
13
|
-
-------
|
|
9
|
+
## Running lint
|
|
14
10
|
|
|
15
|
-
|
|
11
|
+
Run `npx nx lint aml-utils` to execute the lint via [ESLint](https://eslint.org/).
|
|
16
12
|
|
|
17
|
-
|
|
18
|
-
-----------
|
|
13
|
+
## Building
|
|
19
14
|
|
|
20
|
-
|
|
15
|
+
Run `npx nx build aml-utils` to build the package
|
|
21
16
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
- starts webpack on watch mode, recompiling any changes made to the code
|
|
26
|
-
|
|
27
|
-
To test your changes locally go to the repo you are working on's package.json and replace:
|
|
28
|
-
```
|
|
29
|
-
@ellipticltd/aml-utils: "*.*.*"
|
|
30
|
-
```
|
|
31
|
-
with
|
|
32
|
-
```
|
|
33
|
-
@ellipticltd/aml-utils: "file:../aml-utils"
|
|
34
|
-
```
|
|
35
|
-
(if you repositories are in the same directory).
|
|
36
|
-
|
|
37
|
-
Commiting
|
|
38
|
-
-----------
|
|
39
|
-
|
|
40
|
-
**N.B. The semantic release process described below currently does not work, meaning this package has to be deployed manually using npm publish.**
|
|
41
|
-
|
|
42
|
-
**If a permissions error is encountered when authenticating with an npm token, remove .npmrc and authenticate using npm login.**
|
|
43
|
-
|
|
44
|
-
This repository uses [Semantic release](https://semantic-release.gitbook.io/) for version publishing. To create a new version of the package simply push to bitbucket and CircleCI will create a new version. No change to this repo's package.json is required.
|
|
45
|
-
|
|
46
|
-
To work out what the next version of package should be a git commit linter is used. This is enforced by Husky and only commits with the following syntax can be [used](https://github.com/conventional-changelog/commitlint/tree/master/@commitlint/config-angular).
|
|
47
|
-
|
|
48
|
-
Setting up Semantic release
|
|
49
|
-
-----------
|
|
50
|
-
|
|
51
|
-
This [article](https://circleci.com/docs/2.0/gh-bb-integration/#creating-a-bitbucket-user-key) explains the integration between Bitbucket and CirlceCI. An NPM token also needs to be provided for the write access to the npm package
|
|
17
|
+
## Publishing
|
|
18
|
+
Run `npx nx publish aml-utils` to build and publish the package
|
|
19
|
+
You can also publish temp version of the package to npm with a tag by running `npx nx publish aml-utils -- --tag "your-tag-name"`
|
package/lib/errors/errors.js
CHANGED
|
@@ -1,53 +1,42 @@
|
|
|
1
1
|
const create = require('create-error');
|
|
2
|
-
|
|
3
2
|
const AppError = create('AppError');
|
|
4
|
-
|
|
5
3
|
const RequestError = create(AppError, 'RequestError');
|
|
6
|
-
|
|
7
4
|
RequestError.toJSON = () => ({
|
|
8
|
-
|
|
5
|
+
message: this.message,
|
|
9
6
|
});
|
|
10
|
-
|
|
11
7
|
const Forbidden = create(RequestError, 'ForbiddenError', {
|
|
12
|
-
|
|
8
|
+
status: 403,
|
|
13
9
|
});
|
|
14
|
-
|
|
15
10
|
const Unauthorized = create(RequestError, 'UnauthorizedError', {
|
|
16
|
-
|
|
11
|
+
status: 401,
|
|
17
12
|
});
|
|
18
|
-
|
|
19
13
|
const BadRequest = create(RequestError, 'BadRequestError', {
|
|
20
|
-
|
|
14
|
+
status: 400,
|
|
21
15
|
});
|
|
22
|
-
|
|
23
16
|
const NotFound = create(RequestError, 'NotFoundError', {
|
|
24
|
-
|
|
17
|
+
status: 404,
|
|
25
18
|
});
|
|
26
|
-
|
|
27
19
|
const ConflictError = create(RequestError, 'ConflictError', {
|
|
28
|
-
|
|
20
|
+
status: 409,
|
|
29
21
|
});
|
|
30
|
-
|
|
31
22
|
const ServerError = create(RequestError, 'ServerError', {
|
|
32
|
-
|
|
23
|
+
status: 500,
|
|
33
24
|
});
|
|
34
|
-
|
|
35
25
|
const InvalidArguments = create(RequestError, 'InvalidArgumentsError', {
|
|
36
|
-
|
|
26
|
+
status: 500,
|
|
37
27
|
});
|
|
38
|
-
|
|
39
28
|
const ServerTimeout = create(RequestError, 'ServerTimeoutError', {
|
|
40
|
-
|
|
29
|
+
status: 503,
|
|
41
30
|
});
|
|
42
|
-
|
|
43
31
|
module.exports = {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
32
|
+
RequestError,
|
|
33
|
+
ServerError,
|
|
34
|
+
Forbidden,
|
|
35
|
+
Unauthorized,
|
|
36
|
+
BadRequest,
|
|
37
|
+
NotFound,
|
|
38
|
+
ConflictError,
|
|
39
|
+
InvalidArguments,
|
|
40
|
+
ServerTimeout,
|
|
53
41
|
};
|
|
42
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../../../../libs/aml-utils/lib/errors/errors.js"],"names":[],"mappings":"AAAA,MAAM,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;AAEvC,MAAM,QAAQ,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC;AAEpC,MAAM,YAAY,GAAG,MAAM,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;AAEtD,YAAY,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC,CAAC;IAC3B,OAAO,EAAE,IAAI,CAAC,OAAO;CACtB,CAAC,CAAC;AAEH,MAAM,SAAS,GAAG,MAAM,CAAC,YAAY,EAAE,gBAAgB,EAAE;IACvD,MAAM,EAAE,GAAG;CACZ,CAAC,CAAC;AAEH,MAAM,YAAY,GAAG,MAAM,CAAC,YAAY,EAAE,mBAAmB,EAAE;IAC7D,MAAM,EAAE,GAAG;CACZ,CAAC,CAAC;AAEH,MAAM,UAAU,GAAG,MAAM,CAAC,YAAY,EAAE,iBAAiB,EAAE;IACzD,MAAM,EAAE,GAAG;CACZ,CAAC,CAAC;AAEH,MAAM,QAAQ,GAAG,MAAM,CAAC,YAAY,EAAE,eAAe,EAAE;IACrD,MAAM,EAAE,GAAG;CACZ,CAAC,CAAC;AAEH,MAAM,aAAa,GAAG,MAAM,CAAC,YAAY,EAAE,eAAe,EAAE;IAC1D,MAAM,EAAE,GAAG;CACZ,CAAC,CAAC;AAEH,MAAM,WAAW,GAAG,MAAM,CAAC,YAAY,EAAE,aAAa,EAAE;IACtD,MAAM,EAAE,GAAG;CACZ,CAAC,CAAC;AAEH,MAAM,gBAAgB,GAAG,MAAM,CAAC,YAAY,EAAE,uBAAuB,EAAE;IACrE,MAAM,EAAE,GAAG;CACZ,CAAC,CAAC;AAEH,MAAM,aAAa,GAAG,MAAM,CAAC,YAAY,EAAE,oBAAoB,EAAE;IAC/D,MAAM,EAAE,GAAG;CACZ,CAAC,CAAC;AAEH,MAAM,CAAC,OAAO,GAAG;IACf,YAAY;IACZ,WAAW;IACX,SAAS;IACT,YAAY;IACZ,UAAU;IACV,QAAQ;IACR,aAAa;IACb,gBAAgB;IAChB,aAAa;CACd,CAAC","sourcesContent":["const create = require('create-error');\n\nconst AppError = create('AppError');\n\nconst RequestError = create(AppError, 'RequestError');\n\nRequestError.toJSON = () => ({\n message: this.message,\n});\n\nconst Forbidden = create(RequestError, 'ForbiddenError', {\n status: 403,\n});\n\nconst Unauthorized = create(RequestError, 'UnauthorizedError', {\n status: 401,\n});\n\nconst BadRequest = create(RequestError, 'BadRequestError', {\n status: 400,\n});\n\nconst NotFound = create(RequestError, 'NotFoundError', {\n status: 404,\n});\n\nconst ConflictError = create(RequestError, 'ConflictError', {\n status: 409,\n});\n\nconst ServerError = create(RequestError, 'ServerError', {\n status: 500,\n});\n\nconst InvalidArguments = create(RequestError, 'InvalidArgumentsError', {\n status: 500,\n});\n\nconst ServerTimeout = create(RequestError, 'ServerTimeoutError', {\n status: 503,\n});\n\nmodule.exports = {\n RequestError,\n ServerError,\n Forbidden,\n Unauthorized,\n BadRequest,\n NotFound,\n ConflictError,\n InvalidArguments,\n ServerTimeout,\n};\n"]}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.TooManyRowsError = void 0;
|
|
4
|
-
// eslint-disable-next-line import/prefer-default-export
|
|
5
4
|
class TooManyRowsError extends Error {
|
|
6
5
|
constructor() {
|
|
7
6
|
super('More than configured number of rows imported');
|
|
@@ -9,3 +8,4 @@ class TooManyRowsError extends Error {
|
|
|
9
8
|
}
|
|
10
9
|
}
|
|
11
10
|
exports.TooManyRowsError = TooManyRowsError;
|
|
11
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../../../../libs/aml-utils/lib/file-parser/errors.ts"],"names":[],"mappings":";;;AAAA,MAAa,gBAAiB,SAAQ,KAAK;IACzC;QACE,KAAK,CAAC,8CAA8C,CAAC,CAAC;QACtD,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC;IACjC,CAAC;CACF;AALD,4CAKC","sourcesContent":["export class TooManyRowsError extends Error {\n constructor() {\n super('More than configured number of rows imported');\n this.name = 'TooManyRowsError';\n }\n}\n"]}
|
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
};
|
|
4
|
-
declare type Dependencies<T extends ProcessingEntry> = {
|
|
1
|
+
import { ProcessingEntry } from './sanitizeRows';
|
|
2
|
+
type Dependencies<T extends ProcessingEntry> = {
|
|
5
3
|
processRow: (cells: string[]) => T;
|
|
6
4
|
};
|
|
7
5
|
declare function parseFile<T extends ProcessingEntry>(fileContent: string, maxRows: number, dependencies: Dependencies<T>): Promise<T[]>;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
4
|
+
const parse_row_1 = tslib_1.__importDefault(require("./parse-row"));
|
|
5
|
+
const errors_1 = require("./errors");
|
|
6
|
+
const sanitizeRows_1 = tslib_1.__importDefault(require("./sanitizeRows"));
|
|
7
|
+
function chunk(array, size) {
|
|
8
|
+
if (!array.length) {
|
|
9
|
+
return [];
|
|
10
|
+
}
|
|
11
|
+
const head = array.slice(0, size);
|
|
12
|
+
const tail = array.slice(size);
|
|
13
|
+
return [head, ...chunk(tail, size)];
|
|
14
|
+
}
|
|
15
|
+
function processChunk(parsedRows, dependencies) {
|
|
16
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
17
|
+
const { processRow } = dependencies;
|
|
18
|
+
return new Promise((resolve, reject) => {
|
|
19
|
+
setTimeout(() => {
|
|
20
|
+
try {
|
|
21
|
+
const processedRows = parsedRows.map(processRow);
|
|
22
|
+
resolve(processedRows);
|
|
23
|
+
}
|
|
24
|
+
catch (ex) {
|
|
25
|
+
if (ex instanceof Error) {
|
|
26
|
+
reject(ex);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}, 0);
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
function parseFile(fileContent, maxRows, dependencies) {
|
|
34
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
35
|
+
const { processRow } = dependencies;
|
|
36
|
+
if (fileContent === 'invalidFileType') {
|
|
37
|
+
throw Error('Invalid file type');
|
|
38
|
+
}
|
|
39
|
+
const rows = fileContent.split('\n');
|
|
40
|
+
const parsedRows = rows.map(parse_row_1.default);
|
|
41
|
+
const sanitizedRows = (0, sanitizeRows_1.default)(parsedRows, processRow);
|
|
42
|
+
if (sanitizedRows.length > maxRows) {
|
|
43
|
+
throw new errors_1.TooManyRowsError();
|
|
44
|
+
}
|
|
45
|
+
if (sanitizedRows.length === 0) {
|
|
46
|
+
throw new Error('No rows');
|
|
47
|
+
}
|
|
48
|
+
const parsedRowChunks = chunk(sanitizedRows, 30);
|
|
49
|
+
let results = [];
|
|
50
|
+
// eslint-disable-next-line no-restricted-syntax
|
|
51
|
+
for (const currentRowChunk of parsedRowChunks) {
|
|
52
|
+
const chunkResult = yield processChunk(currentRowChunk, dependencies);
|
|
53
|
+
results = results.concat(chunkResult);
|
|
54
|
+
}
|
|
55
|
+
return results;
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
exports.default = parseFile;
|
|
59
|
+
//# sourceMappingURL=file-parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-parser.js","sourceRoot":"","sources":["../../../../../libs/aml-utils/lib/file-parser/file-parser.ts"],"names":[],"mappings":";;;AAAA,oEAAmC;AACnC,qCAA4C;AAC5C,0EAA+D;AAM/D,SAAS,KAAK,CAAI,KAAU,EAAE,IAAY;IACxC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE;QACjB,OAAO,EAAE,CAAC;KACX;IACD,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;IAClC,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAE/B,OAAO,CAAC,IAAI,EAAE,GAAG,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;AACtC,CAAC;AAED,SAAe,YAAY,CAA4B,UAAsB,EAAE,YAA6B;;QAC1G,MAAM,EAAE,UAAU,EAAE,GAAG,YAAY,CAAC;QACpC,OAAO,IAAI,OAAO,CAAC,CAAC,OAA6B,EAAE,MAA8B,EAAQ,EAAE;YACzF,UAAU,CAAC,GAAG,EAAE;gBACd,IAAI;oBACF,MAAM,aAAa,GAAG,UAAU,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;oBACjD,OAAO,CAAC,aAAa,CAAC,CAAC;iBACxB;gBAAC,OAAO,EAAE,EAAE;oBACX,IAAI,EAAE,YAAY,KAAK,EAAE;wBACvB,MAAM,CAAC,EAAE,CAAC,CAAC;qBACZ;iBACF;YACH,CAAC,EAAE,CAAC,CAAC,CAAC;QACR,CAAC,CAAC,CAAC;IACL,CAAC;CAAA;AAED,SAAe,SAAS,CAA4B,WAAmB,EAAE,OAAe,EAAE,YAA6B;;QACrH,MAAM,EAAE,UAAU,EAAE,GAAG,YAAY,CAAC;QAEpC,IAAI,WAAW,KAAK,iBAAiB,EAAE;YACrC,MAAM,KAAK,CAAC,mBAAmB,CAAC,CAAC;SAClC;QAED,MAAM,IAAI,GAAG,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACrC,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,mBAAQ,CAAC,CAAC;QAEtC,MAAM,aAAa,GAAG,IAAA,sBAAY,EAAC,UAAU,EAAE,UAAU,CAAC,CAAC;QAE3D,IAAI,aAAa,CAAC,MAAM,GAAG,OAAO,EAAE;YAClC,MAAM,IAAI,yBAAgB,EAAE,CAAC;SAC9B;QAED,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE;YAC9B,MAAM,IAAI,KAAK,CAAC,SAAS,CAAC,CAAC;SAC5B;QAED,MAAM,eAAe,GAAG,KAAK,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC;QACjD,IAAI,OAAO,GAAQ,EAAE,CAAC;QACtB,gDAAgD;QAChD,KAAK,MAAM,eAAe,IAAI,eAAe,EAAE;YAC7C,MAAM,WAAW,GAAG,MAAM,YAAY,CAAC,eAAe,EAAE,YAAY,CAAC,CAAC;YACtE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;SACvC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;CAAA;AAED,kBAAe,SAAS,CAAC","sourcesContent":["import parseRow from './parse-row';\nimport { TooManyRowsError } from './errors';\nimport sanitizeRows, { ProcessingEntry } from './sanitizeRows';\n\ntype Dependencies<T extends ProcessingEntry> = {\n processRow: (cells: string[]) => T;\n};\n\nfunction chunk<T>(array: T[], size: number): T[][] {\n if (!array.length) {\n return [];\n }\n const head = array.slice(0, size);\n const tail = array.slice(size);\n\n return [head, ...chunk(tail, size)];\n}\n\nasync function processChunk<T extends ProcessingEntry>(parsedRows: string[][], dependencies: Dependencies<T>): Promise<T[]> {\n const { processRow } = dependencies;\n return new Promise((resolve: (value: T[]) => void, reject: (error: Error) => void): void => {\n setTimeout(() => {\n try {\n const processedRows = parsedRows.map(processRow);\n resolve(processedRows);\n } catch (ex) {\n if (ex instanceof Error) {\n reject(ex);\n }\n }\n }, 0);\n });\n}\n\nasync function parseFile<T extends ProcessingEntry>(fileContent: string, maxRows: number, dependencies: Dependencies<T>): Promise<T[]> {\n const { processRow } = dependencies;\n\n if (fileContent === 'invalidFileType') {\n throw Error('Invalid file type');\n }\n\n const rows = fileContent.split('\\n');\n const parsedRows = rows.map(parseRow);\n\n const sanitizedRows = sanitizeRows(parsedRows, processRow);\n\n if (sanitizedRows.length > maxRows) {\n throw new TooManyRowsError();\n }\n\n if (sanitizedRows.length === 0) {\n throw new Error('No rows');\n }\n\n const parsedRowChunks = chunk(sanitizedRows, 30);\n let results: T[] = [];\n // eslint-disable-next-line no-restricted-syntax\n for (const currentRowChunk of parsedRowChunks) {\n const chunkResult = await processChunk(currentRowChunk, dependencies);\n results = results.concat(chunkResult);\n }\n\n return results;\n}\n\nexport default parseFile;\n"]}
|
|
@@ -32,8 +32,9 @@ const parseRow = (row) => {
|
|
|
32
32
|
}
|
|
33
33
|
return line;
|
|
34
34
|
};
|
|
35
|
-
const splitRow = fp_1.pipe(trySplitByTab, trySplitByComa, trySplitByMultipleSpaces, trySplitBySpace, trySplitByNothing);
|
|
35
|
+
const splitRow = (0, fp_1.pipe)(trySplitByTab, trySplitByComa, trySplitByMultipleSpaces, trySplitBySpace, trySplitByNothing);
|
|
36
36
|
const cells = splitRow(row);
|
|
37
37
|
return cells.map((c) => c.trim());
|
|
38
38
|
};
|
|
39
39
|
exports.default = parseRow;
|
|
40
|
+
//# sourceMappingURL=parse-row.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse-row.js","sourceRoot":"","sources":["../../../../../libs/aml-utils/lib/file-parser/parse-row.ts"],"names":[],"mappings":";;AAAA,kCAAiC;AAEjC,MAAM,QAAQ,GAAG,CAAC,GAAW,EAAY,EAAE;IACzC,MAAM,aAAa,GAAG,CAAC,IAAuB,EAAqB,EAAE;QACnE,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE;YAChD,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;SACzB;QACD,OAAO,IAAI,CAAC;IACd,CAAC,CAAC;IAEF,MAAM,cAAc,GAAG,CAAC,IAAuB,EAAqB,EAAE;QACpE,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE;YAC/C,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;SACxB;QACD,OAAO,IAAI,CAAC;IACd,CAAC,CAAC;IAEF,MAAM,wBAAwB,GAAG,CAAC,IAAuB,EAAqB,EAAE;QAC9E,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE;YACnD,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;SAC5B;QACD,OAAO,IAAI,CAAC;IACd,CAAC,CAAC;IAEF,MAAM,eAAe,GAAG,CAAC,IAAuB,EAAqB,EAAE;QACrE,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE;YAC/C,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;SACxB;QACD,OAAO,IAAI,CAAC;IACd,CAAC,CAAC;IAEF,MAAM,iBAAiB,GAAG,CAAC,IAAuB,EAAY,EAAE;QAC9D,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE;YAC5B,OAAO,CAAC,IAAI,CAAC,CAAC;SACf;QACD,OAAO,IAAI,CAAC;IACd,CAAC,CAAC;IAEF,MAAM,QAAQ,GAAG,IAAA,SAAI,EAAC,aAAa,EAAE,cAAc,EAAE,wBAAwB,EAAE,eAAe,EAAE,iBAAiB,CAAC,CAAC;IAEnH,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;IAE5B,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;AAC5C,CAAC,CAAC;AAEF,kBAAe,QAAQ,CAAC","sourcesContent":["import { pipe } from 'lodash/fp';\n\nconst parseRow = (row: string): string[] => {\n const trySplitByTab = (line: string | string[]): string | string[] => {\n if (typeof line === 'string' && line.match('\\t')) {\n return line.split('\\t');\n }\n return line;\n };\n\n const trySplitByComa = (line: string | string[]): string | string[] => {\n if (typeof line === 'string' && line.match(',')) {\n return line.split(',');\n }\n return line;\n };\n\n const trySplitByMultipleSpaces = (line: string | string[]): string | string[] => {\n if (typeof line === 'string' && line.match(/ {3,}/)) {\n return line.split(/ {3,}/);\n }\n return line;\n };\n\n const trySplitBySpace = (line: string | string[]): string | string[] => {\n if (typeof line === 'string' && line.match(' ')) {\n return line.split(' ');\n }\n return line;\n };\n\n const trySplitByNothing = (line: string | string[]): string[] => {\n if (typeof line === 'string') {\n return [line];\n }\n return line;\n };\n\n const splitRow = pipe(trySplitByTab, trySplitByComa, trySplitByMultipleSpaces, trySplitBySpace, trySplitByNothing);\n\n const cells = splitRow(row);\n\n return cells.map((c: string) => c.trim());\n};\n\nexport default parseRow;\n"]}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const sensicalRowCheck = (cells) => cells.some((cell) => !!cell);
|
|
4
|
+
function sanitizeRows(parsedRows, processRow) {
|
|
5
|
+
const firstSensicalRowIndex = parsedRows.findIndex(sensicalRowCheck);
|
|
6
|
+
const lastSensicalRowIndex = [...parsedRows].reverse().findIndex(sensicalRowCheck);
|
|
7
|
+
const sanitizedRows = parsedRows.splice(firstSensicalRowIndex, parsedRows.length - firstSensicalRowIndex - lastSensicalRowIndex);
|
|
8
|
+
const firstRow = processRow(sanitizedRows[0]);
|
|
9
|
+
if (firstRow.isValid) {
|
|
10
|
+
return sanitizedRows;
|
|
11
|
+
}
|
|
12
|
+
return sanitizedRows.splice(1);
|
|
13
|
+
}
|
|
14
|
+
exports.default = sanitizeRows;
|
|
15
|
+
//# sourceMappingURL=sanitizeRows.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sanitizeRows.js","sourceRoot":"","sources":["../../../../../libs/aml-utils/lib/file-parser/sanitizeRows.ts"],"names":[],"mappings":";;AAIA,MAAM,gBAAgB,GAAG,CAAC,KAAe,EAAW,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAY,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;AAE5F,SAAS,YAAY,CAA4B,UAAsB,EAAE,UAAgC;IACvG,MAAM,qBAAqB,GAAG,UAAU,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC;IAErE,MAAM,oBAAoB,GAAG,CAAC,GAAG,UAAU,CAAC,CAAC,OAAO,EAAE,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC;IAEnF,MAAM,aAAa,GAAG,UAAU,CAAC,MAAM,CAAC,qBAAqB,EAAE,UAAU,CAAC,MAAM,GAAG,qBAAqB,GAAG,oBAAoB,CAAC,CAAC;IAEjI,MAAM,QAAQ,GAAG,UAAU,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;IAE9C,IAAI,QAAQ,CAAC,OAAO,EAAE;QACpB,OAAO,aAAa,CAAC;KACtB;IACD,OAAO,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AACjC,CAAC;AAED,kBAAe,YAAY,CAAC","sourcesContent":["export type ProcessingEntry = {\n isValid: boolean;\n};\n\nconst sensicalRowCheck = (cells: string[]): boolean => cells.some((cell: string) => !!cell);\n\nfunction sanitizeRows<T extends ProcessingEntry>(parsedRows: string[][], processRow: (row: string[]) => T): string[][] {\n const firstSensicalRowIndex = parsedRows.findIndex(sensicalRowCheck);\n\n const lastSensicalRowIndex = [...parsedRows].reverse().findIndex(sensicalRowCheck);\n\n const sanitizedRows = parsedRows.splice(firstSensicalRowIndex, parsedRows.length - firstSensicalRowIndex - lastSensicalRowIndex);\n\n const firstRow = processRow(sanitizedRows[0]);\n\n if (firstRow.isValid) {\n return sanitizedRows;\n }\n return sanitizedRows.splice(1);\n}\n\nexport default sanitizeRows;\n"]}
|
|
@@ -1,18 +1,17 @@
|
|
|
1
1
|
const _ = require('lodash');
|
|
2
|
-
|
|
3
2
|
const rethrowError = (fnName, e) => {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
3
|
+
let formattedError;
|
|
4
|
+
if (_.isPlainObject(e.error) || _.isArray(e.error)) {
|
|
5
|
+
formattedError = `\n${JSON.stringify(e.error, null, 2)}`;
|
|
6
|
+
}
|
|
7
|
+
else {
|
|
8
|
+
formattedError = e.error;
|
|
9
|
+
}
|
|
10
|
+
return `${fnName} - ${e.name}: ${e.statusCode} - ${formattedError}`;
|
|
11
11
|
};
|
|
12
|
-
|
|
13
12
|
const sqlEscapeWildcard = (str) => str.replace(/_|%|\\/g, (x) => `\\${x}`);
|
|
14
|
-
|
|
15
13
|
module.exports = {
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
rethrowError,
|
|
15
|
+
sqlEscapeWildcard,
|
|
18
16
|
};
|
|
17
|
+
//# sourceMappingURL=formatting.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatting.js","sourceRoot":"","sources":["../../../../../libs/aml-utils/lib/formatting/formatting.js"],"names":[],"mappings":"AAAA,MAAM,CAAC,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;AAE5B,MAAM,YAAY,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;IACjC,IAAI,cAAc,CAAC;IACnB,IAAI,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE;QAClD,cAAc,GAAG,KAAK,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;KAC1D;SAAM;QACL,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC;KAC1B;IACD,OAAO,GAAG,MAAM,MAAM,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,UAAU,MAAM,cAAc,EAAE,CAAC;AACtE,CAAC,CAAC;AAEF,MAAM,iBAAiB,GAAG,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;AAE3E,MAAM,CAAC,OAAO,GAAG;IACf,YAAY;IACZ,iBAAiB;CAClB,CAAC","sourcesContent":["const _ = require('lodash');\n\nconst rethrowError = (fnName, e) => {\n let formattedError;\n if (_.isPlainObject(e.error) || _.isArray(e.error)) {\n formattedError = `\\n${JSON.stringify(e.error, null, 2)}`;\n } else {\n formattedError = e.error;\n }\n return `${fnName} - ${e.name}: ${e.statusCode} - ${formattedError}`;\n};\n\nconst sqlEscapeWildcard = (str) => str.replace(/_|%|\\\\/g, (x) => `\\\\${x}`);\n\nmodule.exports = {\n rethrowError,\n sqlEscapeWildcard,\n};\n"]}
|
package/{dist → lib}/index.d.ts
RENAMED
|
@@ -6,4 +6,4 @@ import middleware from './middleware/middleware';
|
|
|
6
6
|
import ormHelpers from './orm-helpers/ormHelpers';
|
|
7
7
|
import fileParser from './file-parser/file-parser';
|
|
8
8
|
import structuredFileParser from './structured-file-parser/structured-file-parser';
|
|
9
|
-
export { types, validations, errors, formatting, fileParser, structuredFileParser, middleware, ormHelpers
|
|
9
|
+
export { types, validations, errors, formatting, fileParser, structuredFileParser, middleware, ormHelpers };
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ormHelpers = exports.middleware = exports.structuredFileParser = exports.fileParser = exports.formatting = exports.errors = exports.validations = exports.types = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const types_1 = tslib_1.__importDefault(require("./types/types"));
|
|
6
|
+
exports.types = types_1.default;
|
|
7
|
+
const validations_1 = tslib_1.__importDefault(require("./validations/validations"));
|
|
8
|
+
exports.validations = validations_1.default;
|
|
9
|
+
const errors_1 = tslib_1.__importDefault(require("./errors/errors"));
|
|
10
|
+
exports.errors = errors_1.default;
|
|
11
|
+
const formatting_1 = tslib_1.__importDefault(require("./formatting/formatting"));
|
|
12
|
+
exports.formatting = formatting_1.default;
|
|
13
|
+
const middleware_1 = tslib_1.__importDefault(require("./middleware/middleware"));
|
|
14
|
+
exports.middleware = middleware_1.default;
|
|
15
|
+
const ormHelpers_1 = tslib_1.__importDefault(require("./orm-helpers/ormHelpers"));
|
|
16
|
+
exports.ormHelpers = ormHelpers_1.default;
|
|
17
|
+
const file_parser_1 = tslib_1.__importDefault(require("./file-parser/file-parser"));
|
|
18
|
+
exports.fileParser = file_parser_1.default;
|
|
19
|
+
const structured_file_parser_1 = tslib_1.__importDefault(require("./structured-file-parser/structured-file-parser"));
|
|
20
|
+
exports.structuredFileParser = structured_file_parser_1.default;
|
|
21
|
+
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../libs/aml-utils/lib/index.ts"],"names":[],"mappings":";;;;AAAA,kEAAkC;AASzB,gBATF,eAAK,CASE;AARd,oFAAoD;AAQpC,sBART,qBAAW,CAQS;AAP3B,qEAAqC;AAOR,iBAPtB,gBAAM,CAOsB;AANnC,iFAAiD;AAMZ,qBAN9B,oBAAU,CAM8B;AAL/C,iFAAiD;AAKkC,qBAL5E,oBAAU,CAK4E;AAJ7F,kFAAkD;AAI6C,qBAJxF,oBAAU,CAIwF;AAHzG,oFAAmD;AAGF,qBAH1C,qBAAU,CAG0C;AAF3D,qHAAmF;AAEtB,+BAFtD,gCAAoB,CAEsD","sourcesContent":["import types from './types/types';\nimport validations from './validations/validations';\nimport errors from './errors/errors';\nimport formatting from './formatting/formatting';\nimport middleware from './middleware/middleware';\nimport ormHelpers from './orm-helpers/ormHelpers';\nimport fileParser from './file-parser/file-parser';\nimport structuredFileParser from './structured-file-parser/structured-file-parser';\n\nexport { types, validations, errors, formatting, fileParser, structuredFileParser, middleware, ormHelpers };\n"]}
|
|
@@ -1,25 +1,22 @@
|
|
|
1
1
|
const T = require('../types/types');
|
|
2
|
-
|
|
3
2
|
const ensureType = (type) => (req, res, next, id, name) => {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
3
|
+
let error;
|
|
4
|
+
try {
|
|
5
|
+
T.ensureType(type, id, `Invalid ${name}`);
|
|
6
|
+
return next();
|
|
7
|
+
}
|
|
8
|
+
catch (error1) {
|
|
9
|
+
error = error1;
|
|
10
|
+
return next(error);
|
|
11
|
+
}
|
|
12
12
|
};
|
|
13
|
-
|
|
14
13
|
const ensureUUID = ensureType('UUID');
|
|
15
|
-
|
|
16
14
|
const ensureHex32 = ensureType('Hex32');
|
|
17
|
-
|
|
18
15
|
const ensureInteger = ensureType('IntString');
|
|
19
|
-
|
|
20
16
|
module.exports = {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
17
|
+
ensureType,
|
|
18
|
+
ensureUUID,
|
|
19
|
+
ensureHex32,
|
|
20
|
+
ensureInteger,
|
|
25
21
|
};
|
|
22
|
+
//# sourceMappingURL=middleware.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"middleware.js","sourceRoot":"","sources":["../../../../../libs/aml-utils/lib/middleware/middleware.js"],"names":[],"mappings":"AAAA,MAAM,CAAC,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;AAEpC,MAAM,UAAU,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE;IACxD,IAAI,KAAK,CAAC;IACV,IAAI;QACF,CAAC,CAAC,UAAU,CAAC,IAAI,EAAE,EAAE,EAAE,WAAW,IAAI,EAAE,CAAC,CAAC;QAC1C,OAAO,IAAI,EAAE,CAAC;KACf;IAAC,OAAO,MAAM,EAAE;QACf,KAAK,GAAG,MAAM,CAAC;QACf,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC;KACpB;AACH,CAAC,CAAC;AAEF,MAAM,UAAU,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;AAEtC,MAAM,WAAW,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC;AAExC,MAAM,aAAa,GAAG,UAAU,CAAC,WAAW,CAAC,CAAC;AAE9C,MAAM,CAAC,OAAO,GAAG;IACf,UAAU;IACV,UAAU;IACV,WAAW;IACX,aAAa;CACd,CAAC","sourcesContent":["const T = require('../types/types');\n\nconst ensureType = (type) => (req, res, next, id, name) => {\n let error;\n try {\n T.ensureType(type, id, `Invalid ${name}`);\n return next();\n } catch (error1) {\n error = error1;\n return next(error);\n }\n};\n\nconst ensureUUID = ensureType('UUID');\n\nconst ensureHex32 = ensureType('Hex32');\n\nconst ensureInteger = ensureType('IntString');\n\nmodule.exports = {\n ensureType,\n ensureUUID,\n ensureHex32,\n ensureInteger,\n};\n"]}
|
|
@@ -1,18 +1,17 @@
|
|
|
1
1
|
const _ = require('lodash');
|
|
2
|
-
|
|
3
2
|
const includeNested = (orm, models) => _.map(_.toPairs(models), (arg) => {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
3
|
+
const [modelName, inclusion] = arg;
|
|
4
|
+
const include = includeNested(orm, inclusion);
|
|
5
|
+
const model = orm[modelName];
|
|
6
|
+
if (_.isEmpty(include)) {
|
|
7
|
+
return model;
|
|
8
|
+
}
|
|
9
|
+
return {
|
|
10
|
+
model,
|
|
11
|
+
include,
|
|
12
|
+
};
|
|
14
13
|
});
|
|
15
|
-
|
|
16
14
|
module.exports = {
|
|
17
|
-
|
|
15
|
+
includeNested,
|
|
18
16
|
};
|
|
17
|
+
//# sourceMappingURL=ormHelpers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ormHelpers.js","sourceRoot":"","sources":["../../../../../libs/aml-utils/lib/orm-helpers/ormHelpers.js"],"names":[],"mappings":"AAAA,MAAM,CAAC,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;AAE5B,MAAM,aAAa,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,CACpC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE;IAC/B,MAAM,CAAC,SAAS,EAAE,SAAS,CAAC,GAAG,GAAG,CAAC;IACnC,MAAM,OAAO,GAAG,aAAa,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;IAC9C,MAAM,KAAK,GAAG,GAAG,CAAC,SAAS,CAAC,CAAC;IAC7B,IAAI,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE;QACtB,OAAO,KAAK,CAAC;KACd;IACD,OAAO;QACL,KAAK;QACL,OAAO;KACR,CAAC;AACJ,CAAC,CAAC,CAAC;AAEL,MAAM,CAAC,OAAO,GAAG;IACf,aAAa;CACd,CAAC","sourcesContent":["const _ = require('lodash');\n\nconst includeNested = (orm, models) =>\n _.map(_.toPairs(models), (arg) => {\n const [modelName, inclusion] = arg;\n const include = includeNested(orm, inclusion);\n const model = orm[modelName];\n if (_.isEmpty(include)) {\n return model;\n }\n return {\n model,\n include,\n };\n });\n\nmodule.exports = {\n includeNested,\n};\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../../../../libs/aml-utils/lib/structured-file-parser/errors.ts"],"names":[],"mappings":";;;AAAA,yCAAyC;AACzC,MAAa,gBAAiB,SAAQ,KAAK;IACzC;QACE,KAAK,CAAC,mBAAmB,CAAC,CAAC;QAC3B,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC;IACjC,CAAC;CACF;AALD,4CAKC;AACD,MAAa,gBAAiB,SAAQ,KAAK;IACzC;QACE,KAAK,CAAC,8CAA8C,CAAC,CAAC;QACtD,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC;IACjC,CAAC;CACF;AALD,4CAKC;AACD,MAAa,WAAY,SAAQ,KAAK;IACpC;QACE,KAAK,CAAC,SAAS,CAAC,CAAC;QACjB,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC;IAC5B,CAAC;CACF;AALD,kCAKC;AACD,MAAa,mBAAoB,SAAQ,KAAK;IAC5C;QACE,KAAK,CAAC,oCAAoC,CAAC,CAAC;QAC5C,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC;IACpC,CAAC;CACF;AALD,kDAKC","sourcesContent":["/* eslint-disable max-classes-per-file */\nexport class InvalidFileError extends Error {\n constructor() {\n super('Invalid file type');\n this.name = 'InvalidFileError';\n }\n}\nexport class TooManyRowsError extends Error {\n constructor() {\n super('More than configured number of rows imported');\n this.name = 'TooManyRowsError';\n }\n}\nexport class NoRowsError extends Error {\n constructor() {\n super('No rows');\n this.name = 'NoRowsError';\n }\n}\nexport class InvalidHeadersError extends Error {\n constructor() {\n super('Invalid or incomplete headers list');\n this.name = 'InvalidHeadersError';\n }\n}\n"]}
|
|
@@ -32,8 +32,9 @@ const parseRow = (row) => {
|
|
|
32
32
|
}
|
|
33
33
|
return line;
|
|
34
34
|
};
|
|
35
|
-
const splitRow = fp_1.pipe(trySplitByTab, trySplitByComa, trySplitByMultipleSpaces, trySplitBySpace, trySplitByNothing);
|
|
35
|
+
const splitRow = (0, fp_1.pipe)(trySplitByTab, trySplitByComa, trySplitByMultipleSpaces, trySplitBySpace, trySplitByNothing);
|
|
36
36
|
const cells = splitRow(row);
|
|
37
37
|
return cells.map((c) => c.trim());
|
|
38
38
|
};
|
|
39
39
|
exports.default = parseRow;
|
|
40
|
+
//# sourceMappingURL=parse-row.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse-row.js","sourceRoot":"","sources":["../../../../../libs/aml-utils/lib/structured-file-parser/parse-row.ts"],"names":[],"mappings":";;AAAA,kCAAiC;AAEjC,MAAM,QAAQ,GAAG,CAAC,GAAW,EAAY,EAAE;IACzC,MAAM,aAAa,GAAG,CAAC,IAAuB,EAAqB,EAAE;QACnE,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE;YAChD,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;SACzB;QACD,OAAO,IAAI,CAAC;IACd,CAAC,CAAC;IAEF,MAAM,cAAc,GAAG,CAAC,IAAuB,EAAqB,EAAE;QACpE,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE;YAC/C,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;SACxB;QACD,OAAO,IAAI,CAAC;IACd,CAAC,CAAC;IAEF,MAAM,wBAAwB,GAAG,CAAC,IAAuB,EAAqB,EAAE;QAC9E,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE;YACnD,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;SAC5B;QACD,OAAO,IAAI,CAAC;IACd,CAAC,CAAC;IAEF,MAAM,eAAe,GAAG,CAAC,IAAuB,EAAqB,EAAE;QACrE,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE;YAC/C,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;SACxB;QACD,OAAO,IAAI,CAAC;IACd,CAAC,CAAC;IAEF,MAAM,iBAAiB,GAAG,CAAC,IAAuB,EAAY,EAAE;QAC9D,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE;YAC5B,OAAO,CAAC,IAAI,CAAC,CAAC;SACf;QACD,OAAO,IAAI,CAAC;IACd,CAAC,CAAC;IAEF,MAAM,QAAQ,GAAG,IAAA,SAAI,EAAC,aAAa,EAAE,cAAc,EAAE,wBAAwB,EAAE,eAAe,EAAE,iBAAiB,CAAC,CAAC;IAEnH,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;IAE5B,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;AAC5C,CAAC,CAAC;AAEF,kBAAe,QAAQ,CAAC","sourcesContent":["import { pipe } from 'lodash/fp';\n\nconst parseRow = (row: string): string[] => {\n const trySplitByTab = (line: string | string[]): string | string[] => {\n if (typeof line === 'string' && line.match('\\t')) {\n return line.split('\\t');\n }\n return line;\n };\n\n const trySplitByComa = (line: string | string[]): string | string[] => {\n if (typeof line === 'string' && line.match(',')) {\n return line.split(',');\n }\n return line;\n };\n\n const trySplitByMultipleSpaces = (line: string | string[]): string | string[] => {\n if (typeof line === 'string' && line.match(/ {3,}/)) {\n return line.split(/ {3,}/);\n }\n return line;\n };\n\n const trySplitBySpace = (line: string | string[]): string | string[] => {\n if (typeof line === 'string' && line.match(' ')) {\n return line.split(' ');\n }\n return line;\n };\n\n const trySplitByNothing = (line: string | string[]): string[] => {\n if (typeof line === 'string') {\n return [line];\n }\n return line;\n };\n\n const splitRow = pipe(trySplitByTab, trySplitByComa, trySplitByMultipleSpaces, trySplitBySpace, trySplitByNothing);\n\n const cells = splitRow(row);\n\n return cells.map((c: string) => c.trim());\n};\n\nexport default parseRow;\n"]}
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const sensicalRowCheck = (cells) =>
|
|
3
|
+
const sensicalRowCheck = (cells) => cells.some((cell) => !!cell);
|
|
4
4
|
function sanitizeRows(parsedRows) {
|
|
5
5
|
const firstSensicalRowIndex = parsedRows.findIndex(sensicalRowCheck);
|
|
6
|
-
const lastSensicalRowIndex = [...parsedRows]
|
|
7
|
-
.reverse()
|
|
8
|
-
.findIndex(sensicalRowCheck);
|
|
6
|
+
const lastSensicalRowIndex = [...parsedRows].reverse().findIndex(sensicalRowCheck);
|
|
9
7
|
if (firstSensicalRowIndex < 0) {
|
|
10
8
|
return [];
|
|
11
9
|
}
|
|
@@ -13,3 +11,4 @@ function sanitizeRows(parsedRows) {
|
|
|
13
11
|
return sanitizedRows;
|
|
14
12
|
}
|
|
15
13
|
exports.default = sanitizeRows;
|
|
14
|
+
//# sourceMappingURL=sanitize-rows.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sanitize-rows.js","sourceRoot":"","sources":["../../../../../libs/aml-utils/lib/structured-file-parser/sanitize-rows.ts"],"names":[],"mappings":";;AAAA,MAAM,gBAAgB,GAAG,CAAC,KAAe,EAAW,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAY,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;AAE5F,SAAS,YAAY,CAAC,UAAsB;IAC1C,MAAM,qBAAqB,GAAG,UAAU,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC;IAErE,MAAM,oBAAoB,GAAG,CAAC,GAAG,UAAU,CAAC,CAAC,OAAO,EAAE,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC;IAEnF,IAAI,qBAAqB,GAAG,CAAC,EAAE;QAC7B,OAAO,EAAE,CAAC;KACX;IAED,MAAM,aAAa,GAAG,CAAC,GAAG,UAAU,CAAC,CAAC,MAAM,CAAC,qBAAqB,EAAE,UAAU,CAAC,MAAM,GAAG,qBAAqB,GAAG,oBAAoB,CAAC,CAAC;IAEtI,OAAO,aAAa,CAAC;AACvB,CAAC;AAED,kBAAe,YAAY,CAAC","sourcesContent":["const sensicalRowCheck = (cells: string[]): boolean => cells.some((cell: string) => !!cell);\n\nfunction sanitizeRows(parsedRows: string[][]): string[][] {\n const firstSensicalRowIndex = parsedRows.findIndex(sensicalRowCheck);\n\n const lastSensicalRowIndex = [...parsedRows].reverse().findIndex(sensicalRowCheck);\n\n if (firstSensicalRowIndex < 0) {\n return [];\n }\n\n const sanitizedRows = [...parsedRows].splice(firstSensicalRowIndex, parsedRows.length - firstSensicalRowIndex - lastSensicalRowIndex);\n\n return sanitizedRows;\n}\n\nexport default sanitizeRows;\n"]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export
|
|
1
|
+
export type ProcessingEntry = {
|
|
2
2
|
isValid: boolean;
|
|
3
3
|
};
|
|
4
|
-
|
|
4
|
+
type Dependencies<T extends ProcessingEntry> = {
|
|
5
5
|
processRow: (cells: string[], headers: string[]) => T;
|
|
6
6
|
};
|
|
7
7
|
export declare const hasHeaderRow: (rows: string[][], requiredHeaderNames: string[]) => boolean;
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isHeaderRowValid = exports.hasHeaderRow = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
/* eslint-disable no-restricted-syntax */
|
|
6
|
+
const parse_row_1 = tslib_1.__importDefault(require("./parse-row"));
|
|
7
|
+
const errors_1 = require("./errors");
|
|
8
|
+
const sanitize_rows_1 = tslib_1.__importDefault(require("./sanitize-rows"));
|
|
9
|
+
function chunk(array, size) {
|
|
10
|
+
if (!array.length) {
|
|
11
|
+
return [];
|
|
12
|
+
}
|
|
13
|
+
const head = array.slice(0, size);
|
|
14
|
+
const tail = array.slice(size);
|
|
15
|
+
return [head, ...chunk(tail, size)];
|
|
16
|
+
}
|
|
17
|
+
function processChunk(parsedRows, dependencies) {
|
|
18
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
19
|
+
const { processRow, headers } = dependencies;
|
|
20
|
+
return new Promise((resolve, reject) => {
|
|
21
|
+
setTimeout(() => {
|
|
22
|
+
try {
|
|
23
|
+
const processedRows = parsedRows.map((row) => processRow(row, headers));
|
|
24
|
+
resolve(processedRows);
|
|
25
|
+
}
|
|
26
|
+
catch (ex) {
|
|
27
|
+
reject(ex);
|
|
28
|
+
}
|
|
29
|
+
}, 0);
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
// a row is said to contain headers if two valid header names are present
|
|
34
|
+
const hasHeaderRow = (rows, requiredHeaderNames) => {
|
|
35
|
+
const firstRow = rows[0];
|
|
36
|
+
if (!firstRow) {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
const foundIndex = firstRow.findIndex((value) => requiredHeaderNames.includes(value.toLowerCase()));
|
|
40
|
+
if (foundIndex < 0) {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
const containsSecondHeader = firstRow
|
|
44
|
+
.filter((_val, i) => i !== foundIndex)
|
|
45
|
+
.some((value) => requiredHeaderNames.includes(value.toLowerCase()));
|
|
46
|
+
return containsSecondHeader;
|
|
47
|
+
};
|
|
48
|
+
exports.hasHeaderRow = hasHeaderRow;
|
|
49
|
+
const isHeaderRowValid = (rows, requiredHeaderNames) => {
|
|
50
|
+
const firstRow = rows[0];
|
|
51
|
+
if (!firstRow) {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
return (requiredHeaderNames.every((header) => firstRow.map((value) => value.toLowerCase()).includes(header)) &&
|
|
55
|
+
requiredHeaderNames.length === firstRow.length);
|
|
56
|
+
};
|
|
57
|
+
exports.isHeaderRowValid = isHeaderRowValid;
|
|
58
|
+
function parseFile(fileContent, maxRows, requiredHeaderNames, dependencies) {
|
|
59
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
60
|
+
if (fileContent === 'invalidFileType') {
|
|
61
|
+
throw new errors_1.InvalidFileError();
|
|
62
|
+
}
|
|
63
|
+
const rows = fileContent.split('\n');
|
|
64
|
+
const parsedRows = rows.map(parse_row_1.default);
|
|
65
|
+
const sanitizedRows = (0, sanitize_rows_1.default)(parsedRows);
|
|
66
|
+
if (sanitizedRows.length > maxRows) {
|
|
67
|
+
throw new errors_1.TooManyRowsError();
|
|
68
|
+
}
|
|
69
|
+
if (sanitizedRows.length === 0) {
|
|
70
|
+
throw new errors_1.NoRowsError();
|
|
71
|
+
}
|
|
72
|
+
const containsHeaders = (0, exports.hasHeaderRow)(sanitizedRows, requiredHeaderNames);
|
|
73
|
+
if (containsHeaders && !(0, exports.isHeaderRowValid)(sanitizedRows, requiredHeaderNames)) {
|
|
74
|
+
throw new errors_1.InvalidHeadersError();
|
|
75
|
+
}
|
|
76
|
+
const firstSanitizedRow = sanitizedRows[0];
|
|
77
|
+
if (!firstSanitizedRow) {
|
|
78
|
+
throw new errors_1.NoRowsError();
|
|
79
|
+
}
|
|
80
|
+
const headers = containsHeaders ? firstSanitizedRow.map((value) => value.toLowerCase()) : requiredHeaderNames;
|
|
81
|
+
const dataRows = containsHeaders ? sanitizedRows.splice(1) : sanitizedRows;
|
|
82
|
+
if (dataRows.length === 0) {
|
|
83
|
+
throw new errors_1.NoRowsError();
|
|
84
|
+
}
|
|
85
|
+
const parsedRowChunks = chunk(dataRows, 30);
|
|
86
|
+
let results = [];
|
|
87
|
+
for (const currentRowChunk of parsedRowChunks) {
|
|
88
|
+
const chunkResult = yield processChunk(currentRowChunk, Object.assign(Object.assign({}, dependencies), { headers }));
|
|
89
|
+
results = results.concat(chunkResult);
|
|
90
|
+
}
|
|
91
|
+
return results;
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
exports.default = parseFile;
|
|
95
|
+
//# sourceMappingURL=structured-file-parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"structured-file-parser.js","sourceRoot":"","sources":["../../../../../libs/aml-utils/lib/structured-file-parser/structured-file-parser.ts"],"names":[],"mappings":";;;;AAAA,yCAAyC;AACzC,oEAAmC;AACnC,qCAAgG;AAChG,4EAA2C;AAe3C,SAAS,KAAK,CAAI,KAAU,EAAE,IAAY;IACxC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE;QACjB,OAAO,EAAE,CAAC;KACX;IACD,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;IAClC,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAE/B,OAAO,CAAC,IAAI,EAAE,GAAG,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;AACtC,CAAC;AAED,SAAe,YAAY,CACzB,UAAsB,EACtB,YAAwC;;QAExC,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,GAAG,YAAY,CAAC;QAC7C,OAAO,IAAI,OAAO,CAAC,CAAC,OAAyC,EAAE,MAA8B,EAAQ,EAAE;YACrG,UAAU,CAAC,GAAG,EAAE;gBACd,IAAI;oBACF,MAAM,aAAa,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,UAAU,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC;oBACxE,OAAO,CAAC,aAAa,CAAC,CAAC;iBACxB;gBAAC,OAAO,EAAE,EAAE;oBACX,MAAM,CAAC,EAAE,CAAC,CAAC;iBACZ;YACH,CAAC,EAAE,CAAC,CAAC,CAAC;QACR,CAAC,CAAC,CAAC;IACL,CAAC;CAAA;AAED,yEAAyE;AAClE,MAAM,YAAY,GAAG,CAAC,IAAgB,EAAE,mBAA6B,EAAW,EAAE;IACvF,MAAM,QAAQ,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IACzB,IAAI,CAAC,QAAQ,EAAE;QACb,OAAO,KAAK,CAAC;KACd;IACD,MAAM,UAAU,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,mBAAmB,CAAC,QAAQ,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;IACpG,IAAI,UAAU,GAAG,CAAC,EAAE;QAClB,OAAO,KAAK,CAAC;KACd;IACD,MAAM,oBAAoB,GAAG,QAAQ;SAClC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,UAAU,CAAC;SACrC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,mBAAmB,CAAC,QAAQ,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;IACtE,OAAO,oBAAoB,CAAC;AAC9B,CAAC,CAAC;AAbW,QAAA,YAAY,gBAavB;AAEK,MAAM,gBAAgB,GAAG,CAAC,IAAgB,EAAE,mBAA6B,EAAW,EAAE;IAC3F,MAAM,QAAQ,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IACzB,IAAI,CAAC,QAAQ,EAAE;QACb,OAAO,KAAK,CAAC;KACd;IACD,OAAO,CACL,mBAAmB,CAAC,KAAK,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACpG,mBAAmB,CAAC,MAAM,KAAK,QAAQ,CAAC,MAAM,CAC/C,CAAC;AACJ,CAAC,CAAC;AATW,QAAA,gBAAgB,oBAS3B;AAEF,SAAe,SAAS,CACtB,WAAmB,EACnB,OAAe,EACf,mBAA6B,EAC7B,YAA6B;;QAE7B,IAAI,WAAW,KAAK,iBAAiB,EAAE;YACrC,MAAM,IAAI,yBAAgB,EAAE,CAAC;SAC9B;QAED,MAAM,IAAI,GAAG,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACrC,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,mBAAQ,CAAC,CAAC;QAEtC,MAAM,aAAa,GAAG,IAAA,uBAAY,EAAC,UAAU,CAAC,CAAC;QAE/C,IAAI,aAAa,CAAC,MAAM,GAAG,OAAO,EAAE;YAClC,MAAM,IAAI,yBAAgB,EAAE,CAAC;SAC9B;QAED,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE;YAC9B,MAAM,IAAI,oBAAW,EAAE,CAAC;SACzB;QAED,MAAM,eAAe,GAAG,IAAA,oBAAY,EAAC,aAAa,EAAE,mBAAmB,CAAC,CAAC;QACzE,IAAI,eAAe,IAAI,CAAC,IAAA,wBAAgB,EAAC,aAAa,EAAE,mBAAmB,CAAC,EAAE;YAC5E,MAAM,IAAI,4BAAmB,EAAE,CAAC;SACjC;QAED,MAAM,iBAAiB,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC;QAE3C,IAAI,CAAC,iBAAiB,EAAE;YACtB,MAAM,IAAI,oBAAW,EAAE,CAAC;SACzB;QAED,MAAM,OAAO,GAAG,eAAe,CAAC,CAAC,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,CAAC,mBAAmB,CAAC;QAE9G,MAAM,QAAQ,GAAG,eAAe,CAAC,CAAC,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC;QAE3E,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE;YACzB,MAAM,IAAI,oBAAW,EAAE,CAAC;SACzB;QAED,MAAM,eAAe,GAAG,KAAK,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;QAC5C,IAAI,OAAO,GAAQ,EAAE,CAAC;QACtB,KAAK,MAAM,eAAe,IAAI,eAAe,EAAE;YAC7C,MAAM,WAAW,GAAG,MAAM,YAAY,CAAC,eAAe,kCACjD,YAAY,KACf,OAAO,IACP,CAAC;YACH,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;SACvC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;CAAA;AAED,kBAAe,SAAS,CAAC","sourcesContent":["/* eslint-disable no-restricted-syntax */\nimport parseRow from './parse-row';\nimport { InvalidFileError, TooManyRowsError, NoRowsError, InvalidHeadersError } from './errors';\nimport sanitizeRows from './sanitize-rows';\n\nexport type ProcessingEntry = {\n isValid: boolean;\n};\n\ntype Dependencies<T extends ProcessingEntry> = {\n processRow: (cells: string[], headers: string[]) => T;\n};\n\ntype CompleteDependencies<T extends ProcessingEntry, U extends string[]> = {\n processRow: (cells: string[], headers: U) => T;\n headers: U;\n};\n\nfunction chunk<T>(array: T[], size: number): T[][] {\n if (!array.length) {\n return [];\n }\n const head = array.slice(0, size);\n const tail = array.slice(size);\n\n return [head, ...chunk(tail, size)];\n}\n\nasync function processChunk<T extends ProcessingEntry, U extends string[]>(\n parsedRows: string[][],\n dependencies: CompleteDependencies<T, U>\n): Promise<T[]> {\n const { processRow, headers } = dependencies;\n return new Promise((resolve: (value: T[] | undefined) => void, reject: (error: Error) => void): void => {\n setTimeout(() => {\n try {\n const processedRows = parsedRows.map((row) => processRow(row, headers));\n resolve(processedRows);\n } catch (ex) {\n reject(ex);\n }\n }, 0);\n });\n}\n\n// a row is said to contain headers if two valid header names are present\nexport const hasHeaderRow = (rows: string[][], requiredHeaderNames: string[]): boolean => {\n const firstRow = rows[0];\n if (!firstRow) {\n return false;\n }\n const foundIndex = firstRow.findIndex((value) => requiredHeaderNames.includes(value.toLowerCase()));\n if (foundIndex < 0) {\n return false;\n }\n const containsSecondHeader = firstRow\n .filter((_val, i) => i !== foundIndex)\n .some((value) => requiredHeaderNames.includes(value.toLowerCase()));\n return containsSecondHeader;\n};\n\nexport const isHeaderRowValid = (rows: string[][], requiredHeaderNames: string[]): boolean => {\n const firstRow = rows[0];\n if (!firstRow) {\n return false;\n }\n return (\n requiredHeaderNames.every((header) => firstRow.map((value) => value.toLowerCase()).includes(header)) &&\n requiredHeaderNames.length === firstRow.length\n );\n};\n\nasync function parseFile<T extends ProcessingEntry>(\n fileContent: string,\n maxRows: number,\n requiredHeaderNames: string[],\n dependencies: Dependencies<T>\n): Promise<T[]> {\n if (fileContent === 'invalidFileType') {\n throw new InvalidFileError();\n }\n\n const rows = fileContent.split('\\n');\n const parsedRows = rows.map(parseRow);\n\n const sanitizedRows = sanitizeRows(parsedRows);\n\n if (sanitizedRows.length > maxRows) {\n throw new TooManyRowsError();\n }\n\n if (sanitizedRows.length === 0) {\n throw new NoRowsError();\n }\n\n const containsHeaders = hasHeaderRow(sanitizedRows, requiredHeaderNames);\n if (containsHeaders && !isHeaderRowValid(sanitizedRows, requiredHeaderNames)) {\n throw new InvalidHeadersError();\n }\n\n const firstSanitizedRow = sanitizedRows[0];\n\n if (!firstSanitizedRow) {\n throw new NoRowsError();\n }\n\n const headers = containsHeaders ? firstSanitizedRow.map((value) => value.toLowerCase()) : requiredHeaderNames;\n\n const dataRows = containsHeaders ? sanitizedRows.splice(1) : sanitizedRows;\n\n if (dataRows.length === 0) {\n throw new NoRowsError();\n }\n\n const parsedRowChunks = chunk(dataRows, 30);\n let results: T[] = [];\n for (const currentRowChunk of parsedRowChunks) {\n const chunkResult = await processChunk(currentRowChunk, {\n ...dependencies,\n headers,\n });\n results = results.concat(chunkResult);\n }\n\n return results;\n}\n\nexport default parseFile;\n"]}
|