From 1a657e2a64e9186f3458605a4d4b101c6fdb3d01 Mon Sep 17 00:00:00 2001 From: Sameh Khamis Date: Thu, 12 Nov 2026 16:04:55 -0800 Subject: [PATCH] Keep the library layer namespace in the layer lifecycle package The core layer lifecycle imported the whole Data Library manifest contract only to check the lib- prefix, so the layer-lifecycle package owned a feature module. The namespace rule (prefix, entry id pattern, the two id helpers) now lives in src/data/libraryLayerIds.js, which the lifecycle owns; the manifest contract imports and re-exports it, so library callers are unchanged. --- scripts/package-boundaries.json | 3 ++- src/data/libraryLayerIds.js | 22 ++++++++++++++++++++++ src/data/lifecycle.js | 2 +- src/library/manifest.js | 27 +++++++++++++-------------- 4 files changed, 38 insertions(+), 16 deletions(-) create mode 100644 src/data/libraryLayerIds.js diff --git a/scripts/package-boundaries.json b/scripts/package-boundaries.json index f9244b9b2..873f37f80 100644 --- a/scripts/package-boundaries.json +++ b/scripts/package-boundaries.json @@ -3500,6 +3500,7 @@ "src/voice/geminiCaptureWorklet.js", "src/ui/libraryBrowser.js", "src/library/manifest.js", + "src/data/libraryLayerIds.js", "src/library/selection.js", "src/library/ledger.json", "src/library/entries/ak-statewide-imagery.json", @@ -4571,7 +4572,7 @@ "modules": [ "src/data/lifecycle.js", "src/data/cameraArrival.js", - "src/library/manifest.js" + "src/data/libraryLayerIds.js" ], "external": [] }, diff --git a/src/data/libraryLayerIds.js b/src/data/libraryLayerIds.js new file mode 100644 index 000000000..56bb1fddd --- /dev/null +++ b/src/data/libraryLayerIds.js @@ -0,0 +1,22 @@ +/** + * The Data Library's layer namespace, owned by the layer lifecycle: the + * manager accepts a late registration only under `lib-`, and the + * library names its layers with the same rule. + */ + +/** A library entry id: lowercase, digits and hyphens, 3–48 characters. */ +export const LIBRARY_ID_PATTERN = /^[a-z0-9][a-z0-9-]{2,47}$/; +export const LIBRARY_LAYER_PREFIX = 'lib-'; + +/** The manager id a library entry's layer registers under. */ +export function libraryLayerId(entryId) { + return `${LIBRARY_LAYER_PREFIX}${entryId}`; +} + +/** The entry id behind a library layer id, or null. */ +export function libraryEntryIdOf(layerId) { + if (typeof layerId !== 'string' || !layerId.startsWith(LIBRARY_LAYER_PREFIX)) + return null; + const id = layerId.slice(LIBRARY_LAYER_PREFIX.length); + return LIBRARY_ID_PATTERN.test(id) ? id : null; +} diff --git a/src/data/lifecycle.js b/src/data/lifecycle.js index c67c4287f..97d784261 100644 --- a/src/data/lifecycle.js +++ b/src/data/lifecycle.js @@ -1,5 +1,5 @@ import { cancelCameraArrival } from './cameraArrival.js'; -import { libraryEntryIdOf } from '../library/manifest.js'; +import { libraryEntryIdOf } from './libraryLayerIds.js'; function cloneLayerParams(value) { if (Array.isArray(value)) return value.map(cloneLayerParams); diff --git a/src/library/manifest.js b/src/library/manifest.js index 5d76af235..8b4595c85 100644 --- a/src/library/manifest.js +++ b/src/library/manifest.js @@ -10,6 +10,12 @@ * this module, so it loads no catalogs and touches no DOM. See * docs/DATA-LIBRARY.md for the authoring guide. */ +import { + LIBRARY_ID_PATTERN, + LIBRARY_LAYER_PREFIX, + libraryEntryIdOf, + libraryLayerId, +} from '../data/libraryLayerIds.js'; /** The three entry kinds this build renders. */ export const LIBRARY_KINDS = Object.freeze(['dataset', 'tiles', 'pack']); @@ -88,8 +94,6 @@ export const LIBRARY_FAMILIES = Object.freeze([ /** Host layers a `pack` entry may extend, with the env switch grammar. */ export const PACK_HOSTS = Object.freeze(['cctv']); -export const LIBRARY_ID_PATTERN = /^[a-z0-9][a-z0-9-]{2,47}$/; -export const LIBRARY_LAYER_PREFIX = 'lib-'; export const DEFAULT_CACHE_SECONDS = 3600; export const MIN_CACHE_SECONDS = 60; export const MAX_CACHE_SECONDS = 86_400; @@ -742,18 +746,13 @@ export function validateLibraryCatalog(manifests) { return { ok: errors.length === 0, errors, entries }; } -/** The manager id a library entry's layer registers under. */ -export function libraryLayerId(entryId) { - return `${LIBRARY_LAYER_PREFIX}${entryId}`; -} - -/** The entry id behind a library layer id, or null. */ -export function libraryEntryIdOf(layerId) { - if (typeof layerId !== 'string' || !layerId.startsWith(LIBRARY_LAYER_PREFIX)) - return null; - const id = layerId.slice(LIBRARY_LAYER_PREFIX.length); - return LIBRARY_ID_PATTERN.test(id) ? id : null; -} +// The layer namespace belongs to the layer lifecycle; the library reads it. +export { + LIBRARY_ID_PATTERN, + LIBRARY_LAYER_PREFIX, + libraryEntryIdOf, + libraryLayerId, +}; /** * Whether the operator switched an opt-in entry on. `GEV_LIBRARY_ENABLE`