@20syldev/api 4.7.0 → 4.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +84 -47
- package/dist/app.js +6 -6
- package/dist/app.js.map +1 -1
- package/dist/config/env.js.map +1 -1
- package/dist/config/versions.js +22 -3
- package/dist/config/versions.js.map +1 -1
- package/dist/constants.js +27 -12
- package/dist/constants.js.map +1 -1
- package/dist/middleware/error.js +2 -2
- package/dist/middleware/error.js.map +1 -1
- package/dist/middleware/logger.js.map +1 -1
- package/dist/middleware/ratelimit.js +2 -2
- package/dist/middleware/ratelimit.js.map +1 -1
- package/dist/middleware/version.js.map +1 -1
- package/dist/modules/v3.js +1 -1
- package/dist/modules/v3.js.map +1 -1
- package/{src/modules/v4/address.ts → dist/modules/v4/address.js} +14 -46
- package/dist/modules/v4/address.js.map +1 -0
- package/{src/modules/v4/agent.ts → dist/modules/v4/agent.js} +26 -38
- package/dist/modules/v4/agent.js.map +1 -0
- package/dist/modules/v4/algorithms.js +79 -0
- package/dist/modules/v4/algorithms.js.map +1 -1
- package/dist/modules/v4/avatar.js +136 -0
- package/dist/modules/v4/avatar.js.map +1 -0
- package/dist/modules/v4/barcode.js +440 -0
- package/dist/modules/v4/barcode.js.map +1 -0
- package/dist/modules/v4/captcha.js +7 -0
- package/dist/modules/v4/captcha.js.map +1 -1
- package/dist/modules/v4/chat.js +9 -1
- package/dist/modules/v4/chat.js.map +1 -1
- package/dist/modules/v4/color.js +8 -1
- package/dist/modules/v4/color.js.map +1 -1
- package/dist/modules/v4/convert.js +9 -0
- package/dist/modules/v4/convert.js.map +1 -1
- package/dist/modules/v4/credit.js +104 -0
- package/dist/modules/v4/credit.js.map +1 -0
- package/dist/modules/v4/cron.js +202 -0
- package/dist/modules/v4/cron.js.map +1 -0
- package/dist/modules/v4/dice.js +7 -0
- package/dist/modules/v4/dice.js.map +1 -1
- package/dist/modules/v4/domain.js +6 -1
- package/dist/modules/v4/domain.js.map +1 -1
- package/dist/modules/v4/encode.js +71 -0
- package/dist/modules/v4/encode.js.map +1 -1
- package/dist/modules/v4/geo.js +11 -1
- package/dist/modules/v4/geo.js.map +1 -1
- package/dist/modules/v4/hash.js +10 -1
- package/dist/modules/v4/hash.js.map +1 -1
- package/dist/modules/v4/hyperplanning.js +9 -1
- package/dist/modules/v4/hyperplanning.js.map +1 -1
- package/{src/modules/v4/ip.ts → dist/modules/v4/ip.js} +58 -60
- package/dist/modules/v4/ip.js.map +1 -0
- package/dist/modules/v4/levenshtein.js +8 -0
- package/dist/modules/v4/levenshtein.js.map +1 -1
- package/dist/modules/v4/palette.js +9 -1
- package/dist/modules/v4/palette.js.map +1 -1
- package/{src/modules/v4/password.ts → dist/modules/v4/password.js} +25 -63
- package/dist/modules/v4/password.js.map +1 -0
- package/dist/modules/v4/personal.js +14 -18
- package/dist/modules/v4/personal.js.map +1 -1
- package/dist/modules/v4/placeholder.js +8 -0
- package/dist/modules/v4/placeholder.js.map +1 -1
- package/dist/modules/v4/qrcode.js +10 -3
- package/dist/modules/v4/qrcode.js.map +1 -1
- package/dist/modules/v4/regex.js +48 -0
- package/dist/modules/v4/regex.js.map +1 -0
- package/dist/modules/v4/statistics.js +7 -0
- package/dist/modules/v4/statistics.js.map +1 -1
- package/dist/modules/v4/text.js +30 -0
- package/dist/modules/v4/text.js.map +1 -1
- package/dist/modules/v4/tic_tac_toe.js +9 -1
- package/dist/modules/v4/tic_tac_toe.js.map +1 -1
- package/dist/modules/v4/time.js +62 -11
- package/dist/modules/v4/time.js.map +1 -1
- package/dist/modules/v4/token.js +17 -8
- package/dist/modules/v4/token.js.map +1 -1
- package/dist/modules/v4/username.js +5 -0
- package/dist/modules/v4/username.js.map +1 -1
- package/dist/modules/v4/validate.js +21 -0
- package/dist/modules/v4/validate.js.map +1 -1
- package/dist/modules/v4.js +10 -1
- package/dist/modules/v4.js.map +1 -1
- package/dist/routes/delete.js.map +1 -1
- package/dist/routes/get.js +208 -48
- package/dist/routes/get.js.map +1 -1
- package/dist/routes/index.js +2 -2
- package/dist/routes/index.js.map +1 -1
- package/dist/routes/patch.js.map +1 -1
- package/dist/routes/post.js +2 -2
- package/dist/routes/post.js.map +1 -1
- package/dist/utils/response.js.map +1 -1
- package/package.json +2 -1
- package/.github/FUNDING.yml +0 -1
- package/.prettierrc +0 -7
- package/eslint.config.js +0 -24
- package/robots.txt +0 -74
- package/src/app.ts +0 -53
- package/src/config/env.ts +0 -87
- package/src/config/plans.ts +0 -61
- package/src/config/versions.ts +0 -119
- package/src/constants.ts +0 -46
- package/src/favicon.ico +0 -0
- package/src/middleware/cors.ts +0 -23
- package/src/middleware/error.ts +0 -16
- package/src/middleware/json.ts +0 -9
- package/src/middleware/logger.ts +0 -32
- package/src/middleware/ratelimit.ts +0 -89
- package/src/middleware/version.ts +0 -40
- package/src/modules/v3/algorithms.js +0 -218
- package/src/modules/v3/captcha.js +0 -60
- package/src/modules/v3/chat.js +0 -111
- package/src/modules/v3/color.js +0 -60
- package/src/modules/v3/convert.js +0 -39
- package/src/modules/v3/domain.js +0 -86
- package/src/modules/v3/hash.js +0 -16
- package/src/modules/v3/hyperplanning.js +0 -56
- package/src/modules/v3/levenshtein.js +0 -46
- package/src/modules/v3/personal.js +0 -139
- package/src/modules/v3/qrcode.js +0 -20
- package/src/modules/v3/tic_tac_toe.js +0 -242
- package/src/modules/v3/time.js +0 -98
- package/src/modules/v3/token.js +0 -54
- package/src/modules/v3/username.js +0 -94
- package/src/modules/v3/utils.js +0 -77
- package/src/modules/v3.js +0 -15
- package/src/modules/v4/algorithms.ts +0 -276
- package/src/modules/v4/captcha.ts +0 -114
- package/src/modules/v4/chat.ts +0 -130
- package/src/modules/v4/color.ts +0 -75
- package/src/modules/v4/convert.ts +0 -127
- package/src/modules/v4/dice.ts +0 -46
- package/src/modules/v4/domain.ts +0 -86
- package/src/modules/v4/encode.ts +0 -241
- package/src/modules/v4/geo.ts +0 -63
- package/src/modules/v4/hash.ts +0 -32
- package/src/modules/v4/hyperplanning.ts +0 -93
- package/src/modules/v4/levenshtein.ts +0 -46
- package/src/modules/v4/palette.ts +0 -71
- package/src/modules/v4/personal.ts +0 -140
- package/src/modules/v4/placeholder.ts +0 -197
- package/src/modules/v4/qrcode.ts +0 -121
- package/src/modules/v4/statistics.ts +0 -62
- package/src/modules/v4/text.ts +0 -330
- package/src/modules/v4/tic_tac_toe.ts +0 -264
- package/src/modules/v4/time.ts +0 -103
- package/src/modules/v4/token.ts +0 -53
- package/src/modules/v4/username.ts +0 -94
- package/src/modules/v4/validate.ts +0 -76
- package/src/modules/v4.ts +0 -27
- package/src/routes/delete.ts +0 -72
- package/src/routes/get.ts +0 -835
- package/src/routes/index.ts +0 -59
- package/src/routes/patch.ts +0 -45
- package/src/routes/post.ts +0 -209
- package/src/storage/index.ts +0 -16
- package/src/types/express.d.ts +0 -17
- package/src/types/storage.ts +0 -48
- package/src/utils/colors.ts +0 -91
- package/src/utils/helpers.ts +0 -90
- package/src/utils/response.ts +0 -28
- package/tests/integration/api.test.ts +0 -716
- package/tests/tsconfig.json +0 -3
- package/tests/unit/address.test.ts +0 -84
- package/tests/unit/agent.test.ts +0 -113
- package/tests/unit/algorithms.test.ts +0 -121
- package/tests/unit/captcha.test.ts +0 -62
- package/tests/unit/chat.test.ts +0 -54
- package/tests/unit/color.test.ts +0 -54
- package/tests/unit/convert.test.ts +0 -68
- package/tests/unit/dice.test.ts +0 -58
- package/tests/unit/domain.test.ts +0 -48
- package/tests/unit/encode.test.ts +0 -109
- package/tests/unit/geo.test.ts +0 -46
- package/tests/unit/hash.test.ts +0 -45
- package/tests/unit/hyperplanning.test.ts +0 -97
- package/tests/unit/ip.test.ts +0 -140
- package/tests/unit/levenshtein.test.ts +0 -35
- package/tests/unit/palette.test.ts +0 -54
- package/tests/unit/password.test.ts +0 -86
- package/tests/unit/personal.test.ts +0 -66
- package/tests/unit/placeholder.test.ts +0 -58
- package/tests/unit/qrcode.test.ts +0 -83
- package/tests/unit/statistics.test.ts +0 -58
- package/tests/unit/text.test.ts +0 -108
- package/tests/unit/tic_tac_toe.test.ts +0 -56
- package/tests/unit/time.test.ts +0 -68
- package/tests/unit/token.test.ts +0 -62
- package/tests/unit/username.test.ts +0 -35
- package/tests/unit/validate.test.ts +0 -72
- package/tsconfig.json +0 -17
- package/tsconfig.test.json +0 -9
package/tests/tsconfig.json
DELETED
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
import { strict as assert } from 'node:assert';
|
|
2
|
-
import { describe, test } from 'node:test';
|
|
3
|
-
|
|
4
|
-
import address from '../../src/modules/v4/address.js';
|
|
5
|
-
|
|
6
|
-
describe('address', () => {
|
|
7
|
-
describe('default behavior', () => {
|
|
8
|
-
test('returns an addresses array with one entry by default', () => {
|
|
9
|
-
const r = address();
|
|
10
|
-
assert.equal(r.addresses.length, 1);
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
test('each address has required fields', () => {
|
|
14
|
-
const r = address();
|
|
15
|
-
const a = r.addresses[0]!;
|
|
16
|
-
assert.ok(a.street);
|
|
17
|
-
assert.ok(a.city);
|
|
18
|
-
assert.ok(a.zip);
|
|
19
|
-
assert.ok(a.state);
|
|
20
|
-
assert.ok(a.country);
|
|
21
|
-
assert.ok(a.countryCode);
|
|
22
|
-
});
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
describe('country filtering', () => {
|
|
26
|
-
test('fr returns a French address', () => {
|
|
27
|
-
const r = address('fr');
|
|
28
|
-
assert.equal(r.addresses[0]!.countryCode, 'FR');
|
|
29
|
-
assert.equal(r.addresses[0]!.country, 'France');
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
test('us returns a US address', () => {
|
|
33
|
-
const r = address('us');
|
|
34
|
-
assert.equal(r.addresses[0]!.countryCode, 'US');
|
|
35
|
-
assert.equal(r.addresses[0]!.country, 'United States');
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
test('uk returns a UK address', () => {
|
|
39
|
-
const r = address('uk');
|
|
40
|
-
assert.equal(r.addresses[0]!.countryCode, 'UK');
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
test('de returns a German address', () => {
|
|
44
|
-
const r = address('de');
|
|
45
|
-
assert.equal(r.addresses[0]!.countryCode, 'DE');
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
test('es returns a Spanish address', () => {
|
|
49
|
-
const r = address('es');
|
|
50
|
-
assert.equal(r.addresses[0]!.countryCode, 'ES');
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
test('country code is case-insensitive', () => {
|
|
54
|
-
const r = address('FR');
|
|
55
|
-
assert.equal(r.addresses[0]!.countryCode, 'FR');
|
|
56
|
-
});
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
describe('count', () => {
|
|
60
|
-
test('count=5 returns 5 addresses', () => {
|
|
61
|
-
const r = address('fr', 5);
|
|
62
|
-
assert.equal(r.addresses.length, 5);
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
test('count=10 returns 10 addresses', () => {
|
|
66
|
-
const r = address('us', 10);
|
|
67
|
-
assert.equal(r.addresses.length, 10);
|
|
68
|
-
});
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
describe('errors', () => {
|
|
72
|
-
test('unknown country throws', () => {
|
|
73
|
-
assert.throws(() => address('xx'), /Unknown country code/);
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
test('count=0 throws', () => {
|
|
77
|
-
assert.throws(() => address('fr', 0), /Count must be between/);
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
test('count=11 throws', () => {
|
|
81
|
-
assert.throws(() => address('fr', 11), /Count must be between/);
|
|
82
|
-
});
|
|
83
|
-
});
|
|
84
|
-
});
|
package/tests/unit/agent.test.ts
DELETED
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
import { strict as assert } from 'node:assert';
|
|
2
|
-
import { describe, test } from 'node:test';
|
|
3
|
-
|
|
4
|
-
import agent from '../../src/modules/v4/agent.js';
|
|
5
|
-
|
|
6
|
-
const CHROME_MAC =
|
|
7
|
-
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36';
|
|
8
|
-
const FIREFOX_WIN = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:121.0) Gecko/20100101 Firefox/121.0';
|
|
9
|
-
const SAFARI_IPHONE =
|
|
10
|
-
'Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Mobile/15E148 Safari/604.1';
|
|
11
|
-
const EDGE_WIN =
|
|
12
|
-
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0';
|
|
13
|
-
const GOOGLEBOT = 'Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)';
|
|
14
|
-
const IPAD =
|
|
15
|
-
'Mozilla/5.0 (iPad; CPU OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Mobile/15E148 Safari/604.1';
|
|
16
|
-
|
|
17
|
-
describe('agent', () => {
|
|
18
|
-
describe('browser detection', () => {
|
|
19
|
-
test('Chrome on macOS', () => {
|
|
20
|
-
const r = agent(CHROME_MAC);
|
|
21
|
-
assert.equal(r.browser.name, 'Chrome');
|
|
22
|
-
assert.equal(r.browser.major, '120');
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
test('Firefox on Windows', () => {
|
|
26
|
-
const r = agent(FIREFOX_WIN);
|
|
27
|
-
assert.equal(r.browser.name, 'Firefox');
|
|
28
|
-
assert.equal(r.browser.major, '121');
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
test('Safari on iPhone', () => {
|
|
32
|
-
const r = agent(SAFARI_IPHONE);
|
|
33
|
-
assert.equal(r.browser.name, 'Safari');
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
test('Edge detected before Chrome (both present in UA)', () => {
|
|
37
|
-
const r = agent(EDGE_WIN);
|
|
38
|
-
assert.equal(r.browser.name, 'Edge');
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
test('unknown browser returns unknown', () => {
|
|
42
|
-
const r = agent('UnknownBrowser/1.0');
|
|
43
|
-
assert.equal(r.browser.name, 'unknown');
|
|
44
|
-
});
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
describe('OS detection', () => {
|
|
48
|
-
test('macOS from Chrome UA', () => {
|
|
49
|
-
const r = agent(CHROME_MAC);
|
|
50
|
-
assert.equal(r.os.name, 'macOS');
|
|
51
|
-
assert.equal(r.os.version, '10.15.7');
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
test('Windows 10/11 from Firefox UA', () => {
|
|
55
|
-
const r = agent(FIREFOX_WIN);
|
|
56
|
-
assert.equal(r.os.name, 'Windows 10/11');
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
test('iOS from iPhone UA', () => {
|
|
60
|
-
const r = agent(SAFARI_IPHONE);
|
|
61
|
-
assert.equal(r.os.name, 'iOS');
|
|
62
|
-
assert.equal(r.os.version, '17.0');
|
|
63
|
-
});
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
describe('device detection', () => {
|
|
67
|
-
test('desktop from Chrome macOS', () => {
|
|
68
|
-
assert.equal(agent(CHROME_MAC).device.type, 'desktop');
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
test('mobile from iPhone UA', () => {
|
|
72
|
-
assert.equal(agent(SAFARI_IPHONE).device.type, 'mobile');
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
test('tablet from iPad UA', () => {
|
|
76
|
-
assert.equal(agent(IPAD).device.type, 'tablet');
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
test('Apple vendor from iPhone', () => {
|
|
80
|
-
assert.equal(agent(SAFARI_IPHONE).device.vendor, 'Apple');
|
|
81
|
-
});
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
describe('engine detection', () => {
|
|
85
|
-
test('Chrome uses Blink', () => {
|
|
86
|
-
assert.equal(agent(CHROME_MAC).engine.name, 'Blink');
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
test('Firefox uses Gecko', () => {
|
|
90
|
-
assert.equal(agent(FIREFOX_WIN).engine.name, 'Gecko');
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
test('Edge uses Blink', () => {
|
|
94
|
-
assert.equal(agent(EDGE_WIN).engine.name, 'Blink');
|
|
95
|
-
});
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
describe('bot detection', () => {
|
|
99
|
-
test('Googlebot is a bot', () => {
|
|
100
|
-
assert.equal(agent(GOOGLEBOT).bot, true);
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
test('Chrome is not a bot', () => {
|
|
104
|
-
assert.equal(agent(CHROME_MAC).bot, false);
|
|
105
|
-
});
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
describe('errors', () => {
|
|
109
|
-
test('throws on empty string', () => {
|
|
110
|
-
assert.throws(() => agent(''), /required/);
|
|
111
|
-
});
|
|
112
|
-
});
|
|
113
|
-
});
|
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
import { strict as assert } from 'node:assert';
|
|
2
|
-
import { describe, test } from 'node:test';
|
|
3
|
-
|
|
4
|
-
import {
|
|
5
|
-
anagram,
|
|
6
|
-
factorial,
|
|
7
|
-
fibonacci,
|
|
8
|
-
gcd,
|
|
9
|
-
isprime,
|
|
10
|
-
palindrome,
|
|
11
|
-
primefactors,
|
|
12
|
-
reverse,
|
|
13
|
-
roman,
|
|
14
|
-
} from '../../src/modules/v4/algorithms.js';
|
|
15
|
-
|
|
16
|
-
describe('algorithms', () => {
|
|
17
|
-
describe('anagram', () => {
|
|
18
|
-
test('listen / silent', () => {
|
|
19
|
-
assert.equal(anagram('listen', 'silent'), true);
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
test('hello / world', () => {
|
|
23
|
-
assert.equal(anagram('hello', 'world'), false);
|
|
24
|
-
});
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
describe('factorial', () => {
|
|
28
|
-
test('5! = 120', () => {
|
|
29
|
-
assert.equal(factorial(5), 120);
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
test('0! = 1', () => {
|
|
33
|
-
assert.equal(factorial(0), 1);
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
test('throws on negative', () => {
|
|
37
|
-
assert.throws(() => factorial(-1), /positive/);
|
|
38
|
-
});
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
describe('fibonacci', () => {
|
|
42
|
-
test('first 10 values', () => {
|
|
43
|
-
assert.deepEqual(fibonacci(10), [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]);
|
|
44
|
-
});
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
describe('gcd', () => {
|
|
48
|
-
test('gcd(12, 18) = 6', () => {
|
|
49
|
-
assert.equal(gcd(12, 18), 6);
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
test('gcd(7, 13) = 1', () => {
|
|
53
|
-
assert.equal(gcd(7, 13), 1);
|
|
54
|
-
});
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
describe('isprime', () => {
|
|
58
|
-
test('17 is prime', () => {
|
|
59
|
-
assert.equal(isprime(17), true);
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
test('15 is not prime', () => {
|
|
63
|
-
assert.equal(isprime(15), false);
|
|
64
|
-
});
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
describe('palindrome', () => {
|
|
68
|
-
test('madam is palindrome', () => {
|
|
69
|
-
assert.equal(palindrome('madam'), true);
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
test('hello is not', () => {
|
|
73
|
-
assert.equal(palindrome('hello'), false);
|
|
74
|
-
});
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
describe('primefactors', () => {
|
|
78
|
-
test('factors of 60', () => {
|
|
79
|
-
assert.deepEqual(primefactors(60), [2, 2, 3, 5]);
|
|
80
|
-
});
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
describe('reverse', () => {
|
|
84
|
-
test('reverses a string', () => {
|
|
85
|
-
assert.equal(reverse('abc'), 'cba');
|
|
86
|
-
});
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
describe('roman', () => {
|
|
90
|
-
test('2024 → MMXXIV', () => {
|
|
91
|
-
assert.equal(roman('2024'), 'MMXXIV');
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
test('MMXXIV → 2024', () => {
|
|
95
|
-
assert.equal(roman('MMXXIV'), 2024);
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
test('1 → I', () => {
|
|
99
|
-
assert.equal(roman('1'), 'I');
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
test('3999 → MMMCMXCIX', () => {
|
|
103
|
-
assert.equal(roman('3999'), 'MMMCMXCIX');
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
test('round-trip 1..100', () => {
|
|
107
|
-
for (let i = 1; i <= 100; i++) {
|
|
108
|
-
const r = roman(String(i));
|
|
109
|
-
assert.equal(roman(r as string), i);
|
|
110
|
-
}
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
test('throws on out of range', () => {
|
|
114
|
-
assert.throws(() => roman('4000'), /between 1 and 3999/);
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
test('throws on invalid roman', () => {
|
|
118
|
-
assert.throws(() => roman('XYZ'), /Invalid Roman/);
|
|
119
|
-
});
|
|
120
|
-
});
|
|
121
|
-
});
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import { strict as assert } from 'node:assert';
|
|
2
|
-
import { describe, test } from 'node:test';
|
|
3
|
-
|
|
4
|
-
import captcha from '../../src/modules/v4/captcha.js';
|
|
5
|
-
|
|
6
|
-
const PNG_MAGIC = Buffer.from([0x89, 0x50, 0x4e, 0x47]);
|
|
7
|
-
|
|
8
|
-
describe('captcha', () => {
|
|
9
|
-
test('returns PNG buffer with provided text', () => {
|
|
10
|
-
const result = captcha({ text: 'hello' });
|
|
11
|
-
assert.equal(result.contentType, 'image/png');
|
|
12
|
-
assert.ok(Buffer.isBuffer(result.body));
|
|
13
|
-
assert.ok(result.body.subarray(0, 4).equals(PNG_MAGIC));
|
|
14
|
-
assert.equal(result.text, 'hello');
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
test('auto-generates text when none provided', () => {
|
|
18
|
-
const result = captcha({});
|
|
19
|
-
assert.equal(result.text.length, 6);
|
|
20
|
-
assert.ok(Buffer.isBuffer(result.body));
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
test('respects custom length', () => {
|
|
24
|
-
const result = captcha({ length: 10 });
|
|
25
|
-
assert.equal(result.text.length, 10);
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
test('throws on invalid length', () => {
|
|
29
|
-
assert.throws(() => captcha({ length: 0 }), /length/);
|
|
30
|
-
assert.throws(() => captcha({ length: 99 }), /length/);
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
test('accepts custom dimensions', () => {
|
|
34
|
-
const result = captcha({ text: 'AB', width: 200, height: 80 });
|
|
35
|
-
assert.ok(Buffer.isBuffer(result.body));
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
test('throws on invalid dimensions', () => {
|
|
39
|
-
assert.throws(() => captcha({ text: 'AB', width: 10 }), /width/);
|
|
40
|
-
assert.throws(() => captcha({ text: 'AB', height: 500 }), /height/);
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
test('accepts noise levels', () => {
|
|
44
|
-
for (const noise of ['low', 'medium', 'high'] as const) {
|
|
45
|
-
const result = captcha({ text: 'test', noise });
|
|
46
|
-
assert.ok(Buffer.isBuffer(result.body));
|
|
47
|
-
}
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
test('throws on invalid noise', () => {
|
|
51
|
-
assert.throws(() => captcha({ text: 'test', noise: 'extreme' as 'low' }), /noise/);
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
test('accepts custom colors', () => {
|
|
55
|
-
const result = captcha({ text: 'test', bg: 'f0f0f0', color: '333333' });
|
|
56
|
-
assert.ok(Buffer.isBuffer(result.body));
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
test('throws on invalid color', () => {
|
|
60
|
-
assert.throws(() => captcha({ text: 'test', bg: 'xyz' }), /color/i);
|
|
61
|
-
});
|
|
62
|
-
});
|
package/tests/unit/chat.test.ts
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import { strict as assert } from 'node:assert';
|
|
2
|
-
import { describe, test } from 'node:test';
|
|
3
|
-
|
|
4
|
-
import chat from '../../src/modules/v4/chat.js';
|
|
5
|
-
import type { ChatStorage } from '../../src/types/storage.js';
|
|
6
|
-
|
|
7
|
-
function makeStorage(): ChatStorage {
|
|
8
|
-
return { messages: [], privateChats: {}, sessions: {}, rateLimits: {} };
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
describe('chat', () => {
|
|
12
|
-
test('sends a public message', () => {
|
|
13
|
-
const storage = makeStorage();
|
|
14
|
-
const result = chat('message', { username: 'alice', message: 'hello', session: 'a1', storage });
|
|
15
|
-
assert.ok((result as { message: string }).message.includes('sent'));
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
test('fetches public messages', () => {
|
|
19
|
-
const storage = makeStorage();
|
|
20
|
-
chat('message', { username: 'alice', message: 'test', session: 'a1', storage });
|
|
21
|
-
const result = chat('fetch', { username: 'bob', storage });
|
|
22
|
-
assert.ok(Array.isArray(result));
|
|
23
|
-
assert.equal((result as { message: string }[])[0]!.message, 'test');
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
test('sends and retrieves private messages', () => {
|
|
27
|
-
const storage = makeStorage();
|
|
28
|
-
chat('message', { username: 'alice', message: 'secret', session: 'a1', token: 'tok1', storage });
|
|
29
|
-
const result = chat('private', { username: 'bob', token: 'tok1', storage });
|
|
30
|
-
assert.ok(Array.isArray(result));
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
test('clears a private chat', () => {
|
|
34
|
-
const storage = makeStorage();
|
|
35
|
-
chat('message', { username: 'alice', message: 'secret', session: 'a1', token: 'tok2', storage });
|
|
36
|
-
const result = chat('clear', { username: 'alice', session: 'a1', token: 'tok2', storage });
|
|
37
|
-
assert.ok((result as { message: string }).message.includes('cleared'));
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
test('throws on missing username', () => {
|
|
41
|
-
assert.throws(
|
|
42
|
-
() => chat('message', { username: '', message: 'hi', session: 's', storage: makeStorage() }),
|
|
43
|
-
/username/,
|
|
44
|
-
);
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
test('throws on invalid action', () => {
|
|
48
|
-
assert.throws(() => chat('delete', { username: 'alice', storage: makeStorage() }), /Invalid action/);
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
test('throws on fetch with no messages', () => {
|
|
52
|
-
assert.throws(() => chat('fetch', { username: 'alice', storage: makeStorage() }), /No messages/);
|
|
53
|
-
});
|
|
54
|
-
});
|
package/tests/unit/color.test.ts
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import { strict as assert } from 'node:assert';
|
|
2
|
-
import { describe, test } from 'node:test';
|
|
3
|
-
|
|
4
|
-
import color from '../../src/modules/v4/color.js';
|
|
5
|
-
|
|
6
|
-
describe('color', () => {
|
|
7
|
-
test('returns all 6 formats', () => {
|
|
8
|
-
const result = color();
|
|
9
|
-
assert.ok('hex' in result);
|
|
10
|
-
assert.ok('rgb' in result);
|
|
11
|
-
assert.ok('hsl' in result);
|
|
12
|
-
assert.ok('hsv' in result);
|
|
13
|
-
assert.ok('hwb' in result);
|
|
14
|
-
assert.ok('cmyk' in result);
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
test('hex matches #RRGGBB', () => {
|
|
18
|
-
for (let i = 0; i < 20; i++) {
|
|
19
|
-
assert.match(color().hex, /^#[0-9a-f]{6}$/);
|
|
20
|
-
}
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
test('rgb format', () => {
|
|
24
|
-
assert.match(color().rgb, /^rgb\(\d{1,3}, \d{1,3}, \d{1,3}\)$/);
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
test('hsl format', () => {
|
|
28
|
-
assert.match(color().hsl, /^hsl\(\d+(\.\d+)?, \d+(\.\d+)?%, \d+(\.\d+)?%\)$/);
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
test('cmyk format with 4 channels', () => {
|
|
32
|
-
assert.match(color().cmyk, /^cmyk\(/);
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
test('accepts hex input', () => {
|
|
36
|
-
const result = color('#ff6600');
|
|
37
|
-
assert.equal(result.hex, '#ff6600');
|
|
38
|
-
assert.equal(result.rgb, 'rgb(255, 102, 0)');
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
test('accepts hex without #', () => {
|
|
42
|
-
const result = color('ff6600');
|
|
43
|
-
assert.equal(result.hex, '#ff6600');
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
test('throws on invalid hex', () => {
|
|
47
|
-
assert.throws(() => color('xyz'), /Invalid HEX/);
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
test('HSV correct for equal channels', () => {
|
|
51
|
-
const result = color('#808000');
|
|
52
|
-
assert.match(result.hsv, /^hsv\(60\.0,/);
|
|
53
|
-
});
|
|
54
|
-
});
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
import { strict as assert } from 'node:assert';
|
|
2
|
-
import { describe, test } from 'node:test';
|
|
3
|
-
|
|
4
|
-
import convert from '../../src/modules/v4/convert.js';
|
|
5
|
-
|
|
6
|
-
describe('convert', () => {
|
|
7
|
-
test('celsius to fahrenheit', () => {
|
|
8
|
-
const result = convert(0, 'celsius', 'fahrenheit');
|
|
9
|
-
assert.equal(result.result, 32);
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
test('celsius to kelvin', () => {
|
|
13
|
-
const result = convert(0, 'celsius', 'kelvin');
|
|
14
|
-
assert.equal(result.result, 273.15);
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
test('fahrenheit to celsius', () => {
|
|
18
|
-
const result = convert(32, 'fahrenheit', 'celsius');
|
|
19
|
-
assert.equal(result.result, 0);
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
test('kelvin to celsius', () => {
|
|
23
|
-
const result = convert(273.15, 'kelvin', 'celsius');
|
|
24
|
-
assert.equal(result.result, 0);
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
test('case-insensitive units', () => {
|
|
28
|
-
const result = convert(100, 'CELSIUS', 'Fahrenheit');
|
|
29
|
-
assert.equal(result.result, 212);
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
test('throws on invalid unit', () => {
|
|
33
|
-
assert.throws(() => convert(100, 'celsius', 'banana'), /Invalid conversion/);
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
test('throws on absolute zero violation', () => {
|
|
37
|
-
assert.throws(() => convert(-300, 'celsius', 'kelvin'), /absolute zero/);
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
test('km to mi', () => {
|
|
41
|
-
const result = convert(1, 'km', 'mi');
|
|
42
|
-
assert.ok(Math.abs(result.result - 0.621371) < 0.001);
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
test('kg to lb', () => {
|
|
46
|
-
const result = convert(1, 'kg', 'lb');
|
|
47
|
-
assert.ok(Math.abs(result.result - 2.20462) < 0.001);
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
test('kb to mb', () => {
|
|
51
|
-
const result = convert(1024, 'kb', 'mb');
|
|
52
|
-
assert.equal(result.result, 1);
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
test('km/h to mph', () => {
|
|
56
|
-
const result = convert(100, 'km/h', 'mph');
|
|
57
|
-
assert.ok(Math.abs(result.result - 62.1371) < 0.01);
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
test('negative values allowed for non-temperature', () => {
|
|
61
|
-
const result = convert(-5, 'km', 'mi');
|
|
62
|
-
assert.ok(result.result < 0);
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
test('throws on non-numeric value', () => {
|
|
66
|
-
assert.throws(() => convert(NaN, 'celsius', 'kelvin'), /must be a number/);
|
|
67
|
-
});
|
|
68
|
-
});
|
package/tests/unit/dice.test.ts
DELETED
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
import { strict as assert } from 'node:assert';
|
|
2
|
-
import { describe, test } from 'node:test';
|
|
3
|
-
|
|
4
|
-
import dice from '../../src/modules/v4/dice.js';
|
|
5
|
-
|
|
6
|
-
describe('dice', () => {
|
|
7
|
-
test('parses 2d6+3 notation', () => {
|
|
8
|
-
const result = dice('2d6+3');
|
|
9
|
-
assert.equal(result.count, 2);
|
|
10
|
-
assert.equal(result.sides, 6);
|
|
11
|
-
assert.equal(result.modifier, 3);
|
|
12
|
-
assert.equal(result.results.length, 2);
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
test('total includes positive modifier', () => {
|
|
16
|
-
const result = dice('1d2+10');
|
|
17
|
-
assert.equal(result.modifier, 10);
|
|
18
|
-
assert.ok(result.total === 11 || result.total === 12);
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
test('negative modifier', () => {
|
|
22
|
-
const result = dice('1d2-5');
|
|
23
|
-
assert.equal(result.modifier, -5);
|
|
24
|
-
assert.ok(result.total === -4 || result.total === -3);
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
test('default count of 1 when omitted', () => {
|
|
28
|
-
const result = dice('d20');
|
|
29
|
-
assert.equal(result.count, 1);
|
|
30
|
-
assert.equal(result.sides, 20);
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
test('all results are within 1..sides', () => {
|
|
34
|
-
for (let i = 0; i < 50; i++) {
|
|
35
|
-
const result = dice('5d10');
|
|
36
|
-
for (const r of result.results) {
|
|
37
|
-
assert.ok(r >= 1 && r <= 10, `result ${r} out of range`);
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
test('handles space instead of +', () => {
|
|
43
|
-
const result = dice('2d6 3');
|
|
44
|
-
assert.equal(result.modifier, 3);
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
test('throws on invalid notation', () => {
|
|
48
|
-
assert.throws(() => dice('2x6'), /Invalid notation/);
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
test('throws on too many dice', () => {
|
|
52
|
-
assert.throws(() => dice('200d6'), /between 1 and 100/);
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
test('throws on invalid sides', () => {
|
|
56
|
-
assert.throws(() => dice('2d1'), /between 2 and 1000/);
|
|
57
|
-
});
|
|
58
|
-
});
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import { strict as assert } from 'node:assert';
|
|
2
|
-
import { describe, test } from 'node:test';
|
|
3
|
-
|
|
4
|
-
import domain from '../../src/modules/v4/domain.js';
|
|
5
|
-
|
|
6
|
-
describe('domain', () => {
|
|
7
|
-
test('returns expected fields', () => {
|
|
8
|
-
const result = domain();
|
|
9
|
-
assert.ok('domain' in result);
|
|
10
|
-
assert.ok('full_domain' in result);
|
|
11
|
-
assert.ok('ip_address' in result);
|
|
12
|
-
assert.ok('dns_servers' in result);
|
|
13
|
-
assert.ok('country' in result);
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
test('domain has TLD', () => {
|
|
17
|
-
const result = domain();
|
|
18
|
-
assert.match(
|
|
19
|
-
result.domain as string,
|
|
20
|
-
/\.(com|fr|eu|dev|net|org|io|tech|biz|info|co|app|store|online|shop|tv)$/,
|
|
21
|
-
);
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
test('full_domain starts with subdomain', () => {
|
|
25
|
-
const result = domain();
|
|
26
|
-
const full = result.full_domain as string;
|
|
27
|
-
const dom = result.domain as string;
|
|
28
|
-
assert.ok(full.endsWith(dom));
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
test('ip_address is non-empty array', () => {
|
|
32
|
-
const result = domain();
|
|
33
|
-
const ips = result.ip_address as string[];
|
|
34
|
-
assert.ok(Array.isArray(ips));
|
|
35
|
-
assert.ok(ips.length >= 1);
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
test('seo_score in range 0..99', () => {
|
|
39
|
-
const result = domain();
|
|
40
|
-
const score = result.seo_score as number;
|
|
41
|
-
assert.ok(score >= 0 && score < 100);
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
test('ssl_certified is boolean', () => {
|
|
45
|
-
const result = domain();
|
|
46
|
-
assert.equal(typeof result.ssl_certified, 'boolean');
|
|
47
|
-
});
|
|
48
|
-
});
|