@objectstack/metadata 2.0.6 → 3.0.0

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/dist/index.mjs CHANGED
@@ -179,6 +179,14 @@ var MetadataManager = class {
179
179
  constructor(config) {
180
180
  this.loaders = /* @__PURE__ */ new Map();
181
181
  this.watchCallbacks = /* @__PURE__ */ new Map();
182
+ // In-memory metadata registry: type -> name -> data
183
+ this.registry = /* @__PURE__ */ new Map();
184
+ // Overlay storage: "type:name:scope" -> MetadataOverlay
185
+ this.overlays = /* @__PURE__ */ new Map();
186
+ // Type registry for metadata type info
187
+ this.typeRegistry = [];
188
+ // Dependency tracking: "type:name" -> dependencies
189
+ this.dependencies = /* @__PURE__ */ new Map();
182
190
  this.config = config;
183
191
  this.logger = createLogger({ level: "info", format: "pretty" });
184
192
  this.serializers = /* @__PURE__ */ new Map();
@@ -199,6 +207,12 @@ var MetadataManager = class {
199
207
  config.loaders.forEach((loader) => this.registerLoader(loader));
200
208
  }
201
209
  }
210
+ /**
211
+ * Set the type registry for metadata type discovery.
212
+ */
213
+ setTypeRegistry(entries) {
214
+ this.typeRegistry = entries;
215
+ }
202
216
  /**
203
217
  * Register a new metadata loader (data source)
204
218
  */
@@ -206,9 +220,513 @@ var MetadataManager = class {
206
220
  this.loaders.set(loader.contract.name, loader);
207
221
  this.logger.info(`Registered metadata loader: ${loader.contract.name} (${loader.contract.protocol})`);
208
222
  }
223
+ // ==========================================
224
+ // IMetadataService — Core CRUD Operations
225
+ // ==========================================
226
+ /**
227
+ * Register/save a metadata item by type
228
+ */
229
+ async register(type, name, data) {
230
+ if (!this.registry.has(type)) {
231
+ this.registry.set(type, /* @__PURE__ */ new Map());
232
+ }
233
+ this.registry.get(type).set(name, data);
234
+ }
235
+ /**
236
+ * Get a metadata item by type and name.
237
+ * Checks in-memory registry first, then falls back to loaders.
238
+ */
239
+ async get(type, name) {
240
+ const typeStore = this.registry.get(type);
241
+ if (typeStore?.has(name)) {
242
+ return typeStore.get(name);
243
+ }
244
+ const result = await this.load(type, name);
245
+ return result ?? void 0;
246
+ }
247
+ /**
248
+ * List all metadata items of a given type
249
+ */
250
+ async list(type) {
251
+ const items = /* @__PURE__ */ new Map();
252
+ const typeStore = this.registry.get(type);
253
+ if (typeStore) {
254
+ for (const [name, data] of typeStore) {
255
+ items.set(name, data);
256
+ }
257
+ }
258
+ for (const loader of this.loaders.values()) {
259
+ try {
260
+ const loaderItems = await loader.loadMany(type);
261
+ for (const item of loaderItems) {
262
+ const itemAny = item;
263
+ if (itemAny && typeof itemAny.name === "string" && !items.has(itemAny.name)) {
264
+ items.set(itemAny.name, item);
265
+ }
266
+ }
267
+ } catch (e) {
268
+ this.logger.warn(`Loader ${loader.contract.name} failed to loadMany ${type}`, { error: e });
269
+ }
270
+ }
271
+ return Array.from(items.values());
272
+ }
273
+ /**
274
+ * Unregister/remove a metadata item by type and name
275
+ */
276
+ async unregister(type, name) {
277
+ const typeStore = this.registry.get(type);
278
+ if (typeStore) {
279
+ typeStore.delete(name);
280
+ if (typeStore.size === 0) {
281
+ this.registry.delete(type);
282
+ }
283
+ }
284
+ }
285
+ /**
286
+ * Check if a metadata item exists
287
+ */
288
+ async exists(type, name) {
289
+ if (this.registry.get(type)?.has(name)) {
290
+ return true;
291
+ }
292
+ for (const loader of this.loaders.values()) {
293
+ if (await loader.exists(type, name)) {
294
+ return true;
295
+ }
296
+ }
297
+ return false;
298
+ }
299
+ /**
300
+ * List all names of metadata items of a given type
301
+ */
302
+ async listNames(type) {
303
+ const names = /* @__PURE__ */ new Set();
304
+ const typeStore = this.registry.get(type);
305
+ if (typeStore) {
306
+ for (const name of typeStore.keys()) {
307
+ names.add(name);
308
+ }
309
+ }
310
+ for (const loader of this.loaders.values()) {
311
+ const result = await loader.list(type);
312
+ result.forEach((item) => names.add(item));
313
+ }
314
+ return Array.from(names);
315
+ }
316
+ /**
317
+ * Convenience: get an object definition by name
318
+ */
319
+ async getObject(name) {
320
+ return this.get("object", name);
321
+ }
322
+ /**
323
+ * Convenience: list all object definitions
324
+ */
325
+ async listObjects() {
326
+ return this.list("object");
327
+ }
328
+ // ==========================================
329
+ // Package Management
330
+ // ==========================================
331
+ /**
332
+ * Unregister all metadata items from a specific package
333
+ */
334
+ async unregisterPackage(packageName) {
335
+ for (const [type, typeStore] of this.registry) {
336
+ const toDelete = [];
337
+ for (const [name, data] of typeStore) {
338
+ const meta = data;
339
+ if (meta?.packageId === packageName || meta?.package === packageName) {
340
+ toDelete.push(name);
341
+ }
342
+ }
343
+ for (const name of toDelete) {
344
+ typeStore.delete(name);
345
+ }
346
+ if (typeStore.size === 0) {
347
+ this.registry.delete(type);
348
+ }
349
+ }
350
+ }
351
+ // ==========================================
352
+ // Query / Search
353
+ // ==========================================
354
+ /**
355
+ * Query metadata items with filtering, sorting, and pagination
356
+ */
357
+ async query(query) {
358
+ const { types, search, page = 1, pageSize = 50, sortBy = "name", sortOrder = "asc" } = query;
359
+ const allItems = [];
360
+ const targetTypes = types && types.length > 0 ? types : Array.from(this.registry.keys());
361
+ for (const type of targetTypes) {
362
+ const items = await this.list(type);
363
+ for (const item of items) {
364
+ const meta = item;
365
+ allItems.push({
366
+ type,
367
+ name: meta?.name ?? "",
368
+ namespace: meta?.namespace,
369
+ label: meta?.label,
370
+ scope: meta?.scope,
371
+ state: meta?.state,
372
+ packageId: meta?.packageId,
373
+ updatedAt: meta?.updatedAt
374
+ });
375
+ }
376
+ }
377
+ let filtered = allItems;
378
+ if (search) {
379
+ const searchLower = search.toLowerCase();
380
+ filtered = filtered.filter(
381
+ (item) => item.name.toLowerCase().includes(searchLower) || item.label && item.label.toLowerCase().includes(searchLower)
382
+ );
383
+ }
384
+ if (query.scope) {
385
+ filtered = filtered.filter((item) => item.scope === query.scope);
386
+ }
387
+ if (query.state) {
388
+ filtered = filtered.filter((item) => item.state === query.state);
389
+ }
390
+ if (query.namespaces && query.namespaces.length > 0) {
391
+ filtered = filtered.filter((item) => item.namespace && query.namespaces.includes(item.namespace));
392
+ }
393
+ if (query.packageId) {
394
+ filtered = filtered.filter((item) => item.packageId === query.packageId);
395
+ }
396
+ if (query.tags && query.tags.length > 0) {
397
+ filtered = filtered.filter((item) => {
398
+ const meta = item;
399
+ return meta?.tags && query.tags.some((t) => meta.tags.includes(t));
400
+ });
401
+ }
402
+ filtered.sort((a, b) => {
403
+ const aVal = a[sortBy] ?? "";
404
+ const bVal = b[sortBy] ?? "";
405
+ const cmp = String(aVal).localeCompare(String(bVal));
406
+ return sortOrder === "desc" ? -cmp : cmp;
407
+ });
408
+ const total = filtered.length;
409
+ const start = (page - 1) * pageSize;
410
+ const paged = filtered.slice(start, start + pageSize);
411
+ return {
412
+ items: paged,
413
+ total,
414
+ page,
415
+ pageSize
416
+ };
417
+ }
418
+ // ==========================================
419
+ // Bulk Operations
420
+ // ==========================================
421
+ /**
422
+ * Register multiple metadata items in a single batch
423
+ */
424
+ async bulkRegister(items, options) {
425
+ const { continueOnError = false } = options ?? {};
426
+ let succeeded = 0;
427
+ let failed = 0;
428
+ const errors = [];
429
+ for (const item of items) {
430
+ try {
431
+ await this.register(item.type, item.name, item.data);
432
+ succeeded++;
433
+ } catch (e) {
434
+ failed++;
435
+ errors.push({
436
+ type: item.type,
437
+ name: item.name,
438
+ error: e instanceof Error ? e.message : String(e)
439
+ });
440
+ if (!continueOnError) break;
441
+ }
442
+ }
443
+ return {
444
+ total: items.length,
445
+ succeeded,
446
+ failed,
447
+ errors: errors.length > 0 ? errors : void 0
448
+ };
449
+ }
450
+ /**
451
+ * Unregister multiple metadata items in a single batch
452
+ */
453
+ async bulkUnregister(items) {
454
+ let succeeded = 0;
455
+ let failed = 0;
456
+ const errors = [];
457
+ for (const item of items) {
458
+ try {
459
+ await this.unregister(item.type, item.name);
460
+ succeeded++;
461
+ } catch (e) {
462
+ failed++;
463
+ errors.push({
464
+ type: item.type,
465
+ name: item.name,
466
+ error: e instanceof Error ? e.message : String(e)
467
+ });
468
+ }
469
+ }
470
+ return {
471
+ total: items.length,
472
+ succeeded,
473
+ failed,
474
+ errors: errors.length > 0 ? errors : void 0
475
+ };
476
+ }
477
+ // ==========================================
478
+ // Overlay / Customization Management
479
+ // ==========================================
480
+ overlayKey(type, name, scope = "platform") {
481
+ return `${encodeURIComponent(type)}:${encodeURIComponent(name)}:${scope}`;
482
+ }
483
+ /**
484
+ * Get the active overlay for a metadata item
485
+ */
486
+ async getOverlay(type, name, scope) {
487
+ return this.overlays.get(this.overlayKey(type, name, scope ?? "platform"));
488
+ }
489
+ /**
490
+ * Save/update an overlay for a metadata item
491
+ */
492
+ async saveOverlay(overlay) {
493
+ const key = this.overlayKey(overlay.baseType, overlay.baseName, overlay.scope);
494
+ this.overlays.set(key, overlay);
495
+ }
496
+ /**
497
+ * Remove an overlay, reverting to the base definition
498
+ */
499
+ async removeOverlay(type, name, scope) {
500
+ this.overlays.delete(this.overlayKey(type, name, scope ?? "platform"));
501
+ }
502
+ /**
503
+ * Get the effective (merged) metadata after applying all overlays.
504
+ * Resolution order: system ← merge(platform) ← merge(user)
505
+ */
506
+ async getEffective(type, name) {
507
+ const base = await this.get(type, name);
508
+ if (!base) return void 0;
509
+ let effective = { ...base };
510
+ const platformOverlay = await this.getOverlay(type, name, "platform");
511
+ if (platformOverlay?.active && platformOverlay.patch) {
512
+ effective = { ...effective, ...platformOverlay.patch };
513
+ }
514
+ const userOverlay = await this.getOverlay(type, name, "user");
515
+ if (userOverlay?.active && userOverlay.patch) {
516
+ effective = { ...effective, ...userOverlay.patch };
517
+ }
518
+ return effective;
519
+ }
520
+ // ==========================================
521
+ // Watch / Subscribe (IMetadataService)
522
+ // ==========================================
209
523
  /**
210
- * Load a single metadata item
211
- * Iterates through registered loaders until found
524
+ * Watch for metadata changes (IMetadataService contract).
525
+ * Returns a handle for unsubscribing.
526
+ */
527
+ watchService(type, callback) {
528
+ const wrappedCallback = (event) => {
529
+ const mappedType = event.type === "added" ? "registered" : event.type === "deleted" ? "unregistered" : "updated";
530
+ callback({
531
+ type: mappedType,
532
+ metadataType: event.metadataType ?? type,
533
+ name: event.name ?? "",
534
+ data: event.data
535
+ });
536
+ };
537
+ this.addWatchCallback(type, wrappedCallback);
538
+ return {
539
+ unsubscribe: () => this.removeWatchCallback(type, wrappedCallback)
540
+ };
541
+ }
542
+ // ==========================================
543
+ // Import / Export
544
+ // ==========================================
545
+ /**
546
+ * Export metadata as a portable bundle
547
+ */
548
+ async exportMetadata(options) {
549
+ const bundle = {};
550
+ const targetTypes = options?.types ?? Array.from(this.registry.keys());
551
+ for (const type of targetTypes) {
552
+ const items = await this.list(type);
553
+ if (items.length > 0) {
554
+ bundle[type] = items;
555
+ }
556
+ }
557
+ return bundle;
558
+ }
559
+ /**
560
+ * Import metadata from a portable bundle
561
+ */
562
+ async importMetadata(data, options) {
563
+ const {
564
+ conflictResolution = "skip",
565
+ validate: _validate = true,
566
+ dryRun = false
567
+ } = options ?? {};
568
+ const bundle = data;
569
+ let total = 0;
570
+ let imported = 0;
571
+ let skipped = 0;
572
+ let failed = 0;
573
+ const errors = [];
574
+ for (const [type, items] of Object.entries(bundle)) {
575
+ if (!Array.isArray(items)) continue;
576
+ for (const item of items) {
577
+ total++;
578
+ const meta = item;
579
+ const name = meta?.name;
580
+ if (!name) {
581
+ failed++;
582
+ errors.push({ type, name: "(unknown)", error: "Item missing name field" });
583
+ continue;
584
+ }
585
+ try {
586
+ const itemExists = await this.exists(type, name);
587
+ if (itemExists && conflictResolution === "skip") {
588
+ skipped++;
589
+ continue;
590
+ }
591
+ if (!dryRun) {
592
+ if (itemExists && conflictResolution === "merge") {
593
+ const existing = await this.get(type, name);
594
+ const merged = { ...existing, ...item };
595
+ await this.register(type, name, merged);
596
+ } else {
597
+ await this.register(type, name, item);
598
+ }
599
+ }
600
+ imported++;
601
+ } catch (e) {
602
+ failed++;
603
+ errors.push({
604
+ type,
605
+ name,
606
+ error: e instanceof Error ? e.message : String(e)
607
+ });
608
+ }
609
+ }
610
+ }
611
+ return {
612
+ total,
613
+ imported,
614
+ skipped,
615
+ failed,
616
+ errors: errors.length > 0 ? errors : void 0
617
+ };
618
+ }
619
+ // ==========================================
620
+ // Validation
621
+ // ==========================================
622
+ /**
623
+ * Validate a metadata item against its type schema.
624
+ * Returns validation result with errors and warnings.
625
+ */
626
+ async validate(_type, data) {
627
+ if (data === null || data === void 0) {
628
+ return {
629
+ valid: false,
630
+ errors: [{ path: "", message: "Metadata data cannot be null or undefined" }]
631
+ };
632
+ }
633
+ if (typeof data !== "object") {
634
+ return {
635
+ valid: false,
636
+ errors: [{ path: "", message: "Metadata data must be an object" }]
637
+ };
638
+ }
639
+ const meta = data;
640
+ const warnings = [];
641
+ if (!meta.name) {
642
+ return {
643
+ valid: false,
644
+ errors: [{ path: "name", message: "Metadata item must have a name field" }]
645
+ };
646
+ }
647
+ if (!meta.label) {
648
+ warnings.push({ path: "label", message: "Missing label field (recommended)" });
649
+ }
650
+ return { valid: true, warnings: warnings.length > 0 ? warnings : void 0 };
651
+ }
652
+ // ==========================================
653
+ // Type Registry
654
+ // ==========================================
655
+ /**
656
+ * Get all registered metadata types
657
+ */
658
+ async getRegisteredTypes() {
659
+ const types = /* @__PURE__ */ new Set();
660
+ for (const entry of this.typeRegistry) {
661
+ types.add(entry.type);
662
+ }
663
+ for (const type of this.registry.keys()) {
664
+ types.add(type);
665
+ }
666
+ return Array.from(types);
667
+ }
668
+ /**
669
+ * Get detailed information about a metadata type
670
+ */
671
+ async getTypeInfo(type) {
672
+ const entry = this.typeRegistry.find((e) => e.type === type);
673
+ if (!entry) return void 0;
674
+ return {
675
+ type: entry.type,
676
+ label: entry.label,
677
+ description: entry.description,
678
+ filePatterns: entry.filePatterns,
679
+ supportsOverlay: entry.supportsOverlay,
680
+ domain: entry.domain
681
+ };
682
+ }
683
+ // ==========================================
684
+ // Dependency Tracking
685
+ // ==========================================
686
+ /**
687
+ * Get metadata items that this item depends on
688
+ */
689
+ async getDependencies(type, name) {
690
+ return this.dependencies.get(`${encodeURIComponent(type)}:${encodeURIComponent(name)}`) ?? [];
691
+ }
692
+ /**
693
+ * Get metadata items that depend on this item
694
+ */
695
+ async getDependents(type, name) {
696
+ const dependents = [];
697
+ for (const deps of this.dependencies.values()) {
698
+ for (const dep of deps) {
699
+ if (dep.targetType === type && dep.targetName === name) {
700
+ dependents.push(dep);
701
+ }
702
+ }
703
+ }
704
+ return dependents;
705
+ }
706
+ /**
707
+ * Register a dependency between two metadata items.
708
+ * Used internally to track cross-references.
709
+ * Duplicate dependencies (same source, target, and kind) are ignored.
710
+ */
711
+ addDependency(dep) {
712
+ const key = `${encodeURIComponent(dep.sourceType)}:${encodeURIComponent(dep.sourceName)}`;
713
+ if (!this.dependencies.has(key)) {
714
+ this.dependencies.set(key, []);
715
+ }
716
+ const existing = this.dependencies.get(key);
717
+ const isDuplicate = existing.some(
718
+ (d) => d.targetType === dep.targetType && d.targetName === dep.targetName && d.kind === dep.kind
719
+ );
720
+ if (!isDuplicate) {
721
+ existing.push(dep);
722
+ }
723
+ }
724
+ // ==========================================
725
+ // Legacy Loader API (backward compatible)
726
+ // ==========================================
727
+ /**
728
+ * Load a single metadata item from loaders.
729
+ * Iterates through registered loaders until found.
212
730
  */
213
731
  async load(type, name, options) {
214
732
  for (const loader of this.loaders.values()) {
@@ -224,8 +742,8 @@ var MetadataManager = class {
224
742
  return null;
225
743
  }
226
744
  /**
227
- * Load multiple metadata items
228
- * Aggregates results from all loaders
745
+ * Load multiple metadata items from loaders.
746
+ * Aggregates results from all loaders.
229
747
  */
230
748
  async loadMany(type, options) {
231
749
  const results = [];
@@ -247,10 +765,7 @@ var MetadataManager = class {
247
765
  return results;
248
766
  }
249
767
  /**
250
- * Save metadata to disk
251
- */
252
- /**
253
- * Save metadata item
768
+ * Save metadata item to a loader
254
769
  */
255
770
  async save(type, name, data, options) {
256
771
  const targetLoader = options?.loader;
@@ -296,40 +811,18 @@ var MetadataManager = class {
296
811
  return loader.save(type, name, data, options);
297
812
  }
298
813
  /**
299
- * Check if metadata item exists
814
+ * Register a watch callback for metadata changes
300
815
  */
301
- async exists(type, name) {
302
- for (const loader of this.loaders.values()) {
303
- if (await loader.exists(type, name)) {
304
- return true;
305
- }
306
- }
307
- return false;
308
- }
309
- /**
310
- * List all items of a type
311
- */
312
- async list(type) {
313
- const items = /* @__PURE__ */ new Set();
314
- for (const loader of this.loaders.values()) {
315
- const result = await loader.list(type);
316
- result.forEach((item) => items.add(item));
317
- }
318
- return Array.from(items);
319
- }
320
- /**
321
- * Watch for metadata changes
322
- */
323
- watch(type, callback) {
816
+ addWatchCallback(type, callback) {
324
817
  if (!this.watchCallbacks.has(type)) {
325
818
  this.watchCallbacks.set(type, /* @__PURE__ */ new Set());
326
819
  }
327
820
  this.watchCallbacks.get(type).add(callback);
328
821
  }
329
822
  /**
330
- * Unwatch metadata changes
823
+ * Remove a watch callback for metadata changes
331
824
  */
332
- unwatch(type, callback) {
825
+ removeWatchCallback(type, callback) {
333
826
  const callbacks = this.watchCallbacks.get(type);
334
827
  if (callbacks) {
335
828
  callbacks.delete(callback);
@@ -375,7 +868,7 @@ var FilesystemLoader = class {
375
868
  this.logger = logger;
376
869
  this.contract = {
377
870
  name: "filesystem",
378
- protocol: "file",
871
+ protocol: "file:",
379
872
  capabilities: {
380
873
  read: true,
381
874
  write: true,
@@ -527,7 +1020,7 @@ var FilesystemLoader = class {
527
1020
  const format = this.detectFormat(filePath);
528
1021
  return {
529
1022
  size: stats.size,
530
- modifiedAt: stats.mtime,
1023
+ modifiedAt: stats.mtime.toISOString(),
531
1024
  etag,
532
1025
  format,
533
1026
  path: filePath
@@ -758,14 +1251,14 @@ var NodeMetadataManager = class extends MetadataManager {
758
1251
  name,
759
1252
  path: filePath,
760
1253
  data,
761
- timestamp: /* @__PURE__ */ new Date()
1254
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
762
1255
  };
763
1256
  this.notifyWatchers(type, event);
764
1257
  }
765
1258
  };
766
1259
 
767
1260
  // src/plugin.ts
768
- import { ObjectStackDefinitionSchema } from "@objectstack/spec";
1261
+ import { DEFAULT_METADATA_TYPE_REGISTRY } from "@objectstack/spec/kernel";
769
1262
  var MetadataPlugin = class {
770
1263
  constructor(options = {}) {
771
1264
  this.name = "com.objectstack.metadata";
@@ -779,29 +1272,35 @@ var MetadataPlugin = class {
779
1272
  ctx.registerService("metadata", this.manager);
780
1273
  ctx.logger.info("MetadataPlugin providing metadata service (primary mode)", {
781
1274
  mode: "file-system",
782
- features: ["watch", "persistence", "multi-format"]
1275
+ features: ["watch", "persistence", "multi-format", "query", "overlay", "type-registry"]
783
1276
  });
784
1277
  };
785
1278
  this.start = async (ctx) => {
786
1279
  ctx.logger.info("Loading metadata from file system...");
787
- const metadataTypes = Object.keys(ObjectStackDefinitionSchema.shape).filter((key) => key !== "manifest");
1280
+ const sortedTypes = [...DEFAULT_METADATA_TYPE_REGISTRY].sort((a, b) => a.loadOrder - b.loadOrder);
788
1281
  let totalLoaded = 0;
789
- for (const type of metadataTypes) {
1282
+ for (const entry of sortedTypes) {
790
1283
  try {
791
- const items = await this.manager.loadMany(type, {
1284
+ const items = await this.manager.loadMany(entry.type, {
792
1285
  recursive: true
793
1286
  });
794
1287
  if (items.length > 0) {
795
- ctx.logger.info(`Loaded ${items.length} ${type} from file system`);
1288
+ for (const item of items) {
1289
+ const meta = item;
1290
+ if (meta?.name) {
1291
+ await this.manager.register(entry.type, meta.name, item);
1292
+ }
1293
+ }
1294
+ ctx.logger.info(`Loaded ${items.length} ${entry.type} from file system`);
796
1295
  totalLoaded += items.length;
797
1296
  }
798
1297
  } catch (e) {
799
- ctx.logger.debug(`No ${type} metadata found`, { error: e.message });
1298
+ ctx.logger.debug(`No ${entry.type} metadata found`, { error: e.message });
800
1299
  }
801
1300
  }
802
1301
  ctx.logger.info("Metadata loading complete", {
803
1302
  totalItems: totalLoaded,
804
- note: "ObjectQL will sync these into its registry during its start phase"
1303
+ registeredTypes: sortedTypes.length
805
1304
  });
806
1305
  };
807
1306
  this.options = {
@@ -814,6 +1313,7 @@ var MetadataPlugin = class {
814
1313
  watch: this.options.watch ?? true,
815
1314
  formats: ["yaml", "json", "typescript", "javascript"]
816
1315
  });
1316
+ this.manager.setTypeRegistry(DEFAULT_METADATA_TYPE_REGISTRY);
817
1317
  }
818
1318
  };
819
1319
 
@@ -822,7 +1322,7 @@ var MemoryLoader = class {
822
1322
  constructor() {
823
1323
  this.contract = {
824
1324
  name: "memory",
825
- protocol: "memory",
1325
+ protocol: "memory:",
826
1326
  capabilities: {
827
1327
  read: true,
828
1328
  write: true,
@@ -890,7 +1390,7 @@ var RemoteLoader = class {
890
1390
  this.authToken = authToken;
891
1391
  this.contract = {
892
1392
  name: "remote",
893
- protocol: "http",
1393
+ protocol: "http:",
894
1394
  capabilities: {
895
1395
  read: true,
896
1396
  write: true,