diff --git a/.env b/.env
new file mode 100644
index 0000000..f596af4
--- /dev/null
+++ b/.env
@@ -0,0 +1,21 @@
+# postgrest
+
+POSTGREST_CONTAINER_NAME=postgrest
+POSTGREST_IMAGE=postgrest/postgrest:v12.0.2
+
+# postgres
+
+POSTGRES_CONTAINER_NAME=postgres
+POSTGRES_IMAGE=postgres:latest
+POSTGRES_VOLUME_NAME=postgres
+
+POSTGRES_USER=postgres
+POSTGRES_PASSWORD=postgres
+POSTGRES_DB=postgres
+DB_ANON_ROLE=anon
+DB_SCHEMA=public
+
+# swagger
+
+SWAGGER_CONTAINER_NAME=swagger
+SWAGGER_IMAGE=swaggerapi/swagger-ui:v5.11.0
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..6cb772b
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+node_modules
+tmp
diff --git a/README.md b/README.md
index d10aeca..ccf08aa 100644
--- a/README.md
+++ b/README.md
@@ -7,3 +7,17 @@ Création d'une API unifié pour accéder à l'ensemble des données dont P4Pill
- Base de données : [PostgreSQL](https://www.postgresql.org/)
- API : [PostgREST](https://postgrest.org/) ([Documentation](https://postgrest.org/en/stable/explanations/install.html#docker))
- UI : [Swagger UI](https://swagger.io/tools/swagger-ui/)
+
+
+
+## Données
+
+### FINESS
+
+
+
+### INPI
+
+Il y a 2 posibilités pour récupérer les données :
+- depuis l'API
+- depuis [des fichiers](https://www.data.gouv.fr/fr/datasets/base-sirene-des-entreprises-et-de-leurs-etablissements-siren-siret/)
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 0000000..2a86ce9
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,80 @@
+---
+
+version: "3.8"
+
+volumes:
+ postgres:
+ name: ${POSTGRES_VOLUME_NAME:-postgres}
+
+services:
+
+ postgrest:
+ container_name: ${POSTGREST_CONTAINER_NAME:-postgrest}
+ image: ${POSTGREST_IMAGE:-postgrest/postgrest:v12.0.0}
+ restart: always
+ ports:
+ - "3000:3000"
+ # Available environment variables documented here:
+ # https://postgrest.org/en/latest/configuration.html#environment-variables
+ environment:
+ # The standard connection URI format, documented at
+ # https://www.postgresql.org/docs/current/static/libpq-connect.html#LIBPQ-CONNSTRING
+ PGRST_DB_URI: postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB:?err}
+ # The name of which database schema to expose to REST clients
+ PGRST_DB_SCHEMA: ${DB_SCHEMA}
+ # The database role to use when no client authentication is provided
+ PGRST_DB_ANON_ROLE: ${DB_ANON_ROLE}
+ # Overrides the base URL used within the OpenAPI self-documentation hosted at the API root path
+ PGRST_OPENAPI_SERVER_PROXY_URI: http://localhost:3000
+ depends_on:
+ - postgres
+ networks:
+ - back-end
+
+ postgrest-demo:
+ container_name: postgrest-demo
+ image: nginx:mainline-alpine
+ ports:
+ - "80:80"
+ volumes:
+ # anything in html directory is hosted via nginx
+ - "./html:/usr/share/nginx/html"
+ restart: always
+ networks:
+ - back-end
+
+ postgres:
+ container_name: ${POSTGRES_CONTAINER_NAME:-postgres}
+ image: ${POSTGRES_IMAGE:-postgres:16.1-alpine}
+ restart: always
+ ports:
+ - "5432:5432"
+ environment:
+ POSTGRES_USER: ${POSTGRES_USER:?err}
+ POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?err}
+ POSTGRES_DB: ${POSTGRES_DB:?err}
+ DB_ANON_ROLE: ${DB_ANON_ROLE:?err}
+ DB_SCHEMA: ${DB_SCHEMA:?err}
+ volumes:
+ - postgres:/var/lib/postgresql/data
+ - "./initdb:/docker-entrypoint-initdb.d"
+ - /etc/timezone:/etc/timezone:ro
+ - /etc/localtime:/etc/localtime:ro
+ networks:
+ - back-end
+
+ swagger:
+ container_name: ${SWAGGER_CONTAINER_NAME:-swagger}
+ image: ${SWAGGER_IMAGE:-swaggerapi/swagger-ui:v5.10.3}
+ restart: always
+ ports:
+ - "8080:8080"
+ environment:
+ API_URL: http://localhost:3000/
+ networks:
+ - front-end
+ - back-end
+
+networks:
+ front-end:
+ back-end:
\ No newline at end of file
diff --git a/html/css/app.css b/html/css/app.css
new file mode 100644
index 0000000..6b1eb6a
--- /dev/null
+++ b/html/css/app.css
@@ -0,0 +1,3 @@
+body {
+ margin-bottom: 40px;
+}
\ No newline at end of file
diff --git a/html/css/pure-min.css b/html/css/pure-min.css
new file mode 100644
index 0000000..5b2aaf8
--- /dev/null
+++ b/html/css/pure-min.css
@@ -0,0 +1,11 @@
+/*!
+Pure v2.0.6
+Copyright 2013 Yahoo!
+Licensed under the BSD License.
+https://github.com/pure-css/pure/blob/master/LICENSE
+*/
+/*!
+normalize.css v | MIT License | git.io/normalize
+Copyright (c) Nicolas Gallagher and Jonathan Neal
+*/
+/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}main{display:block}h1{font-size:2em;margin:.67em 0}hr{-webkit-box-sizing:content-box;box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:none;text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{-webkit-box-sizing:border-box;box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{-webkit-box-sizing:border-box;box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details{display:block}summary{display:list-item}template{display:none}[hidden]{display:none}html{font-family:sans-serif}.hidden,[hidden]{display:none!important}.pure-img{max-width:100%;height:auto;display:block}.pure-g{letter-spacing:-.31em;text-rendering:optimizespeed;font-family:FreeSans,Arimo,"Droid Sans",Helvetica,Arial,sans-serif;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-flow:row wrap;flex-flow:row wrap;-ms-flex-line-pack:start;align-content:flex-start}@media all and (-ms-high-contrast:none),(-ms-high-contrast:active){table .pure-g{display:block}}.opera-only :-o-prefocus,.pure-g{word-spacing:-0.43em}.pure-u{display:inline-block;letter-spacing:normal;word-spacing:normal;vertical-align:top;text-rendering:auto}.pure-g [class*=pure-u]{font-family:sans-serif}.pure-u-1,.pure-u-1-1,.pure-u-1-12,.pure-u-1-2,.pure-u-1-24,.pure-u-1-3,.pure-u-1-4,.pure-u-1-5,.pure-u-1-6,.pure-u-1-8,.pure-u-10-24,.pure-u-11-12,.pure-u-11-24,.pure-u-12-24,.pure-u-13-24,.pure-u-14-24,.pure-u-15-24,.pure-u-16-24,.pure-u-17-24,.pure-u-18-24,.pure-u-19-24,.pure-u-2-24,.pure-u-2-3,.pure-u-2-5,.pure-u-20-24,.pure-u-21-24,.pure-u-22-24,.pure-u-23-24,.pure-u-24-24,.pure-u-3-24,.pure-u-3-4,.pure-u-3-5,.pure-u-3-8,.pure-u-4-24,.pure-u-4-5,.pure-u-5-12,.pure-u-5-24,.pure-u-5-5,.pure-u-5-6,.pure-u-5-8,.pure-u-6-24,.pure-u-7-12,.pure-u-7-24,.pure-u-7-8,.pure-u-8-24,.pure-u-9-24{display:inline-block;letter-spacing:normal;word-spacing:normal;vertical-align:top;text-rendering:auto}.pure-u-1-24{width:4.1667%}.pure-u-1-12,.pure-u-2-24{width:8.3333%}.pure-u-1-8,.pure-u-3-24{width:12.5%}.pure-u-1-6,.pure-u-4-24{width:16.6667%}.pure-u-1-5{width:20%}.pure-u-5-24{width:20.8333%}.pure-u-1-4,.pure-u-6-24{width:25%}.pure-u-7-24{width:29.1667%}.pure-u-1-3,.pure-u-8-24{width:33.3333%}.pure-u-3-8,.pure-u-9-24{width:37.5%}.pure-u-2-5{width:40%}.pure-u-10-24,.pure-u-5-12{width:41.6667%}.pure-u-11-24{width:45.8333%}.pure-u-1-2,.pure-u-12-24{width:50%}.pure-u-13-24{width:54.1667%}.pure-u-14-24,.pure-u-7-12{width:58.3333%}.pure-u-3-5{width:60%}.pure-u-15-24,.pure-u-5-8{width:62.5%}.pure-u-16-24,.pure-u-2-3{width:66.6667%}.pure-u-17-24{width:70.8333%}.pure-u-18-24,.pure-u-3-4{width:75%}.pure-u-19-24{width:79.1667%}.pure-u-4-5{width:80%}.pure-u-20-24,.pure-u-5-6{width:83.3333%}.pure-u-21-24,.pure-u-7-8{width:87.5%}.pure-u-11-12,.pure-u-22-24{width:91.6667%}.pure-u-23-24{width:95.8333%}.pure-u-1,.pure-u-1-1,.pure-u-24-24,.pure-u-5-5{width:100%}.pure-button{display:inline-block;line-height:normal;white-space:nowrap;vertical-align:middle;text-align:center;cursor:pointer;-webkit-user-drag:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-box-sizing:border-box;box-sizing:border-box}.pure-button::-moz-focus-inner{padding:0;border:0}.pure-button-group{letter-spacing:-.31em;text-rendering:optimizespeed}.opera-only :-o-prefocus,.pure-button-group{word-spacing:-0.43em}.pure-button-group .pure-button{letter-spacing:normal;word-spacing:normal;vertical-align:top;text-rendering:auto}.pure-button{font-family:inherit;font-size:100%;padding:.5em 1em;color:rgba(0,0,0,.8);border:none transparent;background-color:#e6e6e6;text-decoration:none;border-radius:2px}.pure-button-hover,.pure-button:focus,.pure-button:hover{background-image:-webkit-gradient(linear,left top,left bottom,from(transparent),color-stop(40%,rgba(0,0,0,.05)),to(rgba(0,0,0,.1)));background-image:linear-gradient(transparent,rgba(0,0,0,.05) 40%,rgba(0,0,0,.1))}.pure-button:focus{outline:0}.pure-button-active,.pure-button:active{-webkit-box-shadow:0 0 0 1px rgba(0,0,0,.15) inset,0 0 6px rgba(0,0,0,.2) inset;box-shadow:0 0 0 1px rgba(0,0,0,.15) inset,0 0 6px rgba(0,0,0,.2) inset;border-color:#000}.pure-button-disabled,.pure-button-disabled:active,.pure-button-disabled:focus,.pure-button-disabled:hover,.pure-button[disabled]{border:none;background-image:none;opacity:.4;cursor:not-allowed;-webkit-box-shadow:none;box-shadow:none;pointer-events:none}.pure-button-hidden{display:none}.pure-button-primary,.pure-button-selected,a.pure-button-primary,a.pure-button-selected{background-color:#0078e7;color:#fff}.pure-button-group .pure-button{margin:0;border-radius:0;border-right:1px solid rgba(0,0,0,.2)}.pure-button-group .pure-button:first-child{border-top-left-radius:2px;border-bottom-left-radius:2px}.pure-button-group .pure-button:last-child{border-top-right-radius:2px;border-bottom-right-radius:2px;border-right:none}.pure-form input[type=color],.pure-form input[type=date],.pure-form input[type=datetime-local],.pure-form input[type=datetime],.pure-form input[type=email],.pure-form input[type=month],.pure-form input[type=number],.pure-form input[type=password],.pure-form input[type=search],.pure-form input[type=tel],.pure-form input[type=text],.pure-form input[type=time],.pure-form input[type=url],.pure-form input[type=week],.pure-form select,.pure-form textarea{padding:.5em .6em;display:inline-block;border:1px solid #ccc;-webkit-box-shadow:inset 0 1px 3px #ddd;box-shadow:inset 0 1px 3px #ddd;border-radius:4px;vertical-align:middle;-webkit-box-sizing:border-box;box-sizing:border-box}.pure-form input:not([type]){padding:.5em .6em;display:inline-block;border:1px solid #ccc;-webkit-box-shadow:inset 0 1px 3px #ddd;box-shadow:inset 0 1px 3px #ddd;border-radius:4px;-webkit-box-sizing:border-box;box-sizing:border-box}.pure-form input[type=color]{padding:.2em .5em}.pure-form input[type=color]:focus,.pure-form input[type=date]:focus,.pure-form input[type=datetime-local]:focus,.pure-form input[type=datetime]:focus,.pure-form input[type=email]:focus,.pure-form input[type=month]:focus,.pure-form input[type=number]:focus,.pure-form input[type=password]:focus,.pure-form input[type=search]:focus,.pure-form input[type=tel]:focus,.pure-form input[type=text]:focus,.pure-form input[type=time]:focus,.pure-form input[type=url]:focus,.pure-form input[type=week]:focus,.pure-form select:focus,.pure-form textarea:focus{outline:0;border-color:#129fea}.pure-form input:not([type]):focus{outline:0;border-color:#129fea}.pure-form input[type=checkbox]:focus,.pure-form input[type=file]:focus,.pure-form input[type=radio]:focus{outline:thin solid #129FEA;outline:1px auto #129FEA}.pure-form .pure-checkbox,.pure-form .pure-radio{margin:.5em 0;display:block}.pure-form input[type=color][disabled],.pure-form input[type=date][disabled],.pure-form input[type=datetime-local][disabled],.pure-form input[type=datetime][disabled],.pure-form input[type=email][disabled],.pure-form input[type=month][disabled],.pure-form input[type=number][disabled],.pure-form input[type=password][disabled],.pure-form input[type=search][disabled],.pure-form input[type=tel][disabled],.pure-form input[type=text][disabled],.pure-form input[type=time][disabled],.pure-form input[type=url][disabled],.pure-form input[type=week][disabled],.pure-form select[disabled],.pure-form textarea[disabled]{cursor:not-allowed;background-color:#eaeded;color:#cad2d3}.pure-form input:not([type])[disabled]{cursor:not-allowed;background-color:#eaeded;color:#cad2d3}.pure-form input[readonly],.pure-form select[readonly],.pure-form textarea[readonly]{background-color:#eee;color:#777;border-color:#ccc}.pure-form input:focus:invalid,.pure-form select:focus:invalid,.pure-form textarea:focus:invalid{color:#b94a48;border-color:#e9322d}.pure-form input[type=checkbox]:focus:invalid:focus,.pure-form input[type=file]:focus:invalid:focus,.pure-form input[type=radio]:focus:invalid:focus{outline-color:#e9322d}.pure-form select{height:2.25em;border:1px solid #ccc;background-color:#fff}.pure-form select[multiple]{height:auto}.pure-form label{margin:.5em 0 .2em}.pure-form fieldset{margin:0;padding:.35em 0 .75em;border:0}.pure-form legend{display:block;width:100%;padding:.3em 0;margin-bottom:.3em;color:#333;border-bottom:1px solid #e5e5e5}.pure-form-stacked input[type=color],.pure-form-stacked input[type=date],.pure-form-stacked input[type=datetime-local],.pure-form-stacked input[type=datetime],.pure-form-stacked input[type=email],.pure-form-stacked input[type=file],.pure-form-stacked input[type=month],.pure-form-stacked input[type=number],.pure-form-stacked input[type=password],.pure-form-stacked input[type=search],.pure-form-stacked input[type=tel],.pure-form-stacked input[type=text],.pure-form-stacked input[type=time],.pure-form-stacked input[type=url],.pure-form-stacked input[type=week],.pure-form-stacked label,.pure-form-stacked select,.pure-form-stacked textarea{display:block;margin:.25em 0}.pure-form-stacked input:not([type]){display:block;margin:.25em 0}.pure-form-aligned input,.pure-form-aligned select,.pure-form-aligned textarea,.pure-form-message-inline{display:inline-block;vertical-align:middle}.pure-form-aligned textarea{vertical-align:top}.pure-form-aligned .pure-control-group{margin-bottom:.5em}.pure-form-aligned .pure-control-group label{text-align:right;display:inline-block;vertical-align:middle;width:10em;margin:0 1em 0 0}.pure-form-aligned .pure-controls{margin:1.5em 0 0 11em}.pure-form .pure-input-rounded,.pure-form input.pure-input-rounded{border-radius:2em;padding:.5em 1em}.pure-form .pure-group fieldset{margin-bottom:10px}.pure-form .pure-group input,.pure-form .pure-group textarea{display:block;padding:10px;margin:0 0 -1px;border-radius:0;position:relative;top:-1px}.pure-form .pure-group input:focus,.pure-form .pure-group textarea:focus{z-index:3}.pure-form .pure-group input:first-child,.pure-form .pure-group textarea:first-child{top:1px;border-radius:4px 4px 0 0;margin:0}.pure-form .pure-group input:first-child:last-child,.pure-form .pure-group textarea:first-child:last-child{top:1px;border-radius:4px;margin:0}.pure-form .pure-group input:last-child,.pure-form .pure-group textarea:last-child{top:-2px;border-radius:0 0 4px 4px;margin:0}.pure-form .pure-group button{margin:.35em 0}.pure-form .pure-input-1{width:100%}.pure-form .pure-input-3-4{width:75%}.pure-form .pure-input-2-3{width:66%}.pure-form .pure-input-1-2{width:50%}.pure-form .pure-input-1-3{width:33%}.pure-form .pure-input-1-4{width:25%}.pure-form-message-inline{display:inline-block;padding-left:.3em;color:#666;vertical-align:middle;font-size:.875em}.pure-form-message{display:block;color:#666;font-size:.875em}@media only screen and (max-width :480px){.pure-form button[type=submit]{margin:.7em 0 0}.pure-form input:not([type]),.pure-form input[type=color],.pure-form input[type=date],.pure-form input[type=datetime-local],.pure-form input[type=datetime],.pure-form input[type=email],.pure-form input[type=month],.pure-form input[type=number],.pure-form input[type=password],.pure-form input[type=search],.pure-form input[type=tel],.pure-form input[type=text],.pure-form input[type=time],.pure-form input[type=url],.pure-form input[type=week],.pure-form label{margin-bottom:.3em;display:block}.pure-group input:not([type]),.pure-group input[type=color],.pure-group input[type=date],.pure-group input[type=datetime-local],.pure-group input[type=datetime],.pure-group input[type=email],.pure-group input[type=month],.pure-group input[type=number],.pure-group input[type=password],.pure-group input[type=search],.pure-group input[type=tel],.pure-group input[type=text],.pure-group input[type=time],.pure-group input[type=url],.pure-group input[type=week]{margin-bottom:0}.pure-form-aligned .pure-control-group label{margin-bottom:.3em;text-align:left;display:block;width:100%}.pure-form-aligned .pure-controls{margin:1.5em 0 0 0}.pure-form-message,.pure-form-message-inline{display:block;font-size:.75em;padding:.2em 0 .8em}}.pure-menu{-webkit-box-sizing:border-box;box-sizing:border-box}.pure-menu-fixed{position:fixed;left:0;top:0;z-index:3}.pure-menu-item,.pure-menu-list{position:relative}.pure-menu-list{list-style:none;margin:0;padding:0}.pure-menu-item{padding:0;margin:0;height:100%}.pure-menu-heading,.pure-menu-link{display:block;text-decoration:none;white-space:nowrap}.pure-menu-horizontal{width:100%;white-space:nowrap}.pure-menu-horizontal .pure-menu-list{display:inline-block}.pure-menu-horizontal .pure-menu-heading,.pure-menu-horizontal .pure-menu-item,.pure-menu-horizontal .pure-menu-separator{display:inline-block;vertical-align:middle}.pure-menu-item .pure-menu-item{display:block}.pure-menu-children{display:none;position:absolute;left:100%;top:0;margin:0;padding:0;z-index:3}.pure-menu-horizontal .pure-menu-children{left:0;top:auto;width:inherit}.pure-menu-active>.pure-menu-children,.pure-menu-allow-hover:hover>.pure-menu-children{display:block;position:absolute}.pure-menu-has-children>.pure-menu-link:after{padding-left:.5em;content:"\25B8";font-size:small}.pure-menu-horizontal .pure-menu-has-children>.pure-menu-link:after{content:"\25BE"}.pure-menu-scrollable{overflow-y:scroll;overflow-x:hidden}.pure-menu-scrollable .pure-menu-list{display:block}.pure-menu-horizontal.pure-menu-scrollable .pure-menu-list{display:inline-block}.pure-menu-horizontal.pure-menu-scrollable{white-space:nowrap;overflow-y:hidden;overflow-x:auto;padding:.5em 0}.pure-menu-horizontal .pure-menu-children .pure-menu-separator,.pure-menu-separator{background-color:#ccc;height:1px;margin:.3em 0}.pure-menu-horizontal .pure-menu-separator{width:1px;height:1.3em;margin:0 .3em}.pure-menu-horizontal .pure-menu-children .pure-menu-separator{display:block;width:auto}.pure-menu-heading{text-transform:uppercase;color:#565d64}.pure-menu-link{color:#777}.pure-menu-children{background-color:#fff}.pure-menu-heading,.pure-menu-link{padding:.5em 1em}.pure-menu-disabled{opacity:.5}.pure-menu-disabled .pure-menu-link:hover{background-color:transparent;cursor:default}.pure-menu-active>.pure-menu-link,.pure-menu-link:focus,.pure-menu-link:hover{background-color:#eee}.pure-menu-selected>.pure-menu-link,.pure-menu-selected>.pure-menu-link:visited{color:#000}.pure-table{border-collapse:collapse;border-spacing:0;empty-cells:show;border:1px solid #cbcbcb}.pure-table caption{color:#000;font:italic 85%/1 arial,sans-serif;padding:1em 0;text-align:center}.pure-table td,.pure-table th{border-left:1px solid #cbcbcb;border-width:0 0 0 1px;font-size:inherit;margin:0;overflow:visible;padding:.5em 1em}.pure-table thead{background-color:#e0e0e0;color:#000;text-align:left;vertical-align:bottom}.pure-table td{background-color:transparent}.pure-table-odd td{background-color:#f2f2f2}.pure-table-striped tr:nth-child(2n-1) td{background-color:#f2f2f2}.pure-table-bordered td{border-bottom:1px solid #cbcbcb}.pure-table-bordered tbody>tr:last-child>td{border-bottom-width:0}.pure-table-horizontal td,.pure-table-horizontal th{border-width:0 0 1px 0;border-bottom:1px solid #cbcbcb}.pure-table-horizontal tbody>tr:last-child>td{border-bottom-width:0}
\ No newline at end of file
diff --git a/html/index.html b/html/index.html
new file mode 100644
index 0000000..d76f9ee
--- /dev/null
+++ b/html/index.html
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ World Database
+
+
+
+
+
+
World Database
+
+
+
+
+ Name |
+ District |
+ Country |
+ Population |
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/html/js/app.js b/html/js/app.js
new file mode 100644
index 0000000..96290e8
--- /dev/null
+++ b/html/js/app.js
@@ -0,0 +1,53 @@
+'use strict';
+
+var CITY_QUERY_URL_PREFIX = 'http://localhost:3000/city?name=ilike.'
+
+var app = {};
+
+app.addResultRows = function (rows) {
+ var rowsString = '';
+ var rowsLength = rows.length;
+
+ if (rowsLength > 0) {
+ for (var i = 0; i < rowsLength; i++) {
+ rowsString += app.buildResultRowString(rows[i]);
+ }
+ } else {
+ rowsString = 'Results not found |
';
+ }
+
+ document.getElementById('results-table-body').innerHTML = rowsString;
+ app.showElement('results-table');
+}
+
+app.buildResultRowString = function (row) {
+ return '' +
+ '' + row.name + ' | ' +
+ '' + row.district + ' | ' +
+ '' + row.countrycode + ' | ' +
+ '' + row.population + ' | ' +
+ '
';
+}
+
+app.showElement = function (id) {
+ document.getElementById(id).classList.remove('hidden');
+}
+
+app.queryCity = function (cityName) {
+ var queryURL = CITY_QUERY_URL_PREFIX + '*' + cityName + '*';
+
+ fetch(queryURL)
+ .then(function(response) {
+ return response.json();
+ })
+ .then(function (j) {
+ console.log(j);
+ app.addResultRows(j);
+ })
+}
+
+app.searchClick = function () {
+ var city = document.getElementById('city-input').value;
+
+ app.queryCity(city);
+}
\ No newline at end of file
diff --git a/initdb/1_create_anon_role.sh b/initdb/1_create_anon_role.sh
new file mode 100644
index 0000000..08883dc
--- /dev/null
+++ b/initdb/1_create_anon_role.sh
@@ -0,0 +1,9 @@
+#!/bin/bash
+
+psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-END
+ CREATE USER ${DB_ANON_ROLE};
+ GRANT USAGE ON SCHEMA ${DB_SCHEMA} TO ${DB_ANON_ROLE};
+ ALTER DEFAULT PRIVILEGES IN SCHEMA ${DB_SCHEMA} GRANT SELECT ON TABLES TO ${DB_ANON_ROLE};
+ GRANT SELECT ON ALL SEQUENCES IN SCHEMA ${DB_SCHEMA} TO ${DB_ANON_ROLE};
+ GRANT SELECT ON ALL TABLES IN SCHEMA ${DB_SCHEMA} TO ${DB_ANON_ROLE};
+END
diff --git a/initdb/2_create_finess_database.sql b/initdb/2_create_finess_database.sql
new file mode 100644
index 0000000..d123539
--- /dev/null
+++ b/initdb/2_create_finess_database.sql
@@ -0,0 +1,45 @@
+--
+-- PostgreSQL port of the MySQL "World" database.
+--
+-- The sample data used in the world database is Copyrighted.
+-- Statistics Finland, http://www.stat.fi/worldinfigures
+--
+BEGIN;
+
+SET client_encoding = 'LATIN1';
+
+CREATE TABLE IF NOT EXISTS finess (
+ nofinesset VARCHAR(255),
+ nofinessej VARCHAR(255),
+ rs VARCHAR(255),
+ rslongue VARCHAR(255),
+ complrs VARCHAR(255),
+ compldistrib VARCHAR(255),
+ numvoie VARCHAR(255),
+ typvoie VARCHAR(255),
+ voie VARCHAR(255),
+ compvoie VARCHAR(255),
+ lieuditbp VARCHAR(255),
+ commune VARCHAR(255),
+ departement VARCHAR(255),
+ libdepartement VARCHAR(255),
+ ligneacheminement VARCHAR(255),
+ telephone VARCHAR(255),
+ telecopie VARCHAR(255),
+ categetab VARCHAR(255),
+ libcategetab VARCHAR(255),
+ categagretab VARCHAR(255),
+ libcategagretab VARCHAR(255),
+ siret VARCHAR(255),
+ codeape VARCHAR(255),
+ codemft VARCHAR(255),
+ libmft VARCHAR(255),
+ codesph VARCHAR(255),
+ libsph VARCHAR(255),
+ dateouv DATE DEFAULT '1900-01-01',
+ dateautor DATE DEFAULT '1900-01-01',
+ datemaj DATE DEFAULT '1900-01-01',
+ numuai VARCHAR(255),
+ coordxet FLOAT DEFAULT 0,
+ coordyet FLOAT DEFAULT 0
+);
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 0000000..7a963f1
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,194 @@
+{
+ "name": "data",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "dependencies": {
+ "@etalab/decoupage-administratif": "^3.1.1",
+ "csv-parse": "^5.5.3",
+ "pg": "^8.11.3",
+ "proj4": "^2.10.0"
+ }
+ },
+ "node_modules/@etalab/decoupage-administratif": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/@etalab/decoupage-administratif/-/decoupage-administratif-3.1.1.tgz",
+ "integrity": "sha512-/1yqSlo6Xerdz1MN+rh57hDWcAam18gwSK5u4wFjT1glRUiN/o1A4IQe6pvB9JqGvHv6WbF5X7WyE+yxeMqLig==",
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/buffer-writer": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz",
+ "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/csv-parse": {
+ "version": "5.5.3",
+ "resolved": "https://registry.npmjs.org/csv-parse/-/csv-parse-5.5.3.tgz",
+ "integrity": "sha512-v0KW6C0qlZzoGjk6u5tLmVfyZxNgPGXZsWTXshpAgKVGmGXzaVWGdlCFxNx5iuzcXT/oJN1HHM9DZKwtAtYa+A=="
+ },
+ "node_modules/mgrs": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/mgrs/-/mgrs-1.0.0.tgz",
+ "integrity": "sha512-awNbTOqCxK1DBGjalK3xqWIstBZgN6fxsMSiXLs9/spqWkF2pAhb2rrYCFSsr1/tT7PhcDGjZndG8SWYn0byYA=="
+ },
+ "node_modules/packet-reader": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz",
+ "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ=="
+ },
+ "node_modules/pg": {
+ "version": "8.11.3",
+ "resolved": "https://registry.npmjs.org/pg/-/pg-8.11.3.tgz",
+ "integrity": "sha512-+9iuvG8QfaaUrrph+kpF24cXkH1YOOUeArRNYIxq1viYHZagBxrTno7cecY1Fa44tJeZvaoG+Djpkc3JwehN5g==",
+ "dependencies": {
+ "buffer-writer": "2.0.0",
+ "packet-reader": "1.0.0",
+ "pg-connection-string": "^2.6.2",
+ "pg-pool": "^3.6.1",
+ "pg-protocol": "^1.6.0",
+ "pg-types": "^2.1.0",
+ "pgpass": "1.x"
+ },
+ "engines": {
+ "node": ">= 8.0.0"
+ },
+ "optionalDependencies": {
+ "pg-cloudflare": "^1.1.1"
+ },
+ "peerDependencies": {
+ "pg-native": ">=3.0.1"
+ },
+ "peerDependenciesMeta": {
+ "pg-native": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/pg-cloudflare": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.1.1.tgz",
+ "integrity": "sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==",
+ "optional": true
+ },
+ "node_modules/pg-connection-string": {
+ "version": "2.6.2",
+ "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.6.2.tgz",
+ "integrity": "sha512-ch6OwaeaPYcova4kKZ15sbJ2hKb/VP48ZD2gE7i1J+L4MspCtBMAx8nMgz7bksc7IojCIIWuEhHibSMFH8m8oA=="
+ },
+ "node_modules/pg-int8": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz",
+ "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==",
+ "engines": {
+ "node": ">=4.0.0"
+ }
+ },
+ "node_modules/pg-pool": {
+ "version": "3.6.1",
+ "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.6.1.tgz",
+ "integrity": "sha512-jizsIzhkIitxCGfPRzJn1ZdcosIt3pz9Sh3V01fm1vZnbnCMgmGl5wvGGdNN2EL9Rmb0EcFoCkixH4Pu+sP9Og==",
+ "peerDependencies": {
+ "pg": ">=8.0"
+ }
+ },
+ "node_modules/pg-protocol": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.6.0.tgz",
+ "integrity": "sha512-M+PDm637OY5WM307051+bsDia5Xej6d9IR4GwJse1qA1DIhiKlksvrneZOYQq42OM+spubpcNYEo2FcKQrDk+Q=="
+ },
+ "node_modules/pg-types": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz",
+ "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==",
+ "dependencies": {
+ "pg-int8": "1.0.1",
+ "postgres-array": "~2.0.0",
+ "postgres-bytea": "~1.0.0",
+ "postgres-date": "~1.0.4",
+ "postgres-interval": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/pgpass": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz",
+ "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==",
+ "dependencies": {
+ "split2": "^4.1.0"
+ }
+ },
+ "node_modules/postgres-array": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz",
+ "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/postgres-bytea": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz",
+ "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/postgres-date": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz",
+ "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/postgres-interval": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz",
+ "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==",
+ "dependencies": {
+ "xtend": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/proj4": {
+ "version": "2.10.0",
+ "resolved": "https://registry.npmjs.org/proj4/-/proj4-2.10.0.tgz",
+ "integrity": "sha512-0eyB8h1PDoWxucnq88/EZqt7UZlvjhcfbXCcINpE7hqRN0iRPWE/4mXINGulNa/FAvK+Ie7F+l2OxH/0uKV36A==",
+ "dependencies": {
+ "mgrs": "1.0.0",
+ "wkt-parser": "^1.3.3"
+ }
+ },
+ "node_modules/split2": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz",
+ "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==",
+ "engines": {
+ "node": ">= 10.x"
+ }
+ },
+ "node_modules/wkt-parser": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/wkt-parser/-/wkt-parser-1.3.3.tgz",
+ "integrity": "sha512-ZnV3yH8/k58ZPACOXeiHaMuXIiaTk1t0hSUVisbO0t4RjA5wPpUytcxeyiN2h+LZRrmuHIh/1UlrR9e7DHDvTw=="
+ },
+ "node_modules/xtend": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
+ "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
+ "engines": {
+ "node": ">=0.4"
+ }
+ }
+ }
+}
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..83d4454
--- /dev/null
+++ b/package.json
@@ -0,0 +1,9 @@
+{
+ "type": "module",
+ "dependencies": {
+ "@etalab/decoupage-administratif": "^3.1.1",
+ "csv-parse": "^5.5.3",
+ "pg": "^8.11.3",
+ "proj4": "^2.10.0"
+ }
+}
diff --git a/scripts/download.js b/scripts/download.js
new file mode 100644
index 0000000..502dc49
--- /dev/null
+++ b/scripts/download.js
@@ -0,0 +1,7 @@
+import { downloadFiness } from './helpers/finess.js'
+
+async function main() {
+ downloadFiness()
+}
+
+main()
diff --git a/scripts/helpers/finess.js b/scripts/helpers/finess.js
new file mode 100644
index 0000000..cdc9ff1
--- /dev/null
+++ b/scripts/helpers/finess.js
@@ -0,0 +1,262 @@
+import fs from 'fs';
+import readline from 'readline';
+import pg from 'pg';
+import { downloadJSON, downloadAndSaveFile, filtrerEtEnregistrerLignes, loadEnvFile } from './functions.js'
+import { transformToGPS } from './gps.js'
+
+const { Pool } = pg
+
+export const downloadFiness = async () => {
+ const MAIN_URL = 'https://www.data.gouv.fr/api/1/datasets/finess-extraction-du-fichier-des-etablissements/'
+ const FILENAME = './tmp/finess.csv'
+
+ const data = await downloadJSON(MAIN_URL);
+ const finessUrl = data.resources.find(r => r.type === "main" && r.title.includes('géolocalisés'))?.url
+
+ downloadAndSaveFile(finessUrl, FILENAME)
+}
+
+export const transformFiness = async () => {
+ const fichierEntree = './tmp/finess.csv';
+ const fichierStructures = './tmp/finess_structureet.csv';
+ const fichierGeolocalisation = './tmp/finess_geolocalisation.csv';
+ const conditionFiltre = (ligne) => ligne.includes('structureet');
+
+ await filtrerEtEnregistrerLignes(fichierEntree, fichierStructures, fichierGeolocalisation, conditionFiltre);
+ await fusionnerCoordonneesGPSStructures(fichierStructures, fichierGeolocalisation, fichierEntree);
+}
+
+export const importFiness = async () => {
+ // Exemple d'utilisation avec le nom du fichier CSV
+ const fichierEntree = './tmp/finess.csv';
+ insererDonneesPostgres(fichierEntree);
+}
+
+// Fonction pour fusionner les coordonnées GPS dans le fichier CSV de structures
+export async function fusionnerCoordonneesGPSStructures(fichierStructures, fichierCoordonnees, fichierSortie) {
+ try {
+ // Créer un flux de lecture pour le fichier de coordonnées Lambert 93
+ const lecteurCoordonnees = readline.createInterface({
+ input: fs.createReadStream(fichierCoordonnees),
+ crlfDelay: Infinity
+ });
+
+ // Créer un dictionnaire pour stocker les coordonnées Lambert 93 par structureid
+ const coordonnees = {};
+
+ // Fonction pour traiter chaque ligne du fichier de coordonnées Lambert 93
+ const traiterLigneCoordonnees = (ligne) => {
+ // exemple de ligne
+ // geolocalisation;970300802;317351.6;571220.2;2,ATLASANTE,100,IGN,BD_ADRESSE,V2.2,UTM_N22;2024-01-08
+ const valeurs = ligne.split(';');
+ const structureid = valeurs[1];
+ const coordX = parseFloat(valeurs[2]);
+ const coordY = parseFloat(valeurs[3]);
+ const system = valeurs[4]
+ coordonnees[structureid] = { system, coordX, coordY };
+ };
+
+ // Lire chaque ligne du fichier de coordonnées Lambert 93
+ for await (const ligne of lecteurCoordonnees) {
+ traiterLigneCoordonnees(ligne);
+ }
+
+ // Créer un flux de lecture pour le fichier de structures
+ const lecteurStructures = readline.createInterface({
+ input: fs.createReadStream(fichierStructures),
+ crlfDelay: Infinity
+ });
+
+ // Créer un flux d'écriture vers le fichier de sortie
+ const fichierSortieStream = fs.createWriteStream(fichierSortie);
+
+ // Écrire l'entête dans le fichier de sortie
+ // fichierSortieStream.write('structureid,nofinesset,coordxet,coordyet,latitude,longitude\n');
+
+ // Fonction pour traiter chaque ligne du fichier de structures
+ const traiterLigneStructures = (ligne) => {
+ const valeurs = ligne.split(';');
+ const structureid = valeurs[1];
+
+ // Vérifier si des coordonnées Lambert 93 existent pour cette structureid
+ if (coordonnees.hasOwnProperty(structureid)) {
+ const { system, coordX, coordY } = coordonnees[structureid];
+ const coordonneesGPS = transformToGPS(system, coordX, coordY);
+
+ if (coordonneesGPS) {
+ // Écrire les valeurs dans le fichier de sortie
+ fichierSortieStream.write(`${ligne};${coordonneesGPS.latitude};${coordonneesGPS.longitude}\n`);
+ } else {
+ // Si aucune coordonnée n'est disponible, écrire la ligne telle quelle dans le fichier de sortie
+ fichierSortieStream.write(`${ligne};;\n`);
+ }
+ } else {
+ // Si aucune coordonnée n'est disponible, écrire la ligne telle quelle dans le fichier de sortie
+ fichierSortieStream.write(`${ligne};;\n`);
+ }
+ };
+
+ // Lire chaque ligne du fichier de structures
+ for await (const ligne of lecteurStructures) {
+ traiterLigneStructures(ligne);
+ }
+
+ console.log('Fusion des coordonnées GPS dans le fichier de structures terminée.');
+
+ } catch (erreur) {
+ console.error(`Erreur lors de la fusion des coordonnées GPS : ${erreur.message}`);
+ }
+}
+
+// Fonction pour lire le fichier CSV et insérer les données dans PostgreSQL
+export async function insererDonneesPostgres(nomFichierCSV) {
+ const envVariables = loadEnvFile()
+
+ const pool = new Pool({
+ user: envVariables.POSTGRES_USER,
+ host: 'localhost',
+ database: envVariables.POSTGRES_DB,
+ password: envVariables.POSTGRES_PASSWORD,
+ port: 5432,
+ max: 10, // Nombre maximum de connexions dans le pool
+ idleTimeoutMillis: 30000, // Délai d'attente maximum pour une connexion avant d'être libérée
+ });
+ const client = await pool.connect();
+
+ const columns = [
+ 'nofinesset',
+ 'nofinessej',
+ 'rs',
+ 'rslongue',
+ 'complrs',
+ 'compldistrib',
+ 'numvoie',
+ 'typvoie',
+ 'voie',
+ 'compvoie',
+ 'lieuditbp',
+ 'commune',
+ 'departement',
+ 'libdepartement',
+ 'ligneacheminement',
+ 'telephone',
+ 'telecopie',
+ 'categetab',
+ 'libcategetab',
+ 'categagretab',
+ 'libcategagretab',
+ 'siret',
+ 'codeape',
+ 'codemft',
+ 'libmft',
+ 'codesph',
+ 'libsph',
+ 'dateouv',
+ 'dateautor',
+ 'datemaj',
+ 'numuai',
+ 'coordxet',
+ 'coordyet'
+ ];
+
+ // Fonction pour insérer une ligne dans la base de données
+ async function insertRow(data) {
+ const query = {
+ text: `INSERT INTO finess (${columns.join(', ')}) VALUES (${columns.map((col, index) => `$${index + 1}`).join(', ')})`,
+ values: data,
+ };
+
+ const client = await pool.connect();
+
+ try {
+ await client.query(query);
+ } catch (error) {
+ console.log(data.join(', '))
+ console.error('Erreur lors de l\'insertion de la ligne:', error.message || error);
+ } finally {
+ client.release(); // Libérer la connexion du pool
+ }
+ }
+
+ // Fonction pour lire le fichier ligne par ligne et appeler la fonction d'insertion
+ async function processFile(filePath) {
+ const fileStream = fs.createReadStream(filePath);
+ const rl = readline.createInterface({
+ input: fileStream,
+ crlfDelay: Infinity,
+ });
+
+ for await (const [index, line] of rl) {
+ // Supposons que les données dans le fichier soient séparées par des virgules (à ajuster selon votre format)
+ let data = line.split(';');
+ data.shift();
+ if (data[27] === '') data[27] = null
+ if (data[28] === '') data[28] = null
+ if (data[29] === '') data[29] = null
+
+ // Appeler la fonction d'insertion avec la ligne de données
+ await insertRow(data);
+ console.log(index)
+ }
+
+ // Fermer le pool de connexions à la base de données à la fin du traitement
+ await pool.end();
+ }
+
+ // await creerTableFINESS(client);
+ await processFile(nomFichierCSV)
+}
+
+// Fonction pour créer la table FINESS dans PostgreSQL
+export async function creerTableFINESS(client) {
+ try {
+ // Requête SQL de création de table
+ const requeteCreationTable = `
+ CREATE TABLE IF NOT EXISTS finess (
+ nofinesset VARCHAR(255),
+ nofinessej VARCHAR(255),
+ rs VARCHAR(255),
+ rslongue VARCHAR(255),
+ complrs VARCHAR(255),
+ compldistrib VARCHAR(255),
+ numvoie VARCHAR(255),
+ typvoie VARCHAR(255),
+ voie VARCHAR(255),
+ compvoie VARCHAR(255),
+ lieuditbp VARCHAR(255),
+ commune VARCHAR(255),
+ departement VARCHAR(255),
+ libdepartement VARCHAR(255),
+ ligneacheminement VARCHAR(255),
+ telephone VARCHAR(255),
+ telecopie VARCHAR(255),
+ categetab VARCHAR(255),
+ libcategetab VARCHAR(255),
+ categagretab VARCHAR(255),
+ libcategagretab VARCHAR(255),
+ siret VARCHAR(255),
+ codeape VARCHAR(255),
+ codemft VARCHAR(255),
+ libmft VARCHAR(255),
+ codesph VARCHAR(255),
+ libsph VARCHAR(255),
+ dateouv DATE DEFAULT '1900-01-01',
+ dateautor DATE DEFAULT '1900-01-01',
+ datemaj DATE DEFAULT '1900-01-01',
+ numuai VARCHAR(255),
+ coordxet FLOAT DEFAULT 0,
+ coordyet FLOAT DEFAULT 0,
+ PRIMARY KEY (nofinesset)
+ );
+ `;
+
+ // Exécution de la requête de création de table
+ await client.query(requeteCreationTable);
+
+ console.log('Table FINESS créée avec succès.');
+
+ } catch (erreur) {
+ console.error(`Erreur lors de la création de la table : ${erreur.message}`);
+ }
+}
+
diff --git a/scripts/helpers/functions.js b/scripts/helpers/functions.js
new file mode 100644
index 0000000..8f5bfda
--- /dev/null
+++ b/scripts/helpers/functions.js
@@ -0,0 +1,72 @@
+import path from 'path';
+import fs from 'fs'
+import { writeFile, mkdir } from 'fs/promises'
+import readline from 'readline';
+
+export const loadEnvFile = () => {
+ // Charger les variables d'environnement à partir du fichier .env
+ const envPath = './.env'; // Spécifiez le chemin correct si différent
+ const envFile = fs.readFileSync(envPath, 'utf-8');
+ const envVariables = envFile.split('\n').reduce((acc, line) => {
+ const [key, value] = line.split('=');
+ if (key && value) {
+ acc[key.trim()] = value.trim();
+ }
+ return acc;
+ }, {});
+
+ return envVariables
+}
+
+export const downloadAndSaveFile = async (url, filename) => {
+ const folder = path.dirname(filename)
+ if (!fs.existsSync(folder)) await mkdir(folder)
+ const response = await fetch(url)
+ const buffer = Buffer.from(await response.arrayBuffer())
+ await writeFile(filename, buffer)
+}
+
+export const downloadJSON = async (url) => (await fetch(url)).json()
+
+// Fonction pour lire un fichier ligne par ligne et filtrer les lignes en fonction de la condition
+export async function filtrerEtEnregistrerLignes(fichierEntree, fichierSortie1, fichierSortie2, condition) {
+ try {
+ // Créer un flux de lecture pour le fichier d'entrée
+ const lecteur = readline.createInterface({
+ input: fs.createReadStream(fichierEntree),
+ crlfDelay: Infinity
+ });
+
+ // Créer un flux d'écriture pour le fichier de sortie 1
+ const fichierSortieStream1 = fs.createWriteStream(fichierSortie1);
+
+ // Créer un flux d'écriture pour le fichier de sortie 2
+ const fichierSortieStream2 = fs.createWriteStream(fichierSortie2);
+
+ // Fonction pour traiter chaque ligne du fichier
+ const traiterLigne = (ligne) => {
+ // Appliquer la condition à la ligne
+ if (condition(ligne)) {
+ // Écrire la ligne dans le fichier de sortie 1
+ fichierSortieStream1.write(`${ligne}\n`);
+ } else {
+ // Écrire la ligne dans le fichier de sortie 2
+ fichierSortieStream2.write(`${ligne}\n`);
+ }
+ };
+
+ // Lire chaque ligne du fichier
+ for await (const ligne of lecteur) {
+ traiterLigne(ligne);
+ }
+
+ console.log('Filtrage et enregistrement des lignes terminés.');
+
+ // Fermer les flux d'écriture
+ fichierSortieStream1.end();
+ fichierSortieStream2.end();
+
+ } catch (erreur) {
+ console.error(`Erreur lors du filtrage et de l'enregistrement des lignes : ${erreur.message}`);
+ }
+}
\ No newline at end of file
diff --git a/scripts/helpers/gps.js b/scripts/helpers/gps.js
new file mode 100644
index 0000000..22d5902
--- /dev/null
+++ b/scripts/helpers/gps.js
@@ -0,0 +1,88 @@
+import proj4 from 'proj4'
+
+// Définir les paramètres de la projection WGS84 (EPSG:4326) (GPS)
+proj4.defs('EPSG:4326', '+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs');
+
+// Définir les paramètres de la projection Lambert 93 (EPSG:2154)
+proj4.defs('EPSG:2154', '+proj=lcc +lat_1=49 +lat_2=44 +lat_0=46.5 +lon_0=3 +x_0=700000 +y_0=6600000 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs');
+
+// Définir les paramètres de la projection UTM Zone 20N (EPSG:32620)
+proj4.defs('EPSG:32620', '+proj=utm +zone=20 +ellps=WGS84 +datum=WGS84 +units=m +no_defs');
+
+// Définir les paramètres de la projection UTM_N21 (exemple)
+proj4.defs('EPSG:32621', '+proj=utm +zone=21 +ellps=WGS84 +datum=WGS84 +units=m +no_defs');
+
+// Définir les paramètres de la projection UTM_N22 (exemple)
+proj4.defs('EPSG:32622', '+proj=utm +zone=22 +ellps=WGS84 +datum=WGS84 +units=m +no_defs');
+
+// Définir les paramètres de la projection UTM_S38 (exemple)
+proj4.defs('EPSG:32638', '+proj=utm +zone=38 +ellps=WGS84 +datum=WGS84 +units=m +no_defs');
+
+// Définir les paramètres de la projection UTM_S40 (exemple)
+proj4.defs('EPSG:32740', '+proj=utm +zone=40 +ellps=WGS84 +datum=WGS84 +units=m +no_defs');
+
+
+export const transformToGPS = (system, coordX, coordY, ) => {
+ if (system.includes('LAMBERT_93')) {
+ return lambert93toGPS(coordX, coordY)
+ }
+ if (system.includes('UTM_N20')) {
+ return utmN20toGPS(coordX, coordY)
+ }
+ if (system.includes('UTM_N21')) {
+ return utmN21toGPS(coordX, coordY)
+ }
+ if (system.includes('UTM_N22')) {
+ return utmN22toGPS(coordX, coordY)
+ }
+ if (system.includes('UTM_S38')) {
+ return utmS38toGPS(coordX, coordY)
+ }
+ if (system.includes('UTM_S40')) {
+ return utmS40toGPS(coordX, coordY)
+ }
+
+ console.error(system);
+}
+
+function lambert93toGPS(easting, northing) {
+ // Convertir les coordonnées Lambert 93 en WGS84 (GPS)
+ const [longitude, latitude] = proj4('EPSG:2154', 'EPSG:4326', [easting, northing]);
+
+ return { latitude, longitude };
+}
+
+function utmN20toGPS(easting, northing) {
+ // Convertir les coordonnées UTM en WGS84 (GPS)
+ const [longitude, latitude] = proj4('EPSG:32620', 'EPSG:4326', [easting, northing]);
+
+ return { latitude, longitude };
+}
+
+function utmN21toGPS(easting, northing) {
+ // Convertir les coordonnées UTM_N21 en WGS84 (GPS)
+ const [longitude, latitude] = proj4('EPSG:32621', 'EPSG:4326', [easting, northing]);
+
+ return { latitude, longitude };
+}
+
+function utmN22toGPS(easting, northing) {
+ // Convertir les coordonnées UTM_N22 en WGS84 (GPS)
+ const [longitude, latitude] = proj4('EPSG:32622', 'EPSG:4326', [easting, northing]);
+
+ return { latitude, longitude };
+}
+
+function utmS38toGPS(easting, northing) {
+ // Convertir les coordonnées UTM_S38 en WGS84 (GPS)
+ const [longitude, latitude] = proj4('EPSG:32638', 'EPSG:4326', [easting, northing]);
+
+ return { latitude, longitude };
+}
+
+function utmS40toGPS(easting, northing) {
+ // Convertir les coordonnées UTM_S40 en WGS84 (GPS)
+ const [longitude, latitude] = proj4('EPSG:32740', 'EPSG:4326', [easting, northing]);
+
+ return { latitude, longitude };
+}
diff --git a/scripts/import.js b/scripts/import.js
new file mode 100644
index 0000000..3fae873
--- /dev/null
+++ b/scripts/import.js
@@ -0,0 +1,7 @@
+import { importFiness } from './helpers/finess.js'
+
+async function main() {
+ importFiness()
+}
+
+main()
diff --git a/scripts/transform.js b/scripts/transform.js
new file mode 100644
index 0000000..b24e80b
--- /dev/null
+++ b/scripts/transform.js
@@ -0,0 +1,7 @@
+import { transformFiness } from './helpers/finess.js'
+
+async function main() {
+ await transformFiness()
+}
+
+main()