Skip to content

Commit

Permalink
feat: more static files
Browse files Browse the repository at this point in the history
  • Loading branch information
e-kucheriavyi committed Nov 9, 2024
1 parent 8f6e19d commit a5454ca
Show file tree
Hide file tree
Showing 20 changed files with 166 additions and 62 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
# 0.2.3

- **feat:** read static images
- **feat:** default favicon
- **refactor:** static files moved to dedicated dir

# 0.2.2

- **feat:** static files
Expand Down
4 changes: 2 additions & 2 deletions example/config.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const path = require('path')
const { createConfig } = require('larana-js')
const { defineConfig } = require('larana-js')

module.exports = createConfig({
module.exports = defineConfig({
port: 1610,
defaultTheme: 'dark',
debug: false,
Expand Down
2 changes: 0 additions & 2 deletions example/pages/home-page.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,6 @@ class HomePage extends Page {
}

root() {
const { state } = this.useState()

return layout({
style: [
'body',
Expand Down
40 changes: 40 additions & 0 deletions example/pages/image-page.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
const { Page, layout, image } = require('larana-js')

const { header } = require('../components')

class ImagePage extends Page {
title() {
return 'Image example'
}

root({ w }) {
return layout({
outlineColor: '#00f',
id: 'body',
style: [
'body',
'column',
],
children: [
header({}),
layout({
id: 'layout1',
style: {
direction: w > 1028 ? 'row' : 'column',
size: 9,
padding: 'var:u2',
gap: 'var:u2',
},
outlineColor: '#0f0',
children: [
image({
src: '/static/images/larana.svg',
}),
],
}),
],
})
}
}

module.exports = { ImagePage }
1 change: 1 addition & 0 deletions example/pages/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@ module.exports = {
...require('./sizes-page.js'),
...require('./table-page.js'),
...require('./quiz-page.js'),
...require('./image-page.js'),
...require('./404-page.js'),
}
2 changes: 2 additions & 0 deletions example/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const {
NotFoundPage,
SizesPage,
TablePage,
ImagePage,
QuizPage,
} = require('./pages')

Expand All @@ -24,6 +25,7 @@ module.exports = {
{ path: '/sizes', name: 'sizes', page: SizesPage },
{ path: '/table', name: 'table', page: TablePage },
{ path: '/quiz', name: 'quiz', page: QuizPage },
{ path: '/image', name: 'image', page: ImagePage },

{ path: '404', name: 'not-found', page: NotFoundPage },
],
Expand Down
2 changes: 2 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,6 @@ module.exports = {
...require('./src/shared'),
resources: require('./src/resources'),
...require('./src/resources'),
static: require('./src/static'),
...require('./src/static'),
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "larana-js",
"version": "0.2.2",
"version": "0.2.3",
"description": "Real SSR framework",
"main": "index.js",
"scripts": {
Expand Down
2 changes: 1 addition & 1 deletion roadmap.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Roadmap

# 0.2.3
# 0.2.4

- fix: client fonts
- fix: images jittering
Expand Down
67 changes: 22 additions & 45 deletions src/app.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
const fs = require('node:fs')
const path = require('path')
const { WebSocketServer } = require('ws')
const { createServer } = require('http')
const { MemoryStateManager, Session } = require('./state')
Expand All @@ -9,15 +7,9 @@ const { Response, Request } = require('./network')
const { prepareTemplate } = require('./ui/client')
const { DefaultRouter } = require('./routing')
const { initDefaultStyleVars, initDefaultStyleNames } = require('./ui/style')

const readFavicon = () => {
// eslint-disable-next-line no-undef
const dir = __dirname
const clientPath = path.join(dir, 'static', 'favicon.ico')
return fs.readFileSync(clientPath, 'utf-8')
}

const favicon = readFavicon()
const { prepareStatic } = require('./static/read-static-file.js')
const { getContentType } = require('./static/get-content-type.js')
const { getFavicon } = require('./static/get-favicon.js')

class LaranaApp {
config = { ...defaultConfig }
Expand All @@ -30,6 +22,7 @@ class LaranaApp {
onServe = (data) => {}
onMessage = (data) => {}
onClose = (data) => {}
readStaticFile = (url, callback) => {}

constructor(options) {
const config = options.config
Expand Down Expand Up @@ -81,48 +74,32 @@ class LaranaApp {

initDefaultStyleVars()
initDefaultStyleNames()
}

async serveStatic(req, res) {
console.log(this.config.staticDir)

const url = req.url

const path = this.config.staticDir + url.replace('/static', '')
const ext = path.split('.').pop()

const contentTypes = {
'txt': 'text/plain',
'png': 'image/png',
'jpg': 'image/jpeg',
'webp': 'image/webp',
'svg': 'image/svg+xml',
'ico': 'image/x-icon',
// TODO: more types
}

const contentType = contentTypes[ext] ?? 'text/plain'

res.setHeader('Content-type', contentType)
this.readStaticFile = prepareStatic(this.config.staticDir)
}

fs.readFile(path, (err, data) => {
_serveStatic(req, res) {
this.readStaticFile(req.url, (err, data) => {
if (err) {
res.statusCode = 404
res.end()
return
}

const contentType = getContentType(req.url)
res.setHeader('Content-type', contentType)
res.statusCode = 200
res.end(data)
})
}

async serveFavicon(req, res) {
const path = this.config.staticDir + '/favicon.ico'
fs.readFile(path, (err, data) => {
_serveFavicon(_, res) {
this.readStaticFile('/static/favicon.ico', (err, data) => {
if (err) {
res.statusCode = 404
res.end()
getFavicon(({ favicon }) => {
res.statusCode = 200
res.end(favicon)
})
return
}

Expand All @@ -131,13 +108,13 @@ class LaranaApp {
})
}

server(req, res) {
_server(req, res) {
if (req.url === '/favicon.ico') {
this.serveFavicon(req, res)
this._serveFavicon(req, res)
return
}
if (this.config.staticDir && req.url.startsWith('/static/')) {
this.serveStatic(req, res)
this._serveStatic(req, res)
return
}
const route = this.router.resolve(req.url)
Expand Down Expand Up @@ -204,7 +181,7 @@ class LaranaApp {
this.onServe({ req, route, sessionId })
}

socket(ws) {
_socket(ws) {
ws.send('Connecting')

this.clients.add(ws)
Expand Down Expand Up @@ -280,11 +257,11 @@ class LaranaApp {
}

run() {
const server = createServer((req, res) => this.server(req, res))
const server = createServer((req, res) => this._server(req, res))

const wss = new WebSocketServer({ server })

wss.on('connection', (ws) => this.socket(ws))
wss.on('connection', (ws) => this._socket(ws))

server.listen(this.config.port, () => {
console.log(`Listening on port: ${this.config.port}`)
Expand Down
18 changes: 14 additions & 4 deletions src/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ const configSchemer = new Schemer({
nullable: true,
required: false,
},
host: {
type: 'string',
required: false,
},
})

const defaultConfig = {
Expand All @@ -77,8 +81,11 @@ const defaultConfig = {
defaultTheme: 'dark',
defaultLang: 'en',
staticDir: null,
host: 'http://localhost',
}

let config = { ...defaultConfig }

/**
* @param {{
* debug: boolean;
Expand All @@ -97,13 +104,16 @@ const defaultConfig = {
* }} config
* @returns validated config
*/
const createConfig = (config) => {
configSchemer.validate(config)
const defineConfig = (newConfig) => {
configSchemer.validate(newConfig)

let config = mergeDeep(defaultConfig, newConfig)

return mergeDeep(defaultConfig, config)
return Object.freeze(config)
}

module.exports = {
config,
defaultConfig,
createConfig,
defineConfig,
}
12 changes: 8 additions & 4 deletions src/resources/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
const QRCode = require('qrcode')

const resources = new Map()

const resource = (name, value = null) => {
Expand All @@ -22,8 +20,14 @@ const loadImage = async (src, onFirstLoad, retries = 3) => {
return
}
try {
const r = await fetch(src)
const b = Buffer.from(await r.arrayBuffer())
let b = ''

if (src.startsWith('/static')) {
} else {
const r = await fetch(src)
b = Buffer.from(await r.arrayBuffer())
}

const value = `data:image/png;base64,${b.toString('base64')}`

resource(src, value)
Expand Down
File renamed without changes.
Binary file removed src/static/favicon.ico
Binary file not shown.
23 changes: 23 additions & 0 deletions src/static/get-content-type.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
const contentTypes = {
'txt': 'text/plain',
'png': 'image/png',
'jpg': 'image/jpeg',
'jpeg': 'image/jpeg',
'webp': 'image/webp',
'svg': 'image/svg+xml',
'ico': 'image/x-icon',
// TODO: more types
}

const getContentType = (path) => {
const ext = path.split('.').pop()

const contentType = contentTypes[ext] ?? 'text/plain'

return contentType
}

module.exports = {
contentTypes,
getContentType,
}
14 changes: 14 additions & 0 deletions src/static/get-favicon.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
const fs = require('node:fs')
const { getContentType } = require('./get-content-type.js')

getContentType

const getFavicon = (callback) => {
const faviconPath = __dirname + '/default/favicon.ico'

fs.readFile(faviconPath, (_, data) => {
callback({ favicon: data, contentType: getContentType(faviconPath) })
})
}

module.exports = { getFavicon }
5 changes: 5 additions & 0 deletions src/static/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module.exports = {
...require('./get-content-type.js'),
...require('./read-static-file.js'),
...require('./get-favicon.js'),
}
15 changes: 15 additions & 0 deletions src/static/read-static-file.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
const fs = require('node:fs')

const prepareStatic = (staticDir) => {
return (url, callback) => {
const path = staticDir + url.replace('/static', '')

fs.readFile(path, (err, data) => {
callback(err, data)
})
}
}

module.exports = {
prepareStatic,
}
2 changes: 1 addition & 1 deletion src/ui/client/html/head.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>%TITLE%</title>
<link rel="shortcut icon" href="/static/favicon.ico" type="image/x-icon"/>
<link rel="shortcut icon" href="/favicon.ico" type="image/x-icon"/>
%META%
<style>
html, body, #canvas {
Expand Down
Loading

0 comments on commit a5454ca

Please sign in to comment.