@tricoteuses/senat 2.9.7 → 2.9.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE.md CHANGED
@@ -1,22 +1,22 @@
1
- # Tricoteuses-Senat
2
-
3
- ## _Handle French Sénat's open data_
4
-
5
- By: Emmanuel Raviart <mailto:emmanuel@raviart.com>
6
-
7
- Copyright (C) 2019, 2020, 2021 Emmanuel Raviart
8
-
9
- https://git.tricoteuses.fr/logiciels/tricoteuses-senat
10
-
11
- > Tricoteuses-Senat is free software; you can redistribute it and/or modify
12
- > it under the terms of the GNU Affero General Public License as
13
- > published by the Free Software Foundation, either version 3 of the
14
- > License, or (at your option) any later version.
15
- >
16
- > Tricoteuses-Senat is distributed in the hope that it will be useful,
17
- > but WITHOUT ANY WARRANTY; without even the implied warranty of
18
- > MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19
- > GNU Affero General Public License for more details.
20
- >
21
- > You should have received a copy of the GNU Affero General Public License
22
- > along with this program. If not, see <http://www.gnu.org/licenses/>.
1
+ # Tricoteuses-Senat
2
+
3
+ ## _Handle French Sénat's open data_
4
+
5
+ By: Emmanuel Raviart <mailto:emmanuel@raviart.com>
6
+
7
+ Copyright (C) 2019, 2020, 2021 Emmanuel Raviart
8
+
9
+ https://git.tricoteuses.fr/logiciels/tricoteuses-senat
10
+
11
+ > Tricoteuses-Senat is free software; you can redistribute it and/or modify
12
+ > it under the terms of the GNU Affero General Public License as
13
+ > published by the Free Software Foundation, either version 3 of the
14
+ > License, or (at your option) any later version.
15
+ >
16
+ > Tricoteuses-Senat is distributed in the hope that it will be useful,
17
+ > but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+ > MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19
+ > GNU Affero General Public License for more details.
20
+ >
21
+ > You should have received a copy of the GNU Affero General Public License
22
+ > along with this program. If not, see <http://www.gnu.org/licenses/>.
package/README.md CHANGED
@@ -1,116 +1,116 @@
1
- # Tricoteuses-Senat
2
-
3
- ## _Retrieve, clean up & handle French Sénat's open data_
4
-
5
- ## Requirements
6
-
7
- - Node >= 22
8
-
9
- ## Installation
10
-
11
- ```bash
12
- git clone https://git.tricoteuses.fr/logiciels/tricoteuses-senat
13
- cd tricoteuses-senat/
14
- ```
15
-
16
- Create a `.env` file to set PostgreSQL database informations and other configuration variables (you can use `example.env` as a template). Then
17
-
18
- ```bash
19
- npm install
20
- ```
21
-
22
- ### Database creation (not needed if downloading with Docker image)
23
-
24
- #### Using Docker
25
-
26
- ```bash
27
- docker run --name local-postgres -d -p 5432:5432 -e POSTGRES_PASSWORD=$YOUR_CUSTOM_DB_PASSWORD postgres
28
- # Default Postgres user is postgres
29
- # But scripts require an "opendata" role
30
- docker exec -it local-postgres psql -U postgres -c "CREATE ROLE opendata;"
31
- ```
32
-
33
- ## Download data
34
-
35
- Create a folder where the data will be downloaded and run the following command to download the data and convert it into JSON files.
36
-
37
- ```bash
38
- mkdir ../senat-data/
39
-
40
- # Available options for optional `categories` parameter : All, Ameli, Debats, DosLeg, Questions, Sens
41
- npm run data:download ../senat-data -- [--categories All]
42
- ```
43
-
44
- Data from other sources is also available :
45
- ```bash
46
- # Retrieval of textes and rapports from Sénat's website
47
- # Available options for optional `formats` parameter : xml, html, pdf
48
- # Available options for optional `types` parameter : textes, rapports
49
- npm run data:retrieve_documents ../senat-data -- --fromSession 2022 [--formats xml pdf] [--types textes]
50
-
51
- # Retrieval & parsing (textes in xml format only for now)
52
- npm run data:retrieve_documents ../senat-data -- --fromSession 2022 --parseDocuments
53
-
54
- # Parsing only
55
- npm run data:parse_textes_lois ../senat-data
56
-
57
- # Retrieval (& parsing) of agenda from Sénat's website
58
- npm run data:retrieve_agenda ../senat-data -- --fromSession 2022 [--parseAgenda]
59
-
60
- # Retrieval (& parsing) of comptes-rendus des débats from Sénat's website
61
- npm run data:retrieve_comptes_rendus ../senat-data -- [--parseDebats]
62
-
63
- # Retrieval of sénateurs' pictures from Sénat's website
64
- npm run data:retrieve_senateurs_photos ../senat-data
65
- ```
66
-
67
- ## Data download using Docker
68
-
69
- A Docker image that downloads and converts the data all at once is available. Build it locally or run it from the container registry.
70
- Use the environment variables `FROM_SESSION` and `CATEGORIES` if needed.
71
-
72
- ```bash
73
- docker run --pull always --name tricoteuses-senat -v ../senat-data:/app/senat-data -d git.tricoteuses.fr/logiciels/tricoteuses-senat:latest
74
- ```
75
-
76
- Use the environment variable `CATEGORIES` and `FROM_SESSION` if needed.
77
-
78
- ## Using the data
79
-
80
- Once the data is downloaded, you can use loaders to retrieve it.
81
- To use loaders in your project, you can install the _@tricoteuses/senat_ package, and import the iterator functions that you need.
82
-
83
- ```bash
84
- npm install @tricoteuses/senat
85
- ```
86
-
87
- ```js
88
- import { iterLoadSenatQuestions } from "@tricoteuses/senat/loaders"
89
-
90
- // Pass data directory and legislature as arguments
91
- for (const { item: question } of iterLoadSenatQuestions("../senat-data", 17)) {
92
- console.log(question.id)
93
- }
94
- ```
95
-
96
- ## Generation of raw types from SQL schema (for contributors only)
97
-
98
- ```bash
99
- npm run data:generate_schemas ../senat-data
100
- ```
101
-
102
- ## Publishing
103
-
104
- To publish a new version of this package onto npm, bump the package version and publish.
105
-
106
- ```bash
107
- npm version x.y.z # Bumps version in package.json and creates a new tag x.y.z
108
- npx tsc
109
- npm publish
110
- ```
111
-
112
- The Docker image will be automatically built during a CI Workflow if you push the tag to the remote repository.
113
-
114
- ```bash
115
- git push --tags
116
- ```
1
+ # Tricoteuses-Senat
2
+
3
+ ## _Retrieve, clean up & handle French Sénat's open data_
4
+
5
+ ## Requirements
6
+
7
+ - Node >= 22
8
+
9
+ ## Installation
10
+
11
+ ```bash
12
+ git clone https://git.tricoteuses.fr/logiciels/tricoteuses-senat
13
+ cd tricoteuses-senat/
14
+ ```
15
+
16
+ Create a `.env` file to set PostgreSQL database informations and other configuration variables (you can use `example.env` as a template). Then
17
+
18
+ ```bash
19
+ npm install
20
+ ```
21
+
22
+ ### Database creation (not needed if downloading with Docker image)
23
+
24
+ #### Using Docker
25
+
26
+ ```bash
27
+ docker run --name local-postgres -d -p 5432:5432 -e POSTGRES_PASSWORD=$YOUR_CUSTOM_DB_PASSWORD postgres
28
+ # Default Postgres user is postgres
29
+ # But scripts require an "opendata" role
30
+ docker exec -it local-postgres psql -U postgres -c "CREATE ROLE opendata;"
31
+ ```
32
+
33
+ ## Download data
34
+
35
+ Create a folder where the data will be downloaded and run the following command to download the data and convert it into JSON files.
36
+
37
+ ```bash
38
+ mkdir ../senat-data/
39
+
40
+ # Available options for optional `categories` parameter : All, Ameli, Debats, DosLeg, Questions, Sens
41
+ npm run data:download ../senat-data -- [--categories All]
42
+ ```
43
+
44
+ Data from other sources is also available :
45
+ ```bash
46
+ # Retrieval of textes and rapports from Sénat's website
47
+ # Available options for optional `formats` parameter : xml, html, pdf
48
+ # Available options for optional `types` parameter : textes, rapports
49
+ npm run data:retrieve_documents ../senat-data -- --fromSession 2022 [--formats xml pdf] [--types textes]
50
+
51
+ # Retrieval & parsing (textes in xml format only for now)
52
+ npm run data:retrieve_documents ../senat-data -- --fromSession 2022 --parseDocuments
53
+
54
+ # Parsing only
55
+ npm run data:parse_textes_lois ../senat-data
56
+
57
+ # Retrieval (& parsing) of agenda from Sénat's website
58
+ npm run data:retrieve_agenda ../senat-data -- --fromSession 2022 [--parseAgenda]
59
+
60
+ # Retrieval (& parsing) of comptes-rendus des débats from Sénat's website
61
+ npm run data:retrieve_comptes_rendus ../senat-data -- [--parseDebats]
62
+
63
+ # Retrieval of sénateurs' pictures from Sénat's website
64
+ npm run data:retrieve_senateurs_photos ../senat-data
65
+ ```
66
+
67
+ ## Data download using Docker
68
+
69
+ A Docker image that downloads and converts the data all at once is available. Build it locally or run it from the container registry.
70
+ Use the environment variables `FROM_SESSION` and `CATEGORIES` if needed.
71
+
72
+ ```bash
73
+ docker run --pull always --name tricoteuses-senat -v ../senat-data:/app/senat-data -d git.tricoteuses.fr/logiciels/tricoteuses-senat:latest
74
+ ```
75
+
76
+ Use the environment variable `CATEGORIES` and `FROM_SESSION` if needed.
77
+
78
+ ## Using the data
79
+
80
+ Once the data is downloaded, you can use loaders to retrieve it.
81
+ To use loaders in your project, you can install the _@tricoteuses/senat_ package, and import the iterator functions that you need.
82
+
83
+ ```bash
84
+ npm install @tricoteuses/senat
85
+ ```
86
+
87
+ ```js
88
+ import { iterLoadSenatQuestions } from "@tricoteuses/senat/loaders"
89
+
90
+ // Pass data directory and legislature as arguments
91
+ for (const { item: question } of iterLoadSenatQuestions("../senat-data", 17)) {
92
+ console.log(question.id)
93
+ }
94
+ ```
95
+
96
+ ## Generation of raw types from SQL schema (for contributors only)
97
+
98
+ ```bash
99
+ npm run data:generate_schemas ../senat-data
100
+ ```
101
+
102
+ ## Publishing
103
+
104
+ To publish a new version of this package onto npm, bump the package version and publish.
105
+
106
+ ```bash
107
+ npm version x.y.z # Bumps version in package.json and creates a new tag x.y.z
108
+ npx tsc
109
+ npm publish
110
+ ```
111
+
112
+ The Docker image will be automatically built during a CI Workflow if you push the tag to the remote repository.
113
+
114
+ ```bash
115
+ git push --tags
116
+ ```
package/lib/loaders.d.ts CHANGED
@@ -10,6 +10,7 @@ export { EnabledDatasets } from "./datasets";
10
10
  export declare const AGENDA_FOLDER = "agenda";
