@camstack/server 1.2.593 → 1.2.594
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/dist/addon-root-inventory.js +11 -50
- package/dist/agent/addon-scan.js +6 -44
- package/dist/agent/agent-addon-runtime.js +3 -8
- package/dist/agent/agent-addon-updates.js +12 -52
- package/dist/agent/agent-cap-dispatch-service.js +3 -5
- package/dist/agent/agent-config.js +7 -42
- package/dist/agent/agent-deploy-swap.js +5 -41
- package/dist/agent/agent-group-runner.js +8 -47
- package/dist/agent/agent-http-auth.js +10 -22
- package/dist/agent/agent-http.js +69 -115
- package/dist/agent/agent-hub-addon-update.js +10 -16
- package/dist/agent/agent-hub-registration.js +4 -7
- package/dist/agent/agent-infra-capabilities.js +5 -9
- package/dist/agent/agent-json-file.js +5 -42
- package/dist/agent/agent-mesh-gate.js +5 -8
- package/dist/agent/agent-node-certificates.js +25 -28
- package/dist/agent/agent-pairing-local.js +10 -47
- package/dist/agent/agent-pairing-routes.js +16 -20
- package/dist/agent/agent-pairing-store.js +18 -58
- package/dist/agent/agent-reconnect.js +1 -4
- package/dist/agent/agent-service.js +42 -78
- package/dist/agent/agent-sniffing-listener.js +11 -48
- package/dist/agent/agent-undeploy.js +5 -41
- package/dist/agent/agent-update-routes.js +14 -19
- package/dist/agent/agent-update-service.js +38 -80
- package/dist/agent/apply-model-distribution.js +1 -4
- package/dist/agent/apply-stage-dev-uploads.js +6 -9
- package/dist/agent/derive-hub-url.js +3 -8
- package/dist/agent/fetch-bundle-from-hub.js +6 -9
- package/dist/agent/hubs-found.js +6 -43
- package/dist/agent/infra-boot-guard.js +1 -4
- package/dist/agent/infra-boot-plan.js +2 -6
- package/dist/agent/main.js +158 -186
- package/dist/agent/register-agent-cap-dispatch.js +3 -6
- package/dist/agent/serial-queue.js +2 -7
- package/dist/agent-status-page.js +1 -4
- package/dist/api/addon-upload.js +22 -61
- package/dist/api/agent-addon-delivery.js +6 -11
- package/dist/api/auth-whoami.js +1 -4
- package/dist/api/backup-download-pump.js +5 -9
- package/dist/api/backup-download.js +7 -10
- package/dist/api/core/addon-settings.router.js +16 -19
- package/dist/api/core/agent-pairing.router.js +76 -79
- package/dist/api/core/agents.router.js +21 -24
- package/dist/api/core/auth-admin-tokens.procedures.js +48 -52
- package/dist/api/core/auth-device-cert.procedures.js +62 -67
- package/dist/api/core/auth-limits.js +16 -25
- package/dist/api/core/auth-reauth.procedures.js +32 -37
- package/dist/api/core/auth-revoke-credentials.procedures.js +22 -26
- package/dist/api/core/auth-sessions.procedures.js +52 -56
- package/dist/api/core/auth.router.js +300 -304
- package/dist/api/core/cap-providers.js +74 -121
- package/dist/api/core/capabilities.router.js +34 -37
- package/dist/api/core/capability-preference-writes.js +10 -17
- package/dist/api/core/certificates.router.js +106 -109
- package/dist/api/core/cluster-nodes.router.js +15 -18
- package/dist/api/core/collection-preference.js +2 -6
- package/dist/api/core/event-bus-proxy.router.js +34 -37
- package/dist/api/core/failure-contributions.js +4 -8
- package/dist/api/core/hwaccel.router.js +17 -20
- package/dist/api/core/integration-secrets.js +8 -12
- package/dist/api/core/lifecycle-job-runner.js +13 -49
- package/dist/api/core/live-events.router.js +29 -32
- package/dist/api/core/load-contributions.js +4 -8
- package/dist/api/core/logging-settings.js +30 -43
- package/dist/api/core/logs.router.js +40 -43
- package/dist/api/core/notifications.router.js +15 -18
- package/dist/api/core/public-event-filter.js +4 -8
- package/dist/api/core/repl.router.js +18 -21
- package/dist/api/core/request-census-settings.js +11 -16
- package/dist/api/core/server-management.provider.js +1 -4
- package/dist/api/core/server-name.js +9 -17
- package/dist/api/core/site-location.js +16 -24
- package/dist/api/core/stream-probe.router.js +21 -24
- package/dist/api/core/system-events.router.js +23 -26
- package/dist/api/cors/cors-policy.js +20 -29
- package/dist/api/cors/register-cors-policy.js +9 -14
- package/dist/api/deploy-stage-registry.js +6 -10
- package/dist/api/dev-uploads-bundle.js +12 -50
- package/dist/api/health/adaptive-probe.routes.js +9 -13
- package/dist/api/health/health.routes.js +8 -13
- package/dist/api/hub-cluster-url.js +3 -9
- package/dist/api/model-distributor.js +12 -50
- package/dist/api/oauth2/consent-page.js +10 -13
- package/dist/api/oauth2/oauth2-routes.js +17 -25
- package/dist/api/oauth2/private-host.js +1 -4
- package/dist/api/server-upload-propagate.js +15 -51
- package/dist/api/server-upload.js +13 -50
- package/dist/api/sse-no-compression.js +1 -4
- package/dist/api/static/frame-policy.js +4 -9
- package/dist/api/static/precompressed-asset.js +15 -57
- package/dist/api/static/spa-mount.js +8 -47
- package/dist/api/static/spa-static.js +5 -12
- package/dist/api/tarball-manifest.js +7 -44
- package/dist/api/trpc/cap-mount-helpers.js +7 -12
- package/dist/api/trpc/cap-route-error-formatter.js +10 -13
- package/dist/api/trpc/cap-router-runtime.js +40 -51
- package/dist/api/trpc/client-ip.js +9 -20
- package/dist/api/trpc/core-cap-bridge.js +32 -42
- package/dist/api/trpc/device-collection-dispatch.js +23 -27
- package/dist/api/trpc/device-config-secret-redaction.js +24 -40
- package/dist/api/trpc/generated-cap-mounts.js +218 -222
- package/dist/api/trpc/generated-cap-routers.js +4688 -4850
- package/dist/api/trpc/http-request-census-hook.js +8 -11
- package/dist/api/trpc/http-request-census.js +34 -41
- package/dist/api/trpc/http-request-census.singleton.js +4 -8
- package/dist/api/trpc/localized-schema-paths.js +1 -4
- package/dist/api/trpc/principal-visibility.js +14 -22
- package/dist/api/trpc/remote-addon-update-grant.js +1 -4
- package/dist/api/trpc/scope-access.js +10 -15
- package/dist/api/trpc/server-provided-caps.js +3 -7
- package/dist/api/trpc/share-view-access.js +6 -14
- package/dist/api/trpc/trpc-error-device-tags.js +3 -6
- package/dist/api/trpc/trpc-error-principal.js +2 -6
- package/dist/api/trpc/trpc.context.js +20 -25
- package/dist/api/trpc/trpc.middleware.js +38 -46
- package/dist/api/trpc/trpc.router.js +58 -99
- package/dist/api/trpc/user-error.js +5 -8
- package/dist/api/trpc/ws-request-census.js +17 -24
- package/dist/api/trpc/ws-slow-consumer-guard.js +11 -16
- package/dist/api/upload-auth.js +5 -9
- package/dist/auth/addon-route-jwt-gate.js +4 -7
- package/dist/auth/addon-route-share-gate.js +7 -12
- package/dist/auth/app-confirm-page.js +17 -22
- package/dist/auth/app-confirm-routes.js +26 -31
- package/dist/auth/app-confirmations.js +7 -44
- package/dist/auth/app-page-shell.js +17 -30
- package/dist/auth/app-page-strings.js +11 -17
- package/dist/auth/app-passkey-page.js +16 -21
- package/dist/auth/app-passkey-routes.js +37 -41
- package/dist/auth/app-refused-route.js +13 -18
- package/dist/auth/auth-network-policy.js +11 -15
- package/dist/auth/auth-provider-gate.js +4 -9
- package/dist/auth/auth-rate-limit.js +3 -7
- package/dist/auth/client-address.js +6 -9
- package/dist/auth/device-enroll-proofs.js +6 -43
- package/dist/auth/external-link-intents.js +3 -7
- package/dist/auth/hub-sessions.js +6 -12
- package/dist/auth/native-link-completions.js +7 -11
- package/dist/auth/native-return.js +9 -13
- package/dist/auth/passkey-provider.js +26 -32
- package/dist/auth/second-factors.js +6 -10
- package/dist/auth/session-connections.js +6 -12
- package/dist/auth/session-cookie.js +12 -23
- package/dist/auth/session-lifetimes.js +8 -12
- package/dist/auth/session-mint.js +4 -11
- package/dist/auth/sso-finish-app.js +13 -16
- package/dist/auth/sso-finish-deps.js +21 -27
- package/dist/auth/sso-finish.js +28 -38
- package/dist/auth/sso-routes.js +22 -25
- package/dist/auth/used-bridge-ids.js +1 -5
- package/dist/boot/boot-config.js +16 -55
- package/dist/boot/init-sequence.js +1 -4
- package/dist/boot/integration-id-backfill.js +3 -8
- package/dist/boot/platform-keychain-key.js +5 -42
- package/dist/boot/post-boot.service.js +14 -18
- package/dist/boot/reconcile-lifecycle-jobs.js +3 -6
- package/dist/boot/retired-public-url-env.js +4 -8
- package/dist/bootstrap-packages.js +1 -4
- package/dist/closure-node-modules.js +2 -38
- package/dist/closure-patches/patch-reach.json +6 -2
- package/dist/core/addon/addon-call-gateway.js +1 -5
- package/dist/core/addon/addon-package.service.js +83 -123
- package/dist/core/addon/addon-process-view.js +2 -6
- package/dist/core/addon/addon-realign-plan.js +1 -4
- package/dist/core/addon/addon-registry.service.js +199 -185
- package/dist/core/addon/addon-row-manifest.js +1 -4
- package/dist/core/addon/addon-search.service.js +3 -7
- package/dist/core/addon/addon-settings-provider.js +1 -3
- package/dist/core/addon/addon-uninstall.js +4 -11
- package/dist/core/addon/addon.tokens.js +2 -5
- package/dist/core/addon/device-meta-mirror.js +8 -13
- package/dist/core/addon/forked-custom-actions.js +6 -11
- package/dist/core/addon/integration-visibility.js +3 -6
- package/dist/core/addon/materialize-route-path.js +1 -4
- package/dist/core/addon/package-dir-utils.js +8 -45
- package/dist/core/addon/prune-misplaced-addons.js +5 -43
- package/dist/core/addon/runner-convergence.js +1 -4
- package/dist/core/addon/runner-serialization.js +1 -4
- package/dist/core/addon/runner-spawn-fanout.js +3 -8
- package/dist/core/addon/settings-door-wiring.js +5 -8
- package/dist/core/addon/single-flight-refresh.js +1 -4
- package/dist/core/addon-bridge/addon-bridge.service.js +7 -44
- package/dist/core/addon-pages/addon-pages.service.js +3 -40
- package/dist/core/addon-widgets/addon-widgets.service.js +4 -42
- package/dist/core/agent/agent-addon-backfill.js +9 -17
- package/dist/core/agent/agent-delivery-ledger.js +3 -7
- package/dist/core/agent/agent-liveness-event.js +2 -6
- package/dist/core/agent/agent-pairing-http.js +41 -45
- package/dist/core/agent/agent-registry.service.js +53 -92
- package/dist/core/agent/cluster-node-history-mirror.js +3 -7
- package/dist/core/agent/cluster-node-history-store.js +113 -58
- package/dist/core/agent/hub-agent-pairing.js +1 -5
- package/dist/core/agent/node-certificates-client.js +3 -6
- package/dist/core/agent/node-directory.js +1 -4
- package/dist/core/app-links/well-known-app-links.js +2 -6
- package/dist/core/auth/auth.service.js +3 -8
- package/dist/core/auth/handoff-code.service.js +11 -49
- package/dist/core/auth/record-kinds.js +35 -0
- package/dist/core/auth/share-token.service.js +174 -122
- package/dist/core/capability/capability.service.js +1 -5
- package/dist/core/config/config.schema.js +1 -6
- package/dist/core/config/config.service.js +2 -6
- package/dist/core/events/event-bus.service.js +3 -7
- package/dist/core/feature/feature.service.js +2 -6
- package/dist/core/lifecycle/lifecycle-runner.singleton.js +5 -10
- package/dist/core/lifecycle/lifecycle-state-machine.js +1 -5
- package/dist/core/logging/log-ring-buffer.js +1 -5
- package/dist/core/logging/logging.service.js +5 -9
- package/dist/core/logging/scoped-logger.js +1 -5
- package/dist/core/moleculer/agent-readiness-pull.js +1 -4
- package/dist/core/moleculer/agent-registration-request.js +3 -7
- package/dist/core/moleculer/cap-call-fn.js +39 -5
- package/dist/core/moleculer/cap-route-authority.js +3 -8
- package/dist/core/moleculer/hub-mesh-guard.js +5 -9
- package/dist/core/moleculer/moleculer.service.js +108 -119
- package/dist/core/network/network-quality.service.js +2 -6
- package/dist/core/notification/notification-wrapper.service.js +3 -7
- package/dist/core/notification/toast-wrapper.service.js +3 -7
- package/dist/core/provider/provider.tokens.js +1 -4
- package/dist/core/repl/repl-engine.service.js +4 -8
- package/dist/core/runner-health/runner-boot-check.js +7 -15
- package/dist/core/runner-health/update-preflight.js +9 -14
- package/dist/core/server-update/server-update.service.js +12 -49
- package/dist/core/server-update/system-apply-closure-patches.js +6 -42
- package/dist/core/server-update/system-ensure-prebuilds.js +3 -6
- package/dist/core/server-update/system-exec-npm.js +2 -5
- package/dist/core/storage/fs-storage-backend.js +1 -5
- package/dist/core/storage/storage-location-manager.js +1 -5
- package/dist/core/storage/storage.service.js +2 -6
- package/dist/core/streaming/ffmpeg-stream-info.js +3 -8
- package/dist/core/streaming/stream-probe.service.js +12 -16
- package/dist/core/streaming/ttl-cache.js +1 -5
- package/dist/core/topology/topology-emitter.service.js +19 -23
- package/dist/core/update-availability-emitter.js +3 -7
- package/dist/core/update-availability-store.js +8 -45
- package/dist/core/updates/agent-installed-packages.js +5 -9
- package/dist/core/updates/restart-marker.js +3 -8
- package/dist/core/updates/update-check-scheduler.js +13 -18
- package/dist/core/updates/wrapper-update-checker.js +3 -7
- package/dist/first-boot-addon-plan.js +2 -6
- package/dist/framework-nodepath.js +2 -38
- package/dist/i18n/request-lang.js +7 -11
- package/dist/launcher.js +30 -65
- package/dist/lifecycle-journal-path.js +2 -38
- package/dist/main.js +287 -324
- package/dist/manual-boot.js +120 -157
- package/dist/node-role.js +1 -4
- package/dist/package-inventory.js +7 -48
- package/dist/pending-restore.js +7 -43
- package/dist/single-copy-cleanup-runner.js +9 -45
- package/dist/single-copy-cleanup.js +7 -15
- package/dist/sqlite-restore.js +9 -48
- package/dist/starter.js +4 -39
- package/dist/ui-serving/lazy-ui-serving.js +3 -39
- package/package.json +13 -13
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.TopologyEmitterService = void 0;
|
|
4
1
|
/**
|
|
5
2
|
* TopologyEmitterService — push the cluster topology over the event bus.
|
|
6
3
|
*
|
|
@@ -15,26 +12,26 @@ exports.TopologyEmitterService = void 0;
|
|
|
15
12
|
* subscribe to the snapshot category and read state directly from the
|
|
16
13
|
* payload — zero round-trip.
|
|
17
14
|
*/
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
15
|
+
import { randomUUID } from 'node:crypto';
|
|
16
|
+
import { EventCategory } from '@camstack/types';
|
|
17
|
+
import { computeTopologyPass, } from '../../api/core/cap-providers';
|
|
21
18
|
const DEBOUNCE_MS = 200;
|
|
22
19
|
const HEARTBEAT_MS = 30_000;
|
|
23
20
|
const LIFECYCLE_CATEGORIES = [
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
21
|
+
EventCategory.AgentOnline,
|
|
22
|
+
EventCategory.AgentOffline,
|
|
23
|
+
EventCategory.WorkerOnline,
|
|
24
|
+
EventCategory.WorkerOffline,
|
|
25
|
+
EventCategory.AgentUnregistered,
|
|
26
|
+
EventCategory.AddonStarted,
|
|
27
|
+
EventCategory.AddonStopped,
|
|
28
|
+
EventCategory.AddonRestarted,
|
|
29
|
+
EventCategory.AddonInstalled,
|
|
30
|
+
EventCategory.AddonUninstalled,
|
|
31
|
+
EventCategory.AddonUpdated,
|
|
32
|
+
EventCategory.AddonCrashed,
|
|
36
33
|
];
|
|
37
|
-
class TopologyEmitterService {
|
|
34
|
+
export class TopologyEmitterService {
|
|
38
35
|
eventBus;
|
|
39
36
|
agentRegistry;
|
|
40
37
|
addonRegistry;
|
|
@@ -93,12 +90,12 @@ class TopologyEmitterService {
|
|
|
93
90
|
return;
|
|
94
91
|
this.emitting = true;
|
|
95
92
|
try {
|
|
96
|
-
const { nodes, liveNodes } = await
|
|
93
|
+
const { nodes, liveNodes } = await computeTopologyPass(this.agentRegistry, this.addonRegistry, this.getNodeRootPackage, this.isNodeRegistered);
|
|
97
94
|
this.eventBus.emit({
|
|
98
|
-
id:
|
|
95
|
+
id: randomUUID(),
|
|
99
96
|
timestamp: new Date(),
|
|
100
97
|
source: { type: 'core', id: 'topology-emitter' },
|
|
101
|
-
category:
|
|
98
|
+
category: EventCategory.ClusterTopologySnapshot,
|
|
102
99
|
data: { nodes, timestamp: Date.now() },
|
|
103
100
|
});
|
|
104
101
|
// The durable capture rides THIS pass, not an operator's read (D317).
|
|
@@ -117,4 +114,3 @@ class TopologyEmitterService {
|
|
|
117
114
|
}
|
|
118
115
|
}
|
|
119
116
|
}
|
|
120
|
-
exports.TopologyEmitterService = TopologyEmitterService;
|
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.UpdateAvailabilityEmitter = void 0;
|
|
4
|
-
const types_1 = require("@camstack/types");
|
|
1
|
+
import { EventCategory } from '@camstack/types';
|
|
5
2
|
/**
|
|
6
3
|
* Emits update availability only when a successful check changes an observed
|
|
7
4
|
* `latestVersion` (or first-sees a package/node that has one). Repeated polls
|
|
@@ -26,7 +23,7 @@ const types_1 = require("@camstack/types");
|
|
|
26
23
|
* genuinely newer version still announces. Without one the emitter stays
|
|
27
24
|
* RAM-only (the shape every unit test uses).
|
|
28
25
|
*/
|
|
29
|
-
class UpdateAvailabilityEmitter {
|
|
26
|
+
export class UpdateAvailabilityEmitter {
|
|
30
27
|
eventBus;
|
|
31
28
|
source;
|
|
32
29
|
store;
|
|
@@ -144,7 +141,7 @@ class UpdateAvailabilityEmitter {
|
|
|
144
141
|
.join(',')}`,
|
|
145
142
|
timestamp: new Date(),
|
|
146
143
|
source: this.source,
|
|
147
|
-
category:
|
|
144
|
+
category: EventCategory.UpdateAvailable,
|
|
148
145
|
data: {
|
|
149
146
|
target,
|
|
150
147
|
packageName: head.packageName,
|
|
@@ -161,7 +158,6 @@ class UpdateAvailabilityEmitter {
|
|
|
161
158
|
return `${candidate.target}:${scopeOf(candidate)}:${candidate.packageName}`;
|
|
162
159
|
}
|
|
163
160
|
}
|
|
164
|
-
exports.UpdateAvailabilityEmitter = UpdateAvailabilityEmitter;
|
|
165
161
|
/** The node an availability row belongs to. A row without one is the hub's. */
|
|
166
162
|
function scopeOf(candidate) {
|
|
167
163
|
return candidate.nodeId ?? 'hub';
|
|
@@ -1,39 +1,3 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.FileUpdateAvailabilityStore = exports.UPDATE_AVAILABILITY_DIR = void 0;
|
|
37
1
|
/**
|
|
38
2
|
* Durable backing for {@link UpdateAvailabilityEmitter}'s dedup state.
|
|
39
3
|
*
|
|
@@ -48,24 +12,24 @@ exports.FileUpdateAvailabilityStore = exports.UPDATE_AVAILABILITY_DIR = void 0;
|
|
|
48
12
|
* database, no settings-store dependency (the emitter runs on the AGENT too,
|
|
49
13
|
* where the hub's SQLite settings store does not exist).
|
|
50
14
|
*/
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
15
|
+
import * as fs from 'node:fs';
|
|
16
|
+
import * as path from 'node:path';
|
|
17
|
+
import { errMsg } from '@camstack/types';
|
|
54
18
|
/** Directory under the data dir that holds one file per emitter scope. */
|
|
55
|
-
|
|
19
|
+
export const UPDATE_AVAILABILITY_DIR = 'update-availability';
|
|
56
20
|
/**
|
|
57
21
|
* One file per emitter scope (`addon-packages`, `server-update`,
|
|
58
22
|
* `agent-update`) so two emitters in the same process never overwrite each
|
|
59
23
|
* other's dedup state.
|
|
60
24
|
*/
|
|
61
|
-
class FileUpdateAvailabilityStore {
|
|
25
|
+
export class FileUpdateAvailabilityStore {
|
|
62
26
|
scopeId;
|
|
63
27
|
logger;
|
|
64
28
|
filePath;
|
|
65
29
|
constructor(dataDir, scopeId, logger) {
|
|
66
30
|
this.scopeId = scopeId;
|
|
67
31
|
this.logger = logger;
|
|
68
|
-
this.filePath = path.join(dataDir,
|
|
32
|
+
this.filePath = path.join(dataDir, UPDATE_AVAILABILITY_DIR, `${scopeId}.json`);
|
|
69
33
|
}
|
|
70
34
|
load() {
|
|
71
35
|
try {
|
|
@@ -78,7 +42,7 @@ class FileUpdateAvailabilityStore {
|
|
|
78
42
|
// A corrupt file must not look like "nothing was ever announced" AND
|
|
79
43
|
// must not crash boot. It re-announces once, then heals on the next save.
|
|
80
44
|
this.logger.warn('Update-availability state unreadable; starting from empty', {
|
|
81
|
-
meta: { scopeId: this.scopeId, path: this.filePath, error:
|
|
45
|
+
meta: { scopeId: this.scopeId, path: this.filePath, error: errMsg(error) },
|
|
82
46
|
});
|
|
83
47
|
return null;
|
|
84
48
|
}
|
|
@@ -94,12 +58,11 @@ class FileUpdateAvailabilityStore {
|
|
|
94
58
|
// Losing a write degrades to the old RAM-only behaviour (a re-announce
|
|
95
59
|
// after restart) — never a failed update check.
|
|
96
60
|
this.logger.warn('Failed to persist update-availability state', {
|
|
97
|
-
meta: { scopeId: this.scopeId, path: this.filePath, error:
|
|
61
|
+
meta: { scopeId: this.scopeId, path: this.filePath, error: errMsg(error) },
|
|
98
62
|
});
|
|
99
63
|
}
|
|
100
64
|
}
|
|
101
65
|
}
|
|
102
|
-
exports.FileUpdateAvailabilityStore = FileUpdateAvailabilityStore;
|
|
103
66
|
function parseState(raw) {
|
|
104
67
|
if (raw === null || typeof raw !== 'object')
|
|
105
68
|
return null;
|
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.AGENT_STATUS_TIMEOUT_MS = void 0;
|
|
4
|
-
exports.fetchAgentInstalledPackages = fetchAgentInstalledPackages;
|
|
5
1
|
/**
|
|
6
2
|
* The agent addon roster, as the hub sees it.
|
|
7
3
|
*
|
|
@@ -13,16 +9,16 @@ exports.fetchAgentInstalledPackages = fetchAgentInstalledPackages;
|
|
|
13
9
|
* the framework filter and make the two surfaces disagree about what is
|
|
14
10
|
* installed on a node.
|
|
15
11
|
*/
|
|
16
|
-
|
|
12
|
+
import { isFrameworkPackage } from '../addon/addon-package.service.js';
|
|
17
13
|
/** Timeout for `$agent.status`; a node that cannot answer this fast is unwell. */
|
|
18
|
-
|
|
19
|
-
async function fetchAgentInstalledPackages(broker, nodeId) {
|
|
20
|
-
const status = await broker.call('$agent.status', {}, { nodeID: nodeId, timeout:
|
|
14
|
+
export const AGENT_STATUS_TIMEOUT_MS = 5_000;
|
|
15
|
+
export async function fetchAgentInstalledPackages(broker, nodeId) {
|
|
16
|
+
const status = await broker.call('$agent.status', {}, { nodeID: nodeId, timeout: AGENT_STATUS_TIMEOUT_MS });
|
|
21
17
|
const out = [];
|
|
22
18
|
for (const addon of status.addons ?? []) {
|
|
23
19
|
if (typeof addon.packageName !== 'string' || typeof addon.version !== 'string')
|
|
24
20
|
continue;
|
|
25
|
-
if (
|
|
21
|
+
if (isFrameworkPackage(addon.packageName))
|
|
26
22
|
continue;
|
|
27
23
|
out.push({ name: addon.packageName, version: addon.version });
|
|
28
24
|
}
|
|
@@ -1,13 +1,8 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.buildRestartMarker = buildRestartMarker;
|
|
4
|
-
exports.isServerUpdateReason = isServerUpdateReason;
|
|
5
|
-
exports.versionFromReason = versionFromReason;
|
|
6
1
|
/** Reason-string prefix every `RootUpdateService`-driven restart carries. */
|
|
7
2
|
const SERVER_UPDATE_PREFIX = 'server-update:';
|
|
8
3
|
/** The root package a version-less `server-update:` reason is about. */
|
|
9
4
|
const ROOT_PACKAGE_NAME = '@camstack/server';
|
|
10
|
-
function buildRestartMarker(input) {
|
|
5
|
+
export function buildRestartMarker(input) {
|
|
11
6
|
const { requestedBy, update, requestedAt } = input;
|
|
12
7
|
const toVersion = update?.toVersion ?? versionFromReason(requestedBy);
|
|
13
8
|
const isUpdate = update !== undefined || (isServerUpdateReason(requestedBy) && toVersion !== undefined);
|
|
@@ -27,11 +22,11 @@ function buildRestartMarker(input) {
|
|
|
27
22
|
...(toVersion !== undefined ? { toVersion } : {}),
|
|
28
23
|
};
|
|
29
24
|
}
|
|
30
|
-
function isServerUpdateReason(requestedBy) {
|
|
25
|
+
export function isServerUpdateReason(requestedBy) {
|
|
31
26
|
return requestedBy !== undefined && requestedBy.startsWith(SERVER_UPDATE_PREFIX);
|
|
32
27
|
}
|
|
33
28
|
/** `server-update: @camstack/server@1.2.138` → `1.2.138`; `… manual restart` → none. */
|
|
34
|
-
function versionFromReason(requestedBy) {
|
|
29
|
+
export function versionFromReason(requestedBy) {
|
|
35
30
|
if (requestedBy === undefined)
|
|
36
31
|
return undefined;
|
|
37
32
|
return /@([^@\s]+)$/.exec(requestedBy)?.[1];
|
|
@@ -1,43 +1,39 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.UpdateCheckScheduler = exports.MAX_UPDATE_CHECK_INTERVAL_SECONDS = exports.MIN_UPDATE_CHECK_INTERVAL_SECONDS = exports.DEFAULT_UPDATE_CHECK_INTERVAL_SECONDS = void 0;
|
|
4
|
-
exports.clampUpdateCheckInterval = clampUpdateCheckInterval;
|
|
5
|
-
const types_1 = require("@camstack/types");
|
|
1
|
+
import { errMsg } from '@camstack/types';
|
|
6
2
|
/**
|
|
7
3
|
* Default poll cadence: 6 hours. Registry lookups are cheap but not free, and
|
|
8
4
|
* an operator who is told about a publish within a quarter-day is told in time.
|
|
9
5
|
*/
|
|
10
|
-
|
|
6
|
+
export const DEFAULT_UPDATE_CHECK_INTERVAL_SECONDS = 6 * 60 * 60;
|
|
11
7
|
/**
|
|
12
8
|
* Floor: 15 minutes. Below this the sweep starts overlapping its own npm
|
|
13
9
|
* lookups on a cluster of any size, and the notification stops being a
|
|
14
10
|
* notification. `setAutoUpdateSettings` clamps to this rather than refusing,
|
|
15
11
|
* so a bad value degrades to "poll briskly" instead of "poll never".
|
|
16
12
|
*/
|
|
17
|
-
|
|
13
|
+
export const MIN_UPDATE_CHECK_INTERVAL_SECONDS = 15 * 60;
|
|
18
14
|
/** Ceiling: 7 days. Anything longer is indistinguishable from disabled. */
|
|
19
|
-
|
|
15
|
+
export const MAX_UPDATE_CHECK_INTERVAL_SECONDS = 7 * 24 * 60 * 60;
|
|
20
16
|
/** Grace after boot before the first sweep, so registry I/O never races boot. */
|
|
21
17
|
const DEFAULT_INITIAL_DELAY_MS = 90_000;
|
|
22
18
|
/** Clamp an operator-supplied interval into the supported window. */
|
|
23
|
-
function clampUpdateCheckInterval(seconds) {
|
|
19
|
+
export function clampUpdateCheckInterval(seconds) {
|
|
24
20
|
if (!Number.isFinite(seconds))
|
|
25
|
-
return
|
|
21
|
+
return DEFAULT_UPDATE_CHECK_INTERVAL_SECONDS;
|
|
26
22
|
const whole = Math.floor(seconds);
|
|
27
|
-
if (whole <
|
|
28
|
-
return
|
|
29
|
-
if (whole >
|
|
30
|
-
return
|
|
23
|
+
if (whole < MIN_UPDATE_CHECK_INTERVAL_SECONDS)
|
|
24
|
+
return MIN_UPDATE_CHECK_INTERVAL_SECONDS;
|
|
25
|
+
if (whole > MAX_UPDATE_CHECK_INTERVAL_SECONDS)
|
|
26
|
+
return MAX_UPDATE_CHECK_INTERVAL_SECONDS;
|
|
31
27
|
return whole;
|
|
32
28
|
}
|
|
33
|
-
class UpdateCheckScheduler {
|
|
29
|
+
export class UpdateCheckScheduler {
|
|
34
30
|
logger;
|
|
35
31
|
targets;
|
|
36
32
|
getIntervalSeconds;
|
|
37
33
|
initialDelayMs;
|
|
38
34
|
timer = null;
|
|
39
35
|
bootTimer = null;
|
|
40
|
-
intervalSeconds =
|
|
36
|
+
intervalSeconds = DEFAULT_UPDATE_CHECK_INTERVAL_SECONDS;
|
|
41
37
|
sweeping = false;
|
|
42
38
|
constructor(options) {
|
|
43
39
|
this.logger = options.logger;
|
|
@@ -131,9 +127,8 @@ class UpdateCheckScheduler {
|
|
|
131
127
|
// and destroy the dedup state the operator's notifications rely on.
|
|
132
128
|
this.logger.warn(`Update check failed — ${what}`, {
|
|
133
129
|
tags: { nodeId },
|
|
134
|
-
meta: { error:
|
|
130
|
+
meta: { error: errMsg(error) },
|
|
135
131
|
});
|
|
136
132
|
}
|
|
137
133
|
}
|
|
138
134
|
}
|
|
139
|
-
exports.UpdateCheckScheduler = UpdateCheckScheduler;
|
|
@@ -1,14 +1,11 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.WrapperUpdateChecker = exports.WRAPPER_PACKAGE_NAME = void 0;
|
|
4
1
|
/**
|
|
5
2
|
* The availability row's package name. A shell is not an npm package, but the
|
|
6
3
|
* emitter keys dedup on `(target, node, packageName)` and a stable literal is
|
|
7
4
|
* what makes "one shell per node" the dedup slot. Never rendered: the
|
|
8
5
|
* notification body is chosen from the wrapper KIND.
|
|
9
6
|
*/
|
|
10
|
-
|
|
11
|
-
class WrapperUpdateChecker {
|
|
7
|
+
export const WRAPPER_PACKAGE_NAME = 'camstack-wrapper';
|
|
8
|
+
export class WrapperUpdateChecker {
|
|
12
9
|
emitter;
|
|
13
10
|
logger;
|
|
14
11
|
readStatus;
|
|
@@ -47,7 +44,7 @@ class WrapperUpdateChecker {
|
|
|
47
44
|
}
|
|
48
45
|
const candidate = {
|
|
49
46
|
target: 'wrapper',
|
|
50
|
-
packageName:
|
|
47
|
+
packageName: WRAPPER_PACKAGE_NAME,
|
|
51
48
|
// The SHELL's versions, not the running code's. `wrapper.currentVersion`
|
|
52
49
|
// is what the shell says about ITSELF (an Electron app version), which
|
|
53
50
|
// is not on the same scale as a release; the seed is, and the seed is
|
|
@@ -60,4 +57,3 @@ class WrapperUpdateChecker {
|
|
|
60
57
|
this.emitter.publishSnapshot('wrapper', [candidate], nodeId);
|
|
61
58
|
}
|
|
62
59
|
}
|
|
63
|
-
exports.WrapperUpdateChecker = WrapperUpdateChecker;
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
/**
|
|
3
2
|
* What a node installs at first boot once the image stops carrying a
|
|
4
3
|
* NON-system addon seed tree — [D45](../../../docs/decisions/adr-0045.md),
|
|
@@ -26,11 +25,8 @@
|
|
|
26
25
|
* Pure: the caller supplies the roster, what is on disk and what the closure
|
|
27
26
|
* carries. It installs nothing and can never end a boot.
|
|
28
27
|
*/
|
|
29
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
30
|
-
exports.planFirstBootAddons = planFirstBootAddons;
|
|
31
|
-
exports.formatFirstBootPlan = formatFirstBootPlan;
|
|
32
28
|
/** The plan. Pure; installs nothing. */
|
|
33
|
-
function planFirstBootAddons(input) {
|
|
29
|
+
export function planFirstBootAddons(input) {
|
|
34
30
|
const provided = new Set(input.closureProvided);
|
|
35
31
|
const decisions = input.required.map((pkg) => decide(pkg, input.installed, input.closureVersions, provided));
|
|
36
32
|
const wouldInstall = decisions.filter((d) => d.action === 'install-npm').map((d) => d.pkg);
|
|
@@ -91,7 +87,7 @@ function decide(pkg, installed, closureVersions, closureProvided) {
|
|
|
91
87
|
* `observe` the lines say so explicitly — an observe line that reads like an
|
|
92
88
|
* install is worse than no line at all.
|
|
93
89
|
*/
|
|
94
|
-
function formatFirstBootPlan(plan, mode) {
|
|
90
|
+
export function formatFirstBootPlan(plan, mode) {
|
|
95
91
|
const header = `first-boot addon plan (${mode}) — ${plan.decisions.length} package(s), ` +
|
|
96
92
|
`${plan.wouldInstall.length} to install`;
|
|
97
93
|
const lines = [
|
|
@@ -1,47 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.frameworkNodePaths = frameworkNodePaths;
|
|
37
|
-
const path = __importStar(require("node:path"));
|
|
1
|
+
import * as path from 'node:path';
|
|
38
2
|
/**
|
|
39
3
|
* The framework's node_modules path to prepend to NODE_PATH so the CJS hub
|
|
40
4
|
* resolves @camstack/system (+ hoisted server deps) from /data/framework.
|
|
41
5
|
* CJS honors NODE_PATH (unlike ESM `import`, which is why addons use the
|
|
42
6
|
* resolver hook instead). Empty when unset or absent.
|
|
43
7
|
*/
|
|
44
|
-
function frameworkNodePaths(frameworkDir, exists) {
|
|
8
|
+
export function frameworkNodePaths(frameworkDir, exists) {
|
|
45
9
|
if (!frameworkDir)
|
|
46
10
|
return [];
|
|
47
11
|
const nm = path.join(frameworkDir, 'node_modules');
|
|
@@ -1,24 +1,20 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
exports.resolveRequestLang = resolveRequestLang;
|
|
4
|
-
exports.requestLangInputFrom = requestLangInputFrom;
|
|
5
|
-
const types_1 = require("@camstack/types");
|
|
6
|
-
const app_page_strings_js_1 = require("../auth/app-page-strings.js");
|
|
1
|
+
import { CatalogLangSchema, DEFAULT_CATALOG_LANG } from '@camstack/types';
|
|
2
|
+
import { langFromAcceptLanguage } from '../auth/app-page-strings.js';
|
|
7
3
|
function parseLang(value) {
|
|
8
|
-
const parsed =
|
|
4
|
+
const parsed = CatalogLangSchema.safeParse(typeof value === 'string' ? value.toLowerCase() : value);
|
|
9
5
|
return parsed.success ? parsed.data : undefined;
|
|
10
6
|
}
|
|
11
|
-
function resolveRequestLang(input) {
|
|
7
|
+
export function resolveRequestLang(input) {
|
|
12
8
|
return (parseLang(input.profileLanguage) ??
|
|
13
9
|
parseLang(input.explicitLang) ??
|
|
14
|
-
|
|
15
|
-
|
|
10
|
+
langFromAcceptLanguage(input.acceptLanguage) ??
|
|
11
|
+
DEFAULT_CATALOG_LANG);
|
|
16
12
|
}
|
|
17
13
|
function firstHeader(value) {
|
|
18
14
|
return Array.isArray(value) ? value[0] : value;
|
|
19
15
|
}
|
|
20
16
|
/** Reads the request-borne inputs; `query` is the parsed query object when there is one. */
|
|
21
|
-
function requestLangInputFrom(headers, query, connectionLang) {
|
|
17
|
+
export function requestLangInputFrom(headers, query, connectionLang) {
|
|
22
18
|
const acceptLanguage = headers['accept-language'];
|
|
23
19
|
return {
|
|
24
20
|
explicitLang: firstHeader(headers['x-camstack-lang']) ?? query?.['lang'] ?? connectionLang,
|