From aacc685da1b3a1f4a78a17ec70e4e8ffc250608a Mon Sep 17 00:00:00 2001 From: waveringana Date: Sat, 3 Dec 2022 23:48:16 +0000 Subject: [PATCH] typescripting2 --- README.md | 7 +- app/{app.js => app.ts} | 73 ++++--- app/db.js | 37 ---- app/db.ts | 21 ++ app/routes/{auth.js => auth.ts} | 21 +- app/routes/{index.js => index.ts} | 54 ++--- app/routes/{middleware.js => middleware.ts} | 43 ++-- app/types.ts | 12 ++ docker/Dockerfile | 9 +- package-lock.json | 215 ++++++++++++++++++++ package.json | 13 +- tsconfig.json | 4 +- 12 files changed, 381 insertions(+), 128 deletions(-) rename app/{app.js => app.ts} (67%) delete mode 100644 app/db.js create mode 100644 app/db.ts rename app/routes/{auth.js => auth.ts} (76%) rename app/routes/{index.js => index.ts} (78%) rename app/routes/{middleware.js => middleware.ts} (79%) create mode 100644 app/types.ts diff --git a/README.md b/README.md index 8e4fd9e..9f2cf50 100644 --- a/README.md +++ b/README.md @@ -12,12 +12,11 @@ Upcoming Features: Source: ```Bash -EBPASS=changeme -EBPORT=3000 -EBAPI_KEY=changeme #ShareX support +$ export EBPASS=changeme +$ export EBPORT=3000 +$ export EBAPI_KEY=changeme #ShareX support $ npm install -$ node app/db.js $ npm start ``` Default username is admin with the password being whatever EBPASS is diff --git a/app/app.js b/app/app.ts similarity index 67% rename from app/app.js rename to app/app.ts index f277146..e23229a 100644 --- a/app/app.js +++ b/app/app.ts @@ -1,30 +1,29 @@ +import type {MediaRow, UserRow} from './types'; + require("dotenv").config(); -const express = require("express"); -const passport = require("passport"); -const session = require("express-session"); -const cookieParser = require("cookie-parser"); -const SQLiteStore = require("connect-sqlite3")(session); +import express from "express"; +import passport from "passport"; +import session from "express-session"; +import cookieParser from "cookie-parser"; +import sqlite3 from "connect-sqlite3"; +const SQLiteStore = sqlite3(session); -const fs = require("fs"); -const http = require("http"); -const path = require("path"); +import fs from "fs"; +import http from "http"; +import path from "path"; -const authRouter = require("./routes/auth"); -const indexRouter = require("./routes/index"); +import authRouter from "./routes/auth"; +import indexRouter from "./routes/index"; -const db = require("./db").db; +import {createUser} from "./db"; +import db from "./db" let app = express(); let server = http.createServer(app); let port = normalizePort(process.env.EBPORT || "3000"); -app.set("port", port); -server.listen(port); -server.on("error", onError); -server.on("listening", onListening); - -function normalizePort(val) { +function normalizePort(val: string) { var port = parseInt(val, 10); if (isNaN(port)) { @@ -40,7 +39,12 @@ function normalizePort(val) { return false; } -function onError(error) { +app.set("port", port); +server.listen(port); +server.on("error", onError); +server.on("listening", onListening); + +function onError(error: any) { if (error.syscall !== "listen") { throw error; } @@ -64,6 +68,24 @@ function onError(error) { } } +db.serialize(function() { + // create the database schema for the todos app + db.run("CREATE TABLE IF NOT EXISTS users ( \ + id INTEGER PRIMARY KEY, \ + username TEXT UNIQUE, \ + hashed_password BLOB, \ + salt BLOB \ + )"); + + db.run("CREATE TABLE IF NOT EXISTS media ( \ + id INTEGER PRIMARY KEY, \ + path TEXT NOT NULL, \ + expire INTEGER \ + )"); + + createUser("admin", process.env.EBPASS || "changeme"); +}); + function onListening() { var addr = server.address(); var bind = typeof addr === "string" @@ -90,6 +112,7 @@ app.use(session({ secret: process.env.EBSECRET || "pleasechangeme", resave: false, saveUninitialized: false, + // @ts-ignore store: new SQLiteStore({ db: "sessions.db", dir: "./var/db" @@ -103,7 +126,7 @@ app.use("/", authRouter); app.use("/uploads", express.static("uploads")); function prune () { - db.all("SELECT * FROM media", (err, rows) => { + db.all("SELECT * FROM media", (err: Error, rows: []) => { console.log("Uploaded files: " + rows.length); console.log(rows); }); @@ -111,23 +134,23 @@ function prune () { console.log("Vacuuming database..."); db.run("VACUUM"); - db.all("SELECT * FROM media WHERE expire < ?", [Date.now()], (err, rows) => { + db.all("SELECT * FROM media WHERE expire < ?", [Date.now()], (err: Error, rows: []) => { console.log("Expired rows: " + rows); if (err) return console.error(err); - rows.forEach((row) => { + rows.forEach((row: MediaRow) => { console.log(`Deleting ${row.path}`); fs.unlink(`uploads/${row.path}`, (err) => { if (err) { if(err.errno == -4058) { console.log("File already deleted"); - db.all("DELETE FROM media WHERE path = ?", [row.path], (err) => { + db.all("DELETE FROM media WHERE path = ?", [row.path], (err: Error) => { if (err) return console.error(err); }); } else { console.error(err); } } else { - db.all("DELETE FROM media WHERE path = ?", [row.path], (err) => { + db.all("DELETE FROM media WHERE path = ?", [row.path], (err: Error) => { if (err) return console.error(err); }); } @@ -137,6 +160,4 @@ function prune () { }); } -setInterval(prune, 1000 * 60); //prune every minute - -module.exports = app; +setInterval(prune, 1000 * 60); //prune every minute \ No newline at end of file diff --git a/app/db.js b/app/db.js deleted file mode 100644 index f50acc0..0000000 --- a/app/db.js +++ /dev/null @@ -1,37 +0,0 @@ -const sqlite3 = require("sqlite3"); -const mkdirp = require("mkdirp"); -const crypto = require("crypto"); - -mkdirp.sync("./uploads"); -mkdirp.sync("./var/db"); - -let db = new sqlite3.Database("./var/db/media.db"); - -db.serialize(function() { - // create the database schema for the todos app - db.run("CREATE TABLE IF NOT EXISTS users ( \ - id INTEGER PRIMARY KEY, \ - username TEXT UNIQUE, \ - hashed_password BLOB, \ - salt BLOB \ - )"); - - db.run("CREATE TABLE IF NOT EXISTS media ( \ - id INTEGER PRIMARY KEY, \ - path TEXT NOT NULL, \ - expire INTEGER \ - )"); - - createUser("admin", process.env.EBPASS || "changeme"); -}); - -function createUser(username, password) { - var salt = crypto.randomBytes(16); - db.run("INSERT OR IGNORE INTO users (username, hashed_password, salt) VALUES (?, ?, ?)", [ - username, - crypto.pbkdf2Sync(password, salt, 310000, 32, "sha256"), - salt - ]); -} - -module.exports = {db: db, createUser: createUser}; diff --git a/app/db.ts b/app/db.ts new file mode 100644 index 0000000..d7f8c13 --- /dev/null +++ b/app/db.ts @@ -0,0 +1,21 @@ +import type {RequestHandler as Middleware} from 'express'; + +const sqlite3 = require("sqlite3"); +const mkdirp = require("mkdirp"); +const crypto = require("crypto"); + +mkdirp.sync("./uploads"); +mkdirp.sync("./var/db"); + +let db = new sqlite3.Database("./var/db/media.db"); + +export function createUser(username: string, password: string) { + var salt = crypto.randomBytes(16); + db.run("INSERT OR IGNORE INTO users (username, hashed_password, salt) VALUES (?, ?, ?)", [ + username, + crypto.pbkdf2Sync(password, salt, 310000, 32, "sha256"), + salt + ]); +} + +export default db; diff --git a/app/routes/auth.js b/app/routes/auth.ts similarity index 76% rename from app/routes/auth.js rename to app/routes/auth.ts index c4308eb..1356dd8 100644 --- a/app/routes/auth.js +++ b/app/routes/auth.ts @@ -1,14 +1,18 @@ -const crypto = require("crypto"); -const express = require("express"); -const passport = require("passport"); -const LocalStrategy = require("passport-local"); +import type {MediaRow, UserRow} from '../types'; +import type {RequestHandler as Middleware} from 'express'; -let db = require("../db").db; +import crypto from "crypto"; +import express from "express"; +import passport from "passport"; + +import { Strategy as LocalStrategy } from "passport-local"; + +import db from "../db"; let router = express.Router(); passport.use(new LocalStrategy(function verify(username, password, cb) { - db.get("SELECT * FROM users WHERE username = ?", [username], function(err, row) { + db.get("SELECT * FROM users WHERE username = ?", [username], function(err: Error, row: UserRow) { if (err) { return cb(err); } @@ -35,7 +39,9 @@ passport.use(new LocalStrategy(function verify(username, password, cb) { passport.serializeUser(function(user, cb) { process.nextTick(function() { cb(null, { + // @ts-ignore id: user.id, + // @ts-ignore username: user.username }); }); @@ -47,6 +53,7 @@ passport.deserializeUser(function(user, cb) { }); }); +// @ts-ignore router.get("/login", function(req, res) { res.render("login"); }); @@ -66,4 +73,4 @@ router.post("/logout", function(req, res, next) { }); }); -module.exports = router; +export default router; diff --git a/app/routes/index.js b/app/routes/index.ts similarity index 78% rename from app/routes/index.js rename to app/routes/index.ts index eaebc82..cfe49ac 100644 --- a/app/routes/index.js +++ b/app/routes/index.ts @@ -1,19 +1,24 @@ -const multer = require("multer"); -const express = require("express"); -const ffmpeg = require("fluent-ffmpeg"); -const imageProbe = require("probe-image-size"); -const ffmpegpath = require("@ffmpeg-installer/ffmpeg").path; -const ffprobepath = require("@ffprobe-installer/ffprobe").path; +import type {RequestHandler as Middleware, Router, Request, Response} from 'express'; +import types from 'multer'; -ffmpeg.setFfmpegPath(ffmpegpath); -ffmpeg.setFfprobePath(ffprobepath); +import multer from "multer"; +import express from "express"; +import ffmpeg from "fluent-ffmpeg"; +import imageProbe from "probe-image-size"; +import ffmpegpath from "@ffmpeg-installer/ffmpeg"; +// @ts-ignore +import ffprobepath from "@ffprobe-installer/ffprobe"; -const fs = require("fs"); +ffmpeg.setFfmpegPath(ffmpegpath.path); +ffmpeg.setFfprobePath(ffprobepath.path); -let db = require("../db").db; -let {checkAuth, convert, handleUpload} = require("./middleware"); +import fs from "fs"; -function extension(str){ +import db from "../db"; +import {checkAuth, convert, handleUpload} from "./middleware"; +import { MediaRow } from '../types'; + +function extension(str: String){ let file = str.split("/").pop(); return [file.substr(0,file.lastIndexOf(".")),file.substr(file.lastIndexOf("."),file.length).toLowerCase()]; } @@ -24,7 +29,7 @@ const storage = multer.diskStorage({ }, filename : function(req, file, cb) { let nameAndExtension = extension(file.originalname); - db.all("SELECT * FROM media WHERE path = ?", [nameAndExtension[0] + nameAndExtension[1]], function (err, exists) { + db.all("SELECT * FROM media WHERE path = ?", [nameAndExtension[0] + nameAndExtension[1]], function (err: Error, exists: []) { if (exists.length != 0) { let suffix = new Date().getTime() / 1000; @@ -65,10 +70,10 @@ const fileFilter = function(req, file, cb) { let upload = multer({ storage: storage /**, fileFilter: fileFilter**/ }); //maybe make this a env variable? -function fetchMedia(req, res, next) { - db.all("SELECT * FROM media", (err, rows) => { +const fetchMedia: Middleware = (req, res, next) => { + db.all("SELECT * FROM media", (err: Error, rows: []) => { if (err) return next(err); - let files = rows.map((row)=> { + let files = rows.map((row: MediaRow)=> { return { id: row.id, path: row.path, @@ -84,11 +89,11 @@ function fetchMedia(req, res, next) { let router = express.Router(); -router.get("/", function (req, res, next) { +router.get("/", (req, res, next) => { // @ts-ignore, user is part of req header if (!req.user) { return res.render("home"); } next(); -}, fetchMedia, function(req, res) { +}, fetchMedia, (req, res) => { res.locals.filter = null; // @ts-ignore, user is part of req header res.render("index", { user: req.user }); @@ -125,16 +130,17 @@ router.get("/gifv/:file", async function (req, res, next) { } }); -router.post("/", [upload.array("fileupload"), convert, handleUpload], function(req, res) { +router.post("/", [upload.array("fileupload"), convert, handleUpload], (req: Request, res: Response) => { return res.redirect("/"); }); -router.post("/sharex", [checkAuth, upload.array("fileupload"), convert, handleUpload], function(req, res) { +router.post("/sharex", [checkAuth, upload.array("fileupload"), convert, handleUpload], (req: Request, res: Response) => { + // @ts-ignore return res.send(`${req.protocol}://${req.get("host")}/uploads/${req.files[0].filename}`); }); router.post("/:id(\\d+)/delete", function(req, res, next) { - db.all("SELECT path FROM media WHERE id = ?", [ req.params.id ], function(err, path) { + db.all("SELECT path FROM media WHERE id = ?", [ req.params.id ], function(err: Error, path: Array) { if (err) { return next(err); } fs.unlink(`uploads/${path[0].path}`, (err => { if (err) { @@ -142,7 +148,7 @@ router.post("/:id(\\d+)/delete", function(req, res, next) { if (err.errno == -4058) { //File just doesnt exist anymore db.run("DELETE FROM media WHERE id = ?", [ req.params.id - ], function(err) { + ], (err: Error) => { if (err) { return next(err); } return res.redirect("/"); }); @@ -155,7 +161,7 @@ router.post("/:id(\\d+)/delete", function(req, res, next) { //Callback Hell :D db.run("DELETE FROM media WHERE id = ?", [ req.params.id - ], function(err) { + ], (err: Error) => { if (err) { return next(err); } return res.redirect("/"); }); @@ -164,4 +170,4 @@ router.post("/:id(\\d+)/delete", function(req, res, next) { }); }); -module.exports = router; +export default router; \ No newline at end of file diff --git a/app/routes/middleware.js b/app/routes/middleware.ts similarity index 79% rename from app/routes/middleware.js rename to app/routes/middleware.ts index 21e7cad..89b5cf3 100644 --- a/app/routes/middleware.js +++ b/app/routes/middleware.ts @@ -1,21 +1,25 @@ -const ffmpeg = require("fluent-ffmpeg"); -const ffmpegpath = require("@ffmpeg-installer/ffmpeg").path; -const ffprobepath = require("@ffprobe-installer/ffprobe").path; -ffmpeg.setFfmpegPath(ffmpegpath); -ffmpeg.setFfprobePath(ffprobepath); +import type {MediaRow, UserRow} from '../types'; +import type {RequestHandler as Middleware, Router, Request, Response} from 'express'; -const fs = require("fs"); -const process = require("process"); +import ffmpeg from "fluent-ffmpeg"; +import ffmpegpath from "@ffmpeg-installer/ffmpeg"; +// @ts-ignore +import ffprobepath from "@ffprobe-installer/ffprobe"; +ffmpeg.setFfmpegPath(ffmpegpath.path); +ffmpeg.setFfprobePath(ffprobepath.path); -let db = require("../db.js").db; +import fs from "fs"; +import process from "process"; -function extension(str){ +import db from "../db"; + +function extension(str: String){ let file = str.split("/").pop(); return [file.substr(0,file.lastIndexOf(".")),file.substr(file.lastIndexOf("."),file.length).toLowerCase()]; } //Checks ShareX key -function checkAuth(req, res, next) { +export const checkAuth: Middleware = (req: Request, res: Response, next: Function) => { let auth = process.env.EBAPI_KEY || process.env.EBPASS || "pleaseSetAPI_KEY"; let key = null; @@ -36,8 +40,9 @@ function checkAuth(req, res, next) { } //Converts mp4 to gif and vice versa with ffmpeg -function convert(req, res, next) { +export const convert: Middleware = (req: Request, res: Response, next: Function) => { for (let file in req.files) { + // @ts-ignore let nameAndExtension = extension(req.files[file].originalname); let oembed = { type: "video", @@ -92,7 +97,7 @@ function convert(req, res, next) { next(); } -function handleUpload(req, res, next) { +export const handleUpload: Middleware = (req: Request, res: Response, next: Function) => { if (!req.files || Object.keys(req.files).length === 0) { console.log("No files were uploaded"); return res.status(400).send("No files were uploaded."); @@ -100,31 +105,27 @@ function handleUpload(req, res, next) { for (let file in req.files) { let currentdate = Date.now(); - let expireDate; + let expireDate: Date; if (req.body.expire) { expireDate = new Date(currentdate + (req.body.expire * 24 * 60 * 60 * 1000)); console.log(req.body.expire); console.log(expireDate); } else expireDate = null; + // @ts-ignore db.run("INSERT INTO media (path, expire) VALUES (?, ?)", [req.files[file].filename, expireDate], function (err) { if (err) { console.log(err); return next(err); } + // @ts-ignore console.log(`Uploaded ${req.files[file].filename} to database`); if (expireDate == null) console.log("It will not expire"); - else if (expireDate != null || expireDate != undefined || expireDate != "") + else if (expireDate != null || expireDate != undefined) console.log(`It will expire on ${expireDate}`); }); } next(); -} - -module.exports = { - checkAuth: checkAuth, - convert: convert, - handleUpload: handleUpload -}; \ No newline at end of file +} \ No newline at end of file diff --git a/app/types.ts b/app/types.ts new file mode 100644 index 0000000..f12215c --- /dev/null +++ b/app/types.ts @@ -0,0 +1,12 @@ +export interface MediaRow { + id? : Number, + path: String, + expire: Number +} + +export interface UserRow { + id? : Number, + username: String, + hashed_password: any, + salt: any +} \ No newline at end of file diff --git a/docker/Dockerfile b/docker/Dockerfile index 4e20266..a5b4920 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,22 +1,21 @@ FROM node:16-alpine AS BUILD_IMAGE RUN apk add curl -RUN curl -sf https://gobinaries.com/tj/node-prune | sh COPY package*.json ./ +COPY tsconfig.json ./ +COPY /app ./app RUN npm install RUN npm prune --production -RUN /usr/local/bin/node-prune FROM node:16-alpine COPY --from=BUILD_IMAGE /node_modules ./node_modules -COPY /app ./app +COPY /dist ./dist COPY package*.json ./ +COPY tsconfig.json ./ ENV NODE_ENV=production -RUN node /app/db.js - CMD ["npm", "start"] \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index cdfb5b5..e071c71 100644 --- a/package-lock.json +++ b/package-lock.json @@ -28,9 +28,18 @@ "sqlite3": "^5.0.2" }, "devDependencies": { + "@types/connect-sqlite3": "^0.9.1", + "@types/cookie-parser": "^1.4.3", "@types/dotenv": "^8.2.0", "@types/express": "^4.17.14", + "@types/express-session": "^1.17.5", + "@types/fluent-ffmpeg": "^2.1.20", + "@types/mkdirp": "^1.0.2", + "@types/multer": "^1.4.7", "@types/node": "^18.11.10", + "@types/passport": "^1.0.11", + "@types/passport-local": "^1.0.34", + "@types/probe-image-size": "^7.2.0", "@typescript-eslint/parser": "^5.45.0", "copyfiles": "^2.4.1", "cypress": "^11.1.0", @@ -616,6 +625,24 @@ "@types/node": "*" } }, + "node_modules/@types/connect-sqlite3": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/@types/connect-sqlite3/-/connect-sqlite3-0.9.1.tgz", + "integrity": "sha512-KVwSEPhE76YhQemOp+gTlJ/nq6fswEopmx68J9AuB9ofbR/MA9k8i5J8pE6OvQEtPiOzXHDUIz4wye9o8Fsd7g==", + "dev": true, + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/cookie-parser": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/@types/cookie-parser/-/cookie-parser-1.4.3.tgz", + "integrity": "sha512-CqSKwFwefj4PzZ5n/iwad/bow2hTCh0FlNAeWLtQM3JA/NX/iYagIpWG2cf1bQKQ2c9gU2log5VUCrn7LDOs0w==", + "dev": true, + "dependencies": { + "@types/express": "*" + } + }, "node_modules/@types/dotenv": { "version": "8.2.0", "resolved": "https://registry.npmjs.org/@types/dotenv/-/dotenv-8.2.0.tgz", @@ -649,18 +676,103 @@ "@types/range-parser": "*" } }, + "node_modules/@types/express-session": { + "version": "1.17.5", + "resolved": "https://registry.npmjs.org/@types/express-session/-/express-session-1.17.5.tgz", + "integrity": "sha512-l0DhkvNVfyUPEEis8fcwbd46VptfA/jmMwHfob2TfDMf3HyPLiB9mKD71LXhz5TMUobODXPD27zXSwtFQLHm+w==", + "dev": true, + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/fluent-ffmpeg": { + "version": "2.1.20", + "resolved": "https://registry.npmjs.org/@types/fluent-ffmpeg/-/fluent-ffmpeg-2.1.20.tgz", + "integrity": "sha512-B+OvhCdJ3LgEq2PhvWNOiB/EfwnXLElfMCgc4Z1K5zXgSfo9I6uGKwR/lqmNPFQuebNnes7re3gqkV77SyypLg==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/mime": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-3.0.1.tgz", "integrity": "sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA==", "dev": true }, + "node_modules/@types/mkdirp": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@types/mkdirp/-/mkdirp-1.0.2.tgz", + "integrity": "sha512-o0K1tSO0Dx5X6xlU5F1D6625FawhC3dU3iqr25lluNv/+/QIVH8RLNEiVokgIZo+mz+87w/3Mkg/VvQS+J51fQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/multer": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/@types/multer/-/multer-1.4.7.tgz", + "integrity": "sha512-/SNsDidUFCvqqcWDwxv2feww/yqhNeTRL5CVoL3jU4Goc4kKEL10T7Eye65ZqPNi4HRx8sAEX59pV1aEH7drNA==", + "dev": true, + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/needle": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/@types/needle/-/needle-2.5.3.tgz", + "integrity": "sha512-RwgTwMRaedfyCBe5SSWMpm1Yqzc5UPZEMw0eAd09OSyV93nLRj9/evMGZmgFeHKzUOd4xxtHvgtc+rjcBjI1Qg==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/node": { "version": "18.11.10", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.10.tgz", "integrity": "sha512-juG3RWMBOqcOuXC643OAdSA525V44cVgGV6dUDuiFtss+8Fk5x1hI93Rsld43VeJVIeqlP9I7Fn9/qaVqoEAuQ==", "dev": true }, + "node_modules/@types/passport": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@types/passport/-/passport-1.0.11.tgz", + "integrity": "sha512-pz1cx9ptZvozyGKKKIPLcVDVHwae4hrH5d6g5J+DkMRRjR3cVETb4jMabhXAUbg3Ov7T22nFHEgaK2jj+5CBpw==", + "dev": true, + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/passport-local": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/@types/passport-local/-/passport-local-1.0.34.tgz", + "integrity": "sha512-PSc07UdYx+jhadySxxIYWuv6sAnY5e+gesn/5lkPKfBeGuIYn9OPR+AAEDq73VRUh6NBTpvE/iPE62rzZUslog==", + "dev": true, + "dependencies": { + "@types/express": "*", + "@types/passport": "*", + "@types/passport-strategy": "*" + } + }, + "node_modules/@types/passport-strategy": { + "version": "0.2.35", + "resolved": "https://registry.npmjs.org/@types/passport-strategy/-/passport-strategy-0.2.35.tgz", + "integrity": "sha512-o5D19Jy2XPFoX2rKApykY15et3Apgax00RRLf0RUotPDUsYrQa7x4howLYr9El2mlUApHmCMv5CZ1IXqKFQ2+g==", + "dev": true, + "dependencies": { + "@types/express": "*", + "@types/passport": "*" + } + }, + "node_modules/@types/probe-image-size": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@types/probe-image-size/-/probe-image-size-7.2.0.tgz", + "integrity": "sha512-R5H3vw62gHNHrn+JGZbKejb+Z2D/6E5UNVlhCzIaBBLroMQMOFqy5Pap2gM+ZZHdqBtVU0/cx/M6to+mOJcoew==", + "dev": true, + "dependencies": { + "@types/needle": "*", + "@types/node": "*" + } + }, "node_modules/@types/qs": { "version": "6.9.7", "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", @@ -6139,6 +6251,24 @@ "@types/node": "*" } }, + "@types/connect-sqlite3": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/@types/connect-sqlite3/-/connect-sqlite3-0.9.1.tgz", + "integrity": "sha512-KVwSEPhE76YhQemOp+gTlJ/nq6fswEopmx68J9AuB9ofbR/MA9k8i5J8pE6OvQEtPiOzXHDUIz4wye9o8Fsd7g==", + "dev": true, + "requires": { + "@types/express": "*" + } + }, + "@types/cookie-parser": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/@types/cookie-parser/-/cookie-parser-1.4.3.tgz", + "integrity": "sha512-CqSKwFwefj4PzZ5n/iwad/bow2hTCh0FlNAeWLtQM3JA/NX/iYagIpWG2cf1bQKQ2c9gU2log5VUCrn7LDOs0w==", + "dev": true, + "requires": { + "@types/express": "*" + } + }, "@types/dotenv": { "version": "8.2.0", "resolved": "https://registry.npmjs.org/@types/dotenv/-/dotenv-8.2.0.tgz", @@ -6171,18 +6301,103 @@ "@types/range-parser": "*" } }, + "@types/express-session": { + "version": "1.17.5", + "resolved": "https://registry.npmjs.org/@types/express-session/-/express-session-1.17.5.tgz", + "integrity": "sha512-l0DhkvNVfyUPEEis8fcwbd46VptfA/jmMwHfob2TfDMf3HyPLiB9mKD71LXhz5TMUobODXPD27zXSwtFQLHm+w==", + "dev": true, + "requires": { + "@types/express": "*" + } + }, + "@types/fluent-ffmpeg": { + "version": "2.1.20", + "resolved": "https://registry.npmjs.org/@types/fluent-ffmpeg/-/fluent-ffmpeg-2.1.20.tgz", + "integrity": "sha512-B+OvhCdJ3LgEq2PhvWNOiB/EfwnXLElfMCgc4Z1K5zXgSfo9I6uGKwR/lqmNPFQuebNnes7re3gqkV77SyypLg==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@types/mime": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-3.0.1.tgz", "integrity": "sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA==", "dev": true }, + "@types/mkdirp": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@types/mkdirp/-/mkdirp-1.0.2.tgz", + "integrity": "sha512-o0K1tSO0Dx5X6xlU5F1D6625FawhC3dU3iqr25lluNv/+/QIVH8RLNEiVokgIZo+mz+87w/3Mkg/VvQS+J51fQ==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/multer": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/@types/multer/-/multer-1.4.7.tgz", + "integrity": "sha512-/SNsDidUFCvqqcWDwxv2feww/yqhNeTRL5CVoL3jU4Goc4kKEL10T7Eye65ZqPNi4HRx8sAEX59pV1aEH7drNA==", + "dev": true, + "requires": { + "@types/express": "*" + } + }, + "@types/needle": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/@types/needle/-/needle-2.5.3.tgz", + "integrity": "sha512-RwgTwMRaedfyCBe5SSWMpm1Yqzc5UPZEMw0eAd09OSyV93nLRj9/evMGZmgFeHKzUOd4xxtHvgtc+rjcBjI1Qg==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@types/node": { "version": "18.11.10", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.10.tgz", "integrity": "sha512-juG3RWMBOqcOuXC643OAdSA525V44cVgGV6dUDuiFtss+8Fk5x1hI93Rsld43VeJVIeqlP9I7Fn9/qaVqoEAuQ==", "dev": true }, + "@types/passport": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@types/passport/-/passport-1.0.11.tgz", + "integrity": "sha512-pz1cx9ptZvozyGKKKIPLcVDVHwae4hrH5d6g5J+DkMRRjR3cVETb4jMabhXAUbg3Ov7T22nFHEgaK2jj+5CBpw==", + "dev": true, + "requires": { + "@types/express": "*" + } + }, + "@types/passport-local": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/@types/passport-local/-/passport-local-1.0.34.tgz", + "integrity": "sha512-PSc07UdYx+jhadySxxIYWuv6sAnY5e+gesn/5lkPKfBeGuIYn9OPR+AAEDq73VRUh6NBTpvE/iPE62rzZUslog==", + "dev": true, + "requires": { + "@types/express": "*", + "@types/passport": "*", + "@types/passport-strategy": "*" + } + }, + "@types/passport-strategy": { + "version": "0.2.35", + "resolved": "https://registry.npmjs.org/@types/passport-strategy/-/passport-strategy-0.2.35.tgz", + "integrity": "sha512-o5D19Jy2XPFoX2rKApykY15et3Apgax00RRLf0RUotPDUsYrQa7x4howLYr9El2mlUApHmCMv5CZ1IXqKFQ2+g==", + "dev": true, + "requires": { + "@types/express": "*", + "@types/passport": "*" + } + }, + "@types/probe-image-size": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@types/probe-image-size/-/probe-image-size-7.2.0.tgz", + "integrity": "sha512-R5H3vw62gHNHrn+JGZbKejb+Z2D/6E5UNVlhCzIaBBLroMQMOFqy5Pap2gM+ZZHdqBtVU0/cx/M6to+mOJcoew==", + "dev": true, + "requires": { + "@types/needle": "*", + "@types/node": "*" + } + }, "@types/qs": { "version": "6.9.7", "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", diff --git a/package.json b/package.json index f464a30..c5d10ee 100644 --- a/package.json +++ b/package.json @@ -23,9 +23,9 @@ "scripts": { "start": "node ./dist/app.js", "clean": "rimraf dist/", - "copy-files": "copyfiles -a -V -u 1 app/public/* app/views/* app/public/**/* app/views/**/* dist/", + "copy-files": "copyfiles -a -u 1 app/public/* app/views/* app/public/**/* app/views/**/* dist/", "tsc": "tsc", - "postinstall": "npm run tsc", + "postinstall": "npm run tsc && npm run copy-files", "dev": "tsc-node-dev --respawn --pretty --transpile-only index.ts" }, "dependencies": { @@ -47,9 +47,18 @@ "sqlite3": "^5.0.2" }, "devDependencies": { + "@types/connect-sqlite3": "^0.9.1", + "@types/cookie-parser": "^1.4.3", "@types/dotenv": "^8.2.0", "@types/express": "^4.17.14", + "@types/express-session": "^1.17.5", + "@types/fluent-ffmpeg": "^2.1.20", + "@types/mkdirp": "^1.0.2", + "@types/multer": "^1.4.7", "@types/node": "^18.11.10", + "@types/passport": "^1.0.11", + "@types/passport-local": "^1.0.34", + "@types/probe-image-size": "^7.2.0", "@typescript-eslint/parser": "^5.45.0", "copyfiles": "^2.4.1", "cypress": "^11.1.0", diff --git a/tsconfig.json b/tsconfig.json index 7b221f9..572267d 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -76,9 +76,9 @@ "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ /* Type Checking */ - "strict": false, /* Enable all strict type-checking options. */ + "strict": true, /* Enable all strict type-checking options. */ // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ - // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ + "strictNullChecks": false, /* When type checking, take into account 'null' and 'undefined'. */ // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */