UNPKG

@koopjs/featureserver

Version:

*An open source implementation of the GeoServices specification*

95 lines (73 loc) 3.4 kB
const _ = require('lodash'); const { getDataTypeFromValue } = require('../helpers'); const logManager = require('../log-manager'); function logProviderDataWarnings(geojson, requestParams) { const { f, outFields = '*', returnCountOnly, returnExtentOnly, returnIdsOnly } = requestParams; if (f === 'geojson' || returnCountOnly || returnExtentOnly || returnIdsOnly) { return; } const { metadata = {}, features } = geojson; const properties = _.get(features, '[0].properties'); if (!metadata.idField && properties?.OBJECTID === undefined) { logManager.logger.debug( `provider data has no OBJECTID and has no "idField" assignment. You will get the most reliable behavior from ArcGIS clients if the provider assigns the "idField" to a property that is an integer in range 0 - ${Number.MAX_SAFE_INTEGER}. An OBJECTID field will be auto-generated in the absence of an "idField" assignment.`, // eslint-disable-line ); } if (hasMixedCaseObjectIdKey(metadata.idField)) { logManager.logger.debug( 'requested provider has "idField" that is a mixed-case version of "OBJECTID". This can cause errors in ArcGIS clients.', // eslint-disable-line ); } if (metadata.fields && properties) { const fields = getFieldsDefinitionsForResponse(metadata.fields, outFields); compareFieldDefintionsToFeature(fields, properties); compareFeatureToFieldDefinitions(properties, fields); } } function hasMixedCaseObjectIdKey(idField = '') { return idField.toLowerCase() === 'objectid' && idField !== 'OBJECTID'; } function getFieldsDefinitionsForResponse(fields, outFields) { const outFieldsSet = outFields === '*' || outFields === '' ? null : outFields.split(','); if (!outFieldsSet) { return fields; } return fields.filter((field) => { return outFieldsSet.includes(field.alias) || outFieldsSet.includes(field.name); }); } function compareFieldDefintionsToFeature(fieldDefinitions, featureProperties) { fieldDefinitions.forEach(({ name, alias, type }) => { // look for a defined field in the features properties const featureField = findFeatureProperty(featureProperties, name, alias); if (!featureField || hasTypeMismatch(type, featureField)) { logManager.logger.debug( `field definition "${name} (${type})" not found in first feature of provider's GeoJSON`, ); } }); } function compareFeatureToFieldDefinitions(featureProperties, fieldDefinitions) { Object.keys(featureProperties).forEach((key) => { const definition = _.find(fieldDefinitions, ['name', key]) || _.find(fieldDefinitions, ['name', key]); if (!definition && key !== 'OBJECTID') { logManager.logger.debug( `requested provider has feature with property "${key}" that was not defined in metadata fields array`, // eslint-disable-line ); } }); } function findFeatureProperty(properties, name, alias) { return properties[name] || properties[alias]; } function hasTypeMismatch(definitionType, value) { const propertyType = getDataTypeFromValue(value); return definitionType !== propertyType && !isEsriTypeMatchException(definitionType, propertyType); } function isEsriTypeMatchException(definitionType, propertyType) { if (definitionType === 'Date' || definitionType === 'Double') { return propertyType === 'Integer'; } } module.exports = { logProviderDataWarnings };