updated all dependencies
parent
cc87abe6b5
commit
dfd6ffe02b
13
.babelrc
13
.babelrc
|
@ -1,13 +0,0 @@
|
|||
{
|
||||
"env": {
|
||||
"development": {
|
||||
"presets": ["next/babel"]
|
||||
},
|
||||
"production": {
|
||||
"presets": ["next/babel"]
|
||||
},
|
||||
"test": {
|
||||
"presets": [["next/babel", { "preset-env": { "modules": "commonjs" } }]]
|
||||
}
|
||||
}
|
||||
}
|
22
.eslintrc.js
22
.eslintrc.js
|
@ -4,11 +4,6 @@ module.exports = {
|
|||
"es2020": true,
|
||||
"node": true
|
||||
},
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:react/recommended",
|
||||
"plugin:@typescript-eslint/recommended"
|
||||
],
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"parserOptions": {
|
||||
"ecmaFeatures": {
|
||||
|
@ -22,10 +17,15 @@ module.exports = {
|
|||
"@typescript-eslint"
|
||||
],
|
||||
"rules": {
|
||||
// suppress errors for missing 'import React' in files
|
||||
"@typescript-eslint/explicit-module-boundary-types": "off",
|
||||
"react/react-in-jsx-scope": "off",
|
||||
// allow jsx syntax in js files (for next.js project)
|
||||
"react/jsx-filename-extension": [1, { "extensions": [".js", ".jsx",".ts", ".tsx"] }], //should add ".ts" if typescript project
|
||||
}
|
||||
// suppress errors for missing 'import React' in files
|
||||
"@typescript-eslint/explicit-module-boundary-types": "off",
|
||||
"react/react-in-jsx-scope": "off",
|
||||
// allow jsx syntax in js files (for next.js project)
|
||||
"react/jsx-filename-extension": [1, { "extensions": [".js", ".jsx", ".ts", ".tsx"] }], //should add ".ts" if typescript project
|
||||
},
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:react/recommended",
|
||||
"plugin:@typescript-eslint/recommended"
|
||||
],
|
||||
};
|
||||
|
|
|
@ -12,7 +12,7 @@ declare global {
|
|||
|
||||
declare module 'http' {
|
||||
interface IncomingMessage {
|
||||
session: any
|
||||
session?: any
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
/// <reference types="next" />
|
||||
/// <reference types="next/types/global" />
|
||||
/// <reference types="next/image-types/global" />
|
||||
|
||||
// NOTE: This file should not be edited
|
||||
|
|
|
@ -33,7 +33,6 @@ module.exports = {
|
|||
}
|
||||
return config
|
||||
},
|
||||
webpack5: false,
|
||||
env: { //https://nextjs.org/docs/api-reference/next.config.js/environment-variables
|
||||
recaptcha_site_key: "6LcqV9QUAAAAAEybBVr0FWnUnFQmOVxGoQ_Muhtb",
|
||||
api_domain: "http://localhost/public_api",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"watch": ["server"],
|
||||
"exec": "npx ts-node --project tsconfig.server.json server/index.ts",
|
||||
"exec": "npx ts-node --project tsconfig.server.json src/server/index.ts",
|
||||
"ext": "js ts"
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
88
package.json
88
package.json
|
@ -2,67 +2,63 @@
|
|||
"name": "scenery",
|
||||
"version": "2.0.0",
|
||||
"scripts": {
|
||||
"dev": "nodemon",
|
||||
"build": "next build && tsc --project tsconfig.server.json",
|
||||
"dev": "cross-env NODE_OPTIONS=--openssl-legacy-provider nodemon",
|
||||
"build": "cross-env NODE_OPTIONS=--openssl-legacy-provider next build && tsc --project tsconfig.server.json",
|
||||
"build_pages": "next build",
|
||||
"build_server": "tsc --project tsconfig.server.json",
|
||||
"start": "cross-env NODE_ENV=production node dist/server/index.js",
|
||||
"start": "cross-env NODE_OPTIONS=--openssl-legacy-provider NODE_ENV=production node dist/server/index.js",
|
||||
"start_dev": "cross-env NODE_ENV=development node dist/server/index.js",
|
||||
"pm2_start_ms": "pm2 start ./ambience/microservices.config.js",
|
||||
"pm2_start": "pm2 start ./ambience/microservices.config.js && pm2 start"
|
||||
},
|
||||
"dependencies": {
|
||||
"@emotion/cache": "^11.10.1",
|
||||
"@emotion/react": "^11.10.0",
|
||||
"@emotion/server": "^11.10.0",
|
||||
"@emotion/styled": "^11.10.0",
|
||||
"@fastify/cookie": "^7.4.0",
|
||||
"@fastify/cors": "^8.1.0",
|
||||
"@fastify/formbody": "^7.0.1",
|
||||
"@fastify/multipart": "^7.1.0",
|
||||
"@fastify/session": "^9.0.0",
|
||||
"@fortawesome/fontawesome-svg-core": "^1.2.36",
|
||||
"@fortawesome/free-brands-svg-icons": "^5.15.4",
|
||||
"@fortawesome/react-fontawesome": "^0.1.15",
|
||||
"@material-ui/core": "^4.12.3",
|
||||
"@material-ui/icons": "^4.11.2",
|
||||
"@material-ui/lab": "^4.0.0-alpha.60",
|
||||
"@ronomon/crypto-async": "^5.0.1",
|
||||
"@mui/icons-material": "^5.8.4",
|
||||
"@mui/material": "^5.10.0",
|
||||
"@types/bcrypt": "^5.0.0",
|
||||
"@types/clean-css": "^4.2.5",
|
||||
"@types/grecaptcha": "^3.0.3",
|
||||
"@types/node": "^16.4.13",
|
||||
"@types/nodemailer": "^6.4.4",
|
||||
"@types/puppeteer": "^5.4.4",
|
||||
"@types/react": "^17.0.16",
|
||||
"@types/sharp": "^0.28.5",
|
||||
"@typescript-eslint/eslint-plugin": "^4.29.1",
|
||||
"@typescript-eslint/parser": "^4.29.1",
|
||||
"axios": "^0.21.1",
|
||||
"@types/grecaptcha": "^3.0.4",
|
||||
"@types/node": "^18.7.3",
|
||||
"@types/nodemailer": "^6.4.5",
|
||||
"@types/react": "^18.0.17",
|
||||
"@types/sharp": "^0.30.5",
|
||||
"@typescript-eslint/eslint-plugin": "^5.33.0",
|
||||
"@typescript-eslint/parser": "^5.33.0",
|
||||
"axios": "^0.27.2",
|
||||
"bcrypt": "^5.0.1",
|
||||
"clean-css": "^5.1.5",
|
||||
"clsx": "^1.1.1",
|
||||
"compression-webpack-plugin": "^8.0.1",
|
||||
"connect-mongo": "^4.4.1",
|
||||
"clsx": "^1.2.1",
|
||||
"compression-webpack-plugin": "^10.0.0",
|
||||
"connect-mongo": "^4.6.0",
|
||||
"cross-env": "^7.0.3",
|
||||
"dotenv": "^10.0.0",
|
||||
"eslint": "^7.32.0",
|
||||
"eslint-config-next": "^11.0.1",
|
||||
"eslint-plugin-react": "^7.24.0",
|
||||
"express-session": "^1.17.2",
|
||||
"fastify": "^3.20.1",
|
||||
"fastify-cookie": "^5.3.1",
|
||||
"fastify-cors": "^6.0.2",
|
||||
"fastify-formbody": "^5.1.0",
|
||||
"fastify-multipart": "^4.0.7",
|
||||
"eslint": "^8.22.0",
|
||||
"eslint-plugin-react": "^7.30.1",
|
||||
"express-session": "^1.17.3",
|
||||
"fastify": "^4.4.0",
|
||||
"fastify-recaptcha": "^1.0.0",
|
||||
"fastify-session": "github:qwertyforce/fastify-session",
|
||||
"file-type": "^16.5.3",
|
||||
"file-type": "^16.5.4",
|
||||
"form-data": "^4.0.0",
|
||||
"jest": "^27.0.6",
|
||||
"json-schema-to-ts": "^1.6.4",
|
||||
"material-ui-dropzone": "^3.5.0",
|
||||
"mongodb": "^4.1.1",
|
||||
"next": "^11.1.0",
|
||||
"nodemailer": "^6.6.3",
|
||||
"nodemon": "^2.0.12",
|
||||
"prop-types": "^15.7.2",
|
||||
"puppeteer": "^10.2.0",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
"json-schema-to-ts": "^2.5.5",
|
||||
"mongodb": "^4.8.1",
|
||||
"mui-file-dropzone": "^4.0.1",
|
||||
"next": "^12.2.5",
|
||||
"nodemailer": "^6.7.8",
|
||||
"nodemon": "^2.0.19",
|
||||
"prop-types": "^15.8.1",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-photo-gallery": "github:qwertyforce/react_photo_gallery_build",
|
||||
"sharp": "^0.28.3",
|
||||
"typescript": "^4.3.5"
|
||||
"sharp": "^0.30.7",
|
||||
"tss-react": "^3.7.1",
|
||||
"typescript": "^4.7.4"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,36 +0,0 @@
|
|||
import { Fragment, useEffect } from 'react'
|
||||
import Head from 'next/head'
|
||||
import { AppProps } from 'next/app'
|
||||
import { ThemeProvider } from '@material-ui/core/styles'
|
||||
import CssBaseline from '@material-ui/core/CssBaseline'
|
||||
import theme from '../components/theme'
|
||||
import { DataContextProvider } from "../components/DataContext"
|
||||
import "../components/styles.css"
|
||||
|
||||
export default function MyApp(props: AppProps) {
|
||||
const { Component, pageProps } = props
|
||||
useEffect(() => {
|
||||
// Remove the server-side injected CSS.
|
||||
const jssStyles = document.querySelector('#jss-server-side')
|
||||
if (jssStyles) {
|
||||
jssStyles.parentElement?.removeChild(jssStyles)
|
||||
}
|
||||
if (typeof window !== "undefined" && localStorage.getItem("useIPFS") === null) {
|
||||
localStorage.setItem('useIPFS', 'false')
|
||||
}
|
||||
}, [])
|
||||
return (
|
||||
<Fragment>
|
||||
<Head>
|
||||
<title>Scenery</title>
|
||||
<meta name="viewport" content="minimum-scale=1, initial-scale=1, width=device-width" />
|
||||
</Head>
|
||||
<ThemeProvider theme={theme}>
|
||||
<CssBaseline />
|
||||
<DataContextProvider>
|
||||
<Component {...pageProps} />
|
||||
</DataContextProvider>
|
||||
</ThemeProvider>
|
||||
</Fragment>
|
||||
)
|
||||
}
|
|
@ -1,89 +0,0 @@
|
|||
import Document, { Html, Head, Main, NextScript } from 'next/document'
|
||||
import { ServerStyleSheets } from '@material-ui/core/styles'
|
||||
import theme from '../components/theme'
|
||||
import CleanCSS from "clean-css"
|
||||
import { Children } from 'react'
|
||||
const cleanCSS = new CleanCSS({
|
||||
level: {
|
||||
1: {},
|
||||
2: {}
|
||||
}
|
||||
})
|
||||
const minified_css_cache = new Map()
|
||||
|
||||
export default class MyDocument extends Document {
|
||||
render() {
|
||||
return (
|
||||
<Html lang="en">
|
||||
<Head>
|
||||
{/* PWA primary color */}
|
||||
<meta name="theme-color" content={theme.palette.primary.main} />
|
||||
<link rel='preconnect' href='https://fonts.gstatic.com' crossOrigin="anonymous" />
|
||||
<link rel="preload" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap" as="style" />
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap" />
|
||||
</Head>
|
||||
<body>
|
||||
<Main />
|
||||
<NextScript />
|
||||
<script defer src={`https://www.google.com/recaptcha/api.js?render=${process.env.recaptcha_site_key}`}></script>
|
||||
</body>
|
||||
</Html>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// `getInitialProps` belongs to `_document` (instead of `_app`),
|
||||
// it's compatible with server-side generation (SSG).
|
||||
MyDocument.getInitialProps = async (ctx) => {
|
||||
// Resolution order
|
||||
//
|
||||
// On the server:
|
||||
// 1. app.getInitialProps
|
||||
// 2. page.getInitialProps
|
||||
// 3. document.getInitialProps
|
||||
// 4. app.render
|
||||
// 5. page.render
|
||||
// 6. document.render
|
||||
//
|
||||
// On the server with error:
|
||||
// 1. document.getInitialProps
|
||||
// 2. app.render
|
||||
// 3. page.render
|
||||
// 4. document.render
|
||||
//
|
||||
// On the client
|
||||
// 1. app.getInitialProps
|
||||
// 2. page.getInitialProps
|
||||
// 3. app.render
|
||||
// 4. page.render
|
||||
|
||||
// Render app and page and get the context of the page with collected side effects.
|
||||
const sheets = new ServerStyleSheets()
|
||||
const originalRenderPage = ctx.renderPage
|
||||
|
||||
ctx.renderPage = () =>
|
||||
originalRenderPage({
|
||||
// eslint-disable-next-line react/display-name
|
||||
enhanceApp: (App) => (props) => sheets.collect(<App {...props} />),
|
||||
})
|
||||
|
||||
const initialProps = await Document.getInitialProps(ctx)
|
||||
|
||||
let css = sheets.toString()
|
||||
if (css && process.env.NODE_ENV === "production") {
|
||||
const min_css = minified_css_cache.get(css)
|
||||
if (min_css) {
|
||||
css = min_css
|
||||
} else {
|
||||
const old_css = css
|
||||
css = cleanCSS.minify(css).styles
|
||||
minified_css_cache.set(old_css, css)
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
...initialProps,
|
||||
// Styles fragment is rendered after the app and page rendering finish.
|
||||
styles: [...Children.toArray(initialProps.styles), <style id="jss-server-side" key="jss-server-side" dangerouslySetInnerHTML={{ __html: css }}></style>],
|
||||
}
|
||||
}
|
|
@ -1,22 +1,23 @@
|
|||
import { useContext, useState } from 'react'
|
||||
import { alpha, makeStyles } from '@material-ui/core/styles'
|
||||
import AppBar from '@material-ui/core/AppBar'
|
||||
import Toolbar from '@material-ui/core/Toolbar'
|
||||
import Typography from '@material-ui/core/Typography'
|
||||
import SearchIcon from '@material-ui/icons/Search'
|
||||
import InputBase from '@material-ui/core/InputBase'
|
||||
import { KeyboardEvent, useContext, useState } from 'react'
|
||||
import { alpha } from '@mui/material/styles';
|
||||
import { makeStyles } from 'tss-react/mui';
|
||||
import AppBar from '@mui/material/AppBar'
|
||||
import Toolbar from '@mui/material/Toolbar'
|
||||
import Typography from '@mui/material/Typography'
|
||||
import SearchIcon from '@mui/icons-material/Search'
|
||||
import InputBase from '@mui/material/InputBase'
|
||||
import Link from './Link'
|
||||
import HelpOutlineIcon from '@material-ui/icons/HelpOutline'
|
||||
import ImageSearchIcon from '@material-ui/icons/ImageSearch'
|
||||
import { IconButton } from '@material-ui/core'
|
||||
import Switch from '@material-ui/core/Switch'
|
||||
import HelpOutlineIcon from '@mui/icons-material/HelpOutline'
|
||||
import ImageSearchIcon from '@mui/icons-material/ImageSearch'
|
||||
import { IconButton } from '@mui/material'
|
||||
import Switch from '@mui/material/Switch'
|
||||
import { useRouter } from 'next/router'
|
||||
import MoreIcon from '@material-ui/icons/MoreVert'
|
||||
import MenuItem from '@material-ui/core/MenuItem'
|
||||
import Menu from '@material-ui/core/Menu'
|
||||
import MoreIcon from '@mui/icons-material/MoreVert'
|
||||
import MenuItem from '@mui/material/MenuItem'
|
||||
import Menu from '@mui/material/Menu'
|
||||
import { DataContext } from "./DataContext"
|
||||
|
||||
const useStyles = makeStyles((theme) => ({
|
||||
const useStyles = makeStyles()((theme:any) => ({
|
||||
app_bar: {
|
||||
backgroundColor: "#606ca9"
|
||||
},
|
||||
|
@ -58,7 +59,7 @@ const useStyles = makeStyles((theme) => ({
|
|||
inputInput: {
|
||||
padding: theme.spacing(1, 1, 1, 0),
|
||||
// vertical padding + font size from searchIcon
|
||||
paddingLeft: `calc(1em + ${theme.spacing(4)}px)`,
|
||||
paddingLeft: `calc(1em + ${theme.spacing(4)})`,
|
||||
transition: theme.transitions.create('width'),
|
||||
width: '100%',
|
||||
[theme.breakpoints.up('md')]: {
|
||||
|
@ -90,12 +91,12 @@ const useStyles = makeStyles((theme) => ({
|
|||
display: 'none',
|
||||
}
|
||||
}
|
||||
}))
|
||||
}));
|
||||
|
||||
|
||||
function Search(props: { semanticModeChecked: boolean }) {
|
||||
const placeholders = ["tag1&&(tag2||tag3)", "a picture of a winter forest"]
|
||||
const classes = useStyles()
|
||||
const { classes } = useStyles()
|
||||
const router = useRouter()
|
||||
const [tags, setTags] = useState(router.query.q || '')
|
||||
const searchPlaceholer = placeholders[Number(router.query.semantic || Number(props.semanticModeChecked))]
|
||||
|
@ -113,7 +114,7 @@ function Search(props: { semanticModeChecked: boolean }) {
|
|||
<InputBase
|
||||
placeholder={searchPlaceholer}
|
||||
onChange={(e) => setTags(e.target.value)}
|
||||
onKeyPress={(e) => handleKeyPress(e)}
|
||||
onKeyPress={(e: KeyboardEvent<HTMLDivElement>) => handleKeyPress(e)}
|
||||
classes={{
|
||||
root: classes.inputRoot,
|
||||
input: classes.inputInput,
|
||||
|
@ -127,7 +128,7 @@ function Search(props: { semanticModeChecked: boolean }) {
|
|||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
function MobileMenu(props: any) {
|
||||
const classes = useStyles()
|
||||
const { classes } = useStyles()
|
||||
return (
|
||||
<Menu
|
||||
anchorEl={props.mobileMoreAnchorEl}
|
||||
|
@ -165,7 +166,7 @@ function MobileMenu(props: any) {
|
|||
|
||||
export default function DenseAppBar() {
|
||||
const dataContext = useContext(DataContext)
|
||||
const classes = useStyles()
|
||||
const { classes } = useStyles()
|
||||
const router = useRouter()
|
||||
const mobileMenuId = 'menu-mobile'
|
||||
const [mobileMoreAnchorEl, setMobileMoreAnchorEl] = useState<Element | null>(null)
|
||||
|
@ -200,10 +201,20 @@ export default function DenseAppBar() {
|
|||
<Switch color="secondary" checked={semanticModeChecked} onChange={toggleSemanticModeChecked} />
|
||||
<span>semantic<sub className={classes.sub}>beta</sub></span>
|
||||
</div>
|
||||
<IconButton component={Link} color="inherit" aria-label="search_syntax" href={`${process.env.domain}/search_syntax`}>
|
||||
<IconButton
|
||||
component={Link}
|
||||
color="inherit"
|
||||
aria-label="search_syntax"
|
||||
href={`${process.env.domain}/search_syntax`}
|
||||
size="large">
|
||||
<HelpOutlineIcon />
|
||||
</IconButton>
|
||||
<IconButton component={Link} color="inherit" aria-label="reverse_search" href={`${process.env.domain}/reverse_search`}>
|
||||
<IconButton
|
||||
component={Link}
|
||||
color="inherit"
|
||||
aria-label="reverse_search"
|
||||
href={`${process.env.domain}/reverse_search`}
|
||||
size="large">
|
||||
<ImageSearchIcon />
|
||||
</IconButton>
|
||||
</div>
|
||||
|
@ -214,7 +225,7 @@ export default function DenseAppBar() {
|
|||
aria-haspopup="true"
|
||||
onClick={handleMobileMenuOpen}
|
||||
color="inherit"
|
||||
>
|
||||
size="large">
|
||||
<MoreIcon />
|
||||
</IconButton>
|
||||
</div>
|
||||
|
@ -222,5 +233,5 @@ export default function DenseAppBar() {
|
|||
</AppBar>
|
||||
<MobileMenu {...{ dataContext, semanticModeChecked, mobileMoreAnchorEl, isMobileMenuOpen, handleMobileMenuClose, toggleSemanticModeChecked }} />
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
|
@ -1,14 +1,14 @@
|
|||
import { makeStyles } from '@material-ui/core/styles'
|
||||
import { makeStyles } from 'tss-react/mui';
|
||||
import Link from './Link'
|
||||
const useStyles = makeStyles(() => ({
|
||||
const useStyles = makeStyles()(() => ({
|
||||
footer: {
|
||||
display: "flex",
|
||||
justifyContent: "center"
|
||||
}
|
||||
}))
|
||||
}));
|
||||
|
||||
export default function Footer() {
|
||||
const classes = useStyles()
|
||||
const { classes } = useStyles()
|
||||
return (
|
||||
<div>
|
||||
<div className={classes.footer}>
|
|
@ -3,7 +3,7 @@ import PhotoInterface from "./../types/photo"
|
|||
import Gallery from "react-photo-gallery"
|
||||
import { DataContext } from "./DataContext"
|
||||
import Photo from './Photo'
|
||||
import CircularProgress from '@material-ui/core/CircularProgress'
|
||||
import CircularProgress from '@mui/material/CircularProgress'
|
||||
|
||||
export default function GalleryWrapper(props: { photos: PhotoInterface[] }) {
|
||||
const [photos, setPhotos] = useState<PhotoInterface[]>([])
|
||||
|
@ -23,8 +23,8 @@ export default function GalleryWrapper(props: { photos: PhotoInterface[] }) {
|
|||
} else {
|
||||
setPhotos(props.photos)
|
||||
}
|
||||
setShowLoading(false)
|
||||
}
|
||||
setShowLoading(false)
|
||||
}, [dataContext])
|
||||
|
||||
return (
|
|
@ -3,7 +3,7 @@
|
|||
import clsx from 'clsx'
|
||||
import { useRouter } from 'next/router'
|
||||
import NextLink, { LinkProps as NextLinkProps } from 'next/link'
|
||||
import MuiLink, { LinkProps as MuiLinkProps } from '@material-ui/core/Link'
|
||||
import MuiLink, { LinkProps as MuiLinkProps } from '@mui/material/Link'
|
||||
import { forwardRef } from 'react'
|
||||
|
||||
type NextComposedProps = Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, 'href'> &
|
|
@ -1,5 +1,5 @@
|
|||
import { createTheme } from '@material-ui/core/styles'
|
||||
import { red } from '@material-ui/core/colors'
|
||||
import { createTheme } from '@mui/material/styles'
|
||||
import { red } from '@mui/material/colors'
|
||||
|
||||
// Create a theme instance.
|
||||
const theme = createTheme({
|
|
@ -10,7 +10,7 @@ const server_config = {
|
|||
GITHUB_REDIRECT_URI: "http://localhost/auth/github/callback",
|
||||
gmail_user: "auth.test.reg.email@gmail.com",
|
||||
gmail_password: "sbuLBh9rAV8XD2",
|
||||
mongodb_url: "mongodb://localhost/",
|
||||
mongodb_url: "mongodb://127.0.0.1/",
|
||||
server_port: "80",
|
||||
session_secret: "ghuieorifigyfuu9u3i45jtr73490548t7ht",
|
||||
root_path: path.join(__dirname, "..", ".."),
|
|
@ -0,0 +1,32 @@
|
|||
import { EmotionCache } from "@emotion/react";
|
||||
import { CacheProvider } from '@emotion/react';
|
||||
import createCache from "@emotion/cache"
|
||||
import { ThemeProvider } from "@mui/material/styles"
|
||||
import CssBaseline from "@mui/material/CssBaseline"
|
||||
import theme from '../components/theme'
|
||||
import { useEffect } from "react";
|
||||
import { DataContextProvider } from "../components/DataContext"
|
||||
import { AppProps } from 'next/app'
|
||||
import "../components/styles.css"
|
||||
|
||||
let muiCache: EmotionCache | undefined = undefined;
|
||||
|
||||
export const createMuiCache = () => muiCache = createCache({ "key": "mui", "prepend": true })
|
||||
|
||||
export default function App({ Component, pageProps }: AppProps) {
|
||||
useEffect(() => {
|
||||
if (typeof window !== "undefined" && localStorage.getItem("useIPFS") === null) {
|
||||
localStorage.setItem('useIPFS', 'false')
|
||||
}
|
||||
}, [])
|
||||
return (
|
||||
<CacheProvider value={muiCache ?? createMuiCache()}>
|
||||
<ThemeProvider theme={theme}>
|
||||
<CssBaseline />
|
||||
<DataContextProvider>
|
||||
<Component {...pageProps} />
|
||||
</DataContextProvider>
|
||||
</ThemeProvider>
|
||||
</CacheProvider>
|
||||
)
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
import { withEmotionCache } from "tss-react/nextJs"
|
||||
import { createMuiCache } from "./_app"
|
||||
import Document, { Html, Head, Main, NextScript } from 'next/document'
|
||||
import theme from '../components/theme'
|
||||
|
||||
|
||||
class MyDocument extends Document {
|
||||
render() {
|
||||
return (
|
||||
<Html lang="en">
|
||||
<Head>
|
||||
{/* PWA primary color */}
|
||||
<meta name="theme-color" content={theme.palette.primary.main} />
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap" />
|
||||
</Head>
|
||||
<body>
|
||||
<Main />
|
||||
<NextScript />
|
||||
<script defer src={`https://www.google.com/recaptcha/api.js?render=${process.env.recaptcha_site_key}`}></script>
|
||||
</body>
|
||||
</Html>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default withEmotionCache({
|
||||
//If you have a custom document pass it instead
|
||||
"Document": MyDocument,
|
||||
//Every emotion cache used in the app should be provided.
|
||||
//Caches for MUI should use "prepend": true.
|
||||
"getCaches": ()=> [ createMuiCache() ]
|
||||
});
|
|
@ -1,6 +1,6 @@
|
|||
import Container from '@material-ui/core/Container'
|
||||
import Typography from '@material-ui/core/Typography'
|
||||
import Box from '@material-ui/core/Box'
|
||||
import Container from '@mui/material/Container'
|
||||
import Typography from '@mui/material/Typography'
|
||||
import Box from '@mui/material/Box'
|
||||
import AppBar from '../components/AppBar'
|
||||
|
||||
export default function About() {
|
|
@ -1,23 +1,23 @@
|
|||
import AppBar from '../components/AppBar'
|
||||
import db_ops from '../server/helpers/db_ops'
|
||||
import Button from '@material-ui/core/Button'
|
||||
import Button from '@mui/material/Button'
|
||||
import axios from 'axios'
|
||||
import TextField from '@material-ui/core/TextField'
|
||||
import Backdrop from '@material-ui/core/Backdrop'
|
||||
import CircularProgress from '@material-ui/core/CircularProgress'
|
||||
import TextField from '@mui/material/TextField'
|
||||
import Backdrop from '@mui/material/Backdrop'
|
||||
import CircularProgress from '@mui/material/CircularProgress'
|
||||
import { GetServerSideProps } from 'next'
|
||||
import { makeStyles } from '@material-ui/core/styles'
|
||||
import { useState } from 'react'
|
||||
import { makeStyles } from 'tss-react/mui';
|
||||
import { KeyboardEvent, useState } from 'react'
|
||||
|
||||
const useStyles = makeStyles(() => ({
|
||||
const useStyles = makeStyles()(() => ({
|
||||
backdrop: {
|
||||
zIndex: 9999,
|
||||
color: '#fff',
|
||||
},
|
||||
}))
|
||||
}));
|
||||
|
||||
export default function deleteImage() {
|
||||
const classes = useStyles()
|
||||
const { classes } = useStyles()
|
||||
const [open, setOpen] = useState(false)
|
||||
const [imageID, setImageID] = useState(0)
|
||||
const handleKeyPress = (e: React.KeyboardEvent<HTMLDivElement>) => {
|
||||
|
@ -56,8 +56,8 @@ export default function deleteImage() {
|
|||
label=" image id"
|
||||
placeholder="image id"
|
||||
margin="normal"
|
||||
onChange={(e) => setImageID(parseInt(e.target.value) || 0)}
|
||||
onKeyPress={(e) => handleKeyPress(e)}
|
||||
onChange={(e:any) => setImageID(parseInt(e.target.value) || 0)}
|
||||
onKeyPress={(e: KeyboardEvent<HTMLDivElement>) => handleKeyPress(e)}
|
||||
/>
|
||||
<Button onClick={() => { delete_image() }} variant="contained" color="primary" >Delete image</Button>
|
||||
</div>
|
||||
|
@ -65,7 +65,7 @@ export default function deleteImage() {
|
|||
}
|
||||
|
||||
export const getServerSideProps: GetServerSideProps = async (context) => {
|
||||
if (context.req?.session?.authed && context.req?.session?.user_id) {
|
||||
if (context.req?.session?.user_id) {
|
||||
const user = await db_ops.activated_user.find_user_by_id(context.req.session.user_id)
|
||||
if (user && user.isAdmin) {
|
||||
return {
|
|
@ -1,7 +1,7 @@
|
|||
import AppBar from '../../components/AppBar'
|
||||
import db_ops from '../../server/helpers/db_ops'
|
||||
import Head from 'next/head'
|
||||
import Button from '@material-ui/core/Button'
|
||||
import Button from '@mui/material/Button'
|
||||
import axios from 'axios'
|
||||
import { useEffect } from 'react'
|
||||
import { GetServerSideProps } from 'next'
|
||||
|
@ -42,7 +42,7 @@ export default function Image(props: any) {
|
|||
}
|
||||
|
||||
export const getServerSideProps: GetServerSideProps = async (context) => {
|
||||
if (context.req?.session?.authed && context.req?.session?.user_id) {
|
||||
if (context.req?.session?.user_id) {
|
||||
const user = await db_ops.activated_user.find_user_by_id(context.req?.session?.user_id)
|
||||
if (typeof context.params?.id === "string" && user && user.isAdmin) {
|
||||
const img = await db_ops.image_ops.find_image_by_id(parseInt(context.params.id))
|
|
@ -1,19 +1,19 @@
|
|||
import AppBar from '../../components/AppBar'
|
||||
import { DataContext } from "../../components/DataContext"
|
||||
import { makeStyles } from '@material-ui/core/styles'
|
||||
import Paper from '@material-ui/core/Paper'
|
||||
import Grid from '@material-ui/core/Grid'
|
||||
import LabelIcon from '@material-ui/icons/Label'
|
||||
import CalendarTodayIcon from '@material-ui/icons/CalendarToday'
|
||||
import AspectRatioIcon from '@material-ui/icons/AspectRatio'
|
||||
import LinkIcon from '@material-ui/icons/Link'
|
||||
import { makeStyles } from 'tss-react/mui';
|
||||
import Paper from '@mui/material/Paper'
|
||||
import Grid from '@mui/material/Grid'
|
||||
import LabelIcon from '@mui/icons-material/Label'
|
||||
import CalendarTodayIcon from '@mui/icons-material/CalendarToday'
|
||||
import AspectRatioIcon from '@mui/icons-material/AspectRatio'
|
||||
import LinkIcon from '@mui/icons-material/Link'
|
||||
import { GetServerSideProps } from 'next'
|
||||
import db_ops from '../../server/helpers/db_ops'
|
||||
import CreateIcon from '@material-ui/icons/Create'
|
||||
import Chip from '@material-ui/core/Chip'
|
||||
import CreateIcon from '@mui/icons-material/Create'
|
||||
import Chip from '@mui/material/Chip'
|
||||
import { useContext, useEffect, useState } from 'react'
|
||||
|
||||
const useStyles = makeStyles((theme) => ({
|
||||
const useStyles = makeStyles()((theme:any) => ({
|
||||
root: {
|
||||
flexGrow: 1,
|
||||
},
|
||||
|
@ -37,7 +37,7 @@ const useStyles = makeStyles((theme) => ({
|
|||
textAlign: 'center',
|
||||
color: theme.palette.text.secondary,
|
||||
},
|
||||
}))
|
||||
}));
|
||||
|
||||
interface ImageProps {
|
||||
filename: string,
|
||||
|
@ -54,7 +54,7 @@ interface ImageProps {
|
|||
// upscaled: string,
|
||||
}
|
||||
export default function Image(props: ImageProps) {
|
||||
const classes = useStyles()
|
||||
const { classes } = useStyles()
|
||||
const dataContext = useContext(DataContext)
|
||||
const [photoSrc, setPhotoSrc] = useState("")
|
||||
useEffect(() => {
|
|
@ -1,22 +1,22 @@
|
|||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import { ChangeEvent, Dispatch, SetStateAction, useState } from 'react'
|
||||
import Box from '@material-ui/core/Box'
|
||||
import Box from '@mui/material/Box'
|
||||
import AppBar from '../components/AppBar'
|
||||
import { DropzoneAreaBase } from 'material-ui-dropzone'
|
||||
import Button from '@material-ui/core/Button'
|
||||
import { DropzoneAreaBase } from 'mui-file-dropzone'
|
||||
import Button from '@mui/material/Button'
|
||||
import axios from "axios"
|
||||
import db_ops from '../server/helpers/db_ops'
|
||||
import Backdrop from '@material-ui/core/Backdrop'
|
||||
import CircularProgress from '@material-ui/core/CircularProgress'
|
||||
import { makeStyles } from '@material-ui/core/styles'
|
||||
import TextField from '@material-ui/core/TextField'
|
||||
import Paper from '@material-ui/core/Paper'
|
||||
import Autocomplete, { createFilterOptions } from '@material-ui/lab/Autocomplete'
|
||||
import Chip from '@material-ui/core/Chip'
|
||||
import Backdrop from '@mui/material/Backdrop'
|
||||
import CircularProgress from '@mui/material/CircularProgress'
|
||||
import { makeStyles } from 'tss-react/mui';
|
||||
import TextField from '@mui/material/TextField'
|
||||
import Paper from '@mui/material/Paper'
|
||||
import Autocomplete, { createFilterOptions } from '@mui/material/Autocomplete'
|
||||
import Chip from '@mui/material/Chip'
|
||||
import { GetServerSideProps } from 'next'
|
||||
|
||||
|
||||
const useStyles = makeStyles(() => ({
|
||||
const useStyles = makeStyles()(() => ({
|
||||
backdrop: {
|
||||
zIndex: 9999,
|
||||
color: '#fff',
|
||||
|
@ -41,7 +41,7 @@ const useStyles = makeStyles(() => ({
|
|||
tags_field: {
|
||||
margin: 10
|
||||
}
|
||||
}))
|
||||
}));
|
||||
|
||||
function isValidURL(url: string) {
|
||||
const RegExp = /^(?:(?:(?:https?):)?\/\/)(?:\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-z0-9\u00a1-\uffff][a-z0-9\u00a1-\uffff_-]{0,62})?[a-z0-9\u00a1-\uffff]\.)+(?:[a-z\u00a1-\uffff]{2,}\.?))(?::\d{2,5})?(?:[/?#]\S*)?$/i
|
||||
|
@ -53,7 +53,7 @@ function isValidURL(url: string) {
|
|||
}
|
||||
|
||||
function AutoCompleteTagTextField(props: { all_tags: string[], selectedTags: string[], setSelectedTags: Dispatch<SetStateAction<string[]>> }) {
|
||||
const classes = useStyles()
|
||||
const { classes } = useStyles()
|
||||
const [inputValue, setInputValue] = useState("")
|
||||
const [openTagsAutocomplete, setOpenTagsAutocomplete] = useState(false)
|
||||
const filterOptions = createFilterOptions({
|
||||
|
@ -93,7 +93,7 @@ function AutoCompleteTagTextField(props: { all_tags: string[], selectedTags: str
|
|||
filterSelectedOptions
|
||||
renderTags={(value, getTagProps) =>
|
||||
value.map((option, index) => (
|
||||
<Chip variant="outlined" key={option as string} label={option as string} {...getTagProps({ index })} />
|
||||
<Chip variant="outlined" {...getTagProps({ index })} key={option as string} label={option as string} />
|
||||
))
|
||||
}
|
||||
renderInput={(params) => (
|
||||
|
@ -103,7 +103,7 @@ function AutoCompleteTagTextField(props: { all_tags: string[], selectedTags: str
|
|||
}
|
||||
|
||||
export default function Import(props: { err: boolean, all_tags: string[] }) {
|
||||
const classes = useStyles()
|
||||
const { classes } = useStyles()
|
||||
const [URL, setUrl] = useState("")
|
||||
const [source_URL, setSource_URL] = useState("")
|
||||
const [selectedTags, setSelectedTags] = useState<string[]>([])
|
||||
|
@ -208,7 +208,7 @@ export default function Import(props: { err: boolean, all_tags: string[] }) {
|
|||
<div className={classes.url_div}>
|
||||
<TextField
|
||||
value={source_URL}
|
||||
onChange={(e) => setSource_URL(e.target.value)}
|
||||
onChange={(e:any) => setSource_URL(e.target.value)}
|
||||
type="text"
|
||||
label="Source url"
|
||||
className={classes.url_text_field}
|
||||
|
@ -220,7 +220,7 @@ export default function Import(props: { err: boolean, all_tags: string[] }) {
|
|||
<Paper className={classes.upload_interface} elevation={6}>
|
||||
<h4 style={{ margin: 0, marginBottom: "5px" }}>Image</h4>
|
||||
<div className={classes.fetch_img_div}>
|
||||
<TextField onChange={(e) => setUrl(e.target.value)} value={URL}
|
||||
<TextField onChange={(e:any) => setUrl(e.target.value)} value={URL}
|
||||
className={classes.url_text_field} label="Image url"
|
||||
placeholder="https://somesite.com/image.png" variant="outlined" size="small" />
|
||||
<Button onClick={get_image_by_url} size="small" variant="outlined">Fetch</Button>
|
||||
|
@ -251,7 +251,7 @@ export default function Import(props: { err: boolean, all_tags: string[] }) {
|
|||
)
|
||||
}
|
||||
export const getServerSideProps: GetServerSideProps = async (context) => {
|
||||
if (context.req.session.authed && context.req.session.user_id) {
|
||||
if (context.req?.session?.user_id) {
|
||||
const user = await db_ops.activated_user.find_user_by_id(context.req.session.user_id)
|
||||
if (user?.isAdmin) {
|
||||
const imgs = await db_ops.image_ops.get_all_images()
|
|
@ -1,18 +1,18 @@
|
|||
import { makeStyles } from '@material-ui/core/styles'
|
||||
import { makeStyles } from 'tss-react/mui';
|
||||
import AppBar from '../../components/AppBar'
|
||||
import db_ops from '../../server/helpers/db_ops'
|
||||
import Pagination from '@material-ui/lab/Pagination'
|
||||
import Pagination from '@mui/material/Pagination'
|
||||
import { GetStaticProps, GetStaticPaths } from 'next'
|
||||
import { useRouter } from 'next/router'
|
||||
import Link from '../../components/Link'
|
||||
import Footer from '../../components/Footer'
|
||||
import GalleryWrapper from '../../components/GalleryWrapper'
|
||||
import ErrorPage from 'next/error'
|
||||
import PaginationItem from "@material-ui/lab/PaginationItem/PaginationItem"
|
||||
import PaginationItem from '@mui/material/PaginationItem'
|
||||
import PhotoInterface from '../../types/photo'
|
||||
|
||||
|
||||
const useStyles = makeStyles(() => ({
|
||||
const useStyles = makeStyles()(() => ({
|
||||
flex_center: {
|
||||
display: "flex",
|
||||
justifyContent: 'center'
|
||||
|
@ -23,7 +23,7 @@ const useStyles = makeStyles(() => ({
|
|||
hidden: {
|
||||
visibility: "hidden"
|
||||
}
|
||||
}))
|
||||
}));
|
||||
|
||||
interface LastAddedPageProps {
|
||||
photos: PhotoInterface[],
|
||||
|
@ -34,7 +34,7 @@ interface LastAddedPageProps {
|
|||
|
||||
|
||||
export default function LastAddedPage(props: LastAddedPageProps) {
|
||||
const classes = useStyles()
|
||||
const { classes } = useStyles()
|
||||
const router = useRouter()
|
||||
if (router.isFallback) {
|
||||
return <ErrorPage statusCode={404} />
|
||||
|
@ -80,19 +80,20 @@ export const getStaticProps: GetStaticProps = async (context) => {
|
|||
height: image.height
|
||||
})
|
||||
}
|
||||
return {
|
||||
props: {
|
||||
photos: photos,
|
||||
current_page: page,
|
||||
max_page: Math.ceil(total_num_of_images / images_on_page)
|
||||
},
|
||||
revalidate: 1 * 60 //1 min
|
||||
}
|
||||
}
|
||||
}
|
||||
return {
|
||||
props: { err: true },
|
||||
revalidate: 1 * 60 //1 min
|
||||
return {
|
||||
props: {
|
||||
photos: photos,
|
||||
current_page: page,
|
||||
max_page: Math.ceil(total_num_of_images / images_on_page)
|
||||
},
|
||||
revalidate: 1 * 60 //1 min
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
props: { err: true },
|
||||
revalidate: 1 * 60 //1 min
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,20 +1,20 @@
|
|||
import axios from 'axios'
|
||||
import { makeStyles } from "@material-ui/core/styles"
|
||||
import TextField from '@material-ui/core/TextField'
|
||||
import Card from '@material-ui/core/Card'
|
||||
import CardContent from '@material-ui/core/CardContent'
|
||||
import CardActions from '@material-ui/core/CardActions'
|
||||
import Button from '@material-ui/core/Button'
|
||||
import Box from '@material-ui/core/Box'
|
||||
import { makeStyles } from 'tss-react/mui';
|
||||
import TextField from '@mui/material/TextField'
|
||||
import Card from '@mui/material/Card'
|
||||
import CardContent from '@mui/material/CardContent'
|
||||
import CardActions from '@mui/material/CardActions'
|
||||
import Button from '@mui/material/Button'
|
||||
import Box from '@mui/material/Box'
|
||||
import Link from '../components/Link'
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"
|
||||
import Grid from "@material-ui/core/Grid"
|
||||
import SvgIcon from "@material-ui/core/SvgIcon"
|
||||
import Grid from "@mui/material/Grid"
|
||||
import SvgIcon from "@mui/material/SvgIcon"
|
||||
import { faGoogle, faGithub } from "@fortawesome/free-brands-svg-icons"
|
||||
import { useRouter } from 'next/router'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { KeyboardEvent, useEffect, useState } from 'react'
|
||||
|
||||
const useStyles = makeStyles(theme => ({
|
||||
const useStyles = makeStyles()((theme:any) => ({
|
||||
container: {
|
||||
display: 'flex',
|
||||
flexWrap: 'wrap',
|
||||
|
@ -34,11 +34,11 @@ const useStyles = makeStyles(theme => ({
|
|||
Oauth: {
|
||||
'margin-left': '0px !important'
|
||||
}
|
||||
}))
|
||||
}));
|
||||
|
||||
function LoginForm() {
|
||||
const router = useRouter()
|
||||
const classes = useStyles()
|
||||
const { classes } = useStyles()
|
||||
const [email, setEmail] = useState('')
|
||||
const [password, setPassword] = useState('')
|
||||
const [isButtonDisabled, setIsButtonDisabled] = useState(true)
|
||||
|
@ -102,8 +102,8 @@ function LoginForm() {
|
|||
label="Email"
|
||||
placeholder="Email"
|
||||
margin="normal"
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
onKeyPress={(e) => handleKeyPress(e)}
|
||||
onChange={(e:any) => setEmail(e.target.value)}
|
||||
onKeyPress={(e: KeyboardEvent<HTMLDivElement>) => handleKeyPress(e)}
|
||||
/>
|
||||
<TextField
|
||||
error={error}
|
||||
|
@ -114,8 +114,8 @@ function LoginForm() {
|
|||
placeholder="Password"
|
||||
margin="normal"
|
||||
helperText={helperText}
|
||||
onChange={(e) => setPassword(e.target.value)}
|
||||
onKeyPress={(e) => handleKeyPress(e)}
|
||||
onChange={(e:any) => setPassword(e.target.value)}
|
||||
onKeyPress={(e: KeyboardEvent<HTMLDivElement>) => handleKeyPress(e)}
|
||||
/>
|
||||
<Box display="flex" justifyContent="flex-end">
|
||||
<Button color="primary" component={Link} href="/forgot_pw">
|
||||
|
@ -143,7 +143,7 @@ function LoginForm() {
|
|||
className={classes.Oauth}
|
||||
container
|
||||
direction="row"
|
||||
justify="center"
|
||||
justifyContent="center"
|
||||
spacing={1}
|
||||
alignItems="center"
|
||||
>
|
||||
|
@ -178,7 +178,7 @@ function LoginForm() {
|
|||
</CardActions>
|
||||
</Card>
|
||||
</form>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
export default LoginForm
|
|
@ -1,20 +1,20 @@
|
|||
import Container from '@material-ui/core/Container'
|
||||
import Typography from '@material-ui/core/Typography'
|
||||
import Box from '@material-ui/core/Box'
|
||||
import Container from '@mui/material/Container'
|
||||
import Typography from '@mui/material/Typography'
|
||||
import Box from '@mui/material/Box'
|
||||
import AppBar from '../../components/AppBar'
|
||||
import { makeStyles } from '@material-ui/core/styles'
|
||||
import Paper from '@material-ui/core/Paper'
|
||||
import { makeStyles } from 'tss-react/mui';
|
||||
import Paper from '@mui/material/Paper'
|
||||
|
||||
const useStyles = makeStyles(() => ({
|
||||
const useStyles = makeStyles()(() => ({
|
||||
api_route: {
|
||||
padding: 5,
|
||||
marginTop: 10,
|
||||
width: "fit-content!important"
|
||||
}
|
||||
}))
|
||||
}));
|
||||
|
||||
export default function Api() {
|
||||
const classes = useStyles()
|
||||
const { classes } = useStyles()
|
||||
return (
|
||||
<div>
|
||||
<AppBar />
|
|
@ -1,17 +1,17 @@
|
|||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import { useState } from 'react'
|
||||
import Box from '@material-ui/core/Box'
|
||||
import Box from '@mui/material/Box'
|
||||
import AppBar from '../components/AppBar'
|
||||
import { DropzoneAreaBase } from 'material-ui-dropzone'
|
||||
import Button from '@material-ui/core/Button'
|
||||
import { DropzoneAreaBase } from 'mui-file-dropzone'
|
||||
import Button from '@mui/material/Button'
|
||||
import axios from "axios"
|
||||
import { useRouter } from 'next/router'
|
||||
import Backdrop from '@material-ui/core/Backdrop'
|
||||
import CircularProgress from '@material-ui/core/CircularProgress'
|
||||
import { makeStyles } from '@material-ui/core/styles'
|
||||
import TextField from '@material-ui/core/TextField'
|
||||
import Backdrop from '@mui/material/Backdrop'
|
||||
import CircularProgress from '@mui/material/CircularProgress'
|
||||
import { makeStyles } from 'tss-react/mui';
|
||||
import TextField from '@mui/material/TextField'
|
||||
|
||||
const useStyles = makeStyles(() => ({
|
||||
const useStyles = makeStyles()(() => ({
|
||||
backdrop: {
|
||||
zIndex: 9999,
|
||||
color: '#fff',
|
||||
|
@ -25,7 +25,7 @@ const useStyles = makeStyles(() => ({
|
|||
width: "300px",
|
||||
marginRight: "10px"
|
||||
}
|
||||
}))
|
||||
}));
|
||||
function isValidURL(url: string) {
|
||||
const RegExp = /^(?:(?:(?:https?):)?\/\/)(?:\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-z0-9\u00a1-\uffff][a-z0-9\u00a1-\uffff_-]{0,62})?[a-z0-9\u00a1-\uffff]\.)+(?:[a-z\u00a1-\uffff]{2,}\.?))(?::\d{2,5})?(?:[/?#]\S*)?$/i
|
||||
if (RegExp.test(url)) {
|
||||
|
@ -36,7 +36,7 @@ function isValidURL(url: string) {
|
|||
}
|
||||
|
||||
export default function ReverseSearch() {
|
||||
const classes = useStyles()
|
||||
const { classes } = useStyles()
|
||||
const router = useRouter()
|
||||
const [URL, setUrl] = useState("")
|
||||
const [fileObjects, setFileObjects] = useState([])
|
||||
|
@ -143,7 +143,7 @@ export default function ReverseSearch() {
|
|||
</Backdrop>
|
||||
<Box my={4}>
|
||||
<div className={classes.url_div}>
|
||||
<TextField onChange={(e) => setUrl(e.target.value)} value={URL}
|
||||
<TextField onChange={(e:any) => setUrl(e.target.value)} value={URL}
|
||||
className={classes.url_text_field} label="url"
|
||||
placeholder="https://somesite.com/image.png" variant="outlined" size="small" />
|
||||
<Button onClick={get_image_by_url} size="small" variant="outlined">Fetch</Button>
|
|
@ -1,21 +1,21 @@
|
|||
import { makeStyles } from '@material-ui/core/styles'
|
||||
import { makeStyles } from 'tss-react/mui';
|
||||
import AppBar from '../components/AppBar'
|
||||
import db_ops from '../server/helpers/db_ops'
|
||||
import Pagination from '@material-ui/lab/Pagination'
|
||||
import Pagination from '@mui/material/Pagination'
|
||||
import Link from '../components/Link'
|
||||
import GalleryWrapper from '../components/GalleryWrapper'
|
||||
import PaginationItem from "@material-ui/lab/PaginationItem/PaginationItem"
|
||||
import PaginationItem from '@mui/material/PaginationItem'
|
||||
import PhotoInterface from '../types/photo'
|
||||
import build_ast from "../components/parse"
|
||||
import image_ops from "../server/helpers/image_ops"
|
||||
import { GetServerSideProps } from 'next'
|
||||
|
||||
const useStyles = makeStyles(() => ({
|
||||
const useStyles = makeStyles()(() => ({
|
||||
pagination: {
|
||||
display: "flex",
|
||||
justifyContent: 'center'
|
||||
}
|
||||
}))
|
||||
}));
|
||||
|
||||
interface SearchProps {
|
||||
err: boolean,
|
||||
|
@ -28,7 +28,7 @@ interface SearchProps {
|
|||
}
|
||||
|
||||
export default function Search(props: SearchProps) {
|
||||
const classes = useStyles()
|
||||
const { classes } = useStyles()
|
||||
if (props.err) {
|
||||
return (
|
||||
<div>
|
|
@ -1,6 +1,6 @@
|
|||
import Container from '@material-ui/core/Container'
|
||||
import Typography from '@material-ui/core/Typography'
|
||||
import Box from '@material-ui/core/Box'
|
||||
import Container from '@mui/material/Container'
|
||||
import Typography from '@mui/material/Typography'
|
||||
import Box from '@mui/material/Box'
|
||||
import AppBar from '../components/AppBar'
|
||||
import Link from './../components/Link'
|
||||
|
|
@ -1,14 +1,14 @@
|
|||
import { useEffect, useState } from 'react'
|
||||
import { KeyboardEvent, useEffect, useState } from 'react'
|
||||
import axios from 'axios'
|
||||
import { makeStyles } from "@material-ui/core/styles"
|
||||
import TextField from '@material-ui/core/TextField'
|
||||
import Card from '@material-ui/core/Card'
|
||||
import CardContent from '@material-ui/core/CardContent'
|
||||
import CardActions from '@material-ui/core/CardActions'
|
||||
import Button from '@material-ui/core/Button'
|
||||
import { makeStyles } from 'tss-react/mui';
|
||||
import TextField from '@mui/material/TextField'
|
||||
import Card from '@mui/material/Card'
|
||||
import CardContent from '@mui/material/CardContent'
|
||||
import CardActions from '@mui/material/CardActions'
|
||||
import Button from '@mui/material/Button'
|
||||
|
||||
|
||||
const useStyles = makeStyles(theme => ({
|
||||
const useStyles = makeStyles()((theme:any) => ({
|
||||
container: {
|
||||
display: 'flex',
|
||||
flexWrap: 'wrap',
|
||||
|
@ -26,10 +26,10 @@ const useStyles = makeStyles(theme => ({
|
|||
CardActions: {
|
||||
'flex-wrap': 'wrap'
|
||||
}
|
||||
}))
|
||||
}));
|
||||
|
||||
function SignUpForm() {
|
||||
const classes = useStyles()
|
||||
const { classes } = useStyles()
|
||||
const [email, setEmail] = useState('')
|
||||
const [password, setPassword] = useState('')
|
||||
const [password2, setPassword2] = useState('')
|
||||
|
@ -112,8 +112,8 @@ function SignUpForm() {
|
|||
label="Email"
|
||||
placeholder="Email"
|
||||
margin="normal"
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
onKeyPress={(e) => handleKeyPress(e)}
|
||||
onChange={(e:any) => setEmail(e.target.value)}
|
||||
onKeyPress={(e: KeyboardEvent<HTMLDivElement>) => handleKeyPress(e)}
|
||||
/>
|
||||
<TextField
|
||||
error={error}
|
||||
|
@ -123,8 +123,8 @@ function SignUpForm() {
|
|||
label="Password"
|
||||
placeholder="Password"
|
||||
margin="normal"
|
||||
onChange={(e) => setPassword(e.target.value)}
|
||||
onKeyPress={(e) => handleKeyPress(e)}
|
||||
onChange={(e:any) => setPassword(e.target.value)}
|
||||
onKeyPress={(e: KeyboardEvent<HTMLDivElement>) => handleKeyPress(e)}
|
||||
/>
|
||||
<TextField
|
||||
error={error}
|
||||
|
@ -135,8 +135,8 @@ function SignUpForm() {
|
|||
placeholder="Repeat password"
|
||||
margin="normal"
|
||||
helperText={helperText}
|
||||
onChange={(e) => setPassword2(e.target.value)}
|
||||
onKeyPress={(e) => handleKeyPress(e)}
|
||||
onChange={(e:any) => setPassword2(e.target.value)}
|
||||
onKeyPress={(e:any) => handleKeyPress(e)}
|
||||
/>
|
||||
</div>
|
||||
</CardContent>
|
|
@ -1,15 +1,15 @@
|
|||
import db_ops from '../server/helpers/db_ops'
|
||||
import { GetStaticProps } from 'next'
|
||||
import { makeStyles } from '@material-ui/core/styles'
|
||||
import Chip from '@material-ui/core/Chip'
|
||||
import { Typography } from '@material-ui/core'
|
||||
import { makeStyles } from 'tss-react/mui';
|
||||
import Chip from '@mui/material/Chip'
|
||||
import { Typography } from '@mui/material'
|
||||
import AppBar from '../components/AppBar'
|
||||
|
||||
const useStyles = makeStyles(() => ({
|
||||
const useStyles = makeStyles()(() => ({
|
||||
chip: {
|
||||
margin: 5
|
||||
}
|
||||
}))
|
||||
}));
|
||||
|
||||
interface Tags {
|
||||
_id: string,
|
||||
|
@ -17,7 +17,7 @@ interface Tags {
|
|||
}
|
||||
|
||||
export default function Tags(props: { tags: Tags[] }) {
|
||||
const classes = useStyles()
|
||||
const { classes } = useStyles()
|
||||
// const Seasons = ["winter", "spring", "summer", "autumn"]
|
||||
const Orientation = ["horizontal", "vertical", "square"]
|
||||
const Tags = []
|
|
@ -2,7 +2,6 @@
|
|||
import bcrypt from "bcrypt"
|
||||
import crypto from "crypto"
|
||||
import db_ops from "./db_ops"
|
||||
const cryptoAsync = require('@ronomon/crypto-async');
|
||||
const SALTROUNDS = 10
|
||||
|
||||
async function generate_activation_token(): Promise<string> {
|
||||
|
@ -42,16 +41,16 @@ async function generate_password_recovery_token(): Promise<string> {
|
|||
}
|
||||
|
||||
async function hash_password(password: string): Promise<string> {
|
||||
const hashed_pass = bcrypt.hash(password, SALTROUNDS);
|
||||
const hashed_pass = bcrypt.hash(password, SALTROUNDS)
|
||||
return hashed_pass
|
||||
}
|
||||
|
||||
async function check_password(password: string, hash: string): Promise<boolean> {
|
||||
const result = bcrypt.compare(password, hash);
|
||||
const result = bcrypt.compare(password, hash)
|
||||
return result
|
||||
}
|
||||
async function image_buffer_sha256_hash(image_buffer:Buffer){
|
||||
return cryptoAsync.hash("sha256",image_buffer).toString('hex')
|
||||
function image_buffer_sha256_hash(image_buffer: Buffer) {
|
||||
return crypto.createHash('sha256').update(image_buffer).digest('hex')
|
||||
}
|
||||
|
||||
export default {generate_activation_token,generate_password_recovery_token,hash_password,check_password,image_buffer_sha256_hash}
|
|
@ -9,7 +9,7 @@ import { unlink as fs_unlink_callback } from 'fs'
|
|||
import { promisify } from 'util'
|
||||
import { exec } from 'child_process'
|
||||
const exec_async = promisify(exec);
|
||||
import FileType from 'file-type'
|
||||
import {fromBuffer} from 'file-type'
|
||||
import path from "path"
|
||||
const PATH_TO_IMAGES = path.join(config.root_path, 'public', 'images')
|
||||
const PATH_TO_THUMBNAILS = path.join(config.root_path, 'public', 'thumbnails')
|
||||
|
@ -186,7 +186,7 @@ async function parse_author(tags: string[]) {
|
|||
}
|
||||
|
||||
async function import_image(image_buffer: Buffer, tags: string[] = [], source_url = "") {
|
||||
const sha256_hash = await crypto_ops.image_buffer_sha256_hash(image_buffer)
|
||||
const sha256_hash = crypto_ops.image_buffer_sha256_hash(image_buffer)
|
||||
const found_img = await db_ops.image_ops.find_image_by_sha256(sha256_hash)
|
||||
if (found_img) {
|
||||
return `Image with the same sha256 is already in the db. Image id = ${found_img.id} `
|
||||
|
@ -198,7 +198,7 @@ async function import_image(image_buffer: Buffer, tags: string[] = [], source_ur
|
|||
}
|
||||
}
|
||||
try {
|
||||
const mime_type = (await FileType.fromBuffer(image_buffer))?.mime
|
||||
const mime_type = (await fromBuffer(image_buffer))?.mime
|
||||
let file_ext = ""
|
||||
switch (mime_type) {
|
||||
case "image/png":
|
||||
|
@ -271,7 +271,7 @@ async function import_image_without_check(image_buffer: Buffer, tags: string[] =
|
|||
return `Image with the same sha256 is already in the db. Image id = ${found_img.id} `
|
||||
}
|
||||
try {
|
||||
const mime_type = (await FileType.fromBuffer(image_buffer))?.mime
|
||||
const mime_type = (await fromBuffer(image_buffer))?.mime
|
||||
let file_ext = ""
|
||||
switch (mime_type) {
|
||||
case "image/png":
|
||||
|
@ -295,7 +295,7 @@ async function import_image_without_check(image_buffer: Buffer, tags: string[] =
|
|||
if (config.optimize_images) {
|
||||
image_buffer = await optimize_image(file_ext, image_buffer)
|
||||
}
|
||||
|
||||
|
||||
tags.push(orientation)
|
||||
|
||||
const new_image_id = (await db_ops.image_ops.get_max_image_id()) + 1
|
||||
|
@ -308,7 +308,7 @@ async function import_image_without_check(image_buffer: Buffer, tags: string[] =
|
|||
}
|
||||
await fs.writeFile(`${PATH_TO_THUMBNAILS}/${new_image_id}.jpg`, thumbnail_buffer, 'binary')
|
||||
// console.log(`OK. New image_id: ${new_image_id}`)
|
||||
return {image_id:new_image_id, new_file_name:`${new_image_id}.${file_ext}`}
|
||||
return { image_id: new_image_id, new_file_name: `${new_image_id}.${file_ext}` }
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
|
@ -1,14 +1,21 @@
|
|||
import fastify, { FastifyInstance } from 'fastify'
|
||||
import formBodyPlugin from 'fastify-formbody'
|
||||
import fastifyCookie from 'fastify-cookie'
|
||||
import formBodyPlugin from '@fastify/formbody'
|
||||
import fastifyCookie from '@fastify/cookie'
|
||||
import config from "./../config/config"
|
||||
import MongoStore from 'connect-mongo'
|
||||
import fastifyMultipart from 'fastify-multipart'
|
||||
import fastifyCors from 'fastify-cors'
|
||||
import fastifySession from 'fastify-session';
|
||||
import fastifyMultipart from '@fastify/multipart'
|
||||
import fastifyCors from '@fastify/cors'
|
||||
import fastifySession from '@fastify/session'
|
||||
import fastifyRecaptcha from 'fastify-recaptcha'
|
||||
import next from 'next'
|
||||
|
||||
|
||||
declare module "fastify" {
|
||||
interface Session {
|
||||
user_id?: string
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////INIT DEFAULT FOLDERS
|
||||
import fs from 'fs'
|
||||
import path from "path"
|
||||
|
@ -40,7 +47,7 @@ import google_oauth_callback from './routes/google_oauth_callback';
|
|||
import signup from './routes/signup';
|
||||
import login from './routes/login';
|
||||
import change_password from './routes/change_password';
|
||||
import forgot_password from './routes/forgot_password';
|
||||
// import forgot_password from './routes/forgot_password';
|
||||
import activate_account_email from './routes/activate_account_email';
|
||||
import update_image_data from './routes/update_image_data'
|
||||
import delete_image from './routes/delete_image'
|
||||
|
@ -53,7 +60,13 @@ import get_image_info from './routes/public_api/get_image_info'
|
|||
|
||||
|
||||
function main() {
|
||||
const server = fastify({ trustProxy: true })
|
||||
const server = fastify({ trustProxy: true})
|
||||
|
||||
server.register(fastifyCors, {
|
||||
"origin": config.domain,
|
||||
"methods": "GET,HEAD,PUT,PATCH,POST,DELETE"
|
||||
})
|
||||
|
||||
server.register(formBodyPlugin)
|
||||
server.register(fastifyCookie);
|
||||
server.register(fastifySession, {
|
||||
|
@ -73,7 +86,6 @@ function main() {
|
|||
|
||||
server.register(fastifyMultipart, {
|
||||
attachFieldsToBody: true,
|
||||
sharedSchemaId: '#mySharedSchema',
|
||||
limits: {
|
||||
fieldNameSize: 100, // Max field name size in bytes
|
||||
fieldSize: 1000, // Max field value size in bytes
|
||||
|
@ -84,11 +96,6 @@ function main() {
|
|||
}
|
||||
})
|
||||
|
||||
server.register(fastifyCors, {
|
||||
"origin": config.domain,
|
||||
"methods": "GET,HEAD,PUT,PATCH,POST,DELETE",
|
||||
})
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
server.addHook<{ Body: { "g-recaptcha-response": any } }>('preValidation', async (request) => {
|
||||
if (request.body && typeof request.body["g-recaptcha-response"]?.value === "string") {
|
||||
|
@ -120,7 +127,7 @@ function main() {
|
|||
server.post('/login', login)
|
||||
server.post('/signup', signup)
|
||||
server.post('/change_pw', change_password)
|
||||
server.post('/forgot_pw', forgot_password)
|
||||
// server.post('/forgot_pw', forgot_password)
|
||||
server.get('/activate', activate_account_email)
|
||||
///////////////////////////////////////////////////////////////
|
||||
|
||||
|
@ -137,7 +144,7 @@ function main() {
|
|||
|
||||
server.get('/logout', (req, res) => {
|
||||
if (req.session) {
|
||||
req.destroySession(function (err) {
|
||||
req.session.destroy(function (err) {
|
||||
if (err) {
|
||||
console.log(err)
|
||||
}
|
||||
|
@ -146,13 +153,19 @@ function main() {
|
|||
}
|
||||
})
|
||||
|
||||
server.all('/*', (req, reply) => {
|
||||
server.get('/*', async (req, reply) => {
|
||||
req.raw.session = req.session
|
||||
return handle(req.raw, reply.raw).then(() => {
|
||||
reply.sent = true
|
||||
})
|
||||
await handle(req.raw, reply.raw)
|
||||
reply.hijack()
|
||||
})
|
||||
server.listen(port, "127.0.0.1", function (err, address) {
|
||||
|
||||
server.post('/*', async (req, reply) => {
|
||||
req.raw.session = req.session
|
||||
await handle(req.raw, reply.raw)
|
||||
reply.hijack()
|
||||
})
|
||||
|
||||
server.listen({port:port, host:"127.0.0.1"}, function (err, address) {
|
||||
if (err) {
|
||||
console.error(err)
|
||||
process.exit(1)
|
|
@ -42,7 +42,6 @@ async function github_oauth_callback(req: FastifyRequest<{ Querystring: FromSche
|
|||
} else {
|
||||
req.session.user_id = user.id;
|
||||
}
|
||||
req.session.authed = true;
|
||||
res.redirect(config.domain)
|
||||
} catch (e) {
|
||||
console.log(e)
|
|
@ -38,7 +38,6 @@ async function google_oauth_callback(req: FastifyRequest<{ Querystring: FromSche
|
|||
} else {
|
||||
req.session.user_id = user.id;
|
||||
}
|
||||
req.session.authed = true;
|
||||
res.redirect(config.domain)
|
||||
} catch (e) {
|
||||
console.log(e)
|
|
@ -5,7 +5,15 @@ import { FromSchema } from "json-schema-to-ts";
|
|||
const body_schema_import_image = {
|
||||
type: 'object',
|
||||
properties: {
|
||||
image: { $ref: '#mySharedSchema' },
|
||||
image: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
encoding: { type: 'string' },
|
||||
filename: { type: 'string' },
|
||||
limit: { type: 'boolean' },
|
||||
mimetype: { type: 'string' }
|
||||
}
|
||||
},
|
||||
source_url: {
|
||||
type: "object",
|
||||
properties: {
|
||||
|
@ -40,7 +48,11 @@ async function import_image(req: FastifyRequest<{ Body: FromSchema<typeof body_s
|
|||
}
|
||||
let image_buffer: Buffer;
|
||||
try {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
image_buffer = await (req as any).body.image.toBuffer()
|
||||
if (!Buffer.isBuffer(image_buffer)){
|
||||
throw "not a buffer"
|
||||
}
|
||||
} catch (err) {
|
||||
return res.status(500).send()
|
||||
}
|
||||
|
@ -56,7 +68,7 @@ async function import_image(req: FastifyRequest<{ Body: FromSchema<typeof body_s
|
|||
}
|
||||
|
||||
if (req.session?.user_id) {
|
||||
const user = await db_ops.activated_user.find_user_by_id(req.session?.user_id)
|
||||
const user = await db_ops.activated_user.find_user_by_id(req.session.user_id)
|
||||
if (user && user.isAdmin) {
|
||||
const results = await image_ops.import_image(image_buffer, tags, source_url)
|
||||
if (results) {
|
|
@ -27,7 +27,6 @@ async function login(req: FastifyRequest<{ Body: FromSchema<typeof body_schema_l
|
|||
const match = await crypto_ops.check_password(password, user.password||"");
|
||||
if (match) {
|
||||
if (user.activated === true) {
|
||||
req.session.authed = true;
|
||||
req.session.user_id = user.id;
|
||||
res.send({
|
||||
message: "success"
|
|
@ -4,9 +4,17 @@ import { FastifyRequest, FastifyReply } from "fastify"
|
|||
|
||||
const body_schema_reverse_search = {
|
||||
type: 'object',
|
||||
image: { $ref: '#mySharedSchema' },
|
||||
properties: {
|
||||
"g-recaptcha-response": { type: 'string' },
|
||||
image: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
encoding: { type: 'string' },
|
||||
filename: { type: 'string' },
|
||||
limit: { type: 'boolean' },
|
||||
mimetype: { type: 'string' }
|
||||
}
|
||||
}
|
||||
},
|
||||
required: ['image', 'g-recaptcha-response'],
|
||||
} as const;
|
||||
|
@ -14,7 +22,11 @@ const body_schema_reverse_search = {
|
|||
async function reverse_search(req: FastifyRequest, res: FastifyReply) {
|
||||
let image_buffer: Buffer;
|
||||
try {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
image_buffer = await (req as any).body.image.toBuffer()
|
||||
if (!Buffer.isBuffer(image_buffer)){
|
||||
throw "not a buffer"
|
||||
}
|
||||
} catch (err) {
|
||||
return res.send({ ids: '' })
|
||||
}
|
|
@ -3,7 +3,11 @@
|
|||
"target": "esnext",
|
||||
"module": "esnext",
|
||||
"jsx": "preserve",
|
||||
"lib": ["dom", "es2020","ESNext.String"],
|
||||
"lib": [
|
||||
"dom",
|
||||
"esnext",
|
||||
"ESNext.String"
|
||||
],
|
||||
"baseUrl": ".",
|
||||
"moduleResolution": "node",
|
||||
"strict": true,
|
||||
|
@ -19,8 +23,20 @@
|
|||
"preserveConstEnums": true,
|
||||
"sourceMap": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"resolveJsonModule": true
|
||||
"resolveJsonModule": true,
|
||||
"incremental": true
|
||||
},
|
||||
"exclude": ["dist", ".next", "out", "next.config.js","ambience"],
|
||||
"include": ["next-env.d.ts","additional.d.ts", "**/*.ts", "**/*.tsx"]
|
||||
"exclude": [
|
||||
"dist",
|
||||
".next",
|
||||
"out",
|
||||
"next.config.js",
|
||||
"ambience"
|
||||
],
|
||||
"include": [
|
||||
"next-env.d.ts",
|
||||
"additional.d.ts",
|
||||
"**/*.ts",
|
||||
"**/*.tsx"
|
||||
]
|
||||
}
|
||||
|
|
|
@ -2,11 +2,11 @@
|
|||
"extends": "./tsconfig.json",
|
||||
"ts-node": { "files": true },
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"module": "CommonJS",
|
||||
"outDir": "dist",
|
||||
"target": "esnext",
|
||||
"isolatedModules": false,
|
||||
"noEmit": false
|
||||
},
|
||||
"include": ["additional.d.ts", "server/**/*.ts"]
|
||||
"include": ["additional.d.ts", "src/server/**/*.ts"]
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue