@@ -144,8 +144,8 @@ export class SchemaRegistry {
144144 /** FQN → Merged ServiceObject (cached, invalidated on changes) */
145145 private static mergedObjectCache = new Map < string , ServiceObject > ( ) ;
146146
147- /** Namespace → PackageId (ensures namespace uniqueness ) */
148- private static namespaceRegistry = new Map < string , string > ( ) ;
147+ /** Namespace → Set< PackageId> (multiple packages can share a namespace ) */
148+ private static namespaceRegistry = new Map < string , Set < string > > ( ) ;
149149
150150 // ==========================================
151151 // Generic metadata storage (non-object types)
@@ -160,41 +160,50 @@ export class SchemaRegistry {
160160
161161 /**
162162 * Register a namespace for a package.
163- * Enforces namespace uniqueness within the instance.
164- *
165- * @throws Error if namespace is already registered to a different package
163+ * Multiple packages can share the same namespace (e.g. 'sys').
166164 */
167165 static registerNamespace ( namespace : string , packageId : string ) : void {
168166 if ( ! namespace ) return ;
169-
170- const existing = this . namespaceRegistry . get ( namespace ) ;
171- if ( existing && existing !== packageId ) {
172- throw new Error (
173- `Namespace "${ namespace } " is already registered to package "${ existing } ". ` +
174- `Package "${ packageId } " cannot use the same namespace.`
175- ) ;
167+
168+ let owners = this . namespaceRegistry . get ( namespace ) ;
169+ if ( ! owners ) {
170+ owners = new Set ( ) ;
171+ this . namespaceRegistry . set ( namespace , owners ) ;
176172 }
177-
178- this . namespaceRegistry . set ( namespace , packageId ) ;
173+ owners . add ( packageId ) ;
179174 this . log ( `[Registry] Registered namespace: ${ namespace } → ${ packageId } ` ) ;
180175 }
181176
182177 /**
183178 * Unregister a namespace when a package is uninstalled.
184179 */
185180 static unregisterNamespace ( namespace : string , packageId : string ) : void {
186- const existing = this . namespaceRegistry . get ( namespace ) ;
187- if ( existing === packageId ) {
188- this . namespaceRegistry . delete ( namespace ) ;
189- this . log ( `[Registry] Unregistered namespace: ${ namespace } ` ) ;
181+ const owners = this . namespaceRegistry . get ( namespace ) ;
182+ if ( owners ) {
183+ owners . delete ( packageId ) ;
184+ if ( owners . size === 0 ) {
185+ this . namespaceRegistry . delete ( namespace ) ;
186+ }
187+ this . log ( `[Registry] Unregistered namespace: ${ namespace } ← ${ packageId } ` ) ;
190188 }
191189 }
192190
193191 /**
194- * Get the package that owns a namespace.
192+ * Get the packages that use a namespace.
195193 */
196194 static getNamespaceOwner ( namespace : string ) : string | undefined {
197- return this . namespaceRegistry . get ( namespace ) ;
195+ const owners = this . namespaceRegistry . get ( namespace ) ;
196+ if ( ! owners || owners . size === 0 ) return undefined ;
197+ // Return the first registered package for backwards compatibility
198+ return owners . values ( ) . next ( ) . value ;
199+ }
200+
201+ /**
202+ * Get all packages that share a namespace.
203+ */
204+ static getNamespaceOwners ( namespace : string ) : string [ ] {
205+ const owners = this . namespaceRegistry . get ( namespace ) ;
206+ return owners ? Array . from ( owners ) : [ ] ;
198207 }
199208
200209 // ==========================================
0 commit comments