@open-mercato/ui 0.6.5-develop.4498.1.55dc06a57c → 0.6.5-develop.4534.1.b459babe6d

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.
@@ -170,6 +170,41 @@ function readByDotPath(source, path) {
170
170
  }
171
171
  return current;
172
172
  }
173
+ const PROTO_POLLUTING_KEYS = /* @__PURE__ */ new Set(["__proto__", "prototype", "constructor"]);
174
+ function isProtoPollutingKey(key) {
175
+ return PROTO_POLLUTING_KEYS.has(key);
176
+ }
177
+ function writeByDotPath(target, path, value) {
178
+ const segments = path.split(".").filter(Boolean);
179
+ if (segments.length === 0) return;
180
+ if (segments.some(isProtoPollutingKey)) return;
181
+ let current = target;
182
+ for (let index = 0; index < segments.length - 1; index++) {
183
+ const segment = segments[index];
184
+ const existing = current[segment];
185
+ const isSafeObject = !!existing && typeof existing === "object" && !Array.isArray(existing) && (Object.getPrototypeOf(existing) === Object.prototype || Object.getPrototypeOf(existing) === null);
186
+ if (!isSafeObject) {
187
+ const created = /* @__PURE__ */ Object.create(null);
188
+ current[segment] = created;
189
+ current = created;
190
+ } else {
191
+ current = existing;
192
+ }
193
+ }
194
+ const finalSegment = segments[segments.length - 1];
195
+ if (isProtoPollutingKey(finalSegment)) return;
196
+ current[finalSegment] = value;
197
+ }
198
+ function collapseDotPathFields(source, dotPathFieldIds) {
199
+ if (!dotPathFieldIds.size) return source;
200
+ let result = null;
201
+ for (const fieldId of dotPathFieldIds) {
202
+ if (!Object.prototype.hasOwnProperty.call(source, fieldId)) continue;
203
+ if (!result) result = { ...source };
204
+ writeByDotPath(result, fieldId, source[fieldId]);
205
+ }
206
+ return result ?? source;
207
+ }
173
208
  function readInitialCustomFieldValue(source, key) {
174
209
  if (!source || !key) return void 0;
175
210
  const candidates = [`cf_${key}`, `cf:${key}`, key];
@@ -1257,6 +1292,19 @@ function CrudForm({
1257
1292
  const fieldById = React.useMemo(() => {
1258
1293
  return new globalThis.Map(allFields.map((f) => [f.id, f]));
1259
1294
  }, [allFields]);
1295
+ const dotPathBaseFieldIds = React.useMemo(() => {
1296
+ const ids = /* @__PURE__ */ new Set();
1297
+ const cfFieldIds = new Set(cfFields.map((field) => field.id));
1298
+ for (const field of allFields) {
1299
+ const fieldId = field.id;
1300
+ if (!fieldId.includes(".")) continue;
1301
+ if (injectedFieldIdSet.has(fieldId)) continue;
1302
+ if (fieldId.startsWith("cf_") || fieldId.startsWith("cf:")) continue;
1303
+ if (cfFieldIds.has(fieldId)) continue;
1304
+ ids.add(fieldId);
1305
+ }
1306
+ return ids;
1307
+ }, [allFields, injectedFieldIdSet, cfFields]);
1260
1308
  const validateFieldOnBlur = React.useCallback(async (fieldId, sourceValues) => {
1261
1309
  if (formReadOnly) return;
1262
1310
  const field = fieldById.get(fieldId);
@@ -1307,7 +1355,7 @@ function CrudForm({
1307
1355
  for (const injectedId of injectedFieldIdSet) {
1308
1356
  delete coreValues[injectedId];
1309
1357
  }
1310
- const result = schema.safeParse(coreValues);
1358
+ const result = schema.safeParse(collapseDotPathFields(coreValues, dotPathBaseFieldIds));
1311
1359
  if (!result.success) {
1312
1360
  const schemaFieldErrors = {};
1313
1361
  result.error.issues.forEach((issue) => {
@@ -1336,6 +1384,7 @@ function CrudForm({
1336
1384
  }, [
1337
1385
  cfDefinitions,
1338
1386
  customEntity,
1387
+ dotPathBaseFieldIds,
1339
1388
  fieldById,
1340
1389
  formReadOnly,
1341
1390
  hiddenBaseFieldIds,
@@ -1670,7 +1719,8 @@ function CrudForm({
1670
1719
  const snapshot = JSON.stringify({
1671
1720
  initialValues,
1672
1721
  injectedFieldIds: injectedFieldDefinitions.map((definition) => definition.id),
1673
- customFieldMappings: cfDefinitions.map((definition) => definition.key)
1722
+ customFieldMappings: cfDefinitions.map((definition) => definition.key),
1723
+ dotPathBaseFieldIds: Array.from(dotPathBaseFieldIds)
1674
1724
  });
1675
1725
  if (appliedInitialValuesSnapshotRef.current === snapshot) return;
1676
1726
  appliedInitialValuesSnapshotRef.current = snapshot;
@@ -1695,6 +1745,14 @@ function CrudForm({
1695
1745
  merged[targetId] = extracted;
1696
1746
  }
1697
1747
  }
1748
+ for (const fieldId of dotPathBaseFieldIds) {
1749
+ if (merged[fieldId] !== void 0) continue;
1750
+ const extracted = readByDotPath(initialRecord, fieldId);
1751
+ if (extracted !== void 0) {
1752
+ ;
1753
+ merged[fieldId] = extracted;
1754
+ }
1755
+ }
1698
1756
  mergedValues = merged;
1699
1757
  return mergedValues;
1700
1758
  });
@@ -1725,6 +1783,7 @@ function CrudForm({
1725
1783
  }, [
1726
1784
  cfDefinitions,
1727
1785
  customEntity,
1786
+ dotPathBaseFieldIds,
1728
1787
  extendedInjectionEventsEnabled,
1729
1788
  initialValues,
1730
1789
  injectedFieldDefinitions,
@@ -1881,7 +1940,7 @@ function CrudForm({
1881
1940
  }
1882
1941
  let parsedValues;
1883
1942
  if (schema) {
1884
- const res = schema.safeParse(coreValues);
1943
+ const res = schema.safeParse(collapseDotPathFields(coreValues, dotPathBaseFieldIds));
1885
1944
  if (!res.success) {
1886
1945
  const fieldErrors = {};
1887
1946
  res.error.issues.forEach((issue) => {
@@ -1911,7 +1970,7 @@ function CrudForm({
1911
1970
  for (const injectedId of injectedFieldIdSet) {
1912
1971
  delete projectedCoreValues[injectedId];
1913
1972
  }
1914
- coreSubmitValues = schema ? schema.parse(projectedCoreValues) : projectedCoreValues;
1973
+ coreSubmitValues = schema ? schema.parse(collapseDotPathFields(projectedCoreValues, dotPathBaseFieldIds)) : projectedCoreValues;
1915
1974
  if (result.applyToForm) {
1916
1975
  setValues(result.data);
1917
1976
  }