Просмотр исходного кода

feat: add legacy /api/shops backward-compat aliases

fszontagh 3 месяцев назад
Родитель
Сommit
0993ad6fec

+ 3 - 3
src/api/components/McpEndpoint.ts

@@ -584,7 +584,7 @@ export class McpEndpoint extends BaseEndpointComponent {
 
 
   private async getShopMcpAnalytics(req: Request, res: Response): Promise<void> {
   private async getShopMcpAnalytics(req: Request, res: Response): Promise<void> {
     try {
     try {
-      const { siteId } = req.params;
+      const siteId = req.params.siteId || req.params.id;
       const { dateFrom, dateTo } = req.query;
       const { dateFrom, dateTo } = req.query;
 
 
       // Get site by any ID (try custom_id first, then internal ID)
       // Get site by any ID (try custom_id first, then internal ID)
@@ -725,7 +725,7 @@ export class McpEndpoint extends BaseEndpointComponent {
 
 
   private async getShopMcpLogs(req: Request, res: Response): Promise<void> {
   private async getShopMcpLogs(req: Request, res: Response): Promise<void> {
     try {
     try {
-      const { siteId } = req.params;
+      const siteId = req.params.siteId || req.params.id;
       const { limit, success, tool_name } = req.query;
       const { limit, success, tool_name } = req.query;
 
 
       // Get site from database - try both internal ID and custom ID
       // Get site from database - try both internal ID and custom ID
@@ -759,7 +759,7 @@ export class McpEndpoint extends BaseEndpointComponent {
 
 
   private async clearShopMcpLogs(req: Request, res: Response): Promise<void> {
   private async clearShopMcpLogs(req: Request, res: Response): Promise<void> {
     try {
     try {
-      const { siteId } = req.params;
+      const siteId = req.params.siteId || req.params.id;
 
 
       // Get site from database - try both internal ID and custom ID
       // Get site from database - try both internal ID and custom ID
       // Get site by any ID (try custom_id first, then internal ID)
       // Get site by any ID (try custom_id first, then internal ID)

+ 15 - 15
src/api/components/QdrantEndpoint.ts

@@ -715,7 +715,7 @@ export class QdrantEndpoint extends BaseEndpointComponent {
 
 
   private async getShopQdrantStatus(req: Request, res: Response): Promise<void> {
   private async getShopQdrantStatus(req: Request, res: Response): Promise<void> {
     try {
     try {
-      const { siteId } = req.params;
+      const siteId = req.params.siteId || req.params.id;
 
 
       // Get site by any ID (try custom_id first, then internal ID)
       // Get site by any ID (try custom_id first, then internal ID)
       const site = this.db.getSiteByAnyId(siteId);
       const site = this.db.getSiteByAnyId(siteId);
@@ -756,7 +756,7 @@ export class QdrantEndpoint extends BaseEndpointComponent {
 
 
   private async toggleShopQdrant(req: Request, res: Response): Promise<void> {
   private async toggleShopQdrant(req: Request, res: Response): Promise<void> {
     try {
     try {
-      const { siteId } = req.params;
+      const siteId = req.params.siteId || req.params.id;
       const { enabled } = req.body;
       const { enabled } = req.body;
 
 
       // Get site by any ID (try custom_id first, then internal ID)
       // Get site by any ID (try custom_id first, then internal ID)
@@ -777,7 +777,7 @@ export class QdrantEndpoint extends BaseEndpointComponent {
 
 
   private async updateShopCustomId(req: Request, res: Response): Promise<void> {
   private async updateShopCustomId(req: Request, res: Response): Promise<void> {
     try {
     try {
-      const { siteId } = req.params;
+      const siteId = req.params.siteId || req.params.id;
       const { custom_id } = req.body;
       const { custom_id } = req.body;
 
 
       // Validate custom_id format (alphanumeric, dashes, underscores)
       // Validate custom_id format (alphanumeric, dashes, underscores)
@@ -887,7 +887,7 @@ export class QdrantEndpoint extends BaseEndpointComponent {
 
 
   private async reEmbedSiteContent(req: Request, res: Response): Promise<void> {
   private async reEmbedSiteContent(req: Request, res: Response): Promise<void> {
     try {
     try {
-      const { siteId } = req.params;
+      const siteId = req.params.siteId || req.params.id;
       const { content_type } = req.body || {};
       const { content_type } = req.body || {};
 
 
       // Get site by any ID (try custom_id first, then internal ID)
       // Get site by any ID (try custom_id first, then internal ID)
@@ -925,7 +925,7 @@ export class QdrantEndpoint extends BaseEndpointComponent {
 
 
   private async getShopQdrantErrors(req: Request, res: Response): Promise<void> {
   private async getShopQdrantErrors(req: Request, res: Response): Promise<void> {
     try {
     try {
-      const { siteId } = req.params;
+      const siteId = req.params.siteId || req.params.id;
       const limit = parseInt(req.query.limit as string) || 50;
       const limit = parseInt(req.query.limit as string) || 50;
 
 
       const errors = this.db.getQdrantErrors(siteId);
       const errors = this.db.getQdrantErrors(siteId);
@@ -1007,7 +1007,7 @@ export class QdrantEndpoint extends BaseEndpointComponent {
   // New endpoint handlers for the correct URL structure
   // New endpoint handlers for the correct URL structure
   private async getShopQdrantInfo(req: Request, res: Response): Promise<void> {
   private async getShopQdrantInfo(req: Request, res: Response): Promise<void> {
     try {
     try {
-      const { siteId } = req.params;
+      const siteId = req.params.siteId || req.params.id;
 
 
       // Get site from database - try both internal ID and custom ID
       // Get site from database - try both internal ID and custom ID
       // Get site by any ID (try custom_id first, then internal ID)
       // Get site by any ID (try custom_id first, then internal ID)
@@ -1040,7 +1040,7 @@ export class QdrantEndpoint extends BaseEndpointComponent {
 
 
   private async getShopQdrantEmbeddings(req: Request, res: Response): Promise<void> {
   private async getShopQdrantEmbeddings(req: Request, res: Response): Promise<void> {
     try {
     try {
-      const { siteId } = req.params;
+      const siteId = req.params.siteId || req.params.id;
 
 
       // Get site from database - try both internal ID and custom ID
       // Get site from database - try both internal ID and custom ID
       // Get site by any ID (try custom_id first, then internal ID)
       // Get site by any ID (try custom_id first, then internal ID)
@@ -1078,7 +1078,7 @@ export class QdrantEndpoint extends BaseEndpointComponent {
 
 
   private async getShopQdrantErrorsNew(req: Request, res: Response): Promise<void> {
   private async getShopQdrantErrorsNew(req: Request, res: Response): Promise<void> {
     try {
     try {
-      const { siteId } = req.params;
+      const siteId = req.params.siteId || req.params.id;
 
 
       // Get site from database - try both internal ID and custom ID
       // Get site from database - try both internal ID and custom ID
       // Get site by any ID (try custom_id first, then internal ID)
       // Get site by any ID (try custom_id first, then internal ID)
@@ -1114,7 +1114,7 @@ export class QdrantEndpoint extends BaseEndpointComponent {
 
 
   private async clearShopQdrantErrors(req: Request, res: Response): Promise<void> {
   private async clearShopQdrantErrors(req: Request, res: Response): Promise<void> {
     try {
     try {
-      const { siteId } = req.params;
+      const siteId = req.params.siteId || req.params.id;
 
 
       // Get site from database - try both internal ID and custom ID
       // Get site from database - try both internal ID and custom ID
       // Get site by any ID (try custom_id first, then internal ID)
       // Get site by any ID (try custom_id first, then internal ID)
@@ -1141,7 +1141,7 @@ export class QdrantEndpoint extends BaseEndpointComponent {
 
 
   private async clearPendingEmbeddings(req: Request, res: Response): Promise<void> {
   private async clearPendingEmbeddings(req: Request, res: Response): Promise<void> {
     try {
     try {
-      const { siteId } = req.params;
+      const siteId = req.params.siteId || req.params.id;
 
 
       // Get site from database - try both internal ID and custom ID
       // Get site from database - try both internal ID and custom ID
       // Get site by any ID (try custom_id first, then internal ID)
       // Get site by any ID (try custom_id first, then internal ID)
@@ -1187,7 +1187,7 @@ export class QdrantEndpoint extends BaseEndpointComponent {
 
 
   private async scheduleShopDeletion(req: Request, res: Response): Promise<void> {
   private async scheduleShopDeletion(req: Request, res: Response): Promise<void> {
     try {
     try {
-      const { siteId } = req.params;
+      const siteId = req.params.siteId || req.params.id;
 
 
       // Get site from database - try both internal ID and custom ID
       // Get site from database - try both internal ID and custom ID
       // Get site by any ID (try custom_id first, then internal ID)
       // Get site by any ID (try custom_id first, then internal ID)
@@ -1224,7 +1224,7 @@ export class QdrantEndpoint extends BaseEndpointComponent {
 
 
   private async forceQdrantSync(req: Request, res: Response): Promise<void> {
   private async forceQdrantSync(req: Request, res: Response): Promise<void> {
     try {
     try {
-      const { siteId } = req.params;
+      const siteId = req.params.siteId || req.params.id;
 
 
       // Get site from database - try both internal ID and custom ID
       // Get site from database - try both internal ID and custom ID
       let site = this.db.getSiteByAnyId(siteId);
       let site = this.db.getSiteByAnyId(siteId);
@@ -1322,7 +1322,7 @@ export class QdrantEndpoint extends BaseEndpointComponent {
 
 
   private async getMigrationStatus(req: Request, res: Response): Promise<void> {
   private async getMigrationStatus(req: Request, res: Response): Promise<void> {
     try {
     try {
-      const { siteId } = req.params;
+      const siteId = req.params.siteId || req.params.id;
 
 
       // Get site from database
       // Get site from database
       const site = this.db.getSiteByAnyId(siteId);
       const site = this.db.getSiteByAnyId(siteId);
@@ -1352,7 +1352,7 @@ export class QdrantEndpoint extends BaseEndpointComponent {
 
 
   private async migrateShop(req: Request, res: Response): Promise<void> {
   private async migrateShop(req: Request, res: Response): Promise<void> {
     try {
     try {
-      const { siteId } = req.params;
+      const siteId = req.params.siteId || req.params.id;
 
 
       // Get site from database
       // Get site from database
       const site = this.db.getSiteByAnyId(siteId);
       const site = this.db.getSiteByAnyId(siteId);
@@ -1387,7 +1387,7 @@ export class QdrantEndpoint extends BaseEndpointComponent {
 
 
   private async cleanupOldCollections(req: Request, res: Response): Promise<void> {
   private async cleanupOldCollections(req: Request, res: Response): Promise<void> {
     try {
     try {
-      const { siteId } = req.params;
+      const siteId = req.params.siteId || req.params.id;
       const { dryRun = true } = req.body || {};
       const { dryRun = true } = req.body || {};
 
 
       // Get site from database
       // Get site from database

+ 53 - 0
src/api/middleware/legacyShopAlias.ts

@@ -0,0 +1,53 @@
+import { Request, Response, NextFunction } from 'express';
+
+/**
+ * Key mapping from new site-based naming back to old shop-based naming.
+ * Applied recursively to JSON response bodies for legacy /api/shops/* routes.
+ */
+const KEY_MAP: Record<string, string> = {
+  site_content_id: 'shop_content_id',
+  site_content: 'shop_content',
+  site_usage: 'shop_usage',
+  site_type: 'webshop_type',
+  site_id: 'shop_id',
+  sites: 'shops',
+  site: 'shop',
+};
+
+/**
+ * Recursively rewrite object keys from site-based to shop-based naming.
+ */
+export function rewriteKeys(value: unknown): unknown {
+  if (value == null) {
+    return value;
+  }
+
+  if (Array.isArray(value)) {
+    return value.map(rewriteKeys);
+  }
+
+  if (typeof value === 'object') {
+    const result: Record<string, unknown> = {};
+    for (const [key, val] of Object.entries(value as Record<string, unknown>)) {
+      const mappedKey = KEY_MAP[key] ?? key;
+      result[mappedKey] = rewriteKeys(val);
+    }
+    return result;
+  }
+
+  return value;
+}
+
+/**
+ * Express middleware that monkey-patches res.json() to rewrite response keys
+ * from site-based naming back to shop-based naming for backward compatibility.
+ */
+export function legacyShopAlias(req: Request, res: Response, next?: NextFunction): void {
+  const originalJson = res.json.bind(res);
+
+  res.json = function (body?: any): Response {
+    return originalJson(rewriteKeys(body));
+  };
+
+  next?.();
+}

+ 27 - 0
src/api/routes.ts

@@ -3,6 +3,7 @@ import { JobQueue } from '../queue/JobQueue';
 import { SiteDatabase } from '../database/Database';
 import { SiteDatabase } from '../database/Database';
 import { EndpointRegistry } from './core/EndpointRegistry';
 import { EndpointRegistry } from './core/EndpointRegistry';
 import { authMiddleware } from './middleware/auth';
 import { authMiddleware } from './middleware/auth';
+import { legacyShopAlias } from './middleware/legacyShopAlias';
 import { BaseEndpointComponent } from './core/types';
 import { BaseEndpointComponent } from './core/types';
 
 
 // Import all endpoint components
 // Import all endpoint components
@@ -72,6 +73,32 @@ export function createRouter(jobQueue: JobQueue, apiKey: string, db?: SiteDataba
     }
     }
   }
   }
 
 
+  // Register legacy /api/shops/* backward-compat aliases
+  const legacyPatterns = ['/api/sites', '/api/qdrant/sites', '/api/mcp/sites'];
+  for (const endpoint of registry.getAllEndpoints()) {
+    const matchesLegacy = legacyPatterns.some(p => endpoint.path.includes(p));
+    if (!matchesLegacy) continue;
+
+    const legacyPath = endpoint.path
+      .replace(/\/sites\b/g, '/shops')
+      .replace(/:siteId\b/g, ':id');
+
+    const legacyMiddleware = [legacyShopAlias, ...(endpoint.middleware || [])];
+
+    registry.register({
+      method: endpoint.method,
+      path: legacyPath,
+      handler: endpoint.handler,
+      middleware: legacyMiddleware,
+      documentation: {
+        ...endpoint.documentation,
+        path: legacyPath,
+        summary: `[Legacy] ${endpoint.documentation.summary || ''}`,
+        tags: ['Legacy'],
+      },
+    });
+  }
+
   // Build and return the router
   // Build and return the router
   return registry.buildRouter();
   return registry.buildRouter();
 }
 }