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 charset = utf-8
trim_trailing_whitespace = true trim_trailing_whitespace = true
insert_final_newline = 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: [ extends: [
"eslint:recommended", "eslint:recommended",
"plugin:react/recommended", "plugin:react/recommended",
"plugin:@typescript-eslint/eslint-recommended" "plugin:@typescript-eslint/recommended"
], ],
globals: { globals: {
Atomics: "readonly", Atomics: "readonly",
@ -42,10 +42,17 @@ module.exports = {
], ],
quotes: "off", quotes: "off",
"@typescript-eslint/quotes": ["error", "single", { avoidEscape: true }], "@typescript-eslint/quotes": [
"error",
"single",
{ avoidEscape: true }
],
semi: "off", semi: "off",
"@typescript-eslint/semi": "error", "@typescript-eslint/semi": [
"error",
"never"
],
"no-unused-expressions": "off", "no-unused-expressions": "off",
"@typescript-eslint/no-unused-expressions": ["error", { "allowTernary": true }], "@typescript-eslint/no-unused-expressions": ["error", { "allowTernary": true }],
@ -57,8 +64,8 @@ module.exports = {
default: 'generic' default: 'generic'
} }
], ],
"@typescript-eslint/explicit-module-boundary-types": "off",
"@typescript-eslint/ban-types": "error", "@typescript-eslint/ban-types": "error",
"@typescript-eslint/class-name-casing": "error",
"@typescript-eslint/consistent-type-assertions": "error", "@typescript-eslint/consistent-type-assertions": "error",
"@typescript-eslint/consistent-type-definitions": "error", "@typescript-eslint/consistent-type-definitions": "error",
"@typescript-eslint/explicit-member-accessibility": [ "@typescript-eslint/explicit-member-accessibility": [
@ -92,36 +99,16 @@ module.exports = {
"@typescript-eslint/prefer-for-of": "error", "@typescript-eslint/prefer-for-of": "error",
"@typescript-eslint/prefer-function-type": "error", "@typescript-eslint/prefer-function-type": "error",
"@typescript-eslint/prefer-namespace-keyword": "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/triple-slash-reference": "error",
"@typescript-eslint/type-annotation-spacing": "error", "@typescript-eslint/type-annotation-spacing": "error",
"@typescript-eslint/unified-signatures": "error", "@typescript-eslint/unified-signatures": "error",
"arrow-body-style": "error", "arrow-body-style": "error",
"arrow-parens": [ "arrow-parens": [
"error", "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", complexity: "off",
"constructor-super": "error", "constructor-super": "error",
curly: "error", curly: "error",

2
.gitignore vendored
View File

@ -23,3 +23,5 @@
npm-debug.log* npm-debug.log*
yarn-debug.log* yarn-debug.log*
yarn-error.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 ## Folders
## __tests__ - \__tests__: Test files to test webpage or single components
- docker: Docker files to launch in a Container
Test files to test webpage or single components - public: Static files
- assets: Generally used for Static assets like Pictures
### Components - uploads: used for user uploaded files
- scripts: Contains scripts to quicky make actions (take look in each file to see what it does)
Folder where you put your React components - src: Source folder
- client: Client-side Elements
### libs - components: Components used in pages
- libs: Code used by the Client
Serverside Internal libs - styl: Stylus file location
- modules: Stylus module location
### pages - common: Elements used by both Client-side and Server-side code
- pages: Contains your NextJS pages
NextJS Pages - server: Custom server folder (if you are doing a basic NextJS app you can freely delete this folder)
### public
Static files
### Scripts
Scripts used by the project
### styl
Stylus files location
## TODO list ## TODO list
@ -48,6 +36,9 @@ Stylus files location
- [ ] Support both Stylus CSS modules and purge CSS - [ ] Support both Stylus CSS modules and purge CSS
- [ ] Support typed stylus files - [ ] 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 ## Packages
@ -83,3 +74,4 @@ Stylus files location
- eslint-plugin-react: ESLint React Plugin - eslint-plugin-react: ESLint React Plugin
- jest: Jest tessting framework - jest: Jest tessting framework
- react-test-renderer: Test React components - 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 React from 'react'
import renderer from 'react-test-renderer' import renderer from 'react-test-renderer'
import HelloWorld from '../../components/HelloWorld' import HelloWorld from '../../src/client/components/HelloWorld'
/** /**
* Example Test * 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", "license": "MIT",
"scripts": { "scripts": {
"dev": "next dev", "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", "server": "next start",
"export": "next export && node scripts/generateSitemap", "export": "next export && node scripts/generateSitemap",
"serve": "serve out", "serve": "serve out",
@ -14,7 +16,9 @@
"test": "jest --config jext.config.js" "test": "jest --config jext.config.js"
}, },
"dependencies": { "dependencies": {
"@sentry/browser": "^5.15.5",
"@zeit/next-stylus": "^1.0.1", "@zeit/next-stylus": "^1.0.1",
"express": "^4.17.1",
"glob": "^7.1.6", "glob": "^7.1.6",
"next": "^9.3.3", "next": "^9.3.3",
"next-compose-plugins": "^2.2.0", "next-compose-plugins": "^2.2.0",
@ -32,16 +36,18 @@
"@babel/core": "^7.8.7", "@babel/core": "^7.8.7",
"@babel/preset-env": "^7.8.6", "@babel/preset-env": "^7.8.6",
"@babel/preset-react": "^7.8.3", "@babel/preset-react": "^7.8.3",
"@types/express": "^4.17.6",
"@types/jest": "^25.1.3", "@types/jest": "^25.1.3",
"@types/node": "^13.1.4", "@types/node": "^14.0.0",
"@types/react": "^16.9.17", "@types/react": "^16.9.17",
"@types/react-test-renderer": "^16.9.2", "@types/react-test-renderer": "^16.9.2",
"@typescript-eslint/eslint-plugin": "^2.19.0", "@typescript-eslint/eslint-plugin": "^3.0.0",
"@typescript-eslint/parser": "^2.19.0", "@typescript-eslint/parser": "^3.0.0",
"babel-jest": "^25.1.0", "babel-jest": "^26.0.0",
"eslint": "^6.8.0", "eslint": "^7.1.0",
"eslint-plugin-react": "^7.18.3", "eslint-plugin-react": "^7.18.3",
"jest": "^25.1.0", "jest": "^26.0.0",
"react-test-renderer": "^16.13.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 React, { SyntheticEvent } from 'react'
import css from './Image.module.styl' import css from '@smd/Image.module.styl'
interface Props { interface Props {
defaultHeight?: number defaultHeight?: number
@ -50,7 +50,7 @@ const getMimeType = (img: string) => {
type evType<T = HTMLImageElement> = SyntheticEvent<T, Event> 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 ref: React.RefObject<HTMLImageElement> = React.createRef()
private plchldr: React.RefObject<HTMLDivElement> = 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 React from 'react'
import '../styl/index.styl' import HelloWorld from '@cp/HelloWorld'
import HelloWorld from '../components/HelloWorld' import Image from '@cp/Image'
import Image from '../components/Image'
function isWindow() {
try {
window.isNaN(1)
return true
} catch {
return false
}
}
export default class Index extends React.Component { export default class Index extends React.Component {
public render() { public render() {
if (isWindow()) {
throw new Error('Test')
}
return( return(
<> <>
<HelloWorld>Hello World</HelloWorld> <HelloWorld>Hello World</HelloWorld>
@ -13,7 +25,7 @@ export default class Index extends React.Component {
max={{height:400,width:200}} max={{height:400,width:200}}
default={{width:200,height:100}} default={{width:200,height:100}}
deleteOnError={true} deleteOnError={true}
src="https://source.unusplash.com/random/800x600" src="https://source.unsplash.com/random/800x600"
/> />
<HelloWorld>Hello World</HelloWorld> <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", "moduleResolution": "node",
"resolveJsonModule": true, "resolveJsonModule": true,
"isolatedModules": true, "isolatedModules": true,
"jsx": "preserve" "jsx": "preserve",
"baseUrl": "./src",
"paths": {
"@styl/*": ["client/styl/*"],
"@cp/*": ["client/components/*"],
"@smd/*": ["client/styl/modules/*"],
}
}, },
"exclude": [ "exclude": [
"node_modules", "node_modules",
@ -25,7 +31,7 @@
], ],
"include": [ "include": [
"next-env.d.ts", "next-env.d.ts",
"styl/stylus.d.ts", "src/client/styl/stylus.d.ts",
"**/*.ts", "**/*.ts",
"**/*.tsx" "**/*.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