@tricoteuses/senat 2.20.22 → 2.20.24

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.
@@ -22,12 +22,16 @@ function auteurs(amendementId) {
22
22
  ])
23
23
  .orderBy("ameli.amdsen.rng", "asc"));
24
24
  }
25
- function scrutin(amendementNum, sesann) {
25
+ function scrutin(amendementNum, sesann, lecassidt) {
26
26
  return dbSenat
27
27
  .selectFrom("dosleg.amescr")
28
- .leftJoin("dosleg.scr", "dosleg.amescr.scrnum", "dosleg.scr.scrnum")
28
+ .leftJoin("dosleg.scr", (join) => join
29
+ .onRef("dosleg.amescr.scrnum", "=", "dosleg.scr.scrnum")
30
+ .onRef("dosleg.amescr.sesann", "=", "dosleg.scr.sesann"))
31
+ .leftJoin("dosleg.date_seance", "dosleg.scr.code", "dosleg.date_seance.code")
29
32
  .where("dosleg.amescr.amescrnum", "=", amendementNum)
30
33
  .where("dosleg.amescr.sesann", "=", sesann)
34
+ .where("dosleg.date_seance.lecidt", "=", lecassidt)
31
35
  .select(["dosleg.amescr.scrnum as scrutin_num"])
32
36
  .limit(1)
33
37
  .as("scrutin_num");
@@ -43,7 +47,9 @@ const findAllAmendementsQuery = dbSenat
43
47
  .leftJoin("ameli.typses", "ameli.typses.id", "ameli.ses.typid")
44
48
  .leftJoin("ameli.nat", "ameli.txt_ameli.natid", "ameli.nat.id")
45
49
  .leftJoin("ameli.lec_ameli", "ameli.txt_ameli.lecid", "ameli.lec_ameli.id")
46
- .leftJoin("dosleg.texte", "ameli.txt_ameli.id", "dosleg.texte.texcod")
50
+ .leftJoin("dosleg.texte", (join) => join
51
+ .onRef("ameli.ses.ann", "=", "dosleg.texte.sesann")
52
+ .onRef("ameli.txt_ameli.numabs", "=", "dosleg.texte.texnum"))
47
53
  .leftJoin("dosleg.lecass", "dosleg.texte.lecassidt", "dosleg.lecass.lecassidt")
48
54
  .leftJoin("ameli.mot", "ameli.amd.motid", "ameli.mot.id")
49
55
  .leftJoin("ameli.avicom", "ameli.amd.avcid", "ameli.avicom.id")
@@ -127,7 +133,7 @@ const findAllAmendementsQuery = dbSenat
127
133
  "ameli.grppol_ameli.lilcou as au_nom_de_groupe_politique",
128
134
  "ameli.com_ameli.lil as au_nom_de_commission",
129
135
  eb.case().when("ameli.cab.entid", "is not", null).then(true).else(false).end().as("auteur_est_gouvernement"),
130
- scrutin(ref("ameli.amd.num"), ref("ameli.ses.ann")),
136
+ scrutin(ref("ameli.amd.num"), ref("ameli.ses.ann"), ref("dosleg.texte.lecassidt")),
131
137
  auteurs(ref("ameli.amd.id")).as("auteurs"),
132
138
  ]);
133
139
  export function findAllAmendements(fromSession) {
@@ -1,8 +1,7 @@
1
1
  import { InferResult, SelectQueryBuilder } from "kysely";
2
2
  declare const findAllDossiersQuery: SelectQueryBuilder<any, any, any>;
3
3
  export declare function findAllDossiers(): AsyncIterableIterator<DossierLegislatifResult>;
4
- export declare function createActesLegislatifs(dossier: DossierLegislatifResult): any;
5
4
  export declare function getCodeActeLecture(codeNatureDossier: string, typeLecture: string, assemblee: string): string | null;
6
- export declare function getCodeActeTexte(codeParent: string | null, texteOrigine: string): string | null;
7
5
  export type DossierLegislatifResult = InferResult<typeof findAllDossiersQuery>[0];
6
+ export declare function buildActesLegislatifs(dossier: any): any[];
8
7
  export {};
@@ -29,6 +29,17 @@ function auteursRapport(rapportId) {
29
29
  ])
30
30
  .orderBy("dosleg.ecr.ecrnumtri", "asc"));
