Skip to content

Commit

Permalink
add more results to each ISO standard, options object and more tests
Browse files Browse the repository at this point in the history
  • Loading branch information
dskvr committed Dec 14, 2023
1 parent 993ae15 commit d0cbd6a
Show file tree
Hide file tree
Showing 2 changed files with 181 additions and 26 deletions.
91 changes: 83 additions & 8 deletions src/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { describe, it, expect } from 'vitest';
import ngeotags from './index'; // Adjust the import path as needed

import { iso31661, iso31662, iso31663, ISO31661AssignedEntry, ISO31661Entry } from 'iso-3166';


describe('ngeotags', () => {
it('should throw an error if input is null', () => {
expect(() => ngeotags(null)).toThrow('Input is required');
Expand All @@ -13,6 +16,7 @@ describe('ngeotags', () => {
it('should correctly transform gps coordinates', () => {
const result = ngeotags({ lat: 47.5636, lon: 19.0947 });
expect(result).toContainEqual(['g', '47.5636,19.0947', 'gps']);
console.log('result:', result)
});

it('should correctly transform geohash', () => {
Expand All @@ -22,15 +26,45 @@ describe('ngeotags', () => {
});

it('should correctly transform ISO-3166-1 country name', () => {
const result = ngeotags({ countryCode: 'HU' });
const countryName = result.find(tag => tag[2] === 'ISO-3166-1');
expect(countryName).toBeDefined();
const result = ngeotags({ countryCode: 'HU' }, { iso31661: true });
const countryNames = result.filter(tag => tag?.[3] && tag[3].includes('ISO-3166-1'));
// console.log('result:', result)
// console.log('filtered:', countryNames)
expect(countryNames.length).toBe(4);
});

it('should correctly transform ISO-3166-2 region code', () => {
const result = ngeotags({ country: 'HU', regionName: 'Budapest' });
const regionCode = result.find(tag => tag[2] === 'ISO-3166-2');
expect(regionCode).toBeDefined();
const result = ngeotags({ country: 'HU', regionName: 'Budapest' }, {iso31662: true});
const regionCodes = result.filter(tag => tag?.[3] && tag[3]?.includes('ISO-3166-2'));
expect(regionCodes.length).toBe(3)
});

it('should correctly transform ISO-3166-1 data', () => {
const result = ngeotags({ countryCode: 'HU' }, { iso31661: true });
// console.log('result', result)
expect(result).toContainEqual(['g', 'HU', 'countryCode', 'ISO-3166-1:alpha2']);
expect(result).toContainEqual(['g', 'HUN', 'countryCode', 'ISO-3166-1:alpha3']);
expect(result).toContainEqual(['g', 'HUN', 'countryCode', 'ISO-3166-1:alpha3']);
expect(result).toContainEqual(['g', 'HUN', 'countryCode', 'ISO-3166-1:alpha3']);
// Add checks for numeric and name as well
});

it('should correctly transform ISO-3166-3 changes', () => {
// const countryData = iso31661.find((c: ISO31661Entry) => c.alpha2 === "AI");
// console.log(countryData)
const result = ngeotags({ countryCode: 'AI' }, { iso31663: true }); // Assuming 'AN' has an ISO 3166-3 change
expect(result).toContainEqual([ 'g', 'DJ', 'countryCode', 'ISO-3166-3:alpha2' ]);
expect(result).toContainEqual( [ 'g', 'AIA', 'countryCode', 'ISO-3166-3:alpha3' ]);
expect(result).toContainEqual([ 'g', '660', 'countryCode', 'ISO-3166-3:numeric' ]);
expect(result).toContainEqual([ 'g', 'Anguilla', 'countryCode', 'ISO-3166-3:name' ]);
// Add checks for other fields as needed
});

it('should correctly transform ISO-3166-2 data', () => {
const result = ngeotags({ country: 'HU', regionName: 'Budapest' }, { iso31662: true });
expect(result).toContainEqual(['g', 'HU-BU', 'regionCode', 'ISO-3166-2:code']);
expect(result).toContainEqual(['g', 'Budapest', 'regionCode', 'ISO-3166-2:name']);
expect(result).toContainEqual(['g', 'HU', 'regionCode', 'ISO-3166-2:parent']);
});

it('should correctly transform city name', () => {
Expand All @@ -48,8 +82,49 @@ describe('ngeotags', () => {
expect(result).toContainEqual(['g', 'EU', 'continentCode']);
});

it('should include Earth as planet by default', () => {
const result = ngeotags({});
it('should include not include Earth as planet by default', () => {
const result = ngeotags({}, {}).find(tag => tag[2] === 'planet') || [];
expect(result.length).toBe(0);
});

it('should include should Earth when enabled', () => {
const result = ngeotags({}, {planet: true});
expect(result).toContainEqual(['g', 'Earth', 'planet']);
});

it('should correctly transform geohashes of diminishing resolution', () => {
const result = ngeotags({ lat: 47.5636, lon: 19.0947 });
const geohashTags = result.filter(tag => tag[2] === 'geohash');
expect(geohashTags.length).toBeGreaterThan(1); // Expect multiple geohash resolutions
});

it('should return all possible geotags', () => {
const input = {
"status": "success",
"continent": "Europe",
"continentCode": "EU",
"country": "Hungary",
"countryCode": "HU",
"region": "BU",
"regionName": "Budapest",
"city": "Budapest",
"district": "",
"zip": "1124",
"lat": 47.5636,
"lon": 19.0947,
"timezone": "Europe/Budapest",
"offset": 3600,
"currency": "HUF",
"isp": "Magyar Telekom",
"org": "",
"as": "AS5483 Magyar Telekom plc.",
"asname": "MAGYAR-TELEKOM-MAIN-AS",
"mobile": false,
"proxy": false,
"hosting": false
}
const result = ngeotags(input, { iso31661: true, iso31662: true, iso31663: true, planet: true });
console.log('FULL result:', result)
expect(result.length).toBeGreaterThan(10);
})
});
116 changes: 98 additions & 18 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import ngeohash from 'ngeohash';
import { iso31661, iso31662, ISO31661Entry } from 'iso-3166';
import { iso31661, iso31662, iso31663, ISO31661AssignedEntry, ISO31661Entry } from 'iso-3166';

interface InputData {
lat?: number;
Expand All @@ -13,13 +13,60 @@ interface InputData {
[key: string]: any;
}

const generateTags = (input: InputData): Array<[string, string, string]> => {
const tags: Array<[string, string, string]> = [];
interface Options {
iso31661?: boolean,
iso31662?: boolean,
iso31663?: boolean,
planet?: boolean,
geohash?: boolean,
gps?: boolean,
city?: boolean,
country?: boolean,
region?: boolean,
continent?: boolean,
continentCode?: boolean,
}

// interface ISO31661Entry {
// alpha2: string;
// alpha3: string;
// numeric: string;
// name: string;
// }


tags.push([`g`, `${input.lat},${input.lon}`, 'gps']);
type ISO31663FieldType = 'alpha2' | 'alpha3' | 'numeric' | 'name';

const getUpdatedIso31663Value = (type: ISO31663FieldType, code: string): string => {
const matchedEntry = iso31663.find(entry =>
entry.from[type] === code ||
entry.to.some(change => change[type] === code)
);
if (matchedEntry) {
if (matchedEntry.from[type] === code) {
// If the code matches the 'from' part, return the new value ('to' part)
return matchedEntry.to[0][type]; // Assuming there's always at least one 'to' entry
} else {
// If the code matches the 'to' part, return the same code as it's already the new value
return code;
}
}

// If there's no match, return the original code
return code;
};


const generateTags = (input: InputData, opts: Options): Array<[string, string, string] | [string, string, string, string]> => {
const tags: Array<[string, string, string] | [string, string, string, string]> = [];

// GPS
if (opts.gps && input.lat && input.lon) {
tags.push([`g`, `${input.lat},${input.lon}`, 'gps']);
}

// Geohash
if (input.lat && input.lon) {
if (opts.geohash && input.lat && input.lon) {
const fullGeohash = ngeohash.encode(input.lat, input.lon);

// Generate geohashes of diminishing resolution
Expand All @@ -28,49 +75,82 @@ const generateTags = (input: InputData): Array<[string, string, string]> => {
tags.push(['g', partialGeohash, 'geohash']);
}
}

// ISO-3166-1 Alpha-2 (country code)
if (input.countryCode) {
const countryData = iso31661.find((c: ISO31661Entry) => c.alpha2 === input.countryCode);
if (opts.iso31661 && input.countryCode) {
const countryData = iso31661.find((c: ISO31661AssignedEntry) => c.alpha2 === input.countryCode);
if (countryData) {
tags.push(['g', countryData.name, 'ISO-3166-1']);
(['alpha2', 'alpha3', 'numeric', 'name'] as const).forEach((type) => {
// Make sure type is a valid key of ISO31661AssignedEntry
tags.push(['g', countryData[type as keyof ISO31661AssignedEntry], 'countryCode', `ISO-3166-1:${type}`]);
});
}
}

// ISO-3166-2 (region code)
if (input.country && input.regionName) {
if (opts.iso31662 && input.country && input.regionName) {
const regionData = iso31662.find(r => r.parent === input.country && r.name === input.regionName);
if (regionData) {
tags.push(['g', regionData.code, 'ISO-3166-2']);
['code', 'name', 'parent'].forEach((type) => {
tags.push(['g', regionData[type as keyof typeof regionData], 'regionCode', `ISO-3166-2:${type}`]);
});
}
}

// ISO-3166-3 (changes)
if (opts.iso31663 && input.countryCode) {
const countryData = iso31661.find((c: ISO31661Entry) => c.alpha2 === input.countryCode);
if (countryData) {
(['alpha2', 'alpha3', 'numeric', 'name'] as const).forEach((type) => {
// Here we assert that type is a key of ISO31661Entry
const value = countryData[type as keyof ISO31661Entry];
tags.push(['g', getUpdatedIso31663Value(type, value), 'countryCode', `ISO-3166-3:${type}`]);
});
}
}

// City
if (input.city) {
if (opts.city && input.city) {
tags.push(['g', input.city, 'city']);
}

// Continent
if (input.continent) {
if (opts.continent && input.continent) {
tags.push(['g', input.continent, 'continent']);
}

// Continent Code
if (input.continentCode) {
if (opts.continentCode && input.continentCode) {
tags.push(['g', input.continentCode, 'continentCode']);
}

// Planet - Assuming Earth as there's no specific data for planet
tags.push(['g', 'Earth', 'planet']);
if(opts.planet) {
tags.push(['g', 'Earth', 'planet']);
}

return tags;
};

export default (input: InputData | null): Array<[string, string, string]> => {
export default (input: InputData | null, opts?: Options): Array<[string, string, string] | [string, string, string, string]> => {
if (!input)
throw new Error('Input is required');
if (typeof input !== 'object')
throw new Error('Input must be an object');
opts = {
iso31661: false,
iso31662: true,
iso31663: false,
planet: false,
geohash: true,
gps: true,
city: true,
country: true,
region: true,
continent: true,
continentCode: true,
...opts
};

return generateTags(input);
};
return generateTags(input, opts);
};

0 comments on commit d0cbd6a

Please sign in to comment.