@amxts/core 0.1.0 → 0.2.1

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 (77) hide show
  1. package/README.md +21 -25
  2. package/README.ru.md +22 -24
  3. package/as/amxts.d.ts +63 -3
  4. package/as/constants.ts +684 -116
  5. package/as/entities.ts +1905 -1364
  6. package/as/events.ts +1696 -907
  7. package/as/facade.ts +1240 -220
  8. package/as/fetch.ts +1519 -0
  9. package/as/flags.ts +159 -145
  10. package/as/hlds.ts +1071 -0
  11. package/as/hooks.ts +5226 -5379
  12. package/as/kit.ts +15 -5
  13. package/as/lib/check.ts +1 -1
  14. package/as/natives.ts +2658 -2499
  15. package/as/remote.ts +39 -15
  16. package/as/tsconfig.json +7 -2
  17. package/as/vector.ts +12 -9
  18. package/includes/order.txt +22 -29
  19. package/includes/sources.json +0 -8
  20. package/node_modules/assemblyscript/std/assembly/index.d.ts +20 -11
  21. package/package.json +29 -7
  22. package/runtime/deps/assemblyscript/dist/asc.js +86 -16
  23. package/runtime/deps/assemblyscript/dist/assemblyscript.js +29 -29
  24. package/runtime/licenses/MPL-2.0.txt +373 -0
  25. package/runtime/licenses/README.md +5 -1
  26. package/runtime/licenses/curl-COPYING +22 -0
  27. package/runtime/licenses/libssh2-COPYING +43 -0
  28. package/runtime/licenses/mbedTLS-LICENSE +553 -0
  29. package/runtime/natives.txt +108 -105
  30. package/runtime/patches/assemblyscript-0.28.20-amxts.patch +752 -296
  31. package/runtime/patches/wamr-2.4.5-amxts.patch +148 -0
  32. package/scripts/apply-docs.ts +2 -2
  33. package/scripts/auto-imports.ts +2 -2
  34. package/scripts/build-identity.ts +115 -0
  35. package/scripts/build-wasm.ts +101 -50
  36. package/scripts/check.ts +17 -3
  37. package/scripts/client-messages.ts +246 -0
  38. package/scripts/compile-cache.ts +4 -2
  39. package/scripts/compile-pool.ts +128 -0
  40. package/scripts/compile-worker.ts +23 -0
  41. package/scripts/compile.ts +156 -59
  42. package/scripts/docker-server.ts +13 -3
  43. package/scripts/docs/as/amxts.ts +86 -0
  44. package/scripts/docs/as/facade.ts +688 -188
  45. package/scripts/docs/as/fetch.ts +805 -0
  46. package/scripts/docs/entities.ts +43 -144
  47. package/scripts/docs/events.ts +17 -28
  48. package/scripts/docs/game.ts +68 -22
  49. package/scripts/docs/messages.ts +330 -16
  50. package/scripts/editor-api.ts +101 -0
  51. package/scripts/hlds-events.ts +370 -0
  52. package/scripts/includes.ts +12 -10
  53. package/scripts/player-fields.ts +16 -15
  54. package/scripts/prebuilt.ts +65 -23
  55. package/scripts/prepare.ts +42 -28
  56. package/scripts/project.ts +120 -20
  57. package/scripts/reapi-events.ts +98 -0
  58. package/scripts/shared-modules.ts +85 -23
  59. package/scripts/source-map.ts +242 -0
  60. package/scripts/system.ts +1 -1
  61. package/scripts/typed-commands.ts +263 -0
  62. package/scripts/typed-configs.ts +23 -12
  63. package/scripts/ui.ts +3 -1
  64. package/scripts/upgrade-menus.ts +274 -0
  65. package/scripts/upgrade-names.ts +384 -0
  66. package/scripts/upgrade.ts +857 -0
  67. package/src/cli-api.mjs +37 -4
  68. package/src/system.mjs +74 -3
  69. package/src/testing/compile.ts +8 -5
  70. package/src/testing/index.ts +2 -1
  71. package/src/testing/natives.ts +199 -5
  72. package/src/testing/network.ts +531 -0
  73. package/src/testing/server.ts +572 -48
  74. package/src/testing/setup.ts +1 -1
  75. package/src/testing/tables.ts +25 -0
  76. package/as/modules/http.ts +0 -184
  77. package/scripts/docs/as/modules/http.ts +0 -66
@@ -0,0 +1,805 @@
1
+ // The tooltips of as/fetch.ts, in both languages: scripts/apply-docs.ts writes the
2
+ // one AMXTS_DOCS_LANG picks into the JSDoc above each element.
3
+ export default {
4
+ 'URL': {
5
+ en: `
6
+ A web address taken apart: its protocol, host, path and query.
7
+
8
+ \`\`\`ts
9
+ const url = new URL("https://example.com/api/stats?id=7");
10
+ url.searchParams.set("map", server.map);
11
+ const response = await fetch(url);
12
+ \`\`\`
13
+ `,
14
+ ru: `
15
+ Веб-адрес, разобранный на части: протокол, хост, путь и запрос.
16
+
17
+ \`\`\`ts
18
+ const url = new URL("https://example.com/api/stats?id=7");
19
+ url.searchParams.set("map", server.map);
20
+ const response = await fetch(url);
21
+ \`\`\`
22
+ `,
23
+ },
24
+ 'URL.canParse': {
25
+ en: `\`true\` when \`url\`, relative to \`base\` when given, is a URL \`new URL\` would take.`,
26
+ ru: `\`true\`, если \`url\` (относительно \`base\`, когда он задан) — адрес, который примет \`new URL\`.`,
27
+ },
28
+ 'URL.parse': {
29
+ en: `The URL, or \`null\` when \`url\` is not one - \`new URL\` without the throw.`,
30
+ ru: `Адрес или \`null\`, если \`url\` не адрес, — \`new URL\` без исключения.`,
31
+ },
32
+ 'URL.href': {
33
+ en: `The whole URL as text, e.g. \`"https://example.com/api?id=7"\`.`,
34
+ ru: `Весь адрес текстом, например \`"https://example.com/api?id=7"\`.`,
35
+ },
36
+ 'URL.protocol': {
37
+ en: `The scheme with its colon, e.g. \`"https:"\`.`,
38
+ ru: `Схема с двоеточием, например \`"https:"\`.`,
39
+ },
40
+ 'URL.username': {
41
+ en: `The user name before the host, e.g. \`"admin"\` in \`ftp://admin:secret@example.com\`; \`""\` when there is none.`,
42
+ ru: `Имя пользователя перед хостом, например \`"admin"\` в \`ftp://admin:secret@example.com\`; \`""\`, если его нет.`,
43
+ },
44
+ 'URL.password': {
45
+ en: `The password before the host; \`""\` when there is none.`,
46
+ ru: `Пароль перед хостом; \`""\`, если его нет.`,
47
+ },
48
+ 'URL.host': {
49
+ en: `The host with its port when the URL names one, e.g. \`"example.com:8080"\`.`,
50
+ ru: `Хост с портом, когда адрес его называет, например \`"example.com:8080"\`.`,
51
+ },
52
+ 'URL.hostname': {
53
+ en: `The host without the port, e.g. \`"example.com"\`.`,
54
+ ru: `Хост без порта, например \`"example.com"\`.`,
55
+ },
56
+ 'URL.port': {
57
+ en: `The port as text, e.g. \`"8080"\`; \`""\` for the protocol's default one.`,
58
+ ru: `Порт текстом, например \`"8080"\`; \`""\` для порта протокола по умолчанию.`,
59
+ },
60
+ 'URL.pathname': {
61
+ en: `The path, e.g. \`"/api/stats"\`.`,
62
+ ru: `Путь, например \`"/api/stats"\`.`,
63
+ },
64
+ 'URL.search': {
65
+ en: `The query with its \`?\`, e.g. \`"?id=7"\`; \`""\` when there is none.`,
66
+ ru: `Запрос со знаком \`?\`, например \`"?id=7"\`; \`""\`, если его нет.`,
67
+ },
68
+ 'URL.hash': {
69
+ en: `The fragment with its \`#\`, e.g. \`"#top"\`; \`""\` when there is none.`,
70
+ ru: `Фрагмент со знаком \`#\`, например \`"#top"\`; \`""\`, если его нет.`,
71
+ },
72
+ 'URL.origin': {
73
+ en: `The scheme, host and port, e.g. \`"https://example.com"\`; \`"null"\` for a URL without a host.`,
74
+ ru: `Схема, хост и порт, например \`"https://example.com"\`; \`"null"\` для адреса без хоста.`,
75
+ },
76
+ 'URL.searchParams': {
77
+ en: `The query as names and values; a change to them changes the URL.`,
78
+ ru: `Запрос как имена и значения; их изменение меняет адрес.`,
79
+ },
80
+ 'URL.toString': {
81
+ en: `The whole URL as text, as \`href\`.`,
82
+ ru: `Весь адрес текстом, как \`href\`.`,
83
+ },
84
+ 'URL.toJSON': {
85
+ en: `The whole URL as text: what \`JSON.stringify\` writes for it.`,
86
+ ru: `Весь адрес текстом: то, что пишет для него \`JSON.stringify\`.`,
87
+ },
88
+ 'URLSearchParams': {
89
+ en: `
90
+ A query's names and values, such as \`id=7&map=de_dust2\`.
91
+
92
+ \`\`\`ts
93
+ const query = new URLSearchParams({ id: "7", map: server.map });
94
+ const response = await fetch(\`https://example.com/api?\${query}\`);
95
+ \`\`\`
96
+ `,
97
+ ru: `
98
+ Имена и значения запроса, например \`id=7&map=de_dust2\`.
99
+
100
+ \`\`\`ts
101
+ const query = new URLSearchParams({ id: "7", map: server.map });
102
+ const response = await fetch(\`https://example.com/api?\${query}\`);
103
+ \`\`\`
104
+ `,
105
+ },
106
+ 'URLSearchParams.size': {
107
+ en: `The number of name and value pairs, a name given twice counted twice.`,
108
+ ru: `Число пар имени и значения; имя, данное дважды, считается дважды.`,
109
+ },
110
+ 'URLSearchParams.append': {
111
+ en: `Adds a pair; a name already there keeps its value too.`,
112
+ ru: `Добавляет пару; у имени, которое уже есть, остаётся и прежнее значение.`,
113
+ },
114
+ 'URLSearchParams.delete': {
115
+ en: `Removes every pair of \`name\`.`,
116
+ ru: `Убирает все пары с именем \`name\`.`,
117
+ },
118
+ 'URLSearchParams.get': {
119
+ en: `The first value of \`name\`, or \`null\` when there is none.`,
120
+ ru: `Первое значение \`name\` или \`null\`, если его нет.`,
121
+ },
122
+ 'URLSearchParams.getAll': {
123
+ en: `Every value of \`name\`, in order.`,
124
+ ru: `Все значения \`name\` по порядку.`,
125
+ },
126
+ 'URLSearchParams.has': {
127
+ en: `\`true\` when there is a pair of \`name\`.`,
128
+ ru: `\`true\`, если есть пара с именем \`name\`.`,
129
+ },
130
+ 'URLSearchParams.set': {
131
+ en: `Sets \`name\` to \`value\`: the first pair takes it, the other pairs of the name go.`,
132
+ ru: `Ставит \`name\` значение \`value\`: его получает первая пара, остальные пары этого имени уходят.`,
133
+ },
134
+ 'URLSearchParams.sort': {
135
+ en: `Orders the pairs by name; pairs of one name keep their order.`,
136
+ ru: `Упорядочивает пары по имени; пары одного имени сохраняют свой порядок.`,
137
+ },
138
+ 'URLSearchParams.forEach': {
139
+ en: `Calls \`callback\` with each value and its name, in order.`,
140
+ ru: `Вызывает \`callback\` с каждым значением и его именем по порядку.`,
141
+ },
142
+ 'URLSearchParams.keys': {
143
+ en: `Every name, in order; a name given twice is there twice.`,
144
+ ru: `Все имена по порядку; имя, данное дважды, встречается дважды.`,
145
+ },
146
+ 'URLSearchParams.values': {
147
+ en: `Every value, in order.`,
148
+ ru: `Все значения по порядку.`,
149
+ },
150
+ 'URLSearchParams.entries': {
151
+ en: `Every pair as \`[name, value]\`, in order.`,
152
+ ru: `Все пары как \`[name, value]\` по порядку.`,
153
+ },
154
+ 'URLSearchParams.toString': {
155
+ en: `The query as text, without the \`?\`: \`id=7&map=de_dust2\`.`,
156
+ ru: `Запрос текстом, без \`?\`: \`id=7&map=de_dust2\`.`,
157
+ },
158
+ 'Headers': {
159
+ en: `
160
+ A request's or a response's HTTP headers. Names are matched without
161
+ regard to case.
162
+
163
+ \`\`\`ts
164
+ const type = response.headers.get("content-type");
165
+ \`\`\`
166
+ `,
167
+ ru: `
168
+ HTTP-заголовки запроса или ответа. Имена сравниваются без учёта
169
+ регистра.
170
+
171
+ \`\`\`ts
172
+ const type = response.headers.get("content-type");
173
+ \`\`\`
174
+ `,
175
+ },
176
+ 'Headers.append': {
177
+ en: `Adds a value to \`name\`; one already there stays, and \`get\` joins them.`,
178
+ ru: `Добавляет значение к \`name\`; прежнее остаётся, и \`get\` их объединяет.`,
179
+ },
180
+ 'Headers.delete': {
181
+ en: `Removes \`name\` and all its values.`,
182
+ ru: `Убирает \`name\` со всеми его значениями.`,
183
+ },
184
+ 'Headers.get': {
185
+ en: `The value of \`name\` - its values joined with \`", "\` when it has several - or \`null\` when there is none.`,
186
+ ru: `Значение \`name\` — несколько значений через \`", "\` — или \`null\`, если такого заголовка нет.`,
187
+ },
188
+ 'Headers.getSetCookie': {
189
+ en: `Every \`Set-Cookie\` header of a response, each its own text.`,
190
+ ru: `Все заголовки \`Set-Cookie\` ответа, каждый отдельным текстом.`,
191
+ },
192
+ 'Headers.has': {
193
+ en: `\`true\` when there is a header of \`name\`.`,
194
+ ru: `\`true\`, если есть заголовок \`name\`.`,
195
+ },
196
+ 'Headers.set': {
197
+ en: `Sets \`name\` to \`value\`, in place of every value it had.`,
198
+ ru: `Ставит \`name\` значение \`value\` вместо всех прежних.`,
199
+ },
200
+ 'Headers.forEach': {
201
+ en: `Calls \`callback\` with each header's value and its name in lower case, ordered by name.`,
202
+ ru: `Вызывает \`callback\` со значением каждого заголовка и его именем в нижнем регистре, по порядку имён.`,
203
+ },
204
+ 'Headers.keys': {
205
+ en: `Every header's name in lower case, ordered by name.`,
206
+ ru: `Имена всех заголовков в нижнем регистре, по порядку имён.`,
207
+ },
208
+ 'Headers.values': {
209
+ en: `Every header's value, ordered by name.`,
210
+ ru: `Значения всех заголовков по порядку имён.`,
211
+ },
212
+ 'Headers.entries': {
213
+ en: `Every header as \`[name, value]\`, ordered by name; the values of a name joined, but each \`set-cookie\` on its own.`,
214
+ ru: `Все заголовки как \`[name, value]\` по порядку имён; значения одного имени объединены, но каждый \`set-cookie\` отдельно.`,
215
+ },
216
+ 'TlsOptions': {
217
+ en: `The check of a server's certificate, for HTTPS.`,
218
+ ru: `Проверка сертификата сервера при HTTPS.`,
219
+ },
220
+ 'TlsOptions.ca': {
221
+ en: `
222
+ The certificate authorities a server's certificate must come from, as
223
+ PEM text - for a server with a certificate of its own making. Left out,
224
+ the authorities a browser trusts.
225
+ `,
226
+ ru: `
227
+ Центры сертификации, от которых должен быть сертификат сервера, текстом
228
+ PEM — для сервера с собственным сертификатом. Если не задано — центры,
229
+ которым доверяет браузер.
230
+ `,
231
+ },
232
+ 'RequestInit': {
233
+ en: `A request's options: \`fetch\`'s second argument. Every field is optional.`,
234
+ ru: `Настройки запроса: второй аргумент \`fetch\`. Все поля необязательны.`,
235
+ },
236
+ 'RequestInit.method': {
237
+ en: `The request's method, e.g. \`"POST"\`; \`"GET"\` by default.`,
238
+ ru: `Метод запроса, например \`"POST"\`; по умолчанию \`"GET"\`.`,
239
+ },
240
+ 'RequestInit.headers': {
241
+ en: `The request's headers, as an object of names and values: \`{ Authorization: "Bearer abc" }\`.`,
242
+ ru: `Заголовки запроса, объектом имён и значений: \`{ Authorization: "Bearer abc" }\`.`,
243
+ },
244
+ 'RequestInit.body': {
245
+ en: `The text sent with the request, such as JSON. A GET or HEAD request has none.`,
246
+ ru: `Текст, который уходит с запросом, например JSON. У запроса GET или HEAD его нет.`,
247
+ },
248
+ 'RequestInit.redirect': {
249
+ en: `
250
+ The request's answer to a redirect: one of \`"follow"\` (the default) - on
251
+ to its address, \`"manual"\` - the redirect itself as the response, \`"error"\` - a rejection.
252
+ `,
253
+ ru: `
254
+ Поведение запроса при перенаправлении: одно из \`"follow"\` (по умолчанию) — по
255
+ его адресу, \`"manual"\` — само перенаправление ответом, \`"error"\` — отказ.
256
+ `,
257
+ },
258
+ 'RequestInit.signal': {
259
+ en: `A signal that cancels the request; the promise then rejects with the signal's reason.`,
260
+ ru: `Сигнал, который отменяет запрос; промис тогда отклоняется с причиной сигнала.`,
261
+ },
262
+ 'RequestInit.proxy': {
263
+ en: `A proxy the request goes through, e.g. \`"http://proxy.example.com:3128"\`.`,
264
+ ru: `Прокси, через который идёт запрос, например \`"http://proxy.example.com:3128"\`.`,
265
+ },
266
+ 'RequestInit.tls': {
267
+ en: `The check of the server's certificate, for HTTPS.`,
268
+ ru: `Проверка сертификата сервера при HTTPS.`,
269
+ },
270
+ 'Request': {
271
+ en: `
272
+ A request: its address, method, headers and body - what \`fetch\` sends.
273
+
274
+ \`\`\`ts
275
+ const request = new Request("https://example.com/api", { method: "POST", body: "hi" });
276
+ const response = await fetch(request);
277
+ \`\`\`
278
+ `,
279
+ ru: `
280
+ Запрос: адрес, метод, заголовки и тело — то, что отправляет \`fetch\`.
281
+
282
+ \`\`\`ts
283
+ const request = new Request("https://example.com/api", { method: "POST", body: "hi" });
284
+ const response = await fetch(request);
285
+ \`\`\`
286
+ `,
287
+ },
288
+ 'Request.url': {
289
+ en: `The address the request goes to.`,
290
+ ru: `Адрес, на который идёт запрос.`,
291
+ },
292
+ 'Request.method': {
293
+ en: `The request's method, e.g. \`"GET"\`.`,
294
+ ru: `Метод запроса, например \`"GET"\`.`,
295
+ },
296
+ 'Request.headers': {
297
+ en: `The request's headers.`,
298
+ ru: `Заголовки запроса.`,
299
+ },
300
+ 'Request.redirect': {
301
+ en: `The request's answer to a redirect: one of \`"follow"\`, \`"manual"\` or \`"error"\`.`,
302
+ ru: `Поведение запроса при перенаправлении: одно из \`"follow"\`, \`"manual"\` или \`"error"\`.`,
303
+ },
304
+ 'Request.signal': {
305
+ en: `The signal that cancels the request.`,
306
+ ru: `Сигнал, который отменяет запрос.`,
307
+ },
308
+ 'Request.clone': {
309
+ en: `A copy of the request, to send again.`,
310
+ ru: `Копия запроса, чтобы отправить его ещё раз.`,
311
+ },
312
+ 'ResponseInit': {
313
+ en: `A response's options: \`new Response\`'s second argument.`,
314
+ ru: `Настройки ответа: второй аргумент \`new Response\`.`,
315
+ },
316
+ 'ResponseInit.status': {
317
+ en: `The response's status; \`200\` by default.`,
318
+ ru: `Статус ответа; по умолчанию \`200\`.`,
319
+ },
320
+ 'ResponseInit.statusText': {
321
+ en: `The words after the status, e.g. \`"Not Found"\`; \`""\` by default.`,
322
+ ru: `Слова после статуса, например \`"Not Found"\`; по умолчанию \`""\`.`,
323
+ },
324
+ 'ResponseInit.headers': {
325
+ en: `The response's headers, as an object of names and values.`,
326
+ ru: `Заголовки ответа, объектом имён и значений.`,
327
+ },
328
+ 'Response': {
329
+ en: `
330
+ The server's answer to a request: its status, headers and body.
331
+
332
+ \`\`\`ts
333
+ const response = await fetch("https://example.com/api/stats");
334
+ if (!response.ok) return console.log(\`HTTP \${response.status}\`);
335
+ const stats = await response.json<Stats>();
336
+ \`\`\`
337
+ `,
338
+ ru: `
339
+ Ответ сервера на запрос: статус, заголовки и тело.
340
+
341
+ \`\`\`ts
342
+ const response = await fetch("https://example.com/api/stats");
343
+ if (!response.ok) return console.log(\`HTTP \${response.status}\`);
344
+ const stats = await response.json<Stats>();
345
+ \`\`\`
346
+ `,
347
+ },
348
+ 'Response.status': {
349
+ en: `The response's HTTP status, e.g. \`200\` or \`404\`.`,
350
+ ru: `HTTP-статус ответа, например \`200\` или \`404\`.`,
351
+ },
352
+ 'Response.statusText': {
353
+ en: `The words after the status, e.g. \`"Not Found"\`; \`""\` when the server sent none.`,
354
+ ru: `Слова после статуса, например \`"Not Found"\`; \`""\`, если сервер их не прислал.`,
355
+ },
356
+ 'Response.ok': {
357
+ en: `\`true\` for a status from \`200\` to \`299\`.`,
358
+ ru: `\`true\` при статусе от \`200\` до \`299\`.`,
359
+ },
360
+ 'Response.headers': {
361
+ en: `The response's headers.`,
362
+ ru: `Заголовки ответа.`,
363
+ },
364
+ 'Response.url': {
365
+ en: `The address the response came from, after any redirects.`,
366
+ ru: `Адрес, с которого пришёл ответ, после всех перенаправлений.`,
367
+ },
368
+ 'Response.redirected': {
369
+ en: `\`true\` when the request was redirected on the way.`,
370
+ ru: `\`true\`, если запрос по пути перенаправили.`,
371
+ },
372
+ 'Response.bodyUsed': {
373
+ en: `\`true\` once the body has been read: it can be read once.`,
374
+ ru: `\`true\`, когда тело уже прочитано: прочитать его можно один раз.`,
375
+ },
376
+ 'Response.text': {
377
+ en: `The body as text, decoded as UTF-8.`,
378
+ ru: `Тело текстом, в UTF-8.`,
379
+ },
380
+ 'Response.json': {
381
+ en: `
382
+ The body read as JSON into \`T\`, an interface of the fields the JSON
383
+ has; rejects with a SyntaxError when it is not JSON.
384
+
385
+ \`\`\`ts
386
+ interface Stats {
387
+ kills: number;
388
+ }
389
+ const stats = await response.json<Stats>();
390
+ \`\`\`
391
+ `,
392
+ ru: `
393
+ Тело, прочитанное как JSON в \`T\` — интерфейс с полями этого JSON;
394
+ отклоняется с SyntaxError, если это не JSON.
395
+
396
+ \`\`\`ts
397
+ interface Stats {
398
+ kills: number;
399
+ }
400
+ const stats = await response.json<Stats>();
401
+ \`\`\`
402
+ `,
403
+ },
404
+ 'Response.arrayBuffer': {
405
+ en: `The body as bytes.`,
406
+ ru: `Тело байтами.`,
407
+ },
408
+ 'Response.clone': {
409
+ en: `A copy of the response, whose body can be read apart from this one's.`,
410
+ ru: `Копия ответа, тело которой читается отдельно от этого.`,
411
+ },
412
+ 'fetch': {
413
+ en: `
414
+ Sends a request and gives its response, as the browser's \`fetch\` does.
415
+
416
+ \`\`\`ts
417
+ const response = await fetch("https://example.com/api/stats");
418
+ const stats = await response.json<Stats>();
419
+ \`\`\`
420
+
421
+ The promise is fulfilled once the response's headers and body have come,
422
+ on a later server frame: the game does not wait for it. A status such as
423
+ \`404\` is a response too - check \`response.ok\`. The promise rejects with a
424
+ TypeError when there is no response (no connection, a bad address) and
425
+ with the signal's reason when \`init.signal\` aborts. In an async command
426
+ handler or a player's event, the player leaving aborts it too.
427
+ `,
428
+ ru: `
429
+ Отправляет запрос и даёт ответ, как \`fetch\` в браузере.
430
+
431
+ \`\`\`ts
432
+ const response = await fetch("https://example.com/api/stats");
433
+ const stats = await response.json<Stats>();
434
+ \`\`\`
435
+
436
+ Промис выполняется, когда пришли заголовки и тело ответа, в одном из
437
+ следующих кадров сервера: игра его не ждёт. Статус вроде \`404\` — тоже
438
+ ответ, проверяйте \`response.ok\`. Промис отклоняется с TypeError, если
439
+ ответа нет (нет соединения, плохой адрес), и с причиной сигнала, если
440
+ сработал \`init.signal\`. В async-обработчике команды или события игрока
441
+ запрос отменяется и тогда, когда игрок выходит.
442
+ `,
443
+ },
444
+ 'fetch#2': {
445
+ en: `Sends a request to a URL made with \`new URL\`.`,
446
+ ru: `Отправляет запрос по адресу, сделанному через \`new URL\`.`,
447
+ },
448
+ 'fetch#3': {
449
+ en: `Sends a request made with \`new Request\`; what \`init\` gives takes the place of the request's own.`,
450
+ ru: `Отправляет запрос, сделанный через \`new Request\`; то, что задаёт \`init\`, заменяет его собственное.`,
451
+ },
452
+ 'UseFetchOptions': {
453
+ en: `\`useFetch\`'s options. Every field is optional.`,
454
+ ru: `Настройки \`useFetch\`. Все поля необязательны.`,
455
+ },
456
+ 'UseFetchOptions.method': {
457
+ en: `The request's method, e.g. \`"POST"\`; \`"GET"\` by default.`,
458
+ ru: `Метод запроса, например \`"POST"\`; по умолчанию \`"GET"\`.`,
459
+ },
460
+ 'UseFetchOptions.query': {
461
+ en: `Names and values added to the URL's query: \`{ page: "2" }\` adds \`?page=2\`.`,
462
+ ru: `Имена и значения, которые добавляются в запрос адреса: \`{ page: "2" }\` добавляет \`?page=2\`.`,
463
+ },
464
+ 'UseFetchOptions.headers': {
465
+ en: `The request's headers, as an object of names and values.`,
466
+ ru: `Заголовки запроса, объектом имён и значений.`,
467
+ },
468
+ 'UseFetchOptions.body': {
469
+ en: `
470
+ The request's body: text as it is, or an object of the type given second
471
+ (\`useFetch<Answer, Report>\`) as JSON.
472
+ `,
473
+ ru: `
474
+ Тело запроса: текст как есть или объект типа, данного вторым
475
+ (\`useFetch<Answer, Report>\`), — в виде JSON.
476
+ `,
477
+ },
478
+ 'UseFetchOptions.retry': {
479
+ en: `The number of further tries when a request fails on the way or the server answers \`5xx\`, \`408\` or \`429\`; \`0\` by default.`,
480
+ ru: `Число повторных попыток, если запрос сорвался по пути или сервер ответил \`5xx\`, \`408\` или \`429\`; по умолчанию \`0\`.`,
481
+ },
482
+ 'UseFetchOptions.retryDelay': {
483
+ en: `Milliseconds between two tries; \`500\` by default.`,
484
+ ru: `Миллисекунды между попытками; по умолчанию \`500\`.`,
485
+ },
486
+ 'UseFetchOptions.timeout': {
487
+ en: `Milliseconds a try may take before it is given up with a TimeoutError; no limit by default.`,
488
+ ru: `Миллисекунды на одну попытку, после которых её бросают с TimeoutError; по умолчанию без предела.`,
489
+ },
490
+ 'UseFetchOptions.signal': {
491
+ en: `A signal that cancels the request.`,
492
+ ru: `Сигнал, который отменяет запрос.`,
493
+ },
494
+ 'UseFetchOptions.proxy': {
495
+ en: `A proxy the request goes through, e.g. \`"http://proxy.example.com:3128"\`.`,
496
+ ru: `Прокси, через который идёт запрос, например \`"http://proxy.example.com:3128"\`.`,
497
+ },
498
+ 'UseFetchOptions.tls': {
499
+ en: `The check of the server's certificate, for HTTPS.`,
500
+ ru: `Проверка сертификата сервера при HTTPS.`,
501
+ },
502
+ 'FetchResult': {
503
+ en: `The answer of \`useFetch\`: the data or the error, and the status.`,
504
+ ru: `Результат \`useFetch\`: данные или ошибка, и статус.`,
505
+ },
506
+ 'FetchResult.data': {
507
+ en: `The response's JSON read into \`T\`; \`null\` when there was an error or no body.`,
508
+ ru: `JSON ответа, прочитанный в \`T\`; \`null\`, если была ошибка или тела нет.`,
509
+ },
510
+ 'FetchResult.error': {
511
+ en: `Why there is no data: a FetchError for a status that is not \`2xx\`, a TypeError for no response, the signal's reason for an abort, a SyntaxError for a body that is not JSON.`,
512
+ ru: `Почему данных нет: FetchError для статуса не из \`2xx\`, TypeError, если ответа нет, причина сигнала при отмене, SyntaxError для тела, которое не JSON.`,
513
+ },
514
+ 'FetchResult.status': {
515
+ en: `The response's HTTP status; \`0\` when there was no response.`,
516
+ ru: `HTTP-статус ответа; \`0\`, если ответа не было.`,
517
+ },
518
+ 'FetchError': {
519
+ en: `A response whose status is not \`2xx\`, as \`useFetch\` reports it.`,
520
+ ru: `Ответ со статусом не из \`2xx\`, как о нём сообщает \`useFetch\`.`,
521
+ },
522
+ 'FetchError.status': {
523
+ en: `The response's HTTP status, e.g. \`404\`.`,
524
+ ru: `HTTP-статус ответа, например \`404\`.`,
525
+ },
526
+ 'FetchError.statusText': {
527
+ en: `The words after the status, e.g. \`"Not Found"\`.`,
528
+ ru: `Слова после статуса, например \`"Not Found"\`.`,
529
+ },
530
+ 'FetchError.body': {
531
+ en: `The response's body as text: often what the server says went wrong.`,
532
+ ru: `Тело ответа текстом: часто там сервер пишет, что не так.`,
533
+ },
534
+ 'useFetch': {
535
+ en: `
536
+ Sends a request and reads its JSON into \`T\`, an interface of the fields
537
+ the JSON has. It never throws: what went wrong is \`error\`.
538
+
539
+ \`\`\`ts
540
+ interface Weather {
541
+ temperature: number;
542
+ }
543
+
544
+ const { data, error } = await useFetch<Weather>("https://example.com/weather", { query: { city: "Paris" } });
545
+ if (error) return console.error(error.message);
546
+ print(player, \`\${data!.temperature} °C\`);
547
+ \`\`\`
548
+
549
+ A body that is an object goes as JSON: \`useFetch<Answer, Report>(url, { method: "POST", body: report })\`.
550
+ `,
551
+ ru: `
552
+ Отправляет запрос и читает его JSON в \`T\` — интерфейс с полями этого
553
+ JSON. Никогда не бросает исключение: что пошло не так — в \`error\`.
554
+
555
+ \`\`\`ts
556
+ interface Weather {
557
+ temperature: number;
558
+ }
559
+
560
+ const { data, error } = await useFetch<Weather>("https://example.com/weather", { query: { city: "Paris" } });
561
+ if (error) return console.error(error.message);
562
+ print(player, \`\${data!.temperature} °C\`);
563
+ \`\`\`
564
+
565
+ Тело-объект уходит как JSON: \`useFetch<Answer, Report>(url, { method: "POST", body: report })\`.
566
+ `,
567
+ },
568
+ 'RequestErrorKind': {
569
+ en: `
570
+ Why a request ended without its answer, as \`request\` says it: \`""\` - it
571
+ got one (an HTTP status such as \`404\` is an answer); \`"login"\` - the user,
572
+ password or key was refused; \`"denied"\` - the account may not do it (FTP
573
+ cannot enter a folder, SFTP says permission denied); \`"notFound"\` - no
574
+ such remote file; \`"refused"\` - no connection: the host is unknown or
575
+ refuses it; \`"timeout"\` - \`timeout\` ran out; \`"tls"\` - the secure
576
+ connection failed: a certificate, or an SSH host key, not trusted;
577
+ \`"aborted"\` - the signal aborted it; \`"other"\` - anything else, said in
578
+ \`errorText\`.
579
+ `,
580
+ ru: `
581
+ Почему запрос закончился без ответа, как это говорит \`request\`: \`""\` —
582
+ ответ есть (HTTP-статус вроде \`404\` — тоже ответ); \`"login"\` —
583
+ пользователь, пароль или ключ не приняты; \`"denied"\` — учётной записи это
584
+ нельзя (FTP не может войти в папку, SFTP отвечает «нет прав»);
585
+ \`"notFound"\` — такого файла на сервере нет; \`"refused"\` — нет соединения:
586
+ хост неизвестен или отказывает; \`"timeout"\` — вышло время \`timeout\`;
587
+ \`"tls"\` — не удалось защищённое соединение: сертификату или ключу хоста
588
+ SSH нет доверия; \`"aborted"\` — запрос прервал сигнал; \`"other"\` — всё
589
+ остальное, словами в \`errorText\`.
590
+ `,
591
+ },
592
+ 'RequestOptions': {
593
+ en: `
594
+ \`request\`'s options: what to send and how. Every field is optional; the
595
+ URL's scheme - \`http:\`, \`https:\`, \`ftp:\`, \`ftps:\` or \`sftp:\` - says which
596
+ of them apply.
597
+ `,
598
+ ru: `
599
+ Параметры \`request\`: что отправить и как. Все поля необязательны; схема
600
+ адреса — \`http:\`, \`https:\`, \`ftp:\`, \`ftps:\` или \`sftp:\` — решает, какие
601
+ из них действуют.
602
+ `,
603
+ },
604
+ 'RequestOptions.method': {
605
+ en: `HTTP's method, e.g. \`"POST"\`; \`"GET"\` by default. \`"HEAD"\` transfers nothing - with \`quote\`, only the commands run.`,
606
+ ru: `Метод HTTP, например \`"POST"\`; по умолчанию \`"GET"\`. \`"HEAD"\` ничего не передаёт — с \`quote\` выполняются только команды.`,
607
+ },
608
+ 'RequestOptions.headers': {
609
+ en: `HTTP's headers, as an object of names and values.`,
610
+ ru: `Заголовки HTTP — объект имён и значений.`,
611
+ },
612
+ 'RequestOptions.body': {
613
+ en: `The text sent: HTTP's body, or - with \`upload\` - the file's content.`,
614
+ ru: `Отправляемый текст: тело HTTP или — с \`upload\` — содержимое файла.`,
615
+ },
616
+ 'RequestOptions.user': {
617
+ en: `The user to log in as; the URL's own (\`ftp://user@host\`) when left out.`,
618
+ ru: `Пользователь для входа; если не задан — тот, что в адресе (\`ftp://user@host\`).`,
619
+ },
620
+ 'RequestOptions.password': {
621
+ en: `The password to log in with.`,
622
+ ru: `Пароль для входа.`,
623
+ },
624
+ 'RequestOptions.keyFile': {
625
+ en: `
626
+ SFTP: the private key to log in with, a file of the game folder
627
+ (\`addons/amxmodx/data/id_rsa\`) - an RSA key in PEM
628
+ (\`ssh-keygen -t rsa -m PEM\`).
629
+ `,
630
+ ru: `
631
+ SFTP: закрытый ключ для входа, файл игровой папки
632
+ (\`addons/amxmodx/data/id_rsa\`) — ключ RSA в PEM
633
+ (\`ssh-keygen -t rsa -m PEM\`).
634
+ `,
635
+ },
636
+ 'RequestOptions.keyPassphrase': {
637
+ en: `SFTP: the passphrase \`keyFile\` is encrypted with.`,
638
+ ru: `SFTP: пароль, которым зашифрован \`keyFile\`.`,
639
+ },
640
+ 'RequestOptions.hostKey': {
641
+ en: `
642
+ SFTP: the server's host key, its SHA-256 fingerprint in base64 as
643
+ \`ssh-keygen -lf\` prints it without \`SHA256:\` - a server with another key
644
+ is refused (\`"tls"\`). Left out, any host key is taken.
645
+ `,
646
+ ru: `
647
+ SFTP: ключ хоста сервера — его отпечаток SHA-256 в base64, как его печатает
648
+ \`ssh-keygen -lf\`, без \`SHA256:\`; сервер с другим ключом отвергается
649
+ (\`"tls"\`). Если не задан, принимается любой ключ хоста.
650
+ `,
651
+ },
652
+ 'RequestOptions.ssl': {
653
+ en: `
654
+ FTP: TLS asked for with \`AUTH TLS\` on a plain \`ftp:\` connection - one of
655
+ \`"try"\` (when the server has it), \`"control"\` (the commands at least)
656
+ or \`"all"\` (the commands and the files, or fail). \`ftps:\` is TLS from
657
+ the first byte without it.
658
+ `,
659
+ ru: `
660
+ FTP: TLS, запрошенный через \`AUTH TLS\` на обычном соединении \`ftp:\`, —
661
+ \`"try"\` (если сервер умеет), \`"control"\` (хотя бы команды) или
662
+ \`"all"\` (команды и файлы, иначе ошибка). \`ftps:\` — TLS с первого байта
663
+ и без этого параметра.
664
+ `,
665
+ },
666
+ 'RequestOptions.upload': {
667
+ en: `Sends \`body\` - or \`file\` - to the URL's path, in place of reading it: an FTP or SFTP upload, an HTTP PUT.`,
668
+ ru: `Отправляет \`body\` — или \`file\` — по пути адреса вместо чтения: загрузка на FTP или SFTP, HTTP PUT.`,
669
+ },
670
+ 'RequestOptions.list': {
671
+ en: `FTP and SFTP: the names in the URL's folder, one a line, in place of a listing with sizes and dates.`,
672
+ ru: `FTP и SFTP: имена в папке адреса, по одному в строке, вместо списка с размерами и датами.`,
673
+ },
674
+ 'RequestOptions.quote': {
675
+ en: `FTP or SFTP commands run before the transfer, in order: \`["DELE old.txt"]\`, \`["rename a.txt b.txt"]\`.`,
676
+ ru: `Команды FTP или SFTP, выполняемые по порядку до передачи: \`["DELE old.txt"]\`, \`["rename a.txt b.txt"]\`.`,
677
+ },
678
+ 'RequestOptions.createDirs': {
679
+ en: `FTP and SFTP: an upload makes the folders of its path that are not there.`,
680
+ ru: `FTP и SFTP: загрузка создаёт недостающие папки своего пути.`,
681
+ },
682
+ 'RequestOptions.timeout': {
683
+ en: `Milliseconds the whole request may take; past them it ends as \`"timeout"\`. No limit by default.`,
684
+ ru: `Время в миллисекундах, которое может идти весь запрос; дольше — он заканчивается как \`"timeout"\`. По умолчанию без ограничения.`,
685
+ },
686
+ 'RequestOptions.signal': {
687
+ en: `A signal that aborts the request: it then ends at once as \`"aborted"\`.`,
688
+ ru: `Сигнал, прерывающий запрос: тогда он сразу заканчивается как \`"aborted"\`.`,
689
+ },
690
+ 'RequestOptions.file': {
691
+ en: `
692
+ A file of the game folder (\`maps/de_dust2.bsp\`) the answer is written
693
+ into - or, with \`upload\`, the upload is read from - in place of \`body\`.
694
+ The bytes go between the network and the disk without passing through
695
+ the plugin. A download that fails leaves an older file of that name as
696
+ it was. A path outside the game folder (absolute, or with \`..\`) is
697
+ refused.
698
+ `,
699
+ ru: `
700
+ Файл игровой папки (\`maps/de_dust2.bsp\`), в который пишется ответ, —
701
+ или, с \`upload\`, из которого читается загрузка, — вместо \`body\`.
702
+ Байты идут между сетью и диском, не проходя через плагин. Неудачная
703
+ закачка оставляет прежний файл с этим именем как был. Путь вне игровой
704
+ папки (абсолютный или с \`..\`) отвергается.
705
+ `,
706
+ },
707
+ 'RequestOptions.follow': {
708
+ en: `HTTP: whether a redirect is followed; \`true\` by default.`,
709
+ ru: `HTTP: идти ли по перенаправлению; по умолчанию \`true\`.`,
710
+ },
711
+ 'RequestOptions.proxy': {
712
+ en: `A proxy the request goes through, e.g. \`"http://proxy.example.com:3128"\`.`,
713
+ ru: `Прокси, через который идёт запрос, например \`"http://proxy.example.com:3128"\`.`,
714
+ },
715
+ 'RequestOptions.ca': {
716
+ en: `The certificate authorities a server's certificate must come from, as PEM text; the ones a browser trusts by default.`,
717
+ ru: `Удостоверяющие центры, от которых должен быть сертификат сервера, текстом PEM; по умолчанию — те, которым доверяет браузер.`,
718
+ },
719
+ 'RequestResult': {
720
+ en: `The end of a request: its answer, or why there is none.`,
721
+ ru: `Итог запроса: его ответ или почему ответа нет.`,
722
+ },
723
+ 'RequestResult.status': {
724
+ en: `HTTP's status, or FTP's last reply once the transfer is done (\`226\`); \`0\` for SFTP; \`-1\` when the request failed.`,
725
+ ru: `Статус HTTP или последний ответ FTP после передачи (\`226\`); \`0\` для SFTP; \`-1\`, если запрос не удался.`,
726
+ },
727
+ 'RequestResult.errorKind': {
728
+ en: `Why there is no answer, or \`""\`.`,
729
+ ru: `Почему нет ответа, или \`""\`.`,
730
+ },
731
+ 'RequestResult.errorText': {
732
+ en: `The failure, in words; \`""\` when there was none.`,
733
+ ru: `Неудача словами; \`""\`, если её не было.`,
734
+ },
735
+ 'RequestResult.replyCode': {
736
+ en: `The protocol's last reply code, a failed request's too: HTTP's status, FTP's reply (\`530\`, \`550\`), SFTP's status (\`2\` no such file); \`0\` when there was none.`,
737
+ ru: `Последний код ответа протокола, и у неудавшегося запроса: статус HTTP, ответ FTP (\`530\`, \`550\`), статус SFTP (\`2\` — нет такого файла); \`0\`, если его не было.`,
738
+ },
739
+ 'RequestResult.statusText': {
740
+ en: `The words after HTTP's status, e.g. \`"Not Found"\`.`,
741
+ ru: `Слова после статуса HTTP, например \`"Not Found"\`.`,
742
+ },
743
+ 'RequestResult.headers': {
744
+ en: `HTTP's response headers.`,
745
+ ru: `Заголовки ответа HTTP.`,
746
+ },
747
+ 'RequestResult.body': {
748
+ en: `The answer's bytes - a download, a listing; empty when it went into \`file\`.`,
749
+ ru: `Байты ответа — скачанное, список; пусто, если ответ ушёл в \`file\`.`,
750
+ },
751
+ 'RequestResult.url': {
752
+ en: `The address the answer came from, after any redirects.`,
753
+ ru: `Адрес, откуда пришёл ответ, после всех перенаправлений.`,
754
+ },
755
+ 'RequestResult.redirected': {
756
+ en: `\`true\` when an HTTP redirect was followed on the way.`,
757
+ ru: `\`true\`, если по пути было перенаправление HTTP.`,
758
+ },
759
+ 'RequestResult.text': {
760
+ en: `The answer as text, decoded as UTF-8.`,
761
+ ru: `Ответ текстом, декодированный как UTF-8.`,
762
+ },
763
+ 'request': {
764
+ en: `
765
+ Sends a request to \`url\` - HTTP, HTTPS, FTP, FTPS or SFTP - with the
766
+ server's network client, and gives what it ended with. It never rejects:
767
+ a failure is \`errorKind\` and \`errorText\`.
768
+
769
+ \`\`\`ts
770
+ import { request } from "@amxts/core/kit";
771
+
772
+ const result = await request("sftp://example.com/maps/de_dust2.bsp", {
773
+ user: "admin",
774
+ keyFile: "addons/amxmodx/data/id_rsa",
775
+ upload: true,
776
+ file: "maps/de_dust2.bsp",
777
+ });
778
+ if (result.errorKind != "") console.error(\`\${result.errorKind}: \${result.errorText}\`);
779
+ \`\`\`
780
+
781
+ The promise settles on a later server frame: the game does not wait. In an
782
+ async command handler or a player's event, the player leaving aborts it.
783
+ `,
784
+ ru: `
785
+ Отправляет запрос по \`url\` — HTTP, HTTPS, FTP, FTPS или SFTP — сетевым
786
+ клиентом сервера и даёт то, чем он закончился. Никогда не отклоняется:
787
+ неудача — это \`errorKind\` и \`errorText\`.
788
+
789
+ \`\`\`ts
790
+ import { request } from "@amxts/core/kit";
791
+
792
+ const result = await request("sftp://example.com/maps/de_dust2.bsp", {
793
+ user: "admin",
794
+ keyFile: "addons/amxmodx/data/id_rsa",
795
+ upload: true,
796
+ file: "maps/de_dust2.bsp",
797
+ });
798
+ if (result.errorKind != "") console.error(\`\${result.errorKind}: \${result.errorText}\`);
799
+ \`\`\`
800
+
801
+ Промис выполняется в одном из следующих кадров сервера: игра не ждёт. В
802
+ async-обработчике команды или события игрока уход игрока прерывает запрос.
803
+ `,
804
+ },
805
+ };