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,1137 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, readdirSync, readlinkSync, rmSync, writeFileSync } from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { spawnSync } from "node:child_process";
|
|
4
|
+
import net from "node:net";
|
|
5
|
+
//#region src/service/dev/devProcess.ts
|
|
6
|
+
/**
|
|
7
|
+
* Helpers d'INTROSPECTION des process de développement Nodefony — source de vérité
|
|
8
|
+
* PARTAGÉE entre le superviseur (`DevSupervisor`, écrivain du pidfile) et les
|
|
9
|
+
* commandes de diagnostic (`nodefony status`, `nodefony stop`, lecteurs).
|
|
10
|
+
*
|
|
11
|
+
* 100 % OBSERVATION EXTERNE : pidfile + `ps` + sonde TCP, AUCUN IPC superviseur↔enfant
|
|
12
|
+
* (choix d'architecture). Toute valeur dont la divergence écrivain/lecteur serait un
|
|
13
|
+
* bug (chemin du pidfile, ports surveillés) vit ICI et n'est dupliquée nulle part.
|
|
14
|
+
*/
|
|
15
|
+
/** Titre de process du superviseur de dev (posé par {@link DevSupervisor.start}). */
|
|
16
|
+
const DEV_SUPERVISOR_TITLE = "nodefony-dev-supervisor";
|
|
17
|
+
/** Titre de process du serveur enfant supervisé (posé par `DevCommand` à `onReady`). */
|
|
18
|
+
const DEV_SERVER_TITLE = "nodefony-dev-server";
|
|
19
|
+
/** Préfixe de titre des process Vite (`ViteProcessSupervisor`, via `argv0`). */
|
|
20
|
+
const DEV_VITE_PREFIX = "nodefony-vite";
|
|
21
|
+
/**
|
|
22
|
+
* Titre du serveur prod **mono-process** (`production` ou `cluster` avec `workers:1`,
|
|
23
|
+
* posé par `Prod`/`ClusterCommand.generate`). Espace (≠ tiret de `nodefony-dev-server`)
|
|
24
|
+
* → aucune collision de `String.includes` entre les deux.
|
|
25
|
+
*/
|
|
26
|
+
const PROD_SERVER_TITLE = "nodefony server";
|
|
27
|
+
/** Préfixe du titre du master cluster (posé par `startClusterMaster`, ex. `nodefony master [cluster 6w]`). */
|
|
28
|
+
const CLUSTER_MASTER_PREFIX = "nodefony master";
|
|
29
|
+
/** Préfixe du titre d'un worker cluster (posé par `Prod`/`ClusterCommand.generate`, ex. `nodefony worker 3 [cluster]`). */
|
|
30
|
+
const CLUSTER_WORKER_PREFIX = "nodefony worker";
|
|
31
|
+
/** Rôles « principaux » (tiennent les ports ou supervisent) — Vite exclu (enfant jetable). */
|
|
32
|
+
const PRIMARY_ROLES = /* @__PURE__ */ new Set([
|
|
33
|
+
"supervisor",
|
|
34
|
+
"server",
|
|
35
|
+
"master",
|
|
36
|
+
"worker"
|
|
37
|
+
]);
|
|
38
|
+
/**
|
|
39
|
+
* Chemin du pidfile single-instance du superviseur dev — **source UNIQUE** lue par
|
|
40
|
+
* `status`/`stop` et écrite par le superviseur (divergence = bug : le lecteur ne
|
|
41
|
+
* verrait jamais l'instance). Sous `node_modules/.cache` (déjà gitignoré).
|
|
42
|
+
*/
|
|
43
|
+
function devSupervisorPidFile(cwd) {
|
|
44
|
+
return path.join(cwd, "node_modules", ".cache", "nodefony", "dev-supervisor.pid");
|
|
45
|
+
}
|
|
46
|
+
/** Ports Nodefony historiques — le point de départ, pas une vérité. */
|
|
47
|
+
const FALLBACK_DEV_PORTS = [5151, 5152];
|
|
48
|
+
/**
|
|
49
|
+
* Chemin du **state file runtime** — le canal par lequel le serveur DIT sur quels
|
|
50
|
+
* ports il écoute VRAIMENT.
|
|
51
|
+
*
|
|
52
|
+
* Il existe parce que le port n'est plus une convention : avec
|
|
53
|
+
* `servers.portPolicy: "auto"`, un port occupé fait glisser l'écoute (5151 → 5153).
|
|
54
|
+
* `status`, `stop` et la readiness `--detach` sondaient `[5151, 5152]` **en dur** —
|
|
55
|
+
* ils deviendraient aveugles à la première app décalée. Le serveur écrit donc ses
|
|
56
|
+
* ports effectifs ici, et les lecteurs les prennent à la source.
|
|
57
|
+
*
|
|
58
|
+
* À côté du pidfile, même dossier déjà gitignoré.
|
|
59
|
+
*/
|
|
60
|
+
function runtimeStateFile(cwd) {
|
|
61
|
+
return path.join(cwd, "node_modules", ".cache", "nodefony", "runtime.json");
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Chemin du **canal de disponibilité** — par lequel le serveur DIT *qui* retient
|
|
65
|
+
* sa mise en service, et pourquoi.
|
|
66
|
+
*
|
|
67
|
+
* ## Pourquoi un fichier, et pas la sonde HTTP
|
|
68
|
+
*
|
|
69
|
+
* Le serveur publie déjà ce détail sur `/nodefony/kernel/api/livez`, mais
|
|
70
|
+
* **réservé à un appelant authentifié** : les noms décrivent l'architecture
|
|
71
|
+
* interne, et cette route est publique en production. La gradation est
|
|
72
|
+
* délibérée — l'anonyme reçoit un compte, jamais des noms — et l'ouvrir pour le
|
|
73
|
+
* confort d'un outil local serait payer en surface publique un service rendu sur
|
|
74
|
+
* une seule machine.
|
|
75
|
+
*
|
|
76
|
+
* Le système de fichiers **est** la frontière « local », et une bien meilleure
|
|
77
|
+
* que l'adresse d'appel : un conteneur voisin ou un mandataire présentent la
|
|
78
|
+
* boucle locale sans être l'exploitant. Ici, lire le fichier suppose déjà un
|
|
79
|
+
* accès au dossier du projet.
|
|
80
|
+
*
|
|
81
|
+
* Et il répond quand la sonde ne répond plus — pipeline saturé, boucle
|
|
82
|
+
* d'événements bloquée. C'est précisément le moment où l'on tape `status`.
|
|
83
|
+
*
|
|
84
|
+
* À côté du pidfile et du state file runtime, même dossier déjà gitignoré.
|
|
85
|
+
*/
|
|
86
|
+
function readinessStateFile(cwd) {
|
|
87
|
+
return path.join(cwd, "node_modules", ".cache", "nodefony", "readiness.json");
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Publie qui retient la mise en service — **best-effort, jamais bloquant**.
|
|
91
|
+
*
|
|
92
|
+
* Écrit seulement quand l'état a changé (l'appelant en décide) : en régime
|
|
93
|
+
* établi, ce fichier ne coûte rien. Un système de fichiers en lecture seule, un
|
|
94
|
+
* dossier absent, un disque plein : on n'écrit pas, et le diagnostic retombe sur
|
|
95
|
+
* le compte que la sonde donne déjà. Publier son état ne doit jamais mettre en
|
|
96
|
+
* péril le processus qui sert.
|
|
97
|
+
*
|
|
98
|
+
* @param cwd - racine du projet.
|
|
99
|
+
* @param contributors - l'état de chaque contributeur, tel que le registre le rend.
|
|
100
|
+
*/
|
|
101
|
+
function writeReadinessState(cwd, contributors) {
|
|
102
|
+
try {
|
|
103
|
+
const file = readinessStateFile(cwd);
|
|
104
|
+
mkdirSync(path.dirname(file), { recursive: true });
|
|
105
|
+
writeFileSync(file, JSON.stringify({
|
|
106
|
+
pid: process.pid,
|
|
107
|
+
contributors,
|
|
108
|
+
ts: Date.now()
|
|
109
|
+
}), "utf8");
|
|
110
|
+
} catch {}
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Efface le canal de disponibilité — geste d'un processus qui s'arrête.
|
|
114
|
+
*
|
|
115
|
+
* @param cwd - racine du projet.
|
|
116
|
+
*/
|
|
117
|
+
function clearReadinessState(cwd) {
|
|
118
|
+
try {
|
|
119
|
+
rmSync(readinessStateFile(cwd), { force: true });
|
|
120
|
+
} catch {}
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Lit qui retient la mise en service, ou `null`.
|
|
124
|
+
*
|
|
125
|
+
* **Un fichier dont le process est MORT est ignoré** : sinon `status` nommerait
|
|
126
|
+
* le contributeur d'un serveur d'hier, ce qui est pire que de ne rien nommer —
|
|
127
|
+
* on chercherait une cause déjà disparue.
|
|
128
|
+
*
|
|
129
|
+
* @param cwd - racine du projet à interroger.
|
|
130
|
+
* @returns les contributeurs publiés, ou `null` si rien d'exploitable.
|
|
131
|
+
*/
|
|
132
|
+
function readReadinessState(cwd) {
|
|
133
|
+
try {
|
|
134
|
+
const raw = JSON.parse(readFileSync(readinessStateFile(cwd), "utf8"));
|
|
135
|
+
if (!Array.isArray(raw.contributors)) return null;
|
|
136
|
+
const pid = typeof raw.pid === "number" ? raw.pid : 0;
|
|
137
|
+
if (pid > 0 && !isPidAlive(pid)) return null;
|
|
138
|
+
const out = [];
|
|
139
|
+
for (const c of raw.contributors) {
|
|
140
|
+
if (typeof c?.name !== "string" || typeof c?.ready !== "boolean") continue;
|
|
141
|
+
out.push(typeof c.reason === "string" ? {
|
|
142
|
+
name: c.name,
|
|
143
|
+
ready: c.ready,
|
|
144
|
+
reason: c.reason
|
|
145
|
+
} : {
|
|
146
|
+
name: c.name,
|
|
147
|
+
ready: c.ready
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
return out;
|
|
151
|
+
} catch {
|
|
152
|
+
return null;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Publie les ports EFFECTIFS du runtime. Best-effort : un échec d'écriture ne doit
|
|
157
|
+
* jamais faire tomber un serveur qui, lui, écoute très bien (les lecteurs
|
|
158
|
+
* retomberont sur les ports par défaut).
|
|
159
|
+
*/
|
|
160
|
+
function writeRuntimeState(cwd, state) {
|
|
161
|
+
try {
|
|
162
|
+
const file = runtimeStateFile(cwd);
|
|
163
|
+
mkdirSync(path.dirname(file), { recursive: true });
|
|
164
|
+
writeFileSync(file, JSON.stringify({
|
|
165
|
+
...state,
|
|
166
|
+
ts: Date.now()
|
|
167
|
+
}), "utf8");
|
|
168
|
+
} catch {}
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Lit les ports publiés par le runtime, ou `null`.
|
|
172
|
+
*
|
|
173
|
+
* **Un state file dont le process est MORT est ignoré** (et purgé) : sinon un
|
|
174
|
+
* `status` lirait les ports d'un serveur d'hier et sonderait dans le vide.
|
|
175
|
+
*
|
|
176
|
+
* @param cwd - racine du projet à interroger.
|
|
177
|
+
* @param opts.purgeStale - retirer le fichier d'un process mort (défaut `true`).
|
|
178
|
+
* À passer `false` pour lire l'état d'un projet ÉTRANGER : on interroge son canal
|
|
179
|
+
* pour savoir à qui appartient un port, on ne fait pas son ménage. Purger le décor
|
|
180
|
+
* d'un autre projet depuis une commande scopée à celui-ci serait un effet de bord
|
|
181
|
+
* hors périmètre — et le voisin perdrait la trace de ses propres ports.
|
|
182
|
+
*/
|
|
183
|
+
/**
|
|
184
|
+
* Ports lus d'un FICHIER, ramenés à ce qu'un port peut être.
|
|
185
|
+
*
|
|
186
|
+
* Le fichier d'état est écrit par un process du projet, pas par un tiers — mais
|
|
187
|
+
* il reste une entrée sur disque qui alimente ensuite une sonde réseau (l'hôte,
|
|
188
|
+
* lui, est écrit en dur en boucle locale). Une valeur hors bornes n'ouvre donc
|
|
189
|
+
* aucune porte vers l'extérieur ; elle enverrait la sonde frapper un service
|
|
190
|
+
* local au hasard, et un fichier tronqué suffit à la produire.
|
|
191
|
+
*
|
|
192
|
+
* @param value - la valeur brute lue dans le fichier, de forme inconnue.
|
|
193
|
+
* @returns les entiers retenus dans `1..65535` ; tableau vide si rien n'est valide.
|
|
194
|
+
*/
|
|
195
|
+
function sanitizePorts(value) {
|
|
196
|
+
if (!Array.isArray(value)) return [];
|
|
197
|
+
return value.filter((n) => Number.isInteger(n) && n > 0 && n <= 65535);
|
|
198
|
+
}
|
|
199
|
+
function readRuntimeState(cwd, opts = {}) {
|
|
200
|
+
try {
|
|
201
|
+
const file = runtimeStateFile(cwd);
|
|
202
|
+
const raw = JSON.parse(readFileSync(file, "utf8"));
|
|
203
|
+
const pid = typeof raw.pid === "number" ? raw.pid : 0;
|
|
204
|
+
const ports = sanitizePorts(raw.ports);
|
|
205
|
+
if (ports.length === 0) return null;
|
|
206
|
+
if (pid > 0 && !isPidAlive(pid)) {
|
|
207
|
+
if (opts.purgeStale !== false) clearRuntimeState(cwd);
|
|
208
|
+
return null;
|
|
209
|
+
}
|
|
210
|
+
return {
|
|
211
|
+
pid,
|
|
212
|
+
ports,
|
|
213
|
+
desiredPorts: Array.isArray(raw.desiredPorts) ? sanitizePorts(raw.desiredPorts) : void 0,
|
|
214
|
+
ts: typeof raw.ts === "number" ? raw.ts : 0
|
|
215
|
+
};
|
|
216
|
+
} catch {
|
|
217
|
+
return null;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
/** Retire le state file (arrêt propre, ou reliquat d'un process mort). */
|
|
221
|
+
/**
|
|
222
|
+
* Retrouve le runtime de CE projet par son fichier d'état, sans observer les process.
|
|
223
|
+
*
|
|
224
|
+
* Repli employé là où l'observation externe n'existe pas ({@link isProcessDiscoverySupported}).
|
|
225
|
+
* Le fichier vit sous le `cwd` du projet et porte le PID de qui écoute : l'appartenance au
|
|
226
|
+
* projet est donc acquise par construction, là où `ps` exigeait de lire le répertoire
|
|
227
|
+
* courant d'un process tiers. {@link readRuntimeState} a déjà vérifié que le PID est
|
|
228
|
+
* vivant et purgé le fichier sinon — un reliquat ne peut pas faire tuer un PID recyclé.
|
|
229
|
+
*
|
|
230
|
+
* Rend la TOPOLOGIE, pas un process isolé : le superviseur (pidfile) EN TÊTE, puis le
|
|
231
|
+
* serveur qui écoute (fichier d'état). L'ordre porte une conséquence — un superviseur
|
|
232
|
+
* relance son enfant dès qu'il le voit mourir, donc arrêter le serveur seul ne fait que
|
|
233
|
+
* provoquer un rechargement. Les instances Vite, elles, restent hors de portée : rien ne
|
|
234
|
+
* les publie, et elles meurent avec le superviseur qui les a lancées.
|
|
235
|
+
*
|
|
236
|
+
* Ce que le repli NE donne pas, faute de les observer : mémoire résidente, part CPU,
|
|
237
|
+
* durée de vie du superviseur. Ces colonnes valent zéro et le rapport le dit.
|
|
238
|
+
*
|
|
239
|
+
* @param cwd - racine du projet.
|
|
240
|
+
* @returns les process du projet, du superviseur au serveur ; vide si rien d'exploitable.
|
|
241
|
+
*/
|
|
242
|
+
function discoverFromRuntimeState(cwd) {
|
|
243
|
+
const supervisor = readSupervisorPid(cwd);
|
|
244
|
+
const supervisorAlive = supervisor !== null && isPidAlive(supervisor);
|
|
245
|
+
const state = readRuntimeState(cwd);
|
|
246
|
+
const found = [];
|
|
247
|
+
if (supervisorAlive) found.push({
|
|
248
|
+
pid: supervisor,
|
|
249
|
+
ppid: 0,
|
|
250
|
+
mode: "dev",
|
|
251
|
+
role: "supervisor",
|
|
252
|
+
label: "supervisor",
|
|
253
|
+
rssKb: 0,
|
|
254
|
+
cpu: 0,
|
|
255
|
+
uptimeSec: 0
|
|
256
|
+
});
|
|
257
|
+
if (state && state.pid > 0) found.push({
|
|
258
|
+
pid: state.pid,
|
|
259
|
+
ppid: supervisorAlive ? supervisor : 0,
|
|
260
|
+
mode: supervisorAlive ? "dev" : "prod",
|
|
261
|
+
role: "server",
|
|
262
|
+
label: "server",
|
|
263
|
+
rssKb: 0,
|
|
264
|
+
cpu: 0,
|
|
265
|
+
uptimeSec: Math.max(0, Math.round((Date.now() - state.ts) / 1e3))
|
|
266
|
+
});
|
|
267
|
+
return found;
|
|
268
|
+
}
|
|
269
|
+
function clearRuntimeState(cwd) {
|
|
270
|
+
try {
|
|
271
|
+
rmSync(runtimeStateFile(cwd), { force: true });
|
|
272
|
+
} catch {}
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Chemin du **verrou de suspension du superviseur dev** — le canal par lequel le serveur
|
|
276
|
+
* dit à son parent : « je suis en train d'écrire dans les sources, ne me redémarre pas
|
|
277
|
+
* maintenant ».
|
|
278
|
+
*
|
|
279
|
+
* Il existe parce que le watcher regarde `nodefony/`, `index.ts`, `src/` — et que
|
|
280
|
+
* certaines opérations du serveur écrivent PRÉCISÉMENT là : générer un module depuis
|
|
281
|
+
* Studio, appliquer une migration, installer un module tiers. Sans verrou, le
|
|
282
|
+
* rechargement part au milieu de l'opération et tue le `npm install` en cours (le process
|
|
283
|
+
* npm est un enfant du serveur), laissant un `node_modules` à moitié écrit.
|
|
284
|
+
*
|
|
285
|
+
* Un fichier, et pas un IPC, parce que parent et enfant n'en ont pas (`stdio: [ignore,
|
|
286
|
+
* pipe, pipe]`) — et parce que c'est déjà le patron du pidfile et du state file, au même
|
|
287
|
+
* endroit, déjà gitignoré.
|
|
288
|
+
*/
|
|
289
|
+
function supervisorLockFile(cwd) {
|
|
290
|
+
return path.join(cwd, "node_modules", ".cache", "nodefony", "supervisor.lock");
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* Au-delà de cette durée, un verrou est tenu pour périmé quoi qu'il arrive.
|
|
294
|
+
*
|
|
295
|
+
* Deuxième filet après la vérification du PID : une opération très longue (`npm install`)
|
|
296
|
+
* reste couverte, mais aucun verrou ne peut museler le watcher indéfiniment.
|
|
297
|
+
*/
|
|
298
|
+
const SUPERVISOR_LOCK_TTL_MS = 9e5;
|
|
299
|
+
/**
|
|
300
|
+
* Suspend le rechargement automatique le temps d'une opération qui écrit dans les
|
|
301
|
+
* sources.
|
|
302
|
+
*
|
|
303
|
+
* À utiliser par TOUTE opération serveur qui touche aux fichiers surveillés — génération
|
|
304
|
+
* de code, migration, installation d'un module. Best-effort : un échec d'écriture ne doit
|
|
305
|
+
* jamais faire échouer l'opération elle-même (au pire, le superviseur redémarre).
|
|
306
|
+
*
|
|
307
|
+
* @param cwd - racine du projet.
|
|
308
|
+
* @param reason - raison affichée à l'utilisateur (« génération de code »…).
|
|
309
|
+
* @param detail - précision optionnelle (id de job…).
|
|
310
|
+
*/
|
|
311
|
+
function suspendSupervisor(cwd, reason, detail) {
|
|
312
|
+
try {
|
|
313
|
+
const file = supervisorLockFile(cwd);
|
|
314
|
+
mkdirSync(path.dirname(file), { recursive: true });
|
|
315
|
+
const lock = {
|
|
316
|
+
pid: process.pid,
|
|
317
|
+
reason,
|
|
318
|
+
detail,
|
|
319
|
+
ts: Date.now()
|
|
320
|
+
};
|
|
321
|
+
writeFileSync(file, JSON.stringify(lock), "utf8");
|
|
322
|
+
} catch {}
|
|
323
|
+
}
|
|
324
|
+
/** Rend la main au superviseur (fin de l'opération, quelle qu'en soit l'issue). */
|
|
325
|
+
function resumeSupervisor(cwd) {
|
|
326
|
+
try {
|
|
327
|
+
rmSync(supervisorLockFile(cwd), { force: true });
|
|
328
|
+
} catch {}
|
|
329
|
+
}
|
|
330
|
+
/**
|
|
331
|
+
* Le rechargement est-il suspendu, et pourquoi ?
|
|
332
|
+
*
|
|
333
|
+
* **Fail-safe par construction** : dans le doute, on répond `null` (le watcher fait son
|
|
334
|
+
* travail). Un verrou muselle le rechargement automatique — le laisser traîner serait
|
|
335
|
+
* pire que le mal : on éditerait ses fichiers sans que plus rien ne se recharge, sans la
|
|
336
|
+
* moindre explication. Un verrou n'est donc retenu que s'il est VIVANT :
|
|
337
|
+
*
|
|
338
|
+
* - son process existe encore (`kill(pid, 0)`) — un serveur tué en pleine opération
|
|
339
|
+
* laisse son fichier derrière lui ; on ne le croit pas sur parole ;
|
|
340
|
+
* - il a moins de {@link SUPERVISOR_LOCK_TTL_MS} — filet si un PID est recyclé par l'OS.
|
|
341
|
+
*
|
|
342
|
+
* Un verrou mort est SUPPRIMÉ au passage, pour ne pas se reposer la question.
|
|
343
|
+
*
|
|
344
|
+
* @param cwd - racine du projet.
|
|
345
|
+
* @returns le verrou vivant (avec sa raison, à afficher), ou `null`.
|
|
346
|
+
*/
|
|
347
|
+
function readSupervisorSuspension(cwd) {
|
|
348
|
+
let raw;
|
|
349
|
+
try {
|
|
350
|
+
raw = readFileSync(supervisorLockFile(cwd), "utf8");
|
|
351
|
+
} catch {
|
|
352
|
+
return null;
|
|
353
|
+
}
|
|
354
|
+
let lock;
|
|
355
|
+
try {
|
|
356
|
+
lock = JSON.parse(raw);
|
|
357
|
+
} catch {
|
|
358
|
+
resumeSupervisor(cwd);
|
|
359
|
+
return null;
|
|
360
|
+
}
|
|
361
|
+
if (!lock?.pid || Date.now() - (lock.ts ?? 0) > SUPERVISOR_LOCK_TTL_MS) {
|
|
362
|
+
resumeSupervisor(cwd);
|
|
363
|
+
return null;
|
|
364
|
+
}
|
|
365
|
+
try {
|
|
366
|
+
process.kill(lock.pid, 0);
|
|
367
|
+
} catch {
|
|
368
|
+
resumeSupervisor(cwd);
|
|
369
|
+
return null;
|
|
370
|
+
}
|
|
371
|
+
return lock;
|
|
372
|
+
}
|
|
373
|
+
/**
|
|
374
|
+
* Ports serveur à SONDER (`status`, `stop`, readiness, attente de libération).
|
|
375
|
+
*
|
|
376
|
+
* Ordre de vérité, du plus fiable au moins fiable :
|
|
377
|
+
* 1. `NF_DEV_PORTS` — override explicite de l'opérateur, il gagne toujours ;
|
|
378
|
+
* 2. le **state file runtime** — ce que le serveur écoute VRAIMENT (seule source
|
|
379
|
+
* exacte quand `portPolicy: "auto"` a décalé l'écoute) ;
|
|
380
|
+
* 3. `NF_PORT` / `NF_PORT_HTTPS` — ce que l'application DÉCLARE. L'alias
|
|
381
|
+
* plateforme `PORT` (Cloud Run, Heroku) n'est PAS lu ici : il appartient au
|
|
382
|
+
* gabarit d'application, qui choisit de l'accepter, pas au framework — le
|
|
383
|
+
* lire depuis le cœur ferait précisément la collision que le préfixe `NF_`
|
|
384
|
+
* existe pour empêcher (un `PORT` posé pour un autre outil détournerait la
|
|
385
|
+
* sonde). Sans cette marche, une application qui tourne ailleurs que sur la
|
|
386
|
+
* convention était jugée sur les ports d'un projet VOISIN : `check` rendait
|
|
387
|
+
* « port déjà tenu » sur du code parfait dès qu'un autre serveur tournait
|
|
388
|
+
* sur le poste, et le verdict devenait dépendant de la machine ;
|
|
389
|
+
* 4. `[5151, 5152]` — la convention historique, quand rien n'est déclaré ni ne
|
|
390
|
+
* tourne (cas du tout premier boot : personne n'a pu publier quoi que ce soit).
|
|
391
|
+
*
|
|
392
|
+
* @param cwd - racine du projet (le state file est par projet).
|
|
393
|
+
*/
|
|
394
|
+
function defaultDevPorts(cwd = process.cwd()) {
|
|
395
|
+
const env = process.env.NF_DEV_PORTS;
|
|
396
|
+
if (env) {
|
|
397
|
+
const parsed = env.split(",").map((s) => Number.parseInt(s.trim(), 10)).filter((n) => Number.isInteger(n) && n > 0);
|
|
398
|
+
if (parsed.length > 0) return parsed;
|
|
399
|
+
}
|
|
400
|
+
const state = readRuntimeState(cwd);
|
|
401
|
+
if (state && state.ports.length > 0) return [...state.ports];
|
|
402
|
+
const declares = [process.env.NF_PORT, process.env.NF_PORT_HTTPS].map((v) => Number.parseInt(String(v ?? ""), 10)).filter((n) => Number.isInteger(n) && n > 0);
|
|
403
|
+
if (declares.length > 0) return declares;
|
|
404
|
+
return [...FALLBACK_DEV_PORTS];
|
|
405
|
+
}
|
|
406
|
+
/** Lit le PID du superviseur depuis le pidfile, ou `null` si absent / illisible. */
|
|
407
|
+
function readSupervisorPid(cwd) {
|
|
408
|
+
const file = devSupervisorPidFile(cwd);
|
|
409
|
+
try {
|
|
410
|
+
if (!existsSync(file)) return null;
|
|
411
|
+
const pid = Number.parseInt(readFileSync(file, "utf8").trim(), 10);
|
|
412
|
+
return Number.isInteger(pid) && pid > 0 ? pid : null;
|
|
413
|
+
} catch {
|
|
414
|
+
return null;
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
/** `true` si le process `pid` est vivant (signal 0 — ne le tue pas). */
|
|
418
|
+
function isPidAlive(pid) {
|
|
419
|
+
try {
|
|
420
|
+
process.kill(pid, 0);
|
|
421
|
+
return true;
|
|
422
|
+
} catch {
|
|
423
|
+
return false;
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
/**
|
|
427
|
+
* Nom d'image d'une ligne `tasklist /NH /FO CSV` — fonction PURE.
|
|
428
|
+
*
|
|
429
|
+
* `tasklist` sort `"node.exe","4212","Console","1","52 480 K"`, mais aussi, quand le
|
|
430
|
+
* PID n'existe plus, une phrase en clair (`INFO: No tasks are running…`) avec un code
|
|
431
|
+
* de sortie NUL. Ne rendre un nom que sur la forme CSV attendue est donc ce qui
|
|
432
|
+
* distingue « je l'ai vu » de « je n'ai rien vu ».
|
|
433
|
+
*
|
|
434
|
+
* @param out - sortie brute de `tasklist`.
|
|
435
|
+
* @returns le nom d'image, ou `null` si la sortie ne décrit aucun process.
|
|
436
|
+
*/
|
|
437
|
+
function parseTasklistImage(out) {
|
|
438
|
+
for (const raw of out.split("\n")) {
|
|
439
|
+
const line = raw.trim();
|
|
440
|
+
if (!line.startsWith("\"")) continue;
|
|
441
|
+
const m = /^"([^"]+)","(\d+)"/.exec(line);
|
|
442
|
+
if (m) return m[1];
|
|
443
|
+
}
|
|
444
|
+
return null;
|
|
445
|
+
}
|
|
446
|
+
/**
|
|
447
|
+
* Identifie un process vivant par OBSERVATION EXTERNE, sur toutes les plateformes.
|
|
448
|
+
*
|
|
449
|
+
* POSIX lit la ligne de commande (`ps -o command=`) — la preuve la plus forte, elle
|
|
450
|
+
* contient le titre de process Nodefony. Windows n'a pas d'équivalent bon marché :
|
|
451
|
+
* `tasklist` ne rend que le nom d'IMAGE (`node.exe`), preuve plus faible, qui suffit
|
|
452
|
+
* néanmoins à écarter un PID recyclé par un process tiers. C'est à l'appelant de
|
|
453
|
+
* corroborer (le pidfile qui nomme ce PID vit dans SON projet).
|
|
454
|
+
*
|
|
455
|
+
* @param pid - process à identifier (supposé vivant).
|
|
456
|
+
* @returns le verdict d'observation, cf {@link ProcessIdentity}.
|
|
457
|
+
*/
|
|
458
|
+
function identifyProcess(pid) {
|
|
459
|
+
const cmd = process.platform === "win32" ? {
|
|
460
|
+
file: "tasklist",
|
|
461
|
+
args: [
|
|
462
|
+
"/FI",
|
|
463
|
+
`PID eq ${pid}`,
|
|
464
|
+
"/NH",
|
|
465
|
+
"/FO",
|
|
466
|
+
"CSV"
|
|
467
|
+
]
|
|
468
|
+
} : {
|
|
469
|
+
file: "ps",
|
|
470
|
+
args: [
|
|
471
|
+
"-p",
|
|
472
|
+
String(pid),
|
|
473
|
+
"-o",
|
|
474
|
+
"command="
|
|
475
|
+
]
|
|
476
|
+
};
|
|
477
|
+
try {
|
|
478
|
+
const res = spawnSync(cmd.file, cmd.args, {
|
|
479
|
+
encoding: "utf8",
|
|
480
|
+
env: {
|
|
481
|
+
...process.env,
|
|
482
|
+
LC_ALL: "C",
|
|
483
|
+
LANG: "C"
|
|
484
|
+
}
|
|
485
|
+
});
|
|
486
|
+
if (res.error || typeof res.stdout !== "string") return {
|
|
487
|
+
observed: false,
|
|
488
|
+
command: null
|
|
489
|
+
};
|
|
490
|
+
if (process.platform === "win32") {
|
|
491
|
+
const image = parseTasklistImage(res.stdout);
|
|
492
|
+
return image === null ? {
|
|
493
|
+
observed: res.status === 0,
|
|
494
|
+
command: null
|
|
495
|
+
} : {
|
|
496
|
+
observed: true,
|
|
497
|
+
command: image
|
|
498
|
+
};
|
|
499
|
+
}
|
|
500
|
+
if (res.status !== 0) return {
|
|
501
|
+
observed: true,
|
|
502
|
+
command: null
|
|
503
|
+
};
|
|
504
|
+
const out = res.stdout.trim();
|
|
505
|
+
return {
|
|
506
|
+
observed: true,
|
|
507
|
+
command: out.length > 0 ? out : null
|
|
508
|
+
};
|
|
509
|
+
} catch {
|
|
510
|
+
return {
|
|
511
|
+
observed: false,
|
|
512
|
+
command: null
|
|
513
|
+
};
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
/**
|
|
517
|
+
* Comment atteindre l'ARBRE de `pid` sur `platform` — fonction PURE, sans effet.
|
|
518
|
+
*
|
|
519
|
+
* POSIX répond par un signal au groupe (`-pid`), qui n'a pas d'équivalent Windows :
|
|
520
|
+
* là-bas la seule voie est un programme externe, `taskkill /T`, qui descend la
|
|
521
|
+
* FILIATION (parent → enfants → petits-enfants) au lieu du groupe. C'est pourquoi
|
|
522
|
+
* l'enfant serveur y est spawné `detached:false` : rattaché, il est atteignable.
|
|
523
|
+
*
|
|
524
|
+
* `/F` (forcé) est là par nécessité, pas par choix : `taskkill` sans `/F` poste un
|
|
525
|
+
* `WM_CLOSE` aux FENÊTRES du process, ce qu'un process console n'a pas — la demande
|
|
526
|
+
* gracieuse n'arriverait donc nulle part. **Windows n'offre aucun arrêt gracieux
|
|
527
|
+
* d'arbre**, et ce fait s'ÉNONCE ({@link TreeSignalOutcome}) plutôt qu'il ne se
|
|
528
|
+
* masque derrière un `SIGTERM` qui n'en a que le nom.
|
|
529
|
+
*
|
|
530
|
+
* @param pid - racine de l'arbre à emporter.
|
|
531
|
+
* @param platform - `process.platform` (injecté : c'est ce qui rend la règle testable
|
|
532
|
+
* depuis n'importe quel système).
|
|
533
|
+
* @returns le programme à lancer, ou `null` quand la plateforme passe par les signaux.
|
|
534
|
+
*/
|
|
535
|
+
function killTreeCommand(pid, platform) {
|
|
536
|
+
if (platform !== "win32") return null;
|
|
537
|
+
return {
|
|
538
|
+
file: "taskkill",
|
|
539
|
+
args: [
|
|
540
|
+
"/PID",
|
|
541
|
+
String(pid),
|
|
542
|
+
"/T",
|
|
543
|
+
"/F"
|
|
544
|
+
]
|
|
545
|
+
};
|
|
546
|
+
}
|
|
547
|
+
/** Lance `taskkill` et CONSTATE le résultat (code 128 = process déjà parti : succès). */
|
|
548
|
+
function defaultRunTreeKill(cmd) {
|
|
549
|
+
try {
|
|
550
|
+
const res = spawnSync(cmd.file, cmd.args, { encoding: "utf8" });
|
|
551
|
+
if (res.error) return false;
|
|
552
|
+
return res.status === 0 || res.status === 128;
|
|
553
|
+
} catch {
|
|
554
|
+
return false;
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
/**
|
|
558
|
+
* Envoie `signal` à l'ARBRE de `pid` — enfant serveur ET ses Vite — et dit ce qu'il a
|
|
559
|
+
* pu atteindre. No-op silencieux si le process n'existe plus.
|
|
560
|
+
*
|
|
561
|
+
* POSIX : signal au groupe (`-pid`) puis au pid en repli. Windows : `taskkill /T /F`
|
|
562
|
+
* (cf {@link killTreeCommand}) puis, si le programme manque, `process.kill(pid)` —
|
|
563
|
+
* qui n'emporte QUE l'enfant direct, d'où le verdict `single` à annoncer.
|
|
564
|
+
*
|
|
565
|
+
* @returns ce qui a été atteint, cf {@link TreeSignalOutcome}.
|
|
566
|
+
*/
|
|
567
|
+
function signalProcessGroup(pid, signal, deps = {}) {
|
|
568
|
+
const platform = deps.platform ?? process.platform;
|
|
569
|
+
const killPid = deps.killPid ?? ((p, s) => {
|
|
570
|
+
process.kill(p, s);
|
|
571
|
+
});
|
|
572
|
+
const tree = killTreeCommand(pid, platform);
|
|
573
|
+
if (tree) {
|
|
574
|
+
if ((deps.runTreeKill ?? defaultRunTreeKill)(tree)) return "forced-tree";
|
|
575
|
+
try {
|
|
576
|
+
killPid(pid, signal);
|
|
577
|
+
} catch {
|
|
578
|
+
return "gone";
|
|
579
|
+
}
|
|
580
|
+
return "single";
|
|
581
|
+
}
|
|
582
|
+
const killGroup = deps.killGroup ?? ((p, s) => {
|
|
583
|
+
process.kill(-p, s);
|
|
584
|
+
});
|
|
585
|
+
let group = true;
|
|
586
|
+
try {
|
|
587
|
+
killGroup(pid, signal);
|
|
588
|
+
} catch {
|
|
589
|
+
group = false;
|
|
590
|
+
}
|
|
591
|
+
let self = true;
|
|
592
|
+
try {
|
|
593
|
+
killPid(pid, signal);
|
|
594
|
+
} catch {
|
|
595
|
+
self = false;
|
|
596
|
+
}
|
|
597
|
+
if (group) return "group";
|
|
598
|
+
return self ? "single" : "gone";
|
|
599
|
+
}
|
|
600
|
+
/** Supprime le pidfile du superviseur (best-effort, idempotent). */
|
|
601
|
+
function clearSupervisorPidFile(cwd) {
|
|
602
|
+
try {
|
|
603
|
+
const f = devSupervisorPidFile(cwd);
|
|
604
|
+
if (existsSync(f)) rmSync(f, { force: true });
|
|
605
|
+
} catch {}
|
|
606
|
+
}
|
|
607
|
+
/** Petite pause (poll/backoff des boucles d'attente). */
|
|
608
|
+
const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
609
|
+
/**
|
|
610
|
+
* Racines d'un ensemble de process : ceux dont le parent n'est PAS lui-même dans
|
|
611
|
+
* l'ensemble. Tuer le GROUPE d'une racine suffit à emporter ses descendants présents
|
|
612
|
+
* (le superviseur emporte enfant serveur + Vite ; un orphelin est sa propre racine).
|
|
613
|
+
*/
|
|
614
|
+
function rootProcesses(procs) {
|
|
615
|
+
const pids = new Set(procs.map((p) => p.pid));
|
|
616
|
+
return procs.filter((p) => !pids.has(p.ppid));
|
|
617
|
+
}
|
|
618
|
+
/** Attend que tous les `pids` soient morts (poll), renvoie ceux encore vivants à l'échéance. */
|
|
619
|
+
async function waitAllDead(pids, timeoutMs) {
|
|
620
|
+
const deadline = Date.now() + timeoutMs;
|
|
621
|
+
for (;;) {
|
|
622
|
+
const alive = pids.filter((pid) => isPidAlive(pid));
|
|
623
|
+
if (alive.length === 0) return [];
|
|
624
|
+
if (Date.now() >= deadline) return alive;
|
|
625
|
+
await delay(120);
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
/**
|
|
629
|
+
* Arrête un ensemble de process dev par GROUPE — SIGTERM (arrêt gracieux) sur les
|
|
630
|
+
* racines puis SIGKILL des récalcitrants (groupes racines + PID restants un à un).
|
|
631
|
+
* Renvoie les PID encore vivants à la fin (vide = arrêt complet).
|
|
632
|
+
*
|
|
633
|
+
* OBSERVATION EXTERNE pure (signaux POSIX, aucun IPC). Logique PARTAGÉE entre
|
|
634
|
+
* `nodefony stop` (rapport user, cf {@link DevProcessInfo}) et le verrou single-instance
|
|
635
|
+
* du superviseur (nettoyage des résiduels au démarrage) → une seule définition de « tuer
|
|
636
|
+
* proprement un arbre de process dev » (divergence = bug).
|
|
637
|
+
*/
|
|
638
|
+
async function terminateDevProcesses(procs, opts = {}) {
|
|
639
|
+
if (procs.length === 0) return [];
|
|
640
|
+
const termWaitMs = opts.termWaitMs ?? 4e3;
|
|
641
|
+
const killWaitMs = opts.killWaitMs ?? 1500;
|
|
642
|
+
const roots = rootProcesses(procs);
|
|
643
|
+
for (const r of roots) signalProcessGroup(r.pid, "SIGTERM");
|
|
644
|
+
let alive = await waitAllDead(procs.map((p) => p.pid), termWaitMs);
|
|
645
|
+
if (alive.length > 0) {
|
|
646
|
+
for (const r of roots) signalProcessGroup(r.pid, "SIGKILL");
|
|
647
|
+
for (const pid of alive) try {
|
|
648
|
+
process.kill(pid, "SIGKILL");
|
|
649
|
+
} catch {}
|
|
650
|
+
alive = await waitAllDead(alive, killWaitMs);
|
|
651
|
+
}
|
|
652
|
+
return alive;
|
|
653
|
+
}
|
|
654
|
+
/**
|
|
655
|
+
* Répertoire de travail d'un process — `/proc/<pid>/cwd` (Linux) ou `lsof -d cwd`
|
|
656
|
+
* (macOS/BSD). `null` si irrésolu (process mort, permissions, outil absent).
|
|
657
|
+
*
|
|
658
|
+
* Sert au SCOPING PAR PROJET du multi-app : plusieurs apps Nodefony peuvent
|
|
659
|
+
* tourner en dev sur le même poste — un balayage `ps` global sans notion de
|
|
660
|
+
* projet faisait tuer le runtime d'un AUTRE dossier (destructeur, vécu en
|
|
661
|
+
* design review). Le cwd est le seul identifiant de projet observable de
|
|
662
|
+
* l'extérieur (aucun IPC — choix d'architecture de ce module).
|
|
663
|
+
*/
|
|
664
|
+
function processCwd(pid) {
|
|
665
|
+
if (process.platform === "linux") try {
|
|
666
|
+
return readlinkSync(`/proc/${pid}/cwd`);
|
|
667
|
+
} catch {
|
|
668
|
+
return null;
|
|
669
|
+
}
|
|
670
|
+
try {
|
|
671
|
+
const res = spawnSync("lsof", [
|
|
672
|
+
"-a",
|
|
673
|
+
"-p",
|
|
674
|
+
String(pid),
|
|
675
|
+
"-d",
|
|
676
|
+
"cwd",
|
|
677
|
+
"-Fn"
|
|
678
|
+
], {
|
|
679
|
+
encoding: "utf8",
|
|
680
|
+
env: {
|
|
681
|
+
...process.env,
|
|
682
|
+
LC_ALL: "C"
|
|
683
|
+
}
|
|
684
|
+
});
|
|
685
|
+
if (typeof res.stdout !== "string") return null;
|
|
686
|
+
for (const line of res.stdout.split("\n")) if (line.startsWith("n")) return line.slice(1);
|
|
687
|
+
} catch {}
|
|
688
|
+
return null;
|
|
689
|
+
}
|
|
690
|
+
/**
|
|
691
|
+
* Scinde des process découverts entre CE projet (`mine` — tuables par les gardes
|
|
692
|
+
* single-instance / `nodefony stop`) et les AUTRES (`foreign` — JAMAIS touchés).
|
|
693
|
+
*
|
|
694
|
+
* Règles de rattachement :
|
|
695
|
+
* - rôles racine (supervisor/master/server/worker) : cwd EXACTEMENT le projet —
|
|
696
|
+
* ils sont toujours spawnés à la racine ;
|
|
697
|
+
* - `vite` : projet OU sous-dossier (le builder peut travailler dans `frontend/`) ;
|
|
698
|
+
* - cwd IRRÉSOLU → `foreign` : on préfère laisser vivre un orphelin (bénin, la
|
|
699
|
+
* collision de ports est refusée plus loin) plutôt que tuer la session d'un
|
|
700
|
+
* autre projet (destructeur).
|
|
701
|
+
*
|
|
702
|
+
* Limite assumée : deux projets IMBRIQUÉS (une app dans un sous-dossier du repo)
|
|
703
|
+
* partagent le préfixe → le Vite de l'app peut être adopté par le parent.
|
|
704
|
+
*/
|
|
705
|
+
function splitByProject(procs, projectCwd, getCwd = processCwd) {
|
|
706
|
+
const root = path.resolve(projectCwd);
|
|
707
|
+
const mine = [];
|
|
708
|
+
const foreign = [];
|
|
709
|
+
for (const p of procs) {
|
|
710
|
+
const cwd = getCwd(p.pid);
|
|
711
|
+
const resolved = cwd === null ? null : path.resolve(cwd);
|
|
712
|
+
if (resolved !== null && (resolved === root || p.role === "vite" && resolved.startsWith(root + path.sep))) mine.push(p);
|
|
713
|
+
else foreign.push({
|
|
714
|
+
...p,
|
|
715
|
+
cwd: resolved
|
|
716
|
+
});
|
|
717
|
+
}
|
|
718
|
+
return {
|
|
719
|
+
mine,
|
|
720
|
+
foreign
|
|
721
|
+
};
|
|
722
|
+
}
|
|
723
|
+
/**
|
|
724
|
+
* `true` si `cwd` ressemble à un projet Nodefony : `package.json` déclarant la
|
|
725
|
+
* dépendance `nodefony`, OU `node_modules/nodefony` présent (app installée sans
|
|
726
|
+
* la déclarer). MÊME heuristique que `Kernel.resolveAppEntry` (détection d'app),
|
|
727
|
+
* mais STANDALONE (fs seul, aucun kernel) — pour que `nodefony status`/`stop`
|
|
728
|
+
* lancés hors projet le DISENT au lieu de suggérer un `nodefony dev` voué à
|
|
729
|
+
* l'échec.
|
|
730
|
+
*
|
|
731
|
+
* @param cwd - dossier à tester.
|
|
732
|
+
*/
|
|
733
|
+
function isNodefonyProjectDir(cwd) {
|
|
734
|
+
try {
|
|
735
|
+
const pkg = JSON.parse(readFileSync(path.resolve(cwd, "package.json"), "utf8"));
|
|
736
|
+
if (pkg.dependencies?.nodefony ?? pkg.devDependencies?.nodefony ?? pkg.peerDependencies?.nodefony) return true;
|
|
737
|
+
} catch {}
|
|
738
|
+
return existsSync(path.resolve(cwd, "node_modules", "nodefony"));
|
|
739
|
+
}
|
|
740
|
+
/**
|
|
741
|
+
* Racines de projet des runtimes ÉTRANGERS = cwd des rôles racine
|
|
742
|
+
* (supervisor/master/server/worker), toujours spawnés à la racine de leur projet.
|
|
743
|
+
* Un Vite, lui, peut travailler dans un sous-dossier : il se rattache par préfixe.
|
|
744
|
+
*
|
|
745
|
+
* Fonction PURE, partagée par le groupement d'affichage
|
|
746
|
+
* ({@link formatForeignRuntimes}) et l'attribution des ports
|
|
747
|
+
* ({@link foreignPortOwners}) — deux lectures du même découpage, une seule règle.
|
|
748
|
+
*/
|
|
749
|
+
function foreignProjectRoots(foreign) {
|
|
750
|
+
return [...new Set(foreign.filter((p) => p.role !== "vite" && p.cwd).map((p) => p.cwd))];
|
|
751
|
+
}
|
|
752
|
+
/**
|
|
753
|
+
* À QUI appartient chaque port occupé, quand ce n'est pas à nous.
|
|
754
|
+
*
|
|
755
|
+
* Un port tenu par le voisin n'est pas un arrêt qui a échoué : `stop` marquait
|
|
756
|
+
* `✗ encore occupé` les ports 5151/5152 juste après avoir annoncé lui-même que ces
|
|
757
|
+
* runtimes appartenaient à un AUTRE projet — la croix suggérait un échec là où il
|
|
758
|
+
* n'y avait rien à arrêter. Et `status`, faute de cette distinction, annonçait
|
|
759
|
+
* « 2/2 ports UP » à une application qui ne tournait pas.
|
|
760
|
+
*
|
|
761
|
+
* On interroge le canal que chaque projet publie sur lui-même
|
|
762
|
+
* ({@link readRuntimeState}) : c'est la seule source qui dise les ports EFFECTIFS
|
|
763
|
+
* quand `portPolicy: "auto"` les a décalés. Lecture SANS purge — le ménage d'un
|
|
764
|
+
* projet étranger ne nous appartient pas.
|
|
765
|
+
*
|
|
766
|
+
* @param foreign - runtimes d'autres projets (sortie `splitByProject().foreign`).
|
|
767
|
+
* @param readState - lecture d'un état de projet (injectable pour les tests).
|
|
768
|
+
* @returns port → racine du projet qui le tient (objet nu : sérialisable JSON,
|
|
769
|
+
* donc transportable tel quel par le data plane, là où une `Map` se perdrait).
|
|
770
|
+
*/
|
|
771
|
+
function foreignPortOwners(foreign, readState = (cwd) => readRuntimeState(cwd, { purgeStale: false })) {
|
|
772
|
+
const owners = {};
|
|
773
|
+
for (const root of foreignProjectRoots(foreign)) {
|
|
774
|
+
const state = readState(root);
|
|
775
|
+
if (!state) continue;
|
|
776
|
+
for (const port of state.ports) if (owners[port] === void 0) owners[port] = root;
|
|
777
|
+
}
|
|
778
|
+
return owners;
|
|
779
|
+
}
|
|
780
|
+
/**
|
|
781
|
+
* Qualifie un port sondé à partir des propriétaires connus
|
|
782
|
+
* ({@link foreignPortOwners}). Fonction PURE : c'est LA règle « pas à moi ≠ pas
|
|
783
|
+
* mort », et elle vit à un seul endroit pour que `status` et `stop` la lisent pareil.
|
|
784
|
+
*/
|
|
785
|
+
function portOwnership(state, owners = {}) {
|
|
786
|
+
if (!state.listening) return "free";
|
|
787
|
+
return owners[state.port] === void 0 ? "occupied" : "foreign";
|
|
788
|
+
}
|
|
789
|
+
/**
|
|
790
|
+
* Met en forme les runtimes ÉTRANGERS (autre projet) en bloc multi-lignes AÉRÉ :
|
|
791
|
+
* groupés par racine de projet (un Vite au cwd sous-dossier est rattaché à la
|
|
792
|
+
* racine qui le préfixe, affiché en relatif), un process par ligne (pid + rôle),
|
|
793
|
+
* puis les commandes EXACTES à copier-coller pour les arrêter. Partagé par le
|
|
794
|
+
* refus de boot (`DevSupervisor`), `nodefony dev --detach`, `nodefony stop` et
|
|
795
|
+
* `nodefony status` — même pédagogie partout (vécu : un pavé mono-ligne de 4 pids,
|
|
796
|
+
* dev bloqué sans savoir QUOI taper).
|
|
797
|
+
*
|
|
798
|
+
* @param foreign - runtimes d'autres projets (sortie `splitByProject().foreign`).
|
|
799
|
+
* @returns lignes prêtes à afficher (sans couleur ; l'appelant préfixe/colore).
|
|
800
|
+
*/
|
|
801
|
+
function formatForeignRuntimes(foreign) {
|
|
802
|
+
const roots = foreignProjectRoots(foreign);
|
|
803
|
+
const projectOf = (p) => {
|
|
804
|
+
if (!p.cwd) return "(dossier inconnu)";
|
|
805
|
+
return roots.find((r) => p.cwd === r || p.cwd.startsWith(r + path.sep)) ?? p.cwd;
|
|
806
|
+
};
|
|
807
|
+
const byProject = /* @__PURE__ */ new Map();
|
|
808
|
+
for (const p of foreign) {
|
|
809
|
+
const key = projectOf(p);
|
|
810
|
+
const list = byProject.get(key);
|
|
811
|
+
if (list) list.push(p);
|
|
812
|
+
else byProject.set(key, [p]);
|
|
813
|
+
}
|
|
814
|
+
const lines = [""];
|
|
815
|
+
for (const [project, procs] of byProject) {
|
|
816
|
+
lines.push(` projet ${project}`);
|
|
817
|
+
for (const p of procs) {
|
|
818
|
+
const sub = p.cwd && p.cwd !== project ? ` (${path.relative(project, p.cwd)})` : "";
|
|
819
|
+
lines.push(` · pid ${p.pid} ${p.label}${sub}`);
|
|
820
|
+
}
|
|
821
|
+
}
|
|
822
|
+
lines.push("", " pour les arrêter :");
|
|
823
|
+
for (const project of byProject.keys()) if (!project.startsWith("(")) {
|
|
824
|
+
lines.push(` nodefony stop ${path.basename(project)}`);
|
|
825
|
+
lines.push(` cd ${project} && nodefony stop`);
|
|
826
|
+
}
|
|
827
|
+
lines.push(" nodefony stop --all (tout Nodefony, tous projets)", "");
|
|
828
|
+
return lines;
|
|
829
|
+
}
|
|
830
|
+
/**
|
|
831
|
+
* `true` si un service écoute sur `port` en loopback (connexion acceptée). Inverse de
|
|
832
|
+
* la sonde « port libre » du superviseur : ici on confirme qu'un serveur RÉPOND.
|
|
833
|
+
*/
|
|
834
|
+
function isPortListening(port, host = "127.0.0.1", timeoutMs = 400) {
|
|
835
|
+
return new Promise((resolve) => {
|
|
836
|
+
const socket = net.connect({
|
|
837
|
+
host,
|
|
838
|
+
port
|
|
839
|
+
});
|
|
840
|
+
const settle = (listening) => {
|
|
841
|
+
socket.removeAllListeners();
|
|
842
|
+
socket.destroy();
|
|
843
|
+
resolve(listening);
|
|
844
|
+
};
|
|
845
|
+
socket.once("connect", () => settle(true));
|
|
846
|
+
socket.once("error", () => settle(false));
|
|
847
|
+
socket.setTimeout(timeoutMs, () => settle(false));
|
|
848
|
+
});
|
|
849
|
+
}
|
|
850
|
+
/** Sonde TCP de plusieurs ports en parallèle. */
|
|
851
|
+
async function probePorts(ports) {
|
|
852
|
+
return Promise.all(ports.map(async (port) => ({
|
|
853
|
+
port,
|
|
854
|
+
listening: await isPortListening(port)
|
|
855
|
+
})));
|
|
856
|
+
}
|
|
857
|
+
/** Convertit le champ `etime` de `ps` (`[[DD-]HH:]MM:SS`) en secondes. */
|
|
858
|
+
function parseEtime(etime) {
|
|
859
|
+
let rest = etime.trim();
|
|
860
|
+
let days = 0;
|
|
861
|
+
const dash = rest.indexOf("-");
|
|
862
|
+
if (dash >= 0) {
|
|
863
|
+
days = Number.parseInt(rest.slice(0, dash), 10) || 0;
|
|
864
|
+
rest = rest.slice(dash + 1);
|
|
865
|
+
}
|
|
866
|
+
const parts = rest.split(":").map((n) => Number.parseInt(n, 10) || 0);
|
|
867
|
+
let h = 0;
|
|
868
|
+
let m = 0;
|
|
869
|
+
let s = 0;
|
|
870
|
+
if (parts.length === 3) [h, m, s] = parts;
|
|
871
|
+
else if (parts.length === 2) [m, s] = parts;
|
|
872
|
+
else if (parts.length === 1) [s] = parts;
|
|
873
|
+
return days * 86400 + h * 3600 + m * 60 + s;
|
|
874
|
+
}
|
|
875
|
+
/** Formate une durée (s) en libellé court (`45s`, `2m14s`, `1h03m`, `2d 05h`). */
|
|
876
|
+
function formatUptime(sec) {
|
|
877
|
+
if (sec < 60) return `${sec}s`;
|
|
878
|
+
const d = Math.floor(sec / 86400);
|
|
879
|
+
const h = Math.floor(sec % 86400 / 3600);
|
|
880
|
+
const m = Math.floor(sec % 3600 / 60);
|
|
881
|
+
const s = sec % 60;
|
|
882
|
+
if (d > 0) return `${d}d ${String(h).padStart(2, "0")}h`;
|
|
883
|
+
if (h > 0) return `${h}h${String(m).padStart(2, "0")}m`;
|
|
884
|
+
return `${m}m${String(s).padStart(2, "0")}s`;
|
|
885
|
+
}
|
|
886
|
+
/** Extrait le détail d'un titre Vite (`nodefony-vite[studio]` → `studio`). */
|
|
887
|
+
function viteEntries(command) {
|
|
888
|
+
const m = command.match(/nodefony-vite\[([^\]]*)\]/);
|
|
889
|
+
return m ? m[1] : "";
|
|
890
|
+
}
|
|
891
|
+
/** Regex d'une ligne `ps -o pid=,ppid=,rss=,pcpu=,etime=,command=`. */
|
|
892
|
+
const PS_ROW_RE = /^\s*(\d+)\s+(\d+)\s+(\d+)\s+([\d.,]+)\s+(\S+)\s+(.*)$/;
|
|
893
|
+
/**
|
|
894
|
+
* Parse UNE ligne `ps` (pid ppid rss pcpu etime command) en {@link DevProcessInfo},
|
|
895
|
+
* ou `null` si la ligne ne matche pas ou n'est pas un process dev connu. `%CPU` toléré
|
|
896
|
+
* avec point OU virgule décimale (robustesse locale — la virgule FR a déjà fait passer
|
|
897
|
+
* la détection à zéro). Fonction PURE (testable sans `ps`).
|
|
898
|
+
*/
|
|
899
|
+
function parsePsRow(line) {
|
|
900
|
+
const m = line.match(PS_ROW_RE);
|
|
901
|
+
if (!m) return null;
|
|
902
|
+
const c = classify(m[6]);
|
|
903
|
+
if (!c) return null;
|
|
904
|
+
return {
|
|
905
|
+
pid: Number.parseInt(m[1], 10),
|
|
906
|
+
ppid: Number.parseInt(m[2], 10),
|
|
907
|
+
mode: c.mode,
|
|
908
|
+
role: c.role,
|
|
909
|
+
label: c.label,
|
|
910
|
+
detail: c.detail,
|
|
911
|
+
rssKb: Number.parseInt(m[3], 10),
|
|
912
|
+
cpu: Number.parseFloat(m[4].replace(",", ".")),
|
|
913
|
+
uptimeSec: parseEtime(m[5])
|
|
914
|
+
};
|
|
915
|
+
}
|
|
916
|
+
/**
|
|
917
|
+
* Classe une ligne de commande `ps` en (mode, rôle) runtime Nodefony, ou `null` si hors
|
|
918
|
+
* périmètre. Ordre du matching : titres dev (les plus spécifiques) d'abord, puis cluster
|
|
919
|
+
* (master/worker), puis le serveur prod mono générique en dernier — `nodefony-dev-server`
|
|
920
|
+
* (tiret) ne contient jamais `nodefony server` (espace), donc aucune ambiguïté.
|
|
921
|
+
*
|
|
922
|
+
* **Le titre est ANCRÉ EN TÊTE, jamais cherché dans la ligne.** Poser un
|
|
923
|
+
* `process.title` REMPLACE l'argv entier : `ps` rend alors le titre seul (au
|
|
924
|
+
* padding d'espaces près). Un process qui porte le motif AILLEURS ne fait que le
|
|
925
|
+
* mentionner — `tail -f /dev/null nodefony server`, `vim nodefony master.ts`,
|
|
926
|
+
* `grep -r nodefony-dev-server` — et il ne doit jamais devenir une cible :
|
|
927
|
+
* `nodefony stop --all` ne filtre par aucun projet, la reconnaissance du titre y
|
|
928
|
+
* est le SEUL rempart. Corollaire assumé : la fenêtre PRÉ-titre d'un boot
|
|
929
|
+
* (`npm exec nodefony development`, avant que la commande pose son titre) n'est
|
|
930
|
+
* pas détectée — mieux vaut manquer un process de 200 ms que tuer celui d'autrui.
|
|
931
|
+
*/
|
|
932
|
+
function classify(command) {
|
|
933
|
+
const cmd = command.trim();
|
|
934
|
+
if (cmd.startsWith("nodefony-dev-supervisor")) return {
|
|
935
|
+
mode: "dev",
|
|
936
|
+
role: "supervisor",
|
|
937
|
+
label: "supervisor"
|
|
938
|
+
};
|
|
939
|
+
if (cmd.startsWith("nodefony-dev-server")) return {
|
|
940
|
+
mode: "dev",
|
|
941
|
+
role: "server",
|
|
942
|
+
label: "server"
|
|
943
|
+
};
|
|
944
|
+
if (cmd.startsWith("nodefony-vite")) return {
|
|
945
|
+
mode: "dev",
|
|
946
|
+
role: "vite",
|
|
947
|
+
label: "vite",
|
|
948
|
+
detail: viteEntries(cmd) || void 0
|
|
949
|
+
};
|
|
950
|
+
if (cmd.startsWith("nodefony master")) {
|
|
951
|
+
const w = cmd.match(/\[cluster\s+(\d+)w\]/);
|
|
952
|
+
return {
|
|
953
|
+
mode: "cluster",
|
|
954
|
+
role: "master",
|
|
955
|
+
label: "master",
|
|
956
|
+
detail: w ? `${w[1]} workers` : void 0
|
|
957
|
+
};
|
|
958
|
+
}
|
|
959
|
+
if (cmd.startsWith("nodefony worker")) {
|
|
960
|
+
const id = cmd.match(/^nodefony worker (\d+)/);
|
|
961
|
+
return {
|
|
962
|
+
mode: "cluster",
|
|
963
|
+
role: "worker",
|
|
964
|
+
label: "worker",
|
|
965
|
+
detail: id ? `#${id[1]}` : void 0
|
|
966
|
+
};
|
|
967
|
+
}
|
|
968
|
+
if (cmd.startsWith("nodefony server")) return {
|
|
969
|
+
mode: "prod",
|
|
970
|
+
role: "server",
|
|
971
|
+
label: "server"
|
|
972
|
+
};
|
|
973
|
+
return null;
|
|
974
|
+
}
|
|
975
|
+
/**
|
|
976
|
+
* Découvre les process dev Nodefony vivants par OBSERVATION EXTERNE (`ps`), et DIT si
|
|
977
|
+
* l'observation a eu lieu.
|
|
978
|
+
*
|
|
979
|
+
* Ne retient que les process dont la commande porte un titre dev connu (superviseur /
|
|
980
|
+
* serveur / Vite) et en extrait PID/PPID/RSS/CPU/uptime. S'auto-exclut par défaut (le
|
|
981
|
+
* process appelant) sauf `opts.includeSelf`. Tri : superviseur, puis serveur, puis Vite.
|
|
982
|
+
*
|
|
983
|
+
* @remarks La disponibilité de `ps` ne se DÉDUIT pas de la plateforme, elle se CONSTATE.
|
|
984
|
+
* La supposer d'après `process.platform` revenait à parier que tout ce qui n'est pas
|
|
985
|
+
* Windows embarque `ps` — faux là où ça compte le plus : `procps` n'est pas installé
|
|
986
|
+
* dans les images Node minces (`node:*-slim`, distroless, Alpine nu) qui SONT le
|
|
987
|
+
* modèle de déploiement de Nodefony, et les BSD n'acceptent pas forcément cette
|
|
988
|
+
* syntaxe. Le pari donnait alors « aucun process » sans repli et sans un mot. On rend
|
|
989
|
+
* donc `supported:false` sur tout ce qui empêche de conclure : plateforme sans `ps`,
|
|
990
|
+
* binaire absent (`ENOENT`), code de sortie non nul, sortie illisible.
|
|
991
|
+
*/
|
|
992
|
+
function discoverDevProcessesDetailed(opts = {}) {
|
|
993
|
+
if (process.platform === "win32") return {
|
|
994
|
+
supported: false,
|
|
995
|
+
procs: []
|
|
996
|
+
};
|
|
997
|
+
let out;
|
|
998
|
+
try {
|
|
999
|
+
const res = spawnSync("ps", [
|
|
1000
|
+
"-A",
|
|
1001
|
+
"-o",
|
|
1002
|
+
"pid=,ppid=,rss=,pcpu=,etime=,command="
|
|
1003
|
+
], {
|
|
1004
|
+
encoding: "utf8",
|
|
1005
|
+
maxBuffer: 4194304,
|
|
1006
|
+
env: {
|
|
1007
|
+
...process.env,
|
|
1008
|
+
LC_ALL: "C",
|
|
1009
|
+
LANG: "C"
|
|
1010
|
+
}
|
|
1011
|
+
});
|
|
1012
|
+
if (res.error || res.status !== 0 || typeof res.stdout !== "string") return {
|
|
1013
|
+
supported: false,
|
|
1014
|
+
procs: []
|
|
1015
|
+
};
|
|
1016
|
+
out = res.stdout;
|
|
1017
|
+
} catch {
|
|
1018
|
+
return {
|
|
1019
|
+
supported: false,
|
|
1020
|
+
procs: []
|
|
1021
|
+
};
|
|
1022
|
+
}
|
|
1023
|
+
const procs = [];
|
|
1024
|
+
for (const raw of out.split("\n")) {
|
|
1025
|
+
const info = parsePsRow(raw);
|
|
1026
|
+
if (!info) continue;
|
|
1027
|
+
if (!opts.includeSelf && info.pid === process.pid) continue;
|
|
1028
|
+
procs.push(info);
|
|
1029
|
+
}
|
|
1030
|
+
const order = {
|
|
1031
|
+
supervisor: 0,
|
|
1032
|
+
master: 0,
|
|
1033
|
+
server: 1,
|
|
1034
|
+
worker: 1,
|
|
1035
|
+
vite: 2
|
|
1036
|
+
};
|
|
1037
|
+
procs.sort((a, b) => order[a.role] - order[b.role] || a.pid - b.pid);
|
|
1038
|
+
return {
|
|
1039
|
+
supported: true,
|
|
1040
|
+
procs
|
|
1041
|
+
};
|
|
1042
|
+
}
|
|
1043
|
+
/**
|
|
1044
|
+
* Liste seule des process observés — commodité pour les appelants qui n'ont rien à
|
|
1045
|
+
* décider du « je n'ai pas pu regarder » (le rendu d'un tableau, un décompte).
|
|
1046
|
+
* Quiconque doit choisir un REPLI prend {@link discoverDevProcessesDetailed}, sans quoi
|
|
1047
|
+
* une liste vide se lit « rien ne tourne » alors qu'elle peut signifier l'inverse.
|
|
1048
|
+
*/
|
|
1049
|
+
function discoverDevProcesses(opts = {}) {
|
|
1050
|
+
return discoverDevProcessesDetailed(opts).procs;
|
|
1051
|
+
}
|
|
1052
|
+
/**
|
|
1053
|
+
* Modes runtime présents parmi les process PRINCIPAUX (Vite exclu — un Vite ne « tient »
|
|
1054
|
+
* pas les ports serveur). Set vide = aucun runtime principal vivant. Fonction PURE.
|
|
1055
|
+
*/
|
|
1056
|
+
function runtimeModes(procs) {
|
|
1057
|
+
const modes = /* @__PURE__ */ new Set();
|
|
1058
|
+
for (const p of procs) if (PRIMARY_ROLES.has(p.role)) modes.add(p.mode);
|
|
1059
|
+
return modes;
|
|
1060
|
+
}
|
|
1061
|
+
/**
|
|
1062
|
+
* Mode runtime dominant observé, ou `null` si aucun process principal. Priorité
|
|
1063
|
+
* dev > cluster > prod en cas de cohabitation anormale (le conflit est signalé par
|
|
1064
|
+
* ailleurs en warning / refus). Fonction PURE.
|
|
1065
|
+
*/
|
|
1066
|
+
function detectRuntimeMode(procs) {
|
|
1067
|
+
const modes = runtimeModes(procs);
|
|
1068
|
+
if (modes.has("dev")) return "dev";
|
|
1069
|
+
if (modes.has("cluster")) return "cluster";
|
|
1070
|
+
if (modes.has("prod")) return "prod";
|
|
1071
|
+
return null;
|
|
1072
|
+
}
|
|
1073
|
+
/**
|
|
1074
|
+
* Process PRINCIPAUX appartenant à un runtime d'un mode DIFFÉRENT de `intended` — un
|
|
1075
|
+
* conflit de cohabitation (ex. un `prod`/`cluster` occupe les ports quand on veut
|
|
1076
|
+
* démarrer en `dev`, ou l'inverse). Vite exclu (enfant). Sert aux gardes anti-collision :
|
|
1077
|
+
* fail-loud (refus + message), JAMAIS de kill cross-mode automatique (un prod est
|
|
1078
|
+
* intentionnel). Fonction PURE.
|
|
1079
|
+
*/
|
|
1080
|
+
function findRuntimeConflict(procs, intended) {
|
|
1081
|
+
return procs.filter((p) => PRIMARY_ROLES.has(p.role) && p.mode !== intended);
|
|
1082
|
+
}
|
|
1083
|
+
/** Résout les globs `workspaces` (`a/b`, `a/*`) en chemins de dossiers absolus. */
|
|
1084
|
+
function resolveWorkspaceDirs(cwd, globs) {
|
|
1085
|
+
const out = [];
|
|
1086
|
+
for (const g of globs) if (g.endsWith("/*")) {
|
|
1087
|
+
const base = path.join(cwd, g.slice(0, -2));
|
|
1088
|
+
try {
|
|
1089
|
+
for (const e of readdirSync(base, { withFileTypes: true })) if (e.isDirectory()) out.push(path.join(base, e.name));
|
|
1090
|
+
} catch {}
|
|
1091
|
+
} else out.push(path.join(cwd, g));
|
|
1092
|
+
return out;
|
|
1093
|
+
}
|
|
1094
|
+
/**
|
|
1095
|
+
* Liste les workspaces qui DEVRAIENT produire un dist (présence d'un `rolldown.config.ts`)
|
|
1096
|
+
* mais dont le dossier `dist/` est absent ou vide — renvoie leurs **noms de package**
|
|
1097
|
+
* (pour `turbo --filter`). On cible l'ABSENCE de build, pas l'entrée exacte (le core
|
|
1098
|
+
* sort `dist/node/…`, d'autres `dist/index.js`) → vérifier « dist non vide » est le
|
|
1099
|
+
* critère robuste et uniforme.
|
|
1100
|
+
*
|
|
1101
|
+
* POST-CONDITION du build du superviseur : `turbo run build` peut renvoyer 0 en « cache
|
|
1102
|
+
* hit » SANS restaurer un dist supprimé (gitignored, `clean` partiel, checkout de
|
|
1103
|
+
* branche) → le module manquant tombe en fail-soft au boot et cascade en silence
|
|
1104
|
+
* (« vert mais cassé »). On vérifie le terrain (la confiance n'exclut pas le contrôle).
|
|
1105
|
+
* Pur filesystem, aucun boot. Un workspace sans config de bundler (WIP non câblé) est
|
|
1106
|
+
* ignoré : aucun dist n'est attendu de lui.
|
|
1107
|
+
*/
|
|
1108
|
+
function missingWorkspaceDists(cwd) {
|
|
1109
|
+
let globs;
|
|
1110
|
+
try {
|
|
1111
|
+
globs = JSON.parse(readFileSync(path.join(cwd, "package.json"), "utf8")).workspaces ?? [];
|
|
1112
|
+
} catch {
|
|
1113
|
+
return [];
|
|
1114
|
+
}
|
|
1115
|
+
const missing = [];
|
|
1116
|
+
for (const dir of resolveWorkspaceDirs(cwd, globs)) {
|
|
1117
|
+
if (!existsSync(path.join(dir, "rolldown.config.ts"))) continue;
|
|
1118
|
+
if (distIsBuilt(dir)) continue;
|
|
1119
|
+
let name = path.basename(dir);
|
|
1120
|
+
try {
|
|
1121
|
+
const pj = JSON.parse(readFileSync(path.join(dir, "package.json"), "utf8"));
|
|
1122
|
+
if (pj.name) name = pj.name;
|
|
1123
|
+
} catch {}
|
|
1124
|
+
missing.push(name);
|
|
1125
|
+
}
|
|
1126
|
+
return missing;
|
|
1127
|
+
}
|
|
1128
|
+
/** `true` si le dossier `dist/` du workspace existe et contient au moins un fichier. */
|
|
1129
|
+
function distIsBuilt(dir) {
|
|
1130
|
+
try {
|
|
1131
|
+
return readdirSync(path.join(dir, "dist")).length > 0;
|
|
1132
|
+
} catch {
|
|
1133
|
+
return false;
|
|
1134
|
+
}
|
|
1135
|
+
}
|
|
1136
|
+
//#endregion
|
|
1137
|
+
export { CLUSTER_MASTER_PREFIX, CLUSTER_WORKER_PREFIX, DEV_SERVER_TITLE, DEV_SUPERVISOR_TITLE, DEV_VITE_PREFIX, FALLBACK_DEV_PORTS, PROD_SERVER_TITLE, clearReadinessState, clearRuntimeState, clearSupervisorPidFile, defaultDevPorts, detectRuntimeMode, devSupervisorPidFile, discoverDevProcesses, discoverDevProcessesDetailed, discoverFromRuntimeState, findRuntimeConflict, foreignPortOwners, foreignProjectRoots, formatForeignRuntimes, formatUptime, identifyProcess, isNodefonyProjectDir, isPidAlive, isPortListening, killTreeCommand, missingWorkspaceDists, parsePsRow, parseTasklistImage, portOwnership, probePorts, processCwd, readReadinessState, readRuntimeState, readSupervisorPid, readSupervisorSuspension, readinessStateFile, resumeSupervisor, rootProcesses, runtimeModes, runtimeStateFile, signalProcessGroup, splitByProject, supervisorLockFile, suspendSupervisor, terminateDevProcesses, waitAllDead, writeReadinessState, writeRuntimeState };
|