typescript(pleix-frontend): inital commit
Signed-off-by: prescientmoon <git@moonythm.dev>
This commit is contained in:
parent
047d724e9a
commit
bffd04906b
1
typescript/pleix-frontend/.gitignore
vendored
Normal file
1
typescript/pleix-frontend/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
node_modules
|
7869
typescript/pleix-frontend/package-lock.json
generated
Normal file
7869
typescript/pleix-frontend/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
33
typescript/pleix-frontend/package.json
Normal file
33
typescript/pleix-frontend/package.json
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
{
|
||||||
|
"name": "pleix-client",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"scripts": {
|
||||||
|
"setup": "nvmw use 10.15.3",
|
||||||
|
"start": "webpack-dev-server --open --mode development",
|
||||||
|
"build": "npm run setup 10.15.3 && webpack --mode production"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"css-loader": "^2.1.1",
|
||||||
|
"extract-text-webpack-plugin": "^3.0.2",
|
||||||
|
"file-loader": "^3.0.1",
|
||||||
|
"html-loader": "^0.5.5",
|
||||||
|
"html-webpack-plugin": "^3.2.0",
|
||||||
|
"node-sass": "^4.12.0",
|
||||||
|
"sass-loader": "^7.1.0",
|
||||||
|
"source-map-loader": "^0.2.4",
|
||||||
|
"style-loader": "^0.23.1",
|
||||||
|
"ts-loader": "^6.0.0",
|
||||||
|
"typescript": "^3.4.5",
|
||||||
|
"webpack": "^4.31.0",
|
||||||
|
"webpack-cli": "^3.3.2",
|
||||||
|
"webpack-dev-server": "^3.3.1"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"fromentries": "^1.1.0",
|
||||||
|
"haunted": "^4.2.1",
|
||||||
|
"lit-html": "^1.0.0",
|
||||||
|
"lit-rx": "0.0.2",
|
||||||
|
"prouter": "^9.1.2",
|
||||||
|
"rxjs": "^6.5.2"
|
||||||
|
}
|
||||||
|
}
|
13
typescript/pleix-frontend/src/index.html
Normal file
13
typescript/pleix-frontend/src/index.html
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<title>Welcome to Firebase Hosting</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
50
typescript/pleix-frontend/src/index.ts
Normal file
50
typescript/pleix-frontend/src/index.ts
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
import { html, render } from "lit-html"
|
||||||
|
import { AdrielServer } from "./routes";
|
||||||
|
import { subscribe } from "lit-rx"
|
||||||
|
|
||||||
|
import "./lit-route"
|
||||||
|
import { map } from "rxjs/operators";
|
||||||
|
|
||||||
|
const password = "123"
|
||||||
|
const email = "rafaeladriel11@gmail.com"
|
||||||
|
const name = "Adriel Matei"
|
||||||
|
|
||||||
|
const server = new AdrielServer()
|
||||||
|
|
||||||
|
let timer:number[] = []
|
||||||
|
|
||||||
|
const signup = () => {
|
||||||
|
timer.push(performance.now())
|
||||||
|
server.signup(email, name, password)
|
||||||
|
}
|
||||||
|
|
||||||
|
render(html`
|
||||||
|
<lit-router>
|
||||||
|
<lit-route href="/">
|
||||||
|
<button @click=${signup}>Signup</button>
|
||||||
|
<div>
|
||||||
|
Logged in: ${subscribe(server.authenticated)} <br>
|
||||||
|
It took: ${subscribe(server.authenticated.pipe(map(val =>
|
||||||
|
performance.now() - timer[timer.length - 1]
|
||||||
|
)))} ms
|
||||||
|
</div>
|
||||||
|
</lit-route>
|
||||||
|
<lit-route href="/test">
|
||||||
|
<br>
|
||||||
|
something else
|
||||||
|
</lit-route>
|
||||||
|
<div>
|
||||||
|
this isnt affected
|
||||||
|
</div>
|
||||||
|
<button>
|
||||||
|
<lit-a to="/test">
|
||||||
|
Test
|
||||||
|
</lit-a>
|
||||||
|
</button>
|
||||||
|
<button>
|
||||||
|
<lit-a to="/">
|
||||||
|
Root
|
||||||
|
</lit-a>
|
||||||
|
</button>
|
||||||
|
</lit-router>
|
||||||
|
`, document.body)
|
57
typescript/pleix-frontend/src/lit-route.ts
Normal file
57
typescript/pleix-frontend/src/lit-route.ts
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
import { component, html, useState } from "haunted"
|
||||||
|
import { router } from "./lit-router"
|
||||||
|
|
||||||
|
|
||||||
|
const Route = component((props) => {
|
||||||
|
const [$html] = useState([...props.childNodes])
|
||||||
|
|
||||||
|
return html`
|
||||||
|
${$html}
|
||||||
|
`
|
||||||
|
})
|
||||||
|
|
||||||
|
const routerTagName = "lit-route"
|
||||||
|
customElements.define(routerTagName, Route)
|
||||||
|
|
||||||
|
const Router = component((props) => {
|
||||||
|
let [currentPath, setCurrentPath] = useState("/")
|
||||||
|
let [first, setFirst] = useState(true)
|
||||||
|
|
||||||
|
const [children] = useState([...props.children])
|
||||||
|
|
||||||
|
if (first) {
|
||||||
|
router.use("*", (req, res, next) => {
|
||||||
|
setCurrentPath(req.originalUrl)
|
||||||
|
res.end()
|
||||||
|
})
|
||||||
|
|
||||||
|
router.listen()
|
||||||
|
setFirst(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const safeChildren = children
|
||||||
|
.filter((value: any) => value.tagName != routerTagName.toLocaleUpperCase())
|
||||||
|
|
||||||
|
const routeElements: HTMLElement[] = children
|
||||||
|
.filter((value: any) => value.getAttribute("href") == currentPath)
|
||||||
|
|
||||||
|
return html`
|
||||||
|
${safeChildren}
|
||||||
|
${routeElements}
|
||||||
|
`
|
||||||
|
})
|
||||||
|
|
||||||
|
customElements.define("lit-router", Router)
|
||||||
|
|
||||||
|
const litA = component((props:any) => {
|
||||||
|
const [$html] = useState([...props.childNodes])
|
||||||
|
const [url] = useState(props.getAttribute("to"))
|
||||||
|
|
||||||
|
return html`
|
||||||
|
<span @click=${() => { router.push(url) }}>
|
||||||
|
${$html}
|
||||||
|
</span>`
|
||||||
|
})
|
||||||
|
|
||||||
|
customElements.define("lit-a", litA)
|
3
typescript/pleix-frontend/src/lit-router.ts
Normal file
3
typescript/pleix-frontend/src/lit-router.ts
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
import { browserRouter } from "prouter"
|
||||||
|
|
||||||
|
export const router = browserRouter()
|
1
typescript/pleix-frontend/src/routes/auth/index.ts
Normal file
1
typescript/pleix-frontend/src/routes/auth/index.ts
Normal file
|
@ -0,0 +1 @@
|
||||||
|
export * from "./services/AdrielServer"
|
|
@ -0,0 +1,105 @@
|
||||||
|
import { AdrielRequestOptions, AdrielTokenResponse } from "./interfaces";
|
||||||
|
import { Subject } from "rxjs"
|
||||||
|
import { map } from "rxjs/operators"
|
||||||
|
|
||||||
|
export class AdrielServer {
|
||||||
|
private _ready = new Subject()
|
||||||
|
private token: string = "";
|
||||||
|
|
||||||
|
private static defaultOptions: AdrielRequestOptions = {
|
||||||
|
method: "GET",
|
||||||
|
url: "/",
|
||||||
|
body: {}
|
||||||
|
}
|
||||||
|
|
||||||
|
public url = "http://localhost:8000"
|
||||||
|
public ready = this._ready.toPromise()
|
||||||
|
|
||||||
|
public user = new Subject()
|
||||||
|
public uid = new Subject<string | null>()
|
||||||
|
public authenticated = this.uid.pipe(
|
||||||
|
map(val => !!val)
|
||||||
|
)
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
const tokenPromise = new Promise<string>(async (res,rej) => {
|
||||||
|
if (!localStorage.token) {
|
||||||
|
const token = await this.generateToken()
|
||||||
|
localStorage.token = token
|
||||||
|
res(token)
|
||||||
|
}
|
||||||
|
else
|
||||||
|
res(localStorage.token)
|
||||||
|
})
|
||||||
|
|
||||||
|
tokenPromise.then((token:string) => {
|
||||||
|
this.token = token
|
||||||
|
this._ready.next()
|
||||||
|
this._ready.complete()
|
||||||
|
this.uid.next(null)
|
||||||
|
}).catch(err => {
|
||||||
|
this._ready.error(err)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private async generateToken() {
|
||||||
|
const result = await fetch(`${this.url}/token`)
|
||||||
|
const data: AdrielTokenResponse = await result.json()
|
||||||
|
const token = data.data.token
|
||||||
|
|
||||||
|
return token
|
||||||
|
}
|
||||||
|
|
||||||
|
async request(options: Partial<AdrielRequestOptions>) {
|
||||||
|
await this.ready
|
||||||
|
|
||||||
|
const finalOptions = { ...AdrielServer.defaultOptions, ...options }
|
||||||
|
|
||||||
|
//stringify body
|
||||||
|
finalOptions.body = JSON.stringify(finalOptions.body)
|
||||||
|
|
||||||
|
const forbiddenKyes = ["url"]
|
||||||
|
const optionMixin: Partial<AdrielRequestOptions> = {}
|
||||||
|
|
||||||
|
for (let i in finalOptions) {
|
||||||
|
//only for my editor to shut up
|
||||||
|
const key = i as keyof AdrielRequestOptions
|
||||||
|
|
||||||
|
if (forbiddenKyes.indexOf(key) == -1)
|
||||||
|
optionMixin[key] = finalOptions[key]
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(optionMixin)
|
||||||
|
|
||||||
|
//check if theres a token
|
||||||
|
if (!this.token){
|
||||||
|
throw new Error("cannot make a request without a token")
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await fetch(`${this.url}/${finalOptions.url}`, {
|
||||||
|
...optionMixin,
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
authorization: `Bearer ${this.token}`
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
async signup(email: string, name: string, password: string) {
|
||||||
|
const res = await this.request({
|
||||||
|
url: "auth",
|
||||||
|
method: "POST",
|
||||||
|
body: {
|
||||||
|
password, email, name
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const data = await res.json()
|
||||||
|
|
||||||
|
this.uid.next(data.data.uid)
|
||||||
|
|
||||||
|
return data.data.uid
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
export interface AdrielRequestOptions {
|
||||||
|
method: string
|
||||||
|
url: string
|
||||||
|
body: any
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AdrielResponse {
|
||||||
|
succes:boolean
|
||||||
|
data: any
|
||||||
|
errors?: string[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AdrielTokenResponse extends AdrielResponse {
|
||||||
|
data: {
|
||||||
|
token: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface User {
|
||||||
|
uid:string,
|
||||||
|
name: string,
|
||||||
|
email: string,
|
||||||
|
photoUrl: string,
|
||||||
|
friends: string[]
|
||||||
|
}
|
||||||
|
|
1
typescript/pleix-frontend/src/routes/index.ts
Normal file
1
typescript/pleix-frontend/src/routes/index.ts
Normal file
|
@ -0,0 +1 @@
|
||||||
|
export * from "./auth"
|
15
typescript/pleix-frontend/tsconfig.json
Normal file
15
typescript/pleix-frontend/tsconfig.json
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"include": [
|
||||||
|
"src"
|
||||||
|
],
|
||||||
|
"compilerOptions": {
|
||||||
|
"module": "commonjs",
|
||||||
|
"noImplicitReturns": true,
|
||||||
|
"noUnusedLocals": true,
|
||||||
|
"outDir": "lib",
|
||||||
|
"sourceMap": true,
|
||||||
|
"strict": true,
|
||||||
|
"target": "es2017",
|
||||||
|
"moduleResolution": "node"
|
||||||
|
}
|
||||||
|
}
|
38
typescript/pleix-frontend/webpack.config.js
Normal file
38
typescript/pleix-frontend/webpack.config.js
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
const HtmlWebPackPlugin = require("html-webpack-plugin");
|
||||||
|
// const ExtractTextPlugin = require('extract-text-webpack-plugin');
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
devtool: 'inline-source-map',
|
||||||
|
module: {
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
test: /\.ts$/,
|
||||||
|
use: 'ts-loader',
|
||||||
|
exclude: /node_modules/
|
||||||
|
},
|
||||||
|
{
|
||||||
|
test: /\.html$/,
|
||||||
|
use: [
|
||||||
|
{
|
||||||
|
loader: "html-loader"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
new HtmlWebPackPlugin({
|
||||||
|
template: "./src/index.html",
|
||||||
|
filename: "./index.html"
|
||||||
|
})
|
||||||
|
],
|
||||||
|
resolve: {
|
||||||
|
extensions: [
|
||||||
|
".js",
|
||||||
|
".ts"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
entry: [
|
||||||
|
"./src/index.ts"
|
||||||
|
]
|
||||||
|
};
|
Loading…
Reference in a new issue