1
Fork 0

typescript(pleix-frontend): inital commit

Signed-off-by: prescientmoon <git@moonythm.dev>
This commit is contained in:
Matei Adriel 2019-05-20 17:48:26 +03:00 committed by prescientmoon
parent 047d724e9a
commit bffd04906b
Signed by: prescientmoon
SSH key fingerprint: SHA256:UUF9JT2s8Xfyv76b8ZuVL7XrmimH4o49p4b+iexbVH4
13 changed files with 8212 additions and 0 deletions

1
typescript/pleix-frontend/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
node_modules

7869
typescript/pleix-frontend/package-lock.json generated Normal file

File diff suppressed because it is too large Load diff

View 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"
}
}

View 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>

View 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)

View 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)

View file

@ -0,0 +1,3 @@
import { browserRouter } from "prouter"
export const router = browserRouter()

View file

@ -0,0 +1 @@
export * from "./services/AdrielServer"

View file

@ -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
}
}

View file

@ -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[]
}

View file

@ -0,0 +1 @@
export * from "./auth"

View file

@ -0,0 +1,15 @@
{
"include": [
"src"
],
"compilerOptions": {
"module": "commonjs",
"noImplicitReturns": true,
"noUnusedLocals": true,
"outDir": "lib",
"sourceMap": true,
"strict": true,
"target": "es2017",
"moduleResolution": "node"
}
}

View 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"
]
};