@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.
Files changed (91) hide show
  1. package/README.md +44 -19
  2. package/dist/app.js +9 -4
  3. package/dist/app.js.map +1 -1
  4. package/dist/constants.d.ts +22 -0
  5. package/dist/constants.js +22 -0
  6. package/dist/constants.js.map +1 -1
  7. package/dist/endpoints/define.d.ts +30 -0
  8. package/dist/endpoints/define.js +14 -0
  9. package/dist/endpoints/define.js.map +1 -0
  10. package/dist/endpoints/hash.d.ts +2 -0
  11. package/dist/endpoints/hash.js +16 -0
  12. package/dist/endpoints/hash.js.map +1 -0
  13. package/dist/endpoints/index.d.ts +2 -0
  14. package/dist/endpoints/index.js +4 -0
  15. package/dist/endpoints/index.js.map +1 -0
  16. package/dist/endpoints/router.d.ts +10 -0
  17. package/dist/endpoints/router.js +50 -0
  18. package/dist/endpoints/router.js.map +1 -0
  19. package/dist/manifest.d.ts +11 -0
  20. package/dist/manifest.js +12 -0
  21. package/dist/manifest.js.map +1 -0
  22. package/dist/middleware/cors.d.ts +15 -0
  23. package/dist/middleware/cors.js +25 -7
  24. package/dist/middleware/cors.js.map +1 -1
  25. package/dist/middleware/ratelimit.d.ts +53 -1
  26. package/dist/middleware/ratelimit.js +180 -71
  27. package/dist/middleware/ratelimit.js.map +1 -1
  28. package/dist/modules/v4/barcode.d.ts +1 -1
  29. package/dist/modules/v4/barcode.js +9 -2
  30. package/dist/modules/v4/barcode.js.map +1 -1
  31. package/dist/modules/v4/captcha.d.ts +1 -1
  32. package/dist/modules/v4/captcha.js +5 -1
  33. package/dist/modules/v4/captcha.js.map +1 -1
  34. package/dist/modules/v4/chat.js +61 -12
  35. package/dist/modules/v4/chat.js.map +1 -1
  36. package/dist/modules/v4/cron.js +20 -2
  37. package/dist/modules/v4/cron.js.map +1 -1
  38. package/dist/modules/v4/hyperplanning.d.ts +11 -0
  39. package/dist/modules/v4/hyperplanning.js +30 -29
  40. package/dist/modules/v4/hyperplanning.js.map +1 -1
  41. package/dist/modules/v4/qrcode.d.ts +10 -0
  42. package/dist/modules/v4/qrcode.js +138 -14
  43. package/dist/modules/v4/qrcode.js.map +1 -1
  44. package/dist/modules/v4/regex.d.ts +1 -1
  45. package/dist/modules/v4/regex.js +67 -22
  46. package/dist/modules/v4/regex.js.map +1 -1
  47. package/dist/modules/v4/tic_tac_toe.js +56 -15
  48. package/dist/modules/v4/tic_tac_toe.js.map +1 -1
  49. package/dist/modules/v5/asymmetric.d.ts +15 -0
  50. package/dist/modules/v5/asymmetric.js +67 -5
  51. package/dist/modules/v5/asymmetric.js.map +1 -1
  52. package/dist/modules/v5/barcode.d.ts +1 -1
  53. package/dist/modules/v5/barcode.js +9 -2
  54. package/dist/modules/v5/barcode.js.map +1 -1
  55. package/dist/modules/v5/captcha.d.ts +12 -4
  56. package/dist/modules/v5/captcha.js +25 -8
  57. package/dist/modules/v5/captcha.js.map +1 -1
  58. package/dist/modules/v5/chat.js +66 -17
  59. package/dist/modules/v5/chat.js.map +1 -1
  60. package/dist/modules/v5/cron.d.ts +26 -0
  61. package/dist/modules/v5/cron.js +356 -0
  62. package/dist/modules/v5/cron.js.map +1 -0
  63. package/dist/modules/v5/pow.js +1 -1
  64. package/dist/modules/v5/pow.js.map +1 -1
  65. package/dist/modules/v5/tic_tac_toe.js +61 -20
  66. package/dist/modules/v5/tic_tac_toe.js.map +1 -1
  67. package/dist/modules/v5.d.ts +3 -2
  68. package/dist/modules/v5.js +3 -2
  69. package/dist/modules/v5.js.map +1 -1
  70. package/dist/routes/delete.js +0 -8
  71. package/dist/routes/delete.js.map +1 -1
  72. package/dist/routes/get.js +0 -2
  73. package/dist/routes/get.js.map +1 -1
  74. package/dist/routes/patch.js +0 -4
  75. package/dist/routes/patch.js.map +1 -1
  76. package/dist/routes/post.js +12 -25
  77. package/dist/routes/post.js.map +1 -1
  78. package/dist/storage/index.js +9 -8
  79. package/dist/storage/index.js.map +1 -1
  80. package/dist/types/storage.d.ts +4 -0
  81. package/dist/utils/challenge.d.ts +5 -3
  82. package/dist/utils/challenge.js +52 -6
  83. package/dist/utils/challenge.js.map +1 -1
  84. package/dist/utils/helpers.d.ts +18 -0
  85. package/dist/utils/helpers.js +35 -1
  86. package/dist/utils/helpers.js.map +1 -1
  87. package/dist/utils/remote.d.ts +42 -0
  88. package/dist/utils/remote.js +313 -0
  89. package/dist/utils/remote.js.map +1 -0
  90. package/package.json +28 -8
  91. package/src/favicon.ico +0 -0
