mybase 1.1.22 → 1.1.24
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/package.json +1 -1
- package/ts/index.js +1 -0
- package/ts/index.ts +1 -0
- package/ts/models/IPAddress.jest.js +165 -0
- package/ts/models/IPAddress.js +167 -0
- package/ts/models/IPAddress.test.ts +188 -0
- package/ts/models/IPAddress.ts +172 -0
- package/ts/models/Unixtime.js +18 -1
- package/ts/models/Unixtime.test.ts +4 -0
- package/ts/models/Unixtime.ts +21 -1
package/package.json
CHANGED
package/ts/index.js
CHANGED
|
@@ -43,4 +43,5 @@ __exportStar(require("./funcs/MaxRuntimeHours"), exports);
|
|
|
43
43
|
// models
|
|
44
44
|
__exportStar(require("./models/Unixtime"), exports);
|
|
45
45
|
__exportStar(require("./models/Timespan"), exports);
|
|
46
|
+
__exportStar(require("./models/IPAddress"), exports);
|
|
46
47
|
//# sourceMappingURL=index.js.map
|
package/ts/index.ts
CHANGED
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const ip6addr_1 = __importDefault(require("ip6addr"));
|
|
7
|
+
const IPAddress_1 = require("./IPAddress");
|
|
8
|
+
const __1 = require("../");
|
|
9
|
+
describe('IPAddress', () => {
|
|
10
|
+
it('should create an instance of IPAddress', () => {
|
|
11
|
+
const ipAddress = new IPAddress_1.IPAddress('192.168.0.1');
|
|
12
|
+
expect(ipAddress).toBeInstanceOf(IPAddress_1.IPAddress);
|
|
13
|
+
});
|
|
14
|
+
it('should convert IPAddress to string', () => {
|
|
15
|
+
const ipAddress = new IPAddress_1.IPAddress('192.168.0.1');
|
|
16
|
+
const result = ipAddress.toString();
|
|
17
|
+
expect(result).toBe('192.168.0.1');
|
|
18
|
+
});
|
|
19
|
+
it('should create an instance of IPAddress from string', () => {
|
|
20
|
+
const ipAddress = IPAddress_1.IPAddress.fromString('192.168.0.1');
|
|
21
|
+
expect(ipAddress).toBeInstanceOf(IPAddress_1.IPAddress);
|
|
22
|
+
});
|
|
23
|
+
it('should throw an error when creating an instance of IPAddress from invalid string', () => {
|
|
24
|
+
expect(() => IPAddress_1.IPAddress.fromString('192.168.0')).toThrow();
|
|
25
|
+
expect(() => IPAddress_1.IPAddress.fromString('0.0.0')).toThrow();
|
|
26
|
+
expect(() => IPAddress_1.IPAddress.fromString('')).toThrow();
|
|
27
|
+
//@ts-ignore
|
|
28
|
+
expect(() => IPAddress_1.IPAddress.fromString(null)).toThrow();
|
|
29
|
+
//@ts-ignore
|
|
30
|
+
expect(() => IPAddress_1.IPAddress.fromString(undefined)).toThrow();
|
|
31
|
+
});
|
|
32
|
+
it('should serialize ipv4 to string', () => {
|
|
33
|
+
expect(IPAddress_1.IPAddress.fromString('192.168.0.1').serialize()).toBe('192168000001');
|
|
34
|
+
expect(IPAddress_1.IPAddress.fromString('0.0.0.0').serialize()).toBe('000000000000');
|
|
35
|
+
expect(IPAddress_1.IPAddress.fromString('0.0.0.1').serialize()).toBe('000000000001');
|
|
36
|
+
expect(IPAddress_1.IPAddress.fromString('0.00.000.01').serialize()).toBe('000000000001');
|
|
37
|
+
expect(IPAddress_1.IPAddress.fromString('0.10.0.0').serialize()).toBe('000010000000');
|
|
38
|
+
expect(IPAddress_1.IPAddress.fromString('255.255.255.255').serialize()).toBe('255255255255');
|
|
39
|
+
});
|
|
40
|
+
it('should serialize ipv6 to string', () => {
|
|
41
|
+
expect(IPAddress_1.IPAddress.fromString('::').serialize()).toBe('00000000000000000000000000000000');
|
|
42
|
+
expect(IPAddress_1.IPAddress.fromString('::1').serialize()).toBe('00000000000000000000000000000001');
|
|
43
|
+
expect(IPAddress_1.IPAddress.fromString('::01').serialize()).toBe('00000000000000000000000000000001');
|
|
44
|
+
expect(IPAddress_1.IPAddress.fromString('::001').serialize()).toBe('00000000000000000000000000000001');
|
|
45
|
+
expect(IPAddress_1.IPAddress.fromString('::0001').serialize()).toBe('00000000000000000000000000000001');
|
|
46
|
+
expect(IPAddress_1.IPAddress.fromString('::1:1').serialize()).toBe('00000000000000000000000000010001');
|
|
47
|
+
expect(IPAddress_1.IPAddress.fromString('::2:1').serialize()).toBe('00000000000000000000000000020001');
|
|
48
|
+
});
|
|
49
|
+
// testing unserialize
|
|
50
|
+
it('should unserialize ipv4 from string', () => {
|
|
51
|
+
expect(IPAddress_1.IPAddress.unserialize('192168000001').toString()).toBe('192.168.0.1');
|
|
52
|
+
expect(IPAddress_1.IPAddress.unserialize('192168000002').toString()).toBe('192.168.0.2');
|
|
53
|
+
expect(IPAddress_1.IPAddress.unserialize('000000000000').toString()).toBe('0.0.0.0');
|
|
54
|
+
});
|
|
55
|
+
it('should throw invalid serialization string', () => {
|
|
56
|
+
expect(() => IPAddress_1.IPAddress.unserialize('92168000001')).toThrow(Error);
|
|
57
|
+
expect(() => IPAddress_1.IPAddress.unserialize('168000001')).toThrow(Error);
|
|
58
|
+
expect(() => IPAddress_1.IPAddress.unserialize('292168000002')).toThrow(Error);
|
|
59
|
+
});
|
|
60
|
+
it('randomly generated ipv4 serialization', () => {
|
|
61
|
+
for (let i = 0; i < 100; i++) {
|
|
62
|
+
const ip = (0, __1.randomIP)();
|
|
63
|
+
expect(IPAddress_1.IPAddress.unserialize(IPAddress_1.IPAddress.fromString(ip).serialize()).toString()).toBe(ip);
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
it('randomly generated ipv6 serialization and unserialization', () => {
|
|
67
|
+
for (let i = 0; i < 100; i++) {
|
|
68
|
+
const ip = (0, __1.randomIP6)();
|
|
69
|
+
let ip2 = IPAddress_1.IPAddress.unserialize(IPAddress_1.IPAddress.fromString(ip).serialize()).toString();
|
|
70
|
+
expect(ip6addr_1.default.compare(ip, ip2)).toEqual(0);
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
it('it should detect the kind of ip4', () => {
|
|
74
|
+
for (let i = 0; i < 100; i++)
|
|
75
|
+
expect(IPAddress_1.IPAddress.randomIP4().kind()).toBe(4);
|
|
76
|
+
});
|
|
77
|
+
it('should return shortened address by default toString', () => {
|
|
78
|
+
expect(new IPAddress_1.IPAddress('001.02.3.004').toString()).toBe('1.2.3.4');
|
|
79
|
+
});
|
|
80
|
+
it('randomPad return valid ipv4 results', () => {
|
|
81
|
+
let compared = 0;
|
|
82
|
+
while (compared < 100) {
|
|
83
|
+
const ip1 = IPAddress_1.IPAddress.randomIP4();
|
|
84
|
+
const ip2 = ip1.randomPad();
|
|
85
|
+
if (ip1.toString() !== ip2) { // find ips they are padded from the original
|
|
86
|
+
compared++;
|
|
87
|
+
}
|
|
88
|
+
expect(IPAddress_1.IPAddress.validate(ip2)).toBe(true);
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
it('compare ipv4 should detect equality even if they are padded', () => {
|
|
92
|
+
let compared = 0;
|
|
93
|
+
while (compared < 100) {
|
|
94
|
+
const ip1 = IPAddress_1.IPAddress.randomIP4();
|
|
95
|
+
const ip2 = ip1.randomPad();
|
|
96
|
+
if (ip1.toString() !== ip2) { // find ips they are padded from the original
|
|
97
|
+
compared++;
|
|
98
|
+
}
|
|
99
|
+
expect(ip1.equals(IPAddress_1.IPAddress.fromString(ip2))).toBe(true);
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
describe('IPAddress IPv6', () => {
|
|
104
|
+
it('should work with any form of valid ipv6, prefixed or not', () => {
|
|
105
|
+
expect(new IPAddress_1.IPAddress('2605:2700:0000:0003:a800:00ff:fe10:f0d3')).toBeInstanceOf(IPAddress_1.IPAddress);
|
|
106
|
+
expect(new IPAddress_1.IPAddress('2605:2700:0000:003:a800:00ff:fe10:f0d3')).toBeInstanceOf(IPAddress_1.IPAddress);
|
|
107
|
+
expect(new IPAddress_1.IPAddress('2605:2700:000:003:a800:00ff:fe10:f0d3')).toBeInstanceOf(IPAddress_1.IPAddress);
|
|
108
|
+
expect(new IPAddress_1.IPAddress('2605:2700:0:003:a800:00ff:fe10:f0d3')).toBeInstanceOf(IPAddress_1.IPAddress);
|
|
109
|
+
expect(new IPAddress_1.IPAddress('2605:2700:0:003:a800:0ff:fe10:f0d3')).toBeInstanceOf(IPAddress_1.IPAddress);
|
|
110
|
+
});
|
|
111
|
+
it('should return shortened address by default toString', () => {
|
|
112
|
+
expect(new IPAddress_1.IPAddress('2605:2700:0000:0003:a800:00ff:fe10:f0d3').toString()).toBe('2605:2700::3:a800:ff:fe10:f0d3');
|
|
113
|
+
expect(new IPAddress_1.IPAddress('2605:2700:0000:003:a800:00ff:fe10:f0d3').toString()).toBe('2605:2700::3:a800:ff:fe10:f0d3');
|
|
114
|
+
expect(new IPAddress_1.IPAddress('2605:2700:0000:03:a800:00ff:fe10:f0d3').toString()).toBe('2605:2700::3:a800:ff:fe10:f0d3');
|
|
115
|
+
expect(new IPAddress_1.IPAddress('2605:2700:0000:03:a800:ff:fe10:f0d3').toString()).toBe('2605:2700::3:a800:ff:fe10:f0d3');
|
|
116
|
+
});
|
|
117
|
+
it('ip6 addresses should be lowercased', () => {
|
|
118
|
+
expect(new IPAddress_1.IPAddress('2605:2700:0000:0003:a800:00ff:fe10:f0d3').toString()).toBe('2605:2700::3:a800:ff:fe10:f0d3');
|
|
119
|
+
expect(new IPAddress_1.IPAddress('2605:2700:0000:003:a800:00ff:fe10:f0d3').toString()).toBe('2605:2700::3:a800:ff:fe10:f0d3');
|
|
120
|
+
expect(new IPAddress_1.IPAddress('2605:2700:0000:03:a800:00ff:fe10:f0d3').toString()).toBe('2605:2700::3:a800:ff:fe10:f0d3');
|
|
121
|
+
expect(new IPAddress_1.IPAddress('2605:2700:0000:03:a800:ff:fe10:f0d3').toString()).toBe('2605:2700::3:a800:ff:fe10:f0d3');
|
|
122
|
+
});
|
|
123
|
+
it('it should detect the kind of ip6', () => {
|
|
124
|
+
expect(new IPAddress_1.IPAddress('2605:2700:0000:0003:a800:00ff:fe10:f0d3').kind()).toBe(6);
|
|
125
|
+
for (let i = 0; i < 100; i++)
|
|
126
|
+
expect(IPAddress_1.IPAddress.randomIP6().kind()).toBe(6);
|
|
127
|
+
});
|
|
128
|
+
it('randomPad return valid ipv6 results be compareable with equals', () => {
|
|
129
|
+
let compared = 0;
|
|
130
|
+
while (compared < 500) {
|
|
131
|
+
const ip1 = IPAddress_1.IPAddress.randomIP6();
|
|
132
|
+
const ip2 = ip1.randomPad();
|
|
133
|
+
expect(ip1.kind()).toBe(6);
|
|
134
|
+
if (ip1.toString() !== ip2) { // find ips they are padded from the original
|
|
135
|
+
compared++;
|
|
136
|
+
}
|
|
137
|
+
expect(IPAddress_1.IPAddress.validate(ip2)).toBe(true);
|
|
138
|
+
expect(ip1.equals(IPAddress_1.IPAddress.fromString(ip2))).toBe(true);
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
});
|
|
142
|
+
describe('IPAddress asciiChecksum', () => {
|
|
143
|
+
it('should return the correct checksum for ipv4', () => {
|
|
144
|
+
expect(new IPAddress_1.IPAddress('1.2.3.4').asciiChecksum()).toBe('e');
|
|
145
|
+
expect(new IPAddress_1.IPAddress('1.2.3.6').asciiChecksum()).toBe('i');
|
|
146
|
+
});
|
|
147
|
+
it('should return the correct checksum for ipv6', () => {
|
|
148
|
+
expect(new IPAddress_1.IPAddress('::').asciiChecksum()).toBe('a');
|
|
149
|
+
expect(new IPAddress_1.IPAddress('::1').asciiChecksum()).toBe('a');
|
|
150
|
+
expect(new IPAddress_1.IPAddress('::f').asciiChecksum()).toBe('s');
|
|
151
|
+
});
|
|
152
|
+
it('it should always return a single character ipv4/v6', () => {
|
|
153
|
+
for (let i = 0; i < 10000; i++) {
|
|
154
|
+
expect(new IPAddress_1.IPAddress((0, __1.randomIP)()).asciiChecksum().length).toBe(1);
|
|
155
|
+
expect(new IPAddress_1.IPAddress((0, __1.randomIP6)()).asciiChecksum().length).toBe(1);
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
it('it should return a-z0-9 ascii only', () => {
|
|
159
|
+
for (let i = 0; i < 10000; i++) {
|
|
160
|
+
expect('abcdefghijklmnopqrstuvwxyz0123456789').toContain(new IPAddress_1.IPAddress((0, __1.randomIP)()).asciiChecksum());
|
|
161
|
+
expect('abcdefghijklmnopqrstuvwxyz0123456789').toContain(new IPAddress_1.IPAddress((0, __1.randomIP6)()).asciiChecksum());
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
});
|
|
165
|
+
//# sourceMappingURL=IPAddress.jest.js.map
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
3
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
4
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
5
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
6
|
+
};
|
|
7
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
8
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
9
|
+
};
|
|
10
|
+
var _IPAddress_instances, _IPAddress_padIp6, _IPAddress_padIp4;
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.IPAddress = void 0;
|
|
13
|
+
const __1 = require("./../");
|
|
14
|
+
const ip6addr_1 = __importDefault(require("ip6addr"));
|
|
15
|
+
const ip6 = require('ip6'); // "url": "https://github.com/elgs/ip6"
|
|
16
|
+
// need version "ip6": "0.2.7",!!
|
|
17
|
+
class IPAddress {
|
|
18
|
+
constructor(ip) {
|
|
19
|
+
_IPAddress_instances.add(this);
|
|
20
|
+
if (ip === '-')
|
|
21
|
+
ip = '0.0.0.0';
|
|
22
|
+
try {
|
|
23
|
+
this._ip = ip6addr_1.default.parse(ip);
|
|
24
|
+
}
|
|
25
|
+
catch (err) {
|
|
26
|
+
if (err instanceof Error)
|
|
27
|
+
throw new Error(`IPAddress: '${ip}' Error: ${err.message}`);
|
|
28
|
+
throw err;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
toString(opts = { format: 'auto', zeroElide: false, zeroPad: false }) {
|
|
32
|
+
return this._ip.toString();
|
|
33
|
+
}
|
|
34
|
+
static validate(ip) {
|
|
35
|
+
try {
|
|
36
|
+
new IPAddress(ip);
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
catch (_) {
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
static try(ip) {
|
|
44
|
+
try {
|
|
45
|
+
return new IPAddress(ip);
|
|
46
|
+
}
|
|
47
|
+
catch (_) {
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
static fromString(ip) {
|
|
52
|
+
return new IPAddress(ip);
|
|
53
|
+
}
|
|
54
|
+
static get Empty() {
|
|
55
|
+
//The IP address 0.0.0.0 is a non-routable meta-address used to denote an invalid, unknown,
|
|
56
|
+
// or non-applicable target. It's not assigned to any individual device.
|
|
57
|
+
// It is used in different contexts to mean "any IPv4-enabled network interface" or as a default route
|
|
58
|
+
return new IPAddress('0.0.0.0');
|
|
59
|
+
}
|
|
60
|
+
isLoopbackIP() {
|
|
61
|
+
return (0, __1.isLoopbackIP)(this._ip.toString());
|
|
62
|
+
}
|
|
63
|
+
isLANIP() {
|
|
64
|
+
return (0, __1.isLANIp)(this._ip.toString());
|
|
65
|
+
}
|
|
66
|
+
isPublicIP() {
|
|
67
|
+
return !this.isLoopbackIP() && !this.isLANIP() && this.toString() !== '0.0.0.0';
|
|
68
|
+
}
|
|
69
|
+
static unserialize(serializedIpString) {
|
|
70
|
+
var _a, _b;
|
|
71
|
+
if (serializedIpString.length === 32) {
|
|
72
|
+
// we have possible ipv6
|
|
73
|
+
let ip = (_a = serializedIpString.match(/.{1,4}/g)) === null || _a === void 0 ? void 0 : _a.join(':');
|
|
74
|
+
if (ip)
|
|
75
|
+
return new IPAddress(ip);
|
|
76
|
+
}
|
|
77
|
+
// we have possible ipv4
|
|
78
|
+
let ip = (_b = serializedIpString.match(/.{1,3}/g)) === null || _b === void 0 ? void 0 : _b.join('.');
|
|
79
|
+
if (ip)
|
|
80
|
+
try {
|
|
81
|
+
return new IPAddress(ip);
|
|
82
|
+
}
|
|
83
|
+
catch (_) { }
|
|
84
|
+
throw new Error(`Invalid SerializationString: ${serializedIpString}`);
|
|
85
|
+
}
|
|
86
|
+
static randomIP4() {
|
|
87
|
+
return new IPAddress((0, __1.randomIP)());
|
|
88
|
+
}
|
|
89
|
+
static randomIP6() {
|
|
90
|
+
return new IPAddress((0, __1.randomIP6)());
|
|
91
|
+
}
|
|
92
|
+
serialize() {
|
|
93
|
+
if (this.kind() === 4) {
|
|
94
|
+
// zero pad ipv4
|
|
95
|
+
return this._ip.toString().split('.').map((octet) => {
|
|
96
|
+
return octet.padStart(3, '0');
|
|
97
|
+
}).join('.').replace(/\./g, '');
|
|
98
|
+
}
|
|
99
|
+
// zero pad ipv6
|
|
100
|
+
return ip6.normalize(this._ip.toString()).split(':').map((hextet) => {
|
|
101
|
+
return hextet.padStart(4, '0');
|
|
102
|
+
}).join(':').replace(/:/g, '');
|
|
103
|
+
}
|
|
104
|
+
kind() {
|
|
105
|
+
return this._ip.kind() === 'ipv6' ? 6 : 4;
|
|
106
|
+
}
|
|
107
|
+
equals(secondIp) {
|
|
108
|
+
return this._ip.compare(secondIp._ip) === 0;
|
|
109
|
+
}
|
|
110
|
+
randomPad() {
|
|
111
|
+
if (this.kind() === 4)
|
|
112
|
+
return __classPrivateFieldGet(this, _IPAddress_instances, "m", _IPAddress_padIp4).call(this);
|
|
113
|
+
return __classPrivateFieldGet(this, _IPAddress_instances, "m", _IPAddress_padIp6).call(this);
|
|
114
|
+
}
|
|
115
|
+
normalized() {
|
|
116
|
+
if (this.kind() === 4)
|
|
117
|
+
return this._ip.toString();
|
|
118
|
+
return ip6.normalize(this._ip.toString());
|
|
119
|
+
}
|
|
120
|
+
abbreviated() {
|
|
121
|
+
if (this.kind() === 4)
|
|
122
|
+
return this._ip.toString();
|
|
123
|
+
return ip6.abbreviate(this._ip.toString());
|
|
124
|
+
}
|
|
125
|
+
asciiChecksum() {
|
|
126
|
+
// support ipv4 and ipv6
|
|
127
|
+
// FNV-1a hash parameters
|
|
128
|
+
const FNV_PRIME = 0x01000193;
|
|
129
|
+
const FNV_OFFSET_BASIS = 0x811c9dc5;
|
|
130
|
+
const CHAR_SET = 'abcdefghijklmnopqrstuvwxyz0123456789';
|
|
131
|
+
let hash = FNV_OFFSET_BASIS;
|
|
132
|
+
const ip = this.normalized();
|
|
133
|
+
for (let i = 0; i < ip.length; i++) {
|
|
134
|
+
hash ^= ip.charCodeAt(i);
|
|
135
|
+
hash *= FNV_PRIME;
|
|
136
|
+
hash >>>= 0; // Ensure hash is always a positive 32-bit integer
|
|
137
|
+
}
|
|
138
|
+
// Map the hash to a character in the CHAR_SET
|
|
139
|
+
const index = hash % CHAR_SET.length;
|
|
140
|
+
return CHAR_SET.charAt(index);
|
|
141
|
+
}
|
|
142
|
+
checksum1() {
|
|
143
|
+
// this shall check that the ip is ipv4 and return the last octet as checksum
|
|
144
|
+
if (this.kind() !== 4)
|
|
145
|
+
return 'x';
|
|
146
|
+
return this._ip.toString().split('.').pop() || '-';
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
exports.IPAddress = IPAddress;
|
|
150
|
+
_IPAddress_instances = new WeakSet(), _IPAddress_padIp6 = function _IPAddress_padIp6() {
|
|
151
|
+
const hextets = this.normalized().split(':'); // we need to have the full form
|
|
152
|
+
const paddedHextets = hextets.map(hextet => {
|
|
153
|
+
const cleanHextet = Number(`0x${hextet}`).toString(16);
|
|
154
|
+
const padLength = Math.floor(Math.random() * (4 - cleanHextet.length));
|
|
155
|
+
return cleanHextet.padStart(padLength + cleanHextet.length, '0');
|
|
156
|
+
});
|
|
157
|
+
return paddedHextets.join(':');
|
|
158
|
+
}, _IPAddress_padIp4 = function _IPAddress_padIp4() {
|
|
159
|
+
const octets = this._ip.toString().split('.');
|
|
160
|
+
const paddedOctets = octets.map(octet => {
|
|
161
|
+
const cleanOctet = String(Number(octet));
|
|
162
|
+
const padLength = Math.floor(Math.random() * (3 - cleanOctet.length));
|
|
163
|
+
return cleanOctet.padStart(padLength + cleanOctet.length, '0');
|
|
164
|
+
});
|
|
165
|
+
return paddedOctets.join('.');
|
|
166
|
+
};
|
|
167
|
+
//# sourceMappingURL=IPAddress.js.map
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import ip6addr from 'ip6addr'
|
|
2
|
+
import { IPAddress } from './IPAddress'
|
|
3
|
+
import { randomIP, randomIP6 } from '../'
|
|
4
|
+
|
|
5
|
+
describe('IPAddress', () => {
|
|
6
|
+
it('should create an instance of IPAddress', () => {
|
|
7
|
+
const ipAddress = new IPAddress('192.168.0.1');
|
|
8
|
+
expect(ipAddress).toBeInstanceOf(IPAddress);
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
it('should convert IPAddress to string', () => {
|
|
13
|
+
const ipAddress = new IPAddress('192.168.0.1');
|
|
14
|
+
const result = ipAddress.toString();
|
|
15
|
+
expect(result).toBe('192.168.0.1');
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it('should create an instance of IPAddress from string', () => {
|
|
19
|
+
const ipAddress = IPAddress.fromString('192.168.0.1');
|
|
20
|
+
expect(ipAddress).toBeInstanceOf(IPAddress);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it('should throw an error when creating an instance of IPAddress from invalid string', () => {
|
|
24
|
+
expect(() => IPAddress.fromString('192.168.0')).toThrow()
|
|
25
|
+
expect(() => IPAddress.fromString('0.0.0')).toThrow()
|
|
26
|
+
expect(() => IPAddress.fromString('')).toThrow()
|
|
27
|
+
//@ts-ignore
|
|
28
|
+
expect(() => IPAddress.fromString(null)).toThrow()
|
|
29
|
+
//@ts-ignore
|
|
30
|
+
expect(() => IPAddress.fromString(undefined)).toThrow()
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
it('should serialize ipv4 to string', () => {
|
|
34
|
+
expect(IPAddress.fromString('192.168.0.1').serialize()).toBe('192168000001')
|
|
35
|
+
expect(IPAddress.fromString('0.0.0.0').serialize()).toBe('000000000000')
|
|
36
|
+
expect(IPAddress.fromString('0.0.0.1').serialize()).toBe('000000000001')
|
|
37
|
+
expect(IPAddress.fromString('0.00.000.01').serialize()).toBe('000000000001')
|
|
38
|
+
expect(IPAddress.fromString('0.10.0.0').serialize()).toBe('000010000000')
|
|
39
|
+
expect(IPAddress.fromString('255.255.255.255').serialize()).toBe('255255255255')
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it('should serialize ipv6 to string', () => {
|
|
43
|
+
expect(IPAddress.fromString('::').serialize()).toBe('00000000000000000000000000000000')
|
|
44
|
+
expect(IPAddress.fromString('::1').serialize()).toBe('00000000000000000000000000000001')
|
|
45
|
+
expect(IPAddress.fromString('::01').serialize()).toBe('00000000000000000000000000000001')
|
|
46
|
+
expect(IPAddress.fromString('::001').serialize()).toBe('00000000000000000000000000000001')
|
|
47
|
+
expect(IPAddress.fromString('::0001').serialize()).toBe('00000000000000000000000000000001')
|
|
48
|
+
expect(IPAddress.fromString('::1:1').serialize()).toBe('00000000000000000000000000010001')
|
|
49
|
+
expect(IPAddress.fromString('::2:1').serialize()).toBe('00000000000000000000000000020001')
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
// testing unserialize
|
|
53
|
+
it('should unserialize ipv4 from string', () => {
|
|
54
|
+
expect(IPAddress.unserialize('192168000001').toString()).toBe('192.168.0.1')
|
|
55
|
+
expect(IPAddress.unserialize('192168000002').toString()).toBe('192.168.0.2')
|
|
56
|
+
expect(IPAddress.unserialize('000000000000').toString()).toBe('0.0.0.0')
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
it('should throw invalid serialization string', () => {
|
|
60
|
+
expect(() => IPAddress.unserialize('92168000001')).toThrow(Error)
|
|
61
|
+
expect(() => IPAddress.unserialize('168000001')).toThrow(Error)
|
|
62
|
+
expect(() => IPAddress.unserialize('292168000002')).toThrow(Error)
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
it('randomly generated ipv4 serialization', () => {
|
|
66
|
+
for(let i = 0; i < 100; i++) {
|
|
67
|
+
const ip = randomIP()
|
|
68
|
+
expect(IPAddress.unserialize(IPAddress.fromString(ip).serialize()).toString()).toBe(ip)
|
|
69
|
+
}
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
it('randomly generated ipv6 serialization and unserialization', () => {
|
|
73
|
+
for(let i = 0; i < 100; i++) {
|
|
74
|
+
const ip = randomIP6()
|
|
75
|
+
let ip2 = IPAddress.unserialize(IPAddress.fromString(ip).serialize()).toString()
|
|
76
|
+
expect(ip6addr.compare(ip, ip2)).toEqual(0)
|
|
77
|
+
}
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
it('it should detect the kind of ip4', () => {
|
|
81
|
+
for(let i = 0; i < 100; i++)
|
|
82
|
+
expect(IPAddress.randomIP4().kind()).toBe(4)
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
it('should return shortened address by default toString', () => {
|
|
86
|
+
expect(new IPAddress('001.02.3.004').toString()).toBe('1.2.3.4');
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it('randomPad return valid ipv4 results', () => {
|
|
90
|
+
let compared = 0
|
|
91
|
+
while(compared<100) {
|
|
92
|
+
const ip1 = IPAddress.randomIP4()
|
|
93
|
+
const ip2 = ip1.randomPad()
|
|
94
|
+
if (ip1.toString()!==ip2) { // find ips they are padded from the original
|
|
95
|
+
compared++
|
|
96
|
+
}
|
|
97
|
+
expect(IPAddress.validate(ip2)).toBe(true)
|
|
98
|
+
}
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
it('compare ipv4 should detect equality even if they are padded', () => {
|
|
102
|
+
let compared = 0
|
|
103
|
+
while(compared<100) {
|
|
104
|
+
const ip1 = IPAddress.randomIP4()
|
|
105
|
+
const ip2 = ip1.randomPad()
|
|
106
|
+
if (ip1.toString()!==ip2) { // find ips they are padded from the original
|
|
107
|
+
compared++
|
|
108
|
+
}
|
|
109
|
+
expect(ip1.equals(IPAddress.fromString(ip2))).toBe(true)
|
|
110
|
+
}
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
describe('IPAddress IPv6', () => {
|
|
116
|
+
it('should work with any form of valid ipv6, prefixed or not', () => {
|
|
117
|
+
expect(new IPAddress('2605:2700:0000:0003:a800:00ff:fe10:f0d3')).toBeInstanceOf(IPAddress);
|
|
118
|
+
expect(new IPAddress('2605:2700:0000:003:a800:00ff:fe10:f0d3')).toBeInstanceOf(IPAddress);
|
|
119
|
+
expect(new IPAddress('2605:2700:000:003:a800:00ff:fe10:f0d3')).toBeInstanceOf(IPAddress);
|
|
120
|
+
expect(new IPAddress('2605:2700:0:003:a800:00ff:fe10:f0d3')).toBeInstanceOf(IPAddress);
|
|
121
|
+
expect(new IPAddress('2605:2700:0:003:a800:0ff:fe10:f0d3')).toBeInstanceOf(IPAddress);
|
|
122
|
+
})
|
|
123
|
+
|
|
124
|
+
it('should return shortened address by default toString', () => {
|
|
125
|
+
expect(new IPAddress('2605:2700:0000:0003:a800:00ff:fe10:f0d3').toString()).toBe('2605:2700::3:a800:ff:fe10:f0d3');
|
|
126
|
+
expect(new IPAddress('2605:2700:0000:003:a800:00ff:fe10:f0d3').toString()).toBe('2605:2700::3:a800:ff:fe10:f0d3');
|
|
127
|
+
expect(new IPAddress('2605:2700:0000:03:a800:00ff:fe10:f0d3').toString()).toBe('2605:2700::3:a800:ff:fe10:f0d3');
|
|
128
|
+
expect(new IPAddress('2605:2700:0000:03:a800:ff:fe10:f0d3').toString()).toBe('2605:2700::3:a800:ff:fe10:f0d3');
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
it('ip6 addresses should be lowercased', () => {
|
|
132
|
+
expect(new IPAddress('2605:2700:0000:0003:a800:00ff:fe10:f0d3').toString()).toBe('2605:2700::3:a800:ff:fe10:f0d3');
|
|
133
|
+
expect(new IPAddress('2605:2700:0000:003:a800:00ff:fe10:f0d3').toString()).toBe('2605:2700::3:a800:ff:fe10:f0d3');
|
|
134
|
+
expect(new IPAddress('2605:2700:0000:03:a800:00ff:fe10:f0d3').toString()).toBe('2605:2700::3:a800:ff:fe10:f0d3');
|
|
135
|
+
expect(new IPAddress('2605:2700:0000:03:a800:ff:fe10:f0d3').toString()).toBe('2605:2700::3:a800:ff:fe10:f0d3');
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
it('it should detect the kind of ip6', () => {
|
|
139
|
+
expect(new IPAddress('2605:2700:0000:0003:a800:00ff:fe10:f0d3').kind()).toBe(6);
|
|
140
|
+
for(let i = 0; i < 100; i++)
|
|
141
|
+
expect(IPAddress.randomIP6().kind()).toBe(6)
|
|
142
|
+
})
|
|
143
|
+
|
|
144
|
+
it('randomPad return valid ipv6 results be compareable with equals', () => {
|
|
145
|
+
let compared = 0
|
|
146
|
+
while(compared<500) {
|
|
147
|
+
const ip1 = IPAddress.randomIP6()
|
|
148
|
+
const ip2 = ip1.randomPad()
|
|
149
|
+
expect(ip1.kind()).toBe(6)
|
|
150
|
+
if (ip1.toString()!==ip2) { // find ips they are padded from the original
|
|
151
|
+
compared++
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
expect(IPAddress.validate(ip2)).toBe(true)
|
|
155
|
+
expect(ip1.equals(IPAddress.fromString(ip2))).toBe(true)
|
|
156
|
+
}
|
|
157
|
+
})
|
|
158
|
+
|
|
159
|
+
})
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
describe('IPAddress asciiChecksum', () => {
|
|
164
|
+
it('should return the correct checksum for ipv4', () => {
|
|
165
|
+
expect(new IPAddress('1.2.3.4').asciiChecksum()).toBe('e')
|
|
166
|
+
expect(new IPAddress('1.2.3.6').asciiChecksum()).toBe('i')
|
|
167
|
+
})
|
|
168
|
+
|
|
169
|
+
it('should return the correct checksum for ipv6', () => {
|
|
170
|
+
expect(new IPAddress('::').asciiChecksum()).toBe('a')
|
|
171
|
+
expect(new IPAddress('::1').asciiChecksum()).toBe('a')
|
|
172
|
+
expect(new IPAddress('::f').asciiChecksum()).toBe('s')
|
|
173
|
+
})
|
|
174
|
+
|
|
175
|
+
it('it should always return a single character ipv4/v6', () => {
|
|
176
|
+
for(let i=0;i<10000;i++) {
|
|
177
|
+
expect(new IPAddress(randomIP()).asciiChecksum().length).toBe(1)
|
|
178
|
+
expect(new IPAddress(randomIP6()).asciiChecksum().length).toBe(1)
|
|
179
|
+
}
|
|
180
|
+
})
|
|
181
|
+
|
|
182
|
+
it('it should return a-z0-9 ascii only',()=>{
|
|
183
|
+
for(let i=0;i<10000;i++) {
|
|
184
|
+
expect('abcdefghijklmnopqrstuvwxyz0123456789').toContain(new IPAddress(randomIP()).asciiChecksum())
|
|
185
|
+
expect('abcdefghijklmnopqrstuvwxyz0123456789').toContain(new IPAddress(randomIP6()).asciiChecksum())
|
|
186
|
+
}
|
|
187
|
+
})
|
|
188
|
+
})
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import { randomIP, randomIP6, isLoopbackIP, isLANIp } from "./../"
|
|
2
|
+
import ip6addr, { Addr, ToStringOpts } from 'ip6addr'
|
|
3
|
+
const ip6 = require('ip6') // "url": "https://github.com/elgs/ip6"
|
|
4
|
+
// need version "ip6": "0.2.7",!!
|
|
5
|
+
|
|
6
|
+
export class IPAddress {
|
|
7
|
+
private _ip: Addr
|
|
8
|
+
|
|
9
|
+
constructor(ip: string) { // may throw
|
|
10
|
+
if (ip === '-') ip = '0.0.0.0'
|
|
11
|
+
|
|
12
|
+
try {
|
|
13
|
+
this._ip = ip6addr.parse(ip)
|
|
14
|
+
} catch (err) {
|
|
15
|
+
if (err instanceof Error)
|
|
16
|
+
throw new Error(`IPAddress: '${ip}' Error: ${err.message}`)
|
|
17
|
+
throw err
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
public toString(opts: ToStringOpts = { format: 'auto', zeroElide: false, zeroPad: false }): string {
|
|
22
|
+
return this._ip.toString()
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
public static validate(ip: string): boolean {
|
|
26
|
+
try {
|
|
27
|
+
new IPAddress(ip)
|
|
28
|
+
return true
|
|
29
|
+
} catch (_) {
|
|
30
|
+
return false
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
public static try(ip: string): IPAddress | undefined {
|
|
35
|
+
try {
|
|
36
|
+
return new IPAddress(ip)
|
|
37
|
+
} catch (_) {
|
|
38
|
+
return undefined
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
public static fromString(ip: string): IPAddress {
|
|
43
|
+
return new IPAddress(ip)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
public static get Empty(): IPAddress {
|
|
47
|
+
//The IP address 0.0.0.0 is a non-routable meta-address used to denote an invalid, unknown,
|
|
48
|
+
// or non-applicable target. It's not assigned to any individual device.
|
|
49
|
+
// It is used in different contexts to mean "any IPv4-enabled network interface" or as a default route
|
|
50
|
+
return new IPAddress('0.0.0.0')
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
public isLoopbackIP(): boolean {
|
|
54
|
+
return isLoopbackIP(this._ip.toString())
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
public isLANIP(): boolean {
|
|
58
|
+
return isLANIp(this._ip.toString())
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
public isPublicIP(): boolean {
|
|
62
|
+
return !this.isLoopbackIP() && !this.isLANIP() && this.toString() !== '0.0.0.0'
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
public static unserialize(serializedIpString: string): IPAddress {
|
|
66
|
+
if (serializedIpString.length === 32) {
|
|
67
|
+
// we have possible ipv6
|
|
68
|
+
let ip = serializedIpString.match(/.{1,4}/g)?.join(':')
|
|
69
|
+
if (ip) return new IPAddress(ip)
|
|
70
|
+
}
|
|
71
|
+
// we have possible ipv4
|
|
72
|
+
let ip = serializedIpString.match(/.{1,3}/g)?.join('.')
|
|
73
|
+
if (ip)
|
|
74
|
+
try { return new IPAddress(ip) } catch (_) { }
|
|
75
|
+
|
|
76
|
+
throw new Error(`Invalid SerializationString: ${serializedIpString}`)
|
|
77
|
+
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
public static randomIP4(): IPAddress {
|
|
81
|
+
return new IPAddress(randomIP())
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
public static randomIP6(): IPAddress {
|
|
86
|
+
return new IPAddress(randomIP6())
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
public serialize(): string {
|
|
90
|
+
if (this.kind() === 4) {
|
|
91
|
+
// zero pad ipv4
|
|
92
|
+
return this._ip.toString().split('.').map((octet) => {
|
|
93
|
+
return octet.padStart(3, '0')
|
|
94
|
+
}).join('.').replace(/\./g, '')
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// zero pad ipv6
|
|
98
|
+
return ip6.normalize(this._ip.toString()).split(':').map((hextet: string) => {
|
|
99
|
+
return hextet.padStart(4, '0')
|
|
100
|
+
}).join(':').replace(/:/g, '')
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
public kind(): number {
|
|
104
|
+
return this._ip.kind() === 'ipv6' ? 6 : 4
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
public equals(secondIp: IPAddress): boolean {
|
|
108
|
+
return this._ip.compare(secondIp._ip) === 0
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
public randomPad(): string {
|
|
112
|
+
if (this.kind() === 4) return this.#padIp4()
|
|
113
|
+
return this.#padIp6()
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
public normalized(): string {
|
|
117
|
+
if (this.kind() === 4) return this._ip.toString()
|
|
118
|
+
return ip6.normalize(this._ip.toString())
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
public abbreviated(): string {
|
|
122
|
+
if (this.kind() === 4) return this._ip.toString()
|
|
123
|
+
return ip6.abbreviate(this._ip.toString())
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
#padIp6(): string {
|
|
127
|
+
const hextets = this.normalized().split(':') // we need to have the full form
|
|
128
|
+
const paddedHextets = hextets.map(hextet => {
|
|
129
|
+
const cleanHextet = Number(`0x${hextet}`).toString(16)
|
|
130
|
+
const padLength = Math.floor(Math.random() * (4 - cleanHextet.length))
|
|
131
|
+
return cleanHextet.padStart(padLength + cleanHextet.length, '0')
|
|
132
|
+
})
|
|
133
|
+
|
|
134
|
+
return paddedHextets.join(':')
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
#padIp4(): string {
|
|
138
|
+
const octets = this._ip.toString().split('.')
|
|
139
|
+
const paddedOctets = octets.map(octet => {
|
|
140
|
+
const cleanOctet = String(Number(octet))
|
|
141
|
+
const padLength = Math.floor(Math.random() * (3 - cleanOctet.length))
|
|
142
|
+
return cleanOctet.padStart(padLength + cleanOctet.length, '0')
|
|
143
|
+
});
|
|
144
|
+
return paddedOctets.join('.')
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
asciiChecksum(): string {
|
|
148
|
+
// support ipv4 and ipv6
|
|
149
|
+
// FNV-1a hash parameters
|
|
150
|
+
const FNV_PRIME = 0x01000193;
|
|
151
|
+
const FNV_OFFSET_BASIS = 0x811c9dc5;
|
|
152
|
+
const CHAR_SET = 'abcdefghijklmnopqrstuvwxyz0123456789';
|
|
153
|
+
|
|
154
|
+
let hash = FNV_OFFSET_BASIS;
|
|
155
|
+
const ip = this.normalized()
|
|
156
|
+
for (let i = 0; i < ip.length; i++) {
|
|
157
|
+
hash ^= ip.charCodeAt(i);
|
|
158
|
+
hash *= FNV_PRIME;
|
|
159
|
+
hash >>>= 0; // Ensure hash is always a positive 32-bit integer
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Map the hash to a character in the CHAR_SET
|
|
163
|
+
const index = hash % CHAR_SET.length;
|
|
164
|
+
return CHAR_SET.charAt(index);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
checksum1(): string {
|
|
168
|
+
// this shall check that the ip is ipv4 and return the last octet as checksum
|
|
169
|
+
if (this.kind() !== 4) return 'x'
|
|
170
|
+
return this._ip.toString().split('.').pop() || '-'
|
|
171
|
+
}
|
|
172
|
+
}
|
package/ts/models/Unixtime.js
CHANGED
|
@@ -35,9 +35,15 @@ class Unixtime {
|
|
|
35
35
|
// set the value
|
|
36
36
|
this.value = new Date(value);
|
|
37
37
|
}
|
|
38
|
-
else {
|
|
38
|
+
else if (value instanceof Date) {
|
|
39
39
|
this.value = value;
|
|
40
40
|
}
|
|
41
|
+
else {
|
|
42
|
+
throw new Error('Invalid value');
|
|
43
|
+
}
|
|
44
|
+
if (isNaN(this.value.getTime())) {
|
|
45
|
+
throw new Error('Invalid date');
|
|
46
|
+
}
|
|
41
47
|
}
|
|
42
48
|
addTimespan(timespan) {
|
|
43
49
|
this.value = new Date(this.value.getTime() + timespan.miliseconds);
|
|
@@ -93,6 +99,9 @@ class Unixtime {
|
|
|
93
99
|
(hh > 9 ? '' : '0') + hh
|
|
94
100
|
].join('');
|
|
95
101
|
}
|
|
102
|
+
getDay() {
|
|
103
|
+
return this.value.getDay();
|
|
104
|
+
}
|
|
96
105
|
static from(value) {
|
|
97
106
|
return new Unixtime(value);
|
|
98
107
|
}
|
|
@@ -114,6 +123,14 @@ class Unixtime {
|
|
|
114
123
|
elapsedMinutes() {
|
|
115
124
|
return Math.round(this.elapsedSeconds() / 60);
|
|
116
125
|
}
|
|
126
|
+
static try(value) {
|
|
127
|
+
try {
|
|
128
|
+
return new Unixtime(value);
|
|
129
|
+
}
|
|
130
|
+
catch (e) {
|
|
131
|
+
return null;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
117
134
|
}
|
|
118
135
|
exports.Unixtime = Unixtime;
|
|
119
136
|
Unixtime.EMPTY = new Unixtime(new Date(0));
|
|
@@ -7,6 +7,10 @@ describe('Unixtime', () => {
|
|
|
7
7
|
expect(unixtime.toDate()).toEqual(date);
|
|
8
8
|
});
|
|
9
9
|
|
|
10
|
+
it('create invalid date should throw error', () => {
|
|
11
|
+
expect(() => new Unixtime('invalid date')).toThrow();
|
|
12
|
+
})
|
|
13
|
+
|
|
10
14
|
it('should create Unixtime object from string', () => {
|
|
11
15
|
const dateString = '2022-01-01T00:00:00Z';
|
|
12
16
|
const date = new Date(dateString);
|
package/ts/models/Unixtime.ts
CHANGED
|
@@ -42,8 +42,16 @@ export class Unixtime {
|
|
|
42
42
|
value = Math.round(value)
|
|
43
43
|
// set the value
|
|
44
44
|
this.value = new Date(value)
|
|
45
|
-
}
|
|
45
|
+
}
|
|
46
|
+
else if (value instanceof Date) {
|
|
46
47
|
this.value = value
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
throw new Error('Invalid value')
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (isNaN(this.value.getTime())) {
|
|
54
|
+
throw new Error('Invalid date')
|
|
47
55
|
}
|
|
48
56
|
}
|
|
49
57
|
|
|
@@ -113,6 +121,10 @@ export class Unixtime {
|
|
|
113
121
|
}
|
|
114
122
|
|
|
115
123
|
|
|
124
|
+
public getDay() : number {
|
|
125
|
+
return this.value.getDay()
|
|
126
|
+
}
|
|
127
|
+
|
|
116
128
|
static from(value: Date | string | number) {
|
|
117
129
|
return new Unixtime(value)
|
|
118
130
|
}
|
|
@@ -141,4 +153,12 @@ export class Unixtime {
|
|
|
141
153
|
return Math.round(this.elapsedSeconds() / 60)
|
|
142
154
|
}
|
|
143
155
|
|
|
156
|
+
|
|
157
|
+
static try(value: Date | string | number): Unixtime | null {
|
|
158
|
+
try {
|
|
159
|
+
return new Unixtime(value)
|
|
160
|
+
} catch (e) {
|
|
161
|
+
return null
|
|
162
|
+
}
|
|
163
|
+
}
|
|
144
164
|
}
|