@camstack/server 1.2.594 → 1.2.595
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 +50 -11
- package/dist/agent/addon-scan.js +44 -6
- package/dist/agent/agent-addon-runtime.js +8 -3
- package/dist/agent/agent-addon-updates.js +52 -12
- package/dist/agent/agent-cap-dispatch-service.js +5 -3
- package/dist/agent/agent-config.js +42 -7
- package/dist/agent/agent-deploy-swap.js +41 -5
- package/dist/agent/agent-group-runner.js +47 -8
- package/dist/agent/agent-http-auth.js +22 -10
- package/dist/agent/agent-http.js +113 -64
- package/dist/agent/agent-hub-addon-update.js +16 -10
- package/dist/agent/agent-hub-registration.js +7 -4
- package/dist/agent/agent-infra-capabilities.js +9 -5
- package/dist/agent/agent-json-file.js +42 -5
- package/dist/agent/agent-mesh-gate.js +8 -5
- package/dist/agent/agent-node-certificates.js +28 -25
- package/dist/agent/agent-pairing-local.js +47 -10
- package/dist/agent/agent-pairing-routes.js +20 -16
- package/dist/agent/agent-pairing-store.js +58 -18
- package/dist/agent/agent-reconnect.js +4 -1
- package/dist/agent/agent-service.js +71 -35
- package/dist/agent/agent-sniffing-listener.js +48 -11
- package/dist/agent/agent-undeploy.js +41 -5
- package/dist/agent/agent-update-routes.js +19 -14
- package/dist/agent/agent-update-service.js +80 -38
- package/dist/agent/apply-model-distribution.js +4 -1
- package/dist/agent/apply-stage-dev-uploads.js +9 -6
- package/dist/agent/derive-hub-url.js +8 -3
- package/dist/agent/fetch-bundle-from-hub.js +9 -6
- package/dist/agent/hubs-found.js +43 -6
- package/dist/agent/infra-boot-guard.js +4 -1
- package/dist/agent/infra-boot-plan.js +6 -2
- package/dist/agent/main.js +183 -148
- package/dist/agent/register-agent-cap-dispatch.js +6 -3
- package/dist/agent/serial-queue.js +7 -2
- package/dist/agent-status-page.js +4 -1
- package/dist/api/addon-upload.js +61 -22
- package/dist/api/agent-addon-delivery.js +11 -6
- package/dist/api/auth-whoami.js +4 -1
- package/dist/api/backup-download-pump.js +9 -5
- package/dist/api/backup-download.js +10 -7
- package/dist/api/core/addon-settings.router.js +19 -16
- package/dist/api/core/agent-pairing.router.js +79 -76
- package/dist/api/core/agents.router.js +24 -21
- package/dist/api/core/auth-admin-tokens.procedures.js +52 -48
- package/dist/api/core/auth-device-cert.procedures.js +67 -62
- package/dist/api/core/auth-limits.js +25 -16
- package/dist/api/core/auth-reauth.procedures.js +37 -32
- package/dist/api/core/auth-revoke-credentials.procedures.js +26 -22
- package/dist/api/core/auth-sessions.procedures.js +56 -52
- package/dist/api/core/auth.router.js +304 -300
- package/dist/api/core/cap-providers.js +121 -74
- package/dist/api/core/capabilities.router.js +37 -34
- package/dist/api/core/capability-preference-writes.js +17 -10
- package/dist/api/core/certificates.router.js +109 -106
- package/dist/api/core/cluster-nodes.router.js +18 -15
- package/dist/api/core/collection-preference.js +6 -2
- package/dist/api/core/event-bus-proxy.router.js +37 -34
- package/dist/api/core/failure-contributions.js +8 -4
- package/dist/api/core/hwaccel.router.js +20 -17
- package/dist/api/core/integration-secrets.js +12 -8
- package/dist/api/core/lifecycle-job-runner.js +49 -13
- package/dist/api/core/live-events.router.js +32 -29
- package/dist/api/core/load-contributions.js +8 -4
- package/dist/api/core/logging-settings.js +43 -30
- package/dist/api/core/logs.router.js +43 -40
- package/dist/api/core/notifications.router.js +18 -15
- package/dist/api/core/public-event-filter.js +8 -4
- package/dist/api/core/repl.router.js +21 -18
- package/dist/api/core/request-census-settings.js +16 -11
- package/dist/api/core/server-management.provider.js +4 -1
- package/dist/api/core/server-name.js +17 -9
- package/dist/api/core/site-location.js +24 -16
- package/dist/api/core/stream-probe.router.js +24 -21
- package/dist/api/core/system-events.router.js +26 -23
- package/dist/api/cors/cors-policy.js +29 -20
- package/dist/api/cors/register-cors-policy.js +14 -9
- package/dist/api/deploy-stage-registry.js +10 -6
- package/dist/api/dev-uploads-bundle.js +50 -12
- package/dist/api/health/adaptive-probe.routes.js +13 -9
- package/dist/api/health/health.routes.js +13 -8
- package/dist/api/hub-cluster-url.js +9 -3
- package/dist/api/model-distributor.js +50 -12
- package/dist/api/oauth2/consent-page.js +13 -10
- package/dist/api/oauth2/oauth2-routes.js +25 -17
- package/dist/api/oauth2/private-host.js +4 -1
- package/dist/api/server-upload-propagate.js +51 -15
- package/dist/api/server-upload.js +50 -13
- package/dist/api/sse-no-compression.js +4 -1
- package/dist/api/static/frame-policy.js +9 -4
- package/dist/api/static/precompressed-asset.js +57 -15
- package/dist/api/static/spa-mount.js +47 -8
- package/dist/api/static/spa-static.js +12 -5
- package/dist/api/tarball-manifest.js +44 -7
- package/dist/api/trpc/cap-mount-helpers.js +12 -7
- package/dist/api/trpc/cap-route-error-formatter.js +13 -10
- package/dist/api/trpc/cap-router-runtime.js +51 -40
- package/dist/api/trpc/client-ip.js +20 -9
- package/dist/api/trpc/core-cap-bridge.js +42 -32
- package/dist/api/trpc/device-collection-dispatch.js +27 -23
- package/dist/api/trpc/device-config-secret-redaction.js +40 -24
- package/dist/api/trpc/generated-cap-mounts.js +222 -218
- package/dist/api/trpc/generated-cap-routers.js +4856 -4676
- package/dist/api/trpc/http-request-census-hook.js +11 -8
- package/dist/api/trpc/http-request-census.js +41 -34
- package/dist/api/trpc/http-request-census.singleton.js +8 -4
- package/dist/api/trpc/localized-schema-paths.js +4 -1
- package/dist/api/trpc/principal-visibility.js +22 -14
- package/dist/api/trpc/remote-addon-update-grant.js +4 -1
- package/dist/api/trpc/scope-access.js +15 -10
- package/dist/api/trpc/server-provided-caps.js +7 -3
- package/dist/api/trpc/share-view-access.js +14 -6
- package/dist/api/trpc/trpc-error-device-tags.js +6 -3
- package/dist/api/trpc/trpc-error-principal.js +6 -2
- package/dist/api/trpc/trpc.context.js +25 -20
- package/dist/api/trpc/trpc.middleware.js +46 -38
- package/dist/api/trpc/trpc.router.js +99 -58
- package/dist/api/trpc/user-error.js +8 -5
- package/dist/api/trpc/ws-request-census.js +24 -17
- package/dist/api/trpc/ws-slow-consumer-guard.js +16 -11
- package/dist/api/upload-auth.js +9 -5
- package/dist/auth/addon-route-jwt-gate.js +7 -4
- package/dist/auth/addon-route-share-gate.js +12 -7
- package/dist/auth/app-confirm-page.js +22 -17
- package/dist/auth/app-confirm-routes.js +31 -26
- package/dist/auth/app-confirmations.js +44 -7
- package/dist/auth/app-page-shell.js +30 -17
- package/dist/auth/app-page-strings.js +17 -11
- package/dist/auth/app-passkey-page.js +21 -16
- package/dist/auth/app-passkey-routes.js +41 -37
- package/dist/auth/app-refused-route.js +18 -13
- package/dist/auth/auth-network-policy.js +15 -11
- package/dist/auth/auth-provider-gate.js +9 -4
- package/dist/auth/auth-rate-limit.js +7 -3
- package/dist/auth/client-address.js +9 -6
- package/dist/auth/device-enroll-proofs.js +43 -6
- package/dist/auth/external-link-intents.js +7 -3
- package/dist/auth/hub-sessions.js +12 -6
- package/dist/auth/native-link-completions.js +11 -7
- package/dist/auth/native-return.js +13 -9
- package/dist/auth/passkey-provider.js +32 -26
- package/dist/auth/second-factors.js +10 -6
- package/dist/auth/session-connections.js +12 -6
- package/dist/auth/session-cookie.js +23 -12
- package/dist/auth/session-lifetimes.js +12 -8
- package/dist/auth/session-mint.js +11 -4
- package/dist/auth/sso-finish-app.js +16 -13
- package/dist/auth/sso-finish-deps.js +27 -21
- package/dist/auth/sso-finish.js +38 -28
- package/dist/auth/sso-routes.js +25 -22
- package/dist/auth/used-bridge-ids.js +5 -1
- package/dist/boot/boot-config.js +55 -16
- package/dist/boot/init-sequence.js +4 -1
- package/dist/boot/integration-id-backfill.js +8 -3
- package/dist/boot/platform-keychain-key.js +42 -5
- package/dist/boot/post-boot.service.js +18 -14
- package/dist/boot/reconcile-lifecycle-jobs.js +6 -3
- package/dist/boot/retired-public-url-env.js +8 -4
- package/dist/bootstrap-packages.js +4 -1
- package/dist/closure-node-modules.js +38 -2
- package/dist/core/addon/addon-call-gateway.js +5 -1
- package/dist/core/addon/addon-package.service.js +123 -83
- package/dist/core/addon/addon-process-view.js +6 -2
- package/dist/core/addon/addon-realign-plan.js +4 -1
- package/dist/core/addon/addon-registry.service.js +187 -146
- package/dist/core/addon/addon-row-manifest.js +4 -1
- package/dist/core/addon/addon-search.service.js +7 -3
- package/dist/core/addon/addon-settings-provider.js +3 -1
- package/dist/core/addon/addon-uninstall.js +11 -4
- package/dist/core/addon/addon.tokens.js +5 -2
- package/dist/core/addon/device-meta-mirror.js +13 -8
- package/dist/core/addon/forked-custom-actions.js +11 -6
- package/dist/core/addon/integration-visibility.js +6 -3
- package/dist/core/addon/materialize-route-path.js +4 -1
- package/dist/core/addon/package-dir-utils.js +45 -8
- package/dist/core/addon/prune-misplaced-addons.js +43 -5
- package/dist/core/addon/runner-convergence.js +4 -1
- package/dist/core/addon/runner-serialization.js +4 -1
- package/dist/core/addon/runner-spawn-fanout.js +8 -3
- package/dist/core/addon/settings-door-wiring.js +8 -5
- package/dist/core/addon/single-flight-refresh.js +4 -1
- package/dist/core/addon-bridge/addon-bridge.service.js +44 -7
- package/dist/core/addon-pages/addon-pages.service.js +40 -3
- package/dist/core/addon-widgets/addon-widgets.service.js +42 -4
- package/dist/core/agent/agent-addon-backfill.js +17 -9
- package/dist/core/agent/agent-delivery-ledger.js +7 -3
- package/dist/core/agent/agent-liveness-event.js +6 -2
- package/dist/core/agent/agent-pairing-http.js +45 -41
- package/dist/core/agent/agent-registry.service.js +89 -50
- package/dist/core/agent/cluster-node-history-mirror.js +7 -3
- package/dist/core/agent/cluster-node-history-store.js +35 -31
- package/dist/core/agent/hub-agent-pairing.js +5 -1
- package/dist/core/agent/node-certificates-client.js +6 -3
- package/dist/core/agent/node-directory.js +4 -1
- package/dist/core/app-links/well-known-app-links.js +6 -2
- package/dist/core/auth/auth.service.js +8 -3
- package/dist/core/auth/handoff-code.service.js +49 -11
- package/dist/core/auth/record-kinds.js +19 -16
- package/dist/core/auth/share-token.service.js +79 -42
- package/dist/core/capability/capability.service.js +5 -1
- package/dist/core/config/config.schema.js +6 -1
- package/dist/core/config/config.service.js +6 -2
- package/dist/core/events/event-bus.service.js +7 -3
- package/dist/core/feature/feature.service.js +6 -2
- package/dist/core/lifecycle/lifecycle-runner.singleton.js +10 -5
- package/dist/core/lifecycle/lifecycle-state-machine.js +5 -1
- package/dist/core/logging/log-ring-buffer.js +5 -1
- package/dist/core/logging/logging.service.js +9 -5
- package/dist/core/logging/scoped-logger.js +5 -1
- package/dist/core/moleculer/agent-readiness-pull.js +4 -1
- package/dist/core/moleculer/agent-registration-request.js +7 -3
- package/dist/core/moleculer/cap-call-fn.js +7 -4
- package/dist/core/moleculer/cap-route-authority.js +8 -3
- package/dist/core/moleculer/hub-mesh-guard.js +9 -5
- package/dist/core/moleculer/moleculer.service.js +86 -79
- package/dist/core/network/network-quality.service.js +6 -2
- package/dist/core/notification/notification-wrapper.service.js +7 -3
- package/dist/core/notification/toast-wrapper.service.js +7 -3
- package/dist/core/provider/provider.tokens.js +4 -1
- package/dist/core/repl/repl-engine.service.js +8 -4
- package/dist/core/runner-health/runner-boot-check.js +15 -7
- package/dist/core/runner-health/update-preflight.js +14 -9
- package/dist/core/server-update/server-update.service.js +49 -12
- package/dist/core/server-update/system-apply-closure-patches.js +42 -6
- package/dist/core/server-update/system-ensure-prebuilds.js +6 -3
- package/dist/core/server-update/system-exec-npm.js +5 -2
- package/dist/core/storage/fs-storage-backend.js +5 -1
- package/dist/core/storage/storage-location-manager.js +5 -1
- package/dist/core/storage/storage.service.js +6 -2
- package/dist/core/streaming/ffmpeg-stream-info.js +8 -3
- package/dist/core/streaming/stream-probe.service.js +16 -12
- package/dist/core/streaming/ttl-cache.js +5 -1
- package/dist/core/topology/topology-emitter.service.js +23 -19
- package/dist/core/update-availability-emitter.js +7 -3
- package/dist/core/update-availability-store.js +45 -8
- package/dist/core/updates/agent-installed-packages.js +9 -5
- package/dist/core/updates/restart-marker.js +8 -3
- package/dist/core/updates/update-check-scheduler.js +18 -13
- package/dist/core/updates/wrapper-update-checker.js +7 -3
- package/dist/first-boot-addon-plan.js +6 -2
- package/dist/framework-nodepath.js +38 -2
- package/dist/i18n/request-lang.js +11 -7
- package/dist/launcher.js +65 -30
- package/dist/lifecycle-journal-path.js +38 -2
- package/dist/main.js +324 -286
- package/dist/manual-boot.js +156 -117
- package/dist/node-role.js +4 -1
- package/dist/package-inventory.js +48 -7
- package/dist/pending-restore.js +43 -7
- package/dist/single-copy-cleanup-runner.js +45 -9
- package/dist/single-copy-cleanup.js +15 -7
- package/dist/sqlite-restore.js +48 -9
- package/dist/starter.js +39 -4
- package/dist/ui-serving/lazy-ui-serving.js +39 -3
- package/package.json +1 -1
|
@@ -1,3 +1,39 @@
|
|
|
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.registerServerUploadPropagateRoute = registerServerUploadPropagateRoute;
|
|
1
37
|
/**
|
|
2
38
|
* POST /api/server-upload/propagate — deliver an already-uploaded
|
|
3
39
|
* `dev-uploads/<version>/` set from the hub onto one agent, then leave
|
|
@@ -6,13 +42,13 @@
|
|
|
6
42
|
* Mirrors addon fan-out: pack the version dir → stage one-shot hub-http
|
|
7
43
|
* ticket → `$agent.stageDevUploads`. Does NOT promote the closure.
|
|
8
44
|
*/
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
45
|
+
const fs = __importStar(require("node:fs"));
|
|
46
|
+
const path = __importStar(require("node:path"));
|
|
47
|
+
const agent_addon_delivery_js_1 = require("./agent-addon-delivery.js");
|
|
48
|
+
const addon_upload_js_1 = require("./addon-upload.js");
|
|
49
|
+
const dev_uploads_bundle_js_1 = require("./dev-uploads-bundle.js");
|
|
50
|
+
const upload_auth_js_1 = require("./upload-auth.js");
|
|
51
|
+
const index_js_1 = require("../server-root/index.js");
|
|
16
52
|
function isStageResponse(value) {
|
|
17
53
|
if (value === null || typeof value !== 'object')
|
|
18
54
|
return false;
|
|
@@ -34,7 +70,7 @@ function readBody(value) {
|
|
|
34
70
|
error: 'nodeId must be a top-level agent id (not "hub" and not a child runner id)',
|
|
35
71
|
};
|
|
36
72
|
}
|
|
37
|
-
if (!isSafeDevUploadVersion(body.version)) {
|
|
73
|
+
if (!(0, dev_uploads_bundle_js_1.isSafeDevUploadVersion)(body.version)) {
|
|
38
74
|
return {
|
|
39
75
|
error: `Refused: version "${body.version}" is not a safe dev-channel version ` +
|
|
40
76
|
'(expected `<base>-dev.<epochSeconds>`)',
|
|
@@ -42,10 +78,10 @@ function readBody(value) {
|
|
|
42
78
|
}
|
|
43
79
|
return { version: body.version, nodeId: body.nodeId };
|
|
44
80
|
}
|
|
45
|
-
|
|
81
|
+
function registerServerUploadPropagateRoute(fastify, options) {
|
|
46
82
|
const { authService, addonRegistry, logger, broker, resolveClusterBaseUrl } = options;
|
|
47
83
|
fastify.post('/api/server-upload/propagate', async (request, reply) => {
|
|
48
|
-
const auth = await authorizeUploadRequest({
|
|
84
|
+
const auth = await (0, upload_auth_js_1.authorizeUploadRequest)({
|
|
49
85
|
authHeader: request.headers.authorization,
|
|
50
86
|
authService,
|
|
51
87
|
addonRegistry,
|
|
@@ -59,14 +95,14 @@ export function registerServerUploadPropagateRoute(fastify, options) {
|
|
|
59
95
|
}
|
|
60
96
|
const { version, nodeId } = parsed;
|
|
61
97
|
const dataDir = path.resolve(options.dataDir ?? process.env['CAMSTACK_DATA'] ?? 'camstack-data');
|
|
62
|
-
const versionDir = devUploadVersionDir(serverRootDir(dataDir), version);
|
|
98
|
+
const versionDir = (0, index_js_1.devUploadVersionDir)((0, index_js_1.serverRootDir)(dataDir), version);
|
|
63
99
|
if (!fs.existsSync(versionDir)) {
|
|
64
100
|
return reply.status(404).send({
|
|
65
101
|
error: `No hub-side upload for ${version} at ${versionDir}. ` +
|
|
66
102
|
'Upload first with `camstack deploy-server` (POST /api/server-upload).',
|
|
67
103
|
});
|
|
68
104
|
}
|
|
69
|
-
const manifest = readDevUploadManifest(versionDir);
|
|
105
|
+
const manifest = (0, index_js_1.readDevUploadManifest)(versionDir);
|
|
70
106
|
if (manifest === null) {
|
|
71
107
|
return reply.status(400).send({
|
|
72
108
|
error: `Hub upload for ${version} has a missing or invalid manifest.json`,
|
|
@@ -86,8 +122,8 @@ export function registerServerUploadPropagateRoute(fastify, options) {
|
|
|
86
122
|
let bundle;
|
|
87
123
|
let source;
|
|
88
124
|
try {
|
|
89
|
-
bundle = await packDevUploadVersionDir(versionDir);
|
|
90
|
-
source = buildHubHttpSource(bundle, hubBaseUrl);
|
|
125
|
+
bundle = await (0, dev_uploads_bundle_js_1.packDevUploadVersionDir)(versionDir);
|
|
126
|
+
source = (0, addon_upload_js_1.buildHubHttpSource)(bundle, hubBaseUrl);
|
|
91
127
|
}
|
|
92
128
|
catch (err) {
|
|
93
129
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -97,7 +133,7 @@ export function registerServerUploadPropagateRoute(fastify, options) {
|
|
|
97
133
|
return reply.status(500).send({ error: `Failed to stage upload pack: ${message}` });
|
|
98
134
|
}
|
|
99
135
|
try {
|
|
100
|
-
const raw = await broker.call('$agent.stageDevUploads', { version, source }, { nodeID: nodeId, timeout: AGENT_DEPLOY_CONTROL_TIMEOUT_MS });
|
|
136
|
+
const raw = await broker.call('$agent.stageDevUploads', { version, source }, { nodeID: nodeId, timeout: agent_addon_delivery_js_1.AGENT_DEPLOY_CONTROL_TIMEOUT_MS });
|
|
101
137
|
if (!isStageResponse(raw) || raw.success !== true) {
|
|
102
138
|
logger.warn('server-upload propagate: malformed agent response', {
|
|
103
139
|
meta: { version, nodeId },
|
|
@@ -1,3 +1,40 @@
|
|
|
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.validateTarballSet = validateTarballSet;
|
|
37
|
+
exports.registerServerUploadRoute = registerServerUploadRoute;
|
|
1
38
|
/**
|
|
2
39
|
* POST /api/server-upload — the dev server-deploy channel's upload gateway.
|
|
3
40
|
*
|
|
@@ -23,11 +60,11 @@
|
|
|
23
60
|
* the instance (done by `registerAddonUploadRoute`) — this route only adds
|
|
24
61
|
* the handler.
|
|
25
62
|
*/
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
63
|
+
const fs = __importStar(require("node:fs"));
|
|
64
|
+
const path = __importStar(require("node:path"));
|
|
65
|
+
const index_js_1 = require("../server-root/index.js");
|
|
66
|
+
const tarball_manifest_js_1 = require("./tarball-manifest.js");
|
|
67
|
+
const upload_auth_js_1 = require("./upload-auth.js");
|
|
31
68
|
/**
|
|
32
69
|
* Version chars beyond the dev-channel shape check: strictly semver-ish
|
|
33
70
|
* (alnum, dots, dashes) so the version can never traverse out of
|
|
@@ -54,17 +91,17 @@ function flattenedTgzName(packageName) {
|
|
|
54
91
|
* is derived server-side from the validated PACKAGE name — a client
|
|
55
92
|
* filename never becomes a filesystem path.
|
|
56
93
|
*/
|
|
57
|
-
|
|
94
|
+
function validateTarballSet(files, version) {
|
|
58
95
|
const seen = new Set();
|
|
59
96
|
const validated = [];
|
|
60
97
|
for (const file of files) {
|
|
61
98
|
if (hasPathTraversal(file.filename)) {
|
|
62
99
|
return { error: `Refused: filename contains path separators (${file.filename})` };
|
|
63
100
|
}
|
|
64
|
-
if (!isTarballFilename(file.filename)) {
|
|
101
|
+
if (!(0, tarball_manifest_js_1.isTarballFilename)(file.filename)) {
|
|
65
102
|
return { error: `Refused: ${file.filename} is not a .tgz/.tar.gz archive` };
|
|
66
103
|
}
|
|
67
|
-
const manifest = readTarballManifest(file.buffer, file.filename);
|
|
104
|
+
const manifest = (0, tarball_manifest_js_1.readTarballManifest)(file.buffer, file.filename);
|
|
68
105
|
if (manifest === null) {
|
|
69
106
|
return {
|
|
70
107
|
error: `Refused: ${file.filename} is missing or has a malformed package/package.json`,
|
|
@@ -89,10 +126,10 @@ export function validateTarballSet(files, version) {
|
|
|
89
126
|
}
|
|
90
127
|
return validated;
|
|
91
128
|
}
|
|
92
|
-
|
|
129
|
+
function registerServerUploadRoute(fastify, options) {
|
|
93
130
|
const { authService, addonRegistry, logger } = options;
|
|
94
131
|
fastify.post('/api/server-upload', async (request, reply) => {
|
|
95
|
-
const auth = await authorizeUploadRequest({
|
|
132
|
+
const auth = await (0, upload_auth_js_1.authorizeUploadRequest)({
|
|
96
133
|
authHeader: request.headers.authorization,
|
|
97
134
|
authService,
|
|
98
135
|
addonRegistry,
|
|
@@ -115,7 +152,7 @@ export function registerServerUploadRoute(fastify, options) {
|
|
|
115
152
|
if (version === null || version.length === 0) {
|
|
116
153
|
return reply.status(400).send({ error: 'Missing "version" field' });
|
|
117
154
|
}
|
|
118
|
-
if (!SAFE_VERSION_RE.test(version) || !isDevChannelVersion(version)) {
|
|
155
|
+
if (!SAFE_VERSION_RE.test(version) || !(0, index_js_1.isDevChannelVersion)(version)) {
|
|
119
156
|
return reply.status(400).send({
|
|
120
157
|
error: `Refused: version "${version}" is not dev-channel shaped — this route only ` +
|
|
121
158
|
'accepts `<base>-dev.<epochSeconds>` versions produced by `camstack deploy-server`.',
|
|
@@ -130,7 +167,7 @@ export function registerServerUploadRoute(fastify, options) {
|
|
|
130
167
|
return reply.status(400).send({ error: validated.error });
|
|
131
168
|
}
|
|
132
169
|
const dataDir = path.resolve(options.dataDir ?? process.env['CAMSTACK_DATA'] ?? 'camstack-data');
|
|
133
|
-
const versionDir = devUploadVersionDir(serverRootDir(dataDir), version);
|
|
170
|
+
const versionDir = (0, index_js_1.devUploadVersionDir)((0, index_js_1.serverRootDir)(dataDir), version);
|
|
134
171
|
fs.mkdirSync(versionDir, { recursive: true });
|
|
135
172
|
const packages = {};
|
|
136
173
|
for (const pkg of validated) {
|
|
@@ -138,7 +175,7 @@ export function registerServerUploadRoute(fastify, options) {
|
|
|
138
175
|
fs.writeFileSync(path.join(versionDir, tgzName), pkg.buffer);
|
|
139
176
|
packages[pkg.name] = tgzName;
|
|
140
177
|
}
|
|
141
|
-
writeDevUploadManifest(versionDir, { version, packages });
|
|
178
|
+
(0, index_js_1.writeDevUploadManifest)(versionDir, { version, packages });
|
|
142
179
|
logger.info('server-upload stored dev closure', {
|
|
143
180
|
meta: { version, packages: Object.keys(packages), dir: versionDir },
|
|
144
181
|
});
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.markSseRequestNoCompression = markSseRequestNoCompression;
|
|
1
4
|
/** Mutates the request headers in place; returns whether it marked the request. */
|
|
2
|
-
|
|
5
|
+
function markSseRequestNoCompression(request) {
|
|
3
6
|
const accept = request.headers.accept;
|
|
4
7
|
if (typeof accept === 'string' && accept.includes('text/event-stream')) {
|
|
5
8
|
request.headers['x-no-compression'] = '1';
|
|
@@ -1,8 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FRAME_ANCESTORS_POLICY = void 0;
|
|
4
|
+
exports.isFramePolicyTarget = isFramePolicyTarget;
|
|
5
|
+
exports.registerFramePolicy = registerFramePolicy;
|
|
1
6
|
/** The one directive: frame me from my origin only. */
|
|
2
|
-
|
|
7
|
+
exports.FRAME_ANCESTORS_POLICY = "frame-ancestors 'self'";
|
|
3
8
|
const CSP_HEADER = 'content-security-policy';
|
|
4
9
|
/** Only a document can be framed; assets, JSON and streams are never one. */
|
|
5
|
-
|
|
10
|
+
function isFramePolicyTarget(contentType) {
|
|
6
11
|
return typeof contentType === 'string' && contentType.trim().toLowerCase().startsWith('text/html');
|
|
7
12
|
}
|
|
8
13
|
/**
|
|
@@ -11,13 +16,13 @@ export function isFramePolicyTarget(contentType) {
|
|
|
11
16
|
* reverse proxy's streaming path) are not seen here; they carry no HTML
|
|
12
17
|
* shell of ours.
|
|
13
18
|
*/
|
|
14
|
-
|
|
19
|
+
function registerFramePolicy(fastify) {
|
|
15
20
|
fastify.addHook('onSend', async (_request, reply, payload) => {
|
|
16
21
|
if (!isFramePolicyTarget(reply.getHeader('content-type')))
|
|
17
22
|
return payload;
|
|
18
23
|
if (reply.getHeader(CSP_HEADER) !== undefined)
|
|
19
24
|
return payload;
|
|
20
|
-
reply.header(CSP_HEADER, FRAME_ANCESTORS_POLICY);
|
|
25
|
+
reply.header(CSP_HEADER, exports.FRAME_ANCESTORS_POLICY);
|
|
21
26
|
return payload;
|
|
22
27
|
});
|
|
23
28
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
/**
|
|
2
3
|
* Brotli-compressed copies of static SPA assets, cached on disk.
|
|
3
4
|
*
|
|
@@ -16,12 +17,53 @@
|
|
|
16
17
|
* The first request for a given file still pays the compression, exactly as
|
|
17
18
|
* every request does today. Every request after it pays nothing.
|
|
18
19
|
*/
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
20
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
21
|
+
if (k2 === undefined) k2 = k;
|
|
22
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
23
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
24
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
25
|
+
}
|
|
26
|
+
Object.defineProperty(o, k2, desc);
|
|
27
|
+
}) : (function(o, m, k, k2) {
|
|
28
|
+
if (k2 === undefined) k2 = k;
|
|
29
|
+
o[k2] = m[k];
|
|
30
|
+
}));
|
|
31
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
32
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
33
|
+
}) : function(o, v) {
|
|
34
|
+
o["default"] = v;
|
|
35
|
+
});
|
|
36
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
37
|
+
var ownKeys = function(o) {
|
|
38
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
39
|
+
var ar = [];
|
|
40
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
41
|
+
return ar;
|
|
42
|
+
};
|
|
43
|
+
return ownKeys(o);
|
|
44
|
+
};
|
|
45
|
+
return function (mod) {
|
|
46
|
+
if (mod && mod.__esModule) return mod;
|
|
47
|
+
var result = {};
|
|
48
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
49
|
+
__setModuleDefault(result, mod);
|
|
50
|
+
return result;
|
|
51
|
+
};
|
|
52
|
+
})();
|
|
53
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
54
|
+
exports.acceptsBrotli = acceptsBrotli;
|
|
55
|
+
exports.isCompressibleAsset = isCompressibleAsset;
|
|
56
|
+
exports.resolvePrecompressedAsset = resolvePrecompressedAsset;
|
|
57
|
+
exports.warmPrecompressedAssets = warmPrecompressedAssets;
|
|
58
|
+
exports.resetPrecompressedWarning = resetPrecompressedWarning;
|
|
59
|
+
exports.precompressedTempPath = precompressedTempPath;
|
|
60
|
+
exports.precompressedSiblingExists = precompressedSiblingExists;
|
|
61
|
+
const fs = __importStar(require("node:fs"));
|
|
62
|
+
const fsp = __importStar(require("node:fs/promises"));
|
|
63
|
+
const path = __importStar(require("node:path"));
|
|
64
|
+
const node_zlib_1 = require("node:zlib");
|
|
65
|
+
const node_util_1 = require("node:util");
|
|
66
|
+
const brotli = (0, node_util_1.promisify)(node_zlib_1.brotliCompress);
|
|
25
67
|
/** Below this, the framing costs more than the compression saves — the same
|
|
26
68
|
* threshold `@fastify/compress` is registered with. */
|
|
27
69
|
const MIN_BYTES = 1024;
|
|
@@ -35,12 +77,12 @@ const inFlight = new Map();
|
|
|
35
77
|
* error to repeat on every asset. */
|
|
36
78
|
let warnedUnwritable = false;
|
|
37
79
|
/** Does the client accept brotli? */
|
|
38
|
-
|
|
80
|
+
function acceptsBrotli(acceptEncoding) {
|
|
39
81
|
if (acceptEncoding === undefined)
|
|
40
82
|
return false;
|
|
41
83
|
return /\bbr\b/.test(acceptEncoding);
|
|
42
84
|
}
|
|
43
|
-
|
|
85
|
+
function isCompressibleAsset(relOrAbs) {
|
|
44
86
|
return COMPRESSIBLE.test(relOrAbs);
|
|
45
87
|
}
|
|
46
88
|
/**
|
|
@@ -66,8 +108,8 @@ async function compressToDisk(filePath, brPath, log) {
|
|
|
66
108
|
params: {
|
|
67
109
|
// Quality 11 is worth it BECAUSE this runs once. The per-request path
|
|
68
110
|
// could never afford it, which is why it was set to 4.
|
|
69
|
-
[
|
|
70
|
-
[
|
|
111
|
+
[node_zlib_1.constants.BROTLI_PARAM_QUALITY]: 11,
|
|
112
|
+
[node_zlib_1.constants.BROTLI_PARAM_SIZE_HINT]: raw.byteLength,
|
|
71
113
|
},
|
|
72
114
|
});
|
|
73
115
|
// Write via a temp file + rename so a concurrent reader never sees a
|
|
@@ -100,7 +142,7 @@ async function compressToDisk(filePath, brPath, log) {
|
|
|
100
142
|
* cache could not be written. The caller then serves exactly what it served
|
|
101
143
|
* before, so this can only ever be an optimisation.
|
|
102
144
|
*/
|
|
103
|
-
|
|
145
|
+
async function resolvePrecompressedAsset(filePath, acceptEncoding, log) {
|
|
104
146
|
const plain = { filePath, encoding: null };
|
|
105
147
|
if (!acceptsBrotli(acceptEncoding) || !isCompressibleAsset(filePath))
|
|
106
148
|
return plain;
|
|
@@ -141,7 +183,7 @@ export async function resolvePrecompressedAsset(filePath, acceptEncoding, log) {
|
|
|
141
183
|
* a page load faster would be a bad trade. Failures are silent here — the
|
|
142
184
|
* request path logs them if it ever hits one.
|
|
143
185
|
*/
|
|
144
|
-
|
|
186
|
+
function warmPrecompressedAssets(root, log) {
|
|
145
187
|
void (async () => {
|
|
146
188
|
let warmed = 0;
|
|
147
189
|
for (const file of await listCompressible(root)) {
|
|
@@ -171,7 +213,7 @@ async function listCompressible(dir, out = []) {
|
|
|
171
213
|
return out;
|
|
172
214
|
}
|
|
173
215
|
/** Test seam — the "read-only dist" warning is once per process. */
|
|
174
|
-
|
|
216
|
+
function resetPrecompressedWarning() {
|
|
175
217
|
warnedUnwritable = false;
|
|
176
218
|
}
|
|
177
219
|
/**
|
|
@@ -180,10 +222,10 @@ export function resetPrecompressedWarning() {
|
|
|
180
222
|
* root, which is what CI runs as, and the test that relied on it produced a
|
|
181
223
|
* `.br` in a "read-only" directory (2026-09-23).
|
|
182
224
|
*/
|
|
183
|
-
|
|
225
|
+
function precompressedTempPath(brPath) {
|
|
184
226
|
return `${brPath}.${String(process.pid)}.tmp`;
|
|
185
227
|
}
|
|
186
228
|
/** Synchronous existence probe used by the callers' own guards. */
|
|
187
|
-
|
|
229
|
+
function precompressedSiblingExists(filePath) {
|
|
188
230
|
return fs.existsSync(`${filePath}.br`);
|
|
189
231
|
}
|
|
@@ -1,3 +1,42 @@
|
|
|
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.FORWARDED_PREFIX_HEADER = void 0;
|
|
37
|
+
exports.parseForwardedPrefix = parseForwardedPrefix;
|
|
38
|
+
exports.injectSpaMount = injectSpaMount;
|
|
39
|
+
exports.sendSpaShell = sendSpaShell;
|
|
1
40
|
/**
|
|
2
41
|
* spa-mount — serving the admin-UI shell under a reverse-proxy path prefix.
|
|
3
42
|
*
|
|
@@ -15,10 +54,10 @@
|
|
|
15
54
|
*
|
|
16
55
|
* Without the header nothing changes — the shell is served exactly as before.
|
|
17
56
|
*/
|
|
18
|
-
|
|
19
|
-
|
|
57
|
+
const fs = __importStar(require("node:fs/promises"));
|
|
58
|
+
const spa_static_1 = require("./spa-static");
|
|
20
59
|
/** Node lower-cases incoming header names. */
|
|
21
|
-
|
|
60
|
+
exports.FORWARDED_PREFIX_HEADER = 'x-forwarded-prefix';
|
|
22
61
|
/** The canonical spelling, for `Vary`. */
|
|
23
62
|
const FORWARDED_PREFIX_VARY = 'X-Forwarded-Prefix';
|
|
24
63
|
const MOUNT_META_NAME = 'camstack-mount';
|
|
@@ -34,7 +73,7 @@ const MAX_PREFIX_LENGTH = 512;
|
|
|
34
73
|
* an attribute. Invalid is treated as absent — a relay that gets this wrong
|
|
35
74
|
* gets the root shell, never a 4xx and never a partial injection.
|
|
36
75
|
*/
|
|
37
|
-
|
|
76
|
+
function parseForwardedPrefix(value) {
|
|
38
77
|
if (typeof value !== 'string')
|
|
39
78
|
return null;
|
|
40
79
|
if (value.length === 0 || value.length > MAX_PREFIX_LENGTH)
|
|
@@ -61,7 +100,7 @@ export function parseForwardedPrefix(value) {
|
|
|
61
100
|
* relative build shipped, and only the root worked (operator, 2026-09-07).
|
|
62
101
|
* A root mount is therefore `<base href="/">`, not "no base at all".
|
|
63
102
|
*/
|
|
64
|
-
|
|
103
|
+
function injectSpaMount(html, prefix) {
|
|
65
104
|
const match = /<head(?:\s[^>]*)?>/i.exec(html);
|
|
66
105
|
if (match === null)
|
|
67
106
|
return html;
|
|
@@ -75,8 +114,8 @@ export function injectSpaMount(html, prefix) {
|
|
|
75
114
|
* `Vary: X-Forwarded-Prefix` — a cache that ignores `no-store` must still
|
|
76
115
|
* never hand a root shell to a relayed request or vice versa.
|
|
77
116
|
*/
|
|
78
|
-
|
|
79
|
-
reply.header('cache-control', spaShellCacheControl());
|
|
117
|
+
async function sendSpaShell(reply, indexPath, headers) {
|
|
118
|
+
reply.header('cache-control', (0, spa_static_1.spaShellCacheControl)());
|
|
80
119
|
reply.header('vary', FORWARDED_PREFIX_VARY);
|
|
81
120
|
let html;
|
|
82
121
|
try {
|
|
@@ -88,6 +127,6 @@ export async function sendSpaShell(reply, indexPath, headers) {
|
|
|
88
127
|
}
|
|
89
128
|
// `''` is the root mount: `injectSpaMount` writes `<base href="/">`, which a
|
|
90
129
|
// relative-asset shell needs at every depth. Never "no base".
|
|
91
|
-
const prefix = parseForwardedPrefix(headers[FORWARDED_PREFIX_HEADER]) ?? '';
|
|
130
|
+
const prefix = parseForwardedPrefix(headers[exports.FORWARDED_PREFIX_HEADER]) ?? '';
|
|
92
131
|
return reply.type('text/html').send(injectSpaMount(html, prefix));
|
|
93
132
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
/**
|
|
2
3
|
* spa-static — shared static-serving helpers for the SPAs the hub mounts
|
|
3
4
|
* (admin-ui at `/`, viewer-ui at `/viewer/camstack`). Extracted so both
|
|
@@ -5,6 +6,12 @@
|
|
|
5
6
|
* immutable; the service worker / registration / web manifest + the SPA shell
|
|
6
7
|
* (`index.html`) always revalidate so a redeploy actually reaches clients.
|
|
7
8
|
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.spaShellCacheControl = spaShellCacheControl;
|
|
11
|
+
exports.spaAssetCacheControl = spaAssetCacheControl;
|
|
12
|
+
exports.addonBundleCacheControl = addonBundleCacheControl;
|
|
13
|
+
exports.contentTypeForPath = contentTypeForPath;
|
|
14
|
+
exports.isRetiredPublicPath = isRetiredPublicPath;
|
|
8
15
|
/**
|
|
9
16
|
* Cache-Control for the SPA SHELL (`index.html`) — the HTML entry only, never a
|
|
10
17
|
* hashed asset.
|
|
@@ -22,7 +29,7 @@
|
|
|
22
29
|
* send the shell with NO header at all, which is where the stale copies came
|
|
23
30
|
* from.
|
|
24
31
|
*/
|
|
25
|
-
|
|
32
|
+
function spaShellCacheControl() {
|
|
26
33
|
return 'no-store';
|
|
27
34
|
}
|
|
28
35
|
/**
|
|
@@ -37,7 +44,7 @@ export function spaShellCacheControl() {
|
|
|
37
44
|
* so the same bytes never carry two different policies.
|
|
38
45
|
* - Everything else (favicon, non-hashed files) → `no-cache`.
|
|
39
46
|
*/
|
|
40
|
-
|
|
47
|
+
function spaAssetCacheControl(rel) {
|
|
41
48
|
const base = rel.split('/').pop() ?? rel;
|
|
42
49
|
if (/^(sw\.js|registerSW\.js|workbox-.*\.js|manifest\.webmanifest)$/.test(base)) {
|
|
43
50
|
return 'no-cache, must-revalidate';
|
|
@@ -66,7 +73,7 @@ export function spaAssetCacheControl(rel) {
|
|
|
66
73
|
* until a manual hard-reload. Unknown fixed names now revalidate — the
|
|
67
74
|
* cost is a cheap 304.
|
|
68
75
|
*/
|
|
69
|
-
|
|
76
|
+
function addonBundleCacheControl(filePath) {
|
|
70
77
|
const base = filePath.split('/').pop() ?? filePath;
|
|
71
78
|
// Vite/rolldown content hash: exactly 8 base64url chars between a
|
|
72
79
|
// hyphen and the extension (`dist-CYZr2fwk.mjs`, `….js-CQ-aEQ9b.mjs`).
|
|
@@ -107,14 +114,14 @@ const CONTENT_TYPES = {
|
|
|
107
114
|
* assets directly (the admin-ui path goes through @fastify/static). Defaults
|
|
108
115
|
* to `application/octet-stream` for unknown extensions.
|
|
109
116
|
*/
|
|
110
|
-
|
|
117
|
+
function contentTypeForPath(pathname) {
|
|
111
118
|
const base = pathname.split('/').pop() ?? pathname;
|
|
112
119
|
const dot = base.lastIndexOf('.');
|
|
113
120
|
const ext = dot >= 0 ? base.slice(dot + 1).toLowerCase() : '';
|
|
114
121
|
return CONTENT_TYPES[ext] ?? 'application/octet-stream';
|
|
115
122
|
}
|
|
116
123
|
/** Paths intentionally retired instead of falling through to the admin SPA. */
|
|
117
|
-
|
|
124
|
+
function isRetiredPublicPath(url) {
|
|
118
125
|
const pathname = url.split('?')[0] ?? url;
|
|
119
126
|
return (pathname === '/addon/stream-broker/embed' || pathname.startsWith('/addon/stream-broker/embed/'));
|
|
120
127
|
}
|
|
@@ -1,14 +1,51 @@
|
|
|
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.isTarballFilename = isTarballFilename;
|
|
37
|
+
exports.readTarballManifest = readTarballManifest;
|
|
1
38
|
/**
|
|
2
39
|
* npm-pack tarball manifest inspection — shared by the addon upload route
|
|
3
40
|
* (`/api/addons/upload`) and the dev server-deploy upload route
|
|
4
41
|
* (`/api/server-upload`).
|
|
5
42
|
*/
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
43
|
+
const node_child_process_1 = require("node:child_process");
|
|
44
|
+
const fs = __importStar(require("node:fs"));
|
|
45
|
+
const os = __importStar(require("node:os"));
|
|
46
|
+
const path = __importStar(require("node:path"));
|
|
10
47
|
const TARBALL_EXTENSIONS = ['.tgz', '.tar.gz'];
|
|
11
|
-
|
|
48
|
+
function isTarballFilename(filename) {
|
|
12
49
|
return TARBALL_EXTENSIONS.some((ext) => filename.endsWith(ext));
|
|
13
50
|
}
|
|
14
51
|
/**
|
|
@@ -23,12 +60,12 @@ export function isTarballFilename(filename) {
|
|
|
23
60
|
* fixed inner path. Returns null (not throw) on malformed archives so
|
|
24
61
|
* the caller can surface a precise 400 response.
|
|
25
62
|
*/
|
|
26
|
-
|
|
63
|
+
function readTarballManifest(buffer, filename) {
|
|
27
64
|
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'camstack-tarball-check-'));
|
|
28
65
|
const tgzPath = path.join(tmpDir, path.basename(filename));
|
|
29
66
|
try {
|
|
30
67
|
fs.writeFileSync(tgzPath, buffer);
|
|
31
|
-
const output = execFileSync('tar', ['-xzO', '-f', tgzPath, 'package/package.json'], {
|
|
68
|
+
const output = (0, node_child_process_1.execFileSync)('tar', ['-xzO', '-f', tgzPath, 'package/package.json'], {
|
|
32
69
|
timeout: 5_000,
|
|
33
70
|
stdio: ['ignore', 'pipe', 'ignore'],
|
|
34
71
|
});
|