@tricoteuses/senat 2.9.8 → 2.9.10

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.
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * AUTO-GENERATED FILE - DO NOT EDIT!
3
3
  *
4
- * This file was automatically generated by schemats v.2.8.1
4
+ * This file was automatically generated by schemats v.2.9.8
5
5
  * $ schemats generate -c postgres://username:password@localhost:5433/ameli -t amd -t amdsen -t avicom -t avigvt -t cab -t com_ameli -t ent -t etatxt -t fbu -t grppol_ameli -t gvt -t intora -t irr -t lec_ameli -t mot -t nat -t orarol -t sai -t saisen -t sea -t sen_ameli -t ses -t sor -t sub -t txt_ameli -t typrect -t typses -t typsub -t w_nivrec -s public
6
6
  *
7
7
  */
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * AUTO-GENERATED FILE - DO NOT EDIT!
3
3
  *
4
- * This file was automatically generated by schemats v.2.8.1
4
+ * This file was automatically generated by schemats v.2.9.8
5
5
  * $ schemats generate -c postgres://username:password@localhost:5433/debats -t debats -t intdivers -t intpjl -t lecassdeb -t secdis -t secdivers -t syndeb -t typsec -s public
6
6
  *
7
7
  */
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * AUTO-GENERATED FILE - DO NOT EDIT!
3
3
  *
4
- * This file was automatically generated by schemats v.2.8.1
4
+ * This file was automatically generated by schemats v.2.9.8
5
5
  * $ schemats generate -c postgres://username:password@localhost:5433/dosleg -t amescr -t ass -t aud -t auteur -t ble -t catrap -t corscr -t date_seance -t deccoc -t denrap -t doc -t docatt -t docsea -t ecr -t etaloi -t evtsea -t forpub -t gen -t lecass -t lecassrap -t lecture -t lnkrap -t loi -t loithe -t natloi -t org -t orgnomhis -t orippr -t oritxt -t posvot -t qua -t rap -t raporg -t rapthe -t rolsig -t scr -t ses -t stavot -t texte -t texte_ancien -t the -t titsen -t typatt -t typaut -t typdoc -t typevtsea -t typlec -t typloi -t typorg -t typrap -t typtxt -t typurl -t votsen -s public
6
6
  *
7
7
  */
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * AUTO-GENERATED FILE - DO NOT EDIT!
3
3
  *
4
- * This file was automatically generated by schemats v.2.8.1
4
+ * This file was automatically generated by schemats v.2.9.8
5
5
  * $ schemats generate -c postgres://username:password@localhost:5433/questions -t etatquestion -t legquestion -t naturequestion -t sortquestion -t tam_ministeres -t tam_questions -t tam_reponses -t the -s questions
6
6
  *
7
7
  */
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * AUTO-GENERATED FILE - DO NOT EDIT!
3
3
  *
4
- * This file was automatically generated by schemats v.2.8.1
4
+ * This file was automatically generated by schemats v.2.9.8
5
5
  * $ schemats generate -c postgres://username:password@localhost:5433/sens -t acr -t activite -t activite_audit -t activite_delegation -t activite_delegation_audit -t activite_loi -t activite_loi_audit -t activite_obligatoire -t activite_participant -t activite_participant_audit -t activite_senateur -t activite_senateur_audit -t activite_senateur_params -t activite_senateur_params_audit -t activites_liees -t activites_liees_audit -t actpro -t adhgrpsen -t adr -t adresse -t adrsen -t app -t assparint -t asster -t autgrpsen -t autorisation_profil -t autorisations -t avis_nomination_art13 -t basdes -t bur -t bur3r -t bur4r -t cad -t candid -t candidat -t candtodelete -t categorie_activite -t catpro -t catpro2e -t catterrit -t cible_categorie_periode -t cirdep -t com -t con -t cotgip -t csp -t cspfam -t databasechangelog -t databasechangeloglock -t delega -t derogation -t derogation_audit -t derogation_senateur -t derogation_senateur_audit -t design -t designoep -t designorg -t discou -t div -t dpt -t dpt_seuil_presence -t dptele -t dptele_files -t dptele_processing -t dptele_processing_type -t dpttypman -t droits_acces -t droits_acces_audit -t droits_type_derogation -t ele -t eleloc -t elucan -t eludep -t eludiv -t elueur -t elueur_apf -t elumet -t elureg -t elusen -t elusen2e -t elusen3r -t elusen4r -t elusencommu -t elusenpair -t eluter -t elutit -t eluvil -t etadebman -t etadebman3r -t etadebman4r -t etafinman -t etafinman3r -t etafinman4r -t etaprr -t etarpm -t etasen -t ext2e_bio -t ext2e_csp -t ext2e_mandats -t ext2e_minist -t extsencom_identite -t extsencom_mandat -t fonact_participant -t foncandid -t foncom -t fondelega -t fongrppol -t fongrpsen -t fonmemcom -t fonmemdelega -t fonmemextpar -t fonmemgrppol -t fonmemgrpsen -t fonmemorg -t fonorg -t grppol -t grppol4r -t grpsenami -t grpsenamiadh -t grpsenamiadhreq -t grpsenamiadhreqeta -t grpsenamiunadh -t grpsim -t gvt -t insee_pays2008 -t jhi_authority -t jhi_user -t jhi_user_authority -t lanetr -t libcom -t libdelega -t libgrppol -t libgrpsen -t liborg -t lisdptele -t mel -t memcom -t memcomsea -t memdelega -t memextpar -t memgrppol -t memgrpsen -t memorg -t met -t minind -t minist -t mis -t misetafin -t mismin -t misrapeta -t missen -t moddes -t mode_acces_elusenpair -t nation -t nationgrpsen -t nivlan -t org -t orgext -t orgextpres -t orgthe -t pairie_elusenpair -t parpol -t parpolglo -t participa -t pcs -t pcs24 -t pcs42 -t pcs8 -t pcscatpro -t per -t per_sen -t perapp -t periode_presence -t perpolglo -t perrol -t pj_justificatif -t pj_justificatif_audit -t plaind -t plan_table -t plsql_profiler_runs -t plsql_profiler_units -t poicon -t posvot -t presences_scrutin_surcharge -t presencesrevisionentity -t profil_applicatif -t qua -t rap_the -t reg -t reladr -t requetes_profil -t reslis -t resultat -t reu -t revchanges -t rne_mandat -t rne_mandat_diff -t rne_sen -t rne_sen_diff -t rne_type_mandat -t rol -t sal -t scr -t scrusoldelega -t sea -t sec -t sec2e -t secexe -t sen -t senbur -t senbur3r -t senbur4r -t sennom -t senpj -t sensim -t sentablenom -t senurl -t seuil_presence -t sirpas_elusen -t sirpas_fonmemcom -t sirpas_fonmemdelega -t sirpas_fonmemgrppol -t sirpas_memcom -t sirpas_memdelega -t sirpas_memgrppol -t sirpas_mvt -t sirpas_mvtcm -t sirpas_mvttri -t sirpas_sen -t sirpas_senbur -t sirpas_trf -t srv -t stajur -t stavot -t suspensiontravaux -t suspensiontravaux_audit -t sysage -t syscognos -t sysevt -t sysvar -t sysvar_sendev -t sysvar_senprod -t tapsenrevchanges -t tapsenrevisionentity -t telephone -t temval -t tenpol -t territ -t testoracle -t titele -t titelerne -t titmin -t titnob -t tmpsd -t toutes -t turelu -t typadr -t typapppol -t typbister -t typcandid -t type_activite -t type_activite_participant -t type_activite_rol -t type_activite_senateur -t type_categorie -t type_derogation -t type_droit_acces -t type_pj_justificatif -t type_rne_diff -t type_type_derogation -t typele -t typgrpsen -t typman -t typmin -t typmoddes -t typorg -t typorgext -t typparpol -t typpoicon -t typprs -t typprssta -t typscr -t typtel -t typurl -t typvoi -t uploaded_file -t uploaded_file_type -t validation -t validation_defview_profil -t validation_profil -t vercand -t verres -t votes -t zongeo -s public
