Bibliothèque easyapi — créer des API REST en BERKIOS CODE — v1.1.0
27 commandes pour définir une API REST dans un script, la tester sans réseau (ou contre un vrai serveur), en tirer la description OpenAPI 3.1 et exporter un serveur Node.js autonome (un seul fichier, aucune dépendance). Chaque commande existe en anglais, français, espagnol et swahili (noms swahili non relus par des locuteurs natifs). Permissions demandées : fichiers (pour save-server et save-openapi, qui utilisent telecharger) et reseau (pour call-api sur un serveur désigné par set-server). Ce sont de simples macros vers les 19 commandes intégrées de la catégorie « API REST » (api-creer, api-ressource, api-route… voir la leçon formation/08) : le moteur est dans le Studio (studio/src/model/rest-api-engine.ts), pas dans la bibliothèque.
Une API en cinq lignes
quand clic
easy-api "Boutique" "produits" "nom:texte*, prix:nombre, sku:texte*!"
protect-api
make-key "mobile" "ecriture" "$cle" # le secret s'affiche une seule fois
call-api "$r" "POST" "/api/produits" '{"nom":"Stylo","sku":"A1","prix":2}' "$cle"
status-code "$code" # 201
save-server "serveur.mjs" # télécharge le serveur à déployereasy-api crée l'API Boutique et la ressource produits avec ses six routes : GET /api/produits, POST /api/produits, GET|PUT|PATCH|DELETE /api/produits/:id.
Ce que fait le moteur
- Validation à chaque écriture : types
texte,nombre,entier,booleen,date(AAAA-MM-JJ),email;*= obligatoire,!= unique. Champ inconnu, type faux ou doublon →422ou409avec le détail par champ. - Liste :
?limit=(1–1000, 50 par défaut),?offset=,?after=<id>(pagination par curseur : la réponse portenext_aftertant qu'il reste des pages),?sort=champou?sort=-champ,?q=(recherche dans les textes),?champ=valeur(filtre). Un filtre inconnu est une erreur400, pas ignoré. - Routes personnalisées :
route,get-route,post-route,put-route,patch-route,delete-route. La réponse est du JSON si elle commence par{ou[, sinon du texte ;{param},{query.x},{body.x},{method},{path},{date}sont remplacés à chaque requête. Dans une réponse JSON, les valeurs injectées restent des chaînes : aucune injection possible. - Sécurité :
protect-apiexige une clé (X-API-KeyouAuthorization: Bearer) sur toute requête, même vers une route inconnue, sauf/health,/openapi.jsonet les routes marquéespublic. Rôleslecture(GET),ecriture(+ POST/PUT/PATCH/DELETE),admin. Les secrets ne sont jamais écrits dans la définition ni dans le serveur exporté. - CORS : seules les origines listées par
allow-originsont autorisées ;*doit être écrit explicitement. - Débit :
rate-limit N→429avecRetry-Afterau-delà de N requêtes par minute et par client. - Import en masse :
POST /ressource/bulk(tableau JSON ou{ "data": [...] }, 1 000 enregistrements au plus par requête) est atomique : tout est créé ou rien, avec l'indice de l'enregistrement fautif.seed-dataaccepte jusqu'à 100 000 enregistrements par appel. - Corps limité à 5 Mo, 1 000 000 d'enregistrements par ressource (
507au-delà ;EASYAPI_MAX_RECORDSsur le serveur), 50 ressources, 200 routes, 20 clés ; en-têtesCache-Control: no-storeetX-Content-Type-Options: nosniff.
Tester, documenter, déployer
call-api "$r" "GET" "/api/produits"appelle l'API dans le Studio, sans réseau, avec le même routeur que le serveur exporté ;status-codeetresponse-headerlisent le code et les en-têtes.set-server "https://api.monsite.com"désigne un vrai serveur :call-apienvoie alors de vraies requêtes HTTP (mêmes arguments, mêmes codes,status-codeetresponse-headerlisent la réponse du serveur).set-serversans argument revient à l'API d'essai : un même script sert à l'essai et à la production. Le navigateur du Studio impose le CORS : le serveur doit autoriser l'origine (allow-origin).openapi/save-openapi "openapi.json": description OpenAPI 3.1 (Swagger UI, Postman, générateurs de clients). Elle est aussi servie par le serveur sur/api/openapi.json.export-spec/import-spec: sauvegarde et rechargement de la définition (sans données ni secrets).save-server "serveur.mjs"(ouserver-code "$code") : serveur Node.js 18+, sans dépendance.
EASYAPI_KEYS="mobile:write:UnSecretLongEtAleatoire1234" PORT=3000 HOST=0.0.0.0 node serveur.mjs| Variable | Rôle |
|---|---|
PORT | port d'écoute (3000) |
HOST | interface (127.0.0.1 ; 0.0.0.0 dans un conteneur ou derrière un proxy) |
DATA_FILE | instantané JSON des données (./donnees.json) ; chaque modification est ajoutée au journal DATA_FILE.journal (écriture groupée toutes les 100 ms) puis fusionnée dans l'instantané au démarrage, à l'arrêt et quand le journal dépasse EASYAPI_JOURNAL_MB (64 par défaut) |
EASYAPI_MAX_RECORDS | enregistrements maximum par ressource (1 000 000) ; compter environ 1 Ko de mémoire par enregistrement |
EASYAPI_KEYS | clés nom:role:secret séparées par ; (rôle read, write ou admin, secret de 16 caractères ou plus) |
TRUST_PROXY=1 | lit l'adresse du client dans X-Forwarded-For (proxy de confiance seulement) |
Après un arrêt brutal (kill, coupure), le journal est rejoué au redémarrage : on ne perd que les 100 dernières millisecondes. Une dernière ligne tronquée est ignorée ; une ligne corrompue au milieu du journal empêche le démarrage (rien n'est écrasé). Une API protégée refuse de démarrer sans clé. Placez toujours le serveur derrière HTTPS (Caddy, nginx…).
Limites assumées
- Les données d'essai du Studio vivent en mémoire pour la session d'aperçu et ne sont pas enregistrées dans le projet : la définition, elle, est le script (ou
export-spec).easy-api/new-apirepartent de zéro. - Pas de relations entre ressources ni de transactions (sauf le lot
/bulk, atomique). Gros volumes : tout reste en mémoire (≈ 1 Ko par enregistrement, 1 000 000 au plus par ressource). Accès par id, unicité et filtres d'égalité (?champ=valeur) sont indexés ; le tri est mis en cache par champ ; la pagination par curseur (after) ne coûte pas plus cher à la page 10 000 qu'à la première. La recherche?q=parcourt les textes (linéaire) et un lot d'écritures simultanées reste sérialisé sur un seul processus. Au-delà du million, de plusieurs serveurs ou de besoins de requêtes complexes : une vraie base. - L'instantané est relu avec
JSON.parse: un fichier de données de plusieurs centaines de Mo demande autant de mémoire à la lecture. - Pas de comptes utilisateurs : l'accès se règle par clés d'API.
- Le Studio ne peut pas ouvrir de port réseau : on teste avec
call-api, puis on déploie le serveur exporté. - Flutter : les 19 commandes
api-*(donc toute la bibliothèque) existent dans l'application générée (bridge/runtime/berkios_rest_api.dart, moteur Dart pur) ;set-server+call-apiy envoient de vraies requêtes HTTP (dart:io). Le moteur Dart est un simulateur local en mémoire : mêmes règles et mêmes messages, mais filtres d'égalité sans index. Ce code Dart n'a pas été compilé (ni Dart ni Flutter dans l'environnement de développement) : il est vérifié par des tests statiques et par le gabarit de serveur qu'il assemble ; à compiler au premierflutter build.
Application client-serveur
L'accueil du Studio propose la carte Application client-serveur : projet autonome (client multiplateforme) marqué architecture: "client-serveur", relié à un serveur qui héberge données et API REST. Ajoutez EasyAPI pour écrire l'API en BERKIOS CODE, exportez le serveur, puis appelez-le depuis le client.
Exemple complet
examples/application/api/client-serveur/ : une application de tâches (client BERKIOS avec easyapi, serveur Node exporté, clé d'API, import en masse, pagination par curseur). Essai sans serveur dans le Studio, puis contre serveur.mjs. Généré par node scripts/build-api-client-serveur-example.mjs.
Commandes
| Noms (en · fr · es · sw) | Syntaxe | Effet |
|---|---|---|
easy-api · api-rapide · api-facil · api-rahisi | easy-api "Boutique" "produits" "nom:texte*, prix:nombre" | Crée en une ligne une API complète : son nom et une première ressource avec ses 6 routes REST (liste, lecture, création, remplacement, modification, suppression) et la validation des champs. |
new-api · nouvelle-api · nueva-api · api-mpya | new-api "Nom" ["/prefixe"] ["1.0.0"] | Commence une nouvelle API (efface la précédente) ; préfixe /api et version 1.0.0 par défaut. |
resource · ressource · recurso · rasilimali | resource "produits" "nom:texte*, prix:nombre, sku:texte*!" | Déclare une ressource REST : GET/POST /produits et GET/PUT/PATCH/DELETE /produits/:id. Types : texte, nombre, entier, booleen, date, email ; * obligatoire, ! unique. |
route · chemin-api · ruta · njia | route "GET" "/salut/:nom" "Bonjour {nom}" [statut] [public] | Ajoute une route personnalisée. Réponse JSON si le texte commence par { ou [, sinon texte brut ; {param}, {query.x}, {body.x} sont remplacés à chaque requête. |
get-route · route-get · ruta-get · njia-get | get-route "/chemin" "réponse" [statut] [public] | Raccourci de route pour la méthode GET : get-route "/chemin" "réponse" équivaut à route "GET" "/chemin" "réponse". |
post-route · route-post · ruta-post · njia-post | post-route "/chemin" "réponse" [statut] [public] | Raccourci de route pour la méthode POST : post-route "/chemin" "réponse" équivaut à route "POST" "/chemin" "réponse". |
put-route · route-put · ruta-put · njia-put | put-route "/chemin" "réponse" [statut] [public] | Raccourci de route pour la méthode PUT : put-route "/chemin" "réponse" équivaut à route "PUT" "/chemin" "réponse". |
patch-route · route-patch · ruta-patch · njia-patch | patch-route "/chemin" "réponse" [statut] [public] | Raccourci de route pour la méthode PATCH : patch-route "/chemin" "réponse" équivaut à route "PATCH" "/chemin" "réponse". |
delete-route · route-delete · ruta-delete · njia-delete | delete-route "/chemin" "réponse" [statut] [public] | Raccourci de route pour la méthode DELETE : delete-route "/chemin" "réponse" équivaut à route "DELETE" "/chemin" "réponse". |
seed-data · donnees-api · datos-api · data-ya-api | seed-data "produits" '[{"nom":"Stylo","sku":"A1"}]' | Insère des enregistrements de démonstration (tableau JSON) dans une ressource, validés comme par POST ; tout ou rien. |
protect-api · securiser-api · proteger-api · linda-api | protect-api [oui|non] | Exige une clé d'API (X-API-Key ou Authorization: Bearer) pour toute requête, sauf /health, /openapi.json et les routes « public ». |
make-key · creer-cle · crear-clave · tengeneza-ufunguo | make-key "mobile" "lecture|ecriture|admin" "Résultat" | Crée une clé d'API et écrit son secret dans le résultat (à copier tout de suite : il n'est ni exporté ni relisible). |
allow-origin · autoriser-origine · permitir-origen · ruhusu-asili | allow-origin "https://monsite.com, https://app.monsite.com" | Autorise des origines de navigateur précises (CORS). Aucune origine par défaut ; « * » doit être écrit explicitement. |
rate-limit · limiter-debit · limitar-tasa · punguza-kasi | rate-limit 120 | Limite le nombre de requêtes par minute et par client (0 = aucune) ; au-delà, la réponse est 429 avec Retry-After. |
set-server · serveur-api · servidor-api · seva-ya-api | set-server "https://api.monsite.com" | Désigne le serveur d'API réel : call-api envoie alors ses requêtes HTTP à ce serveur au lieu de l'API d'essai ; sans argument, retour à l'API locale. |
call-api · appeler-api · llamar-api · piga-api | call-api "Résultat" "GET" "/api/produits" ["corps JSON"] ["cle"] | Appelle l'API sans réseau (même routeur que le serveur exporté) et écrit le corps de la réponse ; le code HTTP se lit avec status-code. |
status-code · code-http · codigo-http · msimbo-http | status-code "Résultat" | Écrit le code HTTP de la dernière réponse de call-api (200, 201, 404, 422…). |
response-header · entete-reponse · cabecera-respuesta · kichwa-jibu | response-header "Résultat" "Location" | Écrit un en-tête de la dernière réponse de call-api (texte vide s'il est absent). |
list-routes · lister-routes · listar-rutas · orodhesha-njia | list-routes "Résultat" | Liste les routes de l'API (« METHODE /chemin »), séparées par des virgules. |
openapi · documenter-api · documentar-api · andika-api | openapi "Résultat" | Écrit la description OpenAPI 3.1 de l'API (JSON), utilisable avec Swagger UI, Postman ou un générateur de clients. |
count-records · compter-enregistrements · contar-registros · hesabu-rekodi | count-records "Résultat" "produits" | Nombre d'enregistrements d'une ressource dans les données d'essai. |
clear-data · vider-donnees · vaciar-datos · futa-data | clear-data ["produits"] | Vide les données d'essai d'une ressource (ou de toutes) sans toucher à la définition de l'API. |
export-spec · exporter-definition · exportar-definicion · hamisha-ufafanuzi | export-spec "Résultat" | Écrit la définition de l'API en JSON (sans données ni secrets) pour la sauvegarder ou la partager. |
import-spec · importer-definition · importar-definicion · leta-ufafanuzi | import-spec "Source" | Recharge une définition produite par export-spec (données d'essai remises à zéro ; clés à recréer). |
server-code · code-serveur · codigo-servidor · msimbo-seva | server-code "Résultat" | Écrit le code d'un serveur Node.js autonome pour cette API : un fichier, aucune dépendance, données JSON sur disque, clés lues dans EASYAPI_KEYS. |
save-server · enregistrer-serveur · guardar-servidor · hifadhi-seva | save-server "serveur.mjs" | Télécharge le serveur Node.js autonome de l'API dans un fichier. Lancez-le avec : node serveur.mjs |
save-openapi · enregistrer-openapi · guardar-openapi · hifadhi-openapi | save-openapi "openapi.json" | Télécharge la description OpenAPI 3.1 de l'API dans un fichier. |
Cette page en Markdown · llms.txt · documentation complète pour les IA