@italia-tools/faker
Version:
Italian-specific fake data generator based on Faker.js
213 lines (210 loc) • 8.05 kB
JavaScript
import { CityAdapter } from '../utils/cityAdapter.mjs';
import { WeightedRandomSelector } from '../utils/weightedRandom.mjs';
import { BehaviorSubject, of, from, Observable, lastValueFrom } from 'rxjs';
import { map, catchError, switchMap } from 'rxjs/operators';
import { CountryAdapter } from '../utils/countryAdapter.mjs';
class PlacesModule {
constructor(faker) {
this.faker = faker;
this.dataSubject = new BehaviorSubject(null);
this.countrySubject = new BehaviorSubject(null);
}
loadCityData() {
if (this.dataSubject.getValue()) {
return of(undefined);
}
return from(import('../data/cities.json.mjs')).pipe(map(module => {
const citiesData = module.default;
const citySelector = new WeightedRandomSelector(CityAdapter.toWeightedItems(citiesData));
this.dataSubject.next({
citySelector,
citiesData
});
}), catchError(error => {
console.error('Error loading city data:', error);
throw error;
}));
}
loadCountryData() {
// Check if data is already loaded
const existingData = this.countrySubject.getValue();
if (existingData) {
return of(undefined);
}
return from(import('../data/countries.json.mjs')).pipe(map(module => {
const countries = module.default.map((country) => CountryAdapter.toEnglish(country));
this.countrySubject.next(countries);
}), catchError(error => {
console.error('Error loading countries:', error);
throw new Error(`Failed to load country data: ${error.message}`);
}));
}
randomCity$() {
return this.loadCityData().pipe(map(() => this.selectItalianCity()));
}
randomCities$(count) {
return this.loadCityData().pipe(switchMap(() => {
const uniqueCities = new Set();
return new Observable(observer => {
while (uniqueCities.size < count) {
uniqueCities.add(this.selectItalianCity());
}
observer.next(Array.from(uniqueCities));
observer.complete();
});
}));
}
province$() {
return this.randomCity$().pipe(map(randomCity => ({
name: randomCity.province.name,
code: randomCity.code
})));
}
city$(options) {
return this.loadCityData().pipe(map(() => {
const data = this.dataSubject.getValue();
if (!data) {
throw new Error('City data not initialized');
}
// Search by belfioreCode (exact match)
if (options?.belfioreCode) {
const city = data.citiesData.find(city => city.codiceCatastale.toLowerCase() === options.belfioreCode?.toLowerCase());
return city ? CityAdapter.toEnglish(city) : null;
}
// Search by name (exact match or case-insensitive)
if (options?.cityName) {
const city = data.citiesData.find(city => city.nome.toLowerCase() === options.cityName?.toLowerCase());
return city ? CityAdapter.toEnglish(city) : null;
}
if (options?.province) {
const filteredCities = data.citiesData.filter(city => city.provincia.nome.toLowerCase() === options.province?.toLowerCase());
if (filteredCities.length > 0) {
return CityAdapter.toEnglish(this.faker.helpers.arrayElement(filteredCities));
}
}
if (options?.region) {
const filteredCities = data.citiesData.filter(city => city.regione.nome.toLowerCase() === options.region?.toLowerCase());
if (filteredCities.length > 0) {
return CityAdapter.toEnglish(this.faker.helpers.arrayElement(filteredCities));
}
}
return this.selectItalianCity();
}));
}
allCities$() {
return this.loadCityData().pipe(map(() => {
const data = this.dataSubject.getValue();
if (!data) {
throw new Error('City data not initialized');
}
return data.citiesData.map(city => CityAdapter.toEnglish(city));
}));
}
mostPopulatedCities$(x) {
return this.loadCityData().pipe(map(() => {
const data = this.dataSubject.getValue();
if (!data) {
throw new Error('City data not initialized');
}
const cities = data.citiesData.map(city => CityAdapter.toEnglish(city));
return cities.sort((a, b) => b.population - a.population).slice(0, x);
}));
}
;
getBirthPlace$() {
return this.randomCity$().pipe(map(randomCity => ({
name: randomCity.name,
belfioreCode: randomCity.belfioreCode,
province: randomCity.province.name,
region: randomCity.region.name,
provinceCode: randomCity.provinceCode
})));
}
region$() {
return this.randomCity$().pipe(map(randomCity => randomCity.region.name));
}
preloadData$() {
return this.loadCityData();
}
randomCountry$() {
return this.loadCountryData().pipe(map(() => {
const countries = this.countrySubject.getValue();
if (!countries)
throw new Error('Country data not initialized');
return this.faker.helpers.arrayElement(countries);
}));
}
getCountryByName$(name) {
if (!name || typeof name !== 'string') {
return of(null);
}
return this.loadCountryData().pipe(map(() => {
const countries = this.countrySubject.getValue();
if (!countries || !Array.isArray(countries)) {
throw new Error('Country data not properly initialized');
}
return countries.find(country => country.nameIt.toLowerCase() === name.toLowerCase() ||
country.nameEn.toLowerCase() === name.toLowerCase()) || null;
}), catchError(error => {
console.error('Error in getCountryByName$:', error);
return of(null);
}));
}
getAllCountries$() {
return this.loadCountryData().pipe(map(() => {
const countries = this.countrySubject.getValue();
if (!countries)
throw new Error('Country data not initialized');
return countries;
}));
}
async randomCity() {
return lastValueFrom(this.randomCity$());
}
async randomCities(count) {
return lastValueFrom(this.randomCities$(count));
}
async province() {
return lastValueFrom(this.province$());
}
async city(options) {
return lastValueFrom(this.city$(options));
}
async allCities() {
return lastValueFrom(this.allCities$());
}
async mostPopulatedCities(x) {
return lastValueFrom(this.mostPopulatedCities$(x));
}
async getBirthPlace() {
return lastValueFrom(this.getBirthPlace$());
}
async region() {
return lastValueFrom(this.region$());
}
async preloadData() {
return lastValueFrom(this.preloadData$());
}
async randomCountry() {
return lastValueFrom(this.randomCountry$());
}
async getCountryByName(name) {
return lastValueFrom(this.getCountryByName$(name));
}
async getAllCountries() {
return lastValueFrom(this.getAllCountries$());
}
clearCache() {
this.dataSubject.next(null);
this.countrySubject.next(null);
}
selectItalianCity() {
const data = this.dataSubject.getValue();
if (!data) {
throw new Error('City data not initialized');
}
const randomCity = data.citySelector.select();
return CityAdapter.toEnglish(randomCity);
}
}
export { PlacesModule };