mirror of
https://github.com/Paris-est-Ludique/intranet.git
synced 2025-06-09 17:14:21 +02:00
Add db loading from file to simplify dev
This commit is contained in:
parent
110f3505ab
commit
65d9439308
1
.gitignore
vendored
1
.gitignore
vendored
@ -15,6 +15,7 @@ public/*
|
|||||||
access/gsheets.json
|
access/gsheets.json
|
||||||
access/jwt_secret.json
|
access/jwt_secret.json
|
||||||
access/db.json
|
access/db.json
|
||||||
|
access/dbToLoad.json
|
||||||
|
|
||||||
# Misc
|
# Misc
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
@ -8,13 +8,16 @@ import { GoogleSpreadsheet, GoogleSpreadsheetWorksheet } from "google-spreadshee
|
|||||||
|
|
||||||
const CRED_PATH = path.resolve(process.cwd(), "access/gsheets.json")
|
const CRED_PATH = path.resolve(process.cwd(), "access/gsheets.json")
|
||||||
const DB_PATH = path.resolve(process.cwd(), "access/db.json")
|
const DB_PATH = path.resolve(process.cwd(), "access/db.json")
|
||||||
|
const DB_TO_LOAD_PATH = path.resolve(process.cwd(), "access/dbToLoad.json")
|
||||||
|
|
||||||
const REMOTE_UPDATE_DELAY = 40000
|
const REMOTE_UPDATE_DELAY = 40000
|
||||||
const DELAY_AFTER_QUERY = 2000
|
const DELAY_AFTER_QUERY = 2000
|
||||||
|
|
||||||
let creds: string | undefined | null
|
let creds: string | undefined | null
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||||
let localDb: { [sheetName in keyof SheetNames]?: object[] | undefined } = {}
|
let states: { [sheetName in keyof SheetNames]?: object[] | undefined } = {}
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||||
|
let types: { [sheetName in keyof SheetNames]?: object | undefined } = {}
|
||||||
|
|
||||||
export type ElementWithId<ElementNoId> = { id: number } & ElementNoId
|
export type ElementWithId<ElementNoId> = { id: number } & ElementNoId
|
||||||
|
|
||||||
@ -87,6 +90,8 @@ export class Sheet<
|
|||||||
|
|
||||||
_state: Element[] | undefined
|
_state: Element[] | undefined
|
||||||
|
|
||||||
|
_type: Record<keyof Element, string> | undefined
|
||||||
|
|
||||||
toRunAfterLoad: (() => void)[] | undefined = []
|
toRunAfterLoad: (() => void)[] | undefined = []
|
||||||
|
|
||||||
saveTimestamp = 0
|
saveTimestamp = 0
|
||||||
@ -155,7 +160,7 @@ export class Sheet<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
runAfterLoad(func: () => void): void {
|
addToRunAfterLoad(func: () => void): void {
|
||||||
if (this.toRunAfterLoad) {
|
if (this.toRunAfterLoad) {
|
||||||
this.toRunAfterLoad.push(func)
|
this.toRunAfterLoad.push(func)
|
||||||
} else {
|
} else {
|
||||||
@ -165,27 +170,55 @@ export class Sheet<
|
|||||||
|
|
||||||
private async waitForLoad(): Promise<void> {
|
private async waitForLoad(): Promise<void> {
|
||||||
return new Promise((resolve, _reject) => {
|
return new Promise((resolve, _reject) => {
|
||||||
this.runAfterLoad(() => resolve(undefined))
|
this.addToRunAfterLoad(() => resolve(undefined))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
dbUpdate(): void {
|
async dbUpdate(): Promise<void> {
|
||||||
|
if (await hasGSheetsAccess()) {
|
||||||
if (this.modifiedSinceSave) {
|
if (this.modifiedSinceSave) {
|
||||||
this.dbSave()
|
this.dbSave()
|
||||||
} else {
|
} else {
|
||||||
this.dbLoad()
|
this.dbLoad()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
this.localDbSave()
|
this.localDbSave()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async localDbSave(): Promise<void> {
|
async localDbSave(): Promise<void> {
|
||||||
localDb[this.name] = this._state
|
states[this.name] = this._state
|
||||||
const jsonDB = __DEV__ ? JSON.stringify(localDb, null, 2) : JSON.stringify(localDb)
|
types[this.name] = this._type
|
||||||
|
const toSave = { states, types }
|
||||||
|
const jsonDB = __DEV__ ? JSON.stringify(toSave, null, 2) : JSON.stringify(toSave)
|
||||||
await fs.writeFile(DB_PATH, jsonDB)
|
await fs.writeFile(DB_PATH, jsonDB)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async localDbLoad(): Promise<void> {
|
||||||
|
if (_.isEmpty(states)) {
|
||||||
|
let stringifiedDb
|
||||||
|
try {
|
||||||
|
stringifiedDb = await fs.readFile(DB_TO_LOAD_PATH)
|
||||||
|
} catch {
|
||||||
|
console.error(`No local database save found in ${DB_TO_LOAD_PATH}`)
|
||||||
|
process.exit()
|
||||||
|
}
|
||||||
|
if (stringifiedDb) {
|
||||||
|
const db = JSON.parse(stringifiedDb.toString())
|
||||||
|
states = db.states
|
||||||
|
types = db.types
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!states[this.name]) {
|
||||||
|
console.error(`Sheet ${this.name} couldn't be found in localDb`)
|
||||||
|
process.exit()
|
||||||
|
}
|
||||||
|
this._state = states[this.name] as Element[]
|
||||||
|
this._type = types[this.name] as Record<keyof Element, string>
|
||||||
|
}
|
||||||
|
|
||||||
dbSave(): void {
|
dbSave(): void {
|
||||||
this.saveTimestamp = +new Date()
|
this.saveTimestamp = +new Date()
|
||||||
|
|
||||||
@ -197,39 +230,31 @@ export class Sheet<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dbLoad(): void {
|
async dbLoad(): Promise<void> {
|
||||||
try {
|
try {
|
||||||
this.toRunAfterLoad = []
|
if (await hasGSheetsAccess()) {
|
||||||
this.dbLoadAsync().then(() => {
|
this.dbLoadAsync().then(() => this.doRunAfterLoad())
|
||||||
if (this.toRunAfterLoad) {
|
} else {
|
||||||
this.toRunAfterLoad.map((func) => func())
|
this.doRunAfterLoad()
|
||||||
this.toRunAfterLoad = undefined
|
|
||||||
}
|
}
|
||||||
})
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("Error in dbLoad: ", e)
|
console.error("Error in dbLoad: ", e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
doRunAfterLoad(): void {
|
||||||
|
if (this.toRunAfterLoad) {
|
||||||
|
this.toRunAfterLoad.map((func) => func())
|
||||||
|
this.toRunAfterLoad = undefined
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async dbFirstLoad(): Promise<void> {
|
async dbFirstLoad(): Promise<void> {
|
||||||
if (await hasGSheetsAccess()) {
|
if (!(await hasGSheetsAccess()) && _.isEmpty(states)) {
|
||||||
this.dbLoad()
|
this.localDbLoad()
|
||||||
} else if (_.isEmpty(localDb)) {
|
|
||||||
let stringifiedDb
|
|
||||||
try {
|
|
||||||
stringifiedDb = await fs.readFile(DB_PATH)
|
|
||||||
} catch {
|
|
||||||
console.error(`Error: Found no DB file at ${DB_PATH}`)
|
|
||||||
}
|
|
||||||
if (stringifiedDb) {
|
|
||||||
localDb = JSON.parse(stringifiedDb.toString())
|
|
||||||
if (localDb[this.name]) {
|
|
||||||
this._state = localDb[this.name] as Element[]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
this.dbLoad()
|
this.dbLoad()
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private async dbSaveAsync(): Promise<void> {
|
private async dbSaveAsync(): Promise<void> {
|
||||||
if (!this._state) {
|
if (!this._state) {
|
||||||
@ -249,7 +274,7 @@ export class Sheet<
|
|||||||
}
|
}
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||||
const elements = this._state as Element[]
|
const elements = this._state as Element[]
|
||||||
const types = _.pick(rows[0], Object.values(this.translation)) as Record<
|
this._type = _.pick(rows[0], Object.values(this.translation)) as Record<
|
||||||
keyof Element,
|
keyof Element,
|
||||||
string
|
string
|
||||||
>
|
>
|
||||||
@ -263,7 +288,7 @@ export class Sheet<
|
|||||||
this.invertedTranslation,
|
this.invertedTranslation,
|
||||||
(englishProp: string) => (element as any)[englishProp]
|
(englishProp: string) => (element as any)[englishProp]
|
||||||
) as Element
|
) as Element
|
||||||
const stringifiedRow = this.stringifyElement(frenchElement, types)
|
const stringifiedRow = this.stringifyElement(frenchElement, this._type)
|
||||||
|
|
||||||
if (!row) {
|
if (!row) {
|
||||||
// eslint-disable-next-line no-await-in-loop
|
// eslint-disable-next-line no-await-in-loop
|
||||||
@ -317,17 +342,18 @@ export class Sheet<
|
|||||||
if (!rows[0]) {
|
if (!rows[0]) {
|
||||||
throw new Error(`No column types defined in sheet ${this.name}`)
|
throw new Error(`No column types defined in sheet ${this.name}`)
|
||||||
}
|
}
|
||||||
const types = _.pick(rows[0], Object.values(this.translation)) as Record<
|
const typeList = _.pick(rows[0], Object.values(this.translation)) as Record<
|
||||||
keyof Element,
|
keyof Element,
|
||||||
string
|
string
|
||||||
>
|
>
|
||||||
|
this._type = typeList
|
||||||
rows.shift()
|
rows.shift()
|
||||||
rows.forEach((row) => {
|
rows.forEach((row) => {
|
||||||
const stringifiedElement = _.pick(row, Object.values(this.translation)) as Record<
|
const stringifiedElement = _.pick(row, Object.values(this.translation)) as Record<
|
||||||
keyof Element,
|
keyof Element,
|
||||||
string
|
string
|
||||||
>
|
>
|
||||||
const frenchData: any = this.parseElement(stringifiedElement, types)
|
const frenchData: any = this.parseElement(stringifiedElement, typeList)
|
||||||
if (frenchData !== undefined) {
|
if (frenchData !== undefined) {
|
||||||
const englishElement = _.mapValues(
|
const englishElement = _.mapValues(
|
||||||
this.translation,
|
this.translation,
|
||||||
@ -361,10 +387,10 @@ export class Sheet<
|
|||||||
|
|
||||||
private parseElement(
|
private parseElement(
|
||||||
rawElement: Record<keyof Element, string>,
|
rawElement: Record<keyof Element, string>,
|
||||||
types: Record<keyof Element, string>
|
typeList: Record<keyof Element, string>
|
||||||
): Element {
|
): Element {
|
||||||
const fullElement = _.reduce(
|
const fullElement = _.reduce(
|
||||||
types,
|
typeList,
|
||||||
(element: any, type: string, prop: string) => {
|
(element: any, type: string, prop: string) => {
|
||||||
const rawProp: string = rawElement[prop as keyof Element]
|
const rawProp: string = rawElement[prop as keyof Element]
|
||||||
switch (type) {
|
switch (type) {
|
||||||
@ -469,10 +495,10 @@ export class Sheet<
|
|||||||
|
|
||||||
private stringifyElement(
|
private stringifyElement(
|
||||||
element: Element,
|
element: Element,
|
||||||
types: Record<keyof Element, string>
|
typeList: Record<keyof Element, string>
|
||||||
): Record<keyof Element, string> {
|
): Record<keyof Element, string> {
|
||||||
const rawElement: Record<keyof Element, string> = _.reduce(
|
const rawElement: Record<keyof Element, string> = _.reduce(
|
||||||
types,
|
typeList,
|
||||||
(stringifiedElement: Record<keyof Element, string>, type: string, prop: string) => {
|
(stringifiedElement: Record<keyof Element, string>, type: string, prop: string) => {
|
||||||
const value = element[prop as keyof Element]
|
const value = element[prop as keyof Element]
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
@ -33,6 +33,7 @@ import { wishListGet, wishAdd } from "./gsheets/wishes"
|
|||||||
import config from "../config"
|
import config from "../config"
|
||||||
import notificationsSubscribe from "./notificationsSubscribe"
|
import notificationsSubscribe from "./notificationsSubscribe"
|
||||||
import checkAccess from "./checkAccess"
|
import checkAccess from "./checkAccess"
|
||||||
|
import { hasGSheetsAccess } from "./gsheets/accessors"
|
||||||
|
|
||||||
checkAccess()
|
checkAccess()
|
||||||
|
|
||||||
@ -151,3 +152,11 @@ function onListening(server: any) {
|
|||||||
const bind = typeof addr === "string" ? `pipe ${addr}` : `port ${addr.port}`
|
const bind = typeof addr === "string" ? `pipe ${addr}` : `port ${addr.port}`
|
||||||
console.error(chalk.green(`\nServer listening on ${bind}`))
|
console.error(chalk.green(`\nServer listening on ${bind}`))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hasGSheetsAccess().then((hasApiAccess: boolean) => {
|
||||||
|
if (hasApiAccess) {
|
||||||
|
console.error(chalk.green(`Database: remote Google Sheet`))
|
||||||
|
} else {
|
||||||
|
console.error(chalk.green(`Database: local db`))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
Loading…
x
Reference in New Issue
Block a user