@ai-matrx/content-ir-react 0.4.0 → 0.5.1

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.d.ts CHANGED
@@ -70,6 +70,13 @@ interface KindComponentRow {
70
70
  isActive: boolean;
71
71
  componentSource: string | null;
72
72
  propsTransform: string | null;
73
+ /**
74
+ * Whether the row carries a real `component_source` body — supplied by the
75
+ * host when its warm list is BODY-LESS (the lazy design: metadata travels
76
+ * on the list, the body arrives per kind via the cold fetch). Omitted →
77
+ * derived from `componentSource` itself, so eager hosts change nothing.
78
+ */
79
+ hasComponentSource?: boolean;
73
80
  pinnedKindVersion: number | null;
74
81
  updatedAt: string | null;
75
82
  createdBy: string | null;
@@ -101,6 +108,14 @@ interface ComponentResolution {
101
108
  resolvedBy: "compiled" | "db";
102
109
  componentSource: string | null;
103
110
  propsTransform: string | null;
111
+ /**
112
+ * TRUE when the row owns a real component body — even if `componentSource`
113
+ * is null because the host's warm list is body-less and the cold fetch has
114
+ * not landed it yet. THE routing gate: `routeToDbComponent` re-types on
115
+ * this flag, never on body presence, so a body-less row still routes and
116
+ * the renderer fetches/compiles the body lazily.
117
+ */
118
+ hasComponentSource: boolean;
104
119
  pinnedKindVersion: number | null;
105
120
  /** The db row's `updated_at` — the compile-cache staleness key. */
106
121
  updatedAt: string | null;
@@ -366,6 +381,18 @@ declare class ComponentResolver implements ComponentResolutionSource {
366
381
  subscribe(listener: () => void): () => void;
367
382
  private bumpKind;
368
383
  private notifyChanged;
384
+ /**
385
+ * A warm metadata shell is resolved enough for routing, but not for the
386
+ * host's db-component renderer. Its body must still come from the cold
387
+ * single-kind loader.
388
+ */
389
+ private needsColdFetch;
390
+ /**
391
+ * Cold rows are the authoritative heavy form of warm metadata shells. Keep
392
+ * the same first-row-per-key winner contract, but replace an existing shell
393
+ * so `componentSource` / `propsTransform` can land and repaint the kind.
394
+ */
395
+ private ingestColdRows;
369
396
  /**
370
397
  * The eager lightweight single-kind fetch (streaming path): the moment a
371
398
  * cloud kind is identified mid-stream, pull ONLY that kind's resolver rows
package/dist/index.js CHANGED
@@ -120,6 +120,7 @@ var ComponentResolver = class {
120
120
  resolvedBy: "db",
121
121
  componentSource: dbRow.componentSource,
122
122
  propsTransform: dbRow.propsTransform,
123
+ hasComponentSource: dbRow.hasComponentSource ?? Boolean(dbRow.componentSource && dbRow.componentSource.trim()),
123
124
  pinnedKindVersion: dbRow.pinnedKindVersion,
124
125
  updatedAt: dbRow.updatedAt,
125
126
  createdBy: dbRow.createdBy
@@ -136,6 +137,7 @@ var ComponentResolver = class {
136
137
  resolvedBy: "compiled",
137
138
  componentSource: null,
138
139
  propsTransform: null,
140
+ hasComponentSource: false,
139
141
  pinnedKindVersion: null,
140
142
  updatedAt: null,
141
143
  createdBy: null
@@ -213,6 +215,35 @@ var ComponentResolver = class {
213
215
  this.version += 1;
214
216
  for (const listener of this.listeners) listener();
215
217
  }
218
+ /**
219
+ * A warm metadata shell is resolved enough for routing, but not for the
220
+ * host's db-component renderer. Its body must still come from the cold
221
+ * single-kind loader.
222
+ */
223
+ needsColdFetch(kind, platform, role) {
224
+ const resolution = this.resolve(kind, platform, role);
225
+ return resolution === null || resolution.resolvedBy === "db" && resolution.hasComponentSource && resolution.componentSource === null;
226
+ }
227
+ /**
228
+ * Cold rows are the authoritative heavy form of warm metadata shells. Keep
229
+ * the same first-row-per-key winner contract, but replace an existing shell
230
+ * so `componentSource` / `propsTransform` can land and repaint the kind.
231
+ */
232
+ ingestColdRows(rows) {
233
+ const winners = /* @__PURE__ */ new Map();
234
+ for (const row of rows) {
235
+ const key = keyOf(row.kind, row.platform, row.role);
236
+ if (!winners.has(key)) winners.set(key, row);
237
+ }
238
+ if (winners.size === 0) return;
239
+ const changedKinds = /* @__PURE__ */ new Set();
240
+ for (const [key, row] of winners) {
241
+ this.db.set(key, row);
242
+ changedKinds.add(row.kind);
243
+ }
244
+ for (const kind of changedKinds) this.bumpKind(kind);
245
+ this.notifyChanged();
246
+ }
216
247
  /**
217
248
  * The eager lightweight single-kind fetch (streaming path): the moment a
218
249
  * cloud kind is identified mid-stream, pull ONLY that kind's resolver rows
@@ -223,7 +254,7 @@ var ComponentResolver = class {
223
254
  requestComponent(kind, platform, role) {
224
255
  const loadForKind = this.options.loadForKind;
225
256
  if (!loadForKind) return;
226
- if (this.resolve(kind, platform, role)) return;
257
+ if (!this.needsColdFetch(kind, platform, role)) return;
227
258
  const missKey = keyOf(kind, platform, role);
228
259
  const flightKey = `${kind}${KEY_SEPARATOR}${platform}`;
229
260
  if (this.coldInFlight.has(flightKey) || this.coldMisses.has(missKey)) {
@@ -232,8 +263,10 @@ var ComponentResolver = class {
232
263
  this.coldInFlight.add(flightKey);
233
264
  void (async () => {
234
265
  try {
235
- this.ingestDbRows(await loadForKind(kind, platform));
236
- if (!this.resolve(kind, platform, role)) this.coldMisses.add(missKey);
266
+ this.ingestColdRows(await loadForKind(kind, platform));
267
+ if (this.needsColdFetch(kind, platform, role)) {
268
+ this.coldMisses.add(missKey);
269
+ }
237
270
  } catch (error) {
238
271
  this.reportError({
239
272
  source: "content-ir",
@@ -322,7 +355,7 @@ function resetSourcelessDbRowReports() {
322
355
  }
323
356
  function routeToDbComponent(block, kind, resolution, env) {
324
357
  if (!isDbSourceResolution(resolution)) return null;
325
- if (!resolution.componentSource || !resolution.componentSource.trim()) {
358
+ if (!resolution.hasComponentSource) {
326
359
  reportDbRowWithoutSource(kind, env);
327
360
  return null;
328
361
  }