11
11
  export declare const COMPTES_RENDUS_FOLDER = "seances";
12
12
  export declare const DOSLEG_DOSSIERS_FOLDER = "dossiers";
13
+ export declare const SCRUTINS_FOLDER = "scrutins";
13
14
  export declare const RAPPORT_FOLDER = "rap";
14
15
  export declare const SENS_CIRCONSCRIPTIONS_FOLDER = "circonscriptions";
15
16
  export declare const SENS_ORGANISMES_FOLDER = "organismes";
package/lib/loaders.js CHANGED
@@ -6,6 +6,7 @@ export { EnabledDatasets } from "./datasets";
6
6
  export const AGENDA_FOLDER = "agenda";
7
7
  export const COMPTES_RENDUS_FOLDER = "seances";
8
8
  export const DOSLEG_DOSSIERS_FOLDER = "dossiers";
9
+ export const SCRUTINS_FOLDER = "scrutins";
9
10
  export const RAPPORT_FOLDER = "rap";
10
11
  export const SENS_CIRCONSCRIPTIONS_FOLDER = "circonscriptions";
11
12
  export const SENS_ORGANISMES_FOLDER = "organismes";
@@ -1,7 +1,7 @@
1
1
  import { InferResult } from "kysely";
2
- export type DossierLegislatifResult = InferResult<typeof findAllQuery>[0];
2
+ export type DossierLegislatifResult = InferResult<typeof findAllDossiersQuery>[0];
3
3
  export type AuteurResult = InferResult<typeof findAuteursQuery>[0];
