     1	/**
     2	 * Builds the SELECT clause for a Knex query, handling field selection and table prefixing
     3	 *
     4	 * @param {Object} query - The Knex query builder instance
     5	 * @param {string} tableName - The table name
     6	 * @param {Array<string>|string} fieldsToSelect - Fields to select or '*'
     7	 * @param {boolean} useTablePrefix - Whether to prefix fields with table name
     8	 * @returns {Object} The modified query builder
     9	 *
    10	 * @example
    11	 * // Input: Basic query without specific fields
    12	 * const query = knex('articles');
    13	 * buildQuerySelection(query, 'articles', '*', false);
    14	 *
    15	 * // Effect on query: No modification, Knex defaults to SELECT *
    16	 * // SQL generated: SELECT * FROM articles
    17	 *
    18	 * @example
    19	 * // Input: Query with sparse fieldset
    20	 * const query = knex('articles');
    21	 * const fields = ['id', 'title', 'author_id'];
    22	 * buildQuerySelection(query, 'articles', fields, false);
    23	 *
    24	 * // Effect on query: Adds select() with specific fields
    25	 * // SQL generated: SELECT id, title, author_id FROM articles
    26	 * // Response will only include these 3 fields, reducing payload size
    27	 *
    28	 * @example
    29	 * // Input: Query with joins needing table prefixes
    30	 * const query = knex('articles')
    31	 *   .join('users', 'articles.author_id', 'users.id');
    32	 * const fields = ['id', 'title', 'created_at as published'];
    33	 * buildQuerySelection(query, 'articles', fields, true);
    34	 *
    35	 * // Effect on query: Prefixes all fields with table name
    36	 * // SQL generated: SELECT articles.id, articles.title, articles.created_at as published
    37	 * // Prevents "column 'id' is ambiguous" errors since both tables have id
    38	 *
    39	 * @description
    40	 * Used by:
    41	 * - knex-query-helpers.js calls this when building queries with sparse fieldsets
    42	 * - rest-api-knex-plugin uses this in dataQuery to optimize SELECT clauses
    43	 * - Called whenever fields parameter limits which attributes to return
    44	 *
    45	 * Purpose:
    46	 * - Implements JSON:API sparse fieldsets by selecting only requested fields
    47	 * - Prevents ambiguous column errors in queries with joins
    48	 * - Reduces database transfer by not selecting unnecessary columns
    49	 * - Handles field aliases (e.g., "created_at as published")
    50	 *
    51	 * Data flow:
    52	 * 1. Query parser extracts fields parameter (e.g., fields[articles]=title,author)
    53	 * 2. This function adds appropriate SELECT clause to query
    54	 * 3. Database returns only selected columns
    55	 * 4. Smaller result sets improve query performance
    56	 * 5. JSON:API response includes only requested attributes
    57	 */
    58	export const buildQuerySelection = (
    59	  query,
    60	  tableName,
    61	  fieldsToSelect,
    62	  useTablePrefix = false,
    63	  options = {}
    64	) => {
    65	  const translateColumn = options.translateColumn
    66	
    67	  const applyTranslation = (field, aliasForField) => {
    68	    if (translateColumn) {
    69	      const translated = translateColumn(field, aliasForField)
    70	      if (translated) {
    71	        return translated
    72	      }
    73	    }
    74	
    75	    if (aliasForField) {
    76	      return `${aliasForField}.${field}`
    77	    }
    78	    return field
    79	  }
    80	
    81	  const targetAlias = useTablePrefix ? tableName : null
    82	
    83	  if (fieldsToSelect === '*') {
    84	    const translated = translateColumn ? translateColumn('*', targetAlias) : null
    85	    if (translated) {
    86	      return query.select(translated)
    87	    }
    88	    return useTablePrefix ? query.select(`${tableName}.*`) : query
    89	  }
    90	
    91	  const fieldsArray = Array.isArray(fieldsToSelect)
    92	    ? fieldsToSelect
    93	    : Array.from(fieldsToSelect || [])
    94	
    95	  const translatedFields = fieldsArray.map((field) => {
    96	    if (typeof field !== 'string') return field
    97	
    98	    const aliasMatch = field.match(/\s+as\s+/i)
    99	    if (aliasMatch) {
   100	      const [source, alias] = field.split(/\s+as\s+/i)
   101	      const translatedSource = applyTranslation(source.trim(), targetAlias)
   102	      return `${translatedSource} as ${alias.trim()}`
   103	    }
   104	
   105	    return applyTranslation(field.trim(), targetAlias)
   106	  })
   107	
   108	  return query.select(translatedFields)
   109	}
