refactor: db
This commit is contained in:
parent
9eb3dfe2c7
commit
17153dc50a
|
@ -10,8 +10,10 @@
|
|||
],
|
||||
}
|
||||
'@latus/db': {
|
||||
}
|
||||
'@latus/db/server': {
|
||||
models.decorate: [
|
||||
'@latus/user/local',
|
||||
'@latus/user/local/server',
|
||||
],
|
||||
docker: 'cached',
|
||||
}
|
||||
|
|
2876
app/yarn.lock
2876
app/yarn.lock
File diff suppressed because it is too large
Load Diff
|
@ -34,15 +34,16 @@ export const gatherWithLatus = (
|
|||
) => (latus) => (
|
||||
Object.fromEntries(context.keys().map((path) => {
|
||||
const M = context(path).default;
|
||||
if ('function' !== typeof M) {
|
||||
if ('function' !== typeof M || /^class\s/.test(Function.prototype.toString.call(M))) {
|
||||
throw new ReferenceError(
|
||||
`gatherWithLatus: require(${path}).default is not a function (from: ${context.id})`,
|
||||
);
|
||||
}
|
||||
return [
|
||||
const r = [
|
||||
transformer(basename(path, extname(path))),
|
||||
M(latus),
|
||||
];
|
||||
return r;
|
||||
}))
|
||||
);
|
||||
|
||||
|
@ -65,12 +66,23 @@ export default (
|
|||
Object.entries(composed)
|
||||
.sort(([lname], [rname]) => (lname < rname ? -1 : 1))
|
||||
.map(([type, Class]) => {
|
||||
// eslint-disable-next-line no-eval
|
||||
const Subclass = eval(`(${type}) => class Gathered${type} extends ${type} {}`)(Class);
|
||||
const thisUid = uid++;
|
||||
const source = `
|
||||
(${type}) => class Gathered${type} extends ${type} {
|
||||
|
||||
static get ${idAttribute}() {
|
||||
return ${thisUid};
|
||||
}
|
||||
|
||||
static get ${typeAttribute}() {
|
||||
return '${type}';
|
||||
}
|
||||
|
||||
}
|
||||
`;
|
||||
// eslint-disable-next-line no-eval
|
||||
const Subclass = eval(source)(Class);
|
||||
fromId[thisUid] = Subclass;
|
||||
Subclass[idAttribute] = thisUid;
|
||||
Subclass[typeAttribute] = type;
|
||||
return [
|
||||
type,
|
||||
Subclass,
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
import D from 'debug';
|
||||
import Sequelize from 'sequelize';
|
||||
|
||||
const debug = D('@latus/db/db');
|
||||
|
||||
const {
|
||||
MYSQL_USER,
|
||||
MYSQL_PASSWORD,
|
||||
|
@ -14,7 +11,7 @@ const {
|
|||
export async function createDatabaseConnection(latus) {
|
||||
const {
|
||||
config: {
|
||||
'@latus/db': {
|
||||
'@latus/db/server': {
|
||||
database,
|
||||
host,
|
||||
password,
|
||||
|
@ -32,32 +29,26 @@ export async function createDatabaseConnection(latus) {
|
|||
port: MYSQL_PORT || port,
|
||||
username: MYSQL_USER || user,
|
||||
});
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
latus.config['%sequelize'] = sequelize;
|
||||
// eslint-disable-next-line no-console
|
||||
const Models = latus.invokeReduce('@latus/db/models');
|
||||
debug('models: %O', Object.keys(Models));
|
||||
const map = latus.invokeComposed('@latus/db/models.decorate', Models);
|
||||
const decorated = Object.fromEntries(Object.entries(map).map(([name, Model]) => ([
|
||||
name,
|
||||
class FinalModel extends Model {
|
||||
|
||||
static name = name;
|
||||
|
||||
},
|
||||
])));
|
||||
debug('composed: %O', Object.keys(decorated));
|
||||
Object.entries(decorated)
|
||||
.filter(([, Model]) => Model.attributes)
|
||||
.forEach(([, Model]) => {
|
||||
latus.set('%sequelize', sequelize);
|
||||
const Models = latus.get('%models.fromName');
|
||||
Object.values(Models)
|
||||
.filter((Model) => Model.attributes)
|
||||
.forEach((Model) => {
|
||||
Model.init(Model.attributes, {
|
||||
sequelize,
|
||||
underscored: true,
|
||||
});
|
||||
});
|
||||
Object.entries(decorated).forEach(([, Model]) => Model.associate(decorated));
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
latus.config['%models'] = decorated;
|
||||
Object.values(Models)
|
||||
.forEach((Model) => Model.associate(Models));
|
||||
latus.set('%models.fromName', Models);
|
||||
latus.set(
|
||||
'%models.fromId',
|
||||
Object.fromEntries(
|
||||
Object.values(Models)
|
||||
.map((Model) => [Model.id, Model]),
|
||||
),
|
||||
);
|
||||
// eslint-disable-next-line no-constant-condition
|
||||
while (true) {
|
||||
try {
|
||||
|
@ -70,7 +61,7 @@ export async function createDatabaseConnection(latus) {
|
|||
await new Promise((resolve) => setTimeout(resolve, 250));
|
||||
}
|
||||
}
|
||||
Object.entries(decorated).forEach(([, Model]) => Model.sync());
|
||||
Object.values(Models).forEach((Model) => Model.sync());
|
||||
await sequelize.sync();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,84 +0,0 @@
|
|||
import D from 'debug';
|
||||
import Sequelize from 'sequelize';
|
||||
|
||||
const debug = D('@latus/db/db');
|
||||
|
||||
const {
|
||||
MYSQL_USER,
|
||||
MYSQL_PASSWORD,
|
||||
MYSQL_HOST,
|
||||
MYSQL_PORT,
|
||||
MYSQL_DATABASE,
|
||||
} = process.env;
|
||||
|
||||
export const ModelMap = (latus) => latus.config['%models'];
|
||||
|
||||
export async function createDatabaseConnection(latus) {
|
||||
const {
|
||||
config: {
|
||||
'@latus/db': {
|
||||
database,
|
||||
host,
|
||||
password,
|
||||
port,
|
||||
user,
|
||||
},
|
||||
},
|
||||
} = latus;
|
||||
const sequelize = new Sequelize({
|
||||
database: MYSQL_DATABASE || database,
|
||||
dialect: 'mysql',
|
||||
host: MYSQL_HOST || host,
|
||||
logging: false,
|
||||
password: MYSQL_PASSWORD || password,
|
||||
port: MYSQL_PORT || port,
|
||||
username: MYSQL_USER || user,
|
||||
});
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
latus.config['%sequelize'] = sequelize;
|
||||
// eslint-disable-next-line no-console
|
||||
const Models = latus.invokeReduce('@latus/db/models');
|
||||
debug('models: %O', Object.keys(Models));
|
||||
const map = latus.invokeComposed('@latus/db/models.decorate', Models);
|
||||
const decorated = Object.fromEntries(Object.entries(map).map(([name, Model]) => ([
|
||||
name,
|
||||
class FinalModel extends Model {
|
||||
|
||||
static name = name;
|
||||
|
||||
},
|
||||
])));
|
||||
debug('composed: %O', Object.keys(decorated));
|
||||
Object.entries(decorated)
|
||||
.filter(([, Model]) => Model.attributes)
|
||||
.forEach(([, Model]) => {
|
||||
Model.init(Model.attributes, {
|
||||
sequelize,
|
||||
underscored: true,
|
||||
});
|
||||
});
|
||||
Object.entries(decorated).forEach(([, Model]) => Model.associate(decorated));
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
latus.config['%models'] = decorated;
|
||||
// eslint-disable-next-line no-constant-condition
|
||||
while (true) {
|
||||
try {
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
await sequelize.authenticate();
|
||||
break;
|
||||
}
|
||||
catch (error) {
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
await new Promise((resolve) => setTimeout(resolve, 250));
|
||||
}
|
||||
}
|
||||
Object.entries(decorated).forEach(([, Model]) => Model.sync());
|
||||
await sequelize.sync();
|
||||
}
|
||||
|
||||
export function destroyDatabaseConnection(databaseConnection) {
|
||||
if (!databaseConnection) {
|
||||
return undefined;
|
||||
}
|
||||
return databaseConnection.close();
|
||||
}
|
|
@ -5,7 +5,7 @@ import mkdirp from 'mkdirp';
|
|||
export default function createDockerContainer(latus) {
|
||||
const {
|
||||
config: {
|
||||
'@latus/db': {
|
||||
'@latus/db/server': {
|
||||
database,
|
||||
docker,
|
||||
password,
|
||||
|
|
|
@ -1,14 +1 @@
|
|||
export const ModelMap = (latus) => latus.config['%models'];
|
||||
|
||||
export default {
|
||||
hooks: {
|
||||
'@latus/core/config': () => ({
|
||||
database: 'db',
|
||||
docker: true,
|
||||
host: '127.0.0.1',
|
||||
password: 'UNSAFE_DEV_PASSWORD',
|
||||
port: '32342',
|
||||
user: 'root',
|
||||
}),
|
||||
},
|
||||
};
|
||||
export default {};
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import {gather} from '@latus/core';
|
||||
|
||||
import {createDatabaseConnection} from './connection';
|
||||
import createDockerContainer from './docker';
|
||||
|
||||
|
@ -11,8 +13,26 @@ export {default as Model} from './model';
|
|||
|
||||
export default {
|
||||
hooks: {
|
||||
'@latus/core/config': () => ({
|
||||
database: 'db',
|
||||
docker: true,
|
||||
host: '127.0.0.1',
|
||||
password: 'UNSAFE_DEV_PASSWORD',
|
||||
port: '32342',
|
||||
user: 'root',
|
||||
}),
|
||||
'@latus/core/starting': (latus) => {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
latus.set('%models', gather(
|
||||
latus,
|
||||
{
|
||||
type: '@latus/db/server/models',
|
||||
typeAttribute: 'name',
|
||||
},
|
||||
));
|
||||
},
|
||||
'@latus/core/up': (latus) => {
|
||||
const {config: {'@latus/db': {docker}}} = latus;
|
||||
const {config: {'@latus/db/server': {docker}}} = latus;
|
||||
if ('production' !== NODE_ENV && docker) {
|
||||
createDockerContainer(latus);
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
"test.js.map"
|
||||
],
|
||||
"dependencies": {
|
||||
"@latus/core": "^2.0.0",
|
||||
"debug": "4.3.1",
|
||||
"rate-limiter-flexible": "^2.1.13"
|
||||
},
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import {ModelMap} from '@latus/db';
|
||||
import {gatherWithLatus} from '@latus/core';
|
||||
|
||||
import Ban from './ban';
|
||||
import LimitedPacket from './limited-packet';
|
||||
import createLimiter from './limiter';
|
||||
|
||||
|
@ -8,9 +7,9 @@ export {default as createLimiter} from './limiter';
|
|||
|
||||
export default {
|
||||
hooks: {
|
||||
'@latus/db/models': (latus) => ({
|
||||
Ban: Ban(latus),
|
||||
}),
|
||||
'@latus/db/server/models': gatherWithLatus(
|
||||
require.context('./models', false, /\.js$/),
|
||||
),
|
||||
'@latus/http/request': (latus) => {
|
||||
const {config: {'@latus/governor': {http}}} = latus;
|
||||
const limiter = createLimiter(latus, {
|
||||
|
@ -18,7 +17,7 @@ export default {
|
|||
...http,
|
||||
});
|
||||
return async (req, res, next) => {
|
||||
const {Ban} = ModelMap(latus);
|
||||
const {Ban} = latus.get('%models.fromName');
|
||||
try {
|
||||
await Ban.check(req);
|
||||
}
|
||||
|
@ -51,7 +50,7 @@ export default {
|
|||
});
|
||||
return async (socket, next) => {
|
||||
const {handshake: req} = socket;
|
||||
const {Ban} = ModelMap(latus);
|
||||
const {Ban} = latus.get('%models.fromName');
|
||||
try {
|
||||
await Ban.check(req);
|
||||
}
|
||||
|
|
|
@ -901,7 +901,7 @@
|
|||
object-assign "^4.1.1"
|
||||
scheduler "^0.20.1"
|
||||
|
||||
"@latus/core@2.0.0":
|
||||
"@latus/core@2.0.0", "@latus/core@^2.0.0":
|
||||
version "2.0.0"
|
||||
resolved "http://npm.cha0sdev/@latus%2fcore/-/core-2.0.0.tgz#2ca04903351edc14f29fcec2ad6ab5e19c72e072"
|
||||
integrity sha512-Sq4nPpQzRektLgsXRFQqhZWpUWY1bFTrVbm5X0vGTyTTlfQPmMbHyddmtdVTB8NbANvleuw4PvfuNVqKU4le6w==
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
"files": [
|
||||
"index.js",
|
||||
"index.js.map",
|
||||
"server.js",
|
||||
"server.js.map",
|
||||
"test.js",
|
||||
"test.js.map"
|
||||
],
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
"test.js.map"
|
||||
],
|
||||
"dependencies": {
|
||||
"@latus/core": "^2.0.0",
|
||||
"bcrypt": "^5.0.0",
|
||||
"debug": "4.3.1",
|
||||
"express": "^4.17.1",
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
import {randomBytes} from 'crypto';
|
||||
|
||||
import {ModelMap} from '@latus/db';
|
||||
import {decorateWithLatus} from '@latus/core';
|
||||
import passport from 'passport';
|
||||
import LocalStrategy from 'passport-local';
|
||||
|
||||
import UserLocal from '../models/user-local';
|
||||
|
||||
export default {
|
||||
hooks: {
|
||||
'@latus/core/config': () => ({
|
||||
|
@ -16,7 +14,7 @@ export default {
|
|||
passport.use(new LocalStrategy(
|
||||
{usernameField: 'email'},
|
||||
async (email, password, fn) => {
|
||||
const {User} = ModelMap(latus);
|
||||
const {User} = latus.get('%models.fromName');
|
||||
try {
|
||||
const user = await User.findOne({where: {email}});
|
||||
fn(undefined, user && await user.validatePassword(password) && user);
|
||||
|
@ -27,10 +25,9 @@ export default {
|
|||
},
|
||||
));
|
||||
},
|
||||
'@latus/db/models.decorate': (Models) => ({
|
||||
...Models,
|
||||
User: UserLocal(Models.User),
|
||||
}),
|
||||
'@latus/db/server/models.decorate': decorateWithLatus(
|
||||
require.context('../models/decorators', false, /\.js$/),
|
||||
),
|
||||
'@latus/http/routes': ({
|
||||
config: {
|
||||
'@latus/user/local': {
|
||||
|
@ -67,7 +64,7 @@ export default {
|
|||
},
|
||||
],
|
||||
'@latus/repl/commands': (latus) => {
|
||||
const {User} = ModelMap(latus);
|
||||
const {User} = latus.get('%models.fromName');
|
||||
return {
|
||||
createUser: (spec) => {
|
||||
const [email, maybePassword] = spec.split(' ', 2);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import {Types} from '@latus/db/server';
|
||||
import bcrypt from 'bcrypt';
|
||||
|
||||
export default (User) => class UserLocal extends User {
|
||||
export default (latus, User) => class UserLocal extends User {
|
||||
|
||||
static saltRounds = 10;
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
export {default as Permission} from './permission';
|
||||
export {default as User} from './user';
|
|
@ -1,6 +1,6 @@
|
|||
import {Model, Types} from '@latus/db/server';
|
||||
|
||||
class Permission extends Model {
|
||||
export default () => class Permission extends Model {
|
||||
|
||||
static get attributes() {
|
||||
return {
|
||||
|
@ -13,6 +13,4 @@ class Permission extends Model {
|
|||
this.belongsToMany(User, {through: 'user_permissions'});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default Permission;
|
||||
};
|
||||
|
|
|
@ -4,7 +4,7 @@ import {
|
|||
Types,
|
||||
} from '@latus/db/server';
|
||||
|
||||
class User extends Model {
|
||||
export default () => class User extends Model {
|
||||
|
||||
static get attributes() {
|
||||
return {
|
||||
|
@ -19,6 +19,4 @@ class User extends Model {
|
|||
this.belongsToMany(Permission, {through: 'user_permissions'});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default User;
|
||||
};
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
import {ModelMap} from '@latus/db';
|
||||
import {gatherWithLatus} from '@latus/core';
|
||||
import D from 'debug';
|
||||
import passport from 'passport';
|
||||
import LogOps from 'passport/lib/http/request';
|
||||
|
||||
import * as models from './models';
|
||||
|
||||
const debug = D('@latus/user/passport');
|
||||
|
||||
export default {
|
||||
|
@ -12,7 +10,7 @@ export default {
|
|||
'@latus/core/up': (latus) => {
|
||||
passport.serializeUser((user, fn) => fn(null, user.id));
|
||||
passport.deserializeUser(async (id, fn) => {
|
||||
const {User} = ModelMap(latus);
|
||||
const {User} = latus.get('%models.fromName');
|
||||
try {
|
||||
fn(undefined, await User.findByPk(id));
|
||||
}
|
||||
|
@ -21,14 +19,16 @@ export default {
|
|||
}
|
||||
});
|
||||
},
|
||||
'@latus/db/models': () => models,
|
||||
'@latus/db/server/models': gatherWithLatus(
|
||||
require.context('./models', false, /\.js$/),
|
||||
),
|
||||
'@latus/http/request': (latus) => (req, res, next) => {
|
||||
debug('@latus/http/request: passport.initialize()');
|
||||
passport.initialize()(req, res, () => {
|
||||
debug('@latus/http/request: passport.session()');
|
||||
passport.session()(req, res, () => {
|
||||
if (!req.user) {
|
||||
const {User} = ModelMap(latus);
|
||||
const {User} = latus.get('%models.fromName');
|
||||
req.user = new User();
|
||||
req.user.id = 0;
|
||||
}
|
||||
|
@ -67,7 +67,7 @@ export default {
|
|||
passport.session()(socket.handshake, undefined, async () => {
|
||||
/* eslint-disable no-param-reassign */
|
||||
if (!socket.handshake.user) {
|
||||
const {User} = ModelMap(latus);
|
||||
const {User} = latus.get('%models.fromName');
|
||||
socket.handshake.user = new User();
|
||||
socket.handshake.user.id = 0;
|
||||
}
|
||||
|
|
|
@ -901,7 +901,7 @@
|
|||
object-assign "^4.1.1"
|
||||
scheduler "^0.20.1"
|
||||
|
||||
"@latus/core@2.0.0":
|
||||
"@latus/core@2.0.0", "@latus/core@^2.0.0":
|
||||
version "2.0.0"
|
||||
resolved "http://npm.cha0sdev/@latus%2fcore/-/core-2.0.0.tgz#2ca04903351edc14f29fcec2ad6ab5e19c72e072"
|
||||
integrity sha512-Sq4nPpQzRektLgsXRFQqhZWpUWY1bFTrVbm5X0vGTyTTlfQPmMbHyddmtdVTB8NbANvleuw4PvfuNVqKU4le6w==
|
||||
|
|
Loading…
Reference in New Issue
Block a user