@@ -272,6 +272,13 @@ const getResourceDataRequestSchema: AnySchemaObject = {
272272 } ,
273273 sort : commonSortSchema ,
274274 filters : commonFiltersSchema ,
275+ columns : {
276+ type : 'array' ,
277+ description : 'Optional list of resource column names to include in returned rows. For list requests, computed row helper fields such as _label and _clickUrl are still returned when available.' ,
278+ minItems : 1 ,
279+ uniqueItems : true ,
280+ items : { type : 'string' } ,
281+ } ,
275282 } ,
276283 additionalProperties : true ,
277284 allOf : [
@@ -1296,6 +1303,42 @@ export default class AdminForthRestAPI implements IAdminForthRestAPI {
12961303 }
12971304 }
12981305 const { limit, offset, filters, sort } = body ;
1306+ const selectedColumnNames = body . columns
1307+ ? [ ...new Set ( body . columns as string [ ] ) ]
1308+ : undefined ;
1309+
1310+ if ( selectedColumnNames ) {
1311+ const resourceColumnNames = new Set ( resource . columns . map ( ( col ) => col . name ) ) ;
1312+ const invalidColumnName = selectedColumnNames . find ( ( columnName ) => ! resourceColumnNames . has ( columnName ) ) ;
1313+
1314+ if ( invalidColumnName ) {
1315+ return { error : `Column ${ invalidColumnName } not found in resource ${ resourceId } ` } ;
1316+ }
1317+ }
1318+ const selectedColumnNameSet = selectedColumnNames ? new Set ( selectedColumnNames ) : undefined ;
1319+ const shouldAddListHelpers = source === 'list' ;
1320+ const selectedDataSourceColumnNameSet = selectedColumnNames
1321+ ? new Set ( selectedColumnNames . filter ( ( columnName ) => resource . dataSourceColumns . some ( ( col ) => col . name === columnName ) ) )
1322+ : undefined ;
1323+
1324+ if ( selectedDataSourceColumnNameSet ) {
1325+ for ( const col of resource . columns ) {
1326+ if (
1327+ selectedColumnNameSet . has ( col . name ) &&
1328+ col . foreignResource ?. polymorphicOn
1329+ ) {
1330+ selectedDataSourceColumnNameSet . add ( col . foreignResource . polymorphicOn ) ;
1331+ }
1332+ }
1333+ }
1334+
1335+ const selectedDataSourceColumns = selectedDataSourceColumnNameSet && ! shouldAddListHelpers
1336+ ? (
1337+ resource . dataSourceColumns . some ( ( col ) => selectedDataSourceColumnNameSet . has ( col . name ) )
1338+ ? resource . dataSourceColumns . filter ( ( col ) => selectedDataSourceColumnNameSet . has ( col . name ) )
1339+ : resource . dataSourceColumns . filter ( ( col ) => col . primaryKey || col . name === resource . dataSourceColumns [ 0 ] ?. name )
1340+ )
1341+ : undefined ;
12991342
13001343 // remove virtual fields from sort if still presented after beforeDatasourceRequest hook
13011344 const sortFiltered = sort . filter ( ( sortItem : IAdminForthSort ) => {
@@ -1334,11 +1377,14 @@ export default class AdminForthRestAPI implements IAdminForthRestAPI {
13341377 filters : normalizedFilters as IAdminForthAndOrFilter ,
13351378 sort : sortFiltered ,
13361379 getTotals : source === 'list' ,
1380+ columns : selectedDataSourceColumns ,
13371381 } ) ;
13381382
13391383 // for foreign keys, add references
13401384 await Promise . all (
1341- resource . columns . filter ( ( col ) => col . foreignResource ) . map ( async ( col ) => {
1385+ resource . columns . filter ( ( col ) => (
1386+ col . foreignResource && ( ! selectedColumnNameSet || shouldAddListHelpers || selectedColumnNameSet . has ( col . name ) )
1387+ ) ) . map ( async ( col ) => {
13421388 let targetDataMap = { } ;
13431389
13441390 if ( col . foreignResource . resourceId ) {
@@ -1448,7 +1494,6 @@ export default class AdminForthRestAPI implements IAdminForthRestAPI {
14481494 } )
14491495 ) ;
14501496
1451- const pkField = resource . columns . find ( ( col ) => col . primaryKey ) ?. name ;
14521497 // remove all columns which are not defined in resources, or defined but backendOnly
14531498 {
14541499 const ctx = {
@@ -1471,10 +1516,12 @@ export default class AdminForthRestAPI implements IAdminForthRestAPI {
14711516 delete item [ key ] ;
14721517 }
14731518 }
1474- item . _label = resource . recordLabel ( item ) ;
1519+ if ( ! selectedColumnNameSet || shouldAddListHelpers ) {
1520+ item . _label = resource . recordLabel ( item ) ;
1521+ }
14751522 }
14761523 }
1477- if ( source === 'list' && resource . options . listTableClickUrl ) {
1524+ if ( shouldAddListHelpers && resource . options . listTableClickUrl ) {
14781525 await Promise . all (
14791526 data . data . map ( async ( item ) => {
14801527 item . _clickUrl = await resource . options . listTableClickUrl ( item , adminUser , resource ) ;
@@ -1501,6 +1548,16 @@ export default class AdminForthRestAPI implements IAdminForthRestAPI {
15011548 }
15021549 }
15031550
1551+ if ( selectedColumnNameSet ) {
1552+ for ( const item of data . data ) {
1553+ for ( const key of Object . keys ( item ) ) {
1554+ if ( ! selectedColumnNameSet . has ( key ) && key !== '_label' && key !== '_clickUrl' ) {
1555+ delete item [ key ] ;
1556+ }
1557+ }
1558+ }
1559+ }
1560+
15041561 return data ;
15051562 } ,
15061563 } ) ;
0 commit comments