@ellipticltd/aml-utils 0.16.26 → 0.16.27
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/.circleci/config.yml +87 -0
- package/.claude/settings.local.json +7 -0
- package/.eslintrc +45 -0
- package/.huskyrc +5 -0
- package/.mocharc.json +3 -0
- package/.nvmrc +1 -0
- package/.nycrc.json +11 -0
- package/.releaserc.json +18 -0
- package/.snyk +12 -0
- package/README.md +43 -11
- package/codecov.yml +29 -0
- package/commitlint.config.js +1 -0
- package/dist/errors/errors.js +42 -0
- package/dist/errors/errors.spec.d.ts +1 -0
- package/dist/errors/errors.spec.js +23 -0
- package/dist/file-parser/__tests/file-parser.spec.d.ts +1 -0
- package/dist/file-parser/__tests/file-parser.spec.js +109 -0
- package/dist/file-parser/__tests/parse-row.spec.d.ts +1 -0
- package/dist/file-parser/__tests/parse-row.spec.js +29 -0
- package/dist/file-parser/__tests/sanitize-rows.spec.d.ts +1 -0
- package/dist/file-parser/__tests/sanitize-rows.spec.js +78 -0
- package/{lib → dist}/file-parser/errors.js +1 -1
- package/{lib → dist}/file-parser/file-parser.d.ts +4 -2
- package/dist/file-parser/file-parser.js +55 -0
- package/{lib → dist}/file-parser/parse-row.js +1 -2
- package/{lib/file-parser/sanitizeRows.d.ts → dist/file-parser/sanitzeRows.d.ts} +1 -3
- package/dist/file-parser/sanitzeRows.js +18 -0
- package/dist/formatting/formatting.js +17 -0
- package/dist/formatting/formatting.spec.d.ts +1 -0
- package/dist/formatting/formatting.spec.js +37 -0
- package/{lib → dist}/index.d.ts +1 -1
- package/dist/index.js +22 -0
- package/dist/middleware/middleware.js +22 -0
- package/dist/orm-helpers/ormHelpers.js +17 -0
- package/dist/orm-helpers/ormHelpers.spec.d.ts +1 -0
- package/dist/orm-helpers/ormHelpers.spec.js +38 -0
- package/{lib → dist}/structured-file-parser/errors.js +0 -1
- package/{lib → dist}/structured-file-parser/parse-row.js +1 -2
- package/{lib → dist}/structured-file-parser/sanitize-rows.js +4 -3
- package/{lib → dist}/structured-file-parser/structured-file-parser.d.ts +2 -2
- package/dist/structured-file-parser/structured-file-parser.js +98 -0
- package/{lib → dist}/types/types.d.ts +6 -0
- package/dist/types/types.js +203 -0
- package/{lib → dist}/validations/validations.d.ts +110 -161
- package/dist/validations/validations.js +470 -0
- package/dist/validations/validations.spec.d.ts +1 -0
- package/dist/validations/validations.spec.js +463 -0
- package/lib/errors/errors.js +30 -19
- package/lib/errors/errors.spec.js +37 -0
- package/lib/file-parser/__tests/file-parser.spec.js +107 -0
- package/lib/file-parser/__tests/parse-row.spec.js +35 -0
- package/lib/file-parser/__tests/sanitize-rows.spec.js +88 -0
- package/lib/file-parser/errors.ts +7 -0
- package/lib/file-parser/file-parser.ts +84 -0
- package/lib/file-parser/parse-row.ts +52 -0
- package/lib/file-parser/sanitzeRows.ts +32 -0
- package/lib/formatting/formatting.js +12 -11
- package/lib/formatting/formatting.spec.js +45 -0
- package/lib/index.ts +19 -0
- package/lib/middleware/middleware.js +17 -14
- package/lib/orm-helpers/ormHelpers.js +13 -12
- package/lib/orm-helpers/ormHelpers.spec.js +41 -0
- package/lib/structured-file-parser/errors.ts +25 -0
- package/lib/structured-file-parser/parse-row.ts +52 -0
- package/lib/structured-file-parser/sanitize-rows.ts +24 -0
- package/lib/structured-file-parser/structured-file-parser.ts +155 -0
- package/lib/types/types.js +203 -191
- package/lib/validations/validations.js +461 -669
- package/lib/validations/validations.spec.js +603 -0
- package/package.json +61 -8
- package/tsconfig.json +26 -0
- package/lib/errors/errors.js.map +0 -1
- package/lib/file-parser/errors.js.map +0 -1
- package/lib/file-parser/file-parser.js +0 -59
- package/lib/file-parser/file-parser.js.map +0 -1
- package/lib/file-parser/parse-row.js.map +0 -1
- package/lib/file-parser/sanitizeRows.js +0 -15
- package/lib/file-parser/sanitizeRows.js.map +0 -1
- package/lib/formatting/formatting.js.map +0 -1
- package/lib/index.js +0 -21
- package/lib/index.js.map +0 -1
- package/lib/middleware/middleware.js.map +0 -1
- package/lib/orm-helpers/ormHelpers.js.map +0 -1
- package/lib/structured-file-parser/errors.js.map +0 -1
- package/lib/structured-file-parser/parse-row.js.map +0 -1
- package/lib/structured-file-parser/sanitize-rows.js.map +0 -1
- package/lib/structured-file-parser/structured-file-parser.js +0 -95
- package/lib/structured-file-parser/structured-file-parser.js.map +0 -1
- package/lib/types/types.js.map +0 -1
- package/lib/validations/validations.js.map +0 -1
- /package/{lib → dist}/errors/errors.d.ts +0 -0
- /package/{lib → dist}/file-parser/errors.d.ts +0 -0
- /package/{lib → dist}/file-parser/parse-row.d.ts +0 -0
- /package/{lib → dist}/formatting/formatting.d.ts +0 -0
- /package/{lib → dist}/middleware/middleware.d.ts +0 -0
- /package/{lib → dist}/orm-helpers/ormHelpers.d.ts +0 -0
- /package/{lib → dist}/structured-file-parser/errors.d.ts +0 -0
- /package/{lib → dist}/structured-file-parser/parse-row.d.ts +0 -0
- /package/{lib → dist}/structured-file-parser/sanitize-rows.d.ts +0 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { pipe } from 'lodash/fp';
|
|
2
|
+
|
|
3
|
+
const parseRow = (row: string): string[] => {
|
|
4
|
+
const trySplitByTab = (line: string | string[]): string | string[] => {
|
|
5
|
+
if (typeof line === 'string' && line.match('\t')) {
|
|
6
|
+
return line.split('\t');
|
|
7
|
+
}
|
|
8
|
+
return line;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
const trySplitByComa = (line: string | string[]): string | string[] => {
|
|
12
|
+
if (typeof line === 'string' && line.match(',')) {
|
|
13
|
+
return line.split(',');
|
|
14
|
+
}
|
|
15
|
+
return line;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const trySplitByMultipleSpaces = (line: string | string[]): string | string[] => {
|
|
19
|
+
if (typeof line === 'string' && line.match(/ {3,}/)) {
|
|
20
|
+
return line.split(/ {3,}/);
|
|
21
|
+
}
|
|
22
|
+
return line;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const trySplitBySpace = (line: string | string[]): string | string[] => {
|
|
26
|
+
if (typeof line === 'string' && line.match(' ')) {
|
|
27
|
+
return line.split(' ');
|
|
28
|
+
}
|
|
29
|
+
return line;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const trySplitByNothing = (line: string | string[]): string[] => {
|
|
33
|
+
if (typeof line === 'string') {
|
|
34
|
+
return [line];
|
|
35
|
+
}
|
|
36
|
+
return line;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const splitRow = pipe(
|
|
40
|
+
trySplitByTab,
|
|
41
|
+
trySplitByComa,
|
|
42
|
+
trySplitByMultipleSpaces,
|
|
43
|
+
trySplitBySpace,
|
|
44
|
+
trySplitByNothing,
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
const cells = splitRow(row);
|
|
48
|
+
|
|
49
|
+
return cells.map((c: string) => c.trim());
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export default parseRow;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
const sensicalRowCheck = (cells: string[]): boolean => (
|
|
2
|
+
cells.some((cell: string) => !!cell)
|
|
3
|
+
);
|
|
4
|
+
|
|
5
|
+
function sanitizeRows(parsedRows: string[][]): string[][] {
|
|
6
|
+
const firstSensicalRowIndex = parsedRows.findIndex(sensicalRowCheck);
|
|
7
|
+
|
|
8
|
+
const lastSensicalRowIndex = [...parsedRows]
|
|
9
|
+
.reverse()
|
|
10
|
+
.findIndex(sensicalRowCheck);
|
|
11
|
+
|
|
12
|
+
if (firstSensicalRowIndex < 0) {
|
|
13
|
+
return [];
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const sanitizedRows = [...parsedRows].splice(
|
|
17
|
+
firstSensicalRowIndex,
|
|
18
|
+
parsedRows.length - firstSensicalRowIndex - lastSensicalRowIndex,
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
return sanitizedRows;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export default sanitizeRows;
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/* eslint-disable no-await-in-loop */
|
|
2
|
+
/* eslint-disable no-restricted-syntax */
|
|
3
|
+
import parseRow from './parse-row';
|
|
4
|
+
import {
|
|
5
|
+
InvalidFileError,
|
|
6
|
+
TooManyRowsError,
|
|
7
|
+
NoRowsError,
|
|
8
|
+
InvalidHeadersError,
|
|
9
|
+
} from './errors';
|
|
10
|
+
import sanitizeRows from './sanitize-rows';
|
|
11
|
+
|
|
12
|
+
export type ProcessingEntry = {
|
|
13
|
+
isValid: boolean;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
type Dependencies<T extends ProcessingEntry> = {
|
|
17
|
+
processRow: (cells: string[], headers: string[]) => T;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
type CompleteDependencies<T extends ProcessingEntry, U extends string[]> = {
|
|
21
|
+
processRow: (cells: string[], headers: U) => T;
|
|
22
|
+
headers: U;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
function chunk<T>(array: T[], size: number): T[][] {
|
|
26
|
+
if (!array.length) {
|
|
27
|
+
return [];
|
|
28
|
+
}
|
|
29
|
+
const head = array.slice(0, size);
|
|
30
|
+
const tail = array.slice(size);
|
|
31
|
+
|
|
32
|
+
return [head, ...chunk(tail, size)];
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
async function processChunk<T extends ProcessingEntry, U extends string[]>(
|
|
36
|
+
parsedRows: string[][],
|
|
37
|
+
dependencies: CompleteDependencies<T, U>,
|
|
38
|
+
): Promise<T[]> {
|
|
39
|
+
const { processRow, headers } = dependencies;
|
|
40
|
+
// @ts-ignore
|
|
41
|
+
return new Promise(
|
|
42
|
+
(
|
|
43
|
+
resolve: (value: T[] | undefined) => void,
|
|
44
|
+
reject: (error: Error) => void,
|
|
45
|
+
): void => {
|
|
46
|
+
setTimeout(() => {
|
|
47
|
+
try {
|
|
48
|
+
const processedRows = parsedRows.map((row) => processRow(row, headers));
|
|
49
|
+
resolve(processedRows);
|
|
50
|
+
} catch (ex) {
|
|
51
|
+
// @ts-ignore
|
|
52
|
+
reject(ex);
|
|
53
|
+
}
|
|
54
|
+
}, 0);
|
|
55
|
+
},
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// a row is said to contain headers if two valid header names are present
|
|
60
|
+
export const hasHeaderRow = (
|
|
61
|
+
rows: string[][],
|
|
62
|
+
requiredHeaderNames: string[],
|
|
63
|
+
): boolean => {
|
|
64
|
+
const firstRow = rows[0];
|
|
65
|
+
if (!firstRow) {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
const foundIndex = firstRow.findIndex(
|
|
69
|
+
(value) => requiredHeaderNames.includes(value.toLowerCase()),
|
|
70
|
+
);
|
|
71
|
+
if (foundIndex < 0) {
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
const containsSecondHeader = firstRow
|
|
75
|
+
.filter((_val, i) => i !== foundIndex)
|
|
76
|
+
.some((value) => requiredHeaderNames.includes(value.toLowerCase()));
|
|
77
|
+
return containsSecondHeader;
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
export const isHeaderRowValid = (
|
|
81
|
+
rows: string[][],
|
|
82
|
+
requiredHeaderNames: string[],
|
|
83
|
+
): boolean => {
|
|
84
|
+
const firstRow = rows[0];
|
|
85
|
+
if (!firstRow) {
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
return (
|
|
89
|
+
requiredHeaderNames.every(
|
|
90
|
+
(header) => firstRow.map((value) => value.toLowerCase()).includes(header),
|
|
91
|
+
) && requiredHeaderNames.length === firstRow.length
|
|
92
|
+
);
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
async function parseFile<T extends ProcessingEntry>(
|
|
96
|
+
fileContent: string,
|
|
97
|
+
maxRows: number,
|
|
98
|
+
requiredHeaderNames: string[],
|
|
99
|
+
dependencies: Dependencies<T>,
|
|
100
|
+
): Promise<T[]> {
|
|
101
|
+
if (fileContent === 'invalidFileType') {
|
|
102
|
+
throw new InvalidFileError();
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const rows = fileContent.split('\n');
|
|
106
|
+
const parsedRows = rows.map(parseRow);
|
|
107
|
+
|
|
108
|
+
const sanitizedRows = sanitizeRows(parsedRows);
|
|
109
|
+
|
|
110
|
+
if (sanitizedRows.length > maxRows) {
|
|
111
|
+
throw new TooManyRowsError();
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (sanitizedRows.length === 0) {
|
|
115
|
+
throw new NoRowsError();
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const containsHeaders = hasHeaderRow(sanitizedRows, requiredHeaderNames);
|
|
119
|
+
if (
|
|
120
|
+
containsHeaders
|
|
121
|
+
&& !isHeaderRowValid(sanitizedRows, requiredHeaderNames)
|
|
122
|
+
) {
|
|
123
|
+
throw new InvalidHeadersError();
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const firstSanitizedRow = sanitizedRows[0];
|
|
127
|
+
|
|
128
|
+
if (!firstSanitizedRow) {
|
|
129
|
+
throw new NoRowsError();
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const headers = containsHeaders
|
|
133
|
+
? firstSanitizedRow.map((value) => value.toLowerCase())
|
|
134
|
+
: requiredHeaderNames;
|
|
135
|
+
|
|
136
|
+
const dataRows = containsHeaders ? sanitizedRows.splice(1) : sanitizedRows;
|
|
137
|
+
|
|
138
|
+
if (dataRows.length === 0) {
|
|
139
|
+
throw new NoRowsError();
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const parsedRowChunks = chunk(dataRows, 30);
|
|
143
|
+
let results: T[] = [];
|
|
144
|
+
for (const currentRowChunk of parsedRowChunks) {
|
|
145
|
+
const chunkResult = await processChunk(currentRowChunk, {
|
|
146
|
+
...dependencies,
|
|
147
|
+
headers,
|
|
148
|
+
});
|
|
149
|
+
results = results.concat(chunkResult);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
return results;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
export default parseFile;
|
package/lib/types/types.js
CHANGED
|
@@ -1,201 +1,213 @@
|
|
|
1
1
|
const TC = require('type-check');
|
|
2
|
+
|
|
2
3
|
const _ = require('lodash');
|
|
4
|
+
|
|
3
5
|
const E = require('../errors/errors');
|
|
6
|
+
|
|
4
7
|
const V = require('../validations/validations');
|
|
8
|
+
|
|
5
9
|
const customTypes = {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
10
|
+
Integer: {
|
|
11
|
+
typeOf: 'Number',
|
|
12
|
+
validate(x) {
|
|
13
|
+
return x % 1 === 0;
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
IntString: {
|
|
17
|
+
typeOf: 'String',
|
|
18
|
+
validate: V.isInt,
|
|
19
|
+
},
|
|
20
|
+
BoolString: {
|
|
21
|
+
typeOf: 'String',
|
|
22
|
+
validate: V.isBoolean,
|
|
23
|
+
},
|
|
24
|
+
Hex32: {
|
|
25
|
+
typeOf: 'String',
|
|
26
|
+
validate(x) {
|
|
27
|
+
return V.isHexadecimal(x) && x.length === 32;
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
Email: {
|
|
31
|
+
typeOf: 'String',
|
|
32
|
+
validate: V.isEmail,
|
|
33
|
+
},
|
|
34
|
+
UUID: {
|
|
35
|
+
typeOf: 'String',
|
|
36
|
+
validate: V.isUUID,
|
|
37
|
+
},
|
|
38
|
+
UUIDv4: {
|
|
39
|
+
typeOf: 'String',
|
|
40
|
+
validate(x) {
|
|
41
|
+
return V.isUUID(x, 4);
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
JSON: {
|
|
45
|
+
typeOf: 'String',
|
|
46
|
+
validate: V.isJSON,
|
|
47
|
+
},
|
|
48
|
+
Url: {
|
|
49
|
+
typeOf: 'String',
|
|
50
|
+
validate: V.isURL,
|
|
51
|
+
},
|
|
52
|
+
DateString: {
|
|
53
|
+
typeOf: 'String',
|
|
54
|
+
validate: V.isDate,
|
|
55
|
+
},
|
|
56
|
+
NonEmptyArray: {
|
|
57
|
+
typeOf: 'Array',
|
|
58
|
+
validate: V.nonEmpty,
|
|
59
|
+
},
|
|
60
|
+
NonNullString: {
|
|
61
|
+
typeOf: 'String',
|
|
62
|
+
validate: V.nonEmpty,
|
|
63
|
+
},
|
|
64
|
+
CustomerReference: {
|
|
65
|
+
typeOf: 'String',
|
|
66
|
+
validate: V.isCustomerReference,
|
|
67
|
+
},
|
|
68
|
+
CustomerLabelName: {
|
|
69
|
+
typeOf: 'String',
|
|
70
|
+
validate: V.isCustomerLabelName,
|
|
71
|
+
},
|
|
72
|
+
BitcoinAddress: {
|
|
73
|
+
typeOf: 'String',
|
|
74
|
+
validate: V.bitcoin.isAddress,
|
|
75
|
+
},
|
|
76
|
+
EthereumAddress: {
|
|
77
|
+
typeOf: 'String',
|
|
78
|
+
validate: V.ethereum.isAddress,
|
|
79
|
+
},
|
|
80
|
+
EthereumTx: {
|
|
81
|
+
typeOf: 'String',
|
|
82
|
+
validate: V.ethereum.isTxHash,
|
|
83
|
+
},
|
|
84
|
+
EthereumBlockHash: {
|
|
85
|
+
typeOf: 'String',
|
|
86
|
+
validate: V.ethereum.isBlockHash,
|
|
87
|
+
},
|
|
88
|
+
EthereumWeiAmount: {
|
|
89
|
+
typeOf: 'String',
|
|
90
|
+
validate: V.ethereum.isValidWeiAmount,
|
|
91
|
+
},
|
|
92
|
+
EthereumAddressCode: {
|
|
93
|
+
typeOf: 'String',
|
|
94
|
+
validate: V.ethereum.isAddressCode,
|
|
95
|
+
},
|
|
96
|
+
MineId: {
|
|
97
|
+
typeOf: 'String',
|
|
98
|
+
validate(x) {
|
|
99
|
+
return x === 'mine';
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
BitcoinTxHash: {
|
|
103
|
+
typeOf: 'String',
|
|
104
|
+
validate: V.bitcoin.isTxHash,
|
|
105
|
+
},
|
|
106
|
+
BitcoinAddressArray: {
|
|
107
|
+
typeOf: 'Array',
|
|
108
|
+
validate(as) {
|
|
109
|
+
return _.every(as, V.bitcoin.isAddress);
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
BitcoinTxHashArray: {
|
|
113
|
+
typeOf: 'Array',
|
|
114
|
+
validate(as) {
|
|
115
|
+
return _.every(as, V.bitcoin.isTxHash);
|
|
116
|
+
},
|
|
117
|
+
},
|
|
118
|
+
BitcoinTxHex: {
|
|
119
|
+
typeOf: 'String',
|
|
120
|
+
validate: V.bitcoin.isTxHex,
|
|
121
|
+
},
|
|
122
|
+
BitcoinScriptHex: {
|
|
123
|
+
typeOf: 'String',
|
|
124
|
+
validate: V.bitcoin.isScriptHex,
|
|
125
|
+
},
|
|
126
|
+
BitcoinHDPath: {
|
|
127
|
+
typeOf: 'String',
|
|
128
|
+
validate: V.bitcoin.isHDPath,
|
|
129
|
+
},
|
|
130
|
+
BitcoinPublicKey: {
|
|
131
|
+
typeOf: 'String',
|
|
132
|
+
validate: V.bitcoin.isPublicKey,
|
|
133
|
+
},
|
|
134
|
+
BitcoinXpub: {
|
|
135
|
+
typeOf: 'String',
|
|
136
|
+
validate: V.bitcoin.isHDPublicKey,
|
|
137
|
+
},
|
|
138
|
+
BitcoinTxSignature: {
|
|
139
|
+
typeOf: 'String',
|
|
140
|
+
validate: V.bitcoin.isTxSignature,
|
|
141
|
+
},
|
|
142
|
+
BitcoinBlockHeight: {
|
|
143
|
+
typeOf: 'Number',
|
|
144
|
+
validate: V.bitcoin.isBlockHeight,
|
|
145
|
+
},
|
|
142
146
|
};
|
|
147
|
+
|
|
143
148
|
// add support for nullable properties
|
|
144
|
-
const withNullable = Object.keys(customTypes).reduce((acc,
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
149
|
+
const withNullable = Object.keys(customTypes).reduce((acc, _type) => {
|
|
150
|
+
acc[_type] = customTypes[_type];
|
|
151
|
+
const { typeOf, validate } = customTypes[_type];
|
|
152
|
+
|
|
153
|
+
// for every type, add Nullable+type. A nullable string can also be empty
|
|
154
|
+
acc[`Nullable${_type}`] = Object.assign({}, customTypes[_type], {
|
|
155
|
+
validate: (x) => x == null || (typeOf === 'String' && x === '') || validate(x),
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
return acc;
|
|
150
159
|
}, {});
|
|
160
|
+
|
|
151
161
|
module.exports = {
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
162
|
+
parseType(str) {
|
|
163
|
+
return TC.parseType(str);
|
|
164
|
+
},
|
|
165
|
+
parsedTypeCheck(type, obj) {
|
|
166
|
+
return TC.parsedTypeCheck(type, obj, this.opts);
|
|
167
|
+
},
|
|
168
|
+
typeCheck(type, obj) {
|
|
169
|
+
return TC.typeCheck(type, obj, this.opts);
|
|
170
|
+
},
|
|
171
|
+
opts: {
|
|
172
|
+
customTypes: withNullable,
|
|
173
|
+
},
|
|
174
|
+
ensureType(type, obj, msg) {
|
|
175
|
+
return V.ensure(this.typeCheck(type, obj), msg);
|
|
176
|
+
},
|
|
177
|
+
checkArg(obj, prop, type, msg) {
|
|
178
|
+
let message;
|
|
179
|
+
if (msg == null) {
|
|
180
|
+
message = `Invalid ${prop}`;
|
|
181
|
+
} else {
|
|
182
|
+
message = msg;
|
|
183
|
+
}
|
|
184
|
+
this.ensureType(type, obj[prop], message);
|
|
185
|
+
return obj[prop];
|
|
186
|
+
},
|
|
187
|
+
checkArgs(input, types) {
|
|
188
|
+
const inputKeys = {};
|
|
189
|
+
const [typ] = types;
|
|
190
|
+
const fields = typ.of;
|
|
191
|
+
let numInputKeys = 0;
|
|
192
|
+
let numKeys;
|
|
193
|
+
|
|
194
|
+
Object.keys(input).forEach((k) => {
|
|
195
|
+
inputKeys[k] = true;
|
|
196
|
+
numInputKeys += 1;
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
numKeys = 0;
|
|
200
|
+
|
|
201
|
+
Object.keys(fields).forEach((key) => {
|
|
202
|
+
const objTypes = fields[key];
|
|
203
|
+
V.ensure(this.parsedTypeCheck(objTypes, input[key]), `Invalid ${key}`);
|
|
204
|
+
if (inputKeys[key]) {
|
|
205
|
+
numKeys += 1;
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
if (!(typ.subset || numInputKeys === numKeys)) {
|
|
210
|
+
throw new E.BadRequest('invalid extra arguments are present');
|
|
211
|
+
}
|
|
212
|
+
},
|
|
200
213
|
};
|
|
201
|
-
//# sourceMappingURL=types.js.map
|