31
31
  }
32
+ function documentsAttaches(rapportId) {
33
+ return jsonArrayFrom(dbSenat
34
+ .withSchema("dosleg")
35
+ .selectFrom("docatt")
36
+ .leftJoin("typatt", "docatt.typattcod", "typatt.typattcod")
37
+ .where("docatt.rapcod", "=", rapportId)
38
+ .select([
39
+ "docatt.docatturl as url",
40
+ "typatt.typattlib as type_document"
41
+ ]));
42
+ }
32
43
  function rapports(lectureAssembleeId) {
33
44
  return jsonArrayFrom(dbSenat
34
45
  .withSchema("dosleg")
@@ -55,9 +66,12 @@ function rapports(lectureAssembleeId) {
55
66
  .end()
56
67
  .as("url"),
57
68
  rtrim(ref("denrap.libdenrap")).as("type"),
69
+ rtrim(ref("rap.raptil")).as("titre"),
70
+ rtrim(ref("rap.rapsoustit")).as("sous_titre"),
58
71
  toDateString(ref("rap.date_depot")).as("date"),
59
72
  "sesann as session",
60
73
  auteursRapport(ref("rap.rapcod")).as("auteurs"),
74
+ documentsAttaches(ref("rap.rapcod")).as("documents_annexes"),
61
75
  ]));
62
76
  }