@@ -10,6 +10,24 @@
10
10
  * @throws Error if rate limit is exceeded
11
11
  */
12
12
  export declare function checkRateLimit(rateLimits: Record<string, number[]>, userId: string, timestamp: number, window?: number, limit?: number): boolean;
13
+ /**
14
+ * Throws when a client value is an object or longer than the given limit.
15
+ *
16
+ * Numbers and booleans pass, measured as text, since the stores only compare them and use them as keys.
17
+ *
18
+ * @param value - The client value, skipped when empty so the caller's own missing-field error applies
19
+ * @param name - Field name used in the error messages (e.g. "session ID")
20
+ * @param max - Maximum length in characters
21
+ * @throws Error if the value is an object, an array or a function, or exceeds the limit
22
+ */
23
+ export declare function checkString(value: unknown, name: string, max: number): void;
24
+ /**
25
+ * Checks that a client-supplied timestamp can be stored as it was sent.
26
+ *
27
+ * @param value - The client value, in any format the client chose
28
+ * @returns true for a finite number, a boolean or a string up to MAX_TIMESTAMP_LENGTH characters
29
+ */
30
+ export declare function isTimestamp(value: unknown): boolean;
13
31
  /**
14
32
  * Parses a space-separated environment variable into an array.
15
33
  *
@@ -1,3 +1,4 @@
1
+ import { MAX_TIMESTAMP_LENGTH } from '../constants.js';
1
2
  /**
2
3
  * Tracks requests per user and throws if the rate limit is exceeded.
3
4
  *
@@ -15,7 +16,7 @@ export function checkRateLimit(rateLimits, userId, timestamp, window = 10000, li
15
16
  delete rateLimits[key];
16
17
  }
17
18
  }
18
- rateLimits[userId] = (rateLimits[userId] ?? []).filter((ts) => timestamp - ts < window);
19
+ rateLimits[userId] = (Object.hasOwn(rateLimits, userId) ? rateLimits[userId] : []).filter((ts) => timestamp - ts < window);
19
20
  if (rateLimits[userId].length >= limit) {
20
21
  const remainingTime = Math.ceil((rateLimits[userId][0] + window - timestamp) / 1000);
21
22
  throw new Error(`Rate limit exceeded. Try again in ${remainingTime} seconds.`);
@@ -23,6 +24,39 @@ export function checkRateLimit(rateLimits, userId, timestamp, window = 10000, li
23
24
  rateLimits[userId].push(timestamp);
24
25
  return false;
25
26
  }
27
+ /**
28
+ * Throws when a client value is an object or longer than the given limit.
29
+ *
30
+ * Numbers and booleans pass, measured as text, since the stores only compare them and use them as keys.
31
+ *
32
+ * @param value - The client value, skipped when empty so the caller's own missing-field error applies
33
+ * @param name - Field name used in the error messages (e.g. "session ID")
34
+ * @param max - Maximum length in characters
35
+ * @throws Error if the value is an object, an array or a function, or exceeds the limit
36
+ */
37
+ export function checkString(value, name, max) {
38
+ if (!value)
39
+ return;
40
+ if (typeof value !== 'string' && typeof value !== 'number' && typeof value !== 'boolean') {
41
+ throw new Error(`Please provide a valid ${name}`);
42
+ }
43
+ const label = name.charAt(0).toUpperCase() + name.slice(1);
44
+ if (String(value).length > max)
45
+ throw new Error(`${label} cannot exceed ${max} characters`);
46
+ }
47
+ /**
48
+ * Checks that a client-supplied timestamp can be stored as it was sent.
49
+ *
50
+ * @param value - The client value, in any format the client chose
51
+ * @returns true for a finite number, a boolean or a string up to MAX_TIMESTAMP_LENGTH characters
52
+ */
53
+ export function isTimestamp(value) {
54
+ if (typeof value === 'number')
55
+ return Number.isFinite(value);
56
+ if (typeof value === 'boolean')
57
+ return true;
58
+ return typeof value === 'string' && value.length <= MAX_TIMESTAMP_LENGTH;
59
+ }
26
60
  /**
27
61
  * Parses a space-separated environment variable into an array.
28
62
  *
@@ -1 +1 @@
1
- {"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../src/utils/helpers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,MAAM,UAAU,cAAc,CAC1B,UAAoC,EACpC,MAAc,EACd,SAAiB,EACjB,MAAM,GAAG,KAAK,EACd,KAAK,GAAG,EAAE;IAEV,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;QACxC,IAAI,GAAG,KAAK,MAAM,IAAI,CAAC,UAAU,CAAC,GAAG,CAAE,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,SAAS,GAAG,EAAE,GAAG,MAAM,CAAC,EAAE,CAAC;YAC5E,OAAO,UAAU,CAAC,GAAG,CAAC,CAAC;QAC3B,CAAC;IACL,CAAC;IAED,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,SAAS,GAAG,EAAE,GAAG,MAAM,CAAC,CAAC;IAExF,IAAI,UAAU,CAAC,MAAM,CAAE,CAAC,MAAM,IAAI,KAAK,EAAE,CAAC;QACtC,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,MAAM,CAAE,CAAC,CAAC,CAAE,GAAG,MAAM,GAAG,SAAS,CAAC,GAAG,IAAI,CAAC,CAAC;QACvF,MAAM,IAAI,KAAK,CAAC,qCAAqC,aAAa,WAAW,CAAC,CAAC;IACnF,CAAC;IAED,UAAU,CAAC,MAAM,CAAE,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACpC,OAAO,KAAK,CAAC;AACjB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,OAAO,CAAC,GAAW;IAC/B,MAAM,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC3B,OAAO,CAAC,IAAI,CAAC,KAAK,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AACxD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,UAAU,CAAC,IAAU;IACjC,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,iBAAiB,EAAE,GAAG,KAAK,CAAC,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;AACtG,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,KAAK;IACjB,OAAO,GAAG,YAAY,CAAC,CAAC,EAAE,GAAG,CAAC,IAAI,YAAY,CAAC,CAAC,EAAE,GAAG,CAAC,IAAI,YAAY,CAAC,CAAC,EAAE,GAAG,CAAC,IAAI,YAAY,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;AAC7G,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,MAAM,CAAI,GAAQ;IAC9B,OAAO,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC,CAAE,CAAC;AACxD,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,YAAY,CAAC,GAAW,EAAE,GAAW;IACjD,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC;AAC7D,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,KAAK,CAAC,OAAe,EAAE,GAAW;IAC9C,OAAO,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,IAAI,GAAG,CAAC;AACrD,CAAC"}
1
+ {"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../src/utils/helpers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,42 @@
1
+ import type { LookupAddress } from 'node:dns';
2
+ import type { ClientRequest, IncomingMessage, RequestOptions } from 'node:http';
3
+ import { BlockList } from 'node:net';
4
+ export type RemoteFailure = 'blocked' | 'protocol' | 'size' | 'network' | 'timeout';
5
+ export interface RemoteHead {
6
+ status: number;
7
+ ok: boolean;
8
+ contentType: string;
9
+ }
10
+ export interface RemoteOptions {
11
+ maxBytes: number;
12
+ timeout: number;
13
+ redirects?: number;
14
+ check?: (head: RemoteHead) => void;
15
+ messages?: Partial<Record<RemoteFailure, string>>;
16
+ blocklist?: BlockList;
17
+ resolve?: (hostname: string) => Promise<LookupAddress[]>;
18
+ request?: (url: URL, options: RequestOptions, callback: (response: IncomingMessage) => void) => ClientRequest;
19
+ }
20
+ export type RemoteFetcher = (url: string, options: RemoteOptions) => Promise<Buffer>;
21
+ /**
22
+ * Tells whether an IP address belongs to a private, loopback or otherwise internal range.
23
+ *
24
+ * @param address - IPv4 or IPv6 address, optionally with an IPv6 zone index
25
+ * @param blocklist - Ranges to reject, the internal ranges by default
26
+ * @returns true when the address must not be contacted
27
+ */
28
+ export declare function isPrivateAddress(address: string, blocklist?: BlockList): boolean;
29
+ /**
30
+ * Fetches an HTTPS resource without letting the caller reach internal hosts.
31
+ *
32
+ * The host is resolved once, every address is checked against the internal ranges, and the
33
+ * socket connects to those vetted addresses only. Redirects are followed by hand with the same
34
+ * checks on each hop, the body is streamed and cut past maxBytes, and the whole exchange,
35
+ * redirects and body included, must finish within the timeout.
36
+ *
37
+ * @param url - HTTPS URL to fetch
38
+ * @param options - Size limit, timeout, response check and test seams
39
+ * @returns The decoded response body
40
+ * @throws Error if the URL is invalid or internal, the transfer fails, times out or is too large, or check throws
41
+ */
42
+ export declare function fetchRemote(url: string, options: RemoteOptions): Promise<Buffer>;
@@ -0,0 +1,313 @@
1
+ import { lookup } from 'node:dns/promises';
2
+ import { Agent, request as httpsRequest } from 'node:https';
3
+ import { BlockList, isIP } from 'node:net';
4
+ import { pipeline } from 'node:stream';
5
+ import { constants, createBrotliDecompress, createGunzip, createInflate } from 'node:zlib';
6
+ import { MAX_REMOTE_REDIRECTS } from '../constants.js';
7
+ // Default messages; network and timeout keep the wording fetch() used before this helper
8
+ const MESSAGES = {
9
+ blocked: 'Access to private/internal hosts is not allowed.',
10
+ protocol: 'Only HTTPS URLs are allowed.',
11
+ size: 'Response body is too large.',
12
+ network: 'fetch failed',
13
+ timeout: 'The operation was aborted due to timeout',
14
+ };
15
+ // Same request headers as Node's built-in fetch, so remote servers answer as before
16
+ const HEADERS = {
17
+ accept: '*/*',
18
+ 'accept-language': '*',
19
+ 'sec-fetch-mode': 'cors',
20
+ 'user-agent': 'node',
21
+ 'accept-encoding': 'gzip, deflate',
22
+ };
23
+ const BLOCKED_HOSTS = new Set(['localhost', 'metadata.google.internal']);
24
+ const REDIRECT_STATUSES = new Set([301, 302, 303, 307, 308]);
25
+ // Shared so repeated fetches reuse a socket; a pooled socket only ever connected to a vetted address
26
+ const AGENT = new Agent({ keepAlive: true });
27
+ // Loopback, private, link-local, CGNAT, unspecified, multicast, documentation, relay and reserved ranges
28
+ const PRIVATE_RANGES = new BlockList();
29
+ for (const [network, prefix] of [
30
+ ['0.0.0.0', 8],
31
+ ['10.0.0.0', 8],
32
+ ['100.64.0.0', 10],
33
+ ['127.0.0.0', 8],
34
+ ['169.254.0.0', 16],
35
+ ['172.16.0.0', 12],
36
+ ['192.0.0.0', 24],
37
+ ['192.0.2.0', 24],
38
+ ['192.88.99.0', 24],
39
+ ['192.168.0.0', 16],
40
+ ['198.18.0.0', 15],
41
+ ['198.51.100.0', 24],
42
+ ['203.0.113.0', 24],
43
+ ['224.0.0.0', 4],
44
+ ['240.0.0.0', 4],
45
+ ]) {
46
+ PRIVATE_RANGES.addSubnet(network, prefix, 'ipv4');
47
+ }
48
+ // 6to4 and Teredo embed an IPv4 address reached through a relay, so they are refused as a whole
49
+ for (const [network, prefix] of [
50
+ ['::', 96],
51
+ ['::ffff:0:0:0', 96],
52
+ ['64:ff9b:1::', 48],
53
+ ['100::', 64],
54
+ ['2001::', 32],
55
+ ['2001:db8::', 32],
56
+ ['2002::', 16],
57
+ ['fc00::', 7],
58
+ ['fe80::', 10],
59
+ ['fec0::', 10],
60
+ ['ff00::', 8],
61
+ ]) {
62
+ PRIVATE_RANGES.addSubnet(network, prefix, 'ipv6');
63
+ }
64
+ /**
65
+ * Tells whether an IP address belongs to a private, loopback or otherwise internal range.
66
+ *
67
+ * @param address - IPv4 or IPv6 address, optionally with an IPv6 zone index
68
+ * @param blocklist - Ranges to reject, the internal ranges by default
69
+ * @returns true when the address must not be contacted
70
+ */
71
+ export function isPrivateAddress(address, blocklist = PRIVATE_RANGES) {
72
+ const bare = address.split('%')[0];
73
+ const family = isIP(bare);
74
+ if (family === 0)
75
+ return true;
76
+ if (family === 4)
77
+ return blocklist.check(bare, 'ipv4');
78
+ if (blocklist.check(bare, 'ipv6'))
79
+ return true;
80
+ // IPv4-mapped addresses are matched by BlockList itself, NAT64 ones are not
81
+ const nat64 = /^\[64:ff9b::(?:([0-9a-f]{1,4}):)?([0-9a-f]{1,4})?\]$/.exec(new URL(`http://[${bare}]`).hostname);
82
+ if (!nat64)
83
+ return false;
84
+ const value = (parseInt(nat64[1] ?? '0', 16) << 16) | parseInt(nat64[2] ?? '0', 16);
85
+ const embedded = [24, 16, 8, 0].map((shift) => (value >>> shift) & 255).join('.');
86
+ return blocklist.check(embedded, 'ipv4');
87
+ }
88
+ /**
89
+ * Builds the error thrown for a failed remote fetch.
90
+ *
91
+ * @param kind - Failure category
92
+ * @param messages - Caller overrides for the user-facing messages
93
+ * @returns Error carrying the caller's message, or the default one for that category
94
+ */
95
+ function failure(kind, messages) {
96
+ return new Error(messages?.[kind] ?? MESSAGES[kind]);
97
+ }
98
+ /**
99
+ * Parses a URL to fetch and enforces HTTPS without credentials.
100
+ *
101
+ * @param url - Absolute URL, or a redirect location relative to base
102
+ * @param messages - Caller overrides for the user-facing messages
103
+ * @param base - URL of the response that redirected, if any
104
+ * @returns Parsed URL
105
+ */
106
+ function parse(url, messages, base) {
107
+ let parsed;
108
+ try {
109
+ parsed = new URL(url, base);
110
+ }
111
+ catch {
112
+ throw base ? failure('network', messages) : new Error(`Failed to parse URL from ${url}`);
113
+ }
114
+ if (parsed.protocol !== 'https:')
115
+ throw failure('protocol', messages);
116
+ if (parsed.username || parsed.password) {
117
+ throw base
118
+ ? failure('network', messages)
119
+ : new Error(`Request cannot be constructed from a URL that includes credentials: ${url}`);
120
+ }
121
+ return parsed;
122
+ }
123
+ /**
124
+ * Resolves a hostname with the system resolver, returning every address.
125
+ *
126
+ * @param hostname - Hostname to resolve
127
+ * @returns All addresses the hostname resolves to
128
+ */
129
+ function resolveHost(hostname) {
130
+ return lookup(hostname, { all: true });
131
+ }
132
+ /**
133
+ * Resolves the URL host once and rejects it when any of its addresses is internal.
134
+ *
135
+ * @param url - URL about to be fetched
136
+ * @param options - Fetch options holding the blocklist, resolver and messages
137
+ * @returns The vetted addresses, which are the only ones the connection may use
138
+ */
139
+ async function vet(url, options) {
140
+ const host = url.hostname.replace(/^\[|\]$/g, '').replace(/\.$/, '');
141
+ if (BLOCKED_HOSTS.has(host) || host.endsWith('.localhost'))
142
+ throw failure('blocked', options.messages);
143
+ const family = isIP(host);
144
+ let addresses;
145
+ if (family) {
146
+ addresses = [{ address: host, family }];
147
+ }
148
+ else {
149
+ try {
150
+ addresses = await (options.resolve ?? resolveHost)(host);
151
+ }
152
+ catch {
153
+ throw failure('network', options.messages);
154
+ }
155
+ }
156
+ const blocklist = options.blocklist ?? PRIVATE_RANGES;
157
+ if (!addresses.length || addresses.some(({ address }) => isPrivateAddress(address, blocklist))) {
158
+ throw failure('blocked', options.messages);
159
+ }
160
+ return addresses;
161
+ }
162
+ /**
163
+ * Sends one GET request whose socket can only connect to the vetted addresses.
164
+ *
165
+ * @param url - URL to request
166
+ * @param addresses - Addresses returned by vet()
167
+ * @param options - Fetch options holding the transport and messages
168
+ * @param signal - Signal aborting the request on timeout
169
+ * @returns The response, before its body is read
170
+ */
171
+ function send(url, addresses, options, signal) {
172
+ // Pinning the lookup stops a second DNS answer (rebinding) from changing the target
173
+ const pinned = (_hostname, lookupOptions, callback) => {
174
+ if (lookupOptions.all)
175
+ callback(null, addresses);
176
+ else
177
+ callback(null, addresses[0].address, addresses[0].family);
178
+ };
179
+ return new Promise((resolve, reject) => {
180
+ const req = (options.request ?? httpsRequest)(url, { method: 'GET', headers: HEADERS, lookup: pinned, agent: AGENT, signal }, resolve);
181
+ req.on('error', () => reject(failure('network', options.messages)));
182
+ req.end();
183
+ });
184
+ }
185
+ /**
186
+ * Builds the decompression stages for a Content-Encoding header, like fetch() does.
187
+ *
188
+ * @param header - Content-Encoding header value
189
+ * @returns Decoders to apply in order, or none when an encoding is unknown
190
+ */
191
+ function decoders(header) {
192
+ const codings = (header ?? '')
193
+ .toLowerCase()
194
+ .split(',')
195
+ .map((c) => c.trim())
196
+ .filter(Boolean);
197
+ const zlib = { flush: constants.Z_SYNC_FLUSH, finishFlush: constants.Z_SYNC_FLUSH };
198
+ const brotli = { flush: constants.BROTLI_OPERATION_FLUSH, finishFlush: constants.BROTLI_OPERATION_FLUSH };
199
+ const stages = [];
200
+ for (const coding of codings.reverse()) {
201
+ if (coding === 'gzip' || coding === 'x-gzip')
202
+ stages.push(createGunzip(zlib));
203
+ else if (coding === 'deflate')
204
+ stages.push(createInflate(zlib));
205
+ else if (coding === 'br')
206
+ stages.push(createBrotliDecompress(brotli));
207
+ else
208
+ return [];
209
+ }
210
+ return stages;
211
+ }
212
+ /**
213
+ * Reads a decoded response body and aborts as soon as it grows past the limit.
214
+ *
215
+ * @param response - Response to read
216
+ * @param maxBytes - Largest decoded body accepted
217
+ * @param messages - Caller overrides for the user-facing messages
218
+ * @returns The decoded body
219
+ */
220
+ async function readBody(response, maxBytes, messages) {
221
+ const stages = decoders(response.headers['content-encoding']);
222
+ const stream = stages.length ? pipeline([response, ...stages], () => { }) : response;
223
+ const chunks = [];
224
+ let size = 0;
225
+ try {
226
+ for await (const chunk of stream) {
227
+ size += chunk.length;
228
+ if (size > maxBytes)
229
+ break;
230
+ chunks.push(chunk);
231
+ }
232
+ }
233
+ catch {
234
+ throw failure('network', messages);
235
+ }
236
+ finally {
237
+ response.destroy();
238
+ }
239
+ if (size > maxBytes)
240
+ throw failure('size', messages);
241
+ return Buffer.concat(chunks);
242
+ }
243
+ /**
244
+ * Follows the redirect chain by hand, vetting every hop, then reads the final body.
245
+ *
246
+ * @param url - URL to fetch
247
+ * @param options - Fetch options
248
+ * @param signal - Signal aborted on timeout
249
+ * @returns The decoded body of the final response
250
+ */
251
+ async function download(url, options, signal) {
252
+ const redirects = options.redirects ?? MAX_REMOTE_REDIRECTS;
253
+ let target = parse(url, options.messages);
254
+ for (let hop = 0;; hop++) {
255
+ const addresses = await vet(target, options);
256
+ if (signal.aborted)
257
+ throw failure('timeout', options.messages);
258
+ const response = await send(target, addresses, options, signal);
259
+ const status = response.statusCode ?? 0;
260
+ const location = response.headers.location;
261
+ if (REDIRECT_STATUSES.has(status) && location) {
262
+ response.destroy();
263
+ if (hop >= redirects)
264
+ throw failure('network', options.messages);
265
+ target = parse(location, options.messages, target);
266
+ continue;
267
+ }
268
+ try {
269
+ options.check?.({
270
+ status,
271
+ ok: status >= 200 && status <= 299,
272
+ contentType: response.headers['content-type'] ?? '',
273
+ });
274
+ }
275
+ catch (err) {
276
+ response.destroy();
277
+ throw err;
278
+ }
279
+ return readBody(response, options.maxBytes, options.messages);
280
+ }
281
+ }
282
+ /**
283
+ * Fetches an HTTPS resource without letting the caller reach internal hosts.
284
+ *
285
+ * The host is resolved once, every address is checked against the internal ranges, and the
286
+ * socket connects to those vetted addresses only. Redirects are followed by hand with the same
287
+ * checks on each hop, the body is streamed and cut past maxBytes, and the whole exchange,
288
+ * redirects and body included, must finish within the timeout.
289
+ *
290
+ * @param url - HTTPS URL to fetch
291
+ * @param options - Size limit, timeout, response check and test seams
292
+ * @returns The decoded response body
293
+ * @throws Error if the URL is invalid or internal, the transfer fails, times out or is too large, or check throws
294
+ */
295
+ export async function fetchRemote(url, options) {
296
+ const controller = new AbortController();
297
+ const timer = setTimeout(() => controller.abort(), options.timeout).unref();
298
+ const expired = new Promise((_, reject) => {
299
+ controller.signal.addEventListener('abort', () => reject(failure('timeout', options.messages)), {
300
+ once: true,
301
+ });
302
+ });
303
+ try {
304
+ return await Promise.race([download(url, options, controller.signal), expired]);
305
+ }
306
+ catch (err) {
307
+ throw controller.signal.aborted ? failure('timeout', options.messages) : err;
308
+ }
309
+ finally {
310
+ clearTimeout(timer);
311
+ }
312
+ }
313
+ //# sourceMappingURL=remote.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remote.js","sourceRoot":"","sources":["../../src/utils/remote.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
- "version": "6.0.0-pre",
2
+ "version": "6.2.0",
3
3
  "name": "@moxon/api",
