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,1004 @@
|
|
|
1
|
+
import "../../cli/sysexits.js";
|
|
2
|
+
import { clearRuntimeState, defaultDevPorts, devSupervisorPidFile, discoverDevProcesses, findRuntimeConflict, formatForeignRuntimes, identifyProcess, isPidAlive, missingWorkspaceDists, probePorts, readRuntimeState, readSupervisorSuspension, signalProcessGroup, splitByProject, terminateDevProcesses } from "./devProcess.js";
|
|
3
|
+
import { waitBootVerdict } from "./bootVerdict.js";
|
|
4
|
+
import { existsSync, mkdirSync, readFileSync, readdirSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
import { spawn } from "node:child_process";
|
|
7
|
+
import readline from "node:readline";
|
|
8
|
+
import net from "node:net";
|
|
9
|
+
import { watch } from "chokidar";
|
|
10
|
+
//#region src/service/dev/DevSupervisor.ts
|
|
11
|
+
const ANSI = {
|
|
12
|
+
dim: "\x1B[90m",
|
|
13
|
+
cyan: "\x1B[36m",
|
|
14
|
+
green: "\x1B[32m",
|
|
15
|
+
red: "\x1B[31m",
|
|
16
|
+
yellow: "\x1B[33m",
|
|
17
|
+
reset: "\x1B[0m"
|
|
18
|
+
};
|
|
19
|
+
/** Frames braille du spinner de build (mêmes que le BootReporter enfant). */
|
|
20
|
+
const SPIN = [
|
|
21
|
+
"⠋",
|
|
22
|
+
"⠙",
|
|
23
|
+
"⠹",
|
|
24
|
+
"⠸",
|
|
25
|
+
"⠼",
|
|
26
|
+
"⠴",
|
|
27
|
+
"⠦",
|
|
28
|
+
"⠧",
|
|
29
|
+
"⠇",
|
|
30
|
+
"⠏"
|
|
31
|
+
];
|
|
32
|
+
/**
|
|
33
|
+
* Ce chemin doit-il être IGNORÉ par le watch des sources backend ?
|
|
34
|
+
*
|
|
35
|
+
* Le superviseur ne surveille que le **serveur** : les sources client ont leur
|
|
36
|
+
* propre boucle (HMR Vite), les artefacts (`dist`) sont produits par le build, et
|
|
37
|
+
* les tests ne font pas partie du runtime.
|
|
38
|
+
*
|
|
39
|
+
* ⚠️ Le piège que cette fonction referme : « frontend » est un RÔLE (le dossier
|
|
40
|
+
* des sources SPA d'un module : `studio/frontend/`, `modules/x/frontend/`) **et**
|
|
41
|
+
* un NOM DE PAQUET (`@nodefony/frontend`, le builder Vite — qui est du code
|
|
42
|
+
* SERVEUR). Ignorer tout segment nommé `frontend` rendait le watch AVEUGLE sur
|
|
43
|
+
* tout ce paquet : on l'éditait, il ne se passait rien, jamais. On n'exclut donc
|
|
44
|
+
* le dossier `frontend` que lorsqu'il n'est PAS le paquet `@nodefony/frontend`.
|
|
45
|
+
*
|
|
46
|
+
* Fonction PURE (pas de fs) → testable sans chokidar ni serveur.
|
|
47
|
+
*
|
|
48
|
+
* @param p - chemin du fichier ou dossier (relatif au projet, ou absolu).
|
|
49
|
+
* @param isFile - `true` si l'entrée est un fichier (un non-`.ts` est alors ignoré).
|
|
50
|
+
*/
|
|
51
|
+
function isIgnoredWatchPath(p, isFile = false) {
|
|
52
|
+
if (/(^|[/\\])(?<!@nodefony[/\\])frontend([/\\]|$)/.test(p)) return true;
|
|
53
|
+
if (/(^|[/\\])(node_modules|dist|\.git|tests)([/\\]|$)/.test(p)) return true;
|
|
54
|
+
if (/(^|[/\\])(tmp|var)([/\\]|$)/.test(p)) return true;
|
|
55
|
+
if (/\.(test|spec)\.ts$/.test(p)) return true;
|
|
56
|
+
if (isFile && !p.endsWith(".ts")) return true;
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Applique {@link isIgnoredWatchPath} à une entrée telle que chokidar la fournit —
|
|
61
|
+
* c'est-à-dire en chemin **absolu**.
|
|
62
|
+
*
|
|
63
|
+
* ⚠️ Le piège que cette fonction referme : les segments qui désignent un dossier de
|
|
64
|
+
* travail (`tmp`, `var`) sont des noms ORDINAIRES ailleurs. Sur macOS, `TMPDIR` vaut
|
|
65
|
+
* `/var/folders/…` — une application lancée depuis un dossier temporaire (ce que font
|
|
66
|
+
* nos propres bancs de scaffold) verrait donc CHAQUE entrée rejetée, et le watch
|
|
67
|
+
* deviendrait aveugle sans un mot. La règle ne vaut que **dans** le projet : on
|
|
68
|
+
* relativise au répertoire du projet AVANT de filtrer.
|
|
69
|
+
*
|
|
70
|
+
* @param cwd - racine du projet surveillé.
|
|
71
|
+
* @param p - chemin fourni par le watcher (absolu ou déjà relatif).
|
|
72
|
+
* @param isFile - `true` si l'entrée est un fichier.
|
|
73
|
+
*/
|
|
74
|
+
function shouldIgnoreWatchEntry(cwd, p, isFile = false) {
|
|
75
|
+
const relative = path.relative(cwd, path.resolve(cwd, p));
|
|
76
|
+
return isIgnoredWatchPath(relative.startsWith("..") ? p : relative, isFile);
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Rend une erreur du watcher NON FATALE : la signale et poursuit la surveillance.
|
|
80
|
+
*
|
|
81
|
+
* Le watch est un **capteur**, pas une garantie : un dossier qui disparaît pendant
|
|
82
|
+
* son scan, un lien symbolique cassé, une permission refusée sont des faits du
|
|
83
|
+
* système de fichiers, pas des fautes du superviseur. Sans écouteur `error`, Node
|
|
84
|
+
* convertit l'événement en exception non rattrapée — et le serveur de développement
|
|
85
|
+
* entier meurt d'un incident d'observation.
|
|
86
|
+
*
|
|
87
|
+
* ⚠️ **Portée exacte** : ce garde ne couvre que ce que chokidar émet LUI-MÊME
|
|
88
|
+
* (`_handleError`, dont l'`EPERM` de Windows). Une erreur levée par le flux de
|
|
89
|
+
* parcours interne ne passe PAS par le watcher — chokidar branche `close` et `end`
|
|
90
|
+
* sur ses streams, jamais `error` — et reste donc fatale. C'est pourquoi le cas vécu
|
|
91
|
+
* en intégration continue (la suite de tests supprimait `src/nodefony/tmp/copied`
|
|
92
|
+
* pendant qu'un serveur détaché tournait ; le parcours rendait `EBUSY` et le process
|
|
93
|
+
* sortait en 1) se referme en amont, en ne DESCENDANT pas dans les dossiers de
|
|
94
|
+
* travail — cf {@link isIgnoredWatchPath}, et non ici.
|
|
95
|
+
*
|
|
96
|
+
* Le prix d'une erreur avalée est réel — le watch peut avoir perdu une branche —
|
|
97
|
+
* donc on la DIT : un rechargement qui ne part plus sans un mot est un mystère.
|
|
98
|
+
*
|
|
99
|
+
* @param watcher - l'émetteur à protéger (le `FSWatcher` de chokidar en production).
|
|
100
|
+
* @param log - reçoit le message à journaliser.
|
|
101
|
+
*/
|
|
102
|
+
function attachWatcherErrorGuard(watcher, log) {
|
|
103
|
+
watcher.on("error", (error) => {
|
|
104
|
+
const err = error;
|
|
105
|
+
const code = err?.code ? `${err.code} ` : "";
|
|
106
|
+
const where = err?.path ? ` sur ${err.path}` : "";
|
|
107
|
+
log(`watch : ${code}${err?.message ?? String(error)}${where} — ignoré, surveillance maintenue`);
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Cadence de re-vérification du verrou de suspension du superviseur.
|
|
112
|
+
*
|
|
113
|
+
* Assez court pour que le rechargement suive de près la fin du job, assez long pour ne
|
|
114
|
+
* pas relire un fichier en boucle serrée pendant un `npm install` d'une minute.
|
|
115
|
+
*/
|
|
116
|
+
const SUSPENSION_RECHECK_MS = 1e3;
|
|
117
|
+
/** Au-delà de cette durée de vie, un crash n'est plus considéré « rapide ». */
|
|
118
|
+
const FAST_CRASH_MS = 3e3;
|
|
119
|
+
/** Nombre maximal de redémarrages auto après un crash rapide (anti-boucle). */
|
|
120
|
+
const MAX_SPAWN_RETRIES = 3;
|
|
121
|
+
/** Pause avant un redémarrage après crash rapide (laisse les ports se libérer). */
|
|
122
|
+
const RETRY_DELAY_MS = 1200;
|
|
123
|
+
/** Délai max d'attente de libération des ports avant un restart. */
|
|
124
|
+
const PORTS_FREE_TIMEOUT_MS = 5e3;
|
|
125
|
+
/**
|
|
126
|
+
* Délai max d'attente de l'écoute des ports après un (re)spawn avant de signaler
|
|
127
|
+
* un boot qui ne vient pas. Le boot dev peut être lent (Vite + modules) → marge
|
|
128
|
+
* large : on ne crie au loup que si le serveur est vraiment muet.
|
|
129
|
+
*/
|
|
130
|
+
const READY_TIMEOUT_MS = 3e4;
|
|
131
|
+
/** Cadence de sonde « le serveur écoute-t-il ? » après un (re)spawn. */
|
|
132
|
+
const READY_POLL_MS = 200;
|
|
133
|
+
/**
|
|
134
|
+
* Fenêtre de stabilisation du verdict de santé après que les ports écoutent. Les ports
|
|
135
|
+
* TCP acceptent (bind OS) AVANT que le Kernel finalise `bootServers` / la fin du boot →
|
|
136
|
+
* `livez.degraded` est transitoirement vrai (`healthy=false` tant qu'aucun serveur n'est
|
|
137
|
+
* encore enregistré). On re-sonde jusqu'au verdict STABLE (`booted:true`) au plus ce
|
|
138
|
+
* délai avant de conclure : crier « dégradé » à tort érode la confiance dans le signal
|
|
139
|
+
* (anti-pattern « au loup », l'inverse du but de la sonde).
|
|
140
|
+
*/
|
|
141
|
+
const DEGRADED_SETTLE_MS = 5e3;
|
|
142
|
+
const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
143
|
+
/**
|
|
144
|
+
* Superviseur de développement « auto-restart » (modèle nodemon, cloud-native :
|
|
145
|
+
* le process serveur est jetable).
|
|
146
|
+
*
|
|
147
|
+
* Topologie : ce process **parent** ne boote PAS le kernel applicatif — il
|
|
148
|
+
* `spawn` le serveur dans un process **enfant** (même commande + variable d'env
|
|
149
|
+
* `NF_DEV_CHILD=1`), surveille les sources **backend** et, à chaque
|
|
150
|
+
* changement, rebuild puis **redémarre l'enfant**.
|
|
151
|
+
*
|
|
152
|
+
* Le restart doit emporter l'**arbre** de l'enfant — lui et les instances Vite du
|
|
153
|
+
* `ViteProcessSupervisor` — sans quoi chaque sauvegarde laisse un Vite orphelin
|
|
154
|
+
* retenant son port. Deux grammaires y mènent, une par famille de système, et une
|
|
155
|
+
* seule implémentation les porte (`signalProcessGroup`) : en POSIX l'enfant est
|
|
156
|
+
* spawné **detached**, donc leader d'un groupe que `process.kill(-pid, …)` emporte
|
|
157
|
+
* d'un coup ; sous Windows, où les groupes POSIX n'existent pas, il est au contraire
|
|
158
|
+
* **rattaché** pour que `taskkill /T` puisse descendre la filiation. Avant chaque
|
|
159
|
+
* relance, le superviseur attend que les ports serveur soient libres
|
|
160
|
+
* (anti-`EADDRINUSE`) et retente de façon bornée si l'enfant crashe immédiatement.
|
|
161
|
+
*
|
|
162
|
+
* Pourquoi pas de HMR backend : Node ne décharge pas un module ESM déjà importé →
|
|
163
|
+
* un re-bundle du `dist/` ne rechargerait rien. Le restart de process est le seul
|
|
164
|
+
* rechargement backend fiable. Le **frontend** (Vite) garde son HMR : le dossier
|
|
165
|
+
* `frontend/` est exclu de la surveillance → une modif front ne redémarre pas le
|
|
166
|
+
* serveur.
|
|
167
|
+
*/
|
|
168
|
+
var DevSupervisor = class {
|
|
169
|
+
#cwd;
|
|
170
|
+
#paths;
|
|
171
|
+
#debounceMs;
|
|
172
|
+
#childEnvKey;
|
|
173
|
+
/**
|
|
174
|
+
* Ports imposés à la construction (`options.ports` / `NF_DEV_PORTS`). `null`
|
|
175
|
+
* = on APPREND les ports réels de l'enfant (cf {@link DevSupervisor.ports}) —
|
|
176
|
+
* indispensable depuis `servers.portPolicy: "auto"` : l'enfant peut écouter
|
|
177
|
+
* ailleurs que sur 5151/5152, et le superviseur doit suivre, pas supposer.
|
|
178
|
+
*/
|
|
179
|
+
#portsOverride;
|
|
180
|
+
/**
|
|
181
|
+
* Derniers ports EFFECTIVEMENT publiés par l'enfant (state file). Mémorisés tant
|
|
182
|
+
* que le superviseur vit : au restart, l'enfant est mort et son state file purgé,
|
|
183
|
+
* mais il faut quand même attendre que SES ports se libèrent — sinon il en
|
|
184
|
+
* prendrait de nouveaux à chaque reload et l'onglet du navigateur casserait.
|
|
185
|
+
*/
|
|
186
|
+
#observedPorts = [];
|
|
187
|
+
/**
|
|
188
|
+
* Ports tenus par un AUTRE projet Nodefony, constatés au démarrage. Deux usages,
|
|
189
|
+
* tous deux vitaux depuis que le port peut glisser :
|
|
190
|
+
* - ne pas ATTENDRE leur libération (elle ne viendra pas) ;
|
|
191
|
+
* - ne pas les prendre pour une readiness (sonder « ça écoute » sur le serveur
|
|
192
|
+
* du voisin dirait OUI alors que notre enfant n'est même pas booté).
|
|
193
|
+
*/
|
|
194
|
+
#foreignHeldPorts = /* @__PURE__ */ new Set();
|
|
195
|
+
/** Fichier verrou single-instance (PID du superviseur courant). */
|
|
196
|
+
#pidFile;
|
|
197
|
+
/**
|
|
198
|
+
* App STANDALONE (générée par `create app`) vs monorepo du framework — signal :
|
|
199
|
+
* `turbo.json` (l'orchestrateur multi-workspace n'existe que dans le repo).
|
|
200
|
+
* En standalone, TOUT passage turbo serait un échec bruyant hors sujet
|
|
201
|
+
* (« Could not resolve workspace », vécu dans une app générée) : le seul
|
|
202
|
+
* build est celui de l'app (`rolldown -c`, le même que `npm run build`).
|
|
203
|
+
*/
|
|
204
|
+
#standalone;
|
|
205
|
+
#child = null;
|
|
206
|
+
#childSpawnedAt = 0;
|
|
207
|
+
#spawnRetries = 0;
|
|
208
|
+
#watcher = null;
|
|
209
|
+
#timer = null;
|
|
210
|
+
#building = false;
|
|
211
|
+
#pending = false;
|
|
212
|
+
/**
|
|
213
|
+
* Raison de la suspension en cours du rechargement (verrou posé par le serveur), ou
|
|
214
|
+
* `null`. Sert aussi à ne l.annoncer QU.UNE fois, et à dire quand elle se lève.
|
|
215
|
+
*/
|
|
216
|
+
#suspendedBy = null;
|
|
217
|
+
/**
|
|
218
|
+
* Problèmes du build INITIAL (verdict + tail de sortie), rejoués APRÈS le
|
|
219
|
+
* boot de l'enfant : le splash ASCII + les logs de boot noient le verdict
|
|
220
|
+
* émis AVANT le spawn — en scrollant, le dev ne le retrouvait plus (vécu).
|
|
221
|
+
* `null` = build initial sain, rien à rejouer.
|
|
222
|
+
*/
|
|
223
|
+
#bootBuildIssues = null;
|
|
224
|
+
#spinTimer = null;
|
|
225
|
+
#spinFrame = 0;
|
|
226
|
+
#spinLabel = "";
|
|
227
|
+
#stopping = false;
|
|
228
|
+
/**
|
|
229
|
+
* `true` une fois annoncé qu'un arrêt n'a pu emporter que l'enfant direct. Dit une
|
|
230
|
+
* seule fois : le mode dev rejoue ce chemin à CHAQUE sauvegarde, et un avertissement
|
|
231
|
+
* répété à l'infini cesse d'être lu.
|
|
232
|
+
*/
|
|
233
|
+
#orphanRiskWarned = false;
|
|
234
|
+
/** Fichiers modifiés depuis le dernier build (pour cibler le rebuild). */
|
|
235
|
+
#dirty = /* @__PURE__ */ new Set();
|
|
236
|
+
/** Cache dir → nom de workspace (`null` = app racine). */
|
|
237
|
+
#pkgCache = /* @__PURE__ */ new Map();
|
|
238
|
+
constructor(options) {
|
|
239
|
+
this.#cwd = options.cwd;
|
|
240
|
+
this.#debounceMs = options.debounceMs ?? 250;
|
|
241
|
+
this.#childEnvKey = options.childEnvKey ?? "NF_DEV_CHILD";
|
|
242
|
+
const wanted = options.paths ?? [
|
|
243
|
+
"src",
|
|
244
|
+
"nodefony",
|
|
245
|
+
"config",
|
|
246
|
+
"index.ts",
|
|
247
|
+
"nodefony.config.ts",
|
|
248
|
+
"env.ts"
|
|
249
|
+
];
|
|
250
|
+
this.#paths = wanted.filter((p) => existsSync(path.resolve(this.#cwd, p)));
|
|
251
|
+
this.#portsOverride = options.ports ?? null;
|
|
252
|
+
this.#pidFile = devSupervisorPidFile(this.#cwd);
|
|
253
|
+
this.#standalone = !existsSync(path.resolve(this.#cwd, "turbo.json"));
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Ports que le superviseur surveille — **résolus à chaque lecture**, jamais figés
|
|
257
|
+
* au constructeur.
|
|
258
|
+
*
|
|
259
|
+
* Avant `portPolicy: "auto"`, `[5151, 5152]` était une certitude. Ce n'en est plus
|
|
260
|
+
* une : si un autre projet tient 5151, l'enfant écoute ailleurs et le PUBLIE
|
|
261
|
+
* (state file). Un superviseur qui aurait mémorisé les ports au démarrage
|
|
262
|
+
* attendrait ensuite la libération de ports que personne ne tient, et déclarerait
|
|
263
|
+
* « boot bloqué » sur un serveur qui répond très bien.
|
|
264
|
+
*/
|
|
265
|
+
get #ports() {
|
|
266
|
+
if (this.#portsOverride) return this.#portsOverride;
|
|
267
|
+
const live = defaultDevPorts(this.#cwd);
|
|
268
|
+
if (this.#observedPorts.length === 0) return live;
|
|
269
|
+
return [.../* @__PURE__ */ new Set([...live, ...this.#observedPorts])];
|
|
270
|
+
}
|
|
271
|
+
/** Mémorise les ports réellement pris par l'enfant (lus dans son state file). */
|
|
272
|
+
#observePorts() {
|
|
273
|
+
const state = readRuntimeState(this.#cwd);
|
|
274
|
+
if (state && state.ports.length > 0) this.#observedPorts = [...state.ports];
|
|
275
|
+
}
|
|
276
|
+
/** Écrit une ligne préfixée sur stdout (pas de `console.log` — code core). */
|
|
277
|
+
#log(msg, color = "cyan") {
|
|
278
|
+
process.stdout.write(`${ANSI.dim}[dev]${ANSI.reset} ${ANSI[color]}${msg}${ANSI.reset}\n`);
|
|
279
|
+
}
|
|
280
|
+
/** Démarre le spinner `[dev] ⠋ <label>…` (TTY) ou une ligne statique (non-TTY). */
|
|
281
|
+
#startSpin(label) {
|
|
282
|
+
this.#spinLabel = label;
|
|
283
|
+
if (!process.stdout.isTTY) {
|
|
284
|
+
this.#log(`⚙ ${label}…`, "yellow");
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
287
|
+
this.#renderSpin();
|
|
288
|
+
this.#spinTimer = setInterval(() => this.#renderSpin(), 80);
|
|
289
|
+
this.#spinTimer.unref?.();
|
|
290
|
+
}
|
|
291
|
+
/** Réécrit la ligne du spinner avec la frame suivante (TTY animé). */
|
|
292
|
+
#renderSpin() {
|
|
293
|
+
this.#spinFrame = (this.#spinFrame + 1) % SPIN.length;
|
|
294
|
+
readline.clearLine(process.stdout, 0);
|
|
295
|
+
readline.cursorTo(process.stdout, 0);
|
|
296
|
+
process.stdout.write(`${ANSI.dim}[dev]${ANSI.reset} ${ANSI.cyan}${SPIN[this.#spinFrame]}${ANSI.reset} ${this.#spinLabel}${ANSI.dim}…${ANSI.reset}`);
|
|
297
|
+
}
|
|
298
|
+
/** Fige le spinner sur `[dev] <mark> <msg>` (verdict de la phase de build). */
|
|
299
|
+
#stopSpin(mark, msg, color) {
|
|
300
|
+
if (this.#spinTimer) {
|
|
301
|
+
clearInterval(this.#spinTimer);
|
|
302
|
+
this.#spinTimer = null;
|
|
303
|
+
}
|
|
304
|
+
if (process.stdout.isTTY) {
|
|
305
|
+
readline.clearLine(process.stdout, 0);
|
|
306
|
+
readline.cursorTo(process.stdout, 0);
|
|
307
|
+
}
|
|
308
|
+
process.stdout.write(`${ANSI.dim}[dev]${ANSI.reset} ${mark} ${ANSI[color]}${msg}${ANSI.reset}\n`);
|
|
309
|
+
}
|
|
310
|
+
/**
|
|
311
|
+
* Variante de {@link #run} qui CAPTURE la sortie au lieu de l'hériter — le
|
|
312
|
+
* spinner remplace le mur de logs turbo/rolldown. La sortie n'est révélée que sur
|
|
313
|
+
* ÉCHEC (le dev doit voir l'erreur de build : fail-loud).
|
|
314
|
+
*/
|
|
315
|
+
#runCaptured(cmd, args) {
|
|
316
|
+
return new Promise((resolve) => {
|
|
317
|
+
let output = "";
|
|
318
|
+
const p = spawn(cmd, args, {
|
|
319
|
+
cwd: this.#cwd,
|
|
320
|
+
stdio: [
|
|
321
|
+
"ignore",
|
|
322
|
+
"pipe",
|
|
323
|
+
"pipe"
|
|
324
|
+
],
|
|
325
|
+
shell: process.platform === "win32"
|
|
326
|
+
});
|
|
327
|
+
p.stdout?.on("data", (d) => output += d.toString());
|
|
328
|
+
p.stderr?.on("data", (d) => output += d.toString());
|
|
329
|
+
p.once("exit", (code) => resolve({
|
|
330
|
+
ok: code === 0,
|
|
331
|
+
output
|
|
332
|
+
}));
|
|
333
|
+
p.once("error", () => resolve({
|
|
334
|
+
ok: false,
|
|
335
|
+
output
|
|
336
|
+
}));
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
/** Déverse la sortie d'un build qui a échoué (après avoir figé le spinner). */
|
|
340
|
+
#dumpBuild(output) {
|
|
341
|
+
const txt = output.trim();
|
|
342
|
+
if (txt) process.stdout.write(`${txt}\n`);
|
|
343
|
+
}
|
|
344
|
+
/** Mémorise le verdict + les dernières lignes utiles pour le rejeu post-boot. */
|
|
345
|
+
#rememberBuildIssues(verdict, outputs) {
|
|
346
|
+
const tail = outputs.join("\n").split("\n").map((l) => l.trimEnd()).filter((l) => l.trim().length > 0).slice(-15);
|
|
347
|
+
this.#bootBuildIssues = {
|
|
348
|
+
verdict,
|
|
349
|
+
tail
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
/**
|
|
353
|
+
* Rejoue le verdict de build APRÈS le boot (appelé par {@link #reportReady}) —
|
|
354
|
+
* le splash ASCII et les logs de boot de l'enfant ont défilé depuis : sans ce
|
|
355
|
+
* rappel, un build en échec au démarrage disparaissait dans le scroll.
|
|
356
|
+
*/
|
|
357
|
+
#replayBuildIssues() {
|
|
358
|
+
if (!this.#bootBuildIssues) return;
|
|
359
|
+
const { verdict, tail } = this.#bootBuildIssues;
|
|
360
|
+
this.#bootBuildIssues = null;
|
|
361
|
+
this.#log("── rappel : le BUILD de démarrage avait un problème ──", "red");
|
|
362
|
+
this.#log(verdict, "red");
|
|
363
|
+
for (const line of tail) process.stdout.write(`${line}\n`);
|
|
364
|
+
this.#log("── fin du rappel build (corrige puis sauvegarde) ──", "red");
|
|
365
|
+
}
|
|
366
|
+
/**
|
|
367
|
+
* Démarre le superviseur : revendique le verrou single-instance (tue tout
|
|
368
|
+
* superviseur précédent resté en vie), branche les signaux d'arrêt, attend les
|
|
369
|
+
* ports libres puis lance l'enfant et la surveillance.
|
|
370
|
+
*/
|
|
371
|
+
async start() {
|
|
372
|
+
process.title = "nodefony-dev-supervisor";
|
|
373
|
+
await this.#claimSingleInstance();
|
|
374
|
+
this.#installSignals();
|
|
375
|
+
await this.#ensureBuilt();
|
|
376
|
+
await this.#waitPortsFree();
|
|
377
|
+
this.#spawnChild();
|
|
378
|
+
this.#startWatch();
|
|
379
|
+
this.#log(`superviseur actif (pid ${process.pid}) — recharge le backend à chaque modif de ${this.#paths.join(", ")} (frontend exclu → HMR Vite)`, "green");
|
|
380
|
+
}
|
|
381
|
+
/**
|
|
382
|
+
* Garantit un `dist/` à jour AVANT le premier `spawn` — `turbo` (cache par
|
|
383
|
+
* hash de contenu) décide ce qui doit réellement être reconstruit, l'app racine
|
|
384
|
+
* (`rolldown`, sans cache) n'est rebuildée que si ses sources sont plus récentes
|
|
385
|
+
* que son `dist`.
|
|
386
|
+
*
|
|
387
|
+
* Pourquoi : `start()` spawnait l'enfant sur le `dist/` existant **sans le
|
|
388
|
+
* vérifier**. Si une source avait changé hors d'une session du superviseur
|
|
389
|
+
* (`git pull`, `npm run clean` partiel, build oublié), le serveur bootait sur
|
|
390
|
+
* du vieux code → routes/providers manquants en **404 silencieux** (« vert mais
|
|
391
|
+
* cassé »). On corrige + on **annonce** (fail-loud sur la dégradation) ; un échec
|
|
392
|
+
* d'outillage ne BLOQUE pas le boot (fail-soft sur la disponibilité) mais est
|
|
393
|
+
* signalé bruyamment.
|
|
394
|
+
*/
|
|
395
|
+
async #ensureBuilt() {
|
|
396
|
+
if (this.#standalone) return this.#ensureBuiltStandalone();
|
|
397
|
+
const t0 = Date.now();
|
|
398
|
+
const errors = [];
|
|
399
|
+
const missingBefore = missingWorkspaceDists(this.#cwd);
|
|
400
|
+
this.#startSpin(missingBefore.length ? `Build du framework — ${missingBefore.length} dist manquant(s) : ${missingBefore.join(", ")}` : "Vérification du framework (turbo)");
|
|
401
|
+
const ws = await this.#runCaptured("npx", [
|
|
402
|
+
"turbo",
|
|
403
|
+
"run",
|
|
404
|
+
"build"
|
|
405
|
+
]);
|
|
406
|
+
if (!ws.ok) errors.push(ws.output);
|
|
407
|
+
let rootOk = true;
|
|
408
|
+
if (this.#rootDistStale()) {
|
|
409
|
+
this.#spinLabel = "Build de l'app (rolldown)";
|
|
410
|
+
const root = await this.#runCaptured("npx", [
|
|
411
|
+
"rolldown",
|
|
412
|
+
"-c",
|
|
413
|
+
"rolldown.config.ts"
|
|
414
|
+
]);
|
|
415
|
+
rootOk = root.ok;
|
|
416
|
+
if (!root.ok) errors.push(root.output);
|
|
417
|
+
}
|
|
418
|
+
let missing = missingWorkspaceDists(this.#cwd);
|
|
419
|
+
if (missing.length > 0) {
|
|
420
|
+
this.#spinLabel = `Rebuild forcé : ${missing.join(", ")}`;
|
|
421
|
+
const filters = missing.flatMap((n) => ["--filter", n]);
|
|
422
|
+
const forced = await this.#runCaptured("npx", [
|
|
423
|
+
"turbo",
|
|
424
|
+
"run",
|
|
425
|
+
"build",
|
|
426
|
+
"--force",
|
|
427
|
+
...filters
|
|
428
|
+
]);
|
|
429
|
+
if (!forced.ok) errors.push(forced.output);
|
|
430
|
+
missing = missingWorkspaceDists(this.#cwd);
|
|
431
|
+
}
|
|
432
|
+
const ms = Date.now() - t0;
|
|
433
|
+
if (missing.length > 0) {
|
|
434
|
+
const verdict = `dist TOUJOURS absent : ${missing.join(", ")} — ces modules ne se chargeront pas (app DÉGRADÉE). Corrige puis \`npm run build\`.`;
|
|
435
|
+
this.#stopSpin(`${ANSI.red}✗${ANSI.reset}`, verdict, "red");
|
|
436
|
+
this.#rememberBuildIssues(verdict, errors);
|
|
437
|
+
} else if (ws.ok && rootOk) {
|
|
438
|
+
const built = missingBefore.length ? ` — (re)construits : ${missingBefore.join(", ")}` : "";
|
|
439
|
+
this.#stopSpin(`${ANSI.green}✓${ANSI.reset}`, `Framework prêt${built} (${ms}ms)`, "green");
|
|
440
|
+
} else {
|
|
441
|
+
const verdict = "build INCOMPLET — démarrage sur le dist EXISTANT (possiblement périmé)";
|
|
442
|
+
this.#stopSpin(`${ANSI.yellow}⚠${ANSI.reset}`, verdict, "red");
|
|
443
|
+
this.#rememberBuildIssues(verdict, errors);
|
|
444
|
+
}
|
|
445
|
+
for (const e of errors) this.#dumpBuild(e);
|
|
446
|
+
}
|
|
447
|
+
/**
|
|
448
|
+
* Variante STANDALONE de {@link #ensureBuilt} — même contrat de résilience :
|
|
449
|
+
* fail-soft sur la DISPONIBILITÉ (un dist existant démarre quand même),
|
|
450
|
+
* fail-loud sur la DÉGRADATION (échec de build ANNONCÉ avec sa sortie et la
|
|
451
|
+
* marche à suivre — le dev ne doit jamais rester devant un « qu'est-ce que
|
|
452
|
+
* je fais ? »).
|
|
453
|
+
*/
|
|
454
|
+
async #ensureBuiltStandalone() {
|
|
455
|
+
const dist = path.join(this.#cwd, "dist", "index.js");
|
|
456
|
+
if (!this.#rootDistStale()) {
|
|
457
|
+
this.#log("app déjà construite (dist à jour)", "green");
|
|
458
|
+
return;
|
|
459
|
+
}
|
|
460
|
+
const t0 = Date.now();
|
|
461
|
+
this.#startSpin(existsSync(dist) ? "Rebuild de l'app (rolldown)" : "Premier build de l'app (rolldown)");
|
|
462
|
+
const res = await this.#runCaptured("npx", [
|
|
463
|
+
"rolldown",
|
|
464
|
+
"-c",
|
|
465
|
+
"rolldown.config.ts"
|
|
466
|
+
]);
|
|
467
|
+
if (res.ok) {
|
|
468
|
+
this.#stopSpin(`${ANSI.green}✓${ANSI.reset}`, `app construite (${Date.now() - t0}ms)`, "green");
|
|
469
|
+
return;
|
|
470
|
+
}
|
|
471
|
+
const verdict = existsSync(dist) ? "build en ÉCHEC — démarrage sur le dist EXISTANT (possiblement périmé). Corrige l'erreur ci-dessous puis sauvegarde (rebuild automatique)." : "build en ÉCHEC et AUCUN dist — le serveur ne peut pas démarrer. Corrige l'erreur ci-dessous puis sauvegarde (rebuild automatique).";
|
|
472
|
+
this.#stopSpin(existsSync(dist) ? `${ANSI.yellow}⚠${ANSI.reset}` : `${ANSI.red}✗${ANSI.reset}`, verdict, "red");
|
|
473
|
+
this.#rememberBuildIssues(verdict, [res.output]);
|
|
474
|
+
this.#dumpBuild(res.output);
|
|
475
|
+
}
|
|
476
|
+
/**
|
|
477
|
+
* `true` si le `dist/index.js` racine est absent ou plus ancien qu'une de ses
|
|
478
|
+
* sources — fichiers racine (`index.ts`/`nodefony.config.ts`/`env.ts`, 3 stats)
|
|
479
|
+
* et, en STANDALONE, les sources de l'app (`nodefony/`, `config/`, `modules/`)
|
|
480
|
+
* que turbo ne couvre pas (il n'y a pas de turbo). Une app est petite : la
|
|
481
|
+
* marche récursive coûte quelques stats, une fois, au boot.
|
|
482
|
+
*/
|
|
483
|
+
#rootDistStale() {
|
|
484
|
+
const dist = path.join(this.#cwd, "dist", "index.js");
|
|
485
|
+
if (!existsSync(dist)) return true;
|
|
486
|
+
let distMtime;
|
|
487
|
+
try {
|
|
488
|
+
distMtime = statSync(dist).mtimeMs;
|
|
489
|
+
} catch {
|
|
490
|
+
return true;
|
|
491
|
+
}
|
|
492
|
+
const stale = [
|
|
493
|
+
"index.ts",
|
|
494
|
+
"nodefony.config.ts",
|
|
495
|
+
"env.ts"
|
|
496
|
+
].some((src) => {
|
|
497
|
+
const p = path.join(this.#cwd, src);
|
|
498
|
+
try {
|
|
499
|
+
return existsSync(p) && statSync(p).mtimeMs > distMtime;
|
|
500
|
+
} catch {
|
|
501
|
+
return false;
|
|
502
|
+
}
|
|
503
|
+
});
|
|
504
|
+
if (stale || !this.#standalone) return stale;
|
|
505
|
+
for (const dirName of [
|
|
506
|
+
"nodefony",
|
|
507
|
+
"config",
|
|
508
|
+
"modules"
|
|
509
|
+
]) {
|
|
510
|
+
const dir = path.join(this.#cwd, dirName);
|
|
511
|
+
if (!existsSync(dir)) continue;
|
|
512
|
+
try {
|
|
513
|
+
for (const entry of readdirSync(dir, {
|
|
514
|
+
withFileTypes: true,
|
|
515
|
+
recursive: true
|
|
516
|
+
})) {
|
|
517
|
+
if (!entry.isFile() || !entry.name.endsWith(".ts")) continue;
|
|
518
|
+
const p = path.join(entry.parentPath, entry.name);
|
|
519
|
+
if (statSync(p).mtimeMs > distMtime) return true;
|
|
520
|
+
}
|
|
521
|
+
} catch {}
|
|
522
|
+
}
|
|
523
|
+
return false;
|
|
524
|
+
}
|
|
525
|
+
/**
|
|
526
|
+
* Garde **single-instance** : empêche l'empilement de superviseurs.
|
|
527
|
+
*
|
|
528
|
+
* Le superviseur est de type CONSOLE — il ne bind **aucun** port serveur, donc
|
|
529
|
+
* rien (pas d'`EADDRINUSE`) n'empêche d'en lancer plusieurs. Lancé `detached`,
|
|
530
|
+
* il survit à la fermeture du terminal. Sans ce verrou, chaque
|
|
531
|
+
* `nodefony development` ajoutait un superviseur orphelin de plus, et **tous**
|
|
532
|
+
* rebuildaient (turbo + rolldown) au moindre changement → machine saturée.
|
|
533
|
+
*
|
|
534
|
+
* Deux gardes complémentaires :
|
|
535
|
+
*
|
|
536
|
+
* 1. **Balayage `ps` (vérité terrain)** : single-instance ⇒ au démarrage AUCUN autre
|
|
537
|
+
* process dev ne doit subsister (notre enfant n'est pas encore spawné). On découvre
|
|
538
|
+
* et on tue tout résiduel — superviseur empilé MAIS aussi **orphelins** (serveur/Vite
|
|
539
|
+
* sans superviseur parent, laissés par un `kill -9` brutal que le pidfile périmé ne
|
|
540
|
+
* référence plus → cause de l'empilement). `discoverDevProcesses` s'auto-exclut, on
|
|
541
|
+
* ne se tue donc pas (notre `process.title` est déjà posé).
|
|
542
|
+
* 2. **Fallback pidfile** : si `ps` est indisponible (Windows, sandbox) le balayage rend
|
|
543
|
+
* une liste vide → on retombe sur la garde historique par PID lu dans le pidfile.
|
|
544
|
+
*
|
|
545
|
+
* Puis on écrit notre propre PID.
|
|
546
|
+
*/
|
|
547
|
+
async #claimSingleInstance() {
|
|
548
|
+
try {
|
|
549
|
+
const all = discoverDevProcesses();
|
|
550
|
+
const conflict = findRuntimeConflict(all, "dev");
|
|
551
|
+
const conflictHere = splitByProject(conflict, this.#cwd);
|
|
552
|
+
if (conflictHere.mine.length > 0) {
|
|
553
|
+
const otherMode = conflictHere.mine[0].mode === "cluster" ? "cluster" : "production";
|
|
554
|
+
const pids = conflictHere.mine.map((p) => p.pid).join(", ");
|
|
555
|
+
this.#log(`⛔ un runtime Nodefony ${otherMode} de CE projet tourne déjà (pid ${pids}) sur les ports ${this.#ports.join("/")} — le mode dev ne peut pas démarrer par-dessus`, "red");
|
|
556
|
+
this.#log("arrête-le d'abord : `nodefony stop`", "red");
|
|
557
|
+
process.exit(69);
|
|
558
|
+
}
|
|
559
|
+
const others = [...conflictHere.foreign, ...splitByProject(all.filter((p) => p.mode === "dev"), this.#cwd).foreign];
|
|
560
|
+
if (others.length > 0) {
|
|
561
|
+
const taken = (await probePorts(this.#ports)).filter((p) => p.listening).map((p) => p.port);
|
|
562
|
+
const who = others.map((p) => `pid ${p.pid} (${p.cwd ?? "dossier inconnu"})`).join(", ");
|
|
563
|
+
if (taken.length > 0) {
|
|
564
|
+
for (const p of taken) this.#foreignHeldPorts.add(p);
|
|
565
|
+
this.#log(`ports ${taken.join(", ")} occupés par un AUTRE projet Nodefony (${who}) — non touchés ; cette app prendra les premiers ports libres`, "yellow");
|
|
566
|
+
for (const line of formatForeignRuntimes(others)) process.stdout.write(`${line}\n`);
|
|
567
|
+
this.#log("figer les ports de CETTE app : nodefony.config.ts servers.*.port · échouer plutôt que glisser : servers.portPolicy = \"strict\"", "yellow");
|
|
568
|
+
} else this.#log(`${others.length} runtime(s) Nodefony d'un autre projet détecté(s) (${who}) — non touchés`, "yellow");
|
|
569
|
+
}
|
|
570
|
+
const stale = splitByProject(all.filter((p) => p.mode === "dev"), this.#cwd).mine;
|
|
571
|
+
if (stale.length > 0) {
|
|
572
|
+
this.#log(`${stale.length} process dev résiduel(s) de ce projet — nettoyage avant démarrage`, "yellow");
|
|
573
|
+
const survivors = await terminateDevProcesses(stale, { termWaitMs: 1500 });
|
|
574
|
+
if (survivors.length > 0) this.#log(`⚠ ${survivors.length} process résiduel(s) survivent (pid ${survivors.join(", ")}) — lance \`nodefony stop\` si le démarrage échoue`, "red");
|
|
575
|
+
}
|
|
576
|
+
} catch {}
|
|
577
|
+
try {
|
|
578
|
+
if (existsSync(this.#pidFile)) {
|
|
579
|
+
const prev = Number.parseInt(readFileSync(this.#pidFile, "utf8").trim(), 10);
|
|
580
|
+
if (Number.isInteger(prev) && prev > 0 && prev !== process.pid) {
|
|
581
|
+
if (this.#isNodefonySupervisor(prev)) {
|
|
582
|
+
this.#log(`superviseur précédent encore actif (pid ${prev}) — arrêt avant démarrage`, "yellow");
|
|
583
|
+
await this.#killSupervisor(prev);
|
|
584
|
+
} else if (isPidAlive(prev)) this.#log(`pid ${prev} du pidfile encore vivant mais non confirmé Nodefony — épargné ; s'il s'agit d'un superviseur résiduel : \`nodefony stop\``, "yellow");
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
} catch {}
|
|
588
|
+
try {
|
|
589
|
+
mkdirSync(path.dirname(this.#pidFile), { recursive: true });
|
|
590
|
+
writeFileSync(this.#pidFile, String(process.pid), "utf8");
|
|
591
|
+
} catch {}
|
|
592
|
+
}
|
|
593
|
+
/**
|
|
594
|
+
* `true` si `pid` est vivant ET qu'on a la PREUVE qu'il s'agit d'un superviseur
|
|
595
|
+
* Nodefony — sinon on n'y touche pas.
|
|
596
|
+
*
|
|
597
|
+
* Ce prédicat autorise un `kill`, il doit donc se taire quand il ne sait pas. Il
|
|
598
|
+
* répondait `true` sur toute absence d'observation (Windows, `ps` introuvable),
|
|
599
|
+
* c'est-à-dire qu'il tuait un PID **recyclé** par un process tiers dès que le
|
|
600
|
+
* moyen de regarder manquait — alors que `scopeAllToNodefonyProjects` épargne, à
|
|
601
|
+
* dix fichiers d'ici, tout process dont l'appartenance n'est pas prouvée. Deux
|
|
602
|
+
* doctrines opposées pour la même question ; celle qui épargne l'emporte.
|
|
603
|
+
*
|
|
604
|
+
* Trois faits concordants sont exigés, et le troisième existe partout
|
|
605
|
+
* ({@link identifyProcess}) :
|
|
606
|
+
*
|
|
607
|
+
* 1. le pidfile qui nomme ce PID vit dans **ce** projet (acquis par construction) ;
|
|
608
|
+
* 2. le process est vivant ;
|
|
609
|
+
* 3. l'observation le rattache à Nodefony — la ligne de commande porte le titre
|
|
610
|
+
* (POSIX), ou l'image est un runtime Node (Windows, où `tasklist` ne donne pas
|
|
611
|
+
* mieux : plus faible seule, décisive corroborée par (1)).
|
|
612
|
+
*
|
|
613
|
+
* Sans observation possible, le superviseur résiduel survit — c'est le prix, et il
|
|
614
|
+
* est ANNONCÉ par l'appelant, avec la commande qui le règle.
|
|
615
|
+
*/
|
|
616
|
+
#isNodefonySupervisor(pid) {
|
|
617
|
+
try {
|
|
618
|
+
process.kill(pid, 0);
|
|
619
|
+
} catch {
|
|
620
|
+
return false;
|
|
621
|
+
}
|
|
622
|
+
const { observed, command } = identifyProcess(pid);
|
|
623
|
+
if (!observed || command === null) return false;
|
|
624
|
+
const c = command.toLowerCase();
|
|
625
|
+
return c.includes("nodefony") || process.platform === "win32" && c.startsWith("node");
|
|
626
|
+
}
|
|
627
|
+
/**
|
|
628
|
+
* Tue le superviseur précédent et **son arbre** (enfant serveur + Vite) : SIGTERM
|
|
629
|
+
* (arrêt propre là où il existe), puis SIGKILL si toujours vivant après 1,5 s.
|
|
630
|
+
*/
|
|
631
|
+
async #killSupervisor(pid) {
|
|
632
|
+
signalProcessGroup(pid, "SIGTERM");
|
|
633
|
+
const deadline = Date.now() + 1500;
|
|
634
|
+
while (Date.now() < deadline) {
|
|
635
|
+
await delay(100);
|
|
636
|
+
try {
|
|
637
|
+
process.kill(pid, 0);
|
|
638
|
+
} catch {
|
|
639
|
+
return;
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
signalProcessGroup(pid, "SIGKILL");
|
|
643
|
+
await delay(200);
|
|
644
|
+
}
|
|
645
|
+
/** (Re)lance le serveur enfant — même commande + flag enfant, en leader de groupe. */
|
|
646
|
+
#spawnChild() {
|
|
647
|
+
this.#childSpawnedAt = Date.now();
|
|
648
|
+
clearRuntimeState(this.#cwd);
|
|
649
|
+
const child = spawn(process.execPath, process.argv.slice(1), {
|
|
650
|
+
cwd: this.#cwd,
|
|
651
|
+
env: {
|
|
652
|
+
...process.env,
|
|
653
|
+
[this.#childEnvKey]: "1"
|
|
654
|
+
},
|
|
655
|
+
stdio: "inherit",
|
|
656
|
+
detached: process.platform !== "win32"
|
|
657
|
+
});
|
|
658
|
+
this.#child = child;
|
|
659
|
+
child.once("exit", (code, signal) => {
|
|
660
|
+
if (this.#child !== child) return;
|
|
661
|
+
this.#child = null;
|
|
662
|
+
if (this.#stopping) return;
|
|
663
|
+
this.#onChildCrash(code, signal);
|
|
664
|
+
});
|
|
665
|
+
this.#reportReady(child);
|
|
666
|
+
}
|
|
667
|
+
/**
|
|
668
|
+
* Signale « serveur prêt » dès que les ports écoutent — et, surtout, détecte un
|
|
669
|
+
* boot qui **ne vient jamais** (enfant vivant mais muet : import qui pend, hook
|
|
670
|
+
* lifecycle bloqué) en émettant un avertissement après {@link READY_TIMEOUT_MS}.
|
|
671
|
+
*
|
|
672
|
+
* 100 % OBSERVATION EXTERNE (sonde TCP loopback, cf {@link #isPortFree}) — aucun
|
|
673
|
+
* IPC avec l'enfant (choix d'architecture). La sonde s'efface dès qu'un restart
|
|
674
|
+
* remplace l'enfant ({@link #child} change) ou que le superviseur s'arrête.
|
|
675
|
+
*/
|
|
676
|
+
async #reportReady(child) {
|
|
677
|
+
const t0 = Date.now();
|
|
678
|
+
const deadline = t0 + READY_TIMEOUT_MS;
|
|
679
|
+
for (;;) {
|
|
680
|
+
if (this.#child !== child || this.#stopping) return;
|
|
681
|
+
if (await this.#anyPortListening()) {
|
|
682
|
+
if (await waitBootVerdict(this.#ports[0], DEGRADED_SETTLE_MS, { aborted: () => this.#child !== child || this.#stopping }) === true) this.#log(`✓ ports à l'écoute en ${Date.now() - t0}ms — ⚠ MAIS boot DÉGRADÉ (modules ignorés) : lance \`nodefony status\` / vois les logs ci-dessus`, "yellow");
|
|
683
|
+
else this.#log(`✓ serveur prêt en ${Date.now() - t0}ms — framework ready`, "green");
|
|
684
|
+
this.#replayBuildIssues();
|
|
685
|
+
return;
|
|
686
|
+
}
|
|
687
|
+
if (Date.now() >= deadline) {
|
|
688
|
+
if (this.#child === child && !this.#stopping) {
|
|
689
|
+
this.#log(`⚠ serveur toujours pas à l'écoute après ${Math.round(READY_TIMEOUT_MS / 1e3)}s (ports ${this.#ports.join(", ")}) — boot bloqué ? voir les logs ci-dessus`, "yellow");
|
|
690
|
+
this.#replayBuildIssues();
|
|
691
|
+
}
|
|
692
|
+
return;
|
|
693
|
+
}
|
|
694
|
+
await delay(READY_POLL_MS);
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
/**
|
|
698
|
+
* `true` si AU MOINS UN port surveillé accepte une connexion. « Au moins un »
|
|
699
|
+
* et pas « tous » : la liste est une CONVENTION du superviseur (5151/5152),
|
|
700
|
+
* pas la topologie réelle — une app `https: false` n'ouvre JAMAIS 5152 et un
|
|
701
|
+
* « tous » criait « boot bloqué ? » à 30 s sur un serveur qui répondait très
|
|
702
|
+
* bien (même règle que la readiness de `launchDetached`, vécu 2×).
|
|
703
|
+
*/
|
|
704
|
+
async #anyPortListening() {
|
|
705
|
+
const state = readRuntimeState(this.#cwd);
|
|
706
|
+
if (state && this.#child && state.pid === this.#child.pid) {
|
|
707
|
+
this.#observePorts();
|
|
708
|
+
return (await Promise.all(state.ports.map((p) => this.#isPortFree(p)))).some((free) => !free);
|
|
709
|
+
}
|
|
710
|
+
if (this.#foreignHeldPorts.size > 0) return false;
|
|
711
|
+
if (this.#ports.length === 0) return true;
|
|
712
|
+
return (await Promise.all(this.#ports.map((p) => this.#isPortFree(p)))).some((free) => !free);
|
|
713
|
+
}
|
|
714
|
+
/**
|
|
715
|
+
* Sortie **non sollicitée** de l'enfant. Crash rapide (< {@link FAST_CRASH_MS})
|
|
716
|
+
* → probable port pas encore libre : retry borné après attente des ports. Crash
|
|
717
|
+
* tardif ou exit propre → on attend une sauvegarde (workflow nodemon).
|
|
718
|
+
*/
|
|
719
|
+
#onChildCrash(code, signal) {
|
|
720
|
+
const uptime = Date.now() - this.#childSpawnedAt;
|
|
721
|
+
const killed = signal === "SIGTERM" || signal === "SIGKILL";
|
|
722
|
+
if (!killed && (code === 69 || code === 78)) {
|
|
723
|
+
const why = code === 78 ? "configuration invalide" : "aucun serveur démarré";
|
|
724
|
+
this.#log(`le serveur ne démarre pas (${why}, code ${code}) — corrige puis sauvegarde (voir le diagnostic ci-dessus)`, "red");
|
|
725
|
+
this.#spawnRetries = 0;
|
|
726
|
+
return;
|
|
727
|
+
}
|
|
728
|
+
if (killed || !code) {
|
|
729
|
+
if (killed) this.#log(`serveur tué par un signal EXTERNE (${signal}) — un autre process a pris les ports (autre lancement dev, kill de port ?). Sauvegarde un fichier pour relancer ICI, ou arrête ce superviseur (Ctrl+C) si l'autre runtime est légitime`, "yellow");
|
|
730
|
+
else this.#log(`serveur arrêté (code ${code}) — en attente d'un changement`, "yellow");
|
|
731
|
+
this.#spawnRetries = 0;
|
|
732
|
+
return;
|
|
733
|
+
}
|
|
734
|
+
if (uptime > FAST_CRASH_MS) {
|
|
735
|
+
this.#log(`serveur arrêté (code ${code}) — en attente d'un changement`, "red");
|
|
736
|
+
this.#spawnRetries = 0;
|
|
737
|
+
return;
|
|
738
|
+
}
|
|
739
|
+
if (this.#spawnRetries >= MAX_SPAWN_RETRIES) {
|
|
740
|
+
this.#log(`crash rapide ×${this.#spawnRetries} — abandon ; corrige puis sauvegarde`, "red");
|
|
741
|
+
this.#spawnRetries = 0;
|
|
742
|
+
return;
|
|
743
|
+
}
|
|
744
|
+
this.#spawnRetries += 1;
|
|
745
|
+
this.#log(`crash rapide (${uptime}ms) — retry ${this.#spawnRetries}/${MAX_SPAWN_RETRIES}`, "yellow");
|
|
746
|
+
this.#respawnAfterPorts();
|
|
747
|
+
}
|
|
748
|
+
/** Attend les ports libres puis relance (sauf arrêt en cours). */
|
|
749
|
+
async #respawnAfterPorts() {
|
|
750
|
+
await delay(RETRY_DELAY_MS);
|
|
751
|
+
if (this.#stopping) return;
|
|
752
|
+
await this.#waitPortsFree();
|
|
753
|
+
if (this.#stopping) return;
|
|
754
|
+
this.#spawnChild();
|
|
755
|
+
}
|
|
756
|
+
/**
|
|
757
|
+
* Surveillance chokidar des sources backend (sources client / dist / tests
|
|
758
|
+
* exclus — cf {@link isIgnoredWatchPath}, la règle EXACTE, testée à part).
|
|
759
|
+
*/
|
|
760
|
+
#startWatch() {
|
|
761
|
+
this.#watcher = watch(this.#paths, {
|
|
762
|
+
cwd: this.#cwd,
|
|
763
|
+
ignoreInitial: true,
|
|
764
|
+
ignored: (p, stats) => shouldIgnoreWatchEntry(this.#cwd, p, stats?.isFile() ?? false)
|
|
765
|
+
});
|
|
766
|
+
attachWatcherErrorGuard(this.#watcher, (message) => this.#log(message, "yellow"));
|
|
767
|
+
this.#watcher.on("all", (_event, file) => {
|
|
768
|
+
if (!file.endsWith(".ts")) return;
|
|
769
|
+
this.#dirty.add(file);
|
|
770
|
+
this.#scheduleRestart(file);
|
|
771
|
+
});
|
|
772
|
+
}
|
|
773
|
+
/** Anti-rebond : regroupe plusieurs sauvegardes rapprochées en un restart. */
|
|
774
|
+
#scheduleRestart(file) {
|
|
775
|
+
this.#log(`↻ changement : ${path.relative(this.#cwd, path.resolve(this.#cwd, file))}`);
|
|
776
|
+
if (this.#timer) clearTimeout(this.#timer);
|
|
777
|
+
this.#timer = setTimeout(() => void this.#restart(), this.#debounceMs);
|
|
778
|
+
}
|
|
779
|
+
/** Rebuild (CIBLÉ sur les workspaces touchés) puis tue le groupe et relance. */
|
|
780
|
+
async #restart() {
|
|
781
|
+
if (this.#stopping) return;
|
|
782
|
+
if (this.#building) {
|
|
783
|
+
this.#pending = true;
|
|
784
|
+
return;
|
|
785
|
+
}
|
|
786
|
+
const suspension = readSupervisorSuspension(this.#cwd);
|
|
787
|
+
if (suspension) {
|
|
788
|
+
if (!this.#suspendedBy) {
|
|
789
|
+
this.#suspendedBy = suspension.reason;
|
|
790
|
+
this.#log(`⏸ ${suspension.reason} — rechargement différé`, "yellow");
|
|
791
|
+
}
|
|
792
|
+
if (this.#timer) clearTimeout(this.#timer);
|
|
793
|
+
this.#timer = setTimeout(() => void this.#restart(), SUSPENSION_RECHECK_MS);
|
|
794
|
+
return;
|
|
795
|
+
}
|
|
796
|
+
if (this.#suspendedBy) {
|
|
797
|
+
this.#log(`▶ ${this.#suspendedBy} — terminé, rechargement`, "green");
|
|
798
|
+
this.#suspendedBy = null;
|
|
799
|
+
}
|
|
800
|
+
const dirty = [...this.#dirty];
|
|
801
|
+
this.#dirty.clear();
|
|
802
|
+
this.#building = true;
|
|
803
|
+
const t0 = Date.now();
|
|
804
|
+
const ok = await this.#build(dirty);
|
|
805
|
+
this.#building = false;
|
|
806
|
+
if (!ok) {
|
|
807
|
+
this.#log("build en échec — serveur courant conservé, corrige puis sauvegarde", "red");
|
|
808
|
+
return;
|
|
809
|
+
}
|
|
810
|
+
this.#log(`✓ build OK (${Date.now() - t0}ms) — rechargement backend…`, "green");
|
|
811
|
+
await this.#killChild();
|
|
812
|
+
await this.#waitPortsFree();
|
|
813
|
+
this.#spawnRetries = 0;
|
|
814
|
+
this.#spawnChild();
|
|
815
|
+
if (this.#pending) {
|
|
816
|
+
this.#pending = false;
|
|
817
|
+
this.#scheduleRestart("(modifs en attente)");
|
|
818
|
+
}
|
|
819
|
+
}
|
|
820
|
+
/**
|
|
821
|
+
* Rebuild **ciblé** : ne reconstruit que les workspaces touchés (+ leurs
|
|
822
|
+
* dépendants via `turbo --filter=pkg...`) et l'app racine (`rolldown -c`) si un
|
|
823
|
+
* fichier racine a changé. Évite de rebuilder les 17 workspaces pour un seul
|
|
824
|
+
* fichier (le `npm run build` complet coûtait > 80 s).
|
|
825
|
+
*/
|
|
826
|
+
async #build(dirty) {
|
|
827
|
+
if (this.#standalone) {
|
|
828
|
+
this.#log("rebuild app (rolldown -c)…", "yellow");
|
|
829
|
+
return this.#run("npx", [
|
|
830
|
+
"rolldown",
|
|
831
|
+
"-c",
|
|
832
|
+
"rolldown.config.ts"
|
|
833
|
+
]);
|
|
834
|
+
}
|
|
835
|
+
const pkgs = /* @__PURE__ */ new Set();
|
|
836
|
+
let rootTouched = false;
|
|
837
|
+
for (const f of dirty) {
|
|
838
|
+
const name = this.#resolvePackage(f);
|
|
839
|
+
if (name === null) rootTouched = true;
|
|
840
|
+
else pkgs.add(name);
|
|
841
|
+
}
|
|
842
|
+
if (pkgs.size > 0) {
|
|
843
|
+
const filters = [...pkgs].flatMap((p) => ["--filter", `${p}...`]);
|
|
844
|
+
this.#log(`⚙ rebuild ${[...pkgs].join(", ")}…`, "yellow");
|
|
845
|
+
if (!await this.#run("npx", [
|
|
846
|
+
"turbo",
|
|
847
|
+
"run",
|
|
848
|
+
"build",
|
|
849
|
+
...filters
|
|
850
|
+
])) return false;
|
|
851
|
+
}
|
|
852
|
+
if (rootTouched || pkgs.size === 0) {
|
|
853
|
+
this.#log("rebuild app racine (rolldown -c)…", "yellow");
|
|
854
|
+
if (!await this.#run("npx", [
|
|
855
|
+
"rolldown",
|
|
856
|
+
"-c",
|
|
857
|
+
"rolldown.config.ts"
|
|
858
|
+
])) return false;
|
|
859
|
+
}
|
|
860
|
+
return true;
|
|
861
|
+
}
|
|
862
|
+
/** Spawn une commande de build, résout `true` si code de sortie 0. */
|
|
863
|
+
#run(cmd, args) {
|
|
864
|
+
return new Promise((resolve) => {
|
|
865
|
+
const p = spawn(cmd, args, {
|
|
866
|
+
cwd: this.#cwd,
|
|
867
|
+
stdio: "inherit",
|
|
868
|
+
shell: process.platform === "win32"
|
|
869
|
+
});
|
|
870
|
+
p.once("exit", (code) => resolve(code === 0));
|
|
871
|
+
p.once("error", () => resolve(false));
|
|
872
|
+
});
|
|
873
|
+
}
|
|
874
|
+
/**
|
|
875
|
+
* Remonte de `file` jusqu'au `package.json` le plus proche et renvoie son
|
|
876
|
+
* `name` (workspace turbo), ou `null` si c'est le `package.json` racine
|
|
877
|
+
* (= app, buildée par `rolldown -c`). Résultat caché par dossier.
|
|
878
|
+
*/
|
|
879
|
+
#resolvePackage(file) {
|
|
880
|
+
const root = path.resolve(this.#cwd);
|
|
881
|
+
let dir = path.dirname(path.resolve(this.#cwd, file));
|
|
882
|
+
for (;;) {
|
|
883
|
+
const cached = this.#pkgCache.get(dir);
|
|
884
|
+
if (cached !== void 0) return cached;
|
|
885
|
+
const pj = path.join(dir, "package.json");
|
|
886
|
+
if (existsSync(pj)) {
|
|
887
|
+
let name = null;
|
|
888
|
+
if (dir !== root) try {
|
|
889
|
+
name = JSON.parse(readFileSync(pj, "utf8")).name ?? null;
|
|
890
|
+
} catch {
|
|
891
|
+
name = null;
|
|
892
|
+
}
|
|
893
|
+
this.#pkgCache.set(dir, name);
|
|
894
|
+
return name;
|
|
895
|
+
}
|
|
896
|
+
if (dir === root) return null;
|
|
897
|
+
const parent = path.dirname(dir);
|
|
898
|
+
if (parent === dir) return null;
|
|
899
|
+
dir = parent;
|
|
900
|
+
}
|
|
901
|
+
}
|
|
902
|
+
/**
|
|
903
|
+
* Envoie un signal à l'**arbre** de l'enfant — Vite et tout descendant compris —
|
|
904
|
+
* via l'unique implémentation du dépôt ({@link signalProcessGroup}).
|
|
905
|
+
*
|
|
906
|
+
* Ce point était le plus coûteux du chantier Windows : il retombait sur
|
|
907
|
+
* `child.kill()`, qui n'atteint que l'enfant DIRECT. Chaque rechargement laissait
|
|
908
|
+
* donc un Vite orphelin, et le mode dev en enchaîne un par sauvegarde.
|
|
909
|
+
*
|
|
910
|
+
* Quand même l'arbre est hors de portée, on le DIT (une fois) plutôt que de laisser
|
|
911
|
+
* l'utilisateur découvrir sa machine saturée.
|
|
912
|
+
*/
|
|
913
|
+
#signalGroup(c, signal) {
|
|
914
|
+
if (typeof c.pid !== "number") {
|
|
915
|
+
try {
|
|
916
|
+
c.kill(signal);
|
|
917
|
+
} catch {}
|
|
918
|
+
return;
|
|
919
|
+
}
|
|
920
|
+
if (signalProcessGroup(c.pid, signal) === "single" && !this.#orphanRiskWarned) {
|
|
921
|
+
this.#orphanRiskWarned = true;
|
|
922
|
+
this.#log("arrêt limité au process serveur (arbre hors de portée) — des instances Vite peuvent survivre à ce rechargement ; `nodefony stop` les balaie", "yellow");
|
|
923
|
+
}
|
|
924
|
+
}
|
|
925
|
+
/** Tue le groupe de l'enfant (SIGTERM, puis SIGKILL après 4 s) et attend l'exit. */
|
|
926
|
+
#killChild() {
|
|
927
|
+
return new Promise((resolve) => {
|
|
928
|
+
const c = this.#child;
|
|
929
|
+
this.#child = null;
|
|
930
|
+
if (!c || c.exitCode !== null || c.signalCode !== null) return resolve();
|
|
931
|
+
const kill9 = setTimeout(() => this.#signalGroup(c, "SIGKILL"), 4e3);
|
|
932
|
+
c.once("exit", () => {
|
|
933
|
+
clearTimeout(kill9);
|
|
934
|
+
resolve();
|
|
935
|
+
});
|
|
936
|
+
this.#signalGroup(c, "SIGTERM");
|
|
937
|
+
});
|
|
938
|
+
}
|
|
939
|
+
/** `true` si rien n'écoute sur `port` en loopback (connexion refusée). */
|
|
940
|
+
#isPortFree(port) {
|
|
941
|
+
return new Promise((resolve) => {
|
|
942
|
+
const socket = net.connect({
|
|
943
|
+
host: "127.0.0.1",
|
|
944
|
+
port
|
|
945
|
+
});
|
|
946
|
+
const settle = (free) => {
|
|
947
|
+
socket.removeAllListeners();
|
|
948
|
+
socket.destroy();
|
|
949
|
+
resolve(free);
|
|
950
|
+
};
|
|
951
|
+
socket.once("connect", () => settle(false));
|
|
952
|
+
socket.once("error", () => settle(true));
|
|
953
|
+
socket.setTimeout(400, () => settle(true));
|
|
954
|
+
});
|
|
955
|
+
}
|
|
956
|
+
/** Attend que tous les ports surveillés soient libres (ou expire). */
|
|
957
|
+
async #waitPortsFree(timeoutMs = PORTS_FREE_TIMEOUT_MS) {
|
|
958
|
+
const mine = this.#ports.filter((p) => !this.#foreignHeldPorts.has(p));
|
|
959
|
+
if (mine.length === 0) return;
|
|
960
|
+
const deadline = Date.now() + timeoutMs;
|
|
961
|
+
for (;;) {
|
|
962
|
+
const states = await Promise.all(mine.map((p) => this.#isPortFree(p)));
|
|
963
|
+
if (states.every(Boolean)) return;
|
|
964
|
+
if (Date.now() >= deadline) {
|
|
965
|
+
const busy = mine.filter((_, i) => !states[i]);
|
|
966
|
+
this.#log(`ports encore occupés après ${timeoutMs}ms : ${busy.join(", ")} — relance quand même`, "yellow");
|
|
967
|
+
return;
|
|
968
|
+
}
|
|
969
|
+
await delay(120);
|
|
970
|
+
}
|
|
971
|
+
}
|
|
972
|
+
/** Arrête le superviseur : ferme le watcher, tue le groupe, libère le verrou. */
|
|
973
|
+
async #shutdown() {
|
|
974
|
+
if (this.#stopping) return;
|
|
975
|
+
this.#stopping = true;
|
|
976
|
+
if (this.#timer) clearTimeout(this.#timer);
|
|
977
|
+
await this.#watcher?.close();
|
|
978
|
+
await this.#killChild();
|
|
979
|
+
this.#releaseLock();
|
|
980
|
+
process.exit(0);
|
|
981
|
+
}
|
|
982
|
+
/** Supprime le pidfile s'il nous appartient encore (idempotent, best-effort). */
|
|
983
|
+
#releaseLock() {
|
|
984
|
+
try {
|
|
985
|
+
if (existsSync(this.#pidFile) && readFileSync(this.#pidFile, "utf8").trim() === String(process.pid)) rmSync(this.#pidFile, { force: true });
|
|
986
|
+
} catch {}
|
|
987
|
+
}
|
|
988
|
+
/**
|
|
989
|
+
* Branche les signaux d'arrêt → arrêt propre.
|
|
990
|
+
*
|
|
991
|
+
* `SIGHUP` est **essentiel** : c'est le signal reçu quand le terminal se ferme.
|
|
992
|
+
* Sans lui, un superviseur lancé `detached` survivait indéfiniment (orphelin
|
|
993
|
+
* PPID 1 qui rebuild en boucle). Le handler `exit` libère le verrou en dernier
|
|
994
|
+
* recours (kill non interceptable, ou sortie inattendue).
|
|
995
|
+
*/
|
|
996
|
+
#installSignals() {
|
|
997
|
+
process.once("SIGINT", () => void this.#shutdown());
|
|
998
|
+
process.once("SIGTERM", () => void this.#shutdown());
|
|
999
|
+
process.once("SIGHUP", () => void this.#shutdown());
|
|
1000
|
+
process.once("exit", () => this.#releaseLock());
|
|
1001
|
+
}
|
|
1002
|
+
};
|
|
1003
|
+
//#endregion
|
|
1004
|
+
export { DevSupervisor, DevSupervisor as default, attachWatcherErrorGuard, isIgnoredWatchPath, shouldIgnoreWatchEntry };
|