2023-01-22 10:53:09 +01:00
/ *
2023-04-13 07:46:35 +02:00
This module have to be use in back as well front
2023-01-22 10:53:09 +01:00
can be include in project with
2023-04-13 07:46:35 +02:00
- into a browser : < script src = "https://townName.nationName.dns/nationchains/contracts/Checkjson.js" > < / s c r i p t >
- into a node . js : const Checkjson = require ( ` ../nationchains/socialworld/contracts/Checkjson.js ` ) ;
2023-01-22 10:53:09 +01:00
* /
// --##
2023-04-13 07:46:35 +02:00
const Checkjson = { } ;
Checkjson . schema = { } ;
Checkjson . schema . properties = { } ;
Checkjson . schema . properties . type = { } ;
Checkjson . schema . properties . type . string = ( str ) => typeof str === "string" ;
Checkjson . schema . properties . type . number = ( n ) => typeof n === "number" ;
Checkjson . schema . properties . type . boolean = ( n ) => typeof n === "boolean" ;
Checkjson . schema . properties . type . integer = ( n ) =>
2023-03-27 07:52:21 +02:00
n != "" && ! isNaN ( n ) && Math . round ( n ) == n ;
2023-04-13 07:46:35 +02:00
Checkjson . schema . properties . type . float = ( n ) =>
2023-03-27 07:52:21 +02:00
n != "" && ! isNaN ( n ) && Math . round ( n ) != n ; //not yet in json schema
2023-04-13 07:46:35 +02:00
Checkjson . schema . properties . minLength = ( str , min ) =>
2023-03-27 07:52:21 +02:00
typeof str === "string" && str . length > parseInt ( min ) ;
2023-04-13 07:46:35 +02:00
Checkjson . schema . properties . maxLength = ( str , max ) =>
2023-03-27 07:52:21 +02:00
typeof str === "string" && str . length < parseInt ( max ) ;
2023-04-13 07:46:35 +02:00
Checkjson . schema . properties . multipleOf = ( n , val ) =>
2023-03-27 07:52:21 +02:00
typeof n === "number" &&
typeof val === "number" &&
parseFloat ( n ) / parseFloat ( val ) -
Math . round ( parseFloat ( n ) / parseFloat ( val ) ) <
0.0000001 ;
2023-04-13 07:46:35 +02:00
Checkjson . schema . properties . range = (
2023-03-27 07:52:21 +02:00
n ,
minimum ,
exclusiveMinimum ,
maximum ,
exclusiveMaximum
) => {
//console.log(minimum,exclusiveMinimum,maximum, exclusiveMaximum,n)
if ( typeof n !== "number" ) return false ;
if ( minimum && parseFloat ( n ) < parseFloat ( minimum ) ) return false ;
if ( exclusiveMinimum && parseFloat ( n ) <= parseFloat ( exclusiveMinimum ) )
return false ;
if ( maximum && parseFloat ( n ) > parseFloat ( maximum ) ) return false ;
if ( exclusiveMaximum && parseFloat ( n ) >= parseFloat ( exclusiveMaximum ) )
return false ;
return true ;
2023-01-22 10:53:09 +01:00
} ;
2023-04-13 07:46:35 +02:00
Checkjson . schema . properties . pattern = ( str , pattern ) => {
2023-03-27 07:52:21 +02:00
try {
new RegExp ( pattern ) ;
} catch ( e ) {
return false ;
}
return pattern . test ( str ) ;
2023-01-22 10:53:09 +01:00
} ;
2023-04-13 07:46:35 +02:00
Checkjson . schema . properties . enum = ( str , enumvalues ) =>
2023-03-27 07:52:21 +02:00
typeof str === "string" && enumvalues . includes ( str ) ;
// see format https://json-schema.org/understanding-json-schema/reference/string.html#format
2023-04-13 07:46:35 +02:00
Checkjson . schema . properties . format = {
2023-03-27 07:52:21 +02:00
"date-time" : / / ,
2023-04-13 07:46:35 +02:00
stringalphaonly : /^[A-Za-z0-9]{3,}$/ ,
2023-03-27 07:52:21 +02:00
time : / / ,
date : / / ,
duration : / / ,
email :
/^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/ ,
"idn-email" : / / ,
uuid : /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/ ,
uri : / / ,
"uri-reference" : / / ,
iri : / / ,
hostname : / / ,
"idn-hostname" : / / ,
ipv4 : /^([0– 9]{1,3}.){3}.([0– 9]{1,3})$/ ,
ipv6 : /^((([0– 9A-Fa-f]{1,4}:){7}[0– 9A-Fa-f]{1,4})|(([0– 9A-Fa-f]{1,4}:){6}:[0– 9A-Fa-f]{1,4})|(([0– 9A-Fa-f]{1,4}:){5}:([0– 9A-Fa-f]{1,4}:)?[0– 9A-Fa-f]{1,4})|(([0– 9A-Fa-f]{1,4}:){4}:([0– 9A-Fa-f]{1,4}:){0,2}[0– 9A-Fa-f]{1,4})|(([0– 9A-Fa-f]{1,4}:){3}:([0– 9A-Fa-f]{1,4}:){0,3}[0– 9A-Fa-f]{1,4})|(([0– 9A-Fa-f]{1,4}:){2}:([0– 9A-Fa-f]{1,4}:){0,4}[0– 9A-Fa-f]{1,4})|(([0– 9A-Fa-f]{1,4}:){6}((b((25[0– 5])|(1d{2})|(2[0– 4]d)|(d{1,2}))b).){3}(b((25[0– 5])|(1d{2})|(2[0– 4]d)|(d{1,2}))b))|(([0– 9A-Fa-f]{1,4}:){0,5}:((b((25[0– 5])|(1d{2})|(2[0– 4]d)|(d{1,2}))b).){3}(b((25[0– 5])|(1d{2})|(2[0– 4]d)|(d{1,2}))b))|(::([0– 9A-Fa-f]{1,4}:){0,5}((b((25[0– 5])|(1d{2})|(2[0– 4]d)|(d{1,2}))b).){3}(b((25[0– 5])|(1d{2})|(2[0– 4]d)|(d{1,2}))b))|([0– 9A-Fa-f]{1,4}::([0– 9A-Fa-f]{1,4}:){0,5}[0– 9A-Fa-f]{1,4})|(::([0– 9A-Fa-f]{1,4}:){0,6}[0– 9A-Fa-f]{1,4})|(([0– 9A-Fa-f]{1,4}:){1,7}:))$/ ,
telephonefr : /^0[1-9][0-9]{9}$/ ,
telephoneinter : /^\+*(\d{3})*[0-9,\-]{8,}/ ,
password :
/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[$@$!%*?&.])[A-Za-z\d$@$!%*?&.{}:|\s]{8,}/ ,
postalcodefr : /(^\d{5}$)|(^\d{5}-\d{4}$)/ ,
2023-01-22 10:53:09 +01:00
} ;
2023-04-13 07:46:35 +02:00
Checkjson . schema . properties . default
Checkjson . schema . validation = ( schema ) => {
2023-03-27 07:52:21 +02:00
/*validate a schema structure*/
const res = { status : 200 , err : [ ] } ;
if ( schema . properties ) {
Object . keys ( schema . properties ) . forEach ( ( p ) => {
const properties = schema . properties ;
if (
properties [ p ] . type &&
typeof properties [ p ] . type === "string" &&
2023-04-13 07:46:35 +02:00
! Checkjson . schema . properties . type [ properties [ p ] . type ]
2023-03-27 07:52:21 +02:00
) {
res . err . push ( {
2023-04-13 07:46:35 +02:00
info : "|Checkjson|typedoesnotexistinschema" ,
2023-03-27 07:52:21 +02:00
moreinfo : ` ${ properties [ p ] . type } ` ,
} ) ;
}
if (
properties [ p ] . type &&
typeof properties [ p ] . type === "object" &&
Array . isArray ( properties [ p ] . type )
) {
properties [ p ] . type . forEach ( ( tp ) => {
2023-04-13 07:46:35 +02:00
if ( ! Checkjson . schema . properties . type [ tp ] )
2023-03-27 07:52:21 +02:00
res . err . push ( {
2023-04-13 07:46:35 +02:00
info : "|Checkjson|typedoesnotexistinschema" ,
2023-03-27 07:52:21 +02:00
moreinfo : ` ${ tp } of ${ properties [ p ] . type } ` ,
} ) ;
} ) ;
}
if (
properties [ p ] . format &&
2023-04-13 07:46:35 +02:00
! Checkjson . schema . properties . format [ properties [ p ] . format ]
2023-03-27 07:52:21 +02:00
) {
res . err . push ( {
2023-04-13 07:46:35 +02:00
info : "|Checkjson|formatdoesnotexistinschema" ,
2023-03-27 07:52:21 +02:00
moreinfo : ` ${ properties [ p ] . format } ` ,
} ) ;
}
if ( properties [ p ] . enum && ! Array . isArray ( properties [ p ] . enum ) ) {
res . err . push ( {
2023-04-13 07:46:35 +02:00
info : "|Checkjson|enumisnotarrayinschema" ,
2023-03-27 07:52:21 +02:00
moreinfo : ` ${ properties [ p ] . enum } ` ,
} ) ;
}
} ) ;
}
// 406 means not acceptable
if ( res . err . length > 0 ) res . status = 406 ;
return res ;
2023-01-22 10:53:09 +01:00
} ;
2023-04-13 07:46:35 +02:00
Checkjson . schema . data = ( schema , data , withschemacheck ) => {
2023-03-27 07:52:21 +02:00
/* validate a data set with a schema in a context ctx */
/ *
console . log ( '#################' )
console . log ( schema ) ;
console . log ( '---------' )
console . log ( data )
* /
2023-04-13 07:46:35 +02:00
if ( withschemacheck ) {
const validschema = Checkjson . schema . validation ( schema ) ;
if ( validschema . status != 200 ) return validschema ;
}
2023-03-27 07:52:21 +02:00
const res = { status : 200 , err : [ ] } ;
if ( schema . properties ) {
const properties = schema . properties ;
Object . keys ( properties ) . forEach ( ( p ) => {
//type is mandatory in a propertie
if ( data [ p ] ) {
const typlist =
properties [ p ] . type && typeof properties [ p ] . type === "string"
? [ properties [ p ] . type ]
: properties [ p ] . type ;
let valid = false ;
typlist . forEach ( ( typ ) => {
// at least one test have to be ok
2023-04-13 07:46:35 +02:00
if ( Checkjson . schema . properties . type [ typ ] ( data [ p ] ) ) valid = true ;
2023-03-27 07:52:21 +02:00
} ) ;
if ( ! valid )
res . err . push ( {
2023-04-13 07:46:35 +02:00
info : "|Checkjson|dataerrpropertie" ,
2023-03-27 07:52:21 +02:00
moreinfo : ` ${ p } : ${ data [ p ] } ` ,
} ) ;
if (
properties [ p ] . minLength &&
2023-04-13 07:46:35 +02:00
! Checkjson . schema . properties . minLength ( data [ p ] , properties [ p ] . minLength )
2023-03-27 07:52:21 +02:00
) {
res . err . push ( {
2023-04-13 07:46:35 +02:00
info : "|Checkjson|dataerrpropertie" ,
2023-03-27 07:52:21 +02:00
moreinfo : ` ${ p } : ${ data [ p ] } minLength: ${ properties [ p ] . minLength } ` ,
} ) ;
}
if (
properties [ p ] . maxLength &&
2023-04-13 07:46:35 +02:00
! Checkjson . schema . properties . maxLength ( data [ p ] , properties [ p ] . maxLength )
2023-03-27 07:52:21 +02:00
) {
res . err . push ( {
2023-04-13 07:46:35 +02:00
info : "|Checkjson|dataerrpropertie" ,
2023-03-27 07:52:21 +02:00
moreinfo : ` ${ p } : ${ data [ p ] } maxLength: ${ properties [ p ] . maxLength } ` ,
} ) ;
}
if (
properties [ p ] . multipleOf &&
2023-04-13 07:46:35 +02:00
! Checkjson . schema . properties . multipleOf ( data [ p ] , properties [ p ] . multipleOf )
2023-03-27 07:52:21 +02:00
) {
res . err . push ( {
2023-04-13 07:46:35 +02:00
info : "|Checkjson|dataerrpropertie" ,
2023-03-27 07:52:21 +02:00
moreinfo : ` ${ p } : ${ data [ p ] } not a multipleOf: ${ properties [ p ] . multipleOf } ` ,
} ) ;
}
if (
properties [ p ] . minimum ||
properties [ p ] . maximum ||
properties [ p ] . exclusiveMinimum ||
properties [ p ] . exclusiveMaximum
) {
// test range
if (
2023-04-13 07:46:35 +02:00
! Checkjson . schema . properties . range (
2023-03-27 07:52:21 +02:00
data [ p ] ,
properties [ p ] . minimum ,
properties [ p ] . exclusiveMinimum ,
properties [ p ] . maximum ,
properties [ p ] . exclusiveMaximum
)
) {
res . err . push ( {
2023-04-13 07:46:35 +02:00
info : "|Checkjson|dataerrpropertie" ,
2023-03-27 07:52:21 +02:00
moreinfo : ` ${ p } : ${ data [ p ] } not in range ${ properties [ p ] . minimum } exclu: ${ properties [ p ] . exclusiveMinimum } and ${ properties [ p ] . maximum } exclu: ${ properties [ p ] . exclusiveMaximum } ` ,
} ) ;
}
}
if (
properties [ p ] . enum &&
2023-04-13 07:46:35 +02:00
! Checkjson . schema . properties . enum ( data [ p ] , properties [ p ] . enum )
2023-03-27 07:52:21 +02:00
) {
res . err . push ( {
2023-04-13 07:46:35 +02:00
info : "|Checkjson|dataerrpropertie" ,
2023-03-27 07:52:21 +02:00
moreinfo : ` ${ p } : ${ data [ p ] } not in enum list : ${ properties [ p ] . enum } ` ,
} ) ;
}
if ( properties [ p ] . format ) {
properties [ p ] . pattern =
2023-04-13 07:46:35 +02:00
Checkjson . schema . properties . format [ properties [ p ] . format ] ;
2023-03-27 07:52:21 +02:00
}
if (
properties [ p ] . pattern &&
2023-04-13 07:46:35 +02:00
! Checkjson . schema . properties . pattern ( data [ p ] , properties [ p ] . pattern )
2023-03-27 07:52:21 +02:00
) {
res . err . push ( {
2023-04-13 07:46:35 +02:00
info : "|Checkjson|dataerrpropertie" ,
2023-03-27 07:52:21 +02:00
moreinfo : ` ${ p } : ${ data [ p ] } problem pattern or format ${ properties [ p ] . pattern } ` ,
} ) ;
}
2023-04-13 07:46:35 +02:00
} else if ( schema . required && schema . required . includes ( p ) ) {
2023-03-27 07:52:21 +02:00
res . err . push ( {
2023-04-13 07:46:35 +02:00
info : "|Checkjson|dataerrpropertiesrequired" ,
2023-03-27 07:52:21 +02:00
moreinfo : ` ${ p } ` ,
} ) ;
}
} ) ;
}
if ( res . err . length > 0 ) res . status = 417 ;
return res ;
2023-01-22 10:53:09 +01:00
} ;
2023-04-13 07:46:35 +02:00
if ( typeof module !== "undefined" ) module . exports = Checkjson ;