[{"data":1,"prerenderedAt":418},["ShallowReactive",2],{"docs-nav:fr":3,"docs:\u002Ffr\u002Fdocs\u002Fconcepts\u002Fphilosophy":137},[4],{"title":5,"path":6,"stem":7,"children":8,"page":44},"Fr","\u002Ffr","fr",[9],{"title":10,"path":11,"stem":12,"children":13},"Qu'est-ce que Fougere","\u002Ffr\u002Fdocs","fr\u002Fdocs\u002Findex",[14,15,19,23,27,45,66,95,116],{"title":10,"path":11,"stem":12},{"title":16,"path":17,"stem":18},"Démarrer","\u002Ffr\u002Fdocs\u002Fgetting-started","fr\u002Fdocs\u002F01.getting-started",{"title":20,"path":21,"stem":22},"App Nuxt existante","\u002Ffr\u002Fdocs\u002Fexisting-app","fr\u002Fdocs\u002F02.existing-app",{"title":24,"path":25,"stem":26},"La CLI","\u002Ffr\u002Fdocs\u002Fcli","fr\u002Fdocs\u002F03.cli",{"title":28,"path":29,"stem":30,"children":31,"page":44},"Concepts","\u002Ffr\u002Fdocs\u002Fconcepts","fr\u002Fdocs\u002F2.concepts",[32,36,40],{"title":33,"path":34,"stem":35},"Philosophie","\u002Ffr\u002Fdocs\u002Fconcepts\u002Fphilosophy","fr\u002Fdocs\u002F2.concepts\u002F1.philosophy",{"title":37,"path":38,"stem":39},"La Frond","\u002Ffr\u002Fdocs\u002Fconcepts\u002Ffrond","fr\u002Fdocs\u002F2.concepts\u002F2.frond",{"title":41,"path":42,"stem":43},"Le chemin le plus court","\u002Ffr\u002Fdocs\u002Fconcepts\u002Fshortest-path","fr\u002Fdocs\u002F2.concepts\u002F3.shortest-path",false,{"title":46,"path":47,"stem":48,"children":49,"page":44},"Schéma","\u002Ffr\u002Fdocs\u002Fschema","fr\u002Fdocs\u002F3.schema",[50,54,58,62],{"title":51,"path":52,"stem":53},"Entités","\u002Ffr\u002Fdocs\u002Fschema\u002Fentities","fr\u002Fdocs\u002F3.schema\u002F1.entities",{"title":55,"path":56,"stem":57},"Vues","\u002Ffr\u002Fdocs\u002Fschema\u002Fviews","fr\u002Fdocs\u002F3.schema\u002F2.views",{"title":59,"path":60,"stem":61},"La carte d'identité","\u002Ffr\u002Fdocs\u002Fschema\u002Fcard","fr\u002Fdocs\u002F3.schema\u002F3.card",{"title":63,"path":64,"stem":65},"Standard Schema","\u002Ffr\u002Fdocs\u002Fschema\u002Fstandard-schema","fr\u002Fdocs\u002F3.schema\u002F4.standard-schema",{"title":67,"path":68,"stem":69,"children":70,"page":44},"Métier","\u002Ffr\u002Fdocs\u002Fbusiness","fr\u002Fdocs\u002F4.business",[71,75,79,83,87,91],{"title":72,"path":73,"stem":74},"Handlers","\u002Ffr\u002Fdocs\u002Fbusiness\u002Fhandlers","fr\u002Fdocs\u002F4.business\u002F1.handlers",{"title":76,"path":77,"stem":78},"Presenters","\u002Ffr\u002Fdocs\u002Fbusiness\u002Fpresenters","fr\u002Fdocs\u002F4.business\u002F2.presenters",{"title":80,"path":81,"stem":82},"Collectors","\u002Ffr\u002Fdocs\u002Fbusiness\u002Fcollectors","fr\u002Fdocs\u002F4.business\u002F3.collectors",{"title":84,"path":85,"stem":86},"Erreurs","\u002Ffr\u002Fdocs\u002Fbusiness\u002Ferrors","fr\u002Fdocs\u002F4.business\u002F4.errors",{"title":88,"path":89,"stem":90},"Seeds","\u002Ffr\u002Fdocs\u002Fbusiness\u002Fseeds","fr\u002Fdocs\u002F4.business\u002F5.seeds",{"title":92,"path":93,"stem":94},"Les faits","\u002Ffr\u002Fdocs\u002Fbusiness\u002Ffacts","fr\u002Fdocs\u002F4.business\u002F6.facts",{"title":96,"path":97,"stem":98,"children":99,"page":44},"Client","\u002Ffr\u002Fdocs\u002Fclient","fr\u002Fdocs\u002F5.client",[100,104,108,112],{"title":101,"path":102,"stem":103},"Queries & commands","\u002Ffr\u002Fdocs\u002Fclient\u002Fqueries-commands","fr\u002Fdocs\u002F5.client\u002F1.queries-commands",{"title":105,"path":106,"stem":107},"Formulaires","\u002Ffr\u002Fdocs\u002Fclient\u002Fforms","fr\u002Fdocs\u002F5.client\u002F2.forms",{"title":109,"path":110,"stem":111},"Session","\u002Ffr\u002Fdocs\u002Fclient\u002Fsession","fr\u002Fdocs\u002F5.client\u002F3.session",{"title":113,"path":114,"stem":115},"invoke","\u002Ffr\u002Fdocs\u002Fclient\u002Finvoke","fr\u002Fdocs\u002F5.client\u002F4.invoke",{"title":117,"path":118,"stem":119,"children":120,"page":44},"Infrastructure","\u002Ffr\u002Fdocs\u002Finfra","fr\u002Fdocs\u002F6.infra",[121,125,129,133],{"title":122,"path":123,"stem":124},"Le gradient","\u002Ffr\u002Fdocs\u002Finfra\u002Fgradient","fr\u002Fdocs\u002F6.infra\u002F1.gradient",{"title":126,"path":127,"stem":128},"Surfaces — REST & GraphQL","\u002Ffr\u002Fdocs\u002Finfra\u002Fsurfaces","fr\u002Fdocs\u002F6.infra\u002F2.surfaces",{"title":130,"path":131,"stem":132},"Déploiement","\u002Ffr\u002Fdocs\u002Finfra\u002Fdeployment","fr\u002Fdocs\u002F6.infra\u002F3.deployment",{"title":134,"path":135,"stem":136},"Hôtes","\u002Ffr\u002Fdocs\u002Finfra\u002Fhosts","fr\u002Fdocs\u002F6.infra\u002F4.hosts",{"id":138,"title":33,"body":139,"description":412,"extension":413,"meta":414,"navigation":415,"path":34,"seo":416,"stem":35,"__hash__":417},"docs_fr\u002Ffr\u002Fdocs\u002F2.concepts\u002F1.philosophy.md",{"type":140,"value":141,"toc":395},"minimark",[142,146,150,155,163,167,198,202,208,212,219,239,243,250,264,267,272,275,282,285,303,306,310,317,321,324,338,341,345,348,372,375,379,382,386,389],[143,144,33],"h1",{"id":145},"philosophie",[147,148,149],"p",{},"Fougere décrit une application avec des données, des opérations, des contrats et des\nfrontières de domaine. Des adapters relient ensuite ce modèle à Nuxt, HTTP, SQL, au cache\nou à un processus distant.",[151,152,154],"h2",{"id":153},"les-déclarations-se-projettent","Les déclarations se projettent",[147,156,157,158,162],{},"Une ",[159,160,161],"a",{"href":52},"entité"," décrit des données indépendamment de leur stockage.\nSa déclaration fournit le type TypeScript, la validation et les métadonnées utilisées par\nles formulaires, SQLite et GraphQL. Lorsqu'une même règle apparaît dans plusieurs couches,\nelle doit être placée dans la déclaration commune si son périmètre le permet.",[151,164,166],{"id":165},"des-opérations-pas-des-écritures-de-champ","Des opérations, pas des écritures de champ",[147,168,169,170,174,175,178,179,182,183,187,188,193,194,197],{},"Une Frond expose des ",[171,172,173],"strong",{},"commands"," pour modifier le système, des ",[171,176,177],{},"queries"," pour le lire\net, lorsque c'est utile, des ",[171,180,181],{},"events"," produits par les commands. ",[184,185,186],"code",{},"Crud(Post)"," fournit\nles cinq opérations standard. Une transition métier utilise un verbe explicite :\n",[159,189,190],{"href":73},[184,191,192],{},"publish"," vérifie ses règles avant de modifier ",[184,195,196],{},"status",", au\nlieu de laisser le client écrire ce champ directement.",[151,199,201],{"id":200},"la-frond-possède","La Frond possède",[147,203,157,204,207],{},[159,205,206],{"href":38},"Frond"," regroupe les entités, opérations, règles d'accès et\nadapters d'un domaine. Les interactions avec une autre Frond passent par ses contrats\npublics. L'application compose ces modules sans déplacer leur logique dans les pages,\nles fetchs ou les stores.",[151,209,211],{"id":210},"la-topologie-est-de-la-configuration","La topologie est de la configuration",[147,213,214,215,218],{},"Le fichier de ",[159,216,217],{"href":123},"configuration"," indique si une Frond s'exécute\nlocalement ou sur un hôte distant. Les appels utilisent la même API dans les deux cas.\nLe runner exécute un appel local en mémoire et utilise le transport configuré pour un\nappel distant.",[147,220,221,222,225,226,229,230,233,234,238],{},"Cette frontière permet aussi à une Frond d'avoir son propre dépôt et son propre cycle de\npublication : seul son ",[171,223,224],{},"contrat"," doit voyager, jamais son code source — ",[184,227,228],{},"fougere sync","\nle lit sur l'hôte qui tourne, ",[184,231,232],{},"fougere build-frond"," en fait un paquet installable\n(",[159,235,237],{"href":236},"\u002Ffr\u002Fdocs\u002Finfra\u002Fgradient#o%C3%B9-le-code-vit","où le code vit",").",[151,240,242],{"id":241},"http-est-une-projection-pas-un-socle","HTTP est une projection, pas un socle",[147,244,245,246,249],{},"Beaucoup de frameworks partent d'une route : l'objet premier est une requête, et le modèle,\nla validation et la couche métier viennent s'y accrocher. Ici l'objet premier est\nl'",[171,247,248],{},"opération"," — une méthode publique qui reçoit une invocation, et qui n'a jamais entendu\nparler de HTTP.",[147,251,252,253,256,257,263],{},"Ce n'est pas une préférence de style, c'est ce qui rend le reste possible. Une opération qui\nignore le transport s'appelle en mémoire, se met sur un fil JSON-RPC, se traduit en route\nREST, en champ GraphQL ou en commande de shell — sans qu'aucune de ces formes ne soit\nprivilégiée. ",[184,254,255],{},"@fougere\u002Fcore"," ne dépend d'aucun serveur, et\n",[159,258,260],{"href":259},"\u002Ffr\u002Fdocs\u002Finfra\u002Fsurfaces#le-framework-nest-pas-le-process",[184,261,262],{},"@fougere\u002Fhttp"," n'a aucune\ndépendance du tout : vous apportez Hono, Fastify, Nitro — ou rien.",[147,265,266],{},"Le corollaire est que JavaScript vous emmène partout où il va. La déclaration et son juge\ntournent dans le navigateur comme à la façade : le même objet, pas une copie fidèle.",[268,269,271],"h3",{"id":270},"le-transport-est-une-feuille","Le transport est une feuille",[147,273,274],{},"Une application Fougere complète peut n'avoir aucun HTTP. Les entités, les opérations, le\nstockage, la validation, l'injection et les seeds fonctionnent sans qu'aucun serveur ne\ndémarre. Une commande de shell, un worker, un test, un appel en mémoire ne sont pas des\nversions dégradées de l'application : ce sont des usages entiers.",[147,276,277,278,281],{},"C'est pour cela que HTTP figure au ",[171,279,280],{},"même rang"," que les autres projections, et non en\ndessous. Une même déclaration donne la table SQL, le type GraphQL, le contrat de formulaire\net la route : quatre lectures d'un seul énoncé, aucune n'étant le sol des autres.",[147,283,284],{},"Deux conséquences, et ce sont elles qui rendent le principe utile :",[286,287,288,296],"ul",{},[289,290,291,292,295],"li",{},"si le transport était la fondation, on ne pourrait pas l'enlever — donc pas d'appel en\nmémoire, donc pas de ",[159,293,294],{"href":123},"gradient"," ;",[289,297,298,299,302],{},"les ",[159,300,301],{"href":127},"surfaces"," ne pourraient pas rendre le même verdict, puisque\nl'une d'elles servirait de sol aux autres.",[147,304,305],{},"Ce n'est donc pas une revendication d'indépendance vis-à-vis d'un serveur, ni un choix\nd'implémentation. C'est la règle du haut de cette page — une déclaration, des projections —\nappliquée à l'endroit où beaucoup de frameworks placent leur socle.",[151,307,309],{"id":308},"un-état-est-perdable-ou-durable","Un état est perdable ou durable",[147,311,312,313,316],{},"Pour choisir entre cache et stockage durable, demandez ce que la perte de la donnée\nchange. Une valeur recalculable à partir d'une query peut rester dans un cache. Une valeur\ndont la perte modifie le comportement doit être stockée comme donnée métier, même si sa\ndurée de vie est courte. Un code OAuth à usage unique peut par exemple être représenté\npar ",[184,314,315],{},"{ code, userId, expiresAt }"," avec une lecture destructrice.",[151,318,320],{"id":319},"embarqué-ou-externalisé","Embarqué ou externalisé",[147,322,323],{},"Les éléments utilisés dans plusieurs contextes sont livrés avec la classe ; les détails\nd'exécution sont branchés par le runtime.",[286,325,326,332],{},[289,327,328,331],{},[171,329,330],{},"Embarqué"," — la validation, les projections d'entrée ou de sortie et les métadonnées.\nCes éléments peuvent être utilisés dans le navigateur, à la façade ou dans une Frond\ndistante.",[289,333,334,337],{},[171,335,336],{},"Externalisé"," — le stockage, le transport et le rendu. Ces adapters peuvent varier\nselon l'application et la surface utilisée.",[147,339,340],{},"La validation est embarquée pour appliquer les mêmes règles dans chaque contexte. Le\nstockage reste externe afin que l'application puisse choisir son adapter. Les métadonnées\nne dépendent pas de la topologie ; leur utilisation dépend du runtime qui les charge.",[151,342,344],{"id":343},"lordre-de-conception","L'ordre de conception",[147,346,347],{},"Quand une décision de design se présente, poser les questions dans cet ordre :",[349,350,351,354,357,360,363,366,369],"ol",{},[289,352,353],{},"Quel est le concept applicatif ?",[289,355,356],{},"Quelle est sa frontière de propriété ?",[289,358,359],{},"Quels contrats doit-il exposer ?",[289,361,362],{},"Quelles opérations changent l'état ?",[289,364,365],{},"Quelles queries le lisent ?",[289,367,368],{},"Qu'est-ce qui invalide quoi ?",[289,370,371],{},"Quel adapter exécute ou projette ce modèle ?",[147,373,374],{},"Cet ordre évite de répartir une règle entre une route, une page, une table et un\ntransport.",[151,376,378],{"id":377},"pourquoi-fougere","Pourquoi « Fougere »",[147,380,381],{},"Une fougère est composée de frondes qui répètent une structure proche de la plante. Le nom\nfait référence à la composition du framework : des champs forment une entité, les entités\net leurs opérations forment une Frond, puis l'application compose plusieurs Fronds.",[151,383,385],{"id":384},"position","Position",[147,387,388],{},"Fougere vise les applications data-intensive qui utilisent un même modèle métier depuis\nplusieurs surfaces et modes d'exécution. Nuxt, le CRUD et les transports sont des\nintégrations de ce modèle, pas sa définition.",[147,390,391,392,394],{},"Suite : ",[159,393,37],{"href":38},".",{"title":396,"searchDepth":397,"depth":397,"links":398},"",2,[399,400,401,402,403,407,408,409,410,411],{"id":153,"depth":397,"text":154},{"id":165,"depth":397,"text":166},{"id":200,"depth":397,"text":201},{"id":210,"depth":397,"text":211},{"id":241,"depth":397,"text":242,"children":404},[405],{"id":270,"depth":406,"text":271},3,{"id":308,"depth":397,"text":309},{"id":319,"depth":397,"text":320},{"id":343,"depth":397,"text":344},{"id":377,"depth":397,"text":378},{"id":384,"depth":397,"text":385},"Les principes qui relient déclarations, opérations, Fronds et topologie.","md",{},true,{"title":33,"description":412},"59lNytIzKn-jBWC8gbSEDJiEBfxRQLC2Zzcc4XB_Hrk",1786637819621]