Commit 7fecd905 authored by Emmanuel Raviart's avatar Emmanuel Raviart

Prettify & use Biryani.

parent e87ab1da
......@@ -2013,6 +2013,11 @@
"to-fast-properties": "^2.0.0"
}
},
"@biryani/core": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/@biryani/core/-/core-0.2.0.tgz",
"integrity": "sha512-9cj6BPW49Tgqex2eIFXYFo1HF0QvFOybxwozjk39tE5BjSo+QJHiEoKTBCCWzv4g+fx/HiLW3IRe7DZZwTG+SA=="
},
"@csstools/convert-colors": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/@csstools/convert-colors/-/convert-colors-1.4.0.tgz",
......
......@@ -15,6 +15,7 @@
"> 0.25%, not dead"
],
"dependencies": {
"@biryani/core": "^0.2.0",
"body-parser": "^1.19.0",
"cached-iterable": "^0.3.0",
"compression": "^1.7.4",
......
<script context="module">
import { validateChoice } from "@biryani/core"
import { acceptedLanguages } from "../../locales"
import { language } from "../../stores"
import {
validateChoice,
} from "../../validators/core"
export function preload(page /* , session */) {
const [params, error] = validateParams(page.params)
if (error !== null) {
return this.error(
400,
`Errors in query parameters: ${JSON.stringify(
error,
null,
2,
)}`,
`Errors in query parameters: ${JSON.stringify(error, null, 2)}`,
)
}
......
<script context="module">
import {
faExclamationTriangle,
} from "@fortawesome/free-solid-svg-icons/faExclamationTriangle"
import Icon from "fa-svelte"
import {
validateChain,
validateInteger,
......@@ -13,7 +8,11 @@
validateSetValue,
validateStringToNumber,
validateTest,
} from "../../validators/core"
} from "@biryani/core"
import {
faExclamationTriangle,
} from "@fortawesome/free-solid-svg-icons/faExclamationTriangle"
import Icon from "fa-svelte"
export async function preload(pageInfos, session) {
const { user } = session
......@@ -55,7 +54,7 @@
{
const key = "page"
remainingKeys.delete(key)
const [value, error] = validateChain([
const [value, error] = validateChain(
validateMaybeTrimmedString,
validateOption([
[validateMissing, validateSetValue(1)],
......@@ -65,7 +64,7 @@
validateTest(value => value >= 1, "Expected a number ≥ 1"),
],
]),
])(data[key])
)(data[key])
data[key] = value
if (error !== null) {
errors[key] = error
......@@ -75,7 +74,7 @@
{
const key = "year"
remainingKeys.delete(key)
const [value, error] = validateChain([
const [value, error] = validateChain(
validateMaybeTrimmedString,
validateOption([
[validateMissing, validateSetValue(1930)],
......@@ -88,7 +87,7 @@
),
],
]),
])(data[key])
)(data[key])
data[key] = value
if (error !== null) {
errors[key] = error
......
import { validateNonEmptyTrimmedString } from "@biryani/core"
import { db } from "../../database"
import { toUserJson } from "../../model/users"
import { validateNonEmptyTrimmedString } from "../../validators/core"
export async function post(req, res, next) {
let [body, errors] = validateBody(req.body)
......@@ -13,10 +14,7 @@ export async function post(req, res, next) {
errors = {}
if (
(await db.one(
"SELECT EXISTS (SELECT 1 FROM users WHERE name = $1)",
username,
)).exists
(await db.one("SELECT EXISTS (SELECT 1 FROM users WHERE name = $1)", username)).exists
) {
errors["username"] = "An user with the same name already exists."
}
......
import { validateMaybeTrimmedString } from "@biryani/core"
import { db } from "../database"
import { slugify } from "../strings"
import { validateMaybeTrimmedString } from "../validators/core"
export async function get(req, res) {
const [query, error] = validateQuery(req.query)
......
import { db } from "../database"
import { slugify } from "../strings"
import {
validateStringToNumber,
validateChain,
......@@ -7,7 +5,10 @@ import {
validateMaybeTrimmedString,
validateString,
validateTest,
} from "../validators/core"
} from "@biryani/core"
import { db } from "../database"
import { slugify } from "../strings"
export async function get(req, res) {
const [query, error] = validateQuery(req.query)
......@@ -97,15 +98,12 @@ function validateQuery(data) {
{
const key = "district"
remainingKeys.delete(key)
const [value, error] = validateChain([
const [value, error] = validateChain(
validateString,
validateStringToNumber,
validateInteger,
validateTest(
value => value >= 0,
"Number must be greater than or equal to zero.",
),
])(data[key])
validateTest(value => value >= 0, "Number must be greater than or equal to zero."),
)(data[key])
data[key] = value
if (error !== null) {
errors[key] = error
......@@ -125,7 +123,7 @@ function validateQuery(data) {
{
const key = "year"
remainingKeys.delete(key)
const [value, error] = validateChain([
const [value, error] = validateChain(
validateString,
validateStringToNumber,
validateInteger,
......@@ -133,7 +131,7 @@ function validateQuery(data) {
value => value >= 1700 && value < 2000,
"Expected a year between 1700 and 1999",
),
])(data[key])
)(data[key])
data[key] = value
if (error !== null) {
errors[key] = error
......
import { validateMaybeTrimmedString } from "@biryani/core"
import { db } from "../database"
import { slugify } from "../strings"
import { validateMaybeTrimmedString } from "../validators/core"
export async function get(req, res) {
const [query, error] = validateQuery(req.query)
......
import { db } from "../database"
import { slugify } from "../strings"
import {
validateStringToNumber,
validateChain,
......@@ -7,7 +5,10 @@ import {
validateMaybeTrimmedString,
validateString,
validateTest,
} from "../validators/core"
} from "@biryani/core"
import { db } from "../database"
import { slugify } from "../strings"
export async function get(req, res) {
const [query, error] = validateQuery(req.query)
......@@ -106,7 +107,7 @@ function validateQuery(data) {
{
const key = "year"
remainingKeys.delete(key)
const [value, error] = validateChain([
const [value, error] = validateChain(
validateString,
validateStringToNumber,
validateInteger,
......@@ -114,7 +115,7 @@ function validateQuery(data) {
value => value >= 1700 && value < 2000,
"Expected a year between 1700 and 1999",
),
])(data[key])
)(data[key])
data[key] = value
if (error !== null) {
errors[key] = error
......
import { validateMaybeTrimmedString } from "@biryani/core"
import { db } from "../database"
import { slugify } from "../strings"
import { validateMaybeTrimmedString } from "../validators/core"
export async function get(req, res) {
const [query, error] = validateQuery(req.query)
......
import { db } from "../database"
import {
validateStringToNumber,
validateInteger,
......@@ -6,7 +5,9 @@ import {
validateOption,
validateString,
validateTest,
} from "../validators/core"
} from "@biryani/core"
import { db } from "../database"
export async function get(req, res) {
const [query, error] = validateQuery(req.query)
......
import { db } from "../database"
import { slugify } from "../strings"
import {
validateChain,
validateInteger,
validateNonEmptyTrimmedString,
validateTest,
} from "../validators/core"
} from "@biryani/core"
import { db } from "../database"
import { slugify } from "../strings"
export async function post(req, res) {
const { user } = req
......@@ -30,11 +31,11 @@ export async function post(req, res) {
const [body, error] = await validateBody(req.body)
if (error !== null) {
console.error(
`Error in form:\n${JSON.stringify(
body,
`Error in form:\n${JSON.stringify(body, null, 2)}\n\nError:\n${JSON.stringify(
error,
null,
2,
)}\n\nError:\n${JSON.stringify(error, null, 2)}`,
)}`,
)
res.writeHead(400, {
"Content-Type": "application/json; charset=utf-8",
......@@ -171,9 +172,8 @@ async function validateBody(data) {
if (!slug) {
error = "Le texte ne contient aucun caractère signifiant."
} else if (
(await db.one("SELECT EXISTS(SELECT * FROM city_names WHERE slug=$1)", [
slug,
])).exists
(await db.one("SELECT EXISTS(SELECT * FROM city_names WHERE slug=$1)", [slug]))
.exists
) {
error = "Une localité ayant un nom similaire existe déjà."
}
......@@ -185,13 +185,10 @@ async function validateBody(data) {
for (let key of ["districtId", "page", "year"]) {
remainingKeys.delete(key)
const [value, error] = validateChain([
const [value, error] = validateChain(
validateInteger,
validateTest(
value => value >= 0,
"Number must be greater than or equal to zero.",
),
])(data[key])
validateTest(value => value >= 0, "Number must be greater than or equal to zero."),
)(data[key])
data[key] = value
if (error !== null) {
errors[key] = error
......
import { db } from "../database"
import { slugify } from "../strings"
import {
validateChain,
validateInteger,
validateNonEmptyTrimmedString,
validateTest,
} from "../validators/core"
} from "@biryani/core"
import { db } from "../database"
import { slugify } from "../strings"
export async function post(req, res) {
const { user } = req
......@@ -30,11 +31,11 @@ export async function post(req, res) {
const [body, error] = await validateBody(req.body)
if (error !== null) {
console.error(
`Error in form:\n${JSON.stringify(
body,
`Error in form:\n${JSON.stringify(body, null, 2)}\n\nError:\n${JSON.stringify(
error,
null,
2,
)}\n\nError:\n${JSON.stringify(error, null, 2)}`,
)}`,
)
res.writeHead(400, {
"Content-Type": "application/json; charset=utf-8",
......@@ -134,10 +135,7 @@ async function validateBody(data) {
return [data, "Value is empty."]
}
if (typeof data !== "object") {
return [
data,
`Expected an object, got "${typeof data}".`,
]
return [data, `Expected an object, got "${typeof data}".`]
}
data = {
......@@ -155,10 +153,9 @@ async function validateBody(data) {
if (!slug) {
error = "Le texte ne contient aucun caractère signifiant."
} else if (
(await db.one(
"SELECT EXISTS(SELECT * FROM corporation_names WHERE slug=$1)",
[slug],
)).exists
(await db.one("SELECT EXISTS(SELECT * FROM corporation_names WHERE slug=$1)", [
slug,
])).exists
) {
error = "Une entreprise ayant un nom similaire existe déjà."
}
......@@ -170,10 +167,10 @@ async function validateBody(data) {
for (let key of ["page", "year"]) {
remainingKeys.delete(key)
const [value, error] = validateChain([
const [value, error] = validateChain(
validateInteger,
validateTest(value => value >= 0, "Number must be greater than or equal to zero."),
])(data[key])
)(data[key])
data[key] = value
if (error !== null) {
errors[key] = error
......
import { validateNonEmptyTrimmedString } from "@biryani/core"
import fetch from "node-fetch"
import url from "url"
import serverConfig from "../server-config"
import { validateNonEmptyTrimmedString } from "../validators/core"
const { gitlab } = serverConfig
......@@ -10,11 +10,11 @@ export async function post(req, res) {
const [body, error] = validateBody(req.body)
if (error !== null) {
console.error(
`Error in form:\n${JSON.stringify(
body,
`Error in form:\n${JSON.stringify(body, null, 2)}\n\nError:\n${JSON.stringify(
error,
null,
2,
)}\n\nError:\n${JSON.stringify(error, null, 2)}`,
)}`,
)
res.writeHead(400, {
"Content-Type": "application/json; charset=utf-8",
......
import { validateNonEmptyTrimmedString } from "@biryani/core"
import { db } from "../database"
import { slugify } from "../strings"
import { validateNonEmptyTrimmedString } from "../validators/core"
export async function post(req, res) {
const { user } = req
......@@ -25,11 +26,11 @@ export async function post(req, res) {
const [body, error] = await validateBody(req.body)
if (error !== null) {
console.error(
`Error in form:\n${JSON.stringify(
body,
`Error in form:\n${JSON.stringify(body, null, 2)}\n\nError:\n${JSON.stringify(
error,
null,
2,
)}\n\nError:\n${JSON.stringify(error, null, 2)}`,
)}`,
)
res.writeHead(400, {
"Content-Type": "application/json; charset=utf-8",
......@@ -99,9 +100,7 @@ async function validateBody(data) {
if (!slug) {
error = "Le texte ne contient aucun caractère signifiant."
} else if (
(await db.one("SELECT EXISTS(SELECT * FROM jobs WHERE slug=$1)", [
slug,
])).exists
(await db.one("SELECT EXISTS(SELECT * FROM jobs WHERE slug=$1)", [slug])).exists
) {
error = "Un métier ayant un nom similaire existe déjà."
}
......
import { db } from "../database"
import {
validateStringToNumber,
validateChain,
validateInteger,
validateString,
validateTest,
} from "../validators/core"
} from "@biryani/core"
import { db } from "../database"
export async function get(req, res) {
const [query, error] = validateQuery(req.query)
......@@ -70,7 +71,7 @@ function validateQuery(data) {
{
const key = "year"
remainingKeys.delete(key)
const [value, error] = validateChain([
const [value, error] = validateChain(
validateString,
validateStringToNumber,
validateInteger,
......@@ -78,7 +79,7 @@ function validateQuery(data) {
value => value >= 1700 && value < 2000,
"Expected a year between 1700 and 1999",
),
])(data[key])
)(data[key])
data[key] = value
if (error !== null) {
errors[key] = error
......
import { db } from "../database"
import {
validateBoolean,
validateChain,
......@@ -8,7 +7,9 @@ import {
validateNonEmptyTrimmedString,
validateOption,
validateTest,
} from "../validators/core"
} from "@biryani/core"
import { db } from "../database"
export async function post(req, res) {
const { user } = req
......@@ -33,11 +34,11 @@ export async function post(req, res) {
const [body, error] = validateBody(req.body)
if (error !== null) {
console.error(
`Error in form:\n${JSON.stringify(
body,
`Error in form:\n${JSON.stringify(body, null, 2)}\n\nError:\n${JSON.stringify(
error,
null,
2,
)}\n\nError:\n${JSON.stringify(error, null, 2)}`,
)}`,
)
res.writeHead(400, {
"Content-Type": "application/json; charset=utf-8",
......@@ -149,10 +150,7 @@ function validateBody(data) {
return [data, "Value is empty."]
}
if (typeof data !== "object") {
return [
data,
`Expected an object, got "${typeof data}".`,
]
return [data, `Expected an object, got "${typeof data}".`]
}
data = {
......@@ -163,10 +161,10 @@ function validateBody(data) {
for (let key of ["cityId", "corporationId", "districtId", "page", "year"]) {
remainingKeys.delete(key)
const [value, error] = validateChain([
const [value, error] = validateChain(
validateInteger,
validateTest(value => value >= 0, "Number must be greater than or equal to zero."),
])(data[key])
)(data[key])
data[key] = value
if (error !== null) {
errors[key] = error
......
import assert from "assert"
import commandLineArgs from "command-line-args"
import csvParse from "csv-parse"
import fs from "fs"
import { db } from "../database"
import { slugify } from "../strings"
import { assertValid } from "../validators/assert"
import {
assertValid,
validateChain,
validateFunction,
validateNonEmptyTrimmedString,
......@@ -14,7 +7,14 @@ import {
validateTest,
validateTrimmedString,
validateTuple,
} from "../validators/core"
} from "@biryani/core"
import assert from "assert"
import commandLineArgs from "command-line-args"
import csvParse from "csv-parse"
import fs from "fs"
import { db } from "../database"
import { slugify } from "../strings"
const optionDefinitions = [
{
......@@ -59,8 +59,8 @@ async function main() {
temporary,
fair,
] = assertValid(
validateChain([
validateTuple([
validateChain(
validateTuple(
validateFrenchDateToIsoDate, // startdate
validateFrenchDateToIsoDate, // enddate
validateNonEmptyTrimmedString, // Département
......@@ -73,13 +73,12 @@ async function main() {
validateStringToBoolean, // Jours de foire
validateNonEmptyTrimmedString, // computed
validateStringToNumber, // Localité ID 2
]),
),
validateTest(
record => record[5] === record[11],
record =>
`City IDs are not equal: ${record[5]}${record[11]} in ${record}`,
record => `City IDs are not equal: ${record[5]}${record[11]} in ${record}`,
),
])(record),
)(record),
).slice(0, 10)
const entry = {
bankId,
......@@ -193,13 +192,13 @@ function validateFrenchDate(input) {
}
function validateFrenchDateToIsoDate(input) {
return validateChain([
return validateChain(
validateFrenchDate,
validateFunction(frenchDate => {
const dateSplitted = frenchDate.split("/")
return `${dateSplitted[2]}-${dateSplitted[1]}-${dateSplitted[0]}`
}),
])(input)
)(input)
}
function validateStringToBoolean(input) {
......
import assert from "assert"
import commandLineArgs from "command-line-args"
import csvParse from "csv-parse"
import fs from "fs"
import { db } from "../database"
import { slugify } from "../strings"
import { assertValid } from "../validators/assert"
import {
assertValid,
validateChain,
validateEmpty,
validateNonEmptyTrimmedString,
validateStringToNumber,
validateTest,
validateTuple,
} from "../validators/core"
} from "@biryani/core"
import assert from "assert"
import commandLineArgs from "command-line-args"
import csvParse from "csv-parse"
import fs from "fs"
import { db } from "../database"
import { slugify } from "../strings"
const optionDefinitions = [
{
......@@ -47,8 +47,8 @@ async function main() {
for (let record of records) {
assert.strictEqual(record.length, 11, `Unexpected record: ${record}`)
let [favreDistrictName, favreCityName, districtId, cityId] = assertValid(
validateChain([
validateTuple([
validateChain(
validateTuple(
validateNonEmptyTrimmedString, // DISTRICT_FAVRE
validateNonEmptyTrimmedString, // CITY_FAVRE
validateStringToNumber, // DISTRICT_ID_DFIH
......@@ -60,13 +60,12 @@ async function main() {
validateEmpty,
validateNonEmptyTrimmedString, // computed
validateStringToNumber, // CITY_ID_DFIH
]),
),
validateTest(
record => record[3] === record[10],
record =>
`City IDs are not equal: ${record[3]}${record[10]} in ${record}`,
record => `City IDs are not equal: ${record[3]}${record[10]} in ${record}`,
),
])(record),
)(record),
).slice(0, 4)
if (
......@@ -162,7 +161,9 @@ async function main() {
},
)).exists
) {
console.log(`Adding link between district ${favreDistrictName} and city ${favreCityName}…`)
console.log(
`Adding link between district ${favreDistrictName} and city ${favreCityName}…`,
)
await db.none(
`
INSERT INTO city_district
......
import assert from "assert"
export function assertValid([value, error]) {
assert(
error === null,
`Error ${JSON.stringify(error, null, 2)} for ${JSON.stringify(
value,
null,
2,
)}`,
)
return value
}
import {
validateNonEmptyTrimmedString,
} from "./core"
import { validateNonEmptyTrimmedString } from "@biryani/core"
export function validateConfig(config) {
if (config === null || config === undefined) {
......
// Cf https://stackoverflow.com/questions/1303872/trying-to-validate-url-using-javascript
// But added support for "localhost"
const urlRegExp = /^(?:(?:(?:https?|ftp):)?\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})).?)|localhost(?::\d{2,5})?(?:[/?#]\S*)?$/i
export function validateArray(itemValidator) {
return function(array) {
if (array === null || array === undefined) {
return [array, "Missing value"]
}
if (!Array.isArray(array)) {
return [array, `Expected an array, got "${typeof array}"`]
}
if (itemValidator === null || itemValidator === undefined) {
return [array, null]
}
const errors = {}
array = [...array]
for (let [index, value] of array.entries()) {
const [validatedValue, error] = itemValidator(value)
array[index] = validatedValue
if (error !== null) {
errors[index] = error
}
}
return [array, Object.keys(errors).length === 0 ? null : errors]
}