f02124eb1d
Раздел документации на сайте (documents_ru/documents_en в PocketBase) содержал только два обрубленных стаб-документа. Добавлен полный набор из 12 документов на русском и английском (Core/Security/Network/Legal), технически сверенных с реальной реализацией протокола (NRXP, ChaCha20- Poly1305, X25519, TLS-маскировка под JA3/JA4) и с моделью сессий (HttpOnly-cookie, ротация refresh-токенов) — не маркетинговые обещания, а описание того, что фактически работает в коде. Юридические документы (Privacy/Terms/Refund) содержат явные плейсхолдеры для реквизитов оператора сервиса — сервис ещё не зарегистрирован ни в одной юрисдикции, поэтому не полагаться на них как на итоговый текст без замены плейсхолдеров. scripts/seed-docs.mjs — идемпотентный скрипт наполнения PocketBase (upsert по title, с alias-картой под старые названия стабов); ничего не записывает без --apply и без PB_ADMIN_EMAIL/PB_ADMIN_PASSWORD в окружении — админ-доступ к CMS нигде не хардкожен. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
98 lines
3.9 KiB
JavaScript
98 lines
3.9 KiB
JavaScript
// Наполняет коллекции `documents_ru`/`documents_en` в PocketBase реальным
|
|
// контентом раздела /docs (сейчас там только два "заглушечных" документа с
|
|
// обрубленным текстом — этот скрипт заменяет их полным набором и добавляет
|
|
// остальные документы).
|
|
//
|
|
// Не хранит и не запрашивает секреты нигде, кроме переменных окружения самого
|
|
// оператора — админ-доступ к PocketBase не должен попадать ни в код, ни в чат.
|
|
//
|
|
// Запуск:
|
|
// PB_URL=https://netrunner-vpn.com/cms-api \
|
|
// PB_ADMIN_EMAIL=you@example.com \
|
|
// PB_ADMIN_PASSWORD='...' \
|
|
// node scripts/seed-docs.mjs [--lang=ru|en|all] [--apply]
|
|
//
|
|
// По умолчанию — dry-run для обоих языков (только печатает, что будет
|
|
// сделано). Чтобы реально записать в PocketBase, добавь флаг --apply.
|
|
|
|
import PocketBase from "pocketbase";
|
|
import { DOCS_RU } from "./docs-content.ru.mjs";
|
|
import { DOCS_EN } from "./docs-content.en.mjs";
|
|
|
|
const PB_URL = process.env.PB_URL || "https://netrunner-vpn.com/cms-api";
|
|
const APPLY = process.argv.includes("--apply");
|
|
const langArg = process.argv.find((a) => a.startsWith("--lang="));
|
|
const LANGS = langArg
|
|
? langArg.split("=")[1] === "all"
|
|
? ["ru", "en"]
|
|
: [langArg.split("=")[1]]
|
|
: ["ru", "en"];
|
|
|
|
// Старые "заглушечные" записи в проде названы иначе, чем новые полноценные
|
|
// документы, которые их заменяют, — без этой карты скрипт создал бы дубликаты
|
|
// вместо замены обрубленных стаб-текстов.
|
|
const LEGACY_TITLE_ALIASES = {
|
|
ru: {
|
|
"Политика конфиденциальности": "Политика конфиденциальности (Privacy Policy)",
|
|
"Условия использования": "Условия использования и оплаты (Terms of Use)",
|
|
},
|
|
en: {
|
|
"Privacy Policy": "Privacy Policy",
|
|
"Terms of Use": "Terms of Use & Payment",
|
|
},
|
|
};
|
|
|
|
const DOCS_BY_LANG = { ru: DOCS_RU, en: DOCS_EN };
|
|
|
|
async function seedLang(pb, lang) {
|
|
const docs = DOCS_BY_LANG[lang];
|
|
const aliases = LEGACY_TITLE_ALIASES[lang];
|
|
const collection = pb.collection(`documents_${lang}`);
|
|
const existing = await collection.getFullList({ requestKey: null });
|
|
const byTitle = new Map(existing.map((r) => [r.title, r]));
|
|
|
|
console.log(`\n=== documents_${lang} ===`);
|
|
for (const doc of docs) {
|
|
const match = byTitle.get(doc.title) || byTitle.get(aliases[doc.title]);
|
|
if (match) {
|
|
console.log(`UPDATE "${doc.title}" (id=${match.id})`);
|
|
if (APPLY) await collection.update(match.id, doc);
|
|
} else {
|
|
console.log(`CREATE "${doc.title}"`);
|
|
if (APPLY) await collection.create(doc);
|
|
}
|
|
}
|
|
console.log(`Всего документов: ${docs.length}`);
|
|
}
|
|
|
|
async function main() {
|
|
const pb = new PocketBase(PB_URL);
|
|
|
|
if (APPLY) {
|
|
const email = process.env.PB_ADMIN_EMAIL;
|
|
const password = process.env.PB_ADMIN_PASSWORD;
|
|
if (!email || !password) {
|
|
console.error(
|
|
"Нужны PB_ADMIN_EMAIL и PB_ADMIN_PASSWORD в окружении для записи (--apply).",
|
|
);
|
|
process.exit(1);
|
|
}
|
|
await pb.collection("_superusers").authWithPassword(email, password);
|
|
} else {
|
|
console.log(
|
|
"[dry-run] Ничего не записываю. Проверь вывод ниже, затем перезапусти с --apply.",
|
|
);
|
|
}
|
|
|
|
for (const lang of LANGS) {
|
|
await seedLang(pb, lang);
|
|
}
|
|
|
|
if (!APPLY) console.log("\nЭто был dry-run — добавь --apply, чтобы записать.");
|
|
}
|
|
|
|
main().catch((err) => {
|
|
console.error(err);
|
|
process.exit(1);
|
|
});
|