6
6
  *
7
7
  */
@@ -108,13 +108,13 @@ async function convertDatasetDosLeg(dataDir) {
108
108
  ensureAndClearDir(dossiersReorganizedDir);
109
109
  for await (const loi of findAllDossiers()) {
110
110
  if (options["verbose"]) {
111
- console.log(`Converting ${loi.signet} file…`);
111
+ console.log(`Converting ${loi["signet"]} file…`);
112
112
  }
113
113
  let loiReorganizedDir = path.join(dossiersReorganizedDir, String(UNDEFINED_SESSION));
114
- const session = getSessionFromSignet(loi.signet) || UNDEFINED_SESSION;
114
+ const session = getSessionFromSignet(loi["signet"]) || UNDEFINED_SESSION;
115
115
  loiReorganizedDir = path.join(dossiersReorganizedDir, String(session));
116
116
  fs.ensureDirSync(loiReorganizedDir);
117
- const scrutinFileName = `${loi.signet}.json`;
117
+ const scrutinFileName = `${loi["signet"]}.json`;
118
118
  fs.writeJSONSync(path.join(loiReorganizedDir, scrutinFileName), loi, {
119
119
  spaces: 2,
120
120
  });
@@ -8,9 +8,10 @@ import StreamZip from "node-stream-zip";
8
8
  import readline from "readline";
9
9
  import windows1252 from "windows-1252";
10
10
  import { pipeline } from "stream";
11
+ import iconv from "iconv-lite";
11
12
  import { promisify } from "util";
12
13
  import config from "../config";
13
- import { datasets, getChosenDatasets, getEnabledDatasets } from "../datasets";
14
+ import { getChosenDatasets, getEnabledDatasets } from "../datasets";
14
15
  import { commonOptions } from "./shared/cli_helpers";
15
16
  const badWindows1252CharacterRegex = /[\u0080-\u009f]/g;
16
17
  const optionsDefinitions = [
@@ -67,6 +68,62 @@ async function downloadFile(url, dest) {
67
68
  }
68
69
  await streamPipeline(response.body, fs.createWriteStream(dest));
69
70
  }
71
+ /**
72
+ * Copy a dataset database to the main Senat database (overwriting its contents).
73
+ */
74
+ async function copyToSenat(dataset, dataDir, options) {
75
+ if (!options["silent"]) {
76
+ console.log(`Copying ${dataset.database} to Senat database...`);
77
+ }
78
+ const sqlFilePath = path.join(dataDir, `${dataset.database}.sql`);
79
+ const schemaDumpFile = path.join(dataDir, `${dataset.database}_schema_dump.sql`);
80
+ // Write the header and then stream the rest of the SQL file
81
+ const schemaSqlWriter = fs.createWriteStream(schemaDumpFile, { encoding: "utf8" });
82
+ const lineReader = readline.createInterface({
83
+ input: fs.createReadStream(sqlFilePath, { encoding: "utf8" }),
84
+ crlfDelay: Infinity,
85
+ });
86
+ for await (const line of lineReader) {
87
+ let newLine = line;
88
+ // Replace 'public' schema outside single-quoted strings
89
+ function replacePublicOutsideStrings(line, schema) {
90
+ const parts = line.split(/(')/);
91
+ let inString = false;
92
+ for (let i = 0; i < parts.length; i++) {
93
+ if (parts[i] === "'") {
94
+ inString = !inString;
95
+ }
96
+ else if (!inString) {
97
+ // Only replace outside of strings, including before comma
98
+ parts[i] = parts[i].replace(/\bpublic\b(?=(\s*\.|\s*[,;]|\s|$))/g, schema);
99
+ }
100
+ }
101
+ return parts.join('');
102
+ }
103
+ newLine = replacePublicOutsideStrings(line, dataset.database);
104
+ // Convert to LATIN1, replacing unconvertible characters with '?'
105
+ const latin1Line = iconv.encode(newLine, 'latin1').toString('latin1');
106
+ schemaSqlWriter.write(latin1Line + "\n");
107
+ }
108
+ schemaSqlWriter.end();
109
+ await new Promise((resolve, reject) => {
110
+ schemaSqlWriter.on("finish", () => {
111
+ try {
112
+ execSync(`${options["sudo"] ? `sudo -u ${options["sudo"]} ` : ""}psql --quiet -d senat -f ${schemaDumpFile}`, {
113
+ cwd: dataDir,
114
+ env: process.env,
115
+ encoding: "utf-8",
116
+ });
117
+ }
118
+ finally {
119
+ try { }
120
+ catch { }
121
+ }
122
+ resolve();
123
+ });
124
+ schemaSqlWriter.on("error", reject);
125
+ });
126
+ }
70
127
  async function retrieveDataset(dataDir, dataset) {
71
128
  const zipFilename = dataset.url.substring(dataset.url.lastIndexOf("/") + 1);
72
129
  const zipFilePath = path.join(dataDir, zipFilename);
@@ -120,7 +177,7 @@ async function retrieveDataset(dataDir, dataset) {
120
177
  }
121
178
  if ((options["all"] || options["repairEncoding"]) && dataset.repairEncoding) {
122
179
  if (!options["silent"]) {
123
- console.log(`Repairing Windows CP1252 encoding of ${dataset.title}: ${sqlFilename}…`);
180
+ console.log(`Repairing Windows CP1252 encoding in ${dataset.title}: ${sqlFilename}…`);
124
181
  }
125
182
  const repairedSqlFilePath = sqlFilePath + ".repaired";
126
183
  const repairedSqlWriter = fs.createWriteStream(repairedSqlFilePath, {
@@ -131,7 +188,9 @@ async function retrieveDataset(dataDir, dataset) {
131
188
  crlfDelay: Infinity,
132
189
  });
133
190
  for await (const line of lineReader) {
134
- repairedSqlWriter.write(line.replace(badWindows1252CharacterRegex, (match) => windows1252.decode(match, { mode: "fatal" })) + "\n");
191
+ // Only repair encoding
192
+ let repairedLine = line.replace(badWindows1252CharacterRegex, (match) => windows1252.decode(match, { mode: "fatal" }));
193
+ repairedSqlWriter.write(repairedLine + "\n");
135
194
  }
136
195
  repairedSqlWriter.end();
137
196
  await fs.move(repairedSqlFilePath, sqlFilePath, { overwrite: true });
@@ -140,22 +199,17 @@ async function retrieveDataset(dataDir, dataset) {
140
199
  if (!options["silent"]) {
141
200
  console.log(`Importing ${dataset.title}: ${sqlFilename}…`);
142
201
  }
143
- execSync(`${options["sudo"] ? `sudo -u ${options["sudo"]} ` : ""}psql --quiet -d ${dataset.database} -f ${sqlFilename}`, {
144
- cwd: dataDir,
145
- env: process.env,
146
- encoding: "utf-8",
147
- stdio: ["pipe", "ignore", "ignore"],
148
- });
202
+ await copyToSenat(dataset, dataDir, options);
149
203
  }
150
204
  if (options["schema"]) {
151
205
  let definitionsDir = path.resolve("src", "raw_types_schemats");
152
206
  assert(fs.statSync(definitionsDir).isDirectory());
153
207
  if (!options["silent"]) {
154
- console.log(`Creating TypeScript definitions from schema of database ${dataset.database}…`);
208
+ console.log(`Creating TypeScript definitions from schema '${dataset.database}' in database 'senat'…`);
155
209
  }
156
- const dbConnectionString = `postgres://${process.env["PGUSER"]}:${process.env["PGPASSWORD"]}@${process.env["PGHOST"]}:${process.env["PGPORT"]}/${dataset.database}`;
210
+ const dbConnectionString = `postgres://${process.env["PGUSER"]}:${process.env["PGPASSWORD"]}@${process.env["PGHOST"]}:${process.env["PGPORT"]}/senat`;
157
211
  let definitionFilePath = path.join(definitionsDir, `${dataset.database}.ts`);
158
- execSync(`npx schemats generate -c ${dbConnectionString} -s ${dataset.schema} -o ${definitionFilePath}`, {
212
+ execSync(`npx schemats generate -c ${dbConnectionString} -s ${dataset.database} -o ${definitionFilePath}`, {
159
213
  // cwd: dataDir,
160
214
  env: process.env,
161
215
  encoding: "utf-8",
@@ -168,8 +222,7 @@ async function retrieveDataset(dataDir, dataset) {
168
222
  fs.writeFileSync(definitionFilePath, definitionRepaired);
169
223
  definitionsDir = path.resolve("src", "raw_types");
170
224
  definitionFilePath = path.join(definitionsDir, `${dataset.database}.ts`);
171
- execSync(`kysely-codegen --url ${dbConnectionString} --default-schema=${dataset.schema} --out-file=${definitionFilePath}`, {
172
- // cwd: dataDir,
225
+ execSync(`npx pg-to-ts generate -c '${dbConnectionString}' -s ${dataset.database} -o ${definitionFilePath}`, {
173
226
  env: process.env,
174
227
  encoding: "utf-8",
175
228
  // stdio: ["ignore", "ignore", "pipe"],
@@ -191,18 +244,16 @@ async function retrieveOpenData() {
191
244
  process.env["PGUSER"] &&
192
245
  process.env["PGPASSWORD"], "Missing database configuration: environment variables PGHOST, PGPORT, PGUSER and PGPASSWORD or TRICOTEUSES_SENAT_DB_* in .env file");
193
246
  console.time("data extraction time");
194
- for (const [, dataset] of Object.entries(datasets)) {
195
- execSync(`${options["sudo"] ? `sudo -u ${options["sudo"]} ` : ""}psql --quiet -c "DROP DATABASE IF EXISTS ${dataset.database}"`, {
196
- cwd: dataDir,
197
- env: process.env,
198
- encoding: "utf-8",
199
- });
200
- execSync(`${options["sudo"] ? `sudo -u ${options["sudo"]} ` : ""}psql --quiet -c "CREATE DATABASE ${dataset.database} WITH OWNER opendata"`, {
201
- cwd: dataDir,
202
- env: process.env,
203
- encoding: "utf-8",
204
- });
205
- }
247
+ execSync(`${options["sudo"] ? `sudo -u ${options["sudo"]} ` : ""}psql --quiet -c "DROP DATABASE IF EXISTS senat"`, {
248
+ cwd: dataDir,
249
+ env: process.env,
250
+ encoding: "utf-8",
251
+ });
252
+ execSync(`${options["sudo"] ? `sudo -u ${options["sudo"]} ` : ""}psql --quiet -c "CREATE DATABASE senat WITH OWNER opendata"`, {
253
+ cwd: dataDir,
254
+ env: process.env,
255
+ encoding: "utf-8",
256
+ });
206
257
  const enabledDatasets = getEnabledDatasets(options["categories"]);
207
258
  const chosenDatasets = getChosenDatasets(enabledDatasets);
208
259
  for (const dataset of chosenDatasets) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tricoteuses/senat",
3
- "version": "2.9.8",
3
+ "version": "2.9.10",
4
4
  "description": "Handle French Sénat's open data",
5
5
  "keywords": [
6
6
  "France",
@@ -89,7 +89,8 @@
89
89
  "@typescript-eslint/parser": "^8.13.0",
90
90
  "cross-env": "^10.0.0",
91
91
  "eslint": "^8.57.1",
92
- "kysely-codegen": "^0.18.0",
92
+ "iconv-lite": "^0.7.0",
93
+ "pg-to-ts": "^4.1.1",
93
94
  "prettier": "^3.5.3",
94
95
  "tslib": "^2.1.0",
95
96
  "typescript": "^5.8.3"