@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,37 @@
|
|
|
1
|
+
import type { RestartRequestFile, RestartScope } from "../contracts/core.js";
|
|
2
|
+
import type { Profile, ServiceName } from "../profiles/types.js";
|
|
3
|
+
/**
|
|
4
|
+
* AR: يترجم نطاقًا إلى الخدمات التي يشملها، أو undefined ليعني «كلّ ما في ملفّ التشغيل بترتيبه».
|
|
5
|
+
* **القائمة الشاملة لا تُكتب يدويًا**: الجهاز خدمتان والمستودع ثلاث، وقائمةٌ ثابتة هنا كانت
|
|
6
|
+
* ستحاول إعادة تشغيل واجهةٍ لا وجود لها على الجهاز فتُبلّغ فشلًا كاذبًا.
|
|
7
|
+
* EN: Translates a scope into the services it covers, or `undefined` meaning "everything in the
|
|
8
|
+
* profile, in its order". **The catch-all list is not written by hand**: the appliance has two
|
|
9
|
+
* services and the repository three, and a fixed list here would try to restart a portal that
|
|
10
|
+
* does not exist on the appliance and report a false failure.
|
|
11
|
+
*/
|
|
12
|
+
export declare function servicesForScope(scope: RestartScope): ServiceName[] | undefined;
|
|
13
|
+
export interface RestartExecution {
|
|
14
|
+
scope: RestartScope;
|
|
15
|
+
reason: RestartRequestFile["reason"];
|
|
16
|
+
ok: boolean;
|
|
17
|
+
detail: string;
|
|
18
|
+
}
|
|
19
|
+
export interface ConsumeOptions {
|
|
20
|
+
/**
|
|
21
|
+
* AR: يُسأل قبل التنفيذ حين يطلب الطلب تأجيلًا (force:false وجدولٌ يحترم المشاهدين). يعيد
|
|
22
|
+
* سببًا عربيًّا للتأجيل، أو null للمضيّ. المشرف لا يعرف من يشاهد — النواة تعرف — فيُحقن.
|
|
23
|
+
* EN: Asked before executing when the request permits deferral (`force:false` on a schedule that
|
|
24
|
+
* respects viewers). Returns an Arabic reason to defer, or `null` to proceed. The supervisor
|
|
25
|
+
* does not know who is watching — the core does — so it is injected.
|
|
26
|
+
*/
|
|
27
|
+
deferIf?: () => Promise<string | null>;
|
|
28
|
+
onEvent?: (message: string) => void;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* AR: يستهلك الطلب المعلّق إن وُجد وينفّذه. يعيد null حين لا طلب — وهي الحالة الغالبة في كل جولة.
|
|
32
|
+
* EN: Consumes the pending request if there is one and executes it. Returns `null` when there is no
|
|
33
|
+
* request — which is the usual case on every round.
|
|
34
|
+
*/
|
|
35
|
+
export declare function consumeRestartRequest(profile: Profile, options?: ConsumeOptions): Promise<RestartExecution | null>;
|
|
36
|
+
export declare function executeRestart(profile: Profile, request: RestartRequestFile, options?: ConsumeOptions): Promise<RestartExecution>;
|
|
37
|
+
//# sourceMappingURL=restart-consumer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"restart-consumer.d.ts","sourceRoot":"","sources":["../../src/supervisor/restart-consumer.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAsB,kBAAkB,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACjG,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AA+BjE;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,YAAY,GAAG,WAAW,EAAE,GAAG,SAAS,CAG/E;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,YAAY,CAAC;IACpB,MAAM,EAAE,kBAAkB,CAAC,QAAQ,CAAC,CAAC;IACrC,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,cAAc;IAC7B;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACvC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACrC;AAED;;;;GAIG;AACH,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,OAAO,EAChB,OAAO,GAAE,cAAmB,GAC3B,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAKlC;AAED,wBAAsB,cAAc,CAClC,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,kBAAkB,EAC3B,OAAO,GAAE,cAAmB,GAC3B,OAAO,CAAC,gBAAgB,CAAC,CA4B3B"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { execa } from "execa";
|
|
2
|
+
import { restartServices } from "./orchestrator.js";
|
|
3
|
+
import { REMOTE_STATE_FILES, takeStateJson, writeStateJson } from "./state-files.js";
|
|
4
|
+
// AR: تنفيذ طلب إعادة التشغيل (٠٢٠/US1، US2).
|
|
5
|
+
//
|
|
6
|
+
// **هنا وحده يقع الفعل.** النواة تكتب طلبًا، وهذا الملف — الذي يعيش في عملية تنجو من موتها —
|
|
7
|
+
// ينفّذه. الاتجاه مقصود ولا يُعكَس: النواة لا تملك spawn ولا taskkill ولا shutdown
|
|
8
|
+
// (يحرسه core-never-restarts-itself.spec.ts).
|
|
9
|
+
//
|
|
10
|
+
// **والنتيجة تُكتب بعد التنفيذ لا قبله.** «آخر إعادة تشغيل» في لوحة المالك يجب أن تعني «وقعت»
|
|
11
|
+
// لا «طُلبت»: طلبٌ فشل تنفيذه ثم عُرض كنجاح هو أسوأ من غياب السطر أصلًا، لأنه يغلق التحقيق.
|
|
12
|
+
//
|
|
13
|
+
// **وmachine حالة خاصة تُكتَب نتيجتها قبل الأمر.** بعد shutdown /r لا يبقى شيء ليكتب:
|
|
14
|
+
// العملية تموت مع الآلة. فتُكتب أولًا، وتُصحَّح ضمنًا إن فشل الأمر (نبقى أحياء فنكتب الفشل).
|
|
15
|
+
//
|
|
16
|
+
// EN: Executing a restart request (020/US1, US2).
|
|
17
|
+
//
|
|
18
|
+
// **This is the only place the act happens.** The core writes a request, and this file — living
|
|
19
|
+
// in a process that outlives it — carries it out. The direction is deliberate and never
|
|
20
|
+
// reversed: the core holds no `spawn`, no `taskkill` and no `shutdown` (guarded by
|
|
21
|
+
// `core-never-restarts-itself.spec.ts`).
|
|
22
|
+
//
|
|
23
|
+
// **And the outcome is written after the act, not before.** "Last restart" in the owner's panel
|
|
24
|
+
// must mean "it happened", not "it was asked for": a request that failed and was then shown as a
|
|
25
|
+
// success is worse than no line at all, because it closes the investigation.
|
|
26
|
+
//
|
|
27
|
+
// **`machine` is the one case whose outcome is written first.** After `shutdown /r` there is
|
|
28
|
+
// nothing left to write with: the process dies with the machine. So it is written first, and
|
|
29
|
+
// implicitly corrected if the command fails (we are still alive, so we write the failure).
|
|
30
|
+
/**
|
|
31
|
+
* AR: يترجم نطاقًا إلى الخدمات التي يشملها، أو undefined ليعني «كلّ ما في ملفّ التشغيل بترتيبه».
|
|
32
|
+
* **القائمة الشاملة لا تُكتب يدويًا**: الجهاز خدمتان والمستودع ثلاث، وقائمةٌ ثابتة هنا كانت
|
|
33
|
+
* ستحاول إعادة تشغيل واجهةٍ لا وجود لها على الجهاز فتُبلّغ فشلًا كاذبًا.
|
|
34
|
+
* EN: Translates a scope into the services it covers, or `undefined` meaning "everything in the
|
|
35
|
+
* profile, in its order". **The catch-all list is not written by hand**: the appliance has two
|
|
36
|
+
* services and the repository three, and a fixed list here would try to restart a portal that
|
|
37
|
+
* does not exist on the appliance and report a false failure.
|
|
38
|
+
*/
|
|
39
|
+
export function servicesForScope(scope) {
|
|
40
|
+
if (scope === "machine" || scope === "services")
|
|
41
|
+
return undefined;
|
|
42
|
+
return [scope];
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* AR: يستهلك الطلب المعلّق إن وُجد وينفّذه. يعيد null حين لا طلب — وهي الحالة الغالبة في كل جولة.
|
|
46
|
+
* EN: Consumes the pending request if there is one and executes it. Returns `null` when there is no
|
|
47
|
+
* request — which is the usual case on every round.
|
|
48
|
+
*/
|
|
49
|
+
export async function consumeRestartRequest(profile, options = {}) {
|
|
50
|
+
const request = takeStateJson(profile, REMOTE_STATE_FILES.restartRequest);
|
|
51
|
+
if (!request)
|
|
52
|
+
return null;
|
|
53
|
+
return executeRestart(profile, request, options);
|
|
54
|
+
}
|
|
55
|
+
export async function executeRestart(profile, request, options = {}) {
|
|
56
|
+
if (!request.force && options.deferIf) {
|
|
57
|
+
const reason = await options.deferIf();
|
|
58
|
+
if (reason) {
|
|
59
|
+
// AR: **يُعاد كتابة الطلب** لا يُهمَل: التأجيل يعني «لاحقًا» لا «أُلغي». وإسقاطه هنا كان
|
|
60
|
+
// سيجعل جدولًا يوميًّا يفقد جولته كاملة لأن ضيفًا شاهد دقيقتين.
|
|
61
|
+
// EN: **The request is written back** rather than dropped: a deferral means "later", not
|
|
62
|
+
// "cancelled". Dropping it here would make a daily schedule lose its whole round because
|
|
63
|
+
// one guest watched for two minutes.
|
|
64
|
+
writeStateJson(profile, REMOTE_STATE_FILES.restartRequest, request);
|
|
65
|
+
options.onEvent?.(`deferred (${reason})`);
|
|
66
|
+
return { scope: request.scope, reason: request.reason, ok: false, detail: `deferred — ${reason}` };
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
if (request.scope === "machine")
|
|
70
|
+
return restartMachine(profile, request, options);
|
|
71
|
+
const { started } = await restartServices(profile, { only: servicesForScope(request.scope) });
|
|
72
|
+
const ok = started.ok;
|
|
73
|
+
const detail = ok
|
|
74
|
+
? `restarted ${request.scope}`
|
|
75
|
+
: `failed to restart ${request.scope}: ${started.steps.find((step) => step.status === "failed")?.readiness?.reason ?? "unknown reason"}`;
|
|
76
|
+
if (ok)
|
|
77
|
+
recordOutcome(profile, request);
|
|
78
|
+
options.onEvent?.(detail);
|
|
79
|
+
return { scope: request.scope, reason: request.reason, ok, detail };
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* AR: يعيد تشغيل الآلة. **الأمر الوحيد في المستودع كلّه الذي يُطفئ عتادًا**، ولذلك يعيش هنا وحده
|
|
83
|
+
* وخلف بوّابتين سبقتاه: النواة رفضت الطلب أصلًا ما لم تكن مهمة الإقلاع مسجَّلة، والواجهة عطّلت
|
|
84
|
+
* الزرّ بالسبب نفسه. المهلة عشر ثوانٍ تعطي الخدمات فرصة الإغلاق النظيف قبل أن يقطع ويندوز.
|
|
85
|
+
* EN: Restarts the machine. **The only command in the whole repository that powers hardware down**,
|
|
86
|
+
* which is why it lives here alone and behind two gates that came before it: the core refused
|
|
87
|
+
* the request unless a boot task is registered, and the portal disabled the button for the same
|
|
88
|
+
* reason. The ten-second delay gives the services a chance to close cleanly before Windows cuts
|
|
89
|
+
* them off.
|
|
90
|
+
*/
|
|
91
|
+
async function restartMachine(profile, request, options) {
|
|
92
|
+
if (process.platform !== "win32") {
|
|
93
|
+
const detail = "a machine restart is only supported on Windows";
|
|
94
|
+
options.onEvent?.(detail);
|
|
95
|
+
return { scope: request.scope, reason: request.reason, ok: false, detail };
|
|
96
|
+
}
|
|
97
|
+
// تُكتب قبل الأمر: بعده لا تبقى عملية تكتب. وإن فشل الأمر بقينا أحياء فصحّحنا السطر بأنفسنا.
|
|
98
|
+
recordOutcome(profile, request);
|
|
99
|
+
try {
|
|
100
|
+
await execa("shutdown", ["/r", "/t", "10", "/c", "Fantastic scheduled restart"], { windowsHide: true });
|
|
101
|
+
options.onEvent?.("the machine restarts in 10 seconds");
|
|
102
|
+
return { scope: request.scope, reason: request.reason, ok: true, detail: "machine restart requested" };
|
|
103
|
+
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
const detail = `the machine restart was refused: ${error instanceof Error ? error.message : String(error)}`;
|
|
106
|
+
options.onEvent?.(detail);
|
|
107
|
+
return { scope: request.scope, reason: request.reason, ok: false, detail };
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
/** يكتب ما وقع فعلًا. تقرؤه النواة لتعرض «آخر إعادة تشغيل» بلا أن تفترضها عن نفسها. */
|
|
111
|
+
function recordOutcome(profile, request) {
|
|
112
|
+
const outcome = {
|
|
113
|
+
at: new Date().toISOString(),
|
|
114
|
+
scope: request.scope,
|
|
115
|
+
reason: request.reason,
|
|
116
|
+
};
|
|
117
|
+
writeStateJson(profile, REMOTE_STATE_FILES.restartOutcome, outcome);
|
|
118
|
+
}
|
|
119
|
+
//# sourceMappingURL=restart-consumer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"restart-consumer.js","sourceRoot":"","sources":["../../src/supervisor/restart-consumer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/supervisor/runner.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { StringDecoder } from "node:string_decoder";
|
|
3
|
+
import stripAnsi from "strip-ansi";
|
|
4
|
+
import { LAUNCH_PAYLOAD_ENV, resolveInvocation } from "./invocation.js";
|
|
5
|
+
// AR: المشرف الصغير الذي يقف بين الـ CLI والخدمة. عملية واحدة لكل خدمة، لا تفعل شيئًا سوى إطلاقها
|
|
6
|
+
// وتمرير مخرجها إلى ملف السجلّ ثم الموت معها.
|
|
7
|
+
//
|
|
8
|
+
// **لماذا يوجد أصلًا؟ مقياس على ويندوز، لا تجميل.** كان الـ CLI يُطلق كل خدمة بـ detached،
|
|
9
|
+
// ومعناها على ويندوز DETACHED_PROCESS: عملية **بلا كونسول**. وnpm run يشغّل سكربت الحزمة عبر
|
|
10
|
+
// cmd.exe، وتطبيق كونسول يولده أبٌ بلا كونسول يحصل على **كونسول جديد بنافذة مرئية**. فكانت
|
|
11
|
+
// ثلاث نوافذ سوداء تفتح مع كل fantastic start — ولأن النافذة تملك الكونسول، إغلاق أيّ منها
|
|
12
|
+
// يرسل CTRL_CLOSE_EVENT إلى كل ما هو موصول به، فتموت الخدمة كلها بسحبة فأرة.
|
|
13
|
+
//
|
|
14
|
+
// المخرج الوحيد الذي يتيحه Node: windowsHide يترجَم إلى CREATE_NO_WINDOW، وهذا العَلَم يعطي
|
|
15
|
+
// العملية **كونسولًا بلا نافذة** حين يكون أبوها بلا كونسول — وترثه كل ذريّتها، بما فيها
|
|
16
|
+
// cmd.exe. لكن libuv يتجاهل العَلَم إذا كان أيّ من الأنابيب واصفَ ملف موروثًا، وDETACHED_PROCESS
|
|
17
|
+
// يتقدّم عليه أصلًا. فلا سبيل إلى الجمع بين «ينجو من إغلاق الطرفية» و«بلا نافذة» في إطلاق واحد.
|
|
18
|
+
//
|
|
19
|
+
// فالإطلاق طبقتان: الـ CLI يُطلق **هذا الملف** منفصلًا (بلا كونسول، ينجو)، وهذا الملف يُطلق
|
|
20
|
+
// الخدمة بأنابيب وwindowsHide (كونسول بلا نافذة، ترثه الذرّية). قِيس: صفر نوافذ، والشجرة كاملة
|
|
21
|
+
// تبقى حيّة بعد إغلاق نافذة الإطلاق.
|
|
22
|
+
// EN: The small supervisor that sits between the CLI and a service. One process per service, doing
|
|
23
|
+
// nothing but launching it, forwarding its output to the log file, and dying with it.
|
|
24
|
+
//
|
|
25
|
+
// **Why it exists at all — measured on Windows, not decoration.** The CLI used to launch each
|
|
26
|
+
// service `detached`, which on Windows means DETACHED_PROCESS: a process with **no console**.
|
|
27
|
+
// `npm run` runs the package script through cmd.exe, and a console application spawned by a
|
|
28
|
+
// console-less parent gets a **brand-new console with a visible window**. So three black windows
|
|
29
|
+
// opened on every `fantastic start` — and because the window owns the console, closing any one of
|
|
30
|
+
// them sends CTRL_CLOSE_EVENT to everything attached to it, killing the whole service with a
|
|
31
|
+
// mouse click.
|
|
32
|
+
//
|
|
33
|
+
// The only lever Node exposes: `windowsHide` maps to CREATE_NO_WINDOW, and that flag gives a
|
|
34
|
+
// process **a console with no window** when its parent has no console — which its entire
|
|
35
|
+
// descendancy inherits, cmd.exe included. But libuv skips the flag if any stdio entry is an
|
|
36
|
+
// inherited file descriptor, and DETACHED_PROCESS overrides it regardless. So "survives the
|
|
37
|
+
// terminal closing" and "draws no window" cannot be had in a single spawn.
|
|
38
|
+
//
|
|
39
|
+
// Hence two layers: the CLI launches **this file** detached (no console, survives), and this file
|
|
40
|
+
// launches the service with pipes and `windowsHide` (windowless console, inherited by the tree).
|
|
41
|
+
// Measured: zero windows, and the whole tree stays alive after the launching window closes.
|
|
42
|
+
/** يكتب سطرًا إلى ملف السجلّ. مخرَجنا القياسي **هو** واصف ملف السجلّ، ورّثه إيّانا الـ CLI. */
|
|
43
|
+
function write(line) {
|
|
44
|
+
process.stdout.write(`${line}\n`);
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* يجمّع القطع في أسطر كاملة قبل الكتابة. الأنبوب يقطع حيث شاء، وسطر سجلّ منقطع في منتصفه غير قابل
|
|
48
|
+
* للبحث. ويُجرَّد من ANSI هنا: هذه الطبقة هي أول موضع في التاريخ يمكنه ذلك — الإطلاق المباشر إلى
|
|
49
|
+
* واصف ملف لم يكن يمرّ بأحد.
|
|
50
|
+
*
|
|
51
|
+
* StringDecoder لا chunk.toString(): سجلات النواة عربية، والحرف العربي بايتان في UTF-8. والأنبوب
|
|
52
|
+
* يقطع عند حدّ البايت لا حدّ الحرف، فحرف يقع نصفه في قطعة ونصفه في التالية يخرج من toString
|
|
53
|
+
* علامتَي استفهام لا يعيدهما شيء. المفكّك يحتفظ بالبايتات المعلّقة حتى يكتمل الحرف.
|
|
54
|
+
*/
|
|
55
|
+
function createLineWriter() {
|
|
56
|
+
const decoder = new StringDecoder("utf8");
|
|
57
|
+
let pending = "";
|
|
58
|
+
return {
|
|
59
|
+
push(chunk) {
|
|
60
|
+
pending += decoder.write(chunk);
|
|
61
|
+
const lines = pending.split(/\r?\n/);
|
|
62
|
+
pending = lines.pop() ?? "";
|
|
63
|
+
for (const line of lines)
|
|
64
|
+
write(stripAnsi(line));
|
|
65
|
+
},
|
|
66
|
+
flush() {
|
|
67
|
+
pending += decoder.end();
|
|
68
|
+
if (pending.trim().length > 0)
|
|
69
|
+
write(stripAnsi(pending));
|
|
70
|
+
pending = "";
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
function readPayload() {
|
|
75
|
+
const raw = process.env[LAUNCH_PAYLOAD_ENV];
|
|
76
|
+
if (!raw)
|
|
77
|
+
throw new Error(`${LAUNCH_PAYLOAD_ENV} is missing — this entry is launched by the CLI, not by hand.`);
|
|
78
|
+
return JSON.parse(raw);
|
|
79
|
+
}
|
|
80
|
+
function main() {
|
|
81
|
+
const payload = readPayload();
|
|
82
|
+
// تُحذف من نسختنا فلا تتسرّب إلى بيئة الخدمة ولا إلى أي عملية تحتها.
|
|
83
|
+
delete process.env[LAUNCH_PAYLOAD_ENV];
|
|
84
|
+
const { file, argv } = resolveInvocation(payload.command, payload.args);
|
|
85
|
+
const child = spawn(file, argv, {
|
|
86
|
+
cwd: payload.cwd,
|
|
87
|
+
// NO_COLOR احتياطًا: الأدوات تُعطّل التلوين خارج الطرفية، لكن سجلًّا ملوّثًا بـ ANSI لا يُبحث فيه.
|
|
88
|
+
env: { ...process.env, ...payload.env, NO_COLOR: "1" },
|
|
89
|
+
// أنابيب لا واصفات موروثة: هذا بالضبط شرط libuv لتمرير CREATE_NO_WINDOW. لا خطر من امتلاء
|
|
90
|
+
// الأنبوب لأننا نحيا ما دامت الخدمة تحيا فنستنزفه دائمًا.
|
|
91
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
92
|
+
windowsHide: true,
|
|
93
|
+
});
|
|
94
|
+
write(`--- ${payload.label} started (runner ${process.pid}, service ${child.pid ?? "?"}) ---`);
|
|
95
|
+
const writer = createLineWriter();
|
|
96
|
+
child.stdout?.on("data", writer.push);
|
|
97
|
+
child.stderr?.on("data", writer.push);
|
|
98
|
+
child.on("error", (error) => {
|
|
99
|
+
writer.flush();
|
|
100
|
+
write(`--- ${payload.label} failed to launch: ${error.message} ---`);
|
|
101
|
+
process.exit(1);
|
|
102
|
+
});
|
|
103
|
+
// نموت مع الخدمة. لازم لا مستحبّ: سجلّ العملية يحمل رقمنا نحن، فلو بقينا حيّين بعد موتها لقال
|
|
104
|
+
// status إنها تعمل وهي ميتة.
|
|
105
|
+
child.on("exit", (code, signal) => {
|
|
106
|
+
writer.flush();
|
|
107
|
+
write(`--- ${payload.label} exited (code ${code ?? "—"}, signal ${signal ?? "—"}) ---`);
|
|
108
|
+
process.exit(code ?? 1);
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
try {
|
|
112
|
+
main();
|
|
113
|
+
}
|
|
114
|
+
catch (error) {
|
|
115
|
+
write(`--- runner aborted: ${error instanceof Error ? error.message : String(error)} ---`);
|
|
116
|
+
process.exit(1);
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.js","sourceRoot":"","sources":["../../src/supervisor/runner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { RestartOutcomeFile, RestartScheduleFile } from "../contracts/core.js";
|
|
2
|
+
import type { Profile } from "../profiles/types.js";
|
|
3
|
+
import { type ConsumeOptions, type RestartExecution } from "./restart-consumer.js";
|
|
4
|
+
/** بين محاولتين بعد تأجيل. ربع ساعة: أقصر منها يزعج، وأطول منها يفوّت نافذة هدوء قصيرة. */
|
|
5
|
+
export declare const DEFER_RETRY_MS: number;
|
|
6
|
+
/** أقصى ما نؤجّل قبل التخلّي عن الجولة. */
|
|
7
|
+
export declare const DEFER_CEILING_MS: number;
|
|
8
|
+
/**
|
|
9
|
+
* AR: موعد الجولة التالية بالمللي ثانية، أو null حين لا جدول. **دالّة خالصة**: الزمن يُمرَّر،
|
|
10
|
+
* فتُختبَر سنةٌ من الجداول في مللي ثانية.
|
|
11
|
+
* EN: When the next round is due in milliseconds, or `null` when nothing is scheduled. **A pure
|
|
12
|
+
* function**: time is passed in, so a year of schedules is tested in a millisecond.
|
|
13
|
+
*/
|
|
14
|
+
export declare function dueAt(schedule: RestartScheduleFile, lastRestartAt: string | null, now: number): number | null;
|
|
15
|
+
export interface ScheduleTimerOptions extends ConsumeOptions {
|
|
16
|
+
/** يُحقَن في الاختبار. الافتراض: قراءة المرآة من مجلد الحالة. */
|
|
17
|
+
readSchedule?: () => RestartScheduleFile | null;
|
|
18
|
+
readLastRestart?: () => RestartOutcomeFile | null;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* AR: يقرّر في كل جولة: أحان الموعد؟ وهل نؤجّل؟ وهل بلغنا السقف؟ لا مؤقّت داخله ولا ساعة: الزمن
|
|
22
|
+
* يُمرَّر من الخارج، فهذه الحلقة كلّها قابلة للاختبار بلا انتظار ثانية واحدة.
|
|
23
|
+
* EN: Decides on each round: is it due? should it defer? has it hit the ceiling? It holds no timer
|
|
24
|
+
* and no clock: time comes in from outside, so this whole loop is testable without waiting a
|
|
25
|
+
* single second.
|
|
26
|
+
*/
|
|
27
|
+
export declare class ScheduleTimer {
|
|
28
|
+
private readonly profile;
|
|
29
|
+
private readonly options;
|
|
30
|
+
/** متى بدأ التأجيل الحالي، أو null حين لا تأجيل جارٍ. */
|
|
31
|
+
private deferringSince;
|
|
32
|
+
private nextAttemptAt;
|
|
33
|
+
constructor(profile: Profile, options?: ScheduleTimerOptions);
|
|
34
|
+
round(now?: number): Promise<RestartExecution | null>;
|
|
35
|
+
private readSchedule;
|
|
36
|
+
private readLastRestart;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=schedule-timer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schedule-timer.d.ts","sourceRoot":"","sources":["../../src/supervisor/schedule-timer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAsB,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AACxG,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAEpD,OAAO,EAAkB,KAAK,cAAc,EAAE,KAAK,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AA+CnG,2FAA2F;AAC3F,eAAO,MAAM,cAAc,QAAc,CAAC;AAE1C,2CAA2C;AAC3C,eAAO,MAAM,gBAAgB,QAAgB,CAAC;AAE9C;;;;;GAKG;AACH,wBAAgB,KAAK,CAAC,QAAQ,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,GAAG,IAAI,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAiB7G;AAED,MAAM,WAAW,oBAAqB,SAAQ,cAAc;IAC1D,iEAAiE;IACjE,YAAY,CAAC,EAAE,MAAM,mBAAmB,GAAG,IAAI,CAAC;IAChD,eAAe,CAAC,EAAE,MAAM,kBAAkB,GAAG,IAAI,CAAC;CACnD;AAED;;;;;;GAMG;AACH,qBAAa,aAAa;IAMtB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAN1B,2DAA2D;IAC3D,OAAO,CAAC,cAAc,CAAuB;IAC7C,OAAO,CAAC,aAAa,CAAK;gBAGP,OAAO,EAAE,OAAO,EAChB,OAAO,GAAE,oBAAyB;IAG/C,KAAK,CAAC,GAAG,GAAE,MAAmB,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAsDvE,OAAO,CAAC,YAAY;IAKpB,OAAO,CAAC,eAAe;CAIxB"}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { REMOTE_STATE_FILES, readStateJson } from "./state-files.js";
|
|
2
|
+
import { executeRestart } from "./restart-consumer.js";
|
|
3
|
+
// AR: المؤقّت الدوريّ (٠٢٠/US2).
|
|
4
|
+
//
|
|
5
|
+
// **لماذا يعيش المؤقّت في المشرف لا في النواة؟** لأن الجدول وُضع أصلًا لعلاج التعليق، ومؤقّتٌ
|
|
6
|
+
// داخل النواة يتعلّق معها — أي يفشل في اللحظة الوحيدة التي بُني لها. المشرف يقرأ مرآة الجدول
|
|
7
|
+
// من مجلد الحالة (restart.schedule.json) بلا أن يفتح قاعدة البيانات، وهي قاعدة قائمة في
|
|
8
|
+
// المستودع لا استثناء لها.
|
|
9
|
+
//
|
|
10
|
+
// **والمرساة هي آخر إعادة تشغيل وقعت، لا لحظة الحفظ.** بدونها يعيد كل حفظ ضبطَ العدّاد، فجهازٌ
|
|
11
|
+
// يُعدَّل جدوله كل يوم لا يُعاد تشغيله أبدًا — عطبٌ صامت تمامًا: الإعداد مفعّل، والزمن يمرّ،
|
|
12
|
+
// ولا شيء يقع. وهي المرساة نفسها التي تحسب بها النواة nextRestartAt، فلا تتباعد اللوحة عن
|
|
13
|
+
// الفعل.
|
|
14
|
+
//
|
|
15
|
+
// **والتأجيل له سقف.** «لا نقطع أحدًا» قاعدة، لكن جهازًا في استراحة ممتلئة قد لا يخلو ست ساعات
|
|
16
|
+
// متّصلة، وجدولٌ يؤجّل إلى الأبد هو جدولٌ لا وجود له. عند السقف **نتخلّى عن الجولة** ولا نقطع:
|
|
17
|
+
// تفويت صيانة أهون من قطع فيلم على ضيف — والجولة التالية تأتي في موعدها.
|
|
18
|
+
//
|
|
19
|
+
// EN: The periodic timer (020/US2).
|
|
20
|
+
//
|
|
21
|
+
// **Why does the timer live in the supervisor rather than the core?** Because the schedule
|
|
22
|
+
// exists to cure hangs, and a timer inside the core hangs with it — failing at the one moment it
|
|
23
|
+
// was built for. The supervisor reads the schedule's mirror from the state dir
|
|
24
|
+
// (`restart.schedule.json`) without opening the database, which is a standing repository rule
|
|
25
|
+
// with no exception.
|
|
26
|
+
//
|
|
27
|
+
// **And the anchor is the last restart that actually happened, not the moment of saving.**
|
|
28
|
+
// Without that every save resets the counter, so an appliance whose schedule is edited daily is
|
|
29
|
+
// never restarted at all — a perfectly silent defect: the setting is on, time passes, and
|
|
30
|
+
// nothing happens. It is the same anchor the core uses to compute `nextRestartAt`, so the panel
|
|
31
|
+
// and the act never drift apart.
|
|
32
|
+
//
|
|
33
|
+
// **And deferral has a ceiling.** "Cut nobody off" is a rule, but an appliance in a full
|
|
34
|
+
// rest-house may not go quiet for six straight hours, and a schedule that defers forever is a
|
|
35
|
+
// schedule that does not exist. At the ceiling **we abandon the round** rather than cut: missing
|
|
36
|
+
// one maintenance window is a smaller harm than cutting a guest's film — and the next round
|
|
37
|
+
// arrives on time.
|
|
38
|
+
const HOURS = {
|
|
39
|
+
"2h": 2,
|
|
40
|
+
"4h": 4,
|
|
41
|
+
"6h": 6,
|
|
42
|
+
"12h": 12,
|
|
43
|
+
"24h": 24,
|
|
44
|
+
weekly: 24 * 7,
|
|
45
|
+
};
|
|
46
|
+
/** بين محاولتين بعد تأجيل. ربع ساعة: أقصر منها يزعج، وأطول منها يفوّت نافذة هدوء قصيرة. */
|
|
47
|
+
export const DEFER_RETRY_MS = 15 * 60_000;
|
|
48
|
+
/** أقصى ما نؤجّل قبل التخلّي عن الجولة. */
|
|
49
|
+
export const DEFER_CEILING_MS = 6 * 3_600_000;
|
|
50
|
+
/**
|
|
51
|
+
* AR: موعد الجولة التالية بالمللي ثانية، أو null حين لا جدول. **دالّة خالصة**: الزمن يُمرَّر،
|
|
52
|
+
* فتُختبَر سنةٌ من الجداول في مللي ثانية.
|
|
53
|
+
* EN: When the next round is due in milliseconds, or `null` when nothing is scheduled. **A pure
|
|
54
|
+
* function**: time is passed in, so a year of schedules is tested in a millisecond.
|
|
55
|
+
*/
|
|
56
|
+
export function dueAt(schedule, lastRestartAt, now) {
|
|
57
|
+
if (!schedule.autoEnabled)
|
|
58
|
+
return null;
|
|
59
|
+
const hours = HOURS[schedule.every];
|
|
60
|
+
const parsed = lastRestartAt ? Date.parse(lastRestartAt) : Number.NaN;
|
|
61
|
+
const anchor = Number.isFinite(parsed) ? parsed : now;
|
|
62
|
+
const due = new Date(anchor + hours * 3_600_000);
|
|
63
|
+
// الساعة المفضّلة للجداول اليومية فأطول وحدها: تثبيت جدول كل ساعتين على الرابعة يحوّله جدولًا
|
|
64
|
+
// يوميًّا بصمت — إعدادٌ يُقبَل ويعني غير ما يقول.
|
|
65
|
+
if (schedule.atHour !== null && hours >= 24) {
|
|
66
|
+
due.setHours(schedule.atHour, 0, 0, 0);
|
|
67
|
+
if (due.getTime() <= now)
|
|
68
|
+
due.setDate(due.getDate() + 1);
|
|
69
|
+
}
|
|
70
|
+
return due.getTime();
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* AR: يقرّر في كل جولة: أحان الموعد؟ وهل نؤجّل؟ وهل بلغنا السقف؟ لا مؤقّت داخله ولا ساعة: الزمن
|
|
74
|
+
* يُمرَّر من الخارج، فهذه الحلقة كلّها قابلة للاختبار بلا انتظار ثانية واحدة.
|
|
75
|
+
* EN: Decides on each round: is it due? should it defer? has it hit the ceiling? It holds no timer
|
|
76
|
+
* and no clock: time comes in from outside, so this whole loop is testable without waiting a
|
|
77
|
+
* single second.
|
|
78
|
+
*/
|
|
79
|
+
export class ScheduleTimer {
|
|
80
|
+
profile;
|
|
81
|
+
options;
|
|
82
|
+
/** متى بدأ التأجيل الحالي، أو null حين لا تأجيل جارٍ. */
|
|
83
|
+
deferringSince = null;
|
|
84
|
+
nextAttemptAt = 0;
|
|
85
|
+
constructor(profile, options = {}) {
|
|
86
|
+
this.profile = profile;
|
|
87
|
+
this.options = options;
|
|
88
|
+
}
|
|
89
|
+
async round(now = Date.now()) {
|
|
90
|
+
const schedule = this.readSchedule();
|
|
91
|
+
if (!schedule?.autoEnabled) {
|
|
92
|
+
this.deferringSince = null;
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
if (now < this.nextAttemptAt)
|
|
96
|
+
return null;
|
|
97
|
+
const last = this.readLastRestart();
|
|
98
|
+
const due = dueAt(schedule, last?.at ?? null, now);
|
|
99
|
+
if (due === null || now < due)
|
|
100
|
+
return null;
|
|
101
|
+
if (this.deferringSince !== null && now - this.deferringSince >= DEFER_CEILING_MS) {
|
|
102
|
+
// AR: بلغنا السقف. **نتخلّى ولا نقطع**، ونحرّك المرساة إلى الآن فلا نعيد المحاولة فورًا
|
|
103
|
+
// في الجولة التالية — وإلّا صار «التخلّي» حلقةً محمومة كل ثانية.
|
|
104
|
+
// EN: The ceiling is reached. **We abandon rather than cut**, and move the anchor to now so we
|
|
105
|
+
// do not retry immediately on the next round — otherwise "abandoning" becomes a hot loop
|
|
106
|
+
// every second.
|
|
107
|
+
this.deferringSince = null;
|
|
108
|
+
this.nextAttemptAt = now + HOURS[schedule.every] * 3_600_000;
|
|
109
|
+
this.options.onEvent?.("the scheduled restart was abandoned — guests were watching for six hours");
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
const request = {
|
|
113
|
+
scope: schedule.scope,
|
|
114
|
+
reason: "scheduled",
|
|
115
|
+
// AR: الجدول **لا يقطع أبدًا** حين اختار المالك ذلك. وforce هنا معناه «لا تسأل» لا «اقطع»،
|
|
116
|
+
// فيُشتقّ من إعداده هو لا من رغبتنا في أن ينجح.
|
|
117
|
+
// EN: A schedule **never cuts** when the owner chose so. `force` here means "do not ask" rather
|
|
118
|
+
// than "cut", so it is derived from the owner's own setting rather than from our wish for
|
|
119
|
+
// the round to succeed.
|
|
120
|
+
force: !schedule.deferWhileWatching,
|
|
121
|
+
requestedAt: new Date(now).toISOString(),
|
|
122
|
+
};
|
|
123
|
+
const execution = await executeRestart(this.profile, request, {
|
|
124
|
+
deferIf: this.options.deferIf,
|
|
125
|
+
onEvent: this.options.onEvent,
|
|
126
|
+
});
|
|
127
|
+
if (execution.ok) {
|
|
128
|
+
this.deferringSince = null;
|
|
129
|
+
this.nextAttemptAt = 0;
|
|
130
|
+
return execution;
|
|
131
|
+
}
|
|
132
|
+
// تأجيل (أو فشل): نعاود بعد ربع ساعة، ونبدأ عدّ السقف من أوّل تأجيل لا من آخره.
|
|
133
|
+
this.deferringSince ??= now;
|
|
134
|
+
this.nextAttemptAt = now + DEFER_RETRY_MS;
|
|
135
|
+
return execution;
|
|
136
|
+
}
|
|
137
|
+
readSchedule() {
|
|
138
|
+
if (this.options.readSchedule)
|
|
139
|
+
return this.options.readSchedule();
|
|
140
|
+
return readStateJson(this.profile, REMOTE_STATE_FILES.restartSchedule);
|
|
141
|
+
}
|
|
142
|
+
readLastRestart() {
|
|
143
|
+
if (this.options.readLastRestart)
|
|
144
|
+
return this.options.readLastRestart();
|
|
145
|
+
return readStateJson(this.profile, REMOTE_STATE_FILES.restartOutcome);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
//# sourceMappingURL=schedule-timer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schedule-timer.js","sourceRoot":"","sources":["../../src/supervisor/schedule-timer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type ResultPromise } from "execa";
|
|
2
|
+
import type { Profile, ServiceDefinition } from "../profiles/types.js";
|
|
3
|
+
import { type PidRecord } from "./pidfile.js";
|
|
4
|
+
/** يُطلق خدمة في الخلفية ويسجّل هويتها. العملية تحيا بعد خروج الـ CLI. */
|
|
5
|
+
export declare function launchDetached(profile: Profile, definition: ServiceDefinition): Promise<PidRecord>;
|
|
6
|
+
export interface AttachedService {
|
|
7
|
+
definition: ServiceDefinition;
|
|
8
|
+
child: ResultPromise;
|
|
9
|
+
pid: number;
|
|
10
|
+
close: () => void;
|
|
11
|
+
}
|
|
12
|
+
export interface AttachOptions {
|
|
13
|
+
/** يُنادى لكل سطر مخرَج، لعرضه ببادئة ملوّنة. */
|
|
14
|
+
onLine: (service: ServiceDefinition, line: string) => void;
|
|
15
|
+
}
|
|
16
|
+
/** يُطلق خدمة مرتبطة بالطرفية: الأسطر تذهب إلى الشاشة وإلى ملف السجلّ معًا. */
|
|
17
|
+
export declare function launchAttached(profile: Profile, definition: ServiceDefinition, options: AttachOptions): AttachedService;
|
|
18
|
+
//# sourceMappingURL=spawn.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spawn.d.ts","sourceRoot":"","sources":["../../src/supervisor/spawn.ts"],"names":[],"mappings":"AAIA,OAAO,EAAS,KAAK,aAAa,EAAE,MAAM,OAAO,CAAC;AAElD,OAAO,KAAK,EAAE,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAIvE,OAAO,EAAkB,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAyB9D,0EAA0E;AAC1E,wBAAsB,cAAc,CAClC,OAAO,EAAE,OAAO,EAChB,UAAU,EAAE,iBAAiB,GAC5B,OAAO,CAAC,SAAS,CAAC,CA+CpB;AAED,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,iBAAiB,CAAC;IAC9B,KAAK,EAAE,aAAa,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B,iDAAiD;IACjD,MAAM,EAAE,CAAC,OAAO,EAAE,iBAAiB,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAC5D;AAED,+EAA+E;AAC/E,wBAAgB,cAAc,CAC5B,OAAO,EAAE,OAAO,EAChB,UAAU,EAAE,iBAAiB,EAC7B,OAAO,EAAE,aAAa,GACrB,eAAe,CA+CjB"}
|