@@ -24,6 +24,85 @@ import type { AccountSID } from '@tech-matters/types';
2424import type { FlatResource } from '@tech-matters/resources-types' ;
2525import { parse } from 'date-fns' ;
2626
27+ // https://gist.github.com/mshafrir/2646763
28+ const US_STATE_CODE_MAPPING = {
29+ AL : 'Alabama' ,
30+ AK : 'Alaska' ,
31+ AS : 'American Samoa' ,
32+ AZ : 'Arizona' ,
33+ AR : 'Arkansas' ,
34+ CA : 'California' ,
35+ CO : 'Colorado' ,
36+ CT : 'Connecticut' ,
37+ DE : 'Delaware' ,
38+ DC : 'District Of Columbia' ,
39+ FM : 'Federated States Of Micronesia' ,
40+ FL : 'Florida' ,
41+ GA : 'Georgia' ,
42+ GU : 'Guam' ,
43+ HI : 'Hawaii' ,
44+ ID : 'Idaho' ,
45+ IL : 'Illinois' ,
46+ IN : 'Indiana' ,
47+ IA : 'Iowa' ,
48+ KS : 'Kansas' ,
49+ KY : 'Kentucky' ,
50+ LA : 'Louisiana' ,
51+ ME : 'Maine' ,
52+ MH : 'Marshall Islands' ,
53+ MD : 'Maryland' ,
54+ MA : 'Massachusetts' ,
55+ MI : 'Michigan' ,
56+ MN : 'Minnesota' ,
57+ MS : 'Mississippi' ,
58+ MO : 'Missouri' ,
59+ MT : 'Montana' ,
60+ NE : 'Nebraska' ,
61+ NV : 'Nevada' ,
62+ NH : 'New Hampshire' ,
63+ NJ : 'New Jersey' ,
64+ NM : 'New Mexico' ,
65+ NY : 'New York' ,
66+ NC : 'North Carolina' ,
67+ ND : 'North Dakota' ,
68+ MP : 'Northern Mariana Islands' ,
69+ OH : 'Ohio' ,
70+ OK : 'Oklahoma' ,
71+ OR : 'Oregon' ,
72+ PW : 'Palau' ,
73+ PA : 'Pennsylvania' ,
74+ PR : 'Puerto Rico' ,
75+ RI : 'Rhode Island' ,
76+ SC : 'South Carolina' ,
77+ SD : 'South Dakota' ,
78+ TN : 'Tennessee' ,
79+ TX : 'Texas' ,
80+ UT : 'Utah' ,
81+ VT : 'Vermont' ,
82+ VI : 'Virgin Islands' ,
83+ VA : 'Virginia' ,
84+ WA : 'Washington' ,
85+ WV : 'West Virginia' ,
86+ WI : 'Wisconsin' ,
87+ WY : 'Wyoming' ,
88+ } as Record < string , string > ;
89+
90+ const CANADIAN_PROVINCE_CODE_MAPPING = {
91+ AB : 'Alberta' ,
92+ BC : 'British Columbia' ,
93+ NL : 'Newfoundland and Labrador' ,
94+ PE : 'Île-du-Prince-Édouard' ,
95+ NS : 'Nouvelle-Écosse' ,
96+ NB : 'New Brunswick' ,
97+ ON : 'Ontario' ,
98+ MB : 'Manitoba' ,
99+ SK : 'Saskatchewan' ,
100+ YT : 'Yukon' ,
101+ NT : 'Northwest Territories' ,
102+ NU : 'Nunavut' ,
103+ QC : 'Québec' ,
104+ } as Record < string , string > ;
105+
27106/*
28107 * This defines all the mapping logic to convert Childhelp resource to an Aselo resource.
29108 * The mapping is defined as a tree of nodes.
@@ -93,6 +172,31 @@ export type UschExpandedResource = Partial<
93172 }
94173> ;
95174
175+ const isUnitedStates = ( country : string | undefined ) =>
176+ [ 'us' , 'usa' , 'unitedstates' ] . includes (
177+ ( country ?? '' ) . toLowerCase ( ) . replaceAll ( / [ . \s ] / g, '' ) ,
178+ ) ;
179+
180+ const isUSStateOrTerritory = ( country : string | undefined ) =>
181+ country &&
182+ ( Object . keys ( US_STATE_CODE_MAPPING ) . includes ( country ) ||
183+ Object . values ( US_STATE_CODE_MAPPING ) . includes ( country ) ) ;
184+
185+ const isCanadianProvince = ( country : string | undefined ) =>
186+ country &&
187+ ( Object . keys ( CANADIAN_PROVINCE_CODE_MAPPING ) . includes ( country ) ||
188+ Object . values ( CANADIAN_PROVINCE_CODE_MAPPING ) . includes ( country ) ) ;
189+
190+ const lookupUsStateNameFromCode = ( {
191+ Country : country ,
192+ StateProvince : stateProvince ,
193+ } : UschExpandedResource ) : string | undefined => {
194+ if ( isUnitedStates ( country ) ) {
195+ return US_STATE_CODE_MAPPING [ stateProvince ?? '' ] ?? stateProvince ;
196+ }
197+ return stateProvince ;
198+ } ;
199+
96200export const expandCsvLine = ( csv : UschCsvResource ) : UschExpandedResource => {
97201 const expanded = {
98202 ...csv ,
@@ -113,8 +217,27 @@ export const USCH_MAPPING_NODE: MappingNode = {
113217 Name : resourceFieldMapping ( 'name' ) ,
114218 AlternateName : translatableAttributeMapping ( 'alternateName' , { language : 'en' } ) ,
115219 Address : attributeMapping ( 'stringAttributes' , 'address/street' ) ,
116- City : attributeMapping ( 'stringAttributes' , 'address/city' ) ,
117- StateProvince : attributeMapping ( 'stringAttributes' , 'address/province' ) ,
220+ City : attributeMapping ( 'stringAttributes' , 'address/city' , {
221+ value : ( { currentValue, rootResource } ) =>
222+ [
223+ ( rootResource as UschExpandedResource ) . Country ,
224+ ( rootResource as UschExpandedResource ) . StateProvince ,
225+ currentValue ,
226+ ] . join ( '/' ) ,
227+ info : ( { currentValue, rootResource } ) => ( {
228+ country : ( rootResource as UschExpandedResource ) . Country ,
229+ stateProvince : lookupUsStateNameFromCode ( rootResource as UschExpandedResource ) ,
230+ name : currentValue ,
231+ } ) ,
232+ } ) ,
233+ StateProvince : attributeMapping ( 'stringAttributes' , 'address/province' , {
234+ value : ( { currentValue, rootResource } ) =>
235+ `${ ( rootResource as UschExpandedResource ) . Country } /${ currentValue } ` ,
236+ info : ( { rootResource } ) => ( {
237+ country : ( rootResource as UschExpandedResource ) . Country ,
238+ name : lookupUsStateNameFromCode ( rootResource as UschExpandedResource ) ,
239+ } ) ,
240+ } ) ,
118241 PostalCode : attributeMapping ( 'stringAttributes' , 'address/postalCode' ) ,
119242 Country : attributeMapping ( 'stringAttributes' , 'address/country' ) ,
120243 HoursOfOperation : translatableAttributeMapping ( 'hoursOfOperation' ) ,
@@ -188,10 +311,159 @@ export const USCH_MAPPING_NODE: MappingNode = {
188311 } ,
189312 Coverage : {
190313 children : {
191- '{coverageIndex}' : translatableAttributeMapping ( 'coverage/{coverageIndex}' , {
192- value : ( { currentValue } ) => currentValue ,
193- language : 'en' ,
194- } ) ,
314+ '{coverageIndex}' : {
315+ mappings : [
316+ translatableAttributeMapping ( 'coverage/{coverageIndex}' , {
317+ value : ( { currentValue } ) => {
318+ const [ countryOrState ] = currentValue . toString ( ) . split ( / \s + - \s + / ) ;
319+
320+ if ( isUSStateOrTerritory ( countryOrState ) ) {
321+ return `United States/${ currentValue . replaceAll ( / \s + - \s + / g, '/' ) } ` ;
322+ } else {
323+ return `${ currentValue . replaceAll ( / \s + - \s + / g, '/' ) } ` ;
324+ }
325+ } ,
326+ info : ( { currentValue } ) => {
327+ const [ countryOrState , provinceOrCity , internationalCity ] = currentValue
328+ . toString ( )
329+ . split ( / \s + - \s + / ) ;
330+ if ( isUSStateOrTerritory ( countryOrState ) ) {
331+ return {
332+ country : 'United States' ,
333+ stateProvince :
334+ US_STATE_CODE_MAPPING [ countryOrState ?? '' ] ?? countryOrState ,
335+ city : provinceOrCity ,
336+ name : currentValue ,
337+ } ;
338+ } else if ( isCanadianProvince ( countryOrState ) ) {
339+ return {
340+ country : 'Canada' ,
341+ stateProvince :
342+ CANADIAN_PROVINCE_CODE_MAPPING [ countryOrState ?? '' ] ??
343+ countryOrState ,
344+ city : provinceOrCity ,
345+ name : currentValue ,
346+ } ;
347+ } else {
348+ return {
349+ country : countryOrState ,
350+ stateProvince : provinceOrCity ,
351+ city : internationalCity ,
352+ name : currentValue ,
353+ } ;
354+ }
355+ } ,
356+ language : 'en' ,
357+ } ) ,
358+ // Not using coverage/country because that makes things bessy with root coverage values
359+ translatableAttributeMapping ( 'coverageCountry/{coverageIndex}' , {
360+ value : ( { currentValue } ) => {
361+ const [ countryOrState ] = currentValue . toString ( ) . split ( / \s + - \s + / ) ;
362+ if ( isUSStateOrTerritory ( countryOrState ) ) {
363+ return 'United States' ;
364+ } else if ( isCanadianProvince ( countryOrState ) ) {
365+ return 'Canada' ;
366+ } else {
367+ return countryOrState ;
368+ }
369+ } ,
370+ language : 'en' ,
371+ } ) ,
372+ // Not using coverage/province because that makes things bessy with root coverage values
373+ translatableAttributeMapping ( 'coverageStateProvince/{coverageIndex}' , {
374+ value : ( { currentValue } ) => {
375+ const [ countryOrState , provinceOrCity ] = currentValue
376+ . toString ( )
377+ . split ( / \s + - \s + / ) ;
378+ if ( isUSStateOrTerritory ( countryOrState ) ) {
379+ return `United States/${ countryOrState } ` ;
380+ } else if ( isCanadianProvince ( countryOrState ) ) {
381+ return `Canada/${ countryOrState } ` ;
382+ } else if ( provinceOrCity ) {
383+ return `${ countryOrState } /${ provinceOrCity } ` ;
384+ } else return '' ;
385+ } ,
386+ info : ( { currentValue } ) => {
387+ const [ countryOrState , provinceOrCity ] = currentValue
388+ . toString ( )
389+ . split ( / \s + - \s + / ) ;
390+ if ( isUSStateOrTerritory ( countryOrState ) ) {
391+ const stateProvince =
392+ US_STATE_CODE_MAPPING [ countryOrState ?? '' ] ?? countryOrState ;
393+ return {
394+ country : 'United States' ,
395+ stateProvince,
396+ name : stateProvince ,
397+ } ;
398+ } else if ( isCanadianProvince ( countryOrState ) ) {
399+ const stateProvince =
400+ CANADIAN_PROVINCE_CODE_MAPPING [ countryOrState ?? '' ] ?? countryOrState ;
401+ return {
402+ country : 'Canada' ,
403+ stateProvince,
404+ name : stateProvince ,
405+ } ;
406+ } else if ( provinceOrCity ) {
407+ return {
408+ country : countryOrState ,
409+ stateProvince : provinceOrCity ,
410+ name : provinceOrCity ,
411+ } ;
412+ } else return null ;
413+ } ,
414+ language : 'en' ,
415+ } ) ,
416+ // Not using coverage/city because that makes things messy with root coverage values
417+ translatableAttributeMapping ( 'coverageCity/{coverageIndex}' , {
418+ value : ( { currentValue } ) => {
419+ const [ countryOrState , provinceOrCity , internationalCity ] = currentValue
420+ . toString ( )
421+ . split ( / \s + - \s + / ) ;
422+ if ( isUSStateOrTerritory ( countryOrState ) ) {
423+ return `United States/${ countryOrState } /${ provinceOrCity } ` ;
424+ } else if ( isCanadianProvince ( countryOrState ) ) {
425+ return `Canada/${ countryOrState } /${ provinceOrCity } ` ;
426+ } else if ( internationalCity ) {
427+ return `${ countryOrState } /${ provinceOrCity } /${ internationalCity } ` ;
428+ } else return '' ;
429+ } ,
430+ info : ( { currentValue, rootResource } ) => {
431+ const [ countryOrState , provinceOrCity , internationalCity ] = currentValue
432+ . toString ( )
433+ . split ( / \s + - \s + / ) ;
434+ if ( isUSStateOrTerritory ( countryOrState ) ) {
435+ const stateProvince =
436+ US_STATE_CODE_MAPPING [ countryOrState ?? '' ] ?? countryOrState ;
437+ return {
438+ country : 'United States' ,
439+ stateProvince,
440+ city : provinceOrCity ,
441+ name : provinceOrCity ,
442+ } ;
443+ } else if ( isCanadianProvince ( rootResource . Country ) ) {
444+ const stateProvince =
445+ CANADIAN_PROVINCE_CODE_MAPPING [ countryOrState ?? '' ] ?? countryOrState ;
446+ return {
447+ country : 'Canada' ,
448+ stateProvince,
449+ city : provinceOrCity ,
450+ name : provinceOrCity ,
451+ } ;
452+ } else if ( internationalCity ) {
453+ return {
454+ country : countryOrState ,
455+ stateProvince : provinceOrCity ,
456+ city : internationalCity ,
457+ name : internationalCity ,
458+ } ;
459+ } else {
460+ return null ;
461+ }
462+ } ,
463+ language : 'en' ,
464+ } ) ,
465+ ] ,
466+ } ,
195467 } ,
196468 } ,
197469 Comment : translatableAttributeMapping ( 'comment' , { language : 'en' } ) ,
0 commit comments