Created
October 21, 2018 13:31
-
-
Save joelpurra/90a1f2d877e46b7a9eea45154da9645a to your computer and use it in GitHub Desktop.
monolith was taken so heres the makings to stonehenge
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
((dev) => { | |
"use strict"; | |
const fs = require('fs'); | |
const path = require('path'); | |
const express = require('express'); | |
const log_color = { | |
clear: "\x1b[0m", | |
read: "\x1b[34m", | |
write: "\x1b[33m", | |
error: "\x1b[31m", | |
preparing: "\x1b[36m", | |
server_up: "\x1b[32m" | |
}; | |
class Monolith { | |
constructor( | |
page = { | |
fpath: null, | |
title: null, | |
head: null, | |
styles: null, | |
content: null, | |
scripts: null | |
}, write = false) { | |
let { fpath = __dirname, title = 'sanity', head = '', styles = '', content = '', scripts = '' } = page; | |
this.title = title; | |
this.fpath = fpath; | |
this.head = this.concatonate(head); | |
this.styles = this.concatonate(styles); | |
this.content = this.concatonate(content); | |
this.scripts = this.concatonate(scripts); | |
this.page = null; | |
if (write === true) { | |
this.init(); | |
this.write(); | |
} | |
}; | |
init() { | |
console.log(log_color.preparing, `Preparing page for: ${this.title}`, log_color.clear); | |
// Template strings respect whitespace. | |
this.page = ( | |
`<!DOCTYPE html> | |
<html> | |
<head>${this.head} | |
<title>${this.title}</title> | |
<style>${this.styles} | |
</style> | |
</head> | |
<body>${ !!this.content ? "\n" + this.content : '' } | |
<script>${this.scripts}</script> | |
</body> | |
</html> | |
`); | |
}; | |
check(filepath) { | |
try { fs.accessSync(filepath, fs.F_OK); } | |
catch (e) { return false; } | |
return true; | |
} | |
read( | |
file, | |
type = null, | |
encoding = 'utf8' | |
) { | |
const fp = path.join(__dirname, file); | |
if (this.check(fp) == true) { | |
const data = fs.readFileSync(fp, encoding); | |
if (!type) { return data; } | |
else { | |
this.reassign( | |
{ [type]: (`${(typeof this[type] === 'string' ? this[type] : '')}${ data }`) } | |
); | |
} | |
console.log(log_color.read, `imported successfully: ${fp}`, log_color.clear); | |
} else console.log(log_color.error, `Unable to find: ${fp}`, log_color.clear); | |
} | |
write(output_path = null) { | |
output_path = ( | |
output_path != null | |
? output_path | |
: path.join(this.fpath, this.title, '.html') | |
); | |
fs.writeFileSync(output_path, this.page); | |
console.log(log_color.write, `file write to path at: ${output_path}\n`, log_color.clear); | |
}; | |
concatonate(data, indent='\n ') { | |
return (data instanceof Array ? data.join(indent) : data); | |
}; | |
reassign({ | |
title = null, | |
fpath = null, | |
head = null, | |
styles = null, | |
content = null, | |
scripts = null | |
}, | |
write = false | |
) { | |
const fields = arguments[0]; | |
const keys = Object.keys(fields); | |
for ( | |
let current_field = 0; | |
current_field < keys.length; | |
current_field++ | |
) { | |
let key_i = keys[current_field]; | |
this[key_i] = this.concatonate( | |
(typeof fields[key_i] === 'string') | |
? fields[key_i] | |
: this[key_i] | |
); | |
} | |
if (write == true) this.write(); | |
}; | |
} | |
class Ritual { | |
constructor( | |
pages = [ | |
{ path: '/', page: 'Hello World' }, | |
{ path: '/*', page: 'This endpoint has not been set.' } | |
], | |
router = express.Router() | |
) { | |
this.pages = pages; | |
for ( | |
let iter_pages = 0; | |
iter_pages < this.pages.length; | |
iter_pages++ | |
) { | |
let { | |
path = '', | |
page = '', | |
get = null, | |
post = null, | |
update = null, | |
remove = null } = this.pages[iter_pages]; | |
let dev_get = (req, res) => { res.send(page); }; | |
let dev_log = (req, res) => { console.log(req); }; | |
router.get( path, get || dev_get); | |
router.post( path, post || dev_log); | |
router.put( path, update || dev_log); | |
router.delete(path, remove || dev_log); | |
} this.ritual = router; | |
} | |
} | |
// Monolith test | |
let Homepage = new Monolith({content: 'lalalala it works'}); | |
// Filepath Type | |
Homepage.read(path.join('assets', 'general', 'includes.html'), 'head'); | |
Homepage.read(path.join('assets', 'general', 'index.css'), 'styles'); | |
Homepage.read(path.join('assets', 'general', 'basic-html.html'), 'content'); | |
Homepage.read(path.join('assets', 'general', 'scratch.js'), 'scripts'); | |
Homepage.init(); | |
// Ritual test | |
let FirstPage = { | |
path: '/' + Homepage.title, | |
page: Homepage.page, | |
get: (req, res) => { res.status(200).send(Homepage.page); } | |
}; | |
let TheUninitiated = new Ritual([ | |
FirstPage, | |
{ | |
path: '/', | |
page: 'It works, just goto ' + FirstPage.path | |
}, | |
{ | |
path: '/*', | |
page: '404 Page not found.' | |
} | |
]); | |
const port = process.env.PORT || 3000; | |
let client = express(); | |
client.use(express.static(path.join(__dirname, 'dist'))) | |
client.use(TheUninitiated.ritual); | |
client.listen(port, () => { | |
console.log(log_color.server_up, `Server initiated port: ${port}`, log_color.clear); | |
}); | |
Homepage.read('package.json', 'scripts'); | |
Homepage.init(); | |
})(true); |
I'v updated with ssl support and should be pushing changes tonight if you have any interest.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I'm made some progress by decoupling all dependencies and resolved the platform paths with the naive ternary on process so it will be runnable in the browser.
I believe a couple milestones I can set for myself are enforced https by default and the api for self modification in the context of the payload and user interface.
Authentication for a proper admin portal to access the cached version. No strategy in plan for writes back to the server.
How would you evaluate the attack surface area of express and eventually reaching confidence to allow a copy on write feature?
I'm content with a copy paste of browser view source as it maintains some semblance of security by not exposing fs to the internet.
It also forces manual audit.
I'v never shared code, any advice for placing my repo on npm?