@ai-matrx/records 0.96.3 → 0.96.5

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.
@@ -3967,7 +3967,7 @@ function validateTemplate(raw, options = {}) {
3967
3967
  const keys = /* @__PURE__ */ new Set([...Object.keys(a.values ?? {}), ...Object.keys(b.values ?? {})]);
3968
3968
  let differ = 0;
3969
3969
  for (const k of keys) if (!sameJson(a.values?.[k] ?? null, b.values?.[k] ?? null)) differ += 1;
3970
- if (differ < 3) say(`tables[0] (${main.token}).rows[${j}] (${b.key})`, `"${storeText(b.values?.[main.titleField])}" differs from "${storeText(a.values?.[main.titleField])}" in only ${differ} field(s); two real ${main.labelPlural.toLowerCase()} differ in at least three.`);
3970
+ if (differ < Math.min(3, keys.size)) say(`tables[0] (${main.token}).rows[${j}] (${b.key})`, `"${storeText(b.values?.[main.titleField])}" differs from "${storeText(a.values?.[main.titleField])}" in only ${differ} field(s); two real ${main.labelPlural.toLowerCase()} differ in at least three.`);
3971
3971
  }
3972
3972
  }
3973
3973
  }
@@ -6125,11 +6125,28 @@ function compileInstallPlan(written) {
6125
6125
  const spec = tokenizeValues({ ...written, attachments: void 0 }, attachmentKeys);
6126
6126
  const bound = new Map(allTables(spec).filter((t) => t.bindsTo?.tableId).map((t) => [t.token, t.bindsTo]));
6127
6127
  const has = (token, key) => bound.get(token)?.fields.includes(key) ?? false;
6128
+ const resolves = (target, v) => {
6129
+ const b = bound.get(target);
6130
+ return !b || !!b.seedRows || typeof v === "string" && !!b.rowIds?.[v];
6131
+ };
6128
6132
  const tables = allTables(spec).map((t) => {
6129
- if (bound.has(t.token)) return { ...t, rows: [] };
6130
- const toBound = t.fields.filter((f) => f.parityType === "relation" && f.relationTarget && bound.has(f.relationTarget)).map((f) => f.key);
6133
+ if (bound.has(t.token)) return bound.get(t.token).seedRows ? t : { ...t, rows: [] };
6134
+ const toBound = t.fields.filter((f) => f.parityType === "relation" && f.relationTarget && bound.has(f.relationTarget));
6131
6135
  if (!toBound.length) return t;
6132
- return { ...t, rows: t.rows.map((r) => ({ ...r, values: Object.fromEntries(Object.entries(r.values ?? {}).filter(([k]) => !toBound.includes(k))) })) };
6136
+ const lost = /* @__PURE__ */ new Set();
6137
+ const rows = t.rows.map((r) => {
6138
+ const values = { ...r.values ?? {} };
6139
+ for (const f of toBound) {
6140
+ const v = values[f.key];
6141
+ if (v === null || v === void 0) continue;
6142
+ const keep = Array.isArray(v) ? v.filter((x) => resolves(f.relationTarget, x)) : resolves(f.relationTarget, v) ? v : null;
6143
+ if (Array.isArray(keep) ? keep.length < v.length : keep === null) lost.add(f.key);
6144
+ if (keep === null || Array.isArray(keep) && !keep.length) delete values[f.key];
6145
+ else values[f.key] = keep;
6146
+ }
6147
+ return { ...r, values };
6148
+ });
6149
+ return { ...t, rows, fields: t.fields.map((f) => lost.has(f.key) && f.required ? { ...f, required: false } : f) };
6133
6150
  });
6134
6151
  const steps = [];
6135
6152
  const tableRef = (token) => {
@@ -6205,6 +6222,7 @@ function compileInstallPlan(written) {
6205
6222
  }
6206
6223
  const rowIds = /* @__PURE__ */ new Map();
6207
6224
  for (const t of tables) for (const r of t.rows) rowIds.set(`${t.token}.${r.key}`, minted(`row.${t.token}.${r.key}`));
6225
+ for (const [token, b] of bound) if (!b.seedRows) for (const [key, id] of Object.entries(b.rowIds ?? {})) rowIds.set(`${token}.${key}`, id);
6208
6226
  const deferred = deferredRelations(tables);
6209
6227
  for (const level of rowLevels(tables)) {
6210
6228
  for (const t of level) {
@@ -7664,17 +7682,18 @@ function describeCheck(spec, ctx = {}) {
7664
7682
  for (let round = 0; round < 3; round++) {
7665
7683
  const bad = rowProblemTables(fixed.spec, problems);
7666
7684
  if (!bad.size) break;
7667
- let grew = true;
7668
- while (grew) {
7669
- grew = false;
7670
- for (const t of fixed.spec.tables) {
7671
- if (bad.has(t.token) || !t.rows?.length) continue;
7672
- if (t.fields.some((f) => f.relationTarget && bad.has(f.relationTarget) && t.rows.some((r) => r.values?.[f.key] != null))) {
7673
- bad.add(t.token);
7674
- grew = true;
7675
- }
7685
+ const unlinked = [];
7686
+ for (const t of fixed.spec.tables) {
7687
+ if (bad.has(t.token) || !t.rows?.length) continue;
7688
+ const links = t.fields.filter((f) => f.relationTarget && bad.has(f.relationTarget) && t.rows.some((r) => r.values?.[f.key] != null));
7689
+ if (!links.length) continue;
7690
+ for (const f of links) {
7691
+ for (const r of t.rows) if (r.values) delete r.values[f.key];
7692
+ f.required = false;
7676
7693
  }
7694
+ unlinked.push(`tables.${t.token}.rows: kept without their ${links.map((f) => f.label || f.key).join(" / ")} link (the rows they pointed at were left out)`);
7677
7695
  }
7696
+ fixed.autoFixes.push(...unlinked);
7678
7697
  for (const t of fixed.spec.tables) {
7679
7698
  if (!bad.has(t.token) || !t.rows?.length) continue;
7680
7699
  const why = problems.find((p) => ROW_AT.exec(p.at)?.[1] === t.token)?.says ?? "they did not pass the check";