feat: application n8n Pilot complète (Expo managed workflow)

- Stack : Expo Router, Axios, Zustand, React Native Paper (thème sombre), date-fns
- Sécurité : secrets dans Android Keystore via expo-secure-store, TLS obligatoire,
  headers X-N8N-API-KEY + X-App-Token injectés par intercepteur Axios
- API : client.ts centralisé + workflows.ts + executions.ts (TypeScript strict)
- Store : Zustand appStore avec chargement depuis secure store au démarrage
- Hooks : usePolling (générique), useWorkflows, useExecutions
- Composants : StatusBadge, WorkflowCard, ExecutionCard, SkeletonLoader
- Screens : Dashboard, Workflows, Executions, Logs (détail exécution), Settings
- Navigation Expo Router : 4 tabs + stack Logs + écran Setup initial
- Docs : INSTALL.md, UPDATE.md, BACKUP.md, HAPROXY.md, SECURITY.md

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-20 17:31:55 +02:00
parent ea1705d3b0
commit 92e67d0769
41 changed files with 4891 additions and 58 deletions
+112
View File
@@ -0,0 +1,112 @@
import { apiClient } from './client';
/** Représente un nœud dans un workflow n8n */
export interface WorkflowNode {
id: string;
name: string;
type: string;
position: [number, number];
parameters: Record<string, unknown>;
typeVersion?: number;
}
/** Tag associé à un workflow */
export interface WorkflowTag {
id: string;
name: string;
createdAt: string;
updatedAt: string;
}
/**
* Représente un workflow complet tel que retourné par l'API n8n v1.
* Les champs `nodes` et `connections` sont présents dans les réponses détaillées.
*/
export interface Workflow {
id: string;
name: string;
active: boolean;
createdAt: string;
updatedAt: string;
nodes: WorkflowNode[];
connections: Record<string, unknown>;
settings?: Record<string, unknown>;
tags?: WorkflowTag[];
}
/**
* Réponse paginée standard de l'API n8n.
* nextCursor est null si on est sur la dernière page.
*/
export interface ApiListResponse<T> {
data: T[];
nextCursor: string | null;
}
/**
* Récupère la liste complète des workflows de l'instance n8n.
*
* @returns Tableau de tous les workflows (actifs et inactifs)
* @throws AxiosError — géré par l'intercepteur, remonte via errorHandler
*/
export const fetchWorkflows = async (): Promise<Workflow[]> => {
const response = await apiClient.get<ApiListResponse<Workflow>>('/api/v1/workflows');
return response.data.data;
};
/**
* Récupère le détail complet d'un workflow, incluant ses nœuds et connexions.
*
* @param id - Identifiant du workflow
* @returns Workflow avec tous ses détails
*/
export const fetchWorkflowById = async (id: string): Promise<Workflow> => {
const response = await apiClient.get<Workflow>(`/api/v1/workflows/${id}`);
return response.data;
};
/**
* Active un workflow : il répondra désormais à ses déclencheurs.
*
* @param id - Identifiant du workflow à activer
* @returns Workflow mis à jour avec active = true
*/
export const activateWorkflow = async (id: string): Promise<Workflow> => {
const response = await apiClient.post<Workflow>(`/api/v1/workflows/${id}/activate`);
return response.data;
};
/**
* Désactive un workflow : ses déclencheurs sont mis en veille.
*
* @param id - Identifiant du workflow à désactiver
* @returns Workflow mis à jour avec active = false
*/
export const deactivateWorkflow = async (id: string): Promise<Workflow> => {
const response = await apiClient.post<Workflow>(`/api/v1/workflows/${id}/deactivate`);
return response.data;
};
/** Paramètres optionnels pour le déclenchement manuel d'un workflow */
export interface RunWorkflowParams {
/** Données injectées dans le nœud de démarrage manuel */
workflowData?: Record<string, unknown>;
}
/**
* Déclenche manuellement l'exécution d'un workflow.
*
* @param id - Identifiant du workflow à déclencher
* @param params - Données optionnelles d'entrée
* @returns Identifiant de l'exécution créée
*/
export const runWorkflow = async (
id: string,
params?: RunWorkflowParams
): Promise<{ executionId: string }> => {
const response = await apiClient.post<{ executionId: string }>(
`/api/v1/workflows/${id}/run`,
params ?? {}
);
return response.data;
};