@dossierhq/graphql
Version:
A library for creating GraphQL servers with Dossier.
62 lines • 2.22 kB
JavaScript
/// <reference types="./LocationScalar.d.ts" />
import { GraphQLScalarType } from 'graphql';
import { Kind } from 'graphql/language/index.js';
export const LocationScalar = new GraphQLScalarType({
name: 'Location',
description: 'Geographic location using EPSG:4326/WGS 84',
serialize(value) {
if (value === null)
return null;
assertLocation(value);
return value;
},
parseValue(value) {
if (value === null)
return null;
assertLocation(value);
return value;
},
parseLiteral(ast) {
if (ast.kind === Kind.OBJECT) {
const lat = getFloatFieldValue(ast, 'lat');
const lng = getFloatFieldValue(ast, 'lng');
if (lat === null || lng === null) {
throw new Error('Location must have lat and lng fields');
}
return { lat, lng };
}
if (ast.kind === Kind.NULL) {
return null;
}
throw new Error(`Expected Location to be an object, got ${ast.kind}`);
},
});
function assertLocation(value) {
if (typeof value !== 'object' || value === null) {
throw new Error(`Expected Location to be an object, got ${typeof value}`);
}
const { lat, lng } = value;
if (typeof lat !== 'number') {
throw new Error(`Expected Location.lat to be a number, got ${typeof lat}`);
}
if (typeof lng !== 'number') {
throw new Error(`Expected Location.lng to be a number, got ${typeof lng}`);
}
if (lat < -90 || lat > 90) {
throw new Error(`Expected Location.lat to be between -90 and 90, got ${lat}`);
}
if (lng < -180 || lng > 180) {
throw new Error(`Expected Location.lng to be between -180 and 180, got ${lng}`);
}
}
function getFloatFieldValue(ast, fieldName) {
const field = ast.fields.find((it) => it.name.value === fieldName);
if (field) {
if (field.value.kind === Kind.FLOAT || field.value.kind === Kind.INT) {
return parseFloat(field.value.value);
}
throw new Error(`Expected ${fieldName} to be a float, got ${field.value.kind}`);
}
return null;
}
//# sourceMappingURL=LocationScalar.js.map