@strapi/utils 5.48.1 → 5.50.0

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.
Files changed (131) hide show
  1. package/dist/async.d.ts +2 -1
  2. package/dist/async.d.ts.map +1 -1
  3. package/dist/async.js +5 -1
  4. package/dist/async.js.map +1 -1
  5. package/dist/content-api-router.d.ts.map +1 -1
  6. package/dist/content-types.d.ts +5 -5
  7. package/dist/content-types.d.ts.map +1 -1
  8. package/dist/content-types.js +21 -17
  9. package/dist/content-types.js.map +1 -1
  10. package/dist/convert-query-params.d.ts.map +1 -1
  11. package/dist/convert-query-params.js +23 -19
  12. package/dist/convert-query-params.js.map +1 -1
  13. package/dist/convert-query-params.mjs +2 -2
  14. package/dist/convert-query-params.mjs.map +1 -1
  15. package/dist/env-helper.js +12 -8
  16. package/dist/env-helper.js.map +1 -1
  17. package/dist/errors.d.ts.map +1 -1
  18. package/dist/file.d.ts +0 -10
  19. package/dist/file.d.ts.map +1 -1
  20. package/dist/format-yup-error.d.ts.map +1 -1
  21. package/dist/has-published-version-param.d.ts +1 -1
  22. package/dist/has-published-version-param.d.ts.map +1 -1
  23. package/dist/hooks.d.ts.map +1 -1
  24. package/dist/index.d.ts +3 -0
  25. package/dist/index.d.ts.map +1 -1
  26. package/dist/index.js +12 -2
  27. package/dist/index.js.map +1 -1
  28. package/dist/index.mjs +3 -0
  29. package/dist/index.mjs.map +1 -1
  30. package/dist/install-id.d.ts.map +1 -1
  31. package/dist/install-id.js +6 -2
  32. package/dist/install-id.js.map +1 -1
  33. package/dist/model-cache.d.ts.map +1 -1
  34. package/dist/operators.d.ts.map +1 -1
  35. package/dist/package-manager.d.ts.map +1 -1
  36. package/dist/package-manager.js +7 -2
  37. package/dist/package-manager.js.map +1 -1
  38. package/dist/pagination.d.ts.map +1 -1
  39. package/dist/parse-type.d.ts.map +1 -1
  40. package/dist/parse-type.js +4 -3
  41. package/dist/parse-type.js.map +1 -1
  42. package/dist/policy.d.ts.map +1 -1
  43. package/dist/primitives/arrays.d.ts.map +1 -1
  44. package/dist/primitives/dates.d.ts.map +1 -1
  45. package/dist/primitives/objects.d.ts.map +1 -1
  46. package/dist/primitives/objects.js +6 -2
  47. package/dist/primitives/objects.js.map +1 -1
  48. package/dist/primitives/strings.d.ts.map +1 -1
  49. package/dist/primitives/strings.js +10 -5
  50. package/dist/primitives/strings.js.map +1 -1
  51. package/dist/provider-factory.d.ts.map +1 -1
  52. package/dist/publication-filter.d.ts +1 -1
  53. package/dist/publication-filter.d.ts.map +1 -1
  54. package/dist/relations.d.ts.map +1 -1
  55. package/dist/route-serialization.d.ts.map +1 -1
  56. package/dist/sanitize/index.d.ts.map +1 -1
  57. package/dist/sanitize/index.js +4 -1
  58. package/dist/sanitize/index.js.map +1 -1
  59. package/dist/sanitize/index.mjs +4 -1
  60. package/dist/sanitize/index.mjs.map +1 -1
  61. package/dist/sanitize/sanitizers.d.ts +0 -1
  62. package/dist/sanitize/sanitizers.d.ts.map +1 -1
  63. package/dist/sanitize/visitors/remove-disallowed-fields.d.ts.map +1 -1
  64. package/dist/sanitize/visitors/remove-restricted-fields.d.ts.map +1 -1
  65. package/dist/sanitize/visitors/remove-restricted-relations.d.ts.map +1 -1
  66. package/dist/security.d.ts +1 -1
  67. package/dist/security.d.ts.map +1 -1
  68. package/dist/sessions.d.ts +35 -0
  69. package/dist/sessions.d.ts.map +1 -0
  70. package/dist/sessions.js +46 -0
  71. package/dist/sessions.js.map +1 -0
  72. package/dist/sessions.mjs +42 -0
  73. package/dist/sessions.mjs.map +1 -0
  74. package/dist/set-creator-fields.d.ts.map +1 -1
  75. package/dist/sort-query.js +5 -1
  76. package/dist/sort-query.js.map +1 -1
  77. package/dist/template.d.ts.map +1 -1
  78. package/dist/traverse/factory.d.ts +108 -9
  79. package/dist/traverse/factory.d.ts.map +1 -1
  80. package/dist/traverse/query-fields.d.ts +0 -1
  81. package/dist/traverse/query-fields.d.ts.map +1 -1
  82. package/dist/traverse/query-filters.d.ts +0 -1
  83. package/dist/traverse/query-filters.d.ts.map +1 -1
  84. package/dist/traverse/query-populate.d.ts +0 -1
  85. package/dist/traverse/query-populate.d.ts.map +1 -1
  86. package/dist/traverse/query-populate.js +24 -0
  87. package/dist/traverse/query-populate.js.map +1 -1
  88. package/dist/traverse/query-populate.mjs +24 -0
  89. package/dist/traverse/query-populate.mjs.map +1 -1
  90. package/dist/traverse/query-sort.d.ts +0 -1
  91. package/dist/traverse/query-sort.d.ts.map +1 -1
  92. package/dist/traverse-entity.d.ts +0 -1
  93. package/dist/traverse-entity.d.ts.map +1 -1
  94. package/dist/traverse-entity.js +7 -0
  95. package/dist/traverse-entity.js.map +1 -1
  96. package/dist/traverse-entity.mjs +7 -0
  97. package/dist/traverse-entity.mjs.map +1 -1
  98. package/dist/types.d.ts +0 -25
  99. package/dist/types.d.ts.map +1 -1
  100. package/dist/user-agent.d.ts +23 -0
  101. package/dist/user-agent.d.ts.map +1 -0
  102. package/dist/user-agent.js +74 -0
  103. package/dist/user-agent.js.map +1 -0
  104. package/dist/user-agent.mjs +71 -0
  105. package/dist/user-agent.mjs.map +1 -0
  106. package/dist/validate/index.d.ts.map +1 -1
  107. package/dist/validate/utils.d.ts.map +1 -1
  108. package/dist/validate/validators.d.ts +4 -4
  109. package/dist/validate/validators.d.ts.map +1 -1
  110. package/dist/validate/validators.js +157 -0
  111. package/dist/validate/validators.js.map +1 -1
  112. package/dist/validate/validators.mjs +159 -2
  113. package/dist/validate/validators.mjs.map +1 -1
  114. package/dist/validate/visitors/throw-disallowed-fields.d.ts.map +1 -1
  115. package/dist/validate/visitors/throw-restricted-fields.d.ts.map +1 -1
  116. package/dist/validate/visitors/throw-restricted-relations.d.ts.map +1 -1
  117. package/dist/validation/route-validators/query-params.js +3 -2
  118. package/dist/validation/route-validators/query-params.js.map +1 -1
  119. package/dist/validation/utilities.d.ts +5 -5
  120. package/dist/validation/utilities.d.ts.map +1 -1
  121. package/dist/validators.d.ts.map +1 -1
  122. package/dist/validators.js +3 -2
  123. package/dist/validators.js.map +1 -1
  124. package/dist/yup.d.ts.map +1 -1
  125. package/dist/yup.js +10 -6
  126. package/dist/yup.js.map +1 -1
  127. package/dist/zod.d.ts +1 -1
  128. package/dist/zod.d.ts.map +1 -1
  129. package/dist/zod.js +3 -2
  130. package/dist/zod.js.map +1 -1
  131. package/package.json +9 -5
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../src/sanitize/index.ts"],"sourcesContent":["import { CurriedFunction1 } from 'lodash';\nimport { isArray, cloneDeep, omit, pick } from 'lodash/fp';\nimport type { z } from 'zod/v4';\n\nimport { constants, getNonWritableAttributes } from '../content-types';\nimport { ALLOWED_QUERY_PARAM_KEYS } from '../content-api-constants';\nimport {\n type RouteLike,\n getExtraQueryKeysFromRoute,\n getExtraRootKeysFromRouteBody,\n} from '../content-api-route-params';\nimport { pipe as pipeAsync } from '../async';\n\nimport * as visitors from './visitors';\nimport * as sanitizers from './sanitizers';\nimport traverseEntity from '../traverse-entity';\n\nimport { traverseQueryFilters, traverseQuerySort, traverseQueryPopulate } from '../traverse';\nimport type { Model, Data } from '../types';\nimport { validatePublicationFilterQueryParam } from '../publication-filter';\n\nexport interface Options {\n auth?: unknown;\n /**\n * If true, removes fields that are not declared in the schema (input) or keeps only allowed query param keys (query).\n * Defaults to false for backward compatibility.\n * TODO: In Strapi 6, strictParams will default to true (and may be removed as an option)\n */\n strictParams?: boolean;\n /**\n * When set, extra query/input params are derived from the route's request schema (and validated/sanitized with Zod).\n * When absent, no extra params are allowed in strict mode.\n */\n route?: RouteLike;\n}\n\nexport interface Sanitizer {\n (schema: Model): CurriedFunction1<Data, Promise<Data>>;\n}\nexport interface SanitizeFunc {\n (data: unknown, schema: Model, options?: Options): Promise<unknown>;\n}\n\nexport type SanitizeQueryParamHandler = (\n value: unknown,\n schema: Model,\n options?: Options\n) => Promise<unknown>;\n\nexport type SanitizeBodyParamHandler = (\n value: unknown,\n schema: Model,\n options?: Options\n) => Promise<unknown>;\n\nexport interface APIOptions {\n sanitizers?: Sanitizers;\n getModel: (model: string) => Model;\n}\n\nexport interface Sanitizers {\n input?: Sanitizer[];\n output?: Sanitizer[];\n}\n\nconst createAPISanitizers = (opts: APIOptions) => {\n const { getModel } = opts;\n\n const sanitizeInput: SanitizeFunc = (\n data: unknown,\n schema: Model,\n { auth, strictParams = false, route } = {}\n ) => {\n if (!schema) {\n throw new Error('Missing schema in sanitizeInput');\n }\n if (isArray(data)) {\n return Promise.all(\n data.map((entry) => sanitizeInput(entry, schema, { auth, strictParams, route }))\n );\n }\n\n const allowedExtraRootKeys = getExtraRootKeysFromRouteBody(route);\n\n const nonWritableAttributes = getNonWritableAttributes(schema);\n\n const transforms = [\n // Remove first level ID in inputs\n omit(constants.ID_ATTRIBUTE),\n omit(constants.DOC_ID_ATTRIBUTE),\n // Remove non-writable attributes\n traverseEntity(visitors.removeRestrictedFields(nonWritableAttributes), { schema, getModel }),\n ];\n\n if (strictParams) {\n // Remove unrecognized fields (allowedExtraRootKeys = registered input param keys)\n transforms.push(\n traverseEntity(visitors.removeUnrecognizedFields, {\n schema,\n getModel,\n allowedExtraRootKeys,\n })\n );\n }\n\n if (auth) {\n // Remove restricted relations\n transforms.push(\n traverseEntity(visitors.removeRestrictedRelations(auth), { schema, getModel })\n );\n }\n\n // Apply sanitizers from registry if exists\n opts?.sanitizers?.input?.forEach((sanitizer: Sanitizer) => transforms.push(sanitizer(schema)));\n\n /**\n * For each extra root key from the route's body schema present in data, run Zod safeParse.\n * If parsing fails, the key is removed from the output.\n *\n * Content-api sends the document payload as body.data; the controller calls sanitizeInput(body.data, ctx),\n * so the input we receive here is the inner payload (keys like \"relatedMedia\", \"name\"), not the full body.\n * The route's body schema is z.object({ data: ... }), so its shape includes \"data\". We skip \"data\" because\n * the main document payload is already sanitized above by traverseEntity (removeUnrecognizedFields, etc.);\n * relation ops (connect/disconnect/set) are handled there, not by the route's Zod schema. We only run\n * Zod here for truly extra root keys added via addInputParams (e.g. clientMutationId).\n */\n const routeBodySanitizeTransform = async (data: Data): Promise<Data> => {\n if (!data || typeof data !== 'object' || Array.isArray(data)) return data;\n const obj = data as Record<string, unknown>;\n const bodySchema = route?.request?.body?.['application/json'];\n if (bodySchema && typeof bodySchema === 'object' && 'shape' in bodySchema) {\n const shape = (bodySchema as { shape: Record<string, z.ZodTypeAny> }).shape;\n for (const key of Object.keys(shape)) {\n if (key === 'data' || !(key in obj)) continue;\n const zodSchema = shape[key];\n if (zodSchema && typeof (zodSchema as z.ZodTypeAny).safeParse === 'function') {\n const result = (zodSchema as z.ZodTypeAny).safeParse(obj[key]);\n if (result.success) {\n obj[key] = result.data;\n } else {\n delete obj[key];\n }\n }\n }\n }\n return data;\n };\n (transforms as Array<(data: Data) => Data | Promise<Data>>).push(routeBodySanitizeTransform);\n\n return pipeAsync(...transforms)(data as Data);\n };\n\n const sanitizeOutput: SanitizeFunc = async (data, schema: Model, { auth } = {}) => {\n if (!schema) {\n throw new Error('Missing schema in sanitizeOutput');\n }\n if (isArray(data)) {\n const res = new Array(data.length);\n for (let i = 0; i < data.length; i += 1) {\n res[i] = await sanitizeOutput(data[i], schema, { auth });\n }\n return res;\n }\n\n const transforms = [\n (data: Data) => sanitizers.defaultSanitizeOutput({ schema, getModel }, data),\n ];\n\n if (auth) {\n transforms.push(\n traverseEntity(visitors.removeRestrictedRelations(auth), { schema, getModel })\n );\n }\n\n // Apply sanitizers from registry if exists\n opts?.sanitizers?.output?.forEach((sanitizer: Sanitizer) => transforms.push(sanitizer(schema)));\n\n return pipeAsync(...transforms)(data as Data);\n };\n\n const sanitizeQuery = async (\n query: Record<string, unknown>,\n schema: Model,\n { auth, strictParams = false, route }: Options = {}\n ) => {\n if (!schema) {\n throw new Error('Missing schema in sanitizeQuery');\n }\n const { filters, sort, fields, populate } = query;\n\n const sanitizedQuery = cloneDeep(query);\n\n if ('publicationFilter' in sanitizedQuery) {\n validatePublicationFilterQueryParam(sanitizedQuery.publicationFilter);\n }\n\n if (filters) {\n Object.assign(sanitizedQuery, { filters: await sanitizeFilters(filters, schema, { auth }) });\n }\n\n if (sort) {\n Object.assign(sanitizedQuery, { sort: await sanitizeSort(sort, schema, { auth }) });\n }\n\n if (fields) {\n Object.assign(sanitizedQuery, { fields: await sanitizeFields(fields, schema) });\n }\n\n if (populate) {\n Object.assign(sanitizedQuery, { populate: await sanitizePopulate(populate, schema) });\n }\n\n const extraQueryKeys = getExtraQueryKeysFromRoute(route);\n const routeQuerySchema = route?.request?.query;\n if (routeQuerySchema) {\n for (const key of extraQueryKeys) {\n if (key in query) {\n const zodSchema = routeQuerySchema[key];\n if (zodSchema && typeof (zodSchema as z.ZodTypeAny).safeParse === 'function') {\n const result = (zodSchema as z.ZodTypeAny).safeParse(query[key]);\n if (result.success) {\n sanitizedQuery[key] = result.data;\n } else {\n delete sanitizedQuery[key];\n }\n }\n }\n }\n }\n\n if (strictParams) {\n const allowedKeys = [...ALLOWED_QUERY_PARAM_KEYS, ...extraQueryKeys];\n return pick(allowedKeys, sanitizedQuery) as Record<string, unknown>;\n }\n\n return sanitizedQuery;\n };\n\n const sanitizeFilters: SanitizeFunc = (filters, schema: Model, { auth } = {}) => {\n if (!schema) {\n throw new Error('Missing schema in sanitizeFilters');\n }\n if (isArray(filters)) {\n return Promise.all(filters.map((filter) => sanitizeFilters(filter, schema, { auth })));\n }\n\n const transforms = [sanitizers.defaultSanitizeFilters({ schema, getModel })];\n\n if (auth) {\n transforms.push(\n traverseQueryFilters(visitors.removeRestrictedRelations(auth), { schema, getModel })\n );\n }\n\n return pipeAsync(...transforms)(filters);\n };\n\n const sanitizeSort: SanitizeFunc = (sort, schema: Model, { auth } = {}) => {\n if (!schema) {\n throw new Error('Missing schema in sanitizeSort');\n }\n const transforms = [sanitizers.defaultSanitizeSort({ schema, getModel })];\n\n if (auth) {\n transforms.push(\n traverseQuerySort(visitors.removeRestrictedRelations(auth), { schema, getModel })\n );\n }\n\n return pipeAsync(...transforms)(sort);\n };\n\n const sanitizeFields: SanitizeFunc = (fields, schema: Model) => {\n if (!schema) {\n throw new Error('Missing schema in sanitizeFields');\n }\n const transforms = [sanitizers.defaultSanitizeFields({ schema, getModel })];\n\n return pipeAsync(...transforms)(fields);\n };\n\n const sanitizePopulate: SanitizeFunc = (populate, schema: Model, { auth } = {}) => {\n if (!schema) {\n throw new Error('Missing schema in sanitizePopulate');\n }\n const transforms = [sanitizers.defaultSanitizePopulate({ schema, getModel })];\n\n if (auth) {\n transforms.push(\n traverseQueryPopulate(visitors.removeRestrictedRelations(auth), { schema, getModel })\n );\n }\n\n return pipeAsync(...transforms)(populate);\n };\n\n return {\n input: sanitizeInput,\n output: sanitizeOutput,\n query: sanitizeQuery,\n filters: sanitizeFilters,\n sort: sanitizeSort,\n fields: sanitizeFields,\n populate: sanitizePopulate,\n };\n};\n\nexport { createAPISanitizers, sanitizers, visitors };\n\nexport type APISanitiers = ReturnType<typeof createAPISanitizers>;\n"],"names":["createAPISanitizers","opts","getModel","sanitizeInput","data","schema","auth","strictParams","route","Error","isArray","Promise","all","map","entry","allowedExtraRootKeys","getExtraRootKeysFromRouteBody","nonWritableAttributes","getNonWritableAttributes","transforms","omit","constants","ID_ATTRIBUTE","DOC_ID_ATTRIBUTE","traverseEntity","visitors","push","sanitizers","input","forEach","sanitizer","routeBodySanitizeTransform","Array","obj","bodySchema","request","body","shape","key","Object","keys","zodSchema","safeParse","result","success","pipeAsync","sanitizeOutput","res","length","i","output","sanitizeQuery","query","filters","sort","fields","populate","sanitizedQuery","cloneDeep","validatePublicationFilterQueryParam","publicationFilter","assign","sanitizeFilters","sanitizeSort","sanitizeFields","sanitizePopulate","extraQueryKeys","getExtraQueryKeysFromRoute","routeQuerySchema","allowedKeys","ALLOWED_QUERY_PARAM_KEYS","pick","filter","traverseQueryFilters","traverseQuerySort","traverseQueryPopulate"],"mappings":";;;;;;;;;;;;;;;;;;;AAiEA,MAAMA,sBAAsB,CAACC,IAAAA,GAAAA;IAC3B,MAAM,EAAEC,QAAQ,EAAE,GAAGD,IAAAA;AAErB,IAAA,MAAME,aAAAA,GAA8B,CAClCC,IAAAA,EACAC,MAAAA,EACA,EAAEC,IAAI,EAAEC,YAAAA,GAAe,KAAK,EAAEC,KAAK,EAAE,GAAG,EAAE,GAAA;AAE1C,QAAA,IAAI,CAACH,MAAAA,EAAQ;AACX,YAAA,MAAM,IAAII,KAAAA,CAAM,iCAAA,CAAA;AAClB,QAAA;AACA,QAAA,IAAIC,WAAQN,IAAAA,CAAAA,EAAO;YACjB,OAAOO,OAAAA,CAAQC,GAAG,CAChBR,IAAAA,CAAKS,GAAG,CAAC,CAACC,KAAAA,GAAUX,aAAAA,CAAcW,KAAAA,EAAOT,MAAAA,EAAQ;AAAEC,oBAAAA,IAAAA;AAAMC,oBAAAA,YAAAA;AAAcC,oBAAAA;AAAM,iBAAA,CAAA,CAAA,CAAA;AAEjF,QAAA;AAEA,QAAA,MAAMO,uBAAuBC,mDAAAA,CAA8BR,KAAAA,CAAAA;AAE3D,QAAA,MAAMS,wBAAwBC,qCAAAA,CAAyBb,MAAAA,CAAAA;AAEvD,QAAA,MAAMc,UAAAA,GAAa;;AAEjBC,YAAAA,OAAAA,CAAKC,uBAAUC,YAAY,CAAA;AAC3BF,YAAAA,OAAAA,CAAKC,uBAAUE,gBAAgB,CAAA;;YAE/BC,cAAAA,CAAeC,sBAA+B,CAACR,qBAAAA,CAAAA,EAAwB;AAAEZ,gBAAAA,MAAAA;AAAQH,gBAAAA;AAAS,aAAA;AAC3F,SAAA;AAED,QAAA,IAAIK,YAAAA,EAAc;;AAEhBY,YAAAA,UAAAA,CAAWO,IAAI,CACbF,cAAAA,CAAeC,wBAAiC,EAAE;AAChDpB,gBAAAA,MAAAA;AACAH,gBAAAA,QAAAA;AACAa,gBAAAA;AACF,aAAA,CAAA,CAAA;AAEJ,QAAA;AAEA,QAAA,IAAIT,IAAAA,EAAM;;AAERa,YAAAA,UAAAA,CAAWO,IAAI,CACbF,cAAAA,CAAeC,yBAAkC,CAACnB,IAAAA,CAAAA,EAAO;AAAED,gBAAAA,MAAAA;AAAQH,gBAAAA;AAAS,aAAA,CAAA,CAAA;AAEhF,QAAA;;QAGAD,IAAAA,EAAM0B,UAAAA,EAAYC,OAAOC,OAAAA,CAAQ,CAACC,YAAyBX,UAAAA,CAAWO,IAAI,CAACI,SAAAA,CAAUzB,MAAAA,CAAAA,CAAAA,CAAAA;AAErF;;;;;;;;;;QAWA,MAAM0B,6BAA6B,OAAO3B,IAAAA,GAAAA;YACxC,IAAI,CAACA,QAAQ,OAAOA,IAAAA,KAAS,YAAY4B,KAAAA,CAAMtB,OAAO,CAACN,IAAAA,CAAAA,EAAO,OAAOA,IAAAA;AACrE,YAAA,MAAM6B,GAAAA,GAAM7B,IAAAA;AACZ,YAAA,MAAM8B,UAAAA,GAAa1B,KAAAA,EAAO2B,OAAAA,EAASC,IAAAA,GAAO,kBAAA,CAAmB;AAC7D,YAAA,IAAIF,UAAAA,IAAc,OAAOA,UAAAA,KAAe,QAAA,IAAY,WAAWA,UAAAA,EAAY;gBACzE,MAAMG,KAAAA,GAAQ,UAACH,CAAuDG,KAAK;AAC3E,gBAAA,KAAK,MAAMC,GAAAA,IAAOC,MAAAA,CAAOC,IAAI,CAACH,KAAAA,CAAAA,CAAQ;AACpC,oBAAA,IAAIC,QAAQ,MAAA,IAAU,EAAEA,GAAAA,IAAOL,GAAE,CAAA,EAAI;oBACrC,MAAMQ,SAAAA,GAAYJ,KAAK,CAACC,GAAAA,CAAI;AAC5B,oBAAA,IAAIG,aAAa,OAAQA,SAAAA,CAA2BC,SAAS,KAAK,UAAA,EAAY;AAC5E,wBAAA,MAAMC,SAAS,SAACF,CAA2BC,SAAS,CAACT,GAAG,CAACK,GAAAA,CAAI,CAAA;wBAC7D,IAAIK,MAAAA,CAAOC,OAAO,EAAE;AAClBX,4BAAAA,GAAG,CAACK,GAAAA,CAAI,GAAGK,MAAAA,CAAOvC,IAAI;wBACxB,CAAA,MAAO;4BACL,OAAO6B,GAAG,CAACK,GAAAA,CAAI;AACjB,wBAAA;AACF,oBAAA;AACF,gBAAA;AACF,YAAA;YACA,OAAOlC,IAAAA;AACT,QAAA,CAAA;AACCe,QAAAA,UAAAA,CAA2DO,IAAI,CAACK,0BAAAA,CAAAA;AAEjE,QAAA,OAAOc,cAAa1B,UAAAA,CAAAA,CAAYf,IAAAA,CAAAA;AAClC,IAAA,CAAA;IAEA,MAAM0C,cAAAA,GAA+B,OAAO1C,IAAAA,EAAMC,MAAAA,EAAe,EAAEC,IAAI,EAAE,GAAG,EAAE,GAAA;AAC5E,QAAA,IAAI,CAACD,MAAAA,EAAQ;AACX,YAAA,MAAM,IAAII,KAAAA,CAAM,kCAAA,CAAA;AAClB,QAAA;AACA,QAAA,IAAIC,WAAQN,IAAAA,CAAAA,EAAO;AACjB,YAAA,MAAM2C,GAAAA,GAAM,IAAIf,KAAAA,CAAM5B,IAAAA,CAAK4C,MAAM,CAAA;YACjC,IAAK,IAAIC,IAAI,CAAA,EAAGA,CAAAA,GAAI7C,KAAK4C,MAAM,EAAEC,KAAK,CAAA,CAAG;gBACvCF,GAAG,CAACE,EAAE,GAAG,MAAMH,eAAe1C,IAAI,CAAC6C,CAAAA,CAAE,EAAE5C,MAAAA,EAAQ;AAAEC,oBAAAA;AAAK,iBAAA,CAAA;AACxD,YAAA;YACA,OAAOyC,GAAAA;AACT,QAAA;AAEA,QAAA,MAAM5B,UAAAA,GAAa;YACjB,CAACf,IAAAA,GAAeuB,gCAAgC,CAAC;AAAEtB,oBAAAA,MAAAA;AAAQH,oBAAAA;iBAAS,EAAGE,IAAAA;AACxE,SAAA;AAED,QAAA,IAAIE,IAAAA,EAAM;AACRa,YAAAA,UAAAA,CAAWO,IAAI,CACbF,cAAAA,CAAeC,yBAAkC,CAACnB,IAAAA,CAAAA,EAAO;AAAED,gBAAAA,MAAAA;AAAQH,gBAAAA;AAAS,aAAA,CAAA,CAAA;AAEhF,QAAA;;QAGAD,IAAAA,EAAM0B,UAAAA,EAAYuB,QAAQrB,OAAAA,CAAQ,CAACC,YAAyBX,UAAAA,CAAWO,IAAI,CAACI,SAAAA,CAAUzB,MAAAA,CAAAA,CAAAA,CAAAA;AAEtF,QAAA,OAAOwC,cAAa1B,UAAAA,CAAAA,CAAYf,IAAAA,CAAAA;AAClC,IAAA,CAAA;AAEA,IAAA,MAAM+C,aAAAA,GAAgB,OACpBC,KAAAA,EACA/C,MAAAA,EACA,EAAEC,IAAI,EAAEC,YAAAA,GAAe,KAAK,EAAEC,KAAK,EAAW,GAAG,EAAE,GAAA;AAEnD,QAAA,IAAI,CAACH,MAAAA,EAAQ;AACX,YAAA,MAAM,IAAII,KAAAA,CAAM,iCAAA,CAAA;AAClB,QAAA;QACA,MAAM,EAAE4C,OAAO,EAAEC,IAAI,EAAEC,MAAM,EAAEC,QAAQ,EAAE,GAAGJ,KAAAA;AAE5C,QAAA,MAAMK,iBAAiBC,YAAAA,CAAUN,KAAAA,CAAAA;AAEjC,QAAA,IAAI,uBAAuBK,cAAAA,EAAgB;AACzCE,YAAAA,qDAAAA,CAAoCF,eAAeG,iBAAiB,CAAA;AACtE,QAAA;AAEA,QAAA,IAAIP,OAAAA,EAAS;YACXd,MAAAA,CAAOsB,MAAM,CAACJ,cAAAA,EAAgB;gBAAEJ,OAAAA,EAAS,MAAMS,eAAAA,CAAgBT,OAAAA,EAAShD,MAAAA,EAAQ;AAAEC,oBAAAA;AAAK,iBAAA;AAAG,aAAA,CAAA;AAC5F,QAAA;AAEA,QAAA,IAAIgD,IAAAA,EAAM;YACRf,MAAAA,CAAOsB,MAAM,CAACJ,cAAAA,EAAgB;gBAAEH,IAAAA,EAAM,MAAMS,YAAAA,CAAaT,IAAAA,EAAMjD,MAAAA,EAAQ;AAAEC,oBAAAA;AAAK,iBAAA;AAAG,aAAA,CAAA;AACnF,QAAA;AAEA,QAAA,IAAIiD,MAAAA,EAAQ;YACVhB,MAAAA,CAAOsB,MAAM,CAACJ,cAAAA,EAAgB;gBAAEF,MAAAA,EAAQ,MAAMS,eAAeT,MAAAA,EAAQlD,MAAAA;AAAQ,aAAA,CAAA;AAC/E,QAAA;AAEA,QAAA,IAAImD,QAAAA,EAAU;YACZjB,MAAAA,CAAOsB,MAAM,CAACJ,cAAAA,EAAgB;gBAAED,QAAAA,EAAU,MAAMS,iBAAiBT,QAAAA,EAAUnD,MAAAA;AAAQ,aAAA,CAAA;AACrF,QAAA;AAEA,QAAA,MAAM6D,iBAAiBC,gDAAAA,CAA2B3D,KAAAA,CAAAA;QAClD,MAAM4D,gBAAAA,GAAmB5D,OAAO2B,OAAAA,EAASiB,KAAAA;AACzC,QAAA,IAAIgB,gBAAAA,EAAkB;YACpB,KAAK,MAAM9B,OAAO4B,cAAAA,CAAgB;AAChC,gBAAA,IAAI5B,OAAOc,KAAAA,EAAO;oBAChB,MAAMX,SAAAA,GAAY2B,gBAAgB,CAAC9B,GAAAA,CAAI;AACvC,oBAAA,IAAIG,aAAa,OAAQA,SAAAA,CAA2BC,SAAS,KAAK,UAAA,EAAY;AAC5E,wBAAA,MAAMC,SAAS,SAACF,CAA2BC,SAAS,CAACU,KAAK,CAACd,GAAAA,CAAI,CAAA;wBAC/D,IAAIK,MAAAA,CAAOC,OAAO,EAAE;AAClBa,4BAAAA,cAAc,CAACnB,GAAAA,CAAI,GAAGK,MAAAA,CAAOvC,IAAI;wBACnC,CAAA,MAAO;4BACL,OAAOqD,cAAc,CAACnB,GAAAA,CAAI;AAC5B,wBAAA;AACF,oBAAA;AACF,gBAAA;AACF,YAAA;AACF,QAAA;AAEA,QAAA,IAAI/B,YAAAA,EAAc;AAChB,YAAA,MAAM8D,WAAAA,GAAc;AAAIC,gBAAAA,GAAAA,4CAAAA;AAA6BJ,gBAAAA,GAAAA;AAAe,aAAA;AACpE,YAAA,OAAOK,QAAKF,WAAAA,EAAaZ,cAAAA,CAAAA;AAC3B,QAAA;QAEA,OAAOA,cAAAA;AACT,IAAA,CAAA;IAEA,MAAMK,eAAAA,GAAgC,CAACT,OAAAA,EAAShD,MAAAA,EAAe,EAAEC,IAAI,EAAE,GAAG,EAAE,GAAA;AAC1E,QAAA,IAAI,CAACD,MAAAA,EAAQ;AACX,YAAA,MAAM,IAAII,KAAAA,CAAM,mCAAA,CAAA;AAClB,QAAA;AACA,QAAA,IAAIC,WAAQ2C,OAAAA,CAAAA,EAAU;YACpB,OAAO1C,OAAAA,CAAQC,GAAG,CAACyC,OAAAA,CAAQxC,GAAG,CAAC,CAAC2D,MAAAA,GAAWV,eAAAA,CAAgBU,MAAAA,EAAQnE,MAAAA,EAAQ;AAAEC,oBAAAA;AAAK,iBAAA,CAAA,CAAA,CAAA;AACpF,QAAA;AAEA,QAAA,MAAMa,UAAAA,GAAa;AAACQ,YAAAA,iCAAiC,CAAC;AAAEtB,gBAAAA,MAAAA;AAAQH,gBAAAA;AAAS,aAAA;AAAG,SAAA;AAE5E,QAAA,IAAII,IAAAA,EAAM;AACRa,YAAAA,UAAAA,CAAWO,IAAI,CACb+C,YAAAA,CAAqBhD,yBAAkC,CAACnB,IAAAA,CAAAA,EAAO;AAAED,gBAAAA,MAAAA;AAAQH,gBAAAA;AAAS,aAAA,CAAA,CAAA;AAEtF,QAAA;AAEA,QAAA,OAAO2C,cAAa1B,UAAAA,CAAAA,CAAYkC,OAAAA,CAAAA;AAClC,IAAA,CAAA;IAEA,MAAMU,YAAAA,GAA6B,CAACT,IAAAA,EAAMjD,MAAAA,EAAe,EAAEC,IAAI,EAAE,GAAG,EAAE,GAAA;AACpE,QAAA,IAAI,CAACD,MAAAA,EAAQ;AACX,YAAA,MAAM,IAAII,KAAAA,CAAM,gCAAA,CAAA;AAClB,QAAA;AACA,QAAA,MAAMU,UAAAA,GAAa;AAACQ,YAAAA,8BAA8B,CAAC;AAAEtB,gBAAAA,MAAAA;AAAQH,gBAAAA;AAAS,aAAA;AAAG,SAAA;AAEzE,QAAA,IAAII,IAAAA,EAAM;AACRa,YAAAA,UAAAA,CAAWO,IAAI,CACbgD,SAAAA,CAAkBjD,yBAAkC,CAACnB,IAAAA,CAAAA,EAAO;AAAED,gBAAAA,MAAAA;AAAQH,gBAAAA;AAAS,aAAA,CAAA,CAAA;AAEnF,QAAA;AAEA,QAAA,OAAO2C,cAAa1B,UAAAA,CAAAA,CAAYmC,IAAAA,CAAAA;AAClC,IAAA,CAAA;IAEA,MAAMU,cAAAA,GAA+B,CAACT,MAAAA,EAAQlD,MAAAA,GAAAA;AAC5C,QAAA,IAAI,CAACA,MAAAA,EAAQ;AACX,YAAA,MAAM,IAAII,KAAAA,CAAM,kCAAA,CAAA;AAClB,QAAA;AACA,QAAA,MAAMU,UAAAA,GAAa;AAACQ,YAAAA,gCAAgC,CAAC;AAAEtB,gBAAAA,MAAAA;AAAQH,gBAAAA;AAAS,aAAA;AAAG,SAAA;AAE3E,QAAA,OAAO2C,cAAa1B,UAAAA,CAAAA,CAAYoC,MAAAA,CAAAA;AAClC,IAAA,CAAA;IAEA,MAAMU,gBAAAA,GAAiC,CAACT,QAAAA,EAAUnD,MAAAA,EAAe,EAAEC,IAAI,EAAE,GAAG,EAAE,GAAA;AAC5E,QAAA,IAAI,CAACD,MAAAA,EAAQ;AACX,YAAA,MAAM,IAAII,KAAAA,CAAM,oCAAA,CAAA;AAClB,QAAA;AACA,QAAA,MAAMU,UAAAA,GAAa;AAACQ,YAAAA,kCAAkC,CAAC;AAAEtB,gBAAAA,MAAAA;AAAQH,gBAAAA;AAAS,aAAA;AAAG,SAAA;AAE7E,QAAA,IAAII,IAAAA,EAAM;AACRa,YAAAA,UAAAA,CAAWO,IAAI,CACbiD,aAAAA,CAAsBlD,yBAAkC,CAACnB,IAAAA,CAAAA,EAAO;AAAED,gBAAAA,MAAAA;AAAQH,gBAAAA;AAAS,aAAA,CAAA,CAAA;AAEvF,QAAA;AAEA,QAAA,OAAO2C,cAAa1B,UAAAA,CAAAA,CAAYqC,QAAAA,CAAAA;AAClC,IAAA,CAAA;IAEA,OAAO;QACL5B,KAAAA,EAAOzB,aAAAA;QACP+C,MAAAA,EAAQJ,cAAAA;QACRM,KAAAA,EAAOD,aAAAA;QACPE,OAAAA,EAASS,eAAAA;QACTR,IAAAA,EAAMS,YAAAA;QACNR,MAAAA,EAAQS,cAAAA;QACRR,QAAAA,EAAUS;AACZ,KAAA;AACF;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":["../../src/sanitize/index.ts"],"sourcesContent":["import { CurriedFunction1 } from 'lodash';\nimport { isArray, cloneDeep, omit, pick } from 'lodash/fp';\nimport type { z } from 'zod/v4';\n\nimport { constants, getNonWritableAttributes } from '../content-types';\nimport { ALLOWED_QUERY_PARAM_KEYS } from '../content-api-constants';\nimport {\n type RouteLike,\n getExtraQueryKeysFromRoute,\n getExtraRootKeysFromRouteBody,\n} from '../content-api-route-params';\nimport { pipe as pipeAsync } from '../async';\n\nimport * as visitors from './visitors';\nimport * as sanitizers from './sanitizers';\nimport traverseEntity from '../traverse-entity';\n\nimport { traverseQueryFilters, traverseQuerySort, traverseQueryPopulate } from '../traverse';\nimport type { Model, Data } from '../types';\nimport { validatePublicationFilterQueryParam } from '../publication-filter';\nimport { hasSort } from '../sort-query';\n\nexport interface Options {\n auth?: unknown;\n /**\n * If true, removes fields that are not declared in the schema (input) or keeps only allowed query param keys (query).\n * Defaults to false for backward compatibility.\n * TODO: In Strapi 6, strictParams will default to true (and may be removed as an option)\n */\n strictParams?: boolean;\n /**\n * When set, extra query/input params are derived from the route's request schema (and validated/sanitized with Zod).\n * When absent, no extra params are allowed in strict mode.\n */\n route?: RouteLike;\n}\n\nexport interface Sanitizer {\n (schema: Model): CurriedFunction1<Data, Promise<Data>>;\n}\nexport interface SanitizeFunc {\n (data: unknown, schema: Model, options?: Options): Promise<unknown>;\n}\n\nexport type SanitizeQueryParamHandler = (\n value: unknown,\n schema: Model,\n options?: Options\n) => Promise<unknown>;\n\nexport type SanitizeBodyParamHandler = (\n value: unknown,\n schema: Model,\n options?: Options\n) => Promise<unknown>;\n\nexport interface APIOptions {\n sanitizers?: Sanitizers;\n getModel: (model: string) => Model;\n}\n\nexport interface Sanitizers {\n input?: Sanitizer[];\n output?: Sanitizer[];\n}\n\nconst createAPISanitizers = (opts: APIOptions) => {\n const { getModel } = opts;\n\n const sanitizeInput: SanitizeFunc = (\n data: unknown,\n schema: Model,\n { auth, strictParams = false, route } = {}\n ) => {\n if (!schema) {\n throw new Error('Missing schema in sanitizeInput');\n }\n if (isArray(data)) {\n return Promise.all(\n data.map((entry) => sanitizeInput(entry, schema, { auth, strictParams, route }))\n );\n }\n\n const allowedExtraRootKeys = getExtraRootKeysFromRouteBody(route);\n\n const nonWritableAttributes = getNonWritableAttributes(schema);\n\n const transforms = [\n // Remove first level ID in inputs\n omit(constants.ID_ATTRIBUTE),\n omit(constants.DOC_ID_ATTRIBUTE),\n // Remove non-writable attributes\n traverseEntity(visitors.removeRestrictedFields(nonWritableAttributes), { schema, getModel }),\n ];\n\n if (strictParams) {\n // Remove unrecognized fields (allowedExtraRootKeys = registered input param keys)\n transforms.push(\n traverseEntity(visitors.removeUnrecognizedFields, {\n schema,\n getModel,\n allowedExtraRootKeys,\n })\n );\n }\n\n if (auth) {\n // Remove restricted relations\n transforms.push(\n traverseEntity(visitors.removeRestrictedRelations(auth), { schema, getModel })\n );\n }\n\n // Apply sanitizers from registry if exists\n opts?.sanitizers?.input?.forEach((sanitizer: Sanitizer) => transforms.push(sanitizer(schema)));\n\n /**\n * For each extra root key from the route's body schema present in data, run Zod safeParse.\n * If parsing fails, the key is removed from the output.\n *\n * Content-api sends the document payload as body.data; the controller calls sanitizeInput(body.data, ctx),\n * so the input we receive here is the inner payload (keys like \"relatedMedia\", \"name\"), not the full body.\n * The route's body schema is z.object({ data: ... }), so its shape includes \"data\". We skip \"data\" because\n * the main document payload is already sanitized above by traverseEntity (removeUnrecognizedFields, etc.);\n * relation ops (connect/disconnect/set) are handled there, not by the route's Zod schema. We only run\n * Zod here for truly extra root keys added via addInputParams (e.g. clientMutationId).\n */\n const routeBodySanitizeTransform = async (data: Data): Promise<Data> => {\n if (!data || typeof data !== 'object' || Array.isArray(data)) return data;\n const obj = data as Record<string, unknown>;\n const bodySchema = route?.request?.body?.['application/json'];\n if (bodySchema && typeof bodySchema === 'object' && 'shape' in bodySchema) {\n const shape = (bodySchema as { shape: Record<string, z.ZodTypeAny> }).shape;\n for (const key of Object.keys(shape)) {\n if (key === 'data' || !(key in obj)) continue;\n const zodSchema = shape[key];\n if (zodSchema && typeof (zodSchema as z.ZodTypeAny).safeParse === 'function') {\n const result = (zodSchema as z.ZodTypeAny).safeParse(obj[key]);\n if (result.success) {\n obj[key] = result.data;\n } else {\n delete obj[key];\n }\n }\n }\n }\n return data;\n };\n (transforms as Array<(data: Data) => Data | Promise<Data>>).push(routeBodySanitizeTransform);\n\n return pipeAsync(...transforms)(data as Data);\n };\n\n const sanitizeOutput: SanitizeFunc = async (data, schema: Model, { auth } = {}) => {\n if (!schema) {\n throw new Error('Missing schema in sanitizeOutput');\n }\n if (isArray(data)) {\n const res = new Array(data.length);\n for (let i = 0; i < data.length; i += 1) {\n res[i] = await sanitizeOutput(data[i], schema, { auth });\n }\n return res;\n }\n\n const transforms = [\n (data: Data) => sanitizers.defaultSanitizeOutput({ schema, getModel }, data),\n ];\n\n if (auth) {\n transforms.push(\n traverseEntity(visitors.removeRestrictedRelations(auth), { schema, getModel })\n );\n }\n\n // Apply sanitizers from registry if exists\n opts?.sanitizers?.output?.forEach((sanitizer: Sanitizer) => transforms.push(sanitizer(schema)));\n\n return pipeAsync(...transforms)(data as Data);\n };\n\n const sanitizeQuery = async (\n query: Record<string, unknown>,\n schema: Model,\n { auth, strictParams = false, route }: Options = {}\n ) => {\n if (!schema) {\n throw new Error('Missing schema in sanitizeQuery');\n }\n const { filters, sort, fields, populate } = query;\n\n const sanitizedQuery = cloneDeep(query);\n\n if ('publicationFilter' in sanitizedQuery) {\n validatePublicationFilterQueryParam(sanitizedQuery.publicationFilter);\n }\n\n if (filters) {\n Object.assign(sanitizedQuery, { filters: await sanitizeFilters(filters, schema, { auth }) });\n }\n\n if (hasSort(sort)) {\n Object.assign(sanitizedQuery, { sort: await sanitizeSort(sort, schema, { auth }) });\n } else if ('sort' in sanitizedQuery) {\n delete sanitizedQuery.sort;\n }\n\n if (fields) {\n Object.assign(sanitizedQuery, { fields: await sanitizeFields(fields, schema) });\n }\n\n if (populate) {\n Object.assign(sanitizedQuery, { populate: await sanitizePopulate(populate, schema) });\n }\n\n const extraQueryKeys = getExtraQueryKeysFromRoute(route);\n const routeQuerySchema = route?.request?.query;\n if (routeQuerySchema) {\n for (const key of extraQueryKeys) {\n if (key in query) {\n const zodSchema = routeQuerySchema[key];\n if (zodSchema && typeof (zodSchema as z.ZodTypeAny).safeParse === 'function') {\n const result = (zodSchema as z.ZodTypeAny).safeParse(query[key]);\n if (result.success) {\n sanitizedQuery[key] = result.data;\n } else {\n delete sanitizedQuery[key];\n }\n }\n }\n }\n }\n\n if (strictParams) {\n const allowedKeys = [...ALLOWED_QUERY_PARAM_KEYS, ...extraQueryKeys];\n return pick(allowedKeys, sanitizedQuery) as Record<string, unknown>;\n }\n\n return sanitizedQuery;\n };\n\n const sanitizeFilters: SanitizeFunc = (filters, schema: Model, { auth } = {}) => {\n if (!schema) {\n throw new Error('Missing schema in sanitizeFilters');\n }\n if (isArray(filters)) {\n return Promise.all(filters.map((filter) => sanitizeFilters(filter, schema, { auth })));\n }\n\n const transforms = [sanitizers.defaultSanitizeFilters({ schema, getModel })];\n\n if (auth) {\n transforms.push(\n traverseQueryFilters(visitors.removeRestrictedRelations(auth), { schema, getModel })\n );\n }\n\n return pipeAsync(...transforms)(filters);\n };\n\n const sanitizeSort: SanitizeFunc = (sort, schema: Model, { auth } = {}) => {\n if (!schema) {\n throw new Error('Missing schema in sanitizeSort');\n }\n const transforms = [sanitizers.defaultSanitizeSort({ schema, getModel })];\n\n if (auth) {\n transforms.push(\n traverseQuerySort(visitors.removeRestrictedRelations(auth), { schema, getModel })\n );\n }\n\n return pipeAsync(...transforms)(sort);\n };\n\n const sanitizeFields: SanitizeFunc = (fields, schema: Model) => {\n if (!schema) {\n throw new Error('Missing schema in sanitizeFields');\n }\n const transforms = [sanitizers.defaultSanitizeFields({ schema, getModel })];\n\n return pipeAsync(...transforms)(fields);\n };\n\n const sanitizePopulate: SanitizeFunc = (populate, schema: Model, { auth } = {}) => {\n if (!schema) {\n throw new Error('Missing schema in sanitizePopulate');\n }\n const transforms = [sanitizers.defaultSanitizePopulate({ schema, getModel })];\n\n if (auth) {\n transforms.push(\n traverseQueryPopulate(visitors.removeRestrictedRelations(auth), { schema, getModel })\n );\n }\n\n return pipeAsync(...transforms)(populate);\n };\n\n return {\n input: sanitizeInput,\n output: sanitizeOutput,\n query: sanitizeQuery,\n filters: sanitizeFilters,\n sort: sanitizeSort,\n fields: sanitizeFields,\n populate: sanitizePopulate,\n };\n};\n\nexport { createAPISanitizers, sanitizers, visitors };\n\nexport type APISanitiers = ReturnType<typeof createAPISanitizers>;\n"],"names":["createAPISanitizers","opts","getModel","sanitizeInput","data","schema","auth","strictParams","route","Error","isArray","Promise","all","map","entry","allowedExtraRootKeys","getExtraRootKeysFromRouteBody","nonWritableAttributes","getNonWritableAttributes","transforms","omit","constants","ID_ATTRIBUTE","DOC_ID_ATTRIBUTE","traverseEntity","visitors","push","sanitizers","input","forEach","sanitizer","routeBodySanitizeTransform","Array","obj","bodySchema","request","body","shape","key","Object","keys","zodSchema","safeParse","result","success","pipeAsync","sanitizeOutput","res","length","i","output","sanitizeQuery","query","filters","sort","fields","populate","sanitizedQuery","cloneDeep","validatePublicationFilterQueryParam","publicationFilter","assign","sanitizeFilters","hasSort","sanitizeSort","sanitizeFields","sanitizePopulate","extraQueryKeys","getExtraQueryKeysFromRoute","routeQuerySchema","allowedKeys","ALLOWED_QUERY_PARAM_KEYS","pick","filter","traverseQueryFilters","traverseQuerySort","traverseQueryPopulate"],"mappings":"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"}
@@ -14,6 +14,7 @@ import traverseQuerySort from '../traverse/query-sort.mjs';
14
14
  import traverseQueryPopulate from '../traverse/query-populate.mjs';
15
15
  import '../traverse/query-fields.mjs';
16
16
  import { validatePublicationFilterQueryParam } from '../publication-filter.mjs';
17
+ import { hasSort } from '../sort-query.mjs';
17
18
  import removeUnrecognizedFields from './visitors/remove-unrecognized-fields.mjs';
18
19
  import removeRestrictedRelations from './visitors/remove-restricted-relations.mjs';
19
20
  import removeRestrictedFields from './visitors/remove-restricted-fields.mjs';
@@ -139,12 +140,14 @@ const createAPISanitizers = (opts)=>{
139
140
  })
140
141
  });
