@objectstack/objectql 4.0.1 → 4.0.3

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/src/registry.ts CHANGED
@@ -144,8 +144,8 @@ export class SchemaRegistry {
144
144
  /** FQN → Merged ServiceObject (cached, invalidated on changes) */
145
145
  private static mergedObjectCache = new Map<string, ServiceObject>();
146
146
 
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>>();
149
149
 
150
150
  // ==========================================
151
151
  // Generic metadata storage (non-object types)
@@ -160,22 +160,17 @@ export class SchemaRegistry {
160
160
 
161
161
  /**
162
162
  * 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').
166
164
  */
167
165
  static registerNamespace(namespace: string, packageId: string): void {
168
166
  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);
176
172
  }
177
-
178
- this.namespaceRegistry.set(namespace, packageId);
173
+ owners.add(packageId);
179
174
  this.log(`[Registry] Registered namespace: ${namespace} → ${packageId}`);
180
175
  }
181
176
 
@@ -183,18 +178,32 @@ export class SchemaRegistry {
183
178
  * Unregister a namespace when a package is uninstalled.
184
179
  */
185
180
  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}`);
190
188
  }
191
189
  }
192
190
 
193
191
  /**
194
- * Get the package that owns a namespace.
192
+ * Get the packages that use a namespace.
195
193
  */
196
194
  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) : [];
198
207
  }
199
208
 
200
209
  // ==========================================
@@ -476,7 +485,7 @@ export class SchemaRegistry {
476
485
  if (type === 'object') {
477
486
  return ObjectSchema.parse(item);
478
487
  }
479
- if (type === 'apps') {
488
+ if (type === 'app') {
480
489
  return AppSchema.parse(item);
481
490
  }
482
491
  if (type === 'package') {
@@ -541,7 +550,7 @@ export class SchemaRegistry {
541
550
  if (type === 'object' || type === 'objects') {
542
551
  return this.getAllObjects(packageId) as unknown as T[];
543
552
  }
544
-
553
+
545
554
  const items = Array.from(this.metadata.get(type)?.values() || []) as T[];
546
555
  if (packageId) {
547
556
  return items.filter((item: any) => item._packageId === packageId);
@@ -655,15 +664,15 @@ export class SchemaRegistry {
655
664
  // ==========================================
656
665
 
657
666
  static registerApp(app: any, packageId?: string) {
658
- this.registerItem('apps', app, 'name', packageId);
667
+ this.registerItem('app', app, 'name', packageId);
659
668
  }
660
669
 
661
670
  static getApp(name: string): any {
662
- return this.getItem('apps', name);
671
+ return this.getItem('app', name);
663
672
  }
664
673
 
665
674
  static getAllApps(): any[] {
666
- return this.listItems('apps');
675
+ return this.listItems('app');
667
676
  }
668
677
 
669
678
  // ==========================================