refactor: mixin
This commit is contained in:
parent
37d9a22479
commit
c8a6f68628
1
TODO.md
1
TODO.md
|
@ -29,7 +29,6 @@
|
||||||
- [ ] redux store provider fails if not in request
|
- [ ] redux store provider fails if not in request
|
||||||
- [ ] add building to publish process ...
|
- [ ] add building to publish process ...
|
||||||
- [ ] @babel/register@7.18.x has a bug
|
- [ ] @babel/register@7.18.x has a bug
|
||||||
- [ ] `$flecks/db/sequelize` should be `$flecks/db.sequelize`
|
|
||||||
- [x] `url()` in styles breaks HMR
|
- [x] `url()` in styles breaks HMR
|
||||||
- [x] 2 underscores for `FLECKS_ENV` variables
|
- [x] 2 underscores for `FLECKS_ENV` variables
|
||||||
- [x] flecks add
|
- [x] flecks add
|
||||||
|
|
|
@ -128,8 +128,8 @@ export default class ServerFlecks extends Flecks {
|
||||||
const entries = Object.keys(resolver).map((path) => [path, R(this.resolve(resolver, path))]);
|
const entries = Object.keys(resolver).map((path) => [path, R(this.resolve(resolver, path))]);
|
||||||
// Flecks mixins.
|
// Flecks mixins.
|
||||||
const mixins = entries.map(([, M]) => M.hooks?.['@flecks/core.mixin']).filter((e) => e);
|
const mixins = entries.map(([, M]) => M.hooks?.['@flecks/core.mixin']).filter((e) => e);
|
||||||
const Class = compose(...mixins)(ServerFlecks);
|
const MixedServerFlecks = compose(...mixins)(ServerFlecks);
|
||||||
return new Class({
|
return new MixedServerFlecks({
|
||||||
config,
|
config,
|
||||||
flecks: Object.fromEntries(entries),
|
flecks: Object.fromEntries(entries),
|
||||||
platforms,
|
platforms,
|
||||||
|
|
|
@ -50,7 +50,7 @@ export async function createDatabaseConnection(flecks) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const Models = flecks.get('$flecks/db.models')[ByType];
|
const Models = flecks.db.Models[ByType];
|
||||||
await register(Models, sequelize);
|
await register(Models, sequelize);
|
||||||
debug('synchronizing...');
|
debug('synchronizing...');
|
||||||
await sequelize.sync();
|
await sequelize.sync();
|
||||||
|
|
|
@ -44,21 +44,32 @@ export const hooks = {
|
||||||
}),
|
}),
|
||||||
'@flecks/core.hmr.gathered': (gathered, hook, flecks) => {
|
'@flecks/core.hmr.gathered': (gathered, hook, flecks) => {
|
||||||
if ('@flecks/db/server.models' === hook) {
|
if ('@flecks/db/server.models' === hook) {
|
||||||
register(gathered, flecks.get('$flecks/db/sequelize'));
|
register(gathered, flecks.db.sequelize);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
'@flecks/core.mixin': (Flecks) => (
|
||||||
|
class FlecksWithDb extends Flecks {
|
||||||
|
|
||||||
|
db = {
|
||||||
|
Models: {},
|
||||||
|
$$sequelize: undefined,
|
||||||
|
get sequelize() {
|
||||||
|
return this.$$sequelize;
|
||||||
|
},
|
||||||
|
set sequelize(sequelize) {
|
||||||
|
this.$$sequelize = sequelize;
|
||||||
|
this.transaction = sequelize.transaction.bind(sequelize);
|
||||||
|
},
|
||||||
|
transaction: () => {},
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
),
|
||||||
'@flecks/core.starting': (flecks) => {
|
'@flecks/core.starting': (flecks) => {
|
||||||
flecks.set('$flecks/db.models', flecks.gather(
|
flecks.db.Models = flecks.gather('@flecks/db/server.models', {typeProperty: 'name'});
|
||||||
'@flecks/db/server.models',
|
|
||||||
{typeProperty: 'name'},
|
|
||||||
));
|
|
||||||
},
|
},
|
||||||
'@flecks/docker.containers': containers,
|
'@flecks/docker.containers': containers,
|
||||||
'@flecks/server.up': async (flecks) => {
|
'@flecks/server.up': async (flecks) => {
|
||||||
flecks.set('$flecks/db/sequelize', await createDatabaseConnection(flecks));
|
flecks.db.sequelize = await createDatabaseConnection(flecks);
|
||||||
},
|
},
|
||||||
'@flecks/repl.context': (flecks) => ({
|
|
||||||
Models: flecks.get('$flecks/db.models'),
|
|
||||||
sequelize: flecks.get('$flecks/db/sequelize'),
|
|
||||||
}),
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,6 +2,8 @@ import {join} from 'path';
|
||||||
|
|
||||||
import {banner} from '@flecks/core/server';
|
import {banner} from '@flecks/core/server';
|
||||||
|
|
||||||
|
const electron = __non_webpack_require__('electron');
|
||||||
|
|
||||||
const {
|
const {
|
||||||
NODE_ENV,
|
NODE_ENV,
|
||||||
} = process.env;
|
} = process.env;
|
||||||
|
@ -9,7 +11,7 @@ const {
|
||||||
let win;
|
let win;
|
||||||
|
|
||||||
async function createWindow(flecks) {
|
async function createWindow(flecks) {
|
||||||
const {BrowserWindow} = flecks.get('$flecks/electron');
|
const {BrowserWindow} = flecks.electron;
|
||||||
const {browserWindowOptions} = flecks.get('@flecks/electron/server');
|
const {browserWindowOptions} = flecks.get('@flecks/electron/server');
|
||||||
win = new BrowserWindow(browserWindowOptions);
|
win = new BrowserWindow(browserWindowOptions);
|
||||||
await flecks.invokeSequentialAsync('@flecks/electron/server.window', win);
|
await flecks.invokeSequentialAsync('@flecks/electron/server.window', win);
|
||||||
|
@ -69,6 +71,13 @@ export const hooks = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
'@flecks/core.mixin': (Flecks) => (
|
||||||
|
class FlecksWithElectron extends Flecks {
|
||||||
|
|
||||||
|
electron = electron.app ? electron : undefined;
|
||||||
|
|
||||||
|
}
|
||||||
|
),
|
||||||
'@flecks/electron/server.initialize': async (electron, flecks) => {
|
'@flecks/electron/server.initialize': async (electron, flecks) => {
|
||||||
electron.app.on('window-all-closed', () => {
|
electron.app.on('window-all-closed', () => {
|
||||||
const {quitOnClosed} = flecks.get('@flecks/electron/server');
|
const {quitOnClosed} = flecks.get('@flecks/electron/server');
|
||||||
|
@ -121,14 +130,6 @@ export const hooks = {
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
'@flecks/server.up': async (flecks) => {
|
'@flecks/server.up': async (flecks) => {
|
||||||
// Local require because electron is kinda skittish.
|
await flecks.invokeSequentialAsync('@flecks/electron/server.initialize', flecks.electron);
|
||||||
// eslint-disable-next-line global-require
|
|
||||||
const electron = require('electron');
|
|
||||||
// `electron.app` will be undefined if we aren't running in an electron environment. Just bail.
|
|
||||||
if (!electron.app) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
flecks.set('$flecks/electron', electron);
|
|
||||||
await flecks.invokeSequentialAsync('@flecks/electron/server.initialize', electron);
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -4,8 +4,7 @@ export default (flecks, [name, Packet]) => {
|
||||||
|
|
||||||
constructor(...args) {
|
constructor(...args) {
|
||||||
super(...args);
|
super(...args);
|
||||||
const {[name]: limiter} = flecks.get('$flecks/governor.packet.limiters');
|
this.limit = flecks.governor.packet[name];
|
||||||
this.limit = limiter;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static async validate(packet, socket) {
|
static async validate(packet, socket) {
|
||||||
|
|
|
@ -24,12 +24,18 @@ export const hooks = {
|
||||||
ttl: 30,
|
ttl: 30,
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
|
'@flecks/core.mixin': (Flecks) => (
|
||||||
|
class FlecksWithGovernor extends Flecks {
|
||||||
|
|
||||||
|
governor = {}
|
||||||
|
|
||||||
|
}
|
||||||
|
),
|
||||||
'@flecks/db/server.models': Flecks.provide(require.context('./models', false, /\.js$/)),
|
'@flecks/db/server.models': Flecks.provide(require.context('./models', false, /\.js$/)),
|
||||||
'@flecks/web/server.request.route': (flecks) => {
|
'@flecks/web/server.request.route': (flecks) => {
|
||||||
const {web} = flecks.get('@flecks/governor/server');
|
const {web} = flecks.get('@flecks/governor/server');
|
||||||
const limiter = flecks.get('$flecks/governor.web.limiter');
|
|
||||||
return async (req, res, next) => {
|
return async (req, res, next) => {
|
||||||
const {Ban} = flecks.get('$flecks/db.models');
|
const {Ban} = flecks.db.Models;
|
||||||
try {
|
try {
|
||||||
await Ban.check(req);
|
await Ban.check(req);
|
||||||
}
|
}
|
||||||
|
@ -43,7 +49,7 @@ export const hooks = {
|
||||||
res.status(403).send(`<pre>${Ban.format([ban])}</pre>`);
|
res.status(403).send(`<pre>${Ban.format([ban])}</pre>`);
|
||||||
};
|
};
|
||||||
try {
|
try {
|
||||||
await limiter.consume(req.ip);
|
await flecks.governor.web.consume(req.ip);
|
||||||
next();
|
next();
|
||||||
}
|
}
|
||||||
catch (error) {
|
catch (error) {
|
||||||
|
@ -57,20 +63,18 @@ export const hooks = {
|
||||||
'@flecks/server.up': async (flecks) => {
|
'@flecks/server.up': async (flecks) => {
|
||||||
if (flecks.fleck('@flecks/web/server')) {
|
if (flecks.fleck('@flecks/web/server')) {
|
||||||
const {web} = flecks.get('@flecks/governor/server');
|
const {web} = flecks.get('@flecks/governor/server');
|
||||||
const limiter = await createLimiter(
|
flecks.governor.web = await createLimiter(
|
||||||
flecks,
|
flecks,
|
||||||
{
|
{
|
||||||
keyPrefix: '@flecks/governor.web.request.route',
|
keyPrefix: '@flecks/governor.web.request.route',
|
||||||
...web,
|
...web,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
flecks.set('$flecks/governor.web.limiter', limiter);
|
|
||||||
}
|
}
|
||||||
if (flecks.fleck('@flecks/socket/server')) {
|
if (flecks.fleck('@flecks/socket/server')) {
|
||||||
const {[ByType]: Packets} = flecks.get('$flecks/socket.packets');
|
flecks.governor.packet = Object.fromEntries(
|
||||||
const limiters = Object.fromEntries(
|
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
Object.entries(Packets)
|
Object.entries(flecks.socket.Packets[ByType])
|
||||||
.filter(([, Packet]) => Packet.limit)
|
.filter(([, Packet]) => Packet.limit)
|
||||||
.map(async ([name, Packet]) => (
|
.map(async ([name, Packet]) => (
|
||||||
[
|
[
|
||||||
|
@ -83,23 +87,20 @@ export const hooks = {
|
||||||
)),
|
)),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
flecks.set('$flecks/governor.packet.limiters', limiters);
|
|
||||||
const {socket} = flecks.get('@flecks/governor/server');
|
const {socket} = flecks.get('@flecks/governor/server');
|
||||||
const limiter = await createLimiter(
|
flecks.governor.socket = await createLimiter(
|
||||||
flecks,
|
flecks,
|
||||||
{
|
{
|
||||||
keyPrefix: '@flecks/governor.socket.request.socket',
|
keyPrefix: '@flecks/governor.socket.request.socket',
|
||||||
...socket,
|
...socket,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
flecks.set('$flecks/governor.socket.limiter', limiter);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'@flecks/socket/server.request.socket': (flecks) => {
|
'@flecks/socket/server.request.socket': (flecks) => (
|
||||||
const limiter = flecks.get('$flecks/governor.socket.limiter');
|
async (socket, next) => {
|
||||||
return async (socket, next) => {
|
|
||||||
const {handshake: req} = socket;
|
const {handshake: req} = socket;
|
||||||
const {Ban} = flecks.get('$flecks/db.models');
|
const {Ban} = flecks.db.Models;
|
||||||
try {
|
try {
|
||||||
await Ban.check(req);
|
await Ban.check(req);
|
||||||
}
|
}
|
||||||
|
@ -112,7 +113,7 @@ export const hooks = {
|
||||||
socket.disconnect();
|
socket.disconnect();
|
||||||
};
|
};
|
||||||
try {
|
try {
|
||||||
await limiter.consume(req.ip);
|
await flecks.governor.socket.consume(req.ip);
|
||||||
next();
|
next();
|
||||||
}
|
}
|
||||||
catch (error) {
|
catch (error) {
|
||||||
|
@ -120,8 +121,8 @@ export const hooks = {
|
||||||
await Ban.create(Ban.fromRequest(req, keys, ttl));
|
await Ban.create(Ban.fromRequest(req, keys, ttl));
|
||||||
next(error);
|
next(error);
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
},
|
),
|
||||||
'@flecks/socket.packets.decorate': (Packets, flecks) => (
|
'@flecks/socket.packets.decorate': (Packets, flecks) => (
|
||||||
Object.fromEntries(
|
Object.fromEntries(
|
||||||
Object.entries(Packets).map(([keyPrefix, Packet]) => [
|
Object.entries(Packets).map(([keyPrefix, Packet]) => [
|
||||||
|
|
|
@ -6,7 +6,7 @@ import {HistoryRouter as ReduxHistoryRouter} from 'redux-first-history/rr6';
|
||||||
export const hooks = {
|
export const hooks = {
|
||||||
'@flecks/react.providers': (req, flecks) => (
|
'@flecks/react.providers': (req, flecks) => (
|
||||||
flecks.fleck('@flecks/redux')
|
flecks.fleck('@flecks/redux')
|
||||||
? [ReduxHistoryRouter, {history: createReduxHistory(flecks.get('$flecks/redux.store'))}]
|
? [ReduxHistoryRouter, {history: createReduxHistory(flecks.redux)}]
|
||||||
: [HistoryRouter, {history}]
|
: [HistoryRouter, {history}]
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
|
|
@ -5,13 +5,20 @@ import configureStore, {createReducer} from '../store';
|
||||||
import localStorageEnhancer from './local-storage';
|
import localStorageEnhancer from './local-storage';
|
||||||
|
|
||||||
export const hooks = {
|
export const hooks = {
|
||||||
|
'@flecks/core.mixin': (Flecks) => (
|
||||||
|
class FlecksWithRedux extends Flecks {
|
||||||
|
|
||||||
|
redux;
|
||||||
|
|
||||||
|
}
|
||||||
|
),
|
||||||
'@flecks/react.providers': async (req, flecks) => {
|
'@flecks/react.providers': async (req, flecks) => {
|
||||||
const slices = await flecks.invokeMergeUnique('@flecks/redux.slices');
|
const slices = await flecks.invokeMergeUnique('@flecks/redux.slices');
|
||||||
const reducer = createReducer(flecks, slices);
|
const reducer = createReducer(flecks, slices);
|
||||||
// Hydrate from server.
|
// Hydrate from server.
|
||||||
const {preloadedState} = flecks.get('@flecks/redux/client');
|
const {preloadedState} = flecks.get('@flecks/redux/client');
|
||||||
const store = await configureStore(flecks, reducer, {preloadedState});
|
const store = await configureStore(flecks, reducer, {preloadedState});
|
||||||
flecks.set('$flecks/redux.store', store);
|
flecks.redux = store;
|
||||||
return [Provider, {store}];
|
return [Provider, {store}];
|
||||||
},
|
},
|
||||||
'@flecks/redux.store': ({enhancers}) => {
|
'@flecks/redux.store': ({enhancers}) => {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
export default (Action, flecks) => class ActionClient extends Action {
|
export default (Action, flecks) => class ActionClient extends Action {
|
||||||
|
|
||||||
static async respond(packet) {
|
static async respond(packet) {
|
||||||
flecks.get('$flecks/redux.store').dispatch(packet.data);
|
flecks.redux.dispatch(packet.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -61,7 +61,7 @@ export async function createReplServer(flecks) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const socket = join(tmpdir(), 'flecks', id, 'repl', `${id}-${Date.now()}.sock`);
|
const socket = join(tmpdir(), 'flecks', id, 'repl', `${id}-${Date.now()}.sock`);
|
||||||
flecks.set('$flecks/repl.socket', socket);
|
flecks.repl = socket;
|
||||||
await new Promise((resolve) => {
|
await new Promise((resolve) => {
|
||||||
netServer.listen(socket, resolve);
|
netServer.listen(socket, resolve);
|
||||||
});
|
});
|
||||||
|
|
|
@ -3,5 +3,12 @@ import {createReplServer} from './repl';
|
||||||
|
|
||||||
export const hooks = {
|
export const hooks = {
|
||||||
'@flecks/core.commands': commands,
|
'@flecks/core.commands': commands,
|
||||||
|
'@flecks/core.mixin': (Flecks) => (
|
||||||
|
class FlecksWithRepl extends Flecks {
|
||||||
|
|
||||||
|
repl;
|
||||||
|
|
||||||
|
}
|
||||||
|
),
|
||||||
'@flecks/server.up': (flecks) => createReplServer(flecks),
|
'@flecks/server.up': (flecks) => createReplServer(flecks),
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,8 +2,8 @@ import {mkdir} from 'fs/promises';
|
||||||
import {tmpdir} from 'os';
|
import {tmpdir} from 'os';
|
||||||
import {join} from 'path';
|
import {join} from 'path';
|
||||||
|
|
||||||
import {D} from '@flecks/core';
|
import {compose, D} from '@flecks/core';
|
||||||
import {Flecks} from '@flecks/core/server';
|
import {Flecks as BaseFlecks} from '@flecks/core/server';
|
||||||
|
|
||||||
const {version} = require('../package.json');
|
const {version} = require('../package.json');
|
||||||
|
|
||||||
|
@ -22,12 +22,18 @@ const {version} = require('../package.json');
|
||||||
const debug = D('@flecks/server/entry');
|
const debug = D('@flecks/server/entry');
|
||||||
debug('starting server...');
|
debug('starting server...');
|
||||||
// Make resolver.
|
// Make resolver.
|
||||||
|
// Flecks mixins.
|
||||||
|
const flecks = await loadFlecks();
|
||||||
|
const mixins = Object.entries(flecks)
|
||||||
|
.map(([, M]) => M.hooks?.['@flecks/core.mixin'])
|
||||||
|
.filter((e) => e);
|
||||||
|
const Flecks = compose(...mixins)(BaseFlecks);
|
||||||
const resolver = Flecks.makeResolver(config);
|
const resolver = Flecks.makeResolver(config);
|
||||||
const rcs = Flecks.loadRcs(resolver);
|
const rcs = Flecks.loadRcs(resolver);
|
||||||
Flecks.installCompilers(rcs, resolver);
|
Flecks.installCompilers(rcs, resolver);
|
||||||
global.flecks = new Flecks({
|
global.flecks = new Flecks({
|
||||||
config,
|
config,
|
||||||
flecks: await loadFlecks(),
|
flecks,
|
||||||
platforms,
|
platforms,
|
||||||
resolver,
|
resolver,
|
||||||
rcs,
|
rcs,
|
||||||
|
|
|
@ -1,9 +1,22 @@
|
||||||
import SocketClient from './socket';
|
import SocketClient from './socket';
|
||||||
|
|
||||||
export const hooks = {
|
export const hooks = {
|
||||||
|
'@flecks/core.mixin': (Flecks) => (
|
||||||
|
class FlecksWithSocket extends Flecks {
|
||||||
|
|
||||||
|
constructor(...args) {
|
||||||
|
super(...args);
|
||||||
|
if (!this.socket) {
|
||||||
|
this.socket = {};
|
||||||
|
}
|
||||||
|
this.socket.client = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
),
|
||||||
'@flecks/web/client.up': (flecks) => {
|
'@flecks/web/client.up': (flecks) => {
|
||||||
const socket = new SocketClient(flecks);
|
const socket = new SocketClient(flecks);
|
||||||
flecks.set('$flecks/socket.socket', socket);
|
flecks.socket.client = socket;
|
||||||
socket.connect();
|
socket.connect();
|
||||||
socket.listen();
|
socket.listen();
|
||||||
},
|
},
|
||||||
|
|
|
@ -2,6 +2,5 @@ import {useFlecks} from '@flecks/react';
|
||||||
|
|
||||||
export default function useSocket() {
|
export default function useSocket() {
|
||||||
const flecks = useFlecks();
|
const flecks = useFlecks();
|
||||||
const sock = flecks.get('$flecks/socket.socket');
|
return flecks.socket.client;
|
||||||
return sock;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,11 +8,21 @@ export * from './hooks';
|
||||||
export {Packet, Packer, ValidationError} from './packet';
|
export {Packet, Packer, ValidationError} from './packet';
|
||||||
|
|
||||||
export const hooks = {
|
export const hooks = {
|
||||||
|
'@flecks/core.mixin': (Flecks) => (
|
||||||
|
class FlecksWithSocket extends Flecks {
|
||||||
|
|
||||||
|
constructor(...args) {
|
||||||
|
super(...args);
|
||||||
|
if (!this.socket) {
|
||||||
|
this.socket = {};
|
||||||
|
}
|
||||||
|
this.socket.Packets = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
),
|
||||||
'@flecks/core.starting': (flecks) => {
|
'@flecks/core.starting': (flecks) => {
|
||||||
flecks.set('$flecks/socket.packets', flecks.gather(
|
flecks.socket.Packets = flecks.gather('@flecks/socket.packets', {check: badPacketsCheck});
|
||||||
'@flecks/socket.packets',
|
|
||||||
{check: badPacketsCheck},
|
|
||||||
));
|
|
||||||
},
|
},
|
||||||
'@flecks/web.config': async (
|
'@flecks/web.config': async (
|
||||||
req,
|
req,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
const hydrate = (flecks, [type, data]) => {
|
const hydrate = (flecks, [type, data]) => {
|
||||||
const {[type]: Packet} = flecks.get('$flecks/socket.packets');
|
const {[type]: Packet} = flecks.socket.Packets;
|
||||||
if (!Packet) {
|
if (!Packet) {
|
||||||
throw new TypeError(`No packet of type '${type}'`);
|
throw new TypeError(`No packet of type '${type}'`);
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,7 +68,7 @@ export default (flecks) => class BundlePacket extends PacketClass {
|
||||||
packedPacket.writeUInt8(buffer.readUInt8(caret++), i++);
|
packedPacket.writeUInt8(buffer.readUInt8(caret++), i++);
|
||||||
}
|
}
|
||||||
// Lookup packet.
|
// Lookup packet.
|
||||||
const {[packetId]: Packet} = flecks.get('$flecks/socket.packets');
|
const {[packetId]: Packet} = flecks.socket.Packets;
|
||||||
res.push(new Packet(Packet.decode(packedPacket)));
|
res.push(new Packet(Packet.decode(packedPacket)));
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
|
|
|
@ -1,25 +1,30 @@
|
||||||
import createIntercom from './create-intercom';
|
import createIntercom from './create-intercom';
|
||||||
import SocketServer from './server';
|
import SocketServer from './server';
|
||||||
|
|
||||||
const flecksServers = new WeakMap();
|
|
||||||
|
|
||||||
export const server = (flecks) => flecksServers.get(flecks);
|
|
||||||
|
|
||||||
export const hooks = {
|
export const hooks = {
|
||||||
'@flecks/web/server.request.socket': (flecks) => (req, res, next) => {
|
'@flecks/web/server.request.socket': (flecks) => (req, res, next) => {
|
||||||
req.intercom = createIntercom(server(flecks), 'web');
|
req.intercom = createIntercom(flecks.socket.server, 'web');
|
||||||
next();
|
next();
|
||||||
},
|
},
|
||||||
'@flecks/web/server.up': async (httpServer, flecks) => {
|
'@flecks/web/server.up': async (httpServer, flecks) => {
|
||||||
const server = new SocketServer(httpServer, flecks);
|
const server = new SocketServer(httpServer, flecks);
|
||||||
flecksServers.set(flecks, server);
|
flecks.socket.server = server;
|
||||||
await server.connect();
|
await server.connect();
|
||||||
},
|
},
|
||||||
'@flecks/repl.context': (flecks) => ({
|
|
||||||
Packets: flecks.get('$flecks/socket.packets'),
|
|
||||||
socketServer: server(flecks),
|
|
||||||
}),
|
|
||||||
'@flecks/socket.server': ({config: {'@flecks/core': {id}}}) => ({
|
'@flecks/socket.server': ({config: {'@flecks/core': {id}}}) => ({
|
||||||
path: `/${id}/socket.io`,
|
path: `/${id}/socket.io`,
|
||||||
}),
|
}),
|
||||||
|
'@flecks/core.mixin': (Flecks) => (
|
||||||
|
class FlecksWithSocketServer extends Flecks {
|
||||||
|
|
||||||
|
constructor(...args) {
|
||||||
|
super(...args);
|
||||||
|
if (!this.socket) {
|
||||||
|
this.socket = {};
|
||||||
|
}
|
||||||
|
this.socket.server = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
),
|
||||||
};
|
};
|
||||||
|
|
|
@ -35,7 +35,6 @@ export default class SocketServer {
|
||||||
...await this.flecks.invokeMergeAsync('@flecks/socket.server'),
|
...await this.flecks.invokeMergeAsync('@flecks/socket.server'),
|
||||||
serveClient: false,
|
serveClient: false,
|
||||||
});
|
});
|
||||||
this.flecks.set('$flecks/socket.io', this.io);
|
|
||||||
this.io.use(this.makeSocketMiddleware());
|
this.io.use(this.makeSocketMiddleware());
|
||||||
this.io.on('@flecks/socket.intercom', this.localIntercom);
|
this.io.on('@flecks/socket.intercom', this.localIntercom);
|
||||||
this.flecks.invoke('@flecks/socket.server.io', this);
|
this.flecks.invoke('@flecks/socket.server.io', this);
|
||||||
|
|
|
@ -12,7 +12,7 @@ export default class Socket {
|
||||||
}
|
}
|
||||||
|
|
||||||
listen() {
|
listen() {
|
||||||
const {[ByType]: PacketsByType} = this.flecks.get('$flecks/socket.packets');
|
const {[ByType]: PacketsByType} = this.flecks.socket.Packets;
|
||||||
const Packets = Object.entries(PacketsByType);
|
const Packets = Object.entries(PacketsByType);
|
||||||
for (let i = 0; i < Packets.length; i++) {
|
for (let i = 0; i < Packets.length; i++) {
|
||||||
const [type, Packet] = Packets[i];
|
const [type, Packet] = Packets[i];
|
||||||
|
|
|
@ -29,7 +29,7 @@ export const hooks = {
|
||||||
];
|
];
|
||||||
},
|
},
|
||||||
'@flecks/repl.commands': (flecks) => {
|
'@flecks/repl.commands': (flecks) => {
|
||||||
const {User} = flecks.get('$flecks/db.models');
|
const {User} = flecks.db.Models;
|
||||||
return {
|
return {
|
||||||
createUser: async (spec) => {
|
createUser: async (spec) => {
|
||||||
const [email, maybePassword] = spec.split(' ', 2);
|
const [email, maybePassword] = spec.split(' ', 2);
|
||||||
|
@ -54,7 +54,7 @@ export const hooks = {
|
||||||
passport.use(new LocalStrategy(
|
passport.use(new LocalStrategy(
|
||||||
{usernameField: 'email'},
|
{usernameField: 'email'},
|
||||||
async (email, password, fn) => {
|
async (email, password, fn) => {
|
||||||
const {User} = flecks.get('$flecks/db.models');
|
const {User} = flecks.db.Models;
|
||||||
try {
|
try {
|
||||||
const user = await User.findOne({where: {email}});
|
const user = await User.findOne({where: {email}});
|
||||||
fn(undefined, user && await user.validatePassword(password) && user);
|
fn(undefined, user && await user.validatePassword(password) && user);
|
||||||
|
|
|
@ -13,7 +13,7 @@ export const hooks = {
|
||||||
debugSilly('@flecks/web/server.request.route: passport.session()');
|
debugSilly('@flecks/web/server.request.route: passport.session()');
|
||||||
passport.session()(req, res, () => {
|
passport.session()(req, res, () => {
|
||||||
if (!req.user) {
|
if (!req.user) {
|
||||||
const {User} = flecks.get('$flecks/db.models');
|
const {User} = flecks.db.Models;
|
||||||
req.user = new User();
|
req.user = new User();
|
||||||
req.user.id = 0;
|
req.user.id = 0;
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ export const hooks = {
|
||||||
'@flecks/server.up': (flecks) => {
|
'@flecks/server.up': (flecks) => {
|
||||||
passport.serializeUser((user, fn) => fn(null, user.id));
|
passport.serializeUser((user, fn) => fn(null, user.id));
|
||||||
passport.deserializeUser(async (id, fn) => {
|
passport.deserializeUser(async (id, fn) => {
|
||||||
const {User} = flecks.get('$flecks/db.models');
|
const {User} = flecks.db.Models;
|
||||||
try {
|
try {
|
||||||
fn(undefined, await User.findByPk(id));
|
fn(undefined, await User.findByPk(id));
|
||||||
}
|
}
|
||||||
|
@ -63,7 +63,7 @@ export const hooks = {
|
||||||
debugSilly('@flecks/socket/server.request.socket: passport.session()');
|
debugSilly('@flecks/socket/server.request.socket: passport.session()');
|
||||||
passport.session()(socket.handshake, undefined, async () => {
|
passport.session()(socket.handshake, undefined, async () => {
|
||||||
if (!socket.handshake.user) {
|
if (!socket.handshake.user) {
|
||||||
const {User} = flecks.get('$flecks/db.models');
|
const {User} = flecks.db.Models;
|
||||||
socket.handshake.user = new User();
|
socket.handshake.user = new User();
|
||||||
socket.handshake.user.id = 0;
|
socket.handshake.user.id = 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import {D} from '@flecks/core';
|
import {D} from '@flecks/core';
|
||||||
import express from 'express';
|
import express from 'express';
|
||||||
import expressSession from 'express-session';
|
import user.session from 'express-session';
|
||||||
|
|
||||||
const debug = D('@flecks/user/session');
|
const debug = D('@flecks/user/session');
|
||||||
const debugSilly = debug.extend('silly');
|
const debugSilly = debug.extend('silly');
|
||||||
|
@ -16,6 +16,15 @@ export const hooks = {
|
||||||
'Set the FLECKS_ENV__flecks_user_session_server__cookieSecret environment variable!'
|
'Set the FLECKS_ENV__flecks_user_session_server__cookieSecret environment variable!'
|
||||||
),
|
),
|
||||||
}),
|
}),
|
||||||
|
'@flecks/core.mixin': (Flecks) => (
|
||||||
|
class FlecksWithUser extends Flecks {
|
||||||
|
|
||||||
|
user = {
|
||||||
|
session: undefined,
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
),
|
||||||
'@flecks/web/server.request.route': (flecks) => {
|
'@flecks/web/server.request.route': (flecks) => {
|
||||||
const urle = express.urlencoded({extended: true});
|
const urle = express.urlencoded({extended: true});
|
||||||
return (req, res, next) => {
|
return (req, res, next) => {
|
||||||
|
@ -26,7 +35,7 @@ export const hooks = {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
debugSilly('@flecks/web/server.request.route: session()');
|
debugSilly('@flecks/web/server.request.route: session()');
|
||||||
flecks.get('$flecks/user.session')(req, res, (error) => {
|
flecks.user.session(req, res, (error) => {
|
||||||
if (error) {
|
if (error) {
|
||||||
next(error);
|
next(error);
|
||||||
return;
|
return;
|
||||||
|
@ -38,17 +47,17 @@ export const hooks = {
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
'@flecks/server.up': async (flecks) => {
|
'@flecks/server.up': async (flecks) => {
|
||||||
flecks.set('$flecks/user.session', expressSession({
|
flecks.user.session = user.session({
|
||||||
resave: false,
|
resave: false,
|
||||||
sameSite: true,
|
sameSite: true,
|
||||||
saveUninitialized: false,
|
saveUninitialized: false,
|
||||||
secret: flecks.get('@flecks/user/session/server.cookieSecret'),
|
secret: flecks.get('@flecks/user/session/server.cookieSecret'),
|
||||||
...await flecks.invokeMergeAsync('@flecks/user.session'),
|
...await flecks.invokeMergeAsync('@flecks/user.session'),
|
||||||
}));
|
});
|
||||||
},
|
},
|
||||||
'@flecks/socket/server.request.socket': (flecks) => (socket, next) => {
|
'@flecks/socket/server.request.socket': (flecks) => (socket, next) => {
|
||||||
debugSilly('@flecks/socket/server.request.socket: session()');
|
debugSilly('@flecks/socket/server.request.socket: session()');
|
||||||
flecks.get('$flecks/user.session')(socket.handshake, {}, () => {
|
flecks.user.session(socket.handshake, {}, () => {
|
||||||
const id = socket.handshake.session?.id;
|
const id = socket.handshake.session?.id;
|
||||||
socket.join(id);
|
socket.join(id);
|
||||||
next();
|
next();
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import {compose, D, Flecks} from '@flecks/core';
|
import {compose, D, Flecks as BaseFlecks} from '@flecks/core';
|
||||||
|
|
||||||
// eslint-disable-next-line import/no-extraneous-dependencies, import/no-unresolved
|
// eslint-disable-next-line import/no-extraneous-dependencies, import/no-unresolved
|
||||||
const {version} = require('@flecks/web/package.json');
|
const {version} = require('@flecks/web/package.json');
|
||||||
|
@ -56,8 +56,8 @@ const {version} = require('@flecks/web/package.json');
|
||||||
const mixins = Object.entries(runtime.flecks)
|
const mixins = Object.entries(runtime.flecks)
|
||||||
.map(([, M]) => M.hooks?.['@flecks/core.mixin'])
|
.map(([, M]) => M.hooks?.['@flecks/core.mixin'])
|
||||||
.filter((e) => e);
|
.filter((e) => e);
|
||||||
const Class = compose(...mixins)(Flecks);
|
const Flecks = compose(...mixins)(BaseFlecks);
|
||||||
const flecks = new Class(runtime);
|
const flecks = new Flecks(runtime);
|
||||||
window.flecks = flecks;
|
window.flecks = flecks;
|
||||||
try {
|
try {
|
||||||
await Promise.all(flecks.invokeFlat('@flecks/core.starting'));
|
await Promise.all(flecks.invokeFlat('@flecks/core.starting'));
|
||||||
|
|
|
@ -2,7 +2,7 @@ import {Transform} from 'stream';
|
||||||
|
|
||||||
const config = async (flecks, req) => {
|
const config = async (flecks, req) => {
|
||||||
const httpConfig = await flecks.invokeMergeAsync('@flecks/web.config', req);
|
const httpConfig = await flecks.invokeMergeAsync('@flecks/web.config', req);
|
||||||
const {config} = flecks.get('$flecks/web.flecks');
|
const {config} = flecks.web.flecks;
|
||||||
const reducedConfig = Object.keys(config)
|
const reducedConfig = Object.keys(config)
|
||||||
.filter((path) => !path.startsWith('$'))
|
.filter((path) => !path.startsWith('$'))
|
||||||
.filter((path) => !path.endsWith('/server'))
|
.filter((path) => !path.endsWith('/server'))
|
||||||
|
|
|
@ -32,7 +32,7 @@ export const createHttpServer = async (flecks) => {
|
||||||
app.set('trust proxy', trust);
|
app.set('trust proxy', trust);
|
||||||
const httpServer = createServer(app);
|
const httpServer = createServer(app);
|
||||||
httpServer.app = app;
|
httpServer.app = app;
|
||||||
flecks.set('$flecks/web/server.instance', httpServer);
|
flecks.web.server = httpServer;
|
||||||
// Compression. heheh
|
// Compression. heheh
|
||||||
app.use(compression({level: 'production' === NODE_ENV ? 6 : 9}));
|
app.use(compression({level: 'production' === NODE_ENV ? 6 : 9}));
|
||||||
// Socket connection.
|
// Socket connection.
|
||||||
|
|
|
@ -183,6 +183,16 @@ export const hooks = {
|
||||||
*/
|
*/
|
||||||
trust: false,
|
trust: false,
|
||||||
}),
|
}),
|
||||||
|
'@flecks/core.mixin': (Flecks) => (
|
||||||
|
class FlecksWithWeb extends Flecks {
|
||||||
|
|
||||||
|
web = {
|
||||||
|
flecks: undefined,
|
||||||
|
server: undefined,
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
),
|
||||||
'@flecks/core.starting': (flecks) => {
|
'@flecks/core.starting': (flecks) => {
|
||||||
debug('bootstrapping flecks...');
|
debug('bootstrapping flecks...');
|
||||||
const webFlecks = Flecks.bootstrap({
|
const webFlecks = Flecks.bootstrap({
|
||||||
|
@ -190,7 +200,7 @@ export const hooks = {
|
||||||
platforms: ['client', '!server'],
|
platforms: ['client', '!server'],
|
||||||
});
|
});
|
||||||
debug('bootstrapped');
|
debug('bootstrapped');
|
||||||
flecks.set('$flecks/web.flecks', webFlecks);
|
flecks.web.flecks = webFlecks;
|
||||||
},
|
},
|
||||||
'@flecks/core.targets': (flecks) => [
|
'@flecks/core.targets': (flecks) => [
|
||||||
'web',
|
'web',
|
||||||
|
@ -208,7 +218,4 @@ export const hooks = {
|
||||||
],
|
],
|
||||||
'@flecks/web/server.stream.html': inlineConfig,
|
'@flecks/web/server.stream.html': inlineConfig,
|
||||||
'@flecks/server.up': (flecks) => createHttpServer(flecks),
|
'@flecks/server.up': (flecks) => createHttpServer(flecks),
|
||||||
'@flecks/repl.context': (flecks) => ({
|
|
||||||
httpServer: flecks.get('$flecks/web/server.instance'),
|
|
||||||
}),
|
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue
Block a user