Fixes DB conflict in prod

This commit is contained in:
pikiou 2021-11-18 17:05:27 +01:00
parent 3d63859412
commit 581393f78e
12 changed files with 856 additions and 817 deletions

View File

@ -72,6 +72,7 @@
"@loadable/component": "^5.15.0",
"@loadable/server": "^5.15.0",
"@reduxjs/toolkit": "^1.6.0",
"@types/lodash": "^4.14.177",
"autoprefixer": "^10.2.6",
"axios": "^0.21.1",
"chalk": "^4.1.1",
@ -92,6 +93,7 @@
"lodash": "^4.17.21",
"morgan": "^1.10.0",
"normalize.css": "^8.0.1",
"os": "^0.1.2",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-helmet": "^6.1.0",
@ -127,7 +129,6 @@
"@types/loadable__component": "^5.13.4",
"@types/loadable__server": "^5.12.6",
"@types/loadable__webpack-plugin": "^5.7.3",
"@types/lodash": "^4.14.175",
"@types/mini-css-extract-plugin": "^2.0.1",
"@types/morgan": "^1.9.3",
"@types/react-dom": "^17.0.8",

View File

@ -1,7 +1,7 @@
export default {
HOST: "localhost",
PORT: 3000,
API_URL: "",
API_URL: "http://localhost:3000",
GOOGLE_SHEET_ID: "1pMMKcYx6NXLOqNn6pLHJTPMTOLRYZmSNg2QQcAu7-Pw",
APP: {
htmlAttributes: { lang: "en" },

View File

@ -1,3 +1,9 @@
import os from "os"
const hostname = os.hostname()
export default {
PORT: 4000,
HOST: hostname === "ns3075300" ? "fo.parisestludique.fr" : "localhost",
API_URL: hostname === "ns3075300" ? "http://fo.parisestludique.fr" : "http://localhost:4000",
}

View File

@ -1,8 +1,13 @@
const CACHE_RENEW_DELAY = 10000
export default function DBManager<OperationReturn>(): any {
const cache: { [sheetName: string]: any } = {}
const cacheTime: { [sheetName: string]: number } = {}
export default function DBManager<OperationReturn>(sheetName: string): any {
type OperationType = "add" | "list" | "set"
cacheTime[sheetName] = 0
interface Operation {
task: () => Promise<OperationReturn>
type: OperationType
@ -10,9 +15,6 @@ export default function DBManager<OperationReturn>(): any {
reject: (reason: unknown) => void
}
let cache: any
let cacheTime = 0
const operations: Operation[] = []
async function addDBOperation(type: OperationType, task: () => Promise<OperationReturn>) {
@ -37,21 +39,21 @@ export default function DBManager<OperationReturn>(): any {
const { task, type, resolve, reject } = operation
if (type === "list") {
const now = +new Date()
if (now < cacheTime + CACHE_RENEW_DELAY) {
resolve(cache)
if (now < cacheTime[sheetName] + CACHE_RENEW_DELAY) {
resolve(cache[sheetName])
runNextDBOperation()
} else {
task()
.then((val: OperationReturn) => {
cache = val
cacheTime = now
cache[sheetName] = val
cacheTime[sheetName] = now
resolve(val)
})
.catch(reject)
.finally(runNextDBOperation)
}
} else {
cacheTime = 0
cacheTime[sheetName] = 0
task().then(resolve).catch(reject).finally(runNextDBOperation)
}
}

View File

@ -5,390 +5,391 @@ import { GoogleSpreadsheet, GoogleSpreadsheetWorksheet } from "google-spreadshee
import DBManager from "./DBManager"
const addDBOperation = DBManager()
const SCOPES = ["https://www.googleapis.com/auth/spreadsheets"]
const CRED_PATH = path.resolve(process.cwd(), "access/gsheets.json")
export type ElementWithId = unknown & { id: number }
export async function listGet<Element extends ElementWithId>(
sheetName: string,
specimen: Element
): Promise<Element[]> {
type StringifiedElement = Record<keyof Element, string>
return addDBOperation("list", async () => {
const sheet = await getGSheet(sheetName)
export default function getAccessors<
// eslint-disable-next-line @typescript-eslint/ban-types
ElementNoId extends object,
Element extends ElementNoId & ElementWithId
>(sheetName: string, specimen: Element): any {
const addDBOperation = DBManager(sheetName)
// Load sheet into an array of objects
const rows = (await sheet.getRows()) as StringifiedElement[]
const elements: Element[] = []
if (!rows[0]) {
throw new Error(`No column types defined in sheet ${sheetName}`)
}
const types = _.pick(rows[0], Object.keys(specimen)) as Record<keyof Element, string>
rows.shift()
rows.forEach((row) => {
const stringifiedElement = _.pick(row, Object.keys(specimen)) as Record<
async function listGet(): Promise<Element[]> {
type StringifiedElement = Record<keyof Element, string>
return addDBOperation("list", async () => {
const sheet = await getGSheet()
// Load sheet into an array of objects
const rows = (await sheet.getRows()) as StringifiedElement[]
const elements: Element[] = []
if (!rows[0]) {
throw new Error(`No column types defined in sheet ${sheetName}`)
}
const types = _.pick(rows[0], Object.keys(specimen)) as Record<keyof Element, string>
rows.shift()
rows.forEach((row) => {
const stringifiedElement = _.pick(row, Object.keys(specimen)) as Record<
keyof Element,
string
>
const element = parseElement(stringifiedElement, types)
if (element !== undefined) {
elements.push(element)
}
})
return elements
})
}
async function get(membreId: number): Promise<Element | undefined> {
// No need to addDBOperation here, since listGet does it already
const list = await listGet()
return list.find((element) => element.id === membreId)
}
async function setList(elements: Element[]): Promise<true | undefined> {
return addDBOperation("listSet", async () => {
const sheet = await getGSheet()
// Load sheet into an array of objects
const rows = await sheet.getRows()
if (!rows[0]) {
throw new Error(`No column types defined in sheet ${sheetName}`)
}
const types = _.pick(rows[0], Object.keys(elements[0] || {})) as Record<
keyof Element,
string
>
const element = parseElement<Element>(stringifiedElement, types, specimen)
if (element !== undefined) {
elements.push(element)
}
})
return elements
})
}
// Update received rows
let rowid = 1
// eslint-disable-next-line no-restricted-syntax
for (const element of elements) {
const row = rows[rowid]
const stringifiedRow = stringifyElement(element, types)
export async function get<Element extends ElementWithId>(
sheetName: string,
membreId: number,
specimen: Element
): Promise<Element | undefined> {
// No need to addDBOperation here, since listGet does it already
const list = await listGet<Element>(sheetName, specimen)
return list.find((element) => element.id === membreId)
}
export async function setList<Element extends ElementWithId>(
sheetName: string,
elements: Element[]
): Promise<true | undefined> {
return addDBOperation("listSet", async () => {
const sheet = await getGSheet(sheetName)
// Load sheet into an array of objects
const rows = await sheet.getRows()
if (!rows[0]) {
throw new Error(`No column types defined in sheet ${sheetName}`)
}
const types = _.pick(rows[0], Object.keys(elements[0] || {})) as Record<
keyof Element,
string
>
// Update received rows
let rowid = 1
// eslint-disable-next-line no-restricted-syntax
for (const element of elements) {
const row = rows[rowid]
const stringifiedRow = stringifyElement(element, types)
if (!row) {
// eslint-disable-next-line no-await-in-loop
await sheet.addRow(stringifiedRow)
} else {
const keys = Object.keys(stringifiedRow)
const sameCells = _.every(
keys,
(key: keyof Element) => row[key as string] === stringifiedRow[key]
)
if (!sameCells) {
keys.forEach((key) => {
row[key] = stringifiedRow[key as keyof Element]
})
if (!row) {
// eslint-disable-next-line no-await-in-loop
await row.save()
await sheet.addRow(stringifiedRow)
} else {
const keys = Object.keys(stringifiedRow)
const sameCells = _.every(
keys,
(key: keyof Element) => row[key as string] === stringifiedRow[key]
)
if (!sameCells) {
keys.forEach((key) => {
row[key] = stringifiedRow[key as keyof Element]
})
// eslint-disable-next-line no-await-in-loop
await row.save()
}
}
rowid += 1
}
// Delete all following rows
for (let rowToDelete = sheet.rowCount - 1; rowToDelete >= rowid; rowToDelete -= 1) {
if (rows[rowToDelete]) {
// eslint-disable-next-line no-await-in-loop
await rows[rowToDelete].delete()
}
}
rowid += 1
}
// Delete all following rows
for (let rowToDelete = sheet.rowCount - 1; rowToDelete >= rowid; rowToDelete -= 1) {
if (rows[rowToDelete]) {
// eslint-disable-next-line no-await-in-loop
await rows[rowToDelete].delete()
}
}
return true
})
}
export async function set<Element extends ElementWithId>(
sheetName: string,
element: Element
): Promise<Element | undefined> {
if (!element) {
return undefined
return true
})
}
return addDBOperation("set", async () => {
const sheet = await getGSheet(sheetName)
// Load sheet into an array of objects
const rows = await sheet.getRows()
if (!rows[0]) {
throw new Error(`No column types defined in sheet ${sheetName}`)
}
const types = _.pick(rows[0], Object.keys(element || {})) as Record<keyof Element, string>
rows.shift()
// Replace previous row
const stringifiedRow = stringifyElement(element, types)
const row = rows.find((rowItem) => +rowItem.id === element.id)
if (!row) {
async function set(element: Element): Promise<Element | undefined> {
if (!element) {
return undefined
}
Object.assign(row, stringifiedRow)
await row.save()
return element
})
}
return addDBOperation("set", async () => {
const sheet = await getGSheet()
// eslint-disable-next-line @typescript-eslint/ban-types
export async function add<ElementNoId extends object, Element extends ElementNoId & ElementWithId>(
sheetName: string,
partialElement: Partial<ElementNoId>
): Promise<Element | undefined> {
if (!partialElement) {
return undefined
}
return addDBOperation("add", async () => {
const sheet = await getGSheet(sheetName)
// Load sheet into an array of objects
const rows = await sheet.getRows()
if (!rows[0]) {
throw new Error(`No column types defined in sheet ${sheetName}`)
}
const types = {
id: "number",
...(_.pick(rows[0], Object.keys(partialElement || {})) as Record<
keyof ElementNoId,
// Load sheet into an array of objects
const rows = await sheet.getRows()
if (!rows[0]) {
throw new Error(`No column types defined in sheet ${sheetName}`)
}
const types = _.pick(rows[0], Object.keys(element || {})) as Record<
keyof Element,
string
>),
>
rows.shift()
// Replace previous row
const stringifiedRow = stringifyElement(element, types)
const row = rows.find((rowItem) => +rowItem.id === element.id)
if (!row) {
return undefined
}
Object.assign(row, stringifiedRow)
await row.save()
return element
})
}
async function add(partialElement: Partial<ElementNoId>): Promise<Element | undefined> {
if (!partialElement) {
return undefined
}
return addDBOperation("add", async () => {
const sheet = await getGSheet()
// Create full element
rows.shift()
const highestId = rows.reduce((id: number, row) => Math.max(id, +row.id || 0), 0)
const element = { id: highestId + 1, ...partialElement } as Element
// Load sheet into an array of objects
const rows = await sheet.getRows()
if (!rows[0]) {
throw new Error(`No column types defined in sheet ${sheetName}`)
}
const types = {
id: "number",
...(_.pick(rows[0], Object.keys(partialElement || {})) as Record<
keyof ElementNoId,
string
>),
}
// Add element
const stringifiedRow = stringifyElement(element, types)
await sheet.addRow(stringifiedRow)
// Create full element
rows.shift()
const highestId = rows.reduce((id: number, row) => Math.max(id, +row.id || 0), 0)
const element = { id: highestId + 1, ...partialElement } as Element
return element
})
}
// Add element
const stringifiedRow = stringifyElement(element, types)
await sheet.addRow(stringifiedRow)
async function getGSheet(sheetName: string): Promise<GoogleSpreadsheetWorksheet> {
const doc = new GoogleSpreadsheet("1pMMKcYx6NXLOqNn6pLHJTPMTOLRYZmSNg2QQcAu7-Pw")
const creds = await fs.readFile(CRED_PATH)
// Authentication
await doc.useServiceAccountAuth(JSON.parse(creds.toString()))
await doc.loadInfo()
return doc.sheetsByTitle[sheetName]
}
return element
})
}
// eslint-disable-next-line @typescript-eslint/ban-types
function parseElement<Element extends object>(
rawElement: Record<keyof Element, string>,
types: Record<keyof Element, string>,
specimen: Element
): Element {
const fullElement = _.reduce(
types,
(element: any, type: string, prop: string) => {
const rawProp: string = rawElement[prop as keyof Element]
switch (type) {
case "string":
element[prop] = rawProp
break
async function getGSheet(): Promise<GoogleSpreadsheetWorksheet> {
const doc = new GoogleSpreadsheet("1pMMKcYx6NXLOqNn6pLHJTPMTOLRYZmSNg2QQcAu7-Pw")
const creds = await fs.readFile(CRED_PATH)
// Authentication
await doc.useServiceAccountAuth(JSON.parse(creds.toString()))
await doc.loadInfo()
return doc.sheetsByTitle[sheetName]
}
case "number":
element[prop] = +rawProp
break
case "boolean":
element[prop] = rawProp !== "0" && rawProp !== ""
break
case "date":
// eslint-disable-next-line no-case-declarations
const matchDate = rawProp.match(/^([0-9]+)\/([0-9]+)\/([0-9]+)$/)
if (matchDate) {
element[prop] = new Date(+matchDate[3], +matchDate[2] - 1, +matchDate[1])
function parseElement(
rawElement: Record<keyof Element, string>,
types: Record<keyof Element, string>
): Element {
const fullElement = _.reduce(
types,
(element: any, type: string, prop: string) => {
const rawProp: string = rawElement[prop as keyof Element]
switch (type) {
case "string":
element[prop] = rawProp
break
}
throw new Error(`Unable to read date from ${rawProp}`)
default:
// eslint-disable-next-line no-case-declarations
const matchArrayType = type.match(/^(number|string|boolean|date)\[([^\]]+)\]$/)
if (!matchArrayType) {
throw new Error(`Unknown array type for ${type}`)
}
if (!rawProp) {
element[prop] = []
} else {
case "number":
element[prop] = +rawProp
break
case "boolean":
element[prop] = rawProp !== "0" && rawProp !== ""
break
case "date":
// eslint-disable-next-line no-case-declarations
const matchDate = rawProp.match(/^([0-9]+)\/([0-9]+)\/([0-9]+)$/)
if (matchDate) {
element[prop] = new Date(
+matchDate[3],
+matchDate[2] - 1,
+matchDate[1]
)
break
}
throw new Error(`Unable to read date from ${rawProp}`)
default:
// eslint-disable-next-line no-case-declarations
const matchArrayType = type.match(
/^(number|string|boolean|date)\[([^\]]+)\]$/
)
if (!matchArrayType) {
throw new Error(`Unknown array type for ${type}`)
}
if (!rawProp) {
element[prop] = []
} else {
const arrayType = matchArrayType[1]
const delimiter = matchArrayType[2]
switch (arrayType) {
case "string":
element[prop] = rawProp.split(delimiter)
break
case "number":
element[prop] = _.map(rawProp.split(delimiter), (val) => +val)
break
case "boolean":
element[prop] = _.map(
rawProp.split(delimiter),
(val) => val !== "0" && val !== ""
)
break
case "date":
// eslint-disable-next-line no-case-declarations
const rawDates = rawProp.split(delimiter)
element[prop] = []
// eslint-disable-next-line no-case-declarations
const rightFormat = rawDates.every((rawDate) => {
const matchDateArray = rawDate.match(
/^([0-9]+)\/([0-9]+)\/([0-9]+)$/
)
if (!matchDateArray) {
return false
}
element[prop].push(
new Date(
+matchDateArray[3],
+matchDateArray[2] - 1,
+matchDateArray[1]
)
)
return true
})
if (!rightFormat) {
throw new Error(
`One array item is not a date in ${rawProp}`
)
}
break
default:
throw new Error(`Unknown array type ${arrayType}`)
}
}
}
return element
},
JSON.parse(JSON.stringify(specimen))
)
return fullElement
}
function stringifyElement(
element: Element,
types: { id: string } & Record<keyof ElementNoId, string>
): Record<keyof Element, string> {
const rawElement: Record<keyof Element, string> = _.reduce(
types,
(stringifiedElement: Record<keyof Element, string>, type: string, prop: string) => {
const value = element[prop as keyof Element]
switch (type) {
case "string":
stringifiedElement[prop as keyof Element] = formulaSafe(`${value}`)
break
case "number":
stringifiedElement[prop as keyof Element] = `${value}`
break
case "boolean":
stringifiedElement[prop as keyof Element] = value ? "X" : ""
break
case "date":
stringifiedElement[prop as keyof Element] = stringifiedDate(value)
break
default:
// eslint-disable-next-line no-case-declarations
const matchArrayType = type.match(
/^(number|string|boolean|date)\[([^\]]+)\]$/
)
if (!matchArrayType || !_.isArray(value)) {
throw new Error(
"Unknown matchArrayType or not an array in stringifyElement"
)
}
// eslint-disable-next-line no-case-declarations
const arrayType = matchArrayType[1]
// eslint-disable-next-line no-case-declarations
const delimiter = matchArrayType[2]
switch (arrayType) {
case "string":
element[prop] = rawProp.split(delimiter)
break
case "number":
element[prop] = _.map(rawProp.split(delimiter), (val) => +val)
break
case "boolean":
element[prop] = _.map(
rawProp.split(delimiter),
(val) => val !== "0" && val !== ""
if (!_.every(value, _.isString)) {
throw new Error(`Each date of ${value} is not a string`)
}
stringifiedElement[prop as keyof Element] = formulaSafe(
value.join(delimiter)
)
break
case "date":
// eslint-disable-next-line no-case-declarations
const rawDates = rawProp.split(delimiter)
element[prop] = []
// eslint-disable-next-line no-case-declarations
const rightFormat = rawDates.every((rawDate) => {
const matchDateArray = rawDate.match(
/^([0-9]+)\/([0-9]+)\/([0-9]+)$/
)
if (!matchDateArray) {
return false
}
element[prop].push(
new Date(
+matchDateArray[3],
+matchDateArray[2] - 1,
+matchDateArray[1]
)
)
return true
})
if (!rightFormat) {
throw new Error(`One array item is not a date in ${rawProp}`)
case "number":
if (!_.every(value, _.isNumber)) {
throw new Error(`Each date of ${value} is not a number`)
}
stringifiedElement[prop as keyof Element] = value.join(delimiter)
break
case "boolean":
if (!_.every(value, _.isBoolean)) {
throw new Error(`Each date of ${value} is not a boolean`)
}
stringifiedElement[prop as keyof Element] = _.map(value, (val) =>
val ? "X" : ""
).join(delimiter)
break
case "date":
if (!_.every(value, _.isDate)) {
throw new Error(`Each date of ${value} is not a date`)
}
stringifiedElement[prop as keyof Element] = _.map(
value,
(val) =>
`${val.getDate()}/${
val.getMonth() + 1
}/${val.getFullYear()}`
).join(delimiter)
break
default:
throw new Error(`Unknown array type ${arrayType}`)
}
}
}
return element
},
JSON.parse(JSON.stringify(specimen))
)
return fullElement
}
}
// eslint-disable-next-line @typescript-eslint/ban-types
function stringifyElement<ElementNoId extends object, Element extends ElementNoId & ElementWithId>(
element: Element,
types: { id: string } & Record<keyof ElementNoId, string>
): Record<keyof Element, string> {
const rawElement: Record<keyof Element, string> = _.reduce(
types,
(stringifiedElement: Record<keyof Element, string>, type: string, prop: string) => {
const value = element[prop as keyof Element]
switch (type) {
case "string":
stringifiedElement[prop as keyof Element] = formulaSafe(`${value}`)
break
return stringifiedElement
},
JSON.parse(JSON.stringify(element))
)
case "number":
stringifiedElement[prop as keyof Element] = `${value}`
break
case "boolean":
stringifiedElement[prop as keyof Element] = value ? "X" : ""
break
case "date":
stringifiedElement[prop as keyof Element] = stringifiedDate(value)
break
default:
// eslint-disable-next-line no-case-declarations
const matchArrayType = type.match(/^(number|string|boolean|date)\[([^\]]+)\]$/)
if (!matchArrayType || !_.isArray(value)) {
throw new Error(
"Unknown matchArrayType or not an array in stringifyElement"
)
}
// eslint-disable-next-line no-case-declarations
const arrayType = matchArrayType[1]
// eslint-disable-next-line no-case-declarations
const delimiter = matchArrayType[2]
switch (arrayType) {
case "string":
if (!_.every(value, _.isString)) {
throw new Error(`Each date of ${value} is not a string`)
}
stringifiedElement[prop as keyof Element] = formulaSafe(
value.join(delimiter)
)
break
case "number":
if (!_.every(value, _.isNumber)) {
throw new Error(`Each date of ${value} is not a number`)
}
stringifiedElement[prop as keyof Element] = value.join(delimiter)
break
case "boolean":
if (!_.every(value, _.isBoolean)) {
throw new Error(`Each date of ${value} is not a boolean`)
}
stringifiedElement[prop as keyof Element] = _.map(value, (val) =>
val ? "X" : ""
).join(delimiter)
break
case "date":
if (!_.every(value, _.isDate)) {
throw new Error(`Each date of ${value} is not a date`)
}
stringifiedElement[prop as keyof Element] = _.map(
value,
(val) =>
`${val.getDate()}/${val.getMonth() + 1}/${val.getFullYear()}`
).join(delimiter)
break
default:
throw new Error(`Unknown array type ${arrayType}`)
}
}
return stringifiedElement
},
JSON.parse(JSON.stringify(element))
)
return rawElement
}
function formulaSafe(value: string): string {
return value.replace(/^=+/, "")
}
function stringifiedDate(value: unknown): string {
let date: Date
if (value instanceof Date) {
date = value
} else if (typeof value === "string") {
try {
date = new Date(value)
} catch (e) {
throw new Error("Wrong date string format in stringifyElement")
}
} else {
throw new Error("Wrong date format in stringifyElement")
return rawElement
}
return `${date.getDate()}/${date.getMonth() + 1}/${date.getFullYear()}`
function formulaSafe(value: string): string {
return value.replace(/^=+/, "")
}
function stringifiedDate(value: unknown): string {
let date: Date
if (value instanceof Date) {
date = value
} else if (typeof value === "string") {
try {
date = new Date(value)
} catch (e) {
throw new Error("Wrong date string format in stringifyElement")
}
} else {
throw new Error("Wrong date format in stringifyElement")
}
return `${date.getDate()}/${date.getMonth() + 1}/${date.getFullYear()}`
}
return { listGet, get, setList, set, add }
}
export { SCOPES }

View File

@ -1,12 +1,15 @@
import { listGetRequest, getRequest, setRequest, addRequest } from "./expressAccessors"
import getExpressAccessors from "./expressAccessors"
import { Envie, EnvieWithoutId } from "../services/envies"
const sheetName = "Envies d'aider"
const { listGetRequest, getRequest, setRequest, addRequest } = getExpressAccessors<
EnvieWithoutId,
Envie
>("Envies d'aider", new Envie())
export const envieListGet = listGetRequest(sheetName, new Envie())
export const envieListGet = listGetRequest()
export const envieGet = getRequest(sheetName, new Envie())
export const envieGet = getRequest()
export const envieAdd = addRequest<EnvieWithoutId, Envie>(sheetName)
export const envieAdd = addRequest()
export const envieSet = setRequest(sheetName)
export const envieSet = setRequest()

View File

@ -1,61 +1,69 @@
import { Request, Response, NextFunction } from "express"
import { ElementWithId, get, listGet, add, set } from "./accessors"
import getAccessors, { ElementWithId } from "./accessors"
export function getRequest<Element extends { id: number }>(sheetName: string, specimen: Element) {
return async (request: Request, response: Response, _next: NextFunction): Promise<void> => {
try {
const id = parseInt(request.query.id as string, 10) || -1
const elements = await get<Element>(sheetName, id, specimen)
if (elements) {
response.status(200).json(elements)
export default function getExpressAccessors<
// eslint-disable-next-line @typescript-eslint/ban-types
ElementNoId extends object,
Element extends ElementNoId & ElementWithId
>(sheetName: string, specimen: Element): any {
const { get, listGet, add, set } = getAccessors(sheetName, specimen)
function listGetRequest() {
return async (
_request: Request,
response: Response,
_next: NextFunction
): Promise<void> => {
try {
const elements = await listGet()
if (elements) {
response.status(200).json(elements)
}
} catch (e: unknown) {
response.status(400).json(e)
}
} catch (e: unknown) {
response.status(400).json(e)
}
}
}
// eslint-disable-next-line @typescript-eslint/ban-types
export function addRequest<ElementNoId extends object, Element extends ElementNoId & ElementWithId>(
sheetName: string
) {
return async (request: Request, response: Response, _next: NextFunction): Promise<void> => {
try {
const element = await add<ElementNoId, Element>(sheetName, request.body)
if (element) {
response.status(200).json(element)
function getRequest() {
return async (request: Request, response: Response, _next: NextFunction): Promise<void> => {
try {
const id = parseInt(request.query.id as string, 10) || -1
const elements = await get(id)
if (elements) {
response.status(200).json(elements)
}
} catch (e: unknown) {
response.status(400).json(e)
}
} catch (e: unknown) {
response.status(400).json(e)
}
}
}
export function listGetRequest<Element extends { id: number }>(
sheetName: string,
specimen: Element
) {
return async (_request: Request, response: Response, _next: NextFunction): Promise<void> => {
try {
const elements = await listGet<Element>(sheetName, specimen)
if (elements) {
response.status(200).json(elements)
function addRequest() {
return async (request: Request, response: Response, _next: NextFunction): Promise<void> => {
try {
const element = await add(request.body)
if (element) {
response.status(200).json(element)
}
} catch (e: unknown) {
response.status(400).json(e)
}
} catch (e: unknown) {
response.status(400).json(e)
}
}
}
export function setRequest<Element extends { id: number }>(sheetName: string) {
return async (request: Request, response: Response, _next: NextFunction): Promise<void> => {
try {
const element = await set<Element>(sheetName, request.body)
if (element) {
response.status(200).json(element)
function setRequest() {
return async (request: Request, response: Response, _next: NextFunction): Promise<void> => {
try {
const element = await set(request.body)
if (element) {
response.status(200).json(element)
}
} catch (e: unknown) {
response.status(400).json(e)
}
} catch (e: unknown) {
response.status(400).json(e)
}
}
return { getRequest, addRequest, listGetRequest, setRequest }
}

View File

@ -1,12 +1,15 @@
import { listGetRequest, getRequest, setRequest, addRequest } from "./expressAccessors"
import getExpressAccessors from "./expressAccessors"
import { JeuJav, JeuJavWithoutId } from "../services/jeuxJav"
const sheetName = "Jeux JAV"
const { listGetRequest, getRequest, setRequest, addRequest } = getExpressAccessors<
JeuJavWithoutId,
JeuJav
>("Jeux JAV", new JeuJav())
export const jeuJavListGet = listGetRequest(sheetName, new JeuJav())
export const jeuJavListGet = listGetRequest()
export const jeuJavGet = getRequest(sheetName, new JeuJav())
export const jeuJavGet = getRequest()
export const jeuJavAdd = addRequest<JeuJavWithoutId, JeuJav>(sheetName)
export const jeuJavAdd = addRequest()
export const jeuJavSet = setRequest(sheetName)
export const jeuJavSet = setRequest()

View File

@ -1,12 +1,15 @@
import { listGetRequest, getRequest, setRequest, addRequest } from "./expressAccessors"
import getExpressAccessors from "./expressAccessors"
import { Membre, MembreWithoutId } from "../services/membres"
const sheetName = "Membres"
const { listGetRequest, getRequest, setRequest, addRequest } = getExpressAccessors<
MembreWithoutId,
Membre
>("Membres", new Membre())
export const membreListGet = listGetRequest(sheetName, new Membre())
export const membreListGet = listGetRequest()
export const membreGet = getRequest(sheetName, new Membre())
export const membreGet = getRequest()
export const membreAdd = addRequest<MembreWithoutId, Membre>(sheetName)
export const membreAdd = addRequest()
export const membreSet = setRequest(sheetName)
export const membreSet = setRequest()

View File

@ -8,7 +8,6 @@ import LoadablePlugin from "@loadable/webpack-plugin"
import { BundleAnalyzerPlugin } from "webpack-bundle-analyzer"
export const isDev = process.env.NODE_ENV === "development"
const getStyleLoaders = (isWeb: boolean, isSass?: boolean) => {
let loaders: RuleSetUseItem[] = [
{

View File

@ -53,6 +53,10 @@ const config: Configuration = {
},
optimization: { minimizer: [new CssMinimizerPlugin()] },
plugins: getPlugins(),
performance: {
maxAssetSize: 512000,
maxEntrypointSize: 512000,
},
}
export default merge(baseConfig(true), config)

815
yarn.lock

File diff suppressed because it is too large Load Diff