diff --git a/backend/src/graphql/resolver/util/Location2Point.ts b/backend/src/graphql/resolver/util/Location2Point.ts new file mode 100644 index 000000000..c3849821d --- /dev/null +++ b/backend/src/graphql/resolver/util/Location2Point.ts @@ -0,0 +1,32 @@ +import { Point } from '@dbTools/typeorm' + +import { Location } from '@model/Location' + +export function Location2Point(location: Location): Point { + console.log('in Location2Point:', location) + let pointStr: string + if (location.longitude && location.latitude) { + pointStr = '{ "type": "Point", "coordinates": [' + .concat(location.longitude?.toString()) + .concat(', ') + .concat(location.latitude?.toString()) + .concat('] }') + } else { + pointStr = '{ "type": "Point", "coordinates": [] }' + } + console.log('pointStr:', pointStr) + const point = JSON.parse(pointStr) as Point + console.log('point:', point) + return point +} + +export function Point2Location(point: Point): Location { + console.log('in Point2Location:', point) + const location = new Location() + if (point.type === 'Point' && point.coordinates.length === 2) { + location.longitude = point.coordinates[0] + location.latitude = point.coordinates[1] + } + console.log('location:', location) + return location +} diff --git a/backend/src/graphql/scalar/Geometry.ts b/backend/src/graphql/scalar/Geometry.ts deleted file mode 100644 index c2cd48fdb..000000000 --- a/backend/src/graphql/scalar/Geometry.ts +++ /dev/null @@ -1,33 +0,0 @@ -/* eslint-disable @typescript-eslint/no-unsafe-argument */ -import { Geometry as DbGeometry } from '@dbTools/typeorm' -import { GraphQLScalarType, Kind } from 'graphql' - -import { Location } from '@model/Location' - -export const GeometryScalar = new GraphQLScalarType({ - name: 'Geometry', - description: - 'The `Geometry` scalar type to represent longitude and latitude values of a geo location', - - serialize(value: DbGeometry): Location { - // Check type of value - if (value.type !== 'Point') { - throw new Error(`GeometryScalar can only serialize Geometry type 'Point' values`) - } - - return new Location(value.coordinates[0], value.coordinates[1]) - }, - - parseValue(value): DbGeometry { - const geometry: DbGeometry = JSON.parse(value) as DbGeometry - return geometry - }, - - parseLiteral(ast) { - if (ast.kind !== Kind.STRING) { - throw new TypeError(`${String(ast)} is not a valid Geometry value.`) - } - - return JSON.parse(ast.value) as DbGeometry - }, -}) diff --git a/backend/src/graphql/scalar/Location.ts b/backend/src/graphql/scalar/Location.ts new file mode 100644 index 000000000..6002ee25b --- /dev/null +++ b/backend/src/graphql/scalar/Location.ts @@ -0,0 +1,46 @@ +/* eslint-disable @typescript-eslint/no-unsafe-argument */ +import { GraphQLScalarType, Kind } from 'graphql' + +import { Location } from '@model/Location' + +export const LocationScalar = new GraphQLScalarType({ + name: 'Location', + description: + 'The `Location` scalar type to represent longitude and latitude values of a geo location', + + serialize(value: Location) { + console.log('serialize LocationScalar:', value) + return value + }, + + parseValue(value): Location { + console.log('parseValue LocationScalar:', value) + try { + const loc = new Location() + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment + loc.longitude = value.longitude + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment + loc.latitude = value.latitude + console.log('parsed:', loc) + return loc + } catch (err) { + console.log('Error:', err) + } + return new Location() + }, + + parseLiteral(ast): Location { + console.log('parseLiteral LocationScalar:', ast) + if (ast.kind !== Kind.STRING) { + throw new TypeError(`${String(ast)} is not a valid Location value.`) + } + let loc = new Location() + try { + loc = JSON.parse(ast.value) as Location + console.log('parsed:', loc) + } catch (err) { + console.log('Error:', err) + } + return loc + }, +}) diff --git a/backend/src/graphql/scalar/Point.ts b/backend/src/graphql/scalar/Point.ts new file mode 100644 index 000000000..06af56bfc --- /dev/null +++ b/backend/src/graphql/scalar/Point.ts @@ -0,0 +1,31 @@ +/* eslint-disable @typescript-eslint/no-unsafe-argument */ +import { Point as DbPoint } from '@dbTools/typeorm' +import { GraphQLScalarType, Kind } from 'graphql' + +export const PointScalar = new GraphQLScalarType({ + name: 'Point', + description: + 'The `Point` scalar type to represent longitude and latitude values of a geo location', + + serialize(value: DbPoint) { + // Check type of value + if (value.type !== 'Point') { + throw new Error(`PointScalar can only serialize Geometry type 'Point' values`) + } + return value + }, + + parseValue(value): DbPoint { + const point = JSON.parse(value) as DbPoint + return point + }, + + parseLiteral(ast) { + if (ast.kind !== Kind.STRING) { + throw new TypeError(`${String(ast)} is not a valid Geometry value.`) + } + + const point = JSON.parse(ast.value) as DbPoint + return point + }, +}) diff --git a/backend/src/graphql/schema.ts b/backend/src/graphql/schema.ts index 18214861f..856844c94 100644 --- a/backend/src/graphql/schema.ts +++ b/backend/src/graphql/schema.ts @@ -4,21 +4,27 @@ import { Decimal } from 'decimal.js-light' import { GraphQLSchema } from 'graphql' import { buildSchema } from 'type-graphql' +import { Location } from '@model/Location' + import { isAuthorized } from './directive/isAuthorized' import { DecimalScalar } from './scalar/Decimal' +import { LocationScalar } from './scalar/Location' export const schema = async (): Promise => { return buildSchema({ resolvers: [path.join(__dirname, 'resolver', `!(*.test).{js,ts}`)], authChecker: isAuthorized, - scalarsMap: [{ type: Decimal, scalar: DecimalScalar }], + scalarsMap: [ + { type: Decimal, scalar: DecimalScalar }, + { type: Location, scalar: LocationScalar }, + ], validate: { validationError: { target: false }, skipMissingProperties: true, skipNullProperties: true, - skipUndefinedProperties: false, - forbidUnknownValues: true, - stopAtFirstError: true, + skipUndefinedProperties: true, + forbidUnknownValues: false, + stopAtFirstError: false, }, }) }