@@ -1338,20 +1338,85 @@ export class RestApiHandler<Schema extends SchemaDef = SchemaDef> implements Api
13381338 return Object . values ( modelDef . fields ) . filter ( ( f ) => modelDef . idFields . includes ( f . name ) ) ;
13391339 }
13401340
1341- // map external ID name to unique constraint field
13421341 const externalIdName = this . externalIdMapping [ modelLower ] ;
1343- for ( const [ name , info ] of Object . entries ( modelDef . uniqueFields ) ) {
1344- if ( name === externalIdName ) {
1345- if ( typeof info . type === 'string' ) {
1346- // single unique field
1347- return [ this . requireField ( model , info . type ) ] ;
1348- } else {
1349- // compound unique fields
1350- return Object . keys ( info ) . map ( ( f ) => this . requireField ( model , f ) ) ;
1342+
1343+ // 1. Model-level @@unique(map: ...) (compound keys only)
1344+ if ( Array . isArray ( modelDef . attributes ) ) {
1345+ const uniqueAttr = modelDef . attributes . find (
1346+ ( attr : any ) =>
1347+ attr . name === '@@unique' &&
1348+ Array . isArray ( attr . args ) &&
1349+ attr . args . some ( ( a : any ) => a . name === 'map' && a . value ?. value === externalIdName ) ,
1350+ ) ;
1351+ if ( uniqueAttr ) {
1352+ const fieldsArg = uniqueAttr . args . find ( ( a : any ) => a . name === 'fields' ) ;
1353+ if ( fieldsArg && Array . isArray ( fieldsArg . value ?. items ) && fieldsArg . value . items . length >= 1 ) {
1354+ const fieldNames = fieldsArg . value . items . map ( ( item : any ) => {
1355+ let fieldName : string | undefined = undefined ;
1356+ if ( typeof item . field === 'string' && modelDef . fields [ item . field ] ) {
1357+ fieldName = item . field ;
1358+ } else if (
1359+ typeof item . value === 'object' &&
1360+ typeof item . value . name === 'string' &&
1361+ modelDef . fields [ item . value . name ]
1362+ ) {
1363+ fieldName = item . value . name ;
1364+ }
1365+ if ( ! fieldName ) {
1366+ throw new Error ( `Invalid unique field mapping in model ${ model } : ${ JSON . stringify ( item ) } ` ) ;
1367+ }
1368+ return fieldName ;
1369+ } ) ;
1370+ return fieldNames . map ( ( fieldName : string ) => this . requireField ( model , fieldName ) ) ;
13511371 }
13521372 }
13531373 }
13541374
1375+ // 2. uniqueFields by key name
1376+ const uniqueFieldEntry = Object . entries ( modelDef . uniqueFields ) . find ( ( [ name ] ) => name === externalIdName ) ;
1377+ if ( uniqueFieldEntry ) {
1378+ const [ name , info ] = uniqueFieldEntry ;
1379+ if ( typeof info . type === 'string' ) {
1380+ return [ this . requireField ( model , name ) ] ;
1381+ }
1382+ const fieldNames = Object . keys ( info ) . filter ( ( f ) => {
1383+ if ( ! ( f in modelDef . fields ) ) return false ;
1384+ const fieldInfo = ( info as Record < string , any > ) [ f ] ;
1385+ return typeof fieldInfo === 'object' && fieldInfo !== null && typeof fieldInfo . type === 'string' ;
1386+ } ) ;
1387+ if ( fieldNames . length === 0 ) {
1388+ throw new Error (
1389+ `No valid field names found for compound unique key ${ externalIdName } in model ${ model } ` ,
1390+ ) ;
1391+ }
1392+ return fieldNames . map ( ( f ) => this . requireField ( model , f ) ) ;
1393+ }
1394+
1395+ // 3. Field-level unique attribute (with or without map)
1396+ const field = Object . values ( modelDef . fields ) . find ( ( fieldDef ) => {
1397+ if ( ! Array . isArray ( fieldDef . attributes ) ) return false ;
1398+ // @unique (map: ...)
1399+ const hasMappedUnique = fieldDef . attributes . some (
1400+ ( attr : any ) =>
1401+ attr . name === '@unique' &&
1402+ Array . isArray ( attr . args ) &&
1403+ attr . args . some ( ( a : any ) => a . name === 'map' && a . value ?. value === externalIdName ) ,
1404+ ) ;
1405+ if ( hasMappedUnique ) return true ;
1406+ // @unique (no map), field name matches
1407+ const hasSimpleUnique = fieldDef . attributes . some (
1408+ ( attr : any ) =>
1409+ attr . name === '@unique' &&
1410+ ( ! Array . isArray ( attr . args ) || ! attr . args . some ( ( a : any ) => a . name === 'map' ) ) &&
1411+ fieldDef . name === externalIdName ,
1412+ ) ;
1413+ return hasSimpleUnique ;
1414+ } ) ;
1415+
1416+ if ( field ) {
1417+ return [ field ] ;
1418+ }
1419+
13551420 throw new Error ( `Model ${ model } does not have unique key ${ externalIdName } ` ) ;
13561421 }
13571422
@@ -2060,9 +2125,7 @@ export class RestApiHandler<Schema extends SchemaDef = SchemaDef> implements Api
20602125 }
20612126 } else {
20622127 if ( op === 'between' ) {
2063- const parts = value
2064- . split ( ',' )
2065- . map ( ( v ) => this . coerce ( fieldDef , v ) ) ;
2128+ const parts = value . split ( ',' ) . map ( ( v ) => this . coerce ( fieldDef , v ) ) ;
20662129 if ( parts . length !== 2 ) {
20672130 throw new InvalidValueError ( `"between" expects exactly 2 comma-separated values` ) ;
20682131 }
0 commit comments