feat: Initial Commit

Signed-off-by: Avior <github@avior.me>
This commit is contained in:
Florian Bouillon 2022-11-03 00:58:37 +01:00
commit c467bccbe6
Signed by: Florian Bouillon
GPG Key ID: BEEAF3722D0EBF64
15 changed files with 2830 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
dist/
node_modules

5
client.ts Normal file
View File

@ -0,0 +1,5 @@
import ReactDOM from 'react-dom/client'
document.addEventListener('load', async () => {
ReactDOM.hydrateRoot(document.body, )
})

13
index.html Normal file
View File

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app"><!--ssr-outlet--></div>
<script type="module" src="/src/entry-client.ts"></script>
</body>
</html>

72
main.ts Normal file
View File

@ -0,0 +1,72 @@
import express, { Request } from 'express'
import { createServer } from 'vite'
import fs from 'fs/promises'
// const isProd = process.env.NODE_ENV === 'production'
const isProd = true
;(async () => {
const server = express()
const vite = await createServer({
server: {middlewareMode: true},
appType: 'custom'
})
let index = await fs.readFile('./dist/client/index.html', 'utf-8')
console.log(process.env)
if (!isProd) {
index = await fs.readFile('./index.html', 'utf-8')
}
server.use(vite.middlewares)
server.use('/', express.static('public'))
server.use(async (req, res) => {
const url = req.originalUrl
const template = await vite.transformIndexHtml(url, index)
let render: ((url: Request) => Promise<string>) | null = null
if (isProd) {
/** @ts-expect-error why not m*therfucker */
const route: any = await import('./server/entry-server.js')
render = route.render as any
} else {
const route = await vite.ssrLoadModule('/src/entry-server.tsx')
render = route.render
}
if (!render) {
return res.status(500).end('Error')
}
const appHtml = await render(req)
const html = template.replace('<!--ssr-outlet-->', appHtml)
return res.status(200).set({'Content-Type': 'text/html'}).end(html)
// const url = req.path
// const path = `./pages${url}`
// const is404 = !(await exists(path))
// if (is404) {
// return res.status(404).send('404')
// }
// console.log(url)
// const route = await import(path)
// const props = await route.getServerProps()
// res.send(`<!DOCTYPE html>` + renderToString(<App><route.default {...props} /></App>))
})
server.listen(8080, () => {
console.log('Server Started!')
})
})()

2604
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

27
package.json Normal file
View File

@ -0,0 +1,27 @@
{
"name": "test",
"version": "1.0.0",
"type": "module",
"scripts": {
"dev": "ts-node -T --project tsconfig.json main.tsx",
"build": "npm run build:client && npm run build:server",
"build:client": "vite build --outDir dist/client --ssrManifest",
"build:server": "vite build --outDir dist/server --ssr src/entry-server.tsx && tsc --project tsconfig.json"
},
"dependencies": {
"@dzeio/config": "^1.1.8",
"@tcgdex/sdk": "^2.4.7",
"express": "^4.18.2",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"ts-node": "^10.9.1",
"typescript": "^4.8.4"
},
"devDependencies": {
"@types/express": "^4.17.14",
"@types/node": "^18.11.9",
"@types/react": "^18.0.24",
"@types/react-dom": "^18.0.8",
"vite": "^3.2.2"
}
}

1
public/test.json Normal file
View File

@ -0,0 +1 @@
{"pouet": true}

10
src/Utils.ts Normal file
View File

@ -0,0 +1,10 @@
import fs from 'fs/promises'
export async function exists(path: string): Promise<boolean> {
try {
await fs.access(path + `.tsx`)
return true
} catch {
return false
}
}

0
src/entry-client.ts Normal file
View File

21
src/entry-server.tsx Normal file
View File

@ -0,0 +1,21 @@
import { exists } from './Utils'
import { renderToString } from 'react-dom/server'
import App from './pages/_app'
import React from 'react'
import { Request } from 'express'
import path from 'path'
import { fileURLToPath } from 'url'
const __dirname = path.dirname(fileURLToPath(import.meta.url))
export const render = async (req: Request) => {
const path = `${__dirname}/pages${req.path}`
console.log(req.path, __dirname)
const is404 = !(await exists(path))
if (is404) {
return '404'
}
const route = await import(`${__dirname}/pages${req.path}.tsx`)
const props = await route.getServerProps()
return (`<!DOCTYPE html>` + renderToString(<App><route.default {...props} /></App>))
}

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

@ -0,0 +1,22 @@
import React from 'react'
interface AppProps {
children: React.ReactNode
}
export default class App extends React.Component<AppProps> {
public render = () => (
<>
<html>
<head>
<script
type='application/json'
id="__PROPS"
dangerouslySetInnerHTML={{__html: JSON.stringify(this.props)}}
></script>
</head>
<body>{this.props.children}</body>
</html>
</>
)
}

17
src/pages/path.tsx Normal file
View File

@ -0,0 +1,17 @@
import React from 'react'
import TCGdex, { Card } from '@tcgdex/sdk'
export default class Component extends React.Component<{card: Card}> {
public render = () => (
<div>{this.props.card.name}</div>
)
}
export const getServerProps = async () => {
const tcgdex = new TCGdex()
return {
card: await tcgdex.fetchCard('bw1-1')
}
}

17
src/pages/set.tsx Normal file
View File

@ -0,0 +1,17 @@
import React from 'react'
import TCGdex, { Card, Set } from '@tcgdex/sdk'
export default class Component extends React.Component<{card: Set}> {
public render = () => (
<div onClick={() => console.log('YOLO')}>{this.props.card.name}</div>
)
}
export const getServerProps = async () => {
const tcgdex = new TCGdex()
return {
card: await tcgdex.fetchSet('bw1')
}
}

16
tsconfig.json Normal file
View File

@ -0,0 +1,16 @@
{
//"extends": "./node_modules/@dzeio/config/tsconfig.base.json",
"compilerOptions": {
"jsx": "react-jsx",
"outDir": "dist",
"target": "ES2022",
"module": "NodeNext",
"skipLibCheck": true
},
"files": [
"main.ts"
],
"exclude": [
"node_modules"
]
}

3
tsconfig.prod.json Normal file
View File

@ -0,0 +1,3 @@
{
"extends": "./node_modules/@dzeio/config/tsconfig.esm.json"
}