Skip to content

Commit

Permalink
add websocket support, add new config, add uncaught catch all, update…
Browse files Browse the repository at this point in the history
… readme, version bump
  • Loading branch information
realtux committed Jul 31, 2024
1 parent 75c979d commit 6035c6b
Show file tree
Hide file tree
Showing 13 changed files with 136 additions and 13 deletions.
4 changes: 4 additions & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
declare module '@exajs/core' {
const exa: any;
export default exa;
}
3 changes: 3 additions & 0 deletions lib/core/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ let config = {
/**
* internal config
*/
version: '0.0.11',

paths: {
root: '',
console: '/console',
Expand All @@ -23,6 +25,7 @@ let config = {
use: true,
host: '0.0.0.0',
port: 8118,
base_url: `http://127.0.0.1:8118`,
},

database: {
Expand Down
5 changes: 5 additions & 0 deletions lib/database/models.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ export const init = async () => {
model.has_one = model.hasOne;
model.has_many = model.hasMany;
model.belongs_to_many = model.belongsToMany;
}

// process associations, must be done after all models have been initialized
for (const model_name in models) {
let model = models[model_name];

model.associate && model.associate(models);
}
Expand Down
45 changes: 44 additions & 1 deletion lib/http/express.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import Express from 'express';
import { glob } from 'glob';
import multer from 'multer';
import nunjucks from 'nunjucks';
import { WebSocketServer } from 'ws';

let express = {};

Expand All @@ -30,6 +31,7 @@ export const init = async () => {
app.use(Express.json({ limit: '16mb' }));
app.use('/public', Express.static(`${config.paths.root}/public`));

// mounted http controller routes
let files = await glob(`${config.paths.root}${config.paths.http}/**/*.js`);

for (const file of files) {
Expand Down Expand Up @@ -57,9 +59,50 @@ export const init = async () => {

// console.log(`mounted ${chalk.green(controllers.length)} routes`);

app.listen(config.http.port, () => {
// start server
const server = app.listen(config.http.port, () => {
console.log(`server running on ${config.http.host}:${config.http.port}`);
});

if (config.http.websocket) {
// mount websocket paths
let files = await glob(`${config.paths.root}/websocket/**/*.js`);

let path_mapper = {};

for (const file of files) {
let { default: websocket } = await import(file);

path_mapper[websocket.route || '/'] = websocket;
}

// no files means no need to setup any server
if (files.length > 0) {
const wss = new WebSocketServer({ noServer: true });

wss.on('connection', (socket, req) => {
const { pathname } = new URL(req.url, 'wss://base.url');

try {
if (path_mapper[pathname]) {
path_mapper[pathname].connection(socket, req);
} else {
path_mapper['/'].connection(socket, req);
}
} catch {
console.log('no matching websocket path or fallback file');
socket.close();
}
});

server.on('upgrade', (req, socket, head) => {
wss.handleUpgrade(req, socket, head, socket => {
wss.emit('connection', socket, req)
});
});
}
}

};

export default express;
17 changes: 15 additions & 2 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,18 @@ import { fileURLToPath } from 'node:url';
import { DateTime } from 'luxon';
import { dirname } from 'node:path';

process.on('uncaughtException', err => {
console.log(chalk.red('uncaught last resort'), chalk.yellow(DateTime.now().toISO()));

if (err instanceof Error) {
console.error(err.stack.toString());
} else if (typeof err === 'string') {
console.error(err);
} else if (typeof err === 'object') {
console.error(err.toString());
}
});

export default new class {

config = config
Expand Down Expand Up @@ -44,7 +56,7 @@ export default new class {

if (!quiet) {
console.log();
console.log(`${chalk.yellow('exa.js')} by tux - v0.0.10`);
console.log(`${chalk.yellow('exa.js')} by tux - v${config.version}`);
console.log('-----------------------------');
console.log(`${chalk.green(DateTime.now().toISO())}`);
console.log('-----------------------------');
Expand Down Expand Up @@ -93,7 +105,8 @@ export default new class {
await init_express();
}
} catch (e) {
console.log('failed to start');
console.log('exa uncaught:');
console.log(e.message);
console.log(e.stack);
}
}
Expand Down
27 changes: 24 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 5 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@
"name": "@exajs/core",
"type": "module",
"author": "Brian Seymour <@realtux>",
"version": "0.0.10",
"version": "0.0.11",
"description": "modern opinionated node.js framework",
"license": "MIT",
"homepage": "https://github.com/realtux/exa",
"main": "lib/index.js",
"types": "index.d.ts",
"repository": {
"type": "git",
"url": "git://github.com/realtux/exa.git"
Expand All @@ -19,6 +20,7 @@
},
"exports": {
".": "./lib/index.js",
"./database/models": "./lib/database/models.js",
"./database/connection": "./lib/database/connection.js",
"./system": "./lib/system/index.js",
"./system/sequelize": "./lib/system/sequelize.js"
Expand All @@ -36,7 +38,8 @@
"pg": "8.12.0",
"pg-hstore": "2.3.4",
"sequelize": "6.37.3",
"sqlite3": "5.1.7"
"sqlite3": "5.1.7",
"ws": "8.18.0"
},
"devDependencies": {
"nodemon": "3.1.3"
Expand Down
8 changes: 7 additions & 1 deletion readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ npx @exajs/core init
# start dev with auto reload
npm run watch

# --or--

# start production
npm start
```
Expand All @@ -32,7 +34,7 @@ initializing will create the exa.js template project structure in the current di
*contains console scripts that can be invoked with `npm run console <script name>`. see docs for proper format.*

- **http**
*contains api logic organized in one or more files. each file contains route definitions, middleware, and handlers. see docs for proper format*
*contains api logic organized in one or more files. each file contains route definitions, middleware, and handlers. see docs for proper format.*

- **library**
*contains user defined library files. this is generally relevant js files for your project that don't fit anywhere else.*
Expand All @@ -55,6 +57,9 @@ initializing will create the exa.js template project structure in the current di
- **views**
*contains view templates for traditional non-async frontends. use `res.render(path, variables)` instead of `res.send()` in your api logic.*

- **websocket**
*contains files that represent websocket connection entrypoints. see docs for proper format.*

---

### modularity options
Expand All @@ -66,6 +71,7 @@ the following features can be disabled if desired:
- models (database)
- public
- views
- websocket

---

Expand Down
4 changes: 4 additions & 0 deletions var/template/config/master.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ export default {
host: '0.0.0.0',
// port to run on
port: 8118,
// http server base url
base_url: 'http://127.0.0.1:8118',
// whether or not to listen/handle websocket connections
websocket: true,
},

/**
Expand Down
2 changes: 1 addition & 1 deletion var/template/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ services:
init: true
volumes:
- .:/opt/src
working_dir: /opt/src/console
working_dir: /opt/src
env_file:
- .env
profiles:
Expand Down
2 changes: 1 addition & 1 deletion var/template/docker.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ cd $(dirname "$0")

case $* in
console* )
docker compose run --rm console node app console ${@:2}
docker compose run --rm console node app.js console ${@:2}
;;
jmig* )
docker compose exec app npx jmig ${@:2}
Expand Down
5 changes: 3 additions & 2 deletions var/template/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 20 additions & 0 deletions var/template/websocket/base.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
export default new class {

// will be called for each websocket connection that is established
connection(socket, req) {
console.log('new connection');

socket.on('message', data => {
console.log('new message', data);
});

socket.on('close', () => {
console.log('connection closed');
});

socket.on('error', err => {
console.log('ws error', err);
});
}

}

0 comments on commit 6035c6b

Please sign in to comment.