nodefony 7.0.2 → 10.0.0-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.ai/symbols.json +36135 -0
- package/LICENSE +544 -0
- package/README.md +316 -694
- package/bin/nodefony +2183 -85
- package/dist/client/Container.js +367 -0
- package/dist/client/Event.js +198 -0
- package/dist/client/Service.js +344 -0
- package/dist/client/Tools.js +162 -0
- package/dist/client/client/ClientKernel.js +276 -0
- package/dist/client/client/angular/index.js +352 -0
- package/dist/client/client/announce.js +212 -0
- package/dist/client/client/debugbar/DebugBar.js +1624 -0
- package/dist/client/client/debugbar/format.js +103 -0
- package/dist/client/client/debugbar/hmr.js +37 -0
- package/dist/client/client/debugbar/index.js +29 -0
- package/dist/client/client/debugbar/model.js +133 -0
- package/dist/client/client/debugbar/network.js +173 -0
- package/dist/client/client/debugbar/profile.js +114 -0
- package/dist/client/client/index.js +34 -0
- package/dist/client/client/react/index.js +268 -0
- package/dist/client/client/realtime/AdaptiveRate.js +240 -0
- package/dist/client/client/realtime/BrowserWsTransport.js +57 -0
- package/dist/client/client/realtime/RealtimeClient.js +898 -0
- package/dist/client/client/realtime/localEvents.js +56 -0
- package/dist/client/client/realtime/notice.js +125 -0
- package/dist/client/client/realtime/observe.js +280 -0
- package/dist/client/client/roles/index.js +3 -0
- package/dist/client/client/roles/registry.js +97 -0
- package/dist/client/client/roles/roles.js +91 -0
- package/dist/client/client/shim/events.js +88 -0
- package/dist/client/client/shim/util.js +20 -0
- package/dist/client/client/svelte/index.js +319 -0
- package/dist/client/client/syslog/context.js +122 -0
- package/dist/client/client/syslog/errors.js +49 -0
- package/dist/client/client/syslog/uplink.js +106 -0
- package/dist/client/client/vue/index.js +321 -0
- package/dist/client/colors.js +63 -0
- package/dist/client/debugbar.standalone.js +4274 -0
- package/dist/client/realtime/IRealtimeTransport.js +32 -0
- package/dist/client/realtime/JsonRpcPeer.js +251 -0
- package/dist/client/realtime/channelRate.js +39 -0
- package/dist/client/realtime/platformChannels.js +155 -0
- package/dist/client/syslog/Pdu.js +224 -0
- package/dist/client/syslog/Syslog.js +1159 -0
- package/dist/client/syslog/drivers/pduFlow.js +106 -0
- package/dist/client/syslog/drivers/pduProtocol.js +28 -0
- package/dist/client/syslog/logColor.js +80 -0
- package/dist/client/types/src/Container.d.ts +221 -0
- package/dist/client/types/src/Event.d.ts +171 -0
- package/dist/client/types/src/FileClass.d.ts +184 -0
- package/dist/client/types/src/Service.d.ts +165 -0
- package/dist/client/types/src/Tools.d.ts +116 -0
- package/dist/client/types/src/client/ClientKernel.d.ts +90 -0
- package/dist/client/types/src/client/IClientKernel.d.ts +195 -0
- package/dist/client/types/src/client/angular/index.d.ts +273 -0
- package/dist/client/types/src/client/announce.d.ts +74 -0
- package/dist/client/types/src/client/debugbar/DebugBar.d.ts +279 -0
- package/dist/client/types/src/client/debugbar/format.d.ts +48 -0
- package/dist/client/types/src/client/debugbar/hmr.d.ts +16 -0
- package/dist/client/types/src/client/debugbar/index.d.ts +30 -0
- package/dist/client/types/src/client/debugbar/model.d.ts +158 -0
- package/dist/client/types/src/client/debugbar/network.d.ts +55 -0
- package/dist/client/types/src/client/debugbar/profile.d.ts +99 -0
- package/dist/client/types/src/client/index.d.ts +47 -0
- package/dist/client/types/src/client/react/index.d.ts +207 -0
- package/dist/client/types/src/client/realtime/AdaptiveRate.d.ts +138 -0
- package/dist/client/types/src/client/realtime/BrowserWsTransport.d.ts +27 -0
- package/dist/client/types/src/client/realtime/RealtimeClient.d.ts +573 -0
- package/dist/client/types/src/client/realtime/localEvents.d.ts +53 -0
- package/dist/client/types/src/client/realtime/notice.d.ts +70 -0
- package/dist/client/types/src/client/realtime/observe.d.ts +284 -0
- package/dist/client/types/src/client/roles/index.d.ts +15 -0
- package/dist/client/types/src/client/roles/registry.d.ts +72 -0
- package/dist/client/types/src/client/roles/roles.d.ts +68 -0
- package/dist/client/types/src/client/shim/cli-color.d.ts +2 -0
- package/dist/client/types/src/client/shim/events.d.ts +39 -0
- package/dist/client/types/src/client/shim/util.d.ts +14 -0
- package/dist/client/types/src/client/svelte/index.d.ts +216 -0
- package/dist/client/types/src/client/syslog/context.d.ts +76 -0
- package/dist/client/types/src/client/syslog/errors.d.ts +46 -0
- package/dist/client/types/src/client/syslog/uplink.d.ts +89 -0
- package/dist/client/types/src/client/transport/websocket.d.ts +5 -0
- package/dist/client/types/src/client/vue/index.d.ts +234 -0
- package/dist/client/types/src/colors.d.ts +32 -0
- package/dist/client/types/src/config/infra.d.ts +171 -0
- package/dist/client/types/src/kernel/bootReport.d.ts +112 -0
- package/dist/client/types/src/kernel/readinessRegistry.d.ts +104 -0
- package/dist/client/types/src/realtime/IRealtimeSocket.d.ts +142 -0
- package/dist/client/types/src/realtime/IRealtimeTransport.d.ts +50 -0
- package/dist/client/types/src/realtime/JsonRpcPeer.d.ts +251 -0
- package/dist/client/types/src/realtime/RealtimeEventMap.d.ts +269 -0
- package/dist/client/types/src/realtime/channelRate.d.ts +55 -0
- package/dist/client/types/src/realtime/platformChannels.d.ts +147 -0
- package/dist/client/types/src/syslog/Pdu.d.ts +134 -0
- package/dist/client/types/src/syslog/Syslog.d.ts +482 -0
- package/dist/client/types/src/syslog/drivers/ILogDriver.d.ts +177 -0
- package/dist/client/types/src/syslog/drivers/pduFlow.d.ts +53 -0
- package/dist/client/types/src/syslog/drivers/pduProtocol.d.ts +20 -0
- package/dist/client/types/src/syslog/logColor.d.ts +59 -0
- package/dist/client/types/src/types/ICliKernel.d.ts +28 -0
- package/dist/client/types/src/types/ICommand.d.ts +14 -0
- package/dist/client/types/src/types/IContainer.d.ts +35 -0
- package/dist/client/types/src/types/IKernel.d.ts +138 -0
- package/dist/client/types/src/types/IMcpTool.d.ts +157 -0
- package/dist/client/types/src/types/IModule.d.ts +73 -0
- package/dist/client/types/src/types/IPage.d.ts +119 -0
- package/dist/client/types/src/types/IService.d.ts +62 -0
- package/dist/client/types/src/types/ISyslog.d.ts +58 -0
- package/dist/client/types/src/types/ITransport.d.ts +5 -0
- package/dist/client/types/src/types/globals.d.ts +47 -0
- package/dist/node/Cli.js +750 -0
- package/dist/node/Container.js +367 -0
- package/dist/node/Error.js +309 -0
- package/dist/node/Event.js +198 -0
- package/dist/node/FileClass.js +308 -0
- package/dist/node/Nodefony.js +78 -0
- package/dist/node/Service.js +344 -0
- package/dist/node/Tools.js +205 -0
- package/dist/node/bin/resolveLocalCli.js +10 -0
- package/dist/node/bundler/index.js +103 -0
- package/dist/node/cli/agentTargets.js +461 -0
- package/dist/node/cli/aiMcp.js +553 -0
- package/dist/node/cli/aiMcpReport.js +129 -0
- package/dist/node/cli/aiSync.js +323 -0
- package/dist/node/cli/aiSyncReport.js +142 -0
- package/dist/node/cli/card.js +186 -0
- package/dist/node/cli/cardReport.js +110 -0
- package/dist/node/cli/completion.js +415 -0
- package/dist/node/cli/create.js +805 -0
- package/dist/node/cli/env.js +332 -0
- package/dist/node/cli/envReport.js +159 -0
- package/dist/node/cli/execPortable.js +60 -0
- package/dist/node/cli/gitHooks.js +191 -0
- package/dist/node/cli/gitHooksReport.js +119 -0
- package/dist/node/cli/globalFlags.js +67 -0
- package/dist/node/cli/helpReport.js +288 -0
- package/dist/node/cli/manPage.js +165 -0
- package/dist/node/cli/nodefonyBin.js +61 -0
- package/dist/node/cli/outdated.js +144 -0
- package/dist/node/cli/progress.js +555 -0
- package/dist/node/cli/projectRoot.js +32 -0
- package/dist/node/cli/promptPassword.js +44 -0
- package/dist/node/cli/prompts.js +86 -0
- package/dist/node/cli/scaffold/destination.js +92 -0
- package/dist/node/cli/scaffold/engine.js +2156 -0
- package/dist/node/cli/scaffold/entityFields.js +589 -0
- package/dist/node/cli/scaffold/format.js +243 -0
- package/dist/node/cli/scaffold/interactive.js +124 -0
- package/dist/node/cli/scaffold/moduleLayout.js +38 -0
- package/dist/node/cli/scaffold/reservedEntities.js +74 -0
- package/dist/node/cli/scaffold/spec.js +704 -0
- package/dist/node/cli/scaffold/steps.js +40 -0
- package/dist/node/cli/scaffold/userContractSource.js +133 -0
- package/dist/node/cli/scaffold/versions.js +57 -0
- package/dist/node/cli/scaffold/writer.js +172 -0
- package/dist/node/cli/startMenu.js +496 -0
- package/dist/node/cli/symbols.js +205 -0
- package/dist/node/cli/sysexits.js +34 -0
- package/dist/node/cli/tableReport.js +184 -0
- package/dist/node/cli/usageReport.js +144 -0
- package/dist/node/colors.js +63 -0
- package/dist/node/command/Builder.js +153 -0
- package/dist/node/command/Command.js +348 -0
- package/dist/node/config/configProvenance.js +101 -0
- package/dist/node/config/defaults.js +39 -0
- package/dist/node/config/defineConfig.js +129 -0
- package/dist/node/config/defineEnv.js +264 -0
- package/dist/node/config/envExample.js +41 -0
- package/dist/node/config/envOverride.js +423 -0
- package/dist/node/config/infra.js +163 -0
- package/dist/node/config/reactivity.js +23 -0
- package/dist/node/config/reservedEnv.js +118 -0
- package/dist/node/config/schema.js +134 -0
- package/dist/node/config/use.js +24 -0
- package/dist/node/finder/File.js +49 -0
- package/dist/node/finder/FileResult.js +86 -0
- package/dist/node/finder/Finder.js +201 -0
- package/dist/node/finder/Result.js +45 -0
- package/dist/node/index.js +121 -0
- package/dist/node/kernel/BootConfigurationError.js +54 -0
- package/dist/node/kernel/CliKernel.js +630 -0
- package/dist/node/kernel/Kernel.js +2198 -0
- package/dist/node/kernel/Module.js +453 -0
- package/dist/node/kernel/adminPlane/adminCaller.js +98 -0
- package/dist/node/kernel/adminPlane/adminRbac.js +51 -0
- package/dist/node/kernel/adminPlane/catalog.js +158 -0
- package/dist/node/kernel/adminPlane/executeAdmin.js +78 -0
- package/dist/node/kernel/checks/deep.js +335 -0
- package/dist/node/kernel/checks/freshness.js +139 -0
- package/dist/node/kernel/checks/gating.js +231 -0
- package/dist/node/kernel/checks/guards.js +232 -0
- package/dist/node/kernel/checks/lastBoot.js +136 -0
- package/dist/node/kernel/checks/live.js +330 -0
- package/dist/node/kernel/checks/packageDeps.js +292 -0
- package/dist/node/kernel/checks/readiness.js +153 -0
- package/dist/node/kernel/checks/renderReport.js +780 -0
- package/dist/node/kernel/checks/report.js +421 -0
- package/dist/node/kernel/checks/runDoctor.js +731 -0
- package/dist/node/kernel/checks/surface.js +364 -0
- package/dist/node/kernel/checks/walk.js +100 -0
- package/dist/node/kernel/checks/wiring.js +450 -0
- package/dist/node/kernel/commands/AiMcpCommand.js +65 -0
- package/dist/node/kernel/commands/AiSyncCommand.js +48 -0
- package/dist/node/kernel/commands/BuildCommand.js +49 -0
- package/dist/node/kernel/commands/CardCommand.js +50 -0
- package/dist/node/kernel/commands/ClusterCommand.js +58 -0
- package/dist/node/kernel/commands/CompletionCommand.js +31 -0
- package/dist/node/kernel/commands/CreateCommand.js +45 -0
- package/dist/node/kernel/commands/DevCommand.js +99 -0
- package/dist/node/kernel/commands/DoctorCommand.js +115 -0
- package/dist/node/kernel/commands/EnvCommand.js +52 -0
- package/dist/node/kernel/commands/GitHooksCommand.js +47 -0
- package/dist/node/kernel/commands/InspectCommand.js +153 -0
- package/dist/node/kernel/commands/InstallCommand.js +20 -0
- package/dist/node/kernel/commands/MenuCommand.js +261 -0
- package/dist/node/kernel/commands/OutdatedCommand.js +164 -0
- package/dist/node/kernel/commands/ProdCommand.js +60 -0
- package/dist/node/kernel/commands/StatusCommand.js +30 -0
- package/dist/node/kernel/commands/StopCommand.js +35 -0
- package/dist/node/kernel/commands/SymbolsCommand.js +45 -0
- package/dist/node/kernel/commands/runtimeLauncher.js +95 -0
- package/dist/node/kernel/decorators/kernelDecorator.js +110 -0
- package/dist/node/kernel/injector/injector.js +137 -0
- package/dist/node/kernel/injector/serviceOrder.js +106 -0
- package/dist/node/kernel/inspect/adminSubjects.js +194 -0
- package/dist/node/kernel/inspect/docOutline.js +86 -0
- package/dist/node/kernel/lifecycleTags.js +76 -0
- package/dist/node/kernel/moduleConfig.js +75 -0
- package/dist/node/kernel/moduleGating.js +68 -0
- package/dist/node/kernel/readinessRegistry.js +98 -0
- package/dist/node/kernel/resolveModuleEntry.js +61 -0
- package/dist/node/mcp/caller.js +40 -0
- package/dist/node/mcp/guard.js +51 -0
- package/dist/node/mcp/protocol.js +157 -0
- package/dist/node/mcp/server.js +216 -0
- package/dist/node/mcp/tools.js +861 -0
- package/dist/node/oauth/authorizationServer.js +221 -0
- package/dist/node/oauth/protectedResource.js +293 -0
- package/dist/node/package.js +4 -0
- package/dist/node/realtime/IRealtimeTransport.js +32 -0
- package/dist/node/realtime/JsonRpcPeer.js +251 -0
- package/dist/node/realtime/RealtimeEventMap.js +15 -0
- package/dist/node/realtime/channelRate.js +39 -0
- package/dist/node/realtime/platformChannels.js +155 -0
- package/dist/node/runtime/GcScheduler.js +92 -0
- package/dist/node/runtime/RequestContext.js +76 -0
- package/dist/node/runtime/bearer.js +84 -0
- package/dist/node/runtime/engineEnvironment.js +79 -0
- package/dist/node/runtime/loadEnv.js +105 -0
- package/dist/node/runtime/pageFacets.js +85 -0
- package/dist/node/runtime/pageFilters.js +103 -0
- package/dist/node/runtime/pageGuard.js +84 -0
- package/dist/node/runtime/pageQuery.js +160 -0
- package/dist/node/runtime/pageSort.js +114 -0
- package/dist/node/runtime/redact.js +43 -0
- package/dist/node/runtime/withTimeout.js +71 -0
- package/dist/node/service/cluster/ClusterManager.js +202 -0
- package/dist/node/service/cluster/ClusterProbeAggregator.js +120 -0
- package/dist/node/service/cluster/ClusterRelay.js +74 -0
- package/dist/node/service/cluster/clusterMaster.js +65 -0
- package/dist/node/service/cluster/clusterMessage.js +70 -0
- package/dist/node/service/cluster/cpuQuota.js +59 -0
- package/dist/node/service/cluster/instanceProbe.js +52 -0
- package/dist/node/service/cluster/podEnvironment.js +48 -0
- package/dist/node/service/cluster/processProbe.js +70 -0
- package/dist/node/service/cluster/richProcessProbe.js +115 -0
- package/dist/node/service/cluster/topology.js +71 -0
- package/dist/node/service/dev/BootReporter.js +490 -0
- package/dist/node/service/dev/DevSupervisor.js +1004 -0
- package/dist/node/service/dev/bootVerdict.js +158 -0
- package/dist/node/service/dev/detachedStart.js +372 -0
- package/dist/node/service/dev/devProcess.js +1137 -0
- package/dist/node/service/dev/devProjects.js +138 -0
- package/dist/node/service/dev/devStatusReport.js +395 -0
- package/dist/node/service/dev/devStop.js +263 -0
- package/dist/node/service/fetchService.js +35 -0
- package/dist/node/service/gitService.js +62 -0
- package/dist/node/syslog/Pdu.js +224 -0
- package/dist/node/syslog/Syslog.js +1159 -0
- package/dist/node/syslog/drivers/ClusterFileLogDriver.js +114 -0
- package/dist/node/syslog/drivers/FileLogDriver.js +127 -0
- package/dist/node/syslog/drivers/ILogDriver.js +26 -0
- package/dist/node/syslog/drivers/LokiLogDriver.js +144 -0
- package/dist/node/syslog/drivers/MemoryLogDriver.js +33 -0
- package/dist/node/syslog/drivers/OpenSearchLogDriver.js +159 -0
- package/dist/node/syslog/drivers/builtinLogDrivers.js +114 -0
- package/dist/node/syslog/drivers/filterPdus.js +71 -0
- package/dist/node/syslog/drivers/logDriverRegistry.js +83 -0
- package/dist/node/syslog/drivers/opensearchShared.js +17 -0
- package/dist/node/syslog/drivers/pduFlow.js +106 -0
- package/dist/node/syslog/drivers/pduProtocol.js +28 -0
- package/dist/node/syslog/httpFetch.js +43 -0
- package/dist/node/syslog/logColor.js +80 -0
- package/dist/node/syslog/sinks/FileSink.js +142 -0
- package/dist/node/syslog/transports/BatchingHttpTransport.js +98 -0
- package/dist/node/syslog/transports/ConsoleTransport.js +14 -0
- package/dist/node/syslog/transports/FileTransport.js +17 -0
- package/dist/node/syslog/transports/HttpTransport.js +44 -0
- package/dist/node/syslog/transports/LokiTransport.js +80 -0
- package/dist/node/syslog/transports/OpenSearchTransport.js +53 -0
- package/dist/node/syslog/transports/SyslogTransport.js +13 -0
- package/dist/node/syslog/transports/index.js +8 -0
- package/dist/node/testing/index.js +190 -0
- package/dist/types/Cli.d.ts +177 -0
- package/dist/types/Container.d.ts +221 -0
- package/dist/types/Error.d.ts +162 -0
- package/dist/types/Event.d.ts +171 -0
- package/dist/types/FileClass.d.ts +184 -0
- package/dist/types/Nodefony.d.ts +66 -0
- package/dist/types/Service.d.ts +165 -0
- package/dist/types/Tools.d.ts +116 -0
- package/dist/types/bin/resolveLocalCli.d.ts +49 -0
- package/dist/types/bundler/index.d.ts +66 -0
- package/dist/types/cli/agentTargets.d.ts +378 -0
- package/dist/types/cli/aiMcp.d.ts +239 -0
- package/dist/types/cli/aiMcpReport.d.ts +113 -0
- package/dist/types/cli/aiSync.d.ts +68 -0
- package/dist/types/cli/aiSyncReport.d.ts +149 -0
- package/dist/types/cli/card.d.ts +49 -0
- package/dist/types/cli/cardReport.d.ts +127 -0
- package/dist/types/cli/completion.d.ts +154 -0
- package/dist/types/cli/create.d.ts +177 -0
- package/dist/types/cli/env.d.ts +103 -0
- package/dist/types/cli/envReport.d.ts +153 -0
- package/dist/types/cli/execPortable.d.ts +54 -0
- package/dist/types/cli/gitHooks.d.ts +48 -0
- package/dist/types/cli/gitHooksReport.d.ts +101 -0
- package/dist/types/cli/globalFlags.d.ts +48 -0
- package/dist/types/cli/helpReport.d.ts +110 -0
- package/dist/types/cli/manPage.d.ts +21 -0
- package/dist/types/cli/nodefonyBin.d.ts +45 -0
- package/dist/types/cli/outdated.d.ts +119 -0
- package/dist/types/cli/progress.d.ts +349 -0
- package/dist/types/cli/projectRoot.d.ts +19 -0
- package/dist/types/cli/promptPassword.d.ts +22 -0
- package/dist/types/cli/prompts.d.ts +102 -0
- package/dist/types/cli/scaffold/destination.d.ts +70 -0
- package/dist/types/cli/scaffold/engine.d.ts +545 -0
- package/dist/types/cli/scaffold/entityFields.d.ts +238 -0
- package/dist/types/cli/scaffold/format.d.ts +78 -0
- package/dist/types/cli/scaffold/interactive.d.ts +11 -0
- package/dist/types/cli/scaffold/moduleLayout.d.ts +69 -0
- package/dist/types/cli/scaffold/reservedEntities.d.ts +49 -0
- package/dist/types/cli/scaffold/spec.d.ts +159 -0
- package/dist/types/cli/scaffold/steps.d.ts +24 -0
- package/dist/types/cli/scaffold/userContractSource.d.ts +86 -0
- package/dist/types/cli/scaffold/versions.d.ts +14 -0
- package/dist/types/cli/scaffold/writer.d.ts +100 -0
- package/dist/types/cli/startMenu.d.ts +195 -0
- package/dist/types/cli/symbols.d.ts +84 -0
- package/dist/types/cli/sysexits.d.ts +31 -0
- package/dist/types/cli/tableReport.d.ts +44 -0
- package/dist/types/cli/usageReport.d.ts +108 -0
- package/dist/types/client/ClientKernel.d.ts +90 -0
- package/dist/types/client/IClientKernel.d.ts +195 -0
- package/dist/types/client/angular/index.d.ts +273 -0
- package/dist/types/client/announce.d.ts +74 -0
- package/dist/types/client/debugbar/DebugBar.d.ts +279 -0
- package/dist/types/client/debugbar/format.d.ts +48 -0
- package/dist/types/client/debugbar/hmr.d.ts +16 -0
- package/dist/types/client/debugbar/index.d.ts +30 -0
- package/dist/types/client/debugbar/model.d.ts +158 -0
- package/dist/types/client/debugbar/network.d.ts +55 -0
- package/dist/types/client/debugbar/profile.d.ts +99 -0
- package/dist/types/client/index.d.ts +47 -0
- package/dist/types/client/react/index.d.ts +207 -0
- package/dist/types/client/realtime/AdaptiveRate.d.ts +138 -0
- package/dist/types/client/realtime/BrowserWsTransport.d.ts +27 -0
- package/dist/types/client/realtime/RealtimeClient.d.ts +573 -0
- package/dist/types/client/realtime/localEvents.d.ts +53 -0
- package/dist/types/client/realtime/notice.d.ts +70 -0
- package/dist/types/client/realtime/observe.d.ts +284 -0
- package/dist/types/client/roles/index.d.ts +15 -0
- package/dist/types/client/roles/registry.d.ts +72 -0
- package/dist/types/client/roles/roles.d.ts +68 -0
- package/dist/types/client/shim/cli-color.d.ts +2 -0
- package/dist/types/client/shim/events.d.ts +39 -0
- package/dist/types/client/shim/util.d.ts +14 -0
- package/dist/types/client/svelte/index.d.ts +216 -0
- package/dist/types/client/syslog/context.d.ts +76 -0
- package/dist/types/client/syslog/errors.d.ts +46 -0
- package/dist/types/client/syslog/uplink.d.ts +89 -0
- package/dist/types/client/transport/websocket.d.ts +5 -0
- package/dist/types/client/vue/index.d.ts +234 -0
- package/dist/types/colors.d.ts +32 -0
- package/dist/types/command/Builder.d.ts +47 -0
- package/dist/types/command/Command.d.ts +268 -0
- package/dist/types/config/configMeta.d.ts +53 -0
- package/dist/types/config/configProvenance.d.ts +58 -0
- package/dist/types/config/defaults.d.ts +33 -0
- package/dist/types/config/defineConfig.d.ts +70 -0
- package/dist/types/config/defineEnv.d.ts +170 -0
- package/dist/types/config/envExample.d.ts +23 -0
- package/dist/types/config/envOverride.d.ts +236 -0
- package/dist/types/config/index.d.ts +23 -0
- package/dist/types/config/infra.d.ts +171 -0
- package/dist/types/config/reactivity.d.ts +36 -0
- package/dist/types/config/reservedEnv.d.ts +145 -0
- package/dist/types/config/schema.d.ts +113 -0
- package/dist/types/config/types.d.ts +374 -0
- package/dist/types/config/use.d.ts +80 -0
- package/dist/types/finder/File.d.ts +26 -0
- package/dist/types/finder/FileResult.d.ts +14 -0
- package/dist/types/finder/Finder.d.ts +51 -0
- package/dist/types/finder/Result.d.ts +10 -0
- package/dist/types/index.d.ts +205 -0
- package/dist/types/kernel/BootConfigurationError.d.ts +50 -0
- package/dist/types/kernel/CliKernel.d.ts +289 -0
- package/dist/types/kernel/Kernel.d.ts +1255 -0
- package/dist/types/kernel/Module.d.ts +326 -0
- package/dist/types/kernel/adminPlane/adminCaller.d.ts +105 -0
- package/dist/types/kernel/adminPlane/adminRbac.d.ts +44 -0
- package/dist/types/kernel/adminPlane/catalog.d.ts +122 -0
- package/dist/types/kernel/adminPlane/executeAdmin.d.ts +99 -0
- package/dist/types/kernel/bootReport.d.ts +112 -0
- package/dist/types/kernel/checks/deep.d.ts +122 -0
- package/dist/types/kernel/checks/freshness.d.ts +49 -0
- package/dist/types/kernel/checks/gating.d.ts +134 -0
- package/dist/types/kernel/checks/guards.d.ts +57 -0
- package/dist/types/kernel/checks/lastBoot.d.ts +189 -0
- package/dist/types/kernel/checks/live.d.ts +110 -0
- package/dist/types/kernel/checks/packageDeps.d.ts +44 -0
- package/dist/types/kernel/checks/readiness.d.ts +97 -0
- package/dist/types/kernel/checks/renderReport.d.ts +107 -0
- package/dist/types/kernel/checks/report.d.ts +414 -0
- package/dist/types/kernel/checks/runDoctor.d.ts +361 -0
- package/dist/types/kernel/checks/surface.d.ts +148 -0
- package/dist/types/kernel/checks/walk.d.ts +45 -0
- package/dist/types/kernel/checks/wiring.d.ts +54 -0
- package/dist/types/kernel/commands/AiMcpCommand.d.ts +39 -0
- package/dist/types/kernel/commands/AiSyncCommand.d.ts +28 -0
- package/dist/types/kernel/commands/BuildCommand.d.ts +13 -0
- package/dist/types/kernel/commands/CardCommand.d.ts +34 -0
- package/dist/types/kernel/commands/ClusterCommand.d.ts +29 -0
- package/dist/types/kernel/commands/CompletionCommand.d.ts +17 -0
- package/dist/types/kernel/commands/CreateCommand.d.ts +16 -0
- package/dist/types/kernel/commands/DevCommand.d.ts +40 -0
- package/dist/types/kernel/commands/DoctorCommand.d.ts +55 -0
- package/dist/types/kernel/commands/EnvCommand.d.ts +35 -0
- package/dist/types/kernel/commands/GitHooksCommand.d.ts +27 -0
- package/dist/types/kernel/commands/InspectCommand.d.ts +59 -0
- package/dist/types/kernel/commands/InstallCommand.d.ts +7 -0
- package/dist/types/kernel/commands/MenuCommand.d.ts +58 -0
- package/dist/types/kernel/commands/OutdatedCommand.d.ts +47 -0
- package/dist/types/kernel/commands/ProdCommand.d.ts +29 -0
- package/dist/types/kernel/commands/StatusCommand.d.ts +17 -0
- package/dist/types/kernel/commands/StopCommand.d.ts +17 -0
- package/dist/types/kernel/commands/SymbolsCommand.d.ts +29 -0
- package/dist/types/kernel/commands/runtimeLauncher.d.ts +76 -0
- package/dist/types/kernel/decorators/kernelDecorator.d.ts +76 -0
- package/dist/types/kernel/injector/injector.d.ts +47 -0
- package/dist/types/kernel/injector/serviceOrder.d.ts +29 -0
- package/dist/types/kernel/inspect/adminSubjects.d.ts +169 -0
- package/dist/types/kernel/inspect/docOutline.d.ts +53 -0
- package/dist/types/kernel/lifecycleTags.d.ts +79 -0
- package/dist/types/kernel/moduleConfig.d.ts +35 -0
- package/dist/types/kernel/moduleGating.d.ts +78 -0
- package/dist/types/kernel/readinessRegistry.d.ts +104 -0
- package/dist/types/kernel/resolveModuleEntry.d.ts +46 -0
- package/dist/types/mcp/caller.d.ts +55 -0
- package/dist/types/mcp/guard.d.ts +66 -0
- package/dist/types/mcp/protocol.d.ts +163 -0
- package/dist/types/mcp/server.d.ts +70 -0
- package/dist/types/mcp/tools.d.ts +209 -0
- package/dist/types/oauth/authorizationServer.d.ts +204 -0
- package/dist/types/oauth/protectedResource.d.ts +339 -0
- package/dist/types/realtime/IRealtimeSocket.d.ts +142 -0
- package/dist/types/realtime/IRealtimeTransport.d.ts +50 -0
- package/dist/types/realtime/JsonRpcPeer.d.ts +251 -0
- package/dist/types/realtime/RealtimeEventMap.d.ts +269 -0
- package/dist/types/realtime/channelRate.d.ts +55 -0
- package/dist/types/realtime/platformChannels.d.ts +147 -0
- package/dist/types/runtime/GcScheduler.d.ts +96 -0
- package/dist/types/runtime/RequestContext.d.ts +152 -0
- package/dist/types/runtime/bearer.d.ts +88 -0
- package/dist/types/runtime/engineEnvironment.d.ts +115 -0
- package/dist/types/runtime/loadEnv.d.ts +86 -0
- package/dist/types/runtime/pageFacets.d.ts +104 -0
- package/dist/types/runtime/pageFilters.d.ts +139 -0
- package/dist/types/runtime/pageGuard.d.ts +78 -0
- package/dist/types/runtime/pageQuery.d.ts +138 -0
- package/dist/types/runtime/pageSort.d.ts +86 -0
- package/dist/types/runtime/redact.d.ts +27 -0
- package/dist/types/runtime/withTimeout.d.ts +51 -0
- package/dist/types/service/cluster/ClusterManager.d.ts +112 -0
- package/dist/types/service/cluster/ClusterProbeAggregator.d.ts +68 -0
- package/dist/types/service/cluster/ClusterRelay.d.ts +57 -0
- package/dist/types/service/cluster/clusterMaster.d.ts +40 -0
- package/dist/types/service/cluster/clusterMessage.d.ts +94 -0
- package/dist/types/service/cluster/cpuQuota.d.ts +37 -0
- package/dist/types/service/cluster/instanceProbe.d.ts +82 -0
- package/dist/types/service/cluster/podEnvironment.d.ts +35 -0
- package/dist/types/service/cluster/processProbe.d.ts +53 -0
- package/dist/types/service/cluster/richProcessProbe.d.ts +77 -0
- package/dist/types/service/cluster/topology.d.ts +64 -0
- package/dist/types/service/dev/BootReporter.d.ts +67 -0
- package/dist/types/service/dev/DevSupervisor.d.ts +117 -0
- package/dist/types/service/dev/bootVerdict.d.ts +99 -0
- package/dist/types/service/dev/detachedStart.d.ts +164 -0
- package/dist/types/service/dev/devProcess.d.ts +638 -0
- package/dist/types/service/dev/devProjects.d.ts +121 -0
- package/dist/types/service/dev/devStatusReport.d.ts +141 -0
- package/dist/types/service/dev/devStop.d.ts +57 -0
- package/dist/types/service/fetchService.d.ts +29 -0
- package/dist/types/service/gitService.d.ts +24 -0
- package/dist/types/syslog/Pdu.d.ts +134 -0
- package/dist/types/syslog/Syslog.d.ts +482 -0
- package/dist/types/syslog/drivers/ClusterFileLogDriver.d.ts +40 -0
- package/dist/types/syslog/drivers/FileLogDriver.d.ts +55 -0
- package/dist/types/syslog/drivers/ILogDriver.d.ts +177 -0
- package/dist/types/syslog/drivers/LokiLogDriver.d.ts +44 -0
- package/dist/types/syslog/drivers/MemoryLogDriver.d.ts +20 -0
- package/dist/types/syslog/drivers/OpenSearchLogDriver.d.ts +40 -0
- package/dist/types/syslog/drivers/builtinLogDrivers.d.ts +43 -0
- package/dist/types/syslog/drivers/filterPdus.d.ts +21 -0
- package/dist/types/syslog/drivers/logDriverRegistry.d.ts +100 -0
- package/dist/types/syslog/drivers/opensearchShared.d.ts +11 -0
- package/dist/types/syslog/drivers/pduFlow.d.ts +53 -0
- package/dist/types/syslog/drivers/pduProtocol.d.ts +20 -0
- package/dist/types/syslog/httpFetch.d.ts +48 -0
- package/dist/types/syslog/logColor.d.ts +59 -0
- package/dist/types/syslog/sinks/FileSink.d.ts +78 -0
- package/dist/types/syslog/transports/BatchingHttpTransport.d.ts +59 -0
- package/dist/types/syslog/transports/ConsoleTransport.d.ts +8 -0
- package/dist/types/syslog/transports/FileTransport.d.ts +13 -0
- package/dist/types/syslog/transports/HttpTransport.d.ts +15 -0
- package/dist/types/syslog/transports/LokiTransport.d.ts +45 -0
- package/dist/types/syslog/transports/OpenSearchTransport.d.ts +40 -0
- package/dist/types/syslog/transports/SyslogTransport.d.ts +9 -0
- package/dist/types/syslog/transports/index.d.ts +12 -0
- package/dist/types/testing/index.d.ts +197 -0
- package/dist/types/types/IAdminApi.d.ts +246 -0
- package/dist/types/types/ICliKernel.d.ts +28 -0
- package/dist/types/types/ICommand.d.ts +14 -0
- package/dist/types/types/IContainer.d.ts +35 -0
- package/dist/types/types/IIdempotencyStore.d.ts +159 -0
- package/dist/types/types/IKernel.d.ts +138 -0
- package/dist/types/types/IMcpTool.d.ts +157 -0
- package/dist/types/types/IModule.d.ts +73 -0
- package/dist/types/types/IModuleManifest.d.ts +49 -0
- package/dist/types/types/IPage.d.ts +119 -0
- package/dist/types/types/IService.d.ts +62 -0
- package/dist/types/types/ISyslog.d.ts +58 -0
- package/dist/types/types/ITransport.d.ts +5 -0
- package/dist/types/types/globals.d.ts +47 -0
- package/docs/angular-services.md +318 -0
- package/docs/catalogue.md +184 -0
- package/docs/cli.md +369 -0
- package/docs/client.md +616 -0
- package/docs/debugbar.md +218 -0
- package/docs/environnement.md +308 -0
- package/docs/index.md +388 -0
- package/docs/kernel.md +670 -0
- package/docs/progression.md +228 -0
- package/docs/react-hooks.md +686 -0
- package/docs/request-context.md +507 -0
- package/docs/service.md +590 -0
- package/docs/svelte-reactivite.md +293 -0
- package/docs/syslog.md +848 -0
- package/docs/testing.md +203 -0
- package/docs/vue-composables.md +255 -0
- package/man/nodefony.1 +152 -0
- package/package.json +163 -83
- package/templates/app/agents/AGENTS.md.tpl +967 -0
- package/templates/app/agents/POINTEUR.md.tpl +12 -0
- package/templates/app/base/Dockerfile.tpl +104 -0
- package/templates/app/base/README.md.tpl +314 -0
- package/templates/app/base/dockerignore.tpl +28 -0
- package/templates/app/base/env.ts.tpl +130 -0
- package/templates/app/base/gitattributes.tpl +28 -0
- package/templates/app/base/github/workflows/ci.yml.tpl +91 -0
- package/templates/app/base/gitignore.tpl +46 -0
- package/templates/app/base/gitlab-ci.yml.tpl +42 -0
- package/templates/app/base/index.ts.tpl +69 -0
- package/templates/app/base/nodefony.config.ts.tpl +342 -0
- package/templates/app/base/oxlintrc.json.tpl +127 -0
- package/templates/app/base/package.json.tpl +75 -0
- package/templates/app/base/prettierignore.tpl +24 -0
- package/templates/app/base/prettierrc.json.tpl +12 -0
- package/templates/app/base/rolldown.config.ts.tpl +8 -0
- package/templates/app/base/tests/config.test.ts.tpl +29 -0
- package/templates/app/base/tests/e2e.setup.ts.tpl +181 -0
- package/templates/app/base/tests/e2e.test.ts.tpl +105 -0
- package/templates/app/base/tests/migrations.e2e.test.ts.tpl +579 -0
- package/templates/app/base/tsconfig.json.tpl +47 -0
- package/templates/app/base/vitest.config.ts.tpl +88 -0
- package/templates/app/base/vitest.e2e.config.ts.tpl +39 -0
- package/templates/app/complete/compose.yaml.tpl +328 -0
- package/templates/app/complete/deploy/migrate-job.yaml.tpl +100 -0
- package/templates/app/complete/docker/db/init-nodefony-e2e.sql.tpl +30 -0
- package/templates/app/complete/docker/grafana/provisioning/datasources/loki.yaml.tpl +15 -0
- package/templates/app/complete/env.local.tpl +11 -0
- package/templates/app/complete/env.tpl +53 -0
- package/templates/app/complete/nodefony/entity/User.ts.tpl +69 -0
- package/templates/app/complete/nodefony/security/provisionUsers.ts.tpl +124 -0
- package/templates/app/complete/nodefony/service/AppBannerService.ts.tpl +98 -0
- package/templates/app/complete/nodefony/service/AppInfoService.ts.tpl +85 -0
- package/templates/app/frontend/angular/frontend/src/accent.css.tpl +34 -0
- package/templates/app/frontend/angular/frontend/src/app/app.component.ts.tpl +400 -0
- package/templates/app/frontend/react/frontend/src/App.tsx.tpl +421 -0
- package/templates/app/frontend/react/frontend/src/accent.css.tpl +30 -0
- package/templates/app/frontend/shared/frontend/src/brand.ts.tpl +3 -0
- package/templates/app/frontend/shared/frontend/src/showcase.css.tpl +224 -0
- package/templates/app/frontend/shared/nodefony/controllers/AppController.ts.tpl +45 -0
- package/templates/app/frontend/svelte/frontend/src/App.svelte.tpl +371 -0
- package/templates/app/frontend/svelte/frontend/src/accent.css.tpl +34 -0
- package/templates/app/frontend/vue/frontend/src/App.vue.tpl +367 -0
- package/templates/app/frontend/vue/frontend/src/accent.css.tpl +34 -0
- package/templates/app/home/nodefony/controllers/HomeController.ts.tpl +38 -0
- package/templates/command/nodefony/command/__NAME__.ts.tpl +132 -0
- package/templates/controller/duplex/nodefony/controllers/__NAME__.ts.tpl +188 -0
- package/templates/controller/example/nodefony/controllers/__NAME__.ts.tpl +348 -0
- package/templates/controller/hello/nodefony/controllers/__NAME__.ts.tpl +143 -0
- package/templates/controller/realtime/nodefony/controllers/__NAME__.ts.tpl +153 -0
- package/templates/controller/realtime/tests/__KEBAB__-realtime.test.ts.tpl +79 -0
- package/templates/controller/rest/nodefony/controllers/__NAME__.ts.tpl +159 -0
- package/templates/entity/base/nodefony/entity/__PASCAL__.schema.ts.tpl +31 -0
- package/templates/entity/base/nodefony/entity/__PASCAL__.ts.tpl +68 -0
- package/templates/entity/controller/nodefony/controllers/__PASCAL__Controller.ts.tpl +335 -0
- package/templates/entity/service/nodefony/service/__PASCAL__Service.ts.tpl +126 -0
- package/templates/entity/tests/tests/__KEBAB__.e2e.test.ts.tpl +358 -0
- package/templates/entity/tests/tests/__KEBAB__.test.ts.tpl +87 -0
- package/templates/front/angular/frontend/src/app/app.component.ts.tpl +30 -0
- package/templates/front/base/nodefony/controllers/__NAME__.ts.tpl +60 -0
- package/templates/front/react/frontend/src/App.tsx.tpl +26 -0
- package/templates/front/svelte/frontend/src/App.svelte.tpl +19 -0
- package/templates/front/vue/frontend/src/App.vue.tpl +23 -0
- package/templates/module/ai/AGENTS.md.tpl +71 -0
- package/templates/module/base/README.md.tpl +62 -0
- package/templates/module/base/docs/index.md.tpl +55 -0
- package/templates/module/base/index.ts.tpl +50 -0
- package/templates/module/base/nodefony/config/config.ts.tpl +60 -0
- package/templates/module/base/nodefony/config/defineModuleConfig.ts.tpl +55 -0
- package/templates/module/base/nodefony/src/errors/__PASCAL__Error.ts.tpl +20 -0
- package/templates/module/base/package.json.tpl +53 -0
- package/templates/module/base/rolldown.config.ts.tpl +14 -0
- package/templates/module/base/tests/__KEBAB__.test.ts.tpl +39 -0
- package/templates/module/base/tsconfig.json.tpl +42 -0
- package/templates/module/base/vitest.config.ts.tpl +27 -0
- package/templates/module/packages/CLAUDE.md.tpl +51 -0
- package/templates/module/packages/MEMORY.md.tpl +39 -0
- package/templates/module/packages/tsconfig.declarations.json.tpl +19 -0
- package/templates/module/packages/tsconfig.tests.json.tpl +11 -0
- package/templates/module/service/nodefony/interfaces/I__PASCAL__Service.ts.tpl +14 -0
- package/templates/module/service/nodefony/interfaces/index.ts.tpl +1 -0
- package/templates/module/service/nodefony/service/__PASCAL__Service.ts.tpl +116 -0
- package/templates/service/nodefony/interfaces/I__PASCAL__Service.ts.tpl +19 -0
- package/templates/service/nodefony/service/__PASCAL__Service.ts.tpl +136 -0
- package/templates/service/tests/__PASCAL__Service.test.ts.tpl +53 -0
- package/templates/shared/front-entry/angular/frontend/src/main.ts.tpl +17 -0
- package/templates/shared/front-entry/react/frontend/src/main.tsx.tpl +11 -0
- package/templates/shared/front-entry/svelte/frontend/src/main.ts.tpl +13 -0
- package/templates/shared/front-entry/vue/frontend/src/main.ts.tpl +12 -0
- package/templates/shared/front-registrar/nodefony/frontend/register__PASCAL__Entry.ts.tpl +40 -0
- package/templates/shared/front-shell/frontend/index.html.tpl +39 -0
- package/templates/shared/ng-app-tsconfig/frontend/tsconfig.app.json.tpl +18 -0
- package/templates/shared/svelte-shim/frontend/src/env.d.ts.tpl +12 -0
- package/templates/shared/vue-shim/frontend/src/env.d.ts.tpl +15 -0
- package/.yarnclean +0 -45
- package/CHANGELOG.md +0 -406
- package/autoloader.es6 +0 -253
- package/builder.es6 +0 -366
- package/cli/builder/bundles/bundle.js +0 -328
- package/cli/builder/bundles/controller.js +0 -73
- package/cli/builder/bundles/users-bundle/.yarnclean +0 -45
- package/cli/builder/bundles/users-bundle/Command/fixtureTask.js +0 -47
- package/cli/builder/bundles/users-bundle/Command/usersCommand.js +0 -105
- package/cli/builder/bundles/users-bundle/Entity/mongoose/userEntity.js +0 -168
- package/cli/builder/bundles/users-bundle/Entity/sequelize/userEntity.js +0 -231
- package/cli/builder/bundles/users-bundle/Fixtures/users.js +0 -117
- package/cli/builder/bundles/users-bundle/Fixtures/usersFixtures.js +0 -114
- package/cli/builder/bundles/users-bundle/Resources/config/config.js +0 -90
- package/cli/builder/bundles/users-bundle/Resources/config/routing.js +0 -17
- package/cli/builder/bundles/users-bundle/Resources/config/security.js +0 -96
- package/cli/builder/bundles/users-bundle/Resources/config/services.js +0 -7
- package/cli/builder/bundles/users-bundle/Resources/config/webpack/webpack.dev.config.js +0 -13
- package/cli/builder/bundles/users-bundle/Resources/config/webpack/webpack.prod.config.js +0 -31
- package/cli/builder/bundles/users-bundle/Resources/config/webpack.config.js +0 -146
- package/cli/builder/bundles/users-bundle/Resources/js/users.js +0 -153
- package/cli/builder/bundles/users-bundle/Resources/public/favicon.ico +0 -0
- package/cli/builder/bundles/users-bundle/Resources/public/images/users-logo.png +0 -0
- package/cli/builder/bundles/users-bundle/Resources/scss/awesome/font-awesome.config.js +0 -11
- package/cli/builder/bundles/users-bundle/Resources/scss/custom.scss +0 -23
- package/cli/builder/bundles/users-bundle/Resources/scss/users.scss +0 -59
- package/cli/builder/bundles/users-bundle/Resources/swagger/openapi/login.js +0 -235
- package/cli/builder/bundles/users-bundle/Resources/swagger/openapi/users.js +0 -232
- package/cli/builder/bundles/users-bundle/Resources/translations/login.en_en.yml +0 -14
- package/cli/builder/bundles/users-bundle/Resources/translations/login.fr_fr.yml +0 -14
- package/cli/builder/bundles/users-bundle/Resources/translations/users.en_en.yml +0 -35
- package/cli/builder/bundles/users-bundle/Resources/translations/users.fr_fr.yml +0 -36
- package/cli/builder/bundles/users-bundle/Resources/views/base.html.twig +0 -32
- package/cli/builder/bundles/users-bundle/Resources/views/footer.html.twig +0 -7
- package/cli/builder/bundles/users-bundle/Resources/views/header.html.twig +0 -90
- package/cli/builder/bundles/users-bundle/Resources/views/login/login.html.twig +0 -43
- package/cli/builder/bundles/users-bundle/Resources/views/users/createUser.html.twig +0 -296
- package/cli/builder/bundles/users-bundle/Resources/views/users/readUsers.html.twig +0 -94
- package/cli/builder/bundles/users-bundle/controller/api/graphql/graphqlController.js +0 -56
- package/cli/builder/bundles/users-bundle/controller/api/graphql/userResolver.js +0 -121
- package/cli/builder/bundles/users-bundle/controller/api/graphql/usertype.js +0 -58
- package/cli/builder/bundles/users-bundle/controller/api/openapi/loginApiController.js +0 -210
- package/cli/builder/bundles/users-bundle/controller/api/openapi/restUserController.js +0 -244
- package/cli/builder/bundles/users-bundle/controller/loginController.js +0 -91
- package/cli/builder/bundles/users-bundle/controller/usersController.js +0 -332
- package/cli/builder/bundles/users-bundle/package.json +0 -58
- package/cli/builder/bundles/users-bundle/readme.md +0 -360
- package/cli/builder/bundles/users-bundle/services/usersService.js +0 -411
- package/cli/builder/bundles/users-bundle/src/providers/mongoose/userProvider.js +0 -47
- package/cli/builder/bundles/users-bundle/src/providers/sequelize/userProvider.js +0 -48
- package/cli/builder/bundles/users-bundle/tests/loginTest.js +0 -182
- package/cli/builder/bundles/users-bundle/usersBundle.js +0 -26
- package/cli/builder/microService/microService.js +0 -261
- package/cli/builder/microService/skeletons/.editorconfig +0 -18
- package/cli/builder/microService/skeletons/.env-cmdrc.js +0 -32
- package/cli/builder/microService/skeletons/.jshintrc +0 -37
- package/cli/builder/microService/skeletons/README.md +0 -117
- package/cli/builder/microService/skeletons/bin/bash/hello.sh +0 -5
- package/cli/builder/microService/skeletons/bin/cli +0 -13
- package/cli/builder/microService/skeletons/bin/python/hello.py +0 -20
- package/cli/builder/microService/skeletons/config/config.js +0 -29
- package/cli/builder/microService/skeletons/config/pm2.config.js +0 -72
- package/cli/builder/microService/skeletons/config/webpack/webpack.config.dev.js +0 -8
- package/cli/builder/microService/skeletons/config/webpack/webpack.config.prod.js +0 -25
- package/cli/builder/microService/skeletons/config/webpack.config.js +0 -114
- package/cli/builder/microService/skeletons/package.json +0 -76
- package/cli/builder/microService/skeletons/src/browser/index.css +0 -3
- package/cli/builder/microService/skeletons/src/browser/index.js +0 -16
- package/cli/builder/microService/skeletons/src/browser/socketio.js +0 -46
- package/cli/builder/microService/skeletons/src/cli/cli.js +0 -224
- package/cli/builder/microService/skeletons/src/cli/menu.js +0 -28
- package/cli/builder/microService/skeletons/src/n-api/README.md +0 -1
- package/cli/builder/microService/skeletons/src/n-api/binding.gyp +0 -14
- package/cli/builder/microService/skeletons/src/n-api/hello.cc +0 -14
- package/cli/builder/microService/skeletons/src/n-api/hello.js +0 -23
- package/cli/builder/microService/skeletons/src/n-api/package.json +0 -15
- package/cli/builder/microService/skeletons/src/node/examples/index.js +0 -120
- package/cli/builder/microService/skeletons/src/node/index.js +0 -102
- package/cli/builder/microService/skeletons/src/node/services/markdown/markdown.js +0 -27
- package/cli/builder/microService/skeletons/src/node/services/servers/http.js +0 -45
- package/cli/builder/microService/skeletons/src/node/services/servers/https.js +0 -44
- package/cli/builder/microService/skeletons/src/node/services/socketio/socketio.js +0 -46
- package/cli/builder/microService/skeletons/src/node/services/syscall/syscall.js +0 -111
- package/cli/builder/microService/skeletons/src/node/services/worker/thread.js +0 -59
- package/cli/builder/microService/skeletons/src/node/services/worker/worker.js +0 -60
- package/cli/builder/microService/skeletons/src/templates/base.html +0 -12
- package/cli/builder/microService/skeletons/src/templates/socket.html +0 -23
- package/cli/builder/microService/skeletons/tests/unit/serviceTest.js +0 -30
- package/cli/builder/project/project.js +0 -474
- package/cli/builder/project/skeletons/README.md +0 -778
- package/cli/builder/project/skeletons/bin/dev-deploy.sh +0 -5
- package/cli/builder/project/skeletons/bin/generateCertificates.sh.skeleton +0 -180
- package/cli/builder/project/skeletons/bin/prod-deploy.sh +0 -3
- package/cli/builder/project/skeletons/config/config.js.skeleton +0 -178
- package/cli/builder/project/skeletons/config/openssl/ca/openssl.cnf.skeleton +0 -150
- package/cli/builder/project/skeletons/config/openssl/ca_intermediate/openssl.cnf.skeleton +0 -152
- package/cli/builder/project/skeletons/config/pm2.config.js.skeleton +0 -62
- package/cli/builder/project/skeletons/documentation.html.twig +0 -24
- package/cli/builder/project/skeletons/editorconfig.skeleton +0 -18
- package/cli/builder/project/skeletons/eslintignore.skeleton +0 -15
- package/cli/builder/project/skeletons/eslintrc.js.skeleton +0 -97
- package/cli/builder/project/skeletons/gitignore.skeleton +0 -32
- package/cli/builder/project/skeletons/migrations/2022.12.25T17.37.37.entity-user.js +0 -137
- package/cli/builder/project/skeletons/migrations/2022.12.25T17.37.38.entity-session.js +0 -97
- package/cli/builder/project/skeletons/migrations/2022.12.25T17.37.39.entity-requests.js +0 -115
- package/cli/builder/project/skeletons/migrations/2022.12.25T17.37.40.entity-jwts.js +0 -97
- package/cli/builder/project/skeletons/migrations/migrations.skeleton.js +0 -101
- package/cli/builder/project/skeletons/package.json.twig +0 -71
- package/cli/builder/react/reactBuilder.js +0 -224
- package/cli/builder/react/skeletons/app/Resources/databases/nodefony.db +0 -0
- package/cli/builder/react/skeletons/app/Resources/translations/messages.en_en.yml +0 -5
- package/cli/builder/react/skeletons/app/Resources/translations/messages.fr_fr.yml +0 -5
- package/cli/builder/react/skeletons/app/Resources/views/base.html.twig +0 -33
- package/cli/builder/react/skeletons/app/config/config.js +0 -392
- package/cli/builder/react/skeletons/app/config/routing.js +0 -10
- package/cli/builder/react/skeletons/app/config/security.js +0 -74
- package/cli/builder/react/skeletons/app/controller/appController.js +0 -22
- package/cli/builder/sandbox/sandBoxBuilder.js +0 -610
- package/cli/builder/sandbox/skeletons/Resources/css/entry.css +0 -48
- package/cli/builder/sandbox/skeletons/Resources/js/entry.js +0 -60
- package/cli/builder/sandbox/skeletons/Resources/public/manifest.json +0 -32
- package/cli/builder/sandbox/skeletons/Resources/translations/messages.en_en.yml +0 -5
- package/cli/builder/sandbox/skeletons/Resources/translations/messages.fr_fr.yml +0 -5
- package/cli/builder/sandbox/skeletons/Resources/views/base.html.twig +0 -46
- package/cli/builder/sandbox/skeletons/Resources/views/index.html.twig +0 -34
- package/cli/builder/sandbox/skeletons/bootstrap/custom.scss +0 -27
- package/cli/builder/sandbox/skeletons/bootstrap/entry.scss +0 -60
- package/cli/builder/sandbox/skeletons/workbox/templates/index.html.twig +0 -32
- package/cli/builder/sandbox/skeletons/workbox/workers/service-worker.js +0 -196
- package/cli/builder/skeletons/Resources/public/favicon.ico +0 -0
- package/cli/builder/skeletons/Resources/public/images/app-logo.png +0 -0
- package/cli/builder/skeletons/Resources/views/framework-bundle/views/401.html.twig +0 -1
- package/cli/builder/skeletons/Resources/views/framework-bundle/views/401.json.twig +0 -24
- package/cli/builder/skeletons/Resources/views/framework-bundle/views/403.html.twig +0 -1
- package/cli/builder/skeletons/Resources/views/framework-bundle/views/403.json.twig +0 -20
- package/cli/builder/skeletons/Resources/views/framework-bundle/views/404.html.twig +0 -1
- package/cli/builder/skeletons/Resources/views/framework-bundle/views/404.json.twig +0 -20
- package/cli/builder/skeletons/Resources/views/framework-bundle/views/500.html.twig +0 -1
- package/cli/builder/skeletons/Resources/views/framework-bundle/views/base.html.twig +0 -30
- package/cli/builder/skeletons/Resources/views/framework-bundle/views/exception.html.twig +0 -1
- package/cli/builder/skeletons/Resources/views/framework-bundle/views/exception.json.twig +0 -24
- package/cli/builder/skeletons/Resources/views/framework-bundle/views/footer.html.twig +0 -33
- package/cli/builder/skeletons/Resources/views/framework-bundle/views/header.html.twig +0 -6
- package/cli/builder/skeletons/Resources/views/framework-bundle/views/index.html.twig +0 -6
- package/cli/builder/skeletons/Resources/views/framework-bundle/views/index.json.twig +0 -1
- package/cli/builder/skeletons/Resources/views/framework-bundle/views/layout.html.twig +0 -125
- package/cli/builder/skeletons/Resources/views/framework-bundle/views/layout.json.twig +0 -5
- package/cli/builder/skeletons/Resources/views/framework-bundle/views/timeout.html.twig +0 -1
- package/cli/builder/skeletons/Resources/views/framework-bundle/views/timeout.json.twig +0 -24
- package/cli/builder/skeletons/app/appKernel.js +0 -133
- package/cli/builder/skeletons/binding/binding.cc +0 -26
- package/cli/builder/skeletons/binding/binding.skeleton +0 -8
- package/cli/builder/skeletons/bundle/bundleClass.js +0 -37
- package/cli/builder/skeletons/command/commandClass.js +0 -11
- package/cli/builder/skeletons/command/taskClass.js +0 -20
- package/cli/builder/skeletons/config/config.js +0 -138
- package/cli/builder/skeletons/config/nodefony/elastic-bundle.js +0 -37
- package/cli/builder/skeletons/config/nodefony/framework-bundle.js +0 -22
- package/cli/builder/skeletons/config/nodefony/http-bundle.js +0 -104
- package/cli/builder/skeletons/config/nodefony/mail-bundle.js +0 -44
- package/cli/builder/skeletons/config/nodefony/mongoose-bundle.js +0 -51
- package/cli/builder/skeletons/config/nodefony/monitoring-bundle.js +0 -34
- package/cli/builder/skeletons/config/nodefony/realtime-bundle.js +0 -15
- package/cli/builder/skeletons/config/nodefony/redis-bundle.js +0 -44
- package/cli/builder/skeletons/config/nodefony/security-bundle.js +0 -25
- package/cli/builder/skeletons/config/nodefony/sequelize-bundle.js +0 -156
- package/cli/builder/skeletons/config/routing.js +0 -55
- package/cli/builder/skeletons/config/security.js +0 -102
- package/cli/builder/skeletons/config/services.js +0 -1
- package/cli/builder/skeletons/config/webpack/webpack.dev.config.js +0 -13
- package/cli/builder/skeletons/config/webpack/webpack.prod.config.js +0 -20
- package/cli/builder/skeletons/config/webpack.config.js +0 -148
- package/cli/builder/skeletons/controller/controllerClass.js +0 -75
- package/cli/builder/skeletons/package.json.twig +0 -57
- package/cli/builder/skeletons/unittest/testFile.js +0 -46
- package/cli/builder/vue/skeletons/Resources/public/images/app-logo.png +0 -0
- package/cli/builder/vue/skeletons/Resources/translations/messages.en_en.yml +0 -5
- package/cli/builder/vue/skeletons/Resources/translations/messages.fr_fr.yml +0 -5
- package/cli/builder/vue/skeletons/vue.config.js +0 -129
- package/cli/builder/vue/vueBuilder.js +0 -410
- package/cli/generate/generate.es6 +0 -103
- package/cli/install/install.js +0 -190
- package/cli/sequelize/sequelize.js +0 -94
- package/cli/start.js +0 -702
- package/cli/tools/pm2.es6 +0 -112
- package/cli/tools/tools.es6 +0 -97
- package/cli.es6 +0 -925
- package/container.es6 +0 -272
- package/error.es6 +0 -293
- package/fileClass.es6 +0 -242
- package/finder/file.es6 +0 -33
- package/finder/fileResult.es6 +0 -138
- package/finder/finder2.es6 +0 -275
- package/finder.es6 +0 -427
- package/kernel/annotations/annotations.es6 +0 -286
- package/kernel/api/api.es6 +0 -61
- package/kernel/api/graphqlApi.es6 +0 -107
- package/kernel/api/jsonApi.es6 +0 -177
- package/kernel/api/openApi.es6 +0 -139
- package/kernel/api/schemas/openApiSchema.js +0 -394
- package/kernel/babylon.es6 +0 -162
- package/kernel/bundle.es6 +0 -1200
- package/kernel/cliKernel.es6 +0 -869
- package/kernel/command.es6 +0 -78
- package/kernel/commands/nodefonyCommand.es6 +0 -247
- package/kernel/commands/tasks/bundlesTask.es6 +0 -59
- package/kernel/controllers/controller.es6 +0 -791
- package/kernel/fixture.es6 +0 -19
- package/kernel/injections/injections.es6 +0 -424
- package/kernel/kernel.es6 +0 -1960
- package/kernel/kernelWatcher.es6 +0 -387
- package/kernel/orm/entity.es6 +0 -59
- package/kernel/orm/orm.es6 +0 -139
- package/kernel/reader.es6 +0 -290
- package/kernel/security/encoder.es6 +0 -17
- package/kernel/security/factories/factory.es6 +0 -111
- package/kernel/security/factories/passeportFactory.es6 +0 -61
- package/kernel/security/provider.es6 +0 -58
- package/kernel/security/providers/chainProvider.es6 +0 -99
- package/kernel/security/providers/memoryProvider.es6 +0 -55
- package/kernel/security/providers/providerManager.es6 +0 -67
- package/kernel/security/providers/userEntityProvider.es6 +0 -50
- package/kernel/security/role.es6 +0 -12
- package/kernel/security/secureArea.es6 +0 -431
- package/kernel/security/tokens/token.es6 +0 -171
- package/kernel/security/user.es6 +0 -106
- package/kernel/serviceRealTime.es6 +0 -21
- package/kernel/services/connectionsService.es6 +0 -93
- package/kernel/services/cron/cronService.es6 +0 -123
- package/kernel/task.es6 +0 -80
- package/kernel/templates.es6 +0 -22
- package/kernel/templating/twig.es6 +0 -218
- package/kernel/tests/cliTest.js +0 -59
- package/kernel/tests/containerTest.js +0 -232
- package/kernel/tests/kernelTest.js +0 -39
- package/nodefony.es6 +0 -1084
- package/notificationsCenter.es6 +0 -118
- package/protocol.es6 +0 -86
- package/protocols/bayeux.es6 +0 -174
- package/protocols/jsonRpc/jsonrpc.es6 +0 -56
- package/result.es6 +0 -99
- package/service.es6 +0 -288
- package/syslog/pdu.es6 +0 -141
- package/syslog/syslog.es6 +0 -754
- package/watcher.es6 +0 -113
|
@@ -0,0 +1,967 @@
|
|
|
1
|
+
# AGENTS.md — <%= it.appName %>
|
|
2
|
+
|
|
3
|
+
> **N'invente jamais du code Nodefony : génère-le, imite-le, vérifie-le.**
|
|
4
|
+
> Trois actes pour toute tâche : **LIRE** (ce fichier, puis la doc pointée) →
|
|
5
|
+
> **GÉNÉRER** (`npx nodefony create …` produit du vrai code, à imiter) →
|
|
6
|
+
> **VÉRIFIER** (`npm run verify` — UNE commande : types + lint + tests + câblage).
|
|
7
|
+
>
|
|
8
|
+
> **Le réflexe, avant d'écrire le MOINDRE fichier** : un générateur le
|
|
9
|
+
> produit-il ? Écrire à la main un CRUD, un controller, une entité ou un
|
|
10
|
+
> squelette de module, c'est le signal que tu as raté une commande de la
|
|
11
|
+
> table ci-dessous — arrête-toi et lance-la.
|
|
12
|
+
>
|
|
13
|
+
> **Tu RENDS une réponse ?** `return this.renderJson(obj)` pour du JSON ;
|
|
14
|
+
> `this.setContextHtml()` puis `return this.render(html)` pour une PAGE — le nonce
|
|
15
|
+
> CSP de la requête s'écrit **`this.context?.cspNonce`** (le `?.` n'est pas
|
|
16
|
+
> optionnel : `context` est `ContextType | undefined`, sans lui le code ne
|
|
17
|
+
> compile pas), à recopier dans tout `<script>` en ligne. Ne touche JAMAIS
|
|
18
|
+
> `this.response` à la main : poser `Content-Type` toi-même court-circuite la
|
|
19
|
+
> négociation, et un `this.response as any` est le signal que tu as raté la façade.
|
|
20
|
+
>
|
|
21
|
+
> **Tu LIS une liste ?** Elle se BORNE, toujours. Le service d'une entité hérite
|
|
22
|
+
> `findPage({ limit: 25 })` — il ne charge que `limit + 1` lignes et rend
|
|
23
|
+
> `{ items, hasNext }` ; sinon `find(criteria, { limit })`. Un `find` sans borne
|
|
24
|
+
> matérialise la table ENTIÈRE : indolore sur les quelques lignes du poste de
|
|
25
|
+
> développement, fatal sur les dizaines de milliers de la production. Il te faut
|
|
26
|
+
> une projection de colonnes, une CTE, une agrégation ? Descends au natif **avec
|
|
27
|
+
> son type** — `import type { DrizzleDb } from "@nodefony/drizzle"` puis
|
|
28
|
+
> `orm.getNativeConnection<DrizzleDb>()`. Sans le paramètre de type tu reçois
|
|
29
|
+
> `unknown`, et il ne te reste qu'un `as any` que le contrôle refuse.
|
|
30
|
+
>
|
|
31
|
+
> **Tu SERS un fichier ?** Trois façades, jamais `createReadStream` à la main :
|
|
32
|
+
> `this.renderMediaStream(f)` pour un média qu'on parcourt (`Range` → 206),
|
|
33
|
+
> `this.streamFile(f)` pour le fichier entier, `this.renderFileDownload(f)` pour
|
|
34
|
+
> forcer le téléchargement. Le faire soi-même rend une réponse que le client ne
|
|
35
|
+
> peut pas lire — le détail, plus bas, est MESURÉ.
|
|
36
|
+
|
|
37
|
+
## Générateurs — appelle-les, ne recompose jamais leur sortie de mémoire
|
|
38
|
+
|
|
39
|
+
| Besoin | Commande |
|
|
40
|
+
| ------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ |
|
|
41
|
+
| Module applicatif (workspace npm) | `npx nodefony create module <nom>` |
|
|
42
|
+
| Controller HTTP **et** WebSocket (même classe) | `npx nodefony create controller <nom> --kind hello\|rest\|realtime\|duplex\|example` |
|
|
43
|
+
| Controller **réservé à une habilitation** — garde de classe + rôle déclaré dans la hiérarchie | `npx nodefony create controller <nom> --role ROLE_X` |
|
|
44
|
+
| Ressource REST **complète** — entité + service + controller CRUD + tests (ne JAMAIS l'écrire à la main) | `npx nodefony create entity <Nom> --fields "sku:string! price:float"` |
|
|
45
|
+
| Service métier seul — la logique réutilisable, hors de tout controller | `npx nodefony create service <Nom> [--inject <AutreService>] [--module <m>]` |
|
|
46
|
+
| Frontend Vite (React/Vue/Angular) | `npx nodefony create front <nom> [--module <m>]` |
|
|
47
|
+
| Commande CLI `nodefony <module>:<action>` | `npx nodefony create command <action> [--module <m>] [--phase onReady\|onRegister\|onPostReady]` |
|
|
48
|
+
|
|
49
|
+
**Ces dossiers ne s'écrivent JAMAIS à la main** — y déposer un fichier signifie
|
|
50
|
+
que tu as raté une commande de la table ci-dessus :
|
|
51
|
+
|
|
52
|
+
| Tu t'apprêtes à écrire dans… | Lance plutôt |
|
|
53
|
+
| -------------------------------- | ------------------------------------------------------------------------ |
|
|
54
|
+
| `nodefony/entity/` | `npx nodefony create entity <Nom> --fields "…"` |
|
|
55
|
+
| `nodefony/controllers/` | `npx nodefony create controller <nom> --kind …` |
|
|
56
|
+
| `nodefony/service/` | `npx nodefony create service <Nom>` (ou `create entity`, qui en pose un) |
|
|
57
|
+
| `nodefony/command/` | `npx nodefony create command <action> [--module <m>]` |
|
|
58
|
+
| `modules/<nom>/` (module entier) | `npx nodefony create module <nom>` |
|
|
59
|
+
|
|
60
|
+
Le code écrit à la main compile souvent — c'est tout le piège. Il diverge du
|
|
61
|
+
gabarit courant, et cette divergence ne se voit qu'à la première montée de
|
|
62
|
+
version. `npx nodefony create --help` liste les générateurs de CETTE version : la
|
|
63
|
+
liste s'allonge, ne te fie pas à ta mémoire.
|
|
64
|
+
|
|
65
|
+
Chaque commande se décrit à une machine : `--describe-json` (questions + options
|
|
66
|
+
en JSON), `--answers-json <fichier|->` (réponses en JSON), `--dry-run` (plan et
|
|
67
|
+
diffs, zéro écriture). Un refus n'écrit jamais rien (transaction).
|
|
68
|
+
|
|
69
|
+
Les champs d'une entité se déclarent en positionnels :
|
|
70
|
+
`npx nodefony create entity Post title:string! views:int=0 status:enum(draft,published) slug:string:index author:ref:User`.
|
|
71
|
+
Le `!` interdit le nul, le `?` l'autorise, `:index` pose l'index, `=<valeur>` fixe
|
|
72
|
+
la valeur par défaut, `enum(a,b)` borne les valeurs admises, et
|
|
73
|
+
`ref:<Entité>` crée la colonne de jointure **avec** son index. Les types portent
|
|
74
|
+
leur taille (`string(120)`, `char(2)`, `decimal(10,2)`). Un index de TABLE couvre
|
|
75
|
+
plusieurs colonnes et se répète : `--index "siteId,createdAt"`, `--unique "a,b"`.
|
|
76
|
+
Un `enum` rend la MÊME colonne sur les trois moteurs (pas de type SQL nommé, qui
|
|
77
|
+
exigerait une migration) : c'est le type TypeScript et le schéma Zod qui la
|
|
78
|
+
bornent — donc sur TOUS les transports, REST comme socket.
|
|
79
|
+
|
|
80
|
+
Si la table EXISTE DÉJÀ en base, trois options lui font épouser ses noms sans
|
|
81
|
+
rien renommer à la main : `--table <nom_sql>` (au lieu du pluriel),
|
|
82
|
+
`--column-case snake` (colonne `site_id`, propriété toujours `siteId`) et
|
|
83
|
+
`--id-name <colonne>` (clé primaire `website_id`, propriété toujours `id`). Le
|
|
84
|
+
code TypeScript ne change dans aucun des trois cas — seul le SQL suit.
|
|
85
|
+
`npx nodefony create entity --help` porte la grammaire de CETTE version — elle
|
|
86
|
+
s'enrichit, ta mémoire non.
|
|
87
|
+
|
|
88
|
+
## Où lire AVANT de coder (tâche → doc installée)
|
|
89
|
+
|
|
90
|
+
La référence est INSTALLÉE avec les paquets — lis CIBLÉ, jamais tout le dossier.
|
|
91
|
+
|
|
92
|
+
> 🔎 **Une recherche ORDINAIRE ne voit pas cette documentation.** `rg "terme"`
|
|
93
|
+
> lancé à la racine ne descend pas dans `node_modules` (git l'ignore, `rg` le
|
|
94
|
+
> suit) : le sujet paraît absent alors qu'il occupe quinze pages. Trois gestes
|
|
95
|
+
> justes, du plus utile au plus brut :
|
|
96
|
+
>
|
|
97
|
+
> - **chercher partout, avec le sens** — si le serveur tourne et que l'outil MCP
|
|
98
|
+
> est câblé (`npx nodefony ai:mcp`), `nodefony_docs` avec `query` balaie TOUTE
|
|
99
|
+
> la documentation chargée et rend des extraits ; `nodefony_symbols` rend la
|
|
100
|
+
> SIGNATURE réelle d'un symbole, que le graphe seul ne porte pas ;
|
|
101
|
+
> - **désigner le dossier** — `rg "terme" node_modules/@nodefony/*/docs/` :
|
|
102
|
+
> l'exclusion ne vaut que pour le PARCOURS, un chemin donné en argument est
|
|
103
|
+
> toujours lu ;
|
|
104
|
+
> - **forcer l'inclusion** — `rg --no-ignore "terme"` pour un balayage large.
|
|
105
|
+
>
|
|
106
|
+
> ⚠️ **Si `node_modules/` n'existe pas, la documentation n'est pas là** — et
|
|
107
|
+
> aucun de ces gestes ne répondra. Ce n'est pas « le sujet n'est pas documenté » :
|
|
108
|
+
> c'est `npm install` qui n'a pas été lancé. DIS-LE plutôt que de conclure de son
|
|
109
|
+
> silence, et ne réécris jamais à la main ce que tu n'as pas pu lire.
|
|
110
|
+
|
|
111
|
+
- **Quel module installer pour tel besoin** (et lequel NE PAS installer) — `node_modules/nodefony/docs/catalogue.md`
|
|
112
|
+
- **Variables d'environnement** : cascade des `.env`, précédence, `NF__`, **et dans quel MODE tourne une commande** — `node_modules/nodefony/docs/environnement.md`
|
|
113
|
+
- **Kernel, cycle de vie, CLI** — `node_modules/nodefony/docs/kernel.md` + `cli.md`
|
|
114
|
+
- **Service, DI, container, scopes** — `node_modules/nodefony/docs/service.md`
|
|
115
|
+
- **Client isomorphe (navigateur), hooks React** — `node_modules/nodefony/docs/client.md` + `react-hooks.md`
|
|
116
|
+
- **Serveurs, sessions, cookies, upload, rate-limit** — `node_modules/@nodefony/http/docs/`
|
|
117
|
+
- **Recevoir un FICHIER** (formulaire multipart, `@UploadedFile`, où le ranger sans laisser le client choisir) — `node_modules/@nodefony/http/docs/upload.md`
|
|
118
|
+
- **Journaliser, corréler, tracer une requête** (identifiant de requête, trace) — `node_modules/@nodefony/http/docs/observabilite.md`
|
|
119
|
+
- **Routing, controllers, décorateurs, idempotence** — `node_modules/@nodefony/framework/docs/`
|
|
120
|
+
<% if (it.hasSecurity) { %>- **Firewall, authenticators, CSRF, CORS, clés d'API** — `node_modules/@nodefony/security/docs/firewall.md`
|
|
121
|
+
- **Protéger une action par un RÔLE** (`@IsGranted`), voters, hiérarchie — `node_modules/@nodefony/security/docs/authorization.md`
|
|
122
|
+
- **Le navigateur REFUSE d'exécuter ton script ou de charger une image** (politique de contenu, nonce, `Context.cspNonce`, HSTS, clickjacking) — `node_modules/@nodefony/security/docs/headers.md`
|
|
123
|
+
- **Utilisateurs** : contrat `IUser`, `UserService`, mot de passe — `node_modules/@nodefony/user/docs/index.md`
|
|
124
|
+
- **Notifier un système tiers** (webhook signé, rejeu, endpoints) — `node_modules/@nodefony/security/docs/webhooks.md`
|
|
125
|
+
<% } %><% if (it.hasOrm) { %>- **Entités, repositories, requêtes (ORM)** — `node_modules/@nodefony/orm-core/docs/`
|
|
126
|
+
- **Migrations de schéma** (générer, appliquer, ÉPROUVER sans risque, déployer, réparer) — charge d'abord le skill `nodefony-migrate-schema` ; le détail des verdicts vit dans `node_modules/@nodefony/drizzle/docs/migrations.md`
|
|
127
|
+
<% } %><% if (it.hasRealtime) { %>- **Canaux temps réel, actions, protocole WS** — `node_modules/@nodefony/realtime/docs/`
|
|
128
|
+
<% } %><% if (it.front) { %>- **Builder Vite, entries, HMR** — `node_modules/@nodefony/frontend/docs/`
|
|
129
|
+
<% } %><% if (it.hasStudio) { %>- **Console d'admin Studio (dev)** — `node_modules/@nodefony/studio/docs/` + http://127.0.0.1:5151/nodefony
|
|
130
|
+
<% } %>
|
|
131
|
+
La config de l'app vit dans `nodefony.config.ts` (modules chargés) et `env.ts`
|
|
132
|
+
(variables d'environnement, seul lecteur de `process.env`) — pointe-les, ne les
|
|
133
|
+
recopie pas.
|
|
134
|
+
|
|
135
|
+
**Des skills d'agent sont posés dans `.agents/skills/`** — la marche à suivre
|
|
136
|
+
complète pour les tâches courantes (`ls .agents/skills/` les liste ; leur
|
|
137
|
+
description dit quand chacun s'applique). Ce sont des **pointeurs** vers le
|
|
138
|
+
contenu installé dans `node_modules` : ils suivent la version du framework de CE
|
|
139
|
+
projet, et les éditer ne servirait à rien. Si ton outil ne charge que son propre
|
|
140
|
+
dossier de découverte, lis-les à la main — c'est le chemin le plus court vers la
|
|
141
|
+
bonne façade. `npx nodefony ai:sync` les remet à jour après un `npm update`
|
|
142
|
+
(`--dry-run` dit ce qui changerait).
|
|
143
|
+
|
|
144
|
+
**Les instructions que tu lis vivent dans `AGENTS.md`** — standard porté par
|
|
145
|
+
l'Agentic AI Foundation (Linux Foundation), précédence « le plus proche gagne ».
|
|
146
|
+
Les fichiers au nom d'un outil (`CLAUDE.md`, `GEMINI.md`) n'en sont que des
|
|
147
|
+
POINTEURS : ce qu'on y recopierait divergerait en silence. Deux agents lisent
|
|
148
|
+
`AGENTS.md` d'office (Codex, Vibe), deux ouvrent leur propre fichier.
|
|
149
|
+
|
|
150
|
+
**La porte d'introspection de cette application** (protocole MCP) se câble par
|
|
151
|
+
`npx nodefony ai:mcp` : elle écrit `.mcp.json` à la racine et, si tu le
|
|
152
|
+
demandes, déclare la porte chez tes agents **par leur propre CLI**. En mode
|
|
153
|
+
authentifié (`--auth`), l'en-tête porte `${NF_MCP_TOKEN}` — jamais le jeton
|
|
154
|
+
lui-même, que `npx nodefony security:token --write` émet à part. ⚠️ La porte est
|
|
155
|
+
une ROUTE : elle n'existe que serveur démarré, et un client MCP qui la trouve
|
|
156
|
+
éteinte la marque en échec pour toute sa session.
|
|
157
|
+
|
|
158
|
+
## Les commandes de l'app — demande la liste, ne la devine pas
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
npx nodefony --help # TOUTES les commandes, celles des modules installés comprises
|
|
162
|
+
npx nodefony <commande> --help # les options exactes de l'une d'elles
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
La liste **dépend des modules installés** : elle n'est pas la même d'une app à
|
|
166
|
+
l'autre, et elle s'allonge dès que tu en ajoutes un. C'est pour ça qu'elle se
|
|
167
|
+
demande au lieu de se retenir.
|
|
168
|
+
|
|
169
|
+
**Toujours `npx`, jamais `nodefony` nu.** Le binaire vit dans les `node_modules`
|
|
170
|
+
de CETTE app, pas dans ton PATH : la forme nue rend un code 127 tant que rien
|
|
171
|
+
n'est installé globalement. Une installation globale existe bien
|
|
172
|
+
(`npm i -g nodefony`) — elle sert à créer une app HORS projet — et, dans un
|
|
173
|
+
projet, elle passe la main au binaire local (le projet gagne, comme `gradlew`).
|
|
174
|
+
Mais elle peut être plus ANCIENNE que celle de l'app : `npx` prend directement la
|
|
175
|
+
version que cette application a choisie, sans dépendre de ce qui traîne sur la
|
|
176
|
+
machine.
|
|
177
|
+
|
|
178
|
+
Celles qu'on n'invente pas — faute de savoir qu'elles existent :
|
|
179
|
+
|
|
180
|
+
- Mettre l'app derrière **nginx ou haproxy** — `npx nodefony proxy:generate <nginx|haproxy> [-o <fichier>] [-b <hôte>] [-l <port>] [--reencrypt]`
|
|
181
|
+
- **Servir les fichiers statiques depuis un CDN** — `npx nodefony assets:publish [-o <dossier>] [--clean] [--json]`
|
|
182
|
+
- **Certificat TLS de développement** — `npx nodefony http:certificates [-f] [-j]`
|
|
183
|
+
<% if (it.front) { %>- **Construire le front pour la production** — `npx nodefony frontend:build [-f]`
|
|
184
|
+
- **Où en est le serveur Vite** — `npx nodefony frontend:status [-j]`
|
|
185
|
+
<% } %><% if (it.hasSecurity) { %>- **Clés de chiffrement du firewall** — `npx nodefony security:secrets [-j] [-w]`
|
|
186
|
+
- Créer un compte **administrateur** — `npx nodefony security:user:add <identifiant> --admin`
|
|
187
|
+
<% } %><% if (it.hasOrm) { %>- **Écrire les migrations** des entités modifiées — `npx nodefony orm:generate [--name <nom>] [--custom]`
|
|
188
|
+
- **Appliquer les migrations** (verrou + historique) — `npx nodefony orm:migrate [-n|--dry-run] [--json]`
|
|
189
|
+
- **La base est-elle à jour ?** — `npx nodefony orm:migrate:status [--json]` — **0** = à jour, **1** = en retard : ta barrière de déploiement
|
|
190
|
+
- **Éprouver une migration SANS toucher à ta base** — `NF_MIGRATE_DATABASE_URL="sqlite:/tmp/essai.sqlite" npx nodefony orm:migrate` — migre AILLEURS ; c'est ainsi qu'on prouve qu'une migration s'applique, jamais en refaisant la base
|
|
191
|
+
- **Repartir d'une base vierge EN DÉVELOPPEMENT** — `npx nodefony orm:reset [-c <connecteur>] [-y]` — refusée partout ailleurs, et **elle DÉTRUIT les données** : ce n'est jamais la façon d'éprouver une migration, ni la réponse à une migration qui refuse
|
|
192
|
+
<% } %>- **Dépendances en retard (agrégées, pas le brut de npm)** — `npx nodefony outdated [-j] [-a]`
|
|
193
|
+
- **Cohérence du projet (classe non câblée, route qui répondra 404)** — `npx nodefony doctor [--json]` — depuis n'importe quel sous-dossier
|
|
194
|
+
- **Plusieurs processus, un cœur chacun** — `npx nodefony production -w <n>` · `npx nodefony cluster -w <n>`
|
|
195
|
+
- **Construire l'image de container** — `docker build -t <%= it.appName %> .` — le `Dockerfile` est DÉJÀ là, ne le réécris pas
|
|
196
|
+
<% if (it.hasMigrateRecipe) { %>- **Migrer le schéma avant un déploiement** — `deploy/migrate-job.yaml` est DÉJÀ rendu au nom de cette app (travail Kubernetes, même image, secret DDL séparé) — son mode d'emploi est en tête du fichier, ne le réécris pas
|
|
197
|
+
<% } %>
|
|
198
|
+
- **Complétion au TAB** — `source <(nodefony completion zsh)`
|
|
199
|
+
|
|
200
|
+
Ce tableau ne remplace pas `--help` : lui seul connaît les modules de CETTE app,
|
|
201
|
+
et il fait foi le jour où les deux divergent.
|
|
202
|
+
|
|
203
|
+
## Vérités du framework (anti-préjugés — ce que tu crois savoir est faux ici)
|
|
204
|
+
<% if (it.hasSecurity) { %>
|
|
205
|
+
- **La PROVENANCE d'une requête n'est pas une PREUVE D'INTENTION — une mutation
|
|
206
|
+
exige `@CsrfProtect`.** Le raisonnement qui vient, et qui est faux : « le
|
|
207
|
+
firewall vérifie déjà `Sec-Fetch-Site`, donc une écriture est protégée ». Ces
|
|
208
|
+
en-têtes sont posés par un NAVIGATEUR ; un programme qui parle en HTTP n'en
|
|
209
|
+
envoie aucun, et la défense de provenance le laisse alors passer — c'est son
|
|
210
|
+
rôle, elle distingue les sites, pas les intentions. Résultat mesuré : un
|
|
211
|
+
`POST /api/cart/items` sans jeton rend `201`, et l'application croit avoir une
|
|
212
|
+
défense. Toute action qui ÉCRIT porte donc `@CsrfProtect` explicitement. Le
|
|
213
|
+
jeton ne se demande à AUCUN endpoint : une requête sûre (`GET`) vers la route
|
|
214
|
+
protégée sème le cookie lisible `csrf-token`, et la mutation le rejoue dans
|
|
215
|
+
l'en-tête `x-csrf-token` — c'est le double-submit, sinon `403`. La provenance
|
|
216
|
+
et le jeton se cumulent ; l'une ne remplace jamais l'autre.
|
|
217
|
+
|
|
218
|
+
- **Une origine tierce refusée en 403 se DÉCLARE — elle ne s'exempte pas.** Quand
|
|
219
|
+
les envois d'un partenaire sont rejetés alors que les tiens aboutissent, la
|
|
220
|
+
cause est la défense CSRF, et le réflexe qui vient (`@CsrfExempt` sur la route,
|
|
221
|
+
`checkOrigin: false`, `csrf.enabled: false`) fait passer le partenaire **et
|
|
222
|
+
n'importe quel autre site** : la route cesse de distinguer qui que ce soit,
|
|
223
|
+
c'est-à-dire exactement l'attaque que la défense arrêtait. La réponse est une
|
|
224
|
+
ligne de configuration — ajoute l'origine au bloc `csrf` déjà présent dans
|
|
225
|
+
`use("@nodefony/security", …)`, `nodefony.config.ts` :
|
|
226
|
+
|
|
227
|
+
```ts
|
|
228
|
+
csrf: {
|
|
229
|
+
secret: ctx.env.NF_CSRF_SECRET,
|
|
230
|
+
trustedOrigins: ["https://partenaire.example"],
|
|
231
|
+
},
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
La comparaison porte sur la chaîne d'origine ENTIÈRE (`scheme://host[:port]`) :
|
|
235
|
+
ni joker, ni sous-domaine implicite — une origine par entrée. À ne pas
|
|
236
|
+
confondre avec `cors.origins`, qui autorise EN PLUS le JS du tiers à **lire**
|
|
237
|
+
tes réponses : un partenaire qui POSTE n'en a pas besoin, et les deux
|
|
238
|
+
traversent la défense. Détail :
|
|
239
|
+
`node_modules/@nodefony/security/docs/csrf.md` ; geste complet et pièges :
|
|
240
|
+
skill **`nodefony-protect-route`**.
|
|
241
|
+
<% } %>
|
|
242
|
+
- **Un adaptateur de données ne remplace pas l'autre : ils se COMPLÈTENT.** Chacun
|
|
243
|
+
déclare les _stores_ qu'il sait tenir (`nodefony.stores` de son `package.json`) —
|
|
244
|
+
`drizzle` les huit (session, user, tokens, passkeys, totp, audit, webhooks,
|
|
245
|
+
idempotency), `mongoose` cinq (ni `totp`, ni `audit`, ni `idempotency`), `redis`
|
|
246
|
+
quatre. Ce n'est pas un retard de développement mais un CHOIX : un journal
|
|
247
|
+
d'audit n'a rien à faire dans un moteur documentaire. Ne promets donc jamais une
|
|
248
|
+
parité qui n'existe pas, et vérifie où atterrit chaque donnée :
|
|
249
|
+
`npx nodefony inspect stores`. Le détail par brique :
|
|
250
|
+
`node_modules/nodefony/docs/catalogue.md`.
|
|
251
|
+
|
|
252
|
+
- **Le cœur `nodefony` est ISOMORPHE** : le même paquet se charge côté Node
|
|
253
|
+
ET navigateur. La porte client EXPLICITE est le subpath `nodefony/client`
|
|
254
|
+
(`RealtimeClient`, notices, rôles — résolu à l'identique par Vite, Node et
|
|
255
|
+
le typecheck) ; les hooks React vivent dans `nodefony/react`. Ne réécris
|
|
256
|
+
JAMAIS un client WebSocket/JSON-RPC, ne duplique JAMAIS un type entre front
|
|
257
|
+
et back : un seul contrat, vérifié par le compilateur des deux bouts.
|
|
258
|
+
|
|
259
|
+
- **Une commande ne tourne PAS dans le mode du serveur que tu as lancé — DEMANDE-le.**
|
|
260
|
+
Chaque commande démarre son propre noyau. Sans `NODE_ENV` dans ton shell, elle
|
|
261
|
+
part en `development` ; avec `NODE_ENV=production`, elle lit une AUTRE
|
|
262
|
+
configuration et une AUTRE base de données — sans rien dire de plus. Ne le
|
|
263
|
+
suppose jamais avant d'écrire ou de migrer quoi que ce soit :
|
|
264
|
+
|
|
265
|
+
```bash
|
|
266
|
+
npx nodefony env # le mode, et d'où vient chaque variable
|
|
267
|
+
npx nodefony inspect config # la configuration EFFECTIVE, et sa provenance
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
Pour forcer : `NODE_ENV=production npx nodefony <commande>`. La règle complète
|
|
271
|
+
(absent, posé, valeur non-moteur) est dans
|
|
272
|
+
`node_modules/nodefony/docs/environnement.md`.
|
|
273
|
+
|
|
274
|
+
- **Une initialisation s'ACCROCHE à une phase du démarrage — il n'y a pas de
|
|
275
|
+
`app.use()`.** Nodefony n'est pas un framework à middlewares chaînés : du code
|
|
276
|
+
posé au chargement d'un fichier s'exécute AVANT que la configuration existe, et
|
|
277
|
+
il n'y a rien à quoi « ajouter » un traitement global. Ce qui doit tourner au
|
|
278
|
+
démarrage se déclare depuis un module ou un service :
|
|
279
|
+
`this.module?.hookKernel("onBoot", async () => { … })` — l'étiquette porte alors
|
|
280
|
+
le nom et la criticité du module, ce qu'un `kernel.once(…)` posé à la main
|
|
281
|
+
perdrait. Les phases, dans l'ordre : `onRegister` (les modules se déclarent),
|
|
282
|
+
`onBoot` (tout est chargé, les connexions s'ouvrent), `onReady` (juste AVANT que
|
|
283
|
+
les serveurs se mettent à écouter), `onPostReady` (ils écoutent), `onTerminate`
|
|
284
|
+
(fermeture). Une commande CLI se pose sur la
|
|
285
|
+
même échelle : `npx nodefony create command <action> --phase onReady`.
|
|
286
|
+
⚠️ Si tu t'apprêtes à écrire `as any` sur le kernel pour atteindre une méthode,
|
|
287
|
+
arrête-toi : c'est le signe que tu cherches une API d'un AUTRE framework. Les
|
|
288
|
+
phases, le conteneur et les connecteurs sont typés — la référence est dans
|
|
289
|
+
`node_modules/nodefony/docs/kernel.md`, et `npx nodefony inspect services`
|
|
290
|
+
montre ce qui existe RÉELLEMENT dans cette application.
|
|
291
|
+
|
|
292
|
+
- **Un service n'est pas une classe utilitaire.** Une classe à méthodes `static`,
|
|
293
|
+
ou un objet exporté, COMPILE et marche — et reste invisible au framework. Un
|
|
294
|
+
service Nodefony est une classe `@injectable()` qui `extends Service` : c'est
|
|
295
|
+
de là que lui viennent sa config fusionnée, son journal (`this.log`), les
|
|
296
|
+
événements, et sa place dans le conteneur. Il porte DEUX noms sans que ce soit
|
|
297
|
+
une redondance : le décorateur nomme la CLASSE (ce qu'on écrit dans
|
|
298
|
+
`@inject("…")`), le `super("nom", …)` nomme l'INSTANCE (sa clé pour
|
|
299
|
+
`container.get("…")`). Ne l'écris pas de mémoire :
|
|
300
|
+
`npx nodefony create service <Nom>` en pose un complet, commenté, à imiter ;
|
|
301
|
+
la référence est dans
|
|
302
|
+
`node_modules/nodefony/docs/service.md`.
|
|
303
|
+
**Un service qui en appelle un autre le déclare au CONSTRUCTEUR** :
|
|
304
|
+
`npx nodefony create service <Nom> --inject <AutreService>` écrit le
|
|
305
|
+
`@inject("AutreService")` et l'appel qui va avec. La dépendance est alors
|
|
306
|
+
ordonnée par le conteneur et visible dans la signature — là où
|
|
307
|
+
`container.get("…")` cherche à l'exécution et rend `undefined` en silence si
|
|
308
|
+
le service n'est pas enregistré.
|
|
309
|
+
|
|
310
|
+
- **Les violations de contrainte sont DÉJÀ traduites en HTTP — ne les rattrape pas.**
|
|
311
|
+
Un doublon sur une colonne unique ressort en **409**, une donnée qui viole le
|
|
312
|
+
schéma Zod en **422**, chacun avec son corps JSON : le rendu d'erreur lit le code
|
|
313
|
+
du pilote (`23505` PostgreSQL, `ER_DUP_ENTRY` MySQL, `SQLITE_CONSTRAINT_UNIQUE`,
|
|
314
|
+
`11000` MongoDB) et le mappe, quel que soit le moteur. N'écris donc JAMAIS un
|
|
315
|
+
`throw … 409` dans un service pour un `sku` déjà pris. Le vérifier toi-même
|
|
316
|
+
d'abord (« existe-t-il ? » puis insertion) est plus lent ET **faux sous
|
|
317
|
+
concurrence** : deux requêtes simultanées passent toutes les deux le test avant
|
|
318
|
+
que l'une n'écrive. La contrainte de la base est le seul arbitre exact — laisse-la
|
|
319
|
+
lever, le pipeline traduit.
|
|
320
|
+
|
|
321
|
+
- **Un fichier ne se sert pas à la main.** Trois façades, et le choix se fait sur
|
|
322
|
+
l'usage : `this.renderMediaStream(file)` implémente les **requêtes par plage**
|
|
323
|
+
(`Range` → 206 + `Content-Range`, 416 hors plage) — c'est ce qu'exige un lecteur
|
|
324
|
+
vidéo ou audio pour se déplacer ; `this.streamFile(file)` envoie le fichier
|
|
325
|
+
ENTIER en flux, sans plage ; `this.renderFileDownload(file)` force le
|
|
326
|
+
téléchargement. Recomposer ça avec `createReadStream` et `response.write`
|
|
327
|
+
compile, passe les tests — et rend une réponse **incohérente** : un statut posé
|
|
328
|
+
à la main n'atteint jamais la socket (le pipeline écrit statut et en-têtes à
|
|
329
|
+
SON tour), donc le client reçoit **200 avec un corps partiel** et croit tenir le
|
|
330
|
+
fichier complet. Mesuré au banc, pas supposé.
|
|
331
|
+
|
|
332
|
+
- **Le container DI est PROTOTYPAL** : les services vivent sur une chaîne de
|
|
333
|
+
prototypes — un scope de requête VOIT tous les services du kernel sans
|
|
334
|
+
aucune copie (coût d'un scope ≈ un `Object.create`), et ce qu'on `set()`
|
|
335
|
+
dans un scope MEURT avec la requête. Ne fabrique donc ni cache de services
|
|
336
|
+
par requête, ni singleton maison : `container.get("<nom>")` remonte la
|
|
337
|
+
chaîne, c'est le mécanisme.
|
|
338
|
+
|
|
339
|
+
- **Le WS métier passe par la socket Nodefony** (`--kind realtime` : canaux
|
|
340
|
+
pub/sub + actions RPC + policies). L'echo WS brut des exemples est une démo
|
|
341
|
+
du pipeline partagé, pas un modèle à imiter.
|
|
342
|
+
|
|
343
|
+
<% if (it.hasSecurity) { %>- **Utilisateurs et droits : tout existe, n'improvise RIEN.** Ces gestes
|
|
344
|
+
couvrent l'essentiel, et chacun a sa doc installée (cf. la table « Où lire
|
|
345
|
+
AVANT de coder », plus haut) ; le geste détaillé et ses pièges vivent dans le
|
|
346
|
+
skill **`nodefony-protect-route`** :
|
|
347
|
+
- **protéger un ESPACE de routes** (tout ce qui commence par un préfixe) :
|
|
348
|
+
une zone de firewall dans `nodefony.config.ts`, dont le `pattern` est le
|
|
349
|
+
PRÉFIXE lui-même — `pattern: "^/api/account"`, **jamais** la liste des
|
|
350
|
+
routes du jour (`"^/api/account/(profile|invoices)"`). Énumérer marche à
|
|
351
|
+
l'essai, passe la revue, et laisse la route sœur ajoutée ensuite NAÎTRE
|
|
352
|
+
PUBLIQUE — rien ne le signale, la zone a l'air de couvrir l'espace. Quand
|
|
353
|
+
des routes partagent un préfixe, ne les protège pas une par une ;
|
|
354
|
+
- **protéger une action** : le décorateur `@IsGranted("ROLE_ADMIN")` sur la
|
|
355
|
+
méthode — il vaut pour TOUS les transports (HTTP et socket), et se pose
|
|
356
|
+
**en plus** de la zone de firewall (le firewall AUTHENTIFIE, `@IsGranted`
|
|
357
|
+
AUTORISE) ;
|
|
358
|
+
- **réserver TOUT un controller à une habilitation** : ne l'écris pas,
|
|
359
|
+
demande-le — `npx nodefony create controller <nom> --role ROLE_X` pose la
|
|
360
|
+
garde sur la CLASSE (donc sur les actions à venir) **et** déclare le rôle
|
|
361
|
+
sous `ROLE_ADMIN` dans `roleHierarchy`. Les deux gestes vont ensemble, et
|
|
362
|
+
c'est le second qu'on oublie en les faisant à la main ;
|
|
363
|
+
- **lire l'utilisateur courant** : le paramètre décoré `@CurrentUser()`
|
|
364
|
+
(typé `IUser` de `@nodefony/user`) — l'identité est ré-résolue à chaque
|
|
365
|
+
requête, donc les rôles sont frais et une révocation prend effet tout de
|
|
366
|
+
suite. N'écris pas ton propre lecteur de session ;
|
|
367
|
+
- **déclarer qu'un rôle en implique un autre** : la clé `roleHierarchy` de
|
|
368
|
+
la config du module de sécurité (`ROLE_ADMIN` hérite `ROLE_USER`) — que
|
|
369
|
+
`create controller --role` remplit pour toi quand le rôle naît avec son
|
|
370
|
+
controller. Elle
|
|
371
|
+
est aplatie au boot ; n'écris pas de test d'appartenance à la main — et
|
|
372
|
+
n'énumère pas non plus les rôles du jour sur l'action.
|
|
373
|
+
`@IsGranted(["ROLE_BILLING", "ROLE_ADMIN"])` accorde bien l'accès (un
|
|
374
|
+
attribut suffit), mais la relation entre ces deux rôles n'existe alors
|
|
375
|
+
NULLE PART : la route sœur ajoutée demain devra répéter la liste, et
|
|
376
|
+
l'oubli ne se voit sur aucune route. C'est le piège de la puce
|
|
377
|
+
précédente, un cran plus haut — énumérer ce qu'on a sous les yeux au
|
|
378
|
+
lieu de déclarer la règle ;
|
|
379
|
+
- **créer un compte** : la commande `npx nodefony security:user:add <identifiant>`.
|
|
380
|
+
Ne fabrique pas d'utilisateur en insérant directement dans la base — le mot
|
|
381
|
+
de passe passe par l'encodeur du framework.
|
|
382
|
+
- **ouvrir une API à un PROGRAMME** (service partenaire, script, agent — pas
|
|
383
|
+
un navigateur) : cette zone est **déjà posée** dans `nodefony.config.ts` —
|
|
384
|
+
|
|
385
|
+
```ts
|
|
386
|
+
machine: {
|
|
387
|
+
pattern: "^/api/machine",
|
|
388
|
+
authenticators: ["apikey"], // PAS "session" — ce client n'a pas de cookie
|
|
389
|
+
stateless: true, // false ⇒ un registre de sessions pour un client qui ne le relit pas
|
|
390
|
+
},
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
Pour une route **NEUVE**, fais-la **tomber sous `/api/machine`** plutôt que
|
|
394
|
+
d'ajouter une zone : celle-ci est déjà réglée, et une seconde zone au
|
|
395
|
+
pattern plus court la coifferait sans prévenir (le firewall trie par
|
|
396
|
+
longueur de pattern).
|
|
397
|
+
|
|
398
|
+
🔴 **Mais une URL DÉJÀ PUBLIÉE ne se déplace pas — c'est un contrat.** Quand
|
|
399
|
+
on te demande de protéger une adresse existante (`/api/partenaire/depot`),
|
|
400
|
+
la déménager sous `/api/machine` la fait répondre `404` à celui-là même
|
|
401
|
+
qu'on voulait servir : le partenaire appelle l'ancienne, personne ne l'a
|
|
402
|
+
prévenu, et rien dans l'application ne signale la rupture. Vécu, et le
|
|
403
|
+
contrôle l'a vu — clé d'API valide, `404`. **On adapte la ZONE à l'URL,
|
|
404
|
+
jamais l'URL à la zone** : étends le `pattern` de la zone `machine` pour
|
|
405
|
+
qu'il couvre aussi l'adresse en place —
|
|
406
|
+
|
|
407
|
+
```ts
|
|
408
|
+
machine: {
|
|
409
|
+
pattern: "^/api/(machine|partenaire)",
|
|
410
|
+
authenticators: ["apikey"],
|
|
411
|
+
stateless: true,
|
|
412
|
+
},
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
Une URL ne se déplace que si l'énoncé le demande, et alors l'ancienne
|
|
416
|
+
redirige.
|
|
417
|
+
|
|
418
|
+
⚠️ `stateless: false` (le défaut) **ne fait pas échouer l'essai**, et c'est
|
|
419
|
+
tout le piège : depuis un navigateur ou un `curl -c`, le cookie posé revient
|
|
420
|
+
aux requêtes suivantes et tout semble marcher. Ce que ça coûte n'est pas un
|
|
421
|
+
refus mais un **registre** — chaque appel portant un cookie inconnu fait
|
|
422
|
+
reprendre puis réécrire une session serveur, et renvoyer un `Set-Cookie`,
|
|
423
|
+
pour un appelant qui ne la relira jamais. `stateless: true` ferme cela : la
|
|
424
|
+
zone n'ouvre ni ne reprend de session, et le cookie entrant est ignoré.
|
|
425
|
+
Lister `"session"` dans une zone stateless est une contradiction, et
|
|
426
|
+
l'application **refuse de démarrer** en nommant la zone. Règle : un appelant
|
|
427
|
+
qui ne stocke pas de cookie ne doit rien recevoir qu'il faille stocker.
|
|
428
|
+
Les clés s'émettent par `POST /nodefony/security/api/keys`.
|
|
429
|
+
|
|
430
|
+
- Un droit **métier** qui ne se réduit pas à un rôle (« l'auteur peut éditer
|
|
431
|
+
SON document ») s'écrit en **voter** et s'enregistre par
|
|
432
|
+
`registerVoterFactory` ; `@IsGranted("doc.edit", { subject: "id" })` l'appelle.
|
|
433
|
+
C'est le point d'extension prévu — il n'y a pas de table de permissions à
|
|
434
|
+
inventer.
|
|
435
|
+
|
|
436
|
+
<% } %>## Environnement : ne devine JAMAIS, demande
|
|
437
|
+
|
|
438
|
+
```bash
|
|
439
|
+
npx nodefony env # cascade des .env, valeur EFFECTIVE de chaque variable, sa PROVENANCE
|
|
440
|
+
npx nodefony env --json # même rapport, pour un script
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
**Encadre toute modification de configuration par cette commande** : une fois
|
|
444
|
+
AVANT, pour savoir ce qui s'applique aujourd'hui et d'où ça vient ; une fois
|
|
445
|
+
APRÈS, pour prouver que ta valeur est bien celle qui gagne. Ce n'est pas un
|
|
446
|
+
outil de dépannage qu'on sort quand ça casse — c'est le geste qui remplace la
|
|
447
|
+
déduction.
|
|
448
|
+
|
|
449
|
+
Elle répond aux quatre questions dont dépend toute configuration, et qu'aucune
|
|
450
|
+
lecture de fichier ne tranche : quels fichiers sont lus **et dans quel ordre**,
|
|
451
|
+
quelles variables l'app **déclare**, quelle valeur est **effective et d'où elle
|
|
452
|
+
vient**, et **ce qui est ignoré**. Lire les `.env` toi-même te donne des
|
|
453
|
+
contenus ; la précédence, elle, est un mécanisme — tu ne peux que la supposer,
|
|
454
|
+
et une supposition fausse ne se voit qu'en production. La commande ne boote
|
|
455
|
+
rien, donc elle répond aussi quand l'app ne démarre plus.
|
|
456
|
+
|
|
457
|
+
**Précédence, du plus FORT au plus faible** — le premier qui pose une valeur
|
|
458
|
+
gagne, les suivants sont ignorés en silence :
|
|
459
|
+
|
|
460
|
+
```
|
|
461
|
+
process.env > .env.<déploiement>.local > .env.<mode>.local > .env.local
|
|
462
|
+
> .env.<déploiement> > .env.<mode> > .env
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
`<mode>` = `NODE_ENV` (`development`/`production`). `<déploiement>` = `APP_ENV`
|
|
466
|
+
(`staging`, `canary`… — plus spécifique, donc plus fort). Les `*.local` ne sont
|
|
467
|
+
jamais committés : les secrets y vont, et nulle part ailleurs.
|
|
468
|
+
|
|
469
|
+
**Deux mécanismes à ne pas confondre** :
|
|
470
|
+
|
|
471
|
+
| Forme | Ce que c'est | Où c'est déclaré |
|
|
472
|
+
| ------------------------------------- | ----------------------------------------------------------- | ------------------------------------------------------ |
|
|
473
|
+
| `NF_PORT=5151` | variable de l'APP, typée et validée | `env.ts` (`defineEnv`) — non déclarée = **sans effet** |
|
|
474
|
+
| `NF__HTTP__SERVERS__HTTPS__PORT=8443` | surcharge DIRECTE d'une clé de config d'un module | rien à déclarer — double `__` = séparateur |
|
|
475
|
+
| `NF_TOTP_KEY_FILE=/run/secrets/x` | la même variable, lue depuis un fichier (secret Docker/K8s) | idem `NF_TOTP_KEY` |
|
|
476
|
+
|
|
477
|
+
Une variable `NF_` mal orthographiée n'échoue pas : elle est **ignorée**, et le
|
|
478
|
+
défaut s'applique en silence. `npx nodefony env` est le seul endroit qui la montre
|
|
479
|
+
(avec la correction probable).
|
|
480
|
+
|
|
481
|
+
**Les clés de configuration d'un module, avec leurs défauts, sont LISIBLES :**
|
|
482
|
+
`node_modules/@nodefony/<module>/dist/nodefony/config/config.js` porte le schéma
|
|
483
|
+
Zod du module — chaque clé, son `.default(…)` et sa `.describe(…)`. C'est la
|
|
484
|
+
source, pas une copie : la lire évite d'inventer une option qui n'existe pas
|
|
485
|
+
(une clé inconnue est retirée en silence à la validation). Ne recopie jamais ces
|
|
486
|
+
valeurs dans la doc du projet ; elles bougeront sans toi.
|
|
487
|
+
|
|
488
|
+
Pour ce que le PROJET offre comme choix (connecteurs déclarés, entités déjà
|
|
489
|
+
créées, types de colonnes de ton moteur) :
|
|
490
|
+
`npx nodefony create entity --describe-json` — c'est la même source que le
|
|
491
|
+
formulaire de Studio, à jour par construction.
|
|
492
|
+
|
|
493
|
+
## Pièges qui coûtent cher — vécus, pas théoriques
|
|
494
|
+
|
|
495
|
+
Chacun a déjà fait perdre une heure et beaucoup d'allers-retours. Le symptôme ne
|
|
496
|
+
désigne jamais la cause : c'est ce qui les rend chers.
|
|
497
|
+
|
|
498
|
+
- **Un test rouge en suite, VERT rejoué seul** — une ressource PARTAGÉE entre fichiers (serveur, table, état global) — pas une régression de ton diff → rejoue-le seul : l'isolation dit la vérité ; puis donne à chaque fichier sa propre ressource
|
|
499
|
+
- **Le serveur lancé en arrière-plan a disparu** — `… &` reçoit SIGHUP et meurt ; et tuer le PID du port ne tue pas le superviseur, qui respawne → `npx nodefony production --detach --wait` pour démarrer, `npx nodefony stop` pour arrêter — jamais `&`, jamais un kill par le port
|
|
500
|
+
- **Des dizaines de tests d'intégration rouges d'un coup** — ils FRAPPENT un serveur, ils ne le lancent pas : il est éteint (`ECONNREFUSED`) → `npx nodefony status` d'abord ; en e2e, laisse la commande gérer le cycle
|
|
501
|
+
- **La route existe dans le code et répond 404** — le runtime charge `dist/`, pas tes sources → `npm run build` — et en cas de doute vérifie le `dist/` par son CONTENU (`grep` du symbole), jamais par sa date
|
|
502
|
+
- **Ta route NEUVE répond 404, et le `dist/` est à jour** — elle n'est pas montée où tu crois : le chemin réel est le PRÉFIXE de son controller suivi du `path` de la route — une action `path: "/widget"` posée dans un controller `@controller("/api")` répond sur `/api/widget` → `npx nodefony inspect routes --json` donne le chemin MONTÉ ; si l'URL demandée ne doit pas porter le préfixe, la route va dans un controller qui n'en a pas
|
|
503
|
+
- **TOUT répond 404, même les routes du gabarit** — un AUTRE serveur tient les ports — ou LE TIEN a glissé sur d'autres ports, le port voulu étant pris → `npx nodefony status` : il montre les ports RÉELS, pas ceux que tu as configurés, et NOMME le projet voisin qui tient un port ; `npx nodefony stop <nom>` l'arrête sans te déplacer
|
|
504
|
+
- **L'app démarre, et pourtant une brique manque** (base injoignable, module absent) — une brique peut tomber en fail-soft, ou être écartée par sa `policy` : le boot CONTINUE, et le journal ne le dit qu'une fois, dans le terminal de celui qui a lancé → `npm run doctor` — il lit `var/last-boot.json` et nomme chaque brique absente AVEC sa raison
|
|
505
|
+
- **L'app ne démarre plus et tu n'as pas la sortie** (démarrage détaché, conteneur, CI) — le journal est parti avec le terminal → `npm run doctor` n'exécute rien : il rapporte la phase atteinte et la cause du dernier démarrage
|
|
506
|
+
- **Ça marche en dev, c'est mort en production** — les modules `policy: dev` sont RETIRÉS en production — ce qu'ils portaient disparaît avec eux → avant de livrer, UN boot `npx nodefony production --detach --wait` et rejoue tes vérifications
|
|
507
|
+
- **Un réglage de `nodefony.config.ts` ne change rien** — clé inconnue ou mal placée : retirée EN SILENCE à la validation → `npx nodefony inspect config --json` — la config effective et la provenance de chaque valeur
|
|
508
|
+
- **Une variable d'environnement « ne prend pas »** — mal orthographiée (ignorée en silence) ou masquée par un rang supérieur → `npx nodefony env` — il montre la valeur EFFECTIVE et sa provenance
|
|
509
|
+
- **Après un échec au milieu d'une chaîne `&&`, tout ment** — rien d'aval n'a tourné : tu mesures l'état d'AVANT → après tout échec, considère que la suite n'a pas eu lieu — revérifie que l'artefact mesuré a été régénéré
|
|
510
|
+
- **Les tests passent, `npm run typecheck` échoue** — le runner efface les types : un test vert ne typecheck rien → lance les DEUX avant de conclure
|
|
511
|
+
- **Suite verte, et le câblage est mort** — un test qui ne quitte pas la brique ne prouve que la brique → débranche le point de câblage : si rien ne tombe, il n'est pas testé
|
|
512
|
+
- **Un test vert « prouve » une garantie de sécurité** — elle est vraie dans la fonction, fausse sur le trajet réel → frappe la route en anonyme et regarde si le code a tourné
|
|
513
|
+
- **Un test qui n'a jamais échoué** — il ne garde rien — un test neuf est complaisant par défaut → casse-le exprès une fois, vérifie qu'il rougit
|
|
514
|
+
- **« Tout est vert » alors qu'une suite ne s'est pas exécutée** — un test sauté compte comme réussi — et un fichier jamais COLLECTÉ (erreur de syntaxe, hors du glob) ne compte pas du tout → lis le NOMBRE de tests, pas la couleur
|
|
515
|
+
- **`localhost` et `127.0.0.1` te jouent des tours** — ce sont deux ORIGINES distinctes : cookies, cache et passkeys ne les partagent pas → une seule origine en développement, partout — URL ouverte comme callbacks
|
|
516
|
+
<% if (it.hasSecurity) { %>- **Ta page répond 200 et son script ne s'exécute pas** — la politique de contenu exige un `nonce` sur les scripts, et le navigateur refuse un `<script>` en ligne qui n'en porte pas (« Refused to execute inline script ») : un `curl` ne le voit JAMAIS, il ne lit que le corps → signe le script (`<script nonce="…">`, valeur `this.context?.cspNonce` de ton controller) ou sors-le dans un fichier servi ; ne desserre PAS la politique (`'unsafe-inline'`), et le journal du serveur te le dit en développement — détail : `node_modules/@nodefony/security/docs/headers.md`
|
|
517
|
+
<% } %><% if (it.hasOrm) { %>- **La modif d'une entité « ne prend pas »** (erreur SQL au runtime) — en développement, un champ AJOUTÉ qui accepte le vide est posé au boot suivant, un champ OBLIGATOIRE ne l'est jamais, et aucune colonne n'est jamais retirée → écris la migration (`npx nodefony orm:generate` puis `npx nodefony orm:migrate`), qui vaut en dev comme en production ; `npx nodefony orm:reset` refait la base à neuf et **perd les données** — à ne taper que sur une base dont le contenu ne compte pour personne
|
|
518
|
+
- **Un déploiement où « rien ne répond »** alors que les pods tournent — un exemplaire dont la base est en retard répond 503 sur `/readyz` (jamais sur `/livez`) et reste hors du répartiteur : c'est voulu, ce n'est pas une panne → `npx nodefony orm:migrate:status` dit qui est en retard ; applique les migrations, les pods se mettent en service SEULS
|
|
519
|
+
<% } %><% if (it.hasSecurity) { %>- **Les routes authentifiées plafonnent** quand le reste tient la charge — le stockage de session par défaut est SYNCHRONE : chaque reprise bloque la boucle d'événements → compare une route anonyme et une route authentifiée AVANT d'accuser TLS ou le pare-feu ; passe le stockage sur redis pour la charge
|
|
520
|
+
<% } %><% if (it.front) { %>- **En production, la modif front n'apparaît jamais** — hors développement il n'y a PAS de rechargement à chaud, et le manifeste est lu AU BOOT → `npm run build` → **redémarre le serveur** → rechargement forcé
|
|
521
|
+
- **Ta modif front n'apparaît pas (en dev)** — le navigateur sert son cache — et le rechargement à chaud ne remplace ni un singleton ni un composant qui gagne des hooks : le code neuf tourne sur du vieil état → rechargement forcé, et vérifie que Vite a bien recompilé
|
|
522
|
+
- **Une route d'API répond du HTML** — un repli SPA générique avale les routes voisines — le premier motif qui correspond gagne → repli en préfixe LITTÉRAL ; `npx nodefony inspect routes --json` montre l'ordre réel
|
|
523
|
+
- **Des utilisateurs « déconnectés au hasard »** — le traitement global « 401 = session expirée » frappe aussi les sondes d'authentification, où 401 est NORMAL — et détruit une session valide → exempte les sondes du traitement global
|
|
524
|
+
<% } %>
|
|
525
|
+
**Ce qui coûte le plus de tokens** : enchaîner arrêt → construction → démarrage
|
|
526
|
+
après chaque petite modification. Regroupe TOUTES tes modifications serveur, puis
|
|
527
|
+
UN seul cycle. Le serveur de développement reconstruit tout seul<% if (it.front) { %>, et le front
|
|
528
|
+
passe en rechargement à chaud — zéro redémarrage<% } %>. Et ne lance **jamais** une
|
|
529
|
+
construction pendant qu'une suite de tests interroge le serveur : il redémarre au
|
|
530
|
+
milieu, et tu passes l'heure suivante sur des 404 fantômes.
|
|
531
|
+
|
|
532
|
+
## Modules du projet
|
|
533
|
+
|
|
534
|
+
<% if (it.modules.length === 0) { %>Aucun — `npx nodefony create module <nom>` en pose un (workspace npm sous `modules/`).
|
|
535
|
+
<% } else { %><% it.modules.forEach(function (m) { %>- `<%= m.dir %>/` — `<%= m.name %>` (son `AGENTS.md` local prime quand tu travailles dedans)
|
|
536
|
+
<% }) %><% } %>
|
|
537
|
+
## Gates — vérifier avant de dire « fait »
|
|
538
|
+
|
|
539
|
+
```bash
|
|
540
|
+
npm run verify # ⬅ LA commande. typecheck + lint + tests + doctor, dans cet ordre
|
|
541
|
+
```
|
|
542
|
+
|
|
543
|
+
**Une seule à retenir, et c'est délibéré.** Les quatre gates ci-dessous existent
|
|
544
|
+
séparément pour qu'on puisse en relancer un ; mais tant qu'ils n'étaient QUE
|
|
545
|
+
séparés, il fallait penser à les enchaîner — et le premier oublié était toujours
|
|
546
|
+
le même, `typecheck`, celui que rien d'autre ne remplace : **le bundler ne
|
|
547
|
+
type-check pas**, ton code peut être bâti, servi, et ne pas compiler.
|
|
548
|
+
|
|
549
|
+
`verify` s'arrête au premier rouge, et ce rouge est ta tâche suivante.
|
|
550
|
+
|
|
551
|
+
```bash
|
|
552
|
+
npm run typecheck # types — le seul gate que le build ne fait PAS à ta place
|
|
553
|
+
npm run lint # style et pièges
|
|
554
|
+
npm test # unitaires, rapides, zéro serveur
|
|
555
|
+
npm run doctor # diagnostic : câblage, install, + BILAN du dernier démarrage
|
|
556
|
+
npm run test:e2e # boot RÉEL + HTTP/WS (build inclus) — HORS `verify` : c'est le gate LENT
|
|
557
|
+
```
|
|
558
|
+
|
|
559
|
+
### `doctor` — le premier réflexe quand quelque chose ne va pas
|
|
560
|
+
|
|
561
|
+
**Avant de chercher, demande.** `npx nodefony doctor` (ou `npm run doctor`) est
|
|
562
|
+
la commande de diagnostic : elle répond depuis n'importe quel sous-dossier, elle
|
|
563
|
+
n'exécute RIEN de ton application, et `--json` la rend exploitable par un script.
|
|
564
|
+
`check` en est un alias historique — le nom à retenir est `doctor`.
|
|
565
|
+
|
|
566
|
+
Ce qu'elle t'épargne : une demi-heure à chercher pourquoi une route répond 404,
|
|
567
|
+
pourquoi un service est introuvable, ou pourquoi l'app « marche » sans faire ce
|
|
568
|
+
qu'on lui demande. Elle ne devine pas — elle LIT, et elle nomme le geste.
|
|
569
|
+
|
|
570
|
+
```bash
|
|
571
|
+
npx nodefony doctor # sortie lisible ; sort en erreur s'il manque quelque chose
|
|
572
|
+
npx nodefony doctor --json # même chose, pour un script ou un agent
|
|
573
|
+
```
|
|
574
|
+
|
|
575
|
+
**`doctor` nomme d'abord ce qui empêche de DÉMARRER**, et il le fait sans rien
|
|
576
|
+
exécuter — donc il répond sur une app qui ne se lance plus :
|
|
577
|
+
|
|
578
|
+
- une **variable REQUISE** sans valeur ;
|
|
579
|
+
- un module que le manifeste charge mais qui n'est **pas installé** ;
|
|
580
|
+
- une dépendance déclarée **absente de `node_modules`** ;
|
|
581
|
+
- un **port déjà tenu** par un autre programme (le tien ne compte pas).
|
|
582
|
+
|
|
583
|
+
Il nomme aussi une **classe écrite que rien ne déclare** — une entité hors de
|
|
584
|
+
`@entities([…])`, un controller hors de `@controllers([…])`. Elle compile, les
|
|
585
|
+
tests qui l'importent passent, et la panne n'arrive qu'au démarrage suivant :
|
|
586
|
+
une table jamais créée, une route qui répond 404 sans que rien ne l'explique.
|
|
587
|
+
C'est le mode d'échec de la COPIE, celui qu'on fait en recopiant le voisin au
|
|
588
|
+
lieu d'appeler le générateur.
|
|
589
|
+
|
|
590
|
+
**`doctor` te dit aussi ce qui s'est passé au dernier démarrage**, et c'est la
|
|
591
|
+
seule façon de l'apprendre après coup : l'app écrit son bilan dans
|
|
592
|
+
`var/last-boot.json` à chaque boot. Deux cas que tu ne peux pas voir autrement :
|
|
593
|
+
|
|
594
|
+
- **elle ne démarre plus** — `doctor` n'exécute rien, donc il répond quand même,
|
|
595
|
+
et il nomme la phase atteinte et la cause ;
|
|
596
|
+
- **elle démarre mais AMPUTÉE** — c'est le cas piégeux : tout a l'air sain, et
|
|
597
|
+
une brique manque (base injoignable, module écarté par sa `policy`). Le
|
|
598
|
+
journal l'a dit une fois, au terminal de celui qui a lancé. `doctor` te le
|
|
599
|
+
redit, avec la RAISON de chaque brique absente.
|
|
600
|
+
|
|
601
|
+
Sur une app saine il n'en parle pas. S'il en parle, lis avant de coder.
|
|
602
|
+
|
|
603
|
+
## Piloter le serveur — et l'ARRÊTER
|
|
604
|
+
|
|
605
|
+
```bash
|
|
606
|
+
npm run dev # développement : rechargement auto, Ctrl+C pour arrêter
|
|
607
|
+
npx nodefony development --no-watch # développement SANS rechargement : un seul process, stable
|
|
608
|
+
npx nodefony status # que tourne-t-il ? ports, PID — ne boote rien
|
|
609
|
+
npx nodefony stop # arrêt PROPRE de tout runtime de cette app
|
|
610
|
+
npx nodefony stop <nom|chemin> # arrêter un AUTRE projet, sans changer de dossier
|
|
611
|
+
npx nodefony production --detach --wait # boot réel en arrière-plan ; rend la main ports OUVERTS
|
|
612
|
+
```
|
|
613
|
+
|
|
614
|
+
**Arrête ce que tu démarres.** Un serveur laissé derrière garde les ports : le run
|
|
615
|
+
suivant échoue sur une erreur qui ne parle jamais de lui (`EADDRINUSE`, ou pire, un
|
|
616
|
+
test qui interroge l'ANCIENNE version du code). `npx nodefony stop` est la sortie
|
|
617
|
+
propre, `npx nodefony status` dit ce qui reste.
|
|
618
|
+
|
|
619
|
+
**Ces deux commandes ne voient QUE cette application.** Plusieurs projets Nodefony
|
|
620
|
+
peuvent tourner sur la même machine ; `status` ne compte jamais les process du
|
|
621
|
+
voisin comme les tiens, il les NOMME dans une table à part (nom, ports tenus,
|
|
622
|
+
racine) — et ce nom est ce que `stop` accepte. Deux conséquences pour toi :
|
|
623
|
+
« aucune instance » veut dire « aucune À MOI », pas « rien ne tourne » ; et une
|
|
624
|
+
cible que `stop` ne peut pas désigner sans ambiguïté est REFUSÉE, avec un code de
|
|
625
|
+
sortie non nul et rien d'arrêté — **lis ce code**, un refus ressemble sinon à un
|
|
626
|
+
succès. Ne prends `--all` que pour faire table rase du poste entier : il emporte
|
|
627
|
+
les serveurs des autres projets, y compris ceux que tu n'as pas lancés.
|
|
628
|
+
|
|
629
|
+
**Pour faire tourner une suite contre un serveur, prends `--no-watch`.** Le mode
|
|
630
|
+
développement surveille les sources et relance le serveur dès qu'un fichier bouge —
|
|
631
|
+
ce qui est exactement ce qu'on veut en codant, et exactement ce qu'on ne veut pas
|
|
632
|
+
pendant un run : le redémarrage coupe les connexions sous les tests, et le rouge qui
|
|
633
|
+
en sort accuse le code alors que le fautif est le décor. `--no-watch` garde tout le
|
|
634
|
+
mode développement (mêmes modules, mêmes erreurs détaillées) et retire le seul
|
|
635
|
+
rechargement automatique.
|
|
636
|
+
|
|
637
|
+
⚠️ **Une suite lancée contre un serveur de PRODUCTION reçoit `404` sur tout.** Les
|
|
638
|
+
modules déclarés `policy: "dev"` n'y sont pas chargés — les routes que la suite
|
|
639
|
+
interroge n'existent tout simplement pas. C'est le rôle de cette politique, pas un
|
|
640
|
+
défaut à contourner. Si c'est bien le mode production que tu veux éprouver :
|
|
641
|
+
|
|
642
|
+
```bash
|
|
643
|
+
NF_WITH_DEV_MODULES=1 nodefony production --detach --wait # dérogation explicite
|
|
644
|
+
NF_WITH_DEV_MODULES_TTL_MIN=120 … # campagne longue (charge)
|
|
645
|
+
```
|
|
646
|
+
|
|
647
|
+
Ce runtime **s'arrête tout seul** (30 min par défaut, réglable jusqu'à 4 h, jamais
|
|
648
|
+
désarmable), après un préavis. Ce n'est pas une gêne : c'est ce qui empêche une
|
|
649
|
+
variable oubliée dans une image ou un manifeste de laisser des routes de banc
|
|
650
|
+
ouvertes en production pendant des mois. Règle le délai AVANT une mesure longue — un
|
|
651
|
+
serveur qui tombe au milieu ne rend pas une mesure fausse, il en rend une qu'on
|
|
652
|
+
croira vraie.
|
|
653
|
+
|
|
654
|
+
## Voir un écran toi-même — un navigateur, pas un `curl`
|
|
655
|
+
|
|
656
|
+
Un `curl` prouve qu'une route répond ; il ne dit pas si l'écran **se monte**. Le
|
|
657
|
+
devkit porte des sondes prêtes à l'emploi, qui s'exécutent de deux façons.
|
|
658
|
+
|
|
659
|
+
**Sur cette machine** — le plus court :
|
|
660
|
+
|
|
661
|
+
```bash
|
|
662
|
+
npm run see:setup
|
|
663
|
+
node node_modules/@nodefony/devkit/skills/nodefony-browser/scripts/inspect.mjs /
|
|
664
|
+
```
|
|
665
|
+
|
|
666
|
+
`see:setup` n'installe **rien de lourd par défaut** : le pilote pèse quelques
|
|
667
|
+
mégaoctets, et il essaie d'abord les navigateurs **déjà présents** sur la machine —
|
|
668
|
+
Chrome, puis Edge, qui est préinstallé sur tout Windows. Le navigateur complet
|
|
669
|
+
n'est téléchargé que si aucun ne répond, une seule fois par machine (cache
|
|
670
|
+
utilisateur partagé par tous tes projets, jamais dans `node_modules`) :
|
|
671
|
+
|
|
672
|
+
```bash
|
|
673
|
+
npx playwright install chromium
|
|
674
|
+
```
|
|
675
|
+
|
|
676
|
+
Le champ `navigateur` de la sortie dit lequel a servi — deux mesures faites avec
|
|
677
|
+
des navigateurs différents ne se comparent pas.
|
|
678
|
+
|
|
679
|
+
**En conteneur** — quand tu veux une mesure **comparable** dans le temps (image
|
|
680
|
+
épinglée, donc version figée), de l'**isolation** (le navigateur ne voit ni ton
|
|
681
|
+
disque ni ton réseau), ou que tu ne veux **rien** installer :
|
|
682
|
+
|
|
683
|
+
```bash
|
|
684
|
+
docker compose --profile browser up -d
|
|
685
|
+
docker cp node_modules/@nodefony/devkit/skills/nodefony-browser/scripts/. <%= it.appName %>-browser:/app/see-screen
|
|
686
|
+
docker exec <%= it.appName %>-browser node /app/see-screen/inspect.mjs /
|
|
687
|
+
```
|
|
688
|
+
|
|
689
|
+
Le **`/.`** de la copie n'est pas décoratif : sans lui, une seconde copie imbrique
|
|
690
|
+
un dossier de plus au lieu de remplacer, et tu relances une version périmée des
|
|
691
|
+
sondes sans le moindre message.
|
|
692
|
+
|
|
693
|
+
Tu obtiens un JSON : le titre, la langue, le thème, les **scripts réellement
|
|
694
|
+
servis**, les erreurs de console, une capture horodatée — et surtout des **mesures**
|
|
695
|
+
que ni une capture ni un `curl` ne donnent : la couleur, le fond effectif, le
|
|
696
|
+
**contraste calculé** (luminances WCAG) et la taille de chaque élément que tu
|
|
697
|
+
sondes (`-e "NF_BROWSER_PROBES=libellé=sélecteur,…"`). C'est la différence entre
|
|
698
|
+
« ça me paraît lisible » et « 7,39:1, donc AAA ».
|
|
699
|
+
|
|
700
|
+
`watch.mjs`, à côté, regarde le temps qui coule plutôt qu'un instant : frames
|
|
701
|
+
WebSocket horodatées dans les deux sens, réponses ≥ 400, erreurs de console. C'est
|
|
702
|
+
la seule façon de voir une frame qui n'arrive pas ou une reconnexion en boucle.
|
|
703
|
+
Il s'arrête sur une **condition applicative** (`NF_BROWSER_UNTIL`) plutôt que sur
|
|
704
|
+
une durée — mais **éprouve toute condition d'arrêt avec une condition IMPOSSIBLE**
|
|
705
|
+
avant de lui faire confiance : tant qu'elle n'a pas échoué une fois, rien ne dit
|
|
706
|
+
qu'elle discrimine.
|
|
707
|
+
|
|
708
|
+
### Auditer, pas seulement regarder
|
|
709
|
+
|
|
710
|
+
```bash
|
|
711
|
+
npm run audit:setup
|
|
712
|
+
npm run audit:web -- /tableau-de-bord
|
|
713
|
+
```
|
|
714
|
+
|
|
715
|
+
Lighthouse complet **sur une page authentifiée** — ce que l'extension du navigateur
|
|
716
|
+
ne sait pas faire. Cinq catégories, dont **`agentic-browsing`** : ce qu'un agent
|
|
717
|
+
d'intelligence artificielle trouve en arrivant sur ta page (arbre d'accessibilité,
|
|
718
|
+
stabilité visuelle, annotations WebMCP de tes formulaires, `llms.txt`).
|
|
719
|
+
|
|
720
|
+
`audit:setup` est **séparé** de `see:setup` parce que Lighthouse pèse une
|
|
721
|
+
vingtaine de mégaoctets : tu ne le paies que si tu audites.
|
|
722
|
+
|
|
723
|
+
⚠️ **Ne juge pas la note de performance sur le serveur de développement** :
|
|
724
|
+
modules servis un par un, sources non minifiées, rechargement à chaud. Elle
|
|
725
|
+
s'effondre pour des raisons qui n'existent pas en production. Cette catégorie
|
|
726
|
+
ne se mesure que sur une version bâtie.
|
|
727
|
+
|
|
728
|
+
Le mode d'emploi complet est le skill **`nodefony-browser`** du devkit (`ai:sync` en pose
|
|
729
|
+
le pointeur dans `.agents/skills/`).
|
|
730
|
+
|
|
731
|
+
**Quatre règles, sinon tu diagnostiqueras le vide** :
|
|
732
|
+
|
|
733
|
+
| Règle | Pourquoi |
|
|
734
|
+
| -------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
735
|
+
| Joins l'app par **`host.docker.internal`** | `localhost` désigne le conteneur, pas ta machine. Si tu as activé `domainCheck`, ajoute ce nom aux `trustedHosts` en développement, sinon la barrière répond `421`. |
|
|
736
|
+
| Passe par **HTTPS** | Le cookie de session est `secure` : sur une origine `http://` non-`localhost` le navigateur le **jette**, et tout revient en `401` — on croit alors que le login rate. |
|
|
737
|
+
| **Rien à poser** pour rendre Vite joignable | L'origine des assets se dérive du `Host` de ta requête : arriver par `host.docker.internal` suffit, l'allowlist Vite et le WebSocket du HMR suivent le même nom, et le poste reste servi sur `127.0.0.1` en même temps. Si la page annonce quand même `127.0.0.1:5173` depuis le conteneur, c'est que le nom ne franchit pas `trustedHosts`, ou qu'une `publicOrigin` explicite est configurée (elle gagne toujours). |
|
|
738
|
+
| **Attends un texte propre à l'écran visé** avant de lire ou capturer | Le SPA se monte APRÈS la navigation. Et attendre un texte présent aussi sur la page de connexion (le nom de l'app…) aboutit dans les deux cas : ça ne prouve rien. |
|
|
739
|
+
|
|
740
|
+
Une capture **n'écrase pas** un fichier existant : réutiliser un nom te fait relire
|
|
741
|
+
une image périmée pendant que l'appel répond « OK ». Nom neuf, ou vérifie la date.
|
|
742
|
+
|
|
743
|
+
**🔴 AVANT d'accuser ton code : le bundle SERVI est-il celui que tu as bâti ?** En
|
|
744
|
+
front pré-bâti, trois mécanismes indépendants te font observer du code que la source
|
|
745
|
+
ne contient plus — un build partiel qui ne purge pas la sortie (deux générations de
|
|
746
|
+
chunks, l'`index.html` pouvant désigner l'ancienne), un cache de build qui RESTAURE
|
|
747
|
+
un ancien `dist` par-dessus le tien, et le service d'assets qui lit l'`index.html`
|
|
748
|
+
au démarrage seulement. Le symptôme est traître : l'écran montre un composant que tu
|
|
749
|
+
as remplacé.
|
|
750
|
+
|
|
751
|
+
Le champ **`scripts`** rendu par `inspect.mjs` liste les fichiers servis à la page :
|
|
752
|
+
compare-les à ceux que désigne l'`index.html` produit dans `<module>/dist/frontend/`.
|
|
753
|
+
Deux valeurs différentes ⇒ le défaut n'est pas dans ton code. Rebâtis en forçant
|
|
754
|
+
(cache invalidé), redémarre le serveur, PUIS redémarre le conteneur navigateur —
|
|
755
|
+
son cache HTTP survit à un simple rechargement. Aucun de ces trois pas n'est
|
|
756
|
+
facultatif.
|
|
757
|
+
|
|
758
|
+
**L'autre voie — le serveur MCP.** Le même conteneur expose un serveur MCP
|
|
759
|
+
(`claude mcp add --transport http browser http://127.0.0.1:3001/mcp`) : prends-le
|
|
760
|
+
pour **explorer** une page interactivement, et les sondes ci-dessus pour tout le
|
|
761
|
+
reste. Le protocole intermédiaire coûte plusieurs fois le temps d'un appel direct,
|
|
762
|
+
ne rend rien qu'un script puisse exploiter, et sa session peut tomber sous toi.
|
|
763
|
+
|
|
764
|
+
Ce que ce navigateur ne remplace pas : le rechargement à chaud, l'animation et le
|
|
765
|
+
rendu fin — ça se juge dans un vrai navigateur. Lui répond à « l'écran se monte-t-il,
|
|
766
|
+
s'alimente-t-il, et crie-t-il dans la console ? ».
|
|
767
|
+
|
|
768
|
+
## Demander à l'app, plutôt que déduire du code
|
|
769
|
+
|
|
770
|
+
**Perdu ? Commence par ici** — la carte de visite dit qui répond, ce qui est
|
|
771
|
+
chargé, où lire et quoi lancer :
|
|
772
|
+
|
|
773
|
+
```bash
|
|
774
|
+
npx nodefony card # ajoute -j pour du JSON (| jq)
|
|
775
|
+
```
|
|
776
|
+
|
|
777
|
+
Elle répond **toujours** : sur une application pas encore construite, et depuis
|
|
778
|
+
un terminal qui n'a posé aucune variable d'environnement — elle ne lit que des
|
|
779
|
+
fichiers. Dans ce cas elle le DIT (« modules installés », pas « chargés ») et
|
|
780
|
+
renvoie à `npx nodefony inspect modules` pour ce qui est vraiment monté.
|
|
781
|
+
`devkit:card` reste accepté : c'est son ancien nom.
|
|
782
|
+
|
|
783
|
+
```bash
|
|
784
|
+
npx nodefony inspect routes --json # toutes les routes réelles (chemin, méthodes, controller)
|
|
785
|
+
npx nodefony inspect services --json # services enregistrés, et le module qui les porte
|
|
786
|
+
npx nodefony inspect config --json # config EFFECTIVE de chaque module (+ d'où vient chaque valeur)
|
|
787
|
+
npx nodefony inspect modules --json # modules CHARGÉS — pas ceux que le manifeste déclare
|
|
788
|
+
npx nodefony inspect module http # un module en détail
|
|
789
|
+
npx nodefony inspect entities --json # entités déclarées à l'ORM
|
|
790
|
+
npx nodefony inspect stores --json # où sont RÉELLEMENT écrites les données (sessions, cache…)
|
|
791
|
+
npx nodefony inspect graph --json # graphe des entités et de leurs relations
|
|
792
|
+
```
|
|
793
|
+
|
|
794
|
+
Ces commandes bootent l'app **sans ouvrir un seul port** et rendent exactement ce
|
|
795
|
+
que sert la console d'administration — même code, deux portes. Préfère-les à la
|
|
796
|
+
lecture des sources : une route dépend de décorateurs, d'un manifeste et d'un
|
|
797
|
+
ordre de chargement ; la déduire, c'est se tromper un jour sur deux. `--json` est
|
|
798
|
+
un flux pur, `| jq` fonctionne.
|
|
799
|
+
|
|
800
|
+
**« Que fait cette classe, où est-elle définie, qu'étend-elle ? » → une commande,
|
|
801
|
+
pas une fouille :**
|
|
802
|
+
|
|
803
|
+
```bash
|
|
804
|
+
npx nodefony symbols AbstractCrudService # définition, TSDoc, parenté — en O(1)
|
|
805
|
+
npx nodefony symbols --module @nodefony/http # toute la surface exportée d'un paquet
|
|
806
|
+
npx nodefony symbols # ce que le graphe couvre, et d'où il vient
|
|
807
|
+
```
|
|
808
|
+
|
|
809
|
+
Le graphe symbolique de TOUT le framework est livré avec le paquet `nodefony` :
|
|
810
|
+
la réponse ne dépend ni d'un serveur, ni d'un build, ni de ta connexion. Va y
|
|
811
|
+
chercher un symbole AVANT d'ouvrir un `.d.ts` ou de parcourir `node_modules` —
|
|
812
|
+
et avant, surtout, d'inventer une signature.
|
|
813
|
+
|
|
814
|
+
**Tu préfères des OUTILS à des commandes ? Cette app en expose, par MCP.** Les
|
|
815
|
+
mêmes réponses (`inspect`, `check`, `symbols`, `card`), servies en Model Context
|
|
816
|
+
Protocol — utile si ton client sait appeler des outils mais pas lancer un
|
|
817
|
+
terminal :
|
|
818
|
+
|
|
819
|
+
```bash
|
|
820
|
+
npx nodefony ai:mcp # écrit .mcp.json ; --dry-run pour voir sans écrire
|
|
821
|
+
```
|
|
822
|
+
|
|
823
|
+
Ce n'est **pas un process de plus** : le serveur MCP est une route de cette
|
|
824
|
+
application (`POST /nodefony/mcp`), donc il n'existe **que pendant que l'app
|
|
825
|
+
tourne**, et il suit chaque rechargement du serveur de développement sans rien à
|
|
826
|
+
resynchroniser. Après avoir écrit le fichier, **redémarre ton client** : aucun ne
|
|
827
|
+
relit sa configuration en cours de route.
|
|
828
|
+
|
|
829
|
+
⚠️ **L'ordre compte, et il se paie en silence** : ton client se connecte aux
|
|
830
|
+
serveurs MCP **au démarrage de TA session, une seule fois** — si l'application
|
|
831
|
+
ne tournait pas à cet instant, le serveur reste marqué `failed` et ses outils
|
|
832
|
+
n'apparaîtront **jamais** dans cette session, même après un
|
|
833
|
+
`npx nodefony development --detach --wait`. Démarre l'application D'ABORD, ta
|
|
834
|
+
session ENSUITE. Application éteinte ou session déjà ouverte : les commandes
|
|
835
|
+
CLI (`inspect`, `check`, `symbols`, `card`) rendent les mêmes réponses, sans
|
|
836
|
+
rien exiger.
|
|
837
|
+
|
|
838
|
+
Deux choses à savoir avant de t'étonner : la porte est **refusée à toute adresse
|
|
839
|
+
non locale** et à toute origine de navigateur non déclarée (`403`) — c'est une
|
|
840
|
+
protection contre une page web qui viserait ton `localhost`, pas un bogue ; et
|
|
841
|
+
elle **n'existe pas en production**, le module qui la sert étant `policy: "dev"`.
|
|
842
|
+
Réglages : `use("@nodefony/devkit", { mcp: { … } })`.
|
|
843
|
+
|
|
844
|
+
**Ces quatre outils décrivent le FRAMEWORK. Ceux du métier, c'est toi qui les
|
|
845
|
+
ajoutes** — n'importe quel module de cette application publie les siens en
|
|
846
|
+
implémentant `getMcpTools()`. C'est le seul moyen qu'un agent extérieur
|
|
847
|
+
interroge le domaine plutôt que la plomberie :
|
|
848
|
+
|
|
849
|
+
```ts
|
|
850
|
+
import { Module, mcpText, type IMcpTool } from "nodefony";
|
|
851
|
+
|
|
852
|
+
class Shop extends Module {
|
|
853
|
+
getMcpTools(): IMcpTool[] {
|
|
854
|
+
return [
|
|
855
|
+
{
|
|
856
|
+
name: "shop_stock",
|
|
857
|
+
// La description est ce qui DÉCLENCHE l'outil : dire ce qu'il rend ET
|
|
858
|
+
// quand s'en servir. Un modèle n'appelle pas ce qu'il ne comprend pas.
|
|
859
|
+
description:
|
|
860
|
+
"Stock réel d'une référence produit. À utiliser avant de proposer " +
|
|
861
|
+
"une commande — la réponse vient de la base, pas d'un cache.",
|
|
862
|
+
inputSchema: {
|
|
863
|
+
type: "object",
|
|
864
|
+
properties: { sku: { type: "string", description: "Référence" } },
|
|
865
|
+
required: ["sku"],
|
|
866
|
+
},
|
|
867
|
+
handler: async (args) => mcpText(await this.stock(String(args.sku))),
|
|
868
|
+
},
|
|
869
|
+
];
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
```
|
|
873
|
+
|
|
874
|
+
Rien ne s'enregistre au démarrage : la liste est relue à chaque requête, donc un
|
|
875
|
+
module ajouté apparaît sans rien redémarrer. `mcp.tools` ne filtre que les
|
|
876
|
+
outils **intégrés** — le tien est publié dès qu'il est déclaré. Un outil écarté
|
|
877
|
+
(nom hors `[a-zA-Z0-9_-]{1,64}`, nom déjà pris, handler absent) le dit en
|
|
878
|
+
`WARNING` dans les journaux du serveur : s'il manque à l'appel, la raison y est
|
|
879
|
+
déjà, ne la cherche pas dans ton handler — il n'a pas été appelé.
|
|
880
|
+
|
|
881
|
+
**Un outil qui touche à des données réservées se DÉCLARE tel** — `scopes` (tous
|
|
882
|
+
exigés) et/ou `requiresAuth`, et son handler reçoit l'appelant en second
|
|
883
|
+
paramètre pour borner ce qu'il rend :
|
|
884
|
+
|
|
885
|
+
```ts
|
|
886
|
+
{
|
|
887
|
+
name: "shop_invoice",
|
|
888
|
+
description: "Facture d'une commande.",
|
|
889
|
+
inputSchema: { type: "object", properties: { id: { type: "string" } } },
|
|
890
|
+
scopes: ["shop:read", "shop:billing"],
|
|
891
|
+
handler: async (args, caller) => mcpText(await this.invoice(args.id, caller.subject)),
|
|
892
|
+
}
|
|
893
|
+
```
|
|
894
|
+
|
|
895
|
+
Un outil ainsi déclaré est **retenu** tant que l'appelant ne présente pas ce
|
|
896
|
+
qu'il exige : absent de `tools/list`, **et** inappelable en le nommant — un
|
|
897
|
+
catalogue filtré dont les outils cachés répondent quand même ne serait qu'un
|
|
898
|
+
rideau. Le refus dit « outil inconnu », jamais « interdit » : son existence même
|
|
899
|
+
n'est pas révélée.
|
|
900
|
+
|
|
901
|
+
⚠️ **Aujourd'hui cette porte n'authentifie PERSONNE** — elle ne valide aucun
|
|
902
|
+
jeton. Un outil qui exige des scopes est donc, ici et maintenant, **invisible
|
|
903
|
+
pour toujours**. C'est voulu (fermé par défaut), mais retiens-en la conséquence
|
|
904
|
+
pratique : tant que l'authentification n'est pas branchée, n'attends pas d'un
|
|
905
|
+
outil protégé qu'il réponde — c'est le comportement normal, pas une panne.
|
|
906
|
+
|
|
907
|
+
⚠️ Et pour les outils publics : avant d'exposer une donnée, demande-toi si elle
|
|
908
|
+
supporterait d'être lue **sans identification** par qui a accès à la machine.
|
|
909
|
+
|
|
910
|
+
**Ce que rend `inspect` ENGLOBE tes sources, et les dépasse de loin.** Les modules
|
|
911
|
+
installés — ceux du framework compris — montent leurs propres routes, services et
|
|
912
|
+
entités : une app qui ne définit qu'une poignée de routes en expose couramment plus
|
|
913
|
+
d'une centaine. Un écart d'un ordre de grandeur entre ce que tu lis dans tes
|
|
914
|
+
fichiers et `npx nodefony inspect routes --json | jq 'length'` n'est donc PAS une
|
|
915
|
+
anomalie de l'outil : c'est la différence entre ce que TU as écrit et ce que l'app
|
|
916
|
+
MONTE. Dès que la question porte sur l'app, le chiffre juste est celui d'`inspect` —
|
|
917
|
+
compter dans les sources répond à une autre question que celle posée.
|
|
918
|
+
|
|
919
|
+
**Si la commande te résiste, répare l'APPEL — ne te rabats pas sur les sources.**
|
|
920
|
+
C'est le réflexe qui coûte le plus cher, parce qu'il produit une réponse d'allure
|
|
921
|
+
normale : un shell qui manque un outil (`timeout` n'existe pas sur macOS), un `jq`
|
|
922
|
+
mal formé, et l'on se replie sur ce qu'on sait lire. Les fichiers répondront
|
|
923
|
+
toujours quelque chose — mais pas à la question posée. Relance sans le tube pour
|
|
924
|
+
voir la sortie brute, puis remets ton filtre.
|
|
925
|
+
|
|
926
|
+
N'invente pas d'attente : `--wait` ne rend la main qu'une fois les ports en écoute
|
|
927
|
+
— un `sleep` arbitraire est soit trop court (test rouge sans raison), soit du temps
|
|
928
|
+
perdu à chaque exécution. `npm run test:e2e` gère déjà ce cycle tout seul.
|
|
929
|
+
|
|
930
|
+
## Méthode de travail
|
|
931
|
+
|
|
932
|
+
1. **Budget tokens = une règle de conception** : lire ciblé via les tables
|
|
933
|
+
ci-dessus ; ne jamais scanner le projet entier.
|
|
934
|
+
2. **Le poids du modèle est un CHOIX, et il est mesuré ici** (si ton outil sait
|
|
935
|
+
déléguer à des sous-agents). Une tâche couverte par un **générateur** ne
|
|
936
|
+
demande pas un gros modèle : c'est le générateur qui porte le savoir, pas le
|
|
937
|
+
modèle. Mesuré sur ce framework, « ajoute une ressource REST » rend le MÊME
|
|
938
|
+
résultat en modèle léger et en modèle fort — mêmes contrôles verts, écart
|
|
939
|
+
d'étapes dans le bruit — pour **~3× moins cher**. À l'inverse, le socle SANS
|
|
940
|
+
générateur (flux, session, cycle de vie) fait échouer le modèle léger environ
|
|
941
|
+
une fois sur deux. Donc : **léger** pour appeler un générateur, inventorier,
|
|
942
|
+
lire, vérifier un fait, appliquer un patron ; **fort** pour écrire du socle
|
|
943
|
+
sans générateur et pour arbitrer une architecture. Le test qui tranche en une
|
|
944
|
+
seconde : _la tâche a-t-elle une bonne réponse vérifiable ?_ Aucun nom de
|
|
945
|
+
modèle ici — ils changent tous les trimestres ; raisonne en poids.
|
|
946
|
+
3. **Une règle = une source** : ce fichier POINTE la doc, il ne la recopie
|
|
947
|
+
pas ; n'y recopie rien non plus.
|
|
948
|
+
4. **Batcher les modifs serveur** puis UN SEUL cycle build/restart ; le
|
|
949
|
+
frontend passe en HMR, zéro restart.
|
|
950
|
+
5. **Vérifier avant de dire « fait »** : `npm run verify`, jamais `npm test`
|
|
951
|
+
seul — vitest n'inspecte AUCUN type, une app peut être verte et ne pas
|
|
952
|
+
compiler ; un vert ne couvre que le diff qui l'a produit ; suspecte ton
|
|
953
|
+
propre diff.
|
|
954
|
+
6. **La mémoire de l'app est ci-dessous** : accumule les leçons DURABLES dans
|
|
955
|
+
la zone Notes — pas dans des commentaires éparpillés.
|
|
956
|
+
|
|
957
|
+
## Notes de cette app (zone préservée à la régénération)
|
|
958
|
+
|
|
959
|
+
Fichier 100 % généré (nodefony <%= it.nodefonyVersion %>) — régénéré par les
|
|
960
|
+
commandes `create`, il ne peut pas mentir. Tes leçons propres à CETTE app vont
|
|
961
|
+
dans la zone ci-dessous : elle survit à la régénération.
|
|
962
|
+
|
|
963
|
+
<!-- app-notes:start -->
|
|
964
|
+
|
|
965
|
+
_(vide — leçons, gotchas et conventions propres à cette app, au fil des sessions)_
|
|
966
|
+
|
|
967
|
+
<!-- app-notes:end -->
|