@xcrap/transformer 0.0.1
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/LICENSE +21 -0
- package/README.md +133 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.js +43 -0
- package/dist/transformer.d.ts +6 -0
- package/dist/transformer.js +15 -0
- package/dist/transformers/array.d.ts +14 -0
- package/dist/transformers/array.js +50 -0
- package/dist/transformers/date.d.ts +9 -0
- package/dist/transformers/date.js +57 -0
- package/dist/transformers/index.d.ts +4 -0
- package/dist/transformers/index.js +20 -0
- package/dist/transformers/number.d.ts +27 -0
- package/dist/transformers/number.js +55 -0
- package/dist/transformers/string.d.ts +16 -0
- package/dist/transformers/string.js +57 -0
- package/dist/transforming-model.d.ts +24 -0
- package/dist/transforming-model.js +66 -0
- package/dist/validators/any.d.ts +12 -0
- package/dist/validators/any.js +16 -0
- package/dist/validators/array.d.ts +18 -0
- package/dist/validators/array.js +47 -0
- package/dist/validators/date.d.ts +17 -0
- package/dist/validators/date.js +75 -0
- package/dist/validators/index.d.ts +5 -0
- package/dist/validators/index.js +21 -0
- package/dist/validators/number.d.ts +21 -0
- package/dist/validators/number.js +42 -0
- package/dist/validators/string.d.ts +17 -0
- package/dist/validators/string.js +30 -0
- package/package.json +44 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Marcuth
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
# 🕷️ Xcrap Transformer
|
|
2
|
+
|
|
3
|
+
**Xcrap Transformer** is the data transformation package for data extracted from the **Xcrap** Web Scraping framework.
|
|
4
|
+
|
|
5
|
+
## 📦 Installation
|
|
6
|
+
|
|
7
|
+
Installation is straightforward. Use your preferred dependency manager. Here's an example of how you'd install it using NPM:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm i @xcrap/transformer
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## 🚀 Usage
|
|
14
|
+
|
|
15
|
+
Usage is similar to `@xcrap/parser`; we use declarative models to transform data. See an example below:
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
import {
|
|
19
|
+
StringTransformer,
|
|
20
|
+
StringValidator,
|
|
21
|
+
AnyValidator,
|
|
22
|
+
Transformer,
|
|
23
|
+
TransformingModel,
|
|
24
|
+
transform
|
|
25
|
+
} from "./src"
|
|
26
|
+
|
|
27
|
+
const rawData = [
|
|
28
|
+
{
|
|
29
|
+
id: "1",
|
|
30
|
+
name_: "Marcuth ",
|
|
31
|
+
avatar_url: "/assets/users/1/avatar.png"
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
id: "2,0",
|
|
35
|
+
name_: "JavaScript User ",
|
|
36
|
+
avatar_url: "/assets/users/2/avatar.png"
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
id: 3,
|
|
40
|
+
name_: "Pedro",
|
|
41
|
+
avatar_url: "/assets/users/3/avatar.png"
|
|
42
|
+
},
|
|
43
|
+
]
|
|
44
|
+
|
|
45
|
+
const transformingModel = new TransformingModel({
|
|
46
|
+
id: [ // return key
|
|
47
|
+
transform({
|
|
48
|
+
key: "id", // at index 0 always raw data key
|
|
49
|
+
condition: (value) => AnyValidator.isString(value) && value.includes(","),
|
|
50
|
+
transformer: StringTransformer.replace(",", ".")
|
|
51
|
+
}),
|
|
52
|
+
transform({
|
|
53
|
+
key: "id", // transformed data key
|
|
54
|
+
condition: StringValidator.isNumeric,
|
|
55
|
+
transformer: StringTransformer.toNumber
|
|
56
|
+
})
|
|
57
|
+
],
|
|
58
|
+
name: [ // return key
|
|
59
|
+
transform({
|
|
60
|
+
key: "name_", // at index 0 always raw data key
|
|
61
|
+
transformer: StringTransformer.collapseWhitespace
|
|
62
|
+
})
|
|
63
|
+
],
|
|
64
|
+
avatarUrl: [ // return key
|
|
65
|
+
transform({
|
|
66
|
+
key: "avatar_url", // at index 0 always raw data key
|
|
67
|
+
transformer: StringTransformer.resolveUrl("https://baseurl.com/")
|
|
68
|
+
})
|
|
69
|
+
]
|
|
70
|
+
}).after({
|
|
71
|
+
append: {
|
|
72
|
+
role: "USER"
|
|
73
|
+
},
|
|
74
|
+
delete: [
|
|
75
|
+
"name_",
|
|
76
|
+
"avatar_url"
|
|
77
|
+
]
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
const transformer = new Transformer(rawData)
|
|
81
|
+
|
|
82
|
+
;(async () => {
|
|
83
|
+
const transformedData = await transformer.transform(transformingModel)
|
|
84
|
+
console.log(transformedData)
|
|
85
|
+
})();
|
|
86
|
+
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
**Expected output**:
|
|
90
|
+
|
|
91
|
+
```js
|
|
92
|
+
[
|
|
93
|
+
{
|
|
94
|
+
id: 1,
|
|
95
|
+
name: 'Marcuth',
|
|
96
|
+
avatarUrl: 'https://baseurl.com/assets/users/1/avatar.png',
|
|
97
|
+
role: 'USER'
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
id: 2,
|
|
101
|
+
name: 'JavaScript User',
|
|
102
|
+
avatarUrl: 'https://baseurl.com/assets/users/2/avatar.png',
|
|
103
|
+
role: 'USER'
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
id: 3,
|
|
107
|
+
name: 'Pedro',
|
|
108
|
+
avatarUrl: 'https://baseurl.com/assets/users/3/avatar.png',
|
|
109
|
+
role: 'USER'
|
|
110
|
+
}
|
|
111
|
+
]
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## 🧪 Tests
|
|
115
|
+
|
|
116
|
+
Automated tests are located in `__tests__`. To run them:
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
npm run test
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## 🤝 Contributing
|
|
123
|
+
|
|
124
|
+
- Want to contribute? Follow these steps:
|
|
125
|
+
- Fork the repository.
|
|
126
|
+
- Create a new branch (git checkout -b feature-new).
|
|
127
|
+
- Commit your changes (git commit -m 'Add new feature').
|
|
128
|
+
- Push to the branch (git push origin feature-new).
|
|
129
|
+
- Open a Pull Request.
|
|
130
|
+
|
|
131
|
+
## 📝 License
|
|
132
|
+
|
|
133
|
+
This project is licensed under the MIT License.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export * from "./transforming-model";
|
|
2
|
+
export * from "./transformer";
|
|
3
|
+
export * from "./transformers";
|
|
4
|
+
export * from "./validators";
|
|
5
|
+
export type SkipFunction = () => void;
|
|
6
|
+
export type TransformOptions<T, R> = {
|
|
7
|
+
key: string;
|
|
8
|
+
transformer: (value: T) => R | Promise<R>;
|
|
9
|
+
condition?: (value: T) => boolean | Promise<boolean>;
|
|
10
|
+
};
|
|
11
|
+
export declare function transform<T extends any, R extends any>({ key, transformer, condition }: TransformOptions<T, R>): (data: Record<string, any>, skip: SkipFunction) => Promise<void | R>;
|
|
12
|
+
export type GetOptions<T> = {
|
|
13
|
+
key: string;
|
|
14
|
+
condition?: (value: T) => boolean | Promise<boolean>;
|
|
15
|
+
};
|
|
16
|
+
export declare function get<T extends any>({ key, condition }: GetOptions<T>): (data: Record<string, any>, skip: SkipFunction) => Promise<void | T>;
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.transform = transform;
|
|
18
|
+
exports.get = get;
|
|
19
|
+
__exportStar(require("./transforming-model"), exports);
|
|
20
|
+
__exportStar(require("./transformer"), exports);
|
|
21
|
+
__exportStar(require("./transformers"), exports);
|
|
22
|
+
__exportStar(require("./validators"), exports);
|
|
23
|
+
function transform({ key, transformer, condition }) {
|
|
24
|
+
return async (data, skip) => {
|
|
25
|
+
const value = data[key];
|
|
26
|
+
const isValid = condition ? await condition(value) : true;
|
|
27
|
+
if (!isValid) {
|
|
28
|
+
return skip();
|
|
29
|
+
}
|
|
30
|
+
const transformedValue = await transformer(value);
|
|
31
|
+
return transformedValue;
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
function get({ key, condition }) {
|
|
35
|
+
return async (data, skip) => {
|
|
36
|
+
const value = data[key];
|
|
37
|
+
const isValid = condition ? await condition(value) : true;
|
|
38
|
+
if (!isValid) {
|
|
39
|
+
return skip();
|
|
40
|
+
}
|
|
41
|
+
return value;
|
|
42
|
+
};
|
|
43
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { TransformingModel } from "./transforming-model";
|
|
2
|
+
export declare class Transformer {
|
|
3
|
+
readonly data: Record<string, any> | Record<string, any>[];
|
|
4
|
+
constructor(data: Record<string, any> | Record<string, any>[]);
|
|
5
|
+
transform(transformingModel: TransformingModel): Promise<Record<string, any> | Record<string, any>[]>;
|
|
6
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Transformer = void 0;
|
|
4
|
+
class Transformer {
|
|
5
|
+
constructor(data) {
|
|
6
|
+
this.data = data;
|
|
7
|
+
}
|
|
8
|
+
async transform(transformingModel) {
|
|
9
|
+
if (Array.isArray(this.data)) {
|
|
10
|
+
return await Promise.all(this.data.map((item) => transformingModel.transform(item)));
|
|
11
|
+
}
|
|
12
|
+
return await transformingModel.transform(this.data);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
exports.Transformer = Transformer;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export declare namespace ArrayTransformer {
|
|
2
|
+
const join: (separator: string) => (value: string[]) => string;
|
|
3
|
+
const filter: <T>(predicate: (item: T) => boolean) => (value: T[]) => T[];
|
|
4
|
+
const map: <T, R>(mapper: (item: T) => R) => (value: T[]) => R[];
|
|
5
|
+
const unique: <T>(value: T[]) => T[];
|
|
6
|
+
const sort: <T>(compareFunction?: (a: T, b: T) => number) => (value: T[]) => T[];
|
|
7
|
+
const reduce: <T, R>(reducer: (acc: R, item: T) => R, initialValue: R) => (value: T[]) => R;
|
|
8
|
+
const compact: <T>(value: T[]) => T[];
|
|
9
|
+
const first: <T>(defaultValue?: T) => (value: T[]) => T | undefined;
|
|
10
|
+
const last: <T>(defaultValue?: T) => (value: T[]) => T | undefined;
|
|
11
|
+
const chunk: (size: number) => <T>(value: T[]) => T[][];
|
|
12
|
+
const toNumbers: (value: string[]) => number[];
|
|
13
|
+
const sum: (value: number[]) => number;
|
|
14
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ArrayTransformer = void 0;
|
|
4
|
+
var ArrayTransformer;
|
|
5
|
+
(function (ArrayTransformer) {
|
|
6
|
+
ArrayTransformer.join = (separator) => (value) => value.join(separator);
|
|
7
|
+
ArrayTransformer.filter = (predicate) => {
|
|
8
|
+
return (value) => {
|
|
9
|
+
return value.filter(predicate);
|
|
10
|
+
};
|
|
11
|
+
};
|
|
12
|
+
ArrayTransformer.map = (mapper) => (value) => {
|
|
13
|
+
return value.map(mapper);
|
|
14
|
+
};
|
|
15
|
+
ArrayTransformer.unique = (value) => {
|
|
16
|
+
return [...new Set(value)];
|
|
17
|
+
};
|
|
18
|
+
ArrayTransformer.sort = (compareFunction) => {
|
|
19
|
+
return (value) => {
|
|
20
|
+
return [...value].sort(compareFunction);
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
ArrayTransformer.reduce = (reducer, initialValue) => (value) => {
|
|
24
|
+
return value.reduce(reducer, initialValue);
|
|
25
|
+
};
|
|
26
|
+
ArrayTransformer.compact = (value) => {
|
|
27
|
+
return value.filter(Boolean);
|
|
28
|
+
};
|
|
29
|
+
ArrayTransformer.first = (defaultValue) => (value) => {
|
|
30
|
+
return value.length > 0 ? value[0] : defaultValue;
|
|
31
|
+
};
|
|
32
|
+
ArrayTransformer.last = (defaultValue) => (value) => {
|
|
33
|
+
return value.length > 0 ? value[value.length - 1] : defaultValue;
|
|
34
|
+
};
|
|
35
|
+
ArrayTransformer.chunk = (size) => (value) => {
|
|
36
|
+
if (size <= 0)
|
|
37
|
+
return [value];
|
|
38
|
+
const result = [];
|
|
39
|
+
for (let i = 0; i < value.length; i += size) {
|
|
40
|
+
result.push(value.slice(i, i + size));
|
|
41
|
+
}
|
|
42
|
+
return result;
|
|
43
|
+
};
|
|
44
|
+
ArrayTransformer.toNumbers = (value) => {
|
|
45
|
+
return value.map(item => Number(item.replace(/[^\d.-]/g, "")) || 0);
|
|
46
|
+
};
|
|
47
|
+
ArrayTransformer.sum = (value) => {
|
|
48
|
+
return value.reduce((acc, item) => acc + item, 0);
|
|
49
|
+
};
|
|
50
|
+
})(ArrayTransformer || (exports.ArrayTransformer = ArrayTransformer = {}));
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare namespace DateTansformer {
|
|
2
|
+
const fromString: (template: string) => (value: string) => Date;
|
|
3
|
+
const fromTimestamp: (value: number) => Date;
|
|
4
|
+
const fromISO: (value: string) => Date;
|
|
5
|
+
const isValid: (value: Date) => boolean;
|
|
6
|
+
const toISO: (value: Date) => string;
|
|
7
|
+
const toTimestamp: (value: Date) => number;
|
|
8
|
+
const format: (template: string) => (value: Date) => string;
|
|
9
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.DateTansformer = void 0;
|
|
37
|
+
const dateFns = __importStar(require("date-fns"));
|
|
38
|
+
var DateTansformer;
|
|
39
|
+
(function (DateTansformer) {
|
|
40
|
+
DateTansformer.fromString = (template) => (value) => {
|
|
41
|
+
return dateFns.parse(value, template, new Date());
|
|
42
|
+
};
|
|
43
|
+
DateTansformer.fromTimestamp = (value) => {
|
|
44
|
+
return new Date(value);
|
|
45
|
+
};
|
|
46
|
+
DateTansformer.fromISO = (value) => {
|
|
47
|
+
return dateFns.parseISO(value);
|
|
48
|
+
};
|
|
49
|
+
DateTansformer.isValid = (value) => {
|
|
50
|
+
return dateFns.isValid(value);
|
|
51
|
+
};
|
|
52
|
+
DateTansformer.toISO = (value) => value.toISOString();
|
|
53
|
+
DateTansformer.toTimestamp = (value) => value.getTime();
|
|
54
|
+
DateTansformer.format = (template) => (value) => {
|
|
55
|
+
return dateFns.format(value, template);
|
|
56
|
+
};
|
|
57
|
+
})(DateTansformer || (exports.DateTansformer = DateTansformer = {}));
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./array"), exports);
|
|
18
|
+
__exportStar(require("./date"), exports);
|
|
19
|
+
__exportStar(require("./number"), exports);
|
|
20
|
+
__exportStar(require("./string"), exports);
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export type FormatCurrencyOptions = {
|
|
2
|
+
locale: string;
|
|
3
|
+
currencyCode: string;
|
|
4
|
+
minimumFractionDigits: number;
|
|
5
|
+
};
|
|
6
|
+
export type FormatDecimalOptions = {
|
|
7
|
+
locale: string;
|
|
8
|
+
decimals: number;
|
|
9
|
+
};
|
|
10
|
+
export declare namespace NumberTransformer {
|
|
11
|
+
const toString: (value: number) => string;
|
|
12
|
+
const toInteger: (value: number) => number;
|
|
13
|
+
const multiply: (multiplier: number) => (value: number) => number;
|
|
14
|
+
const divide: (divider: number) => (value: number) => number;
|
|
15
|
+
const add: (addend: number) => (value: number) => number;
|
|
16
|
+
const subtract: (subtrahend: number) => (value: number) => number;
|
|
17
|
+
const power: (exponent: number) => (value: number) => number;
|
|
18
|
+
const sqrt: (value: number) => number;
|
|
19
|
+
const clamp: (min: number, max: number) => (value: number) => number;
|
|
20
|
+
const toBoolean: (value: number) => boolean;
|
|
21
|
+
const toBigint: BigIntConstructor;
|
|
22
|
+
const round: (decimals: number) => (value: number) => number;
|
|
23
|
+
const toPercentage: (decimals: number) => (value: number) => string;
|
|
24
|
+
const toAbsolute: (value: number) => number;
|
|
25
|
+
const formatCurrency: ({ currencyCode, locale, minimumFractionDigits }: FormatCurrencyOptions) => (value: number) => string;
|
|
26
|
+
const formatDecimal: ({ decimals, locale }: FormatDecimalOptions) => (value: number) => string;
|
|
27
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.NumberTransformer = void 0;
|
|
4
|
+
var NumberTransformer;
|
|
5
|
+
(function (NumberTransformer) {
|
|
6
|
+
NumberTransformer.toString = (value) => value.toString();
|
|
7
|
+
NumberTransformer.toInteger = (value) => Math.floor(value);
|
|
8
|
+
NumberTransformer.multiply = (multiplier) => (value) => multiplier * value;
|
|
9
|
+
NumberTransformer.divide = (divider) => (value) => divider * value;
|
|
10
|
+
NumberTransformer.add = (addend) => (value) => value + addend;
|
|
11
|
+
NumberTransformer.subtract = (subtrahend) => (value) => value - subtrahend;
|
|
12
|
+
NumberTransformer.power = (exponent) => (value) => Math.pow(value, exponent);
|
|
13
|
+
NumberTransformer.sqrt = (value) => Math.sqrt(value);
|
|
14
|
+
NumberTransformer.clamp = (min, max) => (value) => {
|
|
15
|
+
return Math.min(Math.max(value, min), max);
|
|
16
|
+
};
|
|
17
|
+
NumberTransformer.toBoolean = (value) => {
|
|
18
|
+
if (value === 0)
|
|
19
|
+
return false;
|
|
20
|
+
if (value === 1)
|
|
21
|
+
return true;
|
|
22
|
+
throw new Error(`The number ${value} cannot be converted to boolean!`);
|
|
23
|
+
};
|
|
24
|
+
NumberTransformer.toBigint = BigInt;
|
|
25
|
+
NumberTransformer.round = (decimals) => {
|
|
26
|
+
return (value) => {
|
|
27
|
+
return Number(value.toFixed(decimals));
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
NumberTransformer.toPercentage = (decimals) => {
|
|
31
|
+
return (value) => {
|
|
32
|
+
return `${(value * 100).toFixed(decimals)}%`;
|
|
33
|
+
};
|
|
34
|
+
};
|
|
35
|
+
NumberTransformer.toAbsolute = (value) => Math.abs(value);
|
|
36
|
+
NumberTransformer.formatCurrency = ({ currencyCode, locale, minimumFractionDigits }) => {
|
|
37
|
+
return (value) => {
|
|
38
|
+
const formatter = new Intl.NumberFormat(locale, {
|
|
39
|
+
style: "currency",
|
|
40
|
+
currency: currencyCode,
|
|
41
|
+
minimumFractionDigits: minimumFractionDigits,
|
|
42
|
+
});
|
|
43
|
+
return formatter.format(value);
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
NumberTransformer.formatDecimal = ({ decimals, locale }) => {
|
|
47
|
+
return (value) => {
|
|
48
|
+
const formatter = new Intl.NumberFormat(locale, {
|
|
49
|
+
minimumFractionDigits: decimals,
|
|
50
|
+
maximumFractionDigits: decimals,
|
|
51
|
+
});
|
|
52
|
+
return formatter.format(value);
|
|
53
|
+
};
|
|
54
|
+
};
|
|
55
|
+
})(NumberTransformer || (exports.NumberTransformer = NumberTransformer = {}));
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export declare namespace StringTransformer {
|
|
2
|
+
const toLowerCase: (value: string) => string;
|
|
3
|
+
const toUpperCase: (value: string) => string;
|
|
4
|
+
const trim: (value: string) => string;
|
|
5
|
+
const toNumber: NumberConstructor;
|
|
6
|
+
const replace: (searchValue: string | RegExp, replaceValue: string) => (value: string) => string;
|
|
7
|
+
const remove: (searchValue: string | RegExp) => (value: string) => string;
|
|
8
|
+
const split: (separator: string) => (value: string) => string[];
|
|
9
|
+
const toBoolean: (value: string) => boolean;
|
|
10
|
+
const normalize: (value: string) => string;
|
|
11
|
+
const removeHtmlTags: (value: string) => string;
|
|
12
|
+
const sanitize: (value: string) => string;
|
|
13
|
+
const collapseWhitespace: (value: string) => string;
|
|
14
|
+
const lookupInRecord: (record: Record<string, any>) => (value: string) => any;
|
|
15
|
+
const resolveUrl: (baseUrl: string) => (value: string) => string;
|
|
16
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.StringTransformer = void 0;
|
|
4
|
+
const string_1 = require("../validators/string");
|
|
5
|
+
var StringTransformer;
|
|
6
|
+
(function (StringTransformer) {
|
|
7
|
+
StringTransformer.toLowerCase = (value) => value.toLowerCase();
|
|
8
|
+
StringTransformer.toUpperCase = (value) => value.toUpperCase();
|
|
9
|
+
StringTransformer.trim = (value) => value.trim();
|
|
10
|
+
StringTransformer.toNumber = Number;
|
|
11
|
+
StringTransformer.replace = (searchValue, replaceValue) => (value) => value.replace(searchValue, replaceValue);
|
|
12
|
+
StringTransformer.remove = (searchValue) => (value) => value.replace(searchValue, "");
|
|
13
|
+
StringTransformer.split = (separator) => (value) => value.split(separator);
|
|
14
|
+
StringTransformer.toBoolean = (value) => {
|
|
15
|
+
if (!string_1.StringValidator.isBooleanText(value)) {
|
|
16
|
+
throw new Error(`'${value}' cannot be converted to boolean!`);
|
|
17
|
+
}
|
|
18
|
+
const truthyValues = ["true", "1", "yes"];
|
|
19
|
+
const lowerValue = value.toLowerCase();
|
|
20
|
+
if (truthyValues.includes(lowerValue)) {
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
23
|
+
return false;
|
|
24
|
+
};
|
|
25
|
+
StringTransformer.normalize = (value) => {
|
|
26
|
+
return value
|
|
27
|
+
.normalize("NFD")
|
|
28
|
+
.toLowerCase()
|
|
29
|
+
.replace(/[\u0300-\u036f]/g, "")
|
|
30
|
+
.trim();
|
|
31
|
+
};
|
|
32
|
+
StringTransformer.removeHtmlTags = (value) => value.replace(/<\/?[^>]+(>|$)/g, "");
|
|
33
|
+
StringTransformer.sanitize = (value) => value.replace(/[^a-zA-Z0-9\s]/g, "").trim();
|
|
34
|
+
StringTransformer.collapseWhitespace = (value) => value.replace(/\s+/g, " ").trim();
|
|
35
|
+
StringTransformer.lookupInRecord = (record) => {
|
|
36
|
+
return (value) => {
|
|
37
|
+
if (!(value in record)) {
|
|
38
|
+
throw new Error(`Record does not have '${value}' as key!`);
|
|
39
|
+
}
|
|
40
|
+
return record[value];
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
StringTransformer.resolveUrl = (baseUrl) => {
|
|
44
|
+
return (value) => {
|
|
45
|
+
try {
|
|
46
|
+
const resolvedUrl = new URL(value, baseUrl).href;
|
|
47
|
+
if (!string_1.StringValidator.isUrl(resolvedUrl)) {
|
|
48
|
+
throw new Error(`Invalid URL: '${value}' with base '${baseUrl}'`);
|
|
49
|
+
}
|
|
50
|
+
return resolvedUrl;
|
|
51
|
+
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
throw new Error(`Invalid URL: '${value}' with base '${baseUrl}'`);
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
};
|
|
57
|
+
})(StringTransformer || (exports.StringTransformer = StringTransformer = {}));
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { SkipFunction } from ".";
|
|
2
|
+
export type TransformerFunction = (data: Record<string, any>, skip: SkipFunction) => any | Promise<any>;
|
|
3
|
+
export type TransformationModelShapeValueBase = TransformerFunction[];
|
|
4
|
+
export type TransformationModelShapeNestedValue = {
|
|
5
|
+
multiple?: boolean;
|
|
6
|
+
model: TransformingModel;
|
|
7
|
+
};
|
|
8
|
+
export type TransformingModelShape = {
|
|
9
|
+
[key: string]: TransformationModelShapeValueBase | TransformationModelShapeNestedValue;
|
|
10
|
+
};
|
|
11
|
+
export type TransformingModelAfterOptions = {
|
|
12
|
+
delete?: string[];
|
|
13
|
+
append?: Record<string, any>;
|
|
14
|
+
};
|
|
15
|
+
export declare class TransformingModel {
|
|
16
|
+
readonly shape: TransformingModelShape;
|
|
17
|
+
private readonly fieldsToDelete;
|
|
18
|
+
private readonly fieldsToAppend;
|
|
19
|
+
constructor(shape: TransformingModelShape);
|
|
20
|
+
transform(data: Record<string, any>): Promise<Record<string, any>>;
|
|
21
|
+
transformValueBase(value: TransformationModelShapeValueBase, key: string, data: any): Promise<any>;
|
|
22
|
+
transformNestedValue(value: TransformationModelShapeNestedValue, data: any): Promise<any[] | Record<string, any>>;
|
|
23
|
+
after({ delete: delete_, append }: TransformingModelAfterOptions): this;
|
|
24
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TransformingModel = void 0;
|
|
4
|
+
class TransformingModel {
|
|
5
|
+
constructor(shape) {
|
|
6
|
+
this.shape = shape;
|
|
7
|
+
this.fieldsToDelete = [];
|
|
8
|
+
this.fieldsToAppend = {};
|
|
9
|
+
}
|
|
10
|
+
async transform(data) {
|
|
11
|
+
const result = { ...data };
|
|
12
|
+
for (const key in this.shape) {
|
|
13
|
+
const value = this.shape[key];
|
|
14
|
+
if (Array.isArray(value)) {
|
|
15
|
+
result[key] = await this.transformValueBase(value, key, result);
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
result[key] = await this.transformNestedValue(value, result);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
for (const field of this.fieldsToDelete) {
|
|
22
|
+
delete result[field];
|
|
23
|
+
}
|
|
24
|
+
for (const [key, value] of Object.entries(this.fieldsToAppend)) {
|
|
25
|
+
result[key] = value;
|
|
26
|
+
}
|
|
27
|
+
return result;
|
|
28
|
+
}
|
|
29
|
+
async transformValueBase(value, key, data) {
|
|
30
|
+
let result = data[key];
|
|
31
|
+
for (const transformer of value) {
|
|
32
|
+
let skiped = false;
|
|
33
|
+
const skip = () => {
|
|
34
|
+
skiped = true;
|
|
35
|
+
};
|
|
36
|
+
let tempResult = await transformer({
|
|
37
|
+
...data,
|
|
38
|
+
[key]: result
|
|
39
|
+
}, skip);
|
|
40
|
+
if (!skiped) {
|
|
41
|
+
result = tempResult;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return result;
|
|
45
|
+
}
|
|
46
|
+
async transformNestedValue(value, data) {
|
|
47
|
+
if (value.multiple) {
|
|
48
|
+
return await Promise.all(data.map(value.model.transform.bind(this)));
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
return await value.model.transform(data);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
after({ delete: delete_, append }) {
|
|
55
|
+
if (delete_) {
|
|
56
|
+
this.fieldsToDelete.push(...delete_);
|
|
57
|
+
}
|
|
58
|
+
if (append) {
|
|
59
|
+
for (const [key, value] of Object.entries(append)) {
|
|
60
|
+
this.fieldsToAppend[key] = value;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return this;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
exports.TransformingModel = TransformingModel;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export declare namespace AnyValidator {
|
|
2
|
+
const isString: (value: any) => value is string;
|
|
3
|
+
const isNumber: (value: any) => boolean;
|
|
4
|
+
const isArray: (arg: any) => arg is any[];
|
|
5
|
+
const isBigint: (value: any) => value is bigint;
|
|
6
|
+
const isFunction: (value: any) => boolean;
|
|
7
|
+
const isSymbol: (value: any) => value is symbol;
|
|
8
|
+
const isObject: (value: any) => boolean;
|
|
9
|
+
const isBoolean: (value: any) => value is boolean;
|
|
10
|
+
const isUndefined: (value: any) => boolean;
|
|
11
|
+
const isNull: (value: any) => boolean;
|
|
12
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AnyValidator = void 0;
|
|
4
|
+
var AnyValidator;
|
|
5
|
+
(function (AnyValidator) {
|
|
6
|
+
AnyValidator.isString = (value) => typeof value === "string";
|
|
7
|
+
AnyValidator.isNumber = (value) => typeof value === "number" && !isNaN(value) && value !== Infinity;
|
|
8
|
+
AnyValidator.isArray = Array.isArray;
|
|
9
|
+
AnyValidator.isBigint = (value) => typeof value === "bigint";
|
|
10
|
+
AnyValidator.isFunction = (value) => typeof value === "function";
|
|
11
|
+
AnyValidator.isSymbol = (value) => typeof value === "symbol";
|
|
12
|
+
AnyValidator.isObject = (value) => typeof value === "object" && !Array.isArray(value) && value !== null;
|
|
13
|
+
AnyValidator.isBoolean = (value) => typeof value === "boolean";
|
|
14
|
+
AnyValidator.isUndefined = (value) => value === undefined;
|
|
15
|
+
AnyValidator.isNull = (value) => value === null;
|
|
16
|
+
})(AnyValidator || (exports.AnyValidator = AnyValidator = {}));
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export declare namespace ArrayValidator {
|
|
2
|
+
const isEmpty: (value: any[]) => boolean;
|
|
3
|
+
const isNotEmpty: (value: any[]) => boolean;
|
|
4
|
+
const minLength: (min: number) => (value: any[]) => boolean;
|
|
5
|
+
const maxLength: (max: number) => (value: any[]) => boolean;
|
|
6
|
+
const exactLength: (length: number) => (value: any[]) => boolean;
|
|
7
|
+
const every: <T>(predicate: (item: T) => boolean) => (value: T[]) => boolean;
|
|
8
|
+
const some: <T>(predicate: (item: T) => boolean) => (value: T[]) => boolean;
|
|
9
|
+
const includes: <T>(item: T) => (value: T[]) => boolean;
|
|
10
|
+
const isUniformType: (value: any[]) => boolean;
|
|
11
|
+
const isAllStrings: (value: any[]) => value is string[];
|
|
12
|
+
const isAllNumbers: (value: any[]) => value is number[];
|
|
13
|
+
const isAllBooleans: (value: any[]) => value is boolean[];
|
|
14
|
+
const hasNoDuplicates: <T>(value: T[]) => boolean;
|
|
15
|
+
const isSorted: (direction?: "asc" | "desc") => <T>(value: T[]) => boolean;
|
|
16
|
+
const isAllTruthy: (value: any[]) => boolean;
|
|
17
|
+
const isAllFalsy: (value: any[]) => boolean;
|
|
18
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ArrayValidator = void 0;
|
|
4
|
+
var ArrayValidator;
|
|
5
|
+
(function (ArrayValidator) {
|
|
6
|
+
ArrayValidator.isEmpty = (value) => value.length === 0;
|
|
7
|
+
ArrayValidator.isNotEmpty = (value) => value.length > 0;
|
|
8
|
+
ArrayValidator.minLength = (min) => {
|
|
9
|
+
return (value) => value.length >= min;
|
|
10
|
+
};
|
|
11
|
+
ArrayValidator.maxLength = (max) => {
|
|
12
|
+
return (value) => value.length <= max;
|
|
13
|
+
};
|
|
14
|
+
ArrayValidator.exactLength = (length) => {
|
|
15
|
+
return (value) => value.length === length;
|
|
16
|
+
};
|
|
17
|
+
ArrayValidator.every = (predicate) => {
|
|
18
|
+
return (value) => value.every(predicate);
|
|
19
|
+
};
|
|
20
|
+
ArrayValidator.some = (predicate) => {
|
|
21
|
+
return (value) => value.some(predicate);
|
|
22
|
+
};
|
|
23
|
+
ArrayValidator.includes = (item) => {
|
|
24
|
+
return (value) => value.includes(item);
|
|
25
|
+
};
|
|
26
|
+
ArrayValidator.isUniformType = (value) => {
|
|
27
|
+
return value.length === 0 || value.every(item => typeof item === typeof value[0]);
|
|
28
|
+
};
|
|
29
|
+
ArrayValidator.isAllStrings = (value) => {
|
|
30
|
+
return value.every(item => typeof item === "string");
|
|
31
|
+
};
|
|
32
|
+
ArrayValidator.isAllNumbers = (value) => {
|
|
33
|
+
return value.every(item => typeof item === "number");
|
|
34
|
+
};
|
|
35
|
+
ArrayValidator.isAllBooleans = (value) => {
|
|
36
|
+
return value.every(item => typeof item === "boolean");
|
|
37
|
+
};
|
|
38
|
+
ArrayValidator.hasNoDuplicates = (value) => {
|
|
39
|
+
return value.length === new Set(value).size;
|
|
40
|
+
};
|
|
41
|
+
ArrayValidator.isSorted = (direction = "asc") => (value) => {
|
|
42
|
+
const compare = direction === "asc" ? (a, b) => a <= b : (a, b) => a >= b;
|
|
43
|
+
return value.every((item, index) => index === 0 || compare(value[index - 1], item));
|
|
44
|
+
};
|
|
45
|
+
ArrayValidator.isAllTruthy = (value) => value.every(Boolean);
|
|
46
|
+
ArrayValidator.isAllFalsy = (value) => value.every(item => !item);
|
|
47
|
+
})(ArrayValidator || (exports.ArrayValidator = ArrayValidator = {}));
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export declare namespace DateValidator {
|
|
2
|
+
const isValid: (value: Date) => boolean;
|
|
3
|
+
const isAfter: (compareDate: Date) => (value: Date) => boolean;
|
|
4
|
+
const isBefore: (compareDate: Date) => (value: Date) => boolean;
|
|
5
|
+
const isEqualDate: (compareDate: Date) => (value: Date) => boolean;
|
|
6
|
+
const isInRange: (start: Date, end: Date) => (value: Date) => boolean;
|
|
7
|
+
const isFuture: (value: Date) => boolean;
|
|
8
|
+
const isPast: (value: Date) => boolean;
|
|
9
|
+
const isToday: (value: Date) => boolean;
|
|
10
|
+
const isWeekend: (value: Date) => boolean;
|
|
11
|
+
const isWeekday: (value: Date) => boolean;
|
|
12
|
+
const isSameMonth: (compareDate: Date) => (value: Date) => boolean;
|
|
13
|
+
const isSameYear: (compareDate: Date) => (value: Date) => boolean;
|
|
14
|
+
const isFirstDayOfMonth: (value: Date) => boolean;
|
|
15
|
+
const isLastDayOfMonth: (value: Date) => boolean;
|
|
16
|
+
const isParsable: (template: string) => (value: string) => boolean;
|
|
17
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.DateValidator = void 0;
|
|
37
|
+
const dateFns = __importStar(require("date-fns"));
|
|
38
|
+
var DateValidator;
|
|
39
|
+
(function (DateValidator) {
|
|
40
|
+
DateValidator.isValid = (value) => dateFns.isValid(value);
|
|
41
|
+
DateValidator.isAfter = (compareDate) => {
|
|
42
|
+
return (value) => dateFns.isAfter(value, compareDate);
|
|
43
|
+
};
|
|
44
|
+
DateValidator.isBefore = (compareDate) => {
|
|
45
|
+
return (value) => dateFns.isBefore(value, compareDate);
|
|
46
|
+
};
|
|
47
|
+
DateValidator.isEqualDate = (compareDate) => {
|
|
48
|
+
return (value) => dateFns.isSameDay(value, compareDate);
|
|
49
|
+
};
|
|
50
|
+
DateValidator.isInRange = (start, end) => {
|
|
51
|
+
return (value) => dateFns.isWithinInterval(value, { start: start, end: end });
|
|
52
|
+
};
|
|
53
|
+
DateValidator.isFuture = (value) => dateFns.isFuture(value);
|
|
54
|
+
DateValidator.isPast = (value) => dateFns.isPast(value);
|
|
55
|
+
DateValidator.isToday = (value) => dateFns.isToday(value);
|
|
56
|
+
DateValidator.isWeekend = (value) => {
|
|
57
|
+
const day = dateFns.getDay(value);
|
|
58
|
+
return day === 0 || day === 6;
|
|
59
|
+
};
|
|
60
|
+
DateValidator.isWeekday = (value) => !DateValidator.isWeekend(value);
|
|
61
|
+
DateValidator.isSameMonth = (compareDate) => {
|
|
62
|
+
return (value) => dateFns.isSameMonth(value, compareDate);
|
|
63
|
+
};
|
|
64
|
+
DateValidator.isSameYear = (compareDate) => {
|
|
65
|
+
return (value) => dateFns.isSameYear(value, compareDate);
|
|
66
|
+
};
|
|
67
|
+
DateValidator.isFirstDayOfMonth = (value) => dateFns.isFirstDayOfMonth(value);
|
|
68
|
+
DateValidator.isLastDayOfMonth = (value) => dateFns.isLastDayOfMonth(value);
|
|
69
|
+
DateValidator.isParsable = (template) => {
|
|
70
|
+
return (value) => {
|
|
71
|
+
const parsed = dateFns.parse(value, template, new Date());
|
|
72
|
+
return dateFns.isValid(parsed);
|
|
73
|
+
};
|
|
74
|
+
};
|
|
75
|
+
})(DateValidator || (exports.DateValidator = DateValidator = {}));
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./array"), exports);
|
|
18
|
+
__exportStar(require("./date"), exports);
|
|
19
|
+
__exportStar(require("./number"), exports);
|
|
20
|
+
__exportStar(require("./string"), exports);
|
|
21
|
+
__exportStar(require("./any"), exports);
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export declare namespace NumberValidator {
|
|
2
|
+
const isValid: (value: number) => boolean;
|
|
3
|
+
const isInteger: (value: number) => boolean;
|
|
4
|
+
const isFloat: (value: number) => boolean;
|
|
5
|
+
const isInfinity: (value: number) => boolean;
|
|
6
|
+
const isPositiveInfinity: (value: number) => boolean;
|
|
7
|
+
const isNegativeInfinity: (value: number) => boolean;
|
|
8
|
+
const isGreaterThan: (min: number) => (value: number) => boolean;
|
|
9
|
+
const isGreaterThanOrEqual: (min: number) => (value: number) => boolean;
|
|
10
|
+
const isLessThan: (max: number) => (value: number) => boolean;
|
|
11
|
+
const isLessThanOrEqual: (max: number) => (value: number) => boolean;
|
|
12
|
+
const isInRange: (min: number, max: number) => (value: number) => boolean;
|
|
13
|
+
const isPositive: (value: number) => boolean;
|
|
14
|
+
const isNegative: (value: number) => boolean;
|
|
15
|
+
const isZero: (value: number) => value is 0;
|
|
16
|
+
const isEven: (value: number) => boolean;
|
|
17
|
+
const isOdd: (value: number) => boolean;
|
|
18
|
+
const isFinite: (value: number) => boolean;
|
|
19
|
+
const isMultipleOf: (divisor: number) => (value: number) => boolean;
|
|
20
|
+
const hasDecimalPlaces: (places: number) => (value: number) => boolean;
|
|
21
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.NumberValidator = void 0;
|
|
4
|
+
var NumberValidator;
|
|
5
|
+
(function (NumberValidator) {
|
|
6
|
+
NumberValidator.isValid = (value) => !isNaN(value) && !NumberValidator.isInfinity(value);
|
|
7
|
+
NumberValidator.isInteger = (value) => Number.isInteger(value);
|
|
8
|
+
NumberValidator.isFloat = (value) => NumberValidator.isValid(value) && !Number.isInteger(value);
|
|
9
|
+
NumberValidator.isInfinity = (value) => {
|
|
10
|
+
return NumberValidator.isPositiveInfinity(value) || NumberValidator.isNegativeInfinity(value);
|
|
11
|
+
};
|
|
12
|
+
NumberValidator.isPositiveInfinity = (value) => value === Infinity;
|
|
13
|
+
NumberValidator.isNegativeInfinity = (value) => value === -Infinity;
|
|
14
|
+
NumberValidator.isGreaterThan = (min) => {
|
|
15
|
+
return (value) => value > min;
|
|
16
|
+
};
|
|
17
|
+
NumberValidator.isGreaterThanOrEqual = (min) => {
|
|
18
|
+
return (value) => value >= min;
|
|
19
|
+
};
|
|
20
|
+
NumberValidator.isLessThan = (max) => {
|
|
21
|
+
return (value) => value < max;
|
|
22
|
+
};
|
|
23
|
+
NumberValidator.isLessThanOrEqual = (max) => {
|
|
24
|
+
return (value) => value <= max;
|
|
25
|
+
};
|
|
26
|
+
NumberValidator.isInRange = (min, max) => {
|
|
27
|
+
return (value) => value >= min && value <= max;
|
|
28
|
+
};
|
|
29
|
+
NumberValidator.isPositive = (value) => value > 0;
|
|
30
|
+
NumberValidator.isNegative = (value) => value < 0;
|
|
31
|
+
NumberValidator.isZero = (value) => value === 0;
|
|
32
|
+
NumberValidator.isEven = (value) => value % 2 === 0;
|
|
33
|
+
NumberValidator.isOdd = (value) => value % 2 !== 0;
|
|
34
|
+
NumberValidator.isFinite = (value) => Number.isFinite(value);
|
|
35
|
+
NumberValidator.isMultipleOf = (divisor) => {
|
|
36
|
+
return (value) => value % divisor === 0;
|
|
37
|
+
};
|
|
38
|
+
NumberValidator.hasDecimalPlaces = (places) => (value) => {
|
|
39
|
+
const decimalPart = (value.toString().split(".")[1] || "").length;
|
|
40
|
+
return decimalPart === places;
|
|
41
|
+
};
|
|
42
|
+
})(NumberValidator || (exports.NumberValidator = NumberValidator = {}));
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export declare namespace StringValidator {
|
|
2
|
+
const includes: (str: string) => (value: string) => boolean;
|
|
3
|
+
const isNumeric: (value: string) => boolean;
|
|
4
|
+
const isEmpty: (value: string) => boolean;
|
|
5
|
+
const minLength: (min: number) => (value: string) => boolean;
|
|
6
|
+
const maxLength: (max: number) => (value: string) => boolean;
|
|
7
|
+
const exactLength: (length: number) => (value: string) => boolean;
|
|
8
|
+
const isEmail: (value: string) => boolean;
|
|
9
|
+
const isUrl: (value: string) => boolean;
|
|
10
|
+
const matches: (regex: RegExp) => (value: string) => boolean;
|
|
11
|
+
const isAlpha: (value: string) => boolean;
|
|
12
|
+
const isAlphanumeric: (value: string) => boolean;
|
|
13
|
+
const isIntegerText: (value: string) => boolean;
|
|
14
|
+
const isDecimalText: (value: string) => boolean;
|
|
15
|
+
const isWhitespace: (value: string) => boolean;
|
|
16
|
+
const isBooleanText: (value: string) => boolean;
|
|
17
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.StringValidator = void 0;
|
|
4
|
+
var StringValidator;
|
|
5
|
+
(function (StringValidator) {
|
|
6
|
+
StringValidator.includes = (str) => (value) => value.includes(str);
|
|
7
|
+
StringValidator.isNumeric = (value) => !isNaN(Number(value));
|
|
8
|
+
StringValidator.isEmpty = (value) => value.trim() === "";
|
|
9
|
+
StringValidator.minLength = (min) => (value) => value.length >= min;
|
|
10
|
+
StringValidator.maxLength = (max) => (value) => value.length <= max;
|
|
11
|
+
StringValidator.exactLength = (length) => (value) => value.length === length;
|
|
12
|
+
StringValidator.isEmail = (value) => {
|
|
13
|
+
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
14
|
+
return emailRegex.test(value);
|
|
15
|
+
};
|
|
16
|
+
StringValidator.isUrl = (value) => {
|
|
17
|
+
const urlRegex = /^(https?:\/\/)?([\w-]+\.)+[\w-]+(\/[\w-./?%&=]*)?$/;
|
|
18
|
+
return urlRegex.test(value);
|
|
19
|
+
};
|
|
20
|
+
StringValidator.matches = (regex) => (value) => regex.test(value);
|
|
21
|
+
StringValidator.isAlpha = (value) => /^[a-zA-Z]+$/.test(value);
|
|
22
|
+
StringValidator.isAlphanumeric = (value) => /^[a-zA-Z0-9]+$/.test(value);
|
|
23
|
+
StringValidator.isIntegerText = (value) => /^\d+$/.test(value);
|
|
24
|
+
StringValidator.isDecimalText = (value) => /^\d+[.,]\d+$/.test(value);
|
|
25
|
+
StringValidator.isWhitespace = (value) => /^\s+$/.test(value);
|
|
26
|
+
StringValidator.isBooleanText = (value) => {
|
|
27
|
+
const booleanValues = ["true", "false", "1", "0", "yes", "no"];
|
|
28
|
+
return booleanValues.includes(value.toLowerCase());
|
|
29
|
+
};
|
|
30
|
+
})(StringValidator || (exports.StringValidator = StringValidator = {}));
|
package/package.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@xcrap/transformer",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Xcrap Transformer is the data transformation package extracted from the Web Scraping framework Xcrap.",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"module": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist/*",
|
|
10
|
+
"!/**/__tests__"
|
|
11
|
+
],
|
|
12
|
+
"scripts": {
|
|
13
|
+
"test": "jest",
|
|
14
|
+
"build": "tsc"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [
|
|
17
|
+
"xcrap",
|
|
18
|
+
"transformer",
|
|
19
|
+
"scrapy",
|
|
20
|
+
"web scraping"
|
|
21
|
+
],
|
|
22
|
+
"author": "Marcuth",
|
|
23
|
+
"license": "MIT",
|
|
24
|
+
"type": "commonjs",
|
|
25
|
+
"devDependencies": {
|
|
26
|
+
"@types/jest": "30.0.0",
|
|
27
|
+
"@types/node": "24.0.3",
|
|
28
|
+
"jest": "30.0.2",
|
|
29
|
+
"ts-jest": "29.4.0",
|
|
30
|
+
"ts-node": "10.9.2",
|
|
31
|
+
"typescript": "5.8.3"
|
|
32
|
+
},
|
|
33
|
+
"dependencies": {
|
|
34
|
+
"date-fns": "4.1.0"
|
|
35
|
+
},
|
|
36
|
+
"repository": {
|
|
37
|
+
"type": "git",
|
|
38
|
+
"url": "git+https://github.com/Xcrap-Cloud/transformer.git"
|
|
39
|
+
},
|
|
40
|
+
"bugs": {
|
|
41
|
+
"url": "https://github.com/Xcrap-Cloud/transformer/issues"
|
|
42
|
+
},
|
|
43
|
+
"homepage": "https://github.com/Xcrap-Cloud/transformer#readme"
|
|
44
|
+
}
|