Signed-off-by: Avior <florian.bouillon@delta-wings.net>
This commit is contained in:
Florian Bouillon 2020-05-26 00:17:30 +02:00
parent 21eba2d473
commit 54d8217133
No known key found for this signature in database
GPG Key ID: B143FF27EF555D16
36 changed files with 3128 additions and 2654 deletions

View File

@ -6,3 +6,8 @@ indent_size = 4
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
indent_style = space
indent_size = 2
trim_trailing_whitespace = false

View File

@ -7,7 +7,7 @@ module.exports = {
extends: [
"eslint:recommended",
"plugin:react/recommended",
"plugin:@typescript-eslint/eslint-recommended"
"plugin:@typescript-eslint/recommended"
],
globals: {
Atomics: "readonly",
@ -42,10 +42,17 @@ module.exports = {
],
quotes: "off",
"@typescript-eslint/quotes": ["error", "single", { avoidEscape: true }],
"@typescript-eslint/quotes": [
"error",
"single",
{ avoidEscape: true }
],
semi: "off",
"@typescript-eslint/semi": "error",
"@typescript-eslint/semi": [
"error",
"never"
],
"no-unused-expressions": "off",
"@typescript-eslint/no-unused-expressions": ["error", { "allowTernary": true }],
@ -57,8 +64,8 @@ module.exports = {
default: 'generic'
}
],
"@typescript-eslint/explicit-module-boundary-types": "off",
"@typescript-eslint/ban-types": "error",
"@typescript-eslint/class-name-casing": "error",
"@typescript-eslint/consistent-type-assertions": "error",
"@typescript-eslint/consistent-type-definitions": "error",
"@typescript-eslint/explicit-member-accessibility": [
@ -92,36 +99,16 @@ module.exports = {
"@typescript-eslint/prefer-for-of": "error",
"@typescript-eslint/prefer-function-type": "error",
"@typescript-eslint/prefer-namespace-keyword": "error",
"@typescript-eslint/quotes": [
"error",
"single",
{
avoidEscape: true
}
],
"@typescript-eslint/semi": [
"error",
"never"
],
"@typescript-eslint/triple-slash-reference": "error",
"@typescript-eslint/type-annotation-spacing": "error",
"@typescript-eslint/unified-signatures": "error",
"arrow-body-style": "error",
"arrow-parens": [
"error",
"as-needed"
"always"
],
camelcase: "off",
"@typescript-eslint/camelcase": ["error", {
properties: "never",
allow: ["^[A-Za-z][a-zA-Za-z]+_[A-Za-z]+$"]
}],
"comma-dangle": [
"error",
"always-multiline"
],
complexity: "off",
"constructor-super": "error",
curly: "error",

2
.gitignore vendored
View File

@ -23,3 +23,5 @@
npm-debug.log*
yarn-debug.log*
yarn-error.log*
dist/

13
Dockerfile Normal file
View File

@ -0,0 +1,13 @@
FROM node:alpine
# instal yarn
RUN apk -q add yarn
# Go to user home
WORKDIR /home/tcgdex
COPY . .
RUN yarn && yarn build && yarn sitemap
CMD ["yarn", "server"]

View File

@ -2,33 +2,21 @@
## Folders
## __tests__
Test files to test webpage or single components
### Components
Folder where you put your React components
### libs
Serverside Internal libs
### pages
NextJS Pages
### public
Static files
### Scripts
Scripts used by the project
### styl
Stylus files location
- \__tests__: Test files to test webpage or single components
- docker: Docker files to launch in a Container
- public: Static files
- assets: Generally used for Static assets like Pictures
- uploads: used for user uploaded files
- scripts: Contains scripts to quicky make actions (take look in each file to see what it does)
- src: Source folder
- client: Client-side Elements
- components: Components used in pages
- libs: Code used by the Client
- styl: Stylus file location
- modules: Stylus module location
- common: Elements used by both Client-side and Server-side code
- pages: Contains your NextJS pages
- server: Custom server folder (if you are doing a basic NextJS app you can freely delete this folder)
## TODO list
@ -48,6 +36,9 @@ Stylus files location
- [ ] Support both Stylus CSS modules and purge CSS
- [ ] Support typed stylus files
## Custom Server
If you want to have a Custom server you simply have to start editing `src/server/server.ts` and after that to dev run `yarn cs-dev`
## Packages
@ -83,3 +74,4 @@ Stylus files location
- eslint-plugin-react: ESLint React Plugin
- jest: Jest tessting framework
- react-test-renderer: Test React components
- ts-node-dev: Start the developpement server and restart it on changes (remove this dev-deps if you're not using a custom server)

View File

@ -1,6 +1,6 @@
import React from 'react'
import renderer from 'react-test-renderer'
import HelloWorld from '../../components/HelloWorld'
import HelloWorld from '../../src/client/components/HelloWorld'
/**
* Example Test

View File

@ -0,0 +1,18 @@
version: "3"
services:
tcgdex:
volumes:
- ../:/home/tcgdex
command: "yarn dev"
tty: true
ports:
- "3000:3000"
phpmyadmin:
image: phpmyadmin/phpmyadmin
ports:
- 8081:80
networks:
- network
env_file:
- .env
- .env.local

View File

@ -0,0 +1,6 @@
version: "3"
services:
tcgdex:
restart: "always"
ports:
- "127.0.0.1:4567:3000"

View File

@ -0,0 +1,5 @@
version: "3"
services:
tcgdex:
ports:
- "3000:3000"

28
docker/docker-compose.yml Normal file
View File

@ -0,0 +1,28 @@
version: "3"
services:
tcgdex:
build:
context: ../
dockerfile: Dockerfile
networks:
- network
depends_on:
- db
env_file:
- .env
- .env.local
db:
image: mysql
command: --default-authentication-plugin=mysql_native_password
env_file:
- .env
- .env.local
networks:
- network
volumes:
- ./.storage/mysql/:/var/lib/mysql
networks:
network:
external: false

View File

@ -4,7 +4,9 @@
"license": "MIT",
"scripts": {
"dev": "next dev",
"build": "next build",
"cs-dev": "ts-node --project tsconfig.server.json src/server/server.ts --respawn --transpileOnly --prefer-ts --watch next.config.js,.env --ignore-watch .next --ignore-watch src/pages --ignore-watch src/client --ignore-watch scripts src/server/server.ts",
"build": "next build && tsc --project tsconfig.server.json",
"cs-server": "NODE_ENV=production node --experimental-modules dist/server/server.js",
"server": "next start",
"export": "next export && node scripts/generateSitemap",
"serve": "serve out",
@ -14,7 +16,9 @@
"test": "jest --config jext.config.js"
},
"dependencies": {
"@sentry/browser": "^5.15.5",
"@zeit/next-stylus": "^1.0.1",
"express": "^4.17.1",
"glob": "^7.1.6",
"next": "^9.3.3",
"next-compose-plugins": "^2.2.0",
@ -32,16 +36,18 @@
"@babel/core": "^7.8.7",
"@babel/preset-env": "^7.8.6",
"@babel/preset-react": "^7.8.3",
"@types/express": "^4.17.6",
"@types/jest": "^25.1.3",
"@types/node": "^13.1.4",
"@types/node": "^14.0.0",
"@types/react": "^16.9.17",
"@types/react-test-renderer": "^16.9.2",
"@typescript-eslint/eslint-plugin": "^2.19.0",
"@typescript-eslint/parser": "^2.19.0",
"babel-jest": "^25.1.0",
"eslint": "^6.8.0",
"@typescript-eslint/eslint-plugin": "^3.0.0",
"@typescript-eslint/parser": "^3.0.0",
"babel-jest": "^26.0.0",
"eslint": "^7.1.0",
"eslint-plugin-react": "^7.18.3",
"jest": "^25.1.0",
"react-test-renderer": "^16.13.0"
"jest": "^26.0.0",
"react-test-renderer": "^16.13.0",
"ts-node-dev": "^1.0.0-pre.44"
}
}

View File

@ -1,21 +0,0 @@
import App from 'next/app'
import Head from 'next/head'
import React from 'react'
import '../styl/index.styl'
export default class CApp extends App {
public render() {
const { Component, pageProps } = this.props
return(
<>
<Head>
<title>Next Template Hello World !</title>
</Head>
<Component {...pageProps} />
</>
)
}
}

0
public/uploads/.gitkeep Normal file
View File

3
scripts/dev Executable file
View File

@ -0,0 +1,3 @@
#!/usr/bin/env sh
cd ..
docker-compose -f docker/docker-compose.yml -f docker/docker-compose.override.yml up

3
scripts/test Executable file
View File

@ -0,0 +1,3 @@
#!/usr/bin/env sh
cd ..
docker-compose -f docker/docker-compose.yml -f docker/docker-compose.test.yml up --build

3
scripts/upgrade Executable file
View File

@ -0,0 +1,3 @@
#!/usr/bin/env sh
cd ..
docker-compose -f docker/docker-compose.yml -f docker/docker-compose.prod.yml up -d --build

View File

@ -1,5 +1,5 @@
import React, { SyntheticEvent } from 'react'
import css from './Image.module.styl'
import css from '@smd/Image.module.styl'
interface Props {
defaultHeight?: number
@ -50,7 +50,7 @@ const getMimeType = (img: string) => {
type evType<T = HTMLImageElement> = SyntheticEvent<T, Event>
export default class Image extends React.Component<Props, {}> {
export default class Image extends React.Component<Props> {
private ref: React.RefObject<HTMLImageElement> = React.createRef()
private plchldr: React.RefObject<HTMLDivElement> = React.createRef()

0
src/client/libs/.gitkeep Normal file
View File

View File

0
src/common/libs/.gitkeep Normal file
View File

11
src/pages/404.tsx Normal file
View File

@ -0,0 +1,11 @@
import React from 'react'
import Error from './_error'
export default class E404 extends React.Component {
public render() {
return(
<Error statusCode={404} />
)
}
}

50
src/pages/_app.tsx Normal file
View File

@ -0,0 +1,50 @@
import App from 'next/app'
import Head from 'next/head'
import React from 'react'
import * as Sentry from '@sentry/browser'
import ErrorPage from './_error'
import '@styl/index.styl'
Sentry.init({
dsn: process.env.NEXT_PUBLIC_SENTRY_DSN
})
interface States {
errorId?: string
}
export default class CApp extends App<Record<string, unknown>, Record<string, unknown>, States> {
public componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
console.log('catching error', error, errorInfo)
Sentry.withScope((scope) => {
Object.keys(errorInfo).forEach((key) => {
scope.setExtra(key, (errorInfo as any)[key])
})
const id = Sentry.captureException(error)
console.log(id)
this.setState({
errorId: id
})
})
}
public render() {
const { Component, pageProps } = this.props
return(
<>
<Head>
<title>Next Template Hello World !</title>
</Head>
{this.state && this.state.errorId && (
<ErrorPage statusCode={500} eventId={this.state.errorId} />
) || (
<Component {...pageProps} />
)}
</>
)
}
}

25
src/pages/_document.tsx Normal file
View File

@ -0,0 +1,25 @@
import React from 'react'
import Document, { Html, Head, Main, NextScript } from 'next/document'
import * as Sentry from '@sentry/browser'
process.on('unhandledRejection', (err) => {
Sentry.captureException(err)
})
process.on('uncaughtException', (err) => {
Sentry.captureException(err)
})
export default class CDocument extends Document {
public render() {
return (
<Html>
<Head />
<body>
<Main />
<NextScript />
</body>
</Html>
)
}
}

31
src/pages/_error.tsx Normal file
View File

@ -0,0 +1,31 @@
import React from 'react'
import { NextPageContext } from 'next'
import * as Sentry from '@sentry/browser'
interface Props {
statusCode: number
eventId?: string
}
export default class Error extends React.Component<Props> {
public static async getInitialProps({res, err}: NextPageContext): Promise<Props> {
const statusCode = res?.statusCode || err?.statusCode || 500
return {
statusCode
}
}
public render() {
return(
<>
<h1>An Error Occured ! {this.props.statusCode}</h1>
{this.props.eventId && (
<button onClick={() => Sentry.showReportDialog({ eventId: this.props.eventId })}>Report Error</button>
)}
</>
)
}
}

View File

@ -1,11 +1,23 @@
import React from 'react'
import '../styl/index.styl'
import HelloWorld from '../components/HelloWorld'
import Image from '../components/Image'
import HelloWorld from '@cp/HelloWorld'
import Image from '@cp/Image'
function isWindow() {
try {
window.isNaN(1)
return true
} catch {
return false
}
}
export default class Index extends React.Component {
public render() {
if (isWindow()) {
throw new Error('Test')
}
return(
<>
<HelloWorld>Hello World</HelloWorld>
@ -13,7 +25,7 @@ export default class Index extends React.Component {
max={{height:400,width:200}}
default={{width:200,height:100}}
deleteOnError={true}
src="https://source.unusplash.com/random/800x600"
src="https://source.unsplash.com/random/800x600"
/>
<HelloWorld>Hello World</HelloWorld>
</>

22
src/server/server.ts Normal file
View File

@ -0,0 +1,22 @@
// Base Server Config
// https://nextjs.org/docs/advanced-features/custom-server
import { createServer } from 'http'
import { parse } from 'url'
import next from 'next'
const dev = process.env.NODE_ENV !== 'production'
const app = next({ dev })
const handle = app.getRequestHandler()
;(async () => {
await app.prepare()
createServer((req, res) => {
// Be sure to pass `true` as the second argument to `url.parse`.
// This tells it to parse the query portion of the URL.
const parsedUrl = parse(req.url || '', true)
handle(req, res, parsedUrl)
}).listen(parseInt(process.env.PORT || '3000', 10), () => {
console.log('> Ready on http://localhost:3000')
})
})()

View File

@ -16,7 +16,13 @@
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve"
"jsx": "preserve",
"baseUrl": "./src",
"paths": {
"@styl/*": ["client/styl/*"],
"@cp/*": ["client/components/*"],
"@smd/*": ["client/styl/modules/*"],
}
},
"exclude": [
"node_modules",
@ -25,7 +31,7 @@
],
"include": [
"next-env.d.ts",
"styl/stylus.d.ts",
"src/client/styl/stylus.d.ts",
"**/*.ts",
"**/*.tsx"
]

13
tsconfig.scripts.json Normal file
View File

@ -0,0 +1,13 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"module": "commonjs",
"outDir": "scripts-dist",
"target": "es2017",
"isolatedModules": false,
"noEmit": false
},
"include": [
"scripts/**/*.ts"
]
}

15
tsconfig.server.json Normal file
View File

@ -0,0 +1,15 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"module": "commonjs",
"outDir": "dist",
"target": "es2017",
"isolatedModules": false,
"noEmit": false,
"emitDecoratorMetadata": true,
"experimentalDecorators": true
},
"include": [
"src/server/**/*.ts"
]
}

5365
yarn.lock

File diff suppressed because it is too large Load Diff