Browse Source
Created Webpack, Nodemon, and BrowserSync harness with UIkit, FontAwesome, Pretty Checkbox configured and tested.develop
16 changed files with 6045 additions and 0 deletions
@ -0,0 +1,4 @@ |
|||||
|
.env |
||||
|
|
||||
|
node_modules |
||||
|
dist |
@ -0,0 +1,25 @@ |
|||||
|
{ |
||||
|
"bitwise": true, |
||||
|
"browser": true, |
||||
|
"curly": true, |
||||
|
"eqeqeq": true, |
||||
|
"latedef": true, |
||||
|
"noarg": true, |
||||
|
"node": true, |
||||
|
"strict": "global", |
||||
|
"undef": true, |
||||
|
"unused": true, |
||||
|
"futurehostile": true, |
||||
|
"esversion": 11, |
||||
|
"mocha": true, |
||||
|
"globals": { |
||||
|
"markdown": true, |
||||
|
"moment": true, |
||||
|
"numeral": true, |
||||
|
"io": true, |
||||
|
"Chart": true, |
||||
|
"CodeMirror": true, |
||||
|
"UIkit": true, |
||||
|
"twttr": true |
||||
|
} |
||||
|
} |
@ -0,0 +1,2 @@ |
|||||
|
DTP Chat Copyright (C) 2024 DTP Technologies, LLC |
||||
|
All Rights Reserved |
@ -0,0 +1,37 @@ |
|||||
|
// home.js
|
||||
|
// Copyright (C) 2024 DTP Technologies, LLC
|
||||
|
// All Rights Reserved
|
||||
|
|
||||
|
'use strict'; |
||||
|
|
||||
|
import express from 'express'; |
||||
|
|
||||
|
export default class HomeController { |
||||
|
|
||||
|
static get isHome ( ) { return true; } |
||||
|
static get slug ( ) { return 'home'; } |
||||
|
static get className ( ) { return 'HomeController'; } |
||||
|
|
||||
|
constructor (dtp) { |
||||
|
this.dtp = dtp; |
||||
|
} |
||||
|
|
||||
|
static create (dtp) { |
||||
|
const instance = new HomeController(dtp); |
||||
|
return instance; |
||||
|
} |
||||
|
|
||||
|
async start ( ) { |
||||
|
const router = express.Router(); |
||||
|
this.dtp.app.use('/', router); |
||||
|
|
||||
|
router.get('/', this.getHome.bind(this)); |
||||
|
|
||||
|
return router; |
||||
|
} |
||||
|
|
||||
|
async getHome (req, res) { |
||||
|
res.locals.pageDescription = 'DTP Chat Home'; |
||||
|
res.render('home'); |
||||
|
} |
||||
|
} |
@ -0,0 +1,20 @@ |
|||||
|
link(rel="apple-touch-icon" sizes="57x57" href=`/img/icon/${site.domainKey}/icon-57x57.png?v=${pkg.version}`) |
||||
|
link(rel="apple-touch-icon" sizes="60x60" href=`/img/icon/${site.domainKey}/icon-60x60.png?v=${pkg.version}`) |
||||
|
link(rel="apple-touch-icon" sizes="72x72" href=`/img/icon/${site.domainKey}/icon-72x72.png?v=${pkg.version}`) |
||||
|
link(rel="apple-touch-icon" sizes="76x76" href=`/img/icon/${site.domainKey}/icon-76x76.png?v=${pkg.version}`) |
||||
|
link(rel="apple-touch-icon" sizes="114x114" href=`/img/icon/${site.domainKey}/icon-114x114.png?v=${pkg.version}`) |
||||
|
link(rel="apple-touch-icon" sizes="120x120" href=`/img/icon/${site.domainKey}/icon-120x120.png?v=${pkg.version}`) |
||||
|
link(rel="apple-touch-icon" sizes="144x144" href=`/img/icon/${site.domainKey}/icon-144x144.png?v=${pkg.version}`) |
||||
|
link(rel="apple-touch-icon" sizes="152x152" href=`/img/icon/${site.domainKey}/icon-152x152.png?v=${pkg.version}`) |
||||
|
link(rel="apple-touch-icon" sizes="180x180" href=`/img/icon/${site.domainKey}/icon-180x180.png?v=${pkg.version}`) |
||||
|
link(rel="icon" type="image/png" sizes="32x32" href=`/img/icon/${site.domainKey}/icon-32x32.png?v=${pkg.version}`) |
||||
|
link(rel="icon" type="image/png" sizes="96x96" href=`/img/icon/${site.domainKey}/icon-96x96.png?v=${pkg.version}`) |
||||
|
link(rel="icon" type="image/png" sizes="16x16" href=`/img/icon/${site.domainKey}/icon-16x16.png?v=${pkg.version}`) |
||||
|
link(rel="icon" type="image/png" sizes="512x512" href=`/img/icon/${site.domainKey}/icon-512x512.png?v=${pkg.version}`) |
||||
|
link(rel="icon" type="image/png" sizes="384x384" href=`/img/icon/${site.domainKey}/icon-384x384.png?v=${pkg.version}`) |
||||
|
link(rel="icon" type="image/png" sizes="256x256" href=`/img/icon/${site.domainKey}/icon-512x512.png?v=${pkg.version}`) |
||||
|
link(rel="icon" type="image/png" sizes="192x192" href=`/img/icon/${site.domainKey}/icon-192x192.png?v=${pkg.version}`) |
||||
|
link(rel="manifest" href=`/manifest.json?v=${pkg.version}`) |
||||
|
meta(name="msapplication-TileColor" content="#f1c52f") |
||||
|
meta(name="msapplication-TileImage" content=`/img/icon/ms-icon-144x144.png?v=${pkg.version}`) |
||||
|
meta(name="theme-color" content="#f1c52f") |
@ -0,0 +1,78 @@ |
|||||
|
block facebook-card |
||||
|
- |
||||
|
var fbCardImg = `https://${site.domain}/img/social-cards/${site.domain}.png?v=${pkg.version}`; |
||||
|
var fbContentType = 'website'; |
||||
|
var fbTitle = pageTitle || site.name; |
||||
|
var fbDescription = pageDescription || site.description; |
||||
|
var fbVideo, fbVideoWidth, fbVideoHeight; |
||||
|
|
||||
|
if ((currentView === 'dvr') && (viewName === 'home-player')) { |
||||
|
// use default social card assigned above |
||||
|
fbTitle = pageTitle; |
||||
|
fbDescription = pageDescription; |
||||
|
} else if (episode && episode.images && episode.images.thumbnail) { |
||||
|
if (clip && clip.images && clip.images.thumbnail) { |
||||
|
fbCardImg = `https://${site.domain}/image/${clip.images.thumbnail._id || clip.images.thumbnail}`; |
||||
|
fbTitle = clip.title; |
||||
|
fbDescription = clip.description; |
||||
|
fbContentType = 'video'; |
||||
|
fbVideoEmbedUrl = `https://${site.domain}/dvr/${clip.episode._id}/clip/${clip._id}/embed`; |
||||
|
fbVideoType = 'video/mp4'; |
||||
|
fbVideoWidth = 960; |
||||
|
fbVideoHeight = 540; |
||||
|
} else { |
||||
|
fbCardImg = `https://${site.domain}/image/${episode.images.thumbnail._id || episode.images.thumbnail}`; |
||||
|
fbTitle = episode.title; |
||||
|
fbDescription = episode.description; |
||||
|
} |
||||
|
} else if (clip && clip.images && clip.images.thumbnail) { |
||||
|
fbCardImg = `https://${site.domain}/image/${clip.images.thumbnail._id || clip.images.thumbnail}`; |
||||
|
fbTitle = clip.title; |
||||
|
fbDescription = clip.description; |
||||
|
fbContentType = 'video'; |
||||
|
fbVideoEmbedUrl = `https://${site.domain}/dvr/${clip.episode._id}/clip/${clip._id}/embed`; |
||||
|
fbVideoType = 'video/mp4'; |
||||
|
fbVideoWidth = 960; |
||||
|
fbVideoHeight = 540; |
||||
|
} else if (video && video.images && video.images.thumbnail) { |
||||
|
fbCardImg = `https://${site.domain}/image/${video.images.thumbnail._id || video.images.thumbnail}`; |
||||
|
fbTitle = video.title; |
||||
|
fbDescription = video.description; |
||||
|
} else if (userProfile) { |
||||
|
fbCardImg = getUserPictureUrl(userProfile, 'large'); |
||||
|
fbTitle = pageTitle; |
||||
|
fbDescription = pageDescription; |
||||
|
} else if (channel && channel.images && channel.images.thumbnail) { |
||||
|
fbCardImg = `https://${site.domain}/image/${channel.images.thumbnail._id || channel.images.thumbnail}`; |
||||
|
fbTitle = channel.name; |
||||
|
fbDescription = channel.description; |
||||
|
} else if (advertisement && advertisement.content) { |
||||
|
fbTitle = advertisement.content.title; |
||||
|
if (advertisement.content.body) { |
||||
|
fbDescription = marked.parse(advertisement.content.body, { renderer: fullMarkdownRenderer }).trim(); |
||||
|
} |
||||
|
switch (advertisement.content.mediaType) { |
||||
|
case 'Image': |
||||
|
fbCardImg = `https://${site.domain}/image/${advertisement.content.media._id}`; |
||||
|
break; |
||||
|
case 'Video': |
||||
|
if (advertisement.content && advertisement.content.media && advertisement.content.media.images && advertisement.content.media.images.thumbnail) { |
||||
|
fbCardImg = `https://${site.domain}/image/${advertisement.content.media.images.thumbnail._id || advertisement.content.media.images.thumbnail}`; |
||||
|
} |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
meta(property='og:site_name', content= site.name) |
||||
|
meta(property='og:type', content= fbContentType) |
||||
|
if fbContentType === 'video' |
||||
|
meta(property='og:video', content= fbVideoEmbedUrl) |
||||
|
meta(property='og:video:type', content= fbVideoType) |
||||
|
meta(property='og:video:width', content= fbVideoWidth) |
||||
|
meta(property='og:video:height', content= fbVideoHeight) |
||||
|
meta(property='og:image', content= fbCardImg) |
||||
|
meta(property='og:image:alt', content= `${fbTitle} | ${fbDescription}`) |
||||
|
meta(property='og:url', content= `https://${site.domain}${dtp.request.originalUrl}`) |
||||
|
meta(property='og:title', content= fbTitle) |
||||
|
if fbDescription && (fbDescription.length > 0) |
||||
|
meta(property='og:description', content= fbDescription) |
@ -0,0 +1,75 @@ |
|||||
|
block twitter-card |
||||
|
- |
||||
|
var twCardType = 'summary_large_image'; |
||||
|
var twCardImg = `https://${site.domain}/img/social-cards/${site.domain}.png?v=${pkg.version}`; |
||||
|
var twTitle = pageTitle || `${site.name} | ${site.description}`; |
||||
|
var twDescription = pageDescription || site.description; |
||||
|
var twPlayerEmbedUrl, twPlayerStreamUrl, twPlayerWidth, twPlayerHeight; |
||||
|
|
||||
|
if ((currentView === 'dvr') && (viewName === 'home-player')) { |
||||
|
// use default social card assigned above |
||||
|
twTitle = pageTitle; |
||||
|
twDescription = pageDescription; |
||||
|
} else if (episode && episode.images && episode.images.thumbnail) { |
||||
|
if (clip && clip.images && clip.images.thumbnail) { |
||||
|
twCardImg = `https://${site.domain}/image/${clip.images.thumbnail._id || clip.images.thumbnail}`; |
||||
|
twTitle = clip.title; |
||||
|
twDescription = clip.description; |
||||
|
twCardType = 'player'; |
||||
|
twPlayerEmbedUrl = `https://${site.domain}/dvr/${clip.episode._id}/clip/${clip._id}/embed`; |
||||
|
twPlayerStreamUrl = `https://${site.domain}/dvr/${clip.episode._id}/clip/${clip._id}/media`; |
||||
|
twPlayerWidth = 960; |
||||
|
twPlayerHeight = 540; |
||||
|
} else { |
||||
|
twCardImg = `https://${site.domain}/image/${episode.images.thumbnail._id || episode.images.thumbnail}`; |
||||
|
twTitle = episode.title; |
||||
|
twDescription = episode.description; |
||||
|
} |
||||
|
} else if (clip && clip.images && clip.images.thumbnail) { |
||||
|
twCardImg = `https://${site.domain}/image/${clip.images.thumbnail._id || clip.images.thumbnail}`; |
||||
|
twTitle = clip.title; |
||||
|
twDescription = clip.description; |
||||
|
twCardType = 'player'; |
||||
|
twPlayerEmbedUrl = `https://${site.domain}/dvr/${clip.episode._id}/clip/${clip._id}/embed`; |
||||
|
twPlayerStreamUrl = `https://${site.domain}/dvr/${clip.episode._id}/clip/${clip._id}/media`; |
||||
|
twPlayerWidth = 960; |
||||
|
twPlayerHeight = 540; |
||||
|
} else if (video && video.images && video.images.thumbnail) { |
||||
|
twCardImg = `https://${site.domain}/image/${video.images.thumbnail._id || video.images.thumbnail}`; |
||||
|
twTitle = video.title; |
||||
|
twDescription = video.description; |
||||
|
} else if (userProfile) { |
||||
|
twCardImg = getUserPictureUrl(userProfile, 'large'); |
||||
|
twTitle = pageTitle; |
||||
|
twDescription = pageDescription; |
||||
|
} else if (channel && channel.images && channel.images.thumbnail) { |
||||
|
twCardImg = `https://${site.domain}/image/${channel.images.thumbnail._id || channel.images.thumbnail}`; |
||||
|
twTitle = channel.name; |
||||
|
twDescription = channel.description; |
||||
|
} else if (advertisement && advertisement.content) { |
||||
|
twTitle = advertisement.content.title; |
||||
|
if (advertisement.content.body) { |
||||
|
twDescription = marked.parse(advertisement.content.body, { renderer: fullMarkdownRenderer }).trim(); |
||||
|
} |
||||
|
switch (advertisement.content.mediaType) { |
||||
|
case 'Image': |
||||
|
twCardImg = `https://${site.domain}/image/${advertisement.content.media._id}`; |
||||
|
break; |
||||
|
case 'Video': |
||||
|
if (advertisement.content && advertisement.content.media && advertisement.content.media.images && advertisement.content.media.images.thumbnail) { |
||||
|
twCardImg = `https://${site.domain}/image/${advertisement.content.media.images.thumbnail._id || advertisement.content.media.images.thumbnail}`; |
||||
|
} |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
meta(name='twitter:card', content= twCardType) |
||||
|
meta(name='twitter:image' content= twCardImg) |
||||
|
meta(name='twitter:title', content= twTitle) |
||||
|
if twDescription && (twDescription.length > 0) |
||||
|
meta(name='twitter:description', content= twDescription) |
||||
|
if twCardType === 'player' |
||||
|
meta(name='twitter:player', content= twPlayerEmbedUrl) |
||||
|
meta(name='twitter:player:stream', content= twPlayerStreamUrl) |
||||
|
meta(name='twitter:player:width', content= twPlayerWidth) |
||||
|
meta(name='twitter:player:height', content= twPlayerHeight) |
@ -0,0 +1,13 @@ |
|||||
|
include layout/main |
||||
|
block view-content |
||||
|
|
||||
|
section.uk-section.uk-section-default |
||||
|
.uk-container |
||||
|
h1= site.name |
||||
|
div= site.description |
||||
|
|
||||
|
p The app is doing something else. |
||||
|
|
||||
|
p |
||||
|
span |
||||
|
i.fas.fa-home |
@ -0,0 +1,84 @@ |
|||||
|
doctype html |
||||
|
html(lang='en', data-obs-widget= obsWidget) |
||||
|
head |
||||
|
meta(charset='UTF-8') |
||||
|
meta(name='viewport', content='width=device-width, initial-scale=1.0') |
||||
|
meta(name='description', content= pageDescription || site.description) |
||||
|
|
||||
|
title= pageTitle ? `${pageTitle} | ${site.name}` : site.name |
||||
|
|
||||
|
meta(name="robots", content= "index,follow") |
||||
|
meta(name="googlebot", content= "index,follow") |
||||
|
meta(name="theme-color", content="#ff0013") |
||||
|
meta(name="apple-mobile-web-app-status-bar-style", content="black-translucent") |
||||
|
|
||||
|
block css |
||||
|
|
||||
|
link(rel='stylesheet', href=`/fontawesome/css/all.min.css?v=${pkg.version}`) |
||||
|
|
||||
|
block vendorcss |
||||
|
|
||||
|
link(rel='stylesheet', href=`/dist/chat-client.css?v=${pkg.version}`) |
||||
|
link(rel='stylesheet', href=`/pretty-checkbox/pretty-checkbox.min.css?v=${pkg.version}`) |
||||
|
|
||||
|
block viewcss |
||||
|
|
||||
|
block js |
||||
|
script(async, src=`/fontawesome/js/fontawesome.min.js?v=${pkg.version}`) |
||||
|
script(src=`/uikit/dist/js/uikit.min.js?v=${pkg.version}`) |
||||
|
script(src=`/uikit/dist/js/uikit-icons.min.js?v=${pkg.version}`) |
||||
|
|
||||
|
block pwa-support |
||||
|
include ../components/pwa-support |
||||
|
|
||||
|
block social-card |
||||
|
include ../components/social-card/twitter |
||||
|
include ../components/social-card/facebook |
||||
|
|
||||
|
block view-header |
||||
|
|
||||
|
script. |
||||
|
|
||||
|
function onImageLoadError (event) { |
||||
|
const imageType = event.currentTarget.getAttribute('data-image-type') || 'thumb'; |
||||
|
console.error('image error', imageType, event); |
||||
|
switch (imageType) { |
||||
|
case 'profile': |
||||
|
event.currentTarget.setAttribute('src', '/img/default-member.png'); |
||||
|
break; |
||||
|
case 'thumb': |
||||
|
event.currentTarget.setAttribute( |
||||
|
'src', |
||||
|
`/img/default-poster.${process.env.DTP_SITE_DOMAIN_KEY}.jpg`, |
||||
|
); |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
body.dtp( |
||||
|
class= 'dtp-dark', |
||||
|
data-dtp-env= process.env.NODE_ENV, |
||||
|
data-dtp-domain= site.domainKey, |
||||
|
data-current-view= currentView, |
||||
|
data-is-popout= isPopOutView, |
||||
|
data-obs-widget= obsWidget, |
||||
|
data-embed-widget= embedWidget, |
||||
|
) |
||||
|
|
||||
|
block view-navbar |
||||
|
nav(uk-navbar).uk-navbar-container |
||||
|
.uk-navbar-left |
||||
|
ul.uk-navbar-nav |
||||
|
li.uk-active |
||||
|
a(href="/") |
||||
|
span |
||||
|
i.fas.fa-home |
||||
|
span HOME |
||||
|
.uk-navbar-right |
||||
|
ul.uk-navbar-nav |
||||
|
li |
||||
|
a(href="/welcome/sign-up") SIGN UP |
||||
|
li |
||||
|
a(href="/welcome/login") LOGIN |
||||
|
|
||||
|
block view-content |
@ -0,0 +1,5 @@ |
|||||
|
@import "uikit/src/less/uikit.less"; |
||||
|
|
||||
|
html, body { |
||||
|
font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; |
||||
|
} |
@ -0,0 +1,11 @@ |
|||||
|
// chat-client.js
|
||||
|
// Copyright (C) 2024 DTP Technologies, LLC
|
||||
|
// All Rights Reserved
|
||||
|
|
||||
|
'use strict'; |
||||
|
|
||||
|
export class ChatApp { |
||||
|
constructor ( ) { |
||||
|
console.log('DTP app client online'); |
||||
|
} |
||||
|
} |
@ -0,0 +1,13 @@ |
|||||
|
// config.js
|
||||
|
// Copyright (C) 2024 DTP Technologies, LLC
|
||||
|
// All Rights Reserved
|
||||
|
|
||||
|
'use strict'; |
||||
|
|
||||
|
export default { |
||||
|
name: process.env.DTP_SITE_NAME, |
||||
|
description: process.env.DTP_SITE_DESCRIPTION, |
||||
|
domain: process.env.DTP_SITE_DOMAIN, |
||||
|
domainKey: process.env.DTP_SITE_DOMAIN_KEY, |
||||
|
company: process.env.DTP_SITE_COMPANY || 'DTP Technologies, LLC', |
||||
|
}; |
@ -0,0 +1,132 @@ |
|||||
|
// dtp-chat.js
|
||||
|
// Copyright (C) 2024 DTP Technologies, LLC
|
||||
|
// All Rights Reserved
|
||||
|
|
||||
|
'use strict'; |
||||
|
|
||||
|
import 'dotenv/config'; |
||||
|
|
||||
|
import path, { dirname } from 'path'; |
||||
|
import { fileURLToPath } from 'url'; |
||||
|
const __dirname = dirname(fileURLToPath(import.meta.url)); // jshint ignore:line
|
||||
|
|
||||
|
import { createRequire } from 'module'; |
||||
|
const require = createRequire(import.meta.url); // jshint ignore:line
|
||||
|
|
||||
|
import * as glob from 'glob'; |
||||
|
|
||||
|
import webpack from 'webpack'; |
||||
|
import webpackDevMiddleware from 'webpack-dev-middleware'; |
||||
|
|
||||
|
import WEBPACK_CONFIG from './webpack.config.js'; |
||||
|
|
||||
|
import express from 'express'; |
||||
|
|
||||
|
const APP_CONFIG = { |
||||
|
pkg: require('./package.json'), |
||||
|
}; |
||||
|
|
||||
|
class Harness { |
||||
|
|
||||
|
constructor ( ) { |
||||
|
this.config = { |
||||
|
root: __dirname, |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
async start ( ) { |
||||
|
this.app = express(); |
||||
|
|
||||
|
this.app.locals.config = APP_CONFIG; |
||||
|
this.app.locals.pkg = APP_CONFIG.pkg; // convenience
|
||||
|
this.app.locals.site = (await import(path.join(this.config.root, 'config', 'site.js'))).default; |
||||
|
|
||||
|
this.app.set('view engine', 'pug'); |
||||
|
this.app.set('views', path.join(__dirname, 'app', 'views')); |
||||
|
|
||||
|
this.app.use('/static', express.static(path.join(__dirname, 'client', 'static'))); |
||||
|
this.app.use('/fontawesome', express.static(path.join(__dirname, 'node_modules', '@fortawesome', 'fontawesome-free'))); |
||||
|
this.app.use('/uikit', express.static(path.join(__dirname, 'node_modules', 'uikit'))); |
||||
|
this.app.use('/pretty-checkbox', express.static(path.join(__dirname, 'node_modules', 'pretty-checkbox', 'dist'))); |
||||
|
|
||||
|
this.app.use('/dist', express.static(path.join(__dirname, 'dist'))); |
||||
|
|
||||
|
/* |
||||
|
* Webpack integration |
||||
|
*/ |
||||
|
if (process.env.NODE_ENV !== 'production') { |
||||
|
this.compiler = webpack(WEBPACK_CONFIG); |
||||
|
this.webpackDevMiddleware = webpackDevMiddleware(this.compiler, { |
||||
|
publicPath: WEBPACK_CONFIG.output.publicPath, |
||||
|
writeToDisk: true, |
||||
|
}); |
||||
|
this.app.use(this.webpackDevMiddleware); |
||||
|
} |
||||
|
|
||||
|
this.app.use((req, res, next) => { |
||||
|
res.locals.dtp = { |
||||
|
request: req, |
||||
|
}; |
||||
|
return next(); |
||||
|
}); |
||||
|
|
||||
|
await this.loadControllers(); |
||||
|
|
||||
|
/* |
||||
|
* Start the ExpressJS server |
||||
|
*/ |
||||
|
const host = process.env.DTP_HTTP_HOST || '127.0.0.1'; |
||||
|
const port = parseInt(process.env.DTP_HTTP_PORT || '3000', 10); |
||||
|
console.log('Starting application server', { host, port }); |
||||
|
this.app.listen(port, host, ( ) => { |
||||
|
console.log(`${APP_CONFIG.pkg.name} online.`); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
async loadControllers ( ) { |
||||
|
const scripts = glob.sync(path.join(this.config.root, 'app', 'controllers', '*.js')); |
||||
|
const inits = [ ]; |
||||
|
|
||||
|
this.controllers = { }; |
||||
|
|
||||
|
for await (const script of scripts) { |
||||
|
try { |
||||
|
const file = path.parse(script); |
||||
|
console.log('loading controller', { name: file.base }); |
||||
|
|
||||
|
let controller = await import(script); |
||||
|
controller = controller.default; |
||||
|
controller.instance = controller.create(this); |
||||
|
|
||||
|
this.controllers[controller.slug] = controller; |
||||
|
inits.push(controller); |
||||
|
} catch (error) { |
||||
|
console.error('failed to load controller', { error }); |
||||
|
throw new Error('failed to load controller', { cause: error }); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
for await (const controller of inits) { |
||||
|
if (controller.isHome) { |
||||
|
continue; |
||||
|
} |
||||
|
await controller.instance.start(); |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
* Start the Home controller |
||||
|
*/ |
||||
|
await this.controllers.home.instance.start(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
(async ( ) => { |
||||
|
|
||||
|
try { |
||||
|
const harness = new Harness(); |
||||
|
await harness.start(); |
||||
|
} catch (error) { |
||||
|
console.log('failed to start application harness', error); |
||||
|
} |
||||
|
|
||||
|
})(); |
@ -0,0 +1,51 @@ |
|||||
|
{ |
||||
|
"name": "dtp-chat", |
||||
|
"type": "module", |
||||
|
"version": "0.1.0", |
||||
|
"description": "Next-generation realtime communications tool for the web.", |
||||
|
"dtpApp": { |
||||
|
"title": "CyberEgg 2077: Interstellar Food Fight", |
||||
|
"description": "In a world where memes come to life, a pineapple takes on evil and wins!" |
||||
|
}, |
||||
|
"main": "dtp-chat.js", |
||||
|
"scripts": { |
||||
|
"develop": "nodemon dtp-chat.js", |
||||
|
"build": "NODE_ENV=production yarn webpack --config webpack.config.js" |
||||
|
}, |
||||
|
"repository": "[email protected]:digital-telepresence/dtp-chat.git", |
||||
|
"author": "Rob Colbert", |
||||
|
"license": "LicenseRef-LICENSE", |
||||
|
"private": true, |
||||
|
"dependencies": { |
||||
|
"@fortawesome/fontawesome-free": "^6.5.1", |
||||
|
"dotenv": "^16.4.5", |
||||
|
"express": "^4.19.2", |
||||
|
"glob": "^10.3.10", |
||||
|
"marked": "^12.0.1", |
||||
|
"mongoose": "^8.2.3", |
||||
|
"multer": "^1.4.5-lts.1", |
||||
|
"numeral": "^2.0.6", |
||||
|
"pretty-checkbox": "^3.0.3", |
||||
|
"pug": "^3.0.2", |
||||
|
"socket.io": "^4.7.5", |
||||
|
"striptags": "^3.2.0" |
||||
|
}, |
||||
|
"devDependencies": { |
||||
|
"browser-sync": "^3.0.2", |
||||
|
"browser-sync-webpack-plugin": "^2.3.0", |
||||
|
"css-loader": "^6.10.0", |
||||
|
"jshint": "^2.13.6", |
||||
|
"less": "^4.2.0", |
||||
|
"less-loader": "^12.2.0", |
||||
|
"mini-css-extract-plugin": "^2.8.1", |
||||
|
"nodemon-webpack-plugin": "^4.8.2", |
||||
|
"style-loader": "^3.3.4", |
||||
|
"terser-webpack-plugin": "^5.3.10", |
||||
|
"uikit": "^3.19.2", |
||||
|
"webpack": "^5.91.0", |
||||
|
"webpack-cli": "^5.1.4", |
||||
|
"webpack-dev-middleware": "^7.1.1", |
||||
|
"webpack-stream": "^7.0.0", |
||||
|
"workbox-webpack-plugin": "^7.0.0" |
||||
|
} |
||||
|
} |
@ -0,0 +1,103 @@ |
|||||
|
// webpack.config.js
|
||||
|
// Copyright (C) 2022 Rob Colbert @[email protected]
|
||||
|
// All Rights Reserved
|
||||
|
|
||||
|
'use strict'; |
||||
|
|
||||
|
import path, { dirname } from 'path'; |
||||
|
import { fileURLToPath } from 'url'; |
||||
|
const __dirname = dirname(fileURLToPath(import.meta.url)); // jshint ignore:line
|
||||
|
|
||||
|
import MiniCssExtractPlugin from 'mini-css-extract-plugin'; |
||||
|
import BrowserSyncPlugin from 'browser-sync-webpack-plugin'; |
||||
|
|
||||
|
const webpackMode = (process.env.NODE_ENV === 'production') ? 'production' : 'development'; |
||||
|
console.log('Webpack mode:', webpackMode); |
||||
|
|
||||
|
const plugins = [ ]; |
||||
|
|
||||
|
plugins.push(new MiniCssExtractPlugin()); |
||||
|
|
||||
|
if (webpackMode === 'development') { |
||||
|
plugins.push( |
||||
|
new BrowserSyncPlugin({ |
||||
|
proxy: { |
||||
|
target: 'http://localhost:3000', |
||||
|
ws: true, |
||||
|
}, |
||||
|
host: 'localhost', |
||||
|
open: 'local', |
||||
|
port: 3333, |
||||
|
cors: true, |
||||
|
ui: { |
||||
|
port: 3400, |
||||
|
}, |
||||
|
notify: false, |
||||
|
ghostMode: { |
||||
|
clicks: false, |
||||
|
forms: false, |
||||
|
scroll: true, |
||||
|
}, |
||||
|
logLevel: 'info', |
||||
|
files: [ |
||||
|
'./dist/*.js', |
||||
|
'./dist/*.css', |
||||
|
], |
||||
|
}), |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
export default { |
||||
|
entry: { |
||||
|
'chat-client': [ |
||||
|
'./client/js/chat-client.js', |
||||
|
'./client/css/main.less', |
||||
|
], |
||||
|
}, |
||||
|
mode: webpackMode, |
||||
|
output: { |
||||
|
filename: '[name].bundle.js', |
||||
|
path: path.resolve(__dirname, 'dist'), |
||||
|
// clean: true,
|
||||
|
// publicPath: '/dist',
|
||||
|
}, |
||||
|
optimization: { |
||||
|
splitChunks: { |
||||
|
chunks: 'all', |
||||
|
}, |
||||
|
}, |
||||
|
plugins, |
||||
|
module: { |
||||
|
rules: [ |
||||
|
{ |
||||
|
test: /\.less$/i, |
||||
|
use: [ |
||||
|
{ |
||||
|
loader: "style-loader", |
||||
|
}, |
||||
|
{ |
||||
|
loader: MiniCssExtractPlugin.loader, |
||||
|
options: { |
||||
|
esModule: false, |
||||
|
}, |
||||
|
}, |
||||
|
{ |
||||
|
loader: "css-loader", |
||||
|
options: { |
||||
|
sourceMap: true, |
||||
|
}, |
||||
|
}, |
||||
|
{ |
||||
|
loader: "less-loader", |
||||
|
options: { |
||||
|
sourceMap: true, |
||||
|
lessOptions: { |
||||
|
strictMath: false, |
||||
|
}, |
||||
|
}, |
||||
|
}, |
||||
|
], |
||||
|
}, |
||||
|
], |
||||
|
}, |
||||
|
}; |
File diff suppressed because it is too large
Loading…
Reference in new issue