@moxon/api 6.0.0-pre
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/.prettierignore +5 -0
- package/LICENSE +28 -0
- package/README.md +277 -0
- package/dist/app.d.ts +2 -0
- package/dist/app.js +55 -0
- package/dist/app.js.map +1 -0
- package/dist/config/env.d.ts +22 -0
- package/dist/config/env.js +36 -0
- package/dist/config/env.js.map +1 -0
- package/dist/config/plans.d.ts +26 -0
- package/dist/config/plans.js +44 -0
- package/dist/config/plans.js.map +1 -0
- package/dist/config/versions.d.ts +18 -0
- package/dist/config/versions.js +248 -0
- package/dist/config/versions.js.map +1 -0
- package/dist/constants.d.ts +48 -0
- package/dist/constants.js +75 -0
- package/dist/constants.js.map +1 -0
- package/dist/middleware/cors.d.ts +2 -0
- package/dist/middleware/cors.js +31 -0
- package/dist/middleware/cors.js.map +1 -0
- package/dist/middleware/error.d.ts +4 -0
- package/dist/middleware/error.js +8 -0
- package/dist/middleware/error.js.map +1 -0
- package/dist/middleware/json.d.ts +2 -0
- package/dist/middleware/json.js +8 -0
- package/dist/middleware/json.js.map +1 -0
- package/dist/middleware/logger.d.ts +26 -0
- package/dist/middleware/logger.js +65 -0
- package/dist/middleware/logger.js.map +1 -0
- package/dist/middleware/ratelimit.d.ts +2 -0
- package/dist/middleware/ratelimit.js +83 -0
- package/dist/middleware/ratelimit.js.map +1 -0
- package/dist/middleware/version.d.ts +3 -0
- package/dist/middleware/version.js +30 -0
- package/dist/middleware/version.js.map +1 -0
- package/dist/modules/v4/address.d.ts +20 -0
- package/dist/modules/v4/address.js +381 -0
- package/dist/modules/v4/address.js.map +1 -0
- package/dist/modules/v4/agent.d.ts +30 -0
- package/dist/modules/v4/agent.js +92 -0
- package/dist/modules/v4/agent.js.map +1 -0
- package/dist/modules/v4/algorithms.d.ts +90 -0
- package/dist/modules/v4/algorithms.js +279 -0
- package/dist/modules/v4/algorithms.js.map +1 -0
- package/dist/modules/v4/avatar.d.ts +23 -0
- package/dist/modules/v4/avatar.js +136 -0
- package/dist/modules/v4/avatar.js.map +1 -0
- package/dist/modules/v4/barcode.d.ts +27 -0
- package/dist/modules/v4/barcode.js +440 -0
- package/dist/modules/v4/barcode.js.map +1 -0
- package/dist/modules/v4/captcha.d.ts +22 -0
- package/dist/modules/v4/captcha.js +79 -0
- package/dist/modules/v4/captcha.js.map +1 -0
- package/dist/modules/v4/chat.d.ts +21 -0
- package/dist/modules/v4/chat.js +100 -0
- package/dist/modules/v4/chat.js.map +1 -0
- package/dist/modules/v4/color.d.ts +16 -0
- package/dist/modules/v4/color.js +59 -0
- package/dist/modules/v4/color.js.map +1 -0
- package/dist/modules/v4/convert.d.ts +15 -0
- package/dist/modules/v4/convert.js +116 -0
- package/dist/modules/v4/convert.js.map +1 -0
- package/dist/modules/v4/credit.d.ts +22 -0
- package/dist/modules/v4/credit.js +104 -0
- package/dist/modules/v4/credit.js.map +1 -0
- package/dist/modules/v4/cron.d.ts +17 -0
- package/dist/modules/v4/cron.js +202 -0
- package/dist/modules/v4/cron.js.map +1 -0
- package/dist/modules/v4/dice.d.ts +16 -0
- package/dist/modules/v4/dice.js +37 -0
- package/dist/modules/v4/dice.js.map +1 -0
- package/dist/modules/v4/domain.d.ts +6 -0
- package/dist/modules/v4/domain.js +83 -0
- package/dist/modules/v4/domain.js.map +1 -0
- package/dist/modules/v4/encode.d.ts +81 -0
- package/dist/modules/v4/encode.js +236 -0
- package/dist/modules/v4/encode.js.map +1 -0
- package/dist/modules/v4/geo.d.ts +30 -0
- package/dist/modules/v4/geo.js +51 -0
- package/dist/modules/v4/geo.js.map +1 -0
- package/dist/modules/v4/hash.d.ts +15 -0
- package/dist/modules/v4/hash.js +25 -0
- package/dist/modules/v4/hash.js.map +1 -0
- package/dist/modules/v4/hyperplanning.d.ts +19 -0
- package/dist/modules/v4/hyperplanning.js +80 -0
- package/dist/modules/v4/hyperplanning.js.map +1 -0
- package/dist/modules/v4/ip.d.ts +19 -0
- package/dist/modules/v4/ip.js +132 -0
- package/dist/modules/v4/ip.js.map +1 -0
- package/dist/modules/v4/levenshtein.d.ts +13 -0
- package/dist/modules/v4/levenshtein.js +37 -0
- package/dist/modules/v4/levenshtein.js.map +1 -0
- package/dist/modules/v4/palette.d.ts +19 -0
- package/dist/modules/v4/palette.js +56 -0
- package/dist/modules/v4/palette.js.map +1 -0
- package/dist/modules/v4/password.d.ts +25 -0
- package/dist/modules/v4/password.js +343 -0
- package/dist/modules/v4/password.js.map +1 -0
- package/dist/modules/v4/personal.d.ts +6 -0
- package/dist/modules/v4/personal.js +121 -0
- package/dist/modules/v4/personal.js.map +1 -0
- package/dist/modules/v4/placeholder.d.ts +30 -0
- package/dist/modules/v4/placeholder.js +160 -0
- package/dist/modules/v4/placeholder.js.map +1 -0
- package/dist/modules/v4/qrcode.d.ts +25 -0
- package/dist/modules/v4/qrcode.js +92 -0
- package/dist/modules/v4/qrcode.js.map +1 -0
- package/dist/modules/v4/regex.d.ts +23 -0
- package/dist/modules/v4/regex.js +48 -0
- package/dist/modules/v4/regex.js.map +1 -0
- package/dist/modules/v4/statistics.d.ts +20 -0
- package/dist/modules/v4/statistics.js +48 -0
- package/dist/modules/v4/statistics.js.map +1 -0
- package/dist/modules/v4/text.d.ts +43 -0
- package/dist/modules/v4/text.js +323 -0
- package/dist/modules/v4/text.js.map +1 -0
- package/dist/modules/v4/tic_tac_toe.d.ts +19 -0
- package/dist/modules/v4/tic_tac_toe.js +214 -0
- package/dist/modules/v4/tic_tac_toe.js.map +1 -0
- package/dist/modules/v4/time.d.ts +15 -0
- package/dist/modules/v4/time.js +124 -0
- package/dist/modules/v4/time.js.map +1 -0
- package/dist/modules/v4/token.d.ts +9 -0
- package/dist/modules/v4/token.js +45 -0
- package/dist/modules/v4/token.js.map +1 -0
- package/dist/modules/v4/username.d.ts +6 -0
- package/dist/modules/v4/username.js +92 -0
- package/dist/modules/v4/username.js.map +1 -0
- package/dist/modules/v4/validate.d.ts +34 -0
- package/dist/modules/v4/validate.js +75 -0
- package/dist/modules/v4/validate.js.map +1 -0
- package/dist/modules/v4.d.ts +32 -0
- package/dist/modules/v4.js +33 -0
- package/dist/modules/v4.js.map +1 -0
- package/dist/modules/v5/address.d.ts +5 -0
- package/dist/modules/v5/address.js +20 -0
- package/dist/modules/v5/address.js.map +1 -0
- package/dist/modules/v5/algorithms.d.ts +9 -0
- package/dist/modules/v5/algorithms.js +39 -0
- package/dist/modules/v5/algorithms.js.map +1 -0
- package/dist/modules/v5/asymmetric.d.ts +26 -0
- package/dist/modules/v5/asymmetric.js +74 -0
- package/dist/modules/v5/asymmetric.js.map +1 -0
- package/dist/modules/v5/barcode.d.ts +27 -0
- package/dist/modules/v5/barcode.js +424 -0
- package/dist/modules/v5/barcode.js.map +1 -0
- package/dist/modules/v5/base.d.ts +16 -0
- package/dist/modules/v5/base.js +41 -0
- package/dist/modules/v5/base.js.map +1 -0
- package/dist/modules/v5/captcha.d.ts +27 -0
- package/dist/modules/v5/captcha.js +136 -0
- package/dist/modules/v5/captcha.js.map +1 -0
- package/dist/modules/v5/case.d.ts +10 -0
- package/dist/modules/v5/case.js +57 -0
- package/dist/modules/v5/case.js.map +1 -0
- package/dist/modules/v5/chart.d.ts +53 -0
- package/dist/modules/v5/chart.js +385 -0
- package/dist/modules/v5/chart.js.map +1 -0
- package/dist/modules/v5/chat.d.ts +21 -0
- package/dist/modules/v5/chat.js +107 -0
- package/dist/modules/v5/chat.js.map +1 -0
- package/dist/modules/v5/csv.d.ts +29 -0
- package/dist/modules/v5/csv.js +143 -0
- package/dist/modules/v5/csv.js.map +1 -0
- package/dist/modules/v5/diff.d.ts +20 -0
- package/dist/modules/v5/diff.js +81 -0
- package/dist/modules/v5/diff.js.map +1 -0
- package/dist/modules/v5/evaluate.d.ts +14 -0
- package/dist/modules/v5/evaluate.js +284 -0
- package/dist/modules/v5/evaluate.js.map +1 -0
- package/dist/modules/v5/jwt.d.ts +11 -0
- package/dist/modules/v5/jwt.js +42 -0
- package/dist/modules/v5/jwt.js.map +1 -0
- package/dist/modules/v5/matrix.d.ts +77 -0
- package/dist/modules/v5/matrix.js +239 -0
- package/dist/modules/v5/matrix.js.map +1 -0
- package/dist/modules/v5/otp.d.ts +30 -0
- package/dist/modules/v5/otp.js +117 -0
- package/dist/modules/v5/otp.js.map +1 -0
- package/dist/modules/v5/pow.d.ts +29 -0
- package/dist/modules/v5/pow.js +49 -0
- package/dist/modules/v5/pow.js.map +1 -0
- package/dist/modules/v5/read.d.ts +20 -0
- package/dist/modules/v5/read.js +59 -0
- package/dist/modules/v5/read.js.map +1 -0
- package/dist/modules/v5/semver.d.ts +33 -0
- package/dist/modules/v5/semver.js +99 -0
- package/dist/modules/v5/semver.js.map +1 -0
- package/dist/modules/v5/symmetric.d.ts +15 -0
- package/dist/modules/v5/symmetric.js +88 -0
- package/dist/modules/v5/symmetric.js.map +1 -0
- package/dist/modules/v5/text.d.ts +5 -0
- package/dist/modules/v5/text.js +12 -0
- package/dist/modules/v5/text.js.map +1 -0
- package/dist/modules/v5/tic_tac_toe.d.ts +19 -0
- package/dist/modules/v5/tic_tac_toe.js +226 -0
- package/dist/modules/v5/tic_tac_toe.js.map +1 -0
- package/dist/modules/v5/url.d.ts +18 -0
- package/dist/modules/v5/url.js +51 -0
- package/dist/modules/v5/url.js.map +1 -0
- package/dist/modules/v5/uuid.d.ts +25 -0
- package/dist/modules/v5/uuid.js +40 -0
- package/dist/modules/v5/uuid.js.map +1 -0
- package/dist/modules/v5.d.ts +24 -0
- package/dist/modules/v5.js +25 -0
- package/dist/modules/v5.js.map +1 -0
- package/dist/modules/v6.d.ts +1 -0
- package/dist/modules/v6.js +2 -0
- package/dist/modules/v6.js.map +1 -0
- package/dist/routes/delete.d.ts +2 -0
- package/dist/routes/delete.js +73 -0
- package/dist/routes/delete.js.map +1 -0
- package/dist/routes/get.d.ts +2 -0
- package/dist/routes/get.js +857 -0
- package/dist/routes/get.js.map +1 -0
- package/dist/routes/index.d.ts +2 -0
- package/dist/routes/index.js +95 -0
- package/dist/routes/index.js.map +1 -0
- package/dist/routes/patch.d.ts +2 -0
- package/dist/routes/patch.js +45 -0
- package/dist/routes/patch.js.map +1 -0
- package/dist/routes/post.d.ts +2 -0
- package/dist/routes/post.js +604 -0
- package/dist/routes/post.js.map +1 -0
- package/dist/storage/index.d.ts +5 -0
- package/dist/storage/index.js +14 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/types/storage.d.ts +52 -0
- package/dist/types/storage.js +2 -0
- package/dist/types/storage.js.map +1 -0
- package/dist/utils/challenge.d.ts +40 -0
- package/dist/utils/challenge.js +75 -0
- package/dist/utils/challenge.js.map +1 -0
- package/dist/utils/colors.d.ts +44 -0
- package/dist/utils/colors.js +93 -0
- package/dist/utils/colors.js.map +1 -0
- package/dist/utils/helpers.d.ts +55 -0
- package/dist/utils/helpers.js +82 -0
- package/dist/utils/helpers.js.map +1 -0
- package/dist/utils/response.d.ts +9 -0
- package/dist/utils/response.js +24 -0
- package/dist/utils/response.js.map +1 -0
- package/package.json +90 -0
- package/robots.txt +74 -0
- package/src/favicon.ico +0 -0
|
@@ -0,0 +1,857 @@
|
|
|
1
|
+
import { Router } from 'express';
|
|
2
|
+
import { env } from '../config/env.js';
|
|
3
|
+
import { versions } from '../config/versions.js';
|
|
4
|
+
import { chatStorage } from '../storage/index.js';
|
|
5
|
+
import { since } from '../utils/helpers.js';
|
|
6
|
+
import { error } from '../utils/response.js';
|
|
7
|
+
const router = Router();
|
|
8
|
+
const postOnly = (name) => (req, res) => {
|
|
9
|
+
const available = versions[req.version]?.endpoints.post.some((e) => e.name === name);
|
|
10
|
+
if (!available) {
|
|
11
|
+
error(res, 404, `Endpoint not available in ${req.version}.`);
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
error(res, 405, 'This endpoint only supports POST requests.');
|
|
15
|
+
};
|
|
16
|
+
// Display version information
|
|
17
|
+
router.get('/:version', (req, res) => {
|
|
18
|
+
const version = req.params.version;
|
|
19
|
+
const versionConfig = versions[version];
|
|
20
|
+
const endpoints = Object.keys(versionConfig.endpoints).reduce((acc, method) => {
|
|
21
|
+
const endpointList = versionConfig.endpoints[method];
|
|
22
|
+
if (!endpointList)
|
|
23
|
+
return acc;
|
|
24
|
+
acc[method] = endpointList
|
|
25
|
+
.sort((a, b) => a.name.localeCompare(b.name))
|
|
26
|
+
.reduce((group, endpoint) => {
|
|
27
|
+
if (endpoint.children) {
|
|
28
|
+
group[endpoint.name] = Object.keys(endpoint.children)
|
|
29
|
+
.sort((a, b) => a.localeCompare(b))
|
|
30
|
+
.reduce((childGroup, childName) => {
|
|
31
|
+
childGroup[childName] = `/${version}${endpoint.children[childName]}`;
|
|
32
|
+
return childGroup;
|
|
33
|
+
}, {});
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
group[endpoint.name] = `/${version}${endpoint.path}`;
|
|
37
|
+
}
|
|
38
|
+
return group;
|
|
39
|
+
}, {});
|
|
40
|
+
return acc;
|
|
41
|
+
}, {});
|
|
42
|
+
res.jsonResponse({
|
|
43
|
+
version,
|
|
44
|
+
...(env.DOCS_URL ? { documentation: `${env.DOCS_URL}/${version}` } : {}),
|
|
45
|
+
endpoints,
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
// Generate a fictional postal address
|
|
49
|
+
router.get('/:version/address', (req, res) => {
|
|
50
|
+
const { country, count } = req.query;
|
|
51
|
+
const { version } = req.params;
|
|
52
|
+
const addressFn = req.module.address;
|
|
53
|
+
if (!addressFn) {
|
|
54
|
+
error(res, 404, `Endpoint not available in ${version}.`);
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
const parsedCount = count !== undefined ? parseInt(count, 10) : 1;
|
|
58
|
+
if (isNaN(parsedCount)) {
|
|
59
|
+
error(res, 400, 'Please provide a valid count (&count={n})');
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
try {
|
|
63
|
+
const result = addressFn(country, parsedCount);
|
|
64
|
+
res.jsonResponse(result);
|
|
65
|
+
}
|
|
66
|
+
catch (err) {
|
|
67
|
+
error(res, 400, err.message);
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
// Parse a User-Agent string
|
|
71
|
+
router.get('/:version/agent', (req, res) => {
|
|
72
|
+
const ua = req.query.ua ?? req.headers['user-agent'] ?? '';
|
|
73
|
+
const agentFn = req.module.agent;
|
|
74
|
+
if (!agentFn) {
|
|
75
|
+
error(res, 404, `Endpoint not available in ${req.version}.`);
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
try {
|
|
79
|
+
const result = agentFn(ua);
|
|
80
|
+
res.jsonResponse(result);
|
|
81
|
+
}
|
|
82
|
+
catch (err) {
|
|
83
|
+
error(res, 400, err.message);
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
// Algorithms
|
|
87
|
+
router.get('/:version/algorithms', (req, res) => {
|
|
88
|
+
const { method, value, value2 } = req.query;
|
|
89
|
+
const algorithms = req.module.algorithms;
|
|
90
|
+
if (!algorithms || !method || !Object.hasOwn(algorithms, method)) {
|
|
91
|
+
error(res, 400, 'Please provide a valid algorithm (?method={algorithm})');
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
try {
|
|
95
|
+
const answer = algorithms[method](value, value2);
|
|
96
|
+
res.jsonResponse({ answer });
|
|
97
|
+
}
|
|
98
|
+
catch (err) {
|
|
99
|
+
error(res, 400, err.message);
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
// GET asymmetric error
|
|
103
|
+
router.get('/:version/asymmetric', postOnly('asymmetric'));
|
|
104
|
+
// Generate an identicon or pixel-art avatar from a seed
|
|
105
|
+
router.get('/:version/avatar', (req, res) => {
|
|
106
|
+
const avatarFn = req.module.avatar;
|
|
107
|
+
if (!avatarFn) {
|
|
108
|
+
error(res, 404, `Endpoint not available in ${req.version}.`);
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
const { seed, size, type, bg, format } = req.query;
|
|
112
|
+
const parsedSize = size !== undefined ? parseInt(size, 10) : undefined;
|
|
113
|
+
if (parsedSize !== undefined && isNaN(parsedSize)) {
|
|
114
|
+
error(res, 400, 'Please provide a valid size (&size={50-2000})');
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
try {
|
|
118
|
+
const { contentType, body } = avatarFn({
|
|
119
|
+
seed: seed,
|
|
120
|
+
size: parsedSize,
|
|
121
|
+
type: type,
|
|
122
|
+
bg: bg,
|
|
123
|
+
format: format,
|
|
124
|
+
});
|
|
125
|
+
res.type(contentType).send(body);
|
|
126
|
+
}
|
|
127
|
+
catch (err) {
|
|
128
|
+
error(res, 400, err.message);
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
// Generate a barcode image
|
|
132
|
+
router.get('/:version/barcode', (req, res) => {
|
|
133
|
+
const barcodeFn = req.module.barcode;
|
|
134
|
+
if (!barcodeFn) {
|
|
135
|
+
error(res, 404, `Endpoint not available in ${req.version}.`);
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
const { data, type, width, height, format, color, bg } = req.query;
|
|
139
|
+
if (!data) {
|
|
140
|
+
error(res, 400, 'Please provide data to encode (?data={string})');
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
const parsedWidth = width !== undefined ? parseInt(width, 10) : undefined;
|
|
144
|
+
const parsedHeight = height !== undefined ? parseInt(height, 10) : undefined;
|
|
145
|
+
if ((parsedWidth !== undefined && isNaN(parsedWidth)) || (parsedHeight !== undefined && isNaN(parsedHeight))) {
|
|
146
|
+
error(res, 400, 'Please provide valid dimensions (&width={px}&height={px})');
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
try {
|
|
150
|
+
const { contentType, body } = barcodeFn({
|
|
151
|
+
data: data,
|
|
152
|
+
type: type,
|
|
153
|
+
width: parsedWidth,
|
|
154
|
+
height: parsedHeight,
|
|
155
|
+
format: format,
|
|
156
|
+
color: color,
|
|
157
|
+
bg: bg,
|
|
158
|
+
});
|
|
159
|
+
res.type(contentType).send(body);
|
|
160
|
+
}
|
|
161
|
+
catch (err) {
|
|
162
|
+
error(res, 400, err.message);
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
// Convert a number between bases
|
|
166
|
+
router.get('/:version/base', (req, res) => {
|
|
167
|
+
const { value, from, to } = req.query;
|
|
168
|
+
const { version } = req.params;
|
|
169
|
+
const baseFn = req.module.base;
|
|
170
|
+
if (!baseFn) {
|
|
171
|
+
error(res, 404, `Endpoint not available in ${version}.`);
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
if (!value || typeof value !== 'string') {
|
|
175
|
+
error(res, 400, 'Please provide a value (?value={value})');
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
try {
|
|
179
|
+
const result = baseFn(value, from !== undefined ? Number(from) : undefined, to !== undefined ? Number(to) : undefined);
|
|
180
|
+
res.jsonResponse(result);
|
|
181
|
+
}
|
|
182
|
+
catch (err) {
|
|
183
|
+
error(res, 400, err.message);
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
// Generate captcha
|
|
187
|
+
router.get('/:version/captcha', (req, res) => {
|
|
188
|
+
try {
|
|
189
|
+
const mode = req.query.mode ?? (since(req.version, 6) ? 'challenge' : 'image');
|
|
190
|
+
if (mode !== 'image' && mode !== 'challenge') {
|
|
191
|
+
error(res, 400, 'Mode must be one of: image, challenge');
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
const challenge = mode === 'challenge';
|
|
195
|
+
if (challenge && !since(req.version, 5)) {
|
|
196
|
+
error(res, 404, `Challenge mode not available in ${req.version}.`);
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
if (challenge && req.query.text) {
|
|
200
|
+
error(res, 400, 'A custom text cannot be used in challenge mode');
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
const options = {
|
|
204
|
+
text: req.query.text,
|
|
205
|
+
length: req.query.length ? Number(req.query.length) : undefined,
|
|
206
|
+
width: req.query.width ? Number(req.query.width) : undefined,
|
|
207
|
+
height: req.query.height ? Number(req.query.height) : undefined,
|
|
208
|
+
noise: req.query.noise,
|
|
209
|
+
bg: req.query.bg,
|
|
210
|
+
color: req.query.color,
|
|
211
|
+
};
|
|
212
|
+
if (challenge) {
|
|
213
|
+
const challengeFn = req.module
|
|
214
|
+
.captchaChallenge;
|
|
215
|
+
const result = challengeFn(options);
|
|
216
|
+
res.set('X-Captcha-Token', result.token);
|
|
217
|
+
res.type('png').send(result.body);
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
const captchaFn = req.module.captcha;
|
|
221
|
+
const result = captchaFn(options);
|
|
222
|
+
res.set('X-Captcha-Text', result.text);
|
|
223
|
+
res.type('png').send(result.body);
|
|
224
|
+
}
|
|
225
|
+
catch (err) {
|
|
226
|
+
error(res, 400, err.message);
|
|
227
|
+
}
|
|
228
|
+
});
|
|
229
|
+
// Convert text to a different case format
|
|
230
|
+
router.get('/:version/case', (req, res) => {
|
|
231
|
+
const { text, to } = req.query;
|
|
232
|
+
const { version } = req.params;
|
|
233
|
+
const caseConvertFn = req.module.caseConvert;
|
|
234
|
+
if (!caseConvertFn) {
|
|
235
|
+
error(res, 404, `Endpoint not available in ${version}.`);
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
if (!text || typeof text !== 'string') {
|
|
239
|
+
error(res, 400, 'Please provide a text (?text={text})');
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
try {
|
|
243
|
+
const result = caseConvertFn(text, to);
|
|
244
|
+
res.jsonResponse(result);
|
|
245
|
+
}
|
|
246
|
+
catch (err) {
|
|
247
|
+
error(res, 400, err.message);
|
|
248
|
+
}
|
|
249
|
+
});
|
|
250
|
+
// GET chart error
|
|
251
|
+
router.get('/:version/chart', postOnly('chart'));
|
|
252
|
+
// Display stored data
|
|
253
|
+
router.get('/:version/chat', (req, res) => {
|
|
254
|
+
try {
|
|
255
|
+
const messages = req.module.chat('fetch', {
|
|
256
|
+
username: `reader:${req.ip ?? 'unknown'}`,
|
|
257
|
+
storage: chatStorage,
|
|
258
|
+
});
|
|
259
|
+
res.jsonResponse(messages);
|
|
260
|
+
}
|
|
261
|
+
catch (err) {
|
|
262
|
+
error(res, 400, err.message);
|
|
263
|
+
}
|
|
264
|
+
});
|
|
265
|
+
// GET private chat error
|
|
266
|
+
router.get('/:version/chat/private', postOnly('chat'));
|
|
267
|
+
// Generate color
|
|
268
|
+
router.get('/:version/color', (req, res) => {
|
|
269
|
+
try {
|
|
270
|
+
const colorFn = req.module.color;
|
|
271
|
+
const hex = req.query.hex;
|
|
272
|
+
const result = colorFn(hex || undefined);
|
|
273
|
+
res.jsonResponse(result);
|
|
274
|
+
}
|
|
275
|
+
catch (err) {
|
|
276
|
+
error(res, 400, err.message);
|
|
277
|
+
}
|
|
278
|
+
});
|
|
279
|
+
// Convert units
|
|
280
|
+
router.get('/:version/convert', (req, res) => {
|
|
281
|
+
const { value, from, to } = req.query;
|
|
282
|
+
if (!value || isNaN(Number(value))) {
|
|
283
|
+
error(res, 400, 'Please provide a valid value (?value={value})');
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
286
|
+
if (!from) {
|
|
287
|
+
error(res, 400, 'Please provide a valid source unit (&from={unit})');
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
290
|
+
if (!to) {
|
|
291
|
+
error(res, 400, 'Please provide a valid target unit (&to={unit})');
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
try {
|
|
295
|
+
const convertFn = req.module.convert;
|
|
296
|
+
const result = convertFn(Number(value), from, to);
|
|
297
|
+
res.jsonResponse(result);
|
|
298
|
+
}
|
|
299
|
+
catch (err) {
|
|
300
|
+
error(res, 400, err.message);
|
|
301
|
+
}
|
|
302
|
+
});
|
|
303
|
+
// Generate fictitious credit card numbers
|
|
304
|
+
router.get('/:version/credit', (req, res) => {
|
|
305
|
+
const creditFn = req.module
|
|
306
|
+
.credit;
|
|
307
|
+
if (!creditFn) {
|
|
308
|
+
error(res, 404, `Endpoint not available in ${req.version}.`);
|
|
309
|
+
return;
|
|
310
|
+
}
|
|
311
|
+
const { brand, count, format } = req.query;
|
|
312
|
+
try {
|
|
313
|
+
const result = creditFn(brand, count !== undefined ? parseInt(count, 10) : 1, format);
|
|
314
|
+
res.jsonResponse(result);
|
|
315
|
+
}
|
|
316
|
+
catch (err) {
|
|
317
|
+
error(res, 400, err.message);
|
|
318
|
+
}
|
|
319
|
+
});
|
|
320
|
+
// Parse a cron expression and compute next execution dates
|
|
321
|
+
router.get('/:version/cron', (req, res) => {
|
|
322
|
+
const { expr, count, from, timezone } = req.query;
|
|
323
|
+
const { version } = req.params;
|
|
324
|
+
const cronFn = req.module.cron;
|
|
325
|
+
if (!cronFn) {
|
|
326
|
+
error(res, 404, `Endpoint not available in ${version}.`);
|
|
327
|
+
return;
|
|
328
|
+
}
|
|
329
|
+
if (!expr) {
|
|
330
|
+
error(res, 400, 'Please provide a cron expression (?expr=* * * * *)');
|
|
331
|
+
return;
|
|
332
|
+
}
|
|
333
|
+
const parsedCount = count !== undefined ? parseInt(count, 10) : 5;
|
|
334
|
+
if (isNaN(parsedCount)) {
|
|
335
|
+
error(res, 400, 'Please provide a valid count (&count={n})');
|
|
336
|
+
return;
|
|
337
|
+
}
|
|
338
|
+
try {
|
|
339
|
+
const result = cronFn(expr, parsedCount, from, timezone ?? 'UTC');
|
|
340
|
+
res.jsonResponse(result);
|
|
341
|
+
}
|
|
342
|
+
catch (err) {
|
|
343
|
+
error(res, 400, err.message);
|
|
344
|
+
}
|
|
345
|
+
});
|
|
346
|
+
// GET csv error
|
|
347
|
+
router.get('/:version/csv', postOnly('csv'));
|
|
348
|
+
// RPG Dice roller
|
|
349
|
+
router.get('/:version/dice', (req, res) => {
|
|
350
|
+
const { roll } = req.query;
|
|
351
|
+
const { version } = req.params;
|
|
352
|
+
const dice = req.module.dice;
|
|
353
|
+
if (!dice) {
|
|
354
|
+
error(res, 404, `Endpoint not available in ${version}.`);
|
|
355
|
+
return;
|
|
356
|
+
}
|
|
357
|
+
if (!roll) {
|
|
358
|
+
error(res, 400, 'Please provide a roll notation (?roll=2d6+3)');
|
|
359
|
+
return;
|
|
360
|
+
}
|
|
361
|
+
try {
|
|
362
|
+
const result = dice(roll);
|
|
363
|
+
res.jsonResponse(result);
|
|
364
|
+
}
|
|
365
|
+
catch (err) {
|
|
366
|
+
error(res, 400, err.message);
|
|
367
|
+
}
|
|
368
|
+
});
|
|
369
|
+
// GET diff error
|
|
370
|
+
router.get('/:version/diff', postOnly('diff'));
|
|
371
|
+
// Generate domain informations
|
|
372
|
+
router.get('/:version/domain', (req, res) => {
|
|
373
|
+
try {
|
|
374
|
+
const result = req.module.domain();
|
|
375
|
+
res.jsonResponse(result);
|
|
376
|
+
}
|
|
377
|
+
catch (err) {
|
|
378
|
+
error(res, 400, err.message);
|
|
379
|
+
}
|
|
380
|
+
});
|
|
381
|
+
// Encode / decode text
|
|
382
|
+
router.get('/:version/encode', (req, res) => {
|
|
383
|
+
const { method, text, shift } = req.query;
|
|
384
|
+
const { version } = req.params;
|
|
385
|
+
const encode = req.module.encode;
|
|
386
|
+
if (!encode) {
|
|
387
|
+
error(res, 404, `Endpoint not available in ${version}.`);
|
|
388
|
+
return;
|
|
389
|
+
}
|
|
390
|
+
if (!method || !Object.hasOwn(encode, method)) {
|
|
391
|
+
error(res, 400, 'Please provide a valid method (?method={method})');
|
|
392
|
+
return;
|
|
393
|
+
}
|
|
394
|
+
try {
|
|
395
|
+
const result = encode[method](text, shift);
|
|
396
|
+
res.jsonResponse({ method, result });
|
|
397
|
+
}
|
|
398
|
+
catch (err) {
|
|
399
|
+
error(res, 400, err.message);
|
|
400
|
+
}
|
|
401
|
+
});
|
|
402
|
+
// Evaluate a math expression
|
|
403
|
+
router.get('/:version/evaluate', (req, res) => {
|
|
404
|
+
const { expr, precision } = req.query;
|
|
405
|
+
const { version } = req.params;
|
|
406
|
+
const evaluateFn = req.module.evaluate;
|
|
407
|
+
if (!evaluateFn) {
|
|
408
|
+
error(res, 404, `Endpoint not available in ${version}.`);
|
|
409
|
+
return;
|
|
410
|
+
}
|
|
411
|
+
if (!expr || typeof expr !== 'string') {
|
|
412
|
+
error(res, 400, 'Please provide a math expression (?expr={expression})');
|
|
413
|
+
return;
|
|
414
|
+
}
|
|
415
|
+
try {
|
|
416
|
+
const result = evaluateFn(expr, precision !== undefined ? parseInt(precision, 10) : undefined);
|
|
417
|
+
res.jsonResponse(result);
|
|
418
|
+
}
|
|
419
|
+
catch (err) {
|
|
420
|
+
error(res, 400, err.message);
|
|
421
|
+
}
|
|
422
|
+
});
|
|
423
|
+
// Geographic distance and bearing between two coordinates
|
|
424
|
+
router.get('/:version/geo', (req, res) => {
|
|
425
|
+
const { lat1, lon1, lat2, lon2 } = req.query;
|
|
426
|
+
const { version } = req.params;
|
|
427
|
+
const geo = req.module.geo;
|
|
428
|
+
if (!geo) {
|
|
429
|
+
error(res, 404, `Endpoint not available in ${version}.`);
|
|
430
|
+
return;
|
|
431
|
+
}
|
|
432
|
+
if (lat1 === undefined || lon1 === undefined || lat2 === undefined || lon2 === undefined) {
|
|
433
|
+
error(res, 400, 'Please provide lat1, lon1, lat2 and lon2');
|
|
434
|
+
return;
|
|
435
|
+
}
|
|
436
|
+
try {
|
|
437
|
+
const result = geo(lat1, lon1, lat2, lon2);
|
|
438
|
+
res.jsonResponse(result);
|
|
439
|
+
}
|
|
440
|
+
catch (err) {
|
|
441
|
+
error(res, 400, err.message);
|
|
442
|
+
}
|
|
443
|
+
});
|
|
444
|
+
// GET hash error
|
|
445
|
+
router.get('/:version/hash', postOnly('hash'));
|
|
446
|
+
// Echo request headers
|
|
447
|
+
router.get('/:version/headers', (req, res) => {
|
|
448
|
+
const redacted = new Set(['authorization', 'cookie', 'set-cookie', 'proxy-authorization']);
|
|
449
|
+
let headers = {};
|
|
450
|
+
for (const [k, v] of Object.entries(req.headers)) {
|
|
451
|
+
headers[k] = redacted.has(k) ? '[redacted]' : v;
|
|
452
|
+
}
|
|
453
|
+
const filterParam = req.query.filter;
|
|
454
|
+
const filter = Array.isArray(filterParam) ? filterParam.join(',') : filterParam;
|
|
455
|
+
if (filter) {
|
|
456
|
+
const keys = new Set(filter.split(',').map((k) => k.trim().toLowerCase()));
|
|
457
|
+
headers = Object.fromEntries(Object.entries(headers).filter(([k]) => keys.has(k)));
|
|
458
|
+
}
|
|
459
|
+
res.jsonResponse({
|
|
460
|
+
count: Object.keys(headers).length,
|
|
461
|
+
headers,
|
|
462
|
+
ip: req.ip,
|
|
463
|
+
method: req.method,
|
|
464
|
+
url: req.originalUrl,
|
|
465
|
+
});
|
|
466
|
+
});
|
|
467
|
+
// GET planning error
|
|
468
|
+
router.get('/:version/hyperplanning', postOnly('hyperplanning'));
|
|
469
|
+
// Display API informations
|
|
470
|
+
router.get('/:version/infos', (req, res) => {
|
|
471
|
+
const endpoints = Object.values(versions[req.version].endpoints).flat();
|
|
472
|
+
const paths = endpoints.flatMap((e) => (e.children ? Object.values(e.children) : e.path ? [e.path] : []));
|
|
473
|
+
res.jsonResponse({
|
|
474
|
+
endpoints: new Set(paths).size,
|
|
475
|
+
last_version: Object.keys(versions).pop(),
|
|
476
|
+
...(env.DOCS_URL ? { documentation: env.DOCS_URL } : {}),
|
|
477
|
+
...(env.REPO_URL ? { github: env.REPO_URL } : {}),
|
|
478
|
+
...(env.INSTANCE_CREATED ? { creation: env.INSTANCE_CREATED } : {}),
|
|
479
|
+
});
|
|
480
|
+
});
|
|
481
|
+
// Analyze an IP address
|
|
482
|
+
router.get('/:version/ip', (req, res) => {
|
|
483
|
+
const address = req.query.address ?? req.ip ?? '';
|
|
484
|
+
const ipFn = req.module.ip;
|
|
485
|
+
if (!ipFn) {
|
|
486
|
+
error(res, 404, `Endpoint not available in ${req.version}.`);
|
|
487
|
+
return;
|
|
488
|
+
}
|
|
489
|
+
try {
|
|
490
|
+
const result = ipFn(address);
|
|
491
|
+
res.jsonResponse(result);
|
|
492
|
+
}
|
|
493
|
+
catch (err) {
|
|
494
|
+
error(res, 400, err.message);
|
|
495
|
+
}
|
|
496
|
+
});
|
|
497
|
+
// GET jwt error
|
|
498
|
+
router.get('/:version/jwt', postOnly('jwt'));
|
|
499
|
+
// Calculate Levenshtein distance
|
|
500
|
+
router.get('/:version/levenshtein', (req, res) => {
|
|
501
|
+
if (since(req.version, 6)) {
|
|
502
|
+
error(res, 405, 'This endpoint only supports POST requests.');
|
|
503
|
+
return;
|
|
504
|
+
}
|
|
505
|
+
const { str1, str2 } = req.query;
|
|
506
|
+
if (!str1 || typeof str1 !== 'string') {
|
|
507
|
+
error(res, 400, 'Please provide a first string (?str1={string})');
|
|
508
|
+
return;
|
|
509
|
+
}
|
|
510
|
+
if (!str2 || typeof str2 !== 'string') {
|
|
511
|
+
error(res, 400, 'Please provide a second string (&str2={string})');
|
|
512
|
+
return;
|
|
513
|
+
}
|
|
514
|
+
try {
|
|
515
|
+
const result = req.module.levenshtein(str1, str2);
|
|
516
|
+
res.jsonResponse(result);
|
|
517
|
+
}
|
|
518
|
+
catch (err) {
|
|
519
|
+
error(res, 400, err.message);
|
|
520
|
+
}
|
|
521
|
+
});
|
|
522
|
+
// GET matrix error
|
|
523
|
+
router.get('/:version/matrix', postOnly('matrix'));
|
|
524
|
+
// GET otp error
|
|
525
|
+
router.get('/:version/otp', postOnly('otp'));
|
|
526
|
+
// Generate a color palette from a base color
|
|
527
|
+
router.get('/:version/palette', (req, res) => {
|
|
528
|
+
const { color, type } = req.query;
|
|
529
|
+
const { version } = req.params;
|
|
530
|
+
const palette = req.module.palette;
|
|
531
|
+
if (!palette) {
|
|
532
|
+
error(res, 404, `Endpoint not available in ${version}.`);
|
|
533
|
+
return;
|
|
534
|
+
}
|
|
535
|
+
if (!color) {
|
|
536
|
+
error(res, 400, 'Please provide a base color (?color=#ff6600)');
|
|
537
|
+
return;
|
|
538
|
+
}
|
|
539
|
+
if (!type) {
|
|
540
|
+
error(res, 400, 'Please provide a palette type (&type=complementary)');
|
|
541
|
+
return;
|
|
542
|
+
}
|
|
543
|
+
try {
|
|
544
|
+
const result = palette(color, type);
|
|
545
|
+
res.jsonResponse(result);
|
|
546
|
+
}
|
|
547
|
+
catch (err) {
|
|
548
|
+
error(res, 400, err.message);
|
|
549
|
+
}
|
|
550
|
+
});
|
|
551
|
+
// Generate a password or passphrase
|
|
552
|
+
router.get('/:version/password', (req, res) => {
|
|
553
|
+
const { type, length, uppercase, lowercase, digits, symbols, exclude, count, separator } = req.query;
|
|
554
|
+
const { version } = req.params;
|
|
555
|
+
const passwordFn = req.module.password;
|
|
556
|
+
if (!passwordFn) {
|
|
557
|
+
error(res, 404, `Endpoint not available in ${version}.`);
|
|
558
|
+
return;
|
|
559
|
+
}
|
|
560
|
+
const parseBool = (v, def) => (v === undefined ? def : v !== 'false');
|
|
561
|
+
try {
|
|
562
|
+
const result = passwordFn(type ?? 'random', length !== undefined ? parseInt(length, 10) : 16, {
|
|
563
|
+
uppercase: parseBool(uppercase, true),
|
|
564
|
+
lowercase: parseBool(lowercase, true),
|
|
565
|
+
digits: parseBool(digits, true),
|
|
566
|
+
symbols: parseBool(symbols, false),
|
|
567
|
+
exclude: exclude ?? '',
|
|
568
|
+
count: count !== undefined ? parseInt(count, 10) : 1,
|
|
569
|
+
separator: separator ?? '-',
|
|
570
|
+
});
|
|
571
|
+
res.jsonResponse(result);
|
|
572
|
+
}
|
|
573
|
+
catch (err) {
|
|
574
|
+
error(res, 400, err.message);
|
|
575
|
+
}
|
|
576
|
+
});
|
|
577
|
+
// Generate personal data
|
|
578
|
+
router.get('/:version/personal', (req, res) => {
|
|
579
|
+
try {
|
|
580
|
+
const result = req.module.personal();
|
|
581
|
+
res.jsonResponse(result);
|
|
582
|
+
}
|
|
583
|
+
catch (err) {
|
|
584
|
+
error(res, 400, err.message);
|
|
585
|
+
}
|
|
586
|
+
});
|
|
587
|
+
// Generate a placeholder image or skeleton
|
|
588
|
+
router.get('/:version/placeholder', (req, res) => {
|
|
589
|
+
const { type = 'image' } = req.query;
|
|
590
|
+
const { version } = req.params;
|
|
591
|
+
const placeholder = req.module.placeholder;
|
|
592
|
+
if (!placeholder) {
|
|
593
|
+
error(res, 404, `Endpoint not available in ${version}.`);
|
|
594
|
+
return;
|
|
595
|
+
}
|
|
596
|
+
try {
|
|
597
|
+
const result = placeholder(type, req.query);
|
|
598
|
+
res.type(result.contentType).send(result.body);
|
|
599
|
+
}
|
|
600
|
+
catch (err) {
|
|
601
|
+
error(res, 400, err.message);
|
|
602
|
+
}
|
|
603
|
+
});
|
|
604
|
+
// Issue a proof-of-work challenge
|
|
605
|
+
router.get('/:version/pow', (req, res) => {
|
|
606
|
+
const { difficulty } = req.query;
|
|
607
|
+
const { version } = req.params;
|
|
608
|
+
const powFn = req.module.pow;
|
|
609
|
+
if (!powFn) {
|
|
610
|
+
error(res, 404, `Endpoint not available in ${version}.`);
|
|
611
|
+
return;
|
|
612
|
+
}
|
|
613
|
+
try {
|
|
614
|
+
const result = powFn(difficulty !== undefined ? Number(difficulty) : undefined);
|
|
615
|
+
res.jsonResponse(result);
|
|
616
|
+
}
|
|
617
|
+
catch (err) {
|
|
618
|
+
error(res, 400, err.message);
|
|
619
|
+
}
|
|
620
|
+
});
|
|
621
|
+
// Generate QR Code
|
|
622
|
+
router.get('/:version/qrcode', async (req, res) => {
|
|
623
|
+
const { url } = req.query;
|
|
624
|
+
if (!url) {
|
|
625
|
+
error(res, 400, 'Please provide a valid url (?url={URL})');
|
|
626
|
+
return;
|
|
627
|
+
}
|
|
628
|
+
try {
|
|
629
|
+
const qrcodeFn = req.module.qrcode;
|
|
630
|
+
const result = await qrcodeFn({
|
|
631
|
+
url: url,
|
|
632
|
+
size: req.query.size ? Number(req.query.size) : undefined,
|
|
633
|
+
margin: req.query.margin ? Number(req.query.margin) : undefined,
|
|
634
|
+
correction: req.query.correction,
|
|
635
|
+
dark: req.query.dark,
|
|
636
|
+
light: req.query.light,
|
|
637
|
+
icon: req.query.icon,
|
|
638
|
+
iconSize: req.query.iconSize ? Number(req.query.iconSize) : undefined,
|
|
639
|
+
iconPadding: req.query.iconPadding ? Number(req.query.iconPadding) : undefined,
|
|
640
|
+
iconRadius: req.query.iconRadius ? Number(req.query.iconRadius) : undefined,
|
|
641
|
+
format: req.query.format,
|
|
642
|
+
});
|
|
643
|
+
if (result.contentType === 'application/json') {
|
|
644
|
+
res.jsonResponse(result.body);
|
|
645
|
+
}
|
|
646
|
+
else {
|
|
647
|
+
res.type(result.contentType).send(result.body);
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
catch (err) {
|
|
651
|
+
error(res, 400, err.message);
|
|
652
|
+
}
|
|
653
|
+
});
|
|
654
|
+
// GET read error
|
|
655
|
+
router.get('/:version/read', postOnly('read'));
|
|
656
|
+
// Test a regex pattern against a text
|
|
657
|
+
router.get('/:version/regex', (req, res) => {
|
|
658
|
+
const { pattern, text, flags } = req.query;
|
|
659
|
+
const { version } = req.params;
|
|
660
|
+
const regexFn = req.module.regex;
|
|
661
|
+
if (!regexFn) {
|
|
662
|
+
error(res, 404, `Endpoint not available in ${version}.`);
|
|
663
|
+
return;
|
|
664
|
+
}
|
|
665
|
+
if (!pattern) {
|
|
666
|
+
error(res, 400, 'Please provide a pattern (?pattern={regex})');
|
|
667
|
+
return;
|
|
668
|
+
}
|
|
669
|
+
if (!text) {
|
|
670
|
+
error(res, 400, 'Please provide a text (&text={string})');
|
|
671
|
+
return;
|
|
672
|
+
}
|
|
673
|
+
try {
|
|
674
|
+
const result = regexFn(pattern, text, flags);
|
|
675
|
+
res.jsonResponse(result);
|
|
676
|
+
}
|
|
677
|
+
catch (err) {
|
|
678
|
+
error(res, 400, err.message);
|
|
679
|
+
}
|
|
680
|
+
});
|
|
681
|
+
// Parse, bump or compare semantic versions
|
|
682
|
+
router.get('/:version/semver', (req, res) => {
|
|
683
|
+
const { version: input, action, part, other } = req.query;
|
|
684
|
+
const { version } = req.params;
|
|
685
|
+
const semverFn = req.module.semver;
|
|
686
|
+
if (!semverFn) {
|
|
687
|
+
error(res, 404, `Endpoint not available in ${version}.`);
|
|
688
|
+
return;
|
|
689
|
+
}
|
|
690
|
+
if (!input || typeof input !== 'string') {
|
|
691
|
+
error(res, 400, 'Please provide a version (?version={version})');
|
|
692
|
+
return;
|
|
693
|
+
}
|
|
694
|
+
const restorePlus = (v) => v.replace(/ /g, '+');
|
|
695
|
+
try {
|
|
696
|
+
const result = semverFn(restorePlus(input), action, part, typeof other === 'string' ? restorePlus(other) : undefined);
|
|
697
|
+
res.jsonResponse(result);
|
|
698
|
+
}
|
|
699
|
+
catch (err) {
|
|
700
|
+
error(res, 400, err.message);
|
|
701
|
+
}
|
|
702
|
+
});
|
|
703
|
+
// Statistics on a list of numbers
|
|
704
|
+
router.get('/:version/statistics', (req, res) => {
|
|
705
|
+
const { values } = req.query;
|
|
706
|
+
const { version } = req.params;
|
|
707
|
+
const statistics = req.module.statistics;
|
|
708
|
+
if (!statistics) {
|
|
709
|
+
error(res, 404, `Endpoint not available in ${version}.`);
|
|
710
|
+
return;
|
|
711
|
+
}
|
|
712
|
+
if (!values) {
|
|
713
|
+
error(res, 400, 'Please provide a list of values (?values=1,2,3)');
|
|
714
|
+
return;
|
|
715
|
+
}
|
|
716
|
+
try {
|
|
717
|
+
const result = statistics(values);
|
|
718
|
+
res.jsonResponse(result);
|
|
719
|
+
}
|
|
720
|
+
catch (err) {
|
|
721
|
+
error(res, 400, err.message);
|
|
722
|
+
}
|
|
723
|
+
});
|
|
724
|
+
// GET symmetric error
|
|
725
|
+
router.get('/:version/symmetric', postOnly('symmetric'));
|
|
726
|
+
// Text utilities (slug, stats, lorem, number)
|
|
727
|
+
router.get('/:version/text', (req, res) => {
|
|
728
|
+
const { method, value, type, count, lang, text } = req.query;
|
|
729
|
+
const { version } = req.params;
|
|
730
|
+
const textMod = req.module.text;
|
|
731
|
+
if (!textMod) {
|
|
732
|
+
error(res, 404, `Endpoint not available in ${version}.`);
|
|
733
|
+
return;
|
|
734
|
+
}
|
|
735
|
+
if (!method || !Object.hasOwn(textMod, method)) {
|
|
736
|
+
error(res, 400, 'Please provide a valid method (?method={slug|stats|lorem|number})');
|
|
737
|
+
return;
|
|
738
|
+
}
|
|
739
|
+
try {
|
|
740
|
+
let result;
|
|
741
|
+
switch (method) {
|
|
742
|
+
case 'slug':
|
|
743
|
+
case 'stats':
|
|
744
|
+
result = textMod[method]((value ?? text));
|
|
745
|
+
break;
|
|
746
|
+
case 'lorem':
|
|
747
|
+
result = textMod.lorem(type || 'words', count || '5');
|
|
748
|
+
break;
|
|
749
|
+
case 'number':
|
|
750
|
+
result = textMod.number(value, lang || 'en');
|
|
751
|
+
break;
|
|
752
|
+
default:
|
|
753
|
+
throw new Error('Unknown method');
|
|
754
|
+
}
|
|
755
|
+
res.jsonResponse({ method, result });
|
|
756
|
+
}
|
|
757
|
+
catch (err) {
|
|
758
|
+
error(res, 400, err.message);
|
|
759
|
+
}
|
|
760
|
+
});
|
|
761
|
+
// GET tic-tac-toe errors
|
|
762
|
+
router.get('/:version/tic-tac-toe', postOnly('tic_tac_toe'));
|
|
763
|
+
router.get('/:version/tic-tac-toe/fetch', postOnly('tic_tac_toe'));
|
|
764
|
+
router.get('/:version/tic-tac-toe/list', postOnly('tic_tac_toe'));
|
|
765
|
+
// Display or generate time informations, or compute a countdown
|
|
766
|
+
router.get('/:version/time', (req, res) => {
|
|
767
|
+
const { type = 'live', start, end, format, timezone, target } = req.query;
|
|
768
|
+
try {
|
|
769
|
+
const timeFn = req.module.time;
|
|
770
|
+
const time = timeFn(type, start, end, format, timezone, target);
|
|
771
|
+
res.jsonResponse(time);
|
|
772
|
+
}
|
|
773
|
+
catch (err) {
|
|
774
|
+
error(res, 400, err.message);
|
|
775
|
+
}
|
|
776
|
+
});
|
|
777
|
+
// GET token error
|
|
778
|
+
router.get('/:version/token', postOnly('token'));
|
|
779
|
+
// Parse a URL into its components
|
|
780
|
+
router.get('/:version/url', (req, res) => {
|
|
781
|
+
const { url } = req.query;
|
|
782
|
+
const { version } = req.params;
|
|
783
|
+
const parseUrlFn = req.module.parseUrl;
|
|
784
|
+
if (!parseUrlFn) {
|
|
785
|
+
error(res, 404, `Endpoint not available in ${version}.`);
|
|
786
|
+
return;
|
|
787
|
+
}
|
|
788
|
+
if (!url || typeof url !== 'string') {
|
|
789
|
+
error(res, 400, 'Please provide a URL (?url={URL})');
|
|
790
|
+
return;
|
|
791
|
+
}
|
|
792
|
+
try {
|
|
793
|
+
const result = parseUrlFn(url);
|
|
794
|
+
res.jsonResponse(result);
|
|
795
|
+
}
|
|
796
|
+
catch (err) {
|
|
797
|
+
error(res, 400, err.message);
|
|
798
|
+
}
|
|
799
|
+
});
|
|
800
|
+
// Generate username
|
|
801
|
+
router.get('/:version/username', (req, res) => {
|
|
802
|
+
try {
|
|
803
|
+
const result = req.module.username();
|
|
804
|
+
res.jsonResponse(result);
|
|
805
|
+
}
|
|
806
|
+
catch (err) {
|
|
807
|
+
error(res, 400, err.message);
|
|
808
|
+
}
|
|
809
|
+
});
|
|
810
|
+
// Generate or parse a UUID
|
|
811
|
+
router.get('/:version/uuid', (req, res) => {
|
|
812
|
+
const { uuid: input, count } = req.query;
|
|
813
|
+
const { version } = req.params;
|
|
814
|
+
const uuidFn = req.module.uuid;
|
|
815
|
+
if (!uuidFn) {
|
|
816
|
+
error(res, 404, `Endpoint not available in ${version}.`);
|
|
817
|
+
return;
|
|
818
|
+
}
|
|
819
|
+
if (input !== undefined && typeof input !== 'string') {
|
|
820
|
+
error(res, 400, 'Please provide a valid UUID (?uuid={uuid})');
|
|
821
|
+
return;
|
|
822
|
+
}
|
|
823
|
+
try {
|
|
824
|
+
const result = uuidFn(input, count !== undefined ? Number(count) : undefined);
|
|
825
|
+
res.jsonResponse(result);
|
|
826
|
+
}
|
|
827
|
+
catch (err) {
|
|
828
|
+
error(res, 400, err.message);
|
|
829
|
+
}
|
|
830
|
+
});
|
|
831
|
+
// Validate data (luhn, iban, email)
|
|
832
|
+
router.get('/:version/validate', (req, res) => {
|
|
833
|
+
const { type, value } = req.query;
|
|
834
|
+
const { version } = req.params;
|
|
835
|
+
const validate = req.module.validate;
|
|
836
|
+
if (!validate) {
|
|
837
|
+
error(res, 404, `Endpoint not available in ${version}.`);
|
|
838
|
+
return;
|
|
839
|
+
}
|
|
840
|
+
if (!type || !Object.hasOwn(validate, type)) {
|
|
841
|
+
error(res, 400, 'Please provide a valid type (?type={luhn|iban|email})');
|
|
842
|
+
return;
|
|
843
|
+
}
|
|
844
|
+
if (!value) {
|
|
845
|
+
error(res, 400, 'Please provide a value (&value={value})');
|
|
846
|
+
return;
|
|
847
|
+
}
|
|
848
|
+
try {
|
|
849
|
+
const result = validate[type](value);
|
|
850
|
+
res.jsonResponse(result);
|
|
851
|
+
}
|
|
852
|
+
catch (err) {
|
|
853
|
+
error(res, 400, err.message);
|
|
854
|
+
}
|
|
855
|
+
});
|
|
856
|
+
export default router;
|
|
857
|
+
//# sourceMappingURL=get.js.map
|