@wasmsoft/fantastic 1.0.0
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/README.md +65 -0
- package/bin/run.js +27 -0
- package/bin/supervisor.js +65 -0
- package/dist/acquire/central-url.d.ts +9 -0
- package/dist/acquire/central-url.d.ts.map +1 -0
- package/dist/acquire/central-url.js +74 -0
- package/dist/acquire/central-url.js.map +1 -0
- package/dist/acquire/code.d.ts +21 -0
- package/dist/acquire/code.d.ts.map +1 -0
- package/dist/acquire/code.js +66 -0
- package/dist/acquire/code.js.map +1 -0
- package/dist/acquire/compatibility.d.ts +18 -0
- package/dist/acquire/compatibility.d.ts.map +1 -0
- package/dist/acquire/compatibility.js +36 -0
- package/dist/acquire/compatibility.js.map +1 -0
- package/dist/acquire/fetch.d.ts +26 -0
- package/dist/acquire/fetch.d.ts.map +1 -0
- package/dist/acquire/fetch.js +72 -0
- package/dist/acquire/fetch.js.map +1 -0
- package/dist/acquire/latest.d.ts +24 -0
- package/dist/acquire/latest.d.ts.map +1 -0
- package/dist/acquire/latest.js +95 -0
- package/dist/acquire/latest.js.map +1 -0
- package/dist/backup/archive.d.ts +26 -0
- package/dist/backup/archive.d.ts.map +1 -0
- package/dist/backup/archive.js +123 -0
- package/dist/backup/archive.js.map +1 -0
- package/dist/backup/restore.d.ts +46 -0
- package/dist/backup/restore.d.ts.map +1 -0
- package/dist/backup/restore.js +164 -0
- package/dist/backup/restore.js.map +1 -0
- package/dist/base-command.d.ts +54 -0
- package/dist/base-command.d.ts.map +1 -0
- package/dist/base-command.js +120 -0
- package/dist/base-command.js.map +1 -0
- package/dist/bundle-format/index.d.ts +6 -0
- package/dist/bundle-format/index.d.ts.map +1 -0
- package/dist/bundle-format/index.js +36 -0
- package/dist/bundle-format/index.js.map +1 -0
- package/dist/commands/activate.d.ts +15 -0
- package/dist/commands/activate.d.ts.map +1 -0
- package/dist/commands/activate.js +139 -0
- package/dist/commands/activate.js.map +1 -0
- package/dist/commands/backup.d.ts +11 -0
- package/dist/commands/backup.d.ts.map +1 -0
- package/dist/commands/backup.js +75 -0
- package/dist/commands/backup.js.map +1 -0
- package/dist/commands/config/get.d.ts +10 -0
- package/dist/commands/config/get.d.ts.map +1 -0
- package/dist/commands/config/get.js +33 -0
- package/dist/commands/config/get.js.map +1 -0
- package/dist/commands/config/list.d.ts +7 -0
- package/dist/commands/config/list.d.ts.map +1 -0
- package/dist/commands/config/list.js +43 -0
- package/dist/commands/config/list.js.map +1 -0
- package/dist/commands/config/set.d.ts +11 -0
- package/dist/commands/config/set.d.ts.map +1 -0
- package/dist/commands/config/set.js +56 -0
- package/dist/commands/config/set.js.map +1 -0
- package/dist/commands/db/migrate.d.ts +10 -0
- package/dist/commands/db/migrate.d.ts.map +1 -0
- package/dist/commands/db/migrate.js +67 -0
- package/dist/commands/db/migrate.js.map +1 -0
- package/dist/commands/dev.d.ts +19 -0
- package/dist/commands/dev.d.ts.map +1 -0
- package/dist/commands/dev.js +149 -0
- package/dist/commands/dev.js.map +1 -0
- package/dist/commands/doctor.d.ts +11 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +75 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/health.d.ts +12 -0
- package/dist/commands/health.d.ts.map +1 -0
- package/dist/commands/health.js +109 -0
- package/dist/commands/health.js.map +1 -0
- package/dist/commands/install.d.ts +60 -0
- package/dist/commands/install.d.ts.map +1 -0
- package/dist/commands/install.js +486 -0
- package/dist/commands/install.js.map +1 -0
- package/dist/commands/iptv/snapshot.d.ts +10 -0
- package/dist/commands/iptv/snapshot.d.ts.map +1 -0
- package/dist/commands/iptv/snapshot.js +55 -0
- package/dist/commands/iptv/snapshot.js.map +1 -0
- package/dist/commands/library/drives.d.ts +7 -0
- package/dist/commands/library/drives.d.ts.map +1 -0
- package/dist/commands/library/drives.js +71 -0
- package/dist/commands/library/drives.js.map +1 -0
- package/dist/commands/library/relink.d.ts +10 -0
- package/dist/commands/library/relink.d.ts.map +1 -0
- package/dist/commands/library/relink.js +72 -0
- package/dist/commands/library/relink.js.map +1 -0
- package/dist/commands/library/scan.d.ts +16 -0
- package/dist/commands/library/scan.d.ts.map +1 -0
- package/dist/commands/library/scan.js +87 -0
- package/dist/commands/library/scan.js.map +1 -0
- package/dist/commands/library/sections.d.ts +7 -0
- package/dist/commands/library/sections.d.ts.map +1 -0
- package/dist/commands/library/sections.js +33 -0
- package/dist/commands/library/sections.js.map +1 -0
- package/dist/commands/library/status.d.ts +7 -0
- package/dist/commands/library/status.d.ts.map +1 -0
- package/dist/commands/library/status.js +37 -0
- package/dist/commands/library/status.js.map +1 -0
- package/dist/commands/list.d.ts +7 -0
- package/dist/commands/list.d.ts.map +1 -0
- package/dist/commands/list.js +73 -0
- package/dist/commands/list.js.map +1 -0
- package/dist/commands/live/channels.d.ts +10 -0
- package/dist/commands/live/channels.d.ts.map +1 -0
- package/dist/commands/live/channels.js +55 -0
- package/dist/commands/live/channels.js.map +1 -0
- package/dist/commands/live/test.d.ts +15 -0
- package/dist/commands/live/test.d.ts.map +1 -0
- package/dist/commands/live/test.js +116 -0
- package/dist/commands/live/test.js.map +1 -0
- package/dist/commands/logs.d.ts +16 -0
- package/dist/commands/logs.d.ts.map +1 -0
- package/dist/commands/logs.js +77 -0
- package/dist/commands/logs.js.map +1 -0
- package/dist/commands/migrate-cli.d.ts +11 -0
- package/dist/commands/migrate-cli.d.ts.map +1 -0
- package/dist/commands/migrate-cli.js +116 -0
- package/dist/commands/migrate-cli.js.map +1 -0
- package/dist/commands/owner/reset.d.ts +7 -0
- package/dist/commands/owner/reset.d.ts.map +1 -0
- package/dist/commands/owner/reset.js +74 -0
- package/dist/commands/owner/reset.js.map +1 -0
- package/dist/commands/restart.d.ts +11 -0
- package/dist/commands/restart.d.ts.map +1 -0
- package/dist/commands/restart.js +53 -0
- package/dist/commands/restart.js.map +1 -0
- package/dist/commands/restore.d.ts +17 -0
- package/dist/commands/restore.d.ts.map +1 -0
- package/dist/commands/restore.js +148 -0
- package/dist/commands/restore.js.map +1 -0
- package/dist/commands/self-update.d.ts +10 -0
- package/dist/commands/self-update.d.ts.map +1 -0
- package/dist/commands/self-update.js +98 -0
- package/dist/commands/self-update.js.map +1 -0
- package/dist/commands/setup.d.ts +19 -0
- package/dist/commands/setup.d.ts.map +1 -0
- package/dist/commands/setup.js +111 -0
- package/dist/commands/setup.js.map +1 -0
- package/dist/commands/shell.d.ts +118 -0
- package/dist/commands/shell.d.ts.map +1 -0
- package/dist/commands/shell.js +415 -0
- package/dist/commands/shell.js.map +1 -0
- package/dist/commands/start.d.ts +12 -0
- package/dist/commands/start.d.ts.map +1 -0
- package/dist/commands/start.js +108 -0
- package/dist/commands/start.js.map +1 -0
- package/dist/commands/status.d.ts +8 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +115 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/stop.d.ts +11 -0
- package/dist/commands/stop.d.ts.map +1 -0
- package/dist/commands/stop.js +45 -0
- package/dist/commands/stop.js.map +1 -0
- package/dist/commands/stream/cancel.d.ts +13 -0
- package/dist/commands/stream/cancel.d.ts.map +1 -0
- package/dist/commands/stream/cancel.js +31 -0
- package/dist/commands/stream/cancel.js.map +1 -0
- package/dist/commands/stream/encoders.d.ts +7 -0
- package/dist/commands/stream/encoders.d.ts.map +1 -0
- package/dist/commands/stream/encoders.js +42 -0
- package/dist/commands/stream/encoders.js.map +1 -0
- package/dist/commands/stream/queue.d.ts +7 -0
- package/dist/commands/stream/queue.d.ts.map +1 -0
- package/dist/commands/stream/queue.js +52 -0
- package/dist/commands/stream/queue.js.map +1 -0
- package/dist/commands/stream/sessions.d.ts +7 -0
- package/dist/commands/stream/sessions.d.ts.map +1 -0
- package/dist/commands/stream/sessions.js +44 -0
- package/dist/commands/stream/sessions.js.map +1 -0
- package/dist/commands/uninstall.d.ts +23 -0
- package/dist/commands/uninstall.d.ts.map +1 -0
- package/dist/commands/uninstall.js +290 -0
- package/dist/commands/uninstall.js.map +1 -0
- package/dist/commands/update.d.ts +21 -0
- package/dist/commands/update.d.ts.map +1 -0
- package/dist/commands/update.js +290 -0
- package/dist/commands/update.js.map +1 -0
- package/dist/commands/watch.d.ts +10 -0
- package/dist/commands/watch.d.ts.map +1 -0
- package/dist/commands/watch.js +38 -0
- package/dist/commands/watch.js.map +1 -0
- package/dist/config/local-config.d.ts +22 -0
- package/dist/config/local-config.d.ts.map +1 -0
- package/dist/config/local-config.js +79 -0
- package/dist/config/local-config.js.map +1 -0
- package/dist/core-scripts/run.d.ts +22 -0
- package/dist/core-scripts/run.d.ts.map +1 -0
- package/dist/core-scripts/run.js +65 -0
- package/dist/core-scripts/run.js.map +1 -0
- package/dist/doctor/check.types.d.ts +51 -0
- package/dist/doctor/check.types.d.ts.map +1 -0
- package/dist/doctor/check.types.js +14 -0
- package/dist/doctor/check.types.js.map +1 -0
- package/dist/doctor/checks/core.check.d.ts +11 -0
- package/dist/doctor/checks/core.check.d.ts.map +1 -0
- package/dist/doctor/checks/core.check.js +104 -0
- package/dist/doctor/checks/core.check.js.map +1 -0
- package/dist/doctor/checks/data.check.d.ts +11 -0
- package/dist/doctor/checks/data.check.d.ts.map +1 -0
- package/dist/doctor/checks/data.check.js +70 -0
- package/dist/doctor/checks/data.check.js.map +1 -0
- package/dist/doctor/checks/environment.check.d.ts +6 -0
- package/dist/doctor/checks/environment.check.d.ts.map +1 -0
- package/dist/doctor/checks/environment.check.js +70 -0
- package/dist/doctor/checks/environment.check.js.map +1 -0
- package/dist/doctor/checks/integrity.check.d.ts +4 -0
- package/dist/doctor/checks/integrity.check.d.ts.map +1 -0
- package/dist/doctor/checks/integrity.check.js +89 -0
- package/dist/doctor/checks/integrity.check.js.map +1 -0
- package/dist/doctor/checks/isolation.check.d.ts +49 -0
- package/dist/doctor/checks/isolation.check.d.ts.map +1 -0
- package/dist/doctor/checks/isolation.check.js +220 -0
- package/dist/doctor/checks/isolation.check.js.map +1 -0
- package/dist/doctor/checks/licence.check.d.ts +8 -0
- package/dist/doctor/checks/licence.check.d.ts.map +1 -0
- package/dist/doctor/checks/licence.check.js +172 -0
- package/dist/doctor/checks/licence.check.js.map +1 -0
- package/dist/doctor/checks/ports.check.d.ts +4 -0
- package/dist/doctor/checks/ports.check.d.ts.map +1 -0
- package/dist/doctor/checks/ports.check.js +52 -0
- package/dist/doctor/checks/ports.check.js.map +1 -0
- package/dist/doctor/checks/supervisor.check.d.ts +19 -0
- package/dist/doctor/checks/supervisor.check.d.ts.map +1 -0
- package/dist/doctor/checks/supervisor.check.js +152 -0
- package/dist/doctor/checks/supervisor.check.js.map +1 -0
- package/dist/doctor/checks/tooling.check.d.ts +3 -0
- package/dist/doctor/checks/tooling.check.d.ts.map +1 -0
- package/dist/doctor/checks/tooling.check.js +43 -0
- package/dist/doctor/checks/tooling.check.js.map +1 -0
- package/dist/doctor/registry.d.ts +15 -0
- package/dist/doctor/registry.d.ts.map +1 -0
- package/dist/doctor/registry.js +53 -0
- package/dist/doctor/registry.js.map +1 -0
- package/dist/exit-codes.d.ts +18 -0
- package/dist/exit-codes.d.ts.map +1 -0
- package/dist/exit-codes.js +23 -0
- package/dist/exit-codes.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/logs/sink.d.ts +11 -0
- package/dist/logs/sink.d.ts.map +1 -0
- package/dist/logs/sink.js +73 -0
- package/dist/logs/sink.js.map +1 -0
- package/dist/logs/tail.d.ts +17 -0
- package/dist/logs/tail.d.ts.map +1 -0
- package/dist/logs/tail.js +98 -0
- package/dist/logs/tail.js.map +1 -0
- package/dist/packaging/boot-task.d.ts +56 -0
- package/dist/packaging/boot-task.d.ts.map +1 -0
- package/dist/packaging/boot-task.js +151 -0
- package/dist/packaging/boot-task.js.map +1 -0
- package/dist/packaging/install.d.ts +154 -0
- package/dist/packaging/install.d.ts.map +1 -0
- package/dist/packaging/install.js +381 -0
- package/dist/packaging/install.js.map +1 -0
- package/dist/packaging/layout.d.ts +153 -0
- package/dist/packaging/layout.d.ts.map +1 -0
- package/dist/packaging/layout.js +168 -0
- package/dist/packaging/layout.js.map +1 -0
- package/dist/packaging/machine-path.d.ts +52 -0
- package/dist/packaging/machine-path.d.ts.map +1 -0
- package/dist/packaging/machine-path.js +237 -0
- package/dist/packaging/machine-path.js.map +1 -0
- package/dist/packaging/manifest.d.ts +37 -0
- package/dist/packaging/manifest.d.ts.map +1 -0
- package/dist/packaging/manifest.js +115 -0
- package/dist/packaging/manifest.js.map +1 -0
- package/dist/packaging/shims.d.ts +31 -0
- package/dist/packaging/shims.d.ts.map +1 -0
- package/dist/packaging/shims.js +165 -0
- package/dist/packaging/shims.js.map +1 -0
- package/dist/probes/internal-paths.d.ts +35 -0
- package/dist/probes/internal-paths.d.ts.map +1 -0
- package/dist/probes/internal-paths.js +58 -0
- package/dist/probes/internal-paths.js.map +1 -0
- package/dist/probes/internal.client.d.ts +54 -0
- package/dist/probes/internal.client.d.ts.map +1 -0
- package/dist/probes/internal.client.js +123 -0
- package/dist/probes/internal.client.js.map +1 -0
- package/dist/probes/port.probe.d.ts +21 -0
- package/dist/probes/port.probe.d.ts.map +1 -0
- package/dist/probes/port.probe.js +42 -0
- package/dist/probes/port.probe.js.map +1 -0
- package/dist/probes/service.probe.d.ts +29 -0
- package/dist/probes/service.probe.d.ts.map +1 -0
- package/dist/probes/service.probe.js +65 -0
- package/dist/probes/service.probe.js.map +1 -0
- package/dist/profiles/appliance.profile.d.ts +20 -0
- package/dist/profiles/appliance.profile.d.ts.map +1 -0
- package/dist/profiles/appliance.profile.js +137 -0
- package/dist/profiles/appliance.profile.js.map +1 -0
- package/dist/profiles/dev.profile.d.ts +22 -0
- package/dist/profiles/dev.profile.d.ts.map +1 -0
- package/dist/profiles/dev.profile.js +104 -0
- package/dist/profiles/dev.profile.js.map +1 -0
- package/dist/profiles/resolve.d.ts +37 -0
- package/dist/profiles/resolve.d.ts.map +1 -0
- package/dist/profiles/resolve.js +198 -0
- package/dist/profiles/resolve.js.map +1 -0
- package/dist/profiles/types.d.ts +57 -0
- package/dist/profiles/types.d.ts.map +1 -0
- package/dist/profiles/types.js +15 -0
- package/dist/profiles/types.js.map +1 -0
- package/dist/registry/local-registry.d.ts +79 -0
- package/dist/registry/local-registry.d.ts.map +1 -0
- package/dist/registry/local-registry.js +252 -0
- package/dist/registry/local-registry.js.map +1 -0
- package/dist/render/banner.d.ts +13 -0
- package/dist/render/banner.d.ts.map +1 -0
- package/dist/render/banner.js +83 -0
- package/dist/render/banner.js.map +1 -0
- package/dist/render/boot.render.d.ts +123 -0
- package/dist/render/boot.render.d.ts.map +1 -0
- package/dist/render/boot.render.js +288 -0
- package/dist/render/boot.render.js.map +1 -0
- package/dist/render/brand.d.ts +16 -0
- package/dist/render/brand.d.ts.map +1 -0
- package/dist/render/brand.js +22 -0
- package/dist/render/brand.js.map +1 -0
- package/dist/render/doctor.render.d.ts +12 -0
- package/dist/render/doctor.render.d.ts.map +1 -0
- package/dist/render/doctor.render.js +95 -0
- package/dist/render/doctor.render.js.map +1 -0
- package/dist/render/json.d.ts +29 -0
- package/dist/render/json.d.ts.map +1 -0
- package/dist/render/json.js +19 -0
- package/dist/render/json.js.map +1 -0
- package/dist/render/licence.render.d.ts +10 -0
- package/dist/render/licence.render.d.ts.map +1 -0
- package/dist/render/licence.render.js +167 -0
- package/dist/render/licence.render.js.map +1 -0
- package/dist/render/status.render.d.ts +6 -0
- package/dist/render/status.render.d.ts.map +1 -0
- package/dist/render/status.render.js +52 -0
- package/dist/render/status.render.js.map +1 -0
- package/dist/render/theme.d.ts +66 -0
- package/dist/render/theme.d.ts.map +1 -0
- package/dist/render/theme.js +89 -0
- package/dist/render/theme.js.map +1 -0
- package/dist/runtime-guard.d.ts +19 -0
- package/dist/runtime-guard.d.ts.map +1 -0
- package/dist/runtime-guard.js +57 -0
- package/dist/runtime-guard.js.map +1 -0
- package/dist/shell/input-mode.d.ts +25 -0
- package/dist/shell/input-mode.d.ts.map +1 -0
- package/dist/shell/input-mode.js +17 -0
- package/dist/shell/input-mode.js.map +1 -0
- package/dist/shell/parse-line.d.ts +6 -0
- package/dist/shell/parse-line.d.ts.map +1 -0
- package/dist/shell/parse-line.js +62 -0
- package/dist/shell/parse-line.js.map +1 -0
- package/dist/shell/suggestions.d.ts +14 -0
- package/dist/shell/suggestions.d.ts.map +1 -0
- package/dist/shell/suggestions.js +35 -0
- package/dist/shell/suggestions.js.map +1 -0
- package/dist/supervisor/dependencies.d.ts +2 -0
- package/dist/supervisor/dependencies.d.ts.map +1 -0
- package/dist/supervisor/dependencies.js +38 -0
- package/dist/supervisor/dependencies.js.map +1 -0
- package/dist/supervisor/entry.d.ts +36 -0
- package/dist/supervisor/entry.d.ts.map +1 -0
- package/dist/supervisor/entry.js +171 -0
- package/dist/supervisor/entry.js.map +1 -0
- package/dist/supervisor/inspect.d.ts +17 -0
- package/dist/supervisor/inspect.d.ts.map +1 -0
- package/dist/supervisor/inspect.js +39 -0
- package/dist/supervisor/inspect.js.map +1 -0
- package/dist/supervisor/invocation.d.ts +27 -0
- package/dist/supervisor/invocation.d.ts.map +1 -0
- package/dist/supervisor/invocation.js +33 -0
- package/dist/supervisor/invocation.js.map +1 -0
- package/dist/supervisor/monitor.d.ts +63 -0
- package/dist/supervisor/monitor.d.ts.map +1 -0
- package/dist/supervisor/monitor.js +141 -0
- package/dist/supervisor/monitor.js.map +1 -0
- package/dist/supervisor/orchestrator.d.ts +52 -0
- package/dist/supervisor/orchestrator.d.ts.map +1 -0
- package/dist/supervisor/orchestrator.js +154 -0
- package/dist/supervisor/orchestrator.js.map +1 -0
- package/dist/supervisor/pidfile.d.ts +21 -0
- package/dist/supervisor/pidfile.d.ts.map +1 -0
- package/dist/supervisor/pidfile.js +39 -0
- package/dist/supervisor/pidfile.js.map +1 -0
- package/dist/supervisor/process-identity.d.ts +19 -0
- package/dist/supervisor/process-identity.d.ts.map +1 -0
- package/dist/supervisor/process-identity.js +51 -0
- package/dist/supervisor/process-identity.js.map +1 -0
- package/dist/supervisor/readiness.d.ts +17 -0
- package/dist/supervisor/readiness.d.ts.map +1 -0
- package/dist/supervisor/readiness.js +52 -0
- package/dist/supervisor/readiness.js.map +1 -0
- package/dist/supervisor/restart-consumer.d.ts +37 -0
- package/dist/supervisor/restart-consumer.d.ts.map +1 -0
- package/dist/supervisor/restart-consumer.js +119 -0
- package/dist/supervisor/restart-consumer.js.map +1 -0
- package/dist/supervisor/runner.d.ts +2 -0
- package/dist/supervisor/runner.d.ts.map +1 -0
- package/dist/supervisor/runner.js +118 -0
- package/dist/supervisor/runner.js.map +1 -0
- package/dist/supervisor/schedule-timer.d.ts +38 -0
- package/dist/supervisor/schedule-timer.d.ts.map +1 -0
- package/dist/supervisor/schedule-timer.js +148 -0
- package/dist/supervisor/schedule-timer.js.map +1 -0
- package/dist/supervisor/spawn.d.ts +18 -0
- package/dist/supervisor/spawn.d.ts.map +1 -0
- package/dist/supervisor/spawn.js +119 -0
- package/dist/supervisor/spawn.js.map +1 -0
- package/dist/supervisor/state-files.d.ts +33 -0
- package/dist/supervisor/state-files.d.ts.map +1 -0
- package/dist/supervisor/state-files.js +110 -0
- package/dist/supervisor/state-files.js.map +1 -0
- package/dist/supervisor/tree-kill.d.ts +14 -0
- package/dist/supervisor/tree-kill.d.ts.map +1 -0
- package/dist/supervisor/tree-kill.js +82 -0
- package/dist/supervisor/tree-kill.js.map +1 -0
- package/dist/ui/health-panel.d.ts +8 -0
- package/dist/ui/health-panel.d.ts.map +1 -0
- package/dist/ui/health-panel.js +91 -0
- package/dist/ui/health-panel.js.map +1 -0
- package/dist/updating/apply.d.ts +50 -0
- package/dist/updating/apply.d.ts.map +1 -0
- package/dist/updating/apply.js +172 -0
- package/dist/updating/apply.js.map +1 -0
- package/dist/updating/download.d.ts +44 -0
- package/dist/updating/download.d.ts.map +1 -0
- package/dist/updating/download.js +144 -0
- package/dist/updating/download.js.map +1 -0
- package/dist/updating/rollback.d.ts +33 -0
- package/dist/updating/rollback.d.ts.map +1 -0
- package/dist/updating/rollback.js +54 -0
- package/dist/updating/rollback.js.map +1 -0
- package/dist/updating/self.d.ts +16 -0
- package/dist/updating/self.d.ts.map +1 -0
- package/dist/updating/self.js +50 -0
- package/dist/updating/self.js.map +1 -0
- package/dist/updating/verify.d.ts +25 -0
- package/dist/updating/verify.d.ts.map +1 -0
- package/dist/updating/verify.js +51 -0
- package/dist/updating/verify.js.map +1 -0
- package/dist/updating/versions.d.ts +31 -0
- package/dist/updating/versions.d.ts.map +1 -0
- package/dist/updating/versions.js +78 -0
- package/dist/updating/versions.js.map +1 -0
- package/dist/version.d.ts +4 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +29 -0
- package/dist/version.js.map +1 -0
- package/package.json +106 -0
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { probeService } from "../probes/service.probe.js";
|
|
2
|
+
import { startServices } from "./orchestrator.js";
|
|
3
|
+
import { REMOTE_STATE_FILES, removeStateFile, writeStateJson } from "./state-files.js";
|
|
4
|
+
// AR: حلقة المراقبة والإحياء (٠٢٠/US1).
|
|
5
|
+
//
|
|
6
|
+
// **الخدمة الميّتة تُحيا، والخدمة التي تموت مرارًا تُترَك.** الجملتان معًا لا إحداهما: الأولى
|
|
7
|
+
// هي الميزة، والثانية هي ما يمنع الميزة من أن تصير عطلًا. خدمةٌ تفشل عند الإقلاع — منفذ محجوز،
|
|
8
|
+
// قاعدة تالفة، قرص امتلأ — تُحيا كل عشرين ثانية إلى الأبد، فتُغرق السجلّ وتستهلك المعالج وتخفي
|
|
9
|
+
// السبب الجذري خلف ضجيج محاولات لا تنتهي. الحارس يوقف الدورة **ويترك أثرًا مقروءًا**: العطل
|
|
10
|
+
// الظاهر أنفع من إخفاءٍ نشيط.
|
|
11
|
+
//
|
|
12
|
+
// **ولماذا فشلان متتاليان قبل الإحياء؟** لأن مسبارًا واحدًا يفشل لأسباب لا علاقة لها بموت
|
|
13
|
+
// الخدمة: النواة مشغولة بفحص مكتبة، أو ffmpeg يستهلك المعالج، أو المهلة انتهت بفارق أجزاء من
|
|
14
|
+
// الثانية. إحياءُ خدمة حيّة يقطع ضيفًا يشاهد — أي أن الدواء يصير الداء.
|
|
15
|
+
//
|
|
16
|
+
// EN: The monitor-and-revive loop (020/US1).
|
|
17
|
+
//
|
|
18
|
+
// **A dead service is revived, and a service that keeps dying is left alone.** Both sentences,
|
|
19
|
+
// not one: the first is the feature and the second is what stops the feature from becoming the
|
|
20
|
+
// fault. A service failing at boot — a held port, a corrupt database, a full disk — would be
|
|
21
|
+
// revived every twenty seconds forever, flooding the log, burning CPU and hiding the root cause
|
|
22
|
+
// behind the noise of endless attempts. The guard stops the cycle **and leaves a readable
|
|
23
|
+
// trace**: a visible fault is more useful than active concealment.
|
|
24
|
+
//
|
|
25
|
+
// **And why two consecutive failures before reviving?** Because a single probe fails for reasons
|
|
26
|
+
// that have nothing to do with a dead service: the core is busy scanning a library, `ffmpeg` is
|
|
27
|
+
// saturating the CPU, or the timeout expired by a fraction of a second. Reviving a live service
|
|
28
|
+
// cuts off a watching guest — the cure becomes the disease.
|
|
29
|
+
/** كم فشلًا متتاليًا قبل أن نعدّ الخدمة ميّتة. */
|
|
30
|
+
export const FAILURES_BEFORE_REVIVAL = 2;
|
|
31
|
+
/** نافذة الحارس وحدّها: أكثر من ثلاث إحياءات في عشر دقائق يعني عطلًا لا حادثة. */
|
|
32
|
+
export const REVIVAL_LIMIT = 3;
|
|
33
|
+
export const REVIVAL_WINDOW_MS = 10 * 60_000;
|
|
34
|
+
/**
|
|
35
|
+
* AR: حارس الدورة، **خالص بلا أثر جانبي وبلا ساعة خاصة به**. الزمن يُمرَّر إليه، فيُختبَر عبور
|
|
36
|
+
* عشر دقائق في سطر بدل انتظارها فعلًا — واختبارٌ لا يُكتَب لأنه بطيء هو اختبارٌ لا يوجد.
|
|
37
|
+
* EN: The loop guard, **pure, side-effect-free, and holding no clock of its own**. Time is passed
|
|
38
|
+
* in, so crossing a ten-minute window is tested in a line instead of waited out — and a test
|
|
39
|
+
* not written because it is slow is a test that does not exist.
|
|
40
|
+
*/
|
|
41
|
+
export class RevivalGuard {
|
|
42
|
+
limit;
|
|
43
|
+
windowMs;
|
|
44
|
+
revivals = new Map();
|
|
45
|
+
stopped = new Set();
|
|
46
|
+
constructor(limit = REVIVAL_LIMIT, windowMs = REVIVAL_WINDOW_MS) {
|
|
47
|
+
this.limit = limit;
|
|
48
|
+
this.windowMs = windowMs;
|
|
49
|
+
}
|
|
50
|
+
/** هل توقّفنا عن إحياء هذه الخدمة؟ */
|
|
51
|
+
isStopped(service) {
|
|
52
|
+
return this.stopped.has(service);
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* يسجّل محاولة إحياء ويقرّر مصيرها. **يُستدعى مرّة لكل محاولة** — استدعاؤه للاستعلام وحده
|
|
56
|
+
* يفسد العدّ.
|
|
57
|
+
*/
|
|
58
|
+
record(service, now) {
|
|
59
|
+
if (this.stopped.has(service))
|
|
60
|
+
return { revive: false, looping: false, attempts: this.limit };
|
|
61
|
+
const recent = (this.revivals.get(service) ?? []).filter((at) => now - at < this.windowMs);
|
|
62
|
+
recent.push(now);
|
|
63
|
+
this.revivals.set(service, recent);
|
|
64
|
+
// المحاولة التي تتجاوز الحدّ **لا تُنفَّذ**: تجاوز الحدّ هو نفسه سبب التوقّف.
|
|
65
|
+
if (recent.length > this.limit) {
|
|
66
|
+
this.stopped.add(service);
|
|
67
|
+
return { revive: false, looping: true, attempts: recent.length };
|
|
68
|
+
}
|
|
69
|
+
return { revive: true, looping: false, attempts: recent.length };
|
|
70
|
+
}
|
|
71
|
+
/** يمسح تاريخ خدمة عادت واستقرّت — أو أعاد المالك تشغيلها بيده. */
|
|
72
|
+
clear(service) {
|
|
73
|
+
this.revivals.delete(service);
|
|
74
|
+
this.stopped.delete(service);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* AR: جولة مراقبة واحدة على كل الخدمات. جولةٌ لا حلقة: من ينادينا يملك الإيقاع، فيُختبَر السلوك
|
|
79
|
+
* بجولات متتابعة بلا مؤقّتات ولا انتظار.
|
|
80
|
+
* EN: One monitoring round over every service. A round rather than a loop: the caller owns the
|
|
81
|
+
* cadence, so the behaviour is tested by calling rounds in sequence with no timers and no waits.
|
|
82
|
+
*/
|
|
83
|
+
export class ServiceMonitor {
|
|
84
|
+
profile;
|
|
85
|
+
options;
|
|
86
|
+
failures = new Map();
|
|
87
|
+
guard;
|
|
88
|
+
constructor(profile, options = {}) {
|
|
89
|
+
this.profile = profile;
|
|
90
|
+
this.options = options;
|
|
91
|
+
this.guard = options.guard ?? new RevivalGuard();
|
|
92
|
+
}
|
|
93
|
+
async round(now = Date.now()) {
|
|
94
|
+
for (const definition of this.profile.services) {
|
|
95
|
+
await this.check(definition, now);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
async check(definition, now) {
|
|
99
|
+
const probe = await probeService(definition, 2_000);
|
|
100
|
+
if (probe.reachable) {
|
|
101
|
+
const wasFailing = (this.failures.get(definition.name) ?? 0) >= FAILURES_BEFORE_REVIVAL;
|
|
102
|
+
this.failures.set(definition.name, 0);
|
|
103
|
+
if (wasFailing) {
|
|
104
|
+
// عادت من تلقائها أو بعد إحيائنا: نمسح تاريخها فلا يُحسَب عطلٌ قديم ضدّ عطلٍ جديد بعد شهر.
|
|
105
|
+
this.guard.clear(definition.name);
|
|
106
|
+
removeStateFile(this.profile, REMOTE_STATE_FILES.restartLoop);
|
|
107
|
+
this.emit(definition.name, "recovered", `${definition.label} is answering again`);
|
|
108
|
+
}
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
const failures = (this.failures.get(definition.name) ?? 0) + 1;
|
|
112
|
+
this.failures.set(definition.name, failures);
|
|
113
|
+
if (failures < FAILURES_BEFORE_REVIVAL)
|
|
114
|
+
return;
|
|
115
|
+
const decision = this.guard.record(definition.name, now);
|
|
116
|
+
if (decision.looping) {
|
|
117
|
+
const loop = {
|
|
118
|
+
service: definition.name,
|
|
119
|
+
attempts: decision.attempts - 1,
|
|
120
|
+
windowMinutes: Math.round(REVIVAL_WINDOW_MS / 60_000),
|
|
121
|
+
stoppedAt: new Date(now).toISOString(),
|
|
122
|
+
};
|
|
123
|
+
writeStateJson(this.profile, REMOTE_STATE_FILES.restartLoop, loop);
|
|
124
|
+
this.emit(definition.name, "loop-stopped", `${definition.label} failed ${loop.attempts} times in ${loop.windowMinutes} minutes — no longer reviving it`);
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
if (!decision.revive)
|
|
128
|
+
return;
|
|
129
|
+
const outcome = await startServices(this.profile, { only: [definition.name] });
|
|
130
|
+
const ok = outcome.ok;
|
|
131
|
+
if (ok)
|
|
132
|
+
this.failures.set(definition.name, 0);
|
|
133
|
+
this.emit(definition.name, ok ? "revived" : "revival-failed", ok
|
|
134
|
+
? `${definition.label} was not answering and has been restarted (attempt ${decision.attempts})`
|
|
135
|
+
: `${definition.label} did not come back: ${outcome.steps.at(-1)?.readiness?.reason ?? "unknown reason"}`);
|
|
136
|
+
}
|
|
137
|
+
emit(service, kind, detail) {
|
|
138
|
+
this.options.onEvent?.({ service, kind, detail });
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
//# sourceMappingURL=monitor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"monitor.js","sourceRoot":"","sources":["../../src/supervisor/monitor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { Profile, ServiceDefinition, ServiceName } from "../profiles/types.js";
|
|
2
|
+
import { type PortConflict } from "../probes/port.probe.js";
|
|
3
|
+
import { type ReadinessOutcome } from "./readiness.js";
|
|
4
|
+
export type StepStatus = "started" | "already-running" | "failed" | "skipped";
|
|
5
|
+
export interface StartStep {
|
|
6
|
+
definition: ServiceDefinition;
|
|
7
|
+
status: StepStatus;
|
|
8
|
+
pid?: number;
|
|
9
|
+
readiness?: ReadinessOutcome;
|
|
10
|
+
}
|
|
11
|
+
export interface StartOutcome {
|
|
12
|
+
steps: StartStep[];
|
|
13
|
+
conflicts: PortConflict[];
|
|
14
|
+
ok: boolean;
|
|
15
|
+
}
|
|
16
|
+
export interface StartOptions {
|
|
17
|
+
/** قصر التشغيل على خدمات بعينها. الترتيب يبقى ترتيب ملفّ التشغيل. */
|
|
18
|
+
only?: ServiceName[];
|
|
19
|
+
onStep?: (definition: ServiceDefinition, phase: "starting" | "waiting" | "done") => void;
|
|
20
|
+
}
|
|
21
|
+
export declare function startServices(profile: Profile, options?: StartOptions): Promise<StartOutcome>;
|
|
22
|
+
export interface StopStep {
|
|
23
|
+
definition: ServiceDefinition;
|
|
24
|
+
/** كانت تعمل قبل الأمر؟ */
|
|
25
|
+
wasRunning: boolean;
|
|
26
|
+
terminated: boolean;
|
|
27
|
+
forced: boolean;
|
|
28
|
+
/** تحرَّر المنفذ فعلًا؟ الدليل الحقيقي على نجاح الإيقاف. */
|
|
29
|
+
portReleased: boolean;
|
|
30
|
+
/** تعمل لكن لم نُطلقها نحن، فلا نملك سجلًّا نقتل به. */
|
|
31
|
+
foreign: boolean;
|
|
32
|
+
/** أوقفناها رغم أننا لم نُطلقها (--force): تُعرَض بوضوح لأنها تخصّ نافذة أخرى. */
|
|
33
|
+
adopted: boolean;
|
|
34
|
+
/** تعمل، ولم نُطلقها، ولم نتعرّف على العملية التي تحجز المنفذ. */
|
|
35
|
+
holderUnknown: boolean;
|
|
36
|
+
}
|
|
37
|
+
export interface StopOptions {
|
|
38
|
+
only?: ServiceName[];
|
|
39
|
+
/**
|
|
40
|
+
* يوقف ما يحجز منفذ الخدمة ولو لم يُطلقه الـ CLI.
|
|
41
|
+
* الافتراضي **لا يفعل**: مشرف عمليات يقتل ما لم يُطلقه هو خطر — قد يكون خادمًا شغّلته يدويًا في
|
|
42
|
+
* نافذة أخرى، أو عمليةً لا تخصّ المشروع أصلًا تصادف أنها تستمع على المنفذ نفسه.
|
|
43
|
+
* ومع ذلك بدون هذا العَلَم يبقى المستخدم بلا وسيلة لإيقاف ما شغّله بيده، فيُتاح صراحةً.
|
|
44
|
+
*/
|
|
45
|
+
force?: boolean;
|
|
46
|
+
}
|
|
47
|
+
export declare function stopServices(profile: Profile, options?: StopOptions): Promise<StopStep[]>;
|
|
48
|
+
export declare function restartServices(profile: Profile, options?: StartOptions & StopOptions): Promise<{
|
|
49
|
+
stopped: StopStep[];
|
|
50
|
+
started: StartOutcome;
|
|
51
|
+
}>;
|
|
52
|
+
//# sourceMappingURL=orchestrator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"orchestrator.d.ts","sourceRoot":"","sources":["../../src/supervisor/orchestrator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACpF,OAAO,EAAqC,KAAK,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAK/F,OAAO,EAAgB,KAAK,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAWrE,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,iBAAiB,GAAG,QAAQ,GAAG,SAAS,CAAC;AAE9E,MAAM,WAAW,SAAS;IACxB,UAAU,EAAE,iBAAiB,CAAC;IAC9B,MAAM,EAAE,UAAU,CAAC;IACnB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,gBAAgB,CAAC;CAC9B;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,SAAS,EAAE,YAAY,EAAE,CAAC;IAC1B,EAAE,EAAE,OAAO,CAAC;CACb;AAED,MAAM,WAAW,YAAY;IAC3B,qEAAqE;IACrE,IAAI,CAAC,EAAE,WAAW,EAAE,CAAC;IACrB,MAAM,CAAC,EAAE,CAAC,UAAU,EAAE,iBAAiB,EAAE,KAAK,EAAE,UAAU,GAAG,SAAS,GAAG,MAAM,KAAK,IAAI,CAAC;CAC1F;AAgBD,wBAAsB,aAAa,CACjC,OAAO,EAAE,OAAO,EAChB,OAAO,GAAE,YAAiB,GACzB,OAAO,CAAC,YAAY,CAAC,CA0DvB;AASD,MAAM,WAAW,QAAQ;IACvB,UAAU,EAAE,iBAAiB,CAAC;IAC9B,2BAA2B;IAC3B,UAAU,EAAE,OAAO,CAAC;IACpB,UAAU,EAAE,OAAO,CAAC;IACpB,MAAM,EAAE,OAAO,CAAC;IAChB,4DAA4D;IAC5D,YAAY,EAAE,OAAO,CAAC;IACtB,wDAAwD;IACxD,OAAO,EAAE,OAAO,CAAC;IACjB,oFAAoF;IACpF,OAAO,EAAE,OAAO,CAAC;IACjB,kEAAkE;IAClE,aAAa,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,CAAC,EAAE,WAAW,EAAE,CAAC;IACrB;;;;;OAKG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,wBAAsB,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,GAAE,WAAgB,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC,CAyFnG;AAED,wBAAsB,eAAe,CACnC,OAAO,EAAE,OAAO,EAChB,OAAO,GAAE,YAAY,GAAG,WAAgB,GACvC,OAAO,CAAC;IAAE,OAAO,EAAE,QAAQ,EAAE,CAAC;IAAC,OAAO,EAAE,YAAY,CAAA;CAAE,CAAC,CAIzD"}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { findPortConflicts, findPortHolder } from "../probes/port.probe.js";
|
|
2
|
+
import { probeService } from "../probes/service.probe.js";
|
|
3
|
+
import { readVerifiedPidRecord, removePidRecord } from "./pidfile.js";
|
|
4
|
+
import { launchDetached } from "./spawn.js";
|
|
5
|
+
import { isRecordedProcessAlive } from "./process-identity.js";
|
|
6
|
+
import { waitForReady } from "./readiness.js";
|
|
7
|
+
import { terminateTree, waitForPortRelease } from "./tree-kill.js";
|
|
8
|
+
function selectServices(profile, only) {
|
|
9
|
+
if (!only || only.length === 0)
|
|
10
|
+
return profile.services;
|
|
11
|
+
return profile.services.filter((service) => only.includes(service.name));
|
|
12
|
+
}
|
|
13
|
+
/** هل الخدمة تعمل أصلًا؟ نسأل السجلّ والمسبار معًا كما يفعل status. */
|
|
14
|
+
async function alreadyRunning(profile, definition) {
|
|
15
|
+
const record = await readVerifiedPidRecord(profile, definition.name);
|
|
16
|
+
if (record)
|
|
17
|
+
return true;
|
|
18
|
+
const probe = await probeService(definition, 1_500);
|
|
19
|
+
return probe.reachable;
|
|
20
|
+
}
|
|
21
|
+
export async function startServices(profile, options = {}) {
|
|
22
|
+
const targets = selectServices(profile, options.only);
|
|
23
|
+
const steps = [];
|
|
24
|
+
// الفحص المسبق للمنافذ يسبق أي إطلاق: رفض واضح يسمّي صاحب المنفذ أنفع من EADDRINUSE خام.
|
|
25
|
+
// نستثني الخدمات التي تعمل أصلًا، فمنفذها محجوز بها هي لا بغريب.
|
|
26
|
+
const runningFlags = await Promise.all(targets.map(async (definition) => ({ definition, running: await alreadyRunning(profile, definition) })));
|
|
27
|
+
const portsToCheck = runningFlags
|
|
28
|
+
.filter((entry) => !entry.running)
|
|
29
|
+
.map((entry) => entry.definition.port);
|
|
30
|
+
const conflicts = await findPortConflicts(portsToCheck);
|
|
31
|
+
if (conflicts.length > 0) {
|
|
32
|
+
return { steps, conflicts, ok: false };
|
|
33
|
+
}
|
|
34
|
+
const started = [];
|
|
35
|
+
for (const { definition, running } of runningFlags) {
|
|
36
|
+
if (running) {
|
|
37
|
+
steps.push({ definition, status: "already-running" });
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
options.onStep?.(definition, "starting");
|
|
41
|
+
const record = await launchDetached(profile, definition);
|
|
42
|
+
options.onStep?.(definition, "waiting");
|
|
43
|
+
const readiness = await waitForReady(definition, {
|
|
44
|
+
logDir: profile.logDir,
|
|
45
|
+
stillRunning: () => isRecordedProcessAlive(record),
|
|
46
|
+
});
|
|
47
|
+
if (!readiness.ready) {
|
|
48
|
+
steps.push({ definition, status: "failed", pid: record.pid, readiness });
|
|
49
|
+
// تراجع نظيف: نُسقط ما أقلعناه في هذه الجولة فلا نترك نظامًا نصف قائم.
|
|
50
|
+
await stopStarted(profile, started);
|
|
51
|
+
for (const remaining of targets.slice(targets.indexOf(definition) + 1)) {
|
|
52
|
+
steps.push({ definition: remaining, status: "skipped" });
|
|
53
|
+
}
|
|
54
|
+
return { steps, conflicts, ok: false };
|
|
55
|
+
}
|
|
56
|
+
const step = { definition, status: "started", pid: record.pid, readiness };
|
|
57
|
+
steps.push(step);
|
|
58
|
+
started.push(step);
|
|
59
|
+
options.onStep?.(definition, "done");
|
|
60
|
+
}
|
|
61
|
+
return { steps, conflicts, ok: true };
|
|
62
|
+
}
|
|
63
|
+
async function stopStarted(profile, steps) {
|
|
64
|
+
for (const step of [...steps].reverse()) {
|
|
65
|
+
if (step.pid)
|
|
66
|
+
await terminateTree(step.pid);
|
|
67
|
+
removePidRecord(profile, step.definition.name);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
export async function stopServices(profile, options = {}) {
|
|
71
|
+
// الإيقاف يعكس ترتيب الإقلاع: نُسقط الواجهة أولًا فلا يصل طلب إلى خدمة تُغلَق تحته.
|
|
72
|
+
const targets = selectServices(profile, options.only).slice().reverse();
|
|
73
|
+
const results = [];
|
|
74
|
+
for (const definition of targets) {
|
|
75
|
+
const record = await readVerifiedPidRecord(profile, definition.name);
|
|
76
|
+
if (!record) {
|
|
77
|
+
const probe = await probeService(definition, 1_500);
|
|
78
|
+
if (!probe.reachable) {
|
|
79
|
+
results.push({
|
|
80
|
+
definition,
|
|
81
|
+
wasRunning: false,
|
|
82
|
+
terminated: false,
|
|
83
|
+
forced: false,
|
|
84
|
+
portReleased: true,
|
|
85
|
+
foreign: false,
|
|
86
|
+
adopted: false,
|
|
87
|
+
holderUnknown: false,
|
|
88
|
+
});
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
// خدمة حيّة بلا سجلّ: أطلقها غيرنا. لا نقتل ما لم نُطلق إلا بطلب صريح (--force).
|
|
92
|
+
if (!options.force) {
|
|
93
|
+
results.push({
|
|
94
|
+
definition,
|
|
95
|
+
wasRunning: true,
|
|
96
|
+
terminated: false,
|
|
97
|
+
forced: false,
|
|
98
|
+
portReleased: false,
|
|
99
|
+
foreign: true,
|
|
100
|
+
adopted: false,
|
|
101
|
+
holderUnknown: false,
|
|
102
|
+
});
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
const holder = await findPortHolder(definition.port);
|
|
106
|
+
if (!holder) {
|
|
107
|
+
results.push({
|
|
108
|
+
definition,
|
|
109
|
+
wasRunning: true,
|
|
110
|
+
terminated: false,
|
|
111
|
+
forced: false,
|
|
112
|
+
portReleased: false,
|
|
113
|
+
foreign: true,
|
|
114
|
+
adopted: false,
|
|
115
|
+
holderUnknown: true,
|
|
116
|
+
});
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
const { terminated, forced } = await terminateTree(holder.pid);
|
|
120
|
+
const portReleased = await waitForPortRelease(definition.port);
|
|
121
|
+
results.push({
|
|
122
|
+
definition,
|
|
123
|
+
wasRunning: true,
|
|
124
|
+
terminated,
|
|
125
|
+
forced,
|
|
126
|
+
portReleased,
|
|
127
|
+
foreign: true,
|
|
128
|
+
adopted: true,
|
|
129
|
+
holderUnknown: false,
|
|
130
|
+
});
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
133
|
+
const { terminated, forced } = await terminateTree(record.pid);
|
|
134
|
+
removePidRecord(profile, definition.name);
|
|
135
|
+
const portReleased = await waitForPortRelease(definition.port);
|
|
136
|
+
results.push({
|
|
137
|
+
definition,
|
|
138
|
+
wasRunning: true,
|
|
139
|
+
terminated,
|
|
140
|
+
forced,
|
|
141
|
+
portReleased,
|
|
142
|
+
foreign: false,
|
|
143
|
+
adopted: false,
|
|
144
|
+
holderUnknown: false,
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
return results;
|
|
148
|
+
}
|
|
149
|
+
export async function restartServices(profile, options = {}) {
|
|
150
|
+
const stopped = await stopServices(profile, { only: options.only });
|
|
151
|
+
const started = await startServices(profile, options);
|
|
152
|
+
return { stopped, started };
|
|
153
|
+
}
|
|
154
|
+
//# sourceMappingURL=orchestrator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"orchestrator.js","sourceRoot":"","sources":["../../src/supervisor/orchestrator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Profile, ServiceName } from "../profiles/types.js";
|
|
2
|
+
export interface PidRecord {
|
|
3
|
+
service: ServiceName;
|
|
4
|
+
pid: number;
|
|
5
|
+
port: number;
|
|
6
|
+
profile: Profile["kind"];
|
|
7
|
+
/** وقت بدء العملية كما قرأه النظام. هذا ما يميّز عمليتنا عن PID أُعيد استعماله. */
|
|
8
|
+
startedAt: string;
|
|
9
|
+
commandLine: string;
|
|
10
|
+
/** وقت كتابة السجلّ. يُستعمل لعرض مدة التشغيل حين لا يتوفّر وقت البدء الحقيقي. */
|
|
11
|
+
writtenAt: string;
|
|
12
|
+
}
|
|
13
|
+
export declare function writePidRecord(profile: Profile, record: PidRecord): void;
|
|
14
|
+
export declare function readPidRecord(profile: Profile, service: ServiceName): PidRecord | undefined;
|
|
15
|
+
export declare function removePidRecord(profile: Profile, service: ServiceName): void;
|
|
16
|
+
/**
|
|
17
|
+
* يقرأ السجلّ **ويتحقّق منه**. السجلّ الذي لم تعد عمليته حيّة (أو صار الـ PID لعملية أخرى) يُحذف
|
|
18
|
+
* ويُعامَل كغير موجود، فلا يتراكم على القرص ولا يخدع أمرًا لاحقًا.
|
|
19
|
+
*/
|
|
20
|
+
export declare function readVerifiedPidRecord(profile: Profile, service: ServiceName): Promise<PidRecord | undefined>;
|
|
21
|
+
//# sourceMappingURL=pidfile.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pidfile.d.ts","sourceRoot":"","sources":["../../src/supervisor/pidfile.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAQjE,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,WAAW,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IACzB,mFAAmF;IACnF,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,kFAAkF;IAClF,SAAS,EAAE,MAAM,CAAC;CACnB;AAMD,wBAAgB,cAAc,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,GAAG,IAAI,CAGxE;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,GAAG,SAAS,GAAG,SAAS,CAU3F;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,GAAG,IAAI,CAE5E;AAED;;;GAGG;AACH,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC,CAQhC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { isRecordedProcessAlive } from "./process-identity.js";
|
|
4
|
+
function recordPath(profile, service) {
|
|
5
|
+
return join(profile.runDir, `${service}.json`);
|
|
6
|
+
}
|
|
7
|
+
export function writePidRecord(profile, record) {
|
|
8
|
+
mkdirSync(profile.runDir, { recursive: true });
|
|
9
|
+
writeFileSync(recordPath(profile, record.service), JSON.stringify(record, null, 2), "utf8");
|
|
10
|
+
}
|
|
11
|
+
export function readPidRecord(profile, service) {
|
|
12
|
+
const path = recordPath(profile, service);
|
|
13
|
+
if (!existsSync(path))
|
|
14
|
+
return undefined;
|
|
15
|
+
try {
|
|
16
|
+
return JSON.parse(readFileSync(path, "utf8"));
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
// سجلّ تالف يُعامَل كغير موجود: الأمر يمضي بالسبر بدل أن يفشل.
|
|
20
|
+
return undefined;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
export function removePidRecord(profile, service) {
|
|
24
|
+
rmSync(recordPath(profile, service), { force: true });
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* يقرأ السجلّ **ويتحقّق منه**. السجلّ الذي لم تعد عمليته حيّة (أو صار الـ PID لعملية أخرى) يُحذف
|
|
28
|
+
* ويُعامَل كغير موجود، فلا يتراكم على القرص ولا يخدع أمرًا لاحقًا.
|
|
29
|
+
*/
|
|
30
|
+
export async function readVerifiedPidRecord(profile, service) {
|
|
31
|
+
const record = readPidRecord(profile, service);
|
|
32
|
+
if (!record)
|
|
33
|
+
return undefined;
|
|
34
|
+
if (await isRecordedProcessAlive(record))
|
|
35
|
+
return record;
|
|
36
|
+
removePidRecord(profile, service);
|
|
37
|
+
return undefined;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=pidfile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pidfile.js","sourceRoot":"","sources":["../../src/supervisor/pidfile.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACrF,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAmB/D,SAAS,UAAU,CAAC,OAAgB,EAAE,OAAoB;IACxD,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,OAAO,OAAO,CAAC,CAAC;AACjD,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,OAAgB,EAAE,MAAiB;IAChE,SAAS,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC/C,aAAa,CAAC,UAAU,CAAC,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;AAC9F,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,OAAgB,EAAE,OAAoB;IAClE,MAAM,IAAI,GAAG,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAC1C,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,SAAS,CAAC;IAExC,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAc,CAAC;IAC7D,CAAC;IAAC,MAAM,CAAC;QACP,+DAA+D;QAC/D,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,OAAgB,EAAE,OAAoB;IACpE,MAAM,CAAC,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;AACxD,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,OAAgB,EAChB,OAAoB;IAEpB,MAAM,MAAM,GAAG,aAAa,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAC/C,IAAI,CAAC,MAAM;QAAE,OAAO,SAAS,CAAC;IAE9B,IAAI,MAAM,sBAAsB,CAAC,MAAM,CAAC;QAAE,OAAO,MAAM,CAAC;IAExD,eAAe,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAClC,OAAO,SAAS,CAAC;AACnB,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export interface ProcessIdentity {
|
|
2
|
+
pid: number;
|
|
3
|
+
/** وقت بدء العملية بصيغة ISO. هو المميّز الحقيقي: رقم الـ PID وحده لا يميّز. */
|
|
4
|
+
startedAt: string;
|
|
5
|
+
commandLine: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* يقرأ هوية عملية حيّة. يُرجع undefined إذا لم تعد موجودة.
|
|
9
|
+
* على غير ويندوز لا نملك مصدرًا موحّدًا للهوية، فنكتفي بفحص الوجود ونعيد هوية فارغة الحقول.
|
|
10
|
+
*/
|
|
11
|
+
export declare function readProcessIdentity(pid: number): Promise<ProcessIdentity | undefined>;
|
|
12
|
+
/**
|
|
13
|
+
* هل العملية الحيّة هي نفسها التي سجّلناها؟
|
|
14
|
+
* وقت البدء هو الفيصل. غيابه (غير ويندوز) يجعلنا نكتفي بالوجود، وهو أضعف لكنه أفضل المتاح.
|
|
15
|
+
*/
|
|
16
|
+
export declare function identityMatches(recorded: Pick<ProcessIdentity, "startedAt" | "commandLine">, live: ProcessIdentity | undefined): boolean;
|
|
17
|
+
/** فحص مجمّع: هل الـ PID المسجَّل ما زال هو عمليتنا؟ */
|
|
18
|
+
export declare function isRecordedProcessAlive(record: Pick<ProcessIdentity, "pid" | "startedAt" | "commandLine">): Promise<boolean>;
|
|
19
|
+
//# sourceMappingURL=process-identity.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"process-identity.d.ts","sourceRoot":"","sources":["../../src/supervisor/process-identity.ts"],"names":[],"mappings":"AAUA,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,gFAAgF;IAChF,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;GAGG;AACH,wBAAsB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,SAAS,CAAC,CAkC3F;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,IAAI,CAAC,eAAe,EAAE,WAAW,GAAG,aAAa,CAAC,EAC5D,IAAI,EAAE,eAAe,GAAG,SAAS,GAChC,OAAO,CAIT;AAED,wDAAwD;AACxD,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,IAAI,CAAC,eAAe,EAAE,KAAK,GAAG,WAAW,GAAG,aAAa,CAAC,GACjE,OAAO,CAAC,OAAO,CAAC,CAGlB"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { execa } from "execa";
|
|
2
|
+
/**
|
|
3
|
+
* يقرأ هوية عملية حيّة. يُرجع undefined إذا لم تعد موجودة.
|
|
4
|
+
* على غير ويندوز لا نملك مصدرًا موحّدًا للهوية، فنكتفي بفحص الوجود ونعيد هوية فارغة الحقول.
|
|
5
|
+
*/
|
|
6
|
+
export async function readProcessIdentity(pid) {
|
|
7
|
+
if (process.platform !== "win32") {
|
|
8
|
+
try {
|
|
9
|
+
process.kill(pid, 0);
|
|
10
|
+
return { pid, startedAt: "", commandLine: "" };
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
return undefined;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
const script = `$p = Get-CimInstance Win32_Process -Filter "ProcessId=${pid}" -ErrorAction SilentlyContinue; if ($p) { "$($p.ProcessId)|$($p.CreationDate.ToString('o'))|$($p.CommandLine)" }`;
|
|
17
|
+
try {
|
|
18
|
+
const { stdout } = await execa("powershell.exe", ["-NoProfile", "-NonInteractive", "-Command", script], { timeout: 8_000, reject: false });
|
|
19
|
+
const line = stdout.trim();
|
|
20
|
+
if (!line)
|
|
21
|
+
return undefined;
|
|
22
|
+
// سطر الأمر نفسه قد يحوي |، فنقسم إلى ثلاثة أجزاء فقط ونضمّ الباقي إلى الأخير.
|
|
23
|
+
const parts = line.split("|");
|
|
24
|
+
const foundPid = Number(parts[0]);
|
|
25
|
+
const startedAt = parts[1] ?? "";
|
|
26
|
+
const commandLine = parts.slice(2).join("|");
|
|
27
|
+
if (!Number.isFinite(foundPid))
|
|
28
|
+
return undefined;
|
|
29
|
+
return { pid: foundPid, startedAt, commandLine };
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
return undefined;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* هل العملية الحيّة هي نفسها التي سجّلناها؟
|
|
37
|
+
* وقت البدء هو الفيصل. غيابه (غير ويندوز) يجعلنا نكتفي بالوجود، وهو أضعف لكنه أفضل المتاح.
|
|
38
|
+
*/
|
|
39
|
+
export function identityMatches(recorded, live) {
|
|
40
|
+
if (!live)
|
|
41
|
+
return false;
|
|
42
|
+
if (!recorded.startedAt || !live.startedAt)
|
|
43
|
+
return true;
|
|
44
|
+
return recorded.startedAt === live.startedAt;
|
|
45
|
+
}
|
|
46
|
+
/** فحص مجمّع: هل الـ PID المسجَّل ما زال هو عمليتنا؟ */
|
|
47
|
+
export async function isRecordedProcessAlive(record) {
|
|
48
|
+
const live = await readProcessIdentity(record.pid);
|
|
49
|
+
return identityMatches(record, live);
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=process-identity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"process-identity.js","sourceRoot":"","sources":["../../src/supervisor/process-identity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAiB9B;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,GAAW;IACnD,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QACjC,IAAI,CAAC;YACH,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;YACrB,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,EAAE,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC;QACjD,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,SAAS,CAAC;QACnB,CAAC;IACH,CAAC;IAED,MAAM,MAAM,GAAG,yDAAyD,GAAG,mHAAmH,CAAC;IAE/L,IAAI,CAAC;QACH,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,KAAK,CAC5B,gBAAgB,EAChB,CAAC,YAAY,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,CAAC,EACrD,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,CAClC,CAAC;QAEF,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;QAC3B,IAAI,CAAC,IAAI;YAAE,OAAO,SAAS,CAAC;QAE5B,iFAAiF;QACjF,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC9B,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QAClC,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QACjC,MAAM,WAAW,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAE7C,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC;YAAE,OAAO,SAAS,CAAC;QAEjD,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,SAAS,EAAE,WAAW,EAAE,CAAC;IACnD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAC7B,QAA4D,EAC5D,IAAiC;IAEjC,IAAI,CAAC,IAAI;QAAE,OAAO,KAAK,CAAC;IACxB,IAAI,CAAC,QAAQ,CAAC,SAAS,IAAI,CAAC,IAAI,CAAC,SAAS;QAAE,OAAO,IAAI,CAAC;IACxD,OAAO,QAAQ,CAAC,SAAS,KAAK,IAAI,CAAC,SAAS,CAAC;AAC/C,CAAC;AAED,wDAAwD;AACxD,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,MAAkE;IAElE,MAAM,IAAI,GAAG,MAAM,mBAAmB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACnD,OAAO,eAAe,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;AACvC,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { ServiceDefinition } from "../profiles/types.js";
|
|
2
|
+
export interface ReadinessOutcome {
|
|
3
|
+
ready: boolean;
|
|
4
|
+
reason?: string;
|
|
5
|
+
/** آخر أسطر السجلّ عند الفشل، للعرض. */
|
|
6
|
+
tail?: string[];
|
|
7
|
+
}
|
|
8
|
+
/** يقرأ آخر أسطر من سجلّ الخدمة. مصدر السبب حين تفشل الجاهزية. */
|
|
9
|
+
export declare function readLogTail(logDir: string, service: ServiceDefinition["name"], lines?: number): string[];
|
|
10
|
+
export interface WaitOptions {
|
|
11
|
+
logDir: string;
|
|
12
|
+
/** يُسأل بين المحاولات: إن ماتت العملية توقّفنا فورًا بدل انتظار المهلة كاملة. */
|
|
13
|
+
stillRunning?: () => Promise<boolean>;
|
|
14
|
+
onAttempt?: (elapsedMs: number) => void;
|
|
15
|
+
}
|
|
16
|
+
export declare function waitForReady(service: ServiceDefinition, options: WaitOptions): Promise<ReadinessOutcome>;
|
|
17
|
+
//# sourceMappingURL=readiness.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"readiness.d.ts","sourceRoot":"","sources":["../../src/supervisor/readiness.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAc9D,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,wCAAwC;IACxC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,kEAAkE;AAClE,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,iBAAiB,CAAC,MAAM,CAAC,EAAE,KAAK,SAAK,GAAG,MAAM,EAAE,CAYpG;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,kFAAkF;IAClF,YAAY,CAAC,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IACtC,SAAS,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;CACzC;AAED,wBAAsB,YAAY,CAChC,OAAO,EAAE,iBAAiB,EAC1B,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,gBAAgB,CAAC,CA2B3B"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { readFileSync, existsSync } from "node:fs";
|
|
2
|
+
import { probeService } from "../probes/service.probe.js";
|
|
3
|
+
import { logFilePath } from "../logs/sink.js";
|
|
4
|
+
// AR: انتظار الجاهزية. المبدأ: «أُطلقت» لا تعني «جاهزة» — NestJS يستغرق ثوانيَ حتى يستمع، وVite يبني
|
|
5
|
+
// الاعتماديات أول مرة. ولكل انتظار مهلة، وعند انتهائها نطبع آخر ما كتبته الخدمة **كسبب**، لأن
|
|
6
|
+
// سبينر يدور إلى الأبد هو أسوأ ما يمكن أن يفعله مشرف عمليات.
|
|
7
|
+
// EN: Readiness waiting. The principle: "spawned" is not "ready" — NestJS takes seconds to listen and
|
|
8
|
+
// Vite builds dependencies on first run. Every wait is bounded, and on expiry we print the
|
|
9
|
+
// service's last output **as the reason**, because a spinner that turns forever is the worst
|
|
10
|
+
// thing a supervisor can do.
|
|
11
|
+
const POLL_MS = 500;
|
|
12
|
+
/** يقرأ آخر أسطر من سجلّ الخدمة. مصدر السبب حين تفشل الجاهزية. */
|
|
13
|
+
export function readLogTail(logDir, service, lines = 20) {
|
|
14
|
+
const path = logFilePath(logDir, service);
|
|
15
|
+
if (!existsSync(path))
|
|
16
|
+
return [];
|
|
17
|
+
try {
|
|
18
|
+
return readFileSync(path, "utf8")
|
|
19
|
+
.split(/\r?\n/)
|
|
20
|
+
.filter((line) => line.trim().length > 0)
|
|
21
|
+
.slice(-lines);
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
return [];
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
export async function waitForReady(service, options) {
|
|
28
|
+
const started = Date.now();
|
|
29
|
+
const deadline = started + service.readyTimeoutMs;
|
|
30
|
+
for (;;) {
|
|
31
|
+
const probe = await probeService(service, 1_500);
|
|
32
|
+
if (probe.reachable)
|
|
33
|
+
return { ready: true };
|
|
34
|
+
if (options.stillRunning && !(await options.stillRunning())) {
|
|
35
|
+
return {
|
|
36
|
+
ready: false,
|
|
37
|
+
reason: "the process exited before it became ready",
|
|
38
|
+
tail: readLogTail(options.logDir, service.name),
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
if (Date.now() >= deadline) {
|
|
42
|
+
return {
|
|
43
|
+
ready: false,
|
|
44
|
+
reason: `not ready within ${Math.round(service.readyTimeoutMs / 1000)}s`,
|
|
45
|
+
tail: readLogTail(options.logDir, service.name),
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
options.onAttempt?.(Date.now() - started);
|
|
49
|
+
await new Promise((resolvePromise) => setTimeout(resolvePromise, POLL_MS));
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=readiness.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"readiness.js","sourceRoot":"","sources":["../../src/supervisor/readiness.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAEnD,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAE9C,qGAAqG;AACrG,kGAAkG;AAClG,iEAAiE;AACjE,sGAAsG;AACtG,+FAA+F;AAC/F,iGAAiG;AACjG,iCAAiC;AAEjC,MAAM,OAAO,GAAG,GAAG,CAAC;AASpB,kEAAkE;AAClE,MAAM,UAAU,WAAW,CAAC,MAAc,EAAE,OAAkC,EAAE,KAAK,GAAG,EAAE;IACxF,MAAM,IAAI,GAAG,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC1C,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,EAAE,CAAC;IAEjC,IAAI,CAAC;QACH,OAAO,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC;aAC9B,KAAK,CAAC,OAAO,CAAC;aACd,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;aACxC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC;IACnB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AASD,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,OAA0B,EAC1B,OAAoB;IAEpB,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC3B,MAAM,QAAQ,GAAG,OAAO,GAAG,OAAO,CAAC,cAAc,CAAC;IAElD,SAAS,CAAC;QACR,MAAM,KAAK,GAAG,MAAM,YAAY,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QACjD,IAAI,KAAK,CAAC,SAAS;YAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;QAE5C,IAAI,OAAO,CAAC,YAAY,IAAI,CAAC,CAAC,MAAM,OAAO,CAAC,YAAY,EAAE,CAAC,EAAE,CAAC;YAC5D,OAAO;gBACL,KAAK,EAAE,KAAK;gBACZ,MAAM,EAAE,2CAA2C;gBACnD,IAAI,EAAE,WAAW,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC;aAChD,CAAC;QACJ,CAAC;QAED,IAAI,IAAI,CAAC,GAAG,EAAE,IAAI,QAAQ,EAAE,CAAC;YAC3B,OAAO;gBACL,KAAK,EAAE,KAAK;gBACZ,MAAM,EAAE,oBAAoB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,GAAG;gBACxE,IAAI,EAAE,WAAW,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC;aAChD,CAAC;QACJ,CAAC;QAED,OAAO,CAAC,SAAS,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC,CAAC;QAC1C,MAAM,IAAI,OAAO,CAAC,CAAC,cAAc,EAAE,EAAE,CAAC,UAAU,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC,CAAC;IAC7E,CAAC;AACH,CAAC"}
|