141
142
  }
142
- if (sort) {
143
+ if (hasSort(sort)) {
143
144
  Object.assign(sanitizedQuery, {
144
145
  sort: await sanitizeSort(sort, schema, {
145
146
  auth
146
147
  })
147
148
  });
149
+ } else if ('sort' in sanitizedQuery) {
150
+ delete sanitizedQuery.sort;
148
151
  }
149
152
  if (fields) {
150
153
  Object.assign(sanitizedQuery, {
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","sources":["../../src/sanitize/index.ts"],"sourcesContent":["import { CurriedFunction1 } from 'lodash';\nimport { isArray, cloneDeep, omit, pick } from 'lodash/fp';\nimport type { z } from 'zod/v4';\n\nimport { constants, getNonWritableAttributes } from '../content-types';\nimport { ALLOWED_QUERY_PARAM_KEYS } from '../content-api-constants';\nimport {\n type RouteLike,\n getExtraQueryKeysFromRoute,\n getExtraRootKeysFromRouteBody,\n} from '../content-api-route-params';\nimport { pipe as pipeAsync } from '../async';\n\nimport * as visitors from './visitors';\nimport * as sanitizers from './sanitizers';\nimport traverseEntity from '../traverse-entity';\n\nimport { traverseQueryFilters, traverseQuerySort, traverseQueryPopulate } from '../traverse';\nimport type { Model, Data } from '../types';\nimport { validatePublicationFilterQueryParam } from '../publication-filter';\n\nexport interface Options {\n auth?: unknown;\n /**\n * If true, removes fields that are not declared in the schema (input) or keeps only allowed query param keys (query).\n * Defaults to false for backward compatibility.\n * TODO: In Strapi 6, strictParams will default to true (and may be removed as an option)\n */\n strictParams?: boolean;\n /**\n * When set, extra query/input params are derived from the route's request schema (and validated/sanitized with Zod).\n * When absent, no extra params are allowed in strict mode.\n */\n route?: RouteLike;\n}\n\nexport interface Sanitizer {\n (schema: Model): CurriedFunction1<Data, Promise<Data>>;\n}\nexport interface SanitizeFunc {\n (data: unknown, schema: Model, options?: Options): Promise<unknown>;\n}\n\nexport type SanitizeQueryParamHandler = (\n value: unknown,\n schema: Model,\n options?: Options\n) => Promise<unknown>;\n\nexport type SanitizeBodyParamHandler = (\n value: unknown,\n schema: Model,\n options?: Options\n) => Promise<unknown>;\n\nexport interface APIOptions {\n sanitizers?: Sanitizers;\n getModel: (model: string) => Model;\n}\n\nexport interface Sanitizers {\n input?: Sanitizer[];\n output?: Sanitizer[];\n}\n\nconst createAPISanitizers = (opts: APIOptions) => {\n const { getModel } = opts;\n\n const sanitizeInput: SanitizeFunc = (\n data: unknown,\n schema: Model,\n { auth, strictParams = false, route } = {}\n ) => {\n if (!schema) {\n throw new Error('Missing schema in sanitizeInput');\n }\n if (isArray(data)) {\n return Promise.all(\n data.map((entry) => sanitizeInput(entry, schema, { auth, strictParams, route }))\n );\n }\n\n const allowedExtraRootKeys = getExtraRootKeysFromRouteBody(route);\n\n const nonWritableAttributes = getNonWritableAttributes(schema);\n\n const transforms = [\n // Remove first level ID in inputs\n omit(constants.ID_ATTRIBUTE),\n omit(constants.DOC_ID_ATTRIBUTE),\n // Remove non-writable attributes\n traverseEntity(visitors.removeRestrictedFields(nonWritableAttributes), { schema, getModel }),\n ];\n\n if (strictParams) {\n // Remove unrecognized fields (allowedExtraRootKeys = registered input param keys)\n transforms.push(\n traverseEntity(visitors.removeUnrecognizedFields, {\n schema,\n getModel,\n allowedExtraRootKeys,\n })\n );\n }\n\n if (auth) {\n // Remove restricted relations\n transforms.push(\n traverseEntity(visitors.removeRestrictedRelations(auth), { schema, getModel })\n );\n }\n\n // Apply sanitizers from registry if exists\n opts?.sanitizers?.input?.forEach((sanitizer: Sanitizer) => transforms.push(sanitizer(schema)));\n\n /**\n * For each extra root key from the route's body schema present in data, run Zod safeParse.\n * If parsing fails, the key is removed from the output.\n *\n * Content-api sends the document payload as body.data; the controller calls sanitizeInput(body.data, ctx),\n * so the input we receive here is the inner payload (keys like \"relatedMedia\", \"name\"), not the full body.\n * The route's body schema is z.object({ data: ... }), so its shape includes \"data\". We skip \"data\" because\n * the main document payload is already sanitized above by traverseEntity (removeUnrecognizedFields, etc.);\n * relation ops (connect/disconnect/set) are handled there, not by the route's Zod schema. We only run\n * Zod here for truly extra root keys added via addInputParams (e.g. clientMutationId).\n */\n const routeBodySanitizeTransform = async (data: Data): Promise<Data> => {\n if (!data || typeof data !== 'object' || Array.isArray(data)) return data;\n const obj = data as Record<string, unknown>;\n const bodySchema = route?.request?.body?.['application/json'];\n if (bodySchema && typeof bodySchema === 'object' && 'shape' in bodySchema) {\n const shape = (bodySchema as { shape: Record<string, z.ZodTypeAny> }).shape;\n for (const key of Object.keys(shape)) {\n if (key === 'data' || !(key in obj)) continue;\n const zodSchema = shape[key];\n if (zodSchema && typeof (zodSchema as z.ZodTypeAny).safeParse === 'function') {\n const result = (zodSchema as z.ZodTypeAny).safeParse(obj[key]);\n if (result.success) {\n obj[key] = result.data;\n } else {\n delete obj[key];\n }\n }\n }\n }\n return data;\n };\n (transforms as Array<(data: Data) => Data | Promise<Data>>).push(routeBodySanitizeTransform);\n\n return pipeAsync(...transforms)(data as Data);\n };\n\n const sanitizeOutput: SanitizeFunc = async (data, schema: Model, { auth } = {}) => {\n if (!schema) {\n throw new Error('Missing schema in sanitizeOutput');\n }\n if (isArray(data)) {\n const res = new Array(data.length);\n for (let i = 0; i < data.length; i += 1) {\n res[i] = await sanitizeOutput(data[i], schema, { auth });\n }\n return res;\n }\n\n const transforms = [\n (data: Data) => sanitizers.defaultSanitizeOutput({ schema, getModel }, data),\n ];\n\n if (auth) {\n transforms.push(\n traverseEntity(visitors.removeRestrictedRelations(auth), { schema, getModel })\n );\n }\n\n // Apply sanitizers from registry if exists\n opts?.sanitizers?.output?.forEach((sanitizer: Sanitizer) => transforms.push(sanitizer(schema)));\n\n return pipeAsync(...transforms)(data as Data);\n };\n\n const sanitizeQuery = async (\n query: Record<string, unknown>,\n schema: Model,\n { auth, strictParams = false, route }: Options = {}\n ) => {\n if (!schema) {\n throw new Error('Missing schema in sanitizeQuery');\n }\n const { filters, sort, fields, populate } = query;\n\n const sanitizedQuery = cloneDeep(query);\n\n if ('publicationFilter' in sanitizedQuery) {\n validatePublicationFilterQueryParam(sanitizedQuery.publicationFilter);\n }\n\n if (filters) {\n Object.assign(sanitizedQuery, { filters: await sanitizeFilters(filters, schema, { auth }) });\n }\n\n if (sort) {\n Object.assign(sanitizedQuery, { sort: await sanitizeSort(sort, schema, { auth }) });\n }\n\n if (fields) {\n Object.assign(sanitizedQuery, { fields: await sanitizeFields(fields, schema) });\n }\n\n if (populate) {\n Object.assign(sanitizedQuery, { populate: await sanitizePopulate(populate, schema) });\n }\n\n const extraQueryKeys = getExtraQueryKeysFromRoute(route);\n const routeQuerySchema = route?.request?.query;\n if (routeQuerySchema) {\n for (const key of extraQueryKeys) {\n if (key in query) {\n const zodSchema = routeQuerySchema[key];\n if (zodSchema && typeof (zodSchema as z.ZodTypeAny).safeParse === 'function') {\n const result = (zodSchema as z.ZodTypeAny).safeParse(query[key]);\n if (result.success) {\n sanitizedQuery[key] = result.data;\n } else {\n delete sanitizedQuery[key];\n }\n }\n }\n }\n }\n\n if (strictParams) {\n const allowedKeys = [...ALLOWED_QUERY_PARAM_KEYS, ...extraQueryKeys];\n return pick(allowedKeys, sanitizedQuery) as Record<string, unknown>;\n }\n\n return sanitizedQuery;\n };\n\n const sanitizeFilters: SanitizeFunc = (filters, schema: Model, { auth } = {}) => {\n if (!schema) {\n throw new Error('Missing schema in sanitizeFilters');\n }\n if (isArray(filters)) {\n return Promise.all(filters.map((filter) => sanitizeFilters(filter, schema, { auth })));\n }\n\n const transforms = [sanitizers.defaultSanitizeFilters({ schema, getModel })];\n\n if (auth) {\n transforms.push(\n traverseQueryFilters(visitors.removeRestrictedRelations(auth), { schema, getModel })\n );\n }\n\n return pipeAsync(...transforms)(filters);\n };\n\n const sanitizeSort: SanitizeFunc = (sort, schema: Model, { auth } = {}) => {\n if (!schema) {\n throw new Error('Missing schema in sanitizeSort');\n }\n const transforms = [sanitizers.defaultSanitizeSort({ schema, getModel })];\n\n if (auth) {\n transforms.push(\n traverseQuerySort(visitors.removeRestrictedRelations(auth), { schema, getModel })\n );\n }\n\n return pipeAsync(...transforms)(sort);\n };\n\n const sanitizeFields: SanitizeFunc = (fields, schema: Model) => {\n if (!schema) {\n throw new Error('Missing schema in sanitizeFields');\n }\n const transforms = [sanitizers.defaultSanitizeFields({ schema, getModel })];\n\n return pipeAsync(...transforms)(fields);\n };\n\n const sanitizePopulate: SanitizeFunc = (populate, schema: Model, { auth } = {}) => {\n if (!schema) {\n throw new Error('Missing schema in sanitizePopulate');\n }\n const transforms = [sanitizers.defaultSanitizePopulate({ schema, getModel })];\n\n if (auth) {\n transforms.push(\n traverseQueryPopulate(visitors.removeRestrictedRelations(auth), { schema, getModel })\n );\n }\n\n return pipeAsync(...transforms)(populate);\n };\n\n return {\n input: sanitizeInput,\n output: sanitizeOutput,\n query: sanitizeQuery,\n filters: sanitizeFilters,\n sort: sanitizeSort,\n fields: sanitizeFields,\n populate: sanitizePopulate,\n };\n};\n\nexport { createAPISanitizers, sanitizers, visitors };\n\nexport type APISanitiers = ReturnType<typeof createAPISanitizers>;\n"],"names":["createAPISanitizers","opts","getModel","sanitizeInput","data","schema","auth","strictParams","route","Error","isArray","Promise","all","map","entry","allowedExtraRootKeys","getExtraRootKeysFromRouteBody","nonWritableAttributes","getNonWritableAttributes","transforms","omit","constants","ID_ATTRIBUTE","DOC_ID_ATTRIBUTE","traverseEntity","visitors","push","sanitizers","input","forEach","sanitizer","routeBodySanitizeTransform","Array","obj","bodySchema","request","body","shape","key","Object","keys","zodSchema","safeParse","result","success","pipeAsync","sanitizeOutput","res","length","i","output","sanitizeQuery","query","filters","sort","fields","populate","sanitizedQuery","cloneDeep","validatePublicationFilterQueryParam","publicationFilter","assign","sanitizeFilters","sanitizeSort","sanitizeFields","sanitizePopulate","extraQueryKeys","getExtraQueryKeysFromRoute","routeQuerySchema","allowedKeys","ALLOWED_QUERY_PARAM_KEYS","pick","filter","traverseQueryFilters","traverseQuerySort","traverseQueryPopulate"],"mappings":";;;;;;;;;;;;;;;;;;;;AAiEA,MAAMA,sBAAsB,CAACC,IAAAA,GAAAA;IAC3B,MAAM,EAAEC,QAAQ,EAAE,GAAGD,IAAAA;AAErB,IAAA,MAAME,aAAAA,GAA8B,CAClCC,IAAAA,EACAC,MAAAA,EACA,EAAEC,IAAI,EAAEC,YAAAA,GAAe,KAAK,EAAEC,KAAK,EAAE,GAAG,EAAE,GAAA;AAE1C,QAAA,IAAI,CAACH,MAAAA,EAAQ;AACX,YAAA,MAAM,IAAII,KAAAA,CAAM,iCAAA,CAAA;AAClB,QAAA;AACA,QAAA,IAAIC,QAAQN,IAAAA,CAAAA,EAAO;YACjB,OAAOO,OAAAA,CAAQC,GAAG,CAChBR,IAAAA,CAAKS,GAAG,CAAC,CAACC,KAAAA,GAAUX,aAAAA,CAAcW,KAAAA,EAAOT,MAAAA,EAAQ;AAAEC,oBAAAA,IAAAA;AAAMC,oBAAAA,YAAAA;AAAcC,oBAAAA;AAAM,iBAAA,CAAA,CAAA,CAAA;AAEjF,QAAA;AAEA,QAAA,MAAMO,uBAAuBC,6BAAAA,CAA8BR,KAAAA,CAAAA;AAE3D,QAAA,MAAMS,wBAAwBC,wBAAAA,CAAyBb,MAAAA,CAAAA;AAEvD,QAAA,MAAMc,UAAAA,GAAa;;AAEjBC,YAAAA,IAAAA,CAAKC,UAAUC,YAAY,CAAA;AAC3BF,YAAAA,IAAAA,CAAKC,UAAUE,gBAAgB,CAAA;;YAE/BC,cAAAA,CAAeC,sBAA+B,CAACR,qBAAAA,CAAAA,EAAwB;AAAEZ,gBAAAA,MAAAA;AAAQH,gBAAAA;AAAS,aAAA;AAC3F,SAAA;AAED,QAAA,IAAIK,YAAAA,EAAc;;AAEhBY,YAAAA,UAAAA,CAAWO,IAAI,CACbF,cAAAA,CAAeC,wBAAiC,EAAE;AAChDpB,gBAAAA,MAAAA;AACAH,gBAAAA,QAAAA;AACAa,gBAAAA;AACF,aAAA,CAAA,CAAA;AAEJ,QAAA;AAEA,QAAA,IAAIT,IAAAA,EAAM;;AAERa,YAAAA,UAAAA,CAAWO,IAAI,CACbF,cAAAA,CAAeC,yBAAkC,CAACnB,IAAAA,CAAAA,EAAO;AAAED,gBAAAA,MAAAA;AAAQH,gBAAAA;AAAS,aAAA,CAAA,CAAA;AAEhF,QAAA;;QAGAD,IAAAA,EAAM0B,UAAAA,EAAYC,OAAOC,OAAAA,CAAQ,CAACC,YAAyBX,UAAAA,CAAWO,IAAI,CAACI,SAAAA,CAAUzB,MAAAA,CAAAA,CAAAA,CAAAA;AAErF;;;;;;;;;;QAWA,MAAM0B,6BAA6B,OAAO3B,IAAAA,GAAAA;YACxC,IAAI,CAACA,QAAQ,OAAOA,IAAAA,KAAS,YAAY4B,KAAAA,CAAMtB,OAAO,CAACN,IAAAA,CAAAA,EAAO,OAAOA,IAAAA;AACrE,YAAA,MAAM6B,GAAAA,GAAM7B,IAAAA;AACZ,YAAA,MAAM8B,UAAAA,GAAa1B,KAAAA,EAAO2B,OAAAA,EAASC,IAAAA,GAAO,kBAAA,CAAmB;AAC7D,YAAA,IAAIF,UAAAA,IAAc,OAAOA,UAAAA,KAAe,QAAA,IAAY,WAAWA,UAAAA,EAAY;gBACzE,MAAMG,KAAAA,GAAQ,UAACH,CAAuDG,KAAK;AAC3E,gBAAA,KAAK,MAAMC,GAAAA,IAAOC,MAAAA,CAAOC,IAAI,CAACH,KAAAA,CAAAA,CAAQ;AACpC,oBAAA,IAAIC,QAAQ,MAAA,IAAU,EAAEA,GAAAA,IAAOL,GAAE,CAAA,EAAI;oBACrC,MAAMQ,SAAAA,GAAYJ,KAAK,CAACC,GAAAA,CAAI;AAC5B,oBAAA,IAAIG,aAAa,OAAQA,SAAAA,CAA2BC,SAAS,KAAK,UAAA,EAAY;AAC5E,wBAAA,MAAMC,SAAS,SAACF,CAA2BC,SAAS,CAACT,GAAG,CAACK,GAAAA,CAAI,CAAA;wBAC7D,IAAIK,MAAAA,CAAOC,OAAO,EAAE;AAClBX,4BAAAA,GAAG,CAACK,GAAAA,CAAI,GAAGK,MAAAA,CAAOvC,IAAI;wBACxB,CAAA,MAAO;4BACL,OAAO6B,GAAG,CAACK,GAAAA,CAAI;AACjB,wBAAA;AACF,oBAAA;AACF,gBAAA;AACF,YAAA;YACA,OAAOlC,IAAAA;AACT,QAAA,CAAA;AACCe,QAAAA,UAAAA,CAA2DO,IAAI,CAACK,0BAAAA,CAAAA;AAEjE,QAAA,OAAOc,QAAa1B,UAAAA,CAAAA,CAAYf,IAAAA,CAAAA;AAClC,IAAA,CAAA;IAEA,MAAM0C,cAAAA,GAA+B,OAAO1C,IAAAA,EAAMC,MAAAA,EAAe,EAAEC,IAAI,EAAE,GAAG,EAAE,GAAA;AAC5E,QAAA,IAAI,CAACD,MAAAA,EAAQ;AACX,YAAA,MAAM,IAAII,KAAAA,CAAM,kCAAA,CAAA;AAClB,QAAA;AACA,QAAA,IAAIC,QAAQN,IAAAA,CAAAA,EAAO;AACjB,YAAA,MAAM2C,GAAAA,GAAM,IAAIf,KAAAA,CAAM5B,IAAAA,CAAK4C,MAAM,CAAA;YACjC,IAAK,IAAIC,IAAI,CAAA,EAAGA,CAAAA,GAAI7C,KAAK4C,MAAM,EAAEC,KAAK,CAAA,CAAG;gBACvCF,GAAG,CAACE,EAAE,GAAG,MAAMH,eAAe1C,IAAI,CAAC6C,CAAAA,CAAE,EAAE5C,MAAAA,EAAQ;AAAEC,oBAAAA;AAAK,iBAAA,CAAA;AACxD,YAAA;YACA,OAAOyC,GAAAA;AACT,QAAA;AAEA,QAAA,MAAM5B,UAAAA,GAAa;YACjB,CAACf,IAAAA,GAAeuB,qBAAgC,CAAC;AAAEtB,oBAAAA,MAAAA;AAAQH,oBAAAA;iBAAS,EAAGE,IAAAA;AACxE,SAAA;AAED,QAAA,IAAIE,IAAAA,EAAM;AACRa,YAAAA,UAAAA,CAAWO,IAAI,CACbF,cAAAA,CAAeC,yBAAkC,CAACnB,IAAAA,CAAAA,EAAO;AAAED,gBAAAA,MAAAA;AAAQH,gBAAAA;AAAS,aAAA,CAAA,CAAA;AAEhF,QAAA;;QAGAD,IAAAA,EAAM0B,UAAAA,EAAYuB,QAAQrB,OAAAA,CAAQ,CAACC,YAAyBX,UAAAA,CAAWO,IAAI,CAACI,SAAAA,CAAUzB,MAAAA,CAAAA,CAAAA,CAAAA;AAEtF,QAAA,OAAOwC,QAAa1B,UAAAA,CAAAA,CAAYf,IAAAA,CAAAA;AAClC,IAAA,CAAA;AAEA,IAAA,MAAM+C,aAAAA,GAAgB,OACpBC,KAAAA,EACA/C,MAAAA,EACA,EAAEC,IAAI,EAAEC,YAAAA,GAAe,KAAK,EAAEC,KAAK,EAAW,GAAG,EAAE,GAAA;AAEnD,QAAA,IAAI,CAACH,MAAAA,EAAQ;AACX,YAAA,MAAM,IAAII,KAAAA,CAAM,iCAAA,CAAA;AAClB,QAAA;QACA,MAAM,EAAE4C,OAAO,EAAEC,IAAI,EAAEC,MAAM,EAAEC,QAAQ,EAAE,GAAGJ,KAAAA;AAE5C,QAAA,MAAMK,iBAAiBC,SAAAA,CAAUN,KAAAA,CAAAA;AAEjC,QAAA,IAAI,uBAAuBK,cAAAA,EAAgB;AACzCE,YAAAA,mCAAAA,CAAoCF,eAAeG,iBAAiB,CAAA;AACtE,QAAA;AAEA,QAAA,IAAIP,OAAAA,EAAS;YACXd,MAAAA,CAAOsB,MAAM,CAACJ,cAAAA,EAAgB;gBAAEJ,OAAAA,EAAS,MAAMS,eAAAA,CAAgBT,OAAAA,EAAShD,MAAAA,EAAQ;AAAEC,oBAAAA;AAAK,iBAAA;AAAG,aAAA,CAAA;AAC5F,QAAA;AAEA,QAAA,IAAIgD,IAAAA,EAAM;YACRf,MAAAA,CAAOsB,MAAM,CAACJ,cAAAA,EAAgB;gBAAEH,IAAAA,EAAM,MAAMS,YAAAA,CAAaT,IAAAA,EAAMjD,MAAAA,EAAQ;AAAEC,oBAAAA;AAAK,iBAAA;AAAG,aAAA,CAAA;AACnF,QAAA;AAEA,QAAA,IAAIiD,MAAAA,EAAQ;YACVhB,MAAAA,CAAOsB,MAAM,CAACJ,cAAAA,EAAgB;gBAAEF,MAAAA,EAAQ,MAAMS,eAAeT,MAAAA,EAAQlD,MAAAA;AAAQ,aAAA,CAAA;AAC/E,QAAA;AAEA,QAAA,IAAImD,QAAAA,EAAU;YACZjB,MAAAA,CAAOsB,MAAM,CAACJ,cAAAA,EAAgB;gBAAED,QAAAA,EAAU,MAAMS,iBAAiBT,QAAAA,EAAUnD,MAAAA;AAAQ,aAAA,CAAA;AACrF,QAAA;AAEA,QAAA,MAAM6D,iBAAiBC,0BAAAA,CAA2B3D,KAAAA,CAAAA;QAClD,MAAM4D,gBAAAA,GAAmB5D,OAAO2B,OAAAA,EAASiB,KAAAA;AACzC,QAAA,IAAIgB,gBAAAA,EAAkB;YACpB,KAAK,MAAM9B,OAAO4B,cAAAA,CAAgB;AAChC,gBAAA,IAAI5B,OAAOc,KAAAA,EAAO;oBAChB,MAAMX,SAAAA,GAAY2B,gBAAgB,CAAC9B,GAAAA,CAAI;AACvC,oBAAA,IAAIG,aAAa,OAAQA,SAAAA,CAA2BC,SAAS,KAAK,UAAA,EAAY;AAC5E,wBAAA,MAAMC,SAAS,SAACF,CAA2BC,SAAS,CAACU,KAAK,CAACd,GAAAA,CAAI,CAAA;wBAC/D,IAAIK,MAAAA,CAAOC,OAAO,EAAE;AAClBa,4BAAAA,cAAc,CAACnB,GAAAA,CAAI,GAAGK,MAAAA,CAAOvC,IAAI;wBACnC,CAAA,MAAO;4BACL,OAAOqD,cAAc,CAACnB,GAAAA,CAAI;AAC5B,wBAAA;AACF,oBAAA;AACF,gBAAA;AACF,YAAA;AACF,QAAA;AAEA,QAAA,IAAI/B,YAAAA,EAAc;AAChB,YAAA,MAAM8D,WAAAA,GAAc;AAAIC,gBAAAA,GAAAA,wBAAAA;AAA6BJ,gBAAAA,GAAAA;AAAe,aAAA;AACpE,YAAA,OAAOK,KAAKF,WAAAA,EAAaZ,cAAAA,CAAAA;AAC3B,QAAA;QAEA,OAAOA,cAAAA;AACT,IAAA,CAAA;IAEA,MAAMK,eAAAA,GAAgC,CAACT,OAAAA,EAAShD,MAAAA,EAAe,EAAEC,IAAI,EAAE,GAAG,EAAE,GAAA;AAC1E,QAAA,IAAI,CAACD,MAAAA,EAAQ;AACX,YAAA,MAAM,IAAII,KAAAA,CAAM,mCAAA,CAAA;AAClB,QAAA;AACA,QAAA,IAAIC,QAAQ2C,OAAAA,CAAAA,EAAU;YACpB,OAAO1C,OAAAA,CAAQC,GAAG,CAACyC,OAAAA,CAAQxC,GAAG,CAAC,CAAC2D,MAAAA,GAAWV,eAAAA,CAAgBU,MAAAA,EAAQnE,MAAAA,EAAQ;AAAEC,oBAAAA;AAAK,iBAAA,CAAA,CAAA,CAAA;AACpF,QAAA;AAEA,QAAA,MAAMa,UAAAA,GAAa;AAACQ,YAAAA,sBAAiC,CAAC;AAAEtB,gBAAAA,MAAAA;AAAQH,gBAAAA;AAAS,aAAA;AAAG,SAAA;AAE5E,QAAA,IAAII,IAAAA,EAAM;AACRa,YAAAA,UAAAA,CAAWO,IAAI,CACb+C,oBAAAA,CAAqBhD,yBAAkC,CAACnB,IAAAA,CAAAA,EAAO;AAAED,gBAAAA,MAAAA;AAAQH,gBAAAA;AAAS,aAAA,CAAA,CAAA;AAEtF,QAAA;AAEA,QAAA,OAAO2C,QAAa1B,UAAAA,CAAAA,CAAYkC,OAAAA,CAAAA;AAClC,IAAA,CAAA;IAEA,MAAMU,YAAAA,GAA6B,CAACT,IAAAA,EAAMjD,MAAAA,EAAe,EAAEC,IAAI,EAAE,GAAG,EAAE,GAAA;AACpE,QAAA,IAAI,CAACD,MAAAA,EAAQ;AACX,YAAA,MAAM,IAAII,KAAAA,CAAM,gCAAA,CAAA;AAClB,QAAA;AACA,QAAA,MAAMU,UAAAA,GAAa;AAACQ,YAAAA,mBAA8B,CAAC;AAAEtB,gBAAAA,MAAAA;AAAQH,gBAAAA;AAAS,aAAA;AAAG,SAAA;AAEzE,QAAA,IAAII,IAAAA,EAAM;AACRa,YAAAA,UAAAA,CAAWO,IAAI,CACbgD,iBAAAA,CAAkBjD,yBAAkC,CAACnB,IAAAA,CAAAA,EAAO;AAAED,gBAAAA,MAAAA;AAAQH,gBAAAA;AAAS,aAAA,CAAA,CAAA;AAEnF,QAAA;AAEA,QAAA,OAAO2C,QAAa1B,UAAAA,CAAAA,CAAYmC,IAAAA,CAAAA;AAClC,IAAA,CAAA;IAEA,MAAMU,cAAAA,GAA+B,CAACT,MAAAA,EAAQlD,MAAAA,GAAAA;AAC5C,QAAA,IAAI,CAACA,MAAAA,EAAQ;AACX,YAAA,MAAM,IAAII,KAAAA,CAAM,kCAAA,CAAA;AAClB,QAAA;AACA,QAAA,MAAMU,UAAAA,GAAa;AAACQ,YAAAA,qBAAgC,CAAC;AAAEtB,gBAAAA,MAAAA;AAAQH,gBAAAA;AAAS,aAAA;AAAG,SAAA;AAE3E,QAAA,OAAO2C,QAAa1B,UAAAA,CAAAA,CAAYoC,MAAAA,CAAAA;AAClC,IAAA,CAAA;IAEA,MAAMU,gBAAAA,GAAiC,CAACT,QAAAA,EAAUnD,MAAAA,EAAe,EAAEC,IAAI,EAAE,GAAG,EAAE,GAAA;AAC5E,QAAA,IAAI,CAACD,MAAAA,EAAQ;AACX,YAAA,MAAM,IAAII,KAAAA,CAAM,oCAAA,CAAA;AAClB,QAAA;AACA,QAAA,MAAMU,UAAAA,GAAa;AAACQ,YAAAA,uBAAkC,CAAC;AAAEtB,gBAAAA,MAAAA;AAAQH,gBAAAA;AAAS,aAAA;AAAG,SAAA;AAE7E,QAAA,IAAII,IAAAA,EAAM;AACRa,YAAAA,UAAAA,CAAWO,IAAI,CACbiD,qBAAAA,CAAsBlD,yBAAkC,CAACnB,IAAAA,CAAAA,EAAO;AAAED,gBAAAA,MAAAA;AAAQH,gBAAAA;AAAS,aAAA,CAAA,CAAA;AAEvF,QAAA;AAEA,QAAA,OAAO2C,QAAa1B,UAAAA,CAAAA,CAAYqC,QAAAA,CAAAA;AAClC,IAAA,CAAA;IAEA,OAAO;QACL5B,KAAAA,EAAOzB,aAAAA;QACP+C,MAAAA,EAAQJ,cAAAA;QACRM,KAAAA,EAAOD,aAAAA;QACPE,OAAAA,EAASS,eAAAA;QACTR,IAAAA,EAAMS,YAAAA;QACNR,MAAAA,EAAQS,cAAAA;QACRR,QAAAA,EAAUS;AACZ,KAAA;AACF;;;;"}
1
+ {"version":3,"file":"index.mjs","sources":["../../src/sanitize/index.ts"],"sourcesContent":["import { CurriedFunction1 } from 'lodash';\nimport { isArray, cloneDeep, omit, pick } from 'lodash/fp';\nimport type { z } from 'zod/v4';\n\nimport { constants, getNonWritableAttributes } from '../content-types';\nimport { ALLOWED_QUERY_PARAM_KEYS } from '../content-api-constants';\nimport {\n type RouteLike,\n getExtraQueryKeysFromRoute,\n getExtraRootKeysFromRouteBody,\n} from '../content-api-route-params';\nimport { pipe as pipeAsync } from '../async';\n\nimport * as visitors from './visitors';\nimport * as sanitizers from './sanitizers';\nimport traverseEntity from '../traverse-entity';\n\nimport { traverseQueryFilters, traverseQuerySort, traverseQueryPopulate } from '../traverse';\nimport type { Model, Data } from '../types';\nimport { validatePublicationFilterQueryParam } from '../publication-filter';\nimport { hasSort } from '../sort-query';\n\nexport interface Options {\n auth?: unknown;\n /**\n * If true, removes fields that are not declared in the schema (input) or keeps only allowed query param keys (query).\n * Defaults to false for backward compatibility.\n * TODO: In Strapi 6, strictParams will default to true (and may be removed as an option)\n */\n strictParams?: boolean;\n /**\n * When set, extra query/input params are derived from the route's request schema (and validated/sanitized with Zod).\n * When absent, no extra params are allowed in strict mode.\n */\n route?: RouteLike;\n}\n\nexport interface Sanitizer {\n (schema: Model): CurriedFunction1<Data, Promise<Data>>;\n}\nexport interface SanitizeFunc {\n (data: unknown, schema: Model, options?: Options): Promise<unknown>;\n}\n\nexport type SanitizeQueryParamHandler = (\n value: unknown,\n schema: Model,\n options?: Options\n) => Promise<unknown>;\n\nexport type SanitizeBodyParamHandler = (\n value: unknown,\n schema: Model,\n options?: Options\n) => Promise<unknown>;\n\nexport interface APIOptions {\n sanitizers?: Sanitizers;\n getModel: (model: string) => Model;\n}\n\nexport interface Sanitizers {\n input?: Sanitizer[];\n output?: Sanitizer[];\n}\n\nconst createAPISanitizers = (opts: APIOptions) => {\n const { getModel } = opts;\n\n const sanitizeInput: SanitizeFunc = (\n data: unknown,\n schema: Model,\n { auth, strictParams = false, route } = {}\n ) => {\n if (!schema) {\n throw new Error('Missing schema in sanitizeInput');\n }\n if (isArray(data)) {\n return Promise.all(\n data.map((entry) => sanitizeInput(entry, schema, { auth, strictParams, route }))\n );\n }\n\n const allowedExtraRootKeys = getExtraRootKeysFromRouteBody(route);\n\n const nonWritableAttributes = getNonWritableAttributes(schema);\n\n const transforms = [\n // Remove first level ID in inputs\n omit(constants.ID_ATTRIBUTE),\n omit(constants.DOC_ID_ATTRIBUTE),\n // Remove non-writable attributes\n traverseEntity(visitors.removeRestrictedFields(nonWritableAttributes), { schema, getModel }),\n ];\n\n if (strictParams) {\n // Remove unrecognized fields (allowedExtraRootKeys = registered input param keys)\n transforms.push(\n traverseEntity(visitors.removeUnrecognizedFields, {\n schema,\n getModel,\n allowedExtraRootKeys,\n })\n );\n }\n\n if (auth) {\n // Remove restricted relations\n transforms.push(\n traverseEntity(visitors.removeRestrictedRelations(auth), { schema, getModel })\n );\n }\n\n // Apply sanitizers from registry if exists\n opts?.sanitizers?.input?.forEach((sanitizer: Sanitizer) => transforms.push(sanitizer(schema)));\n\n /**\n * For each extra root key from the route's body schema present in data, run Zod safeParse.\n * If parsing fails, the key is removed from the output.\n *\n * Content-api sends the document payload as body.data; the controller calls sanitizeInput(body.data, ctx),\n * so the input we receive here is the inner payload (keys like \"relatedMedia\", \"name\"), not the full body.\n * The route's body schema is z.object({ data: ... }), so its shape includes \"data\". We skip \"data\" because\n * the main document payload is already sanitized above by traverseEntity (removeUnrecognizedFields, etc.);\n * relation ops (connect/disconnect/set) are handled there, not by the route's Zod schema. We only run\n * Zod here for truly extra root keys added via addInputParams (e.g. clientMutationId).\n */\n const routeBodySanitizeTransform = async (data: Data): Promise<Data> => {\n if (!data || typeof data !== 'object' || Array.isArray(data)) return data;\n const obj = data as Record<string, unknown>;\n const bodySchema = route?.request?.body?.['application/json'];\n if (bodySchema && typeof bodySchema === 'object' && 'shape' in bodySchema) {\n const shape = (bodySchema as { shape: Record<string, z.ZodTypeAny> }).shape;\n for (const key of Object.keys(shape)) {\n if (key === 'data' || !(key in obj)) continue;\n const zodSchema = shape[key];\n if (zodSchema && typeof (zodSchema as z.ZodTypeAny).safeParse === 'function') {\n const result = (zodSchema as z.ZodTypeAny).safeParse(obj[key]);\n if (result.success) {\n obj[key] = result.data;\n } else {\n delete obj[key];\n }\n }\n }\n }\n return data;\n };\n (transforms as Array<(data: Data) => Data | Promise<Data>>).push(routeBodySanitizeTransform);\n\n return pipeAsync(...transforms)(data as Data);\n };\n\n const sanitizeOutput: SanitizeFunc = async (data, schema: Model, { auth } = {}) => {\n if (!schema) {\n throw new Error('Missing schema in sanitizeOutput');\n }\n if (isArray(data)) {\n const res = new Array(data.length);\n for (let i = 0; i < data.length; i += 1) {\n res[i] = await sanitizeOutput(data[i], schema, { auth });\n }\n return res;\n }\n\n const transforms = [\n (data: Data) => sanitizers.defaultSanitizeOutput({ schema, getModel }, data),\n ];\n\n if (auth) {\n transforms.push(\n traverseEntity(visitors.removeRestrictedRelations(auth), { schema, getModel })\n );\n }\n\n // Apply sanitizers from registry if exists\n opts?.sanitizers?.output?.forEach((sanitizer: Sanitizer) => transforms.push(sanitizer(schema)));\n\n return pipeAsync(...transforms)(data as Data);\n };\n\n const sanitizeQuery = async (\n query: Record<string, unknown>,\n schema: Model,\n { auth, strictParams = false, route }: Options = {}\n ) => {\n if (!schema) {\n throw new Error('Missing schema in sanitizeQuery');\n }\n const { filters, sort, fields, populate } = query;\n\n const sanitizedQuery = cloneDeep(query);\n\n if ('publicationFilter' in sanitizedQuery) {\n validatePublicationFilterQueryParam(sanitizedQuery.publicationFilter);\n }\n\n if (filters) {\n Object.assign(sanitizedQuery, { filters: await sanitizeFilters(filters, schema, { auth }) });\n }\n\n if (hasSort(sort)) {\n Object.assign(sanitizedQuery, { sort: await sanitizeSort(sort, schema, { auth }) });\n } else if ('sort' in sanitizedQuery) {\n delete sanitizedQuery.sort;\n }\n\n if (fields) {\n Object.assign(sanitizedQuery, { fields: await sanitizeFields(fields, schema) });\n }\n\n if (populate) {\n Object.assign(sanitizedQuery, { populate: await sanitizePopulate(populate, schema) });\n }\n\n const extraQueryKeys = getExtraQueryKeysFromRoute(route);\n const routeQuerySchema = route?.request?.query;\n if (routeQuerySchema) {\n for (const key of extraQueryKeys) {\n if (key in query) {\n const zodSchema = routeQuerySchema[key];\n if (zodSchema && typeof (zodSchema as z.ZodTypeAny).safeParse === 'function') {\n const result = (zodSchema as z.ZodTypeAny).safeParse(query[key]);\n if (result.success) {\n sanitizedQuery[key] = result.data;\n } else {\n delete sanitizedQuery[key];\n }\n }\n }\n }\n }\n\n if (strictParams) {\n const allowedKeys = [...ALLOWED_QUERY_PARAM_KEYS, ...extraQueryKeys];\n return pick(allowedKeys, sanitizedQuery) as Record<string, unknown>;\n }\n\n return sanitizedQuery;\n };\n\n const sanitizeFilters: SanitizeFunc = (filters, schema: Model, { auth } = {}) => {\n if (!schema) {\n throw new Error('Missing schema in sanitizeFilters');\n }\n if (isArray(filters)) {\n return Promise.all(filters.map((filter) => sanitizeFilters(filter, schema, { auth })));\n }\n\n const transforms = [sanitizers.defaultSanitizeFilters({ schema, getModel })];\n\n if (auth) {\n transforms.push(\n traverseQueryFilters(visitors.removeRestrictedRelations(auth), { schema, getModel })\n );\n }\n\n return pipeAsync(...transforms)(filters);\n };\n\n const sanitizeSort: SanitizeFunc = (sort, schema: Model, { auth } = {}) => {\n if (!schema) {\n throw new Error('Missing schema in sanitizeSort');\n }\n const transforms = [sanitizers.defaultSanitizeSort({ schema, getModel })];\n\n if (auth) {\n transforms.push(\n traverseQuerySort(visitors.removeRestrictedRelations(auth), { schema, getModel })\n );\n }\n\n return pipeAsync(...transforms)(sort);\n };\n\n const sanitizeFields: SanitizeFunc = (fields, schema: Model) => {\n if (!schema) {\n throw new Error('Missing schema in sanitizeFields');\n }\n const transforms = [sanitizers.defaultSanitizeFields({ schema, getModel })];\n\n return pipeAsync(...transforms)(fields);\n };\n\n const sanitizePopulate: SanitizeFunc = (populate, schema: Model, { auth } = {}) => {\n if (!schema) {\n throw new Error('Missing schema in sanitizePopulate');\n }\n const transforms = [sanitizers.defaultSanitizePopulate({ schema, getModel })];\n\n if (auth) {\n transforms.push(\n traverseQueryPopulate(visitors.removeRestrictedRelations(auth), { schema, getModel })\n );\n }\n\n return pipeAsync(...transforms)(populate);\n };\n\n return {\n input: sanitizeInput,\n output: sanitizeOutput,\n query: sanitizeQuery,\n filters: sanitizeFilters,\n sort: sanitizeSort,\n fields: sanitizeFields,\n populate: sanitizePopulate,\n };\n};\n\nexport { createAPISanitizers, sanitizers, visitors };\n\nexport type APISanitiers = ReturnType<typeof createAPISanitizers>;\n"],"names":["createAPISanitizers","opts","getModel","sanitizeInput","data","schema","auth","strictParams","route","Error","isArray","Promise","all","map","entry","allowedExtraRootKeys","getExtraRootKeysFromRouteBody","nonWritableAttributes","getNonWritableAttributes","transforms","omit","constants","ID_ATTRIBUTE","DOC_ID_ATTRIBUTE","traverseEntity","visitors","push","sanitizers","input","forEach","sanitizer","routeBodySanitizeTransform","Array","obj","bodySchema","request","body","shape","key","Object","keys","zodSchema","safeParse","result","success","pipeAsync","sanitizeOutput","res","length","i","output","sanitizeQuery","query","filters","sort","fields","populate","sanitizedQuery","cloneDeep","validatePublicationFilterQueryParam","publicationFilter","assign","sanitizeFilters","hasSort","sanitizeSort","sanitizeFields","sanitizePopulate","extraQueryKeys","getExtraQueryKeysFromRoute","routeQuerySchema","allowedKeys","ALLOWED_QUERY_PARAM_KEYS","pick","filter","traverseQueryFilters","traverseQuerySort","traverseQueryPopulate"],"mappings":"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"}
@@ -1,4 +1,3 @@
1
- /// <reference types="lodash" />
2
1
  import type { Model, Data } from '../types';
3
2
  import type { Parent } from '../traverse/factory';
4
3
  interface Context {
@@ -1 +1 @@
1
- {"version":3,"file":"sanitizers.d.ts","sourceRoot":"","sources":["../../src/sanitize/sanitizers.ts"],"names":[],"mappings":";AAsBA,OAAO,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAElD,UAAU,OAAO;IACf,MAAM,EAAE,KAAK,CAAC;IACd,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,KAAK,CAAC;IACnC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAID,QAAA,MAAM,iBAAiB,QAAS,OAAO,cAAoB,IAAI,kBAM9D,CAAC;AAEF,QAAA,MAAM,qBAAqB,QAAe,OAAO,UAAU,IAAI,kBAa9D,CAAC;AAEF,QAAA,MAAM,sBAAsB,uEAsC1B,CAAC;AAEH,QAAA,MAAM,mBAAmB,uEAuCvB,CAAC;AAEH,QAAA,MAAM,qBAAqB,uEAyBzB,CAAC;AAEH,QAAA,MAAM,uBAAuB,uEAiC3B,CAAC;AAEH,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,sBAAsB,EACtB,mBAAmB,EACnB,qBAAqB,EACrB,uBAAuB,GACxB,CAAC"}
1
+ {"version":3,"file":"sanitizers.d.ts","sourceRoot":"","sources":["../../src/sanitize/sanitizers.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAElD,UAAU,OAAO;IACf,MAAM,EAAE,KAAK,CAAC;IACd,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,KAAK,CAAC;IACnC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAID,QAAA,MAAM,iBAAiB,GAAI,KAAK,OAAO,MAAY,QAAQ,IAAI,kBAM9D,CAAC;AAEF,QAAA,MAAM,qBAAqB,GAAU,KAAK,OAAO,EAAE,QAAQ,IAAI,kBAa9D,CAAC;AAEF,QAAA,MAAM,sBAAsB,uEAsC1B,CAAC;AAEH,QAAA,MAAM,mBAAmB,uEAuCvB,CAAC;AAEH,QAAA,MAAM,qBAAqB,uEAyBzB,CAAC;AAEH,QAAA,MAAM,uBAAuB,uEAiC3B,CAAC;AAEH,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,sBAAsB,EACtB,mBAAmB,EACnB,qBAAqB,EACrB,uBAAuB,GACxB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"remove-disallowed-fields.d.ts","sourceRoot":"","sources":["../../../src/sanitize/visitors/remove-disallowed-fields.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;yCAEvB,MAAM,EAAE,GAAG,IAAI,KAAU,OAAO;AAA/D,wBAoEI"}
1
+ {"version":3,"file":"remove-disallowed-fields.d.ts","sourceRoot":"","sources":["../../../src/sanitize/visitors/remove-disallowed-fields.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;yBAEtC,gBAAe,MAAM,EAAE,GAAG,IAAW,KAAG,OAAO;AAA/D,wBAoEI"}
@@ -1 +1 @@
1
- {"version":3,"file":"remove-restricted-fields.d.ts","sourceRoot":"","sources":["../../../src/sanitize/visitors/remove-restricted-fields.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;4CAEpB,MAAM,EAAE,GAAG,IAAI,KAAU,OAAO;AAAlE,wBA4BI"}
1
+ {"version":3,"file":"remove-restricted-fields.d.ts","sourceRoot":"","sources":["../../../src/sanitize/visitors/remove-restricted-fields.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;yBAEtC,mBAAkB,MAAM,EAAE,GAAG,IAAW,KAAG,OAAO;AAAlE,wBA4BI"}
@@ -1 +1 @@
1
- {"version":3,"file":"remove-restricted-relations.d.ts","sourceRoot":"","sources":["../../../src/sanitize/visitors/remove-restricted-relations.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;+BAShC,OAAO,KAAG,OAAO;AAAvC,wBA0HI"}
1
+ {"version":3,"file":"remove-restricted-relations.d.ts","sourceRoot":"","sources":["../../../src/sanitize/visitors/remove-restricted-relations.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;yBAStC,MAAM,OAAO,KAAG,OAAO;AAAvC,wBA0HI"}
@@ -17,7 +17,7 @@ export declare const extendMiddlewareConfiguration: (middlewares: (string | {
17
17
  name: string;
18
18
  config?: any;
19
19
  }) => (string | {
20
- name?: string | undefined;
20
+ name?: string;
21
21
  config?: any;
22
22
  })[];
23
23
  //# sourceMappingURL=security.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"security.d.ts","sourceRoot":"","sources":["../src/security.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,YAAY;;;;CAIf,CAAC;AAEX;;;;;;GAMG;AACH,eAAO,MAAM,6BAA6B,gBAC3B,CAAC,MAAM,GAAG;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,GAAG,CAAA;CAAE,CAAC,EAAE,cAC7C;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,GAAG,CAAA;CAAE;;aADO,GAAG;IAyBrD,CAAC"}
1
+ {"version":3,"file":"security.d.ts","sourceRoot":"","sources":["../src/security.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,YAAY;;;;CAIf,CAAC;AAEX;;;;;;GAMG;AACH,eAAO,MAAM,6BAA6B,GACxC,aAAa,CAAC,MAAM,GAAG;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,GAAG,CAAA;CAAE,CAAC,EAAE,EACzD,YAAY;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,GAAG,CAAA;CAAE;WADV,MAAM;aAAW,GAAG;IAyBrD,CAAC"}
@@ -0,0 +1,35 @@
1
+ export interface SessionEntryLike {
2
+ sessionId: string;
3
+ deviceId?: string;
4
+ createdAt?: Date | string | null;
5
+ metadata?: Record<string, unknown> | null;
6
+ }
7
+ export interface SanitizedSessionEntry {
8
+ id: string;
9
+ deviceId?: string;
10
+ deviceName?: string;
11
+ current: boolean;
12
+ loginAt?: string;
13
+ lastActiveAt?: string;
14
+ }
15
+ export interface SessionDisplayEntry {
16
+ current: boolean;
17
+ lastActiveAt?: string;
18
+ }
19
+ /**
20
+ * Sanitizes a session record for client consumption (active devices UI/API).
21
+ * Never includes tokens or internal database identifiers.
22
+ */
23
+ export declare const sanitizeSessionEntry: (session: SessionEntryLike, currentSessionId?: string) => SanitizedSessionEntry;
24
+ /**
25
+ * Builds origin-defined session metadata from generic request context fields.
26
+ */
27
+ export declare const buildSessionMetadata: (params: {
28
+ userAgent?: string | null;
29
+ loginAt?: string;
30
+ }) => Record<string, unknown>;
31
+ /**
32
+ * Sorts sessions for display: current session first, then most recently used.
33
+ */
34
+ export declare const sortSessionsForDisplay: <T extends SessionDisplayEntry>(sessions: T[]) => T[];
35
+ //# sourceMappingURL=sessions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessions.d.ts","sourceRoot":"","sources":["../src/sessions.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,IAAI,GAAG,MAAM,GAAG,IAAI,CAAC;IACjC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;CAC3C;AAED,MAAM,WAAW,qBAAqB;IACpC,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;GAGG;AACH,eAAO,MAAM,oBAAoB,GAC/B,SAAS,gBAAgB,EACzB,mBAAmB,MAAM,KACxB,qBAaF,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,oBAAoB,GAAI,QAAQ;IAC3C,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,KAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAOzB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,sBAAsB,GAAI,CAAC,SAAS,mBAAmB,EAAE,UAAU,CAAC,EAAE,KAAG,CAAC,EAOnF,CAAC"}
@@ -0,0 +1,46 @@
1
+ 'use strict';
2
+
3
+ var userAgent = require('./user-agent.js');
4
+
5
+ /**
6
+ * Sanitizes a session record for client consumption (active devices UI/API).
7
+ * Never includes tokens or internal database identifiers.
8
+ */ const sanitizeSessionEntry = (session, currentSessionId)=>{
9
+ const metadata = session.metadata ?? {};
10
+ return {
11
+ id: session.sessionId,
12
+ deviceId: session.deviceId,
13
+ deviceName: typeof metadata.deviceName === 'string' ? metadata.deviceName : undefined,
14
+ current: Boolean(currentSessionId) && session.sessionId === currentSessionId,
15
+ loginAt: typeof metadata.loginAt === 'string' ? metadata.loginAt : undefined,
16
+ // The active record is re-created on each rotation, so its creation time is the
17
+ // best available "last used" signal without an extra write per request.
18
+ lastActiveAt: session.createdAt ? new Date(session.createdAt).toISOString() : undefined
19
+ };
20
+ };
21
+ /**
22
+ * Builds origin-defined session metadata from generic request context fields.
23
+ */ const buildSessionMetadata = (params)=>{
24
+ const deviceName = userAgent.getDeviceName(params.userAgent);
25
+ return {
26
+ loginAt: params.loginAt ?? new Date().toISOString(),
27
+ ...deviceName ? {
28
+ deviceName
29
+ } : {}
30
+ };
31
+ };
32
+ /**
33
+ * Sorts sessions for display: current session first, then most recently used.
34
+ */ const sortSessionsForDisplay = (sessions)=>[
35
+ ...sessions
36
+ ].sort((a, b)=>{
37
+ if (a.current !== b.current) {
38
+ return a.current ? -1 : 1;
39
+ }
40
+ return (b.lastActiveAt ?? '').localeCompare(a.lastActiveAt ?? '');
41
+ });
42
+
43
+ exports.buildSessionMetadata = buildSessionMetadata;
44
+ exports.sanitizeSessionEntry = sanitizeSessionEntry;
45
+ exports.sortSessionsForDisplay = sortSessionsForDisplay;
46
+ //# sourceMappingURL=sessions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessions.js","sources":["../src/sessions.ts"],"sourcesContent":["import { getDeviceName } from './user-agent';\n\nexport interface SessionEntryLike {\n sessionId: string;\n deviceId?: string;\n createdAt?: Date | string | null;\n metadata?: Record<string, unknown> | null;\n}\n\nexport interface SanitizedSessionEntry {\n id: string;\n deviceId?: string;\n deviceName?: string;\n current: boolean;\n loginAt?: string;\n lastActiveAt?: string;\n}\n\nexport interface SessionDisplayEntry {\n current: boolean;\n lastActiveAt?: string;\n}\n\n/**\n * Sanitizes a session record for client consumption (active devices UI/API).\n * Never includes tokens or internal database identifiers.\n */\nexport const sanitizeSessionEntry = (\n session: SessionEntryLike,\n currentSessionId?: string\n): SanitizedSessionEntry => {\n const metadata = session.metadata ?? {};\n\n return {\n id: session.sessionId,\n deviceId: session.deviceId,\n deviceName: typeof metadata.deviceName === 'string' ? metadata.deviceName : undefined,\n current: Boolean(currentSessionId) && session.sessionId === currentSessionId,\n loginAt: typeof metadata.loginAt === 'string' ? metadata.loginAt : undefined,\n // The active record is re-created on each rotation, so its creation time is the\n // best available \"last used\" signal without an extra write per request.\n lastActiveAt: session.createdAt ? new Date(session.createdAt).toISOString() : undefined,\n };\n};\n\n/**\n * Builds origin-defined session metadata from generic request context fields.\n */\nexport const buildSessionMetadata = (params: {\n userAgent?: string | null;\n loginAt?: string;\n}): Record<string, unknown> => {\n const deviceName = getDeviceName(params.userAgent);\n\n return {\n loginAt: params.loginAt ?? new Date().toISOString(),\n ...(deviceName ? { deviceName } : {}),\n };\n};\n\n/**\n * Sorts sessions for display: current session first, then most recently used.\n */\nexport const sortSessionsForDisplay = <T extends SessionDisplayEntry>(sessions: T[]): T[] =>\n [...sessions].sort((a, b) => {\n if (a.current !== b.current) {\n return a.current ? -1 : 1;\n }\n\n return (b.lastActiveAt ?? '').localeCompare(a.lastActiveAt ?? '');\n });\n"],"names":["sanitizeSessionEntry","session","currentSessionId","metadata","id","sessionId","deviceId","deviceName","undefined","current","Boolean","loginAt","lastActiveAt","createdAt","Date","toISOString","buildSessionMetadata","params","getDeviceName","userAgent","sortSessionsForDisplay","sessions","sort","a","b","localeCompare"],"mappings":";;;;AAuBA;;;AAGC,IACM,MAAMA,oBAAAA,GAAuB,CAClCC,OAAAA,EACAC,gBAAAA,GAAAA;AAEA,IAAA,MAAMC,QAAAA,GAAWF,OAAAA,CAAQE,QAAQ,IAAI,EAAC;IAEtC,OAAO;AACLC,QAAAA,EAAAA,EAAIH,QAAQI,SAAS;AACrBC,QAAAA,QAAAA,EAAUL,QAAQK,QAAQ;AAC1BC,QAAAA,UAAAA,EAAY,OAAOJ,QAAAA,CAASI,UAAU,KAAK,QAAA,GAAWJ,QAAAA,CAASI,UAAU,GAAGC,SAAAA;AAC5EC,QAAAA,OAAAA,EAASC,OAAAA,CAAQR,gBAAAA,CAAAA,IAAqBD,OAAAA,CAAQI,SAAS,KAAKH,gBAAAA;AAC5DS,QAAAA,OAAAA,EAAS,OAAOR,QAAAA,CAASQ,OAAO,KAAK,QAAA,GAAWR,QAAAA,CAASQ,OAAO,GAAGH,SAAAA;;;QAGnEI,YAAAA,EAAcX,OAAAA,CAAQY,SAAS,GAAG,IAAIC,KAAKb,OAAAA,CAAQY,SAAS,CAAA,CAAEE,WAAW,EAAA,GAAKP;AAChF,KAAA;AACF;AAEA;;IAGO,MAAMQ,oBAAAA,GAAuB,CAACC,MAAAA,GAAAA;IAInC,MAAMV,UAAAA,GAAaW,uBAAAA,CAAcD,MAAAA,CAAOE,SAAS,CAAA;IAEjD,OAAO;AACLR,QAAAA,OAAAA,EAASM,MAAAA,CAAON,OAAO,IAAI,IAAIG,OAAOC,WAAW,EAAA;AACjD,QAAA,GAAIR,UAAAA,GAAa;AAAEA,YAAAA;AAAW,SAAA,GAAI;AACpC,KAAA;AACF;AAEA;;AAEC,IACM,MAAMa,sBAAAA,GAAyB,CAAgCC,QAAAA,GACpE;AAAIA,QAAAA,GAAAA;KAAS,CAACC,IAAI,CAAC,CAACC,CAAAA,EAAGC,CAAAA,GAAAA;AACrB,QAAA,IAAID,CAAAA,CAAEd,OAAO,KAAKe,CAAAA,CAAEf,OAAO,EAAE;AAC3B,YAAA,OAAOc,CAAAA,CAAEd,OAAO,GAAG,EAAC,GAAI,CAAA;AAC1B,QAAA;QAEA,OAAQe,CAAAA,CAAAA,CAAEZ,YAAY,IAAI,EAAC,EAAGa,aAAa,CAACF,CAAAA,CAAEX,YAAY,IAAI,EAAA,CAAA;IAChE,CAAA;;;;;;"}
@@ -0,0 +1,42 @@
1
+ import { getDeviceName } from './user-agent.mjs';
2
+
3
+ /**
4
+ * Sanitizes a session record for client consumption (active devices UI/API).
5
+ * Never includes tokens or internal database identifiers.
6
+ */ const sanitizeSessionEntry = (session, currentSessionId)=>{
7
+ const metadata = session.metadata ?? {};
8
+ return {
9
+ id: session.sessionId,
10
+ deviceId: session.deviceId,
11
+ deviceName: typeof metadata.deviceName === 'string' ? metadata.deviceName : undefined,
12
+ current: Boolean(currentSessionId) && session.sessionId === currentSessionId,
13
+ loginAt: typeof metadata.loginAt === 'string' ? metadata.loginAt : undefined,
14
+ // The active record is re-created on each rotation, so its creation time is the
15
+ // best available "last used" signal without an extra write per request.
16
+ lastActiveAt: session.createdAt ? new Date(session.createdAt).toISOString() : undefined
17
+ };
18
+ };
19
+ /**
20
+ * Builds origin-defined session metadata from generic request context fields.
21
+ */ const buildSessionMetadata = (params)=>{
22
+ const deviceName = getDeviceName(params.userAgent);
23
+ return {
24
+ loginAt: params.loginAt ?? new Date().toISOString(),
25
+ ...deviceName ? {
26
+ deviceName
27
+ } : {}
28
+ };
29
+ };
30
+ /**
31
+ * Sorts sessions for display: current session first, then most recently used.
32
+ */ const sortSessionsForDisplay = (sessions)=>[
33
+ ...sessions
34
+ ].sort((a, b)=>{
35
+ if (a.current !== b.current) {
36
+ return a.current ? -1 : 1;
37
+ }
38
+ return (b.lastActiveAt ?? '').localeCompare(a.lastActiveAt ?? '');
39
+ });
40
+
41
+ export { buildSessionMetadata, sanitizeSessionEntry, sortSessionsForDisplay };
42
+ //# sourceMappingURL=sessions.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessions.mjs","sources":["../src/sessions.ts"],"sourcesContent":["import { getDeviceName } from './user-agent';\n\nexport interface SessionEntryLike {\n sessionId: string;\n deviceId?: string;\n createdAt?: Date | string | null;\n metadata?: Record<string, unknown> | null;\n}\n\nexport interface SanitizedSessionEntry {\n id: string;\n deviceId?: string;\n deviceName?: string;\n current: boolean;\n loginAt?: string;\n lastActiveAt?: string;\n}\n\nexport interface SessionDisplayEntry {\n current: boolean;\n lastActiveAt?: string;\n}\n\n/**\n * Sanitizes a session record for client consumption (active devices UI/API).\n * Never includes tokens or internal database identifiers.\n */\nexport const sanitizeSessionEntry = (\n session: SessionEntryLike,\n currentSessionId?: string\n): SanitizedSessionEntry => {\n const metadata = session.metadata ?? {};\n\n return {\n id: session.sessionId,\n deviceId: session.deviceId,\n deviceName: typeof metadata.deviceName === 'string' ? metadata.deviceName : undefined,\n current: Boolean(currentSessionId) && session.sessionId === currentSessionId,\n loginAt: typeof metadata.loginAt === 'string' ? metadata.loginAt : undefined,\n // The active record is re-created on each rotation, so its creation time is the\n // best available \"last used\" signal without an extra write per request.\n lastActiveAt: session.createdAt ? new Date(session.createdAt).toISOString() : undefined,\n };\n};\n\n/**\n * Builds origin-defined session metadata from generic request context fields.\n */\nexport const buildSessionMetadata = (params: {\n userAgent?: string | null;\n loginAt?: string;\n}): Record<string, unknown> => {\n const deviceName = getDeviceName(params.userAgent);\n\n return {\n loginAt: params.loginAt ?? new Date().toISOString(),\n ...(deviceName ? { deviceName } : {}),\n };\n};\n\n/**\n * Sorts sessions for display: current session first, then most recently used.\n */\nexport const sortSessionsForDisplay = <T extends SessionDisplayEntry>(sessions: T[]): T[] =>\n [...sessions].sort((a, b) => {\n if (a.current !== b.current) {\n return a.current ? -1 : 1;\n }\n\n return (b.lastActiveAt ?? '').localeCompare(a.lastActiveAt ?? '');\n });\n"],"names":["sanitizeSessionEntry","session","currentSessionId","metadata","id","sessionId","deviceId","deviceName","undefined","current","Boolean","loginAt","lastActiveAt","createdAt","Date","toISOString","buildSessionMetadata","params","getDeviceName","userAgent","sortSessionsForDisplay","sessions","sort","a","b","localeCompare"],"mappings":";;AAuBA;;;AAGC,IACM,MAAMA,oBAAAA,GAAuB,CAClCC,OAAAA,EACAC,gBAAAA,GAAAA;AAEA,IAAA,MAAMC,QAAAA,GAAWF,OAAAA,CAAQE,QAAQ,IAAI,EAAC;IAEtC,OAAO;AACLC,QAAAA,EAAAA,EAAIH,QAAQI,SAAS;AACrBC,QAAAA,QAAAA,EAAUL,QAAQK,QAAQ;AAC1BC,QAAAA,UAAAA,EAAY,OAAOJ,QAAAA,CAASI,UAAU,KAAK,QAAA,GAAWJ,QAAAA,CAASI,UAAU,GAAGC,SAAAA;AAC5EC,QAAAA,OAAAA,EAASC,OAAAA,CAAQR,gBAAAA,CAAAA,IAAqBD,OAAAA,CAAQI,SAAS,KAAKH,gBAAAA;AAC5DS,QAAAA,OAAAA,EAAS,OAAOR,QAAAA,CAASQ,OAAO,KAAK,QAAA,GAAWR,QAAAA,CAASQ,OAAO,GAAGH,SAAAA;;;QAGnEI,YAAAA,EAAcX,OAAAA,CAAQY,SAAS,GAAG,IAAIC,KAAKb,OAAAA,CAAQY,SAAS,CAAA,CAAEE,WAAW,EAAA,GAAKP;AAChF,KAAA;AACF;AAEA;;IAGO,MAAMQ,oBAAAA,GAAuB,CAACC,MAAAA,GAAAA;IAInC,MAAMV,UAAAA,GAAaW,aAAAA,CAAcD,MAAAA,CAAOE,SAAS,CAAA;IAEjD,OAAO;AACLR,QAAAA,OAAAA,EAASM,MAAAA,CAAON,OAAO,IAAI,IAAIG,OAAOC,WAAW,EAAA;AACjD,QAAA,GAAIR,UAAAA,GAAa;AAAEA,YAAAA;AAAW,SAAA,GAAI;AACpC,KAAA;AACF;AAEA;;AAEC,IACM,MAAMa,sBAAAA,GAAyB,CAAgCC,QAAAA,GACpE;AAAIA,QAAAA,GAAAA;KAAS,CAACC,IAAI,CAAC,CAACC,CAAAA,EAAGC,CAAAA,GAAAA;AACrB,QAAA,IAAID,CAAAA,CAAEd,OAAO,KAAKe,CAAAA,CAAEf,OAAO,EAAE;AAC3B,YAAA,OAAOc,CAAAA,CAAEd,OAAO,GAAG,EAAC,GAAI,CAAA;AAC1B,QAAA;QAEA,OAAQe,CAAAA,CAAAA,CAAEZ,YAAY,IAAI,EAAC,EAAGa,aAAa,CAACF,CAAAA,CAAEX,YAAY,IAAI,EAAA,CAAA;IAChE,CAAA;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"set-creator-fields.d.ts","sourceRoot":"","sources":["../src/set-creator-fields.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,IAAI,CAAC;IACX,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,UAAU,IAAI;IACZ,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;CACrB;AAED,QAAA,MAAM,gBAAgB,8CACgC,OAAO,+CACjB,UAAU,eASnD,CAAC;AAEJ,eAAe,gBAAgB,CAAC"}
1
+ {"version":3,"file":"set-creator-fields.d.ts","sourceRoot":"","sources":["../src/set-creator-fields.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,IAAI,CAAC;IACX,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,UAAU,IAAI;IACZ,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;CACrB;AAED,QAAA,MAAM,gBAAgB,GACnB,KAAK,SAAS,MAAM,EAAE,qBAA6B,OAAO,MAC1D,UAAU,SAAS,MAAM,GAAG,KAAK,EAAE,MAAM,UAAU,eASnD,CAAC;AAEJ,eAAe,gBAAgB,CAAC"}
@@ -2,7 +2,11 @@
2
2
 
3
3
  var _ = require('lodash');
4
4
 
5
- const isPlainObject = (value)=>_.isPlainObject(value);
5
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
6
+
7
+ var ___default = /*#__PURE__*/_interopDefault(_);
8
+
9
+ const isPlainObject = (value)=>___default.default.isPlainObject(value);
6
10
  /**
7
11
  * Splits a REST sort string into trimmed segments with a non-empty field (drops '', ',', trailing commas).
8
12
  */ function getMeaningfulSortSegments(sort) {
@@ -1 +1 @@
1
- {"version":3,"file":"sort-query.js","sources":["../src/sort-query.ts"],"sourcesContent":["import _ from 'lodash';\n\nexport type SortOrder = 'asc' | 'desc';\n\nexport interface SortParamsObject {\n [key: string]: SortOrder | SortParamsObject;\n}\n\nexport type SortParams = string | string[] | SortParamsObject | SortParamsObject[];\n\nconst isPlainObject = (value: unknown): value is Record<string, unknown> => _.isPlainObject(value);\n\n/**\n * Splits a REST sort string into trimmed segments with a non-empty field (drops '', ',', trailing commas).\n */\nexport function getMeaningfulSortSegments(sort: string): string[] {\n return sort\n .split(',')\n .map((segment) => segment.trim())\n .filter((segment) => {\n if (segment.length === 0) {\n return false;\n }\n\n const [field] = segment.split(':');\n return field.trim().length > 0;\n });\n}\n\n/**\n * Whether a nested sort object ({ field: 'asc' } or { relation: { name: 'desc' } }) specifies\n * at least one field to sort on. Empty objects and keys with blank orders are treated as no sort.\n */\nfunction hasMeaningfulSortObject(sort: SortParamsObject): boolean {\n return Object.keys(sort).some((key) => {\n const order = sort[key];\n\n if (typeof order === 'string') {\n return order.length > 0;\n }\n\n if (isPlainObject(order)) {\n return hasMeaningfulSortObject(order as SortParamsObject);\n }\n\n return false;\n });\n}\n\n/** Whether a REST-style sort string contains at least one meaningful segment. */\nfunction hasMeaningfulStringSort(sort: string): boolean {\n return getMeaningfulSortSegments(sort).length > 0;\n}\n\n/**\n * Whether `sort` carries a real ordering instruction. Empty or absent sort must stay undefined so\n * populated relations keep join-table connect order (GraphQL defaults nested sort to []; REST qs\n * `sort[]` with strictNullHandling parses to `[null]`).\n */\nexport function hasSort(sort?: unknown): sort is SortParams {\n if (sort === undefined || sort === null) {\n return false;\n }\n\n if (typeof sort === 'string') {\n return hasMeaningfulStringSort(sort);\n }\n\n if (Array.isArray(sort)) {\n if (sort.length === 0) {\n return false;\n }\n\n return sort.some((item) => {\n if (typeof item === 'string') {\n return hasMeaningfulStringSort(item);\n }\n\n if (isPlainObject(item)) {\n return hasMeaningfulSortObject(item as SortParamsObject);\n }\n\n return false;\n });\n }\n\n if (isPlainObject(sort)) {\n return hasMeaningfulSortObject(sort as SortParamsObject);\n }\n\n return false;\n}\n"],"names":["isPlainObject","value","_","getMeaningfulSortSegments","sort","split","map","segment","trim","filter","length","field","hasMeaningfulSortObject","Object","keys","some","key","order","hasMeaningfulStringSort","hasSort","undefined","Array","isArray","item"],"mappings":";;;;AAUA,MAAMA,aAAAA,GAAgB,CAACC,KAAAA,GAAqDC,CAAAA,CAAEF,aAAa,CAACC,KAAAA,CAAAA;AAE5F;;IAGO,SAASE,yBAAAA,CAA0BC,IAAY,EAAA;AACpD,IAAA,OAAOA,IAAAA,CACJC,KAAK,CAAC,GAAA,CAAA,CACNC,GAAG,CAAC,CAACC,OAAAA,GAAYA,OAAAA,CAAQC,IAAI,EAAA,CAAA,CAC7BC,MAAM,CAAC,CAACF,OAAAA,GAAAA;QACP,IAAIA,OAAAA,CAAQG,MAAM,KAAK,CAAA,EAAG;YACxB,OAAO,KAAA;AACT,QAAA;AAEA,QAAA,MAAM,CAACC,KAAAA,CAAM,GAAGJ,OAAAA,CAAQF,KAAK,CAAC,GAAA,CAAA;AAC9B,QAAA,OAAOM,KAAAA,CAAMH,IAAI,EAAA,CAAGE,MAAM,GAAG,CAAA;AAC/B,IAAA,CAAA,CAAA;AACJ;AAEA;;;IAIA,SAASE,wBAAwBR,IAAsB,EAAA;AACrD,IAAA,OAAOS,OAAOC,IAAI,CAACV,IAAAA,CAAAA,CAAMW,IAAI,CAAC,CAACC,GAAAA,GAAAA;QAC7B,MAAMC,KAAAA,GAAQb,IAAI,CAACY,GAAAA,CAAI;QAEvB,IAAI,OAAOC,UAAU,QAAA,EAAU;YAC7B,OAAOA,KAAAA,CAAMP,MAAM,GAAG,CAAA;AACxB,QAAA;AAEA,QAAA,IAAIV,cAAciB,KAAAA,CAAAA,EAAQ;AACxB,YAAA,OAAOL,uBAAAA,CAAwBK,KAAAA,CAAAA;AACjC,QAAA;QAEA,OAAO,KAAA;AACT,IAAA,CAAA,CAAA;AACF;AAEA,kFACA,SAASC,uBAAAA,CAAwBd,IAAY,EAAA;IAC3C,OAAOD,yBAAAA,CAA0BC,IAAAA,CAAAA,CAAMM,MAAM,GAAG,CAAA;AAClD;AAEA;;;;IAKO,SAASS,OAAAA,CAAQf,IAAc,EAAA;IACpC,IAAIA,IAAAA,KAASgB,SAAAA,IAAahB,IAAAA,KAAS,IAAA,EAAM;QACvC,OAAO,KAAA;AACT,IAAA;IAEA,IAAI,OAAOA,SAAS,QAAA,EAAU;AAC5B,QAAA,OAAOc,uBAAAA,CAAwBd,IAAAA,CAAAA;AACjC,IAAA;IAEA,IAAIiB,KAAAA,CAAMC,OAAO,CAAClB,IAAAA,CAAAA,EAAO;QACvB,IAAIA,IAAAA,CAAKM,MAAM,KAAK,CAAA,EAAG;YACrB,OAAO,KAAA;AACT,QAAA;QAEA,OAAON,IAAAA,CAAKW,IAAI,CAAC,CAACQ,IAAAA,GAAAA;YAChB,IAAI,OAAOA,SAAS,QAAA,EAAU;AAC5B,gBAAA,OAAOL,uBAAAA,CAAwBK,IAAAA,CAAAA;AACjC,YAAA;AAEA,YAAA,IAAIvB,cAAcuB,IAAAA,CAAAA,EAAO;AACvB,gBAAA,OAAOX,uBAAAA,CAAwBW,IAAAA,CAAAA;AACjC,YAAA;YAEA,OAAO,KAAA;AACT,QAAA,CAAA,CAAA;AACF,IAAA;AAEA,IAAA,IAAIvB,cAAcI,IAAAA,CAAAA,EAAO;AACvB,QAAA,OAAOQ,uBAAAA,CAAwBR,IAAAA,CAAAA;AACjC,IAAA;IAEA,OAAO,KAAA;AACT;;;;;"}
1
+ {"version":3,"file":"sort-query.js","sources":["../src/sort-query.ts"],"sourcesContent":["import _ from 'lodash';\n\nexport type SortOrder = 'asc' | 'desc';\n\nexport interface SortParamsObject {\n [key: string]: SortOrder | SortParamsObject;\n}\n\nexport type SortParams = string | string[] | SortParamsObject | SortParamsObject[];\n\nconst isPlainObject = (value: unknown): value is Record<string, unknown> => _.isPlainObject(value);\n\n/**\n * Splits a REST sort string into trimmed segments with a non-empty field (drops '', ',', trailing commas).\n */\nexport function getMeaningfulSortSegments(sort: string): string[] {\n return sort\n .split(',')\n .map((segment) => segment.trim())\n .filter((segment) => {\n if (segment.length === 0) {\n return false;\n }\n\n const [field] = segment.split(':');\n return field.trim().length > 0;\n });\n}\n\n/**\n * Whether a nested sort object ({ field: 'asc' } or { relation: { name: 'desc' } }) specifies\n * at least one field to sort on. Empty objects and keys with blank orders are treated as no sort.\n */\nfunction hasMeaningfulSortObject(sort: SortParamsObject): boolean {\n return Object.keys(sort).some((key) => {\n const order = sort[key];\n\n if (typeof order === 'string') {\n return order.length > 0;\n }\n\n if (isPlainObject(order)) {\n return hasMeaningfulSortObject(order as SortParamsObject);\n }\n\n return false;\n });\n}\n\n/** Whether a REST-style sort string contains at least one meaningful segment. */\nfunction hasMeaningfulStringSort(sort: string): boolean {\n return getMeaningfulSortSegments(sort).length > 0;\n}\n\n/**\n * Whether `sort` carries a real ordering instruction. Empty or absent sort must stay undefined so\n * populated relations keep join-table connect order (GraphQL defaults nested sort to []; REST qs\n * `sort[]` with strictNullHandling parses to `[null]`).\n */\nexport function hasSort(sort?: unknown): sort is SortParams {\n if (sort === undefined || sort === null) {\n return false;\n }\n\n if (typeof sort === 'string') {\n return hasMeaningfulStringSort(sort);\n }\n\n if (Array.isArray(sort)) {\n if (sort.length === 0) {\n return false;\n }\n\n return sort.some((item) => {\n if (typeof item === 'string') {\n return hasMeaningfulStringSort(item);\n }\n\n if (isPlainObject(item)) {\n return hasMeaningfulSortObject(item as SortParamsObject);\n }\n\n return false;\n });\n }\n\n if (isPlainObject(sort)) {\n return hasMeaningfulSortObject(sort as SortParamsObject);\n }\n\n return false;\n}\n"],"names":["isPlainObject","value","_","getMeaningfulSortSegments","sort","split","map","segment","trim","filter","length","field","hasMeaningfulSortObject","Object","keys","some","key","order","hasMeaningfulStringSort","hasSort","undefined","Array","isArray","item"],"mappings":";;;;;;;;AAUA,MAAMA,aAAAA,GAAgB,CAACC,KAAAA,GAAqDC,kBAAAA,CAAEF,aAAa,CAACC,KAAAA,CAAAA;AAE5F;;IAGO,SAASE,yBAAAA,CAA0BC,IAAY,EAAA;AACpD,IAAA,OAAOA,IAAAA,CACJC,KAAK,CAAC,GAAA,CAAA,CACNC,GAAG,CAAC,CAACC,OAAAA,GAAYA,OAAAA,CAAQC,IAAI,EAAA,CAAA,CAC7BC,MAAM,CAAC,CAACF,OAAAA,GAAAA;QACP,IAAIA,OAAAA,CAAQG,MAAM,KAAK,CAAA,EAAG;YACxB,OAAO,KAAA;AACT,QAAA;AAEA,QAAA,MAAM,CAACC,KAAAA,CAAM,GAAGJ,OAAAA,CAAQF,KAAK,CAAC,GAAA,CAAA;AAC9B,QAAA,OAAOM,KAAAA,CAAMH,IAAI,EAAA,CAAGE,MAAM,GAAG,CAAA;AAC/B,IAAA,CAAA,CAAA;AACJ;AAEA;;;IAIA,SAASE,wBAAwBR,IAAsB,EAAA;AACrD,IAAA,OAAOS,OAAOC,IAAI,CAACV,IAAAA,CAAAA,CAAMW,IAAI,CAAC,CAACC,GAAAA,GAAAA;QAC7B,MAAMC,KAAAA,GAAQb,IAAI,CAACY,GAAAA,CAAI;QAEvB,IAAI,OAAOC,UAAU,QAAA,EAAU;YAC7B,OAAOA,KAAAA,CAAMP,MAAM,GAAG,CAAA;AACxB,QAAA;AAEA,QAAA,IAAIV,cAAciB,KAAAA,CAAAA,EAAQ;AACxB,YAAA,OAAOL,uBAAAA,CAAwBK,KAAAA,CAAAA;AACjC,QAAA;QAEA,OAAO,KAAA;AACT,IAAA,CAAA,CAAA;AACF;AAEA,kFACA,SAASC,uBAAAA,CAAwBd,IAAY,EAAA;IAC3C,OAAOD,yBAAAA,CAA0BC,IAAAA,CAAAA,CAAMM,MAAM,GAAG,CAAA;AAClD;AAEA;;;;IAKO,SAASS,OAAAA,CAAQf,IAAc,EAAA;IACpC,IAAIA,IAAAA,KAASgB,SAAAA,IAAahB,IAAAA,KAAS,IAAA,EAAM;QACvC,OAAO,KAAA;AACT,IAAA;IAEA,IAAI,OAAOA,SAAS,QAAA,EAAU;AAC5B,QAAA,OAAOc,uBAAAA,CAAwBd,IAAAA,CAAAA;AACjC,IAAA;IAEA,IAAIiB,KAAAA,CAAMC,OAAO,CAAClB,IAAAA,CAAAA,EAAO;QACvB,IAAIA,IAAAA,CAAKM,MAAM,KAAK,CAAA,EAAG;YACrB,OAAO,KAAA;AACT,QAAA;QAEA,OAAON,IAAAA,CAAKW,IAAI,CAAC,CAACQ,IAAAA,GAAAA;YAChB,IAAI,OAAOA,SAAS,QAAA,EAAU;AAC5B,gBAAA,OAAOL,uBAAAA,CAAwBK,IAAAA,CAAAA;AACjC,YAAA;AAEA,YAAA,IAAIvB,cAAcuB,IAAAA,CAAAA,EAAO;AACvB,gBAAA,OAAOX,uBAAAA,CAAwBW,IAAAA,CAAAA;AACjC,YAAA;YAEA,OAAO,KAAA;AACT,QAAA,CAAA,CAAA;AACF,IAAA;AAEA,IAAA,IAAIvB,cAAcI,IAAAA,CAAAA,EAAO;AACvB,QAAA,OAAOQ,uBAAAA,CAAwBR,IAAAA,CAAAA;AACjC,IAAA;IAEA,OAAO,KAAA;AACT;;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"template.d.ts","sourceRoot":"","sources":["../src/template.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,QAAA,MAAM,+BAA+B,yBAA0B,MAAM,EAAE,SAAS,MAAM,WAOrF,CAAC;AAEF;;GAEG;AACH,QAAA,MAAM,8BAA8B,UAAW,MAAM,WAAyC,CAAC;AAE/F,OAAO,EAAE,+BAA+B,EAAE,8BAA8B,EAAE,CAAC"}
1
+ {"version":3,"file":"template.d.ts","sourceRoot":"","sources":["../src/template.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,QAAA,MAAM,+BAA+B,GAAI,sBAAsB,MAAM,EAAE,EAAE,OAAO,MAAM,WAOrF,CAAC;AAEF;;GAEG;AACH,QAAA,MAAM,8BAA8B,GAAI,OAAO,MAAM,WAAyC,CAAC;AAE/F,OAAO,EAAE,+BAA+B,EAAE,8BAA8B,EAAE,CAAC"}
@@ -75,15 +75,114 @@ interface Context<AttributeType = Attribute> {
75
75
  }
76
76
  declare const _default: () => {
77
77
  traverse: Traverse;
78
- intercept<T>(predicate: Interceptor<T>['predicate'], handler: Interceptor<T>['handler']): any;
79
- parse<T_1>(predicate: (data: unknown) => data is T_1, parser: (data: T_1) => ParseUtils<T_1>): any;
80
- ignore(predicate: Ignore): any;
81
- on(predicate: CommonHandler['predicate'], handler: CommonHandler['handler']): any;
82
- onAttribute(predicate: AttributeHandler['predicate'], handler: AttributeHandler['handler']): any;
83
- onRelation(handler: AttributeHandler<RelationalAttribute>['handler']): any;
84
- onMedia(handler: AttributeHandler<RelationalAttribute>['handler']): any;
85
- onComponent(handler: AttributeHandler<ComponentAttribute>['handler']): any;
86
- onDynamicZone(handler: AttributeHandler<DynamicZoneAttribute>['handler']): any;
78
+ intercept<T>(predicate: Interceptor<T>["predicate"], handler: Interceptor<T>["handler"]): {
79
+ traverse: Traverse;
80
+ intercept<T>(predicate: Interceptor<T>["predicate"], handler: Interceptor<T>["handler"]): /*elided*/ any;
81
+ parse<T_1>(predicate: Parser<T_1>["predicate"], parser: Parser<T_1>["parser"]): /*elided*/ any;
82
+ ignore(predicate: Ignore): /*elided*/ any;
83
+ on(predicate: CommonHandler["predicate"], handler: CommonHandler["handler"]): /*elided*/ any;
84
+ onAttribute(predicate: AttributeHandler["predicate"], handler: AttributeHandler["handler"]): /*elided*/ any;
85
+ onRelation(handler: AttributeHandler<RelationalAttribute>["handler"]): /*elided*/ any;
86
+ onMedia(handler: AttributeHandler<RelationalAttribute>["handler"]): /*elided*/ any;
87
+ onComponent(handler: AttributeHandler<ComponentAttribute>["handler"]): /*elided*/ any;
88
+ onDynamicZone(handler: AttributeHandler<DynamicZoneAttribute>["handler"]): /*elided*/ any;
89
+ };
90
+ parse<T>(predicate: Parser<T>["predicate"], parser: Parser<T>["parser"]): {
91
+ traverse: Traverse;
92
+ intercept<T_1>(predicate: Interceptor<T_1>["predicate"], handler: Interceptor<T_1>["handler"]): /*elided*/ any;
93
+ parse<T>(predicate: Parser<T>["predicate"], parser: Parser<T>["parser"]): /*elided*/ any;
94
+ ignore(predicate: Ignore): /*elided*/ any;
95
+ on(predicate: CommonHandler["predicate"], handler: CommonHandler["handler"]): /*elided*/ any;
96
+ onAttribute(predicate: AttributeHandler["predicate"], handler: AttributeHandler["handler"]): /*elided*/ any;
97
+ onRelation(handler: AttributeHandler<RelationalAttribute>["handler"]): /*elided*/ any;
98
+ onMedia(handler: AttributeHandler<RelationalAttribute>["handler"]): /*elided*/ any;
99
+ onComponent(handler: AttributeHandler<ComponentAttribute>["handler"]): /*elided*/ any;
100
+ onDynamicZone(handler: AttributeHandler<DynamicZoneAttribute>["handler"]): /*elided*/ any;
101
+ };
102
+ ignore(predicate: Ignore): {
103
+ traverse: Traverse;
104
+ intercept<T>(predicate: Interceptor<T>["predicate"], handler: Interceptor<T>["handler"]): /*elided*/ any;
105
+ parse<T>(predicate: Parser<T>["predicate"], parser: Parser<T>["parser"]): /*elided*/ any;
106
+ ignore(predicate: Ignore): /*elided*/ any;
107
+ on(predicate: CommonHandler["predicate"], handler: CommonHandler["handler"]): /*elided*/ any;
108
+ onAttribute(predicate: AttributeHandler["predicate"], handler: AttributeHandler["handler"]): /*elided*/ any;
109
+ onRelation(handler: AttributeHandler<RelationalAttribute>["handler"]): /*elided*/ any;
110
+ onMedia(handler: AttributeHandler<RelationalAttribute>["handler"]): /*elided*/ any;
111
+ onComponent(handler: AttributeHandler<ComponentAttribute>["handler"]): /*elided*/ any;
112
+ onDynamicZone(handler: AttributeHandler<DynamicZoneAttribute>["handler"]): /*elided*/ any;
113
+ };
114
+ on(predicate: CommonHandler["predicate"], handler: CommonHandler["handler"]): {
115
+ traverse: Traverse;
116
+ intercept<T>(predicate: Interceptor<T>["predicate"], handler: Interceptor<T>["handler"]): /*elided*/ any;
117
+ parse<T>(predicate: Parser<T>["predicate"], parser: Parser<T>["parser"]): /*elided*/ any;
118
+ ignore(predicate: Ignore): /*elided*/ any;
119
+ on(predicate: CommonHandler["predicate"], handler: CommonHandler["handler"]): /*elided*/ any;
120
+ onAttribute(predicate: AttributeHandler["predicate"], handler: AttributeHandler["handler"]): /*elided*/ any;
121
+ onRelation(handler: AttributeHandler<RelationalAttribute>["handler"]): /*elided*/ any;
122
+ onMedia(handler: AttributeHandler<RelationalAttribute>["handler"]): /*elided*/ any;
123
+ onComponent(handler: AttributeHandler<ComponentAttribute>["handler"]): /*elided*/ any;
124
+ onDynamicZone(handler: AttributeHandler<DynamicZoneAttribute>["handler"]): /*elided*/ any;
125
+ };
126
+ onAttribute(predicate: AttributeHandler["predicate"], handler: AttributeHandler["handler"]): {
127
+ traverse: Traverse;
128
+ intercept<T>(predicate: Interceptor<T>["predicate"], handler: Interceptor<T>["handler"]): /*elided*/ any;
129
+ parse<T>(predicate: Parser<T>["predicate"], parser: Parser<T>["parser"]): /*elided*/ any;
130
+ ignore(predicate: Ignore): /*elided*/ any;
131
+ on(predicate: CommonHandler["predicate"], handler: CommonHandler["handler"]): /*elided*/ any;
132
+ onAttribute(predicate: AttributeHandler["predicate"], handler: AttributeHandler["handler"]): /*elided*/ any;
133
+ onRelation(handler: AttributeHandler<RelationalAttribute>["handler"]): /*elided*/ any;
134
+ onMedia(handler: AttributeHandler<RelationalAttribute>["handler"]): /*elided*/ any;
135
+ onComponent(handler: AttributeHandler<ComponentAttribute>["handler"]): /*elided*/ any;
136
+ onDynamicZone(handler: AttributeHandler<DynamicZoneAttribute>["handler"]): /*elided*/ any;
137
+ };
138
+ onRelation(handler: AttributeHandler<RelationalAttribute>["handler"]): {
139
+ traverse: Traverse;
140
+ intercept<T>(predicate: Interceptor<T>["predicate"], handler: Interceptor<T>["handler"]): /*elided*/ any;
141
+ parse<T>(predicate: Parser<T>["predicate"], parser: Parser<T>["parser"]): /*elided*/ any;
142
+ ignore(predicate: Ignore): /*elided*/ any;
143
+ on(predicate: CommonHandler["predicate"], handler: CommonHandler["handler"]): /*elided*/ any;
144
+ onAttribute(predicate: AttributeHandler["predicate"], handler: AttributeHandler["handler"]): /*elided*/ any;
145
+ onRelation(handler: AttributeHandler<RelationalAttribute>["handler"]): /*elided*/ any;
146
+ onMedia(handler: AttributeHandler<RelationalAttribute>["handler"]): /*elided*/ any;
147
+ onComponent(handler: AttributeHandler<ComponentAttribute>["handler"]): /*elided*/ any;
148
+ onDynamicZone(handler: AttributeHandler<DynamicZoneAttribute>["handler"]): /*elided*/ any;
149
+ };
150
+ onMedia(handler: AttributeHandler<RelationalAttribute>["handler"]): {
151
+ traverse: Traverse;
152
+ intercept<T>(predicate: Interceptor<T>["predicate"], handler: Interceptor<T>["handler"]): /*elided*/ any;
153
+ parse<T>(predicate: Parser<T>["predicate"], parser: Parser<T>["parser"]): /*elided*/ any;
154
+ ignore(predicate: Ignore): /*elided*/ any;
155
+ on(predicate: CommonHandler["predicate"], handler: CommonHandler["handler"]): /*elided*/ any;
156
+ onAttribute(predicate: AttributeHandler["predicate"], handler: AttributeHandler["handler"]): /*elided*/ any;
157
+ onRelation(handler: AttributeHandler<RelationalAttribute>["handler"]): /*elided*/ any;
158
+ onMedia(handler: AttributeHandler<RelationalAttribute>["handler"]): /*elided*/ any;
159
+ onComponent(handler: AttributeHandler<ComponentAttribute>["handler"]): /*elided*/ any;
160
+ onDynamicZone(handler: AttributeHandler<DynamicZoneAttribute>["handler"]): /*elided*/ any;
161
+ };
162
+ onComponent(handler: AttributeHandler<ComponentAttribute>["handler"]): {
163
+ traverse: Traverse;
164
+ intercept<T>(predicate: Interceptor<T>["predicate"], handler: Interceptor<T>["handler"]): /*elided*/ any;
165
+ parse<T>(predicate: Parser<T>["predicate"], parser: Parser<T>["parser"]): /*elided*/ any;
166
+ ignore(predicate: Ignore): /*elided*/ any;
167
+ on(predicate: CommonHandler["predicate"], handler: CommonHandler["handler"]): /*elided*/ any;
168
+ onAttribute(predicate: AttributeHandler["predicate"], handler: AttributeHandler["handler"]): /*elided*/ any;
169
+ onRelation(handler: AttributeHandler<RelationalAttribute>["handler"]): /*elided*/ any;
170
+ onMedia(handler: AttributeHandler<RelationalAttribute>["handler"]): /*elided*/ any;
171
+ onComponent(handler: AttributeHandler<ComponentAttribute>["handler"]): /*elided*/ any;
172
+ onDynamicZone(handler: AttributeHandler<DynamicZoneAttribute>["handler"]): /*elided*/ any;
173
+ };
174
+ onDynamicZone(handler: AttributeHandler<DynamicZoneAttribute>["handler"]): {
175
+ traverse: Traverse;
176
+ intercept<T>(predicate: Interceptor<T>["predicate"], handler: Interceptor<T>["handler"]): /*elided*/ any;
177
+ parse<T>(predicate: Parser<T>["predicate"], parser: Parser<T>["parser"]): /*elided*/ any;
178
+ ignore(predicate: Ignore): /*elided*/ any;
179
+ on(predicate: CommonHandler["predicate"], handler: CommonHandler["handler"]): /*elided*/ any;
180
+ onAttribute(predicate: AttributeHandler["predicate"], handler: AttributeHandler["handler"]): /*elided*/ any;
181
+ onRelation(handler: AttributeHandler<RelationalAttribute>["handler"]): /*elided*/ any;
182
+ onMedia(handler: AttributeHandler<RelationalAttribute>["handler"]): /*elided*/ any;
183
+ onComponent(handler: AttributeHandler<ComponentAttribute>["handler"]): /*elided*/ any;
184
+ onDynamicZone(handler: AttributeHandler<DynamicZoneAttribute>["handler"]): /*elided*/ any;
185
+ };
87
186
  };
88
187
  export default _default;
89
188
  //# sourceMappingURL=factory.d.ts.map