@@ -1338,20 +1338,89 @@ 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 ) ) {
1354+ if ( fieldsArg . value . items . length > 1 ) {
1355+ const fieldNames = fieldsArg . value . items . map ( ( item : any ) => {
1356+ let fieldName : string | undefined = undefined ;
1357+ if ( typeof item . field === 'string' && modelDef . fields [ item . field ] ) {
1358+ fieldName = item . field ;
1359+ } else if (
1360+ typeof item . value === 'object' &&
1361+ typeof item . value . name === 'string' &&
1362+ modelDef . fields [ item . value . name ]
1363+ ) {
1364+ fieldName = item . value . name ;
1365+ }
1366+ if ( ! fieldName ) {
1367+ throw new Error (
1368+ `Invalid unique field mapping in model ${ model } : ${ JSON . stringify ( item ) } ` ,
1369+ ) ;
1370+ }
1371+ return fieldName ;
1372+ } ) ;
1373+ return fieldNames . map ( ( fieldName : string ) => this . requireField ( model , fieldName ) ) ;
1374+ }
1375+ }
1376+ }
1377+ }
1378+
1379+ // 2. uniqueFields by key name
1380+ const uniqueFieldEntry = Object . entries ( modelDef . uniqueFields ) . find ( ( [ name ] ) => name === externalIdName ) ;
1381+ if ( uniqueFieldEntry ) {
1382+ const [ name , info ] = uniqueFieldEntry ;
1383+ if ( typeof info . type === 'string' ) {
1384+ return [ this . requireField ( model , name ) ] ;
1385+ } else {
1386+ const fieldNames = Object . keys ( info ) . filter ( ( f ) => {
1387+ if ( ! ( f in modelDef . fields ) ) return false ;
1388+ const fieldInfo = ( info as Record < string , any > ) [ f ] ;
1389+ return typeof fieldInfo === 'object' && fieldInfo !== null && typeof fieldInfo . type === 'string' ;
1390+ } ) ;
1391+ if ( fieldNames . length === 0 ) {
1392+ throw new Error (
1393+ `No valid field names found for compound unique key ${ externalIdName } in model ${ model } ` ,
1394+ ) ;
13511395 }
1396+ return fieldNames . map ( ( f ) => this . requireField ( model , f ) ) ;
13521397 }
13531398 }
13541399
1400+ // 3. Field-level unique attribute (with or without map)
1401+ const field = Object . values ( modelDef . fields ) . find ( ( fieldDef ) => {
1402+ if ( ! Array . isArray ( fieldDef . attributes ) ) return false ;
1403+ // @unique (map: ...)
1404+ const hasMappedUnique = fieldDef . attributes . some (
1405+ ( attr : any ) =>
1406+ attr . name === '@unique' &&
1407+ Array . isArray ( attr . args ) &&
1408+ attr . args . some ( ( a : any ) => a . name === 'map' && a . value ?. value === externalIdName ) ,
1409+ ) ;
1410+ if ( hasMappedUnique ) return true ;
1411+ // @unique (no map), field name matches
1412+ const hasSimpleUnique = fieldDef . attributes . some (
1413+ ( attr : any ) =>
1414+ attr . name === '@unique' &&
1415+ ( ! Array . isArray ( attr . args ) || ! attr . args . some ( ( a : any ) => a . name === 'map' ) ) &&
1416+ fieldDef . name === externalIdName ,
1417+ ) ;
1418+ return hasSimpleUnique ;
1419+ } ) ;
1420+ if ( field ) {
1421+ return [ field ] ;
1422+ }
1423+
13551424 throw new Error ( `Model ${ model } does not have unique key ${ externalIdName } ` ) ;
13561425 }
13571426
@@ -2060,9 +2129,7 @@ export class RestApiHandler<Schema extends SchemaDef = SchemaDef> implements Api
20602129 }
20612130 } else {
20622131 if ( op === 'between' ) {
2063- const parts = value
2064- . split ( ',' )
2065- . map ( ( v ) => this . coerce ( fieldDef , v ) ) ;
2132+ const parts = value . split ( ',' ) . map ( ( v ) => this . coerce ( fieldDef , v ) ) ;
20662133 if ( parts . length !== 2 ) {
20672134 throw new InvalidValueError ( `"between" expects exactly 2 comma-separated values` ) ;
20682135 }
0 commit comments