4
- "description": "Node.js API with multiple features. Check the documentation at https://docs.sylvain.sh",
4
+ "description": "Node.js API with 40+ utilities, usable as a library or over HTTP. Documentation at https://moxon.dev",
5
5
  "main": "./dist/modules/v6.js",
6
6
  "types": "./dist/modules/v6.d.ts",
7
7
  "type": "module",
@@ -27,6 +27,10 @@
27
27
  "types": "./dist/app.d.ts",
28
28
  "default": "./dist/app.js"
29
29
  },
30
+ "./manifest": {
31
+ "types": "./dist/manifest.d.ts",
32
+ "default": "./dist/manifest.js"
33
+ },
30
34
  "./v4": {
31
35
  "types": "./dist/modules/v4.d.ts",
32
36
  "default": "./dist/modules/v4.js"
@@ -72,19 +76,35 @@
72
76
  },
73
77
  "repository": {
74
78
  "type": "git",
75
- "url": "git+https://github.com/20syldev/moxon.git"
79
+ "url": "git+https://github.com/moxondev/api.git"
76
80
  },
77
81
  "keywords": [
78
82
  "api",
83
+ "barcode",
84
+ "base64",
85
+ "captcha",
86
+ "chart",
87
+ "crypto",
88
+ "csv",
89
+ "encryption",
79
90
  "express",
80
- "utility",
91
+ "jwt",
92
+ "levenshtein",
81
93
  "math",
82
- "typescript"
94
+ "pow",
95
+ "proof-of-work",
96
+ "qrcode",
97
+ "svg",
98
+ "totp",
99
+ "typescript",
100
+ "utilities",
101
+ "uuid",
102
+ "validation"
83
103
  ],
84
104
  "author": "Sylvain L.",
85
- "license": "BSD 3-Clause",
105
+ "license": "BSD-3-Clause",
86
106
  "bugs": {
87
- "url": "https://github.com/20syldev/moxon/issues"
107
+ "url": "https://github.com/moxondev/api/issues"
88
108
  },
89
- "homepage": "https://api.sylvain.sh"
109
+ "homepage": "https://moxon.dev"
90
110
  }
package/src/favicon.ico DELETED
Binary file