-
-
Notifications
You must be signed in to change notification settings - Fork 20
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
major refactor / cleanup / framework-ification
- Loading branch information
Showing
25 changed files
with
351 additions
and
186 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
10 changes: 5 additions & 5 deletions
10
src/server/live/autocomplete/component.ts → src/examples/autocomplete/component.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import { LiveViewServer } from '../server'; | ||
import { LiveViewRouter } from '../server/types'; | ||
import { AutocompleteLiveViewComponent } from './autocomplete/component'; | ||
import { LicenseLiveViewComponent } from './license_liveview'; | ||
import { LightLiveViewComponent } from './light_liveview'; | ||
import { SearchLiveViewComponent } from './live-search/component'; | ||
import { SalesDashboardLiveViewComponent } from './sales_dashboard_liveview'; | ||
|
||
const lvServer = new LiveViewServer({ | ||
// port: 3002, | ||
// rootView: "./examples/rootView.ejs", | ||
// viewsPath: "./examples/views", | ||
// support different templates? | ||
}); | ||
|
||
export const router: LiveViewRouter = { | ||
"/license": new LicenseLiveViewComponent(), | ||
'/sales-dashboard': new SalesDashboardLiveViewComponent(), | ||
'/search': new SearchLiveViewComponent(), | ||
"/autocomplete": new AutocompleteLiveViewComponent(), | ||
} | ||
|
||
// register all routes | ||
lvServer.registerLiveViewRoutes(router) | ||
|
||
// register single route | ||
lvServer.registerLiveViewRoute("/light", new LightLiveViewComponent()) | ||
|
||
// start server | ||
lvServer.start(); |
8 changes: 4 additions & 4 deletions
8
src/server/live/license_liveview.ts → src/examples/license_liveview.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
6 changes: 3 additions & 3 deletions
6
src/server/live/light_liveview.ts → src/examples/light_liveview.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
11 changes: 6 additions & 5 deletions
11
src/server/live/live-search/component.ts → src/examples/live-search/component.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
File renamed without changes.
10 changes: 5 additions & 5 deletions
10
src/server/live/sales_dashboard_liveview.ts → src/examples/sales_dashboard_liveview.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
"use strict"; | ||
exports.__esModule = true; | ||
exports.numberToCurrency = void 0; | ||
function numberToCurrency(amount) { | ||
var formatter = new Intl.NumberFormat('en-US', { | ||
style: 'currency', | ||
currency: 'USD' | ||
}); | ||
return formatter.format(amount); | ||
} | ||
exports.numberToCurrency = numberToCurrency; |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,93 +1 @@ | ||
import "reflect-metadata"; | ||
import path from "path" | ||
import express, { Request, Response } from 'express' | ||
import { router } from "./live/router"; | ||
import jwt from "jsonwebtoken"; | ||
import session, {MemoryStore} from "express-session"; | ||
import { nanoid } from "nanoid"; | ||
import { PhxSocket } from "./socket/types"; | ||
import { Server } from "http"; | ||
|
||
|
||
const app = express(); | ||
|
||
// TODO replace me with your own secret | ||
export const SIGNING_SECRET = "blah_secret"; | ||
export const sessionStore = new MemoryStore(); | ||
|
||
const publicPath = path.join(__dirname, "..", "dist", "client"); | ||
const viewsPath = path.join(__dirname, "..", "src", "server", "views"); | ||
|
||
app.set('view engine', 'ejs'); | ||
app.set("views", viewsPath) | ||
const server = new Server(app); | ||
|
||
app.use((req: Request, res: Response, next: Function) => { | ||
console.log("req.url", req.url); | ||
// console.log("req.path", req.path); | ||
next(); | ||
}); | ||
|
||
app.use(express.static(publicPath)) | ||
|
||
// configure session storage | ||
app.use(session({ | ||
secret: SIGNING_SECRET, | ||
resave: false, | ||
rolling: true, | ||
saveUninitialized: true, | ||
cookie: {secure: process.env.NODE_ENV === "production"}, | ||
store: sessionStore, | ||
})) | ||
// extend / define session interface | ||
declare module 'express-session' { | ||
interface SessionData { | ||
csrfToken: string; | ||
} | ||
} | ||
|
||
console.log("router", router); | ||
|
||
// register each route path to the component to be rendered | ||
Object.keys(router).forEach(key => { | ||
console.log("register route", key); | ||
app.get(key, (req: Request, res: Response) => { | ||
console.log("key", key); | ||
// new LiveViewId per HTTP requess? | ||
const liveViewId = nanoid(); | ||
const phxSocket: PhxSocket = { | ||
id: liveViewId, | ||
connected: false, // http request | ||
} | ||
|
||
// render the component | ||
const component = router[key]; | ||
const ctx = component.mount({}, {}, phxSocket); | ||
const view = component.render(ctx); | ||
|
||
// lookup / gen csrf token for this session | ||
if(!req.session.csrfToken) { | ||
req.session.csrfToken = nanoid(); | ||
} | ||
|
||
// render the view with all the data | ||
res.render("index", { | ||
page_title: "Live View", | ||
csrf_meta_tag: req.session.csrfToken, | ||
liveViewId, | ||
session: jwt.sign(JSON.stringify(req.session), SIGNING_SECRET), | ||
statics: jwt.sign(JSON.stringify(view.statics), SIGNING_SECRET), | ||
inner_content: view.toString() | ||
}) | ||
|
||
}) | ||
}) | ||
|
||
export {app}; | ||
|
||
// const port: number = 3002 | ||
|
||
// server.listen(port, function () { | ||
// console.log(`App is listening on port ${port} !`) | ||
// }) | ||
|
||
export * from "./live_view_server"; |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
import { LiveViewComponent, LiveViewRouter } from "./types"; | ||
import WebSocket from 'ws'; | ||
import http, { Server, createServer } from 'http'; | ||
import express from "express"; | ||
import { PhxSocket } from "./socket/types"; | ||
import { nanoid } from "nanoid"; | ||
import jwt from "jsonwebtoken"; | ||
import { onMessage } from "./socket/message_router"; | ||
import session, { MemoryStore } from "express-session"; | ||
import path from "path"; | ||
|
||
// extend / define session interface | ||
declare module 'express-session' { | ||
interface SessionData { | ||
csrfToken: string; | ||
} | ||
} | ||
|
||
export interface LiveViewServerOptions { | ||
port: number; | ||
rootView: string; | ||
viewsPath: string; | ||
signingSecret: string; | ||
sessionStore: session.Store; | ||
} | ||
|
||
export class LiveViewServer { | ||
private port: number = 4444; | ||
private rootView: string = "index.html.ejs"; | ||
private viewsPath: string = path.join(__dirname, "..", "..", "src", "server", "web", "views"); | ||
private signingSecret: string = nanoid(); | ||
private sessionStore:session.Store = new MemoryStore(); | ||
|
||
private _router: LiveViewRouter = {}; | ||
|
||
private _topicToPath: { [key: string]: string } = {}; | ||
|
||
constructor(options: Partial<LiveViewServerOptions>) { | ||
this.port = options.port ?? this.port; | ||
this.rootView = options.rootView ?? this.rootView; | ||
this.viewsPath = options.viewsPath ?? this.viewsPath; | ||
this.signingSecret = options.signingSecret ?? this.signingSecret; | ||
this.sessionStore = options.sessionStore ?? this.sessionStore; | ||
} | ||
|
||
registerLiveViewRoutes(router: LiveViewRouter) { | ||
this._router = { ...this._router, ...router }; | ||
} | ||
|
||
registerLiveViewRoute(path: string, component: LiveViewComponent<any>) { | ||
this._router[path] = component; | ||
} | ||
|
||
start() { | ||
console.log("starting") | ||
const app = this.buildExpressApp(); | ||
|
||
const httpServer = new Server(); | ||
const wsServer = new WebSocket.Server({ | ||
server: httpServer | ||
}); | ||
|
||
// register express app for http requests | ||
httpServer.on('request', app); | ||
|
||
// register websocket server ws requests | ||
wsServer.on('connection', socket => { | ||
// handle ws messages | ||
socket.on('message', message => { | ||
onMessage(socket, message, this._topicToPath, this._router); | ||
}); | ||
}); | ||
|
||
httpServer.listen(this.port, () => { | ||
console.log(`LiveView App is listening on port ${this.port} !`) | ||
}) | ||
} | ||
|
||
private buildExpressApp() { | ||
const app = express(); | ||
|
||
const publicPath = path.join(__dirname, "..", "client"); | ||
// console.log("publicPath", publicPath); | ||
|
||
app.use(express.static(publicPath)) | ||
|
||
app.set('view engine', 'ejs'); | ||
app.set("views", this.viewsPath) | ||
|
||
app.use(session({ | ||
secret: this.signingSecret, | ||
resave: false, | ||
rolling: true, | ||
saveUninitialized: true, | ||
cookie: {secure: process.env.NODE_ENV === "production"}, | ||
store: this.sessionStore, | ||
})) | ||
|
||
|
||
|
||
app.get('/:liveview', (req, res) => { | ||
const liveview = req.params.liveview; | ||
console.log("liveview", liveview); | ||
|
||
// new LiveViewId per HTTP requess? | ||
const liveViewId = nanoid(); // TODO allow option for id generator? | ||
const phxSocket: PhxSocket = { | ||
id: liveViewId, | ||
connected: false, // ws socket not connected on http request | ||
} | ||
|
||
// look up component for route | ||
const component = this._router[`/${liveview}`]; | ||
if (!component) { | ||
res.status(404).send("Not found"); | ||
return; | ||
} | ||
|
||
// mount and render component if found | ||
const ctx = component.mount({}, {}, phxSocket); | ||
const view = component.render(ctx); | ||
|
||
// lookup / gen csrf token for this session | ||
if(!req.session.csrfToken) { | ||
req.session.csrfToken = nanoid(); | ||
} | ||
|
||
// render the view with all the data | ||
res.render("index.html.ejs", { | ||
page_title: "Live View", | ||
csrf_meta_tag: req.session.csrfToken, | ||
liveViewId, | ||
session: jwt.sign(JSON.stringify(req.session), this.signingSecret), | ||
statics: jwt.sign(JSON.stringify(view.statics), this.signingSecret), | ||
inner_content: view.toString() | ||
}) | ||
}); | ||
|
||
return app; | ||
} | ||
} |
Oops, something went wrong.