{"version":3,"file":"sanitizers.mjs","sources":["../../src/sanitize/sanitizers.ts"],"sourcesContent":["import { curry, isEmpty, isPlainObject } from 'lodash';\n\nimport { pipe as pipeAsync } from '../async';\nimport traverseEntity from '../traverse-entity';\nimport { isScalarAttribute, constants } from '../content-types';\n\nimport {\n  traverseQueryFilters,\n  traverseQuerySort,\n  traverseQueryPopulate,\n  traverseQueryFields,\n} from '../traverse';\n\nimport {\n  removePassword,\n  removePrivate,\n  removeDynamicZones,\n  removeMorphToRelations,\n  expandWildcardPopulate,\n} from './visitors';\nimport { isOperator } from '../operators';\n\nimport type { Model, Data } from '../types';\nimport type { Parent } from '../traverse/factory';\n\ninterface Context {\n  schema: Model;\n  getModel: (model: string) => Model;\n  parent?: Parent;\n}\n\nconst { ID_ATTRIBUTE, DOC_ID_ATTRIBUTE } = constants;\n\nconst sanitizePasswords = (ctx: Context) => async (entity: Data) => {\n  if (!ctx.schema) {\n    throw new Error('Missing schema in sanitizePasswords');\n  }\n\n  return traverseEntity(removePassword, ctx, entity);\n};\n\nconst defaultSanitizeOutput = async (ctx: Context, entity: Data) => {\n  if (!ctx.schema) {\n    throw new Error('Missing schema in defaultSanitizeOutput');\n  }\n\n  // Named parameters rather than a rest-spread: this runs once per key, per node, per\n  // entity, and `(...args)` allocated a fresh array on every call.\n  return traverseEntity(\n    (visitorOptions, visitorUtils) => {\n      removePassword(visitorOptions, visitorUtils);\n      removePrivate(visitorOptions, visitorUtils);\n    },\n    ctx,\n    entity\n  );\n};\n\nconst defaultSanitizeFilters = curry((ctx: Context, filters: unknown) => {\n  if (!ctx.schema) {\n    throw new Error('Missing schema in defaultSanitizeFilters');\n  }\n\n  return pipeAsync(\n    // Remove keys that are not attributes or valid operators\n    traverseQueryFilters(({ key, attribute }, { remove }) => {\n      const isAttribute = !!attribute;\n\n      // ID is not an attribute per se, so we need to make\n      // an extra check to ensure we're not checking it\n      if ([ID_ATTRIBUTE, DOC_ID_ATTRIBUTE].includes(key)) {\n        return;\n      }\n\n      if (!isAttribute && !isOperator(key)) {\n        remove(key);\n      }\n    }, ctx),\n    // Remove dynamic zones from filters\n    traverseQueryFilters(removeDynamicZones, ctx),\n    // Remove morpTo relations from filters\n    traverseQueryFilters(removeMorphToRelations, ctx),\n    // Remove passwords from filters\n    traverseQueryFilters(removePassword, ctx),\n    // Remove private from filters\n    traverseQueryFilters(removePrivate, ctx),\n    // Remove empty plain objects and empty arrays. Do not use lodash isObject+isEmpty: built-ins with no\n    // enumerable keys (Date, RegExp, boxed primitives, etc.) are \"empty\" and would wrongly drop valid operands.\n    traverseQueryFilters(({ key, value }, { remove }) => {\n      const isEmptyPlainObject = isPlainObject(value) && isEmpty(value);\n      const isEmptyArrayOperand = Array.isArray(value) && value.length === 0;\n      if (isEmptyPlainObject || isEmptyArrayOperand) {\n        remove(key);\n      }\n    }, ctx)\n  )(filters);\n});\n\nconst defaultSanitizeSort = curry((ctx: Context, sort: unknown) => {\n  if (!ctx.schema) {\n    throw new Error('Missing schema in defaultSanitizeSort');\n  }\n\n  return pipeAsync(\n    // Remove non attribute keys\n    traverseQuerySort(({ key, attribute }, { remove }) => {\n      // ID is not an attribute per se, so we need to make\n      // an extra check to ensure we're not checking it\n      if ([ID_ATTRIBUTE, DOC_ID_ATTRIBUTE].includes(key)) {\n        return;\n      }\n\n      if (!attribute) {\n        remove(key);\n      }\n    }, ctx),\n    // Remove dynamic zones from sort\n    traverseQuerySort(removeDynamicZones, ctx),\n    // Remove morpTo relations from sort\n    traverseQuerySort(removeMorphToRelations, ctx),\n    // Remove private from sort\n    traverseQuerySort(removePrivate, ctx),\n    // Remove passwords from filters\n    traverseQuerySort(removePassword, ctx),\n    // Remove keys for empty non-scalar values\n    traverseQuerySort(({ key, attribute, value }, { remove }) => {\n      // ID is not an attribute per se, so we need to make\n      // an extra check to ensure we're not removing it\n      if ([ID_ATTRIBUTE, DOC_ID_ATTRIBUTE].includes(key)) {\n        return;\n      }\n\n      if (!isScalarAttribute(attribute) && isEmpty(value)) {\n        remove(key);\n      }\n    }, ctx)\n  )(sort);\n});\n\nconst defaultSanitizeFields = curry((ctx: Context, fields: unknown) => {\n  if (!ctx.schema) {\n    throw new Error('Missing schema in defaultSanitizeFields');\n  }\n\n  return pipeAsync(\n    // Only keep scalar attributes\n    traverseQueryFields(({ key, attribute }, { remove }) => {\n      // ID is not an attribute per se, so we need to make\n      // an extra check to ensure we're not checking it\n      if ([ID_ATTRIBUTE, DOC_ID_ATTRIBUTE].includes(key)) {\n        return;\n      }\n\n      if (attribute == null || !isScalarAttribute(attribute)) {\n        remove(key);\n      }\n    }, ctx),\n    // Remove private fields\n    traverseQueryFields(removePrivate, ctx),\n    // Remove password fields\n    traverseQueryFields(removePassword, ctx),\n    // Remove nil values from fields array\n    (value) => (Array.isArray(value) ? value.filter((field) => field != null) : value)\n  )(fields);\n});\n\nconst defaultSanitizePopulate = curry((ctx: Context, populate: unknown) => {\n  if (!ctx.schema) {\n    throw new Error('Missing schema in defaultSanitizePopulate');\n  }\n\n  return pipeAsync(\n    traverseQueryPopulate(expandWildcardPopulate, ctx),\n    traverseQueryPopulate(async ({ key, value, schema, attribute, getModel, path }, { set }) => {\n      if (attribute) {\n        return;\n      }\n\n      const parent = { key, path, schema, attribute } satisfies Parent;\n\n      if (key === 'sort') {\n        set(key, await defaultSanitizeSort({ schema, getModel, parent }, value));\n      }\n\n      if (key === 'filters') {\n        set(key, await defaultSanitizeFilters({ schema, getModel, parent }, value));\n      }\n\n      if (key === 'fields') {\n        set(key, await defaultSanitizeFields({ schema, getModel, parent }, value));\n      }\n\n      if (key === 'populate') {\n        set(key, await defaultSanitizePopulate({ schema, getModel, parent }, value));\n      }\n    }, ctx),\n    // Remove private fields\n    traverseQueryPopulate(removePrivate, ctx)\n  )(populate);\n});\n\nexport {\n  sanitizePasswords,\n  defaultSanitizeOutput,\n  defaultSanitizeFilters,\n  defaultSanitizeSort,\n  defaultSanitizeFields,\n  defaultSanitizePopulate,\n};\n"],"names":["ID_ATTRIBUTE","DOC_ID_ATTRIBUTE","constants","sanitizePasswords","ctx","entity","schema","Error","traverseEntity","removePassword","defaultSanitizeOutput","visitorOptions","visitorUtils","removePrivate","defaultSanitizeFilters","curry","filters","pipeAsync","traverseQueryFilters","key","attribute","remove","isAttribute","includes","isOperator","removeDynamicZones","removeMorphToRelations","value","isEmptyPlainObject","isPlainObject","isEmpty","isEmptyArrayOperand","Array","isArray","length","defaultSanitizeSort","sort","traverseQuerySort","isScalarAttribute","defaultSanitizeFields","fields","traverseQueryFields","filter","field","defaultSanitizePopulate","populate","traverseQueryPopulate","expandWildcardPopulate","getModel","path","set","parent"],"mappings":"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"}