Add KALI.
This commit is contained in:
parent
00d3281a68
commit
9a1d93ca65
19 changed files with 1135 additions and 1 deletions
|
@ -12,6 +12,7 @@ Legal data sources:
|
|||
- https://www.dila.premier-ministre.gouv.fr/repertoire-des-informations-publiques/les-donnees-juridiques
|
||||
- DOLE: https://echanges.dila.gouv.fr/OPENDATA/DOLE/
|
||||
- JORF: https://echanges.dila.gouv.fr/OPENDATA/JORF/
|
||||
- KALI: https://echanges.dila.gouv.fr/OPENDATA/KALI/
|
||||
- LEGI: https://echanges.dila.gouv.fr/OPENDATA/LEGI/
|
||||
|
||||
## Installation
|
||||
|
|
|
@ -38,7 +38,21 @@ export interface DossierLegislatif {
|
|||
}
|
||||
}
|
||||
|
||||
export type Etat = "MODIFIE" | "VIGUEUR"
|
||||
export type Etat = "MODIFIE" | "PERIME" | "VIGUEUR"
|
||||
|
||||
export interface Idcc {
|
||||
META: {
|
||||
META_COMMUN: MetaCommun
|
||||
META_SPEC: {
|
||||
META_CONTENEUR: {
|
||||
TITRE: string
|
||||
ETAT: Etat
|
||||
NUM: string
|
||||
DATE_PUBLI: string
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export interface IdWrapper {
|
||||
eli: string
|
||||
|
@ -61,9 +75,11 @@ export interface Jo {
|
|||
export type LegalObject =
|
||||
| Article
|
||||
| DossierLegislatif
|
||||
| Idcc
|
||||
| IdWrapper
|
||||
| Jo
|
||||
| SectionTa
|
||||
| Textekali
|
||||
| Textelr
|
||||
| TexteVersion
|
||||
| VersionsWrapper
|
||||
|
@ -72,9 +88,11 @@ export type LegalObjectType =
|
|||
| "article"
|
||||
| "dossier_legislatif"
|
||||
| "id"
|
||||
| "idcc"
|
||||
| "jo"
|
||||
| "section_ta"
|
||||
| "texte_version"
|
||||
| "textekali"
|
||||
| "textelr"
|
||||
| "versions"
|
||||
|
||||
|
@ -98,6 +116,27 @@ export interface SectionTa {
|
|||
STRUCTURE_TA: { LIEN_ART?: LienArt | LienArt[] }
|
||||
}
|
||||
|
||||
export interface Textekali {
|
||||
META: {
|
||||
META_COMMUN: MetaCommun
|
||||
META_SPEC: {
|
||||
META_TEXTE_CHRONICLE: {
|
||||
CID: string
|
||||
NUM: string
|
||||
NUM_PARUTION: string
|
||||
NUM_SEQUENCE: string
|
||||
NOR: string
|
||||
DATE_PUBLI: string
|
||||
DATE_TEXTE: string
|
||||
DERNIERE_MODIFICATION: string
|
||||
ORIGINE_PUBLI: string
|
||||
PAGE_DEB_PUBLI: string
|
||||
PAGE_FIN_PUBLI: string
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export interface Textelr {
|
||||
META: {
|
||||
META_COMMUN: MetaCommun
|
||||
|
@ -176,12 +215,16 @@ export function pathnameFromLegalObject(
|
|||
}`
|
||||
case "id":
|
||||
return `/id/${(object as IdWrapper).eli}`
|
||||
case "idcc":
|
||||
return `/idcc/${(object as Idcc).META.META_COMMUN.ID}`
|
||||
case "jo":
|
||||
return `/jo/${(object as Jo).META.META_COMMUN.ID}`
|
||||
case "section_ta":
|
||||
return `/section_ta/${(object as SectionTa).ID}`
|
||||
case "texte_version":
|
||||
return `/texte_version/${(object as TexteVersion).META.META_COMMUN.ID}`
|
||||
case "textekali":
|
||||
return `/textekali/${(object as Textekali).META.META_COMMUN.ID}`
|
||||
case "textelr":
|
||||
return `/textelr/${(object as Textelr).META.META_COMMUN.ID}`
|
||||
case "versions":
|
||||
|
@ -203,12 +246,16 @@ export function pathnameFromLegalObjectId(
|
|||
case "id":
|
||||
// Here, id is an ELI.
|
||||
return `/id/{id}`
|
||||
case "idcc":
|
||||
return `/idcc/${id}`
|
||||
case "jo":
|
||||
return `/jo/${id}`
|
||||
case "section_ta":
|
||||
return `/section_ta/${id}`
|
||||
case "texte_version":
|
||||
return `/texte_version/${id}`
|
||||
case "textekali":
|
||||
return `/textekali/${id}`
|
||||
case "textelr":
|
||||
return `/textelr/${id}`
|
||||
case "versions":
|
||||
|
|
127
src/lib/scripts/import_dole.ts
Normal file
127
src/lib/scripts/import_dole.ts
Normal file
|
@ -0,0 +1,127 @@
|
|||
import { auditChain, auditRequire, strictAudit } from "@auditors/core"
|
||||
import assert from "assert"
|
||||
import { XMLParser } from "fast-xml-parser"
|
||||
import fs from "fs-extra"
|
||||
import he from "he"
|
||||
import path from "path"
|
||||
import type { JSONValue } from "postgres"
|
||||
import sade from "sade"
|
||||
|
||||
import type { DossierLegislatif, XmlHeader } from "$lib/data"
|
||||
import { db } from "$lib/server/database"
|
||||
import { walkDir } from "$lib/server/file_systems"
|
||||
|
||||
const xmlParser = new XMLParser({
|
||||
attributeNamePrefix: "@",
|
||||
ignoreAttributes: false,
|
||||
stopNodes: [
|
||||
"DOSSIER_LEGISLATIF.CONTENU.CONTENU_DOSSIER_1",
|
||||
"DOSSIER_LEGISLATIF.CONTENU.CONTENU_DOSSIER_2",
|
||||
"DOSSIER_LEGISLATIF.CONTENU.EXPOSE_MOTIF",
|
||||
],
|
||||
tagValueProcessor: (_tagName, tagValue) => he.decode(tagValue),
|
||||
})
|
||||
|
||||
async function importDole({ resume }: { resume?: string } = {}): Promise<void> {
|
||||
let skip = resume !== undefined
|
||||
const deleteRemainingIds = !skip
|
||||
|
||||
const dossierLegislatifRemainingIds = new Set(
|
||||
(
|
||||
await db<{ id: string }[]>`
|
||||
SELECT id
|
||||
FROM dossier_legislatif
|
||||
`
|
||||
).map(({ id }) => id),
|
||||
)
|
||||
|
||||
const dataDir = path.join("..", "dila-data", "dole")
|
||||
assert(await fs.pathExists(dataDir))
|
||||
iterXmlFiles: for (const relativeSplitPath of walkDir(dataDir)) {
|
||||
const relativePath = path.join(...relativeSplitPath)
|
||||
if (skip) {
|
||||
if (relativePath.startsWith(resume!)) {
|
||||
skip = false
|
||||
console.log(`Resuming at file ${relativePath}...`)
|
||||
} else {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
const filePath = path.join(dataDir, relativePath)
|
||||
if (!filePath.endsWith(".xml")) {
|
||||
console.info(`Skipping non XML file at ${filePath}`)
|
||||
continue
|
||||
}
|
||||
|
||||
try {
|
||||
const xmlString: string = await fs.readFile(filePath, {
|
||||
encoding: "utf8",
|
||||
})
|
||||
const xmlData = xmlParser.parse(xmlString)
|
||||
for (const [key, element] of Object.entries(xmlData) as [
|
||||
string,
|
||||
DossierLegislatif | XmlHeader,
|
||||
][]) {
|
||||
switch (key) {
|
||||
case "?xml": {
|
||||
const xmlHeader = element as XmlHeader
|
||||
assert.strictEqual(xmlHeader["@encoding"], "UTF-8", filePath)
|
||||
assert.strictEqual(xmlHeader["@version"], "1.0", filePath)
|
||||
break
|
||||
}
|
||||
case "DOSSIER_LEGISLATIF": {
|
||||
const dossierLegislatif = element as DossierLegislatif
|
||||
await db`
|
||||
INSERT INTO dossier_legislatif (
|
||||
id,
|
||||
data
|
||||
) VALUES (
|
||||
${dossierLegislatif.META.META_COMMUN.ID},
|
||||
${db.json(dossierLegislatif as unknown as JSONValue)}
|
||||
)
|
||||
ON CONFLICT (id)
|
||||
DO UPDATE SET
|
||||
data = ${db.json(dossierLegislatif as unknown as JSONValue)}
|
||||
`
|
||||
dossierLegislatifRemainingIds.delete(
|
||||
dossierLegislatif.META.META_COMMUN.ID,
|
||||
)
|
||||
break
|
||||
}
|
||||
default: {
|
||||
console.warn(
|
||||
`Unexpected root element "${key}" in XML file: ${filePath}`,
|
||||
)
|
||||
break iterXmlFiles
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("An error occurred while parsing XML file", filePath)
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
if (deleteRemainingIds) {
|
||||
for (const id of dossierLegislatifRemainingIds) {
|
||||
console.log(`Deleting DOSSIER_LEGISLATIF ${id}…`)
|
||||
await db`
|
||||
DELETE FROM dossier_legislatif
|
||||
WHERE id = ${id}
|
||||
`
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sade("import_dole", true)
|
||||
.describe("Import Dila's DOLE database")
|
||||
.option("-r", "--resume", "Resume import at given relative file path")
|
||||
.example(
|
||||
"--resume dole/global/JORF/DOLE/00/00/36/07/36/JORFDOLE000036073697.xml",
|
||||
)
|
||||
.action(async (options) => {
|
||||
await importDole(options)
|
||||
process.exit(0)
|
||||
})
|
||||
.parse(process.argv)
|
301
src/lib/scripts/import_kali.ts
Normal file
301
src/lib/scripts/import_kali.ts
Normal file
|
@ -0,0 +1,301 @@
|
|||
import { auditChain, auditRequire, strictAudit } from "@auditors/core"
|
||||
import assert from "assert"
|
||||
import { XMLParser } from "fast-xml-parser"
|
||||
import fs from "fs-extra"
|
||||
import he from "he"
|
||||
import path from "path"
|
||||
import type { JSONValue } from "postgres"
|
||||
import sade from "sade"
|
||||
|
||||
import type {
|
||||
Article,
|
||||
Idcc,
|
||||
SectionTa,
|
||||
Textekali,
|
||||
Textelr,
|
||||
TexteVersion,
|
||||
XmlHeader,
|
||||
} from "$lib/data"
|
||||
import { db } from "$lib/server/database"
|
||||
import { walkDir } from "$lib/server/file_systems"
|
||||
|
||||
const xmlParser = new XMLParser({
|
||||
attributeNamePrefix: "@",
|
||||
ignoreAttributes: false,
|
||||
stopNodes: ["ARTICLE.BLOC_TEXTUEL.CONTENU", "ARTICLE.SM.CONTENU"],
|
||||
tagValueProcessor: (_tagName, tagValue) => he.decode(tagValue),
|
||||
})
|
||||
|
||||
async function importKali({ resume }: { resume?: string } = {}): Promise<void> {
|
||||
let skip = resume !== undefined
|
||||
const deleteRemainingIds = !skip
|
||||
|
||||
const articleRemainingIds = new Set(
|
||||
(
|
||||
await db<{ id: string }[]>`
|
||||
SELECT id
|
||||
FROM article
|
||||
WHERE id LIKE 'KALI%'
|
||||
`
|
||||
).map(({ id }) => id),
|
||||
)
|
||||
const idccRemainingIds = new Set(
|
||||
(
|
||||
await db<{ id: string }[]>`
|
||||
SELECT id
|
||||
FROM idcc
|
||||
`
|
||||
).map(({ id }) => id),
|
||||
)
|
||||
const sectionTaRemainingIds = new Set(
|
||||
(
|
||||
await db<{ id: string }[]>`
|
||||
SELECT id
|
||||
FROM section_ta
|
||||
WHERE id LIKE 'KALI%'
|
||||
`
|
||||
).map(({ id }) => id),
|
||||
)
|
||||
const textekaliRemainingIds = new Set(
|
||||
(
|
||||
await db<{ id: string }[]>`
|
||||
SELECT id
|
||||
FROM textekali
|
||||
`
|
||||
).map(({ id }) => id),
|
||||
)
|
||||
const textelrRemainingIds = new Set(
|
||||
(
|
||||
await db<{ id: string }[]>`
|
||||
SELECT id
|
||||
FROM textelr
|
||||
WHERE id LIKE 'KALI%'
|
||||
`
|
||||
).map(({ id }) => id),
|
||||
)
|
||||
const texteVersionRemainingIds = new Set(
|
||||
(
|
||||
await db<{ id: string }[]>`
|
||||
SELECT id
|
||||
FROM texte_version
|
||||
WHERE id LIKE 'KALI%'
|
||||
`
|
||||
).map(({ id }) => id),
|
||||
)
|
||||
|
||||
const dataDir = path.join("..", "dila-data", "kali")
|
||||
assert(await fs.pathExists(dataDir))
|
||||
iterXmlFiles: for (const relativeSplitPath of walkDir(dataDir)) {
|
||||
const relativePath = path.join(...relativeSplitPath)
|
||||
if (skip) {
|
||||
if (relativePath.startsWith(resume!)) {
|
||||
skip = false
|
||||
console.log(`Resuming at file ${relativePath}...`)
|
||||
} else {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
const filePath = path.join(dataDir, relativePath)
|
||||
if (!filePath.endsWith(".xml")) {
|
||||
console.info(`Skipping non XML file at ${filePath}`)
|
||||
continue
|
||||
}
|
||||
|
||||
try {
|
||||
const xmlString: string = await fs.readFile(filePath, {
|
||||
encoding: "utf8",
|
||||
})
|
||||
const xmlData = xmlParser.parse(xmlString)
|
||||
for (const [key, element] of Object.entries(xmlData) as [
|
||||
string,
|
||||
(
|
||||
| Article
|
||||
| Idcc
|
||||
| SectionTa
|
||||
| Textekali
|
||||
| Textelr
|
||||
| TexteVersion
|
||||
| XmlHeader
|
||||
),
|
||||
][]) {
|
||||
switch (key) {
|
||||
case "?xml": {
|
||||
const xmlHeader = element as XmlHeader
|
||||
assert.strictEqual(xmlHeader["@encoding"], "UTF-8", filePath)
|
||||
assert.strictEqual(xmlHeader["@version"], "1.0", filePath)
|
||||
break
|
||||
}
|
||||
case "ARTICLE": {
|
||||
const article = element as Article
|
||||
await db`
|
||||
INSERT INTO article (
|
||||
id,
|
||||
data
|
||||
) VALUES (
|
||||
${article.META.META_COMMUN.ID},
|
||||
${db.json(article as unknown as JSONValue)}
|
||||
)
|
||||
ON CONFLICT (id)
|
||||
DO UPDATE SET
|
||||
data = ${db.json(article as unknown as JSONValue)}
|
||||
`
|
||||
articleRemainingIds.delete(article.META.META_COMMUN.ID)
|
||||
break
|
||||
}
|
||||
case "IDCC": {
|
||||
const idcc = element as Idcc
|
||||
await db`
|
||||
INSERT INTO idcc (
|
||||
id,
|
||||
data
|
||||
) VALUES (
|
||||
${idcc.META.META_COMMUN.ID},
|
||||
${db.json(idcc as unknown as JSONValue)}
|
||||
)
|
||||
ON CONFLICT (id)
|
||||
DO UPDATE SET
|
||||
data = ${db.json(idcc as unknown as JSONValue)}
|
||||
`
|
||||
idccRemainingIds.delete(idcc.META.META_COMMUN.ID)
|
||||
break
|
||||
}
|
||||
case "SECTION_TA": {
|
||||
const section = element as SectionTa
|
||||
await db`
|
||||
INSERT INTO section_ta (
|
||||
id,
|
||||
data
|
||||
) VALUES (
|
||||
${section.ID},
|
||||
${db.json(section as unknown as JSONValue)}
|
||||
)
|
||||
ON CONFLICT (id)
|
||||
DO UPDATE SET
|
||||
data = ${db.json(section as unknown as JSONValue)}
|
||||
`
|
||||
sectionTaRemainingIds.delete(section.ID)
|
||||
break
|
||||
}
|
||||
case "TEXTE_VERSION": {
|
||||
const version = element as TexteVersion
|
||||
await db`
|
||||
INSERT INTO texte_version (
|
||||
id,
|
||||
data
|
||||
) VALUES (
|
||||
${version.META.META_COMMUN.ID},
|
||||
${db.json(version as unknown as JSONValue)}
|
||||
)
|
||||
ON CONFLICT (id)
|
||||
DO UPDATE SET
|
||||
data = ${db.json(version as unknown as JSONValue)}
|
||||
`
|
||||
texteVersionRemainingIds.delete(version.META.META_COMMUN.ID)
|
||||
break
|
||||
}
|
||||
case "TEXTEKALI": {
|
||||
const textekali = element as Textekali
|
||||
await db`
|
||||
INSERT INTO textekali (
|
||||
id,
|
||||
data
|
||||
) VALUES (
|
||||
${textekali.META.META_COMMUN.ID},
|
||||
${db.json(textekali as unknown as JSONValue)}
|
||||
)
|
||||
ON CONFLICT (id)
|
||||
DO UPDATE SET
|
||||
data = ${db.json(textekali as unknown as JSONValue)}
|
||||
`
|
||||
textekaliRemainingIds.delete(textekali.META.META_COMMUN.ID)
|
||||
break
|
||||
}
|
||||
case "TEXTELR": {
|
||||
const textelr = element as Textelr
|
||||
await db`
|
||||
INSERT INTO textelr (
|
||||
id,
|
||||
data
|
||||
) VALUES (
|
||||
${textelr.META.META_COMMUN.ID},
|
||||
${db.json(textelr as unknown as JSONValue)}
|
||||
)
|
||||
ON CONFLICT (id)
|
||||
DO UPDATE SET
|
||||
data = ${db.json(textelr as unknown as JSONValue)}
|
||||
`
|
||||
textelrRemainingIds.delete(textelr.META.META_COMMUN.ID)
|
||||
break
|
||||
}
|
||||
default: {
|
||||
console.warn(
|
||||
`Unexpected root element "${key}" in XML file: ${filePath}`,
|
||||
)
|
||||
break iterXmlFiles
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("An error occurred while parsing XML file", filePath)
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
if (deleteRemainingIds) {
|
||||
for (const id of articleRemainingIds) {
|
||||
console.log(`Deleting ARTICLE ${id}…`)
|
||||
await db`
|
||||
DELETE FROM article
|
||||
WHERE id = ${id}
|
||||
`
|
||||
}
|
||||
for (const id of idccRemainingIds) {
|
||||
console.log(`Deleting IDCC ${id}…`)
|
||||
await db`
|
||||
DELETE FROM idcc
|
||||
WHERE id = ${id}
|
||||
`
|
||||
}
|
||||
for (const id of sectionTaRemainingIds) {
|
||||
console.log(`Deleting SECTION_TA ${id}…`)
|
||||
await db`
|
||||
DELETE FROM section_ta
|
||||
WHERE id = ${id}
|
||||
`
|
||||
}
|
||||
for (const id of textekaliRemainingIds) {
|
||||
console.log(`Deleting TEXTEKALI ${id}…`)
|
||||
await db`
|
||||
DELETE FROM textekali
|
||||
WHERE id = ${id}
|
||||
`
|
||||
}
|
||||
for (const id of textelrRemainingIds) {
|
||||
console.log(`Deleting TEXTELR ${id}…`)
|
||||
await db`
|
||||
DELETE FROM textelr
|
||||
WHERE id = ${id}
|
||||
`
|
||||
}
|
||||
for (const id of texteVersionRemainingIds) {
|
||||
console.log(`Deleting TEXTE_VERSION ${id}…`)
|
||||
await db`
|
||||
DELETE FROM texte_version
|
||||
WHERE id = ${id}
|
||||
`
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sade("import_kali", true)
|
||||
.describe("Import Dila's KALI database")
|
||||
.option("-r", "--resume", "Resume import at given relative file path")
|
||||
.example(
|
||||
"--resume global/conteneur/KALI/CONT/00/00/05/63/50/KALICONT000005635082.xml",
|
||||
)
|
||||
.action(async (options) => {
|
||||
await importKali(options)
|
||||
process.exit(0)
|
||||
})
|
||||
.parse(process.argv)
|
|
@ -80,6 +80,14 @@ export async function configureDatabase() {
|
|||
)
|
||||
`
|
||||
|
||||
// Table: idcc
|
||||
await db`
|
||||
CREATE TABLE IF NOT EXISTS idcc (
|
||||
id char(20) PRIMARY KEY,
|
||||
data jsonb NOT NULL
|
||||
)
|
||||
`
|
||||
|
||||
// Table: jo
|
||||
await db`
|
||||
CREATE TABLE IF NOT EXISTS jo (
|
||||
|
@ -104,6 +112,14 @@ export async function configureDatabase() {
|
|||
)
|
||||
`
|
||||
|
||||
// Table: textekali
|
||||
await db`
|
||||
CREATE TABLE IF NOT EXISTS textekali (
|
||||
id char(20) PRIMARY KEY,
|
||||
data jsonb NOT NULL
|
||||
)
|
||||
`
|
||||
|
||||
// Table: textelr
|
||||
await db`
|
||||
CREATE TABLE IF NOT EXISTS textelr (
|
||||
|
|
|
@ -5,6 +5,7 @@ import {
|
|||
type Article,
|
||||
assertNeverLegalObjectType,
|
||||
bestItemForDate,
|
||||
type Idcc,
|
||||
type IdWrapper,
|
||||
type Jo,
|
||||
type LegalObject,
|
||||
|
@ -12,6 +13,7 @@ import {
|
|||
pathnameFromLegalObject,
|
||||
pathnameFromLegalObjectId,
|
||||
type SectionTa,
|
||||
type Textekali,
|
||||
type Textelr,
|
||||
type TexteVersion,
|
||||
type LienArt,
|
||||
|
@ -107,6 +109,17 @@ export const summarizeDossierLegislatifProperties: Summarizer = (
|
|||
return undefined
|
||||
}
|
||||
|
||||
export const summarizeIdccProperties: Summarizer = (access, value) => {
|
||||
if (access?.key === "idcc" && typeof value !== "number") {
|
||||
return summarizeLegalObject(access, "idcc", value)
|
||||
}
|
||||
if (typeof access?.key === "number" && access?.access?.key === "idcc") {
|
||||
return summarizeLegalObjectToLink(access, "idcc", value)
|
||||
}
|
||||
|
||||
return undefined
|
||||
}
|
||||
|
||||
export const summarizeIdWrapperProperties: Summarizer = (access, value) => {
|
||||
if (access?.key === "id" && typeof value !== "number") {
|
||||
return summarizeLegalObject(access, "id", value)
|
||||
|
@ -182,6 +195,10 @@ export function summarizeLegalObject(
|
|||
case "id":
|
||||
const idWrapper = value as IdWrapper | undefined
|
||||
return idWrapper?.eli
|
||||
case "idcc": {
|
||||
const idcc = value as Idcc | undefined
|
||||
return idcc?.META.META_SPEC.META_CONTENEUR.TITRE
|
||||
}
|
||||
case "jo": {
|
||||
const jo = value as Jo | undefined
|
||||
return jo?.META.META_SPEC.META_CONTENEUR.TITRE
|
||||
|
@ -200,6 +217,10 @@ export function summarizeLegalObject(
|
|||
const texteVersion = value as TexteVersion | undefined
|
||||
return texteVersion?.META.META_SPEC.META_TEXTE_VERSION.TITREFULL
|
||||
}
|
||||
case "textekali": {
|
||||
const textekali = value as Textekali | undefined
|
||||
return textekali?.META.META_COMMUN.ID
|
||||
}
|
||||
case "textelr": {
|
||||
const textelr = value as Textelr | undefined
|
||||
return textelr?.META.META_COMMUN.ID
|
||||
|
@ -282,6 +303,17 @@ export const summarizeSectionTaProperties: Summarizer = (access, value) => {
|
|||
return undefined
|
||||
}
|
||||
|
||||
export const summarizeTextekaliProperties: Summarizer = (access, value) => {
|
||||
if (access?.key === "textekali" && typeof value !== "number") {
|
||||
return summarizeLegalObject(access, "textekali", value)
|
||||
}
|
||||
if (typeof access?.key === "number" && access?.access?.key === "textekali") {
|
||||
return summarizeLegalObjectToLink(access, "textekali", value)
|
||||
}
|
||||
|
||||
return undefined
|
||||
}
|
||||
|
||||
export const summarizeTextelrProperties: Summarizer = (access, value) => {
|
||||
if (access?.key === "textelr" && typeof value !== "number") {
|
||||
return summarizeLegalObject(access, "textelr", value)
|
||||
|
|
|
@ -32,9 +32,11 @@
|
|||
{ href: "/article", label: "ARTICLE" },
|
||||
{ href: "/dossier_legislatif", label: "DOSSIER_LEGISLATIF" },
|
||||
{ href: "/id", label: "ID" },
|
||||
{ href: "/idcc", label: "IDCC" },
|
||||
{ href: "/jo", label: "JO" },
|
||||
{ href: "/section_ta", label: "SECTION_TA" },
|
||||
{ href: "/texte_version", label: "TEXTE_VERSION" },
|
||||
{ href: "/textekali", label: "TEXTEKALI" },
|
||||
{ href: "/textelr", label: "TEXTELR" },
|
||||
{ href: "/versions", label: "VERSIONS" },
|
||||
],
|
||||
|
|
43
src/routes/dossier_legislatif/[id].svelte
Normal file
43
src/routes/dossier_legislatif/[id].svelte
Normal file
|
@ -0,0 +1,43 @@
|
|||
<script lang="ts">
|
||||
import { TreeView, SummaryView } from "augmented-data-viewer"
|
||||
|
||||
import ErrorAlert from "$lib/components/errors/ErrorAlert.svelte"
|
||||
import type { DossierLegislatif } from "$lib/data"
|
||||
import {
|
||||
summarizeDossierLegislatifProperties,
|
||||
summarizeLegalObject,
|
||||
} from "$lib/summaries"
|
||||
|
||||
export let error: unknown
|
||||
let dossierLegislatif: DossierLegislatif
|
||||
export { dossierLegislatif as dossier_legislatif }
|
||||
|
||||
const summary = summarizeLegalObject(
|
||||
{ key: "dossier_legislatif" },
|
||||
"dossier_legislatif",
|
||||
dossierLegislatif,
|
||||
)
|
||||
</script>
|
||||
|
||||
<header class="prose my-6 max-w-full">
|
||||
<h2>DOSSIER_LEGISLATIF</h2>
|
||||
{#if summary !== undefined}
|
||||
<h1>
|
||||
<SummaryView {summary} />
|
||||
</h1>
|
||||
{/if}
|
||||
</header>
|
||||
|
||||
{#if error != null}
|
||||
<ErrorAlert {error} />
|
||||
{/if}
|
||||
|
||||
{#if error == null}
|
||||
<TreeView
|
||||
access={{ key: "dossier_legislatif" }}
|
||||
frame={false}
|
||||
open
|
||||
summarize={summarizeDossierLegislatifProperties}
|
||||
value={dossierLegislatif}
|
||||
/>
|
||||
{/if}
|
22
src/routes/dossier_legislatif/[id].ts
Normal file
22
src/routes/dossier_legislatif/[id].ts
Normal file
|
@ -0,0 +1,22 @@
|
|||
import type { RequestHandler } from "@sveltejs/kit"
|
||||
import type { JSONObject } from "@sveltejs/kit/types/private"
|
||||
|
||||
import type { DossierLegislatif } from "$lib/data"
|
||||
import { db } from "$lib/server/database"
|
||||
|
||||
export const GET: RequestHandler = async ({ params }) => {
|
||||
const dossierLegislatif = (
|
||||
await db<{ data: DossierLegislatif }[]>`
|
||||
SELECT data FROM dossier_legislatif
|
||||
WHERE id = ${params.id}
|
||||
`
|
||||
).map(({ data }) => data)[0]
|
||||
|
||||
if (dossierLegislatif === undefined) {
|
||||
return { headers: { "Access-Control-Allow-Origin": "*" }, status: 404 }
|
||||
}
|
||||
return {
|
||||
headers: { "Access-Control-Allow-Origin": "*" },
|
||||
body: { dossier_legislatif: dossierLegislatif as unknown as JSONObject },
|
||||
}
|
||||
}
|
68
src/routes/dossier_legislatif/index.svelte
Normal file
68
src/routes/dossier_legislatif/index.svelte
Normal file
|
@ -0,0 +1,68 @@
|
|||
<script lang="ts">
|
||||
// import Icon from "@iconify/svelte"
|
||||
// import searchIcon from "@iconify-icons/codicon/search"
|
||||
import { TreeView } from "augmented-data-viewer"
|
||||
|
||||
// import { page } from "$app/stores"
|
||||
import ErrorAlert from "$lib/components/errors/ErrorAlert.svelte"
|
||||
import Pagination from "$lib/components/Pagination.svelte"
|
||||
import type { DossierLegislatif } from "$lib/data"
|
||||
import { summarizeDossierLegislatifProperties } from "$lib/summaries"
|
||||
|
||||
let dossiersLegislatifs: DossierLegislatif[]
|
||||
export { dossiersLegislatifs as dossier_legislatif }
|
||||
export let error: unknown
|
||||
</script>
|
||||
|
||||
<header class="prose my-6 max-w-full">
|
||||
<h1>DOSSIER_LEGISLATIF</h1>
|
||||
</header>
|
||||
|
||||
<!-- <form action={$page.url.pathname} class="mx-auto max-w-sm" method="get">
|
||||
<div class="form-control">
|
||||
<div class="input-group">
|
||||
<input
|
||||
class="input input-bordered"
|
||||
name="q"
|
||||
type="search"
|
||||
bind:value={q}
|
||||
/>
|
||||
<button class="btn btn-square" type="submit">
|
||||
<Icon icon={searchIcon} />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-control">
|
||||
<label class="label">
|
||||
<span class="label-text">Législature</span>
|
||||
<select
|
||||
class="select select-bordered"
|
||||
name="legislature"
|
||||
bind:value={legislature}
|
||||
>
|
||||
<option value="">Toutes</option>
|
||||
{#each Object.entries(Legislature) as [key, value]}
|
||||
{#if value !== "*"}
|
||||
<option {value}>{key}</option>
|
||||
{/if}
|
||||
{/each}
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
</form> -->
|
||||
|
||||
{#if error != null}
|
||||
<ErrorAlert {error} />
|
||||
{/if}
|
||||
|
||||
{#if error == null}
|
||||
<TreeView
|
||||
access={{ key: "dossier_legislatif" }}
|
||||
frame={false}
|
||||
open
|
||||
summarize={summarizeDossierLegislatifProperties}
|
||||
value={dossiersLegislatifs}
|
||||
/>
|
||||
|
||||
<Pagination currentPageCount={dossiersLegislatifs.length ?? 0} />
|
||||
{/if}
|
74
src/routes/dossier_legislatif/index.ts
Normal file
74
src/routes/dossier_legislatif/index.ts
Normal file
|
@ -0,0 +1,74 @@
|
|||
import { type Audit, auditSetNullish, cleanAudit } from "@auditors/core"
|
||||
import type { RequestHandler } from "@sveltejs/kit"
|
||||
import type { JSONObject } from "@sveltejs/kit/types/private"
|
||||
|
||||
import { auditSearchQueryContent } from "$lib/auditors/queries"
|
||||
import type { DossierLegislatif } from "$lib/data"
|
||||
import { db } from "$lib/server/database"
|
||||
|
||||
export function auditQuery(
|
||||
audit: Audit,
|
||||
query: URLSearchParams,
|
||||
): [unknown, unknown] {
|
||||
if (query == null) {
|
||||
return [query, null]
|
||||
}
|
||||
if (!(query instanceof URLSearchParams)) {
|
||||
return audit.unexpectedType(query, "URLSearchParams")
|
||||
}
|
||||
|
||||
const data: { [key: string]: unknown } = {}
|
||||
for (const [key, value] of query.entries()) {
|
||||
let values = data[key] as string[] | undefined
|
||||
if (values === undefined) {
|
||||
values = data[key] = []
|
||||
}
|
||||
values.push(value)
|
||||
}
|
||||
const errors: { [key: string]: unknown } = {}
|
||||
const remainingKeys = new Set(Object.keys(data))
|
||||
|
||||
auditSearchQueryContent(audit, data, errors, remainingKeys)
|
||||
|
||||
return audit.reduceRemaining(data, errors, remainingKeys, auditSetNullish({}))
|
||||
}
|
||||
|
||||
export const GET: RequestHandler = async ({ url }) => {
|
||||
const [query, queryError] = auditQuery(cleanAudit, url.searchParams) as [
|
||||
{ limit: number; offset: number; q?: string },
|
||||
unknown,
|
||||
]
|
||||
if (queryError !== null) {
|
||||
console.error(
|
||||
`Error in ${url.pathname} query:\n${JSON.stringify(
|
||||
query,
|
||||
null,
|
||||
2,
|
||||
)}\n\nError:\n${JSON.stringify(queryError, null, 2)}`,
|
||||
)
|
||||
return {
|
||||
// status: 400,
|
||||
headers: { "Access-Control-Allow-Origin": "*" },
|
||||
body: {
|
||||
error: {
|
||||
query: queryError as unknown as JSONObject,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
const { limit, offset } = query
|
||||
|
||||
const dossiersLegislatifs = (
|
||||
await db<{ data: DossierLegislatif }[]>`
|
||||
SELECT data FROM dossier_legislatif
|
||||
OFFSET ${offset}
|
||||
LIMIT ${limit}
|
||||
`
|
||||
).map(({ data }) => data)
|
||||
return {
|
||||
headers: { "Access-Control-Allow-Origin": "*" },
|
||||
body: {
|
||||
dossier_legislatif: dossiersLegislatifs as unknown as JSONObject[],
|
||||
},
|
||||
}
|
||||
}
|
35
src/routes/idcc/[id].svelte
Normal file
35
src/routes/idcc/[id].svelte
Normal file
|
@ -0,0 +1,35 @@
|
|||
<script lang="ts">
|
||||
import { TreeView, SummaryView } from "augmented-data-viewer"
|
||||
|
||||
import ErrorAlert from "$lib/components/errors/ErrorAlert.svelte"
|
||||
import type { Idcc } from "$lib/data"
|
||||
import { summarizeIdccProperties, summarizeLegalObject } from "$lib/summaries"
|
||||
|
||||
export let error: unknown
|
||||
export let idcc: Idcc
|
||||
|
||||
const summary = summarizeLegalObject({ key: "idcc" }, "idcc", idcc)
|
||||
</script>
|
||||
|
||||
<header class="prose my-6 max-w-full">
|
||||
<h2>IDCC</h2>
|
||||
{#if summary !== undefined}
|
||||
<h1>
|
||||
<SummaryView {summary} />
|
||||
</h1>
|
||||
{/if}
|
||||
</header>
|
||||
|
||||
{#if error != null}
|
||||
<ErrorAlert {error} />
|
||||
{/if}
|
||||
|
||||
{#if error == null}
|
||||
<TreeView
|
||||
access={{ key: "idcc" }}
|
||||
frame={false}
|
||||
open
|
||||
summarize={summarizeIdccProperties}
|
||||
value={idcc}
|
||||
/>
|
||||
{/if}
|
22
src/routes/idcc/[id].ts
Normal file
22
src/routes/idcc/[id].ts
Normal file
|
@ -0,0 +1,22 @@
|
|||
import type { RequestHandler } from "@sveltejs/kit"
|
||||
import type { JSONObject } from "@sveltejs/kit/types/private"
|
||||
|
||||
import type { Idcc } from "$lib/data"
|
||||
import { db } from "$lib/server/database"
|
||||
|
||||
export const GET: RequestHandler = async ({ params }) => {
|
||||
const idcc = (
|
||||
await db<{ data: Idcc }[]>`
|
||||
SELECT data FROM idcc
|
||||
WHERE id = ${params.id}
|
||||
`
|
||||
).map(({ data }) => data)[0]
|
||||
|
||||
if (idcc === undefined) {
|
||||
return { headers: { "Access-Control-Allow-Origin": "*" }, status: 404 }
|
||||
}
|
||||
return {
|
||||
headers: { "Access-Control-Allow-Origin": "*" },
|
||||
body: { idcc: idcc as unknown as JSONObject },
|
||||
}
|
||||
}
|
68
src/routes/idcc/index.svelte
Normal file
68
src/routes/idcc/index.svelte
Normal file
|
@ -0,0 +1,68 @@
|
|||
<script lang="ts">
|
||||
// import Icon from "@iconify/svelte"
|
||||
// import searchIcon from "@iconify-icons/codicon/search"
|
||||
import { TreeView } from "augmented-data-viewer"
|
||||
|
||||
// import { page } from "$app/stores"
|
||||
import ErrorAlert from "$lib/components/errors/ErrorAlert.svelte"
|
||||
import Pagination from "$lib/components/Pagination.svelte"
|
||||
import type { Idcc } from "$lib/data"
|
||||
import { summarizeIdccProperties } from "$lib/summaries"
|
||||
|
||||
export let error: unknown
|
||||
let idccArray: Idcc[]
|
||||
export { idccArray as idcc }
|
||||
</script>
|
||||
|
||||
<header class="prose my-6 max-w-full">
|
||||
<h1>IDCC</h1>
|
||||
</header>
|
||||
|
||||
<!-- <form action={$page.url.pathname} class="mx-auto max-w-sm" method="get">
|
||||
<div class="form-control">
|
||||
<div class="input-group">
|
||||
<input
|
||||
class="input input-bordered"
|
||||
name="q"
|
||||
type="search"
|
||||
bind:value={q}
|
||||
/>
|
||||
<button class="btn btn-square" type="submit">
|
||||
<Icon icon={searchIcon} />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-control">
|
||||
<label class="label">
|
||||
<span class="label-text">Législature</span>
|
||||
<select
|
||||
class="select select-bordered"
|
||||
name="legislature"
|
||||
bind:value={legislature}
|
||||
>
|
||||
<option value="">Toutes</option>
|
||||
{#each Object.entries(Legislature) as [key, value]}
|
||||
{#if value !== "*"}
|
||||
<option {value}>{key}</option>
|
||||
{/if}
|
||||
{/each}
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
</form> -->
|
||||
|
||||
{#if error != null}
|
||||
<ErrorAlert {error} />
|
||||
{/if}
|
||||
|
||||
{#if error == null}
|
||||
<TreeView
|
||||
access={{ key: "idcc" }}
|
||||
frame={false}
|
||||
open
|
||||
summarize={summarizeIdccProperties}
|
||||
value={idccArray}
|
||||
/>
|
||||
|
||||
<Pagination currentPageCount={idccArray.length ?? 0} />
|
||||
{/if}
|
72
src/routes/idcc/index.ts
Normal file
72
src/routes/idcc/index.ts
Normal file
|
@ -0,0 +1,72 @@
|
|||
import { type Audit, auditSetNullish, cleanAudit } from "@auditors/core"
|
||||
import type { RequestHandler } from "@sveltejs/kit"
|
||||
import type { JSONObject } from "@sveltejs/kit/types/private"
|
||||
|
||||
import { auditSearchQueryContent } from "$lib/auditors/queries"
|
||||
import type { Idcc } from "$lib/data"
|
||||
import { db } from "$lib/server/database"
|
||||
|
||||
export function auditQuery(
|
||||
audit: Audit,
|
||||
query: URLSearchParams,
|
||||
): [unknown, unknown] {
|
||||
if (query == null) {
|
||||
return [query, null]
|
||||
}
|
||||
if (!(query instanceof URLSearchParams)) {
|
||||
return audit.unexpectedType(query, "URLSearchParams")
|
||||
}
|
||||
|
||||
const data: { [key: string]: unknown } = {}
|
||||
for (const [key, value] of query.entries()) {
|
||||
let values = data[key] as string[] | undefined
|
||||
if (values === undefined) {
|
||||
values = data[key] = []
|
||||
}
|
||||
values.push(value)
|
||||
}
|
||||
const errors: { [key: string]: unknown } = {}
|
||||
const remainingKeys = new Set(Object.keys(data))
|
||||
|
||||
auditSearchQueryContent(audit, data, errors, remainingKeys)
|
||||
|
||||
return audit.reduceRemaining(data, errors, remainingKeys, auditSetNullish({}))
|
||||
}
|
||||
|
||||
export const GET: RequestHandler = async ({ url }) => {
|
||||
const [query, queryError] = auditQuery(cleanAudit, url.searchParams) as [
|
||||
{ limit: number; offset: number; q?: string },
|
||||
unknown,
|
||||
]
|
||||
if (queryError !== null) {
|
||||
console.error(
|
||||
`Error in ${url.pathname} query:\n${JSON.stringify(
|
||||
query,
|
||||
null,
|
||||
2,
|
||||
)}\n\nError:\n${JSON.stringify(queryError, null, 2)}`,
|
||||
)
|
||||
return {
|
||||
// status: 400,
|
||||
headers: { "Access-Control-Allow-Origin": "*" },
|
||||
body: {
|
||||
error: {
|
||||
query: queryError as unknown as JSONObject,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
const { limit, offset } = query
|
||||
|
||||
const idccArray = (
|
||||
await db<{ data: Idcc }[]>`
|
||||
SELECT data FROM idcc
|
||||
OFFSET ${offset}
|
||||
LIMIT ${limit}
|
||||
`
|
||||
).map(({ data }) => data)
|
||||
return {
|
||||
headers: { "Access-Control-Allow-Origin": "*" },
|
||||
body: { idcc: idccArray as unknown as JSONObject[] },
|
||||
}
|
||||
}
|
42
src/routes/textekali/[id].svelte
Normal file
42
src/routes/textekali/[id].svelte
Normal file
|
@ -0,0 +1,42 @@
|
|||
<script lang="ts">
|
||||
import { TreeView, SummaryView } from "augmented-data-viewer"
|
||||
|
||||
import ErrorAlert from "$lib/components/errors/ErrorAlert.svelte"
|
||||
import type { Textekali } from "$lib/data"
|
||||
import {
|
||||
summarizeTextekaliProperties,
|
||||
summarizeLegalObject,
|
||||
} from "$lib/summaries"
|
||||
|
||||
export let error: unknown
|
||||
export let textekali: Textekali
|
||||
|
||||
const summary = summarizeLegalObject(
|
||||
{ key: "textekali" },
|
||||
"textekali",
|
||||
textekali,
|
||||
)
|
||||
</script>
|
||||
|
||||
<header class="prose my-6 max-w-full">
|
||||
<h2>TEXTEKALI</h2>
|
||||
{#if summary !== undefined}
|
||||
<h1>
|
||||
<SummaryView {summary} />
|
||||
</h1>
|
||||
{/if}
|
||||
</header>
|
||||
|
||||
{#if error != null}
|
||||
<ErrorAlert {error} />
|
||||
{/if}
|
||||
|
||||
{#if error == null}
|
||||
<TreeView
|
||||
access={{ key: "textekali" }}
|
||||
frame={false}
|
||||
open
|
||||
summarize={summarizeTextekaliProperties}
|
||||
value={textekali}
|
||||
/>
|
||||
{/if}
|
22
src/routes/textekali/[id].ts
Normal file
22
src/routes/textekali/[id].ts
Normal file
|
@ -0,0 +1,22 @@
|
|||
import type { RequestHandler } from "@sveltejs/kit"
|
||||
import type { JSONObject } from "@sveltejs/kit/types/private"
|
||||
|
||||
import type { Textekali } from "$lib/data"
|
||||
import { db } from "$lib/server/database"
|
||||
|
||||
export const GET: RequestHandler = async ({ params }) => {
|
||||
const textekali = (
|
||||
await db<{ data: Textekali }[]>`
|
||||
SELECT data FROM textekali
|
||||
WHERE id = ${params.id}
|
||||
`
|
||||
).map(({ data }) => data)[0]
|
||||
|
||||
if (textekali === undefined) {
|
||||
return { headers: { "Access-Control-Allow-Origin": "*" }, status: 404 }
|
||||
}
|
||||
return {
|
||||
headers: { "Access-Control-Allow-Origin": "*" },
|
||||
body: { textekali: textekali as unknown as JSONObject },
|
||||
}
|
||||
}
|
68
src/routes/textekali/index.svelte
Normal file
68
src/routes/textekali/index.svelte
Normal file
|
@ -0,0 +1,68 @@
|
|||
<script lang="ts">
|
||||
// import Icon from "@iconify/svelte"
|
||||
// import searchIcon from "@iconify-icons/codicon/search"
|
||||
import { TreeView } from "augmented-data-viewer"
|
||||
|
||||
// import { page } from "$app/stores"
|
||||
import ErrorAlert from "$lib/components/errors/ErrorAlert.svelte"
|
||||
import Pagination from "$lib/components/Pagination.svelte"
|
||||
import type { Textekali } from "$lib/data"
|
||||
import { summarizeTextekaliProperties } from "$lib/summaries"
|
||||
|
||||
export let error: unknown
|
||||
let textekaliArray: Textekali[]
|
||||
export { textekaliArray as textekali }
|
||||
</script>
|
||||
|
||||
<header class="prose my-6 max-w-full">
|
||||
<h1>TEXTEKALI</h1>
|
||||
</header>
|
||||
|
||||
<!-- <form action={$page.url.pathname} class="mx-auto max-w-sm" method="get">
|
||||
<div class="form-control">
|
||||
<div class="input-group">
|
||||
<input
|
||||
class="input input-bordered"
|
||||
name="q"
|
||||
type="search"
|
||||
bind:value={q}
|
||||
/>
|
||||
<button class="btn btn-square" type="submit">
|
||||
<Icon icon={searchIcon} />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-control">
|
||||
<label class="label">
|
||||
<span class="label-text">Législature</span>
|
||||
<select
|
||||
class="select select-bordered"
|
||||
name="legislature"
|
||||
bind:value={legislature}
|
||||
>
|
||||
<option value="">Toutes</option>
|
||||
{#each Object.entries(Legislature) as [key, value]}
|
||||
{#if value !== "*"}
|
||||
<option {value}>{key}</option>
|
||||
{/if}
|
||||
{/each}
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
</form> -->
|
||||
|
||||
{#if error != null}
|
||||
<ErrorAlert {error} />
|
||||
{/if}
|
||||
|
||||
{#if error == null}
|
||||
<TreeView
|
||||
access={{ key: "textekali" }}
|
||||
frame={false}
|
||||
open
|
||||
summarize={summarizeTextekaliProperties}
|
||||
value={textekaliArray}
|
||||
/>
|
||||
|
||||
<Pagination currentPageCount={textekaliArray.length ?? 0} />
|
||||
{/if}
|
72
src/routes/textekali/index.ts
Normal file
72
src/routes/textekali/index.ts
Normal file
|
@ -0,0 +1,72 @@
|
|||
import { type Audit, auditSetNullish, cleanAudit } from "@auditors/core"
|
||||
import type { RequestHandler } from "@sveltejs/kit"
|
||||
import type { JSONObject } from "@sveltejs/kit/types/private"
|
||||
|
||||
import { auditSearchQueryContent } from "$lib/auditors/queries"
|
||||
import type { Textekali } from "$lib/data"
|
||||
import { db } from "$lib/server/database"
|
||||
|
||||
export function auditQuery(
|
||||
audit: Audit,
|
||||
query: URLSearchParams,
|
||||
): [unknown, unknown] {
|
||||
if (query == null) {
|
||||
return [query, null]
|
||||
}
|
||||
if (!(query instanceof URLSearchParams)) {
|
||||
return audit.unexpectedType(query, "URLSearchParams")
|
||||
}
|
||||
|
||||
const data: { [key: string]: unknown } = {}
|
||||
for (const [key, value] of query.entries()) {
|
||||
let values = data[key] as string[] | undefined
|
||||
if (values === undefined) {
|
||||
values = data[key] = []
|
||||
}
|
||||
values.push(value)
|
||||
}
|
||||
const errors: { [key: string]: unknown } = {}
|
||||
const remainingKeys = new Set(Object.keys(data))
|
||||
|
||||
auditSearchQueryContent(audit, data, errors, remainingKeys)
|
||||
|
||||
return audit.reduceRemaining(data, errors, remainingKeys, auditSetNullish({}))
|
||||
}
|
||||
|
||||
export const GET: RequestHandler = async ({ url }) => {
|
||||
const [query, queryError] = auditQuery(cleanAudit, url.searchParams) as [
|
||||
{ limit: number; offset: number; q?: string },
|
||||
unknown,
|
||||
]
|
||||
if (queryError !== null) {
|
||||
console.error(
|
||||
`Error in ${url.pathname} query:\n${JSON.stringify(
|
||||
query,
|
||||
null,
|
||||
2,
|
||||
)}\n\nError:\n${JSON.stringify(queryError, null, 2)}`,
|
||||
)
|
||||
return {
|
||||
// status: 400,
|
||||
headers: { "Access-Control-Allow-Origin": "*" },
|
||||
body: {
|
||||
error: {
|
||||
query: queryError as unknown as JSONObject,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
const { limit, offset } = query
|
||||
|
||||
const textekaliArray = (
|
||||
await db<{ data: Textekali }[]>`
|
||||
SELECT data FROM textekali
|
||||
OFFSET ${offset}
|
||||
LIMIT ${limit}
|
||||
`
|
||||
).map(({ data }) => data)
|
||||
return {
|
||||
headers: { "Access-Control-Allow-Origin": "*" },
|
||||
body: { textekali: textekaliArray as unknown as JSONObject[] },
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue