{"version":3,"file":"order-by.mjs","sources":["../../../src/query/helpers/order-by.ts"],"sourcesContent":["import _ from 'lodash/fp';\nimport knex from 'knex';\n\nimport * as types from '../../utils/types';\nimport { createJoin } from './join';\nimport { toColumnName } from './transform';\n\nimport type { Ctx } from '../types';\n\ntype OrderByCtx = Ctx & { alias?: string };\ntype OrderBy = string | { [key: string]: 'asc' | 'desc' } | OrderBy[];\ntype OrderByColumnValue = { column: string; order?: 'asc' | 'desc' };\ntype OrderByRawValue = { rawExpression: 'status'; isI18n?: boolean; order?: 'asc' | 'desc' };\nexport type OrderByValue = OrderByColumnValue | OrderByRawValue;\n\nconst COL_STRAPI_ROW_NUMBER = '__strapi_row_number';\nconst COL_STRAPI_ORDER_BY_PREFIX = '__strapi_order_by';\n\n/**\n * Builds a SQL CASE expression that maps each row to a numeric status rank:\n *   0 = draft/created (no published sibling with same documentId [+ locale])\n *   1 = modified (draft updated_at > published updated_at for same documentId [+ locale])\n *   2 = published\n *\n * @param db - Database instance (used to access knex raw)\n * @param tableName - Actual DB table name (used in correlated subqueries)\n * @param tableAlias - Alias of the table in the outer query (e.g. \"t0\")\n * @param isI18n - When true, adds a locale condition to avoid cross-locale contamination\n */\nexport const buildStatusSortExpression = (\n  db: { connection: { raw: (sql: string, bindings?: unknown[]) => knex.Knex.Raw } },\n  tableName: string,\n  tableAlias: string,\n  isI18n = false\n): knex.Knex.Raw => {\n  const localeCondition = isI18n ? ` AND sub.locale = ${tableAlias}.locale` : '';\n\n  return db.connection.raw(\n    `CASE WHEN NOT EXISTS(SELECT 1 FROM ?? sub WHERE sub.document_id = ${tableAlias}.document_id AND sub.published_at IS NOT NULL${localeCondition}) THEN 0 WHEN ${tableAlias}.updated_at > (SELECT MAX(sub.updated_at) FROM ?? sub WHERE sub.document_id = ${tableAlias}.document_id AND sub.published_at IS NOT NULL${localeCondition}) THEN 1 ELSE 2 END`,\n    [tableName, tableName]\n  );\n};\n\n/** DB handle accepted by {@link buildStatusSortExpression}. */\ntype StatusSortDb = Parameters<typeof buildStatusSortExpression>[0];\n\n/**\n * Shape passed to Knex `orderBy` for compound ordering. Knex accepts `Knex.Raw` in the column\n * position at runtime; generated typings sometimes only list string.\n */\nexport type KnexOrderByColumnDescriptor = {\n  column: string | knex.Knex.Raw;\n  order?: 'asc' | 'desc';\n};\n\n/**\n * Maps processed {@link OrderByValue} entries to descriptors Knex can consume. Translates the\n * virtual `status` sort into a parameterized raw SQL expression.\n */\nexport const toKnexOrderByDescriptor = (\n  db: StatusSortDb,\n  tableName: string,\n  rootTableAlias: string,\n  entry: OrderByValue\n): KnexOrderByColumnDescriptor => {\n  if ('rawExpression' in entry) {\n    return {\n      column: buildStatusSortExpression(db, tableName, rootTableAlias, entry.isI18n),\n      order: entry.order,\n    };\n  }\n\n  return { column: entry.column, order: entry.order };\n};\n\nexport const processOrderBy = (orderBy: OrderBy, ctx: OrderByCtx): OrderByValue[] => {\n  const { db, uid, qb, alias } = ctx;\n  const meta = db.metadata.get(uid);\n  const { attributes } = meta;\n\n  if (typeof orderBy === 'string') {\n    if (orderBy === 'status') {\n      if (!attributes.publishedAt || !attributes.documentId) {\n        throw new Error(\n          `Cannot order by status on model ${uid}: missing publishedAt or documentId`\n        );\n      }\n      const isI18n = 'locale' in attributes;\n      return [{ rawExpression: 'status' as const, isI18n, order: undefined }];\n    }\n\n    const attribute = attributes[orderBy];\n\n    if (!attribute) {\n      throw new Error(`Attribute ${orderBy} not found on model ${uid}`);\n    }\n\n    const columnName = toColumnName(meta, orderBy);\n\n    return [{ column: qb.aliasColumn(columnName, alias) }];\n  }\n\n  if (Array.isArray(orderBy)) {\n    return orderBy.flatMap((value) => processOrderBy(value, ctx));\n  }\n\n  if (_.isPlainObject(orderBy)) {\n    return Object.entries(orderBy).flatMap(([key, direction]) => {\n      const value = orderBy[key];\n\n      if (key === 'status') {\n        if (!attributes.publishedAt || !attributes.documentId) {\n          throw new Error(\n            `Cannot order by status on model ${uid}: missing publishedAt or documentId`\n          );\n        }\n        const isI18n = 'locale' in attributes;\n        return [{ rawExpression: 'status' as const, isI18n, order: direction as 'asc' | 'desc' }];\n      }\n\n      const attribute = attributes[key];\n\n      if (!attribute) {\n        throw new Error(`Attribute ${key} not found on model ${uid}`);\n      }\n\n      if (types.isScalar(attribute.type)) {\n        const columnName = toColumnName(meta, key);\n\n        return { column: qb.aliasColumn(columnName, alias), order: direction };\n      }\n\n      if (attribute.type === 'relation' && 'target' in attribute) {\n        const subAlias = createJoin(ctx, {\n          alias: alias || qb.alias,\n          attributeName: key,\n          attribute,\n        });\n\n        return processOrderBy(value, {\n          db,\n          qb,\n          alias: subAlias,\n          uid: attribute.target,\n        });\n      }\n\n      throw new Error(`You cannot order on ${attribute.type} types`);\n    });\n  }\n\n  throw new Error('Invalid orderBy syntax');\n};\n\nexport const getStrapiOrderColumnAlias = (column: string) => {\n  const trimmedColumnName = column.replaceAll('.', '_');\n\n  return `${COL_STRAPI_ORDER_BY_PREFIX}__${trimmedColumnName}`;\n};\n\n/**\n * Wraps the original Knex query with deep sorting functionality.\n *\n * The function takes an original query and an OrderByCtx object as parameters and returns a new Knex query with deep sorting applied.\n */\nexport const wrapWithDeepSort = (originalQuery: knex.Knex.QueryBuilder, ctx: OrderByCtx) => {\n  /**\n   * Notes:\n   * - The generated query has the following flow: baseQuery (filtered unsorted data) -> T (partitioned/sorted data) --> resultQuery (distinct, paginated, sorted data)\n   * - Pagination and selection are transferred from the original query to the outer one to avoid pruning rows too early\n   * - Filtering (where) has to be done in the deepest sub query possible to avoid processing invalid rows and corrupting the final results\n   * - We assume that all necessary joins are done in the original query (`originalQuery`), and every needed column is available with the right name and alias.\n   */\n\n  const { db, qb, uid } = ctx;\n\n  const { tableName } = db.metadata.get(uid);\n\n  // The orderBy is cloned to avoid unwanted mutations of the original object\n  const orderBy = _.cloneDeep<OrderByValue[]>(qb.state.orderBy);\n\n  // Separate column-based entries from raw-expression entries (e.g. status)\n  const columnOrderBy = orderBy.filter((ob): ob is OrderByColumnValue => 'column' in ob);\n  const rawExpressionOrderBy = orderBy.filter((ob): ob is OrderByRawValue => 'rawExpression' in ob);\n\n  // 0. Init a new Knex query instance (referenced as resultQuery) using the DB connection\n  //    The connection reuse the original table name (aliased if needed)\n  const resultQueryAlias = qb.getAlias();\n  const aliasedTableName = qb.mustUseAlias() ? alias(resultQueryAlias, tableName) : tableName;\n\n  const resultQuery = db.getConnection(aliasedTableName);\n\n  // 1. Clone the original query to create the sub-query (referenced as baseQuery) and avoid any mutation on the initial object\n  const baseQuery = originalQuery.clone();\n  const baseQueryAlias = qb.getAlias();\n\n  // Clear unwanted statements from the sub-query 'baseQuery'\n  // Note: `first()` is cleared through the combination of `baseQuery.clear('limit')` and calling `baseQuery.select(...)` again\n  // Note: Those statements will be re-applied when duplicates are removed from the final selection\n  baseQuery\n    // Columns selection\n    .clear('select')\n    // Pagination and sorting\n    .clear('order')\n    .clear('limit')\n    .clear('offset');\n\n  // Override the initial select and return only the columns needed for the partitioning.\n  // Only column-based orderBy entries are included here; raw expressions are applied later.\n  baseQuery.select(\n    // Always select the row id for future manipulation\n    prefix(qb.alias, 'id'),\n    // Select every column used in an order by clause, but alias it for future reference\n    // i.e. if t2.name is present in an order by clause:\n    //      Then, \"t2.name\" will become \"t2.name as __strapi_order_by__t2_name\"\n    ...columnOrderBy.map((orderByClause) =>\n      alias(getStrapiOrderColumnAlias(orderByClause.column), orderByClause.column)\n    )\n  );\n\n  // 2. Create a sub-query callback to extract and sort the partitions using row number\n  const partitionedQueryAlias = qb.getAlias();\n\n  const selectRowsAsNumberedPartitions = (partitionedQuery: knex.Knex.QueryBuilder) => {\n    // Transform order by clause to their alias to reference them from baseQuery\n    const prefixedOrderBy = columnOrderBy.map((orderByClause) => ({\n      column: prefix(baseQueryAlias, getStrapiOrderColumnAlias(orderByClause.column)),\n      order: orderByClause.order,\n    }));\n\n    // partitionedQuery select must contain every column used for sorting\n    const orderByColumns = prefixedOrderBy.map<string>(_.prop('column'));\n\n    partitionedQuery\n      .select(\n        // Always select baseQuery.id\n        prefix(baseQueryAlias, 'id'),\n        // Sort columns\n        ...orderByColumns\n      )\n      // The row number is used to assign an index to every row in every partition\n      .rowNumber(COL_STRAPI_ROW_NUMBER, (subQuery) => {\n        for (const orderByClause of prefixedOrderBy) {\n          subQuery.orderBy(orderByClause.column, orderByClause.order, 'last');\n        }\n\n        // And each partition/group is created based on baseQuery.id\n        subQuery.partitionBy(`${baseQueryAlias}.id`);\n      })\n      .from(baseQuery.as(baseQueryAlias))\n      .as(partitionedQueryAlias);\n  };\n\n  // 3. Create the final resultQuery query, that select and sort the wanted data using T\n\n  // Filter to string-only select items before diffing (Knex.Raw items are passed through as-is)\n  const stringSelect = qb.state.select.filter((s): s is string => typeof s === 'string');\n  const originalSelect = _.difference(\n    stringSelect,\n    // Remove column-based order by columns from the initial select (raw expressions are not in select)\n    columnOrderBy.map(_.prop('column'))\n  )\n    // Alias everything in resultQuery\n    .map((col) => `${resultQueryAlias}.${col}`);\n\n  resultQuery\n    .select(originalSelect)\n    // Join T to resultQuery to access sorted data\n    // Notes:\n    // - Only select the first row for each partition\n    // - Since we're applying the \"where\" statement directly on baseQuery (and not on resultQuery), we're using an inner join to avoid unwanted rows\n    .innerJoin(selectRowsAsNumberedPartitions, function () {\n      this\n        // Only select rows that are returned by T\n        .on(`${partitionedQueryAlias}.id`, `${resultQueryAlias}.id`)\n        // By only selecting the rows number equal to 1, we make sure we don't have duplicate, and that\n        // we're selecting rows in the correct order amongst the groups created by the \"partition by\"\n        .andOnVal(`${partitionedQueryAlias}.${COL_STRAPI_ROW_NUMBER}`, '=', 1);\n    });\n\n  // Re-apply pagination params\n\n  if (qb.state.limit) {\n    resultQuery.limit(qb.state.limit);\n  }\n\n  if (qb.state.offset) {\n    resultQuery.offset(qb.state.offset);\n  }\n\n  if (qb.state.first) {\n    resultQuery.first();\n  }\n\n  // Re-apply the sort using T values (column-based), then append raw expression sorts.\n  // Cast to any[] because Knex's TS types don't accept Knex.Raw in the column position,\n  // even though Knex supports it at runtime.\n  resultQuery.orderBy([\n    // Transform column-based \"order by\" clause to their T alias and prefix them with T alias\n    ...columnOrderBy.map((orderByClause) => ({\n      column: prefix(partitionedQueryAlias, getStrapiOrderColumnAlias(orderByClause.column)),\n      order: orderByClause.order,\n    })),\n    // Rebuild raw expression entries with the correct outer alias (resultQueryAlias)\n    ...rawExpressionOrderBy.map((entry) => ({\n      column: buildStatusSortExpression(db, tableName, resultQueryAlias, entry.isI18n),\n      order: entry.order,\n    })),\n    // Add T.id to the order by clause to get consistent results in case several rows have the exact same order\n    { column: `${partitionedQueryAlias}.id`, order: 'asc' },\n  ] as any);\n\n  return resultQuery;\n};\n\n// Utils\nconst alias = _.curry((alias: string, value: string) => `${value} as ${alias}`);\nconst prefix = _.curry((prefix: string, value: string) => `${prefix}.${value}`);\n"],"names":["COL_STRAPI_ROW_NUMBER","COL_STRAPI_ORDER_BY_PREFIX","buildStatusSortExpression","db","tableName","tableAlias","isI18n","localeCondition","connection","raw","toKnexOrderByDescriptor","rootTableAlias","entry","column","order","processOrderBy","orderBy","ctx","uid","qb","alias","meta","metadata","get","attributes","publishedAt","documentId","Error","rawExpression","undefined","attribute","columnName","toColumnName","aliasColumn","Array","isArray","flatMap","value","_","isPlainObject","Object","entries","key","direction","types","type","subAlias","createJoin","attributeName","target","getStrapiOrderColumnAlias","trimmedColumnName","replaceAll","wrapWithDeepSort","originalQuery","cloneDeep","state","columnOrderBy","filter","ob","rawExpressionOrderBy","resultQueryAlias","getAlias","aliasedTableName","mustUseAlias","resultQuery","getConnection","baseQuery","clone","baseQueryAlias","clear","select","prefix","map","orderByClause","partitionedQueryAlias","selectRowsAsNumberedPartitions","partitionedQuery","prefixedOrderBy","orderByColumns","prop","rowNumber","subQuery","partitionBy","from","as","stringSelect","s","originalSelect","difference","col","innerJoin","on","andOnVal","limit","offset","first","curry"],"mappings":"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"}