63
77
  function auteursTexte(texteId) {
@@ -221,90 +235,6 @@ const findAllDossiersQuery = dbSenat
221
235
  export function findAllDossiers() {
222
236
  return findAllDossiersQuery.stream();
223
237
  }
224
- export function createActesLegislatifs(dossier) {
225
- const actesLegislatifs = (dossier["lectures"] || []).flatMap((lecture) => {
226
- const lecturesAssemblee = (lecture["lectures_assemblee"] || []).map((lectureAss) => {
227
- const codeParent = getCodeActeLecture(dossier["code_nature_dossier"], lecture["type_lecture"], lectureAss["assemblee"]);
228
- const textesWithCodeActe = (lectureAss["textes"] || []).map((texte) => ({
229
- code_acte: getCodeActeTexte(codeParent, texte["origine"]),
230
- ...texte,
231
- }));
232
- // Ajout étape -COM-FOND après chaque -DEPOT
233
- let acteLegislatifsLecture = [];
234
- for (let i = 0; i < textesWithCodeActe.length; i++) {
235
- const t = textesWithCodeActe[i];
236
- acteLegislatifsLecture.push(t);
237
- if (t.code_acte?.endsWith("-DEPOT") && t.type === "texte de loi") {
238
- acteLegislatifsLecture.push({
239
- ...t,
240
- code_acte: t.code_acte.replace("-DEPOT", "-COM-FOND"),
241
- });
242
- }
243
- }
244
- if (lectureAss["dates_seances"]?.length > 0) {
245
- acteLegislatifsLecture.push({
246
- session: lectureAss["session"],
247
- type_lecture: lecture["type_lecture"],
248
- libelle_lecture: "Discussion en séance publique",
249
- code_acte: `${codeParent}-DEBATS-SEANCE`,
250
- date: lectureAss["dates_seances"][0]?.["date"],
251
- id: lectureAss["id"],
252
- numero: lectureAss["numero"],
253
- });
254
- }
255
- const { textes, rapports, ...lectureAssWithoutTextes } = lectureAss;
256
- return {
257
- type_lecture: lecture["type_lecture"],
258
- ordre_lecture: lecture["ordre_lecture"],
259
- libelle_lecture: lecture["libelle"],
260
- code_acte: codeParent,
261
- actes_legislatifs: acteLegislatifsLecture,
262
- ...lectureAssWithoutTextes,
263
- };
264
- });
265
- return lecturesAssemblee;
266
- });
267
- if (dossier["date_decision_CoC"]) {
268
- actesLegislatifs.push({
269
- type_lecture: "Conseil constitutionnel",
270
- ordre_lecture: null,
271
- libelle_lecture: "Conseil constitutionnel",
272
- code_acte: "CC",
273
- actes_legislatifs: [
274
- {
275
- code_acte: "CC-SAISIE",
276
- date: dossier["date_saisine_CoC"],
277
- libelle_decision_CoC: dossier["libelle_decision_CoC"],
278
- date_decision_CoC: dossier["date_decision_CoC"],
279
- num_decision_CoC: dossier["num_decision_CoC"],
280
- url_decision_CoC: dossier["url_decision_CoC"],
281
- url_dossier_CoC: dossier["url_dossier_CoC"],
282
- date_saisine_CoC: dossier["date_saisine_CoC"],
283
- condition_saisine_CoC: dossier["condition_saisine_CoC"],
284
- },
285
- ],
286
- });
287
- }
288
- if (dossier["date_publication_JO"]) {
289
- actesLegislatifs.push({
290
- type_lecture: "Promulgation",
291
- ordre_lecture: null,
292
- libelle_lecture: "Promulgation",
293
- code_acte: "PROM",
294
- actes_legislatifs: [
295
- {
296
- code_acte: "PROM-PUB",
297
- date: dossier["date_publication_JO"],
298
- titre_JO: dossier["titre_JO"],
299
- date_publication_JO: dossier["date_publication_JO"],
300
- numero_JO: dossier["numero_JO"],
301
- url_JO: dossier["url_JO"],
302
- },
303
- ],
304
- });
305
- }
306
- return actesLegislatifs;
307
- }
308
238
  export function getCodeActeLecture(codeNatureDossier, typeLecture, assemblee) {
309
239
  const codeAssemblee = assemblee === "Sénat" ? "SN" : assemblee === "Assemblée nationale" ? "AN" : null;
310
240
  if (typeLecture === "Commission mixte paritaire") {
@@ -336,38 +266,177 @@ export function getCodeActeLecture(codeNatureDossier, typeLecture, assemblee) {
336
266
  }
337
267
  return null;
338
268
  }
339
- export function getCodeActeTexte(codeParent, texteOrigine) {
340
- if (codeParent === "CMP") {
341
- if (texteOrigine === "de la commission") {
342
- return "CMP-DEBATS-AN";
343
- }
344
- else if (texteOrigine === "adopté par l'Assemblée Nationale" ||
345
- texteOrigine === "adopté par l'Assemblée nationale") {
346
- return "CMP-DEBATS-SN";
347
- }
348
- }
349
- if (texteOrigine === "transmis au Sénat" ||
350
- texteOrigine === "déposé au Sénat" ||
351
- texteOrigine === "transmis à l'Assemblée nationale" ||
352
- texteOrigine === "déposé à l'Assemblée nationale" ||
353
- texteOrigine === "transmis à l'Assemblée Nationale" ||
354
- texteOrigine === "déposé à l'Assemblée Nationale" ||
355
- texteOrigine === "transmis en application de l'article 47-1, alinéa 2, de la Constitution") {
356
- return `${codeParent}-DEPOT`;
269
+ // Helper pour déterminer le code de phase (SN1, SN2, CMP...)
270
+ function getPhasePrefix(lecture, assemblee) {
271
+ if (assemblee !== "Sénat")
272
+ return null;
273
+ const typeLibelle = (lecture.type_lecture || "").toLowerCase();
274
+ if (typeLibelle.includes("cmp") || typeLibelle.includes("mixte"))
275
+ return "CMP";
276
+ if (typeLibelle.includes("nouvelle lecture"))
277
+ return "SNNLEC";
278
+ if (typeLibelle.includes("d\u00e9finitive"))
279
+ return "SNLDEF";
280
+ if (typeLibelle.includes("unique"))
281
+ return "SNLUNI";
282
+ if (lecture.ordre_lecture) {
283
+ return `SN${lecture.ordre_lecture}`;
357
284
  }
358
- if (texteOrigine === "de la commission" ||
359
- texteOrigine === "de la commission (AN)" ||
360
- texteOrigine === "résultat des travaux de la commission") {
361
- return `${codeParent}-DEBATS-SEANCE`;
285
+ if (typeLibelle.includes("premi\u00e8re"))
286
+ return "SN1";
287
+ if (typeLibelle.includes("deuxi\u00e8me") || typeLibelle.includes("seconde"))
288
+ return "SN2";
289
+ return "SN1";
290
+ }
291
+ export function buildActesLegislatifs(dossier) {
292
+ const actes = [];
293
+ const loiSignet = dossier.signet;
294
+ const lectures = dossier.lectures || [];
295
+ for (const lecture of lectures) {
296
+ const lecturesAssemblee = lecture.lectures_assemblee || [];
297
+ for (const lecAss of lecturesAssemblee) {
298
+ // On ne traite que la partie SÉNAT
299
+ if (lecAss.assemblee !== "Sénat")
300
+ continue;
301
+ const phasePrefix = getPhasePrefix(lecture, lecAss.assemblee);
302
+ if (!phasePrefix)
303
+ continue;
304
+ // Préparation des textes (tri chronologique)
305
+ const textes = lecAss.textes || [];
306
+ const textesTries = [...textes].sort((a, b) => new Date(a.date).getTime() - new Date(b.date).getTime());
307
+ // =================================================================
308
+ // A. DÉPÔT
309
+ // =================================================================
310
+ const depotTexte = textesTries.find((t) => (t.origine || "").toLowerCase().includes("déposé") ||
311
+ (t.origine || "").toLowerCase().includes("transmis") ||
312
+ t.ordre_origine === "0");
313
+ if (depotTexte && depotTexte.date) {
314
+ actes.push({
315
+ code_acte: `${phasePrefix}-DEPOT`,
316
+ date: depotTexte.date,
317
+ libelle: `Dépôt du texte n°${depotTexte.numero}`,
318
+ id: depotTexte.id,
319
+ numero: depotTexte.numero,
320
+ uid: `${loiSignet}-${phasePrefix}-DEPOT`,
321
+ session: lecAss.session,
322
+ chambre: 'SN',
323
+ signet_dossier: loiSignet,
324
+ texte_url: depotTexte.url,
325
+ code_organisme: null
326
+ });
327
+ }
328
+ // =================================================================
329
+ // B. COMMISSION (Rapports)
330
+ // =================================================================
331
+ const rapports = lecAss.rapports || [];
332
+ for (const rap of rapports) {
333
+ if (rap.date) {
334
+ actes.push({
335
+ code_acte: `${phasePrefix}-COM-FOND`,
336
+ date: rap.date,
337
+ libelle: `Rapport n°${rap.numero} de la commission`,
338
+ id: rap.id,
339
+ numero: rap.numero,
340
+ code_organisme: rap.code_organisme,
341
+ adoption: rap.adoption,
342
+ uid: `${loiSignet}-${phasePrefix}-COM`,
343
+ session: lecAss.session,
344
+ chambre: 'SN',
345
+ signet_dossier: loiSignet,
346
+ texte_url: rap.url,
347
+ });
348
+ }
349
+ }
350
+ // =================================================================
351
+ // C. SÉANCE PUBLIQUE
352
+ // =================================================================
353
+ const datesSeances = lecAss.dates_seances || [];
354
+ if (datesSeances.length > 0) {
355
+ // Tri des objets dates
356
+ datesSeances.sort((a, b) => new Date(a.date).getTime() - new Date(b.date).getTime());
357
+ const premiereSeance = datesSeances[0];
358
+ if (premiereSeance && premiereSeance.date) {
359
+ actes.push({
360
+ // Champs pour buildParlementActeLegislatif
361
+ code_acte: `${phasePrefix}-DEBATS-SEANCE`,
362
+ date: premiereSeance.date,
363
+ libelle: `Discussion en séance publique`,
364
+ uid: `${loiSignet}-${phasePrefix}-DEBATS-SEANCE`,
365
+ session: lecAss.session,
366
+ chambre: 'SN',
367
+ signet_dossier: loiSignet,
368
+ code_organisme: null
369
+ });
370
+ }
371
+ }
372
+ // =================================================================
373
+ // D. DÉCISION / VOTE
374
+ // =================================================================
375
+ const texteFinal = [...textesTries].reverse().find((t) => {
376
+ const origine = (t.origine || "").toLowerCase();
377
+ return (origine.includes("adopté") ||
378
+ origine.includes("rejeté") ||
379
+ origine.includes("devenu résolution") ||
380
+ t.code_adoption === "O");
381
+ });
382
+ if (texteFinal && texteFinal.date) {
383
+ const origine = (texteFinal.origine || "").toLowerCase();
384
+ let libelleStatut = "Adopté";
385
+ if (origine.includes("rejeté")) {
386
+ libelleStatut = "Rejeté";
387
+ }
388
+ else if (origine.includes("devenue résolution")) {
389
+ libelleStatut = "Adopté";
390
+ }
391
+ actes.push({
392
+ code_acte: `${phasePrefix}-DEBATS-DEC`,
393
+ date: texteFinal.date,
394
+ libelle: `${libelleStatut === "Adopté" ? "Adoption" : "Rejet"} (Texte n°${texteFinal.numero})`,
395
+ id: texteFinal.id,
396
+ numero: texteFinal.numero,
397
+ adoption: libelleStatut,
398
+ uid: `${loiSignet}-DEC-${texteFinal.numero}`,
399
+ session: lecAss.session,
400
+ chambre: 'SN',
401
+ signet_dossier: loiSignet,
402
+ texte_url: texteFinal.url,
403
+ code_organisme: null
404
+ });
405
+ }
406
+ }
362
407
  }
363
- if (texteOrigine === "retiré par l'auteur") {
364
- return `${codeParent}-RTRINI`;
408
+ // =================================================================
409
+ // E. HORS LECTURE (CC & PROMULGATION)
410
+ // =================================================================
411
+ if (dossier.date_decision_CoC) {
412
+ actes.push({
413
+ code_acte: 'CC',
414
+ date: dossier.date_decision_CoC,
415
+ libelle: `Décision du Conseil constitutionnel`,
416
+ id: dossier.url_decision_CoC,
417
+ uid: `${loiSignet}-CC`,
418
+ chambre: 'AN',
419
+ signet_dossier: loiSignet,
420
+ texte_url: dossier.url_decision_CoC || dossier.url_dossier_CoC,
421
+ });
365
422
  }
366
- if (texteOrigine.includes("adopté") ||
367
- texteOrigine.includes("rejeté") ||
368
- texteOrigine.includes("modifié") ||
369
- texteOrigine === "devenu résolution du Sénat") {
370
- return `${codeParent}-DEBATS-DEC`;
423
+ if (dossier.date_promulgation) {
424
+ actes.push({
425
+ code_acte: 'PROM',
426
+ date: dossier.date_promulgation,
427
+ libelle: `Promulgation de la loi`,
428
+ date_publication_JO: dossier.date_publication_JO,
429
+ numero_JO: dossier.numero_JO,
430
+ url_legifrance: dossier.url_JO,
431
+ id: dossier.url_JO,
432
+ uid: `${loiSignet}-PROM`,
433
+ chambre: 'AN',
434
+ signet_dossier: loiSignet,
435
+ });
371
436
  }
372
- return null;
437
+ return actes.sort((a, b) => {
438
+ const dateA = new Date(a.date).getTime();
439
+ const dateB = new Date(b.date).getTime();
440
+ return dateA - dateB;
441
+ });
373
442
  }
@@ -8,7 +8,7 @@ import { datasets, EnabledDatasets, getEnabledDatasets } from "../datasets";
8
8
  import { DATA_ORIGINAL_FOLDER, DATA_TRANSFORMED_FOLDER, DOCUMENT_METADATA_FILE, DOSLEG_DOSSIERS_FOLDER, SCRUTINS_FOLDER, RAPPORT_FOLDER, SENS_CIRCONSCRIPTIONS_FOLDER, SENS_ORGANISMES_FOLDER, SENS_SENATEURS_FOLDER, TEXTE_FOLDER, } from "../loaders";
9
9
  import { findAllAmendements, findAllCirconscriptions, findAllDebats, findAllDossiers, findAllScrutins, findAllOrganismes, findAllQuestions, findAllSens, findSenatRapportUrls, findSenatTexteUrls, } from "../model";
10
10
  import { processRapport, processTexte } from "./retrieve_documents";
11
- import { createActesLegislatifs } from "../model/dosleg";
11
+ import { buildActesLegislatifs } from "../model/dosleg";
12
12
  import { UNDEFINED_SESSION } from "../types/sessions";
13
13
  import { getSessionFromDate, getSessionFromSignet } from "./datautil";
14
14
  import { commonOptions } from "./shared/cli_helpers";
@@ -151,21 +151,23 @@ async function convertDatasetDosLeg(dataDir, options) {
151
151
  ensureAndClearDir(doslegReorganizedRootDir);
152
152
  ensureAndClearDir(dossiersReorganizedDir);
153
153
  }
154
- for await (const loi of findAllDossiers()) {
154
+ for await (const dossier of findAllDossiers()) {
155
155
  if (options["verbose"]) {
156
- console.log(`Converting ${loi["signet"]} file…`);
156
+ console.log(`Converting ${dossier["signet"]} file…`);
157
157
  }
158
- let loiReorganizedDir = path.join(dossiersReorganizedDir, String(UNDEFINED_SESSION));
159
- const session = getSessionFromSignet(loi["signet"]) || UNDEFINED_SESSION;
158
+ let dossierReorganizedDir = path.join(dossiersReorganizedDir, String(UNDEFINED_SESSION));
159
+ const session = getSessionFromSignet(dossier["signet"]) || UNDEFINED_SESSION;
160
160
  if (options["fromSession"] && session < options["fromSession"]) {
161
161
  continue;
162
162
  }
163
- loiReorganizedDir = path.join(dossiersReorganizedDir, String(session));
164
- // Ajout des actes législatifs au dossier
165
- const actesLegislatifs = createActesLegislatifs(loi);
166
- const loiWithActes = { ...loi, actes_legislatifs: actesLegislatifs };
167
- const dossierFile = `${loi["signet"]}.json`;
168
- await fs.outputJSON(path.join(loiReorganizedDir, dossierFile), loiWithActes, { spaces: 2 });
163
+ dossierReorganizedDir = path.join(dossiersReorganizedDir, String(session));
164
+ const actesBrutsNormalises = buildActesLegislatifs(dossier);
165
+ const dossierWithActes = {
166
+ ...dossier,
167
+ actes_legislatifs: actesBrutsNormalises
168
+ };
169
+ const dossierFile = `${dossier["signet"]}.json`;
170
+ await fs.outputJSON(path.join(dossierReorganizedDir, dossierFile), dossierWithActes, { spaces: 2 });
169
171
  }
170
172
  await convertTexteUrls(dataDir, options);
171
173
  await convertRapportUrls(dataDir, options);
@@ -5,7 +5,7 @@ const optionsDefinitions = [dataDirDefaultOption];
5
5
  const options = commandLineArgs(optionsDefinitions);
6
6
  const session = 2024;
7
7
  const sinceCommit = undefined;
8
- for (const { item: amendement } of iterLoadSenatAmendements(options["dataDir"], session, {
8
+ for (const { item: amendement, filePathFromDataset } of iterLoadSenatAmendements(options["dataDir"], session, {
9
9
  log: true,
10
10
  sinceCommit: sinceCommit,
11
11
  })) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tricoteuses/senat",
3
- "version": "2.20.22",
3
+ "version": "2.20.24",
4
4
  "description": "Handle French Sénat's open data",
5
5
  "keywords": [
6
6
  "France",
@@ -64,17 +64,17 @@
64
64
  "cheerio": "^1.1.2",
65
65
  "command-line-args": "^6.0.1",
66
66
  "dotenv": "^17.2.3",
67
- "fast-xml-parser": "^5.3.2",
68
- "fs-extra": "^11.3.2",
67
+ "fast-xml-parser": "^5.3.3",
68
+ "fs-extra": "^11.3.3",
69
69
  "jsdom": "^27.2.0",
70
- "kysely": "^0.28.8",
70
+ "kysely": "^0.28.9",
71
71
  "luxon": "^3.7.2",
72
72
  "node-stream-zip": "^1.8.2",
73
73
  "p-limit": "^7.2.0",
74
74
  "pg": "^8.13.1",
75
75
  "pg-cursor": "^2.12.1",
76
76
  "slug": "^11.0.0",
77
- "tsx": "^4.20.6",
77
+ "tsx": "^4.21.0",
78
78
  "windows-1252": "^3.0.4"
79
79
  },
80
80
  "devDependencies": {
@@ -92,7 +92,6 @@
92
92
  "@typescript-eslint/parser": "^8.46.0",
93
93
  "cross-env": "^10.1.0",
94
94
  "eslint": "^8.57.1",
95
- "iconv-lite": "^0.7.0",
96
95
  "kysely-codegen": "^0.19.0",
97
96
  "prettier": "^3.5.3",
98
97
  "tslib": "^2.1.0",