@teamscala/service-boot 0.23.413 → 0.23.415

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.
@@ -0,0 +1,64 @@
1
+ /**
2
+ * @system ui-service-boot
3
+ * @status handwritten
4
+ * @edit edit directly
5
+ *
6
+ * Block-coverage guard (protective-layers-fail-explicitly) for registered
7
+ * page routes.
8
+ *
9
+ * Split out of register-registry-page-route.ts (924 lines) — byte-for-byte
10
+ * move; only the import paths adjusted.
11
+ */
12
+
13
+ import { getAppLogger } from "@teamscala/logger/app-loggers";
14
+ import type { RendererComponentEntry } from "../types.ts";
15
+
16
+ /**
17
+ * A page that renders a block whose component is NOT registered — because
18
+ * its package is missing from service_install.config.block_packages —
19
+ * silently renders BLANK. That is the exact failure behind the 2026-06-04
20
+ * scala-sign regression (sign-in-block dropped from block_packages → the
21
+ * gate + signature fields vanished) which left only a benign boot WARN.
22
+ * This turns that silent blank into a loud, GlitchTip-visible ERROR naming
23
+ * the page + block, throttled to once per (service, block type) so a hot
24
+ * path can never spam it.
25
+ */
26
+ const uncoveredBlocksLogged = new Set<string>();
27
+
28
+ function collectBlockTypes(node: unknown, out: Set<string>): void {
29
+ if (Array.isArray(node)) {
30
+ for (const child of node) collectBlockTypes(child, out);
31
+ return;
32
+ }
33
+ if (node && typeof node === "object") {
34
+ const obj = node as Record<string, unknown>;
35
+ if (
36
+ typeof obj.type === "string" &&
37
+ obj.props &&
38
+ typeof obj.props === "object"
39
+ ) {
40
+ out.add(obj.type);
41
+ }
42
+ for (const value of Object.values(obj)) collectBlockTypes(value, out);
43
+ }
44
+ }
45
+
46
+ export function warnUncoveredBlocks(
47
+ pageData: unknown,
48
+ components: Record<string, RendererComponentEntry>,
49
+ serviceSlug: string,
50
+ path: unknown,
51
+ log: ReturnType<typeof getAppLogger>,
52
+ ): void {
53
+ const used = new Set<string>();
54
+ collectBlockTypes(pageData, used);
55
+ for (const type of used) {
56
+ if (type in components) continue;
57
+ const key = `${serviceSlug}:${type}`;
58
+ if (uncoveredBlocksLogged.has(key)) continue;
59
+ uncoveredBlocksLogged.add(key);
60
+ log.error(
61
+ `[scala-install:${serviceSlug}] page "${String(path)}" renders block "${type}" but NO component is registered for it — its package is almost certainly missing from service_install.config.block_packages, so it renders BLANK. Add the owning @teamscala/* package to block_packages and restart. (block-coverage guard)`,
62
+ );
63
+ }
64
+ }