refactor: remove dead code (api_manager.go, unused templates)
CLN-01: Deleted archived api_manager.go (~789 LOC, build-tag ignore) and dev-environment/templates/ (~806 LOC, never used by generator).
This commit is contained in:
parent
763aea15cb
commit
834fa1f979
10 changed files with 0 additions and 1596 deletions
|
|
@ -150,7 +150,6 @@ ci_cd:
|
||||||
tools:
|
tools:
|
||||||
generators:
|
generators:
|
||||||
enabled: true
|
enabled: true
|
||||||
templates_path: "dev-environment/templates"
|
|
||||||
|
|
||||||
validators:
|
validators:
|
||||||
enabled: true
|
enabled: true
|
||||||
|
|
|
||||||
|
|
@ -1,87 +0,0 @@
|
||||||
package handlers
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http"
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"veza-backend-api/internal/types"
|
|
||||||
"veza-backend-api/internal/models"
|
|
||||||
)
|
|
||||||
|
|
||||||
// {{HANDLER_NAME}}Handlers handles HTTP requests for {{DOMAIN}}
|
|
||||||
type {{HANDLER_NAME}}Handlers struct {
|
|
||||||
{{SERVICE_LOWER}}Service types.{{SERVICE_INTERFACE}}
|
|
||||||
}
|
|
||||||
|
|
||||||
// New{{HANDLER_NAME}}Handlers creates a new {{HANDLER_NAME}}Handlers instance
|
|
||||||
func New{{HANDLER_NAME}}Handlers(
|
|
||||||
{{SERVICE_LOWER}}Service types.{{SERVICE_INTERFACE}},
|
|
||||||
) *{{HANDLER_NAME}}Handlers {
|
|
||||||
return &{{HANDLER_NAME}}Handlers{
|
|
||||||
{{SERVICE_LOWER}}Service: {{SERVICE_LOWER}}Service,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create{{ENTITY}} handles POST /api/v1/{{RESOURCE_PATH}}
|
|
||||||
func (h *{{HANDLER_NAME}}Handlers) Create{{ENTITY}}(c *gin.Context) {
|
|
||||||
var req Create{{ENTITY}}Request
|
|
||||||
if err := c.ShouldBindJSON(&req); err != nil {
|
|
||||||
c.JSON(http.StatusBadRequest, gin.H{
|
|
||||||
"error": "invalid request",
|
|
||||||
"details": err.Error(),
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
{{ENTITY_LOWER}}, err := h.{{SERVICE_LOWER}}Service.Create{{ENTITY}}(c.Request.Context(), &req)
|
|
||||||
if err != nil {
|
|
||||||
handleError(c, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
c.JSON(http.StatusCreated, gin.H{
|
|
||||||
"data": {{ENTITY_LOWER}},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get{{ENTITY}} handles GET /api/v1/{{RESOURCE_PATH}}/:id
|
|
||||||
func (h *{{HANDLER_NAME}}Handlers) Get{{ENTITY}}(c *gin.Context) {
|
|
||||||
idParam := c.Param("id")
|
|
||||||
id, err := uuid.Parse(idParam)
|
|
||||||
if err != nil {
|
|
||||||
c.JSON(http.StatusBadRequest, gin.H{
|
|
||||||
"error": "invalid id format",
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
{{ENTITY_LOWER}}, err := h.{{SERVICE_LOWER}}Service.Get{{ENTITY}}ByID(c.Request.Context(), id)
|
|
||||||
if err != nil {
|
|
||||||
handleError(c, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
c.JSON(http.StatusOK, gin.H{
|
|
||||||
"data": {{ENTITY_LOWER}},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// handleError handles errors in a consistent way
|
|
||||||
func handleError(c *gin.Context, err error) {
|
|
||||||
// TODO: Implement error handling logic
|
|
||||||
// Check error type and return appropriate status code
|
|
||||||
c.JSON(http.StatusInternalServerError, gin.H{
|
|
||||||
"error": "internal server error",
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create{{ENTITY}}Request represents the request body for creating a {{ENTITY}}
|
|
||||||
type Create{{ENTITY}}Request struct {
|
|
||||||
// TODO: Add request fields with JSON tags
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,78 +0,0 @@
|
||||||
package repository
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"veza-backend-api/internal/models"
|
|
||||||
"gorm.io/gorm"
|
|
||||||
)
|
|
||||||
|
|
||||||
// {{REPOSITORY_NAME}}Repository implements persistence for {{ENTITY}}
|
|
||||||
type {{REPOSITORY_NAME}}Repository struct {
|
|
||||||
db *gorm.DB
|
|
||||||
}
|
|
||||||
|
|
||||||
// New{{REPOSITORY_NAME}}Repository creates a new {{REPOSITORY_NAME}}Repository instance
|
|
||||||
func New{{REPOSITORY_NAME}}Repository(db *gorm.DB) *{{REPOSITORY_NAME}}Repository {
|
|
||||||
return &{{REPOSITORY_NAME}}Repository{
|
|
||||||
db: db,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create creates a new {{ENTITY}} in the database
|
|
||||||
func (r *{{REPOSITORY_NAME}}Repository) Create(
|
|
||||||
ctx context.Context,
|
|
||||||
{{ENTITY_LOWER}} *models.{{ENTITY}},
|
|
||||||
) error {
|
|
||||||
if err := r.db.WithContext(ctx).Create({{ENTITY_LOWER}}).Error; err != nil {
|
|
||||||
return fmt.Errorf("failed to create {{ENTITY_LOWER}}: %w", err)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// FindByID finds a {{ENTITY}} by ID
|
|
||||||
func (r *{{REPOSITORY_NAME}}Repository) FindByID(
|
|
||||||
ctx context.Context,
|
|
||||||
id uuid.UUID,
|
|
||||||
) (*models.{{ENTITY}}, error) {
|
|
||||||
var {{ENTITY_LOWER}} models.{{ENTITY}}
|
|
||||||
if err := r.db.WithContext(ctx).
|
|
||||||
Where("id = ?", id).
|
|
||||||
First(&{{ENTITY_LOWER}}).Error; err != nil {
|
|
||||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
||||||
return nil, types.ErrNotFound("{{ENTITY_LOWER}} not found")
|
|
||||||
}
|
|
||||||
return nil, fmt.Errorf("failed to find {{ENTITY_LOWER}}: %w", err)
|
|
||||||
}
|
|
||||||
return &{{ENTITY_LOWER}}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update updates an existing {{ENTITY}}
|
|
||||||
func (r *{{REPOSITORY_NAME}}Repository) Update(
|
|
||||||
ctx context.Context,
|
|
||||||
{{ENTITY_LOWER}} *models.{{ENTITY}},
|
|
||||||
) error {
|
|
||||||
if err := r.db.WithContext(ctx).
|
|
||||||
Save({{ENTITY_LOWER}}).Error; err != nil {
|
|
||||||
return fmt.Errorf("failed to update {{ENTITY_LOWER}}: %w", err)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete deletes a {{ENTITY}} by ID
|
|
||||||
func (r *{{REPOSITORY_NAME}}Repository) Delete(
|
|
||||||
ctx context.Context,
|
|
||||||
id uuid.UUID,
|
|
||||||
) error {
|
|
||||||
if err := r.db.WithContext(ctx).
|
|
||||||
Delete(&models.{{ENTITY}}{}, "id = ?", id).Error; err != nil {
|
|
||||||
return fmt.Errorf("failed to delete {{ENTITY_LOWER}}: %w", err)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,90 +0,0 @@
|
||||||
package services
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"veza-backend-api/internal/types"
|
|
||||||
"veza-backend-api/internal/models"
|
|
||||||
)
|
|
||||||
|
|
||||||
// {{SERVICE_NAME}}Service provides business logic for {{DOMAIN}}
|
|
||||||
type {{SERVICE_NAME}}Service struct {
|
|
||||||
repo types.{{REPOSITORY_INTERFACE}}
|
|
||||||
logger types.Logger
|
|
||||||
}
|
|
||||||
|
|
||||||
// New{{SERVICE_NAME}}Service creates a new {{SERVICE_NAME}}Service instance
|
|
||||||
func New{{SERVICE_NAME}}Service(
|
|
||||||
repo types.{{REPOSITORY_INTERFACE}},
|
|
||||||
logger types.Logger,
|
|
||||||
) *{{SERVICE_NAME}}Service {
|
|
||||||
return &{{SERVICE_NAME}}Service{
|
|
||||||
repo: repo,
|
|
||||||
logger: logger,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create{{ENTITY}} creates a new {{ENTITY}}
|
|
||||||
func (s *{{SERVICE_NAME}}Service) Create{{ENTITY}}(
|
|
||||||
ctx context.Context,
|
|
||||||
req *Create{{ENTITY}}Request,
|
|
||||||
) (*models.{{ENTITY}}, error) {
|
|
||||||
// Validation
|
|
||||||
if err := s.validateCreateRequest(req); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Business logic
|
|
||||||
{{ENTITY_LOWER}} := &models.{{ENTITY}}{
|
|
||||||
// TODO: Map request fields to model
|
|
||||||
}
|
|
||||||
|
|
||||||
// Persistence
|
|
||||||
if err := s.repo.Create(ctx, {{ENTITY_LOWER}}); err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to create {{ENTITY_LOWER}}: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
s.logger.Info("{{ENTITY_LOWER}} created", "id", {{ENTITY_LOWER}}.ID)
|
|
||||||
|
|
||||||
return {{ENTITY_LOWER}}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get{{ENTITY}}ByID retrieves a {{ENTITY}} by ID
|
|
||||||
func (s *{{SERVICE_NAME}}Service) Get{{ENTITY}}ByID(
|
|
||||||
ctx context.Context,
|
|
||||||
id uuid.UUID,
|
|
||||||
) (*models.{{ENTITY}}, error) {
|
|
||||||
{{ENTITY_LOWER}}, err := s.repo.FindByID(ctx, id)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to get {{ENTITY_LOWER}}: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return {{ENTITY_LOWER}}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// validateCreateRequest validates the create request
|
|
||||||
func (s *{{SERVICE_NAME}}Service) validateCreateRequest(req *Create{{ENTITY}}Request) error {
|
|
||||||
// TODO: Add validation logic
|
|
||||||
if req == nil {
|
|
||||||
return types.ErrValidation("request is required")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Example validation
|
|
||||||
// if req.Field == "" {
|
|
||||||
// return types.ErrValidation("field is required")
|
|
||||||
// }
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create{{ENTITY}}Request represents a request to create a {{ENTITY}}
|
|
||||||
type Create{{ENTITY}}Request struct {
|
|
||||||
// TODO: Add request fields
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,69 +0,0 @@
|
||||||
import type { {{ENTITY}} } from '@/types';
|
|
||||||
import { use{{ENTITY}} } from '@/hooks/use{{ENTITY}}';
|
|
||||||
import { Spinner } from '@/components/ui/Spinner';
|
|
||||||
import { ErrorMessage } from '@/components/ui/ErrorMessage';
|
|
||||||
import { cn } from '@/lib/utils';
|
|
||||||
|
|
||||||
interface {{COMPONENT_NAME}}Props {
|
|
||||||
{{ENTITY_LOWER}}Id: string;
|
|
||||||
className?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {{COMPONENT_NAME}} component
|
|
||||||
*
|
|
||||||
* @description Displays {{ENTITY_LOWER}} information
|
|
||||||
* @example
|
|
||||||
* ```tsx
|
|
||||||
* <{{COMPONENT_NAME}} {{ENTITY_LOWER}}Id="123" />
|
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
export const {{COMPONENT_NAME}}: React.FC<{{COMPONENT_NAME}}Props> = ({
|
|
||||||
{{ENTITY_LOWER}}Id,
|
|
||||||
className,
|
|
||||||
}) => {
|
|
||||||
// Custom hook handles business logic
|
|
||||||
const { data: {{ENTITY_LOWER}}, isLoading, error } = use{{ENTITY}}({{ENTITY_LOWER}}Id);
|
|
||||||
|
|
||||||
// Loading state
|
|
||||||
if (isLoading) {
|
|
||||||
return (
|
|
||||||
<div className={cn('flex items-center justify-center p-4', className)}>
|
|
||||||
<Spinner />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Error state
|
|
||||||
if (error) {
|
|
||||||
return (
|
|
||||||
<div className={cn('p-4', className)}>
|
|
||||||
<ErrorMessage error={error} />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Not found state
|
|
||||||
if (!{{ENTITY_LOWER}}) {
|
|
||||||
return (
|
|
||||||
<div className={cn('p-4', className)}>
|
|
||||||
<p>{{ENTITY}} not found</p>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Success state - render component
|
|
||||||
return (
|
|
||||||
<div className={cn('p-4', className)}>
|
|
||||||
{/* TODO: Add component content */}
|
|
||||||
<h2>{/* {{ENTITY_LOWER}}.field */}</h2>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,95 +0,0 @@
|
||||||
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
|
||||||
import { {{ENTITY_LOWER}}Service } from '@/services/{{ENTITY_LOWER}}';
|
|
||||||
import type { {{ENTITY}}, Create{{ENTITY}}Request } from '@/types';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Hook to fetch a {{ENTITY_LOWER}} by ID
|
|
||||||
*
|
|
||||||
* @param {{ENTITY_LOWER}}Id - The ID of the {{ENTITY_LOWER}} to fetch
|
|
||||||
* @returns Query result with {{ENTITY_LOWER}} data
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* ```tsx
|
|
||||||
* const { data: {{ENTITY_LOWER}}, isLoading, error } = use{{ENTITY}}('123');
|
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
export function use{{ENTITY}}({{ENTITY_LOWER}}Id: string) {
|
|
||||||
return useQuery({
|
|
||||||
queryKey: ['{{ENTITY_LOWER}}', {{ENTITY_LOWER}}Id],
|
|
||||||
queryFn: () => {{ENTITY_LOWER}}Service.get{{ENTITY}}({{ENTITY_LOWER}}Id),
|
|
||||||
enabled: !!{{ENTITY_LOWER}}Id,
|
|
||||||
staleTime: 5 * 60 * 1000, // 5 minutes
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Hook to create a new {{ENTITY_LOWER}}
|
|
||||||
*
|
|
||||||
* @returns Mutation function to create {{ENTITY_LOWER}}
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* ```tsx
|
|
||||||
* const create{{ENTITY}} = useCreate{{ENTITY}}();
|
|
||||||
*
|
|
||||||
* const handleCreate = async () => {
|
|
||||||
* await create{{ENTITY}}.mutateAsync({
|
|
||||||
* // ... request data
|
|
||||||
* });
|
|
||||||
* };
|
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
export function useCreate{{ENTITY}}() {
|
|
||||||
const queryClient = useQueryClient();
|
|
||||||
|
|
||||||
return useMutation({
|
|
||||||
mutationFn: (request: Create{{ENTITY}}Request) =>
|
|
||||||
{{ENTITY_LOWER}}Service.create{{ENTITY}}(request),
|
|
||||||
onSuccess: () => {
|
|
||||||
// Invalidate and refetch {{ENTITY_LOWER}} list
|
|
||||||
queryClient.invalidateQueries({ queryKey: ['{{ENTITY_LOWER}}s'] });
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Hook to update a {{ENTITY_LOWER}}
|
|
||||||
*
|
|
||||||
* @returns Mutation function to update {{ENTITY_LOWER}}
|
|
||||||
*/
|
|
||||||
export function useUpdate{{ENTITY}}() {
|
|
||||||
const queryClient = useQueryClient();
|
|
||||||
|
|
||||||
return useMutation({
|
|
||||||
mutationFn: ({ id, data }: { id: string; data: Partial<{{ENTITY}}> }) =>
|
|
||||||
{{ENTITY_LOWER}}Service.update{{ENTITY}}(id, data),
|
|
||||||
onSuccess: (_, variables) => {
|
|
||||||
// Invalidate specific {{ENTITY_LOWER}} and list
|
|
||||||
queryClient.invalidateQueries({ queryKey: ['{{ENTITY_LOWER}}', variables.id] });
|
|
||||||
queryClient.invalidateQueries({ queryKey: ['{{ENTITY_LOWER}}s'] });
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Hook to delete a {{ENTITY_LOWER}}
|
|
||||||
*
|
|
||||||
* @returns Mutation function to delete {{ENTITY_LOWER}}
|
|
||||||
*/
|
|
||||||
export function useDelete{{ENTITY}}() {
|
|
||||||
const queryClient = useQueryClient();
|
|
||||||
|
|
||||||
return useMutation({
|
|
||||||
mutationFn: (id: string) => {{ENTITY_LOWER}}Service.delete{{ENTITY}}(id),
|
|
||||||
onSuccess: () => {
|
|
||||||
// Invalidate {{ENTITY_LOWER}} list
|
|
||||||
queryClient.invalidateQueries({ queryKey: ['{{ENTITY_LOWER}}s'] });
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,106 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"time"
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"go.uber.org/zap"
|
|
||||||
)
|
|
||||||
|
|
||||||
// {{.ServiceName}}Service gère les fonctionnalités de {{.ServiceName}}
|
|
||||||
type {{.ServiceName}}Service struct {
|
|
||||||
logger *zap.Logger
|
|
||||||
// Ajoutez vos dépendances ici
|
|
||||||
}
|
|
||||||
|
|
||||||
// New{{.ServiceName}}Service crée une nouvelle instance du service
|
|
||||||
func New{{.ServiceName}}Service(logger *zap.Logger) *{{.ServiceName}}Service {
|
|
||||||
return &{{.ServiceName}}Service{
|
|
||||||
logger: logger,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Exemple de méthode - remplacez par vos méthodes
|
|
||||||
func (s *{{.ServiceName}}Service) Process{{.ServiceName}}(ctx context.Context, input string) (string, error) {
|
|
||||||
s.logger.Info("Processing {{.ServiceName}}", zap.String("input", input))
|
|
||||||
|
|
||||||
// Implémentation de votre logique métier
|
|
||||||
result := fmt.Sprintf("Processed: %s", input)
|
|
||||||
|
|
||||||
s.logger.Info("{{.ServiceName}} processed successfully", zap.String("result", result))
|
|
||||||
return result, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Health check pour le service
|
|
||||||
func (s *{{.ServiceName}}Service) HealthCheck() error {
|
|
||||||
s.logger.Debug("{{.ServiceName}} health check")
|
|
||||||
// Implémentation du health check
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// {{.ServiceName}}Handler gère les endpoints HTTP pour {{.ServiceName}}
|
|
||||||
type {{.ServiceName}}Handler struct {
|
|
||||||
service *{{.ServiceName}}Service
|
|
||||||
logger *zap.Logger
|
|
||||||
}
|
|
||||||
|
|
||||||
// New{{.ServiceName}}Handler crée un nouveau handler
|
|
||||||
func New{{.ServiceName}}Handler(service *{{.ServiceName}}Service, logger *zap.Logger) *{{.ServiceName}}Handler {
|
|
||||||
return &{{.ServiceName}}Handler{
|
|
||||||
service: service,
|
|
||||||
logger: logger,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetupRoutes configure les routes pour ce service
|
|
||||||
func (h *{{.ServiceName}}Handler) SetupRoutes(r *gin.RouterGroup) {
|
|
||||||
r.GET("/{{.ServiceName}}", h.Get{{.ServiceName}})
|
|
||||||
r.POST("/{{.ServiceName}}", h.Create{{.ServiceName}})
|
|
||||||
r.PUT("/{{.ServiceName}}/:id", h.Update{{.ServiceName}})
|
|
||||||
r.DELETE("/{{.ServiceName}}/:id", h.Delete{{.ServiceName}})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get{{.ServiceName}} récupère les données de {{.ServiceName}}
|
|
||||||
func (h *{{.ServiceName}}Handler) Get{{.ServiceName}}(c *gin.Context) {
|
|
||||||
h.logger.Info("Get {{.ServiceName}} request")
|
|
||||||
|
|
||||||
// Implémentation
|
|
||||||
c.JSON(200, gin.H{
|
|
||||||
"message": "Get {{.ServiceName}} endpoint",
|
|
||||||
"timestamp": time.Now(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create{{.ServiceName}} crée une nouvelle entrée
|
|
||||||
func (h *{{.ServiceName}}Handler) Create{{.ServiceName}}(c *gin.Context) {
|
|
||||||
h.logger.Info("Create {{.ServiceName}} request")
|
|
||||||
|
|
||||||
// Implémentation
|
|
||||||
c.JSON(201, gin.H{
|
|
||||||
"message": "Create {{.ServiceName}} endpoint",
|
|
||||||
"timestamp": time.Now(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update{{.ServiceName}} met à jour une entrée existante
|
|
||||||
func (h *{{.ServiceName}}Handler) Update{{.ServiceName}}(c *gin.Context) {
|
|
||||||
h.logger.Info("Update {{.ServiceName}} request")
|
|
||||||
|
|
||||||
// Implémentation
|
|
||||||
c.JSON(200, gin.H{
|
|
||||||
"message": "Update {{.ServiceName}} endpoint",
|
|
||||||
"timestamp": time.Now(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete{{.ServiceName}} supprime une entrée
|
|
||||||
func (h *{{.ServiceName}}Handler) Delete{{.ServiceName}}(c *gin.Context) {
|
|
||||||
h.logger.Info("Delete {{.ServiceName}} request")
|
|
||||||
|
|
||||||
// Implémentation
|
|
||||||
c.JSON(200, gin.H{
|
|
||||||
"message": "Delete {{.ServiceName}} endpoint",
|
|
||||||
"timestamp": time.Now(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
@ -1,91 +0,0 @@
|
||||||
use anyhow::{Result, Context};
|
|
||||||
use sqlx::PgPool;
|
|
||||||
use uuid::Uuid;
|
|
||||||
|
|
||||||
/// {{SERVICE_NAME}}Service provides business logic for {{DOMAIN}}
|
|
||||||
pub struct {{SERVICE_NAME}}Service {
|
|
||||||
pool: PgPool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl {{SERVICE_NAME}}Service {
|
|
||||||
/// Creates a new {{SERVICE_NAME}}Service instance
|
|
||||||
pub fn new(pool: PgPool) -> Self {
|
|
||||||
Self { pool }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates a new {{ENTITY}}
|
|
||||||
pub async fn create_{{ENTITY_LOWER}}(
|
|
||||||
&self,
|
|
||||||
request: Create{{ENTITY}}Request,
|
|
||||||
) -> Result<{{ENTITY}}> {
|
|
||||||
// Validation
|
|
||||||
request.validate()?;
|
|
||||||
|
|
||||||
// Business logic
|
|
||||||
let {{ENTITY_LOWER}} = sqlx::query_as!(
|
|
||||||
{{ENTITY}},
|
|
||||||
r#"
|
|
||||||
INSERT INTO {{TABLE_NAME}} (id, /* TODO: add fields */)
|
|
||||||
VALUES ($1, /* TODO: add values */)
|
|
||||||
RETURNING id, /* TODO: add fields */
|
|
||||||
"#,
|
|
||||||
Uuid::new_v4(),
|
|
||||||
// TODO: add request fields
|
|
||||||
)
|
|
||||||
.fetch_one(&self.pool)
|
|
||||||
.await
|
|
||||||
.context("Failed to create {{ENTITY_LOWER}}")?;
|
|
||||||
|
|
||||||
Ok({{ENTITY_LOWER}})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Gets a {{ENTITY}} by ID
|
|
||||||
pub async fn get_{{ENTITY_LOWER}}_by_id(
|
|
||||||
&self,
|
|
||||||
id: Uuid,
|
|
||||||
) -> Result<{{ENTITY}}> {
|
|
||||||
let {{ENTITY_LOWER}} = sqlx::query_as!(
|
|
||||||
{{ENTITY}},
|
|
||||||
r#"
|
|
||||||
SELECT id, /* TODO: add fields */
|
|
||||||
FROM {{TABLE_NAME}}
|
|
||||||
WHERE id = $1
|
|
||||||
"#,
|
|
||||||
id
|
|
||||||
)
|
|
||||||
.fetch_optional(&self.pool)
|
|
||||||
.await
|
|
||||||
.context("Failed to fetch {{ENTITY_LOWER}}")?
|
|
||||||
.ok_or_else(|| anyhow::anyhow!("{{ENTITY}} not found"))?;
|
|
||||||
|
|
||||||
Ok({{ENTITY_LOWER}})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Request to create a {{ENTITY}}
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct Create{{ENTITY}}Request {
|
|
||||||
// TODO: Add request fields
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Create{{ENTITY}}Request {
|
|
||||||
/// Validates the request
|
|
||||||
pub fn validate(&self) -> Result<()> {
|
|
||||||
// TODO: Add validation logic
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// {{ENTITY}} model
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct {{ENTITY}} {
|
|
||||||
pub id: Uuid,
|
|
||||||
// TODO: Add entity fields
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,190 +0,0 @@
|
||||||
use std::collections::HashMap;
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use tokio::sync::RwLock;
|
|
||||||
use tracing::{info, warn, error, debug};
|
|
||||||
use uuid::Uuid;
|
|
||||||
|
|
||||||
/// {{.ServiceName}}Service gère les fonctionnalités de {{.ServiceName}}
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct {{.ServiceName}}Service {
|
|
||||||
// Ajoutez vos dépendances ici
|
|
||||||
data: Arc<RwLock<HashMap<String, {{.ServiceName}}Data>>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Données pour {{.ServiceName}}
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
||||||
pub struct {{.ServiceName}}Data {
|
|
||||||
pub id: String,
|
|
||||||
pub name: String,
|
|
||||||
pub created_at: chrono::DateTime<chrono::Utc>,
|
|
||||||
pub updated_at: chrono::DateTime<chrono::Utc>,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Erreurs pour {{.ServiceName}}
|
|
||||||
#[derive(Debug, thiserror::Error)]
|
|
||||||
pub enum {{.ServiceName}}Error {
|
|
||||||
#[error("{{.ServiceName}} not found")]
|
|
||||||
NotFound,
|
|
||||||
|
|
||||||
#[error("Invalid input: {0}")]
|
|
||||||
InvalidInput(String),
|
|
||||||
|
|
||||||
#[error("Database error: {0}")]
|
|
||||||
DatabaseError(String),
|
|
||||||
|
|
||||||
#[error("Internal error: {0}")]
|
|
||||||
InternalError(String),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl {{.ServiceName}}Service {
|
|
||||||
/// Crée une nouvelle instance du service
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
data: Arc::new(RwLock::new(HashMap::new())),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Traite les données de {{.ServiceName}}
|
|
||||||
pub async fn process_{{.ServiceName}}(&self, input: String) -> Result<String, {{.ServiceName}}Error> {
|
|
||||||
info!("Processing {{.ServiceName}} with input: {}", input);
|
|
||||||
|
|
||||||
// Implémentation de votre logique métier
|
|
||||||
let result = format!("Processed: {}", input);
|
|
||||||
|
|
||||||
info!("{{.ServiceName}} processed successfully: {}", result);
|
|
||||||
Ok(result)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Crée une nouvelle entrée
|
|
||||||
pub async fn create(&self, name: String) -> Result<{{.ServiceName}}Data, {{.ServiceName}}Error> {
|
|
||||||
info!("Creating {{.ServiceName}} with name: {}", name);
|
|
||||||
|
|
||||||
let id = Uuid::new_v4().to_string();
|
|
||||||
let now = chrono::Utc::now();
|
|
||||||
|
|
||||||
let data = {{.ServiceName}}Data {
|
|
||||||
id: id.clone(),
|
|
||||||
name,
|
|
||||||
created_at: now,
|
|
||||||
updated_at: now,
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut store = self.data.write().await;
|
|
||||||
store.insert(id, data.clone());
|
|
||||||
|
|
||||||
info!("{{.ServiceName}} created successfully: {}", data.id);
|
|
||||||
Ok(data)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Récupère une entrée par ID
|
|
||||||
pub async fn get_by_id(&self, id: &str) -> Result<{{.ServiceName}}Data, {{.ServiceName}}Error> {
|
|
||||||
debug!("Getting {{.ServiceName}} by ID: {}", id);
|
|
||||||
|
|
||||||
let store = self.data.read().await;
|
|
||||||
store.get(id)
|
|
||||||
.cloned()
|
|
||||||
.ok_or({{.ServiceName}}Error::NotFound)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Met à jour une entrée existante
|
|
||||||
pub async fn update(&self, id: &str, name: String) -> Result<{{.ServiceName}}Data, {{.ServiceName}}Error> {
|
|
||||||
info!("Updating {{.ServiceName}} with ID: {}", id);
|
|
||||||
|
|
||||||
let mut store = self.data.write().await;
|
|
||||||
if let Some(data) = store.get_mut(id) {
|
|
||||||
data.name = name;
|
|
||||||
data.updated_at = chrono::Utc::now();
|
|
||||||
info!("{{.ServiceName}} updated successfully: {}", id);
|
|
||||||
Ok(data.clone())
|
|
||||||
} else {
|
|
||||||
Err({{.ServiceName}}Error::NotFound)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Supprime une entrée
|
|
||||||
pub async fn delete(&self, id: &str) -> Result<(), {{.ServiceName}}Error> {
|
|
||||||
info!("Deleting {{.ServiceName}} with ID: {}", id);
|
|
||||||
|
|
||||||
let mut store = self.data.write().await;
|
|
||||||
if store.remove(id).is_some() {
|
|
||||||
info!("{{.ServiceName}} deleted successfully: {}", id);
|
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
Err({{.ServiceName}}Error::NotFound)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Liste toutes les entrées
|
|
||||||
pub async fn list_all(&self) -> Result<Vec<{{.ServiceName}}Data>, {{.ServiceName}}Error> {
|
|
||||||
debug!("Listing all {{.ServiceName}} entries");
|
|
||||||
|
|
||||||
let store = self.data.read().await;
|
|
||||||
Ok(store.values().cloned().collect())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Health check pour le service
|
|
||||||
pub async fn health_check(&self) -> Result<(), {{.ServiceName}}Error> {
|
|
||||||
debug!("{{.ServiceName}} health check");
|
|
||||||
// Implémentation du health check
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[tokio::test]
|
|
||||||
async fn test_create_{{.ServiceName}}() {
|
|
||||||
let service = {{.ServiceName}}Service::new();
|
|
||||||
let result = service.create("Test {{.ServiceName}}".to_string()).await;
|
|
||||||
|
|
||||||
assert!(result.is_ok());
|
|
||||||
let data = result.unwrap();
|
|
||||||
assert_eq!(data.name, "Test {{.ServiceName}}");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tokio::test]
|
|
||||||
async fn test_get_{{.ServiceName}}_by_id() {
|
|
||||||
let service = {{.ServiceName}}Service::new();
|
|
||||||
let created = service.create("Test {{.ServiceName}}".to_string()).await.unwrap();
|
|
||||||
|
|
||||||
let result = service.get_by_id(&created.id).await;
|
|
||||||
assert!(result.is_ok());
|
|
||||||
|
|
||||||
let data = result.unwrap();
|
|
||||||
assert_eq!(data.id, created.id);
|
|
||||||
assert_eq!(data.name, "Test {{.ServiceName}}");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tokio::test]
|
|
||||||
async fn test_update_{{.ServiceName}}() {
|
|
||||||
let service = {{.ServiceName}}Service::new();
|
|
||||||
let created = service.create("Test {{.ServiceName}}".to_string()).await.unwrap();
|
|
||||||
|
|
||||||
let result = service.update(&created.id, "Updated {{.ServiceName}}".to_string()).await;
|
|
||||||
assert!(result.is_ok());
|
|
||||||
|
|
||||||
let updated = result.unwrap();
|
|
||||||
assert_eq!(updated.name, "Updated {{.ServiceName}}");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tokio::test]
|
|
||||||
async fn test_delete_{{.ServiceName}}() {
|
|
||||||
let service = {{.ServiceName}}Service::new();
|
|
||||||
let created = service.create("Test {{.ServiceName}}".to_string()).await.unwrap();
|
|
||||||
|
|
||||||
let result = service.delete(&created.id).await;
|
|
||||||
assert!(result.is_ok());
|
|
||||||
|
|
||||||
let get_result = service.get_by_id(&created.id).await;
|
|
||||||
assert!(get_result.is_err());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tokio::test]
|
|
||||||
async fn test_health_check() {
|
|
||||||
let service = {{.ServiceName}}Service::new();
|
|
||||||
let result = service.health_check().await;
|
|
||||||
assert!(result.is_ok());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,789 +0,0 @@
|
||||||
//go:build ignore
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
// TODO: Réactiver api_manager.go après stabilisation du noyau et alignement des services (graphql, grpc, websocket, features)
|
|
||||||
|
|
||||||
package api
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
|
|
||||||
"veza-backend-api/internal/api/graphql"
|
|
||||||
"veza-backend-api/internal/api/grpc"
|
|
||||||
"veza-backend-api/internal/api/websocket"
|
|
||||||
"veza-backend-api/internal/config"
|
|
||||||
"veza-backend-api/internal/database"
|
|
||||||
"veza-backend-api/internal/features"
|
|
||||||
"veza-backend-api/internal/middleware"
|
|
||||||
)
|
|
||||||
|
|
||||||
// APIManager manages all API protocols (REST, GraphQL, gRPC, WebSocket)
|
|
||||||
type APIManager struct {
|
|
||||||
config *config.Config
|
|
||||||
db *database.DB
|
|
||||||
|
|
||||||
// API Servers
|
|
||||||
restRouter *gin.Engine
|
|
||||||
graphqlServer *graphql.GraphQLServer
|
|
||||||
grpcServer *grpc.GRPCServer
|
|
||||||
websocketManager *websocket.WebSocketManager
|
|
||||||
|
|
||||||
// Feature integration
|
|
||||||
featureManager *features.FeatureManager
|
|
||||||
|
|
||||||
// HTTP Server
|
|
||||||
httpServer *http.Server
|
|
||||||
|
|
||||||
isRunning bool
|
|
||||||
mu sync.RWMutex
|
|
||||||
}
|
|
||||||
|
|
||||||
// APIConfig contains configuration for all API protocols
|
|
||||||
type APIConfig struct {
|
|
||||||
REST RESTConfig `yaml:"rest"`
|
|
||||||
GraphQL graphql.GraphQLConfig `yaml:"graphql"`
|
|
||||||
GRPC grpc.GRPCConfig `yaml:"grpc"`
|
|
||||||
WebSocket websocket.WebSocketConfig `yaml:"websocket"`
|
|
||||||
Global GlobalAPIConfig `yaml:"global"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// RESTConfig contains REST API configuration
|
|
||||||
type RESTConfig struct {
|
|
||||||
Enabled bool `yaml:"enabled"`
|
|
||||||
Host string `yaml:"host"`
|
|
||||||
Port int `yaml:"port"`
|
|
||||||
Mode string `yaml:"mode"` // debug, release, test
|
|
||||||
TrustedProxies []string `yaml:"trusted_proxies"`
|
|
||||||
MaxMultipartMemory int64 `yaml:"max_multipart_memory"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// GlobalAPIConfig contains global API settings
|
|
||||||
type GlobalAPIConfig struct {
|
|
||||||
Timeout time.Duration `yaml:"timeout"`
|
|
||||||
ReadTimeout time.Duration `yaml:"read_timeout"`
|
|
||||||
WriteTimeout time.Duration `yaml:"write_timeout"`
|
|
||||||
IdleTimeout time.Duration `yaml:"idle_timeout"`
|
|
||||||
ShutdownTimeout time.Duration `yaml:"shutdown_timeout"`
|
|
||||||
CORS CORSConfig `yaml:"cors"`
|
|
||||||
RateLimit RateLimitConfig `yaml:"rate_limit"`
|
|
||||||
Security SecurityConfig `yaml:"security"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// CORSConfig contains CORS configuration
|
|
||||||
type CORSConfig struct {
|
|
||||||
Enabled bool `yaml:"enabled"`
|
|
||||||
AllowOrigins []string `yaml:"allow_origins"`
|
|
||||||
AllowMethods []string `yaml:"allow_methods"`
|
|
||||||
AllowHeaders []string `yaml:"allow_headers"`
|
|
||||||
ExposeHeaders []string `yaml:"expose_headers"`
|
|
||||||
AllowCredentials bool `yaml:"allow_credentials"`
|
|
||||||
MaxAge int `yaml:"max_age"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// RateLimitConfig contains rate limiting configuration
|
|
||||||
type RateLimitConfig struct {
|
|
||||||
Enabled bool `yaml:"enabled"`
|
|
||||||
RPS int `yaml:"rps"`
|
|
||||||
Burst int `yaml:"burst"`
|
|
||||||
Window time.Duration `yaml:"window"`
|
|
||||||
KeyFunc string `yaml:"key_func"` // ip, user, api_key
|
|
||||||
SkipPaths []string `yaml:"skip_paths"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// SecurityConfig contains security configuration
|
|
||||||
type SecurityConfig struct {
|
|
||||||
Enabled bool `yaml:"enabled"`
|
|
||||||
JWTSecret string `yaml:"jwt_secret"`
|
|
||||||
APIKeyHeader string `yaml:"api_key_header"`
|
|
||||||
AllowedUserAgents []string `yaml:"allowed_user_agents"`
|
|
||||||
CSRFProtection bool `yaml:"csrf_protection"`
|
|
||||||
HTTPSOnly bool `yaml:"https_only"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewAPIManager creates a new API manager instance
|
|
||||||
func NewAPIManager(config *config.Config, db *database.DB, featureManager *features.FeatureManager) *APIManager {
|
|
||||||
return &APIManager{
|
|
||||||
config: config,
|
|
||||||
db: db,
|
|
||||||
featureManager: featureManager,
|
|
||||||
isRunning: false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize sets up all API protocols
|
|
||||||
func (am *APIManager) Initialize(apiConfig APIConfig) error {
|
|
||||||
am.mu.Lock()
|
|
||||||
defer am.mu.Unlock()
|
|
||||||
|
|
||||||
// Initialize REST API (Gin)
|
|
||||||
if err := am.initializeREST(apiConfig.REST, apiConfig.Global); err != nil {
|
|
||||||
return fmt.Errorf("failed to initialize REST API: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize GraphQL server
|
|
||||||
if apiConfig.GraphQL.Enabled {
|
|
||||||
if err := am.initializeGraphQL(apiConfig.GraphQL); err != nil {
|
|
||||||
return fmt.Errorf("failed to initialize GraphQL: %w", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize gRPC server
|
|
||||||
if apiConfig.GRPC.Enabled {
|
|
||||||
if err := am.initializeGRPC(apiConfig.GRPC); err != nil {
|
|
||||||
return fmt.Errorf("failed to initialize gRPC: %w", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize WebSocket manager
|
|
||||||
if apiConfig.WebSocket.Enabled {
|
|
||||||
if err := am.initializeWebSocket(apiConfig.WebSocket); err != nil {
|
|
||||||
return fmt.Errorf("failed to initialize WebSocket: %w", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Setup HTTP server
|
|
||||||
am.setupHTTPServer(apiConfig)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// initializeREST sets up the REST API with Gin
|
|
||||||
func (am *APIManager) initializeREST(restConfig RESTConfig, globalConfig GlobalAPIConfig) error {
|
|
||||||
if !restConfig.Enabled {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set Gin mode
|
|
||||||
gin.SetMode(restConfig.Mode)
|
|
||||||
|
|
||||||
// Create Gin engine
|
|
||||||
am.restRouter = gin.New()
|
|
||||||
|
|
||||||
// Setup global middleware
|
|
||||||
am.setupGlobalMiddleware(globalConfig)
|
|
||||||
|
|
||||||
// Setup existing REST routes (from router.go)
|
|
||||||
am.setupExistingRESTRoutes()
|
|
||||||
|
|
||||||
// Setup feature-specific routes
|
|
||||||
am.setupFeatureRoutes()
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// initializeGraphQL sets up the GraphQL server
|
|
||||||
func (am *APIManager) initializeGraphQL(graphqlConfig graphql.GraphQLConfig) error {
|
|
||||||
am.graphqlServer = graphql.NewGraphQLServer(am.config, am.db, nil) // logger would be added
|
|
||||||
am.graphqlServer.Configure(graphqlConfig)
|
|
||||||
am.graphqlServer.SetupRoutes(am.restRouter, graphqlConfig)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// initializeGRPC sets up the gRPC server
|
|
||||||
func (am *APIManager) initializeGRPC(grpcConfig grpc.GRPCConfig) error {
|
|
||||||
am.grpcServer = grpc.NewGRPCServer(am.config, am.db)
|
|
||||||
return am.grpcServer.Initialize(grpcConfig)
|
|
||||||
}
|
|
||||||
|
|
||||||
// initializeWebSocket sets up the WebSocket manager
|
|
||||||
func (am *APIManager) initializeWebSocket(wsConfig websocket.WebSocketConfig) error {
|
|
||||||
am.websocketManager = websocket.NewWebSocketManager(am.config, am.db)
|
|
||||||
if err := am.websocketManager.Initialize(wsConfig); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
am.websocketManager.SetupRoutes(am.restRouter, wsConfig)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// setupGlobalMiddleware configures global middleware for REST API
|
|
||||||
func (am *APIManager) setupGlobalMiddleware(globalConfig GlobalAPIConfig) {
|
|
||||||
// Recovery middleware
|
|
||||||
am.restRouter.Use(gin.Recovery())
|
|
||||||
|
|
||||||
// FIX #7: Logger middleware dupliqué supprimé
|
|
||||||
// Le middleware.Logger() non structuré a été supprimé
|
|
||||||
// Utiliser RequestLogger() à la place si ce fichier est réactivé
|
|
||||||
// Note: Ce fichier est actuellement ignoré (//go:build ignore)
|
|
||||||
// am.restRouter.Use(middleware.RequestLogger(logger))
|
|
||||||
|
|
||||||
// CORS middleware
|
|
||||||
if globalConfig.CORS.Enabled {
|
|
||||||
am.restRouter.Use(middleware.CORS())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Rate limiting middleware
|
|
||||||
if globalConfig.RateLimit.Enabled {
|
|
||||||
am.restRouter.Use(middleware.RateLimiter(globalConfig.RateLimit.RPS, globalConfig.RateLimit.Window))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Security middleware
|
|
||||||
if globalConfig.Security.Enabled {
|
|
||||||
am.restRouter.Use(middleware.Security())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Request ID middleware
|
|
||||||
am.restRouter.Use(middleware.RequestID())
|
|
||||||
|
|
||||||
// Timeout middleware
|
|
||||||
am.restRouter.Use(middleware.Timeout(globalConfig.Timeout))
|
|
||||||
}
|
|
||||||
|
|
||||||
// setupExistingRESTRoutes sets up the existing REST routes
|
|
||||||
func (am *APIManager) setupExistingRESTRoutes() {
|
|
||||||
// Use the existing APIRouter setup
|
|
||||||
SetupRoutes(am.restRouter, am.db, am.config)
|
|
||||||
}
|
|
||||||
|
|
||||||
// setupFeatureRoutes sets up feature-specific API routes
|
|
||||||
func (am *APIManager) setupFeatureRoutes() {
|
|
||||||
if am.featureManager == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// API v2 group for new feature-based endpoints
|
|
||||||
v2 := am.restRouter.Group("/api/v2")
|
|
||||||
{
|
|
||||||
// User domain features
|
|
||||||
am.setupUserDomainRoutes(v2)
|
|
||||||
|
|
||||||
// Communication domain features
|
|
||||||
am.setupCommunicationDomainRoutes(v2)
|
|
||||||
|
|
||||||
// Media domain features
|
|
||||||
am.setupMediaDomainRoutes(v2)
|
|
||||||
|
|
||||||
// AI domain features
|
|
||||||
am.setupAIDomainRoutes(v2)
|
|
||||||
|
|
||||||
// Analytics domain features
|
|
||||||
am.setupAnalyticsDomainRoutes(v2)
|
|
||||||
|
|
||||||
// Integration domain features
|
|
||||||
am.setupIntegrationDomainRoutes(v2)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Feature management endpoints
|
|
||||||
admin := am.restRouter.Group("/api/admin")
|
|
||||||
{
|
|
||||||
admin.GET("/features", am.handleGetFeatures)
|
|
||||||
admin.GET("/features/:id", am.handleGetFeature)
|
|
||||||
admin.POST("/features/:id/start", am.handleStartFeature)
|
|
||||||
admin.POST("/features/:id/stop", am.handleStopFeature)
|
|
||||||
admin.GET("/features/health", am.handleFeaturesHealth)
|
|
||||||
admin.GET("/features/metrics", am.handleFeaturesMetrics)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// setupUserDomainRoutes sets up user domain feature routes
|
|
||||||
func (am *APIManager) setupUserDomainRoutes(router *gin.RouterGroup) {
|
|
||||||
userGroup := router.Group("/user")
|
|
||||||
{
|
|
||||||
// User Profiles Feature endpoints
|
|
||||||
userGroup.GET("/profiles/:id", am.handleGetUserProfile)
|
|
||||||
userGroup.PUT("/profiles/:id", am.handleUpdateUserProfile)
|
|
||||||
|
|
||||||
// Social Graph Feature endpoints
|
|
||||||
userGroup.POST("/follow/:id", am.handleFollowUser)
|
|
||||||
userGroup.DELETE("/follow/:id", am.handleUnfollowUser)
|
|
||||||
userGroup.GET("/followers/:id", am.handleGetFollowers)
|
|
||||||
userGroup.GET("/following/:id", am.handleGetFollowing)
|
|
||||||
|
|
||||||
// Achievements endpoints
|
|
||||||
userGroup.GET("/achievements/:id", am.handleGetAchievements)
|
|
||||||
userGroup.GET("/leaderboard", am.handleGetLeaderboard)
|
|
||||||
userGroup.POST("/achievements/:id/claim", am.handleClaimAchievement)
|
|
||||||
|
|
||||||
// User Verification Feature endpoints
|
|
||||||
userGroup.POST("/verify", am.handleStartVerification)
|
|
||||||
userGroup.GET("/verify/status", am.handleGetVerificationStatus)
|
|
||||||
userGroup.GET("/trust-score/:id", am.handleGetTrustScore)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// setupCommunicationDomainRoutes sets up communication domain feature routes
|
|
||||||
func (am *APIManager) setupCommunicationDomainRoutes(router *gin.RouterGroup) {
|
|
||||||
commGroup := router.Group("/communication")
|
|
||||||
{
|
|
||||||
// Chat Rooms Feature endpoints
|
|
||||||
commGroup.GET("/rooms", am.handleGetRooms)
|
|
||||||
commGroup.POST("/rooms", am.handleCreateRoom)
|
|
||||||
commGroup.GET("/rooms/:id", am.handleGetRoom)
|
|
||||||
commGroup.POST("/rooms/:id/join", am.handleJoinRoom)
|
|
||||||
commGroup.POST("/rooms/:id/leave", am.handleLeaveRoom)
|
|
||||||
|
|
||||||
// Voice Chat Feature endpoints
|
|
||||||
commGroup.POST("/voice/start", am.handleStartVoiceChat)
|
|
||||||
commGroup.POST("/voice/stop", am.handleStopVoiceChat)
|
|
||||||
commGroup.GET("/voice/status", am.handleGetVoiceStatus)
|
|
||||||
|
|
||||||
// Video Streaming Feature endpoints
|
|
||||||
commGroup.POST("/video/start", am.handleStartVideoStream)
|
|
||||||
commGroup.POST("/video/stop", am.handleStopVideoStream)
|
|
||||||
commGroup.GET("/video/streams", am.handleGetVideoStreams)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// setupMediaDomainRoutes sets up media domain feature routes
|
|
||||||
func (am *APIManager) setupMediaDomainRoutes(router *gin.RouterGroup) {
|
|
||||||
mediaGroup := router.Group("/media")
|
|
||||||
{
|
|
||||||
// Audio Streaming Feature endpoints
|
|
||||||
mediaGroup.POST("/audio/upload", am.handleUploadAudio)
|
|
||||||
mediaGroup.GET("/audio/:id/stream", am.handleStreamAudio)
|
|
||||||
mediaGroup.GET("/audio/:id/metadata", am.handleGetAudioMetadata)
|
|
||||||
|
|
||||||
// Smart Playlists Feature endpoints
|
|
||||||
mediaGroup.GET("/playlists/smart", am.handleGetSmartPlaylists)
|
|
||||||
mediaGroup.POST("/playlists/smart", am.handleCreateSmartPlaylist)
|
|
||||||
mediaGroup.GET("/playlists/smart/:id", am.handleGetSmartPlaylist)
|
|
||||||
|
|
||||||
// Content Discovery Feature endpoints
|
|
||||||
mediaGroup.GET("/discover", am.handleDiscoverContent)
|
|
||||||
mediaGroup.GET("/trending", am.handleGetTrending)
|
|
||||||
mediaGroup.GET("/similar/:id", am.handleGetSimilarContent)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// setupAIDomainRoutes sets up AI domain feature routes
|
|
||||||
func (am *APIManager) setupAIDomainRoutes(router *gin.RouterGroup) {
|
|
||||||
aiGroup := router.Group("/ai")
|
|
||||||
{
|
|
||||||
// Smart Recommendations Feature endpoints
|
|
||||||
aiGroup.GET("/recommendations", am.handleGetRecommendations)
|
|
||||||
aiGroup.POST("/recommendations/feedback", am.handleRecommendationFeedback)
|
|
||||||
|
|
||||||
// Content Moderation Feature endpoints
|
|
||||||
aiGroup.POST("/moderate", am.handleModerateContent)
|
|
||||||
aiGroup.GET("/moderation/history", am.handleGetModerationHistory)
|
|
||||||
|
|
||||||
// Sentiment Analysis Feature endpoints
|
|
||||||
aiGroup.POST("/sentiment", am.handleAnalyzeSentiment)
|
|
||||||
aiGroup.GET("/sentiment/trends", am.handleGetSentimentTrends)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// setupAnalyticsDomainRoutes sets up analytics domain feature routes
|
|
||||||
func (am *APIManager) setupAnalyticsDomainRoutes(router *gin.RouterGroup) {
|
|
||||||
analyticsGroup := router.Group("/analytics")
|
|
||||||
{
|
|
||||||
// Realtime Dashboards Feature endpoints
|
|
||||||
analyticsGroup.GET("/dashboard", am.handleGetDashboard)
|
|
||||||
analyticsGroup.GET("/metrics/realtime", am.handleGetRealtimeMetrics)
|
|
||||||
|
|
||||||
// User Behavior Analytics Feature endpoints
|
|
||||||
analyticsGroup.GET("/behavior/:id", am.handleGetUserBehavior)
|
|
||||||
analyticsGroup.GET("/engagement", am.handleGetEngagementMetrics)
|
|
||||||
|
|
||||||
// Business Analytics Feature endpoints
|
|
||||||
analyticsGroup.GET("/business/revenue", am.handleGetRevenueAnalytics)
|
|
||||||
analyticsGroup.GET("/business/conversion", am.handleGetConversionMetrics)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// setupIntegrationDomainRoutes sets up integration domain feature routes
|
|
||||||
func (am *APIManager) setupIntegrationDomainRoutes(router *gin.RouterGroup) {
|
|
||||||
integrationGroup := router.Group("/integration")
|
|
||||||
{
|
|
||||||
// External API Gateway Feature endpoints
|
|
||||||
integrationGroup.POST("/external/request", am.handleExternalAPIRequest)
|
|
||||||
integrationGroup.GET("/external/status", am.handleGetExternalAPIStatus)
|
|
||||||
|
|
||||||
// Webhook System Feature endpoints
|
|
||||||
integrationGroup.POST("/webhooks", am.handleCreateWebhook)
|
|
||||||
integrationGroup.GET("/webhooks", am.handleGetWebhooks)
|
|
||||||
integrationGroup.DELETE("/webhooks/:id", am.handleDeleteWebhook)
|
|
||||||
|
|
||||||
// Payment Gateways Feature endpoints
|
|
||||||
integrationGroup.POST("/payments/process", am.handleProcessPayment)
|
|
||||||
integrationGroup.GET("/payments/methods", am.handleGetPaymentMethods)
|
|
||||||
integrationGroup.GET("/payments/history", am.handleGetPaymentHistory)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// setupHTTPServer configures the HTTP server
|
|
||||||
func (am *APIManager) setupHTTPServer(apiConfig APIConfig) {
|
|
||||||
addr := fmt.Sprintf("%s:%d", apiConfig.REST.Host, apiConfig.REST.Port)
|
|
||||||
|
|
||||||
am.httpServer = &http.Server{
|
|
||||||
Addr: addr,
|
|
||||||
Handler: am.restRouter,
|
|
||||||
ReadTimeout: apiConfig.Global.ReadTimeout,
|
|
||||||
WriteTimeout: apiConfig.Global.WriteTimeout,
|
|
||||||
IdleTimeout: apiConfig.Global.IdleTimeout,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start starts all API servers
|
|
||||||
func (am *APIManager) Start(ctx context.Context) error {
|
|
||||||
am.mu.Lock()
|
|
||||||
defer am.mu.Unlock()
|
|
||||||
|
|
||||||
if am.isRunning {
|
|
||||||
return fmt.Errorf("API manager is already running")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start gRPC server if enabled
|
|
||||||
if am.grpcServer != nil {
|
|
||||||
if err := am.grpcServer.Start(ctx); err != nil {
|
|
||||||
return fmt.Errorf("failed to start gRPC server: %w", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start WebSocket manager if enabled
|
|
||||||
if am.websocketManager != nil {
|
|
||||||
if err := am.websocketManager.Start(ctx); err != nil {
|
|
||||||
return fmt.Errorf("failed to start WebSocket manager: %w", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start HTTP server (REST + GraphQL)
|
|
||||||
go func() {
|
|
||||||
if err := am.httpServer.ListenAndServe(); err != nil && err != http.ErrServerClosed {
|
|
||||||
// Handle error
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
am.isRunning = true
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stop stops all API servers
|
|
||||||
func (am *APIManager) Stop(ctx context.Context) error {
|
|
||||||
am.mu.Lock()
|
|
||||||
defer am.mu.Unlock()
|
|
||||||
|
|
||||||
if !am.isRunning {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stop HTTP server
|
|
||||||
if am.httpServer != nil {
|
|
||||||
if err := am.httpServer.Shutdown(ctx); err != nil {
|
|
||||||
return fmt.Errorf("failed to stop HTTP server: %w", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stop WebSocket manager
|
|
||||||
if am.websocketManager != nil {
|
|
||||||
if err := am.websocketManager.Stop(ctx); err != nil {
|
|
||||||
return fmt.Errorf("failed to stop WebSocket manager: %w", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stop gRPC server
|
|
||||||
if am.grpcServer != nil {
|
|
||||||
if err := am.grpcServer.Stop(ctx); err != nil {
|
|
||||||
return fmt.Errorf("failed to stop gRPC server: %w", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stop GraphQL server
|
|
||||||
if am.graphqlServer != nil {
|
|
||||||
if err := am.graphqlServer.Shutdown(ctx); err != nil {
|
|
||||||
return fmt.Errorf("failed to stop GraphQL server: %w", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
am.isRunning = false
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsHealthy checks if all API servers are healthy
|
|
||||||
func (am *APIManager) IsHealthy() bool {
|
|
||||||
am.mu.RLock()
|
|
||||||
defer am.mu.RUnlock()
|
|
||||||
|
|
||||||
if !am.isRunning {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check each server's health
|
|
||||||
if am.grpcServer != nil && !am.grpcServer.IsHealthy() {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
if am.websocketManager != nil && !am.websocketManager.IsHealthy() {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
if am.graphqlServer != nil && !am.graphqlServer.IsHealthy() {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetAPIStatus returns comprehensive API status
|
|
||||||
func (am *APIManager) GetAPIStatus() map[string]interface{} {
|
|
||||||
am.mu.RLock()
|
|
||||||
defer am.mu.RUnlock()
|
|
||||||
|
|
||||||
status := map[string]interface{}{
|
|
||||||
"status": "healthy",
|
|
||||||
"running": am.isRunning,
|
|
||||||
"timestamp": time.Now(),
|
|
||||||
"apis": map[string]interface{}{},
|
|
||||||
}
|
|
||||||
|
|
||||||
apis := status["apis"].(map[string]interface{})
|
|
||||||
|
|
||||||
// REST API status
|
|
||||||
apis["rest"] = map[string]interface{}{
|
|
||||||
"enabled": am.restRouter != nil,
|
|
||||||
"status": "healthy",
|
|
||||||
}
|
|
||||||
|
|
||||||
// GraphQL status
|
|
||||||
if am.graphqlServer != nil {
|
|
||||||
apis["graphql"] = am.graphqlServer.GetMetrics()
|
|
||||||
} else {
|
|
||||||
apis["graphql"] = map[string]interface{}{"enabled": false}
|
|
||||||
}
|
|
||||||
|
|
||||||
// gRPC status
|
|
||||||
if am.grpcServer != nil {
|
|
||||||
apis["grpc"] = am.grpcServer.GetMetrics()
|
|
||||||
} else {
|
|
||||||
apis["grpc"] = map[string]interface{}{"enabled": false}
|
|
||||||
}
|
|
||||||
|
|
||||||
// WebSocket status
|
|
||||||
if am.websocketManager != nil {
|
|
||||||
apis["websocket"] = am.websocketManager.GetMetrics()
|
|
||||||
} else {
|
|
||||||
apis["websocket"] = map[string]interface{}{"enabled": false}
|
|
||||||
}
|
|
||||||
|
|
||||||
return status
|
|
||||||
}
|
|
||||||
|
|
||||||
// Feature management handlers
|
|
||||||
func (am *APIManager) handleGetFeatures(c *gin.Context) {
|
|
||||||
if am.featureManager == nil {
|
|
||||||
c.JSON(http.StatusServiceUnavailable, gin.H{"error": "Feature manager not available"})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
summary := am.featureManager.GetFeatureSummary()
|
|
||||||
c.JSON(http.StatusOK, gin.H{"data": summary})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (am *APIManager) handleGetFeature(c *gin.Context) {
|
|
||||||
featureID := c.Param("id")
|
|
||||||
|
|
||||||
if am.featureManager == nil {
|
|
||||||
c.JSON(http.StatusServiceUnavailable, gin.H{"error": "Feature manager not available"})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
feature, err := am.featureManager.GetFeature(c.Request.Context(), featureID)
|
|
||||||
if err != nil {
|
|
||||||
c.JSON(http.StatusNotFound, gin.H{"error": err.Error()})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
c.JSON(http.StatusOK, gin.H{"data": map[string]interface{}{
|
|
||||||
"id": feature.GetID(),
|
|
||||||
"name": feature.GetName(),
|
|
||||||
"version": feature.GetVersion(),
|
|
||||||
"type": feature.GetType(),
|
|
||||||
"domain": feature.GetDomain(),
|
|
||||||
"healthy": feature.IsHealthy(),
|
|
||||||
"status": feature.GetHealthStatus(),
|
|
||||||
"metrics": feature.GetMetrics(),
|
|
||||||
}})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (am *APIManager) handleStartFeature(c *gin.Context) {
|
|
||||||
// TODO: Implement feature start
|
|
||||||
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (am *APIManager) handleStopFeature(c *gin.Context) {
|
|
||||||
// TODO: Implement feature stop
|
|
||||||
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (am *APIManager) handleFeaturesHealth(c *gin.Context) {
|
|
||||||
if am.featureManager == nil {
|
|
||||||
c.JSON(http.StatusServiceUnavailable, gin.H{"error": "Feature manager not available"})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
healthStatus := am.featureManager.GetFeatureHealthStatus()
|
|
||||||
c.JSON(http.StatusOK, gin.H{"data": healthStatus})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (am *APIManager) handleFeaturesMetrics(c *gin.Context) {
|
|
||||||
if am.featureManager == nil {
|
|
||||||
c.JSON(http.StatusServiceUnavailable, gin.H{"error": "Feature manager not available"})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Implement comprehensive metrics collection
|
|
||||||
c.JSON(http.StatusOK, gin.H{"data": "metrics"})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Placeholder handlers for feature endpoints (to be implemented)
|
|
||||||
func (am *APIManager) handleGetUserProfile(c *gin.Context) {
|
|
||||||
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
||||||
}
|
|
||||||
func (am *APIManager) handleUpdateUserProfile(c *gin.Context) {
|
|
||||||
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
||||||
}
|
|
||||||
func (am *APIManager) handleFollowUser(c *gin.Context) {
|
|
||||||
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
||||||
}
|
|
||||||
func (am *APIManager) handleUnfollowUser(c *gin.Context) {
|
|
||||||
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
||||||
}
|
|
||||||
func (am *APIManager) handleGetFollowers(c *gin.Context) {
|
|
||||||
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
||||||
}
|
|
||||||
func (am *APIManager) handleGetFollowing(c *gin.Context) {
|
|
||||||
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
||||||
}
|
|
||||||
func (am *APIManager) handleGetAchievements(c *gin.Context) {
|
|
||||||
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
||||||
}
|
|
||||||
func (am *APIManager) handleGetLeaderboard(c *gin.Context) {
|
|
||||||
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
||||||
}
|
|
||||||
func (am *APIManager) handleClaimAchievement(c *gin.Context) {
|
|
||||||
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
||||||
}
|
|
||||||
func (am *APIManager) handleStartVerification(c *gin.Context) {
|
|
||||||
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
||||||
}
|
|
||||||
func (am *APIManager) handleGetVerificationStatus(c *gin.Context) {
|
|
||||||
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
||||||
}
|
|
||||||
func (am *APIManager) handleGetTrustScore(c *gin.Context) {
|
|
||||||
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
||||||
}
|
|
||||||
func (am *APIManager) handleGetRooms(c *gin.Context) {
|
|
||||||
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
||||||
}
|
|
||||||
func (am *APIManager) handleCreateRoom(c *gin.Context) {
|
|
||||||
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
||||||
}
|
|
||||||
func (am *APIManager) handleGetRoom(c *gin.Context) {
|
|
||||||
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
||||||
}
|
|
||||||
func (am *APIManager) handleJoinRoom(c *gin.Context) {
|
|
||||||
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
||||||
}
|
|
||||||
func (am *APIManager) handleLeaveRoom(c *gin.Context) {
|
|
||||||
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
||||||
}
|
|
||||||
func (am *APIManager) handleStartVoiceChat(c *gin.Context) {
|
|
||||||
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
||||||
}
|
|
||||||
func (am *APIManager) handleStopVoiceChat(c *gin.Context) {
|
|
||||||
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
||||||
}
|
|
||||||
func (am *APIManager) handleGetVoiceStatus(c *gin.Context) {
|
|
||||||
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
||||||
}
|
|
||||||
func (am *APIManager) handleStartVideoStream(c *gin.Context) {
|
|
||||||
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
||||||
}
|
|
||||||
func (am *APIManager) handleStopVideoStream(c *gin.Context) {
|
|
||||||
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
||||||
}
|
|
||||||
func (am *APIManager) handleGetVideoStreams(c *gin.Context) {
|
|
||||||
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
||||||
}
|
|
||||||
func (am *APIManager) handleUploadAudio(c *gin.Context) {
|
|
||||||
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
||||||
}
|
|
||||||
func (am *APIManager) handleStreamAudio(c *gin.Context) {
|
|
||||||
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
||||||
}
|
|
||||||
func (am *APIManager) handleGetAudioMetadata(c *gin.Context) {
|
|
||||||
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
||||||
}
|
|
||||||
func (am *APIManager) handleGetSmartPlaylists(c *gin.Context) {
|
|
||||||
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
||||||
}
|
|
||||||
func (am *APIManager) handleCreateSmartPlaylist(c *gin.Context) {
|
|
||||||
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
||||||
}
|
|
||||||
func (am *APIManager) handleGetSmartPlaylist(c *gin.Context) {
|
|
||||||
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
||||||
}
|
|
||||||
func (am *APIManager) handleDiscoverContent(c *gin.Context) {
|
|
||||||
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
||||||
}
|
|
||||||
func (am *APIManager) handleGetTrending(c *gin.Context) {
|
|
||||||
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
||||||
}
|
|
||||||
func (am *APIManager) handleGetSimilarContent(c *gin.Context) {
|
|
||||||
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
||||||
}
|
|
||||||
func (am *APIManager) handleGetRecommendations(c *gin.Context) {
|
|
||||||
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
||||||
}
|
|
||||||
func (am *APIManager) handleRecommendationFeedback(c *gin.Context) {
|
|
||||||
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
||||||
}
|
|
||||||
func (am *APIManager) handleModerateContent(c *gin.Context) {
|
|
||||||
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
||||||
}
|
|
||||||
func (am *APIManager) handleGetModerationHistory(c *gin.Context) {
|
|
||||||
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
||||||
}
|
|
||||||
func (am *APIManager) handleAnalyzeSentiment(c *gin.Context) {
|
|
||||||
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
||||||
}
|
|
||||||
func (am *APIManager) handleGetSentimentTrends(c *gin.Context) {
|
|
||||||
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
||||||
}
|
|
||||||
func (am *APIManager) handleGetDashboard(c *gin.Context) {
|
|
||||||
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
||||||
}
|
|
||||||
func (am *APIManager) handleGetRealtimeMetrics(c *gin.Context) {
|
|
||||||
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
||||||
}
|
|
||||||
func (am *APIManager) handleGetUserBehavior(c *gin.Context) {
|
|
||||||
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
||||||
}
|
|
||||||
func (am *APIManager) handleGetEngagementMetrics(c *gin.Context) {
|
|
||||||
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
||||||
}
|
|
||||||
func (am *APIManager) handleGetRevenueAnalytics(c *gin.Context) {
|
|
||||||
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
||||||
}
|
|
||||||
func (am *APIManager) handleGetConversionMetrics(c *gin.Context) {
|
|
||||||
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
||||||
}
|
|
||||||
func (am *APIManager) handleExternalAPIRequest(c *gin.Context) {
|
|
||||||
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
||||||
}
|
|
||||||
func (am *APIManager) handleGetExternalAPIStatus(c *gin.Context) {
|
|
||||||
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
||||||
}
|
|
||||||
func (am *APIManager) handleCreateWebhook(c *gin.Context) {
|
|
||||||
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
||||||
}
|
|
||||||
func (am *APIManager) handleGetWebhooks(c *gin.Context) {
|
|
||||||
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
||||||
}
|
|
||||||
func (am *APIManager) handleDeleteWebhook(c *gin.Context) {
|
|
||||||
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
||||||
}
|
|
||||||
func (am *APIManager) handleProcessPayment(c *gin.Context) {
|
|
||||||
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
||||||
}
|
|
||||||
func (am *APIManager) handleGetPaymentMethods(c *gin.Context) {
|
|
||||||
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
||||||
}
|
|
||||||
func (am *APIManager) handleGetPaymentHistory(c *gin.Context) {
|
|
||||||
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
||||||
}
|
|
||||||
Loading…
Reference in a new issue