@moxon/api 6.0.0-pre → 6.2.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 +44 -19
- package/dist/app.js +9 -4
- package/dist/app.js.map +1 -1
- package/dist/constants.d.ts +22 -0
- package/dist/constants.js +22 -0
- package/dist/constants.js.map +1 -1
- package/dist/endpoints/define.d.ts +30 -0
- package/dist/endpoints/define.js +14 -0
- package/dist/endpoints/define.js.map +1 -0
- package/dist/endpoints/hash.d.ts +2 -0
- package/dist/endpoints/hash.js +16 -0
- package/dist/endpoints/hash.js.map +1 -0
- package/dist/endpoints/index.d.ts +2 -0
- package/dist/endpoints/index.js +4 -0
- package/dist/endpoints/index.js.map +1 -0
- package/dist/endpoints/router.d.ts +10 -0
- package/dist/endpoints/router.js +50 -0
- package/dist/endpoints/router.js.map +1 -0
- package/dist/manifest.d.ts +11 -0
- package/dist/manifest.js +12 -0
- package/dist/manifest.js.map +1 -0
- package/dist/middleware/cors.d.ts +15 -0
- package/dist/middleware/cors.js +25 -7
- package/dist/middleware/cors.js.map +1 -1
- package/dist/middleware/ratelimit.d.ts +53 -1
- package/dist/middleware/ratelimit.js +180 -71
- package/dist/middleware/ratelimit.js.map +1 -1
- package/dist/modules/v4/barcode.d.ts +1 -1
- package/dist/modules/v4/barcode.js +9 -2
- package/dist/modules/v4/barcode.js.map +1 -1
- package/dist/modules/v4/captcha.d.ts +1 -1
- package/dist/modules/v4/captcha.js +5 -1
- package/dist/modules/v4/captcha.js.map +1 -1
- package/dist/modules/v4/chat.js +61 -12
- package/dist/modules/v4/chat.js.map +1 -1
- package/dist/modules/v4/cron.js +20 -2
- package/dist/modules/v4/cron.js.map +1 -1
- package/dist/modules/v4/hyperplanning.d.ts +11 -0
- package/dist/modules/v4/hyperplanning.js +30 -29
- package/dist/modules/v4/hyperplanning.js.map +1 -1
- package/dist/modules/v4/qrcode.d.ts +10 -0
- package/dist/modules/v4/qrcode.js +138 -14
- package/dist/modules/v4/qrcode.js.map +1 -1
- package/dist/modules/v4/regex.d.ts +1 -1
- package/dist/modules/v4/regex.js +67 -22
- package/dist/modules/v4/regex.js.map +1 -1
- package/dist/modules/v4/tic_tac_toe.js +56 -15
- package/dist/modules/v4/tic_tac_toe.js.map +1 -1
- package/dist/modules/v5/asymmetric.d.ts +15 -0
- package/dist/modules/v5/asymmetric.js +67 -5
- package/dist/modules/v5/asymmetric.js.map +1 -1
- package/dist/modules/v5/barcode.d.ts +1 -1
- package/dist/modules/v5/barcode.js +9 -2
- package/dist/modules/v5/barcode.js.map +1 -1
- package/dist/modules/v5/captcha.d.ts +12 -4
- package/dist/modules/v5/captcha.js +25 -8
- package/dist/modules/v5/captcha.js.map +1 -1
- package/dist/modules/v5/chat.js +66 -17
- package/dist/modules/v5/chat.js.map +1 -1
- package/dist/modules/v5/cron.d.ts +26 -0
- package/dist/modules/v5/cron.js +356 -0
- package/dist/modules/v5/cron.js.map +1 -0
- package/dist/modules/v5/pow.js +1 -1
- package/dist/modules/v5/pow.js.map +1 -1
- package/dist/modules/v5/tic_tac_toe.js +61 -20
- package/dist/modules/v5/tic_tac_toe.js.map +1 -1
- package/dist/modules/v5.d.ts +3 -2
- package/dist/modules/v5.js +3 -2
- package/dist/modules/v5.js.map +1 -1
- package/dist/routes/delete.js +0 -8
- package/dist/routes/delete.js.map +1 -1
- package/dist/routes/get.js +0 -2
- package/dist/routes/get.js.map +1 -1
- package/dist/routes/patch.js +0 -4
- package/dist/routes/patch.js.map +1 -1
- package/dist/routes/post.js +12 -25
- package/dist/routes/post.js.map +1 -1
- package/dist/storage/index.js +9 -8
- package/dist/storage/index.js.map +1 -1
- package/dist/types/storage.d.ts +4 -0
- package/dist/utils/challenge.d.ts +5 -3
- package/dist/utils/challenge.js +52 -6
- package/dist/utils/challenge.js.map +1 -1
- package/dist/utils/helpers.d.ts +18 -0
- package/dist/utils/helpers.js +35 -1
- package/dist/utils/helpers.js.map +1 -1
- package/dist/utils/remote.d.ts +42 -0
- package/dist/utils/remote.js +313 -0
- package/dist/utils/remote.js.map +1 -0
- package/package.json +28 -8
- package/src/favicon.ico +0 -0
package/README.md
CHANGED
|
@@ -9,11 +9,11 @@ It works two ways:
|
|
|
9
9
|
- **As a library** — import any module directly into your code.
|
|
10
10
|
- **As a server** — a single import boots an Express app that exposes every module over HTTP.
|
|
11
11
|
|
|
12
|
-
The HTTP surface is versioned from `v4` to `v6`, and every version stays mounted side by side, so a new release never changes the behaviour of the one you already target. The full endpoint reference lives on [
|
|
12
|
+
The HTTP surface is versioned from `v4` to `v6`, and every version stays mounted side by side, so a new release never changes the behaviour of the one you already target. The full endpoint reference lives on [moxon.dev](https://moxon.dev).
|
|
13
13
|
|
|
14
14
|
## Migrating from `@20syldev/api`
|
|
15
15
|
|
|
16
|
-
`@moxon/api` is the new name of `@20syldev/api
|
|
16
|
+
`@moxon/api` is the new name of `@20syldev/api`, which no longer receives updates. `6.0.0-pre` carries the code of `@20syldev/api@6.0.0` under the new name, and every release since ships only as `@moxon/api`. The exports and the `/v6` HTTP API are unchanged, so migrating only takes a rename.
|
|
17
17
|
|
|
18
18
|
```bash
|
|
19
19
|
npm uninstall @20syldev/api
|
|
@@ -75,15 +75,15 @@ console.log(user.username);
|
|
|
75
75
|
|
|
76
76
|
## What's inside
|
|
77
77
|
|
|
78
|
-
| Domain | Exports
|
|
79
|
-
| ------------------ |
|
|
80
|
-
| **Crypto** | `asymmetric` `symmetric` `hash` `jwt` `otp` `token` `password` `captcha`
|
|
81
|
-
| **Math & data** | **`matrix`** **`algorithms`** `evaluate` `statistics` `convert` `csv`
|
|
82
|
-
| **Text** | **`text`** **`encode`** **`validate`** `caseConvert` `levenshtein` `regex` `parseUrl`
|
|
83
|
-
| **Graphics** | **`chart`** `barcode` `qrcode` `avatar` `placeholder` `color` `palette`
|
|
84
|
-
| **Fake data** | `personal` `address` `credit` `username` `dice` `domain` `agent`
|
|
85
|
-
| **Network & time** | `ip` `geo` `time` `cron` `hyperplanning`
|
|
86
|
-
| **Stateful** | `chat` `tic_tac_toe`
|
|
78
|
+
| Domain | Exports |
|
|
79
|
+
| ------------------ | ------------------------------------------------------------------------------------------ |
|
|
80
|
+
| **Crypto** | `asymmetric` `asymmetricAsync` `symmetric` `hash` `jwt` `otp` `token` `password` `captcha` |
|
|
81
|
+
| **Math & data** | **`matrix`** **`algorithms`** `evaluate` `statistics` `convert` `csv` |
|
|
82
|
+
| **Text** | **`text`** **`encode`** **`validate`** `caseConvert` `levenshtein` `regex` `parseUrl` |
|
|
83
|
+
| **Graphics** | **`chart`** `barcode` `qrcode` `avatar` `placeholder` `color` `palette` |
|
|
84
|
+
| **Fake data** | `personal` `address` `credit` `username` `dice` `domain` `agent` |
|
|
85
|
+
| **Network & time** | `ip` `geo` `time` `cron` `hyperplanning` |
|
|
86
|
+
| **Stateful** | `chat` `tic_tac_toe` |
|
|
87
87
|
|
|
88
88
|
The six names in **bold** are namespaces — they group related functions, called as `namespace.method()`:
|
|
89
89
|
|
|
@@ -112,6 +112,7 @@ Two names differ from their HTTP endpoint, because `case` is a reserved word and
|
|
|
112
112
|
```js
|
|
113
113
|
import {
|
|
114
114
|
asymmetric,
|
|
115
|
+
asymmetricAsync,
|
|
115
116
|
caseConvert,
|
|
116
117
|
chart,
|
|
117
118
|
csv,
|
|
@@ -130,6 +131,10 @@ const { result: encrypted } = asymmetric('encrypt', { text: 'secret message', pu
|
|
|
130
131
|
const { result: decrypted } = asymmetric('decrypt', { text: encrypted, privateKey });
|
|
131
132
|
console.log(decrypted); // 'secret message'
|
|
132
133
|
|
|
134
|
+
// Same result, but the key pair is generated off the main thread
|
|
135
|
+
const keys = await asymmetricAsync('keygen', { modulusLength: 4096 });
|
|
136
|
+
console.log(keys.modulusLength); // 4096
|
|
137
|
+
|
|
133
138
|
// AES-256-GCM symmetric encryption, key derived with scrypt
|
|
134
139
|
const { result: blob } = symmetric('encrypt', 'secret message', 'a-strong-key');
|
|
135
140
|
const { result: plain } = symmetric('decrypt', blob, 'a-strong-key');
|
|
@@ -184,6 +189,21 @@ console.log(parsed.host, parsed.port, parsed.params, parsed.fragment);
|
|
|
184
189
|
console.log(validate.email('alice@example.com').valid); // true
|
|
185
190
|
```
|
|
186
191
|
|
|
192
|
+
## Endpoint manifest
|
|
193
|
+
|
|
194
|
+
`@moxon/api/manifest` describes the HTTP endpoints as data — method, path, category, parameters and a request example — for tools that document or call the API. Each entry is typed as `ManifestEntry`.
|
|
195
|
+
|
|
196
|
+
```js
|
|
197
|
+
import { manifest } from '@moxon/api/manifest';
|
|
198
|
+
|
|
199
|
+
const hash = manifest.find((entry) => entry.name === 'hash');
|
|
200
|
+
console.log(hash.method, hash.path); // 'post' '/hash'
|
|
201
|
+
console.log(Object.keys(hash.params)); // ['text', 'method', 'encoding']
|
|
202
|
+
console.log(hash.example); // { text: 'hello', method: 'sha256' }
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
> _The manifest is experimental: it only lists the endpoints already declared as contracts (`hash` for now), and its shape may still change in a minor release._
|
|
206
|
+
|
|
187
207
|
## Running the server
|
|
188
208
|
|
|
189
209
|
From the installed package, one import mounts every version:
|
|
@@ -199,10 +219,13 @@ $ npm run build && npm start
|
|
|
199
219
|
```
|
|
200
220
|
|
|
201
221
|
```console
|
|
202
|
-
> @moxon/api@6.
|
|
203
|
-
> tsc
|
|
222
|
+
> @moxon/api@6.2.0 build
|
|
223
|
+
> npm run clean && tsc
|
|
204
224
|
|
|
205
|
-
> @moxon/api@6.
|
|
225
|
+
> @moxon/api@6.2.0 clean
|
|
226
|
+
> node -e "require('node:fs').rmSync('dist', { recursive: true, force: true })"
|
|
227
|
+
|
|
228
|
+
> @moxon/api@6.2.0 start
|
|
206
229
|
> node dist/app.js
|
|
207
230
|
|
|
208
231
|
API is running on
|
|
@@ -216,7 +239,7 @@ For development with automatic reloading:
|
|
|
216
239
|
$ npm run dev
|
|
217
240
|
```
|
|
218
241
|
|
|
219
|
-
Endpoints follow the `/:version/:endpoint` pattern — `GET /v5/color`, `GET /v5/evaluate?expr=2%2B2`, `POST /v5/matrix`. `GET /` lists the available versions, and `GET /:version` lists that version's endpoints with their
|
|
242
|
+
Endpoints follow the `/:version/:endpoint` pattern — `GET /v5/color`, `GET /v5/evaluate?expr=2%2B2`, `POST /v5/matrix`. `GET /` lists the available versions, and `GET /:version` lists that version's endpoints with their paths.
|
|
220
243
|
|
|
221
244
|
### Configuration
|
|
222
245
|
|
|
@@ -230,7 +253,7 @@ Every setting is optional and read from the environment; a `.env` file at the pr
|
|
|
230
253
|
| `INSTANCE_CREATED` | — | Launch date reported by `/:version/infos` |
|
|
231
254
|
| `LOGS_TOKEN` | — | Value required in the `X-Logs-Token` header to read `/logs`; the route answers 404 while unset |
|
|
232
255
|
| `CHALLENGE_SECRET` | random | Key signing the captcha and proof-of-work tokens; a random one is generated at startup while unset |
|
|
233
|
-
| `TRUSTED_PROXIES` | one hop | CIDR blocks
|
|
256
|
+
| `TRUSTED_PROXIES` | one hop | CIDR blocks or `loopback` / `linklocal` / `uniquelocal`, space or comma separated; unset, exactly one reverse proxy is assumed and a warning is logged |
|
|
234
257
|
| `GLOBAL_LIMIT` | `50000` | Requests per hour accepted across the whole instance |
|
|
235
258
|
| `DEFAULT_LIMIT` | `2000` | Per-client requests per hour |
|
|
236
259
|
| `DEFAULT_BURST` | `50` | Per-client requests per 10-second window |
|
|
@@ -239,7 +262,9 @@ The three metadata variables are omitted from responses when unset, so an instan
|
|
|
239
262
|
|
|
240
263
|
Higher quotas can be granted per client: `ADVANCED_`, `PRO_` and `BUSINESS_` variants of `_LIMIT` and `_BURST` define the tiers, and the matching `*_TOKEN_LIST` variables hold the space-separated bearer tokens that map to them. A client's tier and quota are reported by `GET /auth`.
|
|
241
264
|
|
|
242
|
-
> _Rate-limit counters live in process memory, so each instance of a multi-instance deployment counts separately._
|
|
265
|
+
> _Rate-limit counters live in process memory, so each instance of a multi-instance deployment counts separately. Clients are counted by address: an IPv4-mapped IPv6 address counts as its IPv4 form and any other IPv6 address as its `/64` block, while all the `/64` blocks of one `/48` network share four times the per-client hourly quota. A forwarded address that is not an IP address counts as the connecting peer. Only requests the per-client limits let through use the `GLOBAL_LIMIT` budget._
|
|
266
|
+
|
|
267
|
+
> _The one-hop default reads the client address from the last `X-Forwarded-For` entry, which is right behind a single reverse proxy such as nginx or Caddy. Exposed directly, callers can forge that header and pick their own address; behind several hops, every caller is counted as the nearest proxy. Set `TRUSTED_PROXIES` to match the actual chain._
|
|
243
268
|
|
|
244
269
|
> _Captcha and proof-of-work tokens are signed with `CHALLENGE_SECRET`. While it is unset each process invents its own key, so tokens stop verifying after a restart and are rejected by sibling instances — set it explicitly for any deployment running more than one process, with a full-entropy value such as `openssl rand -hex 32`._
|
|
245
270
|
|
|
@@ -268,9 +293,9 @@ Every version is fully typed. The package root always tracks the latest one.
|
|
|
268
293
|
| `npm run format` | Format with Prettier and auto-fix with ESLint |
|
|
269
294
|
| `npm run check` | TypeScript and ESLint verification |
|
|
270
295
|
|
|
271
|
-
##
|
|
296
|
+
## Documentation
|
|
272
297
|
|
|
273
|
-
|
|
298
|
+
The complete endpoint reference, request examples and usage guides live on [moxon.dev](https://moxon.dev).
|
|
274
299
|
|
|
275
300
|
## License
|
|
276
301
|
|
package/dist/app.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import express from 'express';
|
|
2
2
|
import { env } from './config/env.js';
|
|
3
|
-
import {
|
|
3
|
+
import { endpoints } from './endpoints/index.js';
|
|
4
|
+
import { build } from './endpoints/router.js';
|
|
5
|
+
import { setupCors, setupParsers } from './middleware/cors.js';
|
|
4
6
|
import { errorHandler } from './middleware/error.js';
|
|
5
7
|
import { jsonResponseMiddleware } from './middleware/json.js';
|
|
6
8
|
import { loggerMiddleware } from './middleware/logger.js';
|
|
@@ -13,12 +15,14 @@ import patchRoutes from './routes/patch.js';
|
|
|
13
15
|
import postRoutes from './routes/post.js';
|
|
14
16
|
import { error } from './utils/response.js';
|
|
15
17
|
const app = express();
|
|
16
|
-
//
|
|
18
|
+
// Security headers, CORS, static files
|
|
17
19
|
setupCors(app);
|
|
18
20
|
// Custom JSON response
|
|
19
21
|
app.use(jsonResponseMiddleware);
|
|
20
|
-
// Rate limiting
|
|
22
|
+
// Rate limiting, ahead of body parsing so malformed bodies are counted too
|
|
21
23
|
app.use(rateLimitMiddleware);
|
|
24
|
+
// Body parsing
|
|
25
|
+
setupParsers(app);
|
|
22
26
|
// Request logging
|
|
23
27
|
app.use(loggerMiddleware);
|
|
24
28
|
// Root routes (before version check)
|
|
@@ -36,7 +40,8 @@ try {
|
|
|
36
40
|
catch {
|
|
37
41
|
// No plugins bundled in this build
|
|
38
42
|
}
|
|
39
|
-
// Versioned routes
|
|
43
|
+
// Versioned routes, declared endpoints first
|
|
44
|
+
app.use(build(endpoints));
|
|
40
45
|
app.use(getRoutes);
|
|
41
46
|
app.use(postRoutes);
|
|
42
47
|
app.use(patchRoutes);
|
package/dist/app.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"AAAA,OAAO,OAAqD,MAAM,SAAS,CAAC;AAE5E,OAAO,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,EAAE,uBAAuB,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AAC1F,OAAO,YAAY,MAAM,oBAAoB,CAAC;AAC9C,OAAO,SAAS,MAAM,iBAAiB,CAAC;AACxC,OAAO,WAAW,MAAM,mBAAmB,CAAC;AAC5C,OAAO,WAAW,MAAM,mBAAmB,CAAC;AAC5C,OAAO,UAAU,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAE5C,MAAM,GAAG,GAAG,OAAO,EAAE,CAAC;AAEtB,
|
|
1
|
+
{"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"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"}
|
package/dist/constants.d.ts
CHANGED
|
@@ -1,22 +1,33 @@
|
|
|
1
1
|
export declare const APP_VERSION: string;
|
|
2
2
|
export declare const DEFAULT_PORT = 3000;
|
|
3
3
|
export declare const START_TIME: number;
|
|
4
|
+
export declare const CHALLENGE_MAX_ATTEMPTS = 5;
|
|
4
5
|
export declare const CHALLENGE_TTL = 300000;
|
|
5
6
|
export declare const GAME_CLEANUP_TTL = 600000;
|
|
6
7
|
export declare const MAX_LOG_ENTRIES = 1000;
|
|
8
|
+
export declare const RATE_LIMIT_IPV6_NETWORK = 48;
|
|
9
|
+
export declare const RATE_LIMIT_IPV6_PREFIX = 64;
|
|
10
|
+
export declare const RATE_LIMIT_NETWORK_FACTOR = 4;
|
|
7
11
|
export declare const RATE_LIMIT_WINDOW = 10000;
|
|
8
12
|
export declare const RATE_LIMIT_MAX = 50;
|
|
9
13
|
export declare const SESSION_TTL = 3600000;
|
|
10
14
|
export declare const STATUS_MESSAGES: Record<number, string>;
|
|
11
15
|
export declare const EARTH_RADIUS_KM = 6371;
|
|
12
16
|
export declare const MAX_ADDRESS_COUNT = 10;
|
|
17
|
+
export declare const MAX_BARCODE_DATA_LENGTH = 128;
|
|
13
18
|
export declare const MAX_BASE_VALUE_LENGTH = 100;
|
|
19
|
+
export declare const MAX_CAPTCHA_TEXT_LENGTH = 32;
|
|
14
20
|
export declare const MAX_CHART_DATASETS = 5;
|
|
15
21
|
export declare const MAX_CHART_LABELS = 20;
|
|
22
|
+
export declare const MAX_CHAT_MESSAGES = 200;
|
|
16
23
|
export declare const MAX_CSV_LENGTH = 50000;
|
|
17
24
|
export declare const MAX_CSV_ROWS = 1000;
|
|
18
25
|
export declare const MAX_CREDIT_COUNT = 10;
|
|
26
|
+
export declare const MAX_CONCURRENT_KEYGENS = 2;
|
|
19
27
|
export declare const MAX_COUNTDOWN_YEARS = 100;
|
|
28
|
+
export declare const MAX_CRON_DURATION = 250;
|
|
29
|
+
export declare const MAX_CRON_DURATION_V4 = 1000;
|
|
30
|
+
export declare const MAX_CRON_GAP: number;
|
|
20
31
|
export declare const MAX_CRON_ITERATIONS: number;
|
|
21
32
|
export declare const MAX_CRON_RESULTS = 20;
|
|
22
33
|
export declare const MAX_DIFF_LENGTH = 10000;
|
|
@@ -25,6 +36,10 @@ export declare const MAX_EXPR_DEPTH = 100;
|
|
|
25
36
|
export declare const MAX_EXPR_LENGTH = 500;
|
|
26
37
|
export declare const MAX_FACTORIAL = 170;
|
|
27
38
|
export declare const MAX_GCD_VALUE = 100000;
|
|
39
|
+
export declare const ICS_FETCH_TIMEOUT = 10000;
|
|
40
|
+
export declare const MAX_ICS_BYTES: number;
|
|
41
|
+
export declare const MAX_ICS_EVENTS = 5000;
|
|
42
|
+
export declare const MAX_ID_LENGTH = 256;
|
|
28
43
|
export declare const MAX_JWT_LENGTH = 8192;
|
|
29
44
|
export declare const MAX_LEVENSHTEIN_LENGTH = 1000;
|
|
30
45
|
export declare const MIN_PASSWORD_LENGTH = 8;
|
|
@@ -34,15 +49,22 @@ export declare const MAX_MATRIX_SIZE = 20;
|
|
|
34
49
|
export declare const MAX_PATTERN_LENGTH = 200;
|
|
35
50
|
export declare const MAX_POW_DIFFICULTY = 6;
|
|
36
51
|
export declare const MAX_PRIME_LIST = 10000;
|
|
52
|
+
export declare const MAX_PRIVATE_CHATS = 1000;
|
|
37
53
|
export declare const POW_DEFAULT_DIFFICULTY = 4;
|
|
54
|
+
export declare const MAX_QRCODE_ICON_PIXELS = 16000000;
|
|
38
55
|
export declare const MAX_QRCODE_LOGO_BYTES: number;
|
|
56
|
+
export declare const QRCODE_ICON_TIMEOUT = 5000;
|
|
39
57
|
export declare const MAX_READ_LENGTH = 50000;
|
|
40
58
|
export declare const MAX_REGEX_MATCHES = 100;
|
|
59
|
+
export declare const REGEX_TIMEOUT = 25;
|
|
60
|
+
export declare const MAX_REMOTE_REDIRECTS = 10;
|
|
41
61
|
export declare const MAX_RSA_MODULUS = 4096;
|
|
42
62
|
export declare const MAX_SEMVER_LENGTH = 256;
|
|
43
63
|
export declare const MAX_STRING_LENGTH = 1000;
|
|
64
|
+
export declare const MAX_TIMESTAMP_LENGTH = 128;
|
|
44
65
|
export declare const MIN_TOKEN_LENGTH = 12;
|
|
45
66
|
export declare const MAX_TOKEN_LENGTH = 4096;
|
|
46
67
|
export declare const MAX_URL_LENGTH = 2048;
|
|
68
|
+
export declare const MAX_USERNAME_LENGTH = 100;
|
|
47
69
|
export declare const MAX_UUID_COUNT = 50;
|
|
48
70
|
export declare const ROMAN_VALUES: [number, string][];
|
package/dist/constants.js
CHANGED
|
@@ -4,9 +4,13 @@ export const APP_VERSION = pkg.version;
|
|
|
4
4
|
export const DEFAULT_PORT = 3000;
|
|
5
5
|
export const START_TIME = Date.now();
|
|
6
6
|
// Server
|
|
7
|
+
export const CHALLENGE_MAX_ATTEMPTS = 5;
|
|
7
8
|
export const CHALLENGE_TTL = 300_000;
|
|
8
9
|
export const GAME_CLEANUP_TTL = 600_000;
|
|
9
10
|
export const MAX_LOG_ENTRIES = 1000;
|
|
11
|
+
export const RATE_LIMIT_IPV6_NETWORK = 48;
|
|
12
|
+
export const RATE_LIMIT_IPV6_PREFIX = 64;
|
|
13
|
+
export const RATE_LIMIT_NETWORK_FACTOR = 4;
|
|
10
14
|
export const RATE_LIMIT_WINDOW = 10_000;
|
|
11
15
|
export const RATE_LIMIT_MAX = 50;
|
|
12
16
|
export const SESSION_TTL = 3_600_000;
|
|
@@ -22,13 +26,20 @@ export const STATUS_MESSAGES = {
|
|
|
22
26
|
// Modules
|
|
23
27
|
export const EARTH_RADIUS_KM = 6371;
|
|
24
28
|
export const MAX_ADDRESS_COUNT = 10;
|
|
29
|
+
export const MAX_BARCODE_DATA_LENGTH = 128;
|
|
25
30
|
export const MAX_BASE_VALUE_LENGTH = 100;
|
|
31
|
+
export const MAX_CAPTCHA_TEXT_LENGTH = 32;
|
|
26
32
|
export const MAX_CHART_DATASETS = 5;
|
|
27
33
|
export const MAX_CHART_LABELS = 20;
|
|
34
|
+
export const MAX_CHAT_MESSAGES = 200;
|
|
28
35
|
export const MAX_CSV_LENGTH = 50_000;
|
|
29
36
|
export const MAX_CSV_ROWS = 1000;
|
|
30
37
|
export const MAX_CREDIT_COUNT = 10;
|
|
38
|
+
export const MAX_CONCURRENT_KEYGENS = 2;
|
|
31
39
|
export const MAX_COUNTDOWN_YEARS = 100;
|
|
40
|
+
export const MAX_CRON_DURATION = 250;
|
|
41
|
+
export const MAX_CRON_DURATION_V4 = 1000;
|
|
42
|
+
export const MAX_CRON_GAP = 401 * 366 * 86_400_000;
|
|
32
43
|
export const MAX_CRON_ITERATIONS = 365 * 24 * 60;
|
|
33
44
|
export const MAX_CRON_RESULTS = 20;
|
|
34
45
|
export const MAX_DIFF_LENGTH = 10_000;
|
|
@@ -37,6 +48,10 @@ export const MAX_EXPR_DEPTH = 100;
|
|
|
37
48
|
export const MAX_EXPR_LENGTH = 500;
|
|
38
49
|
export const MAX_FACTORIAL = 170;
|
|
39
50
|
export const MAX_GCD_VALUE = 100_000;
|
|
51
|
+
export const ICS_FETCH_TIMEOUT = 10_000;
|
|
52
|
+
export const MAX_ICS_BYTES = 1024 * 1024;
|
|
53
|
+
export const MAX_ICS_EVENTS = 5000;
|
|
54
|
+
export const MAX_ID_LENGTH = 256;
|
|
40
55
|
export const MAX_JWT_LENGTH = 8192;
|
|
41
56
|
export const MAX_LEVENSHTEIN_LENGTH = 1000;
|
|
42
57
|
export const MIN_PASSWORD_LENGTH = 8;
|
|
@@ -46,16 +61,23 @@ export const MAX_MATRIX_SIZE = 20;
|
|
|
46
61
|
export const MAX_PATTERN_LENGTH = 200;
|
|
47
62
|
export const MAX_POW_DIFFICULTY = 6;
|
|
48
63
|
export const MAX_PRIME_LIST = 10_000;
|
|
64
|
+
export const MAX_PRIVATE_CHATS = 1000;
|
|
49
65
|
export const POW_DEFAULT_DIFFICULTY = 4;
|
|
66
|
+
export const MAX_QRCODE_ICON_PIXELS = 16_000_000;
|
|
50
67
|
export const MAX_QRCODE_LOGO_BYTES = 2 * 1024 * 1024;
|
|
68
|
+
export const QRCODE_ICON_TIMEOUT = 5000;
|
|
51
69
|
export const MAX_READ_LENGTH = 50_000;
|
|
52
70
|
export const MAX_REGEX_MATCHES = 100;
|
|
71
|
+
export const REGEX_TIMEOUT = 25;
|
|
72
|
+
export const MAX_REMOTE_REDIRECTS = 10;
|
|
53
73
|
export const MAX_RSA_MODULUS = 4096;
|
|
54
74
|
export const MAX_SEMVER_LENGTH = 256;
|
|
55
75
|
export const MAX_STRING_LENGTH = 1000;
|
|
76
|
+
export const MAX_TIMESTAMP_LENGTH = 128;
|
|
56
77
|
export const MIN_TOKEN_LENGTH = 12;
|
|
57
78
|
export const MAX_TOKEN_LENGTH = 4096;
|
|
58
79
|
export const MAX_URL_LENGTH = 2048;
|
|
80
|
+
export const MAX_USERNAME_LENGTH = 100;
|
|
59
81
|
export const MAX_UUID_COUNT = 50;
|
|
60
82
|
export const ROMAN_VALUES = [
|
|
61
83
|
[1000, 'M'],
|
package/dist/constants.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,iBAAiB,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AAExD,MAAM;AACN,MAAM,CAAC,MAAM,WAAW,GAAG,GAAG,CAAC,OAAO,CAAC;AACvC,MAAM,CAAC,MAAM,YAAY,GAAG,IAAI,CAAC;AACjC,MAAM,CAAC,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;AAErC,SAAS;AACT,MAAM,CAAC,MAAM,aAAa,GAAG,OAAO,CAAC;AACrC,MAAM,CAAC,MAAM,gBAAgB,GAAG,OAAO,CAAC;AACxC,MAAM,CAAC,MAAM,eAAe,GAAG,IAAI,CAAC;AACpC,MAAM,CAAC,MAAM,iBAAiB,GAAG,MAAM,CAAC;AACxC,MAAM,CAAC,MAAM,cAAc,GAAG,EAAE,CAAC;AACjC,MAAM,CAAC,MAAM,WAAW,GAAG,SAAS,CAAC;AAErC,MAAM,CAAC,MAAM,eAAe,GAA2B;IACnD,GAAG,EAAE,aAAa;IAClB,GAAG,EAAE,cAAc;IACnB,GAAG,EAAE,WAAW;IAChB,GAAG,EAAE,oBAAoB;IACzB,GAAG,EAAE,mBAAmB;IACxB,GAAG,EAAE,mBAAmB;IACxB,GAAG,EAAE,uBAAuB;CAC/B,CAAC;AAEF,UAAU;AACV,MAAM,CAAC,MAAM,eAAe,GAAG,IAAI,CAAC;AACpC,MAAM,CAAC,MAAM,iBAAiB,GAAG,EAAE,CAAC;AACpC,MAAM,CAAC,MAAM,qBAAqB,GAAG,GAAG,CAAC;AACzC,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC;AACpC,MAAM,CAAC,MAAM,gBAAgB,GAAG,EAAE,CAAC;AACnC,MAAM,CAAC,MAAM,cAAc,GAAG,MAAM,CAAC;AACrC,MAAM,CAAC,MAAM,YAAY,GAAG,IAAI,CAAC;AACjC,MAAM,CAAC,MAAM,gBAAgB,GAAG,EAAE,CAAC;AACnC,MAAM,CAAC,MAAM,mBAAmB,GAAG,GAAG,CAAC;AACvC,MAAM,CAAC,MAAM,mBAAmB,GAAG,GAAG,GAAG,EAAE,GAAG,EAAE,CAAC;AACjD,MAAM,CAAC,MAAM,gBAAgB,GAAG,EAAE,CAAC;AACnC,MAAM,CAAC,MAAM,eAAe,GAAG,MAAM,CAAC;AACtC,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,CAAC;AACnC,MAAM,CAAC,MAAM,cAAc,GAAG,GAAG,CAAC;AAClC,MAAM,CAAC,MAAM,eAAe,GAAG,GAAG,CAAC;AACnC,MAAM,CAAC,MAAM,aAAa,GAAG,GAAG,CAAC;AACjC,MAAM,CAAC,MAAM,aAAa,GAAG,OAAO,CAAC;AACrC,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,CAAC;AACnC,MAAM,CAAC,MAAM,sBAAsB,GAAG,IAAI,CAAC;AAC3C,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC;AACrC,MAAM,CAAC,MAAM,mBAAmB,GAAG,GAAG,CAAC;AACvC,MAAM,CAAC,MAAM,kBAAkB,GAAG,EAAE,CAAC;AACrC,MAAM,CAAC,MAAM,eAAe,GAAG,EAAE,CAAC;AAClC,MAAM,CAAC,MAAM,kBAAkB,GAAG,GAAG,CAAC;AACtC,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC;AACpC,MAAM,CAAC,MAAM,cAAc,GAAG,MAAM,CAAC;AACrC,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC;AACxC,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC;AACrD,MAAM,CAAC,MAAM,eAAe,GAAG,MAAM,CAAC;AACtC,MAAM,CAAC,MAAM,iBAAiB,GAAG,GAAG,CAAC;AACrC,MAAM,CAAC,MAAM,eAAe,GAAG,IAAI,CAAC;AACpC,MAAM,CAAC,MAAM,iBAAiB,GAAG,GAAG,CAAC;AACrC,MAAM,CAAC,MAAM,iBAAiB,GAAG,IAAI,CAAC;AACtC,MAAM,CAAC,MAAM,gBAAgB,GAAG,EAAE,CAAC;AACnC,MAAM,CAAC,MAAM,gBAAgB,GAAG,IAAI,CAAC;AACrC,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,CAAC;AACnC,MAAM,CAAC,MAAM,cAAc,GAAG,EAAE,CAAC;AAEjC,MAAM,CAAC,MAAM,YAAY,GAAuB;IAC5C,CAAC,IAAI,EAAE,GAAG,CAAC;IACX,CAAC,GAAG,EAAE,IAAI,CAAC;IACX,CAAC,GAAG,EAAE,GAAG,CAAC;IACV,CAAC,GAAG,EAAE,IAAI,CAAC;IACX,CAAC,GAAG,EAAE,GAAG,CAAC;IACV,CAAC,EAAE,EAAE,IAAI,CAAC;IACV,CAAC,EAAE,EAAE,GAAG,CAAC;IACT,CAAC,EAAE,EAAE,IAAI,CAAC;IACV,CAAC,EAAE,EAAE,GAAG,CAAC;IACT,CAAC,CAAC,EAAE,IAAI,CAAC;IACT,CAAC,CAAC,EAAE,GAAG,CAAC;IACR,CAAC,CAAC,EAAE,IAAI,CAAC;IACT,CAAC,CAAC,EAAE,GAAG,CAAC;CACX,CAAC"}
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { Request } from 'express';
|
|
2
|
+
export type Category = 'security' | 'text' | 'images' | 'compute' | 'fakeData' | 'network' | 'realtime';
|
|
3
|
+
export interface Param {
|
|
4
|
+
required?: boolean;
|
|
5
|
+
missing?: string;
|
|
6
|
+
options?: readonly string[];
|
|
7
|
+
default?: string;
|
|
8
|
+
}
|
|
9
|
+
export type Values<P extends string> = Record<P, string | undefined>;
|
|
10
|
+
export interface Endpoint<P extends string = string> {
|
|
11
|
+
name: string;
|
|
12
|
+
method: 'get' | 'post';
|
|
13
|
+
path: string;
|
|
14
|
+
category: Category;
|
|
15
|
+
since?: number;
|
|
16
|
+
params: Record<P, Param>;
|
|
17
|
+
example: Partial<Record<P, string>>;
|
|
18
|
+
run(values: Values<P>, req: Request): unknown;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Declares an endpoint contract and infers its parameter names, so `run` receives typed values.
|
|
22
|
+
* The HTTP router and the documentation manifest are both built from it, so the two cannot drift apart.
|
|
23
|
+
*
|
|
24
|
+
* @param endpoint - Contract of the route: `since` is the first API version serving it (all of them when
|
|
25
|
+
* omitted), `params` are read from the query string on GET and from the JSON body on POST, `example` is the
|
|
26
|
+
* input the documentation runs to show a real output, and an error thrown by `run` becomes a 400 carrying its
|
|
27
|
+
* message
|
|
28
|
+
* @returns The same contract, typed with its parameter names
|
|
29
|
+
*/
|
|
30
|
+
export declare function define<P extends string>(endpoint: Endpoint<P>): Endpoint<P>;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Declares an endpoint contract and infers its parameter names, so `run` receives typed values.
|
|
3
|
+
* The HTTP router and the documentation manifest are both built from it, so the two cannot drift apart.
|
|
4
|
+
*
|
|
5
|
+
* @param endpoint - Contract of the route: `since` is the first API version serving it (all of them when
|
|
6
|
+
* omitted), `params` are read from the query string on GET and from the JSON body on POST, `example` is the
|
|
7
|
+
* input the documentation runs to show a real output, and an error thrown by `run` becomes a 400 carrying its
|
|
8
|
+
* message
|
|
9
|
+
* @returns The same contract, typed with its parameter names
|
|
10
|
+
*/
|
|
11
|
+
export function define(endpoint) {
|
|
12
|
+
return endpoint;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=define.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"define.js","sourceRoot":"","sources":["../../src/endpoints/define.ts"],"names":[],"mappings":"AAwBA;;;;;;;;;GASG;AACH,MAAM,UAAU,MAAM,CAAmB,QAAqB;IAC1D,OAAO,QAAQ,CAAC;AACpB,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import hash from '../modules/v4/hash.js';
|
|
2
|
+
import { define } from './define.js';
|
|
3
|
+
export default define({
|
|
4
|
+
name: 'hash',
|
|
5
|
+
method: 'post',
|
|
6
|
+
path: '/hash',
|
|
7
|
+
category: 'security',
|
|
8
|
+
params: {
|
|
9
|
+
text: { required: true, missing: 'Please provide a text (?text={text})' },
|
|
10
|
+
method: { required: true, missing: 'Please provide a valid hash algorithm (&method={algorithm})' },
|
|
11
|
+
encoding: { options: ['hex', 'base64'], default: 'hex' },
|
|
12
|
+
},
|
|
13
|
+
example: { text: 'hello', method: 'sha256' },
|
|
14
|
+
run: ({ text, method, encoding }) => hash(text, method, encoding),
|
|
15
|
+
});
|
|
16
|
+
//# sourceMappingURL=hash.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hash.js","sourceRoot":"","sources":["../../src/endpoints/hash.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,uBAAuB,CAAC;AACzC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,eAAe,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM;IACZ,MAAM,EAAE,MAAM;IACd,IAAI,EAAE,OAAO;IACb,QAAQ,EAAE,UAAU;IACpB,MAAM,EAAE;QACJ,IAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,sCAAsC,EAAE;QACzE,MAAM,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,6DAA6D,EAAE;QAClG,QAAQ,EAAE,EAAE,OAAO,EAAE,CAAC,KAAK,EAAE,QAAQ,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE;KAC3D;IACD,OAAO,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE;IAC5C,GAAG,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,IAAK,EAAE,MAAO,EAAE,QAAQ,CAAC;CACtE,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/endpoints/index.ts"],"names":[],"mappings":"AACA,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,yGAAyG;AACzG,MAAM,CAAC,MAAM,SAAS,GAAe,CAAC,IAAI,CAAC,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Router } from 'express';
|
|
2
|
+
import type { Endpoint } from './define.js';
|
|
3
|
+
/**
|
|
4
|
+
* Builds the HTTP routes of the declared endpoints, with the required parameter check and the shared error format.
|
|
5
|
+
* A POST-only endpoint also answers GET with a 405, and a version older than its `since` answers 404.
|
|
6
|
+
*
|
|
7
|
+
* @param endpoints - Contracts to serve, each mounted under `/:version`
|
|
8
|
+
* @returns Router to mount before the hand-written routes, so a declared endpoint takes precedence
|
|
9
|
+
*/
|
|
10
|
+
export declare function build(endpoints: Endpoint[]): Router;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { Router } from 'express';
|
|
2
|
+
import { since } from '../utils/helpers.js';
|
|
3
|
+
import { error } from '../utils/response.js';
|
|
4
|
+
/**
|
|
5
|
+
* Builds the HTTP routes of the declared endpoints, with the required parameter check and the shared error format.
|
|
6
|
+
* A POST-only endpoint also answers GET with a 405, and a version older than its `since` answers 404.
|
|
7
|
+
*
|
|
8
|
+
* @param endpoints - Contracts to serve, each mounted under `/:version`
|
|
9
|
+
* @returns Router to mount before the hand-written routes, so a declared endpoint takes precedence
|
|
10
|
+
*/
|
|
11
|
+
export function build(endpoints) {
|
|
12
|
+
const router = Router();
|
|
13
|
+
for (const endpoint of endpoints) {
|
|
14
|
+
const path = `/:version${endpoint.path}`;
|
|
15
|
+
const served = (req) => !endpoint.since || since(req.version, endpoint.since);
|
|
16
|
+
router[endpoint.method](path, async (req, res) => {
|
|
17
|
+
if (!served(req)) {
|
|
18
|
+
error(res, 404, `Endpoint not available in ${req.version}.`);
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
const source = ((endpoint.method === 'get' ? req.query : req.body) ?? {});
|
|
22
|
+
const values = {};
|
|
23
|
+
for (const [name, param] of Object.entries(endpoint.params)) {
|
|
24
|
+
const value = source[name];
|
|
25
|
+
if (param.required && !value) {
|
|
26
|
+
error(res, 400, param.missing ?? `Please provide a ${name}`);
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
values[name] = value;
|
|
30
|
+
}
|
|
31
|
+
try {
|
|
32
|
+
res.jsonResponse(await endpoint.run(values, req));
|
|
33
|
+
}
|
|
34
|
+
catch (err) {
|
|
35
|
+
error(res, 400, err.message);
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
if (endpoint.method === 'post') {
|
|
39
|
+
router.get(path, (req, res) => {
|
|
40
|
+
if (!served(req)) {
|
|
41
|
+
error(res, 404, `Endpoint not available in ${req.version}.`);
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
error(res, 405, 'This endpoint only supports POST requests.');
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return router;
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=router.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"router.js","sourceRoot":"","sources":["../../src/endpoints/router.ts"],"names":[],"mappings":"AAAA,OAAO,EAA+B,MAAM,EAAE,MAAM,SAAS,CAAC;AAE9D,OAAO,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAC5C,OAAO,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAG7C;;;;;;GAMG;AACH,MAAM,UAAU,KAAK,CAAC,SAAqB;IACvC,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC;IAExB,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QAC/B,MAAM,IAAI,GAAG,YAAY,QAAQ,CAAC,IAAI,EAAE,CAAC;QACzC,MAAM,MAAM,GAAG,CAAC,GAAY,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,IAAI,KAAK,CAAC,GAAG,CAAC,OAAO,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC;QAEvF,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,GAAY,EAAE,GAAa,EAAE,EAAE;YAChE,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;gBACf,KAAK,CAAC,GAAG,EAAE,GAAG,EAAE,6BAA6B,GAAG,CAAC,OAAO,GAAG,CAAC,CAAC;gBAC7D,OAAO;YACX,CAAC;YAED,MAAM,MAAM,GAAG,CAAC,CAAC,QAAQ,CAAC,MAAM,KAAK,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,CAA2B,CAAC;YACpG,MAAM,MAAM,GAAuC,EAAE,CAAC;YAEtD,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC1D,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;gBAC3B,IAAI,KAAK,CAAC,QAAQ,IAAI,CAAC,KAAK,EAAE,CAAC;oBAC3B,KAAK,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,CAAC,OAAO,IAAI,oBAAoB,IAAI,EAAE,CAAC,CAAC;oBAC7D,OAAO;gBACX,CAAC;gBACD,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC;YACzB,CAAC;YAED,IAAI,CAAC;gBACD,GAAG,CAAC,YAAY,CAAC,MAAM,QAAQ,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;YACtD,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACX,KAAK,CAAC,GAAG,EAAE,GAAG,EAAG,GAAa,CAAC,OAAO,CAAC,CAAC;YAC5C,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,IAAI,QAAQ,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;YAC7B,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,GAAY,EAAE,GAAa,EAAE,EAAE;gBAC7C,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;oBACf,KAAK,CAAC,GAAG,EAAE,GAAG,EAAE,6BAA6B,GAAG,CAAC,OAAO,GAAG,CAAC,CAAC;oBAC7D,OAAO;gBACX,CAAC;gBACD,KAAK,CAAC,GAAG,EAAE,GAAG,EAAE,4CAA4C,CAAC,CAAC;YAClE,CAAC,CAAC,CAAC;QACP,CAAC;IACL,CAAC;IAED,OAAO,MAAM,CAAC;AAClB,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Category, Param } from './endpoints/define.js';
|
|
2
|
+
export interface ManifestEntry {
|
|
3
|
+
name: string;
|
|
4
|
+
method: 'get' | 'post';
|
|
5
|
+
path: string;
|
|
6
|
+
category: Category;
|
|
7
|
+
since?: number;
|
|
8
|
+
params: Record<string, Param>;
|
|
9
|
+
example: Record<string, string>;
|
|
10
|
+
}
|
|
11
|
+
export declare const manifest: ManifestEntry[];
|
package/dist/manifest.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { endpoints } from './endpoints/index.js';
|
|
2
|
+
// Declared endpoints without their run function, for the documentation sidebar, parameter lists and playground
|
|
3
|
+
export const manifest = endpoints.map(({ name, method, path, category, since, params, example }) => ({
|
|
4
|
+
name,
|
|
5
|
+
method,
|
|
6
|
+
path,
|
|
7
|
+
category,
|
|
8
|
+
...(since ? { since } : {}),
|
|
9
|
+
params,
|
|
10
|
+
example: example,
|
|
11
|
+
}));
|
|
12
|
+
//# sourceMappingURL=manifest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest.js","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAYjD,+GAA+G;AAC/G,MAAM,CAAC,MAAM,QAAQ,GAAoB,SAAS,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC;IAClH,IAAI;IACJ,MAAM;IACN,IAAI;IACJ,QAAQ;IACR,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAC3B,MAAM;IACN,OAAO,EAAE,OAAiC;CAC7C,CAAC,CAAC,CAAC"}
|
|
@@ -1,2 +1,17 @@
|
|
|
1
1
|
import { type Express } from 'express';
|
|
2
|
+
/**
|
|
3
|
+
* Applies the proxy setting, the security headers, CORS and the robots.txt route.
|
|
4
|
+
*
|
|
5
|
+
* The security headers come first so that every response carries them,
|
|
6
|
+
* preflights and errors included. Body parsing is mounted separately by
|
|
7
|
+
* setupParsers, after the rate limiter.
|
|
8
|
+
*
|
|
9
|
+
* @param app - Express application to configure
|
|
10
|
+
*/
|
|
2
11
|
export declare function setupCors(app: Express): void;
|
|
12
|
+
/**
|
|
13
|
+
* Mounts the URL-encoded and JSON body parsers, both capped at 10 KB.
|
|
14
|
+
*
|
|
15
|
+
* @param app - Express application to configure
|
|
16
|
+
*/
|
|
17
|
+
export declare function setupParsers(app: Express): void;
|
package/dist/middleware/cors.js
CHANGED
|
@@ -5,8 +5,25 @@ import { fileURLToPath } from 'url';
|
|
|
5
5
|
import { env } from '../config/env.js';
|
|
6
6
|
const __filename = fileURLToPath(import.meta.url);
|
|
7
7
|
const __dirname = dirname(__filename);
|
|
8
|
+
/**
|
|
9
|
+
* Applies the proxy setting, the security headers, CORS and the robots.txt route.
|
|
10
|
+
*
|
|
11
|
+
* The security headers come first so that every response carries them,
|
|
12
|
+
* preflights and errors included. Body parsing is mounted separately by
|
|
13
|
+
* setupParsers, after the rate limiter.
|
|
14
|
+
*
|
|
15
|
+
* @param app - Express application to configure
|
|
16
|
+
*/
|
|
8
17
|
export function setupCors(app) {
|
|
9
18
|
app.set('trust proxy', env.TRUSTED_PROXIES ?? 1);
|
|
19
|
+
if (!env.TRUSTED_PROXIES && process.env.NODE_ENV !== 'test') {
|
|
20
|
+
console.warn('TRUSTED_PROXIES is unset: client addresses are read assuming exactly one reverse proxy in front of the API.');
|
|
21
|
+
}
|
|
22
|
+
app.use((_req, res, next) => {
|
|
23
|
+
res.setHeader('X-Content-Type-Options', 'nosniff');
|
|
24
|
+
res.setHeader('X-Frame-Options', 'DENY');
|
|
25
|
+
next();
|
|
26
|
+
});
|
|
10
27
|
app.use(cors({
|
|
11
28
|
methods: ['GET', 'POST', 'PATCH', 'DELETE', 'OPTIONS'],
|
|
12
29
|
exposedHeaders: [
|
|
@@ -18,14 +35,15 @@ export function setupCors(app) {
|
|
|
18
35
|
'Retry-After',
|
|
19
36
|
],
|
|
20
37
|
}));
|
|
38
|
+
app.use('/robots.txt', express.static(join(__dirname, '..', '..', 'robots.txt')));
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Mounts the URL-encoded and JSON body parsers, both capped at 10 KB.
|
|
42
|
+
*
|
|
43
|
+
* @param app - Express application to configure
|
|
44
|
+
*/
|
|
45
|
+
export function setupParsers(app) {
|
|
21
46
|
app.use(express.urlencoded({ extended: true, limit: '10kb' }));
|
|
22
47
|
app.use(express.json({ limit: '10kb' }));
|
|
23
|
-
app.use((_req, res, next) => {
|
|
24
|
-
res.setHeader('X-Content-Type-Options', 'nosniff');
|
|
25
|
-
res.setHeader('X-Frame-Options', 'DENY');
|
|
26
|
-
next();
|
|
27
|
-
});
|
|
28
|
-
app.use('/favicon.ico', express.static(join(__dirname, '..', '..', 'src', 'favicon.ico')));
|
|
29
|
-
app.use('/robots.txt', express.static(join(__dirname, '..', '..', 'robots.txt')));
|
|
30
48
|
}
|
|
31
49
|
//# sourceMappingURL=cors.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cors.js","sourceRoot":"","sources":["../../src/middleware/cors.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,OAAyB,MAAM,SAAS,CAAC;AAChD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AACrC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AAEpC,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AAEvC,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AAEtC,MAAM,UAAU,SAAS,CAAC,GAAY;IAClC,GAAG,CAAC,GAAG,CAAC,aAAa,EAAE,GAAG,CAAC,eAAe,IAAI,CAAC,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"cors.js","sourceRoot":"","sources":["../../src/middleware/cors.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,OAAyB,MAAM,SAAS,CAAC;AAChD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AACrC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AAEpC,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AAEvC,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AAEtC;;;;;;;;GAQG;AACH,MAAM,UAAU,SAAS,CAAC,GAAY;IAClC,GAAG,CAAC,GAAG,CAAC,aAAa,EAAE,GAAG,CAAC,eAAe,IAAI,CAAC,CAAC,CAAC;IACjD,IAAI,CAAC,GAAG,CAAC,eAAe,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,MAAM,EAAE,CAAC;QAC1D,OAAO,CAAC,IAAI,CACR,6GAA6G,CAChH,CAAC;IACN,CAAC;IAED,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QACxB,GAAG,CAAC,SAAS,CAAC,wBAAwB,EAAE,SAAS,CAAC,CAAC;QACnD,GAAG,CAAC,SAAS,CAAC,iBAAiB,EAAE,MAAM,CAAC,CAAC;QACzC,IAAI,EAAE,CAAC;IACX,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,GAAG,CACH,IAAI,CAAC;QACD,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,CAAC;QACtD,cAAc,EAAE;YACZ,gBAAgB;YAChB,iBAAiB;YACjB,mBAAmB;YACnB,uBAAuB;YACvB,mBAAmB;YACnB,aAAa;SAChB;KACJ,CAAC,CACL,CAAC;IAEF,GAAG,CAAC,GAAG,CAAC,aAAa,EAAE,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC;AACtF,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,GAAY;IACrC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;IAC/D,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;AAC7C,CAAC"}
|