Initial commit of framework
This commit is contained in:
0
app/assets/.gitkeep
Normal file
0
app/assets/.gitkeep
Normal file
BIN
app/assets/favicon.ico
Normal file
BIN
app/assets/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
BIN
app/assets/flitter.png
Normal file
BIN
app/assets/flitter.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 19 KiB |
28
app/controllers/Home.controller.js
Normal file
28
app/controllers/Home.controller.js
Normal file
@@ -0,0 +1,28 @@
|
||||
const { Controller } = require('libflitter')
|
||||
|
||||
/*
|
||||
* Home Controller
|
||||
* -------------------------------------------------------------
|
||||
* Controller for the main homepage of this Flitter app. Methods here
|
||||
* are used as handlers for routes specified in the route files.
|
||||
*/
|
||||
class Home extends Controller {
|
||||
|
||||
/*
|
||||
* Serve the main welcome page.
|
||||
*/
|
||||
welcome(req, res){
|
||||
|
||||
/*
|
||||
* Return the welcome view.
|
||||
* The page() method is added by Flitter and passes some
|
||||
* helpful contextual data to the view as well.
|
||||
*/
|
||||
return res.page('welcome', {
|
||||
user: req.user,
|
||||
T: req.T,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Home
|
||||
30
app/models/Example.model.js
Normal file
30
app/models/Example.model.js
Normal file
@@ -0,0 +1,30 @@
|
||||
const { Model } = require('flitter-orm')
|
||||
|
||||
/*
|
||||
* Example Model
|
||||
* -------------------------------------------------------------
|
||||
* This is a sample model. The schema or structure of the model should
|
||||
* be specified here. It is then passed to flitter-orm and can be accessed
|
||||
* globally using the canonical models service.
|
||||
*/
|
||||
class Example extends Model {
|
||||
static get services() {
|
||||
return [...super.services, 'output']
|
||||
}
|
||||
|
||||
/*
|
||||
* Define the flitter-orm schema of the model.
|
||||
*/
|
||||
static get schema() {
|
||||
return {
|
||||
name: String,
|
||||
create_date: {type: Date, default: () => new Date},
|
||||
}
|
||||
}
|
||||
|
||||
log_name() {
|
||||
this.output.info(`[Example Model] ${this.name}`)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = exports = Example
|
||||
18
app/routing/Middleware.js
Normal file
18
app/routing/Middleware.js
Normal file
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Global Middleware Definitions
|
||||
* -------------------------------------------------------------
|
||||
* These middleware are applied, in order, before every request that
|
||||
* Flitter handles, regardless of request type. Each middleware class
|
||||
* can be referenced using the middleware's Flitter canonical name.
|
||||
*
|
||||
* Route-specific middleware should be specified in the corresponding
|
||||
* routes file.
|
||||
*/
|
||||
const Middleware = [
|
||||
|
||||
// Injects the RequestLocalizationHelper
|
||||
"i18n:Localize",
|
||||
|
||||
]
|
||||
|
||||
module.exports = exports = Middleware
|
||||
32
app/routing/middleware/HomeLogger.middleware.js
Normal file
32
app/routing/middleware/HomeLogger.middleware.js
Normal file
@@ -0,0 +1,32 @@
|
||||
const { Middleware } = require('libflitter')
|
||||
|
||||
/*
|
||||
* HomeLogger Middleware
|
||||
* -------------------------------------------------------------
|
||||
* This is a sample middleware. It simply prints a console message when
|
||||
* the route that it is tied to is accessed. By default, it is called if
|
||||
* the '/' route is accessed. It can be injected in routes globally using
|
||||
* the middlewares service.
|
||||
*/
|
||||
class HomeLogger extends Middleware {
|
||||
static get services() {
|
||||
return [...super.services, 'output']
|
||||
}
|
||||
|
||||
/*
|
||||
* Run the middleware test.
|
||||
* This method is required by all Flitter middleware.
|
||||
* It should either call the next function in the stack,
|
||||
* or it should handle the response accordingly.
|
||||
*/
|
||||
test(req, res, next, args) {
|
||||
this.output.debug('Home was accessed!')
|
||||
|
||||
/*
|
||||
* Call the next function in the stack.
|
||||
*/
|
||||
next()
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = HomeLogger
|
||||
7
app/routing/middleware/i18n/Localize.middleware.js
Normal file
7
app/routing/middleware/i18n/Localize.middleware.js
Normal file
@@ -0,0 +1,7 @@
|
||||
const Middleware = require('flitter-i18n/src/middleware/Localize')
|
||||
|
||||
class LocalizeMiddleware extends Middleware {
|
||||
|
||||
}
|
||||
|
||||
module.exports = exports = LocalizeMiddleware
|
||||
7
app/routing/middleware/i18n/Scope.middleware.js
Normal file
7
app/routing/middleware/i18n/Scope.middleware.js
Normal file
@@ -0,0 +1,7 @@
|
||||
const Middleware = require('flitter-i18n/src/middleware/Scope')
|
||||
|
||||
class ScopeMiddleware extends Middleware {
|
||||
|
||||
}
|
||||
|
||||
module.exports = exports = ScopeMiddleware
|
||||
43
app/routing/middleware/util/Config.middleware.js
Normal file
43
app/routing/middleware/util/Config.middleware.js
Normal file
@@ -0,0 +1,43 @@
|
||||
const { Middleware } = require('libflitter')
|
||||
|
||||
/*
|
||||
* Config Middleware
|
||||
* -------------------------------------------------------------
|
||||
* Checks the specified configuration key (and optionally the value).
|
||||
* If the configuration matches the required value, the request can
|
||||
* proceed. Otherwise, a 404 will be returned.
|
||||
*
|
||||
* To use, add the call to your route's middleware:
|
||||
*
|
||||
* ['middleware::util:Config', {key: 'server.ssl.test', value: true}],
|
||||
*
|
||||
* In this case, the request would be allowed to proceed in the case:
|
||||
* services.configs.get('server.ssl.test') === true
|
||||
*
|
||||
* The 'value' attribute is optional. If none is provided, the request
|
||||
* can proceed if the config value is truthy.
|
||||
*/
|
||||
class Config extends Middleware {
|
||||
static get services() {
|
||||
return [...super.services, 'configs', 'output']
|
||||
}
|
||||
|
||||
/*
|
||||
* Run the middleware test.
|
||||
*/
|
||||
test(req, res, next, args = {}){
|
||||
if ( !args.key ) return res.error(500)
|
||||
|
||||
const config = this.configs.get(args.key)
|
||||
|
||||
if ( !args.value && !config ) {
|
||||
if ( !config && typeof config === 'undefined' )
|
||||
this.output.warn(`util:Config middleware check failed because it tried to access a config that doesn't exist. (${key})`)
|
||||
return res.error(404)
|
||||
}
|
||||
else if ( args.value && args.value !== config ) return res.error(404)
|
||||
else return next()
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Config
|
||||
71
app/routing/routers/index.routes.js
Normal file
71
app/routing/routers/index.routes.js
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Index Routes
|
||||
* -------------------------------------------------------------
|
||||
* This is a sample routes file. Routes and their handlers should be
|
||||
* defined here, but no logic should occur.
|
||||
*/
|
||||
const index = {
|
||||
|
||||
/*
|
||||
* Define the prefix applied to each of these routes.
|
||||
* For example, if prefix is '/auth':
|
||||
* '/' becomes '/auth'
|
||||
* '/login' becomes '/auth/login'
|
||||
*/
|
||||
prefix: '/',
|
||||
|
||||
/*
|
||||
* Define middleware that should be applied to all
|
||||
* routes defined in this file. Middleware should be
|
||||
* included using its non-prefixed canonical name.
|
||||
*
|
||||
* You can pass arguments along to a middleware by
|
||||
* specifying it as an array where the first element
|
||||
* is the canonical name of the middleware and the
|
||||
* second element is the argument passed to the
|
||||
* handler's test() method.
|
||||
*/
|
||||
middleware: [
|
||||
// Sets the locale scope
|
||||
['i18n:Scope', {scope: 'common'}],
|
||||
|
||||
['HomeLogger', {note: 'arguments can be specified as the second element in this array'}],
|
||||
// 'MiddlewareName', // Or without arguments
|
||||
],
|
||||
|
||||
/*
|
||||
* Define GET routes.
|
||||
* These routes are registered as GET methods.
|
||||
* Handlers for these routes should be specified as
|
||||
* an array of canonical references to controller methods
|
||||
* or middleware that are applied in order.
|
||||
*/
|
||||
get: {
|
||||
// handlers should be a list of either controller:: or middleware:: references
|
||||
// e.g. middleware::HomeLogger
|
||||
// e.g. controller::Home.welcome
|
||||
'/': [
|
||||
'controller::Home.welcome'
|
||||
],
|
||||
|
||||
// Placeholder for auth dashboard. You'd replace this with
|
||||
// your own route protected by 'middleware::auth:UserOnly'
|
||||
'/dash': [ 'controller::Home.welcome' ],
|
||||
},
|
||||
|
||||
/*
|
||||
* Define POST routes.
|
||||
* These routes are registered as POST methods.
|
||||
* Handlers for these routes should be specified as
|
||||
* an array of canonical references to controller methods
|
||||
* or middleware that are applied in order.
|
||||
*/
|
||||
post: {
|
||||
|
||||
},
|
||||
|
||||
// You can include other HTTP verbs here.
|
||||
// Supported ones are: get, post, put, delete, copy, patch
|
||||
}
|
||||
|
||||
module.exports = exports = index
|
||||
7
app/views/errors/400.pug
Normal file
7
app/views/errors/400.pug
Normal file
@@ -0,0 +1,7 @@
|
||||
extends error
|
||||
|
||||
block head
|
||||
title Bad Request | #{_app ? _app.name : 'Flitter'}
|
||||
|
||||
block message
|
||||
p.flitter-name 400: Bad Request
|
||||
7
app/views/errors/401.pug
Normal file
7
app/views/errors/401.pug
Normal file
@@ -0,0 +1,7 @@
|
||||
extends error
|
||||
|
||||
block head
|
||||
title Access Denied | #{_app ? _app.name : 'Flitter'}
|
||||
|
||||
block message
|
||||
p.flitter-name 401: Access Denied
|
||||
7
app/views/errors/403.pug
Normal file
7
app/views/errors/403.pug
Normal file
@@ -0,0 +1,7 @@
|
||||
extends error
|
||||
|
||||
block head
|
||||
title Forbidden | #{_app ? _app.name : 'Flitter'}
|
||||
|
||||
block message
|
||||
p.flitter-name 403: Forbidden
|
||||
7
app/views/errors/404.pug
Normal file
7
app/views/errors/404.pug
Normal file
@@ -0,0 +1,7 @@
|
||||
extends error
|
||||
|
||||
block head
|
||||
title Not Found | #{_app ? _app.name : 'Flitter'}
|
||||
|
||||
block message
|
||||
p.flitter-name 404: Not Found
|
||||
9
app/views/errors/418.pug
Normal file
9
app/views/errors/418.pug
Normal file
@@ -0,0 +1,9 @@
|
||||
extends error
|
||||
|
||||
block head
|
||||
title I'm a Teapot | #{_app ? _app.name : 'Flitter'}
|
||||
|
||||
block message
|
||||
p.flitter-name
|
||||
a(href='https://en.wikipedia.org/wiki/HTTP_418') 418: I'm a Teapot
|
||||
p.flitter-name Thank you for using Flitter. How'd you get here, anyway?
|
||||
7
app/views/errors/500.pug
Normal file
7
app/views/errors/500.pug
Normal file
@@ -0,0 +1,7 @@
|
||||
extends error
|
||||
|
||||
block head
|
||||
title Internal Server Error | #{_app ? _app.name : 'Flitter'}
|
||||
|
||||
block message
|
||||
p.flitter-name 500: Internal Server Error
|
||||
47
app/views/errors/development.pug
Normal file
47
app/views/errors/development.pug
Normal file
@@ -0,0 +1,47 @@
|
||||
html
|
||||
head
|
||||
title Uh-Oh! | #{_app ? _app.name : 'Flitter'}
|
||||
style(type="text/css").
|
||||
@import url('https://fonts.googleapis.com/css?family=Rajdhani');
|
||||
@import url('https://fonts.googleapis.com/css?family=Oxygen+Mono');
|
||||
html,
|
||||
body {
|
||||
background-color: #c7dbdf;
|
||||
font-family: "Rajdhani",sans-serif;
|
||||
padding-left: 2%;
|
||||
padding-top: 2%;
|
||||
}
|
||||
p {
|
||||
font-family: "Oxygen Mono",sans-serif;
|
||||
font-size: 14pt;
|
||||
}
|
||||
body
|
||||
h1 Error: #{error ? error.message : (message ? message : 'An unknown error has occurred.')}
|
||||
h3 Status: #{error ? error.status : (status ? status : 500)}
|
||||
h4#errmsg
|
||||
if error
|
||||
p !{error.stack.replace(/\n/g, '<br>')}
|
||||
|
||||
script.
|
||||
const errors = [
|
||||
'Insert your Windows installation disc and restart your computer.',
|
||||
'I am a teapot.',
|
||||
'Printing not supported on this printer.',
|
||||
'Keyboard not found. Press F1 to continue.',
|
||||
'Bailing out. You\'re on your own. Good luck.',
|
||||
'A team of highly trained monkeys is on its way.',
|
||||
'Well.... something happened.',
|
||||
'Beats the hell out of me, but something went wrong.',
|
||||
'Yeaaaaah... if you could, like, not, that\'d be great.',
|
||||
'I\'m fine. Everything is fine.',
|
||||
'Blocked by Windows Parental Controls.',
|
||||
'This is not the bug you\'re looking for.',
|
||||
'Houston, we have a problem.',
|
||||
'I don\'t think we\'re in Kansas anymore...',
|
||||
'Please enable ActiveX to continue. ;)',
|
||||
'Your PC ran into a wall.',
|
||||
'Are you on drugs?',
|
||||
'Error: Success',
|
||||
]
|
||||
|
||||
document.getElementById('errmsg').innerHTML = errors[Math.floor(Math.random()*errors.length)]
|
||||
33
app/views/errors/error.pug
Normal file
33
app/views/errors/error.pug
Normal file
@@ -0,0 +1,33 @@
|
||||
html
|
||||
head
|
||||
block head
|
||||
style(type="text/css").
|
||||
@import url('https://fonts.googleapis.com/css?family=Rajdhani');
|
||||
html,
|
||||
body {
|
||||
height: 100%;
|
||||
overflow-y: hidden;
|
||||
background-color: #c7dbdf;
|
||||
}
|
||||
|
||||
.flitter-container {
|
||||
height: 60%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.flitter-image {
|
||||
height: 150px;
|
||||
}
|
||||
|
||||
.flitter-name {
|
||||
font-family: "Rajdhani";
|
||||
font-size: 50pt;
|
||||
margin-left: 35px;
|
||||
color: #00323d;
|
||||
}
|
||||
body
|
||||
.flitter-container
|
||||
img.flitter-image(src="/assets/flitter.png")
|
||||
block message
|
||||
46
app/views/welcome.pug
Normal file
46
app/views/welcome.pug
Normal file
@@ -0,0 +1,46 @@
|
||||
html
|
||||
head
|
||||
title #{T('welcome')} | #{_app.name}
|
||||
style(type="text/css").
|
||||
@import url('https://fonts.googleapis.com/css?family=Rajdhani');
|
||||
html,
|
||||
body {
|
||||
height: 100%;
|
||||
overflow-y: hidden;
|
||||
background-color: #c7dbdf;
|
||||
}
|
||||
|
||||
.flitter-container {
|
||||
height: 60%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.flitter-image {
|
||||
height: 150px;
|
||||
}
|
||||
|
||||
.flitter-name {
|
||||
font-family: "Rajdhani";
|
||||
font-size: 50pt;
|
||||
margin-left: 35px;
|
||||
color: #00323d;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.flitter-text {
|
||||
font-family: "Rajdhani";
|
||||
font-size: 24pt;
|
||||
color: #00323d;
|
||||
}
|
||||
body
|
||||
.flitter-container
|
||||
img.flitter-image(src="/assets/flitter.png")
|
||||
a.flitter-name(href="https://flitter.garrettmills.dev/" target="_blank") #{T('powered_by_flitter')}
|
||||
if user
|
||||
.flitter-container
|
||||
p.flitter-text #{T('welcome')}, #{user.uid}! <a href="/auth/logout">#{T('log_out')}</a>
|
||||
else
|
||||
.flitter-container
|
||||
p.flitter-text #{T('new_to_flitter')} <a href="https://flitter.garrettmills.dev/" target="_blank">#{T('start_here')}</a>
|
||||
Reference in New Issue
Block a user