const { feature } = require('./feature')
/**
* Checks if a GeoJSON Feature has an ID. Providing an optional SearchID argument will check for that exact ID
* or array of possible ID values.
*
* @memberof Core.Features
* @see https://github.com/M-Scott-Lassiter/jest-geojson/issues/36
* @param {object} featureObject a GeoJSON Feature object
* @param {string|number|RegExp|string[]|number[]|RegExp[]} [SearchID] Specific value or array of possible values
* to search for.
* @returns {boolean} True if the Feature object has any ID (no argument provided), or if the ID exactly matches
* the optional argument (single string, number, or RegExp provided), or any value within an array of any
* combination of strings, numbers, or RegExp. If the object has an ID that does not match SearchID, it returns false.
* @throws {Error} Argument must be a GeoJSON Feature object
* @throws {Error} Feature object must have an "id" member
* @throws {Error} Optional SearchID must be either a number, string, RegExp, or array of any of these values
* @example
* const testFeature = {
* type: 'Feature',
* id: 'f1',
* geometry: {...},
* properties: {...}
* }
*
* // All of these return true
* const goodExample1 = hasID(testFeature)
* const goodExample2 = hasID(testFeature, 'f1')
* const goodExample3 = hasID(testFeature, [1, 'F', 'F12', /[a-z]+[0-9]+/])
*
* // Both of these return false
* const badExample1 = hasID(testFeature, 'f12')
* const badExample2 = hasID(testFeature, [1, 'F', 'F12', /SomeID/])
* @example
* const testFeature = {
* type: 'Feature',
* geometry: {...},
* properties: {...}
* }
*
* const example = hasID(testFeature) // false
*/
function hasID(featureObject, SearchID) {
feature(featureObject) // All validation handled here. Let it throw errors if needed.
if (!('id' in featureObject)) {
throw new Error('Feature does not have an "id" member.')
}
// After guard, ID exists, no SearchID provided. Pass.
if (SearchID === undefined || (Array.isArray(SearchID) && SearchID.length === 0)) {
return true
}
// Parse the SearchID into a safe array for further use
let safeArray = []
if (Array.isArray(SearchID)) {
safeArray = [...SearchID]
} else if (
typeof SearchID === 'string' ||
(typeof SearchID === 'number' && !Number.isNaN(SearchID))
) {
safeArray = [SearchID]
} else if (SearchID instanceof RegExp) {
safeArray = [new RegExp(SearchID)]
} else {
throw new Error('SearchID must be a number, string, RegExp, or array of any of these.')
}
let idFound = false
safeArray.forEach((id) => {
if (idFound) {
return
}
if (featureObject.id === id) {
idFound = true
}
if (id instanceof RegExp) {
if (featureObject.id.toString().match(id)) {
idFound = true
}
}
})
return idFound
}
exports.hasID = hasID