Merge branch 'feature/sequelize' of Software_Engineering_I/greenvironment-server into julius-dev
commit
7d9495863f
File diff suppressed because it is too large
Load Diff
@ -1,212 +0,0 @@
|
|||||||
/**
|
|
||||||
* @author Trivernis
|
|
||||||
* @remarks
|
|
||||||
*
|
|
||||||
* Taken from {@link https://github.com/Trivernis/whooshy}
|
|
||||||
*/
|
|
||||||
|
|
||||||
import * as fsx from "fs-extra";
|
|
||||||
import {Pool, PoolClient, QueryConfig, QueryResult} from "pg";
|
|
||||||
import globals from "./globals";
|
|
||||||
|
|
||||||
const logger = globals.logger;
|
|
||||||
|
|
||||||
export interface IAdvancedQueryConfig extends QueryConfig {
|
|
||||||
cache?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Transaction class to wrap SQL transactions.
|
|
||||||
*/
|
|
||||||
export class SqlTransaction {
|
|
||||||
/**
|
|
||||||
* Constructor.
|
|
||||||
* @param client
|
|
||||||
*/
|
|
||||||
constructor(private client: PoolClient) {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Begins the transaction.
|
|
||||||
*/
|
|
||||||
public async begin() {
|
|
||||||
return await this.client.query("BEGIN");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Commits the transaction
|
|
||||||
*/
|
|
||||||
public async commit() {
|
|
||||||
return await this.client.query("COMMIT");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Rolls back the transaction
|
|
||||||
*/
|
|
||||||
public async rollback() {
|
|
||||||
return await this.client.query("ROLLBACK");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Executes a query inside the transaction.
|
|
||||||
* @param query
|
|
||||||
*/
|
|
||||||
public async query(query: QueryConfig) {
|
|
||||||
return await this.client.query(query);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Releases the client back to the pool.
|
|
||||||
*/
|
|
||||||
public release() {
|
|
||||||
this.client.release();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Query helper for easyer fetching of a specific row count.
|
|
||||||
*/
|
|
||||||
export class QueryHelper {
|
|
||||||
private pool: Pool;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor.
|
|
||||||
* @param pgPool
|
|
||||||
* @param [tableCreationFile]
|
|
||||||
* @param [tableUpdateFile]
|
|
||||||
*/
|
|
||||||
constructor(pgPool: Pool, private tableCreationFile?: string, private tableUpdateFile?: string) {
|
|
||||||
this.pool = pgPool;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Async init function
|
|
||||||
*/
|
|
||||||
public async init() {
|
|
||||||
await this.pool.connect();
|
|
||||||
await this.createTables();
|
|
||||||
await this.updateTableDefinitions();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* creates all tables needed if a filepath was given with the constructor
|
|
||||||
*/
|
|
||||||
public async createTables() {
|
|
||||||
if (this.tableCreationFile) {
|
|
||||||
logger.info("Creating nonexistent tables...");
|
|
||||||
const tableSql = await fsx.readFile(this.tableCreationFile, "utf-8");
|
|
||||||
const trans = await this.createTransaction();
|
|
||||||
await trans.begin();
|
|
||||||
try {
|
|
||||||
await trans.query({text: tableSql});
|
|
||||||
await trans.commit();
|
|
||||||
} catch (err) {
|
|
||||||
globals.logger.error(`Error on table creation ${err.message}`);
|
|
||||||
globals.logger.debug(err.stack);
|
|
||||||
await trans.rollback();
|
|
||||||
} finally {
|
|
||||||
trans.release();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates the definition of the tables if the table update file was passed in the constructor
|
|
||||||
*/
|
|
||||||
public async updateTableDefinitions() {
|
|
||||||
if (this.tableUpdateFile) {
|
|
||||||
logger.info("Updating table definitions...");
|
|
||||||
const tableSql = await fsx.readFile(this.tableUpdateFile, "utf-8");
|
|
||||||
const trans = await this.createTransaction();
|
|
||||||
await trans.begin();
|
|
||||||
try {
|
|
||||||
await trans.query({text: tableSql});
|
|
||||||
await trans.commit();
|
|
||||||
} catch (err) {
|
|
||||||
globals.logger.error(`Error on table update ${err.message}`);
|
|
||||||
globals.logger.debug(err.stack);
|
|
||||||
await trans.rollback();
|
|
||||||
} finally {
|
|
||||||
trans.release();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* executes the sql query with values and returns all results.
|
|
||||||
* @param query
|
|
||||||
*/
|
|
||||||
public async all(query: IAdvancedQueryConfig): Promise<any[]> {
|
|
||||||
const result = await this.query(query);
|
|
||||||
return result.rows;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* executes the sql query with values and returns the first result.
|
|
||||||
* @param query
|
|
||||||
*/
|
|
||||||
public async first(query: IAdvancedQueryConfig): Promise<any> {
|
|
||||||
const result = await this.query(query);
|
|
||||||
if (result.rows && result.rows.length > 0) {
|
|
||||||
return result.rows[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new Transaction to be uses with error handling.
|
|
||||||
*/
|
|
||||||
public async createTransaction() {
|
|
||||||
const client: PoolClient = await this.pool.connect();
|
|
||||||
return new SqlTransaction(client);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Queries the database with error handling.
|
|
||||||
* @param query - the sql and values to execute
|
|
||||||
*/
|
|
||||||
private async query(query: IAdvancedQueryConfig): Promise<QueryResult|{rows: any}> {
|
|
||||||
try {
|
|
||||||
query.text = query.text.replace(/[\r\n]/g, " ");
|
|
||||||
globals.logger.silly(`Executing sql '${JSON.stringify(query)}'`);
|
|
||||||
|
|
||||||
if (query.cache) {
|
|
||||||
const key = globals.cache.hashKey(JSON.stringify(query));
|
|
||||||
const cacheResult = globals.cache.get(key);
|
|
||||||
if (cacheResult) {
|
|
||||||
return cacheResult;
|
|
||||||
} else {
|
|
||||||
const result = await this.pool.query(query);
|
|
||||||
globals.cache.set(key, result);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return await this.pool.query(query);
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
logger.debug(`Error on query "${JSON.stringify(query)}".`);
|
|
||||||
logger.error(`Sql query failed: ${err}`);
|
|
||||||
logger.verbose(err.stack);
|
|
||||||
return {
|
|
||||||
rows: null,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the parameterized value sql for inserting
|
|
||||||
* @param columnCount
|
|
||||||
* @param rowCount
|
|
||||||
* @param [offset]
|
|
||||||
*/
|
|
||||||
export function buildSqlParameters(columnCount: number, rowCount: number, offset?: number): string {
|
|
||||||
let sql = "";
|
|
||||||
for (let i = 0; i < rowCount; i++) {
|
|
||||||
sql += "(";
|
|
||||||
for (let j = 0; j < columnCount; j++) {
|
|
||||||
sql += `$${(i * columnCount) + j + 1 + offset},`;
|
|
||||||
}
|
|
||||||
sql = sql.replace(/,$/, "") + "),";
|
|
||||||
}
|
|
||||||
return sql.replace(/,$/, "");
|
|
||||||
}
|
|
@ -1,31 +1,38 @@
|
|||||||
import markdown from "../markdown";
|
import markdown from "../markdown";
|
||||||
import {Chatroom} from "./Chatroom";
|
import {Chatroom} from "./Chatroom";
|
||||||
|
import * as models from "./datamodels/models";
|
||||||
import {User} from "./User";
|
import {User} from "./User";
|
||||||
|
|
||||||
export class ChatMessage {
|
export class ChatMessage {
|
||||||
constructor(
|
|
||||||
public readonly author: User,
|
public id: number;
|
||||||
public readonly chat: Chatroom,
|
public content: string;
|
||||||
public readonly createdAt: number,
|
public createdAt: Date;
|
||||||
public readonly content: string) {}
|
|
||||||
|
constructor(private message: models.ChatMessage) {
|
||||||
|
this.id = message.id;
|
||||||
|
this.content = message.content;
|
||||||
|
this.createdAt = message.createdAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns the author of the chat message.
|
||||||
|
*/
|
||||||
|
public async author(): Promise<User> {
|
||||||
|
return new User(await this.message.getAuthor());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The content rendered by markdown-it.
|
* Returns the rendered html content of the chat message.
|
||||||
*/
|
*/
|
||||||
public htmlContent(): string {
|
public htmlContent(): string {
|
||||||
return markdown.renderInline(this.content);
|
return markdown.renderInline(this.content);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns resolved and rendered content of the chat message.
|
* returns the chatroom for the chatmessage.
|
||||||
*/
|
*/
|
||||||
public resolvedContent() {
|
public async chat(): Promise<Chatroom> {
|
||||||
return {
|
return (await this.message.getChat()).chatroom;
|
||||||
author: this.author.id,
|
|
||||||
chat: this.chat.id,
|
|
||||||
content: this.content,
|
|
||||||
createdAt: this.createdAt,
|
|
||||||
htmlContent: this.htmlContent(),
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,40 +0,0 @@
|
|||||||
/**
|
|
||||||
* abstact DataObject class
|
|
||||||
*/
|
|
||||||
import {EventEmitter} from "events";
|
|
||||||
|
|
||||||
export abstract class DataObject extends EventEmitter {
|
|
||||||
protected dataLoaded: boolean = false;
|
|
||||||
private loadingData: boolean = false;
|
|
||||||
|
|
||||||
constructor(public id: number, protected row?: any) {
|
|
||||||
super();
|
|
||||||
this.id = Number(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns if the object extists by trying to load data.
|
|
||||||
*/
|
|
||||||
public async exists() {
|
|
||||||
await this.loadDataIfNotExists();
|
|
||||||
return this.dataLoaded;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract loadData(): Promise<void>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Loads data from the database if data has not been loaded
|
|
||||||
*/
|
|
||||||
protected async loadDataIfNotExists() {
|
|
||||||
if (!this.dataLoaded && !this.loadingData) {
|
|
||||||
this.loadingData = true;
|
|
||||||
await this.loadData();
|
|
||||||
this.loadingData = false;
|
|
||||||
this.emit("loaded");
|
|
||||||
} else if (this.loadingData) {
|
|
||||||
return new Promise((res) => {
|
|
||||||
this.on("loaded", () => res());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,24 +0,0 @@
|
|||||||
import dataaccess from "./index";
|
|
||||||
import {User} from "./User";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a request to a user.
|
|
||||||
*/
|
|
||||||
export class Request {
|
|
||||||
constructor(
|
|
||||||
public readonly sender: User,
|
|
||||||
public readonly receiver: User,
|
|
||||||
public readonly type: dataaccess.RequestType) {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the resolved request data.
|
|
||||||
*/
|
|
||||||
public resolvedData() {
|
|
||||||
return {
|
|
||||||
receiverId: this.receiver.id,
|
|
||||||
senderId: this.sender.id,
|
|
||||||
type: this.type,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,12 @@
|
|||||||
|
export {
|
||||||
|
init as datainit,
|
||||||
|
User as SqUser,
|
||||||
|
Post as SqPost,
|
||||||
|
Chat as SqChat,
|
||||||
|
Request as SqRequest,
|
||||||
|
PostVotes as SqPostVotes,
|
||||||
|
ChatMessage as SqChatMessage,
|
||||||
|
ChatMembers as SqChatMembers,
|
||||||
|
RequestType as SqRequestType,
|
||||||
|
UserFriends as SqUserFriends,
|
||||||
|
} from "./models";
|
@ -0,0 +1,279 @@
|
|||||||
|
// tslint:disable:object-literal-sort-keys
|
||||||
|
|
||||||
|
import * as sqz from "sequelize";
|
||||||
|
import {
|
||||||
|
Association,
|
||||||
|
BelongsToGetAssociationMixin,
|
||||||
|
BelongsToManyAddAssociationMixin,
|
||||||
|
BelongsToManyCountAssociationsMixin,
|
||||||
|
BelongsToManyCreateAssociationMixin,
|
||||||
|
BelongsToManyGetAssociationsMixin,
|
||||||
|
BelongsToManyHasAssociationMixin,
|
||||||
|
DataTypes,
|
||||||
|
HasManyAddAssociationMixin,
|
||||||
|
HasManyCountAssociationsMixin,
|
||||||
|
HasManyCreateAssociationMixin,
|
||||||
|
HasManyGetAssociationsMixin,
|
||||||
|
HasManyHasAssociationMixin,
|
||||||
|
HasOneGetAssociationMixin,
|
||||||
|
Model,
|
||||||
|
Sequelize,
|
||||||
|
} from "sequelize";
|
||||||
|
import * as wrappers from "../wrappers";
|
||||||
|
|
||||||
|
const underscored = true;
|
||||||
|
|
||||||
|
enum VoteType {
|
||||||
|
UPVOTE = "UPVOTE",
|
||||||
|
DOWNVOTE = "DOWNVOTE",
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum RequestType {
|
||||||
|
FRIENDREQUEST = "FRIENDREQUEST",
|
||||||
|
GROUPINVITE = "GROUPINVITE",
|
||||||
|
EVENTINVITE = "EVENTINVITE",
|
||||||
|
}
|
||||||
|
|
||||||
|
export class User extends Model {
|
||||||
|
|
||||||
|
public static associations: {
|
||||||
|
friends: Association<User, User>;
|
||||||
|
posts: Association<User, Post>;
|
||||||
|
votes: Association<User, PostVotes>;
|
||||||
|
requests: Association<User, Request>;
|
||||||
|
};
|
||||||
|
|
||||||
|
public id!: number;
|
||||||
|
public username!: string;
|
||||||
|
public handle!: string;
|
||||||
|
public email!: string;
|
||||||
|
public password!: string;
|
||||||
|
public rankpoints!: number;
|
||||||
|
|
||||||
|
public readonly createdAt!: Date;
|
||||||
|
public readonly updatedAt!: Date;
|
||||||
|
|
||||||
|
public getFriends!: HasManyGetAssociationsMixin<User>;
|
||||||
|
public addFriend!: HasManyAddAssociationMixin<User, number>;
|
||||||
|
public hasFriend!: HasManyHasAssociationMixin<User, number>;
|
||||||
|
public countFriends!: HasManyCountAssociationsMixin;
|
||||||
|
|
||||||
|
public getPosts!: HasManyGetAssociationsMixin<Post>;
|
||||||
|
public addPost!: HasManyAddAssociationMixin<Post, number>;
|
||||||
|
public hasPost!: HasManyHasAssociationMixin<Post, number>;
|
||||||
|
public countPosts!: HasManyCountAssociationsMixin;
|
||||||
|
public createPost!: HasManyCreateAssociationMixin<Post>;
|
||||||
|
|
||||||
|
public getReceivedRequests!: HasManyGetAssociationsMixin<Request>;
|
||||||
|
public addReceivedRequest!: HasManyAddAssociationMixin<Request, number>;
|
||||||
|
public hasReceivedRequest!: HasManyHasAssociationMixin<Request, number>;
|
||||||
|
public countReceivedRequests!: HasManyCountAssociationsMixin;
|
||||||
|
public createReceivedRequest!: HasManyCreateAssociationMixin<Request>;
|
||||||
|
|
||||||
|
|
||||||
|
public getSentRequests!: HasManyGetAssociationsMixin<Request>;
|
||||||
|
public addSentRequest!: HasManyAddAssociationMixin<Request, number>;
|
||||||
|
public hasSentRequest!: HasManyHasAssociationMixin<Request, number>;
|
||||||
|
public countSentRequests!: HasManyCountAssociationsMixin;
|
||||||
|
public createSentRequest!: HasManyCreateAssociationMixin<Request>;
|
||||||
|
|
||||||
|
public getChats!: BelongsToManyGetAssociationsMixin<Chat>;
|
||||||
|
public addChat!: BelongsToManyAddAssociationMixin<Chat, number>;
|
||||||
|
public hasChat!: BelongsToManyHasAssociationMixin<Chat, number>;
|
||||||
|
public countChats!: BelongsToManyCountAssociationsMixin;
|
||||||
|
public createChat!: BelongsToManyCreateAssociationMixin<Chat>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Getter for joined at as the date the entry was created.
|
||||||
|
*/
|
||||||
|
public get joinedAt(): Date {
|
||||||
|
// @ts-ignore
|
||||||
|
return this.getDataValue("createdAt");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wraps itself into a user
|
||||||
|
*/
|
||||||
|
public get user(): wrappers.User {
|
||||||
|
return new wrappers.User(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns the username.
|
||||||
|
*/
|
||||||
|
public get name(): string {
|
||||||
|
return this.getDataValue("username");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wraps itself into a profile.
|
||||||
|
*/
|
||||||
|
public get profile(): wrappers.Profile {
|
||||||
|
return new wrappers.Profile(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class UserFriends extends Model {
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Post extends Model {
|
||||||
|
|
||||||
|
public static associations: {
|
||||||
|
author: Association<Post, User>,
|
||||||
|
votes: Association<Post, PostVotes>,
|
||||||
|
};
|
||||||
|
|
||||||
|
public id!: number;
|
||||||
|
public content!: string;
|
||||||
|
|
||||||
|
public readonly createdAt!: Date;
|
||||||
|
public readonly updatedAt!: Date;
|
||||||
|
|
||||||
|
public getUser!: BelongsToGetAssociationMixin<User>;
|
||||||
|
|
||||||
|
public getVotes!: HasManyGetAssociationsMixin<PostVotes>;
|
||||||
|
public addVote!: HasManyAddAssociationMixin<PostVotes, number>;
|
||||||
|
public hasVote!: HasManyHasAssociationMixin<PostVotes, number>;
|
||||||
|
public countVotes!: HasManyCountAssociationsMixin;
|
||||||
|
public createVote!: HasManyCreateAssociationMixin<PostVotes>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wraps itself into a Post instance.
|
||||||
|
*/
|
||||||
|
public get post(): wrappers.Post {
|
||||||
|
return new wrappers.Post(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class PostVotes extends Model {
|
||||||
|
public voteType: VoteType;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Request extends Model {
|
||||||
|
public id!: number;
|
||||||
|
public requestType!: RequestType;
|
||||||
|
|
||||||
|
public getSender!: HasOneGetAssociationMixin<User>;
|
||||||
|
public getReceiver!: HasOneGetAssociationMixin<User>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Chat extends Model {
|
||||||
|
public static associations: {
|
||||||
|
members: Association<Chat, User>,
|
||||||
|
messages: Association<Chat, ChatMessage>,
|
||||||
|
};
|
||||||
|
|
||||||
|
public id!: number;
|
||||||
|
|
||||||
|
public readonly createdAt!: Date;
|
||||||
|
public readonly updatedAt!: Date;
|
||||||
|
|
||||||
|
public getMembers!: BelongsToManyGetAssociationsMixin<User>;
|
||||||
|
public addMember!: BelongsToManyAddAssociationMixin<User, number>;
|
||||||
|
public hasMember!: BelongsToManyHasAssociationMixin<User, number>;
|
||||||
|
public countMembers!: BelongsToManyCountAssociationsMixin;
|
||||||
|
|
||||||
|
public getMessages!: HasManyGetAssociationsMixin<ChatMessage>;
|
||||||
|
public addMessage!: HasManyAddAssociationMixin<ChatMessage, number>;
|
||||||
|
public hasMessage!: HasManyHasAssociationMixin<ChatMessage, number>;
|
||||||
|
public countMessages!: HasManyCountAssociationsMixin;
|
||||||
|
public createMessage!: HasManyCreateAssociationMixin<ChatMessage>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* wraps itself into a chatroom.
|
||||||
|
*/
|
||||||
|
public get chatroom(): wrappers.Chatroom {
|
||||||
|
return new wrappers.Chatroom(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ChatMembers extends Model {
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ChatMessage extends Model {
|
||||||
|
public id: number;
|
||||||
|
public content!: string;
|
||||||
|
public readonly createdAt!: Date;
|
||||||
|
public readonly updatedAt!: Date;
|
||||||
|
|
||||||
|
public getAuthor!: BelongsToGetAssociationMixin<User>;
|
||||||
|
public getChat!: BelongsToGetAssociationMixin<Chat>;
|
||||||
|
|
||||||
|
public get message(): wrappers.ChatMessage {
|
||||||
|
return new wrappers.ChatMessage(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function init(sequelize: Sequelize) {
|
||||||
|
User.init({
|
||||||
|
username: {
|
||||||
|
allowNull: false,
|
||||||
|
type: sqz.STRING(128),
|
||||||
|
},
|
||||||
|
handle: {
|
||||||
|
allowNull: false,
|
||||||
|
type: sqz.STRING(128),
|
||||||
|
unique: true,
|
||||||
|
},
|
||||||
|
email: {
|
||||||
|
allowNull: false,
|
||||||
|
type: sqz.STRING(128),
|
||||||
|
unique: true,
|
||||||
|
},
|
||||||
|
password: {
|
||||||
|
allowNull: false,
|
||||||
|
type: sqz.STRING(128),
|
||||||
|
},
|
||||||
|
rankpoints: {
|
||||||
|
allowNull: false,
|
||||||
|
type: DataTypes.INTEGER,
|
||||||
|
defaultValue: 0,
|
||||||
|
},
|
||||||
|
}, {sequelize, underscored});
|
||||||
|
|
||||||
|
UserFriends.init({}, {sequelize, underscored});
|
||||||
|
|
||||||
|
Post.init({
|
||||||
|
content: DataTypes.TEXT,
|
||||||
|
}, {sequelize, underscored});
|
||||||
|
|
||||||
|
PostVotes.init({
|
||||||
|
voteType: {
|
||||||
|
type: DataTypes.ENUM,
|
||||||
|
values: ["UPVOTE", "DOWNVOTE"],
|
||||||
|
},
|
||||||
|
}, {sequelize, underscored});
|
||||||
|
|
||||||
|
Request.init({
|
||||||
|
requestType: {
|
||||||
|
type: DataTypes.ENUM,
|
||||||
|
values: ["FRIENDREQUEST", "GROUPINVITE", "EVENTINVITE"],
|
||||||
|
},
|
||||||
|
}, {sequelize, underscored});
|
||||||
|
|
||||||
|
Chat.init({}, {sequelize, underscored});
|
||||||
|
|
||||||
|
ChatMembers.init({}, {sequelize, underscored});
|
||||||
|
|
||||||
|
ChatMessage.init({
|
||||||
|
content: {
|
||||||
|
type: DataTypes.TEXT,
|
||||||
|
allowNull: false,
|
||||||
|
},
|
||||||
|
}, {sequelize, underscored});
|
||||||
|
|
||||||
|
User.belongsToMany(User, {through: UserFriends, as: "friends"});
|
||||||
|
Post.belongsTo(User, {foreignKey: "userId"});
|
||||||
|
User.hasMany(Post, {as: "posts", foreignKey: "userId"});
|
||||||
|
Post.belongsToMany(User, {through: PostVotes, as: "votes"});
|
||||||
|
User.belongsToMany(Post, {through: PostVotes, as: "votes"});
|
||||||
|
User.hasMany(Request, {as: "sentRequests"});
|
||||||
|
User.hasMany(Request, {as: "receivedRequests"});
|
||||||
|
User.belongsToMany(Chat, {through: ChatMembers});
|
||||||
|
Chat.belongsToMany(User, {through: ChatMembers, as: "members"});
|
||||||
|
Chat.hasMany(ChatMessage, {as: "messages"});
|
||||||
|
ChatMessage.belongsTo(Chat);
|
||||||
|
ChatMessage.belongsTo(User, {as: "author", foreignKey: "userId"});
|
||||||
|
User.hasMany(ChatMessage, {foreignKey: "userId"});
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,5 @@
|
|||||||
|
export {User} from "./User";
|
||||||
|
export {Chatroom} from "./Chatroom";
|
||||||
|
export {Post} from "./Post";
|
||||||
|
export {Profile} from "./Profile";
|
||||||
|
export {ChatMessage} from "./ChatMessage";
|
Loading…
Reference in New Issue