Repository: strapi/strapi
File: packages/core/content-manager/admin/src/pages/EditView/utils/data.ts (TypeScript)

Code before:
/* -------------------------------------------------------------------------------------------------
 * traverseData
 * -----------------------------------------------------------------------------------------------*/

// Make only attributes required since it's the only one Content History has
type PartialSchema = Partial<Schema.Schema> & Pick<Schema.Schema, 'attributes'>;

type Predicate = <TAttribute extends Schema.Attribute.AnyAttribute>(
  attribute: TAttribute,
  value: Schema.Attribute.Value<TAttribute>
) => boolean;
type Transform = <TAttribute extends Schema.Attribute.AnyAttribute>(
  value: any,
  attribute: TAttribute
) => any;
type AnyData = Omit<Document, 'id'>;

const BLOCK_LIST_ATTRIBUTE_KEYS = ['__component', '__temp_key__'];

/**
 * @internal This function is used to traverse the data and transform the values.
 * Given a predicate function, it will transform the value (using the given transform function)
 * if the predicate returns true. If it finds that the attribute is a component or dynamiczone,
 * it will recursively traverse those data structures as well.
 *
 * It is possible to break the ContentManager by using this function incorrectly, for example,
 * if you transform a number into a string but the attribute type is a number, the ContentManager
 * will not be able to save the data and the Form will likely crash because the component it's
 * passing the data too won't succesfully be able to handle the value.
 */
const traverseData =
  (predicate: Predicate, transform: Transform) =>
  (schema: PartialSchema, components: ComponentsDictionary = {}) =>
  (data: AnyData = {}) => {
    const traverse = (datum: AnyData, attributes: Schema.Schema['attributes']) => {
      return Object.entries(datum).reduce<AnyData>((acc, [key, value]) => {
        const attribute = attributes[key];

        /**
         * If the attribute is a block list attribute, we don't want to transform it.
         * We also don't want to transform null or undefined values.
         */
        if (BLOCK_LIST_ATTRIBUTE_KEYS.includes(key) || value === null || value === undefined) {
          acc[key] = value;
          return acc;
        }

        if (attribute.type === 'component') {
          if (attribute.repeatable) {
            const componentValue = (
              predicate(attribute, value) ? transform(value, attribute) : value

Review comment (suggestion):
not really a big issue, but here the regex gets created each call to `getDirectParent`, could we try something like 
```
  const NUMERIC_INDEX_REGEX = /^\d+$/;

  const getDirectParent = (data: unknown, path: string): unknown => {
    if (!path) return undefined;
    const isNumericIndex = (value: string) => NUMERIC_INDEX_REGEX.test(value);
```

😄 

Code after:
/* -------------------------------------------------------------------------------------------------
 * traverseData
 * -----------------------------------------------------------------------------------------------*/

// Make only attributes required since it's the only one Content History has
type PartialSchema = Partial<Schema.Schema> & Pick<Schema.Schema, 'attributes'>;

type Predicate = <TAttribute extends Schema.Attribute.AnyAttribute>(
  attribute: TAttribute,
  value: Schema.Attribute.Value<TAttribute>
) => boolean;
type Transform = <TAttribute extends Schema.Attribute.AnyAttribute>(
  value: any,
  attribute: TAttribute
) => any;
type AnyData = Omit<Document, 'id'>;

const BLOCK_LIST_ATTRIBUTE_KEYS = ['__component', '__temp_key__'];

/**
 * @internal
 * @description Returns the direct parent object for a dot-separated path.
 */
const getDirectParent = (data: unknown, path: string): unknown => {
  if (!path) return undefined;
  const isNumericIndex = (value: string) => /^\d+$/.test(value);
  const segments = path.split('.');
  const parentPath = segments.slice(0, -1);
  let current: unknown = data;

  for (const segment of parentPath) {
    if (current == null) return undefined;

    if (isNumericIndex(segment)) {
      if (!Array.isArray(current)) return undefined;
      current = current[Number(segment)];
      continue;
    }

    if (typeof current !== 'object') return undefined;
    current = (current as Record<string, unknown>)[segment];
  }

  return current;
};

/**
 * @internal This function is used to traverse the data and transform the values.
 * Given a predicate function, it will transform the value (using the given transform function)
 * if the predicate returns true. If it finds that the attribute is a component or dynamiczone,
 * it will recursively traverse those data structures as well.