{"version":3,"file":"factory.mjs","sources":["../../src/traverse/factory.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-loop-func */\nimport { isNil, pick } from 'lodash/fp';\n\nimport {\n  AnyAttribute,\n  Attribute,\n  ComponentAttribute,\n  DynamicZoneAttribute,\n  Model,\n  RelationalAttribute,\n} from '../types';\n\nexport interface Path {\n  raw: string | null;\n  attribute: string | null;\n}\n\nexport interface Parent {\n  attribute?: Attribute;\n  key: string | null;\n  path: Path;\n  schema: Model;\n}\n\nexport interface TraverseOptions {\n  schema: Model;\n  path?: Path;\n  parent?: Parent;\n  getModel(uid: string): Model;\n}\n\nexport interface VisitorOptions {\n  data: unknown;\n  value: unknown;\n  schema: Model;\n  key: string;\n  attribute?: AnyAttribute;\n  path: Path;\n  parent?: Parent;\n  getModel(uid: string): Model;\n}\n\nexport type Traverse = (\n  visitor: Visitor,\n  options: TraverseOptions,\n  data: unknown\n) => Promise<unknown>;\n\nexport interface Visitor {\n  (visitorOptions: VisitorOptions, opts: Pick<TransformUtils, 'set' | 'remove'>): void;\n}\n\ninterface Interceptor<T = unknown> {\n  predicate(data: unknown): data is T;\n  handler(\n    visitor: Visitor,\n    options: TraverseOptions,\n    data: T,\n    recurseOptions: { recurse: Traverse }\n  ): void;\n}\n\ninterface ParseUtils<T> {\n  transform(data: T): unknown;\n  remove(key: string, data: T): unknown;\n  set(key: string, value: unknown, data: T): unknown;\n  keys(data: T): string[];\n  get(key: string, data: T): unknown;\n}\n\ninterface Parser<T = unknown> {\n  predicate(data: unknown): data is T;\n  parser(data: T): ParseUtils<T>;\n}\n\ninterface Ignore {\n  (ctx: Context): boolean;\n}\n\ninterface AttributeHandler<AttributeType = Attribute> {\n  predicate(ctx: Context<AttributeType>): boolean;\n  handler(ctx: Context<AttributeType>, opts: Pick<TransformUtils, 'set' | 'recurse'>): void;\n}\ninterface CommonHandler<AttributeType = Attribute> {\n  predicate(ctx: Context<AttributeType>): boolean;\n  handler(ctx: Context<AttributeType>, opts: Pick<TransformUtils, 'set' | 'recurse'>): void;\n}\n\nexport interface TransformUtils {\n  remove(key: string): void;\n  set(key: string, value: unknown): void;\n  recurse: Traverse;\n}\n\ninterface Context<AttributeType = Attribute> {\n  key: string;\n  value: unknown;\n  attribute: AttributeType;\n  schema: Model;\n  path: Path;\n  data: unknown;\n  visitor: Visitor;\n  parent?: Parent;\n  getModel(uid: string): Model;\n}\n\ninterface State {\n  parsers: Parser[];\n  interceptors: Interceptor[];\n  ignore: Ignore[];\n  handlers: {\n    attributes: AttributeHandler[];\n    common: CommonHandler[];\n  };\n}\n\nconst DEFAULT_PATH = { raw: null, attribute: null } satisfies Path;\n\nexport default () => {\n  const state: State = {\n    parsers: [],\n    interceptors: [],\n    ignore: [],\n    handlers: {\n      attributes: [],\n      common: [],\n    },\n  };\n\n  const traverse: Traverse = async (visitor, options, data) => {\n    const { path = DEFAULT_PATH, parent, schema, getModel } = options ?? {};\n\n    // interceptors\n    for (const { predicate, handler } of state.interceptors) {\n      if (predicate(data)) {\n        return handler(visitor, options, data, { recurse: traverse });\n      }\n    }\n\n    // parsers\n    const parser = state.parsers.find((parser) => parser.predicate(data))?.parser;\n    const utils = parser?.(data);\n\n    // Return the data untouched if we don't know how to traverse it\n    if (!utils) {\n      return data;\n    }\n\n    // main loop\n    let out = utils.transform(data);\n    const keys = utils.keys(out);\n\n    for (const key of keys) {\n      const attribute = schema?.attributes?.[key];\n\n      const newPath = { ...path };\n\n      newPath.raw = isNil(path.raw) ? key : `${path.raw}.${key}`;\n\n      if (!isNil(attribute)) {\n        newPath.attribute = isNil(path.attribute) ? key : `${path.attribute}.${key}`;\n      }\n\n      // visitors\n      const visitorOptions: VisitorOptions = {\n        key,\n        value: utils.get(key, out),\n        attribute,\n        schema,\n        path: newPath,\n        data: out,\n        getModel,\n        parent,\n      };\n\n      const transformUtils: TransformUtils = {\n        remove(key) {\n          out = utils.remove(key, out);\n        },\n        set(key, value) {\n          out = utils.set(key, value, out);\n        },\n        recurse: traverse,\n      };\n\n      await visitor(visitorOptions, pick(['remove', 'set'], transformUtils));\n\n      const value = utils.get(key, out);\n\n      const createContext = (): Context => ({\n        key,\n        value,\n        attribute,\n        schema,\n        path: newPath,\n        data: out,\n        visitor,\n        getModel,\n        parent,\n      });\n\n      // ignore\n      const ignoreCtx = createContext();\n      const shouldIgnore = state.ignore.some((predicate) => predicate(ignoreCtx));\n\n      if (shouldIgnore) {\n        continue;\n      }\n\n      // handlers\n      const handlers = [...state.handlers.common, ...state.handlers.attributes];\n\n      for await (const handler of handlers) {\n        const ctx = createContext();\n        const pass = await handler.predicate(ctx);\n\n        if (pass) {\n          await handler.handler(ctx, pick(['recurse', 'set'], transformUtils));\n        }\n      }\n    }\n\n    return out;\n  };\n\n  return {\n    traverse,\n\n    intercept<T>(predicate: Interceptor<T>['predicate'], handler: Interceptor<T>['handler']) {\n      state.interceptors.push({ predicate, handler });\n      return this;\n    },\n\n    parse<T>(predicate: Parser<T>['predicate'], parser: Parser<T>['parser']) {\n      state.parsers.push({ predicate, parser });\n      return this;\n    },\n\n    ignore(predicate: Ignore) {\n      state.ignore.push(predicate);\n      return this;\n    },\n\n    on(predicate: CommonHandler['predicate'], handler: CommonHandler['handler']) {\n      state.handlers.common.push({ predicate, handler });\n      return this;\n    },\n\n    onAttribute(predicate: AttributeHandler['predicate'], handler: AttributeHandler['handler']) {\n      state.handlers.attributes.push({ predicate, handler });\n      return this;\n    },\n\n    onRelation(handler: AttributeHandler<RelationalAttribute>['handler']) {\n      return this.onAttribute(({ attribute }) => attribute?.type === 'relation', handler);\n    },\n\n    onMedia(handler: AttributeHandler<RelationalAttribute>['handler']) {\n      return this.onAttribute(({ attribute }) => attribute?.type === 'media', handler);\n    },\n\n    onComponent(handler: AttributeHandler<ComponentAttribute>['handler']) {\n      return this.onAttribute(({ attribute }) => attribute?.type === 'component', handler);\n    },\n\n    onDynamicZone(handler: AttributeHandler<DynamicZoneAttribute>['handler']) {\n      return this.onAttribute(({ attribute }) => attribute?.type === 'dynamiczone', handler);\n    },\n  };\n};\n"],"names":["DEFAULT_PATH","raw","attribute","state","parsers","interceptors","ignore","handlers","attributes","common","traverse","visitor","options","data","path","parent","schema","getModel","predicate","handler","recurse","parser","find","utils","out","transform","keys","key","newPath","isNil","visitorOptions","value","get","transformUtils","remove","set","pick","createContext","ignoreCtx","shouldIgnore","some","ctx","pass","intercept","push","parse","on","onAttribute","onRelation","type","onMedia","onComponent","onDynamicZone"],"mappings":"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"}