4
- declare const findAllQuery: import("kysely").SelectQueryBuilder<{
4
+ declare const findAllDossiersQuery: import("kysely").SelectQueryBuilder<{
5
5
  ses: import("../raw_types/dosleg").Ses;
6
6
  qua: import("../raw_types/dosleg").Qua;
7
7
  lecture: import("../raw_types/dosleg").Lecture;
@@ -121,7 +121,7 @@ declare const findAllQuery: import("kysely").SelectQueryBuilder<{
121
121
  numero_JO: string | null;
122
122
  url_JO: string | null;
123
123
  }>;
124
- export declare function findAll(): AsyncIterableIterator<{
124
+ export declare function findAllDossiers(): AsyncIterableIterator<{
125
125
  url: string;
126
126
  signet: string;
127
127
  titre: string;
@@ -187,6 +187,32 @@ export declare function findAll(): AsyncIterableIterator<{
187
187
  numero_JO: string | null;
188
188
  url_JO: string | null;
189
189
  }>;
190
+ export declare function findAllScrutins(): AsyncIterableIterator<{
191
+ session: string;
192
+ numero: string;
193
+ date_scrutin: string;
194
+ date_scrutin_effective: string;
195
+ votes: {
196
+ matricule_votant: string;
197
+ matricule_delegant: string | null;
198
+ position: string | null;
199
+ statut_votant: string | null;
200
+ titre_votant: string | null;
201
+ }[];
202
+ lecture_id: string | null;
203
+ intitule: string | null;
204
+ note: string | null;
205
+ nombre_majorite: string | null;
206
+ nombre_majorite_seance: string | null;
207
+ nombre_votants: string | null;
208
+ nombre_votants_seance: string | null;
209
+ nombre_suffrages: string | null;
210
+ nombre_suffrages_seance: string | null;
211
+ nombre_contre: string | null;
212
+ nombre_contre_seance: string | null;
213
+ nombre_pour: string | null;
214
+ nombre_pour_seance: string | null;
215
+ }>;
190
216
  export declare function findSenatTexteUrls(sessions?: number[]): AsyncIterableIterator<{
191
217
  session: string | null | undefined;
192
218
  url: string;
@@ -135,7 +135,47 @@ function themes(loiId) {
135
135
  "the.thelib as libelle",
136
136
  ]));
137
137
  }
138
- const findAllQuery = dbDosleg
138
+ function votes(scrutinNum) {
139
+ return jsonArrayFrom(dbDosleg
140
+ .selectFrom("votsen")
141
+ .leftJoin("titsen", "titsen.titsencod", "votsen.titsencod")
142
+ .leftJoin("stavot", "stavot.stavotidt", "votsen.stavotidt")
143
+ .leftJoin("posvot", "posvot.posvotcod", "votsen.posvotcod")
144
+ .where("votsen.scrnum", "=", scrutinNum)
145
+ .select([
146
+ "votsen.senmat as matricule_votant",
147
+ "votsen.senmatdel as matricule_delegant",
148
+ "posvot.posvotlib as position",
149
+ "stavot.stavotlib as statut_votant",
150
+ "titsen.titsenlib as titre_votant",
151
+ ]));
152
+ }
153
+ const findAllScrutinsQuery = dbDosleg
154
+ .selectFrom("scr")
155
+ .leftJoin("date_seance", "scr.code", "date_seance.code")
156
+ .leftJoin("lecture", "date_seance.lecidt", "lecture.lecidt")
157
+ .select(({ eb, ref, val }) => [
158
+ "scr.sesann as session",
159
+ "scr.scrnum as numero",
160
+ "date_seance.lecidt as lecture_id",
161
+ toDateString(ref("scr.scrdat")).as("date_scrutin"),
162
+ toDateString(ref("scr.scrdateff")).as("date_scrutin_effective"),
163
+ "scr.scrint as intitule",
164
+ "scr.scrbaspag as note",
165
+ "scr.scrmaj as nombre_majorite",
166
+ "scr.scrmajsea as nombre_majorite_seance",
167
+ "scr.scrvot as nombre_votants",
168
+ "scr.scrvotsea as nombre_votants_seance",
169
+ "scr.scrsuf as nombre_suffrages",
170
+ "scr.scrsufsea as nombre_suffrages_seance",
171
+ "scr.scrcon as nombre_contre",
172
+ "scr.scrconsea as nombre_contre_seance",
173
+ "scr.scrpou as nombre_pour",
174
+ "scr.scrpousea as nombre_pour_seance",
175
+ votes(ref("scr.scrnum")).as("votes"),
176
+ ])
177
+ .$narrowType();
178
+ const findAllDossiersQuery = dbDosleg
139
179
  .selectFrom("loi")
140
180
  .leftJoin("typloi", "typloi.typloicod", "loi.typloicod")
141
181
  .leftJoin("etaloi", "etaloi.etaloicod", "loi.etaloicod")
@@ -169,8 +209,11 @@ const findAllQuery = dbDosleg
169
209
  themes(ref("loi.loicod")).as("themes"),
170
210
  ])
