Новые изменения в компонеты

This commit is contained in:
Web-serfer 2026-05-04 03:10:06 +05:00
parent d3d3ad92c3
commit 3411dd4931
17 changed files with 99 additions and 58 deletions

View file

@ -139,3 +139,44 @@
- URL документации PocketBase: https://pocketbase.io/docs/ - URL документации PocketBase: https://pocketbase.io/docs/
- URL документации SolidJS: https://docs.solidjs.com/solid-start/getting-started - URL документации SolidJS: https://docs.solidjs.com/solid-start/getting-started
- URL документации astro-icons: https://www.astroicon.dev/getting-started/ - URL документации astro-icons: https://www.astroicon.dev/getting-started/
## Переменные окружения для Production (Coolify)
### PocketBase
```
PB_POCKETBASE_URL=https://avt-back.ru
PB_ADMIN_EMAIL=redibedi2019@gmail.com
PB_ADMIN_PASSWORD=Stalin4444
```
PB_POCKETBASE_URL=https://avt-back.ru
PB_ADMIN_EMAIL=redibedi2019@gmail.com
PB_ADMIN_PASSWORD=Stalin4444
```
### SMTP (Resend)
```
SMTP_HOST=smtp.resend.com
SMTP_PORT=465
SMTP_AUTH_USER=resend
SMTP_AUTH_PASS=re_bAXEq3JU_3ezUi6XvBci7Biz48eAavW4M
FROM_EMAIL=onboarding@resend.onlinemail.me
FROM_NAME=Автоюрист Сургут
```
### Site
```
SITE_URL=https://avtourist-surgut.ru
```
### Флаг production
```
PROD=true
```
### Как добавить в Coolify
1. Откройте Coolify → ваш проект
2. Перейдите App Settings → Environment Variables
3. Добавьте каждую переменную
4. Перезапустите контейнер

View file

@ -1,7 +1,7 @@
import PocketBase from 'pocketbase'; import PocketBase from 'pocketbase';
import type { Post } from '../globalInterfaces'; import type { Post } from '../globalInterfaces';
const PB_URL = import.meta.env.POCKETBASE_URL || 'http://127.0.0.1:8090'; const PB_URL = import.meta.env.PB_POCKETBASE_URL || 'http://127.0.0.1:8090';
export const pb = new PocketBase(PB_URL); export const pb = new PocketBase(PB_URL);

View file

@ -1,6 +1,6 @@
import type { APIRoute } from 'astro'; import type { APIRoute } from 'astro';
const POCKETBASE_URL = import.meta.env.POCKETBASE_URL || 'http://localhost:8090'; const PB_POCKETBASE_URL = import.meta.env.PB_POCKETBASE_URL || 'http://localhost:8090';
const PASSWORD_MIN_LENGTH = 8; const PASSWORD_MIN_LENGTH = 8;
const PASSWORD_MAX_LENGTH = 12; const PASSWORD_MAX_LENGTH = 12;
@ -62,7 +62,7 @@ export const POST: APIRoute = async ({ request }) => {
); );
} }
const confirmUrl = `${POCKETBASE_URL}/api/collections/users/confirm-password-reset`; const confirmUrl = `${PB_POCKETBASE_URL}/api/collections/users/confirm-password-reset`;
const response = await fetch(confirmUrl, { const response = await fetch(confirmUrl, {
method: 'POST', method: 'POST',

View file

@ -1,7 +1,7 @@
import type { APIRoute } from 'astro'; import type { APIRoute } from 'astro';
import { pb } from '../../../lib/pb'; import { pb } from '../../../lib/pb';
const POCKETBASE_URL = import.meta.env.POCKETBASE_URL || 'http://127.0.0.1:8090'; const PB_POCKETBASE_URL = import.meta.env.PB_POCKETBASE_URL || 'http://127.0.0.1:8090';
const ADMIN_EMAIL = import.meta.env.PB_ADMIN_EMAIL || 'redibedi2019@gmail.com'; const ADMIN_EMAIL = import.meta.env.PB_ADMIN_EMAIL || 'redibedi2019@gmail.com';
const ADMIN_PASSWORD = import.meta.env.PB_ADMIN_PASSWORD || 'Stalin4444'; const ADMIN_PASSWORD = import.meta.env.PB_ADMIN_PASSWORD || 'Stalin4444';

View file

@ -1,6 +1,6 @@
import type { APIRoute } from "astro"; import type { APIRoute } from "astro";
const POCKETBASE_URL = import.meta.env.POCKETBASE_URL || "http://localhost:8090"; const PB_POCKETBASE_URL = import.meta.env.PB_POCKETBASE_URL || "http://localhost:8090";
export const GET: APIRoute = async ({ cookies, request }) => { export const GET: APIRoute = async ({ cookies, request }) => {
try { try {
@ -16,7 +16,7 @@ export const GET: APIRoute = async ({ cookies, request }) => {
const token = pbAuthCookie.trim(); const token = pbAuthCookie.trim();
const response = await fetch( const response = await fetch(
`${POCKETBASE_URL}/api/collections/users/auth-refresh`, `${PB_POCKETBASE_URL}/api/collections/users/auth-refresh`,
{ {
method: "POST", method: "POST",
headers: { headers: {

View file

@ -1,6 +1,6 @@
import type { APIRoute } from 'astro'; import type { APIRoute } from 'astro';
const POCKETBASE_URL = import.meta.env.POCKETBASE_URL || 'http://localhost:8090'; const PB_POCKETBASE_URL = import.meta.env.PB_POCKETBASE_URL || 'http://localhost:8090';
const RATE_LIMIT_MAX_REQUESTS = 3; const RATE_LIMIT_MAX_REQUESTS = 3;
const RATE_LIMIT_WINDOW_MS = 60 * 60 * 1000; const RATE_LIMIT_WINDOW_MS = 60 * 60 * 1000;
@ -77,7 +77,7 @@ export const POST: APIRoute = async ({ request }) => {
); );
} }
const resetUrl = `${POCKETBASE_URL}/api/collections/users/request-password-reset`; const resetUrl = `${PB_POCKETBASE_URL}/api/collections/users/request-password-reset`;
const response = await fetch(resetUrl, { const response = await fetch(resetUrl, {
method: 'POST', method: 'POST',

View file

@ -1,6 +1,6 @@
import type { APIRoute } from 'astro'; import type { APIRoute } from 'astro';
const POCKETBASE_URL = import.meta.env.POCKETBASE_URL || 'http://127.0.0.1:8090'; const PB_POCKETBASE_URL = import.meta.env.PB_POCKETBASE_URL || 'http://127.0.0.1:8090';
export const POST: APIRoute = async ({ request }) => { export const POST: APIRoute = async ({ request }) => {
try { try {
@ -35,7 +35,7 @@ export const POST: APIRoute = async ({ request }) => {
}), { status: 400 }); }), { status: 400 });
} }
const response = await fetch(`${POCKETBASE_URL}/api/collections/users/confirm-password-reset`, { const response = await fetch(`${PB_POCKETBASE_URL}/api/collections/users/confirm-password-reset`, {
method: 'POST', method: 'POST',
headers: { 'Content-Type': 'application/json' }, headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ body: JSON.stringify({

View file

@ -1,6 +1,6 @@
import type { APIRoute } from "astro"; import type { APIRoute } from "astro";
const POCKETBASE_URL = import.meta.env.POCKETBASE_URL || "http://localhost:8090"; const PB_POCKETBASE_URL = import.meta.env.PB_POCKETBASE_URL || "http://localhost:8090";
export const PATCH: APIRoute = async ({ params, request, cookies }) => { export const PATCH: APIRoute = async ({ params, request, cookies }) => {
const pbAuthCookie = cookies.get("pb_auth")?.value; const pbAuthCookie = cookies.get("pb_auth")?.value;
@ -16,7 +16,7 @@ export const PATCH: APIRoute = async ({ params, request, cookies }) => {
try { try {
let userId: string | null = null; let userId: string | null = null;
const userResponse = await fetch( const userResponse = await fetch(
`${POCKETBASE_URL}/api/collections/users/auth-refresh`, `${PB_POCKETBASE_URL}/api/collections/users/auth-refresh`,
{ {
method: "POST", method: "POST",
headers: { headers: {
@ -46,7 +46,7 @@ export const PATCH: APIRoute = async ({ params, request, cookies }) => {
} }
const commentResponse = await fetch( const commentResponse = await fetch(
`${POCKETBASE_URL}/api/collections/comments/records/${commentId}`, `${PB_POCKETBASE_URL}/api/collections/comments/records/${commentId}`,
{ {
headers: { Authorization: `Bearer ${token}` }, headers: { Authorization: `Bearer ${token}` },
} }
@ -79,7 +79,7 @@ export const PATCH: APIRoute = async ({ params, request, cookies }) => {
} }
const updateResponse = await fetch( const updateResponse = await fetch(
`${POCKETBASE_URL}/api/collections/comments/records/${commentId}`, `${PB_POCKETBASE_URL}/api/collections/comments/records/${commentId}`,
{ {
method: "PATCH", method: "PATCH",
headers: { headers: {
@ -126,7 +126,7 @@ export const DELETE: APIRoute = async ({ params, cookies }) => {
try { try {
let userId: string | null = null; let userId: string | null = null;
const userResponse = await fetch( const userResponse = await fetch(
`${POCKETBASE_URL}/api/collections/users/auth-refresh`, `${PB_POCKETBASE_URL}/api/collections/users/auth-refresh`,
{ {
method: "POST", method: "POST",
headers: { headers: {
@ -156,7 +156,7 @@ export const DELETE: APIRoute = async ({ params, cookies }) => {
} }
const commentResponse = await fetch( const commentResponse = await fetch(
`${POCKETBASE_URL}/api/collections/comments/records/${commentId}`, `${PB_POCKETBASE_URL}/api/collections/comments/records/${commentId}`,
{ {
headers: { Authorization: `Bearer ${token}` }, headers: { Authorization: `Bearer ${token}` },
} }
@ -179,7 +179,7 @@ export const DELETE: APIRoute = async ({ params, cookies }) => {
} }
const deleteResponse = await fetch( const deleteResponse = await fetch(
`${POCKETBASE_URL}/api/collections/comments/records/${commentId}`, `${PB_POCKETBASE_URL}/api/collections/comments/records/${commentId}`,
{ {
method: "DELETE", method: "DELETE",
headers: { Authorization: `Bearer ${token}` }, headers: { Authorization: `Bearer ${token}` },

View file

@ -1,6 +1,6 @@
import type { APIRoute } from "astro"; import type { APIRoute } from "astro";
const POCKETBASE_URL = import.meta.env.POCKETBASE_URL || "http://localhost:8090"; const PB_POCKETBASE_URL = import.meta.env.PB_POCKETBASE_URL || "http://localhost:8090";
export const GET: APIRoute = async ({ url, cookies }) => { export const GET: APIRoute = async ({ url, cookies }) => {
const postSlug = url.searchParams.get("post_slug"); const postSlug = url.searchParams.get("post_slug");
@ -35,7 +35,7 @@ export const GET: APIRoute = async ({ url, cookies }) => {
try { try {
const response = await fetch( const response = await fetch(
`${POCKETBASE_URL}/api/collections/comments/records?expand=${expand}&filter=${encodeURIComponent(filter)}&sort=${sort}`, `${PB_POCKETBASE_URL}/api/collections/comments/records?expand=${expand}&filter=${encodeURIComponent(filter)}&sort=${sort}`,
{ {
headers: token ? { Authorization: `Bearer ${token}` } : {}, headers: token ? { Authorization: `Bearer ${token}` } : {},
} }
@ -81,7 +81,7 @@ export const POST: APIRoute = async ({ request, cookies }) => {
let userId: string | null = null; let userId: string | null = null;
try { try {
const userResponse = await fetch( const userResponse = await fetch(
`${POCKETBASE_URL}/api/collections/users/auth-refresh`, `${PB_POCKETBASE_URL}/api/collections/users/auth-refresh`,
{ {
method: "POST", method: "POST",
headers: { headers: {
@ -137,7 +137,7 @@ export const POST: APIRoute = async ({ request, cookies }) => {
// Проверка: если это ответ на комментарий // Проверка: если это ответ на комментарий
if (parent) { if (parent) {
const parentCommentResponse = await fetch( const parentCommentResponse = await fetch(
`${POCKETBASE_URL}/api/collections/comments/records/${parent}`, `${PB_POCKETBASE_URL}/api/collections/comments/records/${parent}`,
{ {
headers: { headers: {
Authorization: `Bearer ${token}`, Authorization: `Bearer ${token}`,
@ -172,7 +172,7 @@ export const POST: APIRoute = async ({ request, cookies }) => {
// Проверяем: если родительский комментарий уже имеет ответы — запрещаем (только 1 уровень ответов) // Проверяем: если родительский комментарий уже имеет ответы — запрещаем (только 1 уровень ответов)
const existingRepliesResponse = await fetch( const existingRepliesResponse = await fetch(
`${POCKETBASE_URL}/api/collections/comments/records?filter=parent="${parent}"&perPage=1`, `${PB_POCKETBASE_URL}/api/collections/comments/records?filter=parent="${parent}"&perPage=1`,
{ {
headers: { headers: {
Authorization: `Bearer ${token}`, Authorization: `Bearer ${token}`,
@ -204,7 +204,7 @@ export const POST: APIRoute = async ({ request, cookies }) => {
} }
const response = await fetch( const response = await fetch(
`${POCKETBASE_URL}/api/collections/comments/records`, `${PB_POCKETBASE_URL}/api/collections/comments/records`,
{ {
method: "POST", method: "POST",
headers: { headers: {

View file

@ -1,7 +1,7 @@
import type { APIRoute } from 'astro'; import type { APIRoute } from 'astro';
import nodemailer from 'nodemailer'; import nodemailer from 'nodemailer';
const POCKETBASE_URL = import.meta.env.POCKETBASE_URL; // || 'http://localhost:8090'; const PB_POCKETBASE_URL = import.meta.env.PB_POCKETBASE_URL; // || 'http://localhost:8090';
const SMTP_HOST = import.meta.env.SMTP_HOST; // || 'localhost'; const SMTP_HOST = import.meta.env.SMTP_HOST; // || 'localhost';
const SMTP_PORT = import.meta.env.SMTP_PORT; // || '1025'; const SMTP_PORT = import.meta.env.SMTP_PORT; // || '1025';
const NOTIFY_EMAIL = import.meta.env.NOTIFY_EMAIL; // || 'info@avtourist.ru'; const NOTIFY_EMAIL = import.meta.env.NOTIFY_EMAIL; // || 'info@avtourist.ru';
@ -88,7 +88,7 @@ export const POST: APIRoute = async ({ request }) => {
const cleanPhone = phone.replace(/\D/g, ''); const cleanPhone = phone.replace(/\D/g, '');
const response = await fetch( const response = await fetch(
`${POCKETBASE_URL}/api/collections/consultations/records`, `${PB_POCKETBASE_URL}/api/collections/consultations/records`,
{ {
method: 'POST', method: 'POST',
headers: { headers: {

View file

@ -1,7 +1,7 @@
import type { APIRoute } from 'astro'; import type { APIRoute } from 'astro';
import crypto from 'crypto'; import crypto from 'crypto';
const POCKETBASE_URL = import.meta.env.POCKETBASE_URL || 'http://127.0.0.1:8090'; const PB_POCKETBASE_URL = import.meta.env.PB_POCKETBASE_URL || 'http://127.0.0.1:8090';
const POCKETBASE_ID_REGEX = /^[a-z0-9]{15}$/; const POCKETBASE_ID_REGEX = /^[a-z0-9]{15}$/;
@ -24,7 +24,7 @@ function generateVisitorHash(ip: string, userAgent: string): string {
} }
async function pbRequest(method: string, path: string, body?: object) { async function pbRequest(method: string, path: string, body?: object) {
const url = `${POCKETBASE_URL}${path}`; const url = `${PB_POCKETBASE_URL}${path}`;
const options: RequestInit = { const options: RequestInit = {
method, method,
headers: { 'Content-Type': 'application/json' }, headers: { 'Content-Type': 'application/json' },

View file

@ -3,7 +3,7 @@ import PocketBase from 'pocketbase';
export const GET: APIRoute = async ({ params }) => { export const GET: APIRoute = async ({ params }) => {
try { try {
const pb = new PocketBase(import.meta.env.POCKETBASE_URL); const pb = new PocketBase(import.meta.env.PB_POCKETBASE_URL);
const { slug } = params; const { slug } = params;
if (!slug) { if (!slug) {

View file

@ -1,7 +1,7 @@
import type { APIRoute } from 'astro'; import type { APIRoute } from 'astro';
import PocketBase from 'pocketbase'; import PocketBase from 'pocketbase';
const PB_URL = import.meta.env.POCKETBASE_URL || 'http://127.0.0.1:8090'; const PB_URL = import.meta.env.PB_POCKETBASE_URL || 'http://127.0.0.1:8090';
export const GET: APIRoute = async ({ url }) => { export const GET: APIRoute = async ({ url }) => {
try { try {

View file

@ -1,7 +1,7 @@
import type { APIRoute } from "astro"; import type { APIRoute } from "astro";
import { sendEmail } from "../../../lib/email"; import { sendEmail } from "../../../lib/email";
const POCKETBASE_URL = import.meta.env.POCKETBASE_URL || "http://localhost:8090"; const PB_POCKETBASE_URL = import.meta.env.PB_POCKETBASE_URL || "http://localhost:8090";
const ADMIN_EMAIL = import.meta.env.PB_ADMIN_EMAIL || "redibedi2019@gmail.com"; const ADMIN_EMAIL = import.meta.env.PB_ADMIN_EMAIL || "redibedi2019@gmail.com";
export const POST: APIRoute = async ({ request, cookies }) => { export const POST: APIRoute = async ({ request, cookies }) => {
@ -18,7 +18,7 @@ export const POST: APIRoute = async ({ request, cookies }) => {
try { try {
let userId: string | null = null; let userId: string | null = null;
const userResponse = await fetch( const userResponse = await fetch(
`${POCKETBASE_URL}/api/collections/users/auth-refresh`, `${PB_POCKETBASE_URL}/api/collections/users/auth-refresh`,
{ {
method: "POST", method: "POST",
headers: { headers: {
@ -64,7 +64,7 @@ export const POST: APIRoute = async ({ request, cookies }) => {
} }
const response = await fetch( const response = await fetch(
`${POCKETBASE_URL}/api/collections/reviews/records`, `${PB_POCKETBASE_URL}/api/collections/reviews/records`,
{ {
method: "POST", method: "POST",
headers: { headers: {
@ -141,7 +141,7 @@ export const GET: APIRoute = async ({ url }) => {
try { try {
const response = await fetch( const response = await fetch(
`${POCKETBASE_URL}/api/collections/reviews/records?expand=${expand}&filter=${encodeURIComponent(filter)}&sort=${sort}`, `${PB_POCKETBASE_URL}/api/collections/reviews/records?expand=${expand}&filter=${encodeURIComponent(filter)}&sort=${sort}`,
{} {}
); );

View file

@ -1,6 +1,6 @@
import type { APIRoute } from 'astro'; import type { APIRoute } from 'astro';
const POCKETBASE_URL = import.meta.env.POCKETBASE_URL || 'http://127.0.0.1:8090'; const PB_POCKETBASE_URL = import.meta.env.PB_POCKETBASE_URL || 'http://127.0.0.1:8090';
const PB_ID_REGEX = /^[a-z0-9]{15}$/; const PB_ID_REGEX = /^[a-z0-9]{15}$/;
@ -16,7 +16,7 @@ export const POST: APIRoute = async ({ request, cookies }) => {
} }
const authResponse = await fetch( const authResponse = await fetch(
`${POCKETBASE_URL}/api/collections/users/auth-refresh`, `${PB_POCKETBASE_URL}/api/collections/users/auth-refresh`,
{ {
method: 'POST', method: 'POST',
headers: { headers: {
@ -61,7 +61,7 @@ export const POST: APIRoute = async ({ request, cookies }) => {
} }
const existingVoteRes = await fetch( const existingVoteRes = await fetch(
`${POCKETBASE_URL}/api/collections/review_votes/records?filter=(review="${review_id}")&&(user="${userId}")`, `${PB_POCKETBASE_URL}/api/collections/review_votes/records?filter=(review="${review_id}")&&(user="${userId}")`,
{ {
headers: { 'Authorization': `Bearer ${token}` }, headers: { 'Authorization': `Bearer ${token}` },
} }
@ -69,7 +69,7 @@ export const POST: APIRoute = async ({ request, cookies }) => {
let userVote: 'likes' | 'dislikes' | null = null; let userVote: 'likes' | 'dislikes' | null = null;
let method = 'POST'; let method = 'POST';
let url = `${POCKETBASE_URL}/api/collections/review_votes/records`; let url = `${PB_POCKETBASE_URL}/api/collections/review_votes/records`;
let voteId: string | null = null; let voteId: string | null = null;
if (existingVoteRes.ok) { if (existingVoteRes.ok) {
@ -80,10 +80,10 @@ export const POST: APIRoute = async ({ request, cookies }) => {
if (existing.vote_type === vote_type) { if (existing.vote_type === vote_type) {
method = 'DELETE'; method = 'DELETE';
url = `${POCKETBASE_URL}/api/collections/review_votes/records/${voteId}`; url = `${PB_POCKETBASE_URL}/api/collections/review_votes/records/${voteId}`;
} else { } else {
method = 'PATCH'; method = 'PATCH';
url = `${POCKETBASE_URL}/api/collections/review_votes/records/${voteId}`; url = `${PB_POCKETBASE_URL}/api/collections/review_votes/records/${voteId}`;
userVote = vote_type; userVote = vote_type;
} }
} }
@ -114,7 +114,7 @@ export const POST: APIRoute = async ({ request, cookies }) => {
if (method === 'DELETE') userVote = null; if (method === 'DELETE') userVote = null;
const votesRes = await fetch( const votesRes = await fetch(
`${POCKETBASE_URL}/api/collections/review_votes/records?filter=(review="${review_id}")`, `${PB_POCKETBASE_URL}/api/collections/review_votes/records?filter=(review="${review_id}")`,
{ headers: { 'Authorization': `Bearer ${token}` } } { headers: { 'Authorization': `Bearer ${token}` } }
); );
@ -132,7 +132,7 @@ export const POST: APIRoute = async ({ request, cookies }) => {
console.error('[ReviewVote API] Votes error:', errorText); console.error('[ReviewVote API] Votes error:', errorText);
} }
await fetch(`${POCKETBASE_URL}/api/collections/reviews/records/${review_id}`, { await fetch(`${PB_POCKETBASE_URL}/api/collections/reviews/records/${review_id}`, {
method: 'PATCH', method: 'PATCH',
headers: { headers: {
'Authorization': `Bearer ${token}`, 'Authorization': `Bearer ${token}`,
@ -168,7 +168,7 @@ export const GET: APIRoute = async ({ url, cookies }) => {
const authHeaders = token ? { 'Authorization': `Bearer ${token}` } : {}; const authHeaders = token ? { 'Authorization': `Bearer ${token}` } : {};
const votesRes = await fetch( const votesRes = await fetch(
`${POCKETBASE_URL}/api/collections/review_votes/records?filter=(review="${reviewId}")`, `${PB_POCKETBASE_URL}/api/collections/review_votes/records?filter=(review="${reviewId}")`,
{ headers: authHeaders } { headers: authHeaders }
); );
@ -188,7 +188,7 @@ export const GET: APIRoute = async ({ url, cookies }) => {
if (token) { if (token) {
try { try {
const authRes = await fetch( const authRes = await fetch(
`${POCKETBASE_URL}/api/collections/users/auth-refresh`, `${PB_POCKETBASE_URL}/api/collections/users/auth-refresh`,
{ {
method: 'POST', method: 'POST',
headers: { 'Authorization': `Bearer ${token}` }, headers: { 'Authorization': `Bearer ${token}` },
@ -201,7 +201,7 @@ export const GET: APIRoute = async ({ url, cookies }) => {
if (userId && PB_ID_REGEX.test(userId)) { if (userId && PB_ID_REGEX.test(userId)) {
const userVoteRes = await fetch( const userVoteRes = await fetch(
`${POCKETBASE_URL}/api/collections/review_votes/records?filter=(review="${reviewId}")&&(user="${userId}")`, `${PB_POCKETBASE_URL}/api/collections/review_votes/records?filter=(review="${reviewId}")&&(user="${userId}")`,
{ {
headers: { 'Authorization': `Bearer ${token}` }, headers: { 'Authorization': `Bearer ${token}` },
} }

View file

@ -1,7 +1,7 @@
import type { APIRoute } from 'astro'; import type { APIRoute } from 'astro';
import crypto from 'crypto'; import crypto from 'crypto';
const POCKETBASE_URL = import.meta.env.POCKETBASE_URL || 'http://127.0.0.1:8090'; const PB_POCKETBASE_URL = import.meta.env.PB_POCKETBASE_URL || 'http://127.0.0.1:8090';
function getClientIp(request: Request): string { function getClientIp(request: Request): string {
const forwarded = request.headers.get('x-forwarded-for'); const forwarded = request.headers.get('x-forwarded-for');
@ -26,7 +26,7 @@ function generateVisitorHash(ip: string, userAgent: string): string {
} }
async function pbRequest(method: string, path: string, body?: object) { async function pbRequest(method: string, path: string, body?: object) {
const url = `${POCKETBASE_URL}${path}`; const url = `${PB_POCKETBASE_URL}${path}`;
const options: RequestInit = { const options: RequestInit = {
method, method,
headers: { headers: {

View file

@ -1,6 +1,6 @@
import type { APIRoute } from 'astro'; import type { APIRoute } from 'astro';
const POCKETBASE_URL = import.meta.env.POCKETBASE_URL || 'http://127.0.0.1:8090'; const PB_POCKETBASE_URL = import.meta.env.PB_POCKETBASE_URL || 'http://127.0.0.1:8090';
// Валидация ID PocketBase (15 символов, буквы и цифры) // Валидация ID PocketBase (15 символов, буквы и цифры)
const POCKETBASE_ID_REGEX = /^[a-z0-9]{15}$/; const POCKETBASE_ID_REGEX = /^[a-z0-9]{15}$/;
@ -20,7 +20,7 @@ export const POST: APIRoute = async ({ request, cookies }) => {
// Проверяем токен и получаем пользователя через auth-refresh // Проверяем токен и получаем пользователя через auth-refresh
const authResponse = await fetch( const authResponse = await fetch(
`${POCKETBASE_URL}/api/collections/users/auth-refresh`, `${PB_POCKETBASE_URL}/api/collections/users/auth-refresh`,
{ {
method: 'POST', method: 'POST',
headers: { headers: {
@ -84,7 +84,7 @@ export const POST: APIRoute = async ({ request, cookies }) => {
// Проверяем существующий голос // Проверяем существующий голос
const existingVoteRes = await fetch( const existingVoteRes = await fetch(
`${POCKETBASE_URL}/api/collections/post_votes/records?` + `${PB_POCKETBASE_URL}/api/collections/post_votes/records?` +
new URLSearchParams({ new URLSearchParams({
filter: `post="${post_id}" && user="${userId}"`, filter: `post="${post_id}" && user="${userId}"`,
}), }),
@ -95,7 +95,7 @@ export const POST: APIRoute = async ({ request, cookies }) => {
let userVote: 'like' | 'dislike' | null = null; let userVote: 'like' | 'dislike' | null = null;
let method = 'POST'; let method = 'POST';
let url = `${POCKETBASE_URL}/api/collections/post_votes/records`; let url = `${PB_POCKETBASE_URL}/api/collections/post_votes/records`;
let voteId = null; let voteId = null;
if (existingVoteRes.ok) { if (existingVoteRes.ok) {
@ -107,11 +107,11 @@ export const POST: APIRoute = async ({ request, cookies }) => {
if (existing.vote_type === vote_type) { if (existing.vote_type === vote_type) {
// Удаляем голос (toggle off) // Удаляем голос (toggle off)
method = 'DELETE'; method = 'DELETE';
url = `${POCKETBASE_URL}/api/collections/post_votes/records/${voteId}`; url = `${PB_POCKETBASE_URL}/api/collections/post_votes/records/${voteId}`;
} else { } else {
// Обновляем // Обновляем
method = 'PATCH'; method = 'PATCH';
url = `${POCKETBASE_URL}/api/collections/post_votes/records/${voteId}`; url = `${PB_POCKETBASE_URL}/api/collections/post_votes/records/${voteId}`;
userVote = vote_type; userVote = vote_type;
} }
} }
@ -155,7 +155,7 @@ export const POST: APIRoute = async ({ request, cookies }) => {
// Получаем актуальные счетчики (без авторизации) // Получаем актуальные счетчики (без авторизации)
const votesRes = await fetch( const votesRes = await fetch(
`${POCKETBASE_URL}/api/collections/post_votes/records?` + `${PB_POCKETBASE_URL}/api/collections/post_votes/records?` +
new URLSearchParams({ new URLSearchParams({
filter: `post="${post_id}"`, filter: `post="${post_id}"`,
fields: 'vote_type', fields: 'vote_type',
@ -174,7 +174,7 @@ export const POST: APIRoute = async ({ request, cookies }) => {
// Обновляем счетчики в посте только если есть токен // Обновляем счетчики в посте только если есть токен
if (token) { if (token) {
await fetch( await fetch(
`${POCKETBASE_URL}/api/collections/posts/records/${post_id}`, `${PB_POCKETBASE_URL}/api/collections/posts/records/${post_id}`,
{ {
method: 'PATCH', method: 'PATCH',
headers: { headers: {
@ -214,7 +214,7 @@ export const GET: APIRoute = async ({ url, cookies }) => {
// Получаем пост со счетчиками // Получаем пост со счетчиками
const postRes = await fetch( const postRes = await fetch(
`${POCKETBASE_URL}/api/collections/posts/records/${postId}`, `${PB_POCKETBASE_URL}/api/collections/posts/records/${postId}`,
{ {
headers: token ? { 'Authorization': `Bearer ${token}` } : {}, headers: token ? { 'Authorization': `Bearer ${token}` } : {},
} }
@ -231,7 +231,7 @@ export const GET: APIRoute = async ({ url, cookies }) => {
// Получаем счетчики из коллекции голосов (без авторизации) // Получаем счетчики из коллекции голосов (без авторизации)
const votesCountRes = await fetch( const votesCountRes = await fetch(
`${POCKETBASE_URL}/api/collections/post_votes/records?` + `${PB_POCKETBASE_URL}/api/collections/post_votes/records?` +
new URLSearchParams({ new URLSearchParams({
filter: `post="${postId}"`, filter: `post="${postId}"`,
fields: 'vote_type', fields: 'vote_type',
@ -254,7 +254,7 @@ export const GET: APIRoute = async ({ url, cookies }) => {
try { try {
// Проверяем токен // Проверяем токен
const authRes = await fetch( const authRes = await fetch(
`${POCKETBASE_URL}/api/collections/users/auth-refresh`, `${PB_POCKETBASE_URL}/api/collections/users/auth-refresh`,
{ {
method: 'POST', method: 'POST',
headers: { 'Authorization': `Bearer ${token}` }, headers: { 'Authorization': `Bearer ${token}` },
@ -270,7 +270,7 @@ export const GET: APIRoute = async ({ url, cookies }) => {
console.log('[Vote API] GET: Checking for existing vote with:', { post: postId, user: userId }); console.log('[Vote API] GET: Checking for existing vote with:', { post: postId, user: userId });
const userVoteRes = await fetch( const userVoteRes = await fetch(
`${POCKETBASE_URL}/api/collections/post_votes/records?` + `${PB_POCKETBASE_URL}/api/collections/post_votes/records?` +
new URLSearchParams({ new URLSearchParams({
filter: `post="${postId}" && user="${userId}"`, filter: `post="${postId}" && user="${userId}"`,
}), }),