@objectstack/metadata 4.0.2 → 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/dist/node.cjs CHANGED
@@ -1086,6 +1086,16 @@ var MetadataManager = class {
1086
1086
  this.registerLoader(dbLoader);
1087
1087
  this.logger.info("DatabaseLoader configured", { datasource: this.config.datasource, tableName });
1088
1088
  }
1089
+ /**
1090
+ * Set the realtime service for publishing metadata change events.
1091
+ * Should be called after kernel resolves the realtime service.
1092
+ *
1093
+ * @param service - An IRealtimeService instance for event publishing
1094
+ */
1095
+ setRealtimeService(service) {
1096
+ this.realtimeService = service;
1097
+ this.logger.info("RealtimeService configured for metadata events");
1098
+ }
1089
1099
  /**
1090
1100
  * Register a new metadata loader (data source)
1091
1101
  */
@@ -1098,7 +1108,9 @@ var MetadataManager = class {
1098
1108
  // ==========================================
1099
1109
  /**
1100
1110
  * Register/save a metadata item by type
1101
- * Stores in-memory registry and persists to writable loaders (if configured)
1111
+ * Stores in-memory registry and persists to database-backed loaders only.
1112
+ * FilesystemLoader (protocol 'file:') is read-only for static metadata and
1113
+ * should not be written to during runtime registration.
1102
1114
  */
1103
1115
  async register(type, name, data) {
1104
1116
  if (!this.registry.has(type)) {
@@ -1106,10 +1118,29 @@ var MetadataManager = class {
1106
1118
  }
1107
1119
  this.registry.get(type).set(name, data);
1108
1120
  for (const loader of this.loaders.values()) {
1109
- if (loader.save) {
1121
+ if (loader.save && loader.contract.protocol === "datasource:" && loader.contract.capabilities.write) {
1110
1122
  await loader.save(type, name, data);
1111
1123
  }
1112
1124
  }
1125
+ if (this.realtimeService) {
1126
+ const event = {
1127
+ type: `metadata.${type}.created`,
1128
+ object: type,
1129
+ payload: {
1130
+ metadataType: type,
1131
+ name,
1132
+ definition: data,
1133
+ packageId: data?.packageId
1134
+ },
1135
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
1136
+ };
1137
+ try {
1138
+ await this.realtimeService.publish(event);
1139
+ this.logger.debug(`Published metadata.${type}.created event`, { name });
1140
+ } catch (error) {
1141
+ this.logger.warn(`Failed to publish metadata event`, { type, name, error });
1142
+ }
1143
+ }
1113
1144
  }
1114
1145
  /**
1115
1146
  * Get a metadata item by type and name.
@@ -1150,7 +1181,8 @@ var MetadataManager = class {
1150
1181
  return Array.from(items.values());
1151
1182
  }
1152
1183
  /**
1153
- * Unregister/remove a metadata item by type and name
1184
+ * Unregister/remove a metadata item by type and name.
1185
+ * Deletes from database-backed loaders only (same rationale as register()).
1154
1186
  */
1155
1187
  async unregister(type, name) {
1156
1188
  const typeStore = this.registry.get(type);
@@ -1161,6 +1193,7 @@ var MetadataManager = class {
1161
1193
  }
1162
1194
  }
1163
1195
  for (const loader of this.loaders.values()) {
1196
+ if (loader.contract.protocol !== "datasource:" || !loader.contract.capabilities.write) continue;
1164
1197
  if (typeof loader.delete === "function") {
1165
1198
  try {
1166
1199
  await loader.delete(type, name);
@@ -1169,6 +1202,23 @@ var MetadataManager = class {
1169
1202
  }
1170
1203
  }
1171
1204
  }
1205
+ if (this.realtimeService) {
1206
+ const event = {
1207
+ type: `metadata.${type}.deleted`,
1208
+ object: type,
1209
+ payload: {
1210
+ metadataType: type,
1211
+ name
1212
+ },
1213
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
1214
+ };
1215
+ try {
1216
+ await this.realtimeService.publish(event);
1217
+ this.logger.debug(`Published metadata.${type}.deleted event`, { name });
1218
+ } catch (error) {
1219
+ this.logger.warn(`Failed to publish metadata event`, { type, name, error });
1220
+ }
1221
+ }
1172
1222
  }
1173
1223
  /**
1174
1224
  * Check if a metadata item exists
@@ -2514,6 +2564,7 @@ var MetadataPlugin = class {
2514
2564
  watch: this.options.watch
2515
2565
  });
2516
2566
  ctx.registerService("metadata", this.manager);
2567
+ console.log("[MetadataPlugin] Registered metadata service, has getRegisteredTypes:", typeof this.manager.getRegisteredTypes);
2517
2568
  try {
2518
2569
  ctx.getService("manifest").register({
2519
2570
  id: "com.objectstack.metadata",
@@ -2557,6 +2608,33 @@ var MetadataPlugin = class {
2557
2608
  totalItems: totalLoaded,
2558
2609
  registeredTypes: sortedTypes.length
2559
2610
  });
2611
+ try {
2612
+ const services = ctx.getServices();
2613
+ for (const [serviceName, service] of services) {
2614
+ if (serviceName.startsWith("driver.") && service) {
2615
+ ctx.logger.info("[MetadataPlugin] Bridging driver to MetadataManager for database-backed persistence", {
2616
+ driverService: serviceName
2617
+ });
2618
+ this.manager.setDatabaseDriver(service);
2619
+ break;
2620
+ }
2621
+ }
2622
+ } catch (e) {
2623
+ ctx.logger.debug("[MetadataPlugin] No driver service found \u2014 database metadata persistence not available", {
2624
+ error: e.message
2625
+ });
2626
+ }
2627
+ try {
2628
+ const realtimeService = ctx.getService("realtime");
2629
+ if (realtimeService && typeof realtimeService === "object" && "publish" in realtimeService) {
2630
+ ctx.logger.info("[MetadataPlugin] Bridging realtime service to MetadataManager for event publishing");
2631
+ this.manager.setRealtimeService(realtimeService);
2632
+ }
2633
+ } catch (e) {
2634
+ ctx.logger.debug("[MetadataPlugin] No realtime service found \u2014 metadata events will not be published", {
2635
+ error: e.message
2636
+ });
2637
+ }
2560
2638
  };
2561
2639
  this.options = {
2562
2640
  watch: true,