171
211
  .$narrowType();
172
- export function findAll() {
173
- return findAllQuery.stream();
212
+ export function findAllDossiers() {
213
+ return findAllDossiersQuery.stream();
214
+ }
215
+ export function findAllScrutins() {
216
+ return findAllScrutinsQuery.stream();
174
217
  }
175
218
  export function findSenatTexteUrls(sessions = []) {
176
219
  const sessionsStr = sessions.map(session => String(session));
@@ -1,5 +1,5 @@
1
1
  export { findAll as findAllAmendements } from "./ameli";
2
2
  export { findAll as findAllDebats } from "./debats";
3
- export { findAll as findAllLois, findAuteur, findAuteurs, findSenatRapportUrls, findSenatTexteUrls, } from "./dosleg";
3
+ export { findAllDossiers, findAllScrutins, findAuteur, findAuteurs, findSenatRapportUrls, findSenatTexteUrls, } from "./dosleg";
4
4
  export { findAll as findAllQuestions } from "./questions";
5
5
  export { findAll as findAllSens, findAllCirconscriptions, findAllOrganismes, } from "./sens";
@@ -1,5 +1,5 @@
1
1
  export { findAll as findAllAmendements } from "./ameli";
2
2
  export { findAll as findAllDebats } from "./debats";
3
- export { findAll as findAllLois, findAuteur, findAuteurs, findSenatRapportUrls, findSenatTexteUrls, } from "./dosleg";
3
+ export { findAllDossiers, findAllScrutins, findAuteur, findAuteurs, findSenatRapportUrls, findSenatTexteUrls, } from "./dosleg";
4
4
  export { findAll as findAllQuestions } from "./questions";
5
5
  export { findAll as findAllSens, findAllCirconscriptions, findAllOrganismes, } from "./sens";
@@ -13,6 +13,7 @@ declare const findAllQuery: import("kysely").SelectQueryBuilder<{
13
13
  stavot: import("../raw_types/sens").Stavot;
14
14
  typorg: import("../raw_types/sens").Typorg;
15
15
  typurl: import("../raw_types/sens").Typurl;
16
+ votes: import("../raw_types/sens").Votes;
16
17
  sen: import("../raw_types/sens").Sen;
17
18
  acr: import("../raw_types/sens").Acr;
18
19
  activite: import("../raw_types/sens").Activite;
@@ -295,7 +296,6 @@ declare const findAllQuery: import("kysely").SelectQueryBuilder<{
295
296
  validation_profil: import("../raw_types/sens").ValidationProfil;
296
297
  vercand: import("../raw_types/sens").Vercand;
297
298
  verres: import("../raw_types/sens").Verres;
298
- votes: import("../raw_types/sens").Votes;
299
299
  zongeo: import("../raw_types/sens").Zongeo;
300
300
  }, "sen" | "com" | "etasen" | "grppol" | "pcs" | "pcs24" | "pcs42" | "pcs8", {
301
301
  matricule: string;
@@ -391,6 +391,7 @@ declare const findAllCirconscriptionsQuery: import("kysely").SelectQueryBuilder<
391
391
  stavot: import("../raw_types/sens").Stavot;
392
392
  typorg: import("../raw_types/sens").Typorg;
393
393
  typurl: import("../raw_types/sens").Typurl;
394
+ votes: import("../raw_types/sens").Votes;
394
395
  sen: import("../raw_types/sens").Sen;
395
396
  acr: import("../raw_types/sens").Acr;
396
397
  activite: import("../raw_types/sens").Activite;
@@ -673,7 +674,6 @@ declare const findAllCirconscriptionsQuery: import("kysely").SelectQueryBuilder<
673
674
  validation_profil: import("../raw_types/sens").ValidationProfil;
674
675
  vercand: import("../raw_types/sens").Vercand;
675
676
  verres: import("../raw_types/sens").Verres;
676
- votes: import("../raw_types/sens").Votes;
677
677
  zongeo: import("../raw_types/sens").Zongeo;
678
678
  }, "dpt" | "reg", {
679
679
  date_debut: string;
@@ -698,6 +698,7 @@ declare const findAllOrganismesQuery: import("kysely").SelectQueryBuilder<{
698
698
  stavot: import("../raw_types/sens").Stavot;
699
699
  typorg: import("kysely").Nullable<import("../raw_types/sens").Typorg>;
700
700
  typurl: import("../raw_types/sens").Typurl;
701
+ votes: import("../raw_types/sens").Votes;
701
702
  sen: import("../raw_types/sens").Sen;
702
703
  acr: import("../raw_types/sens").Acr;
703
704
  activite: import("../raw_types/sens").Activite;
@@ -980,7 +981,6 @@ declare const findAllOrganismesQuery: import("kysely").SelectQueryBuilder<{
980
981
  validation_profil: import("../raw_types/sens").ValidationProfil;
981
982
  vercand: import("../raw_types/sens").Vercand;
982
983
  verres: import("../raw_types/sens").Verres;
983
- votes: import("../raw_types/sens").Votes;
984
984
  zongeo: import("../raw_types/sens").Zongeo;
985
985
  all_organismes: {
986
986
  orgcod: string;
@@ -3,8 +3,8 @@ import commandLineArgs from "command-line-args";
3
3
  import fs from "fs-extra";
4
4
  import path from "path";
5
5
  import { datasets, EnabledDatasets, getEnabledDatasets } from "../datasets";
6
- import { DATA_ORIGINAL_FOLDER, DOCUMENT_METADATA_FILE, DOSLEG_DOSSIERS_FOLDER, RAPPORT_FOLDER, SENS_CIRCONSCRIPTIONS_FOLDER, SENS_ORGANISMES_FOLDER, SENS_SENATEURS_FOLDER, TEXTE_FOLDER, } from "../loaders";
7
- import { findAllAmendements, findAllCirconscriptions, findAllDebats, findAllLois, findAllOrganismes, findAllQuestions, findAllSens, findAuteurs, findSenatRapportUrls, findSenatTexteUrls, } from "../model";
6
+ import { DATA_ORIGINAL_FOLDER, DOCUMENT_METADATA_FILE, DOSLEG_DOSSIERS_FOLDER, SCRUTINS_FOLDER, RAPPORT_FOLDER, SENS_CIRCONSCRIPTIONS_FOLDER, SENS_ORGANISMES_FOLDER, SENS_SENATEURS_FOLDER, TEXTE_FOLDER, } from "../loaders";
7
+ import { findAllAmendements, findAllCirconscriptions, findAllDebats, findAllDossiers, findAllScrutins, findAllOrganismes, findAllQuestions, findAllSens, findAuteurs, findSenatRapportUrls, findSenatTexteUrls, } from "../model";
8
8
  import { UNDEFINED_SESSION } from "../types/sessions";
9
9
  import { getSessionFromDate, getSessionFromSignet } from "./datautil";
10
10
  import { commonOptions } from "./shared/cli_helpers";
@@ -28,6 +28,7 @@ async function convertData() {
28
28
  }
29
29
  if (enabledDatasets & EnabledDatasets.DosLeg) {
30
30
  await convertDatasetDosLeg(dataDir);
31
+ await convertDatasetScrutins(dataDir);
31
32
  }
32
33
  if (enabledDatasets & EnabledDatasets.Questions) {
33
34
  await convertDatasetQuestions(dataDir);
@@ -105,7 +106,7 @@ async function convertDatasetDosLeg(dataDir) {
105
106
  const dossiersReorganizedDir = path.join(doslegReorganizedRootDir, DOSLEG_DOSSIERS_FOLDER);
106
107
  ensureAndClearDir(doslegReorganizedRootDir);
107
108
  ensureAndClearDir(dossiersReorganizedDir);
108
- for await (const loi of findAllLois()) {
109
+ for await (const loi of findAllDossiers()) {
109
110
  if (options["verbose"]) {
110
111
  console.log(`Converting ${loi.signet} file…`);
111
112
  }
@@ -113,14 +114,35 @@ async function convertDatasetDosLeg(dataDir) {
113
114
  const session = getSessionFromSignet(loi.signet) || UNDEFINED_SESSION;
114
115
  loiReorganizedDir = path.join(dossiersReorganizedDir, String(session));
115
116
  fs.ensureDirSync(loiReorganizedDir);
116
- const loiFileName = `${loi.signet}.json`;
117
- fs.writeJSONSync(path.join(loiReorganizedDir, loiFileName), loi, {
117
+ const scrutinFileName = `${loi.signet}.json`;
118
+ fs.writeJSONSync(path.join(loiReorganizedDir, scrutinFileName), loi, {
118
119
  spaces: 2,
119
120
  });
120
121
  }
121
122
  await convertTexteUrls(dataDir);
122
123
  await convertRapportUrls(dataDir);
123
124
  }
125
+ async function convertDatasetScrutins(dataDir) {
126
+ const dataset = datasets.dosleg;
127
+ if (!options["silent"]) {
128
+ console.log(`Converting database ${dataset.database} scrutins data into files…`);
129
+ }
130
+ const scrutinsReorganizedDir = path.join(dataDir, SCRUTINS_FOLDER);
131
+ ensureAndClearDir(scrutinsReorganizedDir);
132
+ for await (const scrutin of findAllScrutins()) {
133
+ if (options["verbose"]) {
134
+ console.log(`Converting ${scrutin.numero} file…`);
135
+ }
136
+ let scrutinReorganizedDir = path.join(scrutinsReorganizedDir, String(UNDEFINED_SESSION));
137
+ const session = scrutin.session || UNDEFINED_SESSION;
138
+ scrutinReorganizedDir = path.join(scrutinsReorganizedDir, String(session));
139
+ fs.ensureDirSync(scrutinReorganizedDir);
140
+ const scrutinFileName = `${scrutin.numero}.json`;
141
+ fs.writeJSONSync(path.join(scrutinReorganizedDir, scrutinFileName), scrutin, {
142
+ spaces: 2,
143
+ });
144
+ }
145
+ }
124
146
  async function convertDatasetQuestions(dataDir) {
125
147
  const dataset = datasets.questions;
126
148
  if (!options["silent"]) {
package/package.json CHANGED
@@ -1,96 +1,97 @@
1
- {
2
- "name": "@tricoteuses/senat",
3
- "version": "2.9.7",
4
- "description": "Handle French Sénat's open data",
5
- "keywords": [
6
- "France",
7
- "open data",
8
- "Parliament",
9
- "Sénat"
10
- ],
11
- "author": "Emmanuel Raviart <emmanuel@raviart.com>",
12
- "bugs": {
13
- "url": "https://git.tricoteuses.fr/logiciels/tricoteuses-senat/issues"
14
- },
15
- "homepage": "https://tricoteuses.fr/",
16
- "license": "AGPL-3.0-or-later",
17
- "repository": {
18
- "type": "git",
19
- "url": "https://git.tricoteuses.fr/logiciels/tricoteuses-senat.git"
20
- },
21
- "type": "module",
22
- "engines": {
23
- "node": ">=22"
24
- },
25
- "files": [
26
- "lib"
27
- ],
28
- "exports": {
29
- ".": {
30
- "import": "./lib/index.js",
31
- "types": "./lib/index.d.ts"
32
- },
33
- "./loaders": {
34
- "import": "./lib/loaders.js",
35
- "types": "./lib/loaders.d.ts"
36
- },
37
- "./package.json": "./package.json"
38
- },
39
- "publishConfig": {
40
- "access": "public"
41
- },
42
- "scripts": {
43
- "build": "tsc",
44
- "build:types": "tsc --emitDeclarationOnly",
45
- "data:convert_data": "tsx src/scripts/convert_data.ts",
46
- "data:download": "tsx src/scripts/data-download.ts",
47
- "data:generate_schemas": "tsx src/scripts/retrieve_open_data.ts --schema",
48
- "data:retrieve_agenda": "cross-env TZ='Etc/UTC' tsx src/scripts/retrieve_agenda.ts",
49
- "data:retrieve_comptes_rendus": "tsx src/scripts/retrieve_comptes_rendus.ts",
50
- "data:retrieve_documents": "tsx src/scripts/retrieve_documents.ts",
51
- "data:retrieve_open_data": "tsx src/scripts/retrieve_open_data.ts --all",
52
- "data:retrieve_senateurs_photos": "tsx src/scripts/retrieve_senateurs_photos.ts --fetch",
53
- "data:retrieve_videos": "tsx src/scripts/retrieve_videos.ts",
54
- "data:parse_textes_lois": "tsx src/scripts/parse_textes.ts",
55
- "prepare": "npm run build",
56
- "prepublishOnly": "npm run build",
57
- "prettier": "prettier --write 'src/**/*.ts' 'tests/**/*.test.ts'",
58
- "type-check": "tsc --noEmit",
59
- "type-check:watch": "npm run type-check -- --watch"
60
- },
61
- "dependencies": {
62
- "@biryani/core": "^0.2.1",
63
- "cheerio": "^1.1.2",
64
- "command-line-args": "^5.1.1",
65
- "dotenv": "^8.2.0",
66
- "fs-extra": "^9.1.0",
67
- "jsdom": "^26.0.0",
68
- "kysely": "^0.27.4",
69
- "luxon": "^3.5.0",
70
- "node-stream-zip": "^1.8.2",
71
- "pg": "^8.13.1",
72
- "pg-cursor": "^2.12.1",
73
- "slug": "^11.0.0",
74
- "tsx": "^4.19.4",
75
- "windows-1252": "^1.0.0"
76
- },
77
- "devDependencies": {
78
- "@typed-code/schemats": "^5.0.1",
79
- "@types/command-line-args": "^5.0.0",
80
- "@types/fs-extra": "^9.0.7",
81
- "@types/jsdom": "^21.1.7",
82
- "@types/luxon": "^3.4.2",
83
- "@types/node": "^20.17.6",
84
- "@types/pg": "^8.11.10",
85
- "@types/pg-cursor": "^2.7.2",
86
- "@types/slug": "^5.0.9",
87
- "@typescript-eslint/eslint-plugin": "^8.13.0",
88
- "@typescript-eslint/parser": "^8.13.0",
89
- "cross-env": "^10.0.0",
90
- "eslint": "^8.57.1",
91
- "kysely-codegen": "^0.18.0",
92
- "prettier": "^3.5.3",
93
- "tslib": "^2.1.0",
94
- "typescript": "^5.8.3"
95
- }
96
- }
1
+ {
2
+ "name": "@tricoteuses/senat",
3
+ "version": "2.9.8",
4
+ "description": "Handle French Sénat's open data",
5
+ "keywords": [
6
+ "France",
7
+ "open data",
8
+ "Parliament",
9
+ "Sénat"
10
+ ],
11
+ "author": "Emmanuel Raviart <emmanuel@raviart.com>",
12
+ "bugs": {
13
+ "url": "https://git.tricoteuses.fr/logiciels/tricoteuses-senat/issues"
14
+ },
15
+ "homepage": "https://tricoteuses.fr/",
16
+ "license": "AGPL-3.0-or-later",
17
+ "repository": {
18
+ "type": "git",
19
+ "url": "https://git.tricoteuses.fr/logiciels/tricoteuses-senat.git"
20
+ },
21
+ "type": "module",
22
+ "engines": {
23
+ "node": ">=22"
24
+ },
25
+ "files": [
26
+ "lib"
27
+ ],
28
+ "exports": {
29
+ ".": {
30
+ "import": "./lib/index.js",
31
+ "types": "./lib/index.d.ts"
32
+ },
33
+ "./loaders": {
34
+ "import": "./lib/loaders.js",
35
+ "types": "./lib/loaders.d.ts"
36
+ },
37
+ "./package.json": "./package.json"
38
+ },
39
+ "publishConfig": {
40
+ "access": "public"
41
+ },
42
+ "scripts": {
43
+ "build": "tsc",
44
+ "build:types": "tsc --emitDeclarationOnly",
45
+ "data:convert_data": "tsx src/scripts/convert_data.ts",
46
+ "data:download": "tsx src/scripts/data-download.ts",
47
+ "data:generate_schemas": "tsx src/scripts/retrieve_open_data.ts --schema",
48
+ "data:retrieve_agenda": "cross-env TZ='Etc/UTC' tsx src/scripts/retrieve_agenda.ts",
49
+ "data:retrieve_comptes_rendus": "tsx src/scripts/retrieve_comptes_rendus.ts",
50
+ "data:retrieve_documents": "tsx src/scripts/retrieve_documents.ts",
51
+ "data:retrieve_open_data": "tsx src/scripts/retrieve_open_data.ts --all",
52
+ "data:retrieve_senateurs_photos": "tsx src/scripts/retrieve_senateurs_photos.ts --fetch",
53
+ "data:retrieve_videos": "tsx src/scripts/retrieve_videos.ts",
54
+ "data:parse_textes_lois": "tsx src/scripts/parse_textes.ts",
55
+ "prepare": "npm run build",
56
+ "prepublishOnly": "npm run build",
57
+ "prettier": "prettier --write 'src/**/*.ts' 'tests/**/*.test.ts'",
58
+ "type-check": "tsc --noEmit",
59
+ "type-check:watch": "npm run type-check -- --watch"
60
+ },
61
+ "dependencies": {
62
+ "@biryani/core": "^0.2.1",
63
+ "cheerio": "^1.1.2",
64
+ "command-line-args": "^5.1.1",
65
+ "dotenv": "^8.2.0",
66
+ "fs-extra": "^9.1.0",
67
+ "jsdom": "^26.0.0",
68
+ "kysely": "^0.27.4",
69
+ "luxon": "^3.5.0",
70
+ "node-stream-zip": "^1.8.2",
71
+ "pg": "^8.13.1",
72
+ "pg-cursor": "^2.12.1",
73
+ "slug": "^11.0.0",
74
+ "tsx": "^4.19.4",
75
+ "windows-1252": "^1.0.0"
76
+ },
77
+ "devDependencies": {
78
+ "@typed-code/schemats": "^5.0.1",
79
+ "@types/cheerio": "^1.0.0",
80
+ "@types/command-line-args": "^5.0.0",
81
+ "@types/fs-extra": "^9.0.7",
82
+ "@types/jsdom": "^21.1.7",
83
+ "@types/luxon": "^3.4.2",
84
+ "@types/node": "^20.17.6",
85
+ "@types/pg": "^8.11.10",
86
+ "@types/pg-cursor": "^2.7.2",
87
+ "@types/slug": "^5.0.9",
88
+ "@typescript-eslint/eslint-plugin": "^8.13.0",
89
+ "@typescript-eslint/parser": "^8.13.0",
90
+ "cross-env": "^10.0.0",
91
+ "eslint": "^8.57.1",
92
+ "kysely-codegen": "^0.18.0",
93
+ "prettier": "^3.5.3",
94
+ "tslib": "^2.1.0",
95
+ "typescript": "^5.8.3"
96
+ }
97
+ }
File without changes
@@ -1,24 +0,0 @@
1
- "use strict";
2
- // import { validateNonEmptyTrimmedString } from "@biryani/core"
3
- // const acteurUidRegExp = /^PA\d+$/
4
- // const organeUidRegExp = /^PO\d+$/
5
- // export function validateSenateurUid(input: any): [any, any] {
6
- // const [value, error] = validateNonEmptyTrimmedString(input)
7
- // if (error !== null) {
8
- // return [value, error]
9
- // }
10
- // if (!acteurUidRegExp.test(value)) {
11
- // return [value, 'Invalid "acteur" unique ID']
12
- // }
13
- // return [value, null]
14
- // }
15
- // export function validateOrganeUid(input: any): [any, any] {
16
- // const [value, error] = validateNonEmptyTrimmedString(input)
17
- // if (error !== null) {
18
- // return [value, error]
19
- // }
20
- // if (!organeUidRegExp.test(value)) {
21
- // return [value, 'Invalid "organe" unique ID']
22
- // }
23
- // return [value, null]
24
- // }