Данные

Файлы

@amxts/core/fs читает и пишет файлы так же, как fs в Node:

import * as 
fs
from "@amxts/core/fs";
const
rulesFile
= `${
server
.
configsDir
}/myplugin/rules.txt`;
server
.
addCommand
("/rules", ({
player
}) => showRules(
player
));
function showRules(
player
: Player) {
const
text
=
fs
.
readFileSync
(
rulesFile
);
if (
text
== null) return; // файла нет
for (const
line
of
text
.
split
("\n"))
console
.
log
(
line
);
fs
.
appendFileSync
(`${
server
.
dataDir
}/myplugin-rules.log`, `${
player
.
name
} прочитал правила\n`);
}

У каждой функции есть синхронная форма и форма с промисом, для await:

СинхроннаяС промисомЧто делает
readFileSync(path) → string | nullreadFile(path) → Promise<string>читает весь файл как текст
writeFileSync(path, text) → booleanwriteFile(path, text) → Promise<void>записывает файл, заменяя то, что там было
appendFileSync(path, text) → booleanappendFile(path, text) → Promise<void>дописывает в конец, при необходимости создаёт файл
existsSync(path) → booleanexists(path) → Promise<boolean>есть ли такой файл или папка
readdirSync(path) → string[] | nullreaddir(path) → Promise<string[]>имена в папке, без . и ..
mkdirSync(path, options?) → booleanmkdir(path, options?) → Promise<void>создаёт папку; { recursive: true } создаёт и недостающие папки выше
import * as 
fs
from "@amxts/core/fs";
async function saveMap() { await
fs
.
mkdir
(`${
server
.
dataDir
}/myplugin`, {
recursive
: true });
await
fs
.
writeFile
(`${
server
.
dataDir
}/myplugin/last-map.txt`,
server
.
map
);
}
fs
.
readFile
("missing.txt").
catch
((
error
) =>
console
.
log
(
error
.message));
// ENOENT: no such file or directory, open 'missing.txt'

Пути

Путь задаётся относительно папки игры, cstrike/, как у любого плагина AMX Mod X. server.configsDir — папка конфигов (addons/amxmodx/configs), server.dataDir — папка данных (addons/amxmodx/data), где бы сервер их ни держал. Храните файлы плагина в своей папке или под своим именем: configs/myplugin/, data/myplugin-stats.txt.

Текст

Файлы читаются и пишутся как текст в UTF-8. Файл читается целиком, какого бы размера он ни был. Метка порядка байтов (BOM) в начале файла сохраняется, как в Node.

JSON

JSON читает и пишет текст JSON, как в JavaScript. JSON.parse говорят, что он читает, — JSON.parse<Stats>(text) или тип, куда уходит значение, — и он строит этот объект вместе с его массивами, Record и полями:

import * as 
fs
from "@amxts/core/fs";
interface Stats {
kills
: number;
deaths
: number;
lastMap
?: string;
} const
statsFile
= `${
server
.
dataDir
}/myplugin/stats.json`;
function loadStats(): Stats { const
text
=
fs
.
readFileSync
(
statsFile
);
if (
text
== null) return {
kills
: 0,
deaths
: 0 };
return
JSON
.
parse
(
text
);
} function saveStats(
stats
: Stats) {
fs
.
writeFileSync
(
statsFile
,
JSON
.
stringify
(
stats
, null, 2));
}

Текст, который не JSON, — это SyntaxError; значение не того рода, что говорит тип, — текст там, где число, поле, которое должно быть и которого нет, — это TypeError с именем поля. Ловите их через try/catch. JSON.stringify пропускает поле, которое undefined, пишет Date как её текст ISO, а объект с toJSON() — как то, что он отдаёт.

Настройки, которые правит владелец сервера, типизированный конфиг config-core читает одинаково из YAML, JSON и INI.

Когда не получилось

Синхронная функция сообщает об ошибке результатом: null у readFileSync и readdirSync, false у writeFileSync, appendFileSync и mkdirSync — например, если нет папки. Функция с промисом отклоняется с Error, чьё сообщение начинается с ENOENT, как в Node (у mkdir — с EEXIST or ENOENT).

В обоих случаях работа делается сразу: к моменту, когда функция с промисом вернулась, промис уже завершён.

Операционная система

import { 
EOL
,
platform
} from "@amxts/core/os";
if (
platform
() == "linux")
console
.
log
("сервер на Linux");
const
lines
= ["first", "second"].
join
(
EOL
); // "\r\n" в Windows, "\n" в Linux

platform() — это "win32" или "linux", а EOL — перевод строки этой системы.

В тесте фейковый сервер держит папку игры в памяти: server.writeFile(path, text) — до того, как плагин читает, server.file(path) — после того, как он записал (Тесты).