11import dayjs from 'dayjs' ;
22import { MongoClient } from 'mongodb' ;
3- import { Decimal128 } from 'bson' ;
3+ import { Decimal128 , Double } from 'bson' ;
44import { IAdminForthDataSourceConnector , IAdminForthSingleFilter , IAdminForthAndOrFilter , AdminForthResource } from '../types/Back.js' ;
55import AdminForthBaseConnector from './baseConnector.js' ;
66
@@ -9,6 +9,24 @@ import { AdminForthDataTypes, AdminForthFilterOperators, AdminForthSortDirection
99const escapeRegex = ( value ) => {
1010 return value . replace ( / [ . * + ? ^ $ { } ( ) | [ \] \\ ] / g, '\\$&' ) ; // Escapes special characters
1111} ;
12+ function normalizeMongoValue ( v : any ) {
13+ if ( v == null ) {
14+ return v ;
15+ }
16+ if ( v instanceof Decimal128 ) {
17+ return v . toString ( ) ;
18+ }
19+ if ( v instanceof Double ) {
20+ return v . valueOf ( ) ;
21+ }
22+ if ( typeof v === "object" && v . $numberDecimal ) {
23+ return String ( v . $numberDecimal ) ;
24+ }
25+ if ( typeof v === "object" && v . $numberDouble ) {
26+ return Number ( v . $numberDouble ) ;
27+ }
28+ return v ;
29+ }
1230
1331class MongoConnector extends AdminForthBaseConnector implements IAdminForthDataSourceConnector {
1432
@@ -122,30 +140,30 @@ class MongoConnector extends AdminForthBaseConnector implements IAdminForthDataS
122140 }
123141
124142 return Array . from ( fieldTypes . entries ( ) ) . map ( ( [ name , types ] ) => {
125- const primaryKey = name === '_id' ;
126-
127- const priority = [ 'datetime' , 'date' , 'integer' , 'float' , 'boolean' , 'json' , 'decimal' , 'string' ] ;
128-
129- const matched = priority . find ( t => types . has ( t ) ) || 'string' ;
130-
131- const typeMap : Record < string , string > = {
132- string : ' STRING' ,
133- integer : ' INTEGER' ,
134- float : ' FLOAT' ,
135- boolean : ' BOOLEAN' ,
136- datetime : ' DATETIME' ,
137- date : ' DATE' ,
138- json : ' JSON' ,
139- decimal : ' DECIMAL' ,
140- } ;
141- return {
142- name,
143- type : typeMap [ matched ] ?? ' STRING' ,
144- ...( primaryKey ? { isPrimaryKey : true } : { } ) ,
145- sampleValue : sampleValues . get ( name ) ,
146- } ;
143+ const primaryKey = name === '_id' ;
144+
145+ const priority = [ 'datetime' , 'date' , 'decimal' , ' integer', 'float' , 'boolean' , 'json' , 'string' ] ;
146+
147+ const matched = priority . find ( t => types . has ( t ) ) || 'string' ;
148+
149+ const typeMap : Record < string , AdminForthDataTypes > = {
150+ string : AdminForthDataTypes . STRING ,
151+ integer : AdminForthDataTypes . INTEGER ,
152+ float : AdminForthDataTypes . FLOAT ,
153+ boolean : AdminForthDataTypes . BOOLEAN ,
154+ datetime : AdminForthDataTypes . DATETIME ,
155+ date : AdminForthDataTypes . DATE ,
156+ json : AdminForthDataTypes . JSON ,
157+ decimal : AdminForthDataTypes . DECIMAL ,
158+ } ;
159+ return {
160+ name,
161+ type : typeMap [ matched ] ?? AdminForthDataTypes . STRING ,
162+ ...( primaryKey ? { isPrimaryKey : true } : { } ) ,
163+ sampleValue : sampleValues . get ( name ) ,
164+ } ;
147165 } ) ;
148- }
166+ }
149167
150168
151169 async discoverFields ( resource ) {
@@ -200,20 +218,37 @@ class MongoConnector extends AdminForthBaseConnector implements IAdminForthDataS
200218
201219
202220 setFieldValue ( field , value ) {
203- if ( field . type == AdminForthDataTypes . DATETIME ) {
204- if ( ! value ) {
205- return null ;
206- }
207- return dayjs ( value ) . toDate ( ) ;
208-
209- } else if ( field . type == AdminForthDataTypes . BOOLEAN ) {
210- return value === null ? null : ( value ? true : false ) ;
211- } else if ( field . type == AdminForthDataTypes . DECIMAL ) {
212- if ( value === null || value === undefined ) {
221+ if ( value === undefined ) return undefined ;
222+ if ( value === null ) return null ;
223+
224+ if ( field . type === AdminForthDataTypes . DATETIME ) {
225+ if ( value === "" || value === null ) {
213226 return null ;
214227 }
215- return Decimal128 . fromString ( value ?. toString ( ) ) ;
228+ return dayjs ( value ) . isValid ( ) ? dayjs ( value ) . toDate ( ) : null ;
216229 }
230+
231+ if ( field . type === AdminForthDataTypes . INTEGER ) {
232+ if ( value === "" || value === null ) {
233+ return null ;
234+ }
235+ return Number . isFinite ( value ) ? Math . trunc ( value ) : null ;
236+ }
237+
238+ if ( field . type === AdminForthDataTypes . FLOAT ) {
239+ if ( value === "" || value === null ) {
240+ return null ;
241+ }
242+ return Number . isFinite ( value ) ? value : null ;
243+ }
244+
245+ if ( field . type === AdminForthDataTypes . DECIMAL ) {
246+ if ( value === "" || value === null ) {
247+ return null ;
248+ }
249+ return value . toString ( ) ;
250+ }
251+
217252 return value ;
218253 }
219254
@@ -251,7 +286,7 @@ class MongoConnector extends AdminForthBaseConnector implements IAdminForthDataS
251286 return { $expr : { [ mongoExprOp ] : [ left , right ] } } ;
252287 }
253288 const column = resource . dataSourceColumns . find ( ( col ) => col . name === ( filter as IAdminForthSingleFilter ) . field ) ;
254- if ( [ 'integer' , 'decimal' , 'float' ] . includes ( column . type ) ) {
289+ if ( [ AdminForthDataTypes . INTEGER , AdminForthDataTypes . DECIMAL , AdminForthDataTypes . FLOAT ] . includes ( column . type ) ) {
255290 return { [ ( filter as IAdminForthSingleFilter ) . field ] : this . OperatorsMap [ filter . operator ] ( + ( filter as IAdminForthSingleFilter ) . value ) } ;
256291 }
257292 return { [ ( filter as IAdminForthSingleFilter ) . field ] : this . OperatorsMap [ filter . operator ] ( ( filter as IAdminForthSingleFilter ) . value ) } ;
@@ -313,13 +348,20 @@ class MongoConnector extends AdminForthBaseConnector implements IAdminForthDataS
313348 async getMinMaxForColumnsWithOriginalTypes ( { resource, columns } ) {
314349 const tableName = resource . table ;
315350 const collection = this . client . db ( ) . collection ( tableName ) ;
316- const result = { } ;
351+ const result : Record < string , { min : any ; max : any } > = { } ;
352+
317353 for ( const column of columns ) {
318- result [ column ] = await collection
319- . aggregate ( [
320- { $group : { _id : null , min : { $min : `$${ column } ` } , max : { $max : `$${ column } ` } } } ,
321- ] )
322- . toArray ( ) ;
354+ const [ doc ] = await collection
355+ . aggregate ( [
356+ { $group : { _id : null , min : { $min : `$${ column . name } ` } , max : { $max : `$${ column . name } ` } } } ,
357+ { $project : { _id : 0 , min : 1 , max : 1 } } ,
358+ ] )
359+ . toArray ( ) ;
360+
361+ result [ column . name ] = {
362+ min : normalizeMongoValue ( doc ?. min ) ,
363+ max : normalizeMongoValue ( doc ?. max ) ,
364+ } ;
323365 }
324366 return result ;
325367 }
0 commit comments