-
Notifications
You must be signed in to change notification settings - Fork 4
[#171683039] Import and staticize municipalities from csv #59
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
Affected stories
New dependencies added: csv-parseAuthor: David Worms Description: CSV parsing implementing the Node.js `stream.Transform` API Homepage: https://csv.js.org/parse/
|
| Created | over 5 years ago |
| Last Updated | about 1 month ago |
| License | MIT |
| Maintainers | 4 |
| Releases | 58 |
| Direct Dependencies | |
| Keywords | fetch, http and promise |
@types/node-fetch
Author: Unknown
Description: TypeScript definitions for node-fetch
Homepage: http://npmjs.com/package/@types/node-fetch
| Created | almost 4 years ago |
| Last Updated | 3 months ago |
| License | MIT |
| Maintainers | 1 |
| Releases | 33 |
| Direct Dependencies | @types/node and form-data |
README
Installation
npm install --save @types/node-fetch
Summary
This package contains type definitions for node-fetch (https://github.com/bitinn/node-fetch).
Details
Files were exported from https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/node-fetch.
Additional Details
- Last updated: Thu, 23 Apr 2020 19:30:58 GMT
- Dependencies: @types/form-data, @types/node
- Global values: none
Credits
These definitions were written by Torsten Werner, Niklas Lindgren, Vinay Bedre, Antonio Román, Andrew Leedham, Jason Li, Brandon Wilson, Steve Faulkner, ExE Boss, Alex Savin, Alexis Tyler, and Jakub Kisielewski.
Generated by 🚫 dangerJS
Codecov Report
@@ Coverage Diff @@
## master #59 +/- ##
==========================================
- Coverage 86.15% 84.83% -1.32%
==========================================
Files 25 31 +6
Lines 816 1108 +292
Branches 50 64 +14
==========================================
+ Hits 703 940 +237
- Misses 112 167 +55
Partials 1 1
Continue to review full report at Codecov.
|
package.json
Outdated
| "io-ts": "1.8.5", | ||
| "italia-ts-commons": "^8.1.0", | ||
| "randomstring": "^1.1.5", | ||
| "request": "^2.88.2", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
may we use node-fetch instead of request ? it comes from io-functions-commons so we can avoid adding a new dep (moreover, request package is obsolete)
utils/file.ts
Outdated
| () => getBlobAsText(blobService, containerName, blobName).then(e => e), | ||
| toError | ||
| ).foldTaskEither( | ||
| err => fromEither(left(err)), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| err => fromEither(left(err)), | |
| fromLeft, |
| tryCatch( | ||
| () => getBlobAsText(blobService, containerName, blobName).then(e => e), | ||
| toError | ||
| ).foldTaskEither( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why we need this call to foldTaskEither here? it looks like it's mapping identities
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
getBlobAsText returns Promise<Either<Error, BlobResult>> so I've used the same code to turn it into a TaskEither -> see
| const fromPromiseEither = <L, R>( |
utils/file.ts
Outdated
| ).then(e => e), | ||
| toError | ||
| ).foldTaskEither( | ||
| err => fromEither(left(err)), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same as previous
utils/municipality.ts
Outdated
| _.foldL( | ||
| () => fromLeft(new Error("Municipalities with catastale is empty")), | ||
| __ => | ||
| parseCsv(__, optionMunicipalitiesWithCatastale).foldTaskEither( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto
utils/municipality.ts
Outdated
| ) | ||
| .chain(rawFile => | ||
| rawFile.foldL( | ||
| () => fromEither(leftE(new Error("abolished municipalities is empty"))), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fromEither(left) === fromLeft()
utils/municipality.ts
Outdated
| .chain(result => | ||
| array.sequence(taskEither)( | ||
| result | ||
| .filter(r => r[9] !== "") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
a comment here on what's happening would be useful or better you can isolate this filter into its own method with a meaningful name
utils/municipality.ts
Outdated
| ), | ||
| municipality => | ||
| serializeMunicipalityToJson(blobService, { | ||
| codiceCatastale: r[9], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe an object with a map between indexex (integers) and column names (constants) can be useful here
| if (record.length < 13) { | ||
| return leftE([ | ||
| { | ||
| context: [], | ||
| value: "record has not the right length" | ||
| } | ||
| ]); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need this? I think just the validation below is enough (it would return a well-formed validation error indicating that some values are undefined).
So you can keep all the parsing logic in the Municipality decoder
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that this check is trying to avoid column shifting problems, because if a record length is larger than expected, we can assign a wrong value to a property. Moreover we use a positional notation to extract values from csv files.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if a record length is larger than expected
Actually the check is for records shorter than expected, isn't it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, but the logic is the same, maybe we can turn this check into record.length !== <expected_record_length>
utils/municipality.ts
Outdated
| __ => | ||
| parseCsv(__, optionMunicipalitiesWithCatastale).foldTaskEither( | ||
| e => fromEither(leftE(e)), | ||
| matrixString => fromEither(rightE(matrixString)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| matrixString => fromEither(rightE(matrixString)) | |
| matrixString => taskEither.of(matrixString) |
utils/municipality.ts
Outdated
| () => fromLeft(new Error("Municipalities with catastale is empty")), | ||
| __ => | ||
| parseCsv(__, optionMunicipalitiesWithCatastale).foldTaskEither( | ||
| e => fromEither(leftE(e)), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| e => fromEither(leftE(e)), | |
| e => fromLeft(e), |
utils/municipality.ts
Outdated
| .foldTaskEither<Error, Map<string, string>>( | ||
| err => fromLeft(err), | ||
| municipalitiesCatastaleRows => | ||
| fromEither( | ||
| rightE( | ||
| municipalitiesCatastaleRows.reduce( | ||
| (map: Map<string, string>, row) => { | ||
| map.set(row[1].toLowerCase(), row[0]); | ||
| return map; | ||
| }, | ||
| new Map<string, string>() | ||
| ) | ||
| ) | ||
| ) | ||
| ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is foldTaskEither needed? as you are not lifting left type, I think you can use map
.map(
municipalitiesCatastaleRows =>
municipalitiesCatastaleRows.reduce(
(map: Map<string, string>, row) => {
map.set(row[1].toLowerCase(), row[0]);
return map;
},
new Map<string, string>()
)
);(to be verified)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I' ve changed it into a chain
utils/municipality.ts
Outdated
| ); | ||
|
|
||
| const fromAbolishedMunicipalityToSerializableMunicipality = ( | ||
| abolishedMunicipality: t.TypeOf<typeof AbolishedMunicipality>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| abolishedMunicipality: t.TypeOf<typeof AbolishedMunicipality>, | |
| abolishedMunicipality: AbolishedMunicipality, |
utils/municipality.ts
Outdated
| return { | ||
| codiceCatastale, | ||
| municipality: { | ||
| codiceProvincia: "", | ||
| codiceRegione: "", | ||
| denominazione: abolishedMunicipality.comune, | ||
| denominazioneInItaliano: abolishedMunicipality.comune, | ||
| denominazioneRegione: "", | ||
| siglaProvincia: abolishedMunicipality.provincia | ||
| } | ||
| } as ISerializableMunicipality; | ||
| }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm afraid of this cast. The object isn't recognised as ISerializableMunicipality because we're not sure municipality is a Municipality.
Consider decode the municipality field value:
municipality: Municipality.decode({
codiceProvincia: "",
codiceRegione: "",
denominazione: abolishedMunicipality.comune,
denominazioneInItaliano: abolishedMunicipality.comune,
denominazioneRegione: "",
siglaProvincia: abolishedMunicipality.provincia
}).getOrElseL(_ => { throw new Error(/* err message */); }Or even, why not make ISerializableMunicipality a decoder itself?
utils/municipality.ts
Outdated
| ) | ||
| .chain(rawFile => | ||
| rawFile.foldL( | ||
| () => fromEither(leftE(new Error("abolished municipalities is empty"))), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| () => fromEither(leftE(new Error("abolished municipalities is empty"))), | |
| () => fromLeft(new Error("abolished municipalities is empty")), |
utils/municipality.ts
Outdated
| .chain(rawFile => | ||
| rawFile.foldL( | ||
| () => fromEither(leftE(new Error("abolished municipalities is empty"))), | ||
| json => fromEither(rightE(JSON.parse(json))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| json => fromEither(rightE(JSON.parse(json))) | |
| json => taskEither.of(JSON.parse(json))) |
Besides of that, be careful because JSON.parse can throw! Consider use parseJSON
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm apart from minor changes
UpdateMunicipalities/function.json
Outdated
| { | ||
| "bindings": [ | ||
| { | ||
| "schedule": "0 */15 * * * *", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
how many times is this supposed to run ? once a day suffices
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Which hour?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've set every day at 01:00 AM
UpdateMunicipalities/handler.ts
Outdated
| ) | ||
| .foldTaskEither<Error, void>( | ||
| err => { | ||
| context.log.error(`Cannot update municipalities| ${err}`); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
may we prefix the error with the name of the function? moreover get rid of the space after '|'
UpdateMunicipalities/handler.ts
Outdated
| exportCurrentMunicipalities(blobService), | ||
| exportForeignMunicipalities(blobService) | ||
| ) | ||
| .foldTaskEither<Error, void>( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it looks like mapLeft() would suffice here (instead of folding)
UpdateMunicipalities/index.ts
Outdated
|
|
||
| import { getUpdateMunicipalitiesHandler } from "./handler"; | ||
|
|
||
| const storageConnectionString = getRequiredStringEnv("StorageConnection"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| const storageConnectionString = getRequiredStringEnv("StorageConnection"); | |
| const storageConnectionString = getRequiredStringEnv("AssetsStorageConnection"); |
utils/municipality.ts
Outdated
| denominazioneRegione: "", | ||
| siglaProvincia: abolishedMunicipality.provincia | ||
| } | ||
| }).getOrElseL(_ => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
may we just return the either and skip all the invalid entries with a warning?
utils/municipality.ts
Outdated
| abolishedMunArray | ||
| .filter(am => municipalityToCatastale.has(am.comune.toLowerCase())) | ||
| .map(am => | ||
| fromAbolishedMunicipalityToSerializableMunicipality( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this may throw currently, see comment above
utils/municipality.ts
Outdated
| ) | ||
| .chain(result => | ||
| array.sequence(taskEither)( | ||
| filterEmptyCodiceCatastaleRecords(result, 9 as NonNegativeInteger).map( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why "9" ? I guess the index value must be hardcoded into filterEmptyCodiceCatastaleRecords instead of being taken as paramter
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
agree, fixed
|
why draft?= |
| blobService: BlobService | ||
| ) => async (context: Context): Promise<unknown> => { | ||
| return sequenceT(taskEither)( | ||
| const partialResults = sequenceT(taskEitherSeq)( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
|
Kudos, SonarCloud Quality Gate passed!
|
|
@AleDore I assume this to not be actual anymore |
|
Yes it is correct!
Inviato da iPhone
… Il giorno 10 gen 2022, alle ore 17:22, Emanuele De Cupis ***@***.***> ha scritto:
@AleDore I assume this to not be actual anymore
—
Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications on the go with GitHub Mobile for iOS or Android.
You are receiving this because you were mentioned.
|








Municipalities porting and refactor