Skip to content

Commit 41f8c3a

Browse files
committed
fix: update namespace handling in SchemaRegistry to allow multiple packages per namespace
1 parent a8900a4 commit 41f8c3a

2 files changed

Lines changed: 30 additions & 20 deletions

File tree

packages/objectql/src/registry.ts

Lines changed: 29 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -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
// ==========================================

packages/plugins/plugin-setup/src/setup-plugin.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ export class SetupPlugin implements Plugin {
8282
name: 'Setup',
8383
version: '1.0.0',
8484
type: 'plugin',
85+
namespace: 'sys',
8586
objects: [],
8687
apps: [setupApp],
8788
});

0 commit comments

Comments
 (0)