Compare commits
No commits in common. "dadb6f3bcb16ef94cb9515ea27b0c2c62ce46dfb" and "adf24d9b56ac9951697c6a58d3558381afd67643" have entirely different histories.
dadb6f3bcb
...
adf24d9b56
|
|
@ -1,41 +1,14 @@
|
|||
import { Controller, Get, Post, Put, Body, Param, Headers, HttpException, HttpStatus } from '@nestjs/common';
|
||||
import { Controller, Get, Param, Post, Body, Put } from '@nestjs/common';
|
||||
import { MenuService } from './menu.service';
|
||||
import { MenuItem } from './menu.interface';
|
||||
import { Response } from 'express';
|
||||
|
||||
@Controller('menu')
|
||||
export class MenuController {
|
||||
constructor(private readonly menuService: MenuService) { }
|
||||
|
||||
@Get('full')
|
||||
async getFullMenu(@Headers('if-modified-since') ifModifiedSince?: string) {
|
||||
try {
|
||||
const result = await this.menuService.getFullMenuWithCache(ifModifiedSince);
|
||||
|
||||
if (!result.fresh && ifModifiedSince) {
|
||||
throw new HttpException('Not Modified', HttpStatus.NOT_MODIFIED);
|
||||
}
|
||||
|
||||
return result.menu;
|
||||
} catch (error) {
|
||||
if (error.status === HttpStatus.NOT_MODIFIED) {
|
||||
throw error;
|
||||
}
|
||||
throw new HttpException(
|
||||
error.message || 'Failed to load menu',
|
||||
HttpStatus.INTERNAL_SERVER_ERROR
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Get('check-updates')
|
||||
async checkUpdates(@Headers('if-modified-since') ifModifiedSince: string) {
|
||||
if (!ifModifiedSince) {
|
||||
throw new HttpException('If-Modified-Since header is required', HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
|
||||
const hasUpdates = await this.menuService.checkForUpdates(ifModifiedSince);
|
||||
return { hasUpdates };
|
||||
@Get()
|
||||
async getMenu(): Promise<MenuItem> {
|
||||
return this.menuService.getFullMenu();
|
||||
}
|
||||
|
||||
@Post('save')
|
||||
|
|
@ -44,18 +17,21 @@ export class MenuController {
|
|||
return { status: 'saved' };
|
||||
}
|
||||
|
||||
@Get('full')
|
||||
async getFullMenu(): Promise<MenuItem> {
|
||||
return this.menuService.getFullMenu();
|
||||
}
|
||||
|
||||
@Post('overrides')
|
||||
async saveOverrides(@Body() data: { overrides: Partial<MenuItem>[] }) {
|
||||
await this.menuService.saveOverrides(data.overrides);
|
||||
return { status: 'success' };
|
||||
return this.menuService.saveOverrides(data.overrides);
|
||||
}
|
||||
|
||||
@Put(':id')
|
||||
async updateMenuItem(
|
||||
@Param('id') id: string,
|
||||
@Body() update: Partial<MenuItem>
|
||||
) {
|
||||
const updatedItem = await this.menuService.updateMenuItem(id, update);
|
||||
return updatedItem;
|
||||
): Promise<MenuItem> {
|
||||
return this.menuService.updateMenuItem(id, update);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
import { Injectable, HttpException, HttpStatus } from '@nestjs/common';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { PrometheusService } from '../prometheus.service';
|
||||
import { MenuItem } from './menu.interface';
|
||||
import * as fs from 'fs/promises';
|
||||
|
|
@ -7,10 +7,6 @@ import { RangeService } from './range.service';
|
|||
|
||||
@Injectable()
|
||||
export class MenuService {
|
||||
private menuCache: MenuItem | null = null;
|
||||
private lastModified: Date | null = null;
|
||||
private cacheInitialized = false;
|
||||
|
||||
constructor(
|
||||
private readonly prometheusService: PrometheusService,
|
||||
private readonly rangeService: RangeService
|
||||
|
|
@ -19,33 +15,16 @@ export class MenuService {
|
|||
private readonly menuOverridesPath = path.join(process.cwd(), 'data', 'menu.json');
|
||||
|
||||
async saveMenuToFile(): Promise<void> {
|
||||
const { menu } = await this.getFullMenuWithCache();
|
||||
const menu = await this.getFullMenu();
|
||||
await fs.mkdir(path.dirname(this.menuOverridesPath), { recursive: true });
|
||||
await fs.writeFile(this.menuOverridesPath, JSON.stringify(menu, null, 2), 'utf-8');
|
||||
}
|
||||
|
||||
async getFullMenuWithCache(ifModifiedSince?: string): Promise<{ menu: MenuItem; fresh: boolean }> {
|
||||
if (this.menuCache && this.lastModified && (!ifModifiedSince || new Date(ifModifiedSince) >= this.lastModified)) {
|
||||
return { menu: this.menuCache, fresh: false };
|
||||
}
|
||||
|
||||
async getFullMenu(): Promise<MenuItem> {
|
||||
const dynamicItemsPromise = this.generateDynamicItems();
|
||||
const baseMenu = await this.injectDynamicItems(this.getStaticStructure(), dynamicItemsPromise);
|
||||
const overrides = await this.loadOverrides();
|
||||
const freshMenu = this.applyOverrides(baseMenu, overrides);
|
||||
|
||||
this.menuCache = freshMenu;
|
||||
this.lastModified = new Date();
|
||||
this.cacheInitialized = true;
|
||||
|
||||
return { menu: freshMenu, fresh: true };
|
||||
}
|
||||
|
||||
async checkForUpdates(ifModifiedSince: string): Promise<boolean> {
|
||||
if (!this.cacheInitialized) {
|
||||
await this.getFullMenuWithCache();
|
||||
}
|
||||
return !this.lastModified || new Date(ifModifiedSince) < this.lastModified;
|
||||
return this.applyOverrides(baseMenu, overrides);
|
||||
}
|
||||
|
||||
private applyOverrides(menu: MenuItem, overrides: Partial<MenuItem>[]): MenuItem {
|
||||
|
|
@ -283,21 +262,17 @@ export class MenuService {
|
|||
}
|
||||
|
||||
async updateMenuItem(id: string, update: Partial<MenuItem>): Promise<MenuItem> {
|
||||
const { menu: fullMenu } = await this.getFullMenuWithCache();
|
||||
const fullMenu = await this.getFullMenu();
|
||||
const item = this.findMenuItem(fullMenu, id);
|
||||
|
||||
if (!item) throw new Error('Menu item not found');
|
||||
Object.assign(item, update);
|
||||
|
||||
// Инвалидируем кэш после изменения
|
||||
this.menuCache = null;
|
||||
return item;
|
||||
}
|
||||
|
||||
async saveOverrides(overrides: Partial<MenuItem>[]): Promise<void> {
|
||||
await fs.writeFile(this.menuOverridesPath, JSON.stringify({ overrides }, null, 2), 'utf-8');
|
||||
// Инвалидируем кэш после изменения оверрайдов
|
||||
this.menuCache = null;
|
||||
}
|
||||
|
||||
private findMenuItem(menu: MenuItem, id: string): MenuItem | null {
|
||||
|
|
|
|||
Loading…
